otsdaq_utilities  v2_05_02_indev
three.js
1 // File:src/Three.js
2 
7 var THREE = { REVISION: '73' };
8 
9 //
10 
11 if ( typeof define === 'function' && define.amd ) {
12 
13  define( 'three', THREE );
14 
15 } else if ( 'undefined' !== typeof exports && 'undefined' !== typeof module ) {
16 
17  module.exports = THREE;
18 
19 }
20 
21 
22 // polyfills
23 
24 if ( self.requestAnimationFrame === undefined || self.cancelAnimationFrame === undefined ) {
25 
26  // Missing in Android stock browser.
27 
28  ( function () {
29 
30  var lastTime = 0;
31  var vendors = [ 'ms', 'moz', 'webkit', 'o' ];
32 
33  for ( var x = 0; x < vendors.length && ! self.requestAnimationFrame; ++ x ) {
34 
35  self.requestAnimationFrame = self[ vendors[ x ] + 'RequestAnimationFrame' ];
36  self.cancelAnimationFrame = self[ vendors[ x ] + 'CancelAnimationFrame' ] || self[ vendors[ x ] + 'CancelRequestAnimationFrame' ];
37 
38  }
39 
40  if ( self.requestAnimationFrame === undefined && self.setTimeout !== undefined ) {
41 
42  self.requestAnimationFrame = function ( callback ) {
43 
44  var currTime = Date.now(), timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
45  var id = self.setTimeout( function () {
46 
47  callback( currTime + timeToCall );
48 
49  }, timeToCall );
50  lastTime = currTime + timeToCall;
51  return id;
52 
53  };
54 
55  }
56 
57  if ( self.cancelAnimationFrame === undefined && self.clearTimeout !== undefined ) {
58 
59  self.cancelAnimationFrame = function ( id ) {
60 
61  self.clearTimeout( id );
62 
63  };
64 
65  }
66 
67  } )();
68 
69 }
70 
71 //
72 
73 if ( self.performance === undefined ) {
74 
75  self.performance = {};
76 
77 }
78 
79 if ( self.performance.now === undefined ) {
80 
81  ( function () {
82 
83  var start = Date.now();
84 
85  self.performance.now = function () {
86 
87  return Date.now() - start;
88 
89  }
90 
91  } )();
92 
93 }
94 
95 //
96 
97 if ( Number.EPSILON === undefined ) {
98 
99  Number.EPSILON = Math.pow( 2, -52 );
100 
101 }
102 
103 //
104 
105 if ( Math.sign === undefined ) {
106 
107  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
108 
109  Math.sign = function ( x ) {
110 
111  return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x;
112 
113  };
114 
115 }
116 
117 if ( Function.prototype.name === undefined && Object.defineProperty !== undefined ) {
118 
119  // Missing in IE9-11.
120  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
121 
122  Object.defineProperty( Function.prototype, 'name', {
123 
124  get: function () {
125 
126  return this.toString().match( /^\s*function\s*(\S*)\s*\(/ )[ 1 ];
127 
128  }
129 
130  } );
131 
132 }
133 
134 // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent.button
135 
136 THREE.MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
137 
138 // GL STATE CONSTANTS
139 
140 THREE.CullFaceNone = 0;
141 THREE.CullFaceBack = 1;
142 THREE.CullFaceFront = 2;
143 THREE.CullFaceFrontBack = 3;
144 
145 THREE.FrontFaceDirectionCW = 0;
146 THREE.FrontFaceDirectionCCW = 1;
147 
148 // SHADOWING TYPES
149 
150 THREE.BasicShadowMap = 0;
151 THREE.PCFShadowMap = 1;
152 THREE.PCFSoftShadowMap = 2;
153 
154 // MATERIAL CONSTANTS
155 
156 // side
157 
158 THREE.FrontSide = 0;
159 THREE.BackSide = 1;
160 THREE.DoubleSide = 2;
161 
162 // shading
163 
164 THREE.FlatShading = 1;
165 THREE.SmoothShading = 2;
166 
167 // colors
168 
169 THREE.NoColors = 0;
170 THREE.FaceColors = 1;
171 THREE.VertexColors = 2;
172 
173 // blending modes
174 
175 THREE.NoBlending = 0;
176 THREE.NormalBlending = 1;
177 THREE.AdditiveBlending = 2;
178 THREE.SubtractiveBlending = 3;
179 THREE.MultiplyBlending = 4;
180 THREE.CustomBlending = 5;
181 
182 // custom blending equations
183 // (numbers start from 100 not to clash with other
184 // mappings to OpenGL constants defined in Texture.js)
185 
186 THREE.AddEquation = 100;
187 THREE.SubtractEquation = 101;
188 THREE.ReverseSubtractEquation = 102;
189 THREE.MinEquation = 103;
190 THREE.MaxEquation = 104;
191 
192 // custom blending destination factors
193 
194 THREE.ZeroFactor = 200;
195 THREE.OneFactor = 201;
196 THREE.SrcColorFactor = 202;
197 THREE.OneMinusSrcColorFactor = 203;
198 THREE.SrcAlphaFactor = 204;
199 THREE.OneMinusSrcAlphaFactor = 205;
200 THREE.DstAlphaFactor = 206;
201 THREE.OneMinusDstAlphaFactor = 207;
202 
203 // custom blending source factors
204 
205 //THREE.ZeroFactor = 200;
206 //THREE.OneFactor = 201;
207 //THREE.SrcAlphaFactor = 204;
208 //THREE.OneMinusSrcAlphaFactor = 205;
209 //THREE.DstAlphaFactor = 206;
210 //THREE.OneMinusDstAlphaFactor = 207;
211 THREE.DstColorFactor = 208;
212 THREE.OneMinusDstColorFactor = 209;
213 THREE.SrcAlphaSaturateFactor = 210;
214 
215 // depth modes
216 
217 THREE.NeverDepth = 0;
218 THREE.AlwaysDepth = 1;
219 THREE.LessDepth = 2;
220 THREE.LessEqualDepth = 3;
221 THREE.EqualDepth = 4;
222 THREE.GreaterEqualDepth = 5;
223 THREE.GreaterDepth = 6;
224 THREE.NotEqualDepth = 7;
225 
226 
227 // TEXTURE CONSTANTS
228 
229 THREE.MultiplyOperation = 0;
230 THREE.MixOperation = 1;
231 THREE.AddOperation = 2;
232 
233 // Mapping modes
234 
235 THREE.UVMapping = 300;
236 
237 THREE.CubeReflectionMapping = 301;
238 THREE.CubeRefractionMapping = 302;
239 
240 THREE.EquirectangularReflectionMapping = 303;
241 THREE.EquirectangularRefractionMapping = 304;
242 
243 THREE.SphericalReflectionMapping = 305;
244 
245 // Wrapping modes
246 
247 THREE.RepeatWrapping = 1000;
248 THREE.ClampToEdgeWrapping = 1001;
249 THREE.MirroredRepeatWrapping = 1002;
250 
251 // Filters
252 
253 THREE.NearestFilter = 1003;
254 THREE.NearestMipMapNearestFilter = 1004;
255 THREE.NearestMipMapLinearFilter = 1005;
256 THREE.LinearFilter = 1006;
257 THREE.LinearMipMapNearestFilter = 1007;
258 THREE.LinearMipMapLinearFilter = 1008;
259 
260 // Data types
261 
262 THREE.UnsignedByteType = 1009;
263 THREE.ByteType = 1010;
264 THREE.ShortType = 1011;
265 THREE.UnsignedShortType = 1012;
266 THREE.IntType = 1013;
267 THREE.UnsignedIntType = 1014;
268 THREE.FloatType = 1015;
269 THREE.HalfFloatType = 1025;
270 
271 // Pixel types
272 
273 //THREE.UnsignedByteType = 1009;
274 THREE.UnsignedShort4444Type = 1016;
275 THREE.UnsignedShort5551Type = 1017;
276 THREE.UnsignedShort565Type = 1018;
277 
278 // Pixel formats
279 
280 THREE.AlphaFormat = 1019;
281 THREE.RGBFormat = 1020;
282 THREE.RGBAFormat = 1021;
283 THREE.LuminanceFormat = 1022;
284 THREE.LuminanceAlphaFormat = 1023;
285 // THREE.RGBEFormat handled as THREE.RGBAFormat in shaders
286 THREE.RGBEFormat = THREE.RGBAFormat; //1024;
287 
288 // DDS / ST3C Compressed texture formats
289 
290 THREE.RGB_S3TC_DXT1_Format = 2001;
291 THREE.RGBA_S3TC_DXT1_Format = 2002;
292 THREE.RGBA_S3TC_DXT3_Format = 2003;
293 THREE.RGBA_S3TC_DXT5_Format = 2004;
294 
295 
296 // PVRTC compressed texture formats
297 
298 THREE.RGB_PVRTC_4BPPV1_Format = 2100;
299 THREE.RGB_PVRTC_2BPPV1_Format = 2101;
300 THREE.RGBA_PVRTC_4BPPV1_Format = 2102;
301 THREE.RGBA_PVRTC_2BPPV1_Format = 2103;
302 
303 // Loop styles for AnimationAction
304 
305 THREE.LoopOnce = 2200;
306 THREE.LoopRepeat = 2201;
307 THREE.LoopPingPong = 2202;
308 
309 // DEPRECATED
310 
311 THREE.Projector = function () {
312 
313  console.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' );
314 
315  this.projectVector = function ( vector, camera ) {
316 
317  console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );
318  vector.project( camera );
319 
320  };
321 
322  this.unprojectVector = function ( vector, camera ) {
323 
324  console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
325  vector.unproject( camera );
326 
327  };
328 
329  this.pickingRay = function ( vector, camera ) {
330 
331  console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
332 
333  };
334 
335 };
336 
337 THREE.CanvasRenderer = function () {
338 
339  console.error( 'THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js' );
340 
341  this.domElement = document.createElement( 'canvas' );
342  this.clear = function () {};
343  this.render = function () {};
344  this.setClearColor = function () {};
345  this.setSize = function () {};
346 
347 };
348 
349 // File:src/math/Color.js
350 
355 THREE.Color = function ( color ) {
356 
357  if ( arguments.length === 3 ) {
358 
359  return this.fromArray( arguments );
360 
361  }
362 
363  return this.set( color );
364 
365 };
366 
367 THREE.Color.prototype = {
368 
369  constructor: THREE.Color,
370 
371  r: 1, g: 1, b: 1,
372 
373  set: function ( value ) {
374 
375  if ( value instanceof THREE.Color ) {
376 
377  this.copy( value );
378 
379  } else if ( typeof value === 'number' ) {
380 
381  this.setHex( value );
382 
383  } else if ( typeof value === 'string' ) {
384 
385  this.setStyle( value );
386 
387  }
388 
389  return this;
390 
391  },
392 
393  setHex: function ( hex ) {
394 
395  hex = Math.floor( hex );
396 
397  this.r = ( hex >> 16 & 255 ) / 255;
398  this.g = ( hex >> 8 & 255 ) / 255;
399  this.b = ( hex & 255 ) / 255;
400 
401  return this;
402 
403  },
404 
405  setRGB: function ( r, g, b ) {
406 
407  this.r = r;
408  this.g = g;
409  this.b = b;
410 
411  return this;
412 
413  },
414 
415  setHSL: function () {
416 
417  function hue2rgb( p, q, t ) {
418 
419  if ( t < 0 ) t += 1;
420  if ( t > 1 ) t -= 1;
421  if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
422  if ( t < 1 / 2 ) return q;
423  if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
424  return p;
425 
426  }
427 
428  return function ( h, s, l ) {
429 
430  // h,s,l ranges are in 0.0 - 1.0
431  h = THREE.Math.euclideanModulo( h, 1 );
432  s = THREE.Math.clamp( s, 0, 1 );
433  l = THREE.Math.clamp( l, 0, 1 );
434 
435  if ( s === 0 ) {
436 
437  this.r = this.g = this.b = l;
438 
439  } else {
440 
441  var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
442  var q = ( 2 * l ) - p;
443 
444  this.r = hue2rgb( q, p, h + 1 / 3 );
445  this.g = hue2rgb( q, p, h );
446  this.b = hue2rgb( q, p, h - 1 / 3 );
447 
448  }
449 
450  return this;
451 
452  };
453 
454  }(),
455 
456  setStyle: function ( style ) {
457 
458  function handleAlpha( string ) {
459 
460  if ( string === undefined ) return;
461 
462  if ( parseFloat( string ) < 1 ) {
463 
464  console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
465 
466  }
467 
468  }
469 
470 
471  var m;
472 
473  if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
474 
475  // rgb / hsl
476 
477  var color;
478  var name = m[ 1 ];
479  var components = m[ 2 ];
480 
481  switch ( name ) {
482 
483  case 'rgb':
484  case 'rgba':
485 
486  if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
487 
488  // rgb(255,0,0) rgba(255,0,0,0.5)
489  this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
490  this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
491  this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
492 
493  handleAlpha( color[ 5 ] );
494 
495  return this;
496 
497  }
498 
499  if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
500 
501  // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
502  this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
503  this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
504  this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
505 
506  handleAlpha( color[ 5 ] );
507 
508  return this;
509 
510  }
511 
512  break;
513 
514  case 'hsl':
515  case 'hsla':
516 
517  if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
518 
519  // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
520  var h = parseFloat( color[ 1 ] ) / 360;
521  var s = parseInt( color[ 2 ], 10 ) / 100;
522  var l = parseInt( color[ 3 ], 10 ) / 100;
523 
524  handleAlpha( color[ 5 ] );
525 
526  return this.setHSL( h, s, l );
527 
528  }
529 
530  break;
531 
532  }
533 
534  } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
535 
536  // hex color
537 
538  var hex = m[ 1 ];
539  var size = hex.length;
540 
541  if ( size === 3 ) {
542 
543  // #ff0
544  this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
545  this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
546  this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
547 
548  return this;
549 
550  } else if ( size === 6 ) {
551 
552  // #ff0000
553  this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
554  this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
555  this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
556 
557  return this;
558 
559  }
560 
561  }
562 
563  if ( style && style.length > 0 ) {
564 
565  // color keywords
566  var hex = THREE.ColorKeywords[ style ];
567 
568  if ( hex !== undefined ) {
569 
570  // red
571  this.setHex( hex );
572 
573  } else {
574 
575  // unknown color
576  console.warn( 'THREE.Color: Unknown color ' + style );
577 
578  }
579 
580  }
581 
582  return this;
583 
584  },
585 
586  clone: function () {
587 
588  return new this.constructor( this.r, this.g, this.b );
589 
590  },
591 
592  copy: function ( color ) {
593 
594  this.r = color.r;
595  this.g = color.g;
596  this.b = color.b;
597 
598  return this;
599 
600  },
601 
602  copyGammaToLinear: function ( color, gammaFactor ) {
603 
604  if ( gammaFactor === undefined ) gammaFactor = 2.0;
605 
606  this.r = Math.pow( color.r, gammaFactor );
607  this.g = Math.pow( color.g, gammaFactor );
608  this.b = Math.pow( color.b, gammaFactor );
609 
610  return this;
611 
612  },
613 
614  copyLinearToGamma: function ( color, gammaFactor ) {
615 
616  if ( gammaFactor === undefined ) gammaFactor = 2.0;
617 
618  var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
619 
620  this.r = Math.pow( color.r, safeInverse );
621  this.g = Math.pow( color.g, safeInverse );
622  this.b = Math.pow( color.b, safeInverse );
623 
624  return this;
625 
626  },
627 
628  convertGammaToLinear: function () {
629 
630  var r = this.r, g = this.g, b = this.b;
631 
632  this.r = r * r;
633  this.g = g * g;
634  this.b = b * b;
635 
636  return this;
637 
638  },
639 
640  convertLinearToGamma: function () {
641 
642  this.r = Math.sqrt( this.r );
643  this.g = Math.sqrt( this.g );
644  this.b = Math.sqrt( this.b );
645 
646  return this;
647 
648  },
649 
650  getHex: function () {
651 
652  return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
653 
654  },
655 
656  getHexString: function () {
657 
658  return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
659 
660  },
661 
662  getHSL: function ( optionalTarget ) {
663 
664  // h,s,l ranges are in 0.0 - 1.0
665 
666  var hsl = optionalTarget || { h: 0, s: 0, l: 0 };
667 
668  var r = this.r, g = this.g, b = this.b;
669 
670  var max = Math.max( r, g, b );
671  var min = Math.min( r, g, b );
672 
673  var hue, saturation;
674  var lightness = ( min + max ) / 2.0;
675 
676  if ( min === max ) {
677 
678  hue = 0;
679  saturation = 0;
680 
681  } else {
682 
683  var delta = max - min;
684 
685  saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
686 
687  switch ( max ) {
688 
689  case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
690  case g: hue = ( b - r ) / delta + 2; break;
691  case b: hue = ( r - g ) / delta + 4; break;
692 
693  }
694 
695  hue /= 6;
696 
697  }
698 
699  hsl.h = hue;
700  hsl.s = saturation;
701  hsl.l = lightness;
702 
703  return hsl;
704 
705  },
706 
707  getStyle: function () {
708 
709  return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
710 
711  },
712 
713  offsetHSL: function ( h, s, l ) {
714 
715  var hsl = this.getHSL();
716 
717  hsl.h += h; hsl.s += s; hsl.l += l;
718 
719  this.setHSL( hsl.h, hsl.s, hsl.l );
720 
721  return this;
722 
723  },
724 
725  add: function ( color ) {
726 
727  this.r += color.r;
728  this.g += color.g;
729  this.b += color.b;
730 
731  return this;
732 
733  },
734 
735  addColors: function ( color1, color2 ) {
736 
737  this.r = color1.r + color2.r;
738  this.g = color1.g + color2.g;
739  this.b = color1.b + color2.b;
740 
741  return this;
742 
743  },
744 
745  addScalar: function ( s ) {
746 
747  this.r += s;
748  this.g += s;
749  this.b += s;
750 
751  return this;
752 
753  },
754 
755  multiply: function ( color ) {
756 
757  this.r *= color.r;
758  this.g *= color.g;
759  this.b *= color.b;
760 
761  return this;
762 
763  },
764 
765  multiplyScalar: function ( s ) {
766 
767  this.r *= s;
768  this.g *= s;
769  this.b *= s;
770 
771  return this;
772 
773  },
774 
775  lerp: function ( color, alpha ) {
776 
777  this.r += ( color.r - this.r ) * alpha;
778  this.g += ( color.g - this.g ) * alpha;
779  this.b += ( color.b - this.b ) * alpha;
780 
781  return this;
782 
783  },
784 
785  equals: function ( c ) {
786 
787  return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
788 
789  },
790 
791  fromArray: function ( array, offset ) {
792 
793  if ( offset === undefined ) offset = 0;
794 
795  this.r = array[ offset ];
796  this.g = array[ offset + 1 ];
797  this.b = array[ offset + 2 ];
798 
799  return this;
800 
801  },
802 
803  toArray: function ( array, offset ) {
804 
805  if ( array === undefined ) array = [];
806  if ( offset === undefined ) offset = 0;
807 
808  array[ offset ] = this.r;
809  array[ offset + 1 ] = this.g;
810  array[ offset + 2 ] = this.b;
811 
812  return array;
813 
814  }
815 
816 };
817 
818 THREE.ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
819 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
820 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
821 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
822 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
823 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
824 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
825 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
826 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
827 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
828 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
829 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
830 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
831 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
832 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
833 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
834 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
835 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
836 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
837 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
838 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
839 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
840 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
841 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
842 
843 // File:src/math/Quaternion.js
844 
852 THREE.Quaternion = function ( x, y, z, w ) {
853 
854  this._x = x || 0;
855  this._y = y || 0;
856  this._z = z || 0;
857  this._w = ( w !== undefined ) ? w : 1;
858 
859 };
860 
861 THREE.Quaternion.prototype = {
862 
863  constructor: THREE.Quaternion,
864 
865  get x () {
866 
867  return this._x;
868 
869  },
870 
871  set x ( value ) {
872 
873  this._x = value;
874  this.onChangeCallback();
875 
876  },
877 
878  get y () {
879 
880  return this._y;
881 
882  },
883 
884  set y ( value ) {
885 
886  this._y = value;
887  this.onChangeCallback();
888 
889  },
890 
891  get z () {
892 
893  return this._z;
894 
895  },
896 
897  set z ( value ) {
898 
899  this._z = value;
900  this.onChangeCallback();
901 
902  },
903 
904  get w () {
905 
906  return this._w;
907 
908  },
909 
910  set w ( value ) {
911 
912  this._w = value;
913  this.onChangeCallback();
914 
915  },
916 
917  set: function ( x, y, z, w ) {
918 
919  this._x = x;
920  this._y = y;
921  this._z = z;
922  this._w = w;
923 
924  this.onChangeCallback();
925 
926  return this;
927 
928  },
929 
930  clone: function () {
931 
932  return new this.constructor( this._x, this._y, this._z, this._w );
933 
934  },
935 
936  copy: function ( quaternion ) {
937 
938  this._x = quaternion.x;
939  this._y = quaternion.y;
940  this._z = quaternion.z;
941  this._w = quaternion.w;
942 
943  this.onChangeCallback();
944 
945  return this;
946 
947  },
948 
949  setFromEuler: function ( euler, update ) {
950 
951  if ( euler instanceof THREE.Euler === false ) {
952 
953  throw new Error( 'THREE.Quaternion: .setFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
954 
955  }
956 
957  // http://www.mathworks.com/matlabcentral/fileexchange/
958  // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
959  // content/SpinCalc.m
960 
961  var c1 = Math.cos( euler._x / 2 );
962  var c2 = Math.cos( euler._y / 2 );
963  var c3 = Math.cos( euler._z / 2 );
964  var s1 = Math.sin( euler._x / 2 );
965  var s2 = Math.sin( euler._y / 2 );
966  var s3 = Math.sin( euler._z / 2 );
967 
968  var order = euler.order;
969 
970  if ( order === 'XYZ' ) {
971 
972  this._x = s1 * c2 * c3 + c1 * s2 * s3;
973  this._y = c1 * s2 * c3 - s1 * c2 * s3;
974  this._z = c1 * c2 * s3 + s1 * s2 * c3;
975  this._w = c1 * c2 * c3 - s1 * s2 * s3;
976 
977  } else if ( order === 'YXZ' ) {
978 
979  this._x = s1 * c2 * c3 + c1 * s2 * s3;
980  this._y = c1 * s2 * c3 - s1 * c2 * s3;
981  this._z = c1 * c2 * s3 - s1 * s2 * c3;
982  this._w = c1 * c2 * c3 + s1 * s2 * s3;
983 
984  } else if ( order === 'ZXY' ) {
985 
986  this._x = s1 * c2 * c3 - c1 * s2 * s3;
987  this._y = c1 * s2 * c3 + s1 * c2 * s3;
988  this._z = c1 * c2 * s3 + s1 * s2 * c3;
989  this._w = c1 * c2 * c3 - s1 * s2 * s3;
990 
991  } else if ( order === 'ZYX' ) {
992 
993  this._x = s1 * c2 * c3 - c1 * s2 * s3;
994  this._y = c1 * s2 * c3 + s1 * c2 * s3;
995  this._z = c1 * c2 * s3 - s1 * s2 * c3;
996  this._w = c1 * c2 * c3 + s1 * s2 * s3;
997 
998  } else if ( order === 'YZX' ) {
999 
1000  this._x = s1 * c2 * c3 + c1 * s2 * s3;
1001  this._y = c1 * s2 * c3 + s1 * c2 * s3;
1002  this._z = c1 * c2 * s3 - s1 * s2 * c3;
1003  this._w = c1 * c2 * c3 - s1 * s2 * s3;
1004 
1005  } else if ( order === 'XZY' ) {
1006 
1007  this._x = s1 * c2 * c3 - c1 * s2 * s3;
1008  this._y = c1 * s2 * c3 - s1 * c2 * s3;
1009  this._z = c1 * c2 * s3 + s1 * s2 * c3;
1010  this._w = c1 * c2 * c3 + s1 * s2 * s3;
1011 
1012  }
1013 
1014  if ( update !== false ) this.onChangeCallback();
1015 
1016  return this;
1017 
1018  },
1019 
1020  setFromAxisAngle: function ( axis, angle ) {
1021 
1022  // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
1023 
1024  // assumes axis is normalized
1025 
1026  var halfAngle = angle / 2, s = Math.sin( halfAngle );
1027 
1028  this._x = axis.x * s;
1029  this._y = axis.y * s;
1030  this._z = axis.z * s;
1031  this._w = Math.cos( halfAngle );
1032 
1033  this.onChangeCallback();
1034 
1035  return this;
1036 
1037  },
1038 
1039  setFromRotationMatrix: function ( m ) {
1040 
1041  // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
1042 
1043  // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
1044 
1045  var te = m.elements,
1046 
1047  m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
1048  m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
1049  m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
1050 
1051  trace = m11 + m22 + m33,
1052  s;
1053 
1054  if ( trace > 0 ) {
1055 
1056  s = 0.5 / Math.sqrt( trace + 1.0 );
1057 
1058  this._w = 0.25 / s;
1059  this._x = ( m32 - m23 ) * s;
1060  this._y = ( m13 - m31 ) * s;
1061  this._z = ( m21 - m12 ) * s;
1062 
1063  } else if ( m11 > m22 && m11 > m33 ) {
1064 
1065  s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
1066 
1067  this._w = ( m32 - m23 ) / s;
1068  this._x = 0.25 * s;
1069  this._y = ( m12 + m21 ) / s;
1070  this._z = ( m13 + m31 ) / s;
1071 
1072  } else if ( m22 > m33 ) {
1073 
1074  s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
1075 
1076  this._w = ( m13 - m31 ) / s;
1077  this._x = ( m12 + m21 ) / s;
1078  this._y = 0.25 * s;
1079  this._z = ( m23 + m32 ) / s;
1080 
1081  } else {
1082 
1083  s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
1084 
1085  this._w = ( m21 - m12 ) / s;
1086  this._x = ( m13 + m31 ) / s;
1087  this._y = ( m23 + m32 ) / s;
1088  this._z = 0.25 * s;
1089 
1090  }
1091 
1092  this.onChangeCallback();
1093 
1094  return this;
1095 
1096  },
1097 
1098  setFromUnitVectors: function () {
1099 
1100  // http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
1101 
1102  // assumes direction vectors vFrom and vTo are normalized
1103 
1104  var v1, r;
1105 
1106  var EPS = 0.000001;
1107 
1108  return function ( vFrom, vTo ) {
1109 
1110  if ( v1 === undefined ) v1 = new THREE.Vector3();
1111 
1112  r = vFrom.dot( vTo ) + 1;
1113 
1114  if ( r < EPS ) {
1115 
1116  r = 0;
1117 
1118  if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
1119 
1120  v1.set( - vFrom.y, vFrom.x, 0 );
1121 
1122  } else {
1123 
1124  v1.set( 0, - vFrom.z, vFrom.y );
1125 
1126  }
1127 
1128  } else {
1129 
1130  v1.crossVectors( vFrom, vTo );
1131 
1132  }
1133 
1134  this._x = v1.x;
1135  this._y = v1.y;
1136  this._z = v1.z;
1137  this._w = r;
1138 
1139  this.normalize();
1140 
1141  return this;
1142 
1143  }
1144 
1145  }(),
1146 
1147  inverse: function () {
1148 
1149  this.conjugate().normalize();
1150 
1151  return this;
1152 
1153  },
1154 
1155  conjugate: function () {
1156 
1157  this._x *= - 1;
1158  this._y *= - 1;
1159  this._z *= - 1;
1160 
1161  this.onChangeCallback();
1162 
1163  return this;
1164 
1165  },
1166 
1167  dot: function ( v ) {
1168 
1169  return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
1170 
1171  },
1172 
1173  lengthSq: function () {
1174 
1175  return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
1176 
1177  },
1178 
1179  length: function () {
1180 
1181  return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
1182 
1183  },
1184 
1185  normalize: function () {
1186 
1187  var l = this.length();
1188 
1189  if ( l === 0 ) {
1190 
1191  this._x = 0;
1192  this._y = 0;
1193  this._z = 0;
1194  this._w = 1;
1195 
1196  } else {
1197 
1198  l = 1 / l;
1199 
1200  this._x = this._x * l;
1201  this._y = this._y * l;
1202  this._z = this._z * l;
1203  this._w = this._w * l;
1204 
1205  }
1206 
1207  this.onChangeCallback();
1208 
1209  return this;
1210 
1211  },
1212 
1213  multiply: function ( q, p ) {
1214 
1215  if ( p !== undefined ) {
1216 
1217  console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
1218  return this.multiplyQuaternions( q, p );
1219 
1220  }
1221 
1222  return this.multiplyQuaternions( this, q );
1223 
1224  },
1225 
1226  multiplyQuaternions: function ( a, b ) {
1227 
1228  // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
1229 
1230  var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
1231  var qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
1232 
1233  this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
1234  this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
1235  this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
1236  this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
1237 
1238  this.onChangeCallback();
1239 
1240  return this;
1241 
1242  },
1243 
1244  multiplyVector3: function ( vector ) {
1245 
1246  console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
1247  return vector.applyQuaternion( this );
1248 
1249  },
1250 
1251  slerp: function ( qb, t ) {
1252 
1253  if ( t === 0 ) return this;
1254  if ( t === 1 ) return this.copy( qb );
1255 
1256  var x = this._x, y = this._y, z = this._z, w = this._w;
1257 
1258  // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
1259 
1260  var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
1261 
1262  if ( cosHalfTheta < 0 ) {
1263 
1264  this._w = - qb._w;
1265  this._x = - qb._x;
1266  this._y = - qb._y;
1267  this._z = - qb._z;
1268 
1269  cosHalfTheta = - cosHalfTheta;
1270 
1271  } else {
1272 
1273  this.copy( qb );
1274 
1275  }
1276 
1277  if ( cosHalfTheta >= 1.0 ) {
1278 
1279  this._w = w;
1280  this._x = x;
1281  this._y = y;
1282  this._z = z;
1283 
1284  return this;
1285 
1286  }
1287 
1288  var halfTheta = Math.acos( cosHalfTheta );
1289  var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
1290 
1291  if ( Math.abs( sinHalfTheta ) < 0.001 ) {
1292 
1293  this._w = 0.5 * ( w + this._w );
1294  this._x = 0.5 * ( x + this._x );
1295  this._y = 0.5 * ( y + this._y );
1296  this._z = 0.5 * ( z + this._z );
1297 
1298  return this;
1299 
1300  }
1301 
1302  var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
1303  ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
1304 
1305  this._w = ( w * ratioA + this._w * ratioB );
1306  this._x = ( x * ratioA + this._x * ratioB );
1307  this._y = ( y * ratioA + this._y * ratioB );
1308  this._z = ( z * ratioA + this._z * ratioB );
1309 
1310  this.onChangeCallback();
1311 
1312  return this;
1313 
1314  },
1315 
1316  equals: function ( quaternion ) {
1317 
1318  return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
1319 
1320  },
1321 
1322  fromArray: function ( array, offset ) {
1323 
1324  if ( offset === undefined ) offset = 0;
1325 
1326  this._x = array[ offset ];
1327  this._y = array[ offset + 1 ];
1328  this._z = array[ offset + 2 ];
1329  this._w = array[ offset + 3 ];
1330 
1331  this.onChangeCallback();
1332 
1333  return this;
1334 
1335  },
1336 
1337  toArray: function ( array, offset ) {
1338 
1339  if ( array === undefined ) array = [];
1340  if ( offset === undefined ) offset = 0;
1341 
1342  array[ offset ] = this._x;
1343  array[ offset + 1 ] = this._y;
1344  array[ offset + 2 ] = this._z;
1345  array[ offset + 3 ] = this._w;
1346 
1347  return array;
1348 
1349  },
1350 
1351  onChange: function ( callback ) {
1352 
1353  this.onChangeCallback = callback;
1354 
1355  return this;
1356 
1357  },
1358 
1359  onChangeCallback: function () {}
1360 
1361 };
1362 
1363 THREE.Quaternion.slerp = function ( qa, qb, qm, t ) {
1364 
1365  return qm.copy( qa ).slerp( qb, t );
1366 
1367 };
1368 
1369 // File:src/math/Vector2.js
1370 
1378 THREE.Vector2 = function ( x, y ) {
1379 
1380  this.x = x || 0;
1381  this.y = y || 0;
1382 
1383 };
1384 
1385 THREE.Vector2.prototype = {
1386 
1387  constructor: THREE.Vector2,
1388 
1389  get width() { return this.x },
1390  set width( value ) { this.x = value },
1391 
1392  get height() { return this.y },
1393  set height( value ) { this.y = value },
1394 
1395  //
1396 
1397  set: function ( x, y ) {
1398 
1399  this.x = x;
1400  this.y = y;
1401 
1402  return this;
1403 
1404  },
1405 
1406  setX: function ( x ) {
1407 
1408  this.x = x;
1409 
1410  return this;
1411 
1412  },
1413 
1414  setY: function ( y ) {
1415 
1416  this.y = y;
1417 
1418  return this;
1419 
1420  },
1421 
1422  setComponent: function ( index, value ) {
1423 
1424  switch ( index ) {
1425 
1426  case 0: this.x = value; break;
1427  case 1: this.y = value; break;
1428  default: throw new Error( 'index is out of range: ' + index );
1429 
1430  }
1431 
1432  },
1433 
1434  getComponent: function ( index ) {
1435 
1436  switch ( index ) {
1437 
1438  case 0: return this.x;
1439  case 1: return this.y;
1440  default: throw new Error( 'index is out of range: ' + index );
1441 
1442  }
1443 
1444  },
1445 
1446  clone: function () {
1447 
1448  return new this.constructor( this.x, this.y );
1449 
1450  },
1451 
1452  copy: function ( v ) {
1453 
1454  this.x = v.x;
1455  this.y = v.y;
1456 
1457  return this;
1458 
1459  },
1460 
1461  add: function ( v, w ) {
1462 
1463  if ( w !== undefined ) {
1464 
1465  console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
1466  return this.addVectors( v, w );
1467 
1468  }
1469 
1470  this.x += v.x;
1471  this.y += v.y;
1472 
1473  return this;
1474 
1475  },
1476 
1477  addScalar: function ( s ) {
1478 
1479  this.x += s;
1480  this.y += s;
1481 
1482  return this;
1483 
1484  },
1485 
1486  addVectors: function ( a, b ) {
1487 
1488  this.x = a.x + b.x;
1489  this.y = a.y + b.y;
1490 
1491  return this;
1492 
1493  },
1494 
1495  addScaledVector: function ( v, s ) {
1496 
1497  this.x += v.x * s;
1498  this.y += v.y * s;
1499 
1500  return this;
1501 
1502  },
1503 
1504  sub: function ( v, w ) {
1505 
1506  if ( w !== undefined ) {
1507 
1508  console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
1509  return this.subVectors( v, w );
1510 
1511  }
1512 
1513  this.x -= v.x;
1514  this.y -= v.y;
1515 
1516  return this;
1517 
1518  },
1519 
1520  subScalar: function ( s ) {
1521 
1522  this.x -= s;
1523  this.y -= s;
1524 
1525  return this;
1526 
1527  },
1528 
1529  subVectors: function ( a, b ) {
1530 
1531  this.x = a.x - b.x;
1532  this.y = a.y - b.y;
1533 
1534  return this;
1535 
1536  },
1537 
1538  multiply: function ( v ) {
1539 
1540  this.x *= v.x;
1541  this.y *= v.y;
1542 
1543  return this;
1544 
1545  },
1546 
1547  multiplyScalar: function ( scalar ) {
1548 
1549  if ( isFinite( scalar ) ) {
1550  this.x *= scalar;
1551  this.y *= scalar;
1552  } else {
1553  this.x = 0;
1554  this.y = 0;
1555  }
1556 
1557  return this;
1558 
1559  },
1560 
1561  divide: function ( v ) {
1562 
1563  this.x /= v.x;
1564  this.y /= v.y;
1565 
1566  return this;
1567 
1568  },
1569 
1570  divideScalar: function ( scalar ) {
1571 
1572  return this.multiplyScalar( 1 / scalar );
1573 
1574  },
1575 
1576  min: function ( v ) {
1577 
1578  this.x = Math.min( this.x, v.x );
1579  this.y = Math.min( this.y, v.y );
1580 
1581  return this;
1582 
1583  },
1584 
1585  max: function ( v ) {
1586 
1587  this.x = Math.max( this.x, v.x );
1588  this.y = Math.max( this.y, v.y );
1589 
1590  return this;
1591 
1592  },
1593 
1594  clamp: function ( min, max ) {
1595 
1596  // This function assumes min < max, if this assumption isn't true it will not operate correctly
1597 
1598  this.x = Math.max( min.x, Math.min( max.x, this.x ) );
1599  this.y = Math.max( min.y, Math.min( max.y, this.y ) );
1600 
1601  return this;
1602 
1603  },
1604 
1605  clampScalar: function () {
1606 
1607  var min, max;
1608 
1609  return function clampScalar( minVal, maxVal ) {
1610 
1611  if ( min === undefined ) {
1612 
1613  min = new THREE.Vector2();
1614  max = new THREE.Vector2();
1615 
1616  }
1617 
1618  min.set( minVal, minVal );
1619  max.set( maxVal, maxVal );
1620 
1621  return this.clamp( min, max );
1622 
1623  };
1624 
1625  }(),
1626 
1627  clampLength: function ( min, max ) {
1628 
1629  var length = this.length();
1630 
1631  this.multiplyScalar( Math.max( min, Math.min( max, length ) ) / length );
1632 
1633  return this;
1634 
1635  },
1636 
1637  floor: function () {
1638 
1639  this.x = Math.floor( this.x );
1640  this.y = Math.floor( this.y );
1641 
1642  return this;
1643 
1644  },
1645 
1646  ceil: function () {
1647 
1648  this.x = Math.ceil( this.x );
1649  this.y = Math.ceil( this.y );
1650 
1651  return this;
1652 
1653  },
1654 
1655  round: function () {
1656 
1657  this.x = Math.round( this.x );
1658  this.y = Math.round( this.y );
1659 
1660  return this;
1661 
1662  },
1663 
1664  roundToZero: function () {
1665 
1666  this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
1667  this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
1668 
1669  return this;
1670 
1671  },
1672 
1673  negate: function () {
1674 
1675  this.x = - this.x;
1676  this.y = - this.y;
1677 
1678  return this;
1679 
1680  },
1681 
1682  dot: function ( v ) {
1683 
1684  return this.x * v.x + this.y * v.y;
1685 
1686  },
1687 
1688  lengthSq: function () {
1689 
1690  return this.x * this.x + this.y * this.y;
1691 
1692  },
1693 
1694  length: function () {
1695 
1696  return Math.sqrt( this.x * this.x + this.y * this.y );
1697 
1698  },
1699 
1700  lengthManhattan: function() {
1701 
1702  return Math.abs( this.x ) + Math.abs( this.y );
1703 
1704  },
1705 
1706  normalize: function () {
1707 
1708  return this.divideScalar( this.length() );
1709 
1710  },
1711 
1712  distanceTo: function ( v ) {
1713 
1714  return Math.sqrt( this.distanceToSquared( v ) );
1715 
1716  },
1717 
1718  distanceToSquared: function ( v ) {
1719 
1720  var dx = this.x - v.x, dy = this.y - v.y;
1721  return dx * dx + dy * dy;
1722 
1723  },
1724 
1725  setLength: function ( length ) {
1726 
1727  return this.multiplyScalar( length / this.length() );
1728 
1729  },
1730 
1731  lerp: function ( v, alpha ) {
1732 
1733  this.x += ( v.x - this.x ) * alpha;
1734  this.y += ( v.y - this.y ) * alpha;
1735 
1736  return this;
1737 
1738  },
1739 
1740  lerpVectors: function ( v1, v2, alpha ) {
1741 
1742  this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
1743 
1744  return this;
1745 
1746  },
1747 
1748  equals: function ( v ) {
1749 
1750  return ( ( v.x === this.x ) && ( v.y === this.y ) );
1751 
1752  },
1753 
1754  fromArray: function ( array, offset ) {
1755 
1756  if ( offset === undefined ) offset = 0;
1757 
1758  this.x = array[ offset ];
1759  this.y = array[ offset + 1 ];
1760 
1761  return this;
1762 
1763  },
1764 
1765  toArray: function ( array, offset ) {
1766 
1767  if ( array === undefined ) array = [];
1768  if ( offset === undefined ) offset = 0;
1769 
1770  array[ offset ] = this.x;
1771  array[ offset + 1 ] = this.y;
1772 
1773  return array;
1774 
1775  },
1776 
1777  fromAttribute: function ( attribute, index, offset ) {
1778 
1779  if ( offset === undefined ) offset = 0;
1780 
1781  index = index * attribute.itemSize + offset;
1782 
1783  this.x = attribute.array[ index ];
1784  this.y = attribute.array[ index + 1 ];
1785 
1786  return this;
1787 
1788  },
1789 
1790  rotateAround: function ( center, angle ) {
1791 
1792  var c = Math.cos( angle ), s = Math.sin( angle );
1793 
1794  var x = this.x - center.x;
1795  var y = this.y - center.y;
1796 
1797  this.x = x * c - y * s + center.x;
1798  this.y = x * s + y * c + center.y;
1799 
1800  return this;
1801 
1802  }
1803 
1804 };
1805 
1806 // File:src/math/Vector3.js
1807 
1817 THREE.Vector3 = function ( x, y, z ) {
1818 
1819  this.x = x || 0;
1820  this.y = y || 0;
1821  this.z = z || 0;
1822 
1823 };
1824 
1825 THREE.Vector3.prototype = {
1826 
1827  constructor: THREE.Vector3,
1828 
1829  set: function ( x, y, z ) {
1830 
1831  this.x = x;
1832  this.y = y;
1833  this.z = z;
1834 
1835  return this;
1836 
1837  },
1838 
1839  setX: function ( x ) {
1840 
1841  this.x = x;
1842 
1843  return this;
1844 
1845  },
1846 
1847  setY: function ( y ) {
1848 
1849  this.y = y;
1850 
1851  return this;
1852 
1853  },
1854 
1855  setZ: function ( z ) {
1856 
1857  this.z = z;
1858 
1859  return this;
1860 
1861  },
1862 
1863  setComponent: function ( index, value ) {
1864 
1865  switch ( index ) {
1866 
1867  case 0: this.x = value; break;
1868  case 1: this.y = value; break;
1869  case 2: this.z = value; break;
1870  default: throw new Error( 'index is out of range: ' + index );
1871 
1872  }
1873 
1874  },
1875 
1876  getComponent: function ( index ) {
1877 
1878  switch ( index ) {
1879 
1880  case 0: return this.x;
1881  case 1: return this.y;
1882  case 2: return this.z;
1883  default: throw new Error( 'index is out of range: ' + index );
1884 
1885  }
1886 
1887  },
1888 
1889  clone: function () {
1890 
1891  return new this.constructor( this.x, this.y, this.z );
1892 
1893  },
1894 
1895  copy: function ( v ) {
1896 
1897  this.x = v.x;
1898  this.y = v.y;
1899  this.z = v.z;
1900 
1901  return this;
1902 
1903  },
1904 
1905  add: function ( v, w ) {
1906 
1907  if ( w !== undefined ) {
1908 
1909  console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
1910  return this.addVectors( v, w );
1911 
1912  }
1913 
1914  this.x += v.x;
1915  this.y += v.y;
1916  this.z += v.z;
1917 
1918  return this;
1919 
1920  },
1921 
1922  addScalar: function ( s ) {
1923 
1924  this.x += s;
1925  this.y += s;
1926  this.z += s;
1927 
1928  return this;
1929 
1930  },
1931 
1932  addVectors: function ( a, b ) {
1933 
1934  this.x = a.x + b.x;
1935  this.y = a.y + b.y;
1936  this.z = a.z + b.z;
1937 
1938  return this;
1939 
1940  },
1941 
1942  addScaledVector: function ( v, s ) {
1943 
1944  this.x += v.x * s;
1945  this.y += v.y * s;
1946  this.z += v.z * s;
1947 
1948  return this;
1949 
1950  },
1951 
1952  sub: function ( v, w ) {
1953 
1954  if ( w !== undefined ) {
1955 
1956  console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
1957  return this.subVectors( v, w );
1958 
1959  }
1960 
1961  this.x -= v.x;
1962  this.y -= v.y;
1963  this.z -= v.z;
1964 
1965  return this;
1966 
1967  },
1968 
1969  subScalar: function ( s ) {
1970 
1971  this.x -= s;
1972  this.y -= s;
1973  this.z -= s;
1974 
1975  return this;
1976 
1977  },
1978 
1979  subVectors: function ( a, b ) {
1980 
1981  this.x = a.x - b.x;
1982  this.y = a.y - b.y;
1983  this.z = a.z - b.z;
1984 
1985  return this;
1986 
1987  },
1988 
1989  multiply: function ( v, w ) {
1990 
1991  if ( w !== undefined ) {
1992 
1993  console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
1994  return this.multiplyVectors( v, w );
1995 
1996  }
1997 
1998  this.x *= v.x;
1999  this.y *= v.y;
2000  this.z *= v.z;
2001 
2002  return this;
2003 
2004  },
2005 
2006  multiplyScalar: function ( scalar ) {
2007 
2008  if ( isFinite( scalar ) ) {
2009  this.x *= scalar;
2010  this.y *= scalar;
2011  this.z *= scalar;
2012  } else {
2013  this.x = 0;
2014  this.y = 0;
2015  this.z = 0;
2016  }
2017 
2018  return this;
2019 
2020  },
2021 
2022  multiplyVectors: function ( a, b ) {
2023 
2024  this.x = a.x * b.x;
2025  this.y = a.y * b.y;
2026  this.z = a.z * b.z;
2027 
2028  return this;
2029 
2030  },
2031 
2032  applyEuler: function () {
2033 
2034  var quaternion;
2035 
2036  return function applyEuler( euler ) {
2037 
2038  if ( euler instanceof THREE.Euler === false ) {
2039 
2040  console.error( 'THREE.Vector3: .applyEuler() now expects a Euler rotation rather than a Vector3 and order.' );
2041 
2042  }
2043 
2044  if ( quaternion === undefined ) quaternion = new THREE.Quaternion();
2045 
2046  this.applyQuaternion( quaternion.setFromEuler( euler ) );
2047 
2048  return this;
2049 
2050  };
2051 
2052  }(),
2053 
2054  applyAxisAngle: function () {
2055 
2056  var quaternion;
2057 
2058  return function applyAxisAngle( axis, angle ) {
2059 
2060  if ( quaternion === undefined ) quaternion = new THREE.Quaternion();
2061 
2062  this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );
2063 
2064  return this;
2065 
2066  };
2067 
2068  }(),
2069 
2070  applyMatrix3: function ( m ) {
2071 
2072  var x = this.x;
2073  var y = this.y;
2074  var z = this.z;
2075 
2076  var e = m.elements;
2077 
2078  this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
2079  this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
2080  this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
2081 
2082  return this;
2083 
2084  },
2085 
2086  applyMatrix4: function ( m ) {
2087 
2088  // input: THREE.Matrix4 affine matrix
2089 
2090  var x = this.x, y = this.y, z = this.z;
2091 
2092  var e = m.elements;
2093 
2094  this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ];
2095  this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ];
2096  this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ];
2097 
2098  return this;
2099 
2100  },
2101 
2102  applyProjection: function ( m ) {
2103 
2104  // input: THREE.Matrix4 projection matrix
2105 
2106  var x = this.x, y = this.y, z = this.z;
2107 
2108  var e = m.elements;
2109  var d = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); // perspective divide
2110 
2111  this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * d;
2112  this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * d;
2113  this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * d;
2114 
2115  return this;
2116 
2117  },
2118 
2119  applyQuaternion: function ( q ) {
2120 
2121  var x = this.x;
2122  var y = this.y;
2123  var z = this.z;
2124 
2125  var qx = q.x;
2126  var qy = q.y;
2127  var qz = q.z;
2128  var qw = q.w;
2129 
2130  // calculate quat * vector
2131 
2132  var ix = qw * x + qy * z - qz * y;
2133  var iy = qw * y + qz * x - qx * z;
2134  var iz = qw * z + qx * y - qy * x;
2135  var iw = - qx * x - qy * y - qz * z;
2136 
2137  // calculate result * inverse quat
2138 
2139  this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
2140  this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
2141  this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
2142 
2143  return this;
2144 
2145  },
2146 
2147  project: function () {
2148 
2149  var matrix;
2150 
2151  return function project( camera ) {
2152 
2153  if ( matrix === undefined ) matrix = new THREE.Matrix4();
2154 
2155  matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
2156  return this.applyProjection( matrix );
2157 
2158  };
2159 
2160  }(),
2161 
2162  unproject: function () {
2163 
2164  var matrix;
2165 
2166  return function unproject( camera ) {
2167 
2168  if ( matrix === undefined ) matrix = new THREE.Matrix4();
2169 
2170  matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) );
2171  return this.applyProjection( matrix );
2172 
2173  };
2174 
2175  }(),
2176 
2177  transformDirection: function ( m ) {
2178 
2179  // input: THREE.Matrix4 affine matrix
2180  // vector interpreted as a direction
2181 
2182  var x = this.x, y = this.y, z = this.z;
2183 
2184  var e = m.elements;
2185 
2186  this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
2187  this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
2188  this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
2189 
2190  this.normalize();
2191 
2192  return this;
2193 
2194  },
2195 
2196  divide: function ( v ) {
2197 
2198  this.x /= v.x;
2199  this.y /= v.y;
2200  this.z /= v.z;
2201 
2202  return this;
2203 
2204  },
2205 
2206  divideScalar: function ( scalar ) {
2207 
2208  return this.multiplyScalar( 1 / scalar );
2209 
2210  },
2211 
2212  min: function ( v ) {
2213 
2214  this.x = Math.min( this.x, v.x );
2215  this.y = Math.min( this.y, v.y );
2216  this.z = Math.min( this.z, v.z );
2217 
2218  return this;
2219 
2220  },
2221 
2222  max: function ( v ) {
2223 
2224  this.x = Math.max( this.x, v.x );
2225  this.y = Math.max( this.y, v.y );
2226  this.z = Math.max( this.z, v.z );
2227 
2228  return this;
2229 
2230  },
2231 
2232  clamp: function ( min, max ) {
2233 
2234  // This function assumes min < max, if this assumption isn't true it will not operate correctly
2235 
2236  this.x = Math.max( min.x, Math.min( max.x, this.x ) );
2237  this.y = Math.max( min.y, Math.min( max.y, this.y ) );
2238  this.z = Math.max( min.z, Math.min( max.z, this.z ) );
2239 
2240  return this;
2241 
2242  },
2243 
2244  clampScalar: function () {
2245 
2246  var min, max;
2247 
2248  return function clampScalar( minVal, maxVal ) {
2249 
2250  if ( min === undefined ) {
2251 
2252  min = new THREE.Vector3();
2253  max = new THREE.Vector3();
2254 
2255  }
2256 
2257  min.set( minVal, minVal, minVal );
2258  max.set( maxVal, maxVal, maxVal );
2259 
2260  return this.clamp( min, max );
2261 
2262  };
2263 
2264  }(),
2265 
2266  clampLength: function ( min, max ) {
2267 
2268  var length = this.length();
2269 
2270  this.multiplyScalar( Math.max( min, Math.min( max, length ) ) / length );
2271 
2272  return this;
2273 
2274  },
2275 
2276  floor: function () {
2277 
2278  this.x = Math.floor( this.x );
2279  this.y = Math.floor( this.y );
2280  this.z = Math.floor( this.z );
2281 
2282  return this;
2283 
2284  },
2285 
2286  ceil: function () {
2287 
2288  this.x = Math.ceil( this.x );
2289  this.y = Math.ceil( this.y );
2290  this.z = Math.ceil( this.z );
2291 
2292  return this;
2293 
2294  },
2295 
2296  round: function () {
2297 
2298  this.x = Math.round( this.x );
2299  this.y = Math.round( this.y );
2300  this.z = Math.round( this.z );
2301 
2302  return this;
2303 
2304  },
2305 
2306  roundToZero: function () {
2307 
2308  this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
2309  this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
2310  this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
2311 
2312  return this;
2313 
2314  },
2315 
2316  negate: function () {
2317 
2318  this.x = - this.x;
2319  this.y = - this.y;
2320  this.z = - this.z;
2321 
2322  return this;
2323 
2324  },
2325 
2326  dot: function ( v ) {
2327 
2328  return this.x * v.x + this.y * v.y + this.z * v.z;
2329 
2330  },
2331 
2332  lengthSq: function () {
2333 
2334  return this.x * this.x + this.y * this.y + this.z * this.z;
2335 
2336  },
2337 
2338  length: function () {
2339 
2340  return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
2341 
2342  },
2343 
2344  lengthManhattan: function () {
2345 
2346  return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
2347 
2348  },
2349 
2350  normalize: function () {
2351 
2352  return this.divideScalar( this.length() );
2353 
2354  },
2355 
2356  setLength: function ( length ) {
2357 
2358  return this.multiplyScalar( length / this.length() );
2359 
2360  },
2361 
2362  lerp: function ( v, alpha ) {
2363 
2364  this.x += ( v.x - this.x ) * alpha;
2365  this.y += ( v.y - this.y ) * alpha;
2366  this.z += ( v.z - this.z ) * alpha;
2367 
2368  return this;
2369 
2370  },
2371 
2372  lerpVectors: function ( v1, v2, alpha ) {
2373 
2374  this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
2375 
2376  return this;
2377 
2378  },
2379 
2380  cross: function ( v, w ) {
2381 
2382  if ( w !== undefined ) {
2383 
2384  console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
2385  return this.crossVectors( v, w );
2386 
2387  }
2388 
2389  var x = this.x, y = this.y, z = this.z;
2390 
2391  this.x = y * v.z - z * v.y;
2392  this.y = z * v.x - x * v.z;
2393  this.z = x * v.y - y * v.x;
2394 
2395  return this;
2396 
2397  },
2398 
2399  crossVectors: function ( a, b ) {
2400 
2401  var ax = a.x, ay = a.y, az = a.z;
2402  var bx = b.x, by = b.y, bz = b.z;
2403 
2404  this.x = ay * bz - az * by;
2405  this.y = az * bx - ax * bz;
2406  this.z = ax * by - ay * bx;
2407 
2408  return this;
2409 
2410  },
2411 
2412  projectOnVector: function () {
2413 
2414  var v1, dot;
2415 
2416  return function projectOnVector( vector ) {
2417 
2418  if ( v1 === undefined ) v1 = new THREE.Vector3();
2419 
2420  v1.copy( vector ).normalize();
2421 
2422  dot = this.dot( v1 );
2423 
2424  return this.copy( v1 ).multiplyScalar( dot );
2425 
2426  };
2427 
2428  }(),
2429 
2430  projectOnPlane: function () {
2431 
2432  var v1;
2433 
2434  return function projectOnPlane( planeNormal ) {
2435 
2436  if ( v1 === undefined ) v1 = new THREE.Vector3();
2437 
2438  v1.copy( this ).projectOnVector( planeNormal );
2439 
2440  return this.sub( v1 );
2441 
2442  }
2443 
2444  }(),
2445 
2446  reflect: function () {
2447 
2448  // reflect incident vector off plane orthogonal to normal
2449  // normal is assumed to have unit length
2450 
2451  var v1;
2452 
2453  return function reflect( normal ) {
2454 
2455  if ( v1 === undefined ) v1 = new THREE.Vector3();
2456 
2457  return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
2458 
2459  }
2460 
2461  }(),
2462 
2463  angleTo: function ( v ) {
2464 
2465  var theta = this.dot( v ) / ( this.length() * v.length() );
2466 
2467  // clamp, to handle numerical problems
2468 
2469  return Math.acos( THREE.Math.clamp( theta, - 1, 1 ) );
2470 
2471  },
2472 
2473  distanceTo: function ( v ) {
2474 
2475  return Math.sqrt( this.distanceToSquared( v ) );
2476 
2477  },
2478 
2479  distanceToSquared: function ( v ) {
2480 
2481  var dx = this.x - v.x;
2482  var dy = this.y - v.y;
2483  var dz = this.z - v.z;
2484 
2485  return dx * dx + dy * dy + dz * dz;
2486 
2487  },
2488 
2489  setEulerFromRotationMatrix: function ( m, order ) {
2490 
2491  console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
2492 
2493  },
2494 
2495  setEulerFromQuaternion: function ( q, order ) {
2496 
2497  console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
2498 
2499  },
2500 
2501  getPositionFromMatrix: function ( m ) {
2502 
2503  console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
2504 
2505  return this.setFromMatrixPosition( m );
2506 
2507  },
2508 
2509  getScaleFromMatrix: function ( m ) {
2510 
2511  console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
2512 
2513  return this.setFromMatrixScale( m );
2514 
2515  },
2516 
2517  getColumnFromMatrix: function ( index, matrix ) {
2518 
2519  console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
2520 
2521  return this.setFromMatrixColumn( index, matrix );
2522 
2523  },
2524 
2525  setFromMatrixPosition: function ( m ) {
2526 
2527  this.x = m.elements[ 12 ];
2528  this.y = m.elements[ 13 ];
2529  this.z = m.elements[ 14 ];
2530 
2531  return this;
2532 
2533  },
2534 
2535  setFromMatrixScale: function ( m ) {
2536 
2537  var sx = this.set( m.elements[ 0 ], m.elements[ 1 ], m.elements[ 2 ] ).length();
2538  var sy = this.set( m.elements[ 4 ], m.elements[ 5 ], m.elements[ 6 ] ).length();
2539  var sz = this.set( m.elements[ 8 ], m.elements[ 9 ], m.elements[ 10 ] ).length();
2540 
2541  this.x = sx;
2542  this.y = sy;
2543  this.z = sz;
2544 
2545  return this;
2546 
2547  },
2548 
2549  setFromMatrixColumn: function ( index, matrix ) {
2550 
2551  var offset = index * 4;
2552 
2553  var me = matrix.elements;
2554 
2555  this.x = me[ offset ];
2556  this.y = me[ offset + 1 ];
2557  this.z = me[ offset + 2 ];
2558 
2559  return this;
2560 
2561  },
2562 
2563  equals: function ( v ) {
2564 
2565  return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
2566 
2567  },
2568 
2569  fromArray: function ( array, offset ) {
2570 
2571  if ( offset === undefined ) offset = 0;
2572 
2573  this.x = array[ offset ];
2574  this.y = array[ offset + 1 ];
2575  this.z = array[ offset + 2 ];
2576 
2577  return this;
2578 
2579  },
2580 
2581  toArray: function ( array, offset ) {
2582 
2583  if ( array === undefined ) array = [];
2584  if ( offset === undefined ) offset = 0;
2585 
2586  array[ offset ] = this.x;
2587  array[ offset + 1 ] = this.y;
2588  array[ offset + 2 ] = this.z;
2589 
2590  return array;
2591 
2592  },
2593 
2594  fromAttribute: function ( attribute, index, offset ) {
2595 
2596  if ( offset === undefined ) offset = 0;
2597 
2598  index = index * attribute.itemSize + offset;
2599 
2600  this.x = attribute.array[ index ];
2601  this.y = attribute.array[ index + 1 ];
2602  this.z = attribute.array[ index + 2 ];
2603 
2604  return this;
2605 
2606  }
2607 
2608 };
2609 
2610 // File:src/math/Vector4.js
2611 
2620 THREE.Vector4 = function ( x, y, z, w ) {
2621 
2622  this.x = x || 0;
2623  this.y = y || 0;
2624  this.z = z || 0;
2625  this.w = ( w !== undefined ) ? w : 1;
2626 
2627 };
2628 
2629 THREE.Vector4.prototype = {
2630 
2631  constructor: THREE.Vector4,
2632 
2633  set: function ( x, y, z, w ) {
2634 
2635  this.x = x;
2636  this.y = y;
2637  this.z = z;
2638  this.w = w;
2639 
2640  return this;
2641 
2642  },
2643 
2644  setX: function ( x ) {
2645 
2646  this.x = x;
2647 
2648  return this;
2649 
2650  },
2651 
2652  setY: function ( y ) {
2653 
2654  this.y = y;
2655 
2656  return this;
2657 
2658  },
2659 
2660  setZ: function ( z ) {
2661 
2662  this.z = z;
2663 
2664  return this;
2665 
2666  },
2667 
2668  setW: function ( w ) {
2669 
2670  this.w = w;
2671 
2672  return this;
2673 
2674  },
2675 
2676  setComponent: function ( index, value ) {
2677 
2678  switch ( index ) {
2679 
2680  case 0: this.x = value; break;
2681  case 1: this.y = value; break;
2682  case 2: this.z = value; break;
2683  case 3: this.w = value; break;
2684  default: throw new Error( 'index is out of range: ' + index );
2685 
2686  }
2687 
2688  },
2689 
2690  getComponent: function ( index ) {
2691 
2692  switch ( index ) {
2693 
2694  case 0: return this.x;
2695  case 1: return this.y;
2696  case 2: return this.z;
2697  case 3: return this.w;
2698  default: throw new Error( 'index is out of range: ' + index );
2699 
2700  }
2701 
2702  },
2703 
2704  clone: function () {
2705 
2706  return new this.constructor( this.x, this.y, this.z, this.w );
2707 
2708  },
2709 
2710  copy: function ( v ) {
2711 
2712  this.x = v.x;
2713  this.y = v.y;
2714  this.z = v.z;
2715  this.w = ( v.w !== undefined ) ? v.w : 1;
2716 
2717  return this;
2718 
2719  },
2720 
2721  add: function ( v, w ) {
2722 
2723  if ( w !== undefined ) {
2724 
2725  console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
2726  return this.addVectors( v, w );
2727 
2728  }
2729 
2730  this.x += v.x;
2731  this.y += v.y;
2732  this.z += v.z;
2733  this.w += v.w;
2734 
2735  return this;
2736 
2737  },
2738 
2739  addScalar: function ( s ) {
2740 
2741  this.x += s;
2742  this.y += s;
2743  this.z += s;
2744  this.w += s;
2745 
2746  return this;
2747 
2748  },
2749 
2750  addVectors: function ( a, b ) {
2751 
2752  this.x = a.x + b.x;
2753  this.y = a.y + b.y;
2754  this.z = a.z + b.z;
2755  this.w = a.w + b.w;
2756 
2757  return this;
2758 
2759  },
2760 
2761  addScaledVector: function ( v, s ) {
2762 
2763  this.x += v.x * s;
2764  this.y += v.y * s;
2765  this.z += v.z * s;
2766  this.w += v.w * s;
2767 
2768  return this;
2769 
2770  },
2771 
2772  sub: function ( v, w ) {
2773 
2774  if ( w !== undefined ) {
2775 
2776  console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
2777  return this.subVectors( v, w );
2778 
2779  }
2780 
2781  this.x -= v.x;
2782  this.y -= v.y;
2783  this.z -= v.z;
2784  this.w -= v.w;
2785 
2786  return this;
2787 
2788  },
2789 
2790  subScalar: function ( s ) {
2791 
2792  this.x -= s;
2793  this.y -= s;
2794  this.z -= s;
2795  this.w -= s;
2796 
2797  return this;
2798 
2799  },
2800 
2801  subVectors: function ( a, b ) {
2802 
2803  this.x = a.x - b.x;
2804  this.y = a.y - b.y;
2805  this.z = a.z - b.z;
2806  this.w = a.w - b.w;
2807 
2808  return this;
2809 
2810  },
2811 
2812  multiplyScalar: function ( scalar ) {
2813 
2814  if ( isFinite( scalar ) ) {
2815  this.x *= scalar;
2816  this.y *= scalar;
2817  this.z *= scalar;
2818  this.w *= scalar;
2819  } else {
2820  this.x = 0;
2821  this.y = 0;
2822  this.z = 0;
2823  this.w = 0;
2824  }
2825 
2826  return this;
2827 
2828  },
2829 
2830  applyMatrix4: function ( m ) {
2831 
2832  var x = this.x;
2833  var y = this.y;
2834  var z = this.z;
2835  var w = this.w;
2836 
2837  var e = m.elements;
2838 
2839  this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
2840  this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
2841  this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
2842  this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
2843 
2844  return this;
2845 
2846  },
2847 
2848  divideScalar: function ( scalar ) {
2849 
2850  return this.multiplyScalar( 1 / scalar );
2851 
2852  },
2853 
2854  setAxisAngleFromQuaternion: function ( q ) {
2855 
2856  // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
2857 
2858  // q is assumed to be normalized
2859 
2860  this.w = 2 * Math.acos( q.w );
2861 
2862  var s = Math.sqrt( 1 - q.w * q.w );
2863 
2864  if ( s < 0.0001 ) {
2865 
2866  this.x = 1;
2867  this.y = 0;
2868  this.z = 0;
2869 
2870  } else {
2871 
2872  this.x = q.x / s;
2873  this.y = q.y / s;
2874  this.z = q.z / s;
2875 
2876  }
2877 
2878  return this;
2879 
2880  },
2881 
2882  setAxisAngleFromRotationMatrix: function ( m ) {
2883 
2884  // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
2885 
2886  // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2887 
2888  var angle, x, y, z, // variables for result
2889  epsilon = 0.01, // margin to allow for rounding errors
2890  epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees
2891 
2892  te = m.elements,
2893 
2894  m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2895  m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2896  m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
2897 
2898  if ( ( Math.abs( m12 - m21 ) < epsilon )
2899  && ( Math.abs( m13 - m31 ) < epsilon )
2900  && ( Math.abs( m23 - m32 ) < epsilon ) ) {
2901 
2902  // singularity found
2903  // first check for identity matrix which must have +1 for all terms
2904  // in leading diagonal and zero in other terms
2905 
2906  if ( ( Math.abs( m12 + m21 ) < epsilon2 )
2907  && ( Math.abs( m13 + m31 ) < epsilon2 )
2908  && ( Math.abs( m23 + m32 ) < epsilon2 )
2909  && ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
2910 
2911  // this singularity is identity matrix so angle = 0
2912 
2913  this.set( 1, 0, 0, 0 );
2914 
2915  return this; // zero angle, arbitrary axis
2916 
2917  }
2918 
2919  // otherwise this singularity is angle = 180
2920 
2921  angle = Math.PI;
2922 
2923  var xx = ( m11 + 1 ) / 2;
2924  var yy = ( m22 + 1 ) / 2;
2925  var zz = ( m33 + 1 ) / 2;
2926  var xy = ( m12 + m21 ) / 4;
2927  var xz = ( m13 + m31 ) / 4;
2928  var yz = ( m23 + m32 ) / 4;
2929 
2930  if ( ( xx > yy ) && ( xx > zz ) ) {
2931 
2932  // m11 is the largest diagonal term
2933 
2934  if ( xx < epsilon ) {
2935 
2936  x = 0;
2937  y = 0.707106781;
2938  z = 0.707106781;
2939 
2940  } else {
2941 
2942  x = Math.sqrt( xx );
2943  y = xy / x;
2944  z = xz / x;
2945 
2946  }
2947 
2948  } else if ( yy > zz ) {
2949 
2950  // m22 is the largest diagonal term
2951 
2952  if ( yy < epsilon ) {
2953 
2954  x = 0.707106781;
2955  y = 0;
2956  z = 0.707106781;
2957 
2958  } else {
2959 
2960  y = Math.sqrt( yy );
2961  x = xy / y;
2962  z = yz / y;
2963 
2964  }
2965 
2966  } else {
2967 
2968  // m33 is the largest diagonal term so base result on this
2969 
2970  if ( zz < epsilon ) {
2971 
2972  x = 0.707106781;
2973  y = 0.707106781;
2974  z = 0;
2975 
2976  } else {
2977 
2978  z = Math.sqrt( zz );
2979  x = xz / z;
2980  y = yz / z;
2981 
2982  }
2983 
2984  }
2985 
2986  this.set( x, y, z, angle );
2987 
2988  return this; // return 180 deg rotation
2989 
2990  }
2991 
2992  // as we have reached here there are no singularities so we can handle normally
2993 
2994  var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 )
2995  + ( m13 - m31 ) * ( m13 - m31 )
2996  + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
2997 
2998  if ( Math.abs( s ) < 0.001 ) s = 1;
2999 
3000  // prevent divide by zero, should not happen if matrix is orthogonal and should be
3001  // caught by singularity test above, but I've left it in just in case
3002 
3003  this.x = ( m32 - m23 ) / s;
3004  this.y = ( m13 - m31 ) / s;
3005  this.z = ( m21 - m12 ) / s;
3006  this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
3007 
3008  return this;
3009 
3010  },
3011 
3012  min: function ( v ) {
3013 
3014  this.x = Math.min( this.x, v.x );
3015  this.y = Math.min( this.y, v.y );
3016  this.z = Math.min( this.z, v.z );
3017  this.w = Math.min( this.w, v.w );
3018 
3019  return this;
3020 
3021  },
3022 
3023  max: function ( v ) {
3024 
3025  this.x = Math.max( this.x, v.x );
3026  this.y = Math.max( this.y, v.y );
3027  this.z = Math.max( this.z, v.z );
3028  this.w = Math.max( this.w, v.w );
3029 
3030  return this;
3031 
3032  },
3033 
3034  clamp: function ( min, max ) {
3035 
3036  // This function assumes min < max, if this assumption isn't true it will not operate correctly
3037 
3038  this.x = Math.max( min.x, Math.min( max.x, this.x ) );
3039  this.y = Math.max( min.y, Math.min( max.y, this.y ) );
3040  this.z = Math.max( min.z, Math.min( max.z, this.z ) );
3041  this.w = Math.max( min.w, Math.min( max.w, this.w ) );
3042 
3043  return this;
3044 
3045  },
3046 
3047  clampScalar: function () {
3048 
3049  var min, max;
3050 
3051  return function clampScalar( minVal, maxVal ) {
3052 
3053  if ( min === undefined ) {
3054 
3055  min = new THREE.Vector4();
3056  max = new THREE.Vector4();
3057 
3058  }
3059 
3060  min.set( minVal, minVal, minVal, minVal );
3061  max.set( maxVal, maxVal, maxVal, maxVal );
3062 
3063  return this.clamp( min, max );
3064 
3065  };
3066 
3067  }(),
3068 
3069  floor: function () {
3070 
3071  this.x = Math.floor( this.x );
3072  this.y = Math.floor( this.y );
3073  this.z = Math.floor( this.z );
3074  this.w = Math.floor( this.w );
3075 
3076  return this;
3077 
3078  },
3079 
3080  ceil: function () {
3081 
3082  this.x = Math.ceil( this.x );
3083  this.y = Math.ceil( this.y );
3084  this.z = Math.ceil( this.z );
3085  this.w = Math.ceil( this.w );
3086 
3087  return this;
3088 
3089  },
3090 
3091  round: function () {
3092 
3093  this.x = Math.round( this.x );
3094  this.y = Math.round( this.y );
3095  this.z = Math.round( this.z );
3096  this.w = Math.round( this.w );
3097 
3098  return this;
3099 
3100  },
3101 
3102  roundToZero: function () {
3103 
3104  this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
3105  this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
3106  this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
3107  this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
3108 
3109  return this;
3110 
3111  },
3112 
3113  negate: function () {
3114 
3115  this.x = - this.x;
3116  this.y = - this.y;
3117  this.z = - this.z;
3118  this.w = - this.w;
3119 
3120  return this;
3121 
3122  },
3123 
3124  dot: function ( v ) {
3125 
3126  return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
3127 
3128  },
3129 
3130  lengthSq: function () {
3131 
3132  return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
3133 
3134  },
3135 
3136  length: function () {
3137 
3138  return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
3139 
3140  },
3141 
3142  lengthManhattan: function () {
3143 
3144  return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
3145 
3146  },
3147 
3148  normalize: function () {
3149 
3150  return this.divideScalar( this.length() );
3151 
3152  },
3153 
3154  setLength: function ( length ) {
3155 
3156  return this.multiplyScalar( length / this.length() );
3157 
3158  },
3159 
3160  lerp: function ( v, alpha ) {
3161 
3162  this.x += ( v.x - this.x ) * alpha;
3163  this.y += ( v.y - this.y ) * alpha;
3164  this.z += ( v.z - this.z ) * alpha;
3165  this.w += ( v.w - this.w ) * alpha;
3166 
3167  return this;
3168 
3169  },
3170 
3171  lerpVectors: function ( v1, v2, alpha ) {
3172 
3173  this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
3174 
3175  return this;
3176 
3177  },
3178 
3179  equals: function ( v ) {
3180 
3181  return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
3182 
3183  },
3184 
3185  fromArray: function ( array, offset ) {
3186 
3187  if ( offset === undefined ) offset = 0;
3188 
3189  this.x = array[ offset ];
3190  this.y = array[ offset + 1 ];
3191  this.z = array[ offset + 2 ];
3192  this.w = array[ offset + 3 ];
3193 
3194  return this;
3195 
3196  },
3197 
3198  toArray: function ( array, offset ) {
3199 
3200  if ( array === undefined ) array = [];
3201  if ( offset === undefined ) offset = 0;
3202 
3203  array[ offset ] = this.x;
3204  array[ offset + 1 ] = this.y;
3205  array[ offset + 2 ] = this.z;
3206  array[ offset + 3 ] = this.w;
3207 
3208  return array;
3209 
3210  },
3211 
3212  fromAttribute: function ( attribute, index, offset ) {
3213 
3214  if ( offset === undefined ) offset = 0;
3215 
3216  index = index * attribute.itemSize + offset;
3217 
3218  this.x = attribute.array[ index ];
3219  this.y = attribute.array[ index + 1 ];
3220  this.z = attribute.array[ index + 2 ];
3221  this.w = attribute.array[ index + 3 ];
3222 
3223  return this;
3224 
3225  }
3226 
3227 };
3228 
3229 // File:src/math/Euler.js
3230 
3237 THREE.Euler = function ( x, y, z, order ) {
3238 
3239  this._x = x || 0;
3240  this._y = y || 0;
3241  this._z = z || 0;
3242  this._order = order || THREE.Euler.DefaultOrder;
3243 
3244 };
3245 
3246 THREE.Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
3247 
3248 THREE.Euler.DefaultOrder = 'XYZ';
3249 
3250 THREE.Euler.prototype = {
3251 
3252  constructor: THREE.Euler,
3253 
3254  get x () {
3255 
3256  return this._x;
3257 
3258  },
3259 
3260  set x ( value ) {
3261 
3262  this._x = value;
3263  this.onChangeCallback();
3264 
3265  },
3266 
3267  get y () {
3268 
3269  return this._y;
3270 
3271  },
3272 
3273  set y ( value ) {
3274 
3275  this._y = value;
3276  this.onChangeCallback();
3277 
3278  },
3279 
3280  get z () {
3281 
3282  return this._z;
3283 
3284  },
3285 
3286  set z ( value ) {
3287 
3288  this._z = value;
3289  this.onChangeCallback();
3290 
3291  },
3292 
3293  get order () {
3294 
3295  return this._order;
3296 
3297  },
3298 
3299  set order ( value ) {
3300 
3301  this._order = value;
3302  this.onChangeCallback();
3303 
3304  },
3305 
3306  set: function ( x, y, z, order ) {
3307 
3308  this._x = x;
3309  this._y = y;
3310  this._z = z;
3311  this._order = order || this._order;
3312 
3313  this.onChangeCallback();
3314 
3315  return this;
3316 
3317  },
3318 
3319  clone: function () {
3320 
3321  return new this.constructor( this._x, this._y, this._z, this._order);
3322 
3323  },
3324 
3325  copy: function ( euler ) {
3326 
3327  this._x = euler._x;
3328  this._y = euler._y;
3329  this._z = euler._z;
3330  this._order = euler._order;
3331 
3332  this.onChangeCallback();
3333 
3334  return this;
3335 
3336  },
3337 
3338  setFromRotationMatrix: function ( m, order, update ) {
3339 
3340  var clamp = THREE.Math.clamp;
3341 
3342  // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
3343 
3344  var te = m.elements;
3345  var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
3346  var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
3347  var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
3348 
3349  order = order || this._order;
3350 
3351  if ( order === 'XYZ' ) {
3352 
3353  this._y = Math.asin( clamp( m13, - 1, 1 ) );
3354 
3355  if ( Math.abs( m13 ) < 0.99999 ) {
3356 
3357  this._x = Math.atan2( - m23, m33 );
3358  this._z = Math.atan2( - m12, m11 );
3359 
3360  } else {
3361 
3362  this._x = Math.atan2( m32, m22 );
3363  this._z = 0;
3364 
3365  }
3366 
3367  } else if ( order === 'YXZ' ) {
3368 
3369  this._x = Math.asin( - clamp( m23, - 1, 1 ) );
3370 
3371  if ( Math.abs( m23 ) < 0.99999 ) {
3372 
3373  this._y = Math.atan2( m13, m33 );
3374  this._z = Math.atan2( m21, m22 );
3375 
3376  } else {
3377 
3378  this._y = Math.atan2( - m31, m11 );
3379  this._z = 0;
3380 
3381  }
3382 
3383  } else if ( order === 'ZXY' ) {
3384 
3385  this._x = Math.asin( clamp( m32, - 1, 1 ) );
3386 
3387  if ( Math.abs( m32 ) < 0.99999 ) {
3388 
3389  this._y = Math.atan2( - m31, m33 );
3390  this._z = Math.atan2( - m12, m22 );
3391 
3392  } else {
3393 
3394  this._y = 0;
3395  this._z = Math.atan2( m21, m11 );
3396 
3397  }
3398 
3399  } else if ( order === 'ZYX' ) {
3400 
3401  this._y = Math.asin( - clamp( m31, - 1, 1 ) );
3402 
3403  if ( Math.abs( m31 ) < 0.99999 ) {
3404 
3405  this._x = Math.atan2( m32, m33 );
3406  this._z = Math.atan2( m21, m11 );
3407 
3408  } else {
3409 
3410  this._x = 0;
3411  this._z = Math.atan2( - m12, m22 );
3412 
3413  }
3414 
3415  } else if ( order === 'YZX' ) {
3416 
3417  this._z = Math.asin( clamp( m21, - 1, 1 ) );
3418 
3419  if ( Math.abs( m21 ) < 0.99999 ) {
3420 
3421  this._x = Math.atan2( - m23, m22 );
3422  this._y = Math.atan2( - m31, m11 );
3423 
3424  } else {
3425 
3426  this._x = 0;
3427  this._y = Math.atan2( m13, m33 );
3428 
3429  }
3430 
3431  } else if ( order === 'XZY' ) {
3432 
3433  this._z = Math.asin( - clamp( m12, - 1, 1 ) );
3434 
3435  if ( Math.abs( m12 ) < 0.99999 ) {
3436 
3437  this._x = Math.atan2( m32, m22 );
3438  this._y = Math.atan2( m13, m11 );
3439 
3440  } else {
3441 
3442  this._x = Math.atan2( - m23, m33 );
3443  this._y = 0;
3444 
3445  }
3446 
3447  } else {
3448 
3449  console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order )
3450 
3451  }
3452 
3453  this._order = order;
3454 
3455  if ( update !== false ) this.onChangeCallback();
3456 
3457  return this;
3458 
3459  },
3460 
3461  setFromQuaternion: function () {
3462 
3463  var matrix;
3464 
3465  return function ( q, order, update ) {
3466 
3467  if ( matrix === undefined ) matrix = new THREE.Matrix4();
3468  matrix.makeRotationFromQuaternion( q );
3469  this.setFromRotationMatrix( matrix, order, update );
3470 
3471  return this;
3472 
3473  };
3474 
3475  }(),
3476 
3477  setFromVector3: function ( v, order ) {
3478 
3479  return this.set( v.x, v.y, v.z, order || this._order );
3480 
3481  },
3482 
3483  reorder: function () {
3484 
3485  // WARNING: this discards revolution information -bhouston
3486 
3487  var q = new THREE.Quaternion();
3488 
3489  return function ( newOrder ) {
3490 
3491  q.setFromEuler( this );
3492  this.setFromQuaternion( q, newOrder );
3493 
3494  };
3495 
3496  }(),
3497 
3498  equals: function ( euler ) {
3499 
3500  return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
3501 
3502  },
3503 
3504  fromArray: function ( array ) {
3505 
3506  this._x = array[ 0 ];
3507  this._y = array[ 1 ];
3508  this._z = array[ 2 ];
3509  if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
3510 
3511  this.onChangeCallback();
3512 
3513  return this;
3514 
3515  },
3516 
3517  toArray: function ( array, offset ) {
3518 
3519  if ( array === undefined ) array = [];
3520  if ( offset === undefined ) offset = 0;
3521 
3522  array[ offset ] = this._x;
3523  array[ offset + 1 ] = this._y;
3524  array[ offset + 2 ] = this._z;
3525  array[ offset + 3 ] = this._order;
3526 
3527  return array;
3528 
3529  },
3530 
3531  toVector3: function ( optionalResult ) {
3532 
3533  if ( optionalResult ) {
3534 
3535  return optionalResult.set( this._x, this._y, this._z );
3536 
3537  } else {
3538 
3539  return new THREE.Vector3( this._x, this._y, this._z );
3540 
3541  }
3542 
3543  },
3544 
3545  onChange: function ( callback ) {
3546 
3547  this.onChangeCallback = callback;
3548 
3549  return this;
3550 
3551  },
3552 
3553  onChangeCallback: function () {}
3554 
3555 };
3556 
3557 // File:src/math/Line3.js
3558 
3563 THREE.Line3 = function ( start, end ) {
3564 
3565  this.start = ( start !== undefined ) ? start : new THREE.Vector3();
3566  this.end = ( end !== undefined ) ? end : new THREE.Vector3();
3567 
3568 };
3569 
3570 THREE.Line3.prototype = {
3571 
3572  constructor: THREE.Line3,
3573 
3574  set: function ( start, end ) {
3575 
3576  this.start.copy( start );
3577  this.end.copy( end );
3578 
3579  return this;
3580 
3581  },
3582 
3583  clone: function () {
3584 
3585  return new this.constructor().copy( this );
3586 
3587  },
3588 
3589  copy: function ( line ) {
3590 
3591  this.start.copy( line.start );
3592  this.end.copy( line.end );
3593 
3594  return this;
3595 
3596  },
3597 
3598  center: function ( optionalTarget ) {
3599 
3600  var result = optionalTarget || new THREE.Vector3();
3601  return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
3602 
3603  },
3604 
3605  delta: function ( optionalTarget ) {
3606 
3607  var result = optionalTarget || new THREE.Vector3();
3608  return result.subVectors( this.end, this.start );
3609 
3610  },
3611 
3612  distanceSq: function () {
3613 
3614  return this.start.distanceToSquared( this.end );
3615 
3616  },
3617 
3618  distance: function () {
3619 
3620  return this.start.distanceTo( this.end );
3621 
3622  },
3623 
3624  at: function ( t, optionalTarget ) {
3625 
3626  var result = optionalTarget || new THREE.Vector3();
3627 
3628  return this.delta( result ).multiplyScalar( t ).add( this.start );
3629 
3630  },
3631 
3632  closestPointToPointParameter: function () {
3633 
3634  var startP = new THREE.Vector3();
3635  var startEnd = new THREE.Vector3();
3636 
3637  return function ( point, clampToLine ) {
3638 
3639  startP.subVectors( point, this.start );
3640  startEnd.subVectors( this.end, this.start );
3641 
3642  var startEnd2 = startEnd.dot( startEnd );
3643  var startEnd_startP = startEnd.dot( startP );
3644 
3645  var t = startEnd_startP / startEnd2;
3646 
3647  if ( clampToLine ) {
3648 
3649  t = THREE.Math.clamp( t, 0, 1 );
3650 
3651  }
3652 
3653  return t;
3654 
3655  };
3656 
3657  }(),
3658 
3659  closestPointToPoint: function ( point, clampToLine, optionalTarget ) {
3660 
3661  var t = this.closestPointToPointParameter( point, clampToLine );
3662 
3663  var result = optionalTarget || new THREE.Vector3();
3664 
3665  return this.delta( result ).multiplyScalar( t ).add( this.start );
3666 
3667  },
3668 
3669  applyMatrix4: function ( matrix ) {
3670 
3671  this.start.applyMatrix4( matrix );
3672  this.end.applyMatrix4( matrix );
3673 
3674  return this;
3675 
3676  },
3677 
3678  equals: function ( line ) {
3679 
3680  return line.start.equals( this.start ) && line.end.equals( this.end );
3681 
3682  }
3683 
3684 };
3685 
3686 // File:src/math/Box2.js
3687 
3692 THREE.Box2 = function ( min, max ) {
3693 
3694  this.min = ( min !== undefined ) ? min : new THREE.Vector2( Infinity, Infinity );
3695  this.max = ( max !== undefined ) ? max : new THREE.Vector2( - Infinity, - Infinity );
3696 
3697 };
3698 
3699 THREE.Box2.prototype = {
3700 
3701  constructor: THREE.Box2,
3702 
3703  set: function ( min, max ) {
3704 
3705  this.min.copy( min );
3706  this.max.copy( max );
3707 
3708  return this;
3709 
3710  },
3711 
3712  setFromPoints: function ( points ) {
3713 
3714  this.makeEmpty();
3715 
3716  for ( var i = 0, il = points.length; i < il; i ++ ) {
3717 
3718  this.expandByPoint( points[ i ] )
3719 
3720  }
3721 
3722  return this;
3723 
3724  },
3725 
3726  setFromCenterAndSize: function () {
3727 
3728  var v1 = new THREE.Vector2();
3729 
3730  return function ( center, size ) {
3731 
3732  var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
3733  this.min.copy( center ).sub( halfSize );
3734  this.max.copy( center ).add( halfSize );
3735 
3736  return this;
3737 
3738  };
3739 
3740  }(),
3741 
3742  clone: function () {
3743 
3744  return new this.constructor().copy( this );
3745 
3746  },
3747 
3748  copy: function ( box ) {
3749 
3750  this.min.copy( box.min );
3751  this.max.copy( box.max );
3752 
3753  return this;
3754 
3755  },
3756 
3757  makeEmpty: function () {
3758 
3759  this.min.x = this.min.y = Infinity;
3760  this.max.x = this.max.y = - Infinity;
3761 
3762  return this;
3763 
3764  },
3765 
3766  empty: function () {
3767 
3768  // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
3769 
3770  return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
3771 
3772  },
3773 
3774  center: function ( optionalTarget ) {
3775 
3776  var result = optionalTarget || new THREE.Vector2();
3777  return result.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
3778 
3779  },
3780 
3781  size: function ( optionalTarget ) {
3782 
3783  var result = optionalTarget || new THREE.Vector2();
3784  return result.subVectors( this.max, this.min );
3785 
3786  },
3787 
3788  expandByPoint: function ( point ) {
3789 
3790  this.min.min( point );
3791  this.max.max( point );
3792 
3793  return this;
3794 
3795  },
3796 
3797  expandByVector: function ( vector ) {
3798 
3799  this.min.sub( vector );
3800  this.max.add( vector );
3801 
3802  return this;
3803 
3804  },
3805 
3806  expandByScalar: function ( scalar ) {
3807 
3808  this.min.addScalar( - scalar );
3809  this.max.addScalar( scalar );
3810 
3811  return this;
3812 
3813  },
3814 
3815  containsPoint: function ( point ) {
3816 
3817  if ( point.x < this.min.x || point.x > this.max.x ||
3818  point.y < this.min.y || point.y > this.max.y ) {
3819 
3820  return false;
3821 
3822  }
3823 
3824  return true;
3825 
3826  },
3827 
3828  containsBox: function ( box ) {
3829 
3830  if ( ( this.min.x <= box.min.x ) && ( box.max.x <= this.max.x ) &&
3831  ( this.min.y <= box.min.y ) && ( box.max.y <= this.max.y ) ) {
3832 
3833  return true;
3834 
3835  }
3836 
3837  return false;
3838 
3839  },
3840 
3841  getParameter: function ( point, optionalTarget ) {
3842 
3843  // This can potentially have a divide by zero if the box
3844  // has a size dimension of 0.
3845 
3846  var result = optionalTarget || new THREE.Vector2();
3847 
3848  return result.set(
3849  ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
3850  ( point.y - this.min.y ) / ( this.max.y - this.min.y )
3851  );
3852 
3853  },
3854 
3855  isIntersectionBox: function ( box ) {
3856 
3857  // using 6 splitting planes to rule out intersections.
3858 
3859  if ( box.max.x < this.min.x || box.min.x > this.max.x ||
3860  box.max.y < this.min.y || box.min.y > this.max.y ) {
3861 
3862  return false;
3863 
3864  }
3865 
3866  return true;
3867 
3868  },
3869 
3870  clampPoint: function ( point, optionalTarget ) {
3871 
3872  var result = optionalTarget || new THREE.Vector2();
3873  return result.copy( point ).clamp( this.min, this.max );
3874 
3875  },
3876 
3877  distanceToPoint: function () {
3878 
3879  var v1 = new THREE.Vector2();
3880 
3881  return function ( point ) {
3882 
3883  var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
3884  return clampedPoint.sub( point ).length();
3885 
3886  };
3887 
3888  }(),
3889 
3890  intersect: function ( box ) {
3891 
3892  this.min.max( box.min );
3893  this.max.min( box.max );
3894 
3895  return this;
3896 
3897  },
3898 
3899  union: function ( box ) {
3900 
3901  this.min.min( box.min );
3902  this.max.max( box.max );
3903 
3904  return this;
3905 
3906  },
3907 
3908  translate: function ( offset ) {
3909 
3910  this.min.add( offset );
3911  this.max.add( offset );
3912 
3913  return this;
3914 
3915  },
3916 
3917  equals: function ( box ) {
3918 
3919  return box.min.equals( this.min ) && box.max.equals( this.max );
3920 
3921  }
3922 
3923 };
3924 
3925 // File:src/math/Box3.js
3926 
3932 THREE.Box3 = function ( min, max ) {
3933 
3934  this.min = ( min !== undefined ) ? min : new THREE.Vector3( Infinity, Infinity, Infinity );
3935  this.max = ( max !== undefined ) ? max : new THREE.Vector3( - Infinity, - Infinity, - Infinity );
3936 
3937 };
3938 
3939 THREE.Box3.prototype = {
3940 
3941  constructor: THREE.Box3,
3942 
3943  set: function ( min, max ) {
3944 
3945  this.min.copy( min );
3946  this.max.copy( max );
3947 
3948  return this;
3949 
3950  },
3951 
3952  setFromPoints: function ( points ) {
3953 
3954  this.makeEmpty();
3955 
3956  for ( var i = 0, il = points.length; i < il; i ++ ) {
3957 
3958  this.expandByPoint( points[ i ] );
3959 
3960  }
3961 
3962  return this;
3963 
3964  },
3965 
3966  setFromCenterAndSize: function () {
3967 
3968  var v1 = new THREE.Vector3();
3969 
3970  return function ( center, size ) {
3971 
3972  var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
3973 
3974  this.min.copy( center ).sub( halfSize );
3975  this.max.copy( center ).add( halfSize );
3976 
3977  return this;
3978 
3979  };
3980 
3981  }(),
3982 
3983  setFromObject: function () {
3984 
3985  // Computes the world-axis-aligned bounding box of an object (including its children),
3986  // accounting for both the object's, and children's, world transforms
3987 
3988  var v1 = new THREE.Vector3();
3989 
3990  return function ( object ) {
3991 
3992  var scope = this;
3993 
3994  object.updateMatrixWorld( true );
3995 
3996  this.makeEmpty();
3997 
3998  object.traverse( function ( node ) {
3999 
4000  var geometry = node.geometry;
4001 
4002  if ( geometry !== undefined ) {
4003 
4004  if ( geometry instanceof THREE.Geometry ) {
4005 
4006  var vertices = geometry.vertices;
4007 
4008  for ( var i = 0, il = vertices.length; i < il; i ++ ) {
4009 
4010  v1.copy( vertices[ i ] );
4011 
4012  v1.applyMatrix4( node.matrixWorld );
4013 
4014  scope.expandByPoint( v1 );
4015 
4016  }
4017 
4018  } else if ( geometry instanceof THREE.BufferGeometry && geometry.attributes[ 'position' ] !== undefined ) {
4019 
4020  var positions = geometry.attributes[ 'position' ].array;
4021 
4022  for ( var i = 0, il = positions.length; i < il; i += 3 ) {
4023 
4024  v1.set( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );
4025 
4026  v1.applyMatrix4( node.matrixWorld );
4027 
4028  scope.expandByPoint( v1 );
4029 
4030  }
4031 
4032  }
4033 
4034  }
4035 
4036  } );
4037 
4038  return this;
4039 
4040  };
4041 
4042  }(),
4043 
4044  clone: function () {
4045 
4046  return new this.constructor().copy( this );
4047 
4048  },
4049 
4050  copy: function ( box ) {
4051 
4052  this.min.copy( box.min );
4053  this.max.copy( box.max );
4054 
4055  return this;
4056 
4057  },
4058 
4059  makeEmpty: function () {
4060 
4061  this.min.x = this.min.y = this.min.z = Infinity;
4062  this.max.x = this.max.y = this.max.z = - Infinity;
4063 
4064  return this;
4065 
4066  },
4067 
4068  empty: function () {
4069 
4070  // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
4071 
4072  return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
4073 
4074  },
4075 
4076  center: function ( optionalTarget ) {
4077 
4078  var result = optionalTarget || new THREE.Vector3();
4079  return result.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
4080 
4081  },
4082 
4083  size: function ( optionalTarget ) {
4084 
4085  var result = optionalTarget || new THREE.Vector3();
4086  return result.subVectors( this.max, this.min );
4087 
4088  },
4089 
4090  expandByPoint: function ( point ) {
4091 
4092  this.min.min( point );
4093  this.max.max( point );
4094 
4095  return this;
4096 
4097  },
4098 
4099  expandByVector: function ( vector ) {
4100 
4101  this.min.sub( vector );
4102  this.max.add( vector );
4103 
4104  return this;
4105 
4106  },
4107 
4108  expandByScalar: function ( scalar ) {
4109 
4110  this.min.addScalar( - scalar );
4111  this.max.addScalar( scalar );
4112 
4113  return this;
4114 
4115  },
4116 
4117  containsPoint: function ( point ) {
4118 
4119  if ( point.x < this.min.x || point.x > this.max.x ||
4120  point.y < this.min.y || point.y > this.max.y ||
4121  point.z < this.min.z || point.z > this.max.z ) {
4122 
4123  return false;
4124 
4125  }
4126 
4127  return true;
4128 
4129  },
4130 
4131  containsBox: function ( box ) {
4132 
4133  if ( ( this.min.x <= box.min.x ) && ( box.max.x <= this.max.x ) &&
4134  ( this.min.y <= box.min.y ) && ( box.max.y <= this.max.y ) &&
4135  ( this.min.z <= box.min.z ) && ( box.max.z <= this.max.z ) ) {
4136 
4137  return true;
4138 
4139  }
4140 
4141  return false;
4142 
4143  },
4144 
4145  getParameter: function ( point, optionalTarget ) {
4146 
4147  // This can potentially have a divide by zero if the box
4148  // has a size dimension of 0.
4149 
4150  var result = optionalTarget || new THREE.Vector3();
4151 
4152  return result.set(
4153  ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
4154  ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
4155  ( point.z - this.min.z ) / ( this.max.z - this.min.z )
4156  );
4157 
4158  },
4159 
4160  isIntersectionBox: function ( box ) {
4161 
4162  // using 6 splitting planes to rule out intersections.
4163 
4164  if ( box.max.x < this.min.x || box.min.x > this.max.x ||
4165  box.max.y < this.min.y || box.min.y > this.max.y ||
4166  box.max.z < this.min.z || box.min.z > this.max.z ) {
4167 
4168  return false;
4169 
4170  }
4171 
4172  return true;
4173 
4174  },
4175 
4176  clampPoint: function ( point, optionalTarget ) {
4177 
4178  var result = optionalTarget || new THREE.Vector3();
4179  return result.copy( point ).clamp( this.min, this.max );
4180 
4181  },
4182 
4183  distanceToPoint: function () {
4184 
4185  var v1 = new THREE.Vector3();
4186 
4187  return function ( point ) {
4188 
4189  var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
4190  return clampedPoint.sub( point ).length();
4191 
4192  };
4193 
4194  }(),
4195 
4196  getBoundingSphere: function () {
4197 
4198  var v1 = new THREE.Vector3();
4199 
4200  return function ( optionalTarget ) {
4201 
4202  var result = optionalTarget || new THREE.Sphere();
4203 
4204  result.center = this.center();
4205  result.radius = this.size( v1 ).length() * 0.5;
4206 
4207  return result;
4208 
4209  };
4210 
4211  }(),
4212 
4213  intersect: function ( box ) {
4214 
4215  this.min.max( box.min );
4216  this.max.min( box.max );
4217 
4218  return this;
4219 
4220  },
4221 
4222  union: function ( box ) {
4223 
4224  this.min.min( box.min );
4225  this.max.max( box.max );
4226 
4227  return this;
4228 
4229  },
4230 
4231  applyMatrix4: function () {
4232 
4233  var points = [
4234  new THREE.Vector3(),
4235  new THREE.Vector3(),
4236  new THREE.Vector3(),
4237  new THREE.Vector3(),
4238  new THREE.Vector3(),
4239  new THREE.Vector3(),
4240  new THREE.Vector3(),
4241  new THREE.Vector3()
4242  ];
4243 
4244  return function ( matrix ) {
4245 
4246  // NOTE: I am using a binary pattern to specify all 2^3 combinations below
4247  points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
4248  points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
4249  points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
4250  points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
4251  points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
4252  points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
4253  points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
4254  points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
4255 
4256  this.makeEmpty();
4257  this.setFromPoints( points );
4258 
4259  return this;
4260 
4261  };
4262 
4263  }(),
4264 
4265  translate: function ( offset ) {
4266 
4267  this.min.add( offset );
4268  this.max.add( offset );
4269 
4270  return this;
4271 
4272  },
4273 
4274  equals: function ( box ) {
4275 
4276  return box.min.equals( this.min ) && box.max.equals( this.max );
4277 
4278  }
4279 
4280 };
4281 
4282 // File:src/math/Matrix3.js
4283 
4290 THREE.Matrix3 = function () {
4291 
4292  this.elements = new Float32Array( [
4293 
4294  1, 0, 0,
4295  0, 1, 0,
4296  0, 0, 1
4297 
4298  ] );
4299 
4300  if ( arguments.length > 0 ) {
4301 
4302  console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
4303 
4304  }
4305 
4306 };
4307 
4308 THREE.Matrix3.prototype = {
4309 
4310  constructor: THREE.Matrix3,
4311 
4312  set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
4313 
4314  var te = this.elements;
4315 
4316  te[ 0 ] = n11; te[ 3 ] = n12; te[ 6 ] = n13;
4317  te[ 1 ] = n21; te[ 4 ] = n22; te[ 7 ] = n23;
4318  te[ 2 ] = n31; te[ 5 ] = n32; te[ 8 ] = n33;
4319 
4320  return this;
4321 
4322  },
4323 
4324  identity: function () {
4325 
4326  this.set(
4327 
4328  1, 0, 0,
4329  0, 1, 0,
4330  0, 0, 1
4331 
4332  );
4333 
4334  return this;
4335 
4336  },
4337 
4338  clone: function () {
4339 
4340  return new this.constructor().fromArray( this.elements );
4341 
4342  },
4343 
4344  copy: function ( m ) {
4345 
4346  var me = m.elements;
4347 
4348  this.set(
4349 
4350  me[ 0 ], me[ 3 ], me[ 6 ],
4351  me[ 1 ], me[ 4 ], me[ 7 ],
4352  me[ 2 ], me[ 5 ], me[ 8 ]
4353 
4354  );
4355 
4356  return this;
4357 
4358  },
4359 
4360  multiplyVector3: function ( vector ) {
4361 
4362  console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
4363  return vector.applyMatrix3( this );
4364 
4365  },
4366 
4367  multiplyVector3Array: function ( a ) {
4368 
4369  console.warn( 'THREE.Matrix3: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' );
4370  return this.applyToVector3Array( a );
4371 
4372  },
4373 
4374  applyToVector3Array: function () {
4375 
4376  var v1;
4377 
4378  return function ( array, offset, length ) {
4379 
4380  if ( v1 === undefined ) v1 = new THREE.Vector3();
4381  if ( offset === undefined ) offset = 0;
4382  if ( length === undefined ) length = array.length;
4383 
4384  for ( var i = 0, j = offset; i < length; i += 3, j += 3 ) {
4385 
4386  v1.fromArray( array, j );
4387  v1.applyMatrix3( this );
4388  v1.toArray( array, j );
4389 
4390  }
4391 
4392  return array;
4393 
4394  };
4395 
4396  }(),
4397 
4398  applyToBuffer: function () {
4399 
4400  var v1;
4401 
4402  return function applyToBuffer( buffer, offset, length ) {
4403 
4404  if ( v1 === undefined ) v1 = new THREE.Vector3();
4405  if ( offset === undefined ) offset = 0;
4406  if ( length === undefined ) length = buffer.length / buffer.itemSize;
4407 
4408  for ( var i = 0, j = offset; i < length; i ++, j ++ ) {
4409 
4410  v1.x = buffer.getX( j );
4411  v1.y = buffer.getY( j );
4412  v1.z = buffer.getZ( j );
4413 
4414  v1.applyMatrix3( this );
4415 
4416  buffer.setXYZ( v1.x, v1.y, v1.z );
4417 
4418  }
4419 
4420  return buffer;
4421 
4422  };
4423 
4424  }(),
4425 
4426  multiplyScalar: function ( s ) {
4427 
4428  var te = this.elements;
4429 
4430  te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
4431  te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
4432  te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
4433 
4434  return this;
4435 
4436  },
4437 
4438  determinant: function () {
4439 
4440  var te = this.elements;
4441 
4442  var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
4443  d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
4444  g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
4445 
4446  return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
4447 
4448  },
4449 
4450  getInverse: function ( matrix, throwOnInvertible ) {
4451 
4452  // input: THREE.Matrix4
4453  // ( based on http://code.google.com/p/webgl-mjs/ )
4454 
4455  var me = matrix.elements;
4456  var te = this.elements;
4457 
4458  te[ 0 ] = me[ 10 ] * me[ 5 ] - me[ 6 ] * me[ 9 ];
4459  te[ 1 ] = - me[ 10 ] * me[ 1 ] + me[ 2 ] * me[ 9 ];
4460  te[ 2 ] = me[ 6 ] * me[ 1 ] - me[ 2 ] * me[ 5 ];
4461  te[ 3 ] = - me[ 10 ] * me[ 4 ] + me[ 6 ] * me[ 8 ];
4462  te[ 4 ] = me[ 10 ] * me[ 0 ] - me[ 2 ] * me[ 8 ];
4463  te[ 5 ] = - me[ 6 ] * me[ 0 ] + me[ 2 ] * me[ 4 ];
4464  te[ 6 ] = me[ 9 ] * me[ 4 ] - me[ 5 ] * me[ 8 ];
4465  te[ 7 ] = - me[ 9 ] * me[ 0 ] + me[ 1 ] * me[ 8 ];
4466  te[ 8 ] = me[ 5 ] * me[ 0 ] - me[ 1 ] * me[ 4 ];
4467 
4468  var det = me[ 0 ] * te[ 0 ] + me[ 1 ] * te[ 3 ] + me[ 2 ] * te[ 6 ];
4469 
4470  // no inverse
4471 
4472  if ( det === 0 ) {
4473 
4474  var msg = "Matrix3.getInverse(): can't invert matrix, determinant is 0";
4475 
4476  if ( throwOnInvertible || false ) {
4477 
4478  throw new Error( msg );
4479 
4480  } else {
4481 
4482  console.warn( msg );
4483 
4484  }
4485 
4486  this.identity();
4487 
4488  return this;
4489 
4490  }
4491 
4492  this.multiplyScalar( 1.0 / det );
4493 
4494  return this;
4495 
4496  },
4497 
4498  transpose: function () {
4499 
4500  var tmp, m = this.elements;
4501 
4502  tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
4503  tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
4504  tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
4505 
4506  return this;
4507 
4508  },
4509 
4510  flattenToArrayOffset: function ( array, offset ) {
4511 
4512  var te = this.elements;
4513 
4514  array[ offset ] = te[ 0 ];
4515  array[ offset + 1 ] = te[ 1 ];
4516  array[ offset + 2 ] = te[ 2 ];
4517 
4518  array[ offset + 3 ] = te[ 3 ];
4519  array[ offset + 4 ] = te[ 4 ];
4520  array[ offset + 5 ] = te[ 5 ];
4521 
4522  array[ offset + 6 ] = te[ 6 ];
4523  array[ offset + 7 ] = te[ 7 ];
4524  array[ offset + 8 ] = te[ 8 ];
4525 
4526  return array;
4527 
4528  },
4529 
4530  getNormalMatrix: function ( m ) {
4531 
4532  // input: THREE.Matrix4
4533 
4534  this.getInverse( m ).transpose();
4535 
4536  return this;
4537 
4538  },
4539 
4540  transposeIntoArray: function ( r ) {
4541 
4542  var m = this.elements;
4543 
4544  r[ 0 ] = m[ 0 ];
4545  r[ 1 ] = m[ 3 ];
4546  r[ 2 ] = m[ 6 ];
4547  r[ 3 ] = m[ 1 ];
4548  r[ 4 ] = m[ 4 ];
4549  r[ 5 ] = m[ 7 ];
4550  r[ 6 ] = m[ 2 ];
4551  r[ 7 ] = m[ 5 ];
4552  r[ 8 ] = m[ 8 ];
4553 
4554  return this;
4555 
4556  },
4557 
4558  fromArray: function ( array ) {
4559 
4560  this.elements.set( array );
4561 
4562  return this;
4563 
4564  },
4565 
4566  toArray: function () {
4567 
4568  var te = this.elements;
4569 
4570  return [
4571  te[ 0 ], te[ 1 ], te[ 2 ],
4572  te[ 3 ], te[ 4 ], te[ 5 ],
4573  te[ 6 ], te[ 7 ], te[ 8 ]
4574  ];
4575 
4576  }
4577 
4578 };
4579 
4580 // File:src/math/Matrix4.js
4581 
4595 THREE.Matrix4 = function () {
4596 
4597  this.elements = new Float32Array( [
4598 
4599  1, 0, 0, 0,
4600  0, 1, 0, 0,
4601  0, 0, 1, 0,
4602  0, 0, 0, 1
4603 
4604  ] );
4605 
4606  if ( arguments.length > 0 ) {
4607 
4608  console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
4609 
4610  }
4611 
4612 };
4613 
4614 THREE.Matrix4.prototype = {
4615 
4616  constructor: THREE.Matrix4,
4617 
4618  set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
4619 
4620  var te = this.elements;
4621 
4622  te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
4623  te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
4624  te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
4625  te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
4626 
4627  return this;
4628 
4629  },
4630 
4631  identity: function () {
4632 
4633  this.set(
4634 
4635  1, 0, 0, 0,
4636  0, 1, 0, 0,
4637  0, 0, 1, 0,
4638  0, 0, 0, 1
4639 
4640  );
4641 
4642  return this;
4643 
4644  },
4645 
4646  clone: function () {
4647 
4648  return new THREE.Matrix4().fromArray( this.elements );
4649 
4650  },
4651 
4652  copy: function ( m ) {
4653 
4654  this.elements.set( m.elements );
4655 
4656  return this;
4657 
4658  },
4659 
4660  extractPosition: function ( m ) {
4661 
4662  console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
4663  return this.copyPosition( m );
4664 
4665  },
4666 
4667  copyPosition: function ( m ) {
4668 
4669  var te = this.elements;
4670  var me = m.elements;
4671 
4672  te[ 12 ] = me[ 12 ];
4673  te[ 13 ] = me[ 13 ];
4674  te[ 14 ] = me[ 14 ];
4675 
4676  return this;
4677 
4678  },
4679 
4680  extractBasis: function ( xAxis, yAxis, zAxis ) {
4681 
4682  var te = this.elements;
4683 
4684  xAxis.set( te[ 0 ], te[ 1 ], te[ 2 ] );
4685  yAxis.set( te[ 4 ], te[ 5 ], te[ 6 ] );
4686  zAxis.set( te[ 8 ], te[ 9 ], te[ 10 ] );
4687 
4688  return this;
4689 
4690  },
4691 
4692  makeBasis: function ( xAxis, yAxis, zAxis ) {
4693 
4694  this.set(
4695  xAxis.x, yAxis.x, zAxis.x, 0,
4696  xAxis.y, yAxis.y, zAxis.y, 0,
4697  xAxis.z, yAxis.z, zAxis.z, 0,
4698  0, 0, 0, 1
4699  );
4700 
4701  return this;
4702 
4703  },
4704 
4705  extractRotation: function () {
4706 
4707  var v1;
4708 
4709  return function ( m ) {
4710 
4711  if ( v1 === undefined ) v1 = new THREE.Vector3();
4712 
4713  var te = this.elements;
4714  var me = m.elements;
4715 
4716  var scaleX = 1 / v1.set( me[ 0 ], me[ 1 ], me[ 2 ] ).length();
4717  var scaleY = 1 / v1.set( me[ 4 ], me[ 5 ], me[ 6 ] ).length();
4718  var scaleZ = 1 / v1.set( me[ 8 ], me[ 9 ], me[ 10 ] ).length();
4719 
4720  te[ 0 ] = me[ 0 ] * scaleX;
4721  te[ 1 ] = me[ 1 ] * scaleX;
4722  te[ 2 ] = me[ 2 ] * scaleX;
4723 
4724  te[ 4 ] = me[ 4 ] * scaleY;
4725  te[ 5 ] = me[ 5 ] * scaleY;
4726  te[ 6 ] = me[ 6 ] * scaleY;
4727 
4728  te[ 8 ] = me[ 8 ] * scaleZ;
4729  te[ 9 ] = me[ 9 ] * scaleZ;
4730  te[ 10 ] = me[ 10 ] * scaleZ;
4731 
4732  return this;
4733 
4734  };
4735 
4736  }(),
4737 
4738  makeRotationFromEuler: function ( euler ) {
4739 
4740  if ( euler instanceof THREE.Euler === false ) {
4741 
4742  console.error( 'THREE.Matrix: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
4743 
4744  }
4745 
4746  var te = this.elements;
4747 
4748  var x = euler.x, y = euler.y, z = euler.z;
4749  var a = Math.cos( x ), b = Math.sin( x );
4750  var c = Math.cos( y ), d = Math.sin( y );
4751  var e = Math.cos( z ), f = Math.sin( z );
4752 
4753  if ( euler.order === 'XYZ' ) {
4754 
4755  var ae = a * e, af = a * f, be = b * e, bf = b * f;
4756 
4757  te[ 0 ] = c * e;
4758  te[ 4 ] = - c * f;
4759  te[ 8 ] = d;
4760 
4761  te[ 1 ] = af + be * d;
4762  te[ 5 ] = ae - bf * d;
4763  te[ 9 ] = - b * c;
4764 
4765  te[ 2 ] = bf - ae * d;
4766  te[ 6 ] = be + af * d;
4767  te[ 10 ] = a * c;
4768 
4769  } else if ( euler.order === 'YXZ' ) {
4770 
4771  var ce = c * e, cf = c * f, de = d * e, df = d * f;
4772 
4773  te[ 0 ] = ce + df * b;
4774  te[ 4 ] = de * b - cf;
4775  te[ 8 ] = a * d;
4776 
4777  te[ 1 ] = a * f;
4778  te[ 5 ] = a * e;
4779  te[ 9 ] = - b;
4780 
4781  te[ 2 ] = cf * b - de;
4782  te[ 6 ] = df + ce * b;
4783  te[ 10 ] = a * c;
4784 
4785  } else if ( euler.order === 'ZXY' ) {
4786 
4787  var ce = c * e, cf = c * f, de = d * e, df = d * f;
4788 
4789  te[ 0 ] = ce - df * b;
4790  te[ 4 ] = - a * f;
4791  te[ 8 ] = de + cf * b;
4792 
4793  te[ 1 ] = cf + de * b;
4794  te[ 5 ] = a * e;
4795  te[ 9 ] = df - ce * b;
4796 
4797  te[ 2 ] = - a * d;
4798  te[ 6 ] = b;
4799  te[ 10 ] = a * c;
4800 
4801  } else if ( euler.order === 'ZYX' ) {
4802 
4803  var ae = a * e, af = a * f, be = b * e, bf = b * f;
4804 
4805  te[ 0 ] = c * e;
4806  te[ 4 ] = be * d - af;
4807  te[ 8 ] = ae * d + bf;
4808 
4809  te[ 1 ] = c * f;
4810  te[ 5 ] = bf * d + ae;
4811  te[ 9 ] = af * d - be;
4812 
4813  te[ 2 ] = - d;
4814  te[ 6 ] = b * c;
4815  te[ 10 ] = a * c;
4816 
4817  } else if ( euler.order === 'YZX' ) {
4818 
4819  var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
4820 
4821  te[ 0 ] = c * e;
4822  te[ 4 ] = bd - ac * f;
4823  te[ 8 ] = bc * f + ad;
4824 
4825  te[ 1 ] = f;
4826  te[ 5 ] = a * e;
4827  te[ 9 ] = - b * e;
4828 
4829  te[ 2 ] = - d * e;
4830  te[ 6 ] = ad * f + bc;
4831  te[ 10 ] = ac - bd * f;
4832 
4833  } else if ( euler.order === 'XZY' ) {
4834 
4835  var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
4836 
4837  te[ 0 ] = c * e;
4838  te[ 4 ] = - f;
4839  te[ 8 ] = d * e;
4840 
4841  te[ 1 ] = ac * f + bd;
4842  te[ 5 ] = a * e;
4843  te[ 9 ] = ad * f - bc;
4844 
4845  te[ 2 ] = bc * f - ad;
4846  te[ 6 ] = b * e;
4847  te[ 10 ] = bd * f + ac;
4848 
4849  }
4850 
4851  // last column
4852  te[ 3 ] = 0;
4853  te[ 7 ] = 0;
4854  te[ 11 ] = 0;
4855 
4856  // bottom row
4857  te[ 12 ] = 0;
4858  te[ 13 ] = 0;
4859  te[ 14 ] = 0;
4860  te[ 15 ] = 1;
4861 
4862  return this;
4863 
4864  },
4865 
4866  setRotationFromQuaternion: function ( q ) {
4867 
4868  console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
4869 
4870  return this.makeRotationFromQuaternion( q );
4871 
4872  },
4873 
4874  makeRotationFromQuaternion: function ( q ) {
4875 
4876  var te = this.elements;
4877 
4878  var x = q.x, y = q.y, z = q.z, w = q.w;
4879  var x2 = x + x, y2 = y + y, z2 = z + z;
4880  var xx = x * x2, xy = x * y2, xz = x * z2;
4881  var yy = y * y2, yz = y * z2, zz = z * z2;
4882  var wx = w * x2, wy = w * y2, wz = w * z2;
4883 
4884  te[ 0 ] = 1 - ( yy + zz );
4885  te[ 4 ] = xy - wz;
4886  te[ 8 ] = xz + wy;
4887 
4888  te[ 1 ] = xy + wz;
4889  te[ 5 ] = 1 - ( xx + zz );
4890  te[ 9 ] = yz - wx;
4891 
4892  te[ 2 ] = xz - wy;
4893  te[ 6 ] = yz + wx;
4894  te[ 10 ] = 1 - ( xx + yy );
4895 
4896  // last column
4897  te[ 3 ] = 0;
4898  te[ 7 ] = 0;
4899  te[ 11 ] = 0;
4900 
4901  // bottom row
4902  te[ 12 ] = 0;
4903  te[ 13 ] = 0;
4904  te[ 14 ] = 0;
4905  te[ 15 ] = 1;
4906 
4907  return this;
4908 
4909  },
4910 
4911  lookAt: function () {
4912 
4913  var x, y, z;
4914 
4915  return function ( eye, target, up ) {
4916 
4917  if ( x === undefined ) x = new THREE.Vector3();
4918  if ( y === undefined ) y = new THREE.Vector3();
4919  if ( z === undefined ) z = new THREE.Vector3();
4920 
4921  var te = this.elements;
4922 
4923  z.subVectors( eye, target ).normalize();
4924 
4925  if ( z.lengthSq() === 0 ) {
4926 
4927  z.z = 1;
4928 
4929  }
4930 
4931  x.crossVectors( up, z ).normalize();
4932 
4933  if ( x.lengthSq() === 0 ) {
4934 
4935  z.x += 0.0001;
4936  x.crossVectors( up, z ).normalize();
4937 
4938  }
4939 
4940  y.crossVectors( z, x );
4941 
4942 
4943  te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
4944  te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
4945  te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
4946 
4947  return this;
4948 
4949  };
4950 
4951  }(),
4952 
4953  multiply: function ( m, n ) {
4954 
4955  if ( n !== undefined ) {
4956 
4957  console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
4958  return this.multiplyMatrices( m, n );
4959 
4960  }
4961 
4962  return this.multiplyMatrices( this, m );
4963 
4964  },
4965 
4966  multiplyMatrices: function ( a, b ) {
4967 
4968  var ae = a.elements;
4969  var be = b.elements;
4970  var te = this.elements;
4971 
4972  var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
4973  var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
4974  var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
4975  var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
4976 
4977  var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
4978  var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
4979  var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
4980  var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
4981 
4982  te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
4983  te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
4984  te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
4985  te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
4986 
4987  te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
4988  te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
4989  te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
4990  te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
4991 
4992  te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
4993  te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
4994  te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
4995  te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
4996 
4997  te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
4998  te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
4999  te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
5000  te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
5001 
5002  return this;
5003 
5004  },
5005 
5006  multiplyToArray: function ( a, b, r ) {
5007 
5008  var te = this.elements;
5009 
5010  this.multiplyMatrices( a, b );
5011 
5012  r[ 0 ] = te[ 0 ]; r[ 1 ] = te[ 1 ]; r[ 2 ] = te[ 2 ]; r[ 3 ] = te[ 3 ];
5013  r[ 4 ] = te[ 4 ]; r[ 5 ] = te[ 5 ]; r[ 6 ] = te[ 6 ]; r[ 7 ] = te[ 7 ];
5014  r[ 8 ] = te[ 8 ]; r[ 9 ] = te[ 9 ]; r[ 10 ] = te[ 10 ]; r[ 11 ] = te[ 11 ];
5015  r[ 12 ] = te[ 12 ]; r[ 13 ] = te[ 13 ]; r[ 14 ] = te[ 14 ]; r[ 15 ] = te[ 15 ];
5016 
5017  return this;
5018 
5019  },
5020 
5021  multiplyScalar: function ( s ) {
5022 
5023  var te = this.elements;
5024 
5025  te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
5026  te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
5027  te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
5028  te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
5029 
5030  return this;
5031 
5032  },
5033 
5034  multiplyVector3: function ( vector ) {
5035 
5036  console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) or vector.applyProjection( matrix ) instead.' );
5037  return vector.applyProjection( this );
5038 
5039  },
5040 
5041  multiplyVector4: function ( vector ) {
5042 
5043  console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
5044  return vector.applyMatrix4( this );
5045 
5046  },
5047 
5048  multiplyVector3Array: function ( a ) {
5049 
5050  console.warn( 'THREE.Matrix4: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' );
5051  return this.applyToVector3Array( a );
5052 
5053  },
5054 
5055  applyToVector3Array: function () {
5056 
5057  var v1;
5058 
5059  return function ( array, offset, length ) {
5060 
5061  if ( v1 === undefined ) v1 = new THREE.Vector3();
5062  if ( offset === undefined ) offset = 0;
5063  if ( length === undefined ) length = array.length;
5064 
5065  for ( var i = 0, j = offset; i < length; i += 3, j += 3 ) {
5066 
5067  v1.fromArray( array, j );
5068  v1.applyMatrix4( this );
5069  v1.toArray( array, j );
5070 
5071  }
5072 
5073  return array;
5074 
5075  };
5076 
5077  }(),
5078 
5079  applyToBuffer: function () {
5080 
5081  var v1;
5082 
5083  return function applyToBuffer( buffer, offset, length ) {
5084 
5085  if ( v1 === undefined ) v1 = new THREE.Vector3();
5086  if ( offset === undefined ) offset = 0;
5087  if ( length === undefined ) length = buffer.length / buffer.itemSize;
5088 
5089  for ( var i = 0, j = offset; i < length; i ++, j ++ ) {
5090 
5091  v1.x = buffer.getX( j );
5092  v1.y = buffer.getY( j );
5093  v1.z = buffer.getZ( j );
5094 
5095  v1.applyMatrix4( this );
5096 
5097  buffer.setXYZ( v1.x, v1.y, v1.z );
5098 
5099  }
5100 
5101  return buffer;
5102 
5103  };
5104 
5105  }(),
5106 
5107  rotateAxis: function ( v ) {
5108 
5109  console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
5110 
5111  v.transformDirection( this );
5112 
5113  },
5114 
5115  crossVector: function ( vector ) {
5116 
5117  console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
5118  return vector.applyMatrix4( this );
5119 
5120  },
5121 
5122  determinant: function () {
5123 
5124  var te = this.elements;
5125 
5126  var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
5127  var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
5128  var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
5129  var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
5130 
5131  //TODO: make this more efficient
5132  //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
5133 
5134  return (
5135  n41 * (
5136  + n14 * n23 * n32
5137  - n13 * n24 * n32
5138  - n14 * n22 * n33
5139  + n12 * n24 * n33
5140  + n13 * n22 * n34
5141  - n12 * n23 * n34
5142  ) +
5143  n42 * (
5144  + n11 * n23 * n34
5145  - n11 * n24 * n33
5146  + n14 * n21 * n33
5147  - n13 * n21 * n34
5148  + n13 * n24 * n31
5149  - n14 * n23 * n31
5150  ) +
5151  n43 * (
5152  + n11 * n24 * n32
5153  - n11 * n22 * n34
5154  - n14 * n21 * n32
5155  + n12 * n21 * n34
5156  + n14 * n22 * n31
5157  - n12 * n24 * n31
5158  ) +
5159  n44 * (
5160  - n13 * n22 * n31
5161  - n11 * n23 * n32
5162  + n11 * n22 * n33
5163  + n13 * n21 * n32
5164  - n12 * n21 * n33
5165  + n12 * n23 * n31
5166  )
5167 
5168  );
5169 
5170  },
5171 
5172  transpose: function () {
5173 
5174  var te = this.elements;
5175  var tmp;
5176 
5177  tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
5178  tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
5179  tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
5180 
5181  tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
5182  tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
5183  tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
5184 
5185  return this;
5186 
5187  },
5188 
5189  flattenToArrayOffset: function ( array, offset ) {
5190 
5191  var te = this.elements;
5192 
5193  array[ offset ] = te[ 0 ];
5194  array[ offset + 1 ] = te[ 1 ];
5195  array[ offset + 2 ] = te[ 2 ];
5196  array[ offset + 3 ] = te[ 3 ];
5197 
5198  array[ offset + 4 ] = te[ 4 ];
5199  array[ offset + 5 ] = te[ 5 ];
5200  array[ offset + 6 ] = te[ 6 ];
5201  array[ offset + 7 ] = te[ 7 ];
5202 
5203  array[ offset + 8 ] = te[ 8 ];
5204  array[ offset + 9 ] = te[ 9 ];
5205  array[ offset + 10 ] = te[ 10 ];
5206  array[ offset + 11 ] = te[ 11 ];
5207 
5208  array[ offset + 12 ] = te[ 12 ];
5209  array[ offset + 13 ] = te[ 13 ];
5210  array[ offset + 14 ] = te[ 14 ];
5211  array[ offset + 15 ] = te[ 15 ];
5212 
5213  return array;
5214 
5215  },
5216 
5217  getPosition: function () {
5218 
5219  var v1;
5220 
5221  return function () {
5222 
5223  if ( v1 === undefined ) v1 = new THREE.Vector3();
5224  console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
5225 
5226  var te = this.elements;
5227  return v1.set( te[ 12 ], te[ 13 ], te[ 14 ] );
5228 
5229  };
5230 
5231  }(),
5232 
5233  setPosition: function ( v ) {
5234 
5235  var te = this.elements;
5236 
5237  te[ 12 ] = v.x;
5238  te[ 13 ] = v.y;
5239  te[ 14 ] = v.z;
5240 
5241  return this;
5242 
5243  },
5244 
5245  getInverse: function ( m, throwOnInvertible ) {
5246 
5247  // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
5248  var te = this.elements;
5249  var me = m.elements;
5250 
5251  var n11 = me[ 0 ], n12 = me[ 4 ], n13 = me[ 8 ], n14 = me[ 12 ];
5252  var n21 = me[ 1 ], n22 = me[ 5 ], n23 = me[ 9 ], n24 = me[ 13 ];
5253  var n31 = me[ 2 ], n32 = me[ 6 ], n33 = me[ 10 ], n34 = me[ 14 ];
5254  var n41 = me[ 3 ], n42 = me[ 7 ], n43 = me[ 11 ], n44 = me[ 15 ];
5255 
5256  te[ 0 ] = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44;
5257  te[ 4 ] = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44;
5258  te[ 8 ] = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44;
5259  te[ 12 ] = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
5260  te[ 1 ] = n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44;
5261  te[ 5 ] = n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44;
5262  te[ 9 ] = n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44;
5263  te[ 13 ] = n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34;
5264  te[ 2 ] = n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44;
5265  te[ 6 ] = n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44;
5266  te[ 10 ] = n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44;
5267  te[ 14 ] = n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34;
5268  te[ 3 ] = n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43;
5269  te[ 7 ] = n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43;
5270  te[ 11 ] = n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43;
5271  te[ 15 ] = n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33;
5272 
5273  var det = n11 * te[ 0 ] + n21 * te[ 4 ] + n31 * te[ 8 ] + n41 * te[ 12 ];
5274 
5275  if ( det === 0 ) {
5276 
5277  var msg = "THREE.Matrix4.getInverse(): can't invert matrix, determinant is 0";
5278 
5279  if ( throwOnInvertible || false ) {
5280 
5281  throw new Error( msg );
5282 
5283  } else {
5284 
5285  console.warn( msg );
5286 
5287  }
5288 
5289  this.identity();
5290 
5291  return this;
5292 
5293  }
5294 
5295  this.multiplyScalar( 1 / det );
5296 
5297  return this;
5298 
5299  },
5300 
5301  translate: function ( v ) {
5302 
5303  console.error( 'THREE.Matrix4: .translate() has been removed.' );
5304 
5305  },
5306 
5307  rotateX: function ( angle ) {
5308 
5309  console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
5310 
5311  },
5312 
5313  rotateY: function ( angle ) {
5314 
5315  console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
5316 
5317  },
5318 
5319  rotateZ: function ( angle ) {
5320 
5321  console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
5322 
5323  },
5324 
5325  rotateByAxis: function ( axis, angle ) {
5326 
5327  console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
5328 
5329  },
5330 
5331  scale: function ( v ) {
5332 
5333  var te = this.elements;
5334  var x = v.x, y = v.y, z = v.z;
5335 
5336  te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
5337  te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
5338  te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
5339  te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
5340 
5341  return this;
5342 
5343  },
5344 
5345  getMaxScaleOnAxis: function () {
5346 
5347  var te = this.elements;
5348 
5349  var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
5350  var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
5351  var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
5352 
5353  return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
5354 
5355  },
5356 
5357  makeTranslation: function ( x, y, z ) {
5358 
5359  this.set(
5360 
5361  1, 0, 0, x,
5362  0, 1, 0, y,
5363  0, 0, 1, z,
5364  0, 0, 0, 1
5365 
5366  );
5367 
5368  return this;
5369 
5370  },
5371 
5372  makeRotationX: function ( theta ) {
5373 
5374  var c = Math.cos( theta ), s = Math.sin( theta );
5375 
5376  this.set(
5377 
5378  1, 0, 0, 0,
5379  0, c, - s, 0,
5380  0, s, c, 0,
5381  0, 0, 0, 1
5382 
5383  );
5384 
5385  return this;
5386 
5387  },
5388 
5389  makeRotationY: function ( theta ) {
5390 
5391  var c = Math.cos( theta ), s = Math.sin( theta );
5392 
5393  this.set(
5394 
5395  c, 0, s, 0,
5396  0, 1, 0, 0,
5397  - s, 0, c, 0,
5398  0, 0, 0, 1
5399 
5400  );
5401 
5402  return this;
5403 
5404  },
5405 
5406  makeRotationZ: function ( theta ) {
5407 
5408  var c = Math.cos( theta ), s = Math.sin( theta );
5409 
5410  this.set(
5411 
5412  c, - s, 0, 0,
5413  s, c, 0, 0,
5414  0, 0, 1, 0,
5415  0, 0, 0, 1
5416 
5417  );
5418 
5419  return this;
5420 
5421  },
5422 
5423  makeRotationAxis: function ( axis, angle ) {
5424 
5425  // Based on http://www.gamedev.net/reference/articles/article1199.asp
5426 
5427  var c = Math.cos( angle );
5428  var s = Math.sin( angle );
5429  var t = 1 - c;
5430  var x = axis.x, y = axis.y, z = axis.z;
5431  var tx = t * x, ty = t * y;
5432 
5433  this.set(
5434 
5435  tx * x + c, tx * y - s * z, tx * z + s * y, 0,
5436  tx * y + s * z, ty * y + c, ty * z - s * x, 0,
5437  tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
5438  0, 0, 0, 1
5439 
5440  );
5441 
5442  return this;
5443 
5444  },
5445 
5446  makeScale: function ( x, y, z ) {
5447 
5448  this.set(
5449 
5450  x, 0, 0, 0,
5451  0, y, 0, 0,
5452  0, 0, z, 0,
5453  0, 0, 0, 1
5454 
5455  );
5456 
5457  return this;
5458 
5459  },
5460 
5461  compose: function ( position, quaternion, scale ) {
5462 
5463  this.makeRotationFromQuaternion( quaternion );
5464  this.scale( scale );
5465  this.setPosition( position );
5466 
5467  return this;
5468 
5469  },
5470 
5471  decompose: function () {
5472 
5473  var vector, matrix;
5474 
5475  return function ( position, quaternion, scale ) {
5476 
5477  if ( vector === undefined ) vector = new THREE.Vector3();
5478  if ( matrix === undefined ) matrix = new THREE.Matrix4();
5479 
5480  var te = this.elements;
5481 
5482  var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
5483  var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
5484  var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
5485 
5486  // if determine is negative, we need to invert one scale
5487  var det = this.determinant();
5488  if ( det < 0 ) {
5489 
5490  sx = - sx;
5491 
5492  }
5493 
5494  position.x = te[ 12 ];
5495  position.y = te[ 13 ];
5496  position.z = te[ 14 ];
5497 
5498  // scale the rotation part
5499 
5500  matrix.elements.set( this.elements ); // at this point matrix is incomplete so we can't use .copy()
5501 
5502  var invSX = 1 / sx;
5503  var invSY = 1 / sy;
5504  var invSZ = 1 / sz;
5505 
5506  matrix.elements[ 0 ] *= invSX;
5507  matrix.elements[ 1 ] *= invSX;
5508  matrix.elements[ 2 ] *= invSX;
5509 
5510  matrix.elements[ 4 ] *= invSY;
5511  matrix.elements[ 5 ] *= invSY;
5512  matrix.elements[ 6 ] *= invSY;
5513 
5514  matrix.elements[ 8 ] *= invSZ;
5515  matrix.elements[ 9 ] *= invSZ;
5516  matrix.elements[ 10 ] *= invSZ;
5517 
5518  quaternion.setFromRotationMatrix( matrix );
5519 
5520  scale.x = sx;
5521  scale.y = sy;
5522  scale.z = sz;
5523 
5524  return this;
5525 
5526  };
5527 
5528  }(),
5529 
5530  makeFrustum: function ( left, right, bottom, top, near, far ) {
5531 
5532  var te = this.elements;
5533  var x = 2 * near / ( right - left );
5534  var y = 2 * near / ( top - bottom );
5535 
5536  var a = ( right + left ) / ( right - left );
5537  var b = ( top + bottom ) / ( top - bottom );
5538  var c = - ( far + near ) / ( far - near );
5539  var d = - 2 * far * near / ( far - near );
5540 
5541  te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0;
5542  te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0;
5543  te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d;
5544  te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0;
5545 
5546  return this;
5547 
5548  },
5549 
5550  makePerspective: function ( fov, aspect, near, far ) {
5551 
5552  var ymax = near * Math.tan( THREE.Math.degToRad( fov * 0.5 ) );
5553  var ymin = - ymax;
5554  var xmin = ymin * aspect;
5555  var xmax = ymax * aspect;
5556 
5557  return this.makeFrustum( xmin, xmax, ymin, ymax, near, far );
5558 
5559  },
5560 
5561  makeOrthographic: function ( left, right, top, bottom, near, far ) {
5562 
5563  var te = this.elements;
5564  var w = right - left;
5565  var h = top - bottom;
5566  var p = far - near;
5567 
5568  var x = ( right + left ) / w;
5569  var y = ( top + bottom ) / h;
5570  var z = ( far + near ) / p;
5571 
5572  te[ 0 ] = 2 / w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x;
5573  te[ 1 ] = 0; te[ 5 ] = 2 / h; te[ 9 ] = 0; te[ 13 ] = - y;
5574  te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 / p; te[ 14 ] = - z;
5575  te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1;
5576 
5577  return this;
5578 
5579  },
5580 
5581  equals: function ( matrix ) {
5582 
5583  var te = this.elements;
5584  var me = matrix.elements;
5585 
5586  for ( var i = 0; i < 16; i ++ ) {
5587 
5588  if ( te[ i ] !== me[ i ] ) return false;
5589 
5590  }
5591 
5592  return true;
5593 
5594  },
5595 
5596  fromArray: function ( array ) {
5597 
5598  this.elements.set( array );
5599 
5600  return this;
5601 
5602  },
5603 
5604  toArray: function () {
5605 
5606  var te = this.elements;
5607 
5608  return [
5609  te[ 0 ], te[ 1 ], te[ 2 ], te[ 3 ],
5610  te[ 4 ], te[ 5 ], te[ 6 ], te[ 7 ],
5611  te[ 8 ], te[ 9 ], te[ 10 ], te[ 11 ],
5612  te[ 12 ], te[ 13 ], te[ 14 ], te[ 15 ]
5613  ];
5614 
5615  }
5616 
5617 };
5618 
5619 // File:src/math/Ray.js
5620 
5625 THREE.Ray = function ( origin, direction ) {
5626 
5627  this.origin = ( origin !== undefined ) ? origin : new THREE.Vector3();
5628  this.direction = ( direction !== undefined ) ? direction : new THREE.Vector3();
5629 
5630 };
5631 
5632 THREE.Ray.prototype = {
5633 
5634  constructor: THREE.Ray,
5635 
5636  set: function ( origin, direction ) {
5637 
5638  this.origin.copy( origin );
5639  this.direction.copy( direction );
5640 
5641  return this;
5642 
5643  },
5644 
5645  clone: function () {
5646 
5647  return new this.constructor().copy( this );
5648 
5649  },
5650 
5651  copy: function ( ray ) {
5652 
5653  this.origin.copy( ray.origin );
5654  this.direction.copy( ray.direction );
5655 
5656  return this;
5657 
5658  },
5659 
5660  at: function ( t, optionalTarget ) {
5661 
5662  var result = optionalTarget || new THREE.Vector3();
5663 
5664  return result.copy( this.direction ).multiplyScalar( t ).add( this.origin );
5665 
5666  },
5667 
5668  recast: function () {
5669 
5670  var v1 = new THREE.Vector3();
5671 
5672  return function ( t ) {
5673 
5674  this.origin.copy( this.at( t, v1 ) );
5675 
5676  return this;
5677 
5678  };
5679 
5680  }(),
5681 
5682  closestPointToPoint: function ( point, optionalTarget ) {
5683 
5684  var result = optionalTarget || new THREE.Vector3();
5685  result.subVectors( point, this.origin );
5686  var directionDistance = result.dot( this.direction );
5687 
5688  if ( directionDistance < 0 ) {
5689 
5690  return result.copy( this.origin );
5691 
5692  }
5693 
5694  return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
5695 
5696  },
5697 
5698  distanceToPoint: function ( point ) {
5699 
5700  return Math.sqrt( this.distanceSqToPoint( point ) );
5701 
5702  },
5703 
5704  distanceSqToPoint: function () {
5705 
5706  var v1 = new THREE.Vector3();
5707 
5708  return function ( point ) {
5709 
5710  var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
5711 
5712  // point behind the ray
5713 
5714  if ( directionDistance < 0 ) {
5715 
5716  return this.origin.distanceToSquared( point );
5717 
5718  }
5719 
5720  v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
5721 
5722  return v1.distanceToSquared( point );
5723 
5724  };
5725 
5726  }(),
5727 
5728  distanceSqToSegment: function () {
5729 
5730  var segCenter = new THREE.Vector3();
5731  var segDir = new THREE.Vector3();
5732  var diff = new THREE.Vector3();
5733 
5734  return function ( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
5735 
5736  // from http://www.geometrictools.com/LibMathematics/Distance/Wm5DistRay3Segment3.cpp
5737  // It returns the min distance between the ray and the segment
5738  // defined by v0 and v1
5739  // It can also set two optional targets :
5740  // - The closest point on the ray
5741  // - The closest point on the segment
5742 
5743  segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
5744  segDir.copy( v1 ).sub( v0 ).normalize();
5745  diff.copy( this.origin ).sub( segCenter );
5746 
5747  var segExtent = v0.distanceTo( v1 ) * 0.5;
5748  var a01 = - this.direction.dot( segDir );
5749  var b0 = diff.dot( this.direction );
5750  var b1 = - diff.dot( segDir );
5751  var c = diff.lengthSq();
5752  var det = Math.abs( 1 - a01 * a01 );
5753  var s0, s1, sqrDist, extDet;
5754 
5755  if ( det > 0 ) {
5756 
5757  // The ray and segment are not parallel.
5758 
5759  s0 = a01 * b1 - b0;
5760  s1 = a01 * b0 - b1;
5761  extDet = segExtent * det;
5762 
5763  if ( s0 >= 0 ) {
5764 
5765  if ( s1 >= - extDet ) {
5766 
5767  if ( s1 <= extDet ) {
5768 
5769  // region 0
5770  // Minimum at interior points of ray and segment.
5771 
5772  var invDet = 1 / det;
5773  s0 *= invDet;
5774  s1 *= invDet;
5775  sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
5776 
5777  } else {
5778 
5779  // region 1
5780 
5781  s1 = segExtent;
5782  s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5783  sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5784 
5785  }
5786 
5787  } else {
5788 
5789  // region 5
5790 
5791  s1 = - segExtent;
5792  s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5793  sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5794 
5795  }
5796 
5797  } else {
5798 
5799  if ( s1 <= - extDet ) {
5800 
5801  // region 4
5802 
5803  s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
5804  s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
5805  sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5806 
5807  } else if ( s1 <= extDet ) {
5808 
5809  // region 3
5810 
5811  s0 = 0;
5812  s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
5813  sqrDist = s1 * ( s1 + 2 * b1 ) + c;
5814 
5815  } else {
5816 
5817  // region 2
5818 
5819  s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
5820  s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
5821  sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5822 
5823  }
5824 
5825  }
5826 
5827  } else {
5828 
5829  // Ray and segment are parallel.
5830 
5831  s1 = ( a01 > 0 ) ? - segExtent : segExtent;
5832  s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5833  sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5834 
5835  }
5836 
5837  if ( optionalPointOnRay ) {
5838 
5839  optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
5840 
5841  }
5842 
5843  if ( optionalPointOnSegment ) {
5844 
5845  optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter );
5846 
5847  }
5848 
5849  return sqrDist;
5850 
5851  };
5852 
5853  }(),
5854 
5855 
5856  isIntersectionSphere: function ( sphere ) {
5857 
5858  return this.distanceToPoint( sphere.center ) <= sphere.radius;
5859 
5860  },
5861 
5862  intersectSphere: function () {
5863 
5864  // from http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-sphere-intersection/
5865 
5866  var v1 = new THREE.Vector3();
5867 
5868  return function ( sphere, optionalTarget ) {
5869 
5870  v1.subVectors( sphere.center, this.origin );
5871 
5872  var tca = v1.dot( this.direction );
5873 
5874  var d2 = v1.dot( v1 ) - tca * tca;
5875 
5876  var radius2 = sphere.radius * sphere.radius;
5877 
5878  if ( d2 > radius2 ) return null;
5879 
5880  var thc = Math.sqrt( radius2 - d2 );
5881 
5882  // t0 = first intersect point - entrance on front of sphere
5883  var t0 = tca - thc;
5884 
5885  // t1 = second intersect point - exit point on back of sphere
5886  var t1 = tca + thc;
5887 
5888  // test to see if both t0 and t1 are behind the ray - if so, return null
5889  if ( t0 < 0 && t1 < 0 ) return null;
5890 
5891  // test to see if t0 is behind the ray:
5892  // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
5893  // in order to always return an intersect point that is in front of the ray.
5894  if ( t0 < 0 ) return this.at( t1, optionalTarget );
5895 
5896  // else t0 is in front of the ray, so return the first collision point scaled by t0
5897  return this.at( t0, optionalTarget );
5898 
5899  }
5900 
5901  }(),
5902 
5903  isIntersectionPlane: function ( plane ) {
5904 
5905  // check if the ray lies on the plane first
5906 
5907  var distToPoint = plane.distanceToPoint( this.origin );
5908 
5909  if ( distToPoint === 0 ) {
5910 
5911  return true;
5912 
5913  }
5914 
5915  var denominator = plane.normal.dot( this.direction );
5916 
5917  if ( denominator * distToPoint < 0 ) {
5918 
5919  return true;
5920 
5921  }
5922 
5923  // ray origin is behind the plane (and is pointing behind it)
5924 
5925  return false;
5926 
5927  },
5928 
5929  distanceToPlane: function ( plane ) {
5930 
5931  var denominator = plane.normal.dot( this.direction );
5932  if ( denominator === 0 ) {
5933 
5934  // line is coplanar, return origin
5935  if ( plane.distanceToPoint( this.origin ) === 0 ) {
5936 
5937  return 0;
5938 
5939  }
5940 
5941  // Null is preferable to undefined since undefined means.... it is undefined
5942 
5943  return null;
5944 
5945  }
5946 
5947  var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
5948 
5949  // Return if the ray never intersects the plane
5950 
5951  return t >= 0 ? t : null;
5952 
5953  },
5954 
5955  intersectPlane: function ( plane, optionalTarget ) {
5956 
5957  var t = this.distanceToPlane( plane );
5958 
5959  if ( t === null ) {
5960 
5961  return null;
5962 
5963  }
5964 
5965  return this.at( t, optionalTarget );
5966 
5967  },
5968 
5969  isIntersectionBox: function () {
5970 
5971  var v = new THREE.Vector3();
5972 
5973  return function ( box ) {
5974 
5975  return this.intersectBox( box, v ) !== null;
5976 
5977  };
5978 
5979  }(),
5980 
5981  intersectBox: function ( box, optionalTarget ) {
5982 
5983  // http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-box-intersection/
5984 
5985  var tmin, tmax, tymin, tymax, tzmin, tzmax;
5986 
5987  var invdirx = 1 / this.direction.x,
5988  invdiry = 1 / this.direction.y,
5989  invdirz = 1 / this.direction.z;
5990 
5991  var origin = this.origin;
5992 
5993  if ( invdirx >= 0 ) {
5994 
5995  tmin = ( box.min.x - origin.x ) * invdirx;
5996  tmax = ( box.max.x - origin.x ) * invdirx;
5997 
5998  } else {
5999 
6000  tmin = ( box.max.x - origin.x ) * invdirx;
6001  tmax = ( box.min.x - origin.x ) * invdirx;
6002 
6003  }
6004 
6005  if ( invdiry >= 0 ) {
6006 
6007  tymin = ( box.min.y - origin.y ) * invdiry;
6008  tymax = ( box.max.y - origin.y ) * invdiry;
6009 
6010  } else {
6011 
6012  tymin = ( box.max.y - origin.y ) * invdiry;
6013  tymax = ( box.min.y - origin.y ) * invdiry;
6014 
6015  }
6016 
6017  if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
6018 
6019  // These lines also handle the case where tmin or tmax is NaN
6020  // (result of 0 * Infinity). x !== x returns true if x is NaN
6021 
6022  if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
6023 
6024  if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
6025 
6026  if ( invdirz >= 0 ) {
6027 
6028  tzmin = ( box.min.z - origin.z ) * invdirz;
6029  tzmax = ( box.max.z - origin.z ) * invdirz;
6030 
6031  } else {
6032 
6033  tzmin = ( box.max.z - origin.z ) * invdirz;
6034  tzmax = ( box.min.z - origin.z ) * invdirz;
6035 
6036  }
6037 
6038  if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
6039 
6040  if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
6041 
6042  if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
6043 
6044  //return point closest to the ray (positive side)
6045 
6046  if ( tmax < 0 ) return null;
6047 
6048  return this.at( tmin >= 0 ? tmin : tmax, optionalTarget );
6049 
6050  },
6051 
6052  intersectTriangle: function () {
6053 
6054  // Compute the offset origin, edges, and normal.
6055  var diff = new THREE.Vector3();
6056  var edge1 = new THREE.Vector3();
6057  var edge2 = new THREE.Vector3();
6058  var normal = new THREE.Vector3();
6059 
6060  return function ( a, b, c, backfaceCulling, optionalTarget ) {
6061 
6062  // from http://www.geometrictools.com/LibMathematics/Intersection/Wm5IntrRay3Triangle3.cpp
6063 
6064  edge1.subVectors( b, a );
6065  edge2.subVectors( c, a );
6066  normal.crossVectors( edge1, edge2 );
6067 
6068  // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
6069  // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
6070  // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
6071  // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
6072  // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
6073  var DdN = this.direction.dot( normal );
6074  var sign;
6075 
6076  if ( DdN > 0 ) {
6077 
6078  if ( backfaceCulling ) return null;
6079  sign = 1;
6080 
6081  } else if ( DdN < 0 ) {
6082 
6083  sign = - 1;
6084  DdN = - DdN;
6085 
6086  } else {
6087 
6088  return null;
6089 
6090  }
6091 
6092  diff.subVectors( this.origin, a );
6093  var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );
6094 
6095  // b1 < 0, no intersection
6096  if ( DdQxE2 < 0 ) {
6097 
6098  return null;
6099 
6100  }
6101 
6102  var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );
6103 
6104  // b2 < 0, no intersection
6105  if ( DdE1xQ < 0 ) {
6106 
6107  return null;
6108 
6109  }
6110 
6111  // b1+b2 > 1, no intersection
6112  if ( DdQxE2 + DdE1xQ > DdN ) {
6113 
6114  return null;
6115 
6116  }
6117 
6118  // Line intersects triangle, check if ray does.
6119  var QdN = - sign * diff.dot( normal );
6120 
6121  // t < 0, no intersection
6122  if ( QdN < 0 ) {
6123 
6124  return null;
6125 
6126  }
6127 
6128  // Ray intersects triangle.
6129  return this.at( QdN / DdN, optionalTarget );
6130 
6131  };
6132 
6133  }(),
6134 
6135  applyMatrix4: function ( matrix4 ) {
6136 
6137  this.direction.add( this.origin ).applyMatrix4( matrix4 );
6138  this.origin.applyMatrix4( matrix4 );
6139  this.direction.sub( this.origin );
6140  this.direction.normalize();
6141 
6142  return this;
6143 
6144  },
6145 
6146  equals: function ( ray ) {
6147 
6148  return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
6149 
6150  }
6151 
6152 };
6153 
6154 // File:src/math/Sphere.js
6155 
6161 THREE.Sphere = function ( center, radius ) {
6162 
6163  this.center = ( center !== undefined ) ? center : new THREE.Vector3();
6164  this.radius = ( radius !== undefined ) ? radius : 0;
6165 
6166 };
6167 
6168 THREE.Sphere.prototype = {
6169 
6170  constructor: THREE.Sphere,
6171 
6172  set: function ( center, radius ) {
6173 
6174  this.center.copy( center );
6175  this.radius = radius;
6176 
6177  return this;
6178 
6179  },
6180 
6181  setFromPoints: function () {
6182 
6183  var box = new THREE.Box3();
6184 
6185  return function ( points, optionalCenter ) {
6186 
6187  var center = this.center;
6188 
6189  if ( optionalCenter !== undefined ) {
6190 
6191  center.copy( optionalCenter );
6192 
6193  } else {
6194 
6195  box.setFromPoints( points ).center( center );
6196 
6197  }
6198 
6199  var maxRadiusSq = 0;
6200 
6201  for ( var i = 0, il = points.length; i < il; i ++ ) {
6202 
6203  maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
6204 
6205  }
6206 
6207  this.radius = Math.sqrt( maxRadiusSq );
6208 
6209  return this;
6210 
6211  };
6212 
6213  }(),
6214 
6215  clone: function () {
6216 
6217  return new this.constructor().copy( this );
6218 
6219  },
6220 
6221  copy: function ( sphere ) {
6222 
6223  this.center.copy( sphere.center );
6224  this.radius = sphere.radius;
6225 
6226  return this;
6227 
6228  },
6229 
6230  empty: function () {
6231 
6232  return ( this.radius <= 0 );
6233 
6234  },
6235 
6236  containsPoint: function ( point ) {
6237 
6238  return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
6239 
6240  },
6241 
6242  distanceToPoint: function ( point ) {
6243 
6244  return ( point.distanceTo( this.center ) - this.radius );
6245 
6246  },
6247 
6248  intersectsSphere: function ( sphere ) {
6249 
6250  var radiusSum = this.radius + sphere.radius;
6251 
6252  return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
6253 
6254  },
6255 
6256  clampPoint: function ( point, optionalTarget ) {
6257 
6258  var deltaLengthSq = this.center.distanceToSquared( point );
6259 
6260  var result = optionalTarget || new THREE.Vector3();
6261  result.copy( point );
6262 
6263  if ( deltaLengthSq > ( this.radius * this.radius ) ) {
6264 
6265  result.sub( this.center ).normalize();
6266  result.multiplyScalar( this.radius ).add( this.center );
6267 
6268  }
6269 
6270  return result;
6271 
6272  },
6273 
6274  getBoundingBox: function ( optionalTarget ) {
6275 
6276  var box = optionalTarget || new THREE.Box3();
6277 
6278  box.set( this.center, this.center );
6279  box.expandByScalar( this.radius );
6280 
6281  return box;
6282 
6283  },
6284 
6285  applyMatrix4: function ( matrix ) {
6286 
6287  this.center.applyMatrix4( matrix );
6288  this.radius = this.radius * matrix.getMaxScaleOnAxis();
6289 
6290  return this;
6291 
6292  },
6293 
6294  translate: function ( offset ) {
6295 
6296  this.center.add( offset );
6297 
6298  return this;
6299 
6300  },
6301 
6302  equals: function ( sphere ) {
6303 
6304  return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
6305 
6306  }
6307 
6308 };
6309 
6310 // File:src/math/Frustum.js
6311 
6318 THREE.Frustum = function ( p0, p1, p2, p3, p4, p5 ) {
6319 
6320  this.planes = [
6321 
6322  ( p0 !== undefined ) ? p0 : new THREE.Plane(),
6323  ( p1 !== undefined ) ? p1 : new THREE.Plane(),
6324  ( p2 !== undefined ) ? p2 : new THREE.Plane(),
6325  ( p3 !== undefined ) ? p3 : new THREE.Plane(),
6326  ( p4 !== undefined ) ? p4 : new THREE.Plane(),
6327  ( p5 !== undefined ) ? p5 : new THREE.Plane()
6328 
6329  ];
6330 
6331 };
6332 
6333 THREE.Frustum.prototype = {
6334 
6335  constructor: THREE.Frustum,
6336 
6337  set: function ( p0, p1, p2, p3, p4, p5 ) {
6338 
6339  var planes = this.planes;
6340 
6341  planes[ 0 ].copy( p0 );
6342  planes[ 1 ].copy( p1 );
6343  planes[ 2 ].copy( p2 );
6344  planes[ 3 ].copy( p3 );
6345  planes[ 4 ].copy( p4 );
6346  planes[ 5 ].copy( p5 );
6347 
6348  return this;
6349 
6350  },
6351 
6352  clone: function () {
6353 
6354  return new this.constructor().copy( this );
6355 
6356  },
6357 
6358  copy: function ( frustum ) {
6359 
6360  var planes = this.planes;
6361 
6362  for ( var i = 0; i < 6; i ++ ) {
6363 
6364  planes[ i ].copy( frustum.planes[ i ] );
6365 
6366  }
6367 
6368  return this;
6369 
6370  },
6371 
6372  setFromMatrix: function ( m ) {
6373 
6374  var planes = this.planes;
6375  var me = m.elements;
6376  var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
6377  var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
6378  var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
6379  var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
6380 
6381  planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
6382  planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
6383  planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
6384  planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
6385  planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
6386  planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
6387 
6388  return this;
6389 
6390  },
6391 
6392  intersectsObject: function () {
6393 
6394  var sphere = new THREE.Sphere();
6395 
6396  return function ( object ) {
6397 
6398  var geometry = object.geometry;
6399 
6400  if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
6401 
6402  sphere.copy( geometry.boundingSphere );
6403  sphere.applyMatrix4( object.matrixWorld );
6404 
6405  return this.intersectsSphere( sphere );
6406 
6407  };
6408 
6409  }(),
6410 
6411  intersectsSphere: function ( sphere ) {
6412 
6413  var planes = this.planes;
6414  var center = sphere.center;
6415  var negRadius = - sphere.radius;
6416 
6417  for ( var i = 0; i < 6; i ++ ) {
6418 
6419  var distance = planes[ i ].distanceToPoint( center );
6420 
6421  if ( distance < negRadius ) {
6422 
6423  return false;
6424 
6425  }
6426 
6427  }
6428 
6429  return true;
6430 
6431  },
6432 
6433  intersectsBox: function () {
6434 
6435  var p1 = new THREE.Vector3(),
6436  p2 = new THREE.Vector3();
6437 
6438  return function ( box ) {
6439 
6440  var planes = this.planes;
6441 
6442  for ( var i = 0; i < 6 ; i ++ ) {
6443 
6444  var plane = planes[ i ];
6445 
6446  p1.x = plane.normal.x > 0 ? box.min.x : box.max.x;
6447  p2.x = plane.normal.x > 0 ? box.max.x : box.min.x;
6448  p1.y = plane.normal.y > 0 ? box.min.y : box.max.y;
6449  p2.y = plane.normal.y > 0 ? box.max.y : box.min.y;
6450  p1.z = plane.normal.z > 0 ? box.min.z : box.max.z;
6451  p2.z = plane.normal.z > 0 ? box.max.z : box.min.z;
6452 
6453  var d1 = plane.distanceToPoint( p1 );
6454  var d2 = plane.distanceToPoint( p2 );
6455 
6456  // if both outside plane, no intersection
6457 
6458  if ( d1 < 0 && d2 < 0 ) {
6459 
6460  return false;
6461 
6462  }
6463 
6464  }
6465 
6466  return true;
6467 
6468  };
6469 
6470  }(),
6471 
6472 
6473  containsPoint: function ( point ) {
6474 
6475  var planes = this.planes;
6476 
6477  for ( var i = 0; i < 6; i ++ ) {
6478 
6479  if ( planes[ i ].distanceToPoint( point ) < 0 ) {
6480 
6481  return false;
6482 
6483  }
6484 
6485  }
6486 
6487  return true;
6488 
6489  }
6490 
6491 };
6492 
6493 // File:src/math/Plane.js
6494 
6499 THREE.Plane = function ( normal, constant ) {
6500 
6501  this.normal = ( normal !== undefined ) ? normal : new THREE.Vector3( 1, 0, 0 );
6502  this.constant = ( constant !== undefined ) ? constant : 0;
6503 
6504 };
6505 
6506 THREE.Plane.prototype = {
6507 
6508  constructor: THREE.Plane,
6509 
6510  set: function ( normal, constant ) {
6511 
6512  this.normal.copy( normal );
6513  this.constant = constant;
6514 
6515  return this;
6516 
6517  },
6518 
6519  setComponents: function ( x, y, z, w ) {
6520 
6521  this.normal.set( x, y, z );
6522  this.constant = w;
6523 
6524  return this;
6525 
6526  },
6527 
6528  setFromNormalAndCoplanarPoint: function ( normal, point ) {
6529 
6530  this.normal.copy( normal );
6531  this.constant = - point.dot( this.normal ); // must be this.normal, not normal, as this.normal is normalized
6532 
6533  return this;
6534 
6535  },
6536 
6537  setFromCoplanarPoints: function () {
6538 
6539  var v1 = new THREE.Vector3();
6540  var v2 = new THREE.Vector3();
6541 
6542  return function ( a, b, c ) {
6543 
6544  var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize();
6545 
6546  // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
6547 
6548  this.setFromNormalAndCoplanarPoint( normal, a );
6549 
6550  return this;
6551 
6552  };
6553 
6554  }(),
6555 
6556  clone: function () {
6557 
6558  return new this.constructor().copy( this );
6559 
6560  },
6561 
6562  copy: function ( plane ) {
6563 
6564  this.normal.copy( plane.normal );
6565  this.constant = plane.constant;
6566 
6567  return this;
6568 
6569  },
6570 
6571  normalize: function () {
6572 
6573  // Note: will lead to a divide by zero if the plane is invalid.
6574 
6575  var inverseNormalLength = 1.0 / this.normal.length();
6576  this.normal.multiplyScalar( inverseNormalLength );
6577  this.constant *= inverseNormalLength;
6578 
6579  return this;
6580 
6581  },
6582 
6583  negate: function () {
6584 
6585  this.constant *= - 1;
6586  this.normal.negate();
6587 
6588  return this;
6589 
6590  },
6591 
6592  distanceToPoint: function ( point ) {
6593 
6594  return this.normal.dot( point ) + this.constant;
6595 
6596  },
6597 
6598  distanceToSphere: function ( sphere ) {
6599 
6600  return this.distanceToPoint( sphere.center ) - sphere.radius;
6601 
6602  },
6603 
6604  projectPoint: function ( point, optionalTarget ) {
6605 
6606  return this.orthoPoint( point, optionalTarget ).sub( point ).negate();
6607 
6608  },
6609 
6610  orthoPoint: function ( point, optionalTarget ) {
6611 
6612  var perpendicularMagnitude = this.distanceToPoint( point );
6613 
6614  var result = optionalTarget || new THREE.Vector3();
6615  return result.copy( this.normal ).multiplyScalar( perpendicularMagnitude );
6616 
6617  },
6618 
6619  isIntersectionLine: function ( line ) {
6620 
6621  // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
6622 
6623  var startSign = this.distanceToPoint( line.start );
6624  var endSign = this.distanceToPoint( line.end );
6625 
6626  return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
6627 
6628  },
6629 
6630  intersectLine: function () {
6631 
6632  var v1 = new THREE.Vector3();
6633 
6634  return function ( line, optionalTarget ) {
6635 
6636  var result = optionalTarget || new THREE.Vector3();
6637 
6638  var direction = line.delta( v1 );
6639 
6640  var denominator = this.normal.dot( direction );
6641 
6642  if ( denominator === 0 ) {
6643 
6644  // line is coplanar, return origin
6645  if ( this.distanceToPoint( line.start ) === 0 ) {
6646 
6647  return result.copy( line.start );
6648 
6649  }
6650 
6651  // Unsure if this is the correct method to handle this case.
6652  return undefined;
6653 
6654  }
6655 
6656  var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
6657 
6658  if ( t < 0 || t > 1 ) {
6659 
6660  return undefined;
6661 
6662  }
6663 
6664  return result.copy( direction ).multiplyScalar( t ).add( line.start );
6665 
6666  };
6667 
6668  }(),
6669 
6670 
6671  coplanarPoint: function ( optionalTarget ) {
6672 
6673  var result = optionalTarget || new THREE.Vector3();
6674  return result.copy( this.normal ).multiplyScalar( - this.constant );
6675 
6676  },
6677 
6678  applyMatrix4: function () {
6679 
6680  var v1 = new THREE.Vector3();
6681  var v2 = new THREE.Vector3();
6682  var m1 = new THREE.Matrix3();
6683 
6684  return function ( matrix, optionalNormalMatrix ) {
6685 
6686  // compute new normal based on theory here:
6687  // http://www.songho.ca/opengl/gl_normaltransform.html
6688  var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix );
6689  var newNormal = v1.copy( this.normal ).applyMatrix3( normalMatrix );
6690 
6691  var newCoplanarPoint = this.coplanarPoint( v2 );
6692  newCoplanarPoint.applyMatrix4( matrix );
6693 
6694  this.setFromNormalAndCoplanarPoint( newNormal, newCoplanarPoint );
6695 
6696  return this;
6697 
6698  };
6699 
6700  }(),
6701 
6702  translate: function ( offset ) {
6703 
6704  this.constant = this.constant - offset.dot( this.normal );
6705 
6706  return this;
6707 
6708  },
6709 
6710  equals: function ( plane ) {
6711 
6712  return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
6713 
6714  }
6715 
6716 };
6717 
6718 // File:src/math/Math.js
6719 
6725 THREE.Math = {
6726 
6727  generateUUID: function () {
6728 
6729  // http://www.broofa.com/Tools/Math.uuid.htm
6730 
6731  var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split( '' );
6732  var uuid = new Array( 36 );
6733  var rnd = 0, r;
6734 
6735  return function () {
6736 
6737  for ( var i = 0; i < 36; i ++ ) {
6738 
6739  if ( i === 8 || i === 13 || i === 18 || i === 23 ) {
6740 
6741  uuid[ i ] = '-';
6742 
6743  } else if ( i === 14 ) {
6744 
6745  uuid[ i ] = '4';
6746 
6747  } else {
6748 
6749  if ( rnd <= 0x02 ) rnd = 0x2000000 + ( Math.random() * 0x1000000 ) | 0;
6750  r = rnd & 0xf;
6751  rnd = rnd >> 4;
6752  uuid[ i ] = chars[ ( i === 19 ) ? ( r & 0x3 ) | 0x8 : r ];
6753 
6754  }
6755 
6756  }
6757 
6758  return uuid.join( '' );
6759 
6760  };
6761 
6762  }(),
6763 
6764  clamp: function ( value, min, max ) {
6765 
6766  return Math.max( min, Math.min( max, value ) );
6767 
6768  },
6769 
6770  // compute euclidian modulo of m % n
6771  // https://en.wikipedia.org/wiki/Modulo_operation
6772 
6773  euclideanModulo: function ( n, m ) {
6774 
6775  return ( ( n % m ) + m ) % m;
6776 
6777  },
6778 
6779  // Linear mapping from range <a1, a2> to range <b1, b2>
6780 
6781  mapLinear: function ( x, a1, a2, b1, b2 ) {
6782 
6783  return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
6784 
6785  },
6786 
6787  // http://en.wikipedia.org/wiki/Smoothstep
6788 
6789  smoothstep: function ( x, min, max ) {
6790 
6791  if ( x <= min ) return 0;
6792  if ( x >= max ) return 1;
6793 
6794  x = ( x - min ) / ( max - min );
6795 
6796  return x * x * ( 3 - 2 * x );
6797 
6798  },
6799 
6800  smootherstep: function ( x, min, max ) {
6801 
6802  if ( x <= min ) return 0;
6803  if ( x >= max ) return 1;
6804 
6805  x = ( x - min ) / ( max - min );
6806 
6807  return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
6808 
6809  },
6810 
6811  // Random float from <0, 1> with 16 bits of randomness
6812  // (standard Math.random() creates repetitive patterns when applied over larger space)
6813 
6814  random16: function () {
6815 
6816  return ( 65280 * Math.random() + 255 * Math.random() ) / 65535;
6817 
6818  },
6819 
6820  // Random integer from <low, high> interval
6821 
6822  randInt: function ( low, high ) {
6823 
6824  return low + Math.floor( Math.random() * ( high - low + 1 ) );
6825 
6826  },
6827 
6828  // Random float from <low, high> interval
6829 
6830  randFloat: function ( low, high ) {
6831 
6832  return low + Math.random() * ( high - low );
6833 
6834  },
6835 
6836  // Random float from <-range/2, range/2> interval
6837 
6838  randFloatSpread: function ( range ) {
6839 
6840  return range * ( 0.5 - Math.random() );
6841 
6842  },
6843 
6844  degToRad: function () {
6845 
6846  var degreeToRadiansFactor = Math.PI / 180;
6847 
6848  return function ( degrees ) {
6849 
6850  return degrees * degreeToRadiansFactor;
6851 
6852  };
6853 
6854  }(),
6855 
6856  radToDeg: function () {
6857 
6858  var radianToDegreesFactor = 180 / Math.PI;
6859 
6860  return function ( radians ) {
6861 
6862  return radians * radianToDegreesFactor;
6863 
6864  };
6865 
6866  }(),
6867 
6868  isPowerOfTwo: function ( value ) {
6869 
6870  return ( value & ( value - 1 ) ) === 0 && value !== 0;
6871 
6872  },
6873 
6874  nearestPowerOfTwo: function ( value ) {
6875 
6876  return Math.pow( 2, Math.round( Math.log( value ) / Math.LN2 ) );
6877 
6878  },
6879 
6880  nextPowerOfTwo: function ( value ) {
6881 
6882  value --;
6883  value |= value >> 1;
6884  value |= value >> 2;
6885  value |= value >> 4;
6886  value |= value >> 8;
6887  value |= value >> 16;
6888  value ++;
6889 
6890  return value;
6891 
6892  }
6893 
6894 };
6895 
6896 // File:src/math/Spline.js
6897 
6906 THREE.Spline = function ( points ) {
6907 
6908  this.points = points;
6909 
6910  var c = [], v3 = { x: 0, y: 0, z: 0 },
6911  point, intPoint, weight, w2, w3,
6912  pa, pb, pc, pd;
6913 
6914  this.initFromArray = function ( a ) {
6915 
6916  this.points = [];
6917 
6918  for ( var i = 0; i < a.length; i ++ ) {
6919 
6920  this.points[ i ] = { x: a[ i ][ 0 ], y: a[ i ][ 1 ], z: a[ i ][ 2 ] };
6921 
6922  }
6923 
6924  };
6925 
6926  this.getPoint = function ( k ) {
6927 
6928  point = ( this.points.length - 1 ) * k;
6929  intPoint = Math.floor( point );
6930  weight = point - intPoint;
6931 
6932  c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1;
6933  c[ 1 ] = intPoint;
6934  c[ 2 ] = intPoint > this.points.length - 2 ? this.points.length - 1 : intPoint + 1;
6935  c[ 3 ] = intPoint > this.points.length - 3 ? this.points.length - 1 : intPoint + 2;
6936 
6937  pa = this.points[ c[ 0 ] ];
6938  pb = this.points[ c[ 1 ] ];
6939  pc = this.points[ c[ 2 ] ];
6940  pd = this.points[ c[ 3 ] ];
6941 
6942  w2 = weight * weight;
6943  w3 = weight * w2;
6944 
6945  v3.x = interpolate( pa.x, pb.x, pc.x, pd.x, weight, w2, w3 );
6946  v3.y = interpolate( pa.y, pb.y, pc.y, pd.y, weight, w2, w3 );
6947  v3.z = interpolate( pa.z, pb.z, pc.z, pd.z, weight, w2, w3 );
6948 
6949  return v3;
6950 
6951  };
6952 
6953  this.getControlPointsArray = function () {
6954 
6955  var i, p, l = this.points.length,
6956  coords = [];
6957 
6958  for ( i = 0; i < l; i ++ ) {
6959 
6960  p = this.points[ i ];
6961  coords[ i ] = [ p.x, p.y, p.z ];
6962 
6963  }
6964 
6965  return coords;
6966 
6967  };
6968 
6969  // approximate length by summing linear segments
6970 
6971  this.getLength = function ( nSubDivisions ) {
6972 
6973  var i, index, nSamples, position,
6974  point = 0, intPoint = 0, oldIntPoint = 0,
6975  oldPosition = new THREE.Vector3(),
6976  tmpVec = new THREE.Vector3(),
6977  chunkLengths = [],
6978  totalLength = 0;
6979 
6980  // first point has 0 length
6981 
6982  chunkLengths[ 0 ] = 0;
6983 
6984  if ( ! nSubDivisions ) nSubDivisions = 100;
6985 
6986  nSamples = this.points.length * nSubDivisions;
6987 
6988  oldPosition.copy( this.points[ 0 ] );
6989 
6990  for ( i = 1; i < nSamples; i ++ ) {
6991 
6992  index = i / nSamples;
6993 
6994  position = this.getPoint( index );
6995  tmpVec.copy( position );
6996 
6997  totalLength += tmpVec.distanceTo( oldPosition );
6998 
6999  oldPosition.copy( position );
7000 
7001  point = ( this.points.length - 1 ) * index;
7002  intPoint = Math.floor( point );
7003 
7004  if ( intPoint !== oldIntPoint ) {
7005 
7006  chunkLengths[ intPoint ] = totalLength;
7007  oldIntPoint = intPoint;
7008 
7009  }
7010 
7011  }
7012 
7013  // last point ends with total length
7014 
7015  chunkLengths[ chunkLengths.length ] = totalLength;
7016 
7017  return { chunks: chunkLengths, total: totalLength };
7018 
7019  };
7020 
7021  this.reparametrizeByArcLength = function ( samplingCoef ) {
7022 
7023  var i, j,
7024  index, indexCurrent, indexNext,
7025  realDistance,
7026  sampling, position,
7027  newpoints = [],
7028  tmpVec = new THREE.Vector3(),
7029  sl = this.getLength();
7030 
7031  newpoints.push( tmpVec.copy( this.points[ 0 ] ).clone() );
7032 
7033  for ( i = 1; i < this.points.length; i ++ ) {
7034 
7035  //tmpVec.copy( this.points[ i - 1 ] );
7036  //linearDistance = tmpVec.distanceTo( this.points[ i ] );
7037 
7038  realDistance = sl.chunks[ i ] - sl.chunks[ i - 1 ];
7039 
7040  sampling = Math.ceil( samplingCoef * realDistance / sl.total );
7041 
7042  indexCurrent = ( i - 1 ) / ( this.points.length - 1 );
7043  indexNext = i / ( this.points.length - 1 );
7044 
7045  for ( j = 1; j < sampling - 1; j ++ ) {
7046 
7047  index = indexCurrent + j * ( 1 / sampling ) * ( indexNext - indexCurrent );
7048 
7049  position = this.getPoint( index );
7050  newpoints.push( tmpVec.copy( position ).clone() );
7051 
7052  }
7053 
7054  newpoints.push( tmpVec.copy( this.points[ i ] ).clone() );
7055 
7056  }
7057 
7058  this.points = newpoints;
7059 
7060  };
7061 
7062  // Catmull-Rom
7063 
7064  function interpolate( p0, p1, p2, p3, t, t2, t3 ) {
7065 
7066  var v0 = ( p2 - p0 ) * 0.5,
7067  v1 = ( p3 - p1 ) * 0.5;
7068 
7069  return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1;
7070 
7071  }
7072 
7073 };
7074 
7075 // File:src/math/Triangle.js
7076 
7082 THREE.Triangle = function ( a, b, c ) {
7083 
7084  this.a = ( a !== undefined ) ? a : new THREE.Vector3();
7085  this.b = ( b !== undefined ) ? b : new THREE.Vector3();
7086  this.c = ( c !== undefined ) ? c : new THREE.Vector3();
7087 
7088 };
7089 
7090 THREE.Triangle.normal = function () {
7091 
7092  var v0 = new THREE.Vector3();
7093 
7094  return function ( a, b, c, optionalTarget ) {
7095 
7096  var result = optionalTarget || new THREE.Vector3();
7097 
7098  result.subVectors( c, b );
7099  v0.subVectors( a, b );
7100  result.cross( v0 );
7101 
7102  var resultLengthSq = result.lengthSq();
7103  if ( resultLengthSq > 0 ) {
7104 
7105  return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) );
7106 
7107  }
7108 
7109  return result.set( 0, 0, 0 );
7110 
7111  };
7112 
7113 }();
7114 
7115 // static/instance method to calculate barycentric coordinates
7116 // based on: http://www.blackpawn.com/texts/pointinpoly/default.html
7117 THREE.Triangle.barycoordFromPoint = function () {
7118 
7119  var v0 = new THREE.Vector3();
7120  var v1 = new THREE.Vector3();
7121  var v2 = new THREE.Vector3();
7122 
7123  return function ( point, a, b, c, optionalTarget ) {
7124 
7125  v0.subVectors( c, a );
7126  v1.subVectors( b, a );
7127  v2.subVectors( point, a );
7128 
7129  var dot00 = v0.dot( v0 );
7130  var dot01 = v0.dot( v1 );
7131  var dot02 = v0.dot( v2 );
7132  var dot11 = v1.dot( v1 );
7133  var dot12 = v1.dot( v2 );
7134 
7135  var denom = ( dot00 * dot11 - dot01 * dot01 );
7136 
7137  var result = optionalTarget || new THREE.Vector3();
7138 
7139  // collinear or singular triangle
7140  if ( denom === 0 ) {
7141 
7142  // arbitrary location outside of triangle?
7143  // not sure if this is the best idea, maybe should be returning undefined
7144  return result.set( - 2, - 1, - 1 );
7145 
7146  }
7147 
7148  var invDenom = 1 / denom;
7149  var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
7150  var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
7151 
7152  // barycentric coordinates must always sum to 1
7153  return result.set( 1 - u - v, v, u );
7154 
7155  };
7156 
7157 }();
7158 
7159 THREE.Triangle.containsPoint = function () {
7160 
7161  var v1 = new THREE.Vector3();
7162 
7163  return function ( point, a, b, c ) {
7164 
7165  var result = THREE.Triangle.barycoordFromPoint( point, a, b, c, v1 );
7166 
7167  return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 );
7168 
7169  };
7170 
7171 }();
7172 
7173 THREE.Triangle.prototype = {
7174 
7175  constructor: THREE.Triangle,
7176 
7177  set: function ( a, b, c ) {
7178 
7179  this.a.copy( a );
7180  this.b.copy( b );
7181  this.c.copy( c );
7182 
7183  return this;
7184 
7185  },
7186 
7187  setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
7188 
7189  this.a.copy( points[ i0 ] );
7190  this.b.copy( points[ i1 ] );
7191  this.c.copy( points[ i2 ] );
7192 
7193  return this;
7194 
7195  },
7196 
7197  clone: function () {
7198 
7199  return new this.constructor().copy( this );
7200 
7201  },
7202 
7203  copy: function ( triangle ) {
7204 
7205  this.a.copy( triangle.a );
7206  this.b.copy( triangle.b );
7207  this.c.copy( triangle.c );
7208 
7209  return this;
7210 
7211  },
7212 
7213  area: function () {
7214 
7215  var v0 = new THREE.Vector3();
7216  var v1 = new THREE.Vector3();
7217 
7218  return function () {
7219 
7220  v0.subVectors( this.c, this.b );
7221  v1.subVectors( this.a, this.b );
7222 
7223  return v0.cross( v1 ).length() * 0.5;
7224 
7225  };
7226 
7227  }(),
7228 
7229  midpoint: function ( optionalTarget ) {
7230 
7231  var result = optionalTarget || new THREE.Vector3();
7232  return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
7233 
7234  },
7235 
7236  normal: function ( optionalTarget ) {
7237 
7238  return THREE.Triangle.normal( this.a, this.b, this.c, optionalTarget );
7239 
7240  },
7241 
7242  plane: function ( optionalTarget ) {
7243 
7244  var result = optionalTarget || new THREE.Plane();
7245 
7246  return result.setFromCoplanarPoints( this.a, this.b, this.c );
7247 
7248  },
7249 
7250  barycoordFromPoint: function ( point, optionalTarget ) {
7251 
7252  return THREE.Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget );
7253 
7254  },
7255 
7256  containsPoint: function ( point ) {
7257 
7258  return THREE.Triangle.containsPoint( point, this.a, this.b, this.c );
7259 
7260  },
7261 
7262  equals: function ( triangle ) {
7263 
7264  return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
7265 
7266  }
7267 
7268 };
7269 
7270 // File:src/core/Channels.js
7271 
7276 THREE.Channels = function () {
7277 
7278  this.mask = 1;
7279 
7280 };
7281 
7282 THREE.Channels.prototype = {
7283 
7284  constructor: THREE.Channels,
7285 
7286  set: function ( channel ) {
7287 
7288  this.mask = 1 << channel;
7289 
7290  },
7291 
7292  enable: function ( channel ) {
7293 
7294  this.mask |= 1 << channel;
7295 
7296  },
7297 
7298  toggle: function ( channel ) {
7299 
7300  this.mask ^= 1 << channel;
7301 
7302  },
7303 
7304  disable: function ( channel ) {
7305 
7306  this.mask &= ~ ( 1 << channel );
7307 
7308  }
7309 
7310 };
7311 
7312 // File:src/core/Clock.js
7313 
7318 THREE.Clock = function ( autoStart ) {
7319 
7320  this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
7321 
7322  this.startTime = 0;
7323  this.oldTime = 0;
7324  this.elapsedTime = 0;
7325 
7326  this.running = false;
7327 
7328 };
7329 
7330 THREE.Clock.prototype = {
7331 
7332  constructor: THREE.Clock,
7333 
7334  start: function () {
7335 
7336  this.startTime = self.performance.now();
7337 
7338  this.oldTime = this.startTime;
7339  this.running = true;
7340 
7341  },
7342 
7343  stop: function () {
7344 
7345  this.getElapsedTime();
7346  this.running = false;
7347 
7348  },
7349 
7350  getElapsedTime: function () {
7351 
7352  this.getDelta();
7353  return this.elapsedTime;
7354 
7355  },
7356 
7357  getDelta: function () {
7358 
7359  var diff = 0;
7360 
7361  if ( this.autoStart && ! this.running ) {
7362 
7363  this.start();
7364 
7365  }
7366 
7367  if ( this.running ) {
7368 
7369  var newTime = self.performance.now();
7370 
7371  diff = 0.001 * ( newTime - this.oldTime );
7372  this.oldTime = newTime;
7373 
7374  this.elapsedTime += diff;
7375 
7376  }
7377 
7378  return diff;
7379 
7380  }
7381 
7382 };
7383 
7384 // File:src/core/EventDispatcher.js
7385 
7390 THREE.EventDispatcher = function () {};
7391 
7392 THREE.EventDispatcher.prototype = {
7393 
7394  constructor: THREE.EventDispatcher,
7395 
7396  apply: function ( object ) {
7397 
7398  object.addEventListener = THREE.EventDispatcher.prototype.addEventListener;
7399  object.hasEventListener = THREE.EventDispatcher.prototype.hasEventListener;
7400  object.removeEventListener = THREE.EventDispatcher.prototype.removeEventListener;
7401  object.dispatchEvent = THREE.EventDispatcher.prototype.dispatchEvent;
7402 
7403  },
7404 
7405  addEventListener: function ( type, listener ) {
7406 
7407  if ( this._listeners === undefined ) this._listeners = {};
7408 
7409  var listeners = this._listeners;
7410 
7411  if ( listeners[ type ] === undefined ) {
7412 
7413  listeners[ type ] = [];
7414 
7415  }
7416 
7417  if ( listeners[ type ].indexOf( listener ) === - 1 ) {
7418 
7419  listeners[ type ].push( listener );
7420 
7421  }
7422 
7423  },
7424 
7425  hasEventListener: function ( type, listener ) {
7426 
7427  if ( this._listeners === undefined ) return false;
7428 
7429  var listeners = this._listeners;
7430 
7431  if ( listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1 ) {
7432 
7433  return true;
7434 
7435  }
7436 
7437  return false;
7438 
7439  },
7440 
7441  removeEventListener: function ( type, listener ) {
7442 
7443  if ( this._listeners === undefined ) return;
7444 
7445  var listeners = this._listeners;
7446  var listenerArray = listeners[ type ];
7447 
7448  if ( listenerArray !== undefined ) {
7449 
7450  var index = listenerArray.indexOf( listener );
7451 
7452  if ( index !== - 1 ) {
7453 
7454  listenerArray.splice( index, 1 );
7455 
7456  }
7457 
7458  }
7459 
7460  },
7461 
7462  dispatchEvent: function ( event ) {
7463 
7464  if ( this._listeners === undefined ) return;
7465 
7466  var listeners = this._listeners;
7467  var listenerArray = listeners[ event.type ];
7468 
7469  if ( listenerArray !== undefined ) {
7470 
7471  event.target = this;
7472 
7473  var array = [];
7474  var length = listenerArray.length;
7475 
7476  for ( var i = 0; i < length; i ++ ) {
7477 
7478  array[ i ] = listenerArray[ i ];
7479 
7480  }
7481 
7482  for ( var i = 0; i < length; i ++ ) {
7483 
7484  array[ i ].call( this, event );
7485 
7486  }
7487 
7488  }
7489 
7490  }
7491 
7492 };
7493 
7494 // File:src/core/Raycaster.js
7495 
7502 ( function ( THREE ) {
7503 
7504  THREE.Raycaster = function ( origin, direction, near, far ) {
7505 
7506  this.ray = new THREE.Ray( origin, direction );
7507  // direction is assumed to be normalized (for accurate distance calculations)
7508 
7509  this.near = near || 0;
7510  this.far = far || Infinity;
7511 
7512  this.params = {
7513  Mesh: {},
7514  Line: {},
7515  LOD: {},
7516  Points: { threshold: 1 },
7517  Sprite: {}
7518  };
7519 
7520  Object.defineProperties( this.params, {
7521  PointCloud: {
7522  get: function () {
7523  console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );
7524  return this.Points;
7525  }
7526  }
7527  } );
7528 
7529  };
7530 
7531  function descSort( a, b ) {
7532 
7533  return a.distance - b.distance;
7534 
7535  }
7536 
7537  function intersectObject( object, raycaster, intersects, recursive ) {
7538 
7539  if ( object.visible === false ) return;
7540 
7541  object.raycast( raycaster, intersects );
7542 
7543  if ( recursive === true ) {
7544 
7545  var children = object.children;
7546 
7547  for ( var i = 0, l = children.length; i < l; i ++ ) {
7548 
7549  intersectObject( children[ i ], raycaster, intersects, true );
7550 
7551  }
7552 
7553  }
7554 
7555  }
7556 
7557  //
7558 
7559  THREE.Raycaster.prototype = {
7560 
7561  constructor: THREE.Raycaster,
7562 
7563  linePrecision: 1,
7564 
7565  set: function ( origin, direction ) {
7566 
7567  // direction is assumed to be normalized (for accurate distance calculations)
7568 
7569  this.ray.set( origin, direction );
7570 
7571  },
7572 
7573  setFromCamera: function ( coords, camera ) {
7574 
7575  if ( camera instanceof THREE.PerspectiveCamera ) {
7576 
7577  this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
7578  this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
7579 
7580  } else if ( camera instanceof THREE.OrthographicCamera ) {
7581 
7582  this.ray.origin.set( coords.x, coords.y, - 1 ).unproject( camera );
7583  this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
7584 
7585  } else {
7586 
7587  console.error( 'THREE.Raycaster: Unsupported camera type.' );
7588 
7589  }
7590 
7591  },
7592 
7593  intersectObject: function ( object, recursive ) {
7594 
7595  var intersects = [];
7596 
7597  intersectObject( object, this, intersects, recursive );
7598 
7599  intersects.sort( descSort );
7600 
7601  return intersects;
7602 
7603  },
7604 
7605  intersectObjects: function ( objects, recursive ) {
7606 
7607  var intersects = [];
7608 
7609  if ( Array.isArray( objects ) === false ) {
7610 
7611  console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
7612  return intersects;
7613 
7614  }
7615 
7616  for ( var i = 0, l = objects.length; i < l; i ++ ) {
7617 
7618  intersectObject( objects[ i ], this, intersects, recursive );
7619 
7620  }
7621 
7622  intersects.sort( descSort );
7623 
7624  return intersects;
7625 
7626  }
7627 
7628  };
7629 
7630 }( THREE ) );
7631 
7632 // File:src/core/Object3D.js
7633 
7642 THREE.Object3D = function () {
7643 
7644  Object.defineProperty( this, 'id', { value: THREE.Object3DIdCount ++ } );
7645 
7646  this.uuid = THREE.Math.generateUUID();
7647 
7648  this.name = '';
7649  this.type = 'Object3D';
7650 
7651  this.parent = null;
7652  this.channels = new THREE.Channels();
7653  this.children = [];
7654 
7655  this.up = THREE.Object3D.DefaultUp.clone();
7656 
7657  var position = new THREE.Vector3();
7658  var rotation = new THREE.Euler();
7659  var quaternion = new THREE.Quaternion();
7660  var scale = new THREE.Vector3( 1, 1, 1 );
7661 
7662  function onRotationChange() {
7663 
7664  quaternion.setFromEuler( rotation, false );
7665 
7666  }
7667 
7668  function onQuaternionChange() {
7669 
7670  rotation.setFromQuaternion( quaternion, undefined, false );
7671 
7672  }
7673 
7674  rotation.onChange( onRotationChange );
7675  quaternion.onChange( onQuaternionChange );
7676 
7677  Object.defineProperties( this, {
7678  position: {
7679  enumerable: true,
7680  value: position
7681  },
7682  rotation: {
7683  enumerable: true,
7684  value: rotation
7685  },
7686  quaternion: {
7687  enumerable: true,
7688  value: quaternion
7689  },
7690  scale: {
7691  enumerable: true,
7692  value: scale
7693  },
7694  modelViewMatrix: {
7695  value: new THREE.Matrix4()
7696  },
7697  normalMatrix: {
7698  value: new THREE.Matrix3()
7699  }
7700  } );
7701 
7702  this.rotationAutoUpdate = true;
7703 
7704  this.matrix = new THREE.Matrix4();
7705  this.matrixWorld = new THREE.Matrix4();
7706 
7707  this.matrixAutoUpdate = THREE.Object3D.DefaultMatrixAutoUpdate;
7708  this.matrixWorldNeedsUpdate = false;
7709 
7710  this.visible = true;
7711 
7712  this.castShadow = false;
7713  this.receiveShadow = false;
7714 
7715  this.frustumCulled = true;
7716  this.renderOrder = 0;
7717 
7718  this.userData = {};
7719 
7720 };
7721 
7722 THREE.Object3D.DefaultUp = new THREE.Vector3( 0, 1, 0 );
7723 THREE.Object3D.DefaultMatrixAutoUpdate = true;
7724 
7725 THREE.Object3D.prototype = {
7726 
7727  constructor: THREE.Object3D,
7728 
7729  get eulerOrder () {
7730 
7731  console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
7732 
7733  return this.rotation.order;
7734 
7735  },
7736 
7737  set eulerOrder ( value ) {
7738 
7739  console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
7740 
7741  this.rotation.order = value;
7742 
7743  },
7744 
7745  get useQuaternion () {
7746 
7747  console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
7748 
7749  },
7750 
7751  set useQuaternion ( value ) {
7752 
7753  console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
7754 
7755  },
7756 
7757  set renderDepth ( value ) {
7758 
7759  console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
7760 
7761  },
7762 
7763  //
7764 
7765  applyMatrix: function ( matrix ) {
7766 
7767  this.matrix.multiplyMatrices( matrix, this.matrix );
7768 
7769  this.matrix.decompose( this.position, this.quaternion, this.scale );
7770 
7771  },
7772 
7773  setRotationFromAxisAngle: function ( axis, angle ) {
7774 
7775  // assumes axis is normalized
7776 
7777  this.quaternion.setFromAxisAngle( axis, angle );
7778 
7779  },
7780 
7781  setRotationFromEuler: function ( euler ) {
7782 
7783  this.quaternion.setFromEuler( euler, true );
7784 
7785  },
7786 
7787  setRotationFromMatrix: function ( m ) {
7788 
7789  // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
7790 
7791  this.quaternion.setFromRotationMatrix( m );
7792 
7793  },
7794 
7795  setRotationFromQuaternion: function ( q ) {
7796 
7797  // assumes q is normalized
7798 
7799  this.quaternion.copy( q );
7800 
7801  },
7802 
7803  rotateOnAxis: function () {
7804 
7805  // rotate object on axis in object space
7806  // axis is assumed to be normalized
7807 
7808  var q1 = new THREE.Quaternion();
7809 
7810  return function ( axis, angle ) {
7811 
7812  q1.setFromAxisAngle( axis, angle );
7813 
7814  this.quaternion.multiply( q1 );
7815 
7816  return this;
7817 
7818  };
7819 
7820  }(),
7821 
7822  rotateX: function () {
7823 
7824  var v1 = new THREE.Vector3( 1, 0, 0 );
7825 
7826  return function ( angle ) {
7827 
7828  return this.rotateOnAxis( v1, angle );
7829 
7830  };
7831 
7832  }(),
7833 
7834  rotateY: function () {
7835 
7836  var v1 = new THREE.Vector3( 0, 1, 0 );
7837 
7838  return function ( angle ) {
7839 
7840  return this.rotateOnAxis( v1, angle );
7841 
7842  };
7843 
7844  }(),
7845 
7846  rotateZ: function () {
7847 
7848  var v1 = new THREE.Vector3( 0, 0, 1 );
7849 
7850  return function ( angle ) {
7851 
7852  return this.rotateOnAxis( v1, angle );
7853 
7854  };
7855 
7856  }(),
7857 
7858  translateOnAxis: function () {
7859 
7860  // translate object by distance along axis in object space
7861  // axis is assumed to be normalized
7862 
7863  var v1 = new THREE.Vector3();
7864 
7865  return function ( axis, distance ) {
7866 
7867  v1.copy( axis ).applyQuaternion( this.quaternion );
7868 
7869  this.position.add( v1.multiplyScalar( distance ) );
7870 
7871  return this;
7872 
7873  };
7874 
7875  }(),
7876 
7877  translate: function ( distance, axis ) {
7878 
7879  console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
7880  return this.translateOnAxis( axis, distance );
7881 
7882  },
7883 
7884  translateX: function () {
7885 
7886  var v1 = new THREE.Vector3( 1, 0, 0 );
7887 
7888  return function ( distance ) {
7889 
7890  return this.translateOnAxis( v1, distance );
7891 
7892  };
7893 
7894  }(),
7895 
7896  translateY: function () {
7897 
7898  var v1 = new THREE.Vector3( 0, 1, 0 );
7899 
7900  return function ( distance ) {
7901 
7902  return this.translateOnAxis( v1, distance );
7903 
7904  };
7905 
7906  }(),
7907 
7908  translateZ: function () {
7909 
7910  var v1 = new THREE.Vector3( 0, 0, 1 );
7911 
7912  return function ( distance ) {
7913 
7914  return this.translateOnAxis( v1, distance );
7915 
7916  };
7917 
7918  }(),
7919 
7920  localToWorld: function ( vector ) {
7921 
7922  return vector.applyMatrix4( this.matrixWorld );
7923 
7924  },
7925 
7926  worldToLocal: function () {
7927 
7928  var m1 = new THREE.Matrix4();
7929 
7930  return function ( vector ) {
7931 
7932  return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) );
7933 
7934  };
7935 
7936  }(),
7937 
7938  lookAt: function () {
7939 
7940  // This routine does not support objects with rotated and/or translated parent(s)
7941 
7942  var m1 = new THREE.Matrix4();
7943 
7944  return function ( vector ) {
7945 
7946  m1.lookAt( vector, this.position, this.up );
7947 
7948  this.quaternion.setFromRotationMatrix( m1 );
7949 
7950  };
7951 
7952  }(),
7953 
7954  add: function ( object ) {
7955 
7956  if ( arguments.length > 1 ) {
7957 
7958  for ( var i = 0; i < arguments.length; i ++ ) {
7959 
7960  this.add( arguments[ i ] );
7961 
7962  }
7963 
7964  return this;
7965 
7966  }
7967 
7968  if ( object === this ) {
7969 
7970  console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
7971  return this;
7972 
7973  }
7974 
7975  if ( object instanceof THREE.Object3D ) {
7976 
7977  if ( object.parent !== null ) {
7978 
7979  object.parent.remove( object );
7980 
7981  }
7982 
7983  object.parent = this;
7984  object.dispatchEvent( { type: 'added' } );
7985 
7986  this.children.push( object );
7987 
7988  } else {
7989 
7990  console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
7991 
7992  }
7993 
7994  return this;
7995 
7996  },
7997 
7998  remove: function ( object ) {
7999 
8000  if ( arguments.length > 1 ) {
8001 
8002  for ( var i = 0; i < arguments.length; i ++ ) {
8003 
8004  this.remove( arguments[ i ] );
8005 
8006  }
8007 
8008  }
8009 
8010  var index = this.children.indexOf( object );
8011 
8012  if ( index !== - 1 ) {
8013 
8014  object.parent = null;
8015 
8016  object.dispatchEvent( { type: 'removed' } );
8017 
8018  this.children.splice( index, 1 );
8019 
8020  }
8021 
8022  },
8023 
8024  getChildByName: function ( name ) {
8025 
8026  console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
8027  return this.getObjectByName( name );
8028 
8029  },
8030 
8031  getObjectById: function ( id ) {
8032 
8033  return this.getObjectByProperty( 'id', id );
8034 
8035  },
8036 
8037  getObjectByName: function ( name ) {
8038 
8039  return this.getObjectByProperty( 'name', name );
8040 
8041  },
8042 
8043  getObjectByProperty: function ( name, value ) {
8044 
8045  if ( this[ name ] === value ) return this;
8046 
8047  for ( var i = 0, l = this.children.length; i < l; i ++ ) {
8048 
8049  var child = this.children[ i ];
8050  var object = child.getObjectByProperty( name, value );
8051 
8052  if ( object !== undefined ) {
8053 
8054  return object;
8055 
8056  }
8057 
8058  }
8059 
8060  return undefined;
8061 
8062  },
8063 
8064  getWorldPosition: function ( optionalTarget ) {
8065 
8066  var result = optionalTarget || new THREE.Vector3();
8067 
8068  this.updateMatrixWorld( true );
8069 
8070  return result.setFromMatrixPosition( this.matrixWorld );
8071 
8072  },
8073 
8074  getWorldQuaternion: function () {
8075 
8076  var position = new THREE.Vector3();
8077  var scale = new THREE.Vector3();
8078 
8079  return function ( optionalTarget ) {
8080 
8081  var result = optionalTarget || new THREE.Quaternion();
8082 
8083  this.updateMatrixWorld( true );
8084 
8085  this.matrixWorld.decompose( position, result, scale );
8086 
8087  return result;
8088 
8089  };
8090 
8091  }(),
8092 
8093  getWorldRotation: function () {
8094 
8095  var quaternion = new THREE.Quaternion();
8096 
8097  return function ( optionalTarget ) {
8098 
8099  var result = optionalTarget || new THREE.Euler();
8100 
8101  this.getWorldQuaternion( quaternion );
8102 
8103  return result.setFromQuaternion( quaternion, this.rotation.order, false );
8104 
8105  };
8106 
8107  }(),
8108 
8109  getWorldScale: function () {
8110 
8111  var position = new THREE.Vector3();
8112  var quaternion = new THREE.Quaternion();
8113 
8114  return function ( optionalTarget ) {
8115 
8116  var result = optionalTarget || new THREE.Vector3();
8117 
8118  this.updateMatrixWorld( true );
8119 
8120  this.matrixWorld.decompose( position, quaternion, result );
8121 
8122  return result;
8123 
8124  };
8125 
8126  }(),
8127 
8128  getWorldDirection: function () {
8129 
8130  var quaternion = new THREE.Quaternion();
8131 
8132  return function ( optionalTarget ) {
8133 
8134  var result = optionalTarget || new THREE.Vector3();
8135 
8136  this.getWorldQuaternion( quaternion );
8137 
8138  return result.set( 0, 0, 1 ).applyQuaternion( quaternion );
8139 
8140  };
8141 
8142  }(),
8143 
8144  raycast: function () {},
8145 
8146  traverse: function ( callback ) {
8147 
8148  callback( this );
8149 
8150  var children = this.children;
8151 
8152  for ( var i = 0, l = children.length; i < l; i ++ ) {
8153 
8154  children[ i ].traverse( callback );
8155 
8156  }
8157 
8158  },
8159 
8160  traverseVisible: function ( callback ) {
8161 
8162  if ( this.visible === false ) return;
8163 
8164  callback( this );
8165 
8166  var children = this.children;
8167 
8168  for ( var i = 0, l = children.length; i < l; i ++ ) {
8169 
8170  children[ i ].traverseVisible( callback );
8171 
8172  }
8173 
8174  },
8175 
8176  traverseAncestors: function ( callback ) {
8177 
8178  var parent = this.parent;
8179 
8180  if ( parent !== null ) {
8181 
8182  callback( parent );
8183 
8184  parent.traverseAncestors( callback );
8185 
8186  }
8187 
8188  },
8189 
8190  updateMatrix: function () {
8191 
8192  this.matrix.compose( this.position, this.quaternion, this.scale );
8193 
8194  this.matrixWorldNeedsUpdate = true;
8195 
8196  },
8197 
8198  updateMatrixWorld: function ( force ) {
8199 
8200  if ( this.matrixAutoUpdate === true ) this.updateMatrix();
8201 
8202  if ( this.matrixWorldNeedsUpdate === true || force === true ) {
8203 
8204  if ( this.parent === null ) {
8205 
8206  this.matrixWorld.copy( this.matrix );
8207 
8208  } else {
8209 
8210  this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
8211 
8212  }
8213 
8214  this.matrixWorldNeedsUpdate = false;
8215 
8216  force = true;
8217 
8218  }
8219 
8220  // update children
8221 
8222  for ( var i = 0, l = this.children.length; i < l; i ++ ) {
8223 
8224  this.children[ i ].updateMatrixWorld( force );
8225 
8226  }
8227 
8228  },
8229 
8230  toJSON: function ( meta ) {
8231 
8232  var isRootObject = ( meta === undefined );
8233 
8234  var output = {};
8235 
8236  // meta is a hash used to collect geometries, materials.
8237  // not providing it implies that this is the root object
8238  // being serialized.
8239  if ( isRootObject ) {
8240 
8241  // initialize meta obj
8242  meta = {
8243  geometries: {},
8244  materials: {},
8245  textures: {},
8246  images: {}
8247  };
8248 
8249  output.metadata = {
8250  version: 4.4,
8251  type: 'Object',
8252  generator: 'Object3D.toJSON'
8253  };
8254 
8255  }
8256 
8257  // standard Object3D serialization
8258 
8259  var object = {};
8260 
8261  object.uuid = this.uuid;
8262  object.type = this.type;
8263 
8264  if ( this.name !== '' ) object.name = this.name;
8265  if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
8266  if ( this.castShadow === true ) object.castShadow = true;
8267  if ( this.receiveShadow === true ) object.receiveShadow = true;
8268  if ( this.visible === false ) object.visible = false;
8269 
8270  object.matrix = this.matrix.toArray();
8271 
8272  //
8273 
8274  if ( this.geometry !== undefined ) {
8275 
8276  if ( meta.geometries[ this.geometry.uuid ] === undefined ) {
8277 
8278  meta.geometries[ this.geometry.uuid ] = this.geometry.toJSON( meta );
8279 
8280  }
8281 
8282  object.geometry = this.geometry.uuid;
8283 
8284  }
8285 
8286  if ( this.material !== undefined ) {
8287 
8288  if ( meta.materials[ this.material.uuid ] === undefined ) {
8289 
8290  meta.materials[ this.material.uuid ] = this.material.toJSON( meta );
8291 
8292  }
8293 
8294  object.material = this.material.uuid;
8295 
8296  }
8297 
8298  //
8299 
8300  if ( this.children.length > 0 ) {
8301 
8302  object.children = [];
8303 
8304  for ( var i = 0; i < this.children.length; i ++ ) {
8305 
8306  object.children.push( this.children[ i ].toJSON( meta ).object );
8307 
8308  }
8309 
8310  }
8311 
8312  if ( isRootObject ) {
8313 
8314  var geometries = extractFromCache( meta.geometries );
8315  var materials = extractFromCache( meta.materials );
8316  var textures = extractFromCache( meta.textures );
8317  var images = extractFromCache( meta.images );
8318 
8319  if ( geometries.length > 0 ) output.geometries = geometries;
8320  if ( materials.length > 0 ) output.materials = materials;
8321  if ( textures.length > 0 ) output.textures = textures;
8322  if ( images.length > 0 ) output.images = images;
8323 
8324  }
8325 
8326  output.object = object;
8327 
8328  return output;
8329 
8330  // extract data from the cache hash
8331  // remove metadata on each item
8332  // and return as array
8333  function extractFromCache ( cache ) {
8334 
8335  var values = [];
8336  for ( var key in cache ) {
8337 
8338  var data = cache[ key ];
8339  delete data.metadata;
8340  values.push( data );
8341 
8342  }
8343  return values;
8344 
8345  }
8346 
8347  },
8348 
8349  clone: function ( recursive ) {
8350 
8351  return new this.constructor().copy( this, recursive );
8352 
8353  },
8354 
8355  copy: function ( source, recursive ) {
8356 
8357  if ( recursive === undefined ) recursive = true;
8358 
8359  this.name = source.name;
8360 
8361  this.up.copy( source.up );
8362 
8363  this.position.copy( source.position );
8364  this.quaternion.copy( source.quaternion );
8365  this.scale.copy( source.scale );
8366 
8367  this.rotationAutoUpdate = source.rotationAutoUpdate;
8368 
8369  this.matrix.copy( source.matrix );
8370  this.matrixWorld.copy( source.matrixWorld );
8371 
8372  this.matrixAutoUpdate = source.matrixAutoUpdate;
8373  this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
8374 
8375  this.visible = source.visible;
8376 
8377  this.castShadow = source.castShadow;
8378  this.receiveShadow = source.receiveShadow;
8379 
8380  this.frustumCulled = source.frustumCulled;
8381  this.renderOrder = source.renderOrder;
8382 
8383  this.userData = JSON.parse( JSON.stringify( source.userData ) );
8384 
8385  if ( recursive === true ) {
8386 
8387  for ( var i = 0; i < source.children.length; i ++ ) {
8388 
8389  var child = source.children[ i ];
8390  this.add( child.clone() );
8391 
8392  }
8393 
8394  }
8395 
8396  return this;
8397 
8398  }
8399 
8400 };
8401 
8402 THREE.EventDispatcher.prototype.apply( THREE.Object3D.prototype );
8403 
8404 THREE.Object3DIdCount = 0;
8405 
8406 // File:src/core/Face3.js
8407 
8413 THREE.Face3 = function ( a, b, c, normal, color, materialIndex ) {
8414 
8415  this.a = a;
8416  this.b = b;
8417  this.c = c;
8418 
8419  this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3();
8420  this.vertexNormals = Array.isArray( normal ) ? normal : [];
8421 
8422  this.color = color instanceof THREE.Color ? color : new THREE.Color();
8423  this.vertexColors = Array.isArray( color ) ? color : [];
8424 
8425  this.materialIndex = materialIndex !== undefined ? materialIndex : 0;
8426 
8427 };
8428 
8429 THREE.Face3.prototype = {
8430 
8431  constructor: THREE.Face3,
8432 
8433  clone: function () {
8434 
8435  return new this.constructor().copy( this );
8436 
8437  },
8438 
8439  copy: function ( source ) {
8440 
8441  this.a = source.a;
8442  this.b = source.b;
8443  this.c = source.c;
8444 
8445  this.normal.copy( source.normal );
8446  this.color.copy( source.color );
8447 
8448  this.materialIndex = source.materialIndex;
8449 
8450  for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
8451 
8452  this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
8453 
8454  }
8455 
8456  for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {
8457 
8458  this.vertexColors[ i ] = source.vertexColors[ i ].clone();
8459 
8460  }
8461 
8462  return this;
8463 
8464  }
8465 
8466 };
8467 
8468 // File:src/core/Face4.js
8469 
8474 THREE.Face4 = function ( a, b, c, d, normal, color, materialIndex ) {
8475 
8476  console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );
8477  return new THREE.Face3( a, b, c, normal, color, materialIndex );
8478 
8479 };
8480 
8481 // File:src/core/BufferAttribute.js
8482 
8487 THREE.BufferAttribute = function ( array, itemSize ) {
8488 
8489  this.uuid = THREE.Math.generateUUID();
8490 
8491  this.array = array;
8492  this.itemSize = itemSize;
8493 
8494  this.dynamic = false;
8495  this.updateRange = { offset: 0, count: - 1 };
8496 
8497  this.version = 0;
8498 
8499 };
8500 
8501 THREE.BufferAttribute.prototype = {
8502 
8503  constructor: THREE.BufferAttribute,
8504 
8505  get length() {
8506 
8507  console.warn( 'THREE.BufferAttribute: .length has been deprecated. Please use .count.' );
8508  return this.array.length;
8509 
8510  },
8511 
8512  get count() {
8513 
8514  return this.array.length / this.itemSize;
8515 
8516  },
8517 
8518  set needsUpdate( value ) {
8519 
8520  if ( value === true ) this.version ++;
8521 
8522  },
8523 
8524  setDynamic: function ( value ) {
8525 
8526  this.dynamic = value;
8527 
8528  return this;
8529 
8530  },
8531 
8532  copy: function ( source ) {
8533 
8534  this.array = new source.array.constructor( source.array );
8535  this.itemSize = source.itemSize;
8536 
8537  this.dynamic = source.dynamic;
8538 
8539  return this;
8540 
8541  },
8542 
8543  copyAt: function ( index1, attribute, index2 ) {
8544 
8545  index1 *= this.itemSize;
8546  index2 *= attribute.itemSize;
8547 
8548  for ( var i = 0, l = this.itemSize; i < l; i ++ ) {
8549 
8550  this.array[ index1 + i ] = attribute.array[ index2 + i ];
8551 
8552  }
8553 
8554  return this;
8555 
8556  },
8557 
8558  copyArray: function ( array ) {
8559 
8560  this.array.set( array );
8561 
8562  return this;
8563 
8564  },
8565 
8566  copyColorsArray: function ( colors ) {
8567 
8568  var array = this.array, offset = 0;
8569 
8570  for ( var i = 0, l = colors.length; i < l; i ++ ) {
8571 
8572  var color = colors[ i ];
8573 
8574  if ( color === undefined ) {
8575 
8576  console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
8577  color = new THREE.Color();
8578 
8579  }
8580 
8581  array[ offset ++ ] = color.r;
8582  array[ offset ++ ] = color.g;
8583  array[ offset ++ ] = color.b;
8584 
8585  }
8586 
8587  return this;
8588 
8589  },
8590 
8591  copyIndicesArray: function ( indices ) {
8592 
8593  var array = this.array, offset = 0;
8594 
8595  for ( var i = 0, l = indices.length; i < l; i ++ ) {
8596 
8597  var index = indices[ i ];
8598 
8599  array[ offset ++ ] = index.a;
8600  array[ offset ++ ] = index.b;
8601  array[ offset ++ ] = index.c;
8602 
8603  }
8604 
8605  return this;
8606 
8607  },
8608 
8609  copyVector2sArray: function ( vectors ) {
8610 
8611  var array = this.array, offset = 0;
8612 
8613  for ( var i = 0, l = vectors.length; i < l; i ++ ) {
8614 
8615  var vector = vectors[ i ];
8616 
8617  if ( vector === undefined ) {
8618 
8619  console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
8620  vector = new THREE.Vector2();
8621 
8622  }
8623 
8624  array[ offset ++ ] = vector.x;
8625  array[ offset ++ ] = vector.y;
8626 
8627  }
8628 
8629  return this;
8630 
8631  },
8632 
8633  copyVector3sArray: function ( vectors ) {
8634 
8635  var array = this.array, offset = 0;
8636 
8637  for ( var i = 0, l = vectors.length; i < l; i ++ ) {
8638 
8639  var vector = vectors[ i ];
8640 
8641  if ( vector === undefined ) {
8642 
8643  console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
8644  vector = new THREE.Vector3();
8645 
8646  }
8647 
8648  array[ offset ++ ] = vector.x;
8649  array[ offset ++ ] = vector.y;
8650  array[ offset ++ ] = vector.z;
8651 
8652  }
8653 
8654  return this;
8655 
8656  },
8657 
8658  copyVector4sArray: function ( vectors ) {
8659 
8660  var array = this.array, offset = 0;
8661 
8662  for ( var i = 0, l = vectors.length; i < l; i ++ ) {
8663 
8664  var vector = vectors[ i ];
8665 
8666  if ( vector === undefined ) {
8667 
8668  console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
8669  vector = new THREE.Vector4();
8670 
8671  }
8672 
8673  array[ offset ++ ] = vector.x;
8674  array[ offset ++ ] = vector.y;
8675  array[ offset ++ ] = vector.z;
8676  array[ offset ++ ] = vector.w;
8677 
8678  }
8679 
8680  return this;
8681 
8682  },
8683 
8684  set: function ( value, offset ) {
8685 
8686  if ( offset === undefined ) offset = 0;
8687 
8688  this.array.set( value, offset );
8689 
8690  return this;
8691 
8692  },
8693 
8694  getX: function ( index ) {
8695 
8696  return this.array[ index * this.itemSize ];
8697 
8698  },
8699 
8700  setX: function ( index, x ) {
8701 
8702  this.array[ index * this.itemSize ] = x;
8703 
8704  return this;
8705 
8706  },
8707 
8708  getY: function ( index ) {
8709 
8710  return this.array[ index * this.itemSize + 1 ];
8711 
8712  },
8713 
8714  setY: function ( index, y ) {
8715 
8716  this.array[ index * this.itemSize + 1 ] = y;
8717 
8718  return this;
8719 
8720  },
8721 
8722  getZ: function ( index ) {
8723 
8724  return this.array[ index * this.itemSize + 2 ];
8725 
8726  },
8727 
8728  setZ: function ( index, z ) {
8729 
8730  this.array[ index * this.itemSize + 2 ] = z;
8731 
8732  return this;
8733 
8734  },
8735 
8736  getW: function ( index ) {
8737 
8738  return this.array[ index * this.itemSize + 3 ];
8739 
8740  },
8741 
8742  setW: function ( index, w ) {
8743 
8744  this.array[ index * this.itemSize + 3 ] = w;
8745 
8746  return this;
8747 
8748  },
8749 
8750  setXY: function ( index, x, y ) {
8751 
8752  index *= this.itemSize;
8753 
8754  this.array[ index + 0 ] = x;
8755  this.array[ index + 1 ] = y;
8756 
8757  return this;
8758 
8759  },
8760 
8761  setXYZ: function ( index, x, y, z ) {
8762 
8763  index *= this.itemSize;
8764 
8765  this.array[ index + 0 ] = x;
8766  this.array[ index + 1 ] = y;
8767  this.array[ index + 2 ] = z;
8768 
8769  return this;
8770 
8771  },
8772 
8773  setXYZW: function ( index, x, y, z, w ) {
8774 
8775  index *= this.itemSize;
8776 
8777  this.array[ index + 0 ] = x;
8778  this.array[ index + 1 ] = y;
8779  this.array[ index + 2 ] = z;
8780  this.array[ index + 3 ] = w;
8781 
8782  return this;
8783 
8784  },
8785 
8786  clone: function () {
8787 
8788  return new this.constructor().copy( this );
8789 
8790  }
8791 
8792 };
8793 
8794 //
8795 
8796 THREE.Int8Attribute = function ( array, itemSize ) {
8797 
8798  return new THREE.BufferAttribute( new Int8Array( array ), itemSize );
8799 
8800 };
8801 
8802 THREE.Uint8Attribute = function ( array, itemSize ) {
8803 
8804  return new THREE.BufferAttribute( new Uint8Array( array ), itemSize );
8805 
8806 };
8807 
8808 THREE.Uint8ClampedAttribute = function ( array, itemSize ) {
8809 
8810  return new THREE.BufferAttribute( new Uint8ClampedArray( array ), itemSize );
8811 
8812 };
8813 
8814 THREE.Int16Attribute = function ( array, itemSize ) {
8815 
8816  return new THREE.BufferAttribute( new Int16Array( array ), itemSize );
8817 
8818 };
8819 
8820 THREE.Uint16Attribute = function ( array, itemSize ) {
8821 
8822  return new THREE.BufferAttribute( new Uint16Array( array ), itemSize );
8823 
8824 };
8825 
8826 THREE.Int32Attribute = function ( array, itemSize ) {
8827 
8828  return new THREE.BufferAttribute( new Int32Array( array ), itemSize );
8829 
8830 };
8831 
8832 THREE.Uint32Attribute = function ( array, itemSize ) {
8833 
8834  return new THREE.BufferAttribute( new Uint32Array( array ), itemSize );
8835 
8836 };
8837 
8838 THREE.Float32Attribute = function ( array, itemSize ) {
8839 
8840  return new THREE.BufferAttribute( new Float32Array( array ), itemSize );
8841 
8842 };
8843 
8844 THREE.Float64Attribute = function ( array, itemSize ) {
8845 
8846  return new THREE.BufferAttribute( new Float64Array( array ), itemSize );
8847 
8848 };
8849 
8850 
8851 // Deprecated
8852 
8853 THREE.DynamicBufferAttribute = function ( array, itemSize ) {
8854 
8855  console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.' );
8856  return new THREE.BufferAttribute( array, itemSize ).setDynamic( true );
8857 
8858 };
8859 
8860 // File:src/core/InstancedBufferAttribute.js
8861 
8866 THREE.InstancedBufferAttribute = function ( array, itemSize, meshPerAttribute ) {
8867 
8868  THREE.BufferAttribute.call( this, array, itemSize );
8869 
8870  this.meshPerAttribute = meshPerAttribute || 1;
8871 
8872 };
8873 
8874 THREE.InstancedBufferAttribute.prototype = Object.create( THREE.BufferAttribute.prototype );
8875 THREE.InstancedBufferAttribute.prototype.constructor = THREE.InstancedBufferAttribute;
8876 
8877 THREE.InstancedBufferAttribute.prototype.copy = function ( source ) {
8878 
8879  THREE.BufferAttribute.prototype.copy.call( this, source );
8880 
8881  this.meshPerAttribute = source.meshPerAttribute;
8882 
8883  return this;
8884 
8885 };
8886 
8887 // File:src/core/InterleavedBuffer.js
8888 
8893 THREE.InterleavedBuffer = function ( array, stride ) {
8894 
8895  this.uuid = THREE.Math.generateUUID();
8896 
8897  this.array = array;
8898  this.stride = stride;
8899 
8900  this.dynamic = false;
8901  this.updateRange = { offset: 0, count: - 1 };
8902 
8903  this.version = 0;
8904 
8905 };
8906 
8907 THREE.InterleavedBuffer.prototype = {
8908 
8909  constructor: THREE.InterleavedBuffer,
8910 
8911  get length () {
8912 
8913  return this.array.length;
8914 
8915  },
8916 
8917  get count () {
8918 
8919  return this.array.length / this.stride;
8920 
8921  },
8922 
8923  set needsUpdate( value ) {
8924 
8925  if ( value === true ) this.version ++;
8926 
8927  },
8928 
8929  setDynamic: function ( value ) {
8930 
8931  this.dynamic = value;
8932 
8933  return this;
8934 
8935  },
8936 
8937  copy: function ( source ) {
8938 
8939  this.array = new source.array.constructor( source.array );
8940  this.stride = source.stride;
8941  this.dynamic = source.dynamic;
8942 
8943  },
8944 
8945  copyAt: function ( index1, attribute, index2 ) {
8946 
8947  index1 *= this.stride;
8948  index2 *= attribute.stride;
8949 
8950  for ( var i = 0, l = this.stride; i < l; i ++ ) {
8951 
8952  this.array[ index1 + i ] = attribute.array[ index2 + i ];
8953 
8954  }
8955 
8956  return this;
8957 
8958  },
8959 
8960  set: function ( value, offset ) {
8961 
8962  if ( offset === undefined ) offset = 0;
8963 
8964  this.array.set( value, offset );
8965 
8966  return this;
8967 
8968  },
8969 
8970  clone: function () {
8971 
8972  return new this.constructor().copy( this );
8973 
8974  }
8975 
8976 };
8977 
8978 // File:src/core/InstancedInterleavedBuffer.js
8979 
8984 THREE.InstancedInterleavedBuffer = function ( array, stride, meshPerAttribute ) {
8985 
8986  THREE.InterleavedBuffer.call( this, array, stride );
8987 
8988  this.meshPerAttribute = meshPerAttribute || 1;
8989 
8990 };
8991 
8992 THREE.InstancedInterleavedBuffer.prototype = Object.create( THREE.InterleavedBuffer.prototype );
8993 THREE.InstancedInterleavedBuffer.prototype.constructor = THREE.InstancedInterleavedBuffer;
8994 
8995 THREE.InstancedInterleavedBuffer.prototype.copy = function ( source ) {
8996 
8997  THREE.InterleavedBuffer.prototype.copy.call( this, source );
8998 
8999  this.meshPerAttribute = source.meshPerAttribute;
9000 
9001  return this;
9002 
9003 };
9004 
9005 // File:src/core/InterleavedBufferAttribute.js
9006 
9011 THREE.InterleavedBufferAttribute = function ( interleavedBuffer, itemSize, offset ) {
9012 
9013  this.uuid = THREE.Math.generateUUID();
9014 
9015  this.data = interleavedBuffer;
9016  this.itemSize = itemSize;
9017  this.offset = offset;
9018 
9019 };
9020 
9021 
9022 THREE.InterleavedBufferAttribute.prototype = {
9023 
9024  constructor: THREE.InterleavedBufferAttribute,
9025 
9026  get length() {
9027 
9028  console.warn( 'THREE.BufferAttribute: .length has been deprecated. Please use .count.' );
9029  return this.array.length;
9030 
9031  },
9032 
9033  get count() {
9034 
9035  return this.data.array.length / this.data.stride;
9036 
9037  },
9038 
9039  setX: function ( index, x ) {
9040 
9041  this.data.array[ index * this.data.stride + this.offset ] = x;
9042 
9043  return this;
9044 
9045  },
9046 
9047  setY: function ( index, y ) {
9048 
9049  this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
9050 
9051  return this;
9052 
9053  },
9054 
9055  setZ: function ( index, z ) {
9056 
9057  this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
9058 
9059  return this;
9060 
9061  },
9062 
9063  setW: function ( index, w ) {
9064 
9065  this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
9066 
9067  return this;
9068 
9069  },
9070 
9071  getX: function ( index ) {
9072 
9073  return this.data.array[ index * this.data.stride + this.offset ];
9074 
9075  },
9076 
9077  getY: function ( index ) {
9078 
9079  return this.data.array[ index * this.data.stride + this.offset + 1 ];
9080 
9081  },
9082 
9083  getZ: function ( index ) {
9084 
9085  return this.data.array[ index * this.data.stride + this.offset + 2 ];
9086 
9087  },
9088 
9089  getW: function ( index ) {
9090 
9091  return this.data.array[ index * this.data.stride + this.offset + 3 ];
9092 
9093  },
9094 
9095  setXY: function ( index, x, y ) {
9096 
9097  index = index * this.data.stride + this.offset;
9098 
9099  this.data.array[ index + 0 ] = x;
9100  this.data.array[ index + 1 ] = y;
9101 
9102  return this;
9103 
9104  },
9105 
9106  setXYZ: function ( index, x, y, z ) {
9107 
9108  index = index * this.data.stride + this.offset;
9109 
9110  this.data.array[ index + 0 ] = x;
9111  this.data.array[ index + 1 ] = y;
9112  this.data.array[ index + 2 ] = z;
9113 
9114  return this;
9115 
9116  },
9117 
9118  setXYZW: function ( index, x, y, z, w ) {
9119 
9120  index = index * this.data.stride + this.offset;
9121 
9122  this.data.array[ index + 0 ] = x;
9123  this.data.array[ index + 1 ] = y;
9124  this.data.array[ index + 2 ] = z;
9125  this.data.array[ index + 3 ] = w;
9126 
9127  return this;
9128 
9129  }
9130 
9131 };
9132 
9133 // File:src/core/Geometry.js
9134 
9144 THREE.Geometry = function () {
9145 
9146  Object.defineProperty( this, 'id', { value: THREE.GeometryIdCount ++ } );
9147 
9148  this.uuid = THREE.Math.generateUUID();
9149 
9150  this.name = '';
9151  this.type = 'Geometry';
9152 
9153  this.vertices = [];
9154  this.colors = [];
9155  this.faces = [];
9156  this.faceVertexUvs = [ [] ];
9157 
9158  this.morphTargets = [];
9159  this.morphNormals = [];
9160 
9161  this.skinWeights = [];
9162  this.skinIndices = [];
9163 
9164  this.lineDistances = [];
9165 
9166  this.boundingBox = null;
9167  this.boundingSphere = null;
9168 
9169  // update flags
9170 
9171  this.verticesNeedUpdate = false;
9172  this.elementsNeedUpdate = false;
9173  this.uvsNeedUpdate = false;
9174  this.normalsNeedUpdate = false;
9175  this.colorsNeedUpdate = false;
9176  this.lineDistancesNeedUpdate = false;
9177  this.groupsNeedUpdate = false;
9178 
9179 };
9180 
9181 THREE.Geometry.prototype = {
9182 
9183  constructor: THREE.Geometry,
9184 
9185  applyMatrix: function ( matrix ) {
9186 
9187  var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
9188 
9189  for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
9190 
9191  var vertex = this.vertices[ i ];
9192  vertex.applyMatrix4( matrix );
9193 
9194  }
9195 
9196  for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
9197 
9198  var face = this.faces[ i ];
9199  face.normal.applyMatrix3( normalMatrix ).normalize();
9200 
9201  for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
9202 
9203  face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
9204 
9205  }
9206 
9207  }
9208 
9209  if ( this.boundingBox !== null ) {
9210 
9211  this.computeBoundingBox();
9212 
9213  }
9214 
9215  if ( this.boundingSphere !== null ) {
9216 
9217  this.computeBoundingSphere();
9218 
9219  }
9220 
9221  this.verticesNeedUpdate = true;
9222  this.normalsNeedUpdate = true;
9223 
9224  },
9225 
9226  rotateX: function () {
9227 
9228  // rotate geometry around world x-axis
9229 
9230  var m1;
9231 
9232  return function rotateX( angle ) {
9233 
9234  if ( m1 === undefined ) m1 = new THREE.Matrix4();
9235 
9236  m1.makeRotationX( angle );
9237 
9238  this.applyMatrix( m1 );
9239 
9240  return this;
9241 
9242  };
9243 
9244  }(),
9245 
9246  rotateY: function () {
9247 
9248  // rotate geometry around world y-axis
9249 
9250  var m1;
9251 
9252  return function rotateY( angle ) {
9253 
9254  if ( m1 === undefined ) m1 = new THREE.Matrix4();
9255 
9256  m1.makeRotationY( angle );
9257 
9258  this.applyMatrix( m1 );
9259 
9260  return this;
9261 
9262  };
9263 
9264  }(),
9265 
9266  rotateZ: function () {
9267 
9268  // rotate geometry around world z-axis
9269 
9270  var m1;
9271 
9272  return function rotateZ( angle ) {
9273 
9274  if ( m1 === undefined ) m1 = new THREE.Matrix4();
9275 
9276  m1.makeRotationZ( angle );
9277 
9278  this.applyMatrix( m1 );
9279 
9280  return this;
9281 
9282  };
9283 
9284  }(),
9285 
9286  translate: function () {
9287 
9288  // translate geometry
9289 
9290  var m1;
9291 
9292  return function translate( x, y, z ) {
9293 
9294  if ( m1 === undefined ) m1 = new THREE.Matrix4();
9295 
9296  m1.makeTranslation( x, y, z );
9297 
9298  this.applyMatrix( m1 );
9299 
9300  return this;
9301 
9302  };
9303 
9304  }(),
9305 
9306  scale: function () {
9307 
9308  // scale geometry
9309 
9310  var m1;
9311 
9312  return function scale( x, y, z ) {
9313 
9314  if ( m1 === undefined ) m1 = new THREE.Matrix4();
9315 
9316  m1.makeScale( x, y, z );
9317 
9318  this.applyMatrix( m1 );
9319 
9320  return this;
9321 
9322  };
9323 
9324  }(),
9325 
9326  lookAt: function () {
9327 
9328  var obj;
9329 
9330  return function lookAt( vector ) {
9331 
9332  if ( obj === undefined ) obj = new THREE.Object3D();
9333 
9334  obj.lookAt( vector );
9335 
9336  obj.updateMatrix();
9337 
9338  this.applyMatrix( obj.matrix );
9339 
9340  };
9341 
9342  }(),
9343 
9344  fromBufferGeometry: function ( geometry ) {
9345 
9346  var scope = this;
9347 
9348  var indices = geometry.index !== null ? geometry.index.array : undefined;
9349  var attributes = geometry.attributes;
9350 
9351  var vertices = attributes.position.array;
9352  var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
9353  var colors = attributes.color !== undefined ? attributes.color.array : undefined;
9354  var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
9355  var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
9356 
9357  if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
9358 
9359  var tempNormals = [];
9360  var tempUVs = [];
9361  var tempUVs2 = [];
9362 
9363  for ( var i = 0, j = 0, k = 0; i < vertices.length; i += 3, j += 2, k += 4 ) {
9364 
9365  scope.vertices.push( new THREE.Vector3( vertices[ i ], vertices[ i + 1 ], vertices[ i + 2 ] ) );
9366 
9367  if ( normals !== undefined ) {
9368 
9369  tempNormals.push( new THREE.Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) );
9370 
9371  }
9372 
9373  if ( colors !== undefined ) {
9374 
9375  scope.colors.push( new THREE.Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) );
9376 
9377  }
9378 
9379  if ( uvs !== undefined ) {
9380 
9381  tempUVs.push( new THREE.Vector2( uvs[ j ], uvs[ j + 1 ] ) );
9382 
9383  }
9384 
9385  if ( uvs2 !== undefined ) {
9386 
9387  tempUVs2.push( new THREE.Vector2( uvs2[ j ], uvs2[ j + 1 ] ) );
9388 
9389  }
9390 
9391  }
9392 
9393  function addFace( a, b, c ) {
9394 
9395  var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : [];
9396  var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : [];
9397 
9398  var face = new THREE.Face3( a, b, c, vertexNormals, vertexColors );
9399 
9400  scope.faces.push( face );
9401 
9402  if ( uvs !== undefined ) {
9403 
9404  scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] );
9405 
9406  }
9407 
9408  if ( uvs2 !== undefined ) {
9409 
9410  scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] );
9411 
9412  }
9413 
9414  };
9415 
9416  if ( indices !== undefined ) {
9417 
9418  var groups = geometry.groups;
9419 
9420  if ( groups.length > 0 ) {
9421 
9422  for ( var i = 0; i < groups.length; i ++ ) {
9423 
9424  var group = groups[ i ];
9425 
9426  var start = group.start;
9427  var count = group.count;
9428 
9429  for ( var j = start, jl = start + count; j < jl; j += 3 ) {
9430 
9431  addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ] );
9432 
9433  }
9434 
9435  }
9436 
9437  } else {
9438 
9439  for ( var i = 0; i < indices.length; i += 3 ) {
9440 
9441  addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
9442 
9443  }
9444 
9445  }
9446 
9447  } else {
9448 
9449  for ( var i = 0; i < vertices.length / 3; i += 3 ) {
9450 
9451  addFace( i, i + 1, i + 2 );
9452 
9453  }
9454 
9455  }
9456 
9457  this.computeFaceNormals();
9458 
9459  if ( geometry.boundingBox !== null ) {
9460 
9461  this.boundingBox = geometry.boundingBox.clone();
9462 
9463  }
9464 
9465  if ( geometry.boundingSphere !== null ) {
9466 
9467  this.boundingSphere = geometry.boundingSphere.clone();
9468 
9469  }
9470 
9471  return this;
9472 
9473  },
9474 
9475  center: function () {
9476 
9477  this.computeBoundingBox();
9478 
9479  var offset = this.boundingBox.center().negate();
9480 
9481  this.translate( offset.x, offset.y, offset.z );
9482 
9483  return offset;
9484 
9485  },
9486 
9487  normalize: function () {
9488 
9489  this.computeBoundingSphere();
9490 
9491  var center = this.boundingSphere.center;
9492  var radius = this.boundingSphere.radius;
9493 
9494  var s = radius === 0 ? 1 : 1.0 / radius;
9495 
9496  var matrix = new THREE.Matrix4();
9497  matrix.set(
9498  s, 0, 0, - s * center.x,
9499  0, s, 0, - s * center.y,
9500  0, 0, s, - s * center.z,
9501  0, 0, 0, 1
9502  );
9503 
9504  this.applyMatrix( matrix );
9505 
9506  return this;
9507 
9508  },
9509 
9510  computeFaceNormals: function () {
9511 
9512  var cb = new THREE.Vector3(), ab = new THREE.Vector3();
9513 
9514  for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
9515 
9516  var face = this.faces[ f ];
9517 
9518  var vA = this.vertices[ face.a ];
9519  var vB = this.vertices[ face.b ];
9520  var vC = this.vertices[ face.c ];
9521 
9522  cb.subVectors( vC, vB );
9523  ab.subVectors( vA, vB );
9524  cb.cross( ab );
9525 
9526  cb.normalize();
9527 
9528  face.normal.copy( cb );
9529 
9530  }
9531 
9532  },
9533 
9534  computeVertexNormals: function ( areaWeighted ) {
9535 
9536  var v, vl, f, fl, face, vertices;
9537 
9538  vertices = new Array( this.vertices.length );
9539 
9540  for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
9541 
9542  vertices[ v ] = new THREE.Vector3();
9543 
9544  }
9545 
9546  if ( areaWeighted ) {
9547 
9548  // vertex normals weighted by triangle areas
9549  // http://www.iquilezles.org/www/articles/normals/normals.htm
9550 
9551  var vA, vB, vC;
9552  var cb = new THREE.Vector3(), ab = new THREE.Vector3();
9553 
9554  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9555 
9556  face = this.faces[ f ];
9557 
9558  vA = this.vertices[ face.a ];
9559  vB = this.vertices[ face.b ];
9560  vC = this.vertices[ face.c ];
9561 
9562  cb.subVectors( vC, vB );
9563  ab.subVectors( vA, vB );
9564  cb.cross( ab );
9565 
9566  vertices[ face.a ].add( cb );
9567  vertices[ face.b ].add( cb );
9568  vertices[ face.c ].add( cb );
9569 
9570  }
9571 
9572  } else {
9573 
9574  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9575 
9576  face = this.faces[ f ];
9577 
9578  vertices[ face.a ].add( face.normal );
9579  vertices[ face.b ].add( face.normal );
9580  vertices[ face.c ].add( face.normal );
9581 
9582  }
9583 
9584  }
9585 
9586  for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
9587 
9588  vertices[ v ].normalize();
9589 
9590  }
9591 
9592  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9593 
9594  face = this.faces[ f ];
9595 
9596  var vertexNormals = face.vertexNormals;
9597 
9598  if ( vertexNormals.length === 3 ) {
9599 
9600  vertexNormals[ 0 ].copy( vertices[ face.a ] );
9601  vertexNormals[ 1 ].copy( vertices[ face.b ] );
9602  vertexNormals[ 2 ].copy( vertices[ face.c ] );
9603 
9604  } else {
9605 
9606  vertexNormals[ 0 ] = vertices[ face.a ].clone();
9607  vertexNormals[ 1 ] = vertices[ face.b ].clone();
9608  vertexNormals[ 2 ] = vertices[ face.c ].clone();
9609 
9610  }
9611 
9612  }
9613 
9614  },
9615 
9616  computeMorphNormals: function () {
9617 
9618  var i, il, f, fl, face;
9619 
9620  // save original normals
9621  // - create temp variables on first access
9622  // otherwise just copy (for faster repeated calls)
9623 
9624  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9625 
9626  face = this.faces[ f ];
9627 
9628  if ( ! face.__originalFaceNormal ) {
9629 
9630  face.__originalFaceNormal = face.normal.clone();
9631 
9632  } else {
9633 
9634  face.__originalFaceNormal.copy( face.normal );
9635 
9636  }
9637 
9638  if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
9639 
9640  for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
9641 
9642  if ( ! face.__originalVertexNormals[ i ] ) {
9643 
9644  face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
9645 
9646  } else {
9647 
9648  face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
9649 
9650  }
9651 
9652  }
9653 
9654  }
9655 
9656  // use temp geometry to compute face and vertex normals for each morph
9657 
9658  var tmpGeo = new THREE.Geometry();
9659  tmpGeo.faces = this.faces;
9660 
9661  for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
9662 
9663  // create on first access
9664 
9665  if ( ! this.morphNormals[ i ] ) {
9666 
9667  this.morphNormals[ i ] = {};
9668  this.morphNormals[ i ].faceNormals = [];
9669  this.morphNormals[ i ].vertexNormals = [];
9670 
9671  var dstNormalsFace = this.morphNormals[ i ].faceNormals;
9672  var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
9673 
9674  var faceNormal, vertexNormals;
9675 
9676  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9677 
9678  faceNormal = new THREE.Vector3();
9679  vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
9680 
9681  dstNormalsFace.push( faceNormal );
9682  dstNormalsVertex.push( vertexNormals );
9683 
9684  }
9685 
9686  }
9687 
9688  var morphNormals = this.morphNormals[ i ];
9689 
9690  // set vertices to morph target
9691 
9692  tmpGeo.vertices = this.morphTargets[ i ].vertices;
9693 
9694  // compute morph normals
9695 
9696  tmpGeo.computeFaceNormals();
9697  tmpGeo.computeVertexNormals();
9698 
9699  // store morph normals
9700 
9701  var faceNormal, vertexNormals;
9702 
9703  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9704 
9705  face = this.faces[ f ];
9706 
9707  faceNormal = morphNormals.faceNormals[ f ];
9708  vertexNormals = morphNormals.vertexNormals[ f ];
9709 
9710  faceNormal.copy( face.normal );
9711 
9712  vertexNormals.a.copy( face.vertexNormals[ 0 ] );
9713  vertexNormals.b.copy( face.vertexNormals[ 1 ] );
9714  vertexNormals.c.copy( face.vertexNormals[ 2 ] );
9715 
9716  }
9717 
9718  }
9719 
9720  // restore original normals
9721 
9722  for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
9723 
9724  face = this.faces[ f ];
9725 
9726  face.normal = face.__originalFaceNormal;
9727  face.vertexNormals = face.__originalVertexNormals;
9728 
9729  }
9730 
9731  },
9732 
9733  computeTangents: function () {
9734 
9735  console.warn( 'THREE.Geometry: .computeTangents() has been removed.' );
9736 
9737  },
9738 
9739  computeLineDistances: function () {
9740 
9741  var d = 0;
9742  var vertices = this.vertices;
9743 
9744  for ( var i = 0, il = vertices.length; i < il; i ++ ) {
9745 
9746  if ( i > 0 ) {
9747 
9748  d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
9749 
9750  }
9751 
9752  this.lineDistances[ i ] = d;
9753 
9754  }
9755 
9756  },
9757 
9758  computeBoundingBox: function () {
9759 
9760  if ( this.boundingBox === null ) {
9761 
9762  this.boundingBox = new THREE.Box3();
9763 
9764  }
9765 
9766  this.boundingBox.setFromPoints( this.vertices );
9767 
9768  },
9769 
9770  computeBoundingSphere: function () {
9771 
9772  if ( this.boundingSphere === null ) {
9773 
9774  this.boundingSphere = new THREE.Sphere();
9775 
9776  }
9777 
9778  this.boundingSphere.setFromPoints( this.vertices );
9779 
9780  },
9781 
9782  merge: function ( geometry, matrix, materialIndexOffset ) {
9783 
9784  if ( geometry instanceof THREE.Geometry === false ) {
9785 
9786  console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
9787  return;
9788 
9789  }
9790 
9791  var normalMatrix,
9792  vertexOffset = this.vertices.length,
9793  vertices1 = this.vertices,
9794  vertices2 = geometry.vertices,
9795  faces1 = this.faces,
9796  faces2 = geometry.faces,
9797  uvs1 = this.faceVertexUvs[ 0 ],
9798  uvs2 = geometry.faceVertexUvs[ 0 ];
9799 
9800  if ( materialIndexOffset === undefined ) materialIndexOffset = 0;
9801 
9802  if ( matrix !== undefined ) {
9803 
9804  normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
9805 
9806  }
9807 
9808  // vertices
9809 
9810  for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
9811 
9812  var vertex = vertices2[ i ];
9813 
9814  var vertexCopy = vertex.clone();
9815 
9816  if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
9817 
9818  vertices1.push( vertexCopy );
9819 
9820  }
9821 
9822  // faces
9823 
9824  for ( i = 0, il = faces2.length; i < il; i ++ ) {
9825 
9826  var face = faces2[ i ], faceCopy, normal, color,
9827  faceVertexNormals = face.vertexNormals,
9828  faceVertexColors = face.vertexColors;
9829 
9830  faceCopy = new THREE.Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
9831  faceCopy.normal.copy( face.normal );
9832 
9833  if ( normalMatrix !== undefined ) {
9834 
9835  faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
9836 
9837  }
9838 
9839  for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
9840 
9841  normal = faceVertexNormals[ j ].clone();
9842 
9843  if ( normalMatrix !== undefined ) {
9844 
9845  normal.applyMatrix3( normalMatrix ).normalize();
9846 
9847  }
9848 
9849  faceCopy.vertexNormals.push( normal );
9850 
9851  }
9852 
9853  faceCopy.color.copy( face.color );
9854 
9855  for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
9856 
9857  color = faceVertexColors[ j ];
9858  faceCopy.vertexColors.push( color.clone() );
9859 
9860  }
9861 
9862  faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
9863 
9864  faces1.push( faceCopy );
9865 
9866  }
9867 
9868  // uvs
9869 
9870  for ( i = 0, il = uvs2.length; i < il; i ++ ) {
9871 
9872  var uv = uvs2[ i ], uvCopy = [];
9873 
9874  if ( uv === undefined ) {
9875 
9876  continue;
9877 
9878  }
9879 
9880  for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
9881 
9882  uvCopy.push( uv[ j ].clone() );
9883 
9884  }
9885 
9886  uvs1.push( uvCopy );
9887 
9888  }
9889 
9890  },
9891 
9892  mergeMesh: function ( mesh ) {
9893 
9894  if ( mesh instanceof THREE.Mesh === false ) {
9895 
9896  console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
9897  return;
9898 
9899  }
9900 
9901  mesh.matrixAutoUpdate && mesh.updateMatrix();
9902 
9903  this.merge( mesh.geometry, mesh.matrix );
9904 
9905  },
9906 
9907  /*
9908  * Checks for duplicate vertices with hashmap.
9909  * Duplicated vertices are removed
9910  * and faces' vertices are updated.
9911  */
9912 
9913  mergeVertices: function () {
9914 
9915  var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
9916  var unique = [], changes = [];
9917 
9918  var v, key;
9919  var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001
9920  var precision = Math.pow( 10, precisionPoints );
9921  var i, il, face;
9922  var indices, j, jl;
9923 
9924  for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
9925 
9926  v = this.vertices[ i ];
9927  key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
9928 
9929  if ( verticesMap[ key ] === undefined ) {
9930 
9931  verticesMap[ key ] = i;
9932  unique.push( this.vertices[ i ] );
9933  changes[ i ] = unique.length - 1;
9934 
9935  } else {
9936 
9937  //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
9938  changes[ i ] = changes[ verticesMap[ key ] ];
9939 
9940  }
9941 
9942  }
9943 
9944 
9945  // if faces are completely degenerate after merging vertices, we
9946  // have to remove them from the geometry.
9947  var faceIndicesToRemove = [];
9948 
9949  for ( i = 0, il = this.faces.length; i < il; i ++ ) {
9950 
9951  face = this.faces[ i ];
9952 
9953  face.a = changes[ face.a ];
9954  face.b = changes[ face.b ];
9955  face.c = changes[ face.c ];
9956 
9957  indices = [ face.a, face.b, face.c ];
9958 
9959  var dupIndex = - 1;
9960 
9961  // if any duplicate vertices are found in a Face3
9962  // we have to remove the face as nothing can be saved
9963  for ( var n = 0; n < 3; n ++ ) {
9964 
9965  if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
9966 
9967  dupIndex = n;
9968  faceIndicesToRemove.push( i );
9969  break;
9970 
9971  }
9972 
9973  }
9974 
9975  }
9976 
9977  for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
9978 
9979  var idx = faceIndicesToRemove[ i ];
9980 
9981  this.faces.splice( idx, 1 );
9982 
9983  for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
9984 
9985  this.faceVertexUvs[ j ].splice( idx, 1 );
9986 
9987  }
9988 
9989  }
9990 
9991  // Use unique set of vertices
9992 
9993  var diff = this.vertices.length - unique.length;
9994  this.vertices = unique;
9995  return diff;
9996 
9997  },
9998 
9999  sortFacesByMaterialIndex: function () {
10000 
10001  var faces = this.faces;
10002  var length = faces.length;
10003 
10004  // tag faces
10005 
10006  for ( var i = 0; i < length; i ++ ) {
10007 
10008  faces[ i ]._id = i;
10009 
10010  }
10011 
10012  // sort faces
10013 
10014  function materialIndexSort( a, b ) {
10015 
10016  return a.materialIndex - b.materialIndex;
10017 
10018  }
10019 
10020  faces.sort( materialIndexSort );
10021 
10022  // sort uvs
10023 
10024  var uvs1 = this.faceVertexUvs[ 0 ];
10025  var uvs2 = this.faceVertexUvs[ 1 ];
10026 
10027  var newUvs1, newUvs2;
10028 
10029  if ( uvs1 && uvs1.length === length ) newUvs1 = [];
10030  if ( uvs2 && uvs2.length === length ) newUvs2 = [];
10031 
10032  for ( var i = 0; i < length; i ++ ) {
10033 
10034  var id = faces[ i ]._id;
10035 
10036  if ( newUvs1 ) newUvs1.push( uvs1[ id ] );
10037  if ( newUvs2 ) newUvs2.push( uvs2[ id ] );
10038 
10039  }
10040 
10041  if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;
10042  if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;
10043 
10044  },
10045 
10046  toJSON: function () {
10047 
10048  var data = {
10049  metadata: {
10050  version: 4.4,
10051  type: 'Geometry',
10052  generator: 'Geometry.toJSON'
10053  }
10054  };
10055 
10056  // standard Geometry serialization
10057 
10058  data.uuid = this.uuid;
10059  data.type = this.type;
10060  if ( this.name !== '' ) data.name = this.name;
10061 
10062  if ( this.parameters !== undefined ) {
10063 
10064  var parameters = this.parameters;
10065 
10066  for ( var key in parameters ) {
10067 
10068  if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
10069 
10070  }
10071 
10072  return data;
10073 
10074  }
10075 
10076  var vertices = [];
10077 
10078  for ( var i = 0; i < this.vertices.length; i ++ ) {
10079 
10080  var vertex = this.vertices[ i ];
10081  vertices.push( vertex.x, vertex.y, vertex.z );
10082 
10083  }
10084 
10085  var faces = [];
10086  var normals = [];
10087  var normalsHash = {};
10088  var colors = [];
10089  var colorsHash = {};
10090  var uvs = [];
10091  var uvsHash = {};
10092 
10093  for ( var i = 0; i < this.faces.length; i ++ ) {
10094 
10095  var face = this.faces[ i ];
10096 
10097  var hasMaterial = false; // face.materialIndex !== undefined;
10098  var hasFaceUv = false; // deprecated
10099  var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
10100  var hasFaceNormal = face.normal.length() > 0;
10101  var hasFaceVertexNormal = face.vertexNormals.length > 0;
10102  var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
10103  var hasFaceVertexColor = face.vertexColors.length > 0;
10104 
10105  var faceType = 0;
10106 
10107  faceType = setBit( faceType, 0, 0 );
10108  faceType = setBit( faceType, 1, hasMaterial );
10109  faceType = setBit( faceType, 2, hasFaceUv );
10110  faceType = setBit( faceType, 3, hasFaceVertexUv );
10111  faceType = setBit( faceType, 4, hasFaceNormal );
10112  faceType = setBit( faceType, 5, hasFaceVertexNormal );
10113  faceType = setBit( faceType, 6, hasFaceColor );
10114  faceType = setBit( faceType, 7, hasFaceVertexColor );
10115 
10116  faces.push( faceType );
10117  faces.push( face.a, face.b, face.c );
10118 
10119  if ( hasFaceVertexUv ) {
10120 
10121  var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
10122 
10123  faces.push(
10124  getUvIndex( faceVertexUvs[ 0 ] ),
10125  getUvIndex( faceVertexUvs[ 1 ] ),
10126  getUvIndex( faceVertexUvs[ 2 ] )
10127  );
10128 
10129  }
10130 
10131  if ( hasFaceNormal ) {
10132 
10133  faces.push( getNormalIndex( face.normal ) );
10134 
10135  }
10136 
10137  if ( hasFaceVertexNormal ) {
10138 
10139  var vertexNormals = face.vertexNormals;
10140 
10141  faces.push(
10142  getNormalIndex( vertexNormals[ 0 ] ),
10143  getNormalIndex( vertexNormals[ 1 ] ),
10144  getNormalIndex( vertexNormals[ 2 ] )
10145  );
10146 
10147  }
10148 
10149  if ( hasFaceColor ) {
10150 
10151  faces.push( getColorIndex( face.color ) );
10152 
10153  }
10154 
10155  if ( hasFaceVertexColor ) {
10156 
10157  var vertexColors = face.vertexColors;
10158 
10159  faces.push(
10160  getColorIndex( vertexColors[ 0 ] ),
10161  getColorIndex( vertexColors[ 1 ] ),
10162  getColorIndex( vertexColors[ 2 ] )
10163  );
10164 
10165  }
10166 
10167  }
10168 
10169  function setBit( value, position, enabled ) {
10170 
10171  return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
10172 
10173  }
10174 
10175  function getNormalIndex( normal ) {
10176 
10177  var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
10178 
10179  if ( normalsHash[ hash ] !== undefined ) {
10180 
10181  return normalsHash[ hash ];
10182 
10183  }
10184 
10185  normalsHash[ hash ] = normals.length / 3;
10186  normals.push( normal.x, normal.y, normal.z );
10187 
10188  return normalsHash[ hash ];
10189 
10190  }
10191 
10192  function getColorIndex( color ) {
10193 
10194  var hash = color.r.toString() + color.g.toString() + color.b.toString();
10195 
10196  if ( colorsHash[ hash ] !== undefined ) {
10197 
10198  return colorsHash[ hash ];
10199 
10200  }
10201 
10202  colorsHash[ hash ] = colors.length;
10203  colors.push( color.getHex() );
10204 
10205  return colorsHash[ hash ];
10206 
10207  }
10208 
10209  function getUvIndex( uv ) {
10210 
10211  var hash = uv.x.toString() + uv.y.toString();
10212 
10213  if ( uvsHash[ hash ] !== undefined ) {
10214 
10215  return uvsHash[ hash ];
10216 
10217  }
10218 
10219  uvsHash[ hash ] = uvs.length / 2;
10220  uvs.push( uv.x, uv.y );
10221 
10222  return uvsHash[ hash ];
10223 
10224  }
10225 
10226  data.data = {};
10227 
10228  data.data.vertices = vertices;
10229  data.data.normals = normals;
10230  if ( colors.length > 0 ) data.data.colors = colors;
10231  if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
10232  data.data.faces = faces;
10233 
10234  return data;
10235 
10236  },
10237 
10238  clone: function () {
10239 
10240  return new this.constructor().copy( this );
10241 
10242  },
10243 
10244  copy: function ( source ) {
10245 
10246  this.vertices = [];
10247  this.faces = [];
10248  this.faceVertexUvs = [ [] ];
10249 
10250  var vertices = source.vertices;
10251 
10252  for ( var i = 0, il = vertices.length; i < il; i ++ ) {
10253 
10254  this.vertices.push( vertices[ i ].clone() );
10255 
10256  }
10257 
10258  var faces = source.faces;
10259 
10260  for ( var i = 0, il = faces.length; i < il; i ++ ) {
10261 
10262  this.faces.push( faces[ i ].clone() );
10263 
10264  }
10265 
10266  for ( var i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
10267 
10268  var faceVertexUvs = source.faceVertexUvs[ i ];
10269 
10270  if ( this.faceVertexUvs[ i ] === undefined ) {
10271 
10272  this.faceVertexUvs[ i ] = [];
10273 
10274  }
10275 
10276  for ( var j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
10277 
10278  var uvs = faceVertexUvs[ j ], uvsCopy = [];
10279 
10280  for ( var k = 0, kl = uvs.length; k < kl; k ++ ) {
10281 
10282  var uv = uvs[ k ];
10283 
10284  uvsCopy.push( uv.clone() );
10285 
10286  }
10287 
10288  this.faceVertexUvs[ i ].push( uvsCopy );
10289 
10290  }
10291 
10292  }
10293 
10294  return this;
10295 
10296  },
10297 
10298  dispose: function () {
10299 
10300  this.dispatchEvent( { type: 'dispose' } );
10301 
10302  }
10303 
10304 };
10305 
10306 THREE.EventDispatcher.prototype.apply( THREE.Geometry.prototype );
10307 
10308 THREE.GeometryIdCount = 0;
10309 
10310 // File:src/core/DirectGeometry.js
10311 
10316 THREE.DirectGeometry = function () {
10317 
10318  Object.defineProperty( this, 'id', { value: THREE.GeometryIdCount ++ } );
10319 
10320  this.uuid = THREE.Math.generateUUID();
10321 
10322  this.name = '';
10323  this.type = 'DirectGeometry';
10324 
10325  this.indices = [];
10326  this.vertices = [];
10327  this.normals = [];
10328  this.colors = [];
10329  this.uvs = [];
10330  this.uvs2 = [];
10331 
10332  this.groups = [];
10333 
10334  this.morphTargets = {};
10335 
10336  this.skinWeights = [];
10337  this.skinIndices = [];
10338 
10339  // this.lineDistances = [];
10340 
10341  this.boundingBox = null;
10342  this.boundingSphere = null;
10343 
10344  // update flags
10345 
10346  this.verticesNeedUpdate = false;
10347  this.normalsNeedUpdate = false;
10348  this.colorsNeedUpdate = false;
10349  this.uvsNeedUpdate = false;
10350  this.groupsNeedUpdate = false;
10351 
10352 };
10353 
10354 THREE.DirectGeometry.prototype = {
10355 
10356  constructor: THREE.DirectGeometry,
10357 
10358  computeBoundingBox: THREE.Geometry.prototype.computeBoundingBox,
10359  computeBoundingSphere: THREE.Geometry.prototype.computeBoundingSphere,
10360 
10361  computeFaceNormals: function () {
10362 
10363  console.warn( 'THREE.DirectGeometry: computeFaceNormals() is not a method of this type of geometry.' );
10364 
10365  },
10366 
10367  computeVertexNormals: function () {
10368 
10369  console.warn( 'THREE.DirectGeometry: computeVertexNormals() is not a method of this type of geometry.' );
10370 
10371  },
10372 
10373  computeGroups: function ( geometry ) {
10374 
10375  var group;
10376  var groups = [];
10377  var materialIndex;
10378 
10379  var faces = geometry.faces;
10380 
10381  for ( var i = 0; i < faces.length; i ++ ) {
10382 
10383  var face = faces[ i ];
10384 
10385  // materials
10386 
10387  if ( face.materialIndex !== materialIndex ) {
10388 
10389  materialIndex = face.materialIndex;
10390 
10391  if ( group !== undefined ) {
10392 
10393  group.count = ( i * 3 ) - group.start;
10394  groups.push( group );
10395 
10396  }
10397 
10398  group = {
10399  start: i * 3,
10400  materialIndex: materialIndex
10401  };
10402 
10403  }
10404 
10405  }
10406 
10407  if ( group !== undefined ) {
10408 
10409  group.count = ( i * 3 ) - group.start;
10410  groups.push( group );
10411 
10412  }
10413 
10414  this.groups = groups;
10415 
10416  },
10417 
10418  fromGeometry: function ( geometry ) {
10419 
10420  var faces = geometry.faces;
10421  var vertices = geometry.vertices;
10422  var faceVertexUvs = geometry.faceVertexUvs;
10423 
10424  var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
10425  var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
10426 
10427  // morphs
10428 
10429  var morphTargets = geometry.morphTargets;
10430  var morphTargetsLength = morphTargets.length;
10431 
10432  if ( morphTargetsLength > 0 ) {
10433 
10434  var morphTargetsPosition = [];
10435 
10436  for ( var i = 0; i < morphTargetsLength; i ++ ) {
10437 
10438  morphTargetsPosition[ i ] = [];
10439 
10440  }
10441 
10442  this.morphTargets.position = morphTargetsPosition;
10443 
10444  }
10445 
10446  var morphNormals = geometry.morphNormals;
10447  var morphNormalsLength = morphNormals.length;
10448 
10449  if ( morphNormalsLength > 0 ) {
10450 
10451  var morphTargetsNormal = [];
10452 
10453  for ( var i = 0; i < morphNormalsLength; i ++ ) {
10454 
10455  morphTargetsNormal[ i ] = [];
10456 
10457  }
10458 
10459  this.morphTargets.normal = morphTargetsNormal;
10460 
10461  }
10462 
10463  // skins
10464 
10465  var skinIndices = geometry.skinIndices;
10466  var skinWeights = geometry.skinWeights;
10467 
10468  var hasSkinIndices = skinIndices.length === vertices.length;
10469  var hasSkinWeights = skinWeights.length === vertices.length;
10470 
10471  //
10472 
10473  for ( var i = 0; i < faces.length; i ++ ) {
10474 
10475  var face = faces[ i ];
10476 
10477  this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
10478 
10479  var vertexNormals = face.vertexNormals;
10480 
10481  if ( vertexNormals.length === 3 ) {
10482 
10483  this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
10484 
10485  } else {
10486 
10487  var normal = face.normal;
10488 
10489  this.normals.push( normal, normal, normal );
10490 
10491  }
10492 
10493  var vertexColors = face.vertexColors;
10494 
10495  if ( vertexColors.length === 3 ) {
10496 
10497  this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
10498 
10499  } else {
10500 
10501  var color = face.color;
10502 
10503  this.colors.push( color, color, color );
10504 
10505  }
10506 
10507  if ( hasFaceVertexUv === true ) {
10508 
10509  var vertexUvs = faceVertexUvs[ 0 ][ i ];
10510 
10511  if ( vertexUvs !== undefined ) {
10512 
10513  this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
10514 
10515  } else {
10516 
10517  console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
10518 
10519  this.uvs.push( new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() );
10520 
10521  }
10522 
10523  }
10524 
10525  if ( hasFaceVertexUv2 === true ) {
10526 
10527  var vertexUvs = faceVertexUvs[ 1 ][ i ];
10528 
10529  if ( vertexUvs !== undefined ) {
10530 
10531  this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
10532 
10533  } else {
10534 
10535  console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
10536 
10537  this.uvs2.push( new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() );
10538 
10539  }
10540 
10541  }
10542 
10543  // morphs
10544 
10545  for ( var j = 0; j < morphTargetsLength; j ++ ) {
10546 
10547  var morphTarget = morphTargets[ j ].vertices;
10548 
10549  morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
10550 
10551  }
10552 
10553  for ( var j = 0; j < morphNormalsLength; j ++ ) {
10554 
10555  var morphNormal = morphNormals[ j ].vertexNormals[ i ];
10556 
10557  morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c );
10558 
10559  }
10560 
10561  // skins
10562 
10563  if ( hasSkinIndices ) {
10564 
10565  this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
10566 
10567  }
10568 
10569  if ( hasSkinWeights ) {
10570 
10571  this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
10572 
10573  }
10574 
10575  }
10576 
10577  this.computeGroups( geometry );
10578 
10579  this.verticesNeedUpdate = geometry.verticesNeedUpdate;
10580  this.normalsNeedUpdate = geometry.normalsNeedUpdate;
10581  this.colorsNeedUpdate = geometry.colorsNeedUpdate;
10582  this.uvsNeedUpdate = geometry.uvsNeedUpdate;
10583  this.groupsNeedUpdate = geometry.groupsNeedUpdate;
10584 
10585  return this;
10586 
10587  },
10588 
10589  dispose: function () {
10590 
10591  this.dispatchEvent( { type: 'dispose' } );
10592 
10593  }
10594 
10595 };
10596 
10597 THREE.EventDispatcher.prototype.apply( THREE.DirectGeometry.prototype );
10598 
10599 // File:src/core/BufferGeometry.js
10600 
10606 THREE.BufferGeometry = function () {
10607 
10608  Object.defineProperty( this, 'id', { value: THREE.GeometryIdCount ++ } );
10609 
10610  this.uuid = THREE.Math.generateUUID();
10611 
10612  this.name = '';
10613  this.type = 'BufferGeometry';
10614 
10615  this.index = null;
10616  this.attributes = {};
10617 
10618  this.morphAttributes = {};
10619 
10620  this.groups = [];
10621 
10622  this.boundingBox = null;
10623  this.boundingSphere = null;
10624 
10625  this.drawRange = { start: 0, count: Infinity };
10626 
10627 };
10628 
10629 THREE.BufferGeometry.prototype = {
10630 
10631  constructor: THREE.BufferGeometry,
10632 
10633  addIndex: function ( index ) {
10634 
10635  console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
10636  this.setIndex( index );
10637 
10638  },
10639 
10640  getIndex: function () {
10641 
10642  return this.index;
10643 
10644  },
10645 
10646  setIndex: function ( index ) {
10647 
10648  this.index = index;
10649 
10650  },
10651 
10652  addAttribute: function ( name, attribute ) {
10653 
10654  if ( attribute instanceof THREE.BufferAttribute === false && attribute instanceof THREE.InterleavedBufferAttribute === false ) {
10655 
10656  console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
10657 
10658  this.addAttribute( name, new THREE.BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
10659 
10660  return;
10661 
10662  }
10663 
10664  if ( name === 'index' ) {
10665 
10666  console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
10667  this.setIndex( attribute );
10668 
10669  return;
10670 
10671  }
10672 
10673  this.attributes[ name ] = attribute;
10674 
10675  },
10676 
10677  getAttribute: function ( name ) {
10678 
10679  return this.attributes[ name ];
10680 
10681  },
10682 
10683  removeAttribute: function ( name ) {
10684 
10685  delete this.attributes[ name ];
10686 
10687  },
10688 
10689  get drawcalls() {
10690 
10691  console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
10692  return this.groups;
10693 
10694  },
10695 
10696  get offsets() {
10697 
10698  console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
10699  return this.groups;
10700 
10701  },
10702 
10703  addDrawCall: function ( start, count, indexOffset ) {
10704 
10705  if ( indexOffset !== undefined ) {
10706 
10707  console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
10708 
10709  }
10710 
10711  console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
10712  this.addGroup( start, count );
10713 
10714  },
10715 
10716  clearDrawCalls: function () {
10717 
10718  console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
10719  this.clearGroups();
10720 
10721  },
10722 
10723  addGroup: function ( start, count, materialIndex ) {
10724 
10725  this.groups.push( {
10726 
10727  start: start,
10728  count: count,
10729  materialIndex: materialIndex !== undefined ? materialIndex : 0
10730 
10731  } );
10732 
10733  },
10734 
10735  clearGroups: function () {
10736 
10737  this.groups = [];
10738 
10739  },
10740 
10741  setDrawRange: function ( start, count ) {
10742 
10743  this.drawRange.start = start;
10744  this.drawRange.count = count;
10745 
10746  },
10747 
10748  applyMatrix: function ( matrix ) {
10749 
10750  var position = this.attributes.position;
10751 
10752  if ( position !== undefined ) {
10753 
10754  matrix.applyToVector3Array( position.array );
10755  position.needsUpdate = true;
10756 
10757  }
10758 
10759  var normal = this.attributes.normal;
10760 
10761  if ( normal !== undefined ) {
10762 
10763  var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
10764 
10765  normalMatrix.applyToVector3Array( normal.array );
10766  normal.needsUpdate = true;
10767 
10768  }
10769 
10770  if ( this.boundingBox !== null ) {
10771 
10772  this.computeBoundingBox();
10773 
10774  }
10775 
10776  if ( this.boundingSphere !== null ) {
10777 
10778  this.computeBoundingSphere();
10779 
10780  }
10781 
10782  },
10783 
10784  rotateX: function () {
10785 
10786  // rotate geometry around world x-axis
10787 
10788  var m1;
10789 
10790  return function rotateX( angle ) {
10791 
10792  if ( m1 === undefined ) m1 = new THREE.Matrix4();
10793 
10794  m1.makeRotationX( angle );
10795 
10796  this.applyMatrix( m1 );
10797 
10798  return this;
10799 
10800  };
10801 
10802  }(),
10803 
10804  rotateY: function () {
10805 
10806  // rotate geometry around world y-axis
10807 
10808  var m1;
10809 
10810  return function rotateY( angle ) {
10811 
10812  if ( m1 === undefined ) m1 = new THREE.Matrix4();
10813 
10814  m1.makeRotationY( angle );
10815 
10816  this.applyMatrix( m1 );
10817 
10818  return this;
10819 
10820  };
10821 
10822  }(),
10823 
10824  rotateZ: function () {
10825 
10826  // rotate geometry around world z-axis
10827 
10828  var m1;
10829 
10830  return function rotateZ( angle ) {
10831 
10832  if ( m1 === undefined ) m1 = new THREE.Matrix4();
10833 
10834  m1.makeRotationZ( angle );
10835 
10836  this.applyMatrix( m1 );
10837 
10838  return this;
10839 
10840  };
10841 
10842  }(),
10843 
10844  translate: function () {
10845 
10846  // translate geometry
10847 
10848  var m1;
10849 
10850  return function translate( x, y, z ) {
10851 
10852  if ( m1 === undefined ) m1 = new THREE.Matrix4();
10853 
10854  m1.makeTranslation( x, y, z );
10855 
10856  this.applyMatrix( m1 );
10857 
10858  return this;
10859 
10860  };
10861 
10862  }(),
10863 
10864  scale: function () {
10865 
10866  // scale geometry
10867 
10868  var m1;
10869 
10870  return function scale( x, y, z ) {
10871 
10872  if ( m1 === undefined ) m1 = new THREE.Matrix4();
10873 
10874  m1.makeScale( x, y, z );
10875 
10876  this.applyMatrix( m1 );
10877 
10878  return this;
10879 
10880  };
10881 
10882  }(),
10883 
10884  lookAt: function () {
10885 
10886  var obj;
10887 
10888  return function lookAt( vector ) {
10889 
10890  if ( obj === undefined ) obj = new THREE.Object3D();
10891 
10892  obj.lookAt( vector );
10893 
10894  obj.updateMatrix();
10895 
10896  this.applyMatrix( obj.matrix );
10897 
10898  };
10899 
10900  }(),
10901 
10902  center: function () {
10903 
10904  this.computeBoundingBox();
10905 
10906  var offset = this.boundingBox.center().negate();
10907 
10908  this.translate( offset.x, offset.y, offset.z );
10909 
10910  return offset;
10911 
10912  },
10913 
10914  setFromObject: function ( object ) {
10915 
10916  // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
10917 
10918  var geometry = object.geometry;
10919 
10920  if ( object instanceof THREE.Points || object instanceof THREE.Line ) {
10921 
10922  var positions = new THREE.Float32Attribute( geometry.vertices.length * 3, 3 );
10923  var colors = new THREE.Float32Attribute( geometry.colors.length * 3, 3 );
10924 
10925  this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
10926  this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
10927 
10928  if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
10929 
10930  var lineDistances = new THREE.Float32Attribute( geometry.lineDistances.length, 1 );
10931 
10932  this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
10933 
10934  }
10935 
10936  if ( geometry.boundingSphere !== null ) {
10937 
10938  this.boundingSphere = geometry.boundingSphere.clone();
10939 
10940  }
10941 
10942  if ( geometry.boundingBox !== null ) {
10943 
10944  this.boundingBox = geometry.boundingBox.clone();
10945 
10946  }
10947 
10948  } else if ( object instanceof THREE.Mesh ) {
10949 
10950  if ( geometry instanceof THREE.Geometry ) {
10951 
10952  this.fromGeometry( geometry );
10953 
10954  }
10955 
10956  }
10957 
10958  return this;
10959 
10960  },
10961 
10962  updateFromObject: function ( object ) {
10963 
10964  var geometry = object.geometry;
10965 
10966  if ( object instanceof THREE.Mesh ) {
10967 
10968  var direct = geometry.__directGeometry;
10969 
10970  if ( direct === undefined ) {
10971 
10972  return this.fromGeometry( geometry );
10973 
10974  }
10975 
10976  direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
10977  direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
10978  direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
10979  direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
10980  direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
10981 
10982  geometry.verticesNeedUpdate = false;
10983  geometry.normalsNeedUpdate = false;
10984  geometry.colorsNeedUpdate = false;
10985  geometry.uvsNeedUpdate = false;
10986  geometry.groupsNeedUpdate = false;
10987 
10988  geometry = direct;
10989 
10990  }
10991 
10992  if ( geometry.verticesNeedUpdate === true ) {
10993 
10994  var attribute = this.attributes.position;
10995 
10996  if ( attribute !== undefined ) {
10997 
10998  attribute.copyVector3sArray( geometry.vertices );
10999  attribute.needsUpdate = true;
11000 
11001  }
11002 
11003  geometry.verticesNeedUpdate = false;
11004 
11005  }
11006 
11007  if ( geometry.normalsNeedUpdate === true ) {
11008 
11009  var attribute = this.attributes.normal;
11010 
11011  if ( attribute !== undefined ) {
11012 
11013  attribute.copyVector3sArray( geometry.normals );
11014  attribute.needsUpdate = true;
11015 
11016  }
11017 
11018  geometry.normalsNeedUpdate = false;
11019 
11020  }
11021 
11022  if ( geometry.colorsNeedUpdate === true ) {
11023 
11024  var attribute = this.attributes.color;
11025 
11026  if ( attribute !== undefined ) {
11027 
11028  attribute.copyColorsArray( geometry.colors );
11029  attribute.needsUpdate = true;
11030 
11031  }
11032 
11033  geometry.colorsNeedUpdate = false;
11034 
11035  }
11036 
11037  if ( geometry.uvsNeedUpdate ) {
11038 
11039  var attribute = this.attributes.uv;
11040 
11041  if ( attribute !== undefined ) {
11042 
11043  attribute.copyVector2sArray( geometry.uvs );
11044  attribute.needsUpdate = true;
11045 
11046  }
11047 
11048  geometry.uvsNeedUpdate = false;
11049 
11050  }
11051 
11052  if ( geometry.lineDistancesNeedUpdate ) {
11053 
11054  var attribute = this.attributes.lineDistance;
11055 
11056  if ( attribute !== undefined ) {
11057 
11058  attribute.copyArray( geometry.lineDistances );
11059  attribute.needsUpdate = true;
11060 
11061  }
11062 
11063  geometry.lineDistancesNeedUpdate = false;
11064 
11065  }
11066 
11067  if ( geometry.groupsNeedUpdate ) {
11068 
11069  geometry.computeGroups( object.geometry );
11070  this.groups = geometry.groups;
11071 
11072  geometry.groupsNeedUpdate = false;
11073 
11074  }
11075 
11076  return this;
11077 
11078  },
11079 
11080  fromGeometry: function ( geometry ) {
11081 
11082  geometry.__directGeometry = new THREE.DirectGeometry().fromGeometry( geometry );
11083 
11084  return this.fromDirectGeometry( geometry.__directGeometry );
11085 
11086  },
11087 
11088  fromDirectGeometry: function ( geometry ) {
11089 
11090  var positions = new Float32Array( geometry.vertices.length * 3 );
11091  this.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
11092 
11093  if ( geometry.normals.length > 0 ) {
11094 
11095  var normals = new Float32Array( geometry.normals.length * 3 );
11096  this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
11097 
11098  }
11099 
11100  if ( geometry.colors.length > 0 ) {
11101 
11102  var colors = new Float32Array( geometry.colors.length * 3 );
11103  this.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
11104 
11105  }
11106 
11107  if ( geometry.uvs.length > 0 ) {
11108 
11109  var uvs = new Float32Array( geometry.uvs.length * 2 );
11110  this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
11111 
11112  }
11113 
11114  if ( geometry.uvs2.length > 0 ) {
11115 
11116  var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
11117  this.addAttribute( 'uv2', new THREE.BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
11118 
11119  }
11120 
11121  if ( geometry.indices.length > 0 ) {
11122 
11123  var TypeArray = geometry.vertices.length > 65535 ? Uint32Array : Uint16Array;
11124  var indices = new TypeArray( geometry.indices.length * 3 );
11125  this.setIndex( new THREE.BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) );
11126 
11127  }
11128 
11129  // groups
11130 
11131  this.groups = geometry.groups;
11132 
11133  // morphs
11134 
11135  for ( var name in geometry.morphTargets ) {
11136 
11137  var array = [];
11138  var morphTargets = geometry.morphTargets[ name ];
11139 
11140  for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {
11141 
11142  var morphTarget = morphTargets[ i ];
11143 
11144  var attribute = new THREE.Float32Attribute( morphTarget.length * 3, 3 );
11145 
11146  array.push( attribute.copyVector3sArray( morphTarget ) );
11147 
11148  }
11149 
11150  this.morphAttributes[ name ] = array;
11151 
11152  }
11153 
11154  // skinning
11155 
11156  if ( geometry.skinIndices.length > 0 ) {
11157 
11158  var skinIndices = new THREE.Float32Attribute( geometry.skinIndices.length * 4, 4 );
11159  this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
11160 
11161  }
11162 
11163  if ( geometry.skinWeights.length > 0 ) {
11164 
11165  var skinWeights = new THREE.Float32Attribute( geometry.skinWeights.length * 4, 4 );
11166  this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
11167 
11168  }
11169 
11170  //
11171 
11172  if ( geometry.boundingSphere !== null ) {
11173 
11174  this.boundingSphere = geometry.boundingSphere.clone();
11175 
11176  }
11177 
11178  if ( geometry.boundingBox !== null ) {
11179 
11180  this.boundingBox = geometry.boundingBox.clone();
11181 
11182  }
11183 
11184  return this;
11185 
11186  },
11187 
11188  computeBoundingBox: function () {
11189 
11190  var vector = new THREE.Vector3();
11191 
11192  return function () {
11193 
11194  if ( this.boundingBox === null ) {
11195 
11196  this.boundingBox = new THREE.Box3();
11197 
11198  }
11199 
11200  var positions = this.attributes.position.array;
11201 
11202  if ( positions ) {
11203 
11204  var bb = this.boundingBox;
11205  bb.makeEmpty();
11206 
11207  for ( var i = 0, il = positions.length; i < il; i += 3 ) {
11208 
11209  vector.fromArray( positions, i );
11210  bb.expandByPoint( vector );
11211 
11212  }
11213 
11214  }
11215 
11216  if ( positions === undefined || positions.length === 0 ) {
11217 
11218  this.boundingBox.min.set( 0, 0, 0 );
11219  this.boundingBox.max.set( 0, 0, 0 );
11220 
11221  }
11222 
11223  if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
11224 
11225  console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
11226 
11227  }
11228 
11229  };
11230 
11231  }(),
11232 
11233  computeBoundingSphere: function () {
11234 
11235  var box = new THREE.Box3();
11236  var vector = new THREE.Vector3();
11237 
11238  return function () {
11239 
11240  if ( this.boundingSphere === null ) {
11241 
11242  this.boundingSphere = new THREE.Sphere();
11243 
11244  }
11245 
11246  var positions = this.attributes.position.array;
11247 
11248  if ( positions ) {
11249 
11250  box.makeEmpty();
11251 
11252  var center = this.boundingSphere.center;
11253 
11254  for ( var i = 0, il = positions.length; i < il; i += 3 ) {
11255 
11256  vector.fromArray( positions, i );
11257  box.expandByPoint( vector );
11258 
11259  }
11260 
11261  box.center( center );
11262 
11263  // hoping to find a boundingSphere with a radius smaller than the
11264  // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
11265 
11266  var maxRadiusSq = 0;
11267 
11268  for ( var i = 0, il = positions.length; i < il; i += 3 ) {
11269 
11270  vector.fromArray( positions, i );
11271  maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
11272 
11273  }
11274 
11275  this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
11276 
11277  if ( isNaN( this.boundingSphere.radius ) ) {
11278 
11279  console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
11280 
11281  }
11282 
11283  }
11284 
11285  };
11286 
11287  }(),
11288 
11289  computeFaceNormals: function () {
11290 
11291  // backwards compatibility
11292 
11293  },
11294 
11295  computeVertexNormals: function () {
11296 
11297  var index = this.index;
11298  var attributes = this.attributes;
11299  var groups = this.groups;
11300 
11301  if ( attributes.position ) {
11302 
11303  var positions = attributes.position.array;
11304 
11305  if ( attributes.normal === undefined ) {
11306 
11307  this.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( positions.length ), 3 ) );
11308 
11309  } else {
11310 
11311  // reset existing normals to zero
11312 
11313  var normals = attributes.normal.array;
11314 
11315  for ( var i = 0, il = normals.length; i < il; i ++ ) {
11316 
11317  normals[ i ] = 0;
11318 
11319  }
11320 
11321  }
11322 
11323  var normals = attributes.normal.array;
11324 
11325  var vA, vB, vC,
11326 
11327  pA = new THREE.Vector3(),
11328  pB = new THREE.Vector3(),
11329  pC = new THREE.Vector3(),
11330 
11331  cb = new THREE.Vector3(),
11332  ab = new THREE.Vector3();
11333 
11334  // indexed elements
11335 
11336  if ( index ) {
11337 
11338  var indices = index.array;
11339 
11340  if ( groups.length === 0 ) {
11341 
11342  this.addGroup( 0, indices.length );
11343 
11344  }
11345 
11346  for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
11347 
11348  var group = groups[ j ];
11349 
11350  var start = group.start;
11351  var count = group.count;
11352 
11353  for ( var i = start, il = start + count; i < il; i += 3 ) {
11354 
11355  vA = indices[ i + 0 ] * 3;
11356  vB = indices[ i + 1 ] * 3;
11357  vC = indices[ i + 2 ] * 3;
11358 
11359  pA.fromArray( positions, vA );
11360  pB.fromArray( positions, vB );
11361  pC.fromArray( positions, vC );
11362 
11363  cb.subVectors( pC, pB );
11364  ab.subVectors( pA, pB );
11365  cb.cross( ab );
11366 
11367  normals[ vA ] += cb.x;
11368  normals[ vA + 1 ] += cb.y;
11369  normals[ vA + 2 ] += cb.z;
11370 
11371  normals[ vB ] += cb.x;
11372  normals[ vB + 1 ] += cb.y;
11373  normals[ vB + 2 ] += cb.z;
11374 
11375  normals[ vC ] += cb.x;
11376  normals[ vC + 1 ] += cb.y;
11377  normals[ vC + 2 ] += cb.z;
11378 
11379  }
11380 
11381  }
11382 
11383  } else {
11384 
11385  // non-indexed elements (unconnected triangle soup)
11386 
11387  for ( var i = 0, il = positions.length; i < il; i += 9 ) {
11388 
11389  pA.fromArray( positions, i );
11390  pB.fromArray( positions, i + 3 );
11391  pC.fromArray( positions, i + 6 );
11392 
11393  cb.subVectors( pC, pB );
11394  ab.subVectors( pA, pB );
11395  cb.cross( ab );
11396 
11397  normals[ i ] = cb.x;
11398  normals[ i + 1 ] = cb.y;
11399  normals[ i + 2 ] = cb.z;
11400 
11401  normals[ i + 3 ] = cb.x;
11402  normals[ i + 4 ] = cb.y;
11403  normals[ i + 5 ] = cb.z;
11404 
11405  normals[ i + 6 ] = cb.x;
11406  normals[ i + 7 ] = cb.y;
11407  normals[ i + 8 ] = cb.z;
11408 
11409  }
11410 
11411  }
11412 
11413  this.normalizeNormals();
11414 
11415  attributes.normal.needsUpdate = true;
11416 
11417  }
11418 
11419  },
11420 
11421  computeTangents: function () {
11422 
11423  console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );
11424 
11425  },
11426 
11427  computeOffsets: function ( size ) {
11428 
11429  console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.')
11430 
11431  },
11432 
11433  merge: function ( geometry, offset ) {
11434 
11435  if ( geometry instanceof THREE.BufferGeometry === false ) {
11436 
11437  console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
11438  return;
11439 
11440  }
11441 
11442  if ( offset === undefined ) offset = 0;
11443 
11444  var attributes = this.attributes;
11445 
11446  for ( var key in attributes ) {
11447 
11448  if ( geometry.attributes[ key ] === undefined ) continue;
11449 
11450  var attribute1 = attributes[ key ];
11451  var attributeArray1 = attribute1.array;
11452 
11453  var attribute2 = geometry.attributes[ key ];
11454  var attributeArray2 = attribute2.array;
11455 
11456  var attributeSize = attribute2.itemSize;
11457 
11458  for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) {
11459 
11460  attributeArray1[ j ] = attributeArray2[ i ];
11461 
11462  }
11463 
11464  }
11465 
11466  return this;
11467 
11468  },
11469 
11470  normalizeNormals: function () {
11471 
11472  var normals = this.attributes.normal.array;
11473 
11474  var x, y, z, n;
11475 
11476  for ( var i = 0, il = normals.length; i < il; i += 3 ) {
11477 
11478  x = normals[ i ];
11479  y = normals[ i + 1 ];
11480  z = normals[ i + 2 ];
11481 
11482  n = 1.0 / Math.sqrt( x * x + y * y + z * z );
11483 
11484  normals[ i ] *= n;
11485  normals[ i + 1 ] *= n;
11486  normals[ i + 2 ] *= n;
11487 
11488  }
11489 
11490  },
11491 
11492  toJSON: function () {
11493 
11494  var data = {
11495  metadata: {
11496  version: 4.4,
11497  type: 'BufferGeometry',
11498  generator: 'BufferGeometry.toJSON'
11499  }
11500  };
11501 
11502  // standard BufferGeometry serialization
11503 
11504  data.uuid = this.uuid;
11505  data.type = this.type;
11506  if ( this.name !== '' ) data.name = this.name;
11507 
11508  if ( this.parameters !== undefined ) {
11509 
11510  var parameters = this.parameters;
11511 
11512  for ( var key in parameters ) {
11513 
11514  if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
11515 
11516  }
11517 
11518  return data;
11519 
11520  }
11521 
11522  data.data = { attributes: {} };
11523 
11524  var index = this.index;
11525 
11526  if ( index !== null ) {
11527 
11528  var array = Array.prototype.slice.call( index.array );
11529 
11530  data.data.index = {
11531  type: index.array.constructor.name,
11532  array: array
11533  };
11534 
11535  }
11536 
11537  var attributes = this.attributes;
11538 
11539  for ( var key in attributes ) {
11540 
11541  var attribute = attributes[ key ];
11542 
11543  var array = Array.prototype.slice.call( attribute.array );
11544 
11545  data.data.attributes[ key ] = {
11546  itemSize: attribute.itemSize,
11547  type: attribute.array.constructor.name,
11548  array: array
11549  };
11550 
11551  }
11552 
11553  var groups = this.groups;
11554 
11555  if ( groups.length > 0 ) {
11556 
11557  data.data.groups = JSON.parse( JSON.stringify( groups ) );
11558 
11559  }
11560 
11561  var boundingSphere = this.boundingSphere;
11562 
11563  if ( boundingSphere !== null ) {
11564 
11565  data.data.boundingSphere = {
11566  center: boundingSphere.center.toArray(),
11567  radius: boundingSphere.radius
11568  };
11569 
11570  }
11571 
11572  return data;
11573 
11574  },
11575 
11576  clone: function () {
11577 
11578  return new this.constructor().copy( this );
11579 
11580  },
11581 
11582  copy: function ( source ) {
11583 
11584  var index = source.index;
11585 
11586  if ( index !== null ) {
11587 
11588  this.setIndex( index.clone() );
11589 
11590  }
11591 
11592  var attributes = source.attributes;
11593 
11594  for ( var name in attributes ) {
11595 
11596  var attribute = attributes[ name ];
11597  this.addAttribute( name, attribute.clone() );
11598 
11599  }
11600 
11601  var groups = source.groups;
11602 
11603  for ( var i = 0, l = groups.length; i < l; i ++ ) {
11604 
11605  var group = groups[ i ];
11606  this.addGroup( group.start, group.count );
11607 
11608  }
11609 
11610  return this;
11611 
11612  },
11613 
11614  dispose: function () {
11615 
11616  this.dispatchEvent( { type: 'dispose' } );
11617 
11618  }
11619 
11620 };
11621 
11622 THREE.EventDispatcher.prototype.apply( THREE.BufferGeometry.prototype );
11623 
11624 THREE.BufferGeometry.MaxIndex = 65535;
11625 
11626 // File:src/core/InstancedBufferGeometry.js
11627 
11632 THREE.InstancedBufferGeometry = function () {
11633 
11634  THREE.BufferGeometry.call( this );
11635 
11636  this.type = 'InstancedBufferGeometry';
11637  this.maxInstancedCount = undefined;
11638 
11639 };
11640 
11641 THREE.InstancedBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
11642 THREE.InstancedBufferGeometry.prototype.constructor = THREE.InstancedBufferGeometry;
11643 
11644 THREE.InstancedBufferGeometry.prototype.addGroup = function ( start, count, instances ) {
11645 
11646  this.groups.push( {
11647 
11648  start: start,
11649  count: count,
11650  instances: instances
11651 
11652  } );
11653 
11654 };
11655 
11656 THREE.InstancedBufferGeometry.prototype.copy = function ( source ) {
11657 
11658  var index = source.index;
11659 
11660  if ( index !== null ) {
11661 
11662  this.setIndex( index.clone() );
11663 
11664  }
11665 
11666  var attributes = source.attributes;
11667 
11668  for ( var name in attributes ) {
11669 
11670  var attribute = attributes[ name ];
11671  this.addAttribute( name, attribute.clone() );
11672 
11673  }
11674 
11675  var groups = source.groups;
11676 
11677  for ( var i = 0, l = groups.length; i < l; i ++ ) {
11678 
11679  var group = groups[ i ];
11680  this.addGroup( group.start, group.count, group.instances );
11681 
11682  }
11683 
11684  return this;
11685 
11686 };
11687 
11688 THREE.EventDispatcher.prototype.apply( THREE.InstancedBufferGeometry.prototype );
11689 
11690 // File:src/animation/AnimationAction.js
11691 
11700 THREE.AnimationAction = function ( clip, startTime, timeScale, weight, loop ) {
11701 
11702  if ( clip === undefined ) throw new Error( 'clip is null' );
11703  this.clip = clip;
11704  this.localRoot = null;
11705  this.startTime = startTime || 0;
11706  this.timeScale = timeScale || 1;
11707  this.weight = weight || 1;
11708  this.loop = loop || THREE.LoopRepeat;
11709  this.loopCount = 0;
11710  this.enabled = true; // allow for easy disabling of the action.
11711 
11712  this.actionTime = - this.startTime;
11713  this.clipTime = 0;
11714 
11715  this.propertyBindings = [];
11716 };
11717 
11718 /*
11719 THREE.LoopOnce = 2200;
11720 THREE.LoopRepeat = 2201;
11721 THREE.LoopPingPing = 2202;
11722 */
11723 
11724 THREE.AnimationAction.prototype = {
11725 
11726  constructor: THREE.AnimationAction,
11727 
11728  setLocalRoot: function( localRoot ) {
11729 
11730  this.localRoot = localRoot;
11731 
11732  return this;
11733 
11734  },
11735 
11736  updateTime: function( clipDeltaTime ) {
11737 
11738  var previousClipTime = this.clipTime;
11739  var previousLoopCount = this.loopCount;
11740  var previousActionTime = this.actionTime;
11741 
11742  var duration = this.clip.duration;
11743 
11744  this.actionTime = this.actionTime + clipDeltaTime;
11745 
11746  if ( this.loop === THREE.LoopOnce ) {
11747 
11748  this.loopCount = 0;
11749  this.clipTime = Math.min( Math.max( this.actionTime, 0 ), duration );
11750 
11751  // if time is changed since last time, see if we have hit a start/end limit
11752  if ( this.clipTime !== previousClipTime ) {
11753 
11754  if ( this.clipTime === duration ) {
11755 
11756  this.mixer.dispatchEvent( { type: 'finished', action: this, direction: 1 } );
11757 
11758  } else if ( this.clipTime === 0 ) {
11759 
11760  this.mixer.dispatchEvent( { type: 'finished', action: this, direction: -1 } );
11761 
11762  }
11763 
11764  }
11765 
11766 
11767  return this.clipTime;
11768 
11769  }
11770 
11771  this.loopCount = Math.floor( this.actionTime / duration );
11772 
11773  var newClipTime = this.actionTime - this.loopCount * duration;
11774  newClipTime = newClipTime % duration;
11775 
11776  // if we are ping pong looping, ensure that we go backwards when appropriate
11777  if ( this.loop == THREE.LoopPingPong ) {
11778 
11779  if ( Math.abs( this.loopCount % 2 ) === 1 ) {
11780 
11781  newClipTime = duration - newClipTime;
11782 
11783  }
11784 
11785  }
11786 
11787  this.clipTime = newClipTime;
11788 
11789  if ( this.loopCount !== previousLoopCount ) {
11790 
11791  this.mixer.dispatchEvent( { type: 'loop', action: this, loopDelta: ( this.loopCount - this.loopCount ) } );
11792 
11793  }
11794 
11795  return this.clipTime;
11796 
11797  },
11798 
11799  syncWith: function( action ) {
11800 
11801  this.actionTime = action.actionTime;
11802  this.timeScale = action.timeScale;
11803 
11804  return this;
11805  },
11806 
11807  warpToDuration: function( duration ) {
11808 
11809  this.timeScale = this.clip.duration / duration;
11810 
11811  return this;
11812  },
11813 
11814  init: function( time ) {
11815 
11816  this.clipTime = time - this.startTime;
11817 
11818  return this;
11819 
11820  },
11821 
11822  update: function( clipDeltaTime ) {
11823 
11824  this.updateTime( clipDeltaTime );
11825 
11826  var clipResults = this.clip.getAt( this.clipTime );
11827 
11828  return clipResults;
11829 
11830  },
11831 
11832  getTimeScaleAt: function( time ) {
11833 
11834  if ( this.timeScale.getAt ) {
11835  // pass in time, not clip time, allows for fadein/fadeout across multiple loops of the clip
11836  return this.timeScale.getAt( time );
11837 
11838  }
11839 
11840  return this.timeScale;
11841 
11842  },
11843 
11844  getWeightAt: function( time ) {
11845 
11846  if ( this.weight.getAt ) {
11847  // pass in time, not clip time, allows for fadein/fadeout across multiple loops of the clip
11848  return this.weight.getAt( time );
11849 
11850  }
11851 
11852  return this.weight;
11853 
11854  }
11855 
11856 };
11857 
11858 // File:src/animation/AnimationClip.js
11859 
11868 THREE.AnimationClip = function ( name, duration, tracks ) {
11869 
11870  this.name = name;
11871  this.tracks = tracks;
11872  this.duration = ( duration !== undefined ) ? duration : -1;
11873 
11874  // this means it should figure out its duration by scanning the tracks
11875  if ( this.duration < 0 ) {
11876  for ( var i = 0; i < this.tracks.length; i ++ ) {
11877  var track = this.tracks[i];
11878  this.duration = Math.max( track.keys[ track.keys.length - 1 ].time );
11879  }
11880  }
11881 
11882  // maybe only do these on demand, as doing them here could potentially slow down loading
11883  // but leaving these here during development as this ensures a lot of testing of these functions
11884  this.trim();
11885  this.optimize();
11886 
11887  this.results = [];
11888 
11889 };
11890 
11891 THREE.AnimationClip.prototype = {
11892 
11893  constructor: THREE.AnimationClip,
11894 
11895  getAt: function( clipTime ) {
11896 
11897  clipTime = Math.max( 0, Math.min( clipTime, this.duration ) );
11898 
11899  for ( var i = 0; i < this.tracks.length; i ++ ) {
11900 
11901  var track = this.tracks[ i ];
11902 
11903  this.results[ i ] = track.getAt( clipTime );
11904 
11905  }
11906 
11907  return this.results;
11908  },
11909 
11910  trim: function() {
11911 
11912  for ( var i = 0; i < this.tracks.length; i ++ ) {
11913 
11914  this.tracks[ i ].trim( 0, this.duration );
11915 
11916  }
11917 
11918  return this;
11919 
11920  },
11921 
11922  optimize: function() {
11923 
11924  for ( var i = 0; i < this.tracks.length; i ++ ) {
11925 
11926  this.tracks[ i ].optimize();
11927 
11928  }
11929 
11930  return this;
11931 
11932  }
11933 
11934 };
11935 
11936 
11937 THREE.AnimationClip.CreateFromMorphTargetSequence = function( name, morphTargetSequence, fps ) {
11938 
11939 
11940  var numMorphTargets = morphTargetSequence.length;
11941  var tracks = [];
11942 
11943  for ( var i = 0; i < numMorphTargets; i ++ ) {
11944 
11945  var keys = [];
11946 
11947  keys.push( { time: ( i + numMorphTargets - 1 ) % numMorphTargets, value: 0 } );
11948  keys.push( { time: i, value: 1 } );
11949  keys.push( { time: ( i + 1 ) % numMorphTargets, value: 0 } );
11950 
11951  keys.sort( THREE.KeyframeTrack.keyComparer );
11952 
11953  // if there is a key at the first frame, duplicate it as the last frame as well for perfect loop.
11954  if ( keys[0].time === 0 ) {
11955  keys.push( {
11956  time: numMorphTargets,
11957  value: keys[0].value
11958  });
11959  }
11960 
11961  tracks.push( new THREE.NumberKeyframeTrack( '.morphTargetInfluences[' + morphTargetSequence[i].name + ']', keys ).scale( 1.0 / fps ) );
11962  }
11963 
11964  return new THREE.AnimationClip( name, -1, tracks );
11965 
11966 };
11967 
11968 THREE.AnimationClip.findByName = function( clipArray, name ) {
11969 
11970  for ( var i = 0; i < clipArray.length; i ++ ) {
11971 
11972  if ( clipArray[i].name === name ) {
11973 
11974  return clipArray[i];
11975 
11976  }
11977  }
11978 
11979  return null;
11980 
11981 };
11982 
11983 THREE.AnimationClip.CreateClipsFromMorphTargetSequences = function( morphTargets, fps ) {
11984 
11985  var animationToMorphTargets = {};
11986 
11987  // tested with https://regex101.com/ on trick sequences such flamingo_flyA_003, flamingo_run1_003, crdeath0059
11988  var pattern = /^([\w-]*?)([\d]+)$/;
11989 
11990  // sort morph target names into animation groups based patterns like Walk_001, Walk_002, Run_001, Run_002
11991  for ( var i = 0, il = morphTargets.length; i < il; i ++ ) {
11992 
11993  var morphTarget = morphTargets[ i ];
11994  var parts = morphTarget.name.match( pattern );
11995 
11996  if ( parts && parts.length > 1 ) {
11997 
11998  var name = parts[ 1 ];
11999 
12000  var animationMorphTargets = animationToMorphTargets[ name ];
12001  if ( ! animationMorphTargets ) {
12002  animationToMorphTargets[ name ] = animationMorphTargets = [];
12003  }
12004 
12005  animationMorphTargets.push( morphTarget );
12006 
12007  }
12008 
12009  }
12010 
12011  var clips = [];
12012 
12013  for ( var name in animationToMorphTargets ) {
12014 
12015  clips.push( THREE.AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps ) );
12016  }
12017 
12018  return clips;
12019 
12020 };
12021 
12022 // parse the standard JSON format for clips
12023 THREE.AnimationClip.parse = function( json ) {
12024 
12025  var tracks = [];
12026 
12027  for ( var i = 0; i < json.tracks.length; i ++ ) {
12028 
12029  tracks.push( THREE.KeyframeTrack.parse( json.tracks[i] ).scale( 1.0 / json.fps ) );
12030 
12031  }
12032 
12033  return new THREE.AnimationClip( json.name, json.duration, tracks );
12034 
12035 };
12036 
12037 
12038 // parse the animation.hierarchy format
12039 THREE.AnimationClip.parseAnimation = function( animation, bones, nodeName ) {
12040 
12041  if ( ! animation ) {
12042  console.error( " no animation in JSONLoader data" );
12043  return null;
12044  }
12045 
12046  var convertTrack = function( trackName, animationKeys, propertyName, trackType, animationKeyToValueFunc ) {
12047 
12048  var keys = [];
12049 
12050  for ( var k = 0; k < animationKeys.length; k ++ ) {
12051 
12052  var animationKey = animationKeys[k];
12053 
12054  if ( animationKey[propertyName] !== undefined ) {
12055 
12056  keys.push( { time: animationKey.time, value: animationKeyToValueFunc( animationKey ) } );
12057  }
12058 
12059  }
12060 
12061  // only return track if there are actually keys.
12062  if ( keys.length > 0 ) {
12063 
12064  return new trackType( trackName, keys );
12065 
12066  }
12067 
12068  return null;
12069 
12070  };
12071 
12072  var tracks = [];
12073 
12074  var clipName = animation.name || 'default';
12075  var duration = animation.length || -1; // automatic length determination in AnimationClip.
12076  var fps = animation.fps || 30;
12077 
12078  var hierarchyTracks = animation.hierarchy || [];
12079 
12080  for ( var h = 0; h < hierarchyTracks.length; h ++ ) {
12081 
12082  var animationKeys = hierarchyTracks[ h ].keys;
12083 
12084  // skip empty tracks
12085  if ( ! animationKeys || animationKeys.length == 0 ) {
12086  continue;
12087  }
12088 
12089  // process morph targets in a way exactly compatible with AnimationHandler.init( animation )
12090  if ( animationKeys[0].morphTargets ) {
12091 
12092  // figure out all morph targets used in this track
12093  var morphTargetNames = {};
12094  for ( var k = 0; k < animationKeys.length; k ++ ) {
12095 
12096  if ( animationKeys[k].morphTargets ) {
12097  for ( var m = 0; m < animationKeys[k].morphTargets.length; m ++ ) {
12098 
12099  morphTargetNames[ animationKeys[k].morphTargets[m] ] = -1;
12100  }
12101  }
12102 
12103  }
12104 
12105  // create a track for each morph target with all zero morphTargetInfluences except for the keys in which the morphTarget is named.
12106  for ( var morphTargetName in morphTargetNames ) {
12107 
12108  var keys = [];
12109 
12110  for ( var m = 0; m < animationKeys[k].morphTargets.length; m ++ ) {
12111 
12112  var animationKey = animationKeys[k];
12113 
12114  keys.push( {
12115  time: animationKey.time,
12116  value: (( animationKey.morphTarget === morphTargetName ) ? 1 : 0 )
12117  });
12118 
12119  }
12120 
12121  tracks.push( new THREE.NumberKeyframeTrack( nodeName + '.morphTargetInfluence[' + morphTargetName + ']', keys ) );
12122 
12123  }
12124 
12125  duration = morphTargetNames.length * ( fps || 1.0 );
12126 
12127  } else {
12128 
12129  var boneName = nodeName + '.bones[' + bones[ h ].name + ']';
12130 
12131  // track contains positions...
12132  var positionTrack = convertTrack( boneName + '.position', animationKeys, 'pos', THREE.VectorKeyframeTrack, function( animationKey ) {
12133  return new THREE.Vector3().fromArray( animationKey.pos )
12134  } );
12135 
12136  if ( positionTrack ) tracks.push( positionTrack );
12137 
12138  // track contains quaternions...
12139  var quaternionTrack = convertTrack( boneName + '.quaternion', animationKeys, 'rot', THREE.QuaternionKeyframeTrack, function( animationKey ) {
12140  if ( animationKey.rot.slerp ) {
12141  return animationKey.rot.clone();
12142  } else {
12143  return new THREE.Quaternion().fromArray( animationKey.rot );
12144  }
12145  } );
12146 
12147  if ( quaternionTrack ) tracks.push( quaternionTrack );
12148 
12149  // track contains quaternions...
12150  var scaleTrack = convertTrack( boneName + '.scale', animationKeys, 'scl', THREE.VectorKeyframeTrack, function( animationKey ) {
12151  return new THREE.Vector3().fromArray( animationKey.scl )
12152  } );
12153 
12154  if ( scaleTrack ) tracks.push( scaleTrack );
12155 
12156  }
12157  }
12158 
12159  if ( tracks.length === 0 ) {
12160 
12161  return null;
12162 
12163  }
12164 
12165  var clip = new THREE.AnimationClip( clipName, duration, tracks );
12166 
12167  return clip;
12168 
12169 };
12170 
12171 // File:src/animation/AnimationMixer.js
12172 
12182 THREE.AnimationMixer = function( root ) {
12183 
12184  this.root = root;
12185  this.time = 0;
12186  this.timeScale = 1.0;
12187  this.actions = [];
12188  this.propertyBindingMap = {};
12189 
12190 };
12191 
12192 THREE.AnimationMixer.prototype = {
12193 
12194  constructor: THREE.AnimationMixer,
12195 
12196  addAction: function( action ) {
12197 
12198  // TODO: check for duplicate action names? Or provide each action with a UUID?
12199 
12200  this.actions.push( action );
12201  action.init( this.time );
12202  action.mixer = this;
12203 
12204  var tracks = action.clip.tracks;
12205 
12206  var root = action.localRoot || this.root;
12207 
12208  for ( var i = 0; i < tracks.length; i ++ ) {
12209 
12210  var track = tracks[ i ];
12211 
12212  var propertyBindingKey = root.uuid + '-' + track.name;
12213  var propertyBinding = this.propertyBindingMap[ propertyBindingKey ];
12214 
12215  if ( propertyBinding === undefined ) {
12216 
12217  propertyBinding = new THREE.PropertyBinding( root, track.name );
12218  this.propertyBindingMap[ propertyBindingKey ] = propertyBinding;
12219 
12220  }
12221 
12222  // push in the same order as the tracks.
12223  action.propertyBindings.push( propertyBinding );
12224 
12225  // track usages of shared property bindings, because if we leave too many around, the mixer can get slow
12226  propertyBinding.referenceCount += 1;
12227 
12228  }
12229 
12230  },
12231 
12232  removeAllActions: function() {
12233 
12234  for ( var i = 0; i < this.actions.length; i ++ ) {
12235 
12236  this.actions[i].mixer = null;
12237 
12238  }
12239 
12240  // unbind all property bindings
12241  for ( var properyBindingKey in this.propertyBindingMap ) {
12242 
12243  this.propertyBindingMap[ properyBindingKey ].unbind();
12244 
12245  }
12246 
12247  this.actions = [];
12248  this.propertyBindingMap = {};
12249 
12250  return this;
12251 
12252  },
12253 
12254  removeAction: function( action ) {
12255 
12256  var index = this.actions.indexOf( action );
12257 
12258  if ( index !== - 1 ) {
12259 
12260  this.actions.splice( index, 1 );
12261  action.mixer = null;
12262 
12263  }
12264 
12265 
12266  // remove unused property bindings because if we leave them around the mixer can get slow
12267  var root = action.localRoot || this.root;
12268  var tracks = action.clip.tracks;
12269 
12270  for ( var i = 0; i < tracks.length; i ++ ) {
12271 
12272  var track = tracks[ i ];
12273 
12274  var propertyBindingKey = root.uuid + '-' + track.name;
12275  var propertyBinding = this.propertyBindingMap[ propertyBindingKey ];
12276 
12277  propertyBinding.referenceCount -= 1;
12278 
12279  if ( propertyBinding.referenceCount <= 0 ) {
12280 
12281  propertyBinding.unbind();
12282 
12283  delete this.propertyBindingMap[ propertyBindingKey ];
12284 
12285  }
12286  }
12287 
12288  return this;
12289 
12290  },
12291 
12292  // can be optimized if needed
12293  findActionByName: function( name ) {
12294 
12295  for ( var i = 0; i < this.actions.length; i ++ ) {
12296 
12297  if ( this.actions[i].name === name ) return this.actions[i];
12298 
12299  }
12300 
12301  return null;
12302 
12303  },
12304 
12305  play: function( action, optionalFadeInDuration ) {
12306 
12307  action.startTime = this.time;
12308  this.addAction( action );
12309 
12310  return this;
12311 
12312  },
12313 
12314  fadeOut: function( action, duration ) {
12315 
12316  var keys = [];
12317 
12318  keys.push( { time: this.time, value: 1 } );
12319  keys.push( { time: this.time + duration, value: 0 } );
12320 
12321  action.weight = new THREE.NumberKeyframeTrack( "weight", keys );
12322 
12323  return this;
12324 
12325  },
12326 
12327  fadeIn: function( action, duration ) {
12328 
12329  var keys = [];
12330 
12331  keys.push( { time: this.time, value: 0 } );
12332  keys.push( { time: this.time + duration, value: 1 } );
12333 
12334  action.weight = new THREE.NumberKeyframeTrack( "weight", keys );
12335 
12336  return this;
12337 
12338  },
12339 
12340  warp: function( action, startTimeScale, endTimeScale, duration ) {
12341 
12342  var keys = [];
12343 
12344  keys.push( { time: this.time, value: startTimeScale } );
12345  keys.push( { time: this.time + duration, value: endTimeScale } );
12346 
12347  action.timeScale = new THREE.NumberKeyframeTrack( "timeScale", keys );
12348 
12349  return this;
12350 
12351  },
12352 
12353  crossFade: function( fadeOutAction, fadeInAction, duration, warp ) {
12354 
12355  this.fadeOut( fadeOutAction, duration );
12356  this.fadeIn( fadeInAction, duration );
12357 
12358  if ( warp ) {
12359 
12360  var startEndRatio = fadeOutAction.clip.duration / fadeInAction.clip.duration;
12361  var endStartRatio = 1.0 / startEndRatio;
12362 
12363  this.warp( fadeOutAction, 1.0, startEndRatio, duration );
12364  this.warp( fadeInAction, endStartRatio, 1.0, duration );
12365 
12366  }
12367 
12368  return this;
12369 
12370  },
12371 
12372  update: function( deltaTime ) {
12373 
12374  var mixerDeltaTime = deltaTime * this.timeScale;
12375  this.time += mixerDeltaTime;
12376 
12377  for ( var i = 0; i < this.actions.length; i ++ ) {
12378 
12379  var action = this.actions[i];
12380 
12381  var weight = action.getWeightAt( this.time );
12382 
12383  var actionTimeScale = action.getTimeScaleAt( this.time );
12384  var actionDeltaTime = mixerDeltaTime * actionTimeScale;
12385 
12386  var actionResults = action.update( actionDeltaTime );
12387 
12388  if ( action.weight <= 0 || ! action.enabled ) continue;
12389 
12390  for ( var j = 0; j < actionResults.length; j ++ ) {
12391 
12392  var name = action.clip.tracks[j].name;
12393 
12394  action.propertyBindings[ j ].accumulate( actionResults[j], weight );
12395 
12396  }
12397 
12398  }
12399 
12400  // apply to nodes
12401  for ( var propertyBindingKey in this.propertyBindingMap ) {
12402 
12403  this.propertyBindingMap[ propertyBindingKey ].apply();
12404 
12405  }
12406 
12407  return this;
12408 
12409  }
12410 
12411 };
12412 
12413 THREE.EventDispatcher.prototype.apply( THREE.AnimationMixer.prototype );
12414 
12415 // File:src/animation/AnimationUtils.js
12416 
12422 THREE.AnimationUtils = {
12423 
12424  getEqualsFunc: function( exemplarValue ) {
12425 
12426  if ( exemplarValue.equals ) {
12427  return function equals_object( a, b ) {
12428  return a.equals( b );
12429  }
12430  }
12431 
12432  return function equals_primitive( a, b ) {
12433  return ( a === b );
12434  };
12435 
12436  },
12437 
12438  clone: function( exemplarValue ) {
12439 
12440  var typeName = typeof exemplarValue;
12441  if ( typeName === "object" ) {
12442  if ( exemplarValue.clone ) {
12443  return exemplarValue.clone();
12444  }
12445  console.error( "can not figure out how to copy exemplarValue", exemplarValue );
12446  }
12447 
12448  return exemplarValue;
12449 
12450  },
12451 
12452  lerp: function( a, b, alpha, interTrack ) {
12453 
12454  var lerpFunc = THREE.AnimationUtils.getLerpFunc( a, interTrack );
12455 
12456  return lerpFunc( a, b, alpha );
12457 
12458  },
12459 
12460  lerp_object: function( a, b, alpha ) {
12461  return a.lerp( b, alpha );
12462  },
12463 
12464  slerp_object: function( a, b, alpha ) {
12465  return a.slerp( b, alpha );
12466  },
12467 
12468  lerp_number: function( a, b, alpha ) {
12469  return a * ( 1 - alpha ) + b * alpha;
12470  },
12471 
12472  lerp_boolean: function( a, b, alpha ) {
12473  return ( alpha < 0.5 ) ? a : b;
12474  },
12475 
12476  lerp_boolean_immediate: function( a, b, alpha ) {
12477  return a;
12478  },
12479 
12480  lerp_string: function( a, b, alpha ) {
12481  return ( alpha < 0.5 ) ? a : b;
12482  },
12483 
12484  lerp_string_immediate: function( a, b, alpha ) {
12485  return a;
12486  },
12487 
12488  // NOTE: this is an accumulator function that modifies the first argument (e.g. a). This is to minimize memory alocations.
12489  getLerpFunc: function( exemplarValue, interTrack ) {
12490 
12491  if ( exemplarValue === undefined || exemplarValue === null ) throw new Error( "examplarValue is null" );
12492 
12493  var typeName = typeof exemplarValue;
12494 
12495  switch( typeName ) {
12496 
12497  case "object":
12498  if ( exemplarValue.lerp ) {
12499  return THREE.AnimationUtils.lerp_object;
12500  }
12501 
12502  if ( exemplarValue.slerp ) {
12503  return THREE.AnimationUtils.slerp_object;
12504  }
12505  break;
12506 
12507  case "number":
12508  return THREE.AnimationUtils.lerp_number;
12509 
12510  case "boolean":
12511  if ( interTrack ) {
12512  return THREE.AnimationUtils.lerp_boolean;
12513  } else {
12514  return THREE.AnimationUtils.lerp_boolean_immediate;
12515  }
12516 
12517  case "string":
12518  if ( interTrack ) {
12519  return THREE.AnimationUtils.lerp_string;
12520  } else {
12521  return THREE.AnimationUtils.lerp_string_immediate;
12522  }
12523 
12524  }
12525 
12526  }
12527 
12528 };
12529 
12530 // File:src/animation/KeyframeTrack.js
12531 
12540 THREE.KeyframeTrack = function ( name, keys ) {
12541 
12542  if ( name === undefined ) throw new Error( "track name is undefined" );
12543  if ( keys === undefined || keys.length === 0 ) throw new Error( "no keys in track named " + name );
12544 
12545  this.name = name;
12546  this.keys = keys; // time in seconds, value as value
12547 
12548  // the index of the last result, used as a starting point for local search.
12549  this.lastIndex = 0;
12550 
12551  this.validate();
12552  this.optimize();
12553 
12554 };
12555 
12556 THREE.KeyframeTrack.prototype = {
12557 
12558  constructor: THREE.KeyframeTrack,
12559 
12560  getAt: function( time ) {
12561 
12562 
12563  // this can not go higher than this.keys.length.
12564  while( ( this.lastIndex < this.keys.length ) && ( time >= this.keys[this.lastIndex].time ) ) {
12565  this.lastIndex ++;
12566  };
12567 
12568  // this can not go lower than 0.
12569  while( ( this.lastIndex > 0 ) && ( time < this.keys[this.lastIndex - 1].time ) ) {
12570  this.lastIndex --;
12571  }
12572 
12573  if ( this.lastIndex >= this.keys.length ) {
12574 
12575  this.setResult( this.keys[ this.keys.length - 1 ].value );
12576 
12577  return this.result;
12578 
12579  }
12580 
12581  if ( this.lastIndex === 0 ) {
12582 
12583  this.setResult( this.keys[ 0 ].value );
12584 
12585  return this.result;
12586 
12587  }
12588 
12589  var prevKey = this.keys[ this.lastIndex - 1 ];
12590  this.setResult( prevKey.value );
12591 
12592  // if true, means that prev/current keys are identical, thus no interpolation required.
12593  if ( prevKey.constantToNext ) {
12594 
12595  return this.result;
12596 
12597  }
12598 
12599  // linear interpolation to start with
12600  var currentKey = this.keys[ this.lastIndex ];
12601  var alpha = ( time - prevKey.time ) / ( currentKey.time - prevKey.time );
12602  this.result = this.lerpValues( this.result, currentKey.value, alpha );
12603 
12604  return this.result;
12605 
12606  },
12607 
12608  // move all keyframes either forwards or backwards in time
12609  shift: function( timeOffset ) {
12610 
12611  if ( timeOffset !== 0.0 ) {
12612 
12613  for ( var i = 0; i < this.keys.length; i ++ ) {
12614  this.keys[i].time += timeOffset;
12615  }
12616 
12617  }
12618 
12619  return this;
12620 
12621  },
12622 
12623  // scale all keyframe times by a factor (useful for frame <-> seconds conversions)
12624  scale: function( timeScale ) {
12625 
12626  if ( timeScale !== 1.0 ) {
12627 
12628  for ( var i = 0; i < this.keys.length; i ++ ) {
12629  this.keys[i].time *= timeScale;
12630  }
12631 
12632  }
12633 
12634  return this;
12635 
12636  },
12637 
12638  // removes keyframes before and after animation without changing any values within the range [startTime, endTime].
12639  // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
12640  trim: function( startTime, endTime ) {
12641 
12642  var firstKeysToRemove = 0;
12643  for ( var i = 1; i < this.keys.length; i ++ ) {
12644  if ( this.keys[i] <= startTime ) {
12645  firstKeysToRemove ++;
12646  }
12647  }
12648 
12649  var lastKeysToRemove = 0;
12650  for ( var i = this.keys.length - 2; i > 0; i ++ ) {
12651  if ( this.keys[i] >= endTime ) {
12652  lastKeysToRemove ++;
12653  } else {
12654  break;
12655  }
12656  }
12657 
12658  // remove last keys first because it doesn't affect the position of the first keys (the otherway around doesn't work as easily)
12659  if ( ( firstKeysToRemove + lastKeysToRemove ) > 0 ) {
12660  this.keys = this.keys.splice( firstKeysToRemove, this.keys.length - lastKeysToRemove - firstKeysToRemove );;
12661  }
12662 
12663  return this;
12664 
12665  },
12666 
12667  /* NOTE: This is commented out because we really shouldn't have to handle unsorted key lists
12668  Tracks with out of order keys should be considered to be invalid. - bhouston
12669  sort: function() {
12670 
12671  this.keys.sort( THREE.KeyframeTrack.keyComparer );
12672 
12673  return this;
12674 
12675  },*/
12676 
12677  // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
12678  // One could eventually ensure that all key.values in a track are all of the same type (otherwise interpolation makes no sense.)
12679  validate: function() {
12680 
12681  var prevKey = null;
12682 
12683  if ( this.keys.length === 0 ) {
12684  console.error( " track is empty, no keys", this );
12685  return;
12686  }
12687 
12688  for ( var i = 0; i < this.keys.length; i ++ ) {
12689 
12690  var currKey = this.keys[i];
12691 
12692  if ( ! currKey ) {
12693  console.error( " key is null in track", this, i );
12694  return;
12695  }
12696 
12697  if ( ( typeof currKey.time ) !== 'number' || isNaN( currKey.time ) ) {
12698  console.error( " key.time is not a valid number", this, i, currKey );
12699  return;
12700  }
12701 
12702  if ( currKey.value === undefined || currKey.value === null) {
12703  console.error( " key.value is null in track", this, i, currKey );
12704  return;
12705  }
12706 
12707  if ( prevKey && prevKey.time > currKey.time ) {
12708  console.error( " key.time is less than previous key time, out of order keys", this, i, currKey, prevKey );
12709  return;
12710  }
12711 
12712  prevKey = currKey;
12713 
12714  }
12715 
12716  return this;
12717 
12718  },
12719 
12720  // currently only removes equivalent sequential keys (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0), which are common in morph target animations
12721  optimize: function() {
12722 
12723  var newKeys = [];
12724  var prevKey = this.keys[0];
12725  newKeys.push( prevKey );
12726 
12727  var equalsFunc = THREE.AnimationUtils.getEqualsFunc( prevKey.value );
12728 
12729  for ( var i = 1; i < this.keys.length - 1; i ++ ) {
12730  var currKey = this.keys[i];
12731  var nextKey = this.keys[i+1];
12732 
12733  // if prevKey & currKey are the same time, remove currKey. If you want immediate adjacent keys, use an epsilon offset
12734  // it is not possible to have two keys at the same time as we sort them. The sort is not stable on keys with the same time.
12735  if ( ( prevKey.time === currKey.time ) ) {
12736 
12737  continue;
12738 
12739  }
12740 
12741  // remove completely unnecessary keyframes that are the same as their prev and next keys
12742  if ( this.compareValues( prevKey.value, currKey.value ) && this.compareValues( currKey.value, nextKey.value ) ) {
12743 
12744  continue;
12745 
12746  }
12747 
12748  // determine if interpolation is required
12749  prevKey.constantToNext = this.compareValues( prevKey.value, currKey.value );
12750 
12751  newKeys.push( currKey );
12752  prevKey = currKey;
12753  }
12754  newKeys.push( this.keys[ this.keys.length - 1 ] );
12755 
12756  this.keys = newKeys;
12757 
12758  return this;
12759 
12760  }
12761 
12762 };
12763 
12764 THREE.KeyframeTrack.keyComparer = function keyComparator(key0, key1) {
12765  return key0.time - key1.time;
12766 };
12767 
12768 THREE.KeyframeTrack.parse = function( json ) {
12769 
12770  if ( json.type === undefined ) throw new Error( "track type undefined, can not parse" );
12771 
12772  var trackType = THREE.KeyframeTrack.GetTrackTypeForTypeName( json.type );
12773 
12774  return trackType.parse( json );
12775 
12776 };
12777 
12778 THREE.KeyframeTrack.GetTrackTypeForTypeName = function( typeName ) {
12779  switch( typeName.toLowerCase() ) {
12780  case "vector":
12781  case "vector2":
12782  case "vector3":
12783  case "vector4":
12784  return THREE.VectorKeyframeTrack;
12785 
12786  case "quaternion":
12787  return THREE.QuaternionKeyframeTrack;
12788 
12789  case "integer":
12790  case "scalar":
12791  case "double":
12792  case "float":
12793  case "number":
12794  return THREE.NumberKeyframeTrack;
12795 
12796  case "bool":
12797  case "boolean":
12798  return THREE.BooleanKeyframeTrack;
12799 
12800  case "string":
12801  return THREE.StringKeyframeTrack;
12802  };
12803 
12804  throw new Error( "Unsupported typeName: " + typeName );
12805 };
12806 
12807 // File:src/animation/PropertyBinding.js
12808 
12817 THREE.PropertyBinding = function ( rootNode, trackName ) {
12818 
12819  this.rootNode = rootNode;
12820  this.trackName = trackName;
12821  this.referenceCount = 0;
12822  this.originalValue = null; // the value of the property before it was controlled by this binding
12823 
12824  var parseResults = THREE.PropertyBinding.parseTrackName( trackName );
12825 
12826  this.directoryName = parseResults.directoryName;
12827  this.nodeName = parseResults.nodeName;
12828  this.objectName = parseResults.objectName;
12829  this.objectIndex = parseResults.objectIndex;
12830  this.propertyName = parseResults.propertyName;
12831  this.propertyIndex = parseResults.propertyIndex;
12832 
12833  this.node = THREE.PropertyBinding.findNode( rootNode, this.nodeName ) || rootNode;
12834 
12835  this.cumulativeValue = null;
12836  this.cumulativeWeight = 0;
12837 };
12838 
12839 THREE.PropertyBinding.prototype = {
12840 
12841  constructor: THREE.PropertyBinding,
12842 
12843  reset: function() {
12844 
12845  this.cumulativeValue = null;
12846  this.cumulativeWeight = 0;
12847 
12848  },
12849 
12850  accumulate: function( value, weight ) {
12851 
12852  if ( ! this.isBound ) this.bind();
12853 
12854  if ( this.cumulativeWeight === 0 ) {
12855 
12856  if ( weight > 0 ) {
12857 
12858  if ( this.cumulativeValue === null ) {
12859  this.cumulativeValue = THREE.AnimationUtils.clone( value );
12860  }
12861  this.cumulativeWeight = weight;
12862 
12863  }
12864 
12865  } else {
12866 
12867  var lerpAlpha = weight / ( this.cumulativeWeight + weight );
12868  this.cumulativeValue = this.lerpValue( this.cumulativeValue, value, lerpAlpha );
12869  this.cumulativeWeight += weight;
12870 
12871  }
12872 
12873  },
12874 
12875  unbind: function() {
12876 
12877  if ( ! this.isBound ) return;
12878 
12879  this.setValue( this.originalValue );
12880 
12881  this.setValue = null;
12882  this.getValue = null;
12883  this.lerpValue = null;
12884  this.equalsValue = null;
12885  this.triggerDirty = null;
12886  this.isBound = false;
12887 
12888  },
12889 
12890  // bind to the real property in the scene graph, remember original value, memorize various accessors for speed/inefficiency
12891  bind: function() {
12892 
12893  if ( this.isBound ) return;
12894 
12895  var targetObject = this.node;
12896 
12897  // ensure there is a value node
12898  if ( ! targetObject ) {
12899  console.error( " trying to update node for track: " + this.trackName + " but it wasn't found." );
12900  return;
12901  }
12902 
12903  if ( this.objectName ) {
12904  // special case were we need to reach deeper into the hierarchy to get the face materials....
12905  if ( this.objectName === "materials" ) {
12906  if ( ! targetObject.material ) {
12907  console.error( ' can not bind to material as node does not have a material', this );
12908  return;
12909  }
12910  if ( ! targetObject.material.materials ) {
12911  console.error( ' can not bind to material.materials as node.material does not have a materials array', this );
12912  return;
12913  }
12914  targetObject = targetObject.material.materials;
12915  } else if ( this.objectName === "bones" ) {
12916  if ( ! targetObject.skeleton ) {
12917  console.error( ' can not bind to bones as node does not have a skeleton', this );
12918  return;
12919  }
12920  // potential future optimization: skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
12921 
12922  targetObject = targetObject.skeleton.bones;
12923 
12924  // support resolving morphTarget names into indices.
12925  for ( var i = 0; i < targetObject.length; i ++ ) {
12926  if ( targetObject[i].name === this.objectIndex ) {
12927  this.objectIndex = i;
12928  break;
12929  }
12930  }
12931  } else {
12932 
12933  if ( targetObject[ this.objectName ] === undefined ) {
12934  console.error( ' can not bind to objectName of node, undefined', this );
12935  return;
12936  }
12937  targetObject = targetObject[ this.objectName ];
12938  }
12939 
12940  if ( this.objectIndex !== undefined ) {
12941  if ( targetObject[ this.objectIndex ] === undefined ) {
12942  console.error( " trying to bind to objectIndex of objectName, but is undefined:", this, targetObject );
12943  return;
12944  }
12945 
12946  targetObject = targetObject[ this.objectIndex ];
12947  }
12948 
12949  }
12950 
12951  // special case mappings
12952  var nodeProperty = targetObject[ this.propertyName ];
12953  if ( ! nodeProperty ) {
12954  console.error( " trying to update property for track: " + this.nodeName + '.' + this.propertyName + " but it wasn't found.", targetObject );
12955  return;
12956  }
12957 
12958  // access a sub element of the property array (only primitives are supported right now)
12959  if ( this.propertyIndex !== undefined ) {
12960 
12961  if ( this.propertyName === "morphTargetInfluences" ) {
12962  // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
12963 
12964  // support resolving morphTarget names into indices.
12965  if ( ! targetObject.geometry ) {
12966  console.error( ' can not bind to morphTargetInfluences becasuse node does not have a geometry', this );
12967  }
12968  if ( ! targetObject.geometry.morphTargets ) {
12969  console.error( ' can not bind to morphTargetInfluences becasuse node does not have a geometry.morphTargets', this );
12970  }
12971 
12972  for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) {
12973  if ( targetObject.geometry.morphTargets[i].name === this.propertyIndex ) {
12974  this.propertyIndex = i;
12975  break;
12976  }
12977  }
12978  }
12979 
12980  this.setValue = function setValue_propertyIndexed( value ) {
12981  if ( ! this.equalsValue( nodeProperty[ this.propertyIndex ], value ) ) {
12982  nodeProperty[ this.propertyIndex ] = value;
12983  return true;
12984  }
12985  return false;
12986  };
12987 
12988  this.getValue = function getValue_propertyIndexed() {
12989  return nodeProperty[ this.propertyIndex ];
12990  };
12991 
12992  }
12993  // must use copy for Object3D.Euler/Quaternion
12994  else if ( nodeProperty.copy ) {
12995 
12996  this.setValue = function setValue_propertyObject( value ) {
12997  if ( ! this.equalsValue( nodeProperty, value ) ) {
12998  nodeProperty.copy( value );
12999  return true;
13000  }
13001  return false;
13002  }
13003 
13004  this.getValue = function getValue_propertyObject() {
13005  return nodeProperty;
13006  };
13007 
13008  }
13009  // otherwise just set the property directly on the node (do not use nodeProperty as it may not be a reference object)
13010  else {
13011 
13012  this.setValue = function setValue_property( value ) {
13013  if ( ! this.equalsValue( targetObject[ this.propertyName ], value ) ) {
13014  targetObject[ this.propertyName ] = value;
13015  return true;
13016  }
13017  return false;
13018  }
13019 
13020  this.getValue = function getValue_property() {
13021  return targetObject[ this.propertyName ];
13022  };
13023 
13024  }
13025 
13026  // trigger node dirty
13027  if ( targetObject.needsUpdate !== undefined ) { // material
13028 
13029  this.triggerDirty = function triggerDirty_needsUpdate() {
13030  this.node.needsUpdate = true;
13031  }
13032 
13033  } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
13034 
13035  this.triggerDirty = function triggerDirty_matrixWorldNeedsUpdate() {
13036  targetObject.matrixWorldNeedsUpdate = true;
13037  }
13038 
13039  }
13040 
13041  this.originalValue = this.getValue();
13042 
13043  this.equalsValue = THREE.AnimationUtils.getEqualsFunc( this.originalValue );
13044  this.lerpValue = THREE.AnimationUtils.getLerpFunc( this.originalValue, true );
13045 
13046  this.isBound = true;
13047 
13048  },
13049 
13050  apply: function() {
13051 
13052  // for speed capture the setter pattern as a closure (sort of a memoization pattern: https://en.wikipedia.org/wiki/Memoization)
13053  if ( ! this.isBound ) this.bind();
13054 
13055  // early exit if there is nothing to apply.
13056  if ( this.cumulativeWeight > 0 ) {
13057 
13058  // blend with original value
13059  if ( this.cumulativeWeight < 1 ) {
13060 
13061  var remainingWeight = 1 - this.cumulativeWeight;
13062  var lerpAlpha = remainingWeight / ( this.cumulativeWeight + remainingWeight );
13063  this.cumulativeValue = this.lerpValue( this.cumulativeValue, this.originalValue, lerpAlpha );
13064 
13065  }
13066 
13067  var valueChanged = this.setValue( this.cumulativeValue );
13068 
13069  if ( valueChanged && this.triggerDirty ) {
13070  this.triggerDirty();
13071  }
13072 
13073  // reset accumulator
13074  this.cumulativeValue = null;
13075  this.cumulativeWeight = 0;
13076 
13077  }
13078  }
13079 
13080 };
13081 
13082 
13083 THREE.PropertyBinding.parseTrackName = function( trackName ) {
13084 
13085  // matches strings in the form of:
13086  // nodeName.property
13087  // nodeName.property[accessor]
13088  // nodeName.material.property[accessor]
13089  // uuid.property[accessor]
13090  // uuid.objectName[objectIndex].propertyName[propertyIndex]
13091  // parentName/nodeName.property
13092  // parentName/parentName/nodeName.property[index]
13093  // .bone[Armature.DEF_cog].position
13094  // created and tested via https://regex101.com/#javascript
13095 
13096  var re = /^(([\w]+\/)*)([\w-\d]+)?(\.([\w]+)(\[([\w\d\[\]\_. ]+)\])?)?(\.([\w.]+)(\[([\w\d\[\]\_. ]+)\])?)$/;
13097  var matches = re.exec(trackName);
13098 
13099  if ( ! matches ) {
13100  throw new Error( "cannot parse trackName at all: " + trackName );
13101  }
13102 
13103  if (matches.index === re.lastIndex) {
13104  re.lastIndex++;
13105  }
13106 
13107  var results = {
13108  directoryName: matches[1],
13109  nodeName: matches[3], // allowed to be null, specified root node.
13110  objectName: matches[5],
13111  objectIndex: matches[7],
13112  propertyName: matches[9],
13113  propertyIndex: matches[11] // allowed to be null, specifies that the whole property is set.
13114  };
13115 
13116  if ( results.propertyName === null || results.propertyName.length === 0 ) {
13117  throw new Error( "can not parse propertyName from trackName: " + trackName );
13118  }
13119 
13120  return results;
13121 
13122 };
13123 
13124 THREE.PropertyBinding.findNode = function( root, nodeName ) {
13125 
13126  function searchSkeleton( skeleton ) {
13127 
13128  for ( var i = 0; i < skeleton.bones.length; i ++ ) {
13129 
13130  var bone = skeleton.bones[i];
13131 
13132  if ( bone.name === nodeName ) {
13133 
13134  return bone;
13135 
13136  }
13137  }
13138 
13139  return null;
13140 
13141  }
13142 
13143  function searchNodeSubtree( children ) {
13144 
13145  for ( var i = 0; i < children.length; i ++ ) {
13146 
13147  var childNode = children[i];
13148 
13149  if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
13150 
13151  return childNode;
13152 
13153  }
13154 
13155  var result = searchNodeSubtree( childNode.children );
13156 
13157  if ( result ) return result;
13158 
13159  }
13160 
13161  return null;
13162 
13163  }
13164 
13165  //
13166 
13167  if ( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === -1 || nodeName === root.name || nodeName === root.uuid ) {
13168 
13169  return root;
13170 
13171  }
13172 
13173  // search into skeleton bones.
13174  if ( root.skeleton ) {
13175 
13176  var bone = searchSkeleton( root.skeleton );
13177 
13178  if ( bone ) {
13179 
13180  return bone;
13181 
13182  }
13183  }
13184 
13185  // search into node subtree.
13186  if ( root.children ) {
13187 
13188  var subTreeNode = searchNodeSubtree( root.children );
13189 
13190  if ( subTreeNode ) {
13191 
13192  return subTreeNode;
13193 
13194  }
13195 
13196  }
13197 
13198  return null;
13199 }
13200 
13201 // File:src/animation/tracks/VectorKeyframeTrack.js
13202 
13211 THREE.VectorKeyframeTrack = function ( name, keys ) {
13212 
13213  THREE.KeyframeTrack.call( this, name, keys );
13214 
13215  // local cache of value type to avoid allocations during runtime.
13216  this.result = this.keys[0].value.clone();
13217 
13218 };
13219 
13220 THREE.VectorKeyframeTrack.prototype = Object.create( THREE.KeyframeTrack.prototype );
13221 
13222 THREE.VectorKeyframeTrack.prototype.constructor = THREE.VectorKeyframeTrack;
13223 
13224 THREE.VectorKeyframeTrack.prototype.setResult = function( value ) {
13225 
13226  this.result.copy( value );
13227 
13228 };
13229 
13230 // memoization of the lerp function for speed.
13231 // NOTE: Do not optimize as a prototype initialization closure, as value0 will be different on a per class basis.
13232 THREE.VectorKeyframeTrack.prototype.lerpValues = function( value0, value1, alpha ) {
13233 
13234  return value0.lerp( value1, alpha );
13235 
13236 };
13237 
13238 THREE.VectorKeyframeTrack.prototype.compareValues = function( value0, value1 ) {
13239 
13240  return value0.equals( value1 );
13241 
13242 };
13243 
13244 THREE.VectorKeyframeTrack.prototype.clone = function() {
13245 
13246  var clonedKeys = [];
13247 
13248  for ( var i = 0; i < this.keys.length; i ++ ) {
13249 
13250  var key = this.keys[i];
13251  clonedKeys.push( {
13252  time: key.time,
13253  value: key.value.clone()
13254  } );
13255  }
13256 
13257  return new THREE.VectorKeyframeTrack( this.name, clonedKeys );
13258 
13259 };
13260 
13261 THREE.VectorKeyframeTrack.parse = function( json ) {
13262 
13263  var elementCount = json.keys[0].value.length;
13264  var valueType = THREE[ 'Vector' + elementCount ];
13265 
13266  var keys = [];
13267 
13268  for ( var i = 0; i < json.keys.length; i ++ ) {
13269  var jsonKey = json.keys[i];
13270  keys.push( {
13271  value: new valueType().fromArray( jsonKey.value ),
13272  time: jsonKey.time
13273  } );
13274  }
13275 
13276  return new THREE.VectorKeyframeTrack( json.name, keys );
13277 
13278 };
13279 
13280 // File:src/animation/tracks/QuaternionKeyframeTrack.js
13281 
13290 THREE.QuaternionKeyframeTrack = function ( name, keys ) {
13291 
13292  THREE.KeyframeTrack.call( this, name, keys );
13293 
13294  // local cache of value type to avoid allocations during runtime.
13295  this.result = this.keys[0].value.clone();
13296 
13297 };
13298 
13299 THREE.QuaternionKeyframeTrack.prototype = Object.create( THREE.KeyframeTrack.prototype );
13300 
13301 THREE.QuaternionKeyframeTrack.prototype.constructor = THREE.QuaternionKeyframeTrack;
13302 
13303 THREE.QuaternionKeyframeTrack.prototype.setResult = function( value ) {
13304 
13305  this.result.copy( value );
13306 
13307 };
13308 
13309 // memoization of the lerp function for speed.
13310 // NOTE: Do not optimize as a prototype initialization closure, as value0 will be different on a per class basis.
13311 THREE.QuaternionKeyframeTrack.prototype.lerpValues = function( value0, value1, alpha ) {
13312 
13313  return value0.slerp( value1, alpha );
13314 
13315 };
13316 
13317 THREE.QuaternionKeyframeTrack.prototype.compareValues = function( value0, value1 ) {
13318 
13319  return value0.equals( value1 );
13320 
13321 };
13322 
13323 THREE.QuaternionKeyframeTrack.prototype.multiply = function( quat ) {
13324 
13325  for ( var i = 0; i < this.keys.length; i ++ ) {
13326 
13327  this.keys[i].value.multiply( quat );
13328 
13329  }
13330 
13331  return this;
13332 
13333 };
13334 
13335 THREE.QuaternionKeyframeTrack.prototype.clone = function() {
13336 
13337  var clonedKeys = [];
13338 
13339  for ( var i = 0; i < this.keys.length; i ++ ) {
13340 
13341  var key = this.keys[i];
13342  clonedKeys.push( {
13343  time: key.time,
13344  value: key.value.clone()
13345  } );
13346  }
13347 
13348  return new THREE.QuaternionKeyframeTrack( this.name, clonedKeys );
13349 
13350 };
13351 
13352 THREE.QuaternionKeyframeTrack.parse = function( json ) {
13353 
13354  var keys = [];
13355 
13356  for ( var i = 0; i < json.keys.length; i ++ ) {
13357  var jsonKey = json.keys[i];
13358  keys.push( {
13359  value: new THREE.Quaternion().fromArray( jsonKey.value ),
13360  time: jsonKey.time
13361  } );
13362  }
13363 
13364  return new THREE.QuaternionKeyframeTrack( json.name, keys );
13365 
13366 };
13367 
13368 // File:src/animation/tracks/StringKeyframeTrack.js
13369 
13378 THREE.StringKeyframeTrack = function ( name, keys ) {
13379 
13380  THREE.KeyframeTrack.call( this, name, keys );
13381 
13382  // local cache of value type to avoid allocations during runtime.
13383  this.result = this.keys[0].value;
13384 
13385 };
13386 
13387 THREE.StringKeyframeTrack.prototype = Object.create( THREE.KeyframeTrack.prototype );
13388 
13389 THREE.StringKeyframeTrack.prototype.constructor = THREE.StringKeyframeTrack;
13390 
13391 THREE.StringKeyframeTrack.prototype.setResult = function( value ) {
13392 
13393  this.result = value;
13394 
13395 };
13396 
13397 // memoization of the lerp function for speed.
13398 // NOTE: Do not optimize as a prototype initialization closure, as value0 will be different on a per class basis.
13399 THREE.StringKeyframeTrack.prototype.lerpValues = function( value0, value1, alpha ) {
13400 
13401  return ( alpha < 1.0 ) ? value0 : value1;
13402 
13403 };
13404 
13405 THREE.StringKeyframeTrack.prototype.compareValues = function( value0, value1 ) {
13406 
13407  return ( value0 === value1 );
13408 
13409 };
13410 
13411 THREE.StringKeyframeTrack.prototype.clone = function() {
13412 
13413  var clonedKeys = [];
13414 
13415  for ( var i = 0; i < this.keys.length; i ++ ) {
13416 
13417  var key = this.keys[i];
13418  clonedKeys.push( {
13419  time: key.time,
13420  value: key.value
13421  } );
13422  }
13423 
13424  return new THREE.StringKeyframeTrack( this.name, clonedKeys );
13425 
13426 };
13427 
13428 THREE.StringKeyframeTrack.parse = function( json ) {
13429 
13430  return new THREE.StringKeyframeTrack( json.name, json.keys );
13431 
13432 };
13433 
13434 // File:src/animation/tracks/BooleanKeyframeTrack.js
13435 
13444 THREE.BooleanKeyframeTrack = function ( name, keys ) {
13445 
13446  THREE.KeyframeTrack.call( this, name, keys );
13447 
13448  // local cache of value type to avoid allocations during runtime.
13449  this.result = this.keys[0].value;
13450 
13451 };
13452 
13453 THREE.BooleanKeyframeTrack.prototype = Object.create( THREE.KeyframeTrack.prototype );
13454 
13455 THREE.BooleanKeyframeTrack.prototype.constructor = THREE.BooleanKeyframeTrack;
13456 
13457 THREE.BooleanKeyframeTrack.prototype.setResult = function( value ) {
13458 
13459  this.result = value;
13460 
13461 };
13462 
13463 // memoization of the lerp function for speed.
13464 // NOTE: Do not optimize as a prototype initialization closure, as value0 will be different on a per class basis.
13465 THREE.BooleanKeyframeTrack.prototype.lerpValues = function( value0, value1, alpha ) {
13466 
13467  return ( alpha < 1.0 ) ? value0 : value1;
13468 
13469 };
13470 
13471 THREE.BooleanKeyframeTrack.prototype.compareValues = function( value0, value1 ) {
13472 
13473  return ( value0 === value1 );
13474 
13475 };
13476 
13477 THREE.BooleanKeyframeTrack.prototype.clone = function() {
13478 
13479  var clonedKeys = [];
13480 
13481  for ( var i = 0; i < this.keys.length; i ++ ) {
13482 
13483  var key = this.keys[i];
13484  clonedKeys.push( {
13485  time: key.time,
13486  value: key.value
13487  } );
13488  }
13489 
13490  return new THREE.BooleanKeyframeTrack( this.name, clonedKeys );
13491 
13492 };
13493 
13494 THREE.BooleanKeyframeTrack.parse = function( json ) {
13495 
13496  return new THREE.BooleanKeyframeTrack( json.name, json.keys );
13497 
13498 };
13499 
13500 // File:src/animation/tracks/NumberKeyframeTrack.js
13501 
13510 THREE.NumberKeyframeTrack = function ( name, keys ) {
13511 
13512  THREE.KeyframeTrack.call( this, name, keys );
13513 
13514  // local cache of value type to avoid allocations during runtime.
13515  this.result = this.keys[0].value;
13516 
13517 };
13518 
13519 THREE.NumberKeyframeTrack.prototype = Object.create( THREE.KeyframeTrack.prototype );
13520 
13521 THREE.NumberKeyframeTrack.prototype.constructor = THREE.NumberKeyframeTrack;
13522 
13523 THREE.NumberKeyframeTrack.prototype.setResult = function( value ) {
13524 
13525  this.result = value;
13526 
13527 };
13528 
13529 // memoization of the lerp function for speed.
13530 // NOTE: Do not optimize as a prototype initialization closure, as value0 will be different on a per class basis.
13531 THREE.NumberKeyframeTrack.prototype.lerpValues = function( value0, value1, alpha ) {
13532 
13533  return value0 * ( 1 - alpha ) + value1 * alpha;
13534 
13535 };
13536 
13537 THREE.NumberKeyframeTrack.prototype.compareValues = function( value0, value1 ) {
13538 
13539  return ( value0 === value1 );
13540 
13541 };
13542 
13543 THREE.NumberKeyframeTrack.prototype.clone = function() {
13544 
13545  var clonedKeys = [];
13546 
13547  for ( var i = 0; i < this.keys.length; i ++ ) {
13548 
13549  var key = this.keys[i];
13550  clonedKeys.push( {
13551  time: key.time,
13552  value: key.value
13553  } );
13554  }
13555 
13556  return new THREE.NumberKeyframeTrack( this.name, clonedKeys );
13557 
13558 };
13559 
13560 THREE.NumberKeyframeTrack.parse = function( json ) {
13561 
13562  return new THREE.NumberKeyframeTrack( json.name, json.keys );
13563 
13564 };
13565 
13566 // File:src/cameras/Camera.js
13567 
13574 THREE.Camera = function () {
13575 
13576  THREE.Object3D.call( this );
13577 
13578  this.type = 'Camera';
13579 
13580  this.matrixWorldInverse = new THREE.Matrix4();
13581  this.projectionMatrix = new THREE.Matrix4();
13582 
13583 };
13584 
13585 THREE.Camera.prototype = Object.create( THREE.Object3D.prototype );
13586 THREE.Camera.prototype.constructor = THREE.Camera;
13587 
13588 THREE.Camera.prototype.getWorldDirection = function () {
13589 
13590  var quaternion = new THREE.Quaternion();
13591 
13592  return function ( optionalTarget ) {
13593 
13594  var result = optionalTarget || new THREE.Vector3();
13595 
13596  this.getWorldQuaternion( quaternion );
13597 
13598  return result.set( 0, 0, - 1 ).applyQuaternion( quaternion );
13599 
13600  };
13601 
13602 }();
13603 
13604 THREE.Camera.prototype.lookAt = function () {
13605 
13606  // This routine does not support cameras with rotated and/or translated parent(s)
13607 
13608  var m1 = new THREE.Matrix4();
13609 
13610  return function ( vector ) {
13611 
13612  m1.lookAt( this.position, vector, this.up );
13613 
13614  this.quaternion.setFromRotationMatrix( m1 );
13615 
13616  };
13617 
13618 }();
13619 
13620 THREE.Camera.prototype.clone = function () {
13621 
13622  return new this.constructor().copy( this );
13623 
13624 };
13625 
13626 THREE.Camera.prototype.copy = function ( source ) {
13627 
13628  THREE.Object3D.prototype.copy.call( this, source );
13629 
13630  this.matrixWorldInverse.copy( source.matrixWorldInverse );
13631  this.projectionMatrix.copy( source.projectionMatrix );
13632 
13633  return this;
13634 
13635 };
13636 
13637 // File:src/cameras/CubeCamera.js
13638 
13646 THREE.CubeCamera = function ( near, far, cubeResolution ) {
13647 
13648  THREE.Object3D.call( this );
13649 
13650  this.type = 'CubeCamera';
13651 
13652  var fov = 90, aspect = 1;
13653 
13654  var cameraPX = new THREE.PerspectiveCamera( fov, aspect, near, far );
13655  cameraPX.up.set( 0, - 1, 0 );
13656  cameraPX.lookAt( new THREE.Vector3( 1, 0, 0 ) );
13657  this.add( cameraPX );
13658 
13659  var cameraNX = new THREE.PerspectiveCamera( fov, aspect, near, far );
13660  cameraNX.up.set( 0, - 1, 0 );
13661  cameraNX.lookAt( new THREE.Vector3( - 1, 0, 0 ) );
13662  this.add( cameraNX );
13663 
13664  var cameraPY = new THREE.PerspectiveCamera( fov, aspect, near, far );
13665  cameraPY.up.set( 0, 0, 1 );
13666  cameraPY.lookAt( new THREE.Vector3( 0, 1, 0 ) );
13667  this.add( cameraPY );
13668 
13669  var cameraNY = new THREE.PerspectiveCamera( fov, aspect, near, far );
13670  cameraNY.up.set( 0, 0, - 1 );
13671  cameraNY.lookAt( new THREE.Vector3( 0, - 1, 0 ) );
13672  this.add( cameraNY );
13673 
13674  var cameraPZ = new THREE.PerspectiveCamera( fov, aspect, near, far );
13675  cameraPZ.up.set( 0, - 1, 0 );
13676  cameraPZ.lookAt( new THREE.Vector3( 0, 0, 1 ) );
13677  this.add( cameraPZ );
13678 
13679  var cameraNZ = new THREE.PerspectiveCamera( fov, aspect, near, far );
13680  cameraNZ.up.set( 0, - 1, 0 );
13681  cameraNZ.lookAt( new THREE.Vector3( 0, 0, - 1 ) );
13682  this.add( cameraNZ );
13683 
13684  this.renderTarget = new THREE.WebGLRenderTargetCube( cubeResolution, cubeResolution, { format: THREE.RGBFormat, magFilter: THREE.LinearFilter, minFilter: THREE.LinearFilter } );
13685 
13686  this.updateCubeMap = function ( renderer, scene ) {
13687 
13688  if ( this.parent === null ) this.updateMatrixWorld();
13689 
13690  var renderTarget = this.renderTarget;
13691  var generateMipmaps = renderTarget.texture.generateMipmaps;
13692 
13693  renderTarget.texture.generateMipmaps = false;
13694 
13695  renderTarget.activeCubeFace = 0;
13696  renderer.render( scene, cameraPX, renderTarget );
13697 
13698  renderTarget.activeCubeFace = 1;
13699  renderer.render( scene, cameraNX, renderTarget );
13700 
13701  renderTarget.activeCubeFace = 2;
13702  renderer.render( scene, cameraPY, renderTarget );
13703 
13704  renderTarget.activeCubeFace = 3;
13705  renderer.render( scene, cameraNY, renderTarget );
13706 
13707  renderTarget.activeCubeFace = 4;
13708  renderer.render( scene, cameraPZ, renderTarget );
13709 
13710  renderTarget.texture.generateMipmaps = generateMipmaps;
13711 
13712  renderTarget.activeCubeFace = 5;
13713  renderer.render( scene, cameraNZ, renderTarget );
13714 
13715  renderer.setRenderTarget( null );
13716 
13717  };
13718 
13719 };
13720 
13721 THREE.CubeCamera.prototype = Object.create( THREE.Object3D.prototype );
13722 THREE.CubeCamera.prototype.constructor = THREE.CubeCamera;
13723 
13724 // File:src/cameras/OrthographicCamera.js
13725 
13730 THREE.OrthographicCamera = function ( left, right, top, bottom, near, far ) {
13731 
13732  THREE.Camera.call( this );
13733 
13734  this.type = 'OrthographicCamera';
13735 
13736  this.zoom = 1;
13737 
13738  this.left = left;
13739  this.right = right;
13740  this.top = top;
13741  this.bottom = bottom;
13742 
13743  this.near = ( near !== undefined ) ? near : 0.1;
13744  this.far = ( far !== undefined ) ? far : 2000;
13745 
13746  this.updateProjectionMatrix();
13747 
13748 };
13749 
13750 THREE.OrthographicCamera.prototype = Object.create( THREE.Camera.prototype );
13751 THREE.OrthographicCamera.prototype.constructor = THREE.OrthographicCamera;
13752 
13753 THREE.OrthographicCamera.prototype.updateProjectionMatrix = function () {
13754 
13755  var dx = ( this.right - this.left ) / ( 2 * this.zoom );
13756  var dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
13757  var cx = ( this.right + this.left ) / 2;
13758  var cy = ( this.top + this.bottom ) / 2;
13759 
13760  this.projectionMatrix.makeOrthographic( cx - dx, cx + dx, cy + dy, cy - dy, this.near, this.far );
13761 
13762 };
13763 
13764 THREE.OrthographicCamera.prototype.copy = function ( source ) {
13765 
13766  THREE.Camera.prototype.copy.call( this, source );
13767 
13768  this.left = source.left;
13769  this.right = source.right;
13770  this.top = source.top;
13771  this.bottom = source.bottom;
13772  this.near = source.near;
13773  this.far = source.far;
13774 
13775  this.zoom = source.zoom;
13776 
13777  return this;
13778 
13779 };
13780 
13781 THREE.OrthographicCamera.prototype.toJSON = function ( meta ) {
13782 
13783  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
13784 
13785  data.object.zoom = this.zoom;
13786  data.object.left = this.left;
13787  data.object.right = this.right;
13788  data.object.top = this.top;
13789  data.object.bottom = this.bottom;
13790  data.object.near = this.near;
13791  data.object.far = this.far;
13792 
13793  return data;
13794 
13795 };
13796 
13797 // File:src/cameras/PerspectiveCamera.js
13798 
13805 THREE.PerspectiveCamera = function ( fov, aspect, near, far ) {
13806 
13807  THREE.Camera.call( this );
13808 
13809  this.type = 'PerspectiveCamera';
13810 
13811  this.zoom = 1;
13812 
13813  this.fov = fov !== undefined ? fov : 50;
13814  this.aspect = aspect !== undefined ? aspect : 1;
13815  this.near = near !== undefined ? near : 0.1;
13816  this.far = far !== undefined ? far : 2000;
13817 
13818  this.updateProjectionMatrix();
13819 
13820 };
13821 
13822 THREE.PerspectiveCamera.prototype = Object.create( THREE.Camera.prototype );
13823 THREE.PerspectiveCamera.prototype.constructor = THREE.PerspectiveCamera;
13824 
13825 
13832 THREE.PerspectiveCamera.prototype.setLens = function ( focalLength, frameHeight ) {
13833 
13834  if ( frameHeight === undefined ) frameHeight = 24;
13835 
13836  this.fov = 2 * THREE.Math.radToDeg( Math.atan( frameHeight / ( focalLength * 2 ) ) );
13837  this.updateProjectionMatrix();
13838 
13839 };
13840 
13841 
13878 THREE.PerspectiveCamera.prototype.setViewOffset = function ( fullWidth, fullHeight, x, y, width, height ) {
13879 
13880  this.fullWidth = fullWidth;
13881  this.fullHeight = fullHeight;
13882  this.x = x;
13883  this.y = y;
13884  this.width = width;
13885  this.height = height;
13886 
13887  this.updateProjectionMatrix();
13888 
13889 };
13890 
13891 
13892 THREE.PerspectiveCamera.prototype.updateProjectionMatrix = function () {
13893 
13894  var fov = THREE.Math.radToDeg( 2 * Math.atan( Math.tan( THREE.Math.degToRad( this.fov ) * 0.5 ) / this.zoom ) );
13895 
13896  if ( this.fullWidth ) {
13897 
13898  var aspect = this.fullWidth / this.fullHeight;
13899  var top = Math.tan( THREE.Math.degToRad( fov * 0.5 ) ) * this.near;
13900  var bottom = - top;
13901  var left = aspect * bottom;
13902  var right = aspect * top;
13903  var width = Math.abs( right - left );
13904  var height = Math.abs( top - bottom );
13905 
13906  this.projectionMatrix.makeFrustum(
13907  left + this.x * width / this.fullWidth,
13908  left + ( this.x + this.width ) * width / this.fullWidth,
13909  top - ( this.y + this.height ) * height / this.fullHeight,
13910  top - this.y * height / this.fullHeight,
13911  this.near,
13912  this.far
13913  );
13914 
13915  } else {
13916 
13917  this.projectionMatrix.makePerspective( fov, this.aspect, this.near, this.far );
13918 
13919  }
13920 
13921 };
13922 
13923 THREE.PerspectiveCamera.prototype.copy = function ( source ) {
13924 
13925  THREE.Camera.prototype.copy.call( this, source );
13926 
13927  this.fov = source.fov;
13928  this.aspect = source.aspect;
13929  this.near = source.near;
13930  this.far = source.far;
13931 
13932  this.zoom = source.zoom;
13933 
13934  return this;
13935 
13936 };
13937 
13938 THREE.PerspectiveCamera.prototype.toJSON = function ( meta ) {
13939 
13940  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
13941 
13942  data.object.zoom = this.zoom;
13943  data.object.fov = this.fov;
13944  data.object.aspect = this.aspect;
13945  data.object.near = this.near;
13946  data.object.far = this.far;
13947 
13948  return data;
13949 
13950 };
13951 
13952 // File:src/lights/Light.js
13953 
13959 THREE.Light = function ( color ) {
13960 
13961  THREE.Object3D.call( this );
13962 
13963  this.type = 'Light';
13964 
13965  this.color = new THREE.Color( color );
13966 
13967  this.receiveShadow = undefined;
13968 
13969 };
13970 
13971 THREE.Light.prototype = Object.create( THREE.Object3D.prototype );
13972 THREE.Light.prototype.constructor = THREE.Light;
13973 
13974 Object.defineProperties( THREE.Light.prototype, {
13975  onlyShadow: {
13976  set: function ( value ) {
13977  console.warn( 'THREE.Light: .onlyShadow has been removed.' );
13978  }
13979  },
13980  shadowCameraFov: {
13981  set: function ( value ) {
13982  this.shadow.camera.fov = value;
13983  }
13984  },
13985  shadowCameraLeft: {
13986  set: function ( value ) {
13987  this.shadow.camera.left = value;
13988  }
13989  },
13990  shadowCameraRight: {
13991  set: function ( value ) {
13992  this.shadow.camera.right = value;
13993  }
13994  },
13995  shadowCameraTop: {
13996  set: function ( value ) {
13997  this.shadow.camera.top = value;
13998  }
13999  },
14000  shadowCameraBottom: {
14001  set: function ( value ) {
14002  this.shadow.camera.bottom = value;
14003  }
14004  },
14005  shadowCameraNear: {
14006  set: function ( value ) {
14007  this.shadow.camera.near = value;
14008  }
14009  },
14010  shadowCameraFar: {
14011  set: function ( value ) {
14012  this.shadow.camera.far = value;
14013  }
14014  },
14015  shadowCameraVisible: {
14016  set: function ( value ) {
14017  console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow ) instead.' );
14018  }
14019  },
14020  shadowBias: {
14021  set: function ( value ) {
14022  this.shadow.bias = value;
14023  }
14024  },
14025  shadowDarkness: {
14026  set: function ( value ) {
14027  this.shadow.darkness = value;
14028  }
14029  },
14030  shadowMapWidth: {
14031  set: function ( value ) {
14032  this.shadow.mapSize.width = value;
14033  }
14034  },
14035  shadowMapHeight: {
14036  set: function ( value ) {
14037  this.shadow.mapSize.height = value;
14038  }
14039  }
14040 } );
14041 
14042 THREE.Light.prototype.copy = function ( source ) {
14043 
14044  THREE.Object3D.prototype.copy.call( this, source );
14045 
14046  this.color.copy( source.color );
14047 
14048  return this;
14049 
14050 };
14051 
14052 THREE.Light.prototype.toJSON = function ( meta ) {
14053 
14054  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
14055 
14056  data.object.color = this.color.getHex();
14057  if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
14058 
14059  if ( this.intensity !== undefined ) data.object.intensity = this.intensity;
14060  if ( this.distance !== undefined ) data.object.distance = this.distance;
14061  if ( this.angle !== undefined ) data.object.angle = this.angle;
14062  if ( this.decay !== undefined ) data.object.decay = this.decay;
14063  if ( this.exponent !== undefined ) data.object.exponent = this.exponent;
14064 
14065  return data;
14066 
14067 };
14068 
14069 // File:src/lights/LightShadow.js
14070 
14075 THREE.LightShadow = function ( camera ) {
14076 
14077  this.camera = camera;
14078 
14079  this.bias = 0;
14080  this.darkness = 1;
14081 
14082  this.mapSize = new THREE.Vector2( 512, 512 );
14083 
14084  this.map = null;
14085  this.matrix = null;
14086 
14087 };
14088 
14089 THREE.LightShadow.prototype = {
14090 
14091  constructor: THREE.LightShadow,
14092 
14093  copy: function ( source ) {
14094 
14095  this.camera = source.camera.clone();
14096 
14097  this.bias = source.bias;
14098  this.darkness = source.darkness;
14099 
14100  this.mapSize.copy( source.mapSize );
14101 
14102  },
14103 
14104  clone: function () {
14105 
14106  return new this.constructor().copy( this );
14107 
14108  }
14109 
14110 };
14111 
14112 // File:src/lights/AmbientLight.js
14113 
14118 THREE.AmbientLight = function ( color ) {
14119 
14120  THREE.Light.call( this, color );
14121 
14122  this.type = 'AmbientLight';
14123 
14124  this.castShadow = undefined;
14125 
14126 };
14127 
14128 THREE.AmbientLight.prototype = Object.create( THREE.Light.prototype );
14129 THREE.AmbientLight.prototype.constructor = THREE.AmbientLight;
14130 
14131 // File:src/lights/DirectionalLight.js
14132 
14138 THREE.DirectionalLight = function ( color, intensity ) {
14139 
14140  THREE.Light.call( this, color );
14141 
14142  this.type = 'DirectionalLight';
14143 
14144  this.position.set( 0, 1, 0 );
14145  this.updateMatrix();
14146 
14147  this.target = new THREE.Object3D();
14148 
14149  this.intensity = ( intensity !== undefined ) ? intensity : 1;
14150 
14151  this.shadow = new THREE.LightShadow( new THREE.OrthographicCamera( - 500, 500, 500, - 500, 50, 5000 ) );
14152 
14153 };
14154 
14155 THREE.DirectionalLight.prototype = Object.create( THREE.Light.prototype );
14156 THREE.DirectionalLight.prototype.constructor = THREE.DirectionalLight;
14157 
14158 THREE.DirectionalLight.prototype.copy = function ( source ) {
14159 
14160  THREE.Light.prototype.copy.call( this, source );
14161 
14162  this.intensity = source.intensity;
14163  this.target = source.target.clone();
14164 
14165  this.shadow = source.shadow.clone();
14166 
14167  return this;
14168 
14169 };
14170 
14171 // File:src/lights/HemisphereLight.js
14172 
14177 THREE.HemisphereLight = function ( skyColor, groundColor, intensity ) {
14178 
14179  THREE.Light.call( this, skyColor );
14180 
14181  this.type = 'HemisphereLight';
14182 
14183  this.castShadow = undefined;
14184 
14185  this.position.set( 0, 1, 0 );
14186  this.updateMatrix();
14187 
14188  this.groundColor = new THREE.Color( groundColor );
14189  this.intensity = ( intensity !== undefined ) ? intensity : 1;
14190 
14191 };
14192 
14193 THREE.HemisphereLight.prototype = Object.create( THREE.Light.prototype );
14194 THREE.HemisphereLight.prototype.constructor = THREE.HemisphereLight;
14195 
14196 THREE.HemisphereLight.prototype.copy = function ( source ) {
14197 
14198  THREE.Light.prototype.copy.call( this, source );
14199 
14200  this.groundColor.copy( source.groundColor );
14201  this.intensity = source.intensity;
14202 
14203  return this;
14204 
14205 };
14206 
14207 // File:src/lights/PointLight.js
14208 
14214 THREE.PointLight = function ( color, intensity, distance, decay ) {
14215 
14216  THREE.Light.call( this, color );
14217 
14218  this.type = 'PointLight';
14219 
14220  this.intensity = ( intensity !== undefined ) ? intensity : 1;
14221  this.distance = ( distance !== undefined ) ? distance : 0;
14222  this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2.
14223 
14224  this.shadow = new THREE.LightShadow( new THREE.PerspectiveCamera( 90, 1, 1, 500 ) );
14225 
14226 };
14227 
14228 THREE.PointLight.prototype = Object.create( THREE.Light.prototype );
14229 THREE.PointLight.prototype.constructor = THREE.PointLight;
14230 
14231 THREE.PointLight.prototype.copy = function ( source ) {
14232 
14233  THREE.Light.prototype.copy.call( this, source );
14234 
14235  this.intensity = source.intensity;
14236  this.distance = source.distance;
14237  this.decay = source.decay;
14238 
14239  this.shadow = source.shadow.clone();
14240 
14241  return this;
14242 
14243 };
14244 
14245 // File:src/lights/SpotLight.js
14246 
14251 THREE.SpotLight = function ( color, intensity, distance, angle, exponent, decay ) {
14252 
14253  THREE.Light.call( this, color );
14254 
14255  this.type = 'SpotLight';
14256 
14257  this.position.set( 0, 1, 0 );
14258  this.updateMatrix();
14259 
14260  this.target = new THREE.Object3D();
14261 
14262  this.intensity = ( intensity !== undefined ) ? intensity : 1;
14263  this.distance = ( distance !== undefined ) ? distance : 0;
14264  this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
14265  this.exponent = ( exponent !== undefined ) ? exponent : 10;
14266  this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2.
14267 
14268  this.shadow = new THREE.LightShadow( new THREE.PerspectiveCamera( 50, 1, 50, 5000 ) );
14269 
14270 };
14271 
14272 THREE.SpotLight.prototype = Object.create( THREE.Light.prototype );
14273 THREE.SpotLight.prototype.constructor = THREE.SpotLight;
14274 
14275 THREE.SpotLight.prototype.copy = function ( source ) {
14276 
14277  THREE.Light.prototype.copy.call( this, source );
14278 
14279  this.intensity = source.intensity;
14280  this.distance = source.distance;
14281  this.angle = source.angle;
14282  this.exponent = source.exponent;
14283  this.decay = source.decay;
14284 
14285  this.target = source.target.clone();
14286 
14287  this.shadow = source.shadow.clone();
14288 
14289  return this;
14290 
14291 };
14292 
14293 // File:src/loaders/Cache.js
14294 
14299 THREE.Cache = {
14300 
14301  enabled: false,
14302 
14303  files: {},
14304 
14305  add: function ( key, file ) {
14306 
14307  if ( this.enabled === false ) return;
14308 
14309  // console.log( 'THREE.Cache', 'Adding key:', key );
14310 
14311  this.files[ key ] = file;
14312 
14313  },
14314 
14315  get: function ( key ) {
14316 
14317  if ( this.enabled === false ) return;
14318 
14319  // console.log( 'THREE.Cache', 'Checking key:', key );
14320 
14321  return this.files[ key ];
14322 
14323  },
14324 
14325  remove: function ( key ) {
14326 
14327  delete this.files[ key ];
14328 
14329  },
14330 
14331  clear: function () {
14332 
14333  this.files = {};
14334 
14335  }
14336 
14337 };
14338 
14339 // File:src/loaders/Loader.js
14340 
14345 THREE.Loader = function () {
14346 
14347  this.onLoadStart = function () {};
14348  this.onLoadProgress = function () {};
14349  this.onLoadComplete = function () {};
14350 
14351 };
14352 
14353 THREE.Loader.prototype = {
14354 
14355  constructor: THREE.Loader,
14356 
14357  crossOrigin: undefined,
14358 
14359  extractUrlBase: function ( url ) {
14360 
14361  var parts = url.split( '/' );
14362 
14363  if ( parts.length === 1 ) return './';
14364 
14365  parts.pop();
14366 
14367  return parts.join( '/' ) + '/';
14368 
14369  },
14370 
14371  initMaterials: function ( materials, texturePath, crossOrigin ) {
14372 
14373  var array = [];
14374 
14375  for ( var i = 0; i < materials.length; ++ i ) {
14376 
14377  array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin );
14378 
14379  }
14380 
14381  return array;
14382 
14383  },
14384 
14385  createMaterial: ( function () {
14386 
14387  var color, textureLoader, materialLoader;
14388 
14389  return function ( m, texturePath, crossOrigin ) {
14390 
14391  if ( color === undefined ) color = new THREE.Color();
14392  if ( textureLoader === undefined ) textureLoader = new THREE.TextureLoader();
14393  if ( materialLoader === undefined ) materialLoader = new THREE.MaterialLoader();
14394 
14395  // convert from old material format
14396 
14397  var textures = {};
14398 
14399  function loadTexture( path, repeat, offset, wrap, anisotropy ) {
14400 
14401  var fullPath = texturePath + path;
14402  var loader = THREE.Loader.Handlers.get( fullPath );
14403 
14404  var texture;
14405 
14406  if ( loader !== null ) {
14407 
14408  texture = loader.load( fullPath );
14409 
14410  } else {
14411 
14412  textureLoader.setCrossOrigin( crossOrigin );
14413  texture = textureLoader.load( fullPath );
14414 
14415  }
14416 
14417  if ( repeat !== undefined ) {
14418 
14419  texture.repeat.fromArray( repeat );
14420 
14421  if ( repeat[ 0 ] !== 1 ) texture.wrapS = THREE.RepeatWrapping;
14422  if ( repeat[ 1 ] !== 1 ) texture.wrapT = THREE.RepeatWrapping;
14423 
14424  }
14425 
14426  if ( offset !== undefined ) {
14427 
14428  texture.offset.fromArray( offset );
14429 
14430  }
14431 
14432  if ( wrap !== undefined ) {
14433 
14434  if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = THREE.RepeatWrapping;
14435  if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = THREE.MirroredRepeatWrapping;
14436 
14437  if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = THREE.RepeatWrapping;
14438  if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = THREE.MirroredRepeatWrapping;
14439 
14440  }
14441 
14442  if ( anisotropy !== undefined ) {
14443 
14444  texture.anisotropy = anisotropy;
14445 
14446  }
14447 
14448  var uuid = THREE.Math.generateUUID();
14449 
14450  textures[ uuid ] = texture;
14451 
14452  return uuid;
14453 
14454  }
14455 
14456  //
14457 
14458  var json = {
14459  uuid: THREE.Math.generateUUID(),
14460  type: 'MeshLambertMaterial'
14461  };
14462 
14463  for ( var name in m ) {
14464 
14465  var value = m[ name ];
14466 
14467  switch ( name ) {
14468  case 'DbgColor':
14469  json.color = value;
14470  break;
14471  case 'DbgIndex':
14472  case 'opticalDensity':
14473  case 'illumination':
14474  // These were never supported
14475  break;
14476  case 'DbgName':
14477  json.name = value;
14478  break;
14479  case 'blending':
14480  json.blending = THREE[ value ];
14481  break;
14482  case 'colorDiffuse':
14483  json.color = color.fromArray( value ).getHex();
14484  break;
14485  case 'colorSpecular':
14486  json.specular = color.fromArray( value ).getHex();
14487  break;
14488  case 'colorEmissive':
14489  json.emissive = color.fromArray( value ).getHex();
14490  break;
14491  case 'specularCoef':
14492  json.shininess = value;
14493  break;
14494  case 'shading':
14495  if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial';
14496  if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial';
14497  break;
14498  case 'mapDiffuse':
14499  json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
14500  break;
14501  case 'mapDiffuseRepeat':
14502  case 'mapDiffuseOffset':
14503  case 'mapDiffuseWrap':
14504  case 'mapDiffuseAnisotropy':
14505  break;
14506  case 'mapLight':
14507  json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
14508  break;
14509  case 'mapLightRepeat':
14510  case 'mapLightOffset':
14511  case 'mapLightWrap':
14512  case 'mapLightAnisotropy':
14513  break;
14514  case 'mapAO':
14515  json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy );
14516  break;
14517  case 'mapAORepeat':
14518  case 'mapAOOffset':
14519  case 'mapAOWrap':
14520  case 'mapAOAnisotropy':
14521  break;
14522  case 'mapBump':
14523  json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
14524  break;
14525  case 'mapBumpScale':
14526  json.bumpScale = value;
14527  break;
14528  case 'mapBumpRepeat':
14529  case 'mapBumpOffset':
14530  case 'mapBumpWrap':
14531  case 'mapBumpAnisotropy':
14532  break;
14533  case 'mapNormal':
14534  json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
14535  break;
14536  case 'mapNormalFactor':
14537  json.normalScale = [ value, value ];
14538  break;
14539  case 'mapNormalRepeat':
14540  case 'mapNormalOffset':
14541  case 'mapNormalWrap':
14542  case 'mapNormalAnisotropy':
14543  break;
14544  case 'mapSpecular':
14545  json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
14546  break;
14547  case 'mapSpecularRepeat':
14548  case 'mapSpecularOffset':
14549  case 'mapSpecularWrap':
14550  case 'mapSpecularAnisotropy':
14551  break;
14552  case 'mapAlpha':
14553  json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
14554  break;
14555  case 'mapAlphaRepeat':
14556  case 'mapAlphaOffset':
14557  case 'mapAlphaWrap':
14558  case 'mapAlphaAnisotropy':
14559  break;
14560  case 'flipSided':
14561  json.side = THREE.BackSide;
14562  break;
14563  case 'doubleSided':
14564  json.side = THREE.DoubleSide;
14565  break;
14566  case 'transparency':
14567  console.warn( 'THREE.Loader: transparency has been renamed to opacity' );
14568  json.opacity = value;
14569  break;
14570  case 'opacity':
14571  case 'transparent':
14572  case 'depthTest':
14573  case 'depthWrite':
14574  case 'transparent':
14575  case 'visible':
14576  case 'wireframe':
14577  json[ name ] = value;
14578  break;
14579  case 'vertexColors':
14580  if ( value === true ) json.vertexColors = THREE.VertexColors;
14581  if ( value === 'face' ) json.vertexColors = THREE.FaceColors;
14582  break;
14583  default:
14584  console.error( 'Loader.createMaterial: Unsupported', name, value );
14585  break;
14586  }
14587 
14588  }
14589 
14590  if ( json.type !== 'MeshPhongMaterial' ) delete json.specular;
14591  if ( json.opacity < 1 ) json.transparent = true;
14592 
14593  materialLoader.setTextures( textures );
14594 
14595  return materialLoader.parse( json );
14596 
14597  };
14598 
14599  } )()
14600 
14601 };
14602 
14603 THREE.Loader.Handlers = {
14604 
14605  handlers: [],
14606 
14607  add: function ( regex, loader ) {
14608 
14609  this.handlers.push( regex, loader );
14610 
14611  },
14612 
14613  get: function ( file ) {
14614 
14615  var handlers = this.handlers;
14616 
14617  for ( var i = 0, l = handlers.length; i < l; i += 2 ) {
14618 
14619  var regex = handlers[ i ];
14620  var loader = handlers[ i + 1 ];
14621 
14622  if ( regex.test( file ) ) {
14623 
14624  return loader;
14625 
14626  }
14627 
14628  }
14629 
14630  return null;
14631 
14632  }
14633 
14634 };
14635 
14636 // File:src/loaders/XHRLoader.js
14637 
14642 THREE.XHRLoader = function ( manager ) {
14643 
14644  this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
14645 
14646 };
14647 
14648 THREE.XHRLoader.prototype = {
14649 
14650  constructor: THREE.XHRLoader,
14651 
14652  load: function ( url, onLoad, onProgress, onError ) {
14653 
14654  var scope = this;
14655 
14656  var cached = THREE.Cache.get( url );
14657 
14658  if ( cached !== undefined ) {
14659 
14660  if ( onLoad ) {
14661 
14662  setTimeout( function () {
14663 
14664  onLoad( cached );
14665 
14666  }, 0 );
14667 
14668  }
14669 
14670  return cached;
14671 
14672  }
14673 
14674  var request = new XMLHttpRequest();
14675  request.open( 'GET', url, true );
14676 
14677  request.addEventListener( 'load', function ( event ) {
14678 
14679  var response = event.target.response;
14680 
14681  THREE.Cache.add( url, response );
14682 
14683  if ( onLoad ) onLoad( response );
14684 
14685  scope.manager.itemEnd( url );
14686 
14687  }, false );
14688 
14689  if ( onProgress !== undefined ) {
14690 
14691  request.addEventListener( 'progress', function ( event ) {
14692 
14693  onProgress( event );
14694 
14695  }, false );
14696 
14697  }
14698 
14699  request.addEventListener( 'error', function ( event ) {
14700 
14701  if ( onError ) onError( event );
14702 
14703  scope.manager.itemError( url );
14704 
14705  }, false );
14706 
14707  if ( this.crossOrigin !== undefined ) request.crossOrigin = this.crossOrigin;
14708  if ( this.responseType !== undefined ) request.responseType = this.responseType;
14709  if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
14710 
14711  request.send( null );
14712 
14713  scope.manager.itemStart( url );
14714 
14715  return request;
14716 
14717  },
14718 
14719  setResponseType: function ( value ) {
14720 
14721  this.responseType = value;
14722 
14723  },
14724 
14725  setCrossOrigin: function ( value ) {
14726 
14727  this.crossOrigin = value;
14728 
14729  },
14730 
14731  setWithCredentials: function ( value ) {
14732 
14733  this.withCredentials = value;
14734 
14735  }
14736 
14737 };
14738 
14739 // File:src/loaders/ImageLoader.js
14740 
14745 THREE.ImageLoader = function ( manager ) {
14746 
14747  this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
14748 
14749 };
14750 
14751 THREE.ImageLoader.prototype = {
14752 
14753  constructor: THREE.ImageLoader,
14754 
14755  load: function ( url, onLoad, onProgress, onError ) {
14756 
14757  var scope = this;
14758 
14759  var cached = THREE.Cache.get( url );
14760 
14761  if ( cached !== undefined ) {
14762 
14763  scope.manager.itemStart( url );
14764 
14765  if ( onLoad ) {
14766 
14767  setTimeout( function () {
14768 
14769  onLoad( cached );
14770 
14771  scope.manager.itemEnd( url );
14772 
14773  }, 0 );
14774 
14775  } else {
14776 
14777  scope.manager.itemEnd( url );
14778 
14779  }
14780 
14781  return cached;
14782 
14783  }
14784 
14785  var image = document.createElement( 'img' );
14786 
14787  image.addEventListener( 'load', function ( event ) {
14788 
14789  THREE.Cache.add( url, this );
14790 
14791  if ( onLoad ) onLoad( this );
14792 
14793  scope.manager.itemEnd( url );
14794 
14795  }, false );
14796 
14797  if ( onProgress !== undefined ) {
14798 
14799  image.addEventListener( 'progress', function ( event ) {
14800 
14801  onProgress( event );
14802 
14803  }, false );
14804 
14805  }
14806 
14807  image.addEventListener( 'error', function ( event ) {
14808 
14809  if ( onError ) onError( event );
14810 
14811  scope.manager.itemError( url );
14812 
14813  }, false );
14814 
14815  if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
14816 
14817  scope.manager.itemStart( url );
14818 
14819  image.src = url;
14820 
14821  return image;
14822 
14823  },
14824 
14825  setCrossOrigin: function ( value ) {
14826 
14827  this.crossOrigin = value;
14828 
14829  }
14830 
14831 };
14832 
14833 // File:src/loaders/JSONLoader.js
14834 
14840 THREE.JSONLoader = function ( manager ) {
14841 
14842  if ( typeof manager === 'boolean' ) {
14843 
14844  console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' );
14845  manager = undefined;
14846 
14847  }
14848 
14849  this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
14850 
14851  this.withCredentials = false;
14852 
14853 };
14854 
14855 THREE.JSONLoader.prototype = {
14856 
14857  constructor: THREE.JSONLoader,
14858 
14859  // Deprecated
14860 
14861  get statusDomElement () {
14862 
14863  if ( this._statusDomElement === undefined ) {
14864 
14865  this._statusDomElement = document.createElement( 'div' );
14866 
14867  }
14868 
14869  console.warn( 'THREE.JSONLoader: .statusDomElement has been removed.' );
14870  return this._statusDomElement;
14871 
14872  },
14873 
14874  load: function( url, onLoad, onProgress, onError ) {
14875 
14876  var scope = this;
14877 
14878  var texturePath = this.texturePath && ( typeof this.texturePath === "string" ) ? this.texturePath : THREE.Loader.prototype.extractUrlBase( url );
14879 
14880  var loader = new THREE.XHRLoader( this.manager );
14881  loader.setCrossOrigin( this.crossOrigin );
14882  loader.setWithCredentials( this.withCredentials );
14883  loader.load( url, function ( text ) {
14884 
14885  var json = JSON.parse( text );
14886  var metadata = json.metadata;
14887 
14888  if ( metadata !== undefined ) {
14889 
14890  if ( metadata.type === 'object' ) {
14891 
14892  console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
14893  return;
14894 
14895  }
14896 
14897  if ( metadata.type === 'scene' ) {
14898 
14899  console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.SceneLoader instead.' );
14900  return;
14901 
14902  }
14903 
14904  }
14905 
14906  var object = scope.parse( json, texturePath );
14907  onLoad( object.geometry, object.materials );
14908 
14909  } );
14910 
14911  },
14912 
14913  setCrossOrigin: function ( value ) {
14914 
14915  this.crossOrigin = value;
14916 
14917  },
14918 
14919  setTexturePath: function ( value ) {
14920 
14921  this.texturePath = value;
14922 
14923  },
14924 
14925  parse: function ( json, texturePath ) {
14926 
14927  var geometry = new THREE.Geometry(),
14928  scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
14929 
14930  parseModel( scale );
14931 
14932  parseSkin();
14933  parseMorphing( scale );
14934  parseAnimations();
14935 
14936  geometry.computeFaceNormals();
14937  geometry.computeBoundingSphere();
14938 
14939  function parseModel( scale ) {
14940 
14941  function isBitSet( value, position ) {
14942 
14943  return value & ( 1 << position );
14944 
14945  }
14946 
14947  var i, j, fi,
14948 
14949  offset, zLength,
14950 
14951  colorIndex, normalIndex, uvIndex, materialIndex,
14952 
14953  type,
14954  isQuad,
14955  hasMaterial,
14956  hasFaceVertexUv,
14957  hasFaceNormal, hasFaceVertexNormal,
14958  hasFaceColor, hasFaceVertexColor,
14959 
14960  vertex, face, faceA, faceB, hex, normal,
14961 
14962  uvLayer, uv, u, v,
14963 
14964  faces = json.faces,
14965  vertices = json.vertices,
14966  normals = json.normals,
14967  colors = json.colors,
14968 
14969  nUvLayers = 0;
14970 
14971  if ( json.uvs !== undefined ) {
14972 
14973  // disregard empty arrays
14974 
14975  for ( i = 0; i < json.uvs.length; i ++ ) {
14976 
14977  if ( json.uvs[ i ].length ) nUvLayers ++;
14978 
14979  }
14980 
14981  for ( i = 0; i < nUvLayers; i ++ ) {
14982 
14983  geometry.faceVertexUvs[ i ] = [];
14984 
14985  }
14986 
14987  }
14988 
14989  offset = 0;
14990  zLength = vertices.length;
14991 
14992  while ( offset < zLength ) {
14993 
14994  vertex = new THREE.Vector3();
14995 
14996  vertex.x = vertices[ offset ++ ] * scale;
14997  vertex.y = vertices[ offset ++ ] * scale;
14998  vertex.z = vertices[ offset ++ ] * scale;
14999 
15000  geometry.vertices.push( vertex );
15001 
15002  }
15003 
15004  offset = 0;
15005  zLength = faces.length;
15006 
15007  while ( offset < zLength ) {
15008 
15009  type = faces[ offset ++ ];
15010 
15011 
15012  isQuad = isBitSet( type, 0 );
15013  hasMaterial = isBitSet( type, 1 );
15014  hasFaceVertexUv = isBitSet( type, 3 );
15015  hasFaceNormal = isBitSet( type, 4 );
15016  hasFaceVertexNormal = isBitSet( type, 5 );
15017  hasFaceColor = isBitSet( type, 6 );
15018  hasFaceVertexColor = isBitSet( type, 7 );
15019 
15020  // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
15021 
15022  if ( isQuad ) {
15023 
15024  faceA = new THREE.Face3();
15025  faceA.a = faces[ offset ];
15026  faceA.b = faces[ offset + 1 ];
15027  faceA.c = faces[ offset + 3 ];
15028 
15029  faceB = new THREE.Face3();
15030  faceB.a = faces[ offset + 1 ];
15031  faceB.b = faces[ offset + 2 ];
15032  faceB.c = faces[ offset + 3 ];
15033 
15034  offset += 4;
15035 
15036  if ( hasMaterial ) {
15037 
15038  materialIndex = faces[ offset ++ ];
15039  faceA.materialIndex = materialIndex;
15040  faceB.materialIndex = materialIndex;
15041 
15042  }
15043 
15044  // to get face <=> uv index correspondence
15045 
15046  fi = geometry.faces.length;
15047 
15048  if ( hasFaceVertexUv ) {
15049 
15050  for ( i = 0; i < nUvLayers; i ++ ) {
15051 
15052  uvLayer = json.uvs[ i ];
15053 
15054  geometry.faceVertexUvs[ i ][ fi ] = [];
15055  geometry.faceVertexUvs[ i ][ fi + 1 ] = [];
15056 
15057  for ( j = 0; j < 4; j ++ ) {
15058 
15059  uvIndex = faces[ offset ++ ];
15060 
15061  u = uvLayer[ uvIndex * 2 ];
15062  v = uvLayer[ uvIndex * 2 + 1 ];
15063 
15064  uv = new THREE.Vector2( u, v );
15065 
15066  if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
15067  if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
15068 
15069  }
15070 
15071  }
15072 
15073  }
15074 
15075  if ( hasFaceNormal ) {
15076 
15077  normalIndex = faces[ offset ++ ] * 3;
15078 
15079  faceA.normal.set(
15080  normals[ normalIndex ++ ],
15081  normals[ normalIndex ++ ],
15082  normals[ normalIndex ]
15083  );
15084 
15085  faceB.normal.copy( faceA.normal );
15086 
15087  }
15088 
15089  if ( hasFaceVertexNormal ) {
15090 
15091  for ( i = 0; i < 4; i ++ ) {
15092 
15093  normalIndex = faces[ offset ++ ] * 3;
15094 
15095  normal = new THREE.Vector3(
15096  normals[ normalIndex ++ ],
15097  normals[ normalIndex ++ ],
15098  normals[ normalIndex ]
15099  );
15100 
15101 
15102  if ( i !== 2 ) faceA.vertexNormals.push( normal );
15103  if ( i !== 0 ) faceB.vertexNormals.push( normal );
15104 
15105  }
15106 
15107  }
15108 
15109 
15110  if ( hasFaceColor ) {
15111 
15112  colorIndex = faces[ offset ++ ];
15113  hex = colors[ colorIndex ];
15114 
15115  faceA.color.setHex( hex );
15116  faceB.color.setHex( hex );
15117 
15118  }
15119 
15120 
15121  if ( hasFaceVertexColor ) {
15122 
15123  for ( i = 0; i < 4; i ++ ) {
15124 
15125  colorIndex = faces[ offset ++ ];
15126  hex = colors[ colorIndex ];
15127 
15128  if ( i !== 2 ) faceA.vertexColors.push( new THREE.Color( hex ) );
15129  if ( i !== 0 ) faceB.vertexColors.push( new THREE.Color( hex ) );
15130 
15131  }
15132 
15133  }
15134 
15135  geometry.faces.push( faceA );
15136  geometry.faces.push( faceB );
15137 
15138  } else {
15139 
15140  face = new THREE.Face3();
15141  face.a = faces[ offset ++ ];
15142  face.b = faces[ offset ++ ];
15143  face.c = faces[ offset ++ ];
15144 
15145  if ( hasMaterial ) {
15146 
15147  materialIndex = faces[ offset ++ ];
15148  face.materialIndex = materialIndex;
15149 
15150  }
15151 
15152  // to get face <=> uv index correspondence
15153 
15154  fi = geometry.faces.length;
15155 
15156  if ( hasFaceVertexUv ) {
15157 
15158  for ( i = 0; i < nUvLayers; i ++ ) {
15159 
15160  uvLayer = json.uvs[ i ];
15161 
15162  geometry.faceVertexUvs[ i ][ fi ] = [];
15163 
15164  for ( j = 0; j < 3; j ++ ) {
15165 
15166  uvIndex = faces[ offset ++ ];
15167 
15168  u = uvLayer[ uvIndex * 2 ];
15169  v = uvLayer[ uvIndex * 2 + 1 ];
15170 
15171  uv = new THREE.Vector2( u, v );
15172 
15173  geometry.faceVertexUvs[ i ][ fi ].push( uv );
15174 
15175  }
15176 
15177  }
15178 
15179  }
15180 
15181  if ( hasFaceNormal ) {
15182 
15183  normalIndex = faces[ offset ++ ] * 3;
15184 
15185  face.normal.set(
15186  normals[ normalIndex ++ ],
15187  normals[ normalIndex ++ ],
15188  normals[ normalIndex ]
15189  );
15190 
15191  }
15192 
15193  if ( hasFaceVertexNormal ) {
15194 
15195  for ( i = 0; i < 3; i ++ ) {
15196 
15197  normalIndex = faces[ offset ++ ] * 3;
15198 
15199  normal = new THREE.Vector3(
15200  normals[ normalIndex ++ ],
15201  normals[ normalIndex ++ ],
15202  normals[ normalIndex ]
15203  );
15204 
15205  face.vertexNormals.push( normal );
15206 
15207  }
15208 
15209  }
15210 
15211 
15212  if ( hasFaceColor ) {
15213 
15214  colorIndex = faces[ offset ++ ];
15215  face.color.setHex( colors[ colorIndex ] );
15216 
15217  }
15218 
15219 
15220  if ( hasFaceVertexColor ) {
15221 
15222  for ( i = 0; i < 3; i ++ ) {
15223 
15224  colorIndex = faces[ offset ++ ];
15225  face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );
15226 
15227  }
15228 
15229  }
15230 
15231  geometry.faces.push( face );
15232 
15233  }
15234 
15235  }
15236 
15237  };
15238 
15239  function parseSkin() {
15240 
15241  var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
15242 
15243  if ( json.skinWeights ) {
15244 
15245  for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
15246 
15247  var x = json.skinWeights[ i ];
15248  var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
15249  var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
15250  var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
15251 
15252  geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
15253 
15254  }
15255 
15256  }
15257 
15258  if ( json.skinIndices ) {
15259 
15260  for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
15261 
15262  var a = json.skinIndices[ i ];
15263  var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
15264  var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
15265  var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
15266 
15267  geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
15268 
15269  }
15270 
15271  }
15272 
15273  geometry.bones = json.bones;
15274 
15275  if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
15276 
15277  console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
15278  geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
15279 
15280  }
15281 
15282  };
15283 
15284  function parseMorphing( scale ) {
15285 
15286  if ( json.morphTargets !== undefined ) {
15287 
15288  for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) {
15289 
15290  geometry.morphTargets[ i ] = {};
15291  geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
15292  geometry.morphTargets[ i ].vertices = [];
15293 
15294  var dstVertices = geometry.morphTargets[ i ].vertices;
15295  var srcVertices = json.morphTargets[ i ].vertices;
15296 
15297  for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
15298 
15299  var vertex = new THREE.Vector3();
15300  vertex.x = srcVertices[ v ] * scale;
15301  vertex.y = srcVertices[ v + 1 ] * scale;
15302  vertex.z = srcVertices[ v + 2 ] * scale;
15303 
15304  dstVertices.push( vertex );
15305 
15306  }
15307 
15308  }
15309 
15310  }
15311 
15312  if ( json.morphColors !== undefined && json.morphColors.length > 0 ) {
15313 
15314  console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' );
15315 
15316  var faces = geometry.faces;
15317  var morphColors = json.morphColors[ 0 ].colors;
15318 
15319  for ( var i = 0, l = faces.length; i < l; i ++ ) {
15320 
15321  faces[ i ].color.fromArray( morphColors, i * 3 );
15322 
15323  }
15324 
15325  }
15326 
15327  }
15328 
15329  function parseAnimations() {
15330 
15331  var outputAnimations = [];
15332 
15333  // parse old style Bone/Hierarchy animations
15334  var animations = [];
15335  if ( json.animation !== undefined ) {
15336  animations.push( json.animation );
15337  }
15338  if ( json.animations !== undefined ) {
15339  if ( json.animations.length ) {
15340  animations = animations.concat( json.animations );
15341  } else {
15342  animations.push( json.animations );
15343  }
15344  }
15345 
15346  for ( var i = 0; i < animations.length; i ++ ) {
15347 
15348  var clip = THREE.AnimationClip.parseAnimation( animations[i], geometry.bones );
15349  if ( clip ) outputAnimations.push( clip );
15350 
15351  }
15352 
15353  // parse implicit morph animations
15354  if ( geometry.morphTargets ) {
15355 
15356  // TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary.
15357  var morphAnimationClips = THREE.AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 );
15358  outputAnimations = outputAnimations.concat( morphAnimationClips );
15359 
15360  }
15361 
15362  if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations;
15363 
15364  };
15365 
15366  if ( json.materials === undefined || json.materials.length === 0 ) {
15367 
15368  return { geometry: geometry };
15369 
15370  } else {
15371 
15372  var materials = THREE.Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin );
15373 
15374  return { geometry: geometry, materials: materials };
15375 
15376  }
15377 
15378  }
15379 
15380 };
15381 
15382 // File:src/loaders/LoadingManager.js
15383 
15388 THREE.LoadingManager = function ( onLoad, onProgress, onError ) {
15389 
15390  var scope = this;
15391 
15392  var isLoading = false, itemsLoaded = 0, itemsTotal = 0;
15393 
15394  this.onStart = undefined;
15395  this.onLoad = onLoad;
15396  this.onProgress = onProgress;
15397  this.onError = onError;
15398 
15399  this.itemStart = function ( url ) {
15400 
15401  itemsTotal ++;
15402 
15403  if ( isLoading === false ) {
15404 
15405  if ( scope.onStart !== undefined ) {
15406 
15407  scope.onStart( url, itemsLoaded, itemsTotal );
15408 
15409  }
15410 
15411  }
15412 
15413  isLoading = true;
15414 
15415  };
15416 
15417  this.itemEnd = function ( url ) {
15418 
15419  itemsLoaded ++;
15420 
15421  if ( scope.onProgress !== undefined ) {
15422 
15423  scope.onProgress( url, itemsLoaded, itemsTotal );
15424 
15425  }
15426 
15427  if ( itemsLoaded === itemsTotal ) {
15428 
15429  isLoading = false;
15430 
15431  if ( scope.onLoad !== undefined ) {
15432 
15433  scope.onLoad();
15434 
15435  }
15436 
15437  }
15438 
15439  };
15440 
15441  this.itemError = function ( url ) {
15442 
15443  if ( scope.onError !== undefined ) {
15444 
15445  scope.onError( url );
15446 
15447  }
15448 
15449  };
15450 
15451 };
15452 
15453 THREE.DefaultLoadingManager = new THREE.LoadingManager();
15454 
15455 // File:src/loaders/BufferGeometryLoader.js
15456 
15461 THREE.BufferGeometryLoader = function ( manager ) {
15462 
15463  this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
15464 
15465 };
15466 
15467 THREE.BufferGeometryLoader.prototype = {
15468 
15469  constructor: THREE.BufferGeometryLoader,
15470 
15471  load: function ( url, onLoad, onProgress, onError ) {
15472 
15473  var scope = this;
15474 
15475  var loader = new THREE.XHRLoader( scope.manager );
15476  loader.setCrossOrigin( this.crossOrigin );
15477  loader.load( url, function ( text ) {
15478 
15479  onLoad( scope.parse( JSON.parse( text ) ) );
15480 
15481  }, onProgress, onError );
15482 
15483  },
15484 
15485  setCrossOrigin: function ( value ) {
15486 
15487  this.crossOrigin = value;
15488 
15489  },
15490 
15491  parse: function ( json ) {
15492 
15493  var geometry = new THREE.BufferGeometry();
15494 
15495  var index = json.data.index;
15496 
15497  if ( index !== undefined ) {
15498 
15499  var typedArray = new self[ index.type ]( index.array );
15500  geometry.setIndex( new THREE.BufferAttribute( typedArray, 1 ) );
15501 
15502  }
15503 
15504  var attributes = json.data.attributes;
15505 
15506  for ( var key in attributes ) {
15507 
15508  var attribute = attributes[ key ];
15509  var typedArray = new self[ attribute.type ]( attribute.array );
15510 
15511  geometry.addAttribute( key, new THREE.BufferAttribute( typedArray, attribute.itemSize ) );
15512 
15513  }
15514 
15515  var groups = json.data.groups || json.data.drawcalls || json.data.offsets;
15516 
15517  if ( groups !== undefined ) {
15518 
15519  for ( var i = 0, n = groups.length; i !== n; ++ i ) {
15520 
15521  var group = groups[ i ];
15522 
15523  geometry.addGroup( group.start, group.count );
15524 
15525  }
15526 
15527  }
15528 
15529  var boundingSphere = json.data.boundingSphere;
15530 
15531  if ( boundingSphere !== undefined ) {
15532 
15533  var center = new THREE.Vector3();
15534 
15535  if ( boundingSphere.center !== undefined ) {
15536 
15537  center.fromArray( boundingSphere.center );
15538 
15539  }
15540 
15541  geometry.boundingSphere = new THREE.Sphere( center, boundingSphere.radius );
15542 
15543  }
15544 
15545  return geometry;
15546 
15547  }
15548 
15549 };
15550 
15551 // File:src/loaders/MaterialLoader.js
15552 
15557 THREE.MaterialLoader = function ( manager ) {
15558 
15559  this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
15560  this.textures = {};
15561 
15562 };
15563 
15564 THREE.MaterialLoader.prototype = {
15565 
15566  constructor: THREE.MaterialLoader,
15567 
15568  load: function ( url, onLoad, onProgress, onError ) {
15569 
15570  var scope = this;
15571 
15572  var loader = new THREE.XHRLoader( scope.manager );
15573  loader.setCrossOrigin( this.crossOrigin );
15574  loader.load( url, function ( text ) {
15575 
15576  onLoad( scope.parse( JSON.parse( text ) ) );
15577 
15578  }, onProgress, onError );
15579 
15580  },
15581 
15582  setCrossOrigin: function ( value ) {
15583 
15584  this.crossOrigin = value;
15585 
15586  },
15587 
15588  setTextures: function ( value ) {
15589 
15590  this.textures = value;
15591 
15592  },
15593 
15594  getTexture: function ( name ) {
15595 
15596  var textures = this.textures;
15597 
15598  if ( textures[ name ] === undefined ) {
15599 
15600  console.warn( 'THREE.MaterialLoader: Undefined texture', name );
15601 
15602  }
15603 
15604  return textures[ name ];
15605 
15606  },
15607 
15608  parse: function ( json ) {
15609 
15610  var material = new THREE[ json.type ];
15611  material.uuid = json.uuid;
15612 
15613  if ( json.name !== undefined ) material.name = json.name;
15614  if ( json.color !== undefined ) material.color.setHex( json.color );
15615  if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive );
15616  if ( json.specular !== undefined ) material.specular.setHex( json.specular );
15617  if ( json.shininess !== undefined ) material.shininess = json.shininess;
15618  if ( json.uniforms !== undefined ) material.uniforms = json.uniforms;
15619  if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
15620  if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
15621  if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors;
15622  if ( json.shading !== undefined ) material.shading = json.shading;
15623  if ( json.blending !== undefined ) material.blending = json.blending;
15624  if ( json.side !== undefined ) material.side = json.side;
15625  if ( json.opacity !== undefined ) material.opacity = json.opacity;
15626  if ( json.transparent !== undefined ) material.transparent = json.transparent;
15627  if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
15628  if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
15629  if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
15630  if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
15631  if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
15632 
15633  // for PointsMaterial
15634  if ( json.size !== undefined ) material.size = json.size;
15635  if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
15636 
15637  // maps
15638 
15639  if ( json.map !== undefined ) material.map = this.getTexture( json.map );
15640 
15641  if ( json.alphaMap !== undefined ) {
15642 
15643  material.alphaMap = this.getTexture( json.alphaMap );
15644  material.transparent = true;
15645 
15646  }
15647 
15648  if ( json.bumpMap !== undefined ) material.bumpMap = this.getTexture( json.bumpMap );
15649  if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
15650 
15651  if ( json.normalMap !== undefined ) material.normalMap = this.getTexture( json.normalMap );
15652  if ( json.normalScale ) material.normalScale = new THREE.Vector2( json.normalScale, json.normalScale );
15653 
15654  if ( json.displacementMap !== undefined ) material.displacementMap = this.getTexture( json.displacementMap );
15655  if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
15656  if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
15657 
15658  if ( json.specularMap !== undefined ) material.specularMap = this.getTexture( json.specularMap );
15659 
15660  if ( json.envMap !== undefined ) {
15661 
15662  material.envMap = this.getTexture( json.envMap );
15663  material.combine = THREE.MultiplyOperation;
15664 
15665  }
15666 
15667  if ( json.reflectivity ) material.reflectivity = json.reflectivity;
15668 
15669  if ( json.lightMap !== undefined ) material.lightMap = this.getTexture( json.lightMap );
15670  if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
15671 
15672  if ( json.aoMap !== undefined ) material.aoMap = this.getTexture( json.aoMap );
15673  if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
15674 
15675  // MeshFaceMaterial
15676 
15677  if ( json.materials !== undefined ) {
15678 
15679  for ( var i = 0, l = json.materials.length; i < l; i ++ ) {
15680 
15681  material.materials.push( this.parse( json.materials[ i ] ) );
15682 
15683  }
15684 
15685  }
15686 
15687  return material;
15688 
15689  }
15690 
15691 };
15692 
15693 // File:src/loaders/ObjectLoader.js
15694 
15699 THREE.ObjectLoader = function ( manager ) {
15700 
15701  this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
15702  this.texturePath = '';
15703 
15704 };
15705 
15706 THREE.ObjectLoader.prototype = {
15707 
15708  constructor: THREE.ObjectLoader,
15709 
15710  load: function ( url, onLoad, onProgress, onError ) {
15711 
15712  if ( this.texturePath === '' ) {
15713 
15714  this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );
15715 
15716  }
15717 
15718  var scope = this;
15719 
15720  var loader = new THREE.XHRLoader( scope.manager );
15721  loader.setCrossOrigin( this.crossOrigin );
15722  loader.load( url, function ( text ) {
15723 
15724  scope.parse( JSON.parse( text ), onLoad );
15725 
15726  }, onProgress, onError );
15727 
15728  },
15729 
15730  setTexturePath: function ( value ) {
15731 
15732  this.texturePath = value;
15733 
15734  },
15735 
15736  setCrossOrigin: function ( value ) {
15737 
15738  this.crossOrigin = value;
15739 
15740  },
15741 
15742  parse: function ( json, onLoad ) {
15743 
15744  var geometries = this.parseGeometries( json.geometries );
15745 
15746  var images = this.parseImages( json.images, function () {
15747 
15748  if ( onLoad !== undefined ) onLoad( object );
15749 
15750  } );
15751 
15752  var textures = this.parseTextures( json.textures, images );
15753  var materials = this.parseMaterials( json.materials, textures );
15754 
15755  var object = this.parseObject( json.object, geometries, materials );
15756 
15757  if ( json.animations ) {
15758 
15759  object.animations = this.parseAnimations( json.animations );
15760 
15761  }
15762 
15763  if ( json.images === undefined || json.images.length === 0 ) {
15764 
15765  if ( onLoad !== undefined ) onLoad( object );
15766 
15767  }
15768 
15769  return object;
15770 
15771  },
15772 
15773  parseGeometries: function ( json ) {
15774 
15775  var geometries = {};
15776 
15777  if ( json !== undefined ) {
15778 
15779  var geometryLoader = new THREE.JSONLoader();
15780  var bufferGeometryLoader = new THREE.BufferGeometryLoader();
15781 
15782  for ( var i = 0, l = json.length; i < l; i ++ ) {
15783 
15784  var geometry;
15785  var data = json[ i ];
15786 
15787  switch ( data.type ) {
15788 
15789  case 'PlaneGeometry':
15790  case 'PlaneBufferGeometry':
15791 
15792  geometry = new THREE[ data.type ](
15793  data.width,
15794  data.height,
15795  data.widthSegments,
15796  data.heightSegments
15797  );
15798 
15799  break;
15800 
15801  case 'BoxGeometry':
15802  case 'CubeGeometry': // backwards compatible
15803 
15804  geometry = new THREE.BoxGeometry(
15805  data.width,
15806  data.height,
15807  data.depth,
15808  data.widthSegments,
15809  data.heightSegments,
15810  data.depthSegments
15811  );
15812 
15813  break;
15814 
15815  case 'CircleBufferGeometry':
15816 
15817  geometry = new THREE.CircleBufferGeometry(
15818  data.radius,
15819  data.segments,
15820  data.thetaStart,
15821  data.thetaLength
15822  );
15823 
15824  break;
15825 
15826  case 'CircleGeometry':
15827 
15828  geometry = new THREE.CircleGeometry(
15829  data.radius,
15830  data.segments,
15831  data.thetaStart,
15832  data.thetaLength
15833  );
15834 
15835  break;
15836 
15837  case 'CylinderGeometry':
15838 
15839  geometry = new THREE.CylinderGeometry(
15840  data.radiusTop,
15841  data.radiusBottom,
15842  data.height,
15843  data.radialSegments,
15844  data.heightSegments,
15845  data.openEnded,
15846  data.thetaStart,
15847  data.thetaLength
15848  );
15849 
15850  break;
15851 
15852  case 'SphereGeometry':
15853 
15854  geometry = new THREE.SphereGeometry(
15855  data.radius,
15856  data.widthSegments,
15857  data.heightSegments,
15858  data.phiStart,
15859  data.phiLength,
15860  data.thetaStart,
15861  data.thetaLength
15862  );
15863 
15864  break;
15865 
15866  case 'SphereBufferGeometry':
15867 
15868  geometry = new THREE.SphereBufferGeometry(
15869  data.radius,
15870  data.widthSegments,
15871  data.heightSegments,
15872  data.phiStart,
15873  data.phiLength,
15874  data.thetaStart,
15875  data.thetaLength
15876  );
15877 
15878  break;
15879 
15880  case 'DodecahedronGeometry':
15881 
15882  geometry = new THREE.DodecahedronGeometry(
15883  data.radius,
15884  data.detail
15885  );
15886 
15887  break;
15888 
15889  case 'IcosahedronGeometry':
15890 
15891  geometry = new THREE.IcosahedronGeometry(
15892  data.radius,
15893  data.detail
15894  );
15895 
15896  break;
15897 
15898  case 'OctahedronGeometry':
15899 
15900  geometry = new THREE.OctahedronGeometry(
15901  data.radius,
15902  data.detail
15903  );
15904 
15905  break;
15906 
15907  case 'TetrahedronGeometry':
15908 
15909  geometry = new THREE.TetrahedronGeometry(
15910  data.radius,
15911  data.detail
15912  );
15913 
15914  break;
15915 
15916  case 'RingGeometry':
15917 
15918  geometry = new THREE.RingGeometry(
15919  data.innerRadius,
15920  data.outerRadius,
15921  data.thetaSegments,
15922  data.phiSegments,
15923  data.thetaStart,
15924  data.thetaLength
15925  );
15926 
15927  break;
15928 
15929  case 'TorusGeometry':
15930 
15931  geometry = new THREE.TorusGeometry(
15932  data.radius,
15933  data.tube,
15934  data.radialSegments,
15935  data.tubularSegments,
15936  data.arc
15937  );
15938 
15939  break;
15940 
15941  case 'TorusKnotGeometry':
15942 
15943  geometry = new THREE.TorusKnotGeometry(
15944  data.radius,
15945  data.tube,
15946  data.radialSegments,
15947  data.tubularSegments,
15948  data.p,
15949  data.q,
15950  data.heightScale
15951  );
15952 
15953  break;
15954 
15955  case 'BufferGeometry':
15956 
15957  geometry = bufferGeometryLoader.parse( data );
15958 
15959  break;
15960 
15961  case 'Geometry':
15962 
15963  geometry = geometryLoader.parse( data.data, this.texturePath ).geometry;
15964 
15965  break;
15966 
15967  default:
15968 
15969  console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
15970 
15971  continue;
15972 
15973  }
15974 
15975  geometry.uuid = data.uuid;
15976 
15977  if ( data.name !== undefined ) geometry.name = data.name;
15978 
15979  geometries[ data.uuid ] = geometry;
15980 
15981  }
15982 
15983  }
15984 
15985  return geometries;
15986 
15987  },
15988 
15989  parseMaterials: function ( json, textures ) {
15990 
15991  var materials = {};
15992 
15993  if ( json !== undefined ) {
15994 
15995  var loader = new THREE.MaterialLoader();
15996  loader.setTextures( textures );
15997 
15998  for ( var i = 0, l = json.length; i < l; i ++ ) {
15999 
16000  var material = loader.parse( json[ i ] );
16001  materials[ material.uuid ] = material;
16002 
16003  }
16004 
16005  }
16006 
16007  return materials;
16008 
16009  },
16010 
16011  parseAnimations: function ( json ) {
16012 
16013  var animations = [];
16014 
16015  for ( var i = 0; i < json.length; i ++ ) {
16016 
16017  var clip = THREE.AnimationClip.parse( json[i] );
16018 
16019  animations.push( clip );
16020 
16021  }
16022 
16023  return animations;
16024 
16025  },
16026 
16027  parseImages: function ( json, onLoad ) {
16028 
16029  var scope = this;
16030  var images = {};
16031 
16032  function loadImage( url ) {
16033 
16034  scope.manager.itemStart( url );
16035 
16036  return loader.load( url, function () {
16037 
16038  scope.manager.itemEnd( url );
16039 
16040  } );
16041 
16042  }
16043 
16044  if ( json !== undefined && json.length > 0 ) {
16045 
16046  var manager = new THREE.LoadingManager( onLoad );
16047 
16048  var loader = new THREE.ImageLoader( manager );
16049  loader.setCrossOrigin( this.crossOrigin );
16050 
16051  for ( var i = 0, l = json.length; i < l; i ++ ) {
16052 
16053  var image = json[ i ];
16054  var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url;
16055 
16056  images[ image.uuid ] = loadImage( path );
16057 
16058  }
16059 
16060  }
16061 
16062  return images;
16063 
16064  },
16065 
16066  parseTextures: function ( json, images ) {
16067 
16068  function parseConstant( value ) {
16069 
16070  if ( typeof( value ) === 'number' ) return value;
16071 
16072  console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
16073 
16074  return THREE[ value ];
16075 
16076  }
16077 
16078  var textures = {};
16079 
16080  if ( json !== undefined ) {
16081 
16082  for ( var i = 0, l = json.length; i < l; i ++ ) {
16083 
16084  var data = json[ i ];
16085 
16086  if ( data.image === undefined ) {
16087 
16088  console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
16089 
16090  }
16091 
16092  if ( images[ data.image ] === undefined ) {
16093 
16094  console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
16095 
16096  }
16097 
16098  var texture = new THREE.Texture( images[ data.image ] );
16099  texture.needsUpdate = true;
16100 
16101  texture.uuid = data.uuid;
16102 
16103  if ( data.name !== undefined ) texture.name = data.name;
16104  if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping );
16105  if ( data.offset !== undefined ) texture.offset = new THREE.Vector2( data.offset[ 0 ], data.offset[ 1 ] );
16106  if ( data.repeat !== undefined ) texture.repeat = new THREE.Vector2( data.repeat[ 0 ], data.repeat[ 1 ] );
16107  if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter );
16108  if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter );
16109  if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
16110  if ( Array.isArray( data.wrap ) ) {
16111 
16112  texture.wrapS = parseConstant( data.wrap[ 0 ] );
16113  texture.wrapT = parseConstant( data.wrap[ 1 ] );
16114 
16115  }
16116 
16117  textures[ data.uuid ] = texture;
16118 
16119  }
16120 
16121  }
16122 
16123  return textures;
16124 
16125  },
16126 
16127  parseObject: function () {
16128 
16129  var matrix = new THREE.Matrix4();
16130 
16131  return function ( data, geometries, materials ) {
16132 
16133  var object;
16134 
16135  function getGeometry( name ) {
16136 
16137  if ( geometries[ name ] === undefined ) {
16138 
16139  console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
16140 
16141  }
16142 
16143  return geometries[ name ];
16144 
16145  }
16146 
16147  function getMaterial( name ) {
16148 
16149  if ( name === undefined ) return undefined;
16150 
16151  if ( materials[ name ] === undefined ) {
16152 
16153  console.warn( 'THREE.ObjectLoader: Undefined material', name );
16154 
16155  }
16156 
16157  return materials[ name ];
16158 
16159  }
16160 
16161  switch ( data.type ) {
16162 
16163  case 'Scene':
16164 
16165  object = new THREE.Scene();
16166 
16167  break;
16168 
16169  case 'PerspectiveCamera':
16170 
16171  object = new THREE.PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
16172 
16173  break;
16174 
16175  case 'OrthographicCamera':
16176 
16177  object = new THREE.OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
16178 
16179  break;
16180 
16181  case 'AmbientLight':
16182 
16183  object = new THREE.AmbientLight( data.color );
16184 
16185  break;
16186 
16187  case 'DirectionalLight':
16188 
16189  object = new THREE.DirectionalLight( data.color, data.intensity );
16190 
16191  break;
16192 
16193  case 'PointLight':
16194 
16195  object = new THREE.PointLight( data.color, data.intensity, data.distance, data.decay );
16196 
16197  break;
16198 
16199  case 'SpotLight':
16200 
16201  object = new THREE.SpotLight( data.color, data.intensity, data.distance, data.angle, data.exponent, data.decay );
16202 
16203  break;
16204 
16205  case 'HemisphereLight':
16206 
16207  object = new THREE.HemisphereLight( data.color, data.groundColor, data.intensity );
16208 
16209  break;
16210 
16211  case 'Mesh':
16212 
16213  object = new THREE.Mesh( getGeometry( data.geometry ), getMaterial( data.material ) );
16214 
16215  break;
16216 
16217  case 'LOD':
16218 
16219  object = new THREE.LOD();
16220 
16221  break;
16222 
16223  case 'Line':
16224 
16225  object = new THREE.Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
16226 
16227  break;
16228 
16229  case 'PointCloud':
16230  case 'Points':
16231 
16232  object = new THREE.Points( getGeometry( data.geometry ), getMaterial( data.material ) );
16233 
16234  break;
16235 
16236  case 'Sprite':
16237 
16238  object = new THREE.Sprite( getMaterial( data.material ) );
16239 
16240  break;
16241 
16242  case 'Group':
16243 
16244  object = new THREE.Group();
16245 
16246  break;
16247 
16248  default:
16249 
16250  object = new THREE.Object3D();
16251 
16252  }
16253 
16254  object.uuid = data.uuid;
16255 
16256  if ( data.name !== undefined ) object.name = data.name;
16257  if ( data.matrix !== undefined ) {
16258 
16259  matrix.fromArray( data.matrix );
16260  matrix.decompose( object.position, object.quaternion, object.scale );
16261 
16262  } else {
16263 
16264  if ( data.position !== undefined ) object.position.fromArray( data.position );
16265  if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
16266  if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
16267 
16268  }
16269 
16270  if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
16271  if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
16272 
16273  if ( data.visible !== undefined ) object.visible = data.visible;
16274  if ( data.userData !== undefined ) object.userData = data.userData;
16275 
16276  if ( data.children !== undefined ) {
16277 
16278  for ( var child in data.children ) {
16279 
16280  object.add( this.parseObject( data.children[ child ], geometries, materials ) );
16281 
16282  }
16283 
16284  }
16285 
16286  if ( data.type === 'LOD' ) {
16287 
16288  var levels = data.levels;
16289 
16290  for ( var l = 0; l < levels.length; l ++ ) {
16291 
16292  var level = levels[ l ];
16293  var child = object.getObjectByProperty( 'uuid', level.object );
16294 
16295  if ( child !== undefined ) {
16296 
16297  object.addLevel( child, level.distance );
16298 
16299  }
16300 
16301  }
16302 
16303  }
16304 
16305  return object;
16306 
16307  }
16308 
16309  }()
16310 
16311 };
16312 
16313 // File:src/loaders/TextureLoader.js
16314 
16319 THREE.TextureLoader = function ( manager ) {
16320 
16321  this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
16322 
16323 };
16324 
16325 THREE.TextureLoader.prototype = {
16326 
16327  constructor: THREE.TextureLoader,
16328 
16329  load: function ( url, onLoad, onProgress, onError ) {
16330 
16331  var texture = new THREE.Texture();
16332 
16333  var loader = new THREE.ImageLoader( this.manager );
16334  loader.setCrossOrigin( this.crossOrigin );
16335  loader.load( url, function ( image ) {
16336 
16337  texture.image = image;
16338  texture.needsUpdate = true;
16339 
16340  if ( onLoad !== undefined ) {
16341 
16342  onLoad( texture );
16343 
16344  }
16345 
16346  }, onProgress, onError );
16347 
16348  return texture;
16349 
16350  },
16351 
16352  setCrossOrigin: function ( value ) {
16353 
16354  this.crossOrigin = value;
16355 
16356  }
16357 
16358 };
16359 
16360 // File:src/loaders/CubeTextureLoader.js
16361 
16366 THREE.CubeTextureLoader = function ( manager ) {
16367 
16368  this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
16369 
16370 };
16371 
16372 THREE.CubeTextureLoader.prototype = {
16373 
16374  constructor: THREE.CubeTextureLoader,
16375 
16376  load: function ( urls, onLoad, onProgress, onError ) {
16377 
16378  var texture = new THREE.CubeTexture( [] );
16379 
16380  var loader = new THREE.ImageLoader();
16381  loader.setCrossOrigin( this.crossOrigin );
16382 
16383  var loaded = 0;
16384 
16385  function loadTexture( i ) {
16386 
16387  loader.load( urls[ i ], function ( image ) {
16388 
16389  texture.images[ i ] = image;
16390 
16391  loaded ++;
16392 
16393  if ( loaded === 6 ) {
16394 
16395  texture.needsUpdate = true;
16396 
16397  if ( onLoad ) onLoad( texture );
16398 
16399  }
16400 
16401  }, undefined, onError );
16402 
16403  }
16404 
16405  for ( var i = 0; i < urls.length; ++ i ) {
16406 
16407  loadTexture( i );
16408 
16409  }
16410 
16411  return texture;
16412 
16413  },
16414 
16415  setCrossOrigin: function ( value ) {
16416 
16417  this.crossOrigin = value;
16418 
16419  }
16420 
16421 };
16422 
16423 // File:src/loaders/BinaryTextureLoader.js
16424 
16431 THREE.DataTextureLoader = THREE.BinaryTextureLoader = function ( manager ) {
16432 
16433  this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
16434 
16435  // override in sub classes
16436  this._parser = null;
16437 
16438 };
16439 
16440 THREE.BinaryTextureLoader.prototype = {
16441 
16442  constructor: THREE.BinaryTextureLoader,
16443 
16444  load: function ( url, onLoad, onProgress, onError ) {
16445 
16446  var scope = this;
16447 
16448  var texture = new THREE.DataTexture();
16449 
16450  var loader = new THREE.XHRLoader( this.manager );
16451  loader.setCrossOrigin( this.crossOrigin );
16452  loader.setResponseType( 'arraybuffer' );
16453 
16454  loader.load( url, function ( buffer ) {
16455 
16456  var texData = scope._parser( buffer );
16457 
16458  if ( ! texData ) return;
16459 
16460  if ( undefined !== texData.image ) {
16461 
16462  texture.image = texData.image;
16463 
16464  } else if ( undefined !== texData.data ) {
16465 
16466  texture.image.width = texData.width;
16467  texture.image.height = texData.height;
16468  texture.image.data = texData.data;
16469 
16470  }
16471 
16472  texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : THREE.ClampToEdgeWrapping;
16473  texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : THREE.ClampToEdgeWrapping;
16474 
16475  texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : THREE.LinearFilter;
16476  texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : THREE.LinearMipMapLinearFilter;
16477 
16478  texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1;
16479 
16480  if ( undefined !== texData.format ) {
16481 
16482  texture.format = texData.format;
16483 
16484  }
16485  if ( undefined !== texData.type ) {
16486 
16487  texture.type = texData.type;
16488 
16489  }
16490 
16491  if ( undefined !== texData.mipmaps ) {
16492 
16493  texture.mipmaps = texData.mipmaps;
16494 
16495  }
16496 
16497  if ( 1 === texData.mipmapCount ) {
16498 
16499  texture.minFilter = THREE.LinearFilter;
16500 
16501  }
16502 
16503  texture.needsUpdate = true;
16504 
16505  if ( onLoad ) onLoad( texture, texData );
16506 
16507  }, onProgress, onError );
16508 
16509 
16510  return texture;
16511 
16512  },
16513 
16514  setCrossOrigin: function ( value ) {
16515 
16516  this.crossOrigin = value;
16517 
16518  }
16519 
16520 };
16521 
16522 // File:src/loaders/CompressedTextureLoader.js
16523 
16530 THREE.CompressedTextureLoader = function ( manager ) {
16531 
16532  this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
16533 
16534  // override in sub classes
16535  this._parser = null;
16536 
16537 };
16538 
16539 
16540 THREE.CompressedTextureLoader.prototype = {
16541 
16542  constructor: THREE.CompressedTextureLoader,
16543 
16544  load: function ( url, onLoad, onProgress, onError ) {
16545 
16546  var scope = this;
16547 
16548  var images = [];
16549 
16550  var texture = new THREE.CompressedTexture();
16551  texture.image = images;
16552 
16553  var loader = new THREE.XHRLoader( this.manager );
16554  loader.setCrossOrigin( this.crossOrigin );
16555  loader.setResponseType( 'arraybuffer' );
16556 
16557  if ( Array.isArray( url ) ) {
16558 
16559  var loaded = 0;
16560 
16561  var loadTexture = function ( i ) {
16562 
16563  loader.load( url[ i ], function ( buffer ) {
16564 
16565  var texDatas = scope._parser( buffer, true );
16566 
16567  images[ i ] = {
16568  width: texDatas.width,
16569  height: texDatas.height,
16570  format: texDatas.format,
16571  mipmaps: texDatas.mipmaps
16572  };
16573 
16574  loaded += 1;
16575 
16576  if ( loaded === 6 ) {
16577 
16578  if ( texDatas.mipmapCount === 1 )
16579  texture.minFilter = THREE.LinearFilter;
16580 
16581  texture.format = texDatas.format;
16582  texture.needsUpdate = true;
16583 
16584  if ( onLoad ) onLoad( texture );
16585 
16586  }
16587 
16588  }, onProgress, onError );
16589 
16590  };
16591 
16592  for ( var i = 0, il = url.length; i < il; ++ i ) {
16593 
16594  loadTexture( i );
16595 
16596  }
16597 
16598  } else {
16599 
16600  // compressed cubemap texture stored in a single DDS file
16601 
16602  loader.load( url, function ( buffer ) {
16603 
16604  var texDatas = scope._parser( buffer, true );
16605 
16606  if ( texDatas.isCubemap ) {
16607 
16608  var faces = texDatas.mipmaps.length / texDatas.mipmapCount;
16609 
16610  for ( var f = 0; f < faces; f ++ ) {
16611 
16612  images[ f ] = { mipmaps : [] };
16613 
16614  for ( var i = 0; i < texDatas.mipmapCount; i ++ ) {
16615 
16616  images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
16617  images[ f ].format = texDatas.format;
16618  images[ f ].width = texDatas.width;
16619  images[ f ].height = texDatas.height;
16620 
16621  }
16622 
16623  }
16624 
16625  } else {
16626 
16627  texture.image.width = texDatas.width;
16628  texture.image.height = texDatas.height;
16629  texture.mipmaps = texDatas.mipmaps;
16630 
16631  }
16632 
16633  if ( texDatas.mipmapCount === 1 ) {
16634 
16635  texture.minFilter = THREE.LinearFilter;
16636 
16637  }
16638 
16639  texture.format = texDatas.format;
16640  texture.needsUpdate = true;
16641 
16642  if ( onLoad ) onLoad( texture );
16643 
16644  }, onProgress, onError );
16645 
16646  }
16647 
16648  return texture;
16649 
16650  },
16651 
16652  setCrossOrigin: function ( value ) {
16653 
16654  this.crossOrigin = value;
16655 
16656  }
16657 
16658 };
16659 
16660 // File:src/materials/Material.js
16661 
16667 THREE.Material = function () {
16668 
16669  Object.defineProperty( this, 'id', { value: THREE.MaterialIdCount ++ } );
16670 
16671  this.uuid = THREE.Math.generateUUID();
16672 
16673  this.name = '';
16674  this.type = 'Material';
16675 
16676  this.side = THREE.FrontSide;
16677 
16678  this.opacity = 1;
16679  this.transparent = false;
16680 
16681  this.blending = THREE.NormalBlending;
16682 
16683  this.blendSrc = THREE.SrcAlphaFactor;
16684  this.blendDst = THREE.OneMinusSrcAlphaFactor;
16685  this.blendEquation = THREE.AddEquation;
16686  this.blendSrcAlpha = null;
16687  this.blendDstAlpha = null;
16688  this.blendEquationAlpha = null;
16689 
16690  this.depthFunc = THREE.LessEqualDepth;
16691  this.depthTest = true;
16692  this.depthWrite = true;
16693 
16694  this.colorWrite = true;
16695 
16696  this.precision = null; // override the renderer's default precision for this material
16697 
16698  this.polygonOffset = false;
16699  this.polygonOffsetFactor = 0;
16700  this.polygonOffsetUnits = 0;
16701 
16702  this.alphaTest = 0;
16703 
16704  this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer
16705 
16706  this.visible = true;
16707 
16708  this._needsUpdate = true;
16709 
16710 };
16711 
16712 THREE.Material.prototype = {
16713 
16714  constructor: THREE.Material,
16715 
16716  get needsUpdate () {
16717 
16718  return this._needsUpdate;
16719 
16720  },
16721 
16722  set needsUpdate ( value ) {
16723 
16724  if ( value === true ) this.update();
16725 
16726  this._needsUpdate = value;
16727 
16728  },
16729 
16730  setValues: function ( values ) {
16731 
16732  if ( values === undefined ) return;
16733 
16734  for ( var key in values ) {
16735 
16736  var newValue = values[ key ];
16737 
16738  if ( newValue === undefined ) {
16739 
16740  console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
16741  continue;
16742 
16743  }
16744 
16745  var currentValue = this[ key ];
16746 
16747  if ( currentValue === undefined ) {
16748 
16749  console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
16750  continue;
16751 
16752  }
16753 
16754  if ( currentValue instanceof THREE.Color ) {
16755 
16756  currentValue.set( newValue );
16757 
16758  } else if ( currentValue instanceof THREE.Vector3 && newValue instanceof THREE.Vector3 ) {
16759 
16760  currentValue.copy( newValue );
16761 
16762  } else if ( key === 'overdraw' ) {
16763 
16764  // ensure overdraw is backwards-compatible with legacy boolean type
16765  this[ key ] = Number( newValue );
16766 
16767  } else {
16768 
16769  this[ key ] = newValue;
16770 
16771  }
16772 
16773  }
16774 
16775  },
16776 
16777  toJSON: function ( meta ) {
16778 
16779  var data = {
16780  metadata: {
16781  version: 4.4,
16782  type: 'Material',
16783  generator: 'Material.toJSON'
16784  }
16785  };
16786 
16787  // standard Material serialization
16788  data.uuid = this.uuid;
16789  data.type = this.type;
16790  if ( this.name !== '' ) data.name = this.name;
16791 
16792  if ( this.color instanceof THREE.Color ) data.color = this.color.getHex();
16793  if ( this.emissive instanceof THREE.Color ) data.emissive = this.emissive.getHex();
16794  if ( this.specular instanceof THREE.Color ) data.specular = this.specular.getHex();
16795  if ( this.shininess !== undefined ) data.shininess = this.shininess;
16796 
16797  if ( this.map instanceof THREE.Texture ) data.map = this.map.toJSON( meta ).uuid;
16798  if ( this.alphaMap instanceof THREE.Texture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
16799  if ( this.lightMap instanceof THREE.Texture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
16800  if ( this.bumpMap instanceof THREE.Texture ) {
16801 
16802  data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
16803  data.bumpScale = this.bumpScale;
16804 
16805  }
16806  if ( this.normalMap instanceof THREE.Texture ) {
16807 
16808  data.normalMap = this.normalMap.toJSON( meta ).uuid;
16809  data.normalScale = this.normalScale; // Removed for now, causes issue in editor ui.js
16810 
16811  }
16812  if ( this.displacementMap instanceof THREE.Texture ) {
16813 
16814  data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
16815  data.displacementScale = this.displacementScale;
16816  data.displacementBias = this.displacementBias;
16817 
16818  }
16819  if ( this.specularMap instanceof THREE.Texture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
16820  if ( this.envMap instanceof THREE.Texture ) {
16821 
16822  data.envMap = this.envMap.toJSON( meta ).uuid;
16823  data.reflectivity = this.reflectivity; // Scale behind envMap
16824 
16825  }
16826 
16827  if ( this.size !== undefined ) data.size = this.size;
16828  if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
16829 
16830  if ( this.vertexColors !== undefined && this.vertexColors !== THREE.NoColors ) data.vertexColors = this.vertexColors;
16831  if ( this.shading !== undefined && this.shading !== THREE.SmoothShading ) data.shading = this.shading;
16832  if ( this.blending !== undefined && this.blending !== THREE.NormalBlending ) data.blending = this.blending;
16833  if ( this.side !== undefined && this.side !== THREE.FrontSide ) data.side = this.side;
16834 
16835  if ( this.opacity < 1 ) data.opacity = this.opacity;
16836  if ( this.transparent === true ) data.transparent = this.transparent;
16837  if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
16838  if ( this.wireframe === true ) data.wireframe = this.wireframe;
16839  if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
16840 
16841  return data;
16842 
16843  },
16844 
16845  clone: function () {
16846 
16847  return new this.constructor().copy( this );
16848 
16849  },
16850 
16851  copy: function ( source ) {
16852 
16853  this.name = source.name;
16854 
16855  this.side = source.side;
16856 
16857  this.opacity = source.opacity;
16858  this.transparent = source.transparent;
16859 
16860  this.blending = source.blending;
16861 
16862  this.blendSrc = source.blendSrc;
16863  this.blendDst = source.blendDst;
16864  this.blendEquation = source.blendEquation;
16865  this.blendSrcAlpha = source.blendSrcAlpha;
16866  this.blendDstAlpha = source.blendDstAlpha;
16867  this.blendEquationAlpha = source.blendEquationAlpha;
16868 
16869  this.depthFunc = source.depthFunc;
16870  this.depthTest = source.depthTest;
16871  this.depthWrite = source.depthWrite;
16872 
16873  this.precision = source.precision;
16874 
16875  this.polygonOffset = source.polygonOffset;
16876  this.polygonOffsetFactor = source.polygonOffsetFactor;
16877  this.polygonOffsetUnits = source.polygonOffsetUnits;
16878 
16879  this.alphaTest = source.alphaTest;
16880 
16881  this.overdraw = source.overdraw;
16882 
16883  this.visible = source.visible;
16884 
16885  return this;
16886 
16887  },
16888 
16889  update: function () {
16890 
16891  this.dispatchEvent( { type: 'update' } );
16892 
16893  },
16894 
16895  dispose: function () {
16896 
16897  this.dispatchEvent( { type: 'dispose' } );
16898 
16899  },
16900 
16901  // Deprecated
16902 
16903  get wrapAround () {
16904 
16905  console.warn( 'THREE.' + this.type + ': .wrapAround has been removed.' );
16906 
16907  },
16908 
16909  set wrapAround ( boolean ) {
16910 
16911  console.warn( 'THREE.' + this.type + ': .wrapAround has been removed.' );
16912 
16913  },
16914 
16915  get wrapRGB () {
16916 
16917  console.warn( 'THREE.' + this.type + ': .wrapRGB has been removed.' );
16918  return new THREE.Color();
16919 
16920  }
16921 
16922 };
16923 
16924 THREE.EventDispatcher.prototype.apply( THREE.Material.prototype );
16925 
16926 THREE.MaterialIdCount = 0;
16927 
16928 // File:src/materials/LineBasicMaterial.js
16929 
16952 THREE.LineBasicMaterial = function ( parameters ) {
16953 
16954  THREE.Material.call( this );
16955 
16956  this.type = 'LineBasicMaterial';
16957 
16958  this.color = new THREE.Color( 0xffffff );
16959 
16960  this.linewidth = 1;
16961  this.linecap = 'round';
16962  this.linejoin = 'round';
16963 
16964  this.vertexColors = THREE.NoColors;
16965 
16966  this.fog = true;
16967 
16968  this.setValues( parameters );
16969 
16970 };
16971 
16972 THREE.LineBasicMaterial.prototype = Object.create( THREE.Material.prototype );
16973 THREE.LineBasicMaterial.prototype.constructor = THREE.LineBasicMaterial;
16974 
16975 THREE.LineBasicMaterial.prototype.copy = function ( source ) {
16976 
16977  THREE.Material.prototype.copy.call( this, source );
16978 
16979  this.color.copy( source.color );
16980 
16981  this.linewidth = source.linewidth;
16982  this.linecap = source.linecap;
16983  this.linejoin = source.linejoin;
16984 
16985  this.vertexColors = source.vertexColors;
16986 
16987  this.fog = source.fog;
16988 
16989  return this;
16990 
16991 };
16992 
16993 // File:src/materials/LineDashedMaterial.js
16994 
17018 THREE.LineDashedMaterial = function ( parameters ) {
17019 
17020  THREE.Material.call( this );
17021 
17022  this.type = 'LineDashedMaterial';
17023 
17024  this.color = new THREE.Color( 0xffffff );
17025 
17026  this.linewidth = 1;
17027 
17028  this.scale = 1;
17029  this.dashSize = 3;
17030  this.gapSize = 1;
17031 
17032  this.vertexColors = false;
17033 
17034  this.fog = true;
17035 
17036  this.setValues( parameters );
17037 
17038 };
17039 
17040 THREE.LineDashedMaterial.prototype = Object.create( THREE.Material.prototype );
17041 THREE.LineDashedMaterial.prototype.constructor = THREE.LineDashedMaterial;
17042 
17043 THREE.LineDashedMaterial.prototype.copy = function ( source ) {
17044 
17045  THREE.Material.prototype.copy.call( this, source );
17046 
17047  this.color.copy( source.color );
17048 
17049  this.linewidth = source.linewidth;
17050 
17051  this.scale = source.scale;
17052  this.dashSize = source.dashSize;
17053  this.gapSize = source.gapSize;
17054 
17055  this.vertexColors = source.vertexColors;
17056 
17057  this.fog = source.fog;
17058 
17059  return this;
17060 
17061 };
17062 
17063 // File:src/materials/MeshBasicMaterial.js
17064 
17103 THREE.MeshBasicMaterial = function ( parameters ) {
17104 
17105  THREE.Material.call( this );
17106 
17107  this.type = 'MeshBasicMaterial';
17108 
17109  this.color = new THREE.Color( 0xffffff ); // emissive
17110 
17111  this.map = null;
17112 
17113  this.aoMap = null;
17114  this.aoMapIntensity = 1.0;
17115 
17116  this.specularMap = null;
17117 
17118  this.alphaMap = null;
17119 
17120  this.envMap = null;
17121  this.combine = THREE.MultiplyOperation;
17122  this.reflectivity = 1;
17123  this.refractionRatio = 0.98;
17124 
17125  this.fog = true;
17126 
17127  this.shading = THREE.SmoothShading;
17128 
17129  this.wireframe = false;
17130  this.wireframeLinewidth = 1;
17131  this.wireframeLinecap = 'round';
17132  this.wireframeLinejoin = 'round';
17133 
17134  this.vertexColors = THREE.NoColors;
17135 
17136  this.skinning = false;
17137  this.morphTargets = false;
17138 
17139  this.setValues( parameters );
17140 
17141 };
17142 
17143 THREE.MeshBasicMaterial.prototype = Object.create( THREE.Material.prototype );
17144 THREE.MeshBasicMaterial.prototype.constructor = THREE.MeshBasicMaterial;
17145 
17146 THREE.MeshBasicMaterial.prototype.copy = function ( source ) {
17147 
17148  THREE.Material.prototype.copy.call( this, source );
17149 
17150  this.color.copy( source.color );
17151 
17152  this.map = source.map;
17153 
17154  this.aoMap = source.aoMap;
17155  this.aoMapIntensity = source.aoMapIntensity;
17156 
17157  this.specularMap = source.specularMap;
17158 
17159  this.alphaMap = source.alphaMap;
17160 
17161  this.envMap = source.envMap;
17162  this.combine = source.combine;
17163  this.reflectivity = source.reflectivity;
17164  this.refractionRatio = source.refractionRatio;
17165 
17166  this.fog = source.fog;
17167 
17168  this.shading = source.shading;
17169 
17170  this.wireframe = source.wireframe;
17171  this.wireframeLinewidth = source.wireframeLinewidth;
17172  this.wireframeLinecap = source.wireframeLinecap;
17173  this.wireframeLinejoin = source.wireframeLinejoin;
17174 
17175  this.vertexColors = source.vertexColors;
17176 
17177  this.skinning = source.skinning;
17178  this.morphTargets = source.morphTargets;
17179 
17180  return this;
17181 
17182 };
17183 
17184 // File:src/materials/MeshLambertMaterial.js
17185 
17223 THREE.MeshLambertMaterial = function ( parameters ) {
17224 
17225  THREE.Material.call( this );
17226 
17227  this.type = 'MeshLambertMaterial';
17228 
17229  this.color = new THREE.Color( 0xffffff ); // diffuse
17230  this.emissive = new THREE.Color( 0x000000 );
17231 
17232  this.map = null;
17233 
17234  this.specularMap = null;
17235 
17236  this.alphaMap = null;
17237 
17238  this.envMap = null;
17239  this.combine = THREE.MultiplyOperation;
17240  this.reflectivity = 1;
17241  this.refractionRatio = 0.98;
17242 
17243  this.fog = true;
17244 
17245  this.wireframe = false;
17246  this.wireframeLinewidth = 1;
17247  this.wireframeLinecap = 'round';
17248  this.wireframeLinejoin = 'round';
17249 
17250  this.vertexColors = THREE.NoColors;
17251 
17252  this.skinning = false;
17253  this.morphTargets = false;
17254  this.morphNormals = false;
17255 
17256  this.setValues( parameters );
17257 
17258 };
17259 
17260 THREE.MeshLambertMaterial.prototype = Object.create( THREE.Material.prototype );
17261 THREE.MeshLambertMaterial.prototype.constructor = THREE.MeshLambertMaterial;
17262 
17263 THREE.MeshLambertMaterial.prototype.copy = function ( source ) {
17264 
17265  THREE.Material.prototype.copy.call( this, source );
17266 
17267  this.color.copy( source.color );
17268  this.emissive.copy( source.emissive );
17269 
17270  this.map = source.map;
17271 
17272  this.specularMap = source.specularMap;
17273 
17274  this.alphaMap = source.alphaMap;
17275 
17276  this.envMap = source.envMap;
17277  this.combine = source.combine;
17278  this.reflectivity = source.reflectivity;
17279  this.refractionRatio = source.refractionRatio;
17280 
17281  this.fog = source.fog;
17282 
17283  this.wireframe = source.wireframe;
17284  this.wireframeLinewidth = source.wireframeLinewidth;
17285  this.wireframeLinecap = source.wireframeLinecap;
17286  this.wireframeLinejoin = source.wireframeLinejoin;
17287 
17288  this.vertexColors = source.vertexColors;
17289 
17290  this.skinning = source.skinning;
17291  this.morphTargets = source.morphTargets;
17292  this.morphNormals = source.morphNormals;
17293 
17294  return this;
17295 
17296 };
17297 
17298 // File:src/materials/MeshPhongMaterial.js
17299 
17358 THREE.MeshPhongMaterial = function ( parameters ) {
17359 
17360  THREE.Material.call( this );
17361 
17362  this.type = 'MeshPhongMaterial';
17363 
17364  this.color = new THREE.Color( 0xffffff ); // diffuse
17365  this.emissive = new THREE.Color( 0x000000 );
17366  this.specular = new THREE.Color( 0x111111 );
17367  this.shininess = 30;
17368 
17369  this.metal = false;
17370 
17371  this.map = null;
17372 
17373  this.lightMap = null;
17374  this.lightMapIntensity = 1.0;
17375 
17376  this.aoMap = null;
17377  this.aoMapIntensity = 1.0;
17378 
17379  this.emissiveMap = null;
17380 
17381  this.bumpMap = null;
17382  this.bumpScale = 1;
17383 
17384  this.normalMap = null;
17385  this.normalScale = new THREE.Vector2( 1, 1 );
17386 
17387  this.displacementMap = null;
17388  this.displacementScale = 1;
17389  this.displacementBias = 0;
17390 
17391  this.specularMap = null;
17392 
17393  this.alphaMap = null;
17394 
17395  this.envMap = null;
17396  this.combine = THREE.MultiplyOperation;
17397  this.reflectivity = 1;
17398  this.refractionRatio = 0.98;
17399 
17400  this.fog = true;
17401 
17402  this.shading = THREE.SmoothShading;
17403 
17404  this.wireframe = false;
17405  this.wireframeLinewidth = 1;
17406  this.wireframeLinecap = 'round';
17407  this.wireframeLinejoin = 'round';
17408 
17409  this.vertexColors = THREE.NoColors;
17410 
17411  this.skinning = false;
17412  this.morphTargets = false;
17413  this.morphNormals = false;
17414 
17415  this.setValues( parameters );
17416 
17417 };
17418 
17419 THREE.MeshPhongMaterial.prototype = Object.create( THREE.Material.prototype );
17420 THREE.MeshPhongMaterial.prototype.constructor = THREE.MeshPhongMaterial;
17421 
17422 THREE.MeshPhongMaterial.prototype.copy = function ( source ) {
17423 
17424  THREE.Material.prototype.copy.call( this, source );
17425 
17426  this.color.copy( source.color );
17427  this.emissive.copy( source.emissive );
17428  this.specular.copy( source.specular );
17429  this.shininess = source.shininess;
17430 
17431  this.metal = source.metal;
17432 
17433  this.map = source.map;
17434 
17435  this.lightMap = source.lightMap;
17436  this.lightMapIntensity = source.lightMapIntensity;
17437 
17438  this.aoMap = source.aoMap;
17439  this.aoMapIntensity = source.aoMapIntensity;
17440 
17441  this.emissiveMap = source.emissiveMap;
17442 
17443  this.bumpMap = source.bumpMap;
17444  this.bumpScale = source.bumpScale;
17445 
17446  this.normalMap = source.normalMap;
17447  this.normalScale.copy( source.normalScale );
17448 
17449  this.displacementMap = source.displacementMap;
17450  this.displacementScale = source.displacementScale;
17451  this.displacementBias = source.displacementBias;
17452 
17453  this.specularMap = source.specularMap;
17454 
17455  this.alphaMap = source.alphaMap;
17456 
17457  this.envMap = source.envMap;
17458  this.combine = source.combine;
17459  this.reflectivity = source.reflectivity;
17460  this.refractionRatio = source.refractionRatio;
17461 
17462  this.fog = source.fog;
17463 
17464  this.shading = source.shading;
17465 
17466  this.wireframe = source.wireframe;
17467  this.wireframeLinewidth = source.wireframeLinewidth;
17468  this.wireframeLinecap = source.wireframeLinecap;
17469  this.wireframeLinejoin = source.wireframeLinejoin;
17470 
17471  this.vertexColors = source.vertexColors;
17472 
17473  this.skinning = source.skinning;
17474  this.morphTargets = source.morphTargets;
17475  this.morphNormals = source.morphNormals;
17476 
17477  return this;
17478 
17479 };
17480 
17481 // File:src/materials/MeshDepthMaterial.js
17482 
17499 THREE.MeshDepthMaterial = function ( parameters ) {
17500 
17501  THREE.Material.call( this );
17502 
17503  this.type = 'MeshDepthMaterial';
17504 
17505  this.morphTargets = false;
17506  this.wireframe = false;
17507  this.wireframeLinewidth = 1;
17508 
17509  this.setValues( parameters );
17510 
17511 };
17512 
17513 THREE.MeshDepthMaterial.prototype = Object.create( THREE.Material.prototype );
17514 THREE.MeshDepthMaterial.prototype.constructor = THREE.MeshDepthMaterial;
17515 
17516 THREE.MeshDepthMaterial.prototype.copy = function ( source ) {
17517 
17518  THREE.Material.prototype.copy.call( this, source );
17519 
17520  this.wireframe = source.wireframe;
17521  this.wireframeLinewidth = source.wireframeLinewidth;
17522 
17523  return this;
17524 
17525 };
17526 
17527 // File:src/materials/MeshNormalMaterial.js
17528 
17545 THREE.MeshNormalMaterial = function ( parameters ) {
17546 
17547  THREE.Material.call( this, parameters );
17548 
17549  this.type = 'MeshNormalMaterial';
17550 
17551  this.wireframe = false;
17552  this.wireframeLinewidth = 1;
17553 
17554  this.morphTargets = false;
17555 
17556  this.setValues( parameters );
17557 
17558 };
17559 
17560 THREE.MeshNormalMaterial.prototype = Object.create( THREE.Material.prototype );
17561 THREE.MeshNormalMaterial.prototype.constructor = THREE.MeshNormalMaterial;
17562 
17563 THREE.MeshNormalMaterial.prototype.copy = function ( source ) {
17564 
17565  THREE.Material.prototype.copy.call( this, source );
17566 
17567  this.wireframe = source.wireframe;
17568  this.wireframeLinewidth = source.wireframeLinewidth;
17569 
17570  return this;
17571 
17572 };
17573 
17574 // File:src/materials/MultiMaterial.js
17575 
17580 THREE.MultiMaterial = function ( materials ) {
17581 
17582  this.uuid = THREE.Math.generateUUID();
17583 
17584  this.type = 'MultiMaterial';
17585 
17586  this.materials = materials instanceof Array ? materials : [];
17587 
17588  this.visible = true;
17589 
17590 };
17591 
17592 THREE.MultiMaterial.prototype = {
17593 
17594  constructor: THREE.MultiMaterial,
17595 
17596  toJSON: function () {
17597 
17598  var output = {
17599  metadata: {
17600  version: 4.2,
17601  type: 'material',
17602  generator: 'MaterialExporter'
17603  },
17604  uuid: this.uuid,
17605  type: this.type,
17606  materials: []
17607  };
17608 
17609  for ( var i = 0, l = this.materials.length; i < l; i ++ ) {
17610 
17611  output.materials.push( this.materials[ i ].toJSON() );
17612 
17613  }
17614 
17615  output.visible = this.visible;
17616 
17617  return output;
17618 
17619  },
17620 
17621  clone: function () {
17622 
17623  var material = new this.constructor();
17624 
17625  for ( var i = 0; i < this.materials.length; i ++ ) {
17626 
17627  material.materials.push( this.materials[ i ].clone() );
17628 
17629  }
17630 
17631  material.visible = this.visible;
17632 
17633  return material;
17634 
17635  }
17636 
17637 };
17638 
17639 // backwards compatibility
17640 
17641 THREE.MeshFaceMaterial = THREE.MultiMaterial;
17642 
17643 // File:src/materials/PointsMaterial.js
17644 
17667 THREE.PointsMaterial = function ( parameters ) {
17668 
17669  THREE.Material.call( this );
17670 
17671  this.type = 'PointsMaterial';
17672 
17673  this.color = new THREE.Color( 0xffffff );
17674 
17675  this.map = null;
17676 
17677  this.size = 1;
17678  this.sizeAttenuation = true;
17679 
17680  this.vertexColors = THREE.NoColors;
17681 
17682  this.fog = true;
17683 
17684  this.setValues( parameters );
17685 
17686 };
17687 
17688 THREE.PointsMaterial.prototype = Object.create( THREE.Material.prototype );
17689 THREE.PointsMaterial.prototype.constructor = THREE.PointsMaterial;
17690 
17691 THREE.PointsMaterial.prototype.copy = function ( source ) {
17692 
17693  THREE.Material.prototype.copy.call( this, source );
17694 
17695  this.color.copy( source.color );
17696 
17697  this.map = source.map;
17698 
17699  this.size = source.size;
17700  this.sizeAttenuation = source.sizeAttenuation;
17701 
17702  this.vertexColors = source.vertexColors;
17703 
17704  this.fog = source.fog;
17705 
17706  return this;
17707 
17708 };
17709 
17710 // backwards compatibility
17711 
17712 THREE.PointCloudMaterial = function ( parameters ) {
17713 
17714  console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );
17715  return new THREE.PointsMaterial( parameters );
17716 
17717 };
17718 
17719 THREE.ParticleBasicMaterial = function ( parameters ) {
17720 
17721  console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );
17722  return new THREE.PointsMaterial( parameters );
17723 
17724 };
17725 
17726 THREE.ParticleSystemMaterial = function ( parameters ) {
17727 
17728  console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );
17729  return new THREE.PointsMaterial( parameters );
17730 
17731 };
17732 
17733 // File:src/materials/ShaderMaterial.js
17734 
17765 THREE.ShaderMaterial = function ( parameters ) {
17766 
17767  THREE.Material.call( this );
17768 
17769  this.type = 'ShaderMaterial';
17770 
17771  this.defines = {};
17772  this.uniforms = {};
17773 
17774  this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}';
17775  this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}';
17776 
17777  this.shading = THREE.SmoothShading;
17778 
17779  this.linewidth = 1;
17780 
17781  this.wireframe = false;
17782  this.wireframeLinewidth = 1;
17783 
17784  this.fog = false; // set to use scene fog
17785 
17786  this.lights = false; // set to use scene lights
17787 
17788  this.vertexColors = THREE.NoColors; // set to use "color" attribute stream
17789 
17790  this.skinning = false; // set to use skinning attribute streams
17791 
17792  this.morphTargets = false; // set to use morph targets
17793  this.morphNormals = false; // set to use morph normals
17794 
17795  this.derivatives = false; // set to use derivatives
17796 
17797  // When rendered geometry doesn't include these attributes but the material does,
17798  // use these default values in WebGL. This avoids errors when buffer data is missing.
17799  this.defaultAttributeValues = {
17800  'color': [ 1, 1, 1 ],
17801  'uv': [ 0, 0 ],
17802  'uv2': [ 0, 0 ]
17803  };
17804 
17805  this.index0AttributeName = undefined;
17806 
17807  if ( parameters !== undefined ) {
17808 
17809  if ( parameters.attributes !== undefined ) {
17810 
17811  console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
17812 
17813  }
17814 
17815  this.setValues( parameters );
17816 
17817  }
17818 
17819 };
17820 
17821 THREE.ShaderMaterial.prototype = Object.create( THREE.Material.prototype );
17822 THREE.ShaderMaterial.prototype.constructor = THREE.ShaderMaterial;
17823 
17824 THREE.ShaderMaterial.prototype.copy = function ( source ) {
17825 
17826  THREE.Material.prototype.copy.call( this, source );
17827 
17828  this.fragmentShader = source.fragmentShader;
17829  this.vertexShader = source.vertexShader;
17830 
17831  this.uniforms = THREE.UniformsUtils.clone( source.uniforms );
17832 
17833  this.attributes = source.attributes;
17834  this.defines = source.defines;
17835 
17836  this.shading = source.shading;
17837 
17838  this.wireframe = source.wireframe;
17839  this.wireframeLinewidth = source.wireframeLinewidth;
17840 
17841  this.fog = source.fog;
17842 
17843  this.lights = source.lights;
17844 
17845  this.vertexColors = source.vertexColors;
17846 
17847  this.skinning = source.skinning;
17848 
17849  this.morphTargets = source.morphTargets;
17850  this.morphNormals = source.morphNormals;
17851 
17852  this.derivatives = source.derivatives;
17853 
17854  return this;
17855 
17856 };
17857 
17858 THREE.ShaderMaterial.prototype.toJSON = function ( meta ) {
17859 
17860  var data = THREE.Material.prototype.toJSON.call( this, meta );
17861 
17862  data.uniforms = this.uniforms;
17863  data.attributes = this.attributes;
17864  data.vertexShader = this.vertexShader;
17865  data.fragmentShader = this.fragmentShader;
17866 
17867  return data;
17868 
17869 };
17870 
17871 // File:src/materials/RawShaderMaterial.js
17872 
17877 THREE.RawShaderMaterial = function ( parameters ) {
17878 
17879  THREE.ShaderMaterial.call( this, parameters );
17880 
17881  this.type = 'RawShaderMaterial';
17882 
17883 };
17884 
17885 THREE.RawShaderMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype );
17886 THREE.RawShaderMaterial.prototype.constructor = THREE.RawShaderMaterial;
17887 // File:src/materials/SpriteMaterial.js
17888 
17908 THREE.SpriteMaterial = function ( parameters ) {
17909 
17910  THREE.Material.call( this );
17911 
17912  this.type = 'SpriteMaterial';
17913 
17914  this.color = new THREE.Color( 0xffffff );
17915  this.map = null;
17916 
17917  this.rotation = 0;
17918 
17919  this.fog = false;
17920 
17921  // set parameters
17922 
17923  this.setValues( parameters );
17924 
17925 };
17926 
17927 THREE.SpriteMaterial.prototype = Object.create( THREE.Material.prototype );
17928 THREE.SpriteMaterial.prototype.constructor = THREE.SpriteMaterial;
17929 
17930 THREE.SpriteMaterial.prototype.copy = function ( source ) {
17931 
17932  THREE.Material.prototype.copy.call( this, source );
17933 
17934  this.color.copy( source.color );
17935  this.map = source.map;
17936 
17937  this.rotation = source.rotation;
17938 
17939  this.fog = source.fog;
17940 
17941  return this;
17942 
17943 };
17944 
17945 // File:src/textures/Texture.js
17946 
17953 THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
17954 
17955  Object.defineProperty( this, 'id', { value: THREE.TextureIdCount ++ } );
17956 
17957  this.uuid = THREE.Math.generateUUID();
17958 
17959  this.name = '';
17960  this.sourceFile = '';
17961 
17962  this.image = image !== undefined ? image : THREE.Texture.DEFAULT_IMAGE;
17963  this.mipmaps = [];
17964 
17965  this.mapping = mapping !== undefined ? mapping : THREE.Texture.DEFAULT_MAPPING;
17966 
17967  this.wrapS = wrapS !== undefined ? wrapS : THREE.ClampToEdgeWrapping;
17968  this.wrapT = wrapT !== undefined ? wrapT : THREE.ClampToEdgeWrapping;
17969 
17970  this.magFilter = magFilter !== undefined ? magFilter : THREE.LinearFilter;
17971  this.minFilter = minFilter !== undefined ? minFilter : THREE.LinearMipMapLinearFilter;
17972 
17973  this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
17974 
17975  this.format = format !== undefined ? format : THREE.RGBAFormat;
17976  this.type = type !== undefined ? type : THREE.UnsignedByteType;
17977 
17978  this.offset = new THREE.Vector2( 0, 0 );
17979  this.repeat = new THREE.Vector2( 1, 1 );
17980 
17981  this.generateMipmaps = true;
17982  this.premultiplyAlpha = false;
17983  this.flipY = true;
17984  this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
17985 
17986  this.version = 0;
17987  this.onUpdate = null;
17988 
17989 };
17990 
17991 THREE.Texture.DEFAULT_IMAGE = undefined;
17992 THREE.Texture.DEFAULT_MAPPING = THREE.UVMapping;
17993 
17994 THREE.Texture.prototype = {
17995 
17996  constructor: THREE.Texture,
17997 
17998  set needsUpdate ( value ) {
17999 
18000  if ( value === true ) this.version ++;
18001 
18002  },
18003 
18004  clone: function () {
18005 
18006  return new this.constructor().copy( this );
18007 
18008  },
18009 
18010  copy: function ( source ) {
18011 
18012  this.image = source.image;
18013  this.mipmaps = source.mipmaps.slice( 0 );
18014 
18015  this.mapping = source.mapping;
18016 
18017  this.wrapS = source.wrapS;
18018  this.wrapT = source.wrapT;
18019 
18020  this.magFilter = source.magFilter;
18021  this.minFilter = source.minFilter;
18022 
18023  this.anisotropy = source.anisotropy;
18024 
18025  this.format = source.format;
18026  this.type = source.type;
18027 
18028  this.offset.copy( source.offset );
18029  this.repeat.copy( source.repeat );
18030 
18031  this.generateMipmaps = source.generateMipmaps;
18032  this.premultiplyAlpha = source.premultiplyAlpha;
18033  this.flipY = source.flipY;
18034  this.unpackAlignment = source.unpackAlignment;
18035 
18036  return this;
18037 
18038  },
18039 
18040  toJSON: function ( meta ) {
18041 
18042  if ( meta.textures[ this.uuid ] !== undefined ) {
18043 
18044  return meta.textures[ this.uuid ];
18045 
18046  }
18047 
18048  function getDataURL( image ) {
18049 
18050  var canvas;
18051 
18052  if ( image.toDataURL !== undefined ) {
18053 
18054  canvas = image;
18055 
18056  } else {
18057 
18058  canvas = document.createElement( 'canvas' );
18059  canvas.width = image.width;
18060  canvas.height = image.height;
18061 
18062  canvas.getContext( '2d' ).drawImage( image, 0, 0, image.width, image.height );
18063 
18064  }
18065 
18066  if ( canvas.width > 2048 || canvas.height > 2048 ) {
18067 
18068  return canvas.toDataURL( 'image/jpeg', 0.6 );
18069 
18070  } else {
18071 
18072  return canvas.toDataURL( 'image/png' );
18073 
18074  }
18075 
18076  }
18077 
18078  var output = {
18079  metadata: {
18080  version: 4.4,
18081  type: 'Texture',
18082  generator: 'Texture.toJSON'
18083  },
18084 
18085  uuid: this.uuid,
18086  name: this.name,
18087 
18088  mapping: this.mapping,
18089 
18090  repeat: [ this.repeat.x, this.repeat.y ],
18091  offset: [ this.offset.x, this.offset.y ],
18092  wrap: [ this.wrapS, this.wrapT ],
18093 
18094  minFilter: this.minFilter,
18095  magFilter: this.magFilter,
18096  anisotropy: this.anisotropy
18097  };
18098 
18099  if ( this.image !== undefined ) {
18100 
18101  // TODO: Move to THREE.Image
18102 
18103  var image = this.image;
18104 
18105  if ( image.uuid === undefined ) {
18106 
18107  image.uuid = THREE.Math.generateUUID(); // UGH
18108 
18109  }
18110 
18111  if ( meta.images[ image.uuid ] === undefined ) {
18112 
18113  meta.images[ image.uuid ] = {
18114  uuid: image.uuid,
18115  url: getDataURL( image )
18116  };
18117 
18118  }
18119 
18120  output.image = image.uuid;
18121 
18122  }
18123 
18124  meta.textures[ this.uuid ] = output;
18125 
18126  return output;
18127 
18128  },
18129 
18130  dispose: function () {
18131 
18132  this.dispatchEvent( { type: 'dispose' } );
18133 
18134  },
18135 
18136  transformUv: function ( uv ) {
18137 
18138  if ( this.mapping !== THREE.UVMapping ) return;
18139 
18140  uv.multiply( this.repeat );
18141  uv.add( this.offset );
18142 
18143  if ( uv.x < 0 || uv.x > 1 ) {
18144 
18145  switch ( this.wrapS ) {
18146 
18147  case THREE.RepeatWrapping:
18148 
18149  uv.x = uv.x - Math.floor( uv.x );
18150  break;
18151 
18152  case THREE.ClampToEdgeWrapping:
18153 
18154  uv.x = uv.x < 0 ? 0 : 1;
18155  break;
18156 
18157  case THREE.MirroredRepeatWrapping:
18158 
18159  if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
18160 
18161  uv.x = Math.ceil( uv.x ) - uv.x;
18162 
18163  } else {
18164 
18165  uv.x = uv.x - Math.floor( uv.x );
18166 
18167  }
18168  break;
18169 
18170  }
18171 
18172  }
18173 
18174  if ( uv.y < 0 || uv.y > 1 ) {
18175 
18176  switch ( this.wrapT ) {
18177 
18178  case THREE.RepeatWrapping:
18179 
18180  uv.y = uv.y - Math.floor( uv.y );
18181  break;
18182 
18183  case THREE.ClampToEdgeWrapping:
18184 
18185  uv.y = uv.y < 0 ? 0 : 1;
18186  break;
18187 
18188  case THREE.MirroredRepeatWrapping:
18189 
18190  if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
18191 
18192  uv.y = Math.ceil( uv.y ) - uv.y;
18193 
18194  } else {
18195 
18196  uv.y = uv.y - Math.floor( uv.y );
18197 
18198  }
18199  break;
18200 
18201  }
18202 
18203  }
18204 
18205  if ( this.flipY ) {
18206 
18207  uv.y = 1 - uv.y;
18208 
18209  }
18210 
18211  }
18212 
18213 };
18214 
18215 THREE.EventDispatcher.prototype.apply( THREE.Texture.prototype );
18216 
18217 THREE.TextureIdCount = 0;
18218 
18219 // File:src/textures/CanvasTexture.js
18220 
18225 THREE.CanvasTexture = function ( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
18226 
18227  THREE.Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
18228 
18229  this.needsUpdate = true;
18230 
18231 };
18232 
18233 THREE.CanvasTexture.prototype = Object.create( THREE.Texture.prototype );
18234 THREE.CanvasTexture.prototype.constructor = THREE.CanvasTexture;
18235 
18236 // File:src/textures/CubeTexture.js
18237 
18242 THREE.CubeTexture = function ( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
18243 
18244  mapping = mapping !== undefined ? mapping : THREE.CubeReflectionMapping;
18245 
18246  THREE.Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
18247 
18248  this.images = images;
18249  this.flipY = false;
18250 
18251 };
18252 
18253 THREE.CubeTexture.prototype = Object.create( THREE.Texture.prototype );
18254 THREE.CubeTexture.prototype.constructor = THREE.CubeTexture;
18255 
18256 THREE.CubeTexture.prototype.copy = function ( source ) {
18257 
18258  THREE.Texture.prototype.copy.call( this, source );
18259 
18260  this.images = source.images;
18261 
18262  return this;
18263 
18264 };
18265 // File:src/textures/CompressedTexture.js
18266 
18271 THREE.CompressedTexture = function ( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy ) {
18272 
18273  THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
18274 
18275  this.image = { width: width, height: height };
18276  this.mipmaps = mipmaps;
18277 
18278  // no flipping for cube textures
18279  // (also flipping doesn't work for compressed textures )
18280 
18281  this.flipY = false;
18282 
18283  // can't generate mipmaps for compressed textures
18284  // mips must be embedded in DDS files
18285 
18286  this.generateMipmaps = false;
18287 
18288 };
18289 
18290 THREE.CompressedTexture.prototype = Object.create( THREE.Texture.prototype );
18291 THREE.CompressedTexture.prototype.constructor = THREE.CompressedTexture;
18292 
18293 // File:src/textures/DataTexture.js
18294 
18299 THREE.DataTexture = function ( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy ) {
18300 
18301  THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
18302 
18303  this.image = { data: data, width: width, height: height };
18304 
18305  this.magFilter = magFilter !== undefined ? magFilter : THREE.NearestFilter;
18306  this.minFilter = minFilter !== undefined ? minFilter : THREE.NearestFilter;
18307 
18308  this.flipY = false;
18309  this.generateMipmaps = false;
18310 
18311 };
18312 
18313 THREE.DataTexture.prototype = Object.create( THREE.Texture.prototype );
18314 THREE.DataTexture.prototype.constructor = THREE.DataTexture;
18315 
18316 // File:src/textures/VideoTexture.js
18317 
18322 THREE.VideoTexture = function ( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
18323 
18324  THREE.Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
18325 
18326  this.generateMipmaps = false;
18327 
18328  var scope = this;
18329 
18330  function update() {
18331 
18332  requestAnimationFrame( update );
18333 
18334  if ( video.readyState === video.HAVE_ENOUGH_DATA ) {
18335 
18336  scope.needsUpdate = true;
18337 
18338  }
18339 
18340  }
18341 
18342  update();
18343 
18344 };
18345 
18346 THREE.VideoTexture.prototype = Object.create( THREE.Texture.prototype );
18347 THREE.VideoTexture.prototype.constructor = THREE.VideoTexture;
18348 
18349 // File:src/objects/Group.js
18350 
18355 THREE.Group = function () {
18356 
18357  THREE.Object3D.call( this );
18358 
18359  this.type = 'Group';
18360 
18361 };
18362 
18363 THREE.Group.prototype = Object.create( THREE.Object3D.prototype );
18364 THREE.Group.prototype.constructor = THREE.Group;
18365 // File:src/objects/Points.js
18366 
18371 THREE.Points = function ( geometry, material ) {
18372 
18373  THREE.Object3D.call( this );
18374 
18375  this.type = 'Points';
18376 
18377  this.geometry = geometry !== undefined ? geometry : new THREE.Geometry();
18378  this.material = material !== undefined ? material : new THREE.PointsMaterial( { color: Math.random() * 0xffffff } );
18379 
18380 };
18381 
18382 THREE.Points.prototype = Object.create( THREE.Object3D.prototype );
18383 THREE.Points.prototype.constructor = THREE.Points;
18384 
18385 THREE.Points.prototype.raycast = ( function () {
18386 
18387  var inverseMatrix = new THREE.Matrix4();
18388  var ray = new THREE.Ray();
18389 
18390  return function raycast( raycaster, intersects ) {
18391 
18392  var object = this;
18393  var geometry = object.geometry;
18394  var threshold = raycaster.params.Points.threshold;
18395 
18396  inverseMatrix.getInverse( this.matrixWorld );
18397  ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
18398 
18399  if ( geometry.boundingBox !== null ) {
18400 
18401  if ( ray.isIntersectionBox( geometry.boundingBox ) === false ) {
18402 
18403  return;
18404 
18405  }
18406 
18407  }
18408 
18409  var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
18410  var localThresholdSq = localThreshold * localThreshold;
18411  var position = new THREE.Vector3();
18412 
18413  function testPoint( point, index ) {
18414 
18415  var rayPointDistanceSq = ray.distanceSqToPoint( point );
18416 
18417  if ( rayPointDistanceSq < localThresholdSq ) {
18418 
18419  var intersectPoint = ray.closestPointToPoint( point );
18420  intersectPoint.applyMatrix4( object.matrixWorld );
18421 
18422  var distance = raycaster.ray.origin.distanceTo( intersectPoint );
18423 
18424  if ( distance < raycaster.near || distance > raycaster.far ) return;
18425 
18426  intersects.push( {
18427 
18428  distance: distance,
18429  distanceToRay: Math.sqrt( rayPointDistanceSq ),
18430  point: intersectPoint.clone(),
18431  index: index,
18432  face: null,
18433  object: object
18434 
18435  } );
18436 
18437  }
18438 
18439  }
18440 
18441  if ( geometry instanceof THREE.BufferGeometry ) {
18442 
18443  var index = geometry.index;
18444  var attributes = geometry.attributes;
18445  var positions = attributes.position.array;
18446 
18447  if ( index !== null ) {
18448 
18449  var indices = index.array;
18450 
18451  for ( var i = 0, il = indices.length; i < il; i ++ ) {
18452 
18453  var a = indices[ i ];
18454 
18455  position.fromArray( positions, a * 3 );
18456 
18457  testPoint( position, a );
18458 
18459  }
18460 
18461  } else {
18462 
18463  for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
18464 
18465  position.fromArray( positions, i * 3 );
18466 
18467  testPoint( position, i );
18468 
18469  }
18470 
18471  }
18472 
18473  } else {
18474 
18475  var vertices = geometry.vertices;
18476 
18477  for ( var i = 0, l = vertices.length; i < l; i ++ ) {
18478 
18479  testPoint( vertices[ i ], i );
18480 
18481  }
18482 
18483  }
18484 
18485  };
18486 
18487 }() );
18488 
18489 THREE.Points.prototype.clone = function () {
18490 
18491  return new this.constructor( this.geometry, this.material ).copy( this );
18492 
18493 };
18494 
18495 // Backwards compatibility
18496 
18497 THREE.PointCloud = function ( geometry, material ) {
18498 
18499  console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );
18500  return new THREE.Points( geometry, material );
18501 
18502 };
18503 
18504 THREE.ParticleSystem = function ( geometry, material ) {
18505 
18506  console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );
18507  return new THREE.Points( geometry, material );
18508 
18509 };
18510 
18511 // File:src/objects/Line.js
18512 
18517 THREE.Line = function ( geometry, material, mode ) {
18518 
18519  if ( mode === 1 ) {
18520 
18521  console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' );
18522  return new THREE.LineSegments( geometry, material );
18523 
18524  }
18525 
18526  THREE.Object3D.call( this );
18527 
18528  this.type = 'Line';
18529 
18530  this.geometry = geometry !== undefined ? geometry : new THREE.Geometry();
18531  this.material = material !== undefined ? material : new THREE.LineBasicMaterial( { color: Math.random() * 0xffffff } );
18532 
18533 };
18534 
18535 THREE.Line.prototype = Object.create( THREE.Object3D.prototype );
18536 THREE.Line.prototype.constructor = THREE.Line;
18537 
18538 THREE.Line.prototype.raycast = ( function () {
18539 
18540  var inverseMatrix = new THREE.Matrix4();
18541  var ray = new THREE.Ray();
18542  var sphere = new THREE.Sphere();
18543 
18544  return function raycast( raycaster, intersects ) {
18545 
18546  var precision = raycaster.linePrecision;
18547  var precisionSq = precision * precision;
18548 
18549  var geometry = this.geometry;
18550 
18551  if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
18552 
18553  // Checking boundingSphere distance to ray
18554 
18555  sphere.copy( geometry.boundingSphere );
18556  sphere.applyMatrix4( this.matrixWorld );
18557 
18558  if ( raycaster.ray.isIntersectionSphere( sphere ) === false ) {
18559 
18560  return;
18561 
18562  }
18563 
18564  inverseMatrix.getInverse( this.matrixWorld );
18565  ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
18566 
18567  var vStart = new THREE.Vector3();
18568  var vEnd = new THREE.Vector3();
18569  var interSegment = new THREE.Vector3();
18570  var interRay = new THREE.Vector3();
18571  var step = this instanceof THREE.LineSegments ? 2 : 1;
18572 
18573  if ( geometry instanceof THREE.BufferGeometry ) {
18574 
18575  var index = geometry.index;
18576  var attributes = geometry.attributes;
18577 
18578  if ( index !== null ) {
18579 
18580  var indices = index.array;
18581  var positions = attributes.position.array;
18582 
18583  for ( var i = 0, l = indices.length - 1; i < l; i += step ) {
18584 
18585  var a = indices[ i ];
18586  var b = indices[ i + 1 ];
18587 
18588  vStart.fromArray( positions, a * 3 );
18589  vEnd.fromArray( positions, b * 3 );
18590 
18591  var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
18592 
18593  if ( distSq > precisionSq ) continue;
18594 
18595  interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
18596 
18597  var distance = raycaster.ray.origin.distanceTo( interRay );
18598 
18599  if ( distance < raycaster.near || distance > raycaster.far ) continue;
18600 
18601  intersects.push( {
18602 
18603  distance: distance,
18604  // What do we want? intersection point on the ray or on the segment??
18605  // point: raycaster.ray.at( distance ),
18606  point: interSegment.clone().applyMatrix4( this.matrixWorld ),
18607  index: i,
18608  face: null,
18609  faceIndex: null,
18610  object: this
18611 
18612  } );
18613 
18614  }
18615 
18616  } else {
18617 
18618  var positions = attributes.position.array;
18619 
18620  for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {
18621 
18622  vStart.fromArray( positions, 3 * i );
18623  vEnd.fromArray( positions, 3 * i + 3 );
18624 
18625  var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
18626 
18627  if ( distSq > precisionSq ) continue;
18628 
18629  interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
18630 
18631  var distance = raycaster.ray.origin.distanceTo( interRay );
18632 
18633  if ( distance < raycaster.near || distance > raycaster.far ) continue;
18634 
18635  intersects.push( {
18636 
18637  distance: distance,
18638  // What do we want? intersection point on the ray or on the segment??
18639  // point: raycaster.ray.at( distance ),
18640  point: interSegment.clone().applyMatrix4( this.matrixWorld ),
18641  index: i,
18642  face: null,
18643  faceIndex: null,
18644  object: this
18645 
18646  } );
18647 
18648  }
18649 
18650  }
18651 
18652  } else if ( geometry instanceof THREE.Geometry ) {
18653 
18654  var vertices = geometry.vertices;
18655  var nbVertices = vertices.length;
18656 
18657  for ( var i = 0; i < nbVertices - 1; i += step ) {
18658 
18659  var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
18660 
18661  if ( distSq > precisionSq ) continue;
18662 
18663  interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
18664 
18665  var distance = raycaster.ray.origin.distanceTo( interRay );
18666 
18667  if ( distance < raycaster.near || distance > raycaster.far ) continue;
18668 
18669  intersects.push( {
18670 
18671  distance: distance,
18672  // What do we want? intersection point on the ray or on the segment??
18673  // point: raycaster.ray.at( distance ),
18674  point: interSegment.clone().applyMatrix4( this.matrixWorld ),
18675  index: i,
18676  face: null,
18677  faceIndex: null,
18678  object: this
18679 
18680  } );
18681 
18682  }
18683 
18684  }
18685 
18686  };
18687 
18688 }() );
18689 
18690 THREE.Line.prototype.clone = function () {
18691 
18692  return new this.constructor( this.geometry, this.material ).copy( this );
18693 
18694 };
18695 
18696 // DEPRECATED
18697 
18698 THREE.LineStrip = 0;
18699 THREE.LinePieces = 1;
18700 
18701 // File:src/objects/LineSegments.js
18702 
18707 THREE.LineSegments = function ( geometry, material ) {
18708 
18709  THREE.Line.call( this, geometry, material );
18710 
18711  this.type = 'LineSegments';
18712 
18713 };
18714 
18715 THREE.LineSegments.prototype = Object.create( THREE.Line.prototype );
18716 THREE.LineSegments.prototype.constructor = THREE.LineSegments;
18717 
18718 // File:src/objects/Mesh.js
18719 
18727 THREE.Mesh = function ( geometry, material ) {
18728 
18729  THREE.Object3D.call( this );
18730 
18731  this.type = 'Mesh';
18732 
18733  this.geometry = geometry !== undefined ? geometry : new THREE.Geometry();
18734  this.material = material !== undefined ? material : new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } );
18735 
18736  this.updateMorphTargets();
18737 
18738 };
18739 
18740 THREE.Mesh.prototype = Object.create( THREE.Object3D.prototype );
18741 THREE.Mesh.prototype.constructor = THREE.Mesh;
18742 
18743 THREE.Mesh.prototype.updateMorphTargets = function () {
18744 
18745  if ( this.geometry.morphTargets !== undefined && this.geometry.morphTargets.length > 0 ) {
18746 
18747  this.morphTargetBase = - 1;
18748  this.morphTargetInfluences = [];
18749  this.morphTargetDictionary = {};
18750 
18751  for ( var m = 0, ml = this.geometry.morphTargets.length; m < ml; m ++ ) {
18752 
18753  this.morphTargetInfluences.push( 0 );
18754  this.morphTargetDictionary[ this.geometry.morphTargets[ m ].name ] = m;
18755 
18756  }
18757 
18758  }
18759 
18760 };
18761 
18762 THREE.Mesh.prototype.getMorphTargetIndexByName = function ( name ) {
18763 
18764  if ( this.morphTargetDictionary[ name ] !== undefined ) {
18765 
18766  return this.morphTargetDictionary[ name ];
18767 
18768  }
18769 
18770  console.warn( 'THREE.Mesh.getMorphTargetIndexByName: morph target ' + name + ' does not exist. Returning 0.' );
18771 
18772  return 0;
18773 
18774 };
18775 
18776 
18777 THREE.Mesh.prototype.raycast = ( function () {
18778 
18779  var inverseMatrix = new THREE.Matrix4();
18780  var ray = new THREE.Ray();
18781  var sphere = new THREE.Sphere();
18782 
18783  var vA = new THREE.Vector3();
18784  var vB = new THREE.Vector3();
18785  var vC = new THREE.Vector3();
18786 
18787  var tempA = new THREE.Vector3();
18788  var tempB = new THREE.Vector3();
18789  var tempC = new THREE.Vector3();
18790 
18791  var uvA = new THREE.Vector2();
18792  var uvB = new THREE.Vector2();
18793  var uvC = new THREE.Vector2();
18794 
18795  var barycoord = new THREE.Vector3();
18796 
18797  var intersectionPoint = new THREE.Vector3();
18798  var intersectionPointWorld = new THREE.Vector3();
18799 
18800  function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) {
18801 
18802  THREE.Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord );
18803 
18804  uv1.multiplyScalar( barycoord.x );
18805  uv2.multiplyScalar( barycoord.y );
18806  uv3.multiplyScalar( barycoord.z );
18807 
18808  uv1.add( uv2 ).add( uv3 );
18809 
18810  return uv1.clone();
18811 
18812  }
18813 
18814  function checkIntersection( object, raycaster, ray, pA, pB, pC, point ){
18815 
18816  var intersect;
18817  var material = object.material;
18818 
18819  if ( material.side === THREE.BackSide ) {
18820 
18821  intersect = ray.intersectTriangle( pC, pB, pA, true, point );
18822 
18823  } else {
18824 
18825  intersect = ray.intersectTriangle( pA, pB, pC, material.side !== THREE.DoubleSide, point );
18826 
18827  }
18828 
18829  if ( intersect === null ) return null;
18830 
18831  intersectionPointWorld.copy( point );
18832  intersectionPointWorld.applyMatrix4( object.matrixWorld );
18833 
18834  var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld );
18835 
18836  if ( distance < raycaster.near || distance > raycaster.far ) return null;
18837 
18838  return {
18839  distance: distance,
18840  point: intersectionPointWorld.clone(),
18841  object: object
18842  };
18843 
18844  }
18845 
18846  function checkBufferGeometryIntersection( object, raycaster, ray, positions, uvs, a, b, c ) {
18847 
18848  vA.fromArray( positions, a * 3 );
18849  vB.fromArray( positions, b * 3 );
18850  vC.fromArray( positions, c * 3 );
18851 
18852  var intersection = checkIntersection( object, raycaster, ray, vA, vB, vC, intersectionPoint );
18853 
18854  if ( intersection ) {
18855 
18856  if ( uvs ) {
18857 
18858  uvA.fromArray( uvs, a * 2 );
18859  uvB.fromArray( uvs, b * 2 );
18860  uvC.fromArray( uvs, c * 2 );
18861 
18862  intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC );
18863 
18864  }
18865 
18866  intersection.face = new THREE.Face3( a, b, c, THREE.Triangle.normal( vA, vB, vC ) );
18867  intersection.faceIndex = a;
18868 
18869  }
18870 
18871  return intersection;
18872 
18873  }
18874 
18875  return function raycast( raycaster, intersects ) {
18876 
18877  var geometry = this.geometry;
18878  var material = this.material;
18879 
18880  if ( material === undefined ) return;
18881 
18882  // Checking boundingSphere distance to ray
18883 
18884  if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
18885 
18886  var matrixWorld = this.matrixWorld;
18887 
18888  sphere.copy( geometry.boundingSphere );
18889  sphere.applyMatrix4( matrixWorld );
18890 
18891  if ( raycaster.ray.isIntersectionSphere( sphere ) === false ) return;
18892 
18893  // Check boundingBox before continuing
18894 
18895  inverseMatrix.getInverse( matrixWorld );
18896  ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
18897 
18898  if ( geometry.boundingBox !== null ) {
18899 
18900  if ( ray.isIntersectionBox( geometry.boundingBox ) === false ) return;
18901 
18902  }
18903 
18904  var uvs, intersection;
18905 
18906  if ( geometry instanceof THREE.BufferGeometry ) {
18907 
18908  var a, b, c;
18909  var index = geometry.index;
18910  var attributes = geometry.attributes;
18911  var positions = attributes.position.array;
18912 
18913  if ( attributes.uv !== undefined ){
18914 
18915  uvs = attributes.uv.array;
18916 
18917  }
18918 
18919  if ( index !== null ) {
18920 
18921  var indices = index.array;
18922 
18923  for ( var i = 0, l = indices.length; i < l; i += 3 ) {
18924 
18925  a = indices[ i ];
18926  b = indices[ i + 1 ];
18927  c = indices[ i + 2 ];
18928 
18929  intersection = checkBufferGeometryIntersection( this, raycaster, ray, positions, uvs, a, b, c );
18930 
18931  if ( intersection ) {
18932 
18933  intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics
18934  intersects.push( intersection );
18935 
18936  }
18937 
18938  }
18939 
18940  } else {
18941 
18942 
18943  for ( var i = 0, l = positions.length; i < l; i += 9 ) {
18944 
18945  a = i / 3;
18946  b = a + 1;
18947  c = a + 2;
18948 
18949  intersection = checkBufferGeometryIntersection( this, raycaster, ray, positions, uvs, a, b, c );
18950 
18951  if ( intersection ) {
18952 
18953  intersection.index = a; // triangle number in positions buffer semantics
18954  intersects.push( intersection );
18955 
18956  }
18957 
18958  }
18959 
18960  }
18961 
18962  } else if ( geometry instanceof THREE.Geometry ) {
18963 
18964  var fvA, fvB, fvC;
18965  var isFaceMaterial = material instanceof THREE.MeshFaceMaterial;
18966  var materials = isFaceMaterial === true ? material.materials : null;
18967 
18968  var vertices = geometry.vertices;
18969  var faces = geometry.faces;
18970  var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
18971  if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
18972 
18973  for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
18974 
18975  var face = faces[ f ];
18976  var faceMaterial = isFaceMaterial === true ? materials[ face.materialIndex ] : material;
18977 
18978  if ( faceMaterial === undefined ) continue;
18979 
18980  fvA = vertices[ face.a ];
18981  fvB = vertices[ face.b ];
18982  fvC = vertices[ face.c ];
18983 
18984  if ( faceMaterial.morphTargets === true ) {
18985 
18986  var morphTargets = geometry.morphTargets;
18987  var morphInfluences = this.morphTargetInfluences;
18988 
18989  vA.set( 0, 0, 0 );
18990  vB.set( 0, 0, 0 );
18991  vC.set( 0, 0, 0 );
18992 
18993  for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
18994 
18995  var influence = morphInfluences[ t ];
18996 
18997  if ( influence === 0 ) continue;
18998 
18999  var targets = morphTargets[ t ].vertices;
19000 
19001  vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence );
19002  vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence );
19003  vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence );
19004 
19005  }
19006 
19007  vA.add( fvA );
19008  vB.add( fvB );
19009  vC.add( fvC );
19010 
19011  fvA = vA;
19012  fvB = vB;
19013  fvC = vC;
19014 
19015  }
19016 
19017  intersection = checkIntersection( this, raycaster, ray, fvA, fvB, fvC, intersectionPoint );
19018 
19019  if ( intersection ) {
19020 
19021  if ( uvs ) {
19022 
19023  var uvs_f = uvs[ f ];
19024  uvA.copy( uvs_f[ 0 ] );
19025  uvB.copy( uvs_f[ 1 ] );
19026  uvC.copy( uvs_f[ 2 ] );
19027 
19028  intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC );
19029 
19030  }
19031 
19032  intersection.face = face;
19033  intersection.faceIndex = f;
19034  intersects.push( intersection );
19035 
19036  }
19037 
19038  }
19039 
19040  }
19041 
19042  };
19043 
19044 }() );
19045 
19046 THREE.Mesh.prototype.clone = function () {
19047 
19048  return new this.constructor( this.geometry, this.material ).copy( this );
19049 
19050 };
19051 
19052 // File:src/objects/Bone.js
19053 
19060 THREE.Bone = function ( skin ) {
19061 
19062  THREE.Object3D.call( this );
19063 
19064  this.type = 'Bone';
19065 
19066  this.skin = skin;
19067 
19068 };
19069 
19070 THREE.Bone.prototype = Object.create( THREE.Object3D.prototype );
19071 THREE.Bone.prototype.constructor = THREE.Bone;
19072 
19073 THREE.Bone.prototype.copy = function ( source ) {
19074 
19075  THREE.Object3D.prototype.copy.call( this, source );
19076 
19077  this.skin = source.skin;
19078 
19079  return this;
19080 
19081 };
19082 
19083 // File:src/objects/Skeleton.js
19084 
19092 THREE.Skeleton = function ( bones, boneInverses, useVertexTexture ) {
19093 
19094  this.useVertexTexture = useVertexTexture !== undefined ? useVertexTexture : true;
19095 
19096  this.identityMatrix = new THREE.Matrix4();
19097 
19098  // copy the bone array
19099 
19100  bones = bones || [];
19101 
19102  this.bones = bones.slice( 0 );
19103 
19104  // create a bone texture or an array of floats
19105 
19106  if ( this.useVertexTexture ) {
19107 
19108  // layout (1 matrix = 4 pixels)
19109  // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
19110  // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)
19111  // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)
19112  // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)
19113  // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
19114 
19115 
19116  var size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix
19117  size = THREE.Math.nextPowerOfTwo( Math.ceil( size ) );
19118  size = Math.max( size, 4 );
19119 
19120  this.boneTextureWidth = size;
19121  this.boneTextureHeight = size;
19122 
19123  this.boneMatrices = new Float32Array( this.boneTextureWidth * this.boneTextureHeight * 4 ); // 4 floats per RGBA pixel
19124  this.boneTexture = new THREE.DataTexture( this.boneMatrices, this.boneTextureWidth, this.boneTextureHeight, THREE.RGBAFormat, THREE.FloatType );
19125 
19126  } else {
19127 
19128  this.boneMatrices = new Float32Array( 16 * this.bones.length );
19129 
19130  }
19131 
19132  // use the supplied bone inverses or calculate the inverses
19133 
19134  if ( boneInverses === undefined ) {
19135 
19136  this.calculateInverses();
19137 
19138  } else {
19139 
19140  if ( this.bones.length === boneInverses.length ) {
19141 
19142  this.boneInverses = boneInverses.slice( 0 );
19143 
19144  } else {
19145 
19146  console.warn( 'THREE.Skeleton bonInverses is the wrong length.' );
19147 
19148  this.boneInverses = [];
19149 
19150  for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
19151 
19152  this.boneInverses.push( new THREE.Matrix4() );
19153 
19154  }
19155 
19156  }
19157 
19158  }
19159 
19160 };
19161 
19162 THREE.Skeleton.prototype.calculateInverses = function () {
19163 
19164  this.boneInverses = [];
19165 
19166  for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
19167 
19168  var inverse = new THREE.Matrix4();
19169 
19170  if ( this.bones[ b ] ) {
19171 
19172  inverse.getInverse( this.bones[ b ].matrixWorld );
19173 
19174  }
19175 
19176  this.boneInverses.push( inverse );
19177 
19178  }
19179 
19180 };
19181 
19182 THREE.Skeleton.prototype.pose = function () {
19183 
19184  var bone;
19185 
19186  // recover the bind-time world matrices
19187 
19188  for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
19189 
19190  bone = this.bones[ b ];
19191 
19192  if ( bone ) {
19193 
19194  bone.matrixWorld.getInverse( this.boneInverses[ b ] );
19195 
19196  }
19197 
19198  }
19199 
19200  // compute the local matrices, positions, rotations and scales
19201 
19202  for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
19203 
19204  bone = this.bones[ b ];
19205 
19206  if ( bone ) {
19207 
19208  if ( bone.parent ) {
19209 
19210  bone.matrix.getInverse( bone.parent.matrixWorld );
19211  bone.matrix.multiply( bone.matrixWorld );
19212 
19213  } else {
19214 
19215  bone.matrix.copy( bone.matrixWorld );
19216 
19217  }
19218 
19219  bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
19220 
19221  }
19222 
19223  }
19224 
19225 };
19226 
19227 THREE.Skeleton.prototype.update = ( function () {
19228 
19229  var offsetMatrix = new THREE.Matrix4();
19230 
19231  return function update() {
19232 
19233  // flatten bone matrices to array
19234 
19235  for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
19236 
19237  // compute the offset between the current and the original transform
19238 
19239  var matrix = this.bones[ b ] ? this.bones[ b ].matrixWorld : this.identityMatrix;
19240 
19241  offsetMatrix.multiplyMatrices( matrix, this.boneInverses[ b ] );
19242  offsetMatrix.flattenToArrayOffset( this.boneMatrices, b * 16 );
19243 
19244  }
19245 
19246  if ( this.useVertexTexture ) {
19247 
19248  this.boneTexture.needsUpdate = true;
19249 
19250  }
19251 
19252  };
19253 
19254 } )();
19255 
19256 THREE.Skeleton.prototype.clone = function () {
19257 
19258  return new THREE.Skeleton( this.bones, this.boneInverses, this.useVertexTexture );
19259 
19260 };
19261 
19262 // File:src/objects/SkinnedMesh.js
19263 
19270 THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) {
19271 
19272  THREE.Mesh.call( this, geometry, material );
19273 
19274  this.type = 'SkinnedMesh';
19275 
19276  this.bindMode = "attached";
19277  this.bindMatrix = new THREE.Matrix4();
19278  this.bindMatrixInverse = new THREE.Matrix4();
19279 
19280  // init bones
19281 
19282  // TODO: remove bone creation as there is no reason (other than
19283  // convenience) for THREE.SkinnedMesh to do this.
19284 
19285  var bones = [];
19286 
19287  if ( this.geometry && this.geometry.bones !== undefined ) {
19288 
19289  var bone, gbone;
19290 
19291  for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
19292 
19293  gbone = this.geometry.bones[ b ];
19294 
19295  bone = new THREE.Bone( this );
19296  bones.push( bone );
19297 
19298  bone.name = gbone.name;
19299  bone.position.fromArray( gbone.pos );
19300  bone.quaternion.fromArray( gbone.rotq );
19301  if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
19302 
19303  }
19304 
19305  for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
19306 
19307  gbone = this.geometry.bones[ b ];
19308 
19309  if ( gbone.parent !== - 1 && gbone.parent !== null) {
19310 
19311  bones[ gbone.parent ].add( bones[ b ] );
19312 
19313  } else {
19314 
19315  this.add( bones[ b ] );
19316 
19317  }
19318 
19319  }
19320 
19321  }
19322 
19323  this.normalizeSkinWeights();
19324 
19325  this.updateMatrixWorld( true );
19326  this.bind( new THREE.Skeleton( bones, undefined, useVertexTexture ), this.matrixWorld );
19327 
19328 };
19329 
19330 
19331 THREE.SkinnedMesh.prototype = Object.create( THREE.Mesh.prototype );
19332 THREE.SkinnedMesh.prototype.constructor = THREE.SkinnedMesh;
19333 
19334 THREE.SkinnedMesh.prototype.bind = function( skeleton, bindMatrix ) {
19335 
19336  this.skeleton = skeleton;
19337 
19338  if ( bindMatrix === undefined ) {
19339 
19340  this.updateMatrixWorld( true );
19341 
19342  this.skeleton.calculateInverses();
19343 
19344  bindMatrix = this.matrixWorld;
19345 
19346  }
19347 
19348  this.bindMatrix.copy( bindMatrix );
19349  this.bindMatrixInverse.getInverse( bindMatrix );
19350 
19351 };
19352 
19353 THREE.SkinnedMesh.prototype.pose = function () {
19354 
19355  this.skeleton.pose();
19356 
19357 };
19358 
19359 THREE.SkinnedMesh.prototype.normalizeSkinWeights = function () {
19360 
19361  if ( this.geometry instanceof THREE.Geometry ) {
19362 
19363  for ( var i = 0; i < this.geometry.skinIndices.length; i ++ ) {
19364 
19365  var sw = this.geometry.skinWeights[ i ];
19366 
19367  var scale = 1.0 / sw.lengthManhattan();
19368 
19369  if ( scale !== Infinity ) {
19370 
19371  sw.multiplyScalar( scale );
19372 
19373  } else {
19374 
19375  sw.set( 1 ); // this will be normalized by the shader anyway
19376 
19377  }
19378 
19379  }
19380 
19381  } else {
19382 
19383  // skinning weights assumed to be normalized for THREE.BufferGeometry
19384 
19385  }
19386 
19387 };
19388 
19389 THREE.SkinnedMesh.prototype.updateMatrixWorld = function( force ) {
19390 
19391  THREE.Mesh.prototype.updateMatrixWorld.call( this, true );
19392 
19393  if ( this.bindMode === "attached" ) {
19394 
19395  this.bindMatrixInverse.getInverse( this.matrixWorld );
19396 
19397  } else if ( this.bindMode === "detached" ) {
19398 
19399  this.bindMatrixInverse.getInverse( this.bindMatrix );
19400 
19401  } else {
19402 
19403  console.warn( 'THREE.SkinnedMesh unrecognized bindMode: ' + this.bindMode );
19404 
19405  }
19406 
19407 };
19408 
19409 THREE.SkinnedMesh.prototype.clone = function() {
19410 
19411  return new this.constructor( this.geometry, this.material, this.useVertexTexture ).copy( this );
19412 
19413 };
19414 
19415 // File:src/objects/LOD.js
19416 
19423 THREE.LOD = function () {
19424 
19425  THREE.Object3D.call( this );
19426 
19427  this.type = 'LOD';
19428 
19429  Object.defineProperties( this, {
19430  levels: {
19431  enumerable: true,
19432  value: []
19433  },
19434  objects: {
19435  get: function () {
19436 
19437  console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
19438  return this.levels;
19439 
19440  }
19441  }
19442  } );
19443 
19444 };
19445 
19446 
19447 THREE.LOD.prototype = Object.create( THREE.Object3D.prototype );
19448 THREE.LOD.prototype.constructor = THREE.LOD;
19449 
19450 THREE.LOD.prototype.addLevel = function ( object, distance ) {
19451 
19452  if ( distance === undefined ) distance = 0;
19453 
19454  distance = Math.abs( distance );
19455 
19456  var levels = this.levels;
19457 
19458  for ( var l = 0; l < levels.length; l ++ ) {
19459 
19460  if ( distance < levels[ l ].distance ) {
19461 
19462  break;
19463 
19464  }
19465 
19466  }
19467 
19468  levels.splice( l, 0, { distance: distance, object: object } );
19469 
19470  this.add( object );
19471 
19472 };
19473 
19474 THREE.LOD.prototype.getObjectForDistance = function ( distance ) {
19475 
19476  var levels = this.levels;
19477 
19478  for ( var i = 1, l = levels.length; i < l; i ++ ) {
19479 
19480  if ( distance < levels[ i ].distance ) {
19481 
19482  break;
19483 
19484  }
19485 
19486  }
19487 
19488  return levels[ i - 1 ].object;
19489 
19490 };
19491 
19492 THREE.LOD.prototype.raycast = ( function () {
19493 
19494  var matrixPosition = new THREE.Vector3();
19495 
19496  return function raycast( raycaster, intersects ) {
19497 
19498  matrixPosition.setFromMatrixPosition( this.matrixWorld );
19499 
19500  var distance = raycaster.ray.origin.distanceTo( matrixPosition );
19501 
19502  this.getObjectForDistance( distance ).raycast( raycaster, intersects );
19503 
19504  };
19505 
19506 }() );
19507 
19508 THREE.LOD.prototype.update = function () {
19509 
19510  var v1 = new THREE.Vector3();
19511  var v2 = new THREE.Vector3();
19512 
19513  return function update( camera ) {
19514 
19515  var levels = this.levels;
19516 
19517  if ( levels.length > 1 ) {
19518 
19519  v1.setFromMatrixPosition( camera.matrixWorld );
19520  v2.setFromMatrixPosition( this.matrixWorld );
19521 
19522  var distance = v1.distanceTo( v2 );
19523 
19524  levels[ 0 ].object.visible = true;
19525 
19526  for ( var i = 1, l = levels.length; i < l; i ++ ) {
19527 
19528  if ( distance >= levels[ i ].distance ) {
19529 
19530  levels[ i - 1 ].object.visible = false;
19531  levels[ i ].object.visible = true;
19532 
19533  } else {
19534 
19535  break;
19536 
19537  }
19538 
19539  }
19540 
19541  for ( ; i < l; i ++ ) {
19542 
19543  levels[ i ].object.visible = false;
19544 
19545  }
19546 
19547  }
19548 
19549  };
19550 
19551 }();
19552 
19553 THREE.LOD.prototype.copy = function ( source ) {
19554 
19555  THREE.Object3D.prototype.copy.call( this, source, false );
19556 
19557  var levels = source.levels;
19558 
19559  for ( var i = 0, l = levels.length; i < l; i ++ ) {
19560 
19561  var level = levels[ i ];
19562 
19563  this.addLevel( level.object.clone(), level.distance );
19564 
19565  }
19566 
19567  return this;
19568 
19569 };
19570 
19571 THREE.LOD.prototype.toJSON = function ( meta ) {
19572 
19573  var data = THREE.Object3D.prototype.toJSON.call( this, meta );
19574 
19575  data.object.levels = [];
19576 
19577  var levels = this.levels;
19578 
19579  for ( var i = 0, l = levels.length; i < l; i ++ ) {
19580 
19581  var level = levels[ i ];
19582 
19583  data.object.levels.push( {
19584  object: level.object.uuid,
19585  distance: level.distance
19586  } );
19587 
19588  }
19589 
19590  return data;
19591 
19592 };
19593 
19594 // File:src/objects/Sprite.js
19595 
19601 THREE.Sprite = ( function () {
19602 
19603  var indices = new Uint16Array( [ 0, 1, 2, 0, 2, 3 ] );
19604  var vertices = new Float32Array( [ - 0.5, - 0.5, 0, 0.5, - 0.5, 0, 0.5, 0.5, 0, - 0.5, 0.5, 0 ] );
19605  var uvs = new Float32Array( [ 0, 0, 1, 0, 1, 1, 0, 1 ] );
19606 
19607  var geometry = new THREE.BufferGeometry();
19608  geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
19609  geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
19610  geometry.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
19611 
19612  return function Sprite( material ) {
19613 
19614  THREE.Object3D.call( this );
19615 
19616  this.type = 'Sprite';
19617 
19618  this.geometry = geometry;
19619  this.material = ( material !== undefined ) ? material : new THREE.SpriteMaterial();
19620 
19621  };
19622 
19623 } )();
19624 
19625 THREE.Sprite.prototype = Object.create( THREE.Object3D.prototype );
19626 THREE.Sprite.prototype.constructor = THREE.Sprite;
19627 
19628 THREE.Sprite.prototype.raycast = ( function () {
19629 
19630  var matrixPosition = new THREE.Vector3();
19631 
19632  return function raycast( raycaster, intersects ) {
19633 
19634  matrixPosition.setFromMatrixPosition( this.matrixWorld );
19635 
19636  var distanceSq = raycaster.ray.distanceSqToPoint( matrixPosition );
19637  var guessSizeSq = this.scale.x * this.scale.y;
19638 
19639  if ( distanceSq > guessSizeSq ) {
19640 
19641  return;
19642 
19643  }
19644 
19645  intersects.push( {
19646 
19647  distance: Math.sqrt( distanceSq ),
19648  point: this.position,
19649  face: null,
19650  object: this
19651 
19652  } );
19653 
19654  };
19655 
19656 }() );
19657 
19658 THREE.Sprite.prototype.clone = function () {
19659 
19660  return new this.constructor( this.material ).copy( this );
19661 
19662 };
19663 
19664 // Backwards compatibility
19665 
19666 THREE.Particle = THREE.Sprite;
19667 
19668 // File:src/objects/LensFlare.js
19669 
19675 THREE.LensFlare = function ( texture, size, distance, blending, color ) {
19676 
19677  THREE.Object3D.call( this );
19678 
19679  this.lensFlares = [];
19680 
19681  this.positionScreen = new THREE.Vector3();
19682  this.customUpdateCallback = undefined;
19683 
19684  if ( texture !== undefined ) {
19685 
19686  this.add( texture, size, distance, blending, color );
19687 
19688  }
19689 
19690 };
19691 
19692 THREE.LensFlare.prototype = Object.create( THREE.Object3D.prototype );
19693 THREE.LensFlare.prototype.constructor = THREE.LensFlare;
19694 
19695 
19696 /*
19697  * Add: adds another flare
19698  */
19699 
19700 THREE.LensFlare.prototype.add = function ( texture, size, distance, blending, color, opacity ) {
19701 
19702  if ( size === undefined ) size = - 1;
19703  if ( distance === undefined ) distance = 0;
19704  if ( opacity === undefined ) opacity = 1;
19705  if ( color === undefined ) color = new THREE.Color( 0xffffff );
19706  if ( blending === undefined ) blending = THREE.NormalBlending;
19707 
19708  distance = Math.min( distance, Math.max( 0, distance ) );
19709 
19710  this.lensFlares.push( {
19711  texture: texture, // THREE.Texture
19712  size: size, // size in pixels (-1 = use texture.width)
19713  distance: distance, // distance (0-1) from light source (0=at light source)
19714  x: 0, y: 0, z: 0, // screen position (-1 => 1) z = 0 is in front z = 1 is back
19715  scale: 1, // scale
19716  rotation: 0, // rotation
19717  opacity: opacity, // opacity
19718  color: color, // color
19719  blending: blending // blending
19720  } );
19721 
19722 };
19723 
19724 /*
19725  * Update lens flares update positions on all flares based on the screen position
19726  * Set myLensFlare.customUpdateCallback to alter the flares in your project specific way.
19727  */
19728 
19729 THREE.LensFlare.prototype.updateLensFlares = function () {
19730 
19731  var f, fl = this.lensFlares.length;
19732  var flare;
19733  var vecX = - this.positionScreen.x * 2;
19734  var vecY = - this.positionScreen.y * 2;
19735 
19736  for ( f = 0; f < fl; f ++ ) {
19737 
19738  flare = this.lensFlares[ f ];
19739 
19740  flare.x = this.positionScreen.x + vecX * flare.distance;
19741  flare.y = this.positionScreen.y + vecY * flare.distance;
19742 
19743  flare.wantedRotation = flare.x * Math.PI * 0.25;
19744  flare.rotation += ( flare.wantedRotation - flare.rotation ) * 0.25;
19745 
19746  }
19747 
19748 };
19749 
19750 THREE.LensFlare.prototype.copy = function ( source ) {
19751 
19752  THREE.Object3D.prototype.copy.call( this, source );
19753 
19754  this.positionScreen.copy( source.positionScreen );
19755  this.customUpdateCallback = source.customUpdateCallback;
19756 
19757  for ( var i = 0, l = source.lensFlares.length; i < l; i ++ ) {
19758 
19759  this.lensFlares.push( source.lensFlares[ i ] );
19760 
19761  }
19762 
19763  return this;
19764 
19765 };
19766 
19767 // File:src/scenes/Scene.js
19768 
19773 THREE.Scene = function () {
19774 
19775  THREE.Object3D.call( this );
19776 
19777  this.type = 'Scene';
19778 
19779  this.fog = null;
19780  this.overrideMaterial = null;
19781 
19782  this.autoUpdate = true; // checked by the renderer
19783 
19784 };
19785 
19786 THREE.Scene.prototype = Object.create( THREE.Object3D.prototype );
19787 THREE.Scene.prototype.constructor = THREE.Scene;
19788 
19789 THREE.Scene.prototype.copy = function ( source ) {
19790 
19791  THREE.Object3D.prototype.copy.call( this, source );
19792 
19793  if ( source.fog !== null ) this.fog = source.fog.clone();
19794  if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
19795 
19796  this.autoUpdate = source.autoUpdate;
19797  this.matrixAutoUpdate = source.matrixAutoUpdate;
19798 
19799  return this;
19800 
19801 };
19802 
19803 // File:src/scenes/Fog.js
19804 
19810 THREE.Fog = function ( color, near, far ) {
19811 
19812  this.name = '';
19813 
19814  this.color = new THREE.Color( color );
19815 
19816  this.near = ( near !== undefined ) ? near : 1;
19817  this.far = ( far !== undefined ) ? far : 1000;
19818 
19819 };
19820 
19821 THREE.Fog.prototype.clone = function () {
19822 
19823  return new THREE.Fog( this.color.getHex(), this.near, this.far );
19824 
19825 };
19826 
19827 // File:src/scenes/FogExp2.js
19828 
19834 THREE.FogExp2 = function ( color, density ) {
19835 
19836  this.name = '';
19837 
19838  this.color = new THREE.Color( color );
19839  this.density = ( density !== undefined ) ? density : 0.00025;
19840 
19841 };
19842 
19843 THREE.FogExp2.prototype.clone = function () {
19844 
19845  return new THREE.FogExp2( this.color.getHex(), this.density );
19846 
19847 };
19848 
19849 // File:src/renderers/shaders/ShaderChunk.js
19850 
19851 THREE.ShaderChunk = {};
19852 
19853 // File:src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl
19854 
19855 THREE.ShaderChunk[ 'alphamap_fragment'] = "#ifdef USE_ALPHAMAP\n\n diffuseColor.a *= texture2D( alphaMap, vUv ).g;\n\n#endif\n";
19856 
19857 // File:src/renderers/shaders/ShaderChunk/alphamap_pars_fragment.glsl
19858 
19859 THREE.ShaderChunk[ 'alphamap_pars_fragment'] = "#ifdef USE_ALPHAMAP\n\n uniform sampler2D alphaMap;\n\n#endif\n";
19860 
19861 // File:src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl
19862 
19863 THREE.ShaderChunk[ 'alphatest_fragment'] = "#ifdef ALPHATEST\n\n if ( diffuseColor.a < ALPHATEST ) discard;\n\n#endif\n";
19864 
19865 // File:src/renderers/shaders/ShaderChunk/aomap_fragment.glsl
19866 
19867 THREE.ShaderChunk[ 'aomap_fragment'] = "#ifdef USE_AOMAP\n\n totalAmbientLight *= ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\n#endif\n";
19868 
19869 // File:src/renderers/shaders/ShaderChunk/aomap_pars_fragment.glsl
19870 
19871 THREE.ShaderChunk[ 'aomap_pars_fragment'] = "#ifdef USE_AOMAP\n\n uniform sampler2D aoMap;\n uniform float aoMapIntensity;\n\n#endif";
19872 
19873 // File:src/renderers/shaders/ShaderChunk/begin_vertex.glsl
19874 
19875 THREE.ShaderChunk[ 'begin_vertex'] = "\nvec3 transformed = vec3( position );\n";
19876 
19877 // File:src/renderers/shaders/ShaderChunk/beginnormal_vertex.glsl
19878 
19879 THREE.ShaderChunk[ 'beginnormal_vertex'] = "\nvec3 objectNormal = vec3( normal );\n";
19880 
19881 // File:src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl
19882 
19883 THREE.ShaderChunk[ 'bumpmap_pars_fragment'] = "#ifdef USE_BUMPMAP\n\n uniform sampler2D bumpMap;\n uniform float bumpScale;\n\n\n\n vec2 dHdxy_fwd() {\n\n vec2 dSTdx = dFdx( vUv );\n vec2 dSTdy = dFdy( vUv );\n\n float Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\n return vec2( dBx, dBy );\n\n }\n\n vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\n vec3 vSigmaX = dFdx( surf_pos );\n vec3 vSigmaY = dFdy( surf_pos );\n vec3 vN = surf_norm;\n vec3 R1 = cross( vSigmaY, vN );\n vec3 R2 = cross( vN, vSigmaX );\n\n float fDet = dot( vSigmaX, R1 );\n\n vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n return normalize( abs( fDet ) * surf_norm - vGrad );\n\n }\n\n#endif\n";
19884 
19885 // File:src/renderers/shaders/ShaderChunk/color_fragment.glsl
19886 
19887 THREE.ShaderChunk[ 'color_fragment'] = "#ifdef USE_COLOR\n\n diffuseColor.rgb *= vColor;\n\n#endif";
19888 
19889 // File:src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl
19890 
19891 THREE.ShaderChunk[ 'color_pars_fragment'] = "#ifdef USE_COLOR\n\n varying vec3 vColor;\n\n#endif\n";
19892 
19893 // File:src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl
19894 
19895 THREE.ShaderChunk[ 'color_pars_vertex'] = "#ifdef USE_COLOR\n\n varying vec3 vColor;\n\n#endif";
19896 
19897 // File:src/renderers/shaders/ShaderChunk/color_vertex.glsl
19898 
19899 THREE.ShaderChunk[ 'color_vertex'] = "#ifdef USE_COLOR\n\n vColor.xyz = color.xyz;\n\n#endif";
19900 
19901 // File:src/renderers/shaders/ShaderChunk/common.glsl
19902 
19903 THREE.ShaderChunk[ 'common'] = "#define PI 3.14159\n#define PI2 6.28318\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\n\nvec3 transformDirection( in vec3 normal, in mat4 matrix ) {\n\n return normalize( ( matrix * vec4( normal, 0.0 ) ).xyz );\n\n}\n\nvec3 inverseTransformDirection( in vec3 normal, in mat4 matrix ) {\n\n return normalize( ( vec4( normal, 0.0 ) * matrix ).xyz );\n\n}\n\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\n float distance = dot( planeNormal, point - pointOnPlane );\n\n return - distance * planeNormal + point;\n\n}\n\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\n return sign( dot( point - pointOnPlane, planeNormal ) );\n\n}\n\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\n return lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n\n}\n\nfloat calcLightAttenuation( float lightDistance, float cutoffDistance, float decayExponent ) {\n\n if ( decayExponent > 0.0 ) {\n\n return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\n }\n\n return 1.0;\n\n}\n\nvec3 F_Schlick( in vec3 specularColor, in float dotLH ) {\n\n\n float fresnel = exp2( ( -5.55437 * dotLH - 6.98316 ) * dotLH );\n\n return ( 1.0 - specularColor ) * fresnel + specularColor;\n\n}\n\nfloat G_BlinnPhong_Implicit( /* in float dotNL, in float dotNV */ ) {\n\n\n return 0.25;\n\n}\n\nfloat D_BlinnPhong( in float shininess, in float dotNH ) {\n\n\n return ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n\n}\n\nvec3 BRDF_BlinnPhong( in vec3 specularColor, in float shininess, in vec3 normal, in vec3 lightDir, in vec3 viewDir ) {\n\n vec3 halfDir = normalize( lightDir + viewDir );\n\n float dotNH = saturate( dot( normal, halfDir ) );\n float dotLH = saturate( dot( lightDir, halfDir ) );\n\n vec3 F = F_Schlick( specularColor, dotLH );\n\n float G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ );\n\n float D = D_BlinnPhong( shininess, dotNH );\n\n return F * G * D;\n\n}\n\nvec3 inputToLinear( in vec3 a ) {\n\n #ifdef GAMMA_INPUT\n\n return pow( a, vec3( float( GAMMA_FACTOR ) ) );\n\n #else\n\n return a;\n\n #endif\n\n}\n\nvec3 linearToOutput( in vec3 a ) {\n\n #ifdef GAMMA_OUTPUT\n\n return pow( a, vec3( 1.0 / float( GAMMA_FACTOR ) ) );\n\n #else\n\n return a;\n\n #endif\n\n}\n";
19904 
19905 // File:src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl
19906 
19907 THREE.ShaderChunk[ 'defaultnormal_vertex'] = "#ifdef FLIP_SIDED\n\n objectNormal = -objectNormal;\n\n#endif\n\nvec3 transformedNormal = normalMatrix * objectNormal;\n";
19908 
19909 // File:src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl
19910 
19911 THREE.ShaderChunk[ 'displacementmap_vertex'] = "#ifdef USE_DISPLACEMENTMAP\n\n transformed += normal * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n\n#endif\n";
19912 
19913 // File:src/renderers/shaders/ShaderChunk/displacementmap_pars_vertex.glsl
19914 
19915 THREE.ShaderChunk[ 'displacementmap_pars_vertex'] = "#ifdef USE_DISPLACEMENTMAP\n\n uniform sampler2D displacementMap;\n uniform float displacementScale;\n uniform float displacementBias;\n\n#endif\n";
19916 
19917 // File:src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl
19918 
19919 THREE.ShaderChunk[ 'emissivemap_fragment'] = "#ifdef USE_EMISSIVEMAP\n\n vec4 emissiveColor = texture2D( emissiveMap, vUv );\n\n emissiveColor.rgb = inputToLinear( emissiveColor.rgb );\n\n totalEmissiveLight *= emissiveColor.rgb;\n\n#endif\n";
19920 
19921 // File:src/renderers/shaders/ShaderChunk/emissivemap_pars_fragment.glsl
19922 
19923 THREE.ShaderChunk[ 'emissivemap_pars_fragment'] = "#ifdef USE_EMISSIVEMAP\n\n uniform sampler2D emissiveMap;\n\n#endif\n";
19924 
19925 // File:src/renderers/shaders/ShaderChunk/envmap_fragment.glsl
19926 
19927 THREE.ShaderChunk[ 'envmap_fragment'] = "#ifdef USE_ENVMAP\n\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\n vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\n vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\n #ifdef ENVMAP_MODE_REFLECTION\n\n vec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\n #else\n\n vec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\n #endif\n\n #else\n\n vec3 reflectVec = vReflect;\n\n #endif\n\n #ifdef DOUBLE_SIDED\n float flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n #else\n float flipNormal = 1.0;\n #endif\n\n #ifdef ENVMAP_TYPE_CUBE\n vec4 envColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\n #elif defined( ENVMAP_TYPE_EQUIREC )\n vec2 sampleUV;\n sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );\n sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n vec4 envColor = texture2D( envMap, sampleUV );\n\n #elif defined( ENVMAP_TYPE_SPHERE )\n vec3 reflectView = flipNormal * normalize((viewMatrix * vec4( reflectVec, 0.0 )).xyz + vec3(0.0,0.0,1.0));\n vec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n #endif\n\n envColor.xyz = inputToLinear( envColor.xyz );\n\n #ifdef ENVMAP_BLENDING_MULTIPLY\n\n outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\n #elif defined( ENVMAP_BLENDING_MIX )\n\n outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\n #elif defined( ENVMAP_BLENDING_ADD )\n\n outgoingLight += envColor.xyz * specularStrength * reflectivity;\n\n #endif\n\n#endif\n";
19928 
19929 // File:src/renderers/shaders/ShaderChunk/envmap_pars_fragment.glsl
19930 
19931 THREE.ShaderChunk[ 'envmap_pars_fragment'] = "#ifdef USE_ENVMAP\n\n uniform float reflectivity;\n #ifdef ENVMAP_TYPE_CUBE\n uniform samplerCube envMap;\n #else\n uniform sampler2D envMap;\n #endif\n uniform float flipEnvMap;\n\n #if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\n uniform float refractionRatio;\n\n #else\n\n varying vec3 vReflect;\n\n #endif\n\n#endif\n";
19932 
19933 // File:src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl
19934 
19935 THREE.ShaderChunk[ 'envmap_pars_vertex'] = "#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP ) && ! defined( PHONG )\n\n varying vec3 vReflect;\n\n uniform float refractionRatio;\n\n#endif\n";
19936 
19937 // File:src/renderers/shaders/ShaderChunk/envmap_vertex.glsl
19938 
19939 THREE.ShaderChunk[ 'envmap_vertex'] = "#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP ) && ! defined( PHONG )\n\n vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\n vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\n #ifdef ENVMAP_MODE_REFLECTION\n\n vReflect = reflect( cameraToVertex, worldNormal );\n\n #else\n\n vReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\n #endif\n\n#endif\n";
19940 
19941 // File:src/renderers/shaders/ShaderChunk/fog_fragment.glsl
19942 
19943 THREE.ShaderChunk[ 'fog_fragment'] = "#ifdef USE_FOG\n\n #ifdef USE_LOGDEPTHBUF_EXT\n\n float depth = gl_FragDepthEXT / gl_FragCoord.w;\n\n #else\n\n float depth = gl_FragCoord.z / gl_FragCoord.w;\n\n #endif\n\n #ifdef FOG_EXP2\n\n float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );\n\n #else\n\n float fogFactor = smoothstep( fogNear, fogFar, depth );\n\n #endif\n \n outgoingLight = mix( outgoingLight, fogColor, fogFactor );\n\n#endif";
19944 
19945 // File:src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl
19946 
19947 THREE.ShaderChunk[ 'fog_pars_fragment'] = "#ifdef USE_FOG\n\n uniform vec3 fogColor;\n\n #ifdef FOG_EXP2\n\n uniform float fogDensity;\n\n #else\n\n uniform float fogNear;\n uniform float fogFar;\n #endif\n\n#endif";
19948 
19949 // File:src/renderers/shaders/ShaderChunk/hemilight_fragment.glsl
19950 
19951 THREE.ShaderChunk[ 'hemilight_fragment'] = "#if MAX_HEMI_LIGHTS > 0\n\n for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\n\n vec3 lightDir = hemisphereLightDirection[ i ];\n\n float dotProduct = dot( normal, lightDir );\n\n float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\n\n vec3 lightColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n\n totalAmbientLight += lightColor;\n\n }\n\n#endif\n\n";
19952 
19953 // File:src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl
19954 
19955 THREE.ShaderChunk[ 'lightmap_fragment'] = "#ifdef USE_LIGHTMAP\n\n totalAmbientLight += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\n#endif\n";
19956 
19957 // File:src/renderers/shaders/ShaderChunk/lightmap_pars_fragment.glsl
19958 
19959 THREE.ShaderChunk[ 'lightmap_pars_fragment'] = "#ifdef USE_LIGHTMAP\n\n uniform sampler2D lightMap;\n uniform float lightMapIntensity;\n\n#endif";
19960 
19961 // File:src/renderers/shaders/ShaderChunk/lights_lambert_pars_vertex.glsl
19962 
19963 THREE.ShaderChunk[ 'lights_lambert_pars_vertex'] = "#if MAX_DIR_LIGHTS > 0\n\n uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\n uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n uniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n uniform float pointLightDecay[ MAX_POINT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\n uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDecay[ MAX_SPOT_LIGHTS ];\n\n#endif\n";
19964 
19965 // File:src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl
19966 
19967 THREE.ShaderChunk[ 'lights_lambert_vertex'] = "vLightFront = vec3( 0.0 );\n\n#ifdef DOUBLE_SIDED\n\n vLightBack = vec3( 0.0 );\n\n#endif\n\nvec3 normal = normalize( transformedNormal );\n\n#if MAX_POINT_LIGHTS > 0\n\n for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n\n vec3 lightColor = pointLightColor[ i ];\n\n vec3 lVector = pointLightPosition[ i ] - mvPosition.xyz;\n vec3 lightDir = normalize( lVector );\n\n\n float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );\n\n\n float dotProduct = dot( normal, lightDir );\n\n vLightFront += lightColor * attenuation * saturate( dotProduct );\n\n #ifdef DOUBLE_SIDED\n\n vLightBack += lightColor * attenuation * saturate( - dotProduct );\n\n #endif\n\n }\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n\n vec3 lightColor = spotLightColor[ i ];\n\n vec3 lightPosition = spotLightPosition[ i ];\n vec3 lVector = lightPosition - mvPosition.xyz;\n vec3 lightDir = normalize( lVector );\n\n float spotEffect = dot( spotLightDirection[ i ], lightDir );\n\n if ( spotEffect > spotLightAngleCos[ i ] ) {\n\n spotEffect = saturate( pow( saturate( spotEffect ), spotLightExponent[ i ] ) );\n\n\n float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );\n\n attenuation *= spotEffect;\n\n\n float dotProduct = dot( normal, lightDir );\n\n vLightFront += lightColor * attenuation * saturate( dotProduct );\n\n #ifdef DOUBLE_SIDED\n\n vLightBack += lightColor * attenuation * saturate( - dotProduct );\n\n #endif\n\n }\n\n }\n\n#endif\n\n#if MAX_DIR_LIGHTS > 0\n\n for ( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\n\n vec3 lightColor = directionalLightColor[ i ];\n\n vec3 lightDir = directionalLightDirection[ i ];\n\n\n float dotProduct = dot( normal, lightDir );\n\n vLightFront += lightColor * saturate( dotProduct );\n\n #ifdef DOUBLE_SIDED\n\n vLightBack += lightColor * saturate( - dotProduct );\n\n #endif\n\n }\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\n\n vec3 lightDir = hemisphereLightDirection[ i ];\n\n\n float dotProduct = dot( normal, lightDir );\n\n float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\n\n vLightFront += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n\n #ifdef DOUBLE_SIDED\n\n float hemiDiffuseWeightBack = - 0.5 * dotProduct + 0.5;\n\n vLightBack += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeightBack );\n\n #endif\n\n }\n\n#endif\n";
19968 
19969 // File:src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl
19970 
19971 THREE.ShaderChunk[ 'lights_phong_fragment'] = "vec3 viewDir = normalize( vViewPosition );\n\nvec3 totalDiffuseLight = vec3( 0.0 );\nvec3 totalSpecularLight = vec3( 0.0 );\n\n#if MAX_POINT_LIGHTS > 0\n\n for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n\n vec3 lightColor = pointLightColor[ i ];\n\n vec3 lightPosition = pointLightPosition[ i ];\n vec3 lVector = lightPosition + vViewPosition.xyz;\n vec3 lightDir = normalize( lVector );\n\n\n float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );\n\n\n float cosineTerm = saturate( dot( normal, lightDir ) );\n\n totalDiffuseLight += lightColor * attenuation * cosineTerm;\n\n\n vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );\n\n totalSpecularLight += brdf * specularStrength * lightColor * attenuation * cosineTerm;\n\n\n }\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n\n vec3 lightColor = spotLightColor[ i ];\n\n vec3 lightPosition = spotLightPosition[ i ];\n vec3 lVector = lightPosition + vViewPosition.xyz;\n vec3 lightDir = normalize( lVector );\n\n float spotEffect = dot( spotLightDirection[ i ], lightDir );\n\n if ( spotEffect > spotLightAngleCos[ i ] ) {\n\n spotEffect = saturate( pow( saturate( spotEffect ), spotLightExponent[ i ] ) );\n\n\n float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );\n\n attenuation *= spotEffect;\n\n\n float cosineTerm = saturate( dot( normal, lightDir ) );\n\n totalDiffuseLight += lightColor * attenuation * cosineTerm;\n\n\n vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );\n\n totalSpecularLight += brdf * specularStrength * lightColor * attenuation * cosineTerm;\n\n }\n\n }\n\n#endif\n\n#if MAX_DIR_LIGHTS > 0\n\n for ( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\n\n vec3 lightColor = directionalLightColor[ i ];\n\n vec3 lightDir = directionalLightDirection[ i ];\n\n\n float cosineTerm = saturate( dot( normal, lightDir ) );\n\n totalDiffuseLight += lightColor * cosineTerm;\n\n\n vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );\n\n totalSpecularLight += brdf * specularStrength * lightColor * cosineTerm;\n\n }\n\n#endif\n";
19972 
19973 // File:src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl
19974 
19975 THREE.ShaderChunk[ 'lights_phong_pars_fragment'] = "uniform vec3 ambientLightColor;\n\n#if MAX_DIR_LIGHTS > 0\n\n uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\n uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n\n uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n uniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n uniform float pointLightDecay[ MAX_POINT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\n uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\n uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDecay[ MAX_SPOT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0 || defined( USE_ENVMAP )\n\n varying vec3 vWorldPosition;\n\n#endif\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n varying vec3 vNormal;\n\n#endif\n";
19976 
19977 // File:src/renderers/shaders/ShaderChunk/lights_phong_pars_vertex.glsl
19978 
19979 THREE.ShaderChunk[ 'lights_phong_pars_vertex'] = "#if MAX_SPOT_LIGHTS > 0 || defined( USE_ENVMAP )\n\n varying vec3 vWorldPosition;\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n\n#endif\n";
19980 
19981 // File:src/renderers/shaders/ShaderChunk/lights_phong_vertex.glsl
19982 
19983 THREE.ShaderChunk[ 'lights_phong_vertex'] = "#if MAX_SPOT_LIGHTS > 0 || defined( USE_ENVMAP )\n\n vWorldPosition = worldPosition.xyz;\n\n#endif\n";
19984 
19985 // File:src/renderers/shaders/ShaderChunk/linear_to_gamma_fragment.glsl
19986 
19987 THREE.ShaderChunk[ 'linear_to_gamma_fragment'] = "\n outgoingLight = linearToOutput( outgoingLight );\n";
19988 
19989 // File:src/renderers/shaders/ShaderChunk/logdepthbuf_fragment.glsl
19990 
19991 THREE.ShaderChunk[ 'logdepthbuf_fragment'] = "#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)\n\n gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;\n\n#endif";
19992 
19993 // File:src/renderers/shaders/ShaderChunk/logdepthbuf_pars_fragment.glsl
19994 
19995 THREE.ShaderChunk[ 'logdepthbuf_pars_fragment'] = "#ifdef USE_LOGDEPTHBUF\n\n uniform float logDepthBufFC;\n\n #ifdef USE_LOGDEPTHBUF_EXT\n\n varying float vFragDepth;\n\n #endif\n\n#endif\n";
19996 
19997 // File:src/renderers/shaders/ShaderChunk/logdepthbuf_pars_vertex.glsl
19998 
19999 THREE.ShaderChunk[ 'logdepthbuf_pars_vertex'] = "#ifdef USE_LOGDEPTHBUF\n\n #ifdef USE_LOGDEPTHBUF_EXT\n\n varying float vFragDepth;\n\n #endif\n\n uniform float logDepthBufFC;\n\n#endif";
20000 
20001 // File:src/renderers/shaders/ShaderChunk/logdepthbuf_vertex.glsl
20002 
20003 THREE.ShaderChunk[ 'logdepthbuf_vertex'] = "#ifdef USE_LOGDEPTHBUF\n\n gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;\n\n #ifdef USE_LOGDEPTHBUF_EXT\n\n vFragDepth = 1.0 + gl_Position.w;\n\n#else\n\n gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;\n\n #endif\n\n#endif";
20004 
20005 // File:src/renderers/shaders/ShaderChunk/map_fragment.glsl
20006 
20007 THREE.ShaderChunk[ 'map_fragment'] = "#ifdef USE_MAP\n\n vec4 texelColor = texture2D( map, vUv );\n\n texelColor.xyz = inputToLinear( texelColor.xyz );\n\n diffuseColor *= texelColor;\n\n#endif\n";
20008 
20009 // File:src/renderers/shaders/ShaderChunk/map_pars_fragment.glsl
20010 
20011 THREE.ShaderChunk[ 'map_pars_fragment'] = "#ifdef USE_MAP\n\n uniform sampler2D map;\n\n#endif";
20012 
20013 // File:src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl
20014 
20015 THREE.ShaderChunk[ 'map_particle_fragment'] = "#ifdef USE_MAP\n\n diffuseColor *= texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) * offsetRepeat.zw + offsetRepeat.xy );\n\n#endif\n";
20016 
20017 // File:src/renderers/shaders/ShaderChunk/map_particle_pars_fragment.glsl
20018 
20019 THREE.ShaderChunk[ 'map_particle_pars_fragment'] = "#ifdef USE_MAP\n\n uniform vec4 offsetRepeat;\n uniform sampler2D map;\n\n#endif\n";
20020 
20021 // File:src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl
20022 
20023 THREE.ShaderChunk[ 'morphnormal_vertex'] = "#ifdef USE_MORPHNORMALS\n\n objectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n objectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n objectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n objectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n\n#endif\n";
20024 
20025 // File:src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl
20026 
20027 THREE.ShaderChunk[ 'morphtarget_pars_vertex'] = "#ifdef USE_MORPHTARGETS\n\n #ifndef USE_MORPHNORMALS\n\n uniform float morphTargetInfluences[ 8 ];\n\n #else\n\n uniform float morphTargetInfluences[ 4 ];\n\n #endif\n\n#endif";
20028 
20029 // File:src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl
20030 
20031 THREE.ShaderChunk[ 'morphtarget_vertex'] = "#ifdef USE_MORPHTARGETS\n\n transformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n transformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n transformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n transformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\n #ifndef USE_MORPHNORMALS\n\n transformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n transformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n transformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n transformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\n #endif\n\n#endif\n";
20032 
20033 // File:src/renderers/shaders/ShaderChunk/normal_phong_fragment.glsl
20034 
20035 THREE.ShaderChunk[ 'normal_phong_fragment'] = "#ifndef FLAT_SHADED\n\n vec3 normal = normalize( vNormal );\n\n #ifdef DOUBLE_SIDED\n\n normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n\n #endif\n\n#else\n\n vec3 fdx = dFdx( vViewPosition );\n vec3 fdy = dFdy( vViewPosition );\n vec3 normal = normalize( cross( fdx, fdy ) );\n\n#endif\n\n#ifdef USE_NORMALMAP\n\n normal = perturbNormal2Arb( -vViewPosition, normal );\n\n#elif defined( USE_BUMPMAP )\n\n normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n\n#endif\n\n";
20036 
20037 // File:src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl
20038 
20039 THREE.ShaderChunk[ 'normalmap_pars_fragment'] = "#ifdef USE_NORMALMAP\n\n uniform sampler2D normalMap;\n uniform vec2 normalScale;\n\n\n vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\n vec3 q0 = dFdx( eye_pos.xyz );\n vec3 q1 = dFdy( eye_pos.xyz );\n vec2 st0 = dFdx( vUv.st );\n vec2 st1 = dFdy( vUv.st );\n\n vec3 S = normalize( q0 * st1.t - q1 * st0.t );\n vec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n vec3 N = normalize( surf_norm );\n\n vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n mapN.xy = normalScale * mapN.xy;\n mat3 tsn = mat3( S, T, N );\n return normalize( tsn * mapN );\n\n }\n\n#endif\n";
20040 
20041 // File:src/renderers/shaders/ShaderChunk/project_vertex.glsl
20042 
20043 THREE.ShaderChunk[ 'project_vertex'] = "#ifdef USE_SKINNING\n\n vec4 mvPosition = modelViewMatrix * skinned;\n\n#else\n\n vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\n\n#endif\n\ngl_Position = projectionMatrix * mvPosition;\n";
20044 
20045 // File:src/renderers/shaders/ShaderChunk/shadowmap_fragment.glsl
20046 
20047 THREE.ShaderChunk[ 'shadowmap_fragment'] = "#ifdef USE_SHADOWMAP\n\n for ( int i = 0; i < MAX_SHADOWS; i ++ ) {\n\n float texelSizeY = 1.0 / shadowMapSize[ i ].y;\n\n float shadow = 0.0;\n\n#if defined( POINT_LIGHT_SHADOWS )\n\n bool isPointLight = shadowDarkness[ i ] < 0.0;\n\n if ( isPointLight ) {\n\n float realShadowDarkness = abs( shadowDarkness[ i ] );\n\n vec3 lightToPosition = vShadowCoord[ i ].xyz;\n\n #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\n vec3 bd3D = normalize( lightToPosition );\n float dp = length( lightToPosition );\n\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );\n\n\n #if defined( SHADOWMAP_TYPE_PCF )\n const float Dr = 1.25;\n #elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n const float Dr = 2.25;\n #endif\n\n float os = Dr * 2.0 * texelSizeY;\n\n const vec3 Gsd = vec3( - 1, 0, 1 );\n\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzz * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxz * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxz * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzz * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzx * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxx * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxx * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzx * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzy * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxy * os, texelSizeY ) ), shadowBias[ i ], shadow );\n\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxy * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzy * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zyz * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xyz * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zyx * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xyx * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yzz * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yxz * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yxx * os, texelSizeY ) ), shadowBias[ i ], shadow );\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yzx * os, texelSizeY ) ), shadowBias[ i ], shadow );\n\n shadow *= realShadowDarkness * ( 1.0 / 21.0 );\n\n #else \n vec3 bd3D = normalize( lightToPosition );\n float dp = length( lightToPosition );\n\n adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );\n\n shadow *= realShadowDarkness;\n\n #endif\n\n } else {\n\n#endif \n float texelSizeX = 1.0 / shadowMapSize[ i ].x;\n\n vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;\n\n\n bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n bool inFrustum = all( inFrustumVec );\n\n bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\n bool frustumTest = all( frustumTestVec );\n\n if ( frustumTest ) {\n\n #if defined( SHADOWMAP_TYPE_PCF )\n\n\n /*\n for ( float y = -1.25; y <= 1.25; y += 1.25 )\n for ( float x = -1.25; x <= 1.25; x += 1.25 ) {\n vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );\n float fDepth = unpackDepth( rgbaDepth );\n if ( fDepth < shadowCoord.z )\n shadow += 1.0;\n }\n shadow /= 9.0;\n */\n\n shadowCoord.z += shadowBias[ i ];\n\n const float ShadowDelta = 1.0 / 9.0;\n\n float xPixelOffset = texelSizeX;\n float yPixelOffset = texelSizeY;\n\n float dx0 = - 1.25 * xPixelOffset;\n float dy0 = - 1.25 * yPixelOffset;\n float dx1 = 1.25 * xPixelOffset;\n float dy1 = 1.25 * yPixelOffset;\n\n float fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\n if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;\n\n fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\n if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;\n\n shadow *= shadowDarkness[ i ];\n\n #elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\n\n shadowCoord.z += shadowBias[ i ];\n\n float xPixelOffset = texelSizeX;\n float yPixelOffset = texelSizeY;\n\n float dx0 = - 1.0 * xPixelOffset;\n float dy0 = - 1.0 * yPixelOffset;\n float dx1 = 1.0 * xPixelOffset;\n float dy1 = 1.0 * yPixelOffset;\n\n mat3 shadowKernel;\n mat3 depthKernel;\n\n depthKernel[ 0 ][ 0 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );\n depthKernel[ 0 ][ 1 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );\n depthKernel[ 0 ][ 2 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );\n depthKernel[ 1 ][ 0 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );\n depthKernel[ 1 ][ 1 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );\n depthKernel[ 1 ][ 2 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );\n depthKernel[ 2 ][ 0 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );\n depthKernel[ 2 ][ 1 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );\n depthKernel[ 2 ][ 2 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );\n\n vec3 shadowZ = vec3( shadowCoord.z );\n shadowKernel[ 0 ] = vec3( lessThan( depthKernel[ 0 ], shadowZ ) );\n shadowKernel[ 0 ] *= vec3( 0.25 );\n\n shadowKernel[ 1 ] = vec3( lessThan( depthKernel[ 1 ], shadowZ ) );\n shadowKernel[ 1 ] *= vec3( 0.25 );\n\n shadowKernel[ 2 ] = vec3( lessThan( depthKernel[ 2 ], shadowZ ) );\n shadowKernel[ 2 ] *= vec3( 0.25 );\n\n vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[ i ].xy );\n\n shadowKernel[ 0 ] = mix( shadowKernel[ 1 ], shadowKernel[ 0 ], fractionalCoord.x );\n shadowKernel[ 1 ] = mix( shadowKernel[ 2 ], shadowKernel[ 1 ], fractionalCoord.x );\n\n vec4 shadowValues;\n shadowValues.x = mix( shadowKernel[ 0 ][ 1 ], shadowKernel[ 0 ][ 0 ], fractionalCoord.y );\n shadowValues.y = mix( shadowKernel[ 0 ][ 2 ], shadowKernel[ 0 ][ 1 ], fractionalCoord.y );\n shadowValues.z = mix( shadowKernel[ 1 ][ 1 ], shadowKernel[ 1 ][ 0 ], fractionalCoord.y );\n shadowValues.w = mix( shadowKernel[ 1 ][ 2 ], shadowKernel[ 1 ][ 1 ], fractionalCoord.y );\n\n shadow = dot( shadowValues, vec4( 1.0 ) ) * shadowDarkness[ i ];\n\n #else \n shadowCoord.z += shadowBias[ i ];\n\n vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );\n float fDepth = unpackDepth( rgbaDepth );\n\n if ( fDepth < shadowCoord.z )\n shadow = shadowDarkness[ i ];\n\n #endif\n\n }\n\n#ifdef SHADOWMAP_DEBUG\n\n if ( inFrustum ) {\n\n if ( i == 0 ) {\n\n outgoingLight *= vec3( 1.0, 0.5, 0.0 );\n\n } else if ( i == 1 ) {\n\n outgoingLight *= vec3( 0.0, 1.0, 0.8 );\n\n } else {\n\n outgoingLight *= vec3( 0.0, 0.5, 1.0 );\n\n }\n\n }\n\n#endif\n\n#if defined( POINT_LIGHT_SHADOWS )\n\n }\n\n#endif\n\n shadowMask = shadowMask * vec3( 1.0 - shadow );\n\n }\n\n#endif\n";
20048 
20049 // File:src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl
20050 
20051 THREE.ShaderChunk[ 'shadowmap_pars_fragment'] = "#ifdef USE_SHADOWMAP\n\n uniform sampler2D shadowMap[ MAX_SHADOWS ];\n uniform vec2 shadowMapSize[ MAX_SHADOWS ];\n\n uniform float shadowDarkness[ MAX_SHADOWS ];\n uniform float shadowBias[ MAX_SHADOWS ];\n\n varying vec4 vShadowCoord[ MAX_SHADOWS ];\n\n float unpackDepth( const in vec4 rgba_depth ) {\n\n const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\n float depth = dot( rgba_depth, bit_shift );\n return depth;\n\n }\n\n #if defined(POINT_LIGHT_SHADOWS)\n\n\n void adjustShadowValue1K( const float testDepth, const vec4 textureData, const float bias, inout float shadowValue ) {\n\n const vec4 bitSh = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );\n if ( testDepth >= dot( textureData, bitSh ) * 1000.0 + bias )\n shadowValue += 1.0;\n\n }\n\n\n vec2 cubeToUV( vec3 v, float texelSizeY ) {\n\n\n vec3 absV = abs( v );\n\n\n float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n absV *= scaleToCube;\n\n\n v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\n\n\n vec2 planar = v.xy;\n\n float almostATexel = 1.5 * texelSizeY;\n float almostOne = 1.0 - almostATexel;\n\n if ( absV.z >= almostOne ) {\n\n if ( v.z > 0.0 )\n planar.x = 4.0 - v.x;\n\n } else if ( absV.x >= almostOne ) {\n\n float signX = sign( v.x );\n planar.x = v.z * signX + 2.0 * signX;\n\n } else if ( absV.y >= almostOne ) {\n\n float signY = sign( v.y );\n planar.x = v.x + 2.0 * signY + 2.0;\n planar.y = v.z * signY - 2.0;\n\n }\n\n\n return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\n }\n\n #endif\n\n#endif\n";
20052 
20053 // File:src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl
20054 
20055 THREE.ShaderChunk[ 'shadowmap_pars_vertex'] = "#ifdef USE_SHADOWMAP\n\n uniform float shadowDarkness[ MAX_SHADOWS ];\n uniform mat4 shadowMatrix[ MAX_SHADOWS ];\n varying vec4 vShadowCoord[ MAX_SHADOWS ];\n\n#endif";
20056 
20057 // File:src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl
20058 
20059 THREE.ShaderChunk[ 'shadowmap_vertex'] = "#ifdef USE_SHADOWMAP\n\n for ( int i = 0; i < MAX_SHADOWS; i ++ ) {\n\n vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;\n\n }\n\n#endif";
20060 
20061 // File:src/renderers/shaders/ShaderChunk/skinbase_vertex.glsl
20062 
20063 THREE.ShaderChunk[ 'skinbase_vertex'] = "#ifdef USE_SKINNING\n\n mat4 boneMatX = getBoneMatrix( skinIndex.x );\n mat4 boneMatY = getBoneMatrix( skinIndex.y );\n mat4 boneMatZ = getBoneMatrix( skinIndex.z );\n mat4 boneMatW = getBoneMatrix( skinIndex.w );\n\n#endif";
20064 
20065 // File:src/renderers/shaders/ShaderChunk/skinning_pars_vertex.glsl
20066 
20067 THREE.ShaderChunk[ 'skinning_pars_vertex'] = "#ifdef USE_SKINNING\n\n uniform mat4 bindMatrix;\n uniform mat4 bindMatrixInverse;\n\n #ifdef BONE_TEXTURE\n\n uniform sampler2D boneTexture;\n uniform int boneTextureWidth;\n uniform int boneTextureHeight;\n\n mat4 getBoneMatrix( const in float i ) {\n\n float j = i * 4.0;\n float x = mod( j, float( boneTextureWidth ) );\n float y = floor( j / float( boneTextureWidth ) );\n\n float dx = 1.0 / float( boneTextureWidth );\n float dy = 1.0 / float( boneTextureHeight );\n\n y = dy * ( y + 0.5 );\n\n vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\n mat4 bone = mat4( v1, v2, v3, v4 );\n\n return bone;\n\n }\n\n #else\n\n uniform mat4 boneGlobalMatrices[ MAX_BONES ];\n\n mat4 getBoneMatrix( const in float i ) {\n\n mat4 bone = boneGlobalMatrices[ int(i) ];\n return bone;\n\n }\n\n #endif\n\n#endif\n";
20068 
20069 // File:src/renderers/shaders/ShaderChunk/skinning_vertex.glsl
20070 
20071 THREE.ShaderChunk[ 'skinning_vertex'] = "#ifdef USE_SKINNING\n\n vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\n vec4 skinned = vec4( 0.0 );\n skinned += boneMatX * skinVertex * skinWeight.x;\n skinned += boneMatY * skinVertex * skinWeight.y;\n skinned += boneMatZ * skinVertex * skinWeight.z;\n skinned += boneMatW * skinVertex * skinWeight.w;\n skinned = bindMatrixInverse * skinned;\n\n#endif\n";
20072 
20073 // File:src/renderers/shaders/ShaderChunk/skinnormal_vertex.glsl
20074 
20075 THREE.ShaderChunk[ 'skinnormal_vertex'] = "#ifdef USE_SKINNING\n\n mat4 skinMatrix = mat4( 0.0 );\n skinMatrix += skinWeight.x * boneMatX;\n skinMatrix += skinWeight.y * boneMatY;\n skinMatrix += skinWeight.z * boneMatZ;\n skinMatrix += skinWeight.w * boneMatW;\n skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\n objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\n#endif\n";
20076 
20077 // File:src/renderers/shaders/ShaderChunk/specularmap_fragment.glsl
20078 
20079 THREE.ShaderChunk[ 'specularmap_fragment'] = "float specularStrength;\n\n#ifdef USE_SPECULARMAP\n\n vec4 texelSpecular = texture2D( specularMap, vUv );\n specularStrength = texelSpecular.r;\n\n#else\n\n specularStrength = 1.0;\n\n#endif";
20080 
20081 // File:src/renderers/shaders/ShaderChunk/specularmap_pars_fragment.glsl
20082 
20083 THREE.ShaderChunk[ 'specularmap_pars_fragment'] = "#ifdef USE_SPECULARMAP\n\n uniform sampler2D specularMap;\n\n#endif";
20084 
20085 // File:src/renderers/shaders/ShaderChunk/uv2_pars_fragment.glsl
20086 
20087 THREE.ShaderChunk[ 'uv2_pars_fragment'] = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\n varying vec2 vUv2;\n\n#endif";
20088 
20089 // File:src/renderers/shaders/ShaderChunk/uv2_pars_vertex.glsl
20090 
20091 THREE.ShaderChunk[ 'uv2_pars_vertex'] = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\n attribute vec2 uv2;\n varying vec2 vUv2;\n\n#endif";
20092 
20093 // File:src/renderers/shaders/ShaderChunk/uv2_vertex.glsl
20094 
20095 THREE.ShaderChunk[ 'uv2_vertex'] = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\n vUv2 = uv2;\n\n#endif";
20096 
20097 // File:src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl
20098 
20099 THREE.ShaderChunk[ 'uv_pars_fragment'] = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP )\n\n varying vec2 vUv;\n\n#endif";
20100 
20101 // File:src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl
20102 
20103 THREE.ShaderChunk[ 'uv_pars_vertex'] = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP )\n\n varying vec2 vUv;\n uniform vec4 offsetRepeat;\n\n#endif\n";
20104 
20105 // File:src/renderers/shaders/ShaderChunk/uv_vertex.glsl
20106 
20107 THREE.ShaderChunk[ 'uv_vertex'] = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP )\n\n vUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n\n#endif";
20108 
20109 // File:src/renderers/shaders/ShaderChunk/worldpos_vertex.glsl
20110 
20111 THREE.ShaderChunk[ 'worldpos_vertex'] = "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n\n #ifdef USE_SKINNING\n\n vec4 worldPosition = modelMatrix * skinned;\n\n #else\n\n vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n\n #endif\n\n#endif\n";
20112 
20113 // File:src/renderers/shaders/UniformsUtils.js
20114 
20119 THREE.UniformsUtils = {
20120 
20121  merge: function ( uniforms ) {
20122 
20123  var merged = {};
20124 
20125  for ( var u = 0; u < uniforms.length; u ++ ) {
20126 
20127  var tmp = this.clone( uniforms[ u ] );
20128 
20129  for ( var p in tmp ) {
20130 
20131  merged[ p ] = tmp[ p ];
20132 
20133  }
20134 
20135  }
20136 
20137  return merged;
20138 
20139  },
20140 
20141  clone: function ( uniforms_src ) {
20142 
20143  var uniforms_dst = {};
20144 
20145  for ( var u in uniforms_src ) {
20146 
20147  uniforms_dst[ u ] = {};
20148 
20149  for ( var p in uniforms_src[ u ] ) {
20150 
20151  var parameter_src = uniforms_src[ u ][ p ];
20152 
20153  if ( parameter_src instanceof THREE.Color ||
20154  parameter_src instanceof THREE.Vector2 ||
20155  parameter_src instanceof THREE.Vector3 ||
20156  parameter_src instanceof THREE.Vector4 ||
20157  parameter_src instanceof THREE.Matrix3 ||
20158  parameter_src instanceof THREE.Matrix4 ||
20159  parameter_src instanceof THREE.Texture ) {
20160 
20161  uniforms_dst[ u ][ p ] = parameter_src.clone();
20162 
20163  } else if ( Array.isArray( parameter_src ) ) {
20164 
20165  uniforms_dst[ u ][ p ] = parameter_src.slice();
20166 
20167  } else {
20168 
20169  uniforms_dst[ u ][ p ] = parameter_src;
20170 
20171  }
20172 
20173  }
20174 
20175  }
20176 
20177  return uniforms_dst;
20178 
20179  }
20180 
20181 };
20182 
20183 // File:src/renderers/shaders/UniformsLib.js
20184 
20189 THREE.UniformsLib = {
20190 
20191  common: {
20192 
20193  "diffuse" : { type: "c", value: new THREE.Color( 0xeeeeee ) },
20194  "opacity" : { type: "f", value: 1.0 },
20195 
20196  "map" : { type: "t", value: null },
20197  "offsetRepeat" : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
20198 
20199  "specularMap" : { type: "t", value: null },
20200  "alphaMap" : { type: "t", value: null },
20201 
20202  "envMap" : { type: "t", value: null },
20203  "flipEnvMap" : { type: "f", value: - 1 },
20204  "reflectivity" : { type: "f", value: 1.0 },
20205  "refractionRatio" : { type: "f", value: 0.98 }
20206 
20207  },
20208 
20209  aomap: {
20210 
20211  "aoMap" : { type: "t", value: null },
20212  "aoMapIntensity" : { type: "f", value: 1 },
20213 
20214  },
20215 
20216  lightmap: {
20217 
20218  "lightMap" : { type: "t", value: null },
20219  "lightMapIntensity" : { type: "f", value: 1 },
20220 
20221  },
20222 
20223  emissivemap: {
20224 
20225  "emissiveMap" : { type: "t", value: null },
20226 
20227  },
20228 
20229  bumpmap: {
20230 
20231  "bumpMap" : { type: "t", value: null },
20232  "bumpScale" : { type: "f", value: 1 }
20233 
20234  },
20235 
20236  normalmap: {
20237 
20238  "normalMap" : { type: "t", value: null },
20239  "normalScale" : { type: "v2", value: new THREE.Vector2( 1, 1 ) }
20240 
20241  },
20242 
20243  displacementmap: {
20244 
20245  "displacementMap" : { type: "t", value: null },
20246  "displacementScale" : { type: "f", value: 1 },
20247  "displacementBias" : { type: "f", value: 0 }
20248 
20249  },
20250 
20251  fog : {
20252 
20253  "fogDensity" : { type: "f", value: 0.00025 },
20254  "fogNear" : { type: "f", value: 1 },
20255  "fogFar" : { type: "f", value: 2000 },
20256  "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) }
20257 
20258  },
20259 
20260  lights: {
20261 
20262  "ambientLightColor" : { type: "fv", value: [] },
20263 
20264  "directionalLightDirection" : { type: "fv", value: [] },
20265  "directionalLightColor" : { type: "fv", value: [] },
20266 
20267  "hemisphereLightDirection" : { type: "fv", value: [] },
20268  "hemisphereLightSkyColor" : { type: "fv", value: [] },
20269  "hemisphereLightGroundColor" : { type: "fv", value: [] },
20270 
20271  "pointLightColor" : { type: "fv", value: [] },
20272  "pointLightPosition" : { type: "fv", value: [] },
20273  "pointLightDistance" : { type: "fv1", value: [] },
20274  "pointLightDecay" : { type: "fv1", value: [] },
20275 
20276  "spotLightColor" : { type: "fv", value: [] },
20277  "spotLightPosition" : { type: "fv", value: [] },
20278  "spotLightDirection" : { type: "fv", value: [] },
20279  "spotLightDistance" : { type: "fv1", value: [] },
20280  "spotLightAngleCos" : { type: "fv1", value: [] },
20281  "spotLightExponent" : { type: "fv1", value: [] },
20282  "spotLightDecay" : { type: "fv1", value: [] }
20283 
20284  },
20285 
20286  points: {
20287 
20288  "psColor" : { type: "c", value: new THREE.Color( 0xeeeeee ) },
20289  "opacity" : { type: "f", value: 1.0 },
20290  "size" : { type: "f", value: 1.0 },
20291  "scale" : { type: "f", value: 1.0 },
20292  "map" : { type: "t", value: null },
20293  "offsetRepeat" : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
20294 
20295  "fogDensity" : { type: "f", value: 0.00025 },
20296  "fogNear" : { type: "f", value: 1 },
20297  "fogFar" : { type: "f", value: 2000 },
20298  "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) }
20299 
20300  },
20301 
20302  shadowmap: {
20303 
20304  "shadowMap": { type: "tv", value: [] },
20305  "shadowMapSize": { type: "v2v", value: [] },
20306 
20307  "shadowBias" : { type: "fv1", value: [] },
20308  "shadowDarkness": { type: "fv1", value: [] },
20309 
20310  "shadowMatrix" : { type: "m4v", value: [] }
20311 
20312  }
20313 
20314 };
20315 
20316 // File:src/renderers/shaders/ShaderLib.js
20317 
20327 THREE.ShaderLib = {
20328 
20329  'basic': {
20330 
20331  uniforms: THREE.UniformsUtils.merge( [
20332 
20333  THREE.UniformsLib[ "common" ],
20334  THREE.UniformsLib[ "aomap" ],
20335  THREE.UniformsLib[ "fog" ],
20336  THREE.UniformsLib[ "shadowmap" ]
20337 
20338  ] ),
20339 
20340  vertexShader: [
20341 
20342  THREE.ShaderChunk[ "common" ],
20343  THREE.ShaderChunk[ "uv_pars_vertex" ],
20344  THREE.ShaderChunk[ "uv2_pars_vertex" ],
20345  THREE.ShaderChunk[ "envmap_pars_vertex" ],
20346  THREE.ShaderChunk[ "color_pars_vertex" ],
20347  THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
20348  THREE.ShaderChunk[ "skinning_pars_vertex" ],
20349  THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
20350  THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],
20351 
20352  "void main() {",
20353 
20354  THREE.ShaderChunk[ "uv_vertex" ],
20355  THREE.ShaderChunk[ "uv2_vertex" ],
20356  THREE.ShaderChunk[ "color_vertex" ],
20357  THREE.ShaderChunk[ "skinbase_vertex" ],
20358 
20359  " #ifdef USE_ENVMAP",
20360 
20361  THREE.ShaderChunk[ "beginnormal_vertex" ],
20362  THREE.ShaderChunk[ "morphnormal_vertex" ],
20363  THREE.ShaderChunk[ "skinnormal_vertex" ],
20364  THREE.ShaderChunk[ "defaultnormal_vertex" ],
20365 
20366  " #endif",
20367 
20368  THREE.ShaderChunk[ "begin_vertex" ],
20369  THREE.ShaderChunk[ "morphtarget_vertex" ],
20370  THREE.ShaderChunk[ "skinning_vertex" ],
20371  THREE.ShaderChunk[ "project_vertex" ],
20372  THREE.ShaderChunk[ "logdepthbuf_vertex" ],
20373 
20374  THREE.ShaderChunk[ "worldpos_vertex" ],
20375  THREE.ShaderChunk[ "envmap_vertex" ],
20376  THREE.ShaderChunk[ "shadowmap_vertex" ],
20377 
20378  "}"
20379 
20380  ].join( "\n" ),
20381 
20382  fragmentShader: [
20383 
20384  "uniform vec3 diffuse;",
20385  "uniform float opacity;",
20386 
20387  THREE.ShaderChunk[ "common" ],
20388  THREE.ShaderChunk[ "color_pars_fragment" ],
20389  THREE.ShaderChunk[ "uv_pars_fragment" ],
20390  THREE.ShaderChunk[ "uv2_pars_fragment" ],
20391  THREE.ShaderChunk[ "map_pars_fragment" ],
20392  THREE.ShaderChunk[ "alphamap_pars_fragment" ],
20393  THREE.ShaderChunk[ "aomap_pars_fragment" ],
20394  THREE.ShaderChunk[ "envmap_pars_fragment" ],
20395  THREE.ShaderChunk[ "fog_pars_fragment" ],
20396  THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
20397  THREE.ShaderChunk[ "specularmap_pars_fragment" ],
20398  THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
20399 
20400  "void main() {",
20401 
20402  " vec3 outgoingLight = vec3( 0.0 );",
20403  " vec4 diffuseColor = vec4( diffuse, opacity );",
20404  " vec3 totalAmbientLight = vec3( 1.0 );", // hardwired
20405  " vec3 shadowMask = vec3( 1.0 );",
20406 
20407  THREE.ShaderChunk[ "logdepthbuf_fragment" ],
20408  THREE.ShaderChunk[ "map_fragment" ],
20409  THREE.ShaderChunk[ "color_fragment" ],
20410  THREE.ShaderChunk[ "alphamap_fragment" ],
20411  THREE.ShaderChunk[ "alphatest_fragment" ],
20412  THREE.ShaderChunk[ "specularmap_fragment" ],
20413  THREE.ShaderChunk[ "aomap_fragment" ],
20414  THREE.ShaderChunk[ "shadowmap_fragment" ],
20415 
20416  " outgoingLight = diffuseColor.rgb * totalAmbientLight * shadowMask;",
20417 
20418  THREE.ShaderChunk[ "envmap_fragment" ],
20419 
20420  THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
20421 
20422  THREE.ShaderChunk[ "fog_fragment" ],
20423 
20424  " gl_FragColor = vec4( outgoingLight, diffuseColor.a );",
20425 
20426  "}"
20427 
20428  ].join( "\n" )
20429 
20430  },
20431 
20432  'lambert': {
20433 
20434  uniforms: THREE.UniformsUtils.merge( [
20435 
20436  THREE.UniformsLib[ "common" ],
20437  THREE.UniformsLib[ "fog" ],
20438  THREE.UniformsLib[ "lights" ],
20439  THREE.UniformsLib[ "shadowmap" ],
20440 
20441  {
20442  "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) }
20443  }
20444 
20445  ] ),
20446 
20447  vertexShader: [
20448 
20449  "#define LAMBERT",
20450 
20451  "varying vec3 vLightFront;",
20452 
20453  "#ifdef DOUBLE_SIDED",
20454 
20455  " varying vec3 vLightBack;",
20456 
20457  "#endif",
20458 
20459  THREE.ShaderChunk[ "common" ],
20460  THREE.ShaderChunk[ "uv_pars_vertex" ],
20461  THREE.ShaderChunk[ "uv2_pars_vertex" ],
20462  THREE.ShaderChunk[ "envmap_pars_vertex" ],
20463  THREE.ShaderChunk[ "lights_lambert_pars_vertex" ],
20464  THREE.ShaderChunk[ "color_pars_vertex" ],
20465  THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
20466  THREE.ShaderChunk[ "skinning_pars_vertex" ],
20467  THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
20468  THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],
20469 
20470  "void main() {",
20471 
20472  THREE.ShaderChunk[ "uv_vertex" ],
20473  THREE.ShaderChunk[ "uv2_vertex" ],
20474  THREE.ShaderChunk[ "color_vertex" ],
20475 
20476  THREE.ShaderChunk[ "beginnormal_vertex" ],
20477  THREE.ShaderChunk[ "morphnormal_vertex" ],
20478  THREE.ShaderChunk[ "skinbase_vertex" ],
20479  THREE.ShaderChunk[ "skinnormal_vertex" ],
20480  THREE.ShaderChunk[ "defaultnormal_vertex" ],
20481 
20482  THREE.ShaderChunk[ "begin_vertex" ],
20483  THREE.ShaderChunk[ "morphtarget_vertex" ],
20484  THREE.ShaderChunk[ "skinning_vertex" ],
20485  THREE.ShaderChunk[ "project_vertex" ],
20486  THREE.ShaderChunk[ "logdepthbuf_vertex" ],
20487 
20488  THREE.ShaderChunk[ "worldpos_vertex" ],
20489  THREE.ShaderChunk[ "envmap_vertex" ],
20490  THREE.ShaderChunk[ "lights_lambert_vertex" ],
20491  THREE.ShaderChunk[ "shadowmap_vertex" ],
20492 
20493  "}"
20494 
20495  ].join( "\n" ),
20496 
20497  fragmentShader: [
20498 
20499  "uniform vec3 diffuse;",
20500  "uniform vec3 emissive;",
20501  "uniform float opacity;",
20502 
20503  "uniform vec3 ambientLightColor;",
20504 
20505  "varying vec3 vLightFront;",
20506 
20507  "#ifdef DOUBLE_SIDED",
20508 
20509  " varying vec3 vLightBack;",
20510 
20511  "#endif",
20512 
20513  THREE.ShaderChunk[ "common" ],
20514  THREE.ShaderChunk[ "color_pars_fragment" ],
20515  THREE.ShaderChunk[ "uv_pars_fragment" ],
20516  THREE.ShaderChunk[ "uv2_pars_fragment" ],
20517  THREE.ShaderChunk[ "map_pars_fragment" ],
20518  THREE.ShaderChunk[ "alphamap_pars_fragment" ],
20519  THREE.ShaderChunk[ "envmap_pars_fragment" ],
20520  THREE.ShaderChunk[ "fog_pars_fragment" ],
20521  THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
20522  THREE.ShaderChunk[ "specularmap_pars_fragment" ],
20523  THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
20524 
20525  "void main() {",
20526 
20527  " vec3 outgoingLight = vec3( 0.0 );", // outgoing light does not have an alpha, the surface does
20528  " vec4 diffuseColor = vec4( diffuse, opacity );",
20529  " vec3 totalAmbientLight = ambientLightColor;",
20530  " vec3 shadowMask = vec3( 1.0 );",
20531 
20532  THREE.ShaderChunk[ "logdepthbuf_fragment" ],
20533  THREE.ShaderChunk[ "map_fragment" ],
20534  THREE.ShaderChunk[ "color_fragment" ],
20535  THREE.ShaderChunk[ "alphamap_fragment" ],
20536  THREE.ShaderChunk[ "alphatest_fragment" ],
20537  THREE.ShaderChunk[ "specularmap_fragment" ],
20538  THREE.ShaderChunk[ "shadowmap_fragment" ],
20539 
20540  " #ifdef DOUBLE_SIDED",
20541 
20542  " if ( gl_FrontFacing )",
20543  " outgoingLight += diffuseColor.rgb * ( vLightFront * shadowMask + totalAmbientLight ) + emissive;",
20544  " else",
20545  " outgoingLight += diffuseColor.rgb * ( vLightBack * shadowMask + totalAmbientLight ) + emissive;",
20546 
20547  " #else",
20548 
20549  " outgoingLight += diffuseColor.rgb * ( vLightFront * shadowMask + totalAmbientLight ) + emissive;",
20550 
20551  " #endif",
20552 
20553  THREE.ShaderChunk[ "envmap_fragment" ],
20554 
20555  THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
20556 
20557  THREE.ShaderChunk[ "fog_fragment" ],
20558 
20559  " gl_FragColor = vec4( outgoingLight, diffuseColor.a );",
20560 
20561  "}"
20562 
20563  ].join( "\n" )
20564 
20565  },
20566 
20567  'phong': {
20568 
20569  uniforms: THREE.UniformsUtils.merge( [
20570 
20571  THREE.UniformsLib[ "common" ],
20572  THREE.UniformsLib[ "aomap" ],
20573  THREE.UniformsLib[ "lightmap" ],
20574  THREE.UniformsLib[ "emissivemap" ],
20575  THREE.UniformsLib[ "bumpmap" ],
20576  THREE.UniformsLib[ "normalmap" ],
20577  THREE.UniformsLib[ "displacementmap" ],
20578  THREE.UniformsLib[ "fog" ],
20579  THREE.UniformsLib[ "lights" ],
20580  THREE.UniformsLib[ "shadowmap" ],
20581 
20582  {
20583  "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
20584  "specular" : { type: "c", value: new THREE.Color( 0x111111 ) },
20585  "shininess": { type: "f", value: 30 }
20586  }
20587 
20588  ] ),
20589 
20590  vertexShader: [
20591 
20592  "#define PHONG",
20593 
20594  "varying vec3 vViewPosition;",
20595 
20596  "#ifndef FLAT_SHADED",
20597 
20598  " varying vec3 vNormal;",
20599 
20600  "#endif",
20601 
20602  THREE.ShaderChunk[ "common" ],
20603  THREE.ShaderChunk[ "uv_pars_vertex" ],
20604  THREE.ShaderChunk[ "uv2_pars_vertex" ],
20605  THREE.ShaderChunk[ "displacementmap_pars_vertex" ],
20606  THREE.ShaderChunk[ "envmap_pars_vertex" ],
20607  THREE.ShaderChunk[ "lights_phong_pars_vertex" ],
20608  THREE.ShaderChunk[ "color_pars_vertex" ],
20609  THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
20610  THREE.ShaderChunk[ "skinning_pars_vertex" ],
20611  THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
20612  THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],
20613 
20614  "void main() {",
20615 
20616  THREE.ShaderChunk[ "uv_vertex" ],
20617  THREE.ShaderChunk[ "uv2_vertex" ],
20618  THREE.ShaderChunk[ "color_vertex" ],
20619 
20620  THREE.ShaderChunk[ "beginnormal_vertex" ],
20621  THREE.ShaderChunk[ "morphnormal_vertex" ],
20622  THREE.ShaderChunk[ "skinbase_vertex" ],
20623  THREE.ShaderChunk[ "skinnormal_vertex" ],
20624  THREE.ShaderChunk[ "defaultnormal_vertex" ],
20625 
20626  "#ifndef FLAT_SHADED", // Normal computed with derivatives when FLAT_SHADED
20627 
20628  " vNormal = normalize( transformedNormal );",
20629 
20630  "#endif",
20631 
20632  THREE.ShaderChunk[ "begin_vertex" ],
20633  THREE.ShaderChunk[ "displacementmap_vertex" ],
20634  THREE.ShaderChunk[ "morphtarget_vertex" ],
20635  THREE.ShaderChunk[ "skinning_vertex" ],
20636  THREE.ShaderChunk[ "project_vertex" ],
20637  THREE.ShaderChunk[ "logdepthbuf_vertex" ],
20638 
20639  " vViewPosition = - mvPosition.xyz;",
20640 
20641  THREE.ShaderChunk[ "worldpos_vertex" ],
20642  THREE.ShaderChunk[ "envmap_vertex" ],
20643  THREE.ShaderChunk[ "lights_phong_vertex" ],
20644  THREE.ShaderChunk[ "shadowmap_vertex" ],
20645 
20646  "}"
20647 
20648  ].join( "\n" ),
20649 
20650  fragmentShader: [
20651 
20652  "#define PHONG",
20653 
20654  "uniform vec3 diffuse;",
20655  "uniform vec3 emissive;",
20656  "uniform vec3 specular;",
20657  "uniform float shininess;",
20658  "uniform float opacity;",
20659 
20660  THREE.ShaderChunk[ "common" ],
20661  THREE.ShaderChunk[ "color_pars_fragment" ],
20662  THREE.ShaderChunk[ "uv_pars_fragment" ],
20663  THREE.ShaderChunk[ "uv2_pars_fragment" ],
20664  THREE.ShaderChunk[ "map_pars_fragment" ],
20665  THREE.ShaderChunk[ "alphamap_pars_fragment" ],
20666  THREE.ShaderChunk[ "aomap_pars_fragment" ],
20667  THREE.ShaderChunk[ "lightmap_pars_fragment" ],
20668  THREE.ShaderChunk[ "emissivemap_pars_fragment" ],
20669  THREE.ShaderChunk[ "envmap_pars_fragment" ],
20670  THREE.ShaderChunk[ "fog_pars_fragment" ],
20671  THREE.ShaderChunk[ "lights_phong_pars_fragment" ],
20672  THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
20673  THREE.ShaderChunk[ "bumpmap_pars_fragment" ],
20674  THREE.ShaderChunk[ "normalmap_pars_fragment" ],
20675  THREE.ShaderChunk[ "specularmap_pars_fragment" ],
20676  THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
20677 
20678  "void main() {",
20679 
20680  " vec3 outgoingLight = vec3( 0.0 );",
20681  " vec4 diffuseColor = vec4( diffuse, opacity );",
20682  " vec3 totalAmbientLight = ambientLightColor;",
20683  " vec3 totalEmissiveLight = emissive;",
20684  " vec3 shadowMask = vec3( 1.0 );",
20685 
20686  THREE.ShaderChunk[ "logdepthbuf_fragment" ],
20687  THREE.ShaderChunk[ "map_fragment" ],
20688  THREE.ShaderChunk[ "color_fragment" ],
20689  THREE.ShaderChunk[ "alphamap_fragment" ],
20690  THREE.ShaderChunk[ "alphatest_fragment" ],
20691  THREE.ShaderChunk[ "specularmap_fragment" ],
20692  THREE.ShaderChunk[ "normal_phong_fragment" ],
20693  THREE.ShaderChunk[ "lightmap_fragment" ],
20694  THREE.ShaderChunk[ "hemilight_fragment" ],
20695  THREE.ShaderChunk[ "aomap_fragment" ],
20696  THREE.ShaderChunk[ "emissivemap_fragment" ],
20697 
20698  THREE.ShaderChunk[ "lights_phong_fragment" ],
20699  THREE.ShaderChunk[ "shadowmap_fragment" ],
20700 
20701  "totalDiffuseLight *= shadowMask;",
20702  "totalSpecularLight *= shadowMask;",
20703 
20704  "#ifdef METAL",
20705 
20706  " outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalAmbientLight ) * specular + totalSpecularLight + totalEmissiveLight;",
20707 
20708  "#else",
20709 
20710  " outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalAmbientLight ) + totalSpecularLight + totalEmissiveLight;",
20711 
20712  "#endif",
20713 
20714  THREE.ShaderChunk[ "envmap_fragment" ],
20715 
20716  THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
20717 
20718  THREE.ShaderChunk[ "fog_fragment" ],
20719 
20720  " gl_FragColor = vec4( outgoingLight, diffuseColor.a );",
20721 
20722  "}"
20723 
20724  ].join( "\n" )
20725 
20726  },
20727 
20728  'points': {
20729 
20730  uniforms: THREE.UniformsUtils.merge( [
20731 
20732  THREE.UniformsLib[ "points" ],
20733  THREE.UniformsLib[ "shadowmap" ]
20734 
20735  ] ),
20736 
20737  vertexShader: [
20738 
20739  "uniform float size;",
20740  "uniform float scale;",
20741 
20742  THREE.ShaderChunk[ "common" ],
20743  THREE.ShaderChunk[ "color_pars_vertex" ],
20744  THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
20745  THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],
20746 
20747  "void main() {",
20748 
20749  THREE.ShaderChunk[ "color_vertex" ],
20750 
20751  " vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
20752 
20753  " #ifdef USE_SIZEATTENUATION",
20754  " gl_PointSize = size * ( scale / length( mvPosition.xyz ) );",
20755  " #else",
20756  " gl_PointSize = size;",
20757  " #endif",
20758 
20759  " gl_Position = projectionMatrix * mvPosition;",
20760 
20761  THREE.ShaderChunk[ "logdepthbuf_vertex" ],
20762  THREE.ShaderChunk[ "worldpos_vertex" ],
20763  THREE.ShaderChunk[ "shadowmap_vertex" ],
20764 
20765  "}"
20766 
20767  ].join( "\n" ),
20768 
20769  fragmentShader: [
20770 
20771  "uniform vec3 psColor;",
20772  "uniform float opacity;",
20773 
20774  THREE.ShaderChunk[ "common" ],
20775  THREE.ShaderChunk[ "color_pars_fragment" ],
20776  THREE.ShaderChunk[ "map_particle_pars_fragment" ],
20777  THREE.ShaderChunk[ "fog_pars_fragment" ],
20778  THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
20779  THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
20780 
20781  "void main() {",
20782 
20783  " vec3 outgoingLight = vec3( 0.0 );",
20784  " vec4 diffuseColor = vec4( psColor, opacity );",
20785  " vec3 shadowMask = vec3( 1.0 );",
20786 
20787  THREE.ShaderChunk[ "logdepthbuf_fragment" ],
20788  THREE.ShaderChunk[ "map_particle_fragment" ],
20789  THREE.ShaderChunk[ "color_fragment" ],
20790  THREE.ShaderChunk[ "alphatest_fragment" ],
20791  THREE.ShaderChunk[ "shadowmap_fragment" ],
20792 
20793  " outgoingLight = diffuseColor.rgb * shadowMask;",
20794 
20795  THREE.ShaderChunk[ "fog_fragment" ],
20796 
20797  " gl_FragColor = vec4( outgoingLight, diffuseColor.a );",
20798 
20799  "}"
20800 
20801  ].join( "\n" )
20802 
20803  },
20804 
20805  'dashed': {
20806 
20807  uniforms: THREE.UniformsUtils.merge( [
20808 
20809  THREE.UniformsLib[ "common" ],
20810  THREE.UniformsLib[ "fog" ],
20811 
20812  {
20813  "scale" : { type: "f", value: 1 },
20814  "dashSize" : { type: "f", value: 1 },
20815  "totalSize": { type: "f", value: 2 }
20816  }
20817 
20818  ] ),
20819 
20820  vertexShader: [
20821 
20822  "uniform float scale;",
20823  "attribute float lineDistance;",
20824 
20825  "varying float vLineDistance;",
20826 
20827  THREE.ShaderChunk[ "common" ],
20828  THREE.ShaderChunk[ "color_pars_vertex" ],
20829  THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],
20830 
20831  "void main() {",
20832 
20833  THREE.ShaderChunk[ "color_vertex" ],
20834 
20835  " vLineDistance = scale * lineDistance;",
20836 
20837  " vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
20838  " gl_Position = projectionMatrix * mvPosition;",
20839 
20840  THREE.ShaderChunk[ "logdepthbuf_vertex" ],
20841 
20842  "}"
20843 
20844  ].join( "\n" ),
20845 
20846  fragmentShader: [
20847 
20848  "uniform vec3 diffuse;",
20849  "uniform float opacity;",
20850 
20851  "uniform float dashSize;",
20852  "uniform float totalSize;",
20853 
20854  "varying float vLineDistance;",
20855 
20856  THREE.ShaderChunk[ "common" ],
20857  THREE.ShaderChunk[ "color_pars_fragment" ],
20858  THREE.ShaderChunk[ "fog_pars_fragment" ],
20859  THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
20860 
20861  "void main() {",
20862 
20863  " if ( mod( vLineDistance, totalSize ) > dashSize ) {",
20864 
20865  " discard;",
20866 
20867  " }",
20868 
20869  " vec3 outgoingLight = vec3( 0.0 );",
20870  " vec4 diffuseColor = vec4( diffuse, opacity );",
20871 
20872  THREE.ShaderChunk[ "logdepthbuf_fragment" ],
20873  THREE.ShaderChunk[ "color_fragment" ],
20874 
20875  " outgoingLight = diffuseColor.rgb;", // simple shader
20876 
20877  THREE.ShaderChunk[ "fog_fragment" ],
20878 
20879  " gl_FragColor = vec4( outgoingLight, diffuseColor.a );",
20880 
20881  "}"
20882 
20883  ].join( "\n" )
20884 
20885  },
20886 
20887  'depth': {
20888 
20889  uniforms: {
20890 
20891  "mNear": { type: "f", value: 1.0 },
20892  "mFar" : { type: "f", value: 2000.0 },
20893  "opacity" : { type: "f", value: 1.0 }
20894 
20895  },
20896 
20897  vertexShader: [
20898 
20899  THREE.ShaderChunk[ "common" ],
20900  THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
20901  THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],
20902 
20903  "void main() {",
20904 
20905  THREE.ShaderChunk[ "begin_vertex" ],
20906  THREE.ShaderChunk[ "morphtarget_vertex" ],
20907  THREE.ShaderChunk[ "project_vertex" ],
20908  THREE.ShaderChunk[ "logdepthbuf_vertex" ],
20909 
20910  "}"
20911 
20912  ].join( "\n" ),
20913 
20914  fragmentShader: [
20915 
20916  "uniform float mNear;",
20917  "uniform float mFar;",
20918  "uniform float opacity;",
20919 
20920  THREE.ShaderChunk[ "common" ],
20921  THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
20922 
20923  "void main() {",
20924 
20925  THREE.ShaderChunk[ "logdepthbuf_fragment" ],
20926 
20927  " #ifdef USE_LOGDEPTHBUF_EXT",
20928 
20929  " float depth = gl_FragDepthEXT / gl_FragCoord.w;",
20930 
20931  " #else",
20932 
20933  " float depth = gl_FragCoord.z / gl_FragCoord.w;",
20934 
20935  " #endif",
20936 
20937  " float color = 1.0 - smoothstep( mNear, mFar, depth );",
20938  " gl_FragColor = vec4( vec3( color ), opacity );",
20939 
20940  "}"
20941 
20942  ].join( "\n" )
20943 
20944  },
20945 
20946  'normal': {
20947 
20948  uniforms: {
20949 
20950  "opacity" : { type: "f", value: 1.0 }
20951 
20952  },
20953 
20954  vertexShader: [
20955 
20956  "varying vec3 vNormal;",
20957 
20958  THREE.ShaderChunk[ "common" ],
20959  THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
20960  THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],
20961 
20962  "void main() {",
20963 
20964  " vNormal = normalize( normalMatrix * normal );",
20965 
20966  THREE.ShaderChunk[ "begin_vertex" ],
20967  THREE.ShaderChunk[ "morphtarget_vertex" ],
20968  THREE.ShaderChunk[ "project_vertex" ],
20969  THREE.ShaderChunk[ "logdepthbuf_vertex" ],
20970 
20971  "}"
20972 
20973  ].join( "\n" ),
20974 
20975  fragmentShader: [
20976 
20977  "uniform float opacity;",
20978  "varying vec3 vNormal;",
20979 
20980  THREE.ShaderChunk[ "common" ],
20981  THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
20982 
20983  "void main() {",
20984 
20985  " gl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );",
20986 
20987  THREE.ShaderChunk[ "logdepthbuf_fragment" ],
20988 
20989  "}"
20990 
20991  ].join( "\n" )
20992 
20993  },
20994 
20995  /* -------------------------------------------------------------------------
20996  // Cube map shader
20997  ------------------------------------------------------------------------- */
20998 
20999  'cube': {
21000 
21001  uniforms: { "tCube": { type: "t", value: null },
21002  "tFlip": { type: "f", value: - 1 } },
21003 
21004  vertexShader: [
21005 
21006  "varying vec3 vWorldPosition;",
21007 
21008  THREE.ShaderChunk[ "common" ],
21009  THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],
21010 
21011  "void main() {",
21012 
21013  " vWorldPosition = transformDirection( position, modelMatrix );",
21014 
21015  " gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
21016 
21017  THREE.ShaderChunk[ "logdepthbuf_vertex" ],
21018 
21019  "}"
21020 
21021  ].join( "\n" ),
21022 
21023  fragmentShader: [
21024 
21025  "uniform samplerCube tCube;",
21026  "uniform float tFlip;",
21027 
21028  "varying vec3 vWorldPosition;",
21029 
21030  THREE.ShaderChunk[ "common" ],
21031  THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
21032 
21033  "void main() {",
21034 
21035  " gl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );",
21036 
21037  THREE.ShaderChunk[ "logdepthbuf_fragment" ],
21038 
21039  "}"
21040 
21041  ].join( "\n" )
21042 
21043  },
21044 
21045  /* -------------------------------------------------------------------------
21046  // Cube map shader
21047  ------------------------------------------------------------------------- */
21048 
21049  'equirect': {
21050 
21051  uniforms: { "tEquirect": { type: "t", value: null },
21052  "tFlip": { type: "f", value: - 1 } },
21053 
21054  vertexShader: [
21055 
21056  "varying vec3 vWorldPosition;",
21057 
21058  THREE.ShaderChunk[ "common" ],
21059  THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],
21060 
21061  "void main() {",
21062 
21063  " vWorldPosition = transformDirection( position, modelMatrix );",
21064 
21065  " gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
21066 
21067  THREE.ShaderChunk[ "logdepthbuf_vertex" ],
21068 
21069  "}"
21070 
21071  ].join( "\n" ),
21072 
21073  fragmentShader: [
21074 
21075  "uniform sampler2D tEquirect;",
21076  "uniform float tFlip;",
21077 
21078  "varying vec3 vWorldPosition;",
21079 
21080  THREE.ShaderChunk[ "common" ],
21081  THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
21082 
21083  "void main() {",
21084 
21085  // " gl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );",
21086  "vec3 direction = normalize( vWorldPosition );",
21087  "vec2 sampleUV;",
21088  "sampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );",
21089  "sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;",
21090  "gl_FragColor = texture2D( tEquirect, sampleUV );",
21091 
21092  THREE.ShaderChunk[ "logdepthbuf_fragment" ],
21093 
21094  "}"
21095 
21096  ].join( "\n" )
21097 
21098  },
21099 
21100  /* Depth encoding into RGBA texture
21101  *
21102  * based on SpiderGL shadow map example
21103  * http://spidergl.org/example.php?id=6
21104  *
21105  * originally from
21106  * http://www.gamedev.net/topic/442138-packing-a-float-into-a-a8r8g8b8-texture-shader/page__whichpage__1%25EF%25BF%25BD
21107  *
21108  * see also
21109  * http://aras-p.info/blog/2009/07/30/encoding-floats-to-rgba-the-final/
21110  */
21111 
21112  'depthRGBA': {
21113 
21114  uniforms: {},
21115 
21116  vertexShader: [
21117 
21118  THREE.ShaderChunk[ "common" ],
21119  THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
21120  THREE.ShaderChunk[ "skinning_pars_vertex" ],
21121  THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],
21122 
21123  "void main() {",
21124 
21125  THREE.ShaderChunk[ "skinbase_vertex" ],
21126 
21127  THREE.ShaderChunk[ "begin_vertex" ],
21128  THREE.ShaderChunk[ "morphtarget_vertex" ],
21129  THREE.ShaderChunk[ "skinning_vertex" ],
21130  THREE.ShaderChunk[ "project_vertex" ],
21131  THREE.ShaderChunk[ "logdepthbuf_vertex" ],
21132 
21133  "}"
21134 
21135  ].join( "\n" ),
21136 
21137  fragmentShader: [
21138 
21139  THREE.ShaderChunk[ "common" ],
21140  THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
21141 
21142  "vec4 pack_depth( const in float depth ) {",
21143 
21144  " const vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );",
21145  " const vec4 bit_mask = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );",
21146  " vec4 res = mod( depth * bit_shift * vec4( 255 ), vec4( 256 ) ) / vec4( 255 );", // " vec4 res = fract( depth * bit_shift );",
21147  " res -= res.xxyz * bit_mask;",
21148  " return res;",
21149 
21150  "}",
21151 
21152  "void main() {",
21153 
21154  THREE.ShaderChunk[ "logdepthbuf_fragment" ],
21155 
21156  " #ifdef USE_LOGDEPTHBUF_EXT",
21157 
21158  " gl_FragData[ 0 ] = pack_depth( gl_FragDepthEXT );",
21159 
21160  " #else",
21161 
21162  " gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );",
21163 
21164  " #endif",
21165 
21166  //"gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z / gl_FragCoord.w );",
21167  //"float z = ( ( gl_FragCoord.z / gl_FragCoord.w ) - 3.0 ) / ( 4000.0 - 3.0 );",
21168  //"gl_FragData[ 0 ] = pack_depth( z );",
21169  //"gl_FragData[ 0 ] = vec4( z, z, z, 1.0 );",
21170 
21171  "}"
21172 
21173  ].join( "\n" )
21174 
21175  },
21176 
21177 
21178  'distanceRGBA': {
21179 
21180  uniforms: {
21181 
21182  "lightPos": { type: "v3", value: new THREE.Vector3( 0, 0, 0 ) }
21183 
21184  },
21185 
21186  vertexShader: [
21187 
21188  "varying vec4 vWorldPosition;",
21189 
21190  THREE.ShaderChunk[ "common" ],
21191  THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
21192  THREE.ShaderChunk[ "skinning_pars_vertex" ],
21193 
21194  "void main() {",
21195 
21196  THREE.ShaderChunk[ "skinbase_vertex" ],
21197  THREE.ShaderChunk[ "begin_vertex" ],
21198  THREE.ShaderChunk[ "morphtarget_vertex" ],
21199  THREE.ShaderChunk[ "skinning_vertex" ],
21200  THREE.ShaderChunk[ "project_vertex" ],
21201  THREE.ShaderChunk[ "worldpos_vertex" ],
21202 
21203  "vWorldPosition = worldPosition;",
21204 
21205  "}"
21206 
21207  ].join( "\n" ),
21208 
21209  fragmentShader: [
21210 
21211  "uniform vec3 lightPos;",
21212  "varying vec4 vWorldPosition;",
21213 
21214  THREE.ShaderChunk[ "common" ],
21215 
21216  "vec4 pack1K ( float depth ) {",
21217 
21218  " depth /= 1000.0;",
21219  " const vec4 bitSh = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );",
21220  " const vec4 bitMsk = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );",
21221  " vec4 res = fract( depth * bitSh );",
21222  " res -= res.xxyz * bitMsk;",
21223  " return res; ",
21224 
21225  "}",
21226 
21227  "float unpack1K ( vec4 color ) {",
21228 
21229  " const vec4 bitSh = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );",
21230  " return dot( color, bitSh ) * 1000.0;",
21231 
21232  "}",
21233 
21234  "void main () {",
21235 
21236  " gl_FragColor = pack1K( length( vWorldPosition.xyz - lightPos.xyz ) );",
21237 
21238  "}"
21239 
21240  ].join( "\n" )
21241 
21242  }
21243 
21244 };
21245 
21246 // File:src/renderers/WebGLRenderer.js
21247 
21255 THREE.WebGLRenderer = function ( parameters ) {
21256 
21257  console.log( 'THREE.WebGLRenderer', THREE.REVISION );
21258 
21259  parameters = parameters || {};
21260 
21261  var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
21262  _context = parameters.context !== undefined ? parameters.context : null,
21263 
21264  _width = _canvas.width,
21265  _height = _canvas.height,
21266 
21267  pixelRatio = 1,
21268 
21269  _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
21270  _depth = parameters.depth !== undefined ? parameters.depth : true,
21271  _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
21272  _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
21273  _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
21274  _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
21275 
21276  _clearColor = new THREE.Color( 0x000000 ),
21277  _clearAlpha = 0;
21278 
21279  var lights = [];
21280 
21281  var opaqueObjects = [];
21282  var opaqueObjectsLastIndex = - 1;
21283  var transparentObjects = [];
21284  var transparentObjectsLastIndex = - 1;
21285 
21286  var morphInfluences = new Float32Array( 8 );
21287 
21288 
21289  var sprites = [];
21290  var lensFlares = [];
21291 
21292  // public properties
21293 
21294  this.domElement = _canvas;
21295  this.context = null;
21296 
21297  // clearing
21298 
21299  this.autoClear = true;
21300  this.autoClearColor = true;
21301  this.autoClearDepth = true;
21302  this.autoClearStencil = true;
21303 
21304  // scene graph
21305 
21306  this.sortObjects = true;
21307 
21308  // physically based shading
21309 
21310  this.gammaFactor = 2.0; // for backwards compatibility
21311  this.gammaInput = false;
21312  this.gammaOutput = false;
21313 
21314  // morphs
21315 
21316  this.maxMorphTargets = 8;
21317  this.maxMorphNormals = 4;
21318 
21319  // flags
21320 
21321  this.autoScaleCubemaps = true;
21322 
21323  // internal properties
21324 
21325  var _this = this,
21326 
21327  // internal state cache
21328 
21329  _currentProgram = null,
21330  _currentFramebuffer = null,
21331  _currentMaterialId = - 1,
21332  _currentGeometryProgram = '',
21333  _currentCamera = null,
21334 
21335  _usedTextureUnits = 0,
21336 
21337  _viewportX = 0,
21338  _viewportY = 0,
21339  _viewportWidth = _canvas.width,
21340  _viewportHeight = _canvas.height,
21341  _currentWidth = 0,
21342  _currentHeight = 0,
21343 
21344  // frustum
21345 
21346  _frustum = new THREE.Frustum(),
21347 
21348  // camera matrices cache
21349 
21350  _projScreenMatrix = new THREE.Matrix4(),
21351 
21352  _vector3 = new THREE.Vector3(),
21353 
21354  // light arrays cache
21355 
21356  _direction = new THREE.Vector3(),
21357 
21358  _lightsNeedUpdate = true,
21359 
21360  _lights = {
21361 
21362  ambient: [ 0, 0, 0 ],
21363  directional: { length: 0, colors: [], positions: [] },
21364  point: { length: 0, colors: [], positions: [], distances: [], decays: [] },
21365  spot: { length: 0, colors: [], positions: [], distances: [], directions: [], anglesCos: [], exponents: [], decays: [] },
21366  hemi: { length: 0, skyColors: [], groundColors: [], positions: [] }
21367 
21368  },
21369 
21370  // info
21371 
21372  _infoMemory = {
21373 
21374  geometries: 0,
21375  textures: 0
21376 
21377  },
21378 
21379  _infoRender = {
21380 
21381  calls: 0,
21382  vertices: 0,
21383  faces: 0,
21384  points: 0
21385 
21386  };
21387 
21388  this.info = {
21389 
21390  render: _infoRender,
21391  memory: _infoMemory,
21392  programs: null
21393 
21394  };
21395 
21396 
21397  // initialize
21398 
21399  var _gl;
21400 
21401  try {
21402 
21403  var attributes = {
21404  alpha: _alpha,
21405  depth: _depth,
21406  stencil: _stencil,
21407  antialias: _antialias,
21408  premultipliedAlpha: _premultipliedAlpha,
21409  preserveDrawingBuffer: _preserveDrawingBuffer
21410  };
21411 
21412  _gl = _context || _canvas.getContext( 'webgl', attributes ) || _canvas.getContext( 'experimental-webgl', attributes );
21413 
21414  if ( _gl === null ) {
21415 
21416  if ( _canvas.getContext( 'webgl' ) !== null ) {
21417 
21418  throw 'Error creating WebGL context with your selected attributes.';
21419 
21420  } else {
21421 
21422  throw 'Error creating WebGL context.';
21423 
21424  }
21425 
21426  }
21427 
21428  _canvas.addEventListener( 'webglcontextlost', onContextLost, false );
21429 
21430  } catch ( error ) {
21431 
21432  console.error( 'THREE.WebGLRenderer: ' + error );
21433 
21434  }
21435 
21436  var extensions = new THREE.WebGLExtensions( _gl );
21437 
21438  extensions.get( 'OES_texture_float' );
21439  extensions.get( 'OES_texture_float_linear' );
21440  extensions.get( 'OES_texture_half_float' );
21441  extensions.get( 'OES_texture_half_float_linear' );
21442  extensions.get( 'OES_standard_derivatives' );
21443  extensions.get( 'ANGLE_instanced_arrays' );
21444 
21445  if ( extensions.get( 'OES_element_index_uint' ) ) {
21446 
21447  THREE.BufferGeometry.MaxIndex = 4294967296;
21448 
21449  }
21450 
21451  var capabilities = new THREE.WebGLCapabilities( _gl, extensions, parameters );
21452 
21453  var state = new THREE.WebGLState( _gl, extensions, paramThreeToGL );
21454  var properties = new THREE.WebGLProperties();
21455  var objects = new THREE.WebGLObjects( _gl, properties, this.info );
21456  var programCache = new THREE.WebGLPrograms( this, capabilities );
21457 
21458  this.info.programs = programCache.programs;
21459 
21460  var bufferRenderer = new THREE.WebGLBufferRenderer( _gl, extensions, _infoRender );
21461  var indexedBufferRenderer = new THREE.WebGLIndexedBufferRenderer( _gl, extensions, _infoRender );
21462 
21463  //
21464 
21465  function glClearColor( r, g, b, a ) {
21466 
21467  if ( _premultipliedAlpha === true ) {
21468 
21469  r *= a; g *= a; b *= a;
21470 
21471  }
21472 
21473  _gl.clearColor( r, g, b, a );
21474 
21475  }
21476 
21477  function setDefaultGLState() {
21478 
21479  state.init();
21480 
21481  _gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
21482 
21483  glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
21484 
21485  }
21486 
21487  function resetGLState() {
21488 
21489  _currentProgram = null;
21490  _currentCamera = null;
21491 
21492  _currentGeometryProgram = '';
21493  _currentMaterialId = - 1;
21494 
21495  _lightsNeedUpdate = true;
21496 
21497  state.reset();
21498 
21499  }
21500 
21501  setDefaultGLState();
21502 
21503  this.context = _gl;
21504  this.capabilities = capabilities;
21505  this.extensions = extensions;
21506  this.state = state;
21507 
21508  // shadow map
21509 
21510  var shadowMap = new THREE.WebGLShadowMap( this, lights, objects );
21511 
21512  this.shadowMap = shadowMap;
21513 
21514 
21515  // Plugins
21516 
21517  var spritePlugin = new THREE.SpritePlugin( this, sprites );
21518  var lensFlarePlugin = new THREE.LensFlarePlugin( this, lensFlares );
21519 
21520  // API
21521 
21522  this.getContext = function () {
21523 
21524  return _gl;
21525 
21526  };
21527 
21528  this.getContextAttributes = function () {
21529 
21530  return _gl.getContextAttributes();
21531 
21532  };
21533 
21534  this.forceContextLoss = function () {
21535 
21536  extensions.get( 'WEBGL_lose_context' ).loseContext();
21537 
21538  };
21539 
21540  this.getMaxAnisotropy = ( function () {
21541 
21542  var value;
21543 
21544  return function getMaxAnisotropy() {
21545 
21546  if ( value !== undefined ) return value;
21547 
21548  var extension = extensions.get( 'EXT_texture_filter_anisotropic' );
21549 
21550  if ( extension !== null ) {
21551 
21552  value = _gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
21553 
21554  } else {
21555 
21556  value = 0;
21557 
21558  }
21559 
21560  return value;
21561 
21562  }
21563 
21564  } )();
21565 
21566  this.getPrecision = function () {
21567 
21568  return capabilities.precision;
21569 
21570  };
21571 
21572  this.getPixelRatio = function () {
21573 
21574  return pixelRatio;
21575 
21576  };
21577 
21578  this.setPixelRatio = function ( value ) {
21579 
21580  if ( value !== undefined ) pixelRatio = value;
21581 
21582  };
21583 
21584  this.getSize = function () {
21585 
21586  return {
21587  width: _width,
21588  height: _height
21589  };
21590 
21591  };
21592 
21593  this.setSize = function ( width, height, updateStyle ) {
21594 
21595  _width = width;
21596  _height = height;
21597 
21598  _canvas.width = width * pixelRatio;
21599  _canvas.height = height * pixelRatio;
21600 
21601  if ( updateStyle !== false ) {
21602 
21603  _canvas.style.width = width + 'px';
21604  _canvas.style.height = height + 'px';
21605 
21606  }
21607 
21608  this.setViewport( 0, 0, width, height );
21609 
21610  };
21611 
21612  this.setViewport = function ( x, y, width, height ) {
21613 
21614  _viewportX = x * pixelRatio;
21615  _viewportY = y * pixelRatio;
21616 
21617  _viewportWidth = width * pixelRatio;
21618  _viewportHeight = height * pixelRatio;
21619 
21620  _gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
21621 
21622  };
21623 
21624  this.getViewport = function ( dimensions ) {
21625 
21626  dimensions.x = _viewportX / pixelRatio;
21627  dimensions.y = _viewportY / pixelRatio;
21628 
21629  dimensions.z = _viewportWidth / pixelRatio;
21630  dimensions.w = _viewportHeight / pixelRatio;
21631 
21632  };
21633 
21634  this.setScissor = function ( x, y, width, height ) {
21635 
21636  _gl.scissor(
21637  x * pixelRatio,
21638  y * pixelRatio,
21639  width * pixelRatio,
21640  height * pixelRatio
21641  );
21642 
21643  };
21644 
21645  this.enableScissorTest = function ( boolean ) {
21646 
21647  state.setScissorTest( boolean );
21648 
21649  };
21650 
21651  // Clearing
21652 
21653  this.getClearColor = function () {
21654 
21655  return _clearColor;
21656 
21657  };
21658 
21659  this.setClearColor = function ( color, alpha ) {
21660 
21661  _clearColor.set( color );
21662 
21663  _clearAlpha = alpha !== undefined ? alpha : 1;
21664 
21665  glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
21666 
21667  };
21668 
21669  this.getClearAlpha = function () {
21670 
21671  return _clearAlpha;
21672 
21673  };
21674 
21675  this.setClearAlpha = function ( alpha ) {
21676 
21677  _clearAlpha = alpha;
21678 
21679  glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
21680 
21681  };
21682 
21683  this.clear = function ( color, depth, stencil ) {
21684 
21685  var bits = 0;
21686 
21687  if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
21688  if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
21689  if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
21690 
21691  _gl.clear( bits );
21692 
21693  };
21694 
21695  this.clearColor = function () {
21696 
21697  _gl.clear( _gl.COLOR_BUFFER_BIT );
21698 
21699  };
21700 
21701  this.clearDepth = function () {
21702 
21703  _gl.clear( _gl.DEPTH_BUFFER_BIT );
21704 
21705  };
21706 
21707  this.clearStencil = function () {
21708 
21709  _gl.clear( _gl.STENCIL_BUFFER_BIT );
21710 
21711  };
21712 
21713  this.clearTarget = function ( renderTarget, color, depth, stencil ) {
21714 
21715  this.setRenderTarget( renderTarget );
21716  this.clear( color, depth, stencil );
21717 
21718  };
21719 
21720  // Reset
21721 
21722  this.resetGLState = resetGLState;
21723 
21724  this.dispose = function() {
21725 
21726  _canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
21727 
21728  };
21729 
21730  // Events
21731 
21732  function onContextLost( event ) {
21733 
21734  event.preventDefault();
21735 
21736  resetGLState();
21737  setDefaultGLState();
21738 
21739  properties.clear();
21740 
21741  };
21742 
21743  function onTextureDispose( event ) {
21744 
21745  var texture = event.target;
21746 
21747  texture.removeEventListener( 'dispose', onTextureDispose );
21748 
21749  deallocateTexture( texture );
21750 
21751  _infoMemory.textures --;
21752 
21753 
21754  }
21755 
21756  function onRenderTargetDispose( event ) {
21757 
21758  var renderTarget = event.target;
21759 
21760  renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
21761 
21762  deallocateRenderTarget( renderTarget );
21763 
21764  _infoMemory.textures --;
21765 
21766  }
21767 
21768  function onMaterialDispose( event ) {
21769 
21770  var material = event.target;
21771 
21772  material.removeEventListener( 'dispose', onMaterialDispose );
21773 
21774  deallocateMaterial( material );
21775 
21776  }
21777 
21778  // Buffer deallocation
21779 
21780  function deallocateTexture( texture ) {
21781 
21782  var textureProperties = properties.get( texture );
21783 
21784  if ( texture.image && textureProperties.__image__webglTextureCube ) {
21785 
21786  // cube texture
21787 
21788  _gl.deleteTexture( textureProperties.__image__webglTextureCube );
21789 
21790  } else {
21791 
21792  // 2D texture
21793 
21794  if ( textureProperties.__webglInit === undefined ) return;
21795 
21796  _gl.deleteTexture( textureProperties.__webglTexture );
21797 
21798  }
21799 
21800  // remove all webgl properties
21801  properties.delete( texture );
21802 
21803  }
21804 
21805  function deallocateRenderTarget( renderTarget ) {
21806 
21807  var renderTargetProperties = properties.get( renderTarget );
21808  var textureProperties = properties.get( renderTarget.texture );
21809 
21810  if ( ! renderTarget || textureProperties.__webglTexture === undefined ) return;
21811 
21812  _gl.deleteTexture( textureProperties.__webglTexture );
21813 
21814  if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
21815 
21816  for ( var i = 0; i < 6; i ++ ) {
21817 
21818  _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
21819  _gl.deleteRenderbuffer( renderTargetProperties.__webglRenderbuffer[ i ] );
21820 
21821  }
21822 
21823  } else {
21824 
21825  _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
21826  _gl.deleteRenderbuffer( renderTargetProperties.__webglRenderbuffer );
21827 
21828  }
21829 
21830  properties.delete( renderTarget.texture );
21831  properties.delete( renderTarget );
21832 
21833  }
21834 
21835  function deallocateMaterial( material ) {
21836 
21837  releaseMaterialProgramReference( material );
21838 
21839  properties.delete( material );
21840 
21841  }
21842 
21843 
21844  function releaseMaterialProgramReference( material ) {
21845 
21846  var programInfo = properties.get( material ).program;
21847 
21848  material.program = undefined;
21849 
21850  if ( programInfo !== undefined ) {
21851 
21852  programCache.releaseProgram( programInfo );
21853 
21854  }
21855 
21856  }
21857 
21858  // Buffer rendering
21859 
21860  this.renderBufferImmediate = function ( object, program, material ) {
21861 
21862  state.initAttributes();
21863 
21864  var buffers = properties.get( object );
21865 
21866  if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
21867  if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
21868  if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
21869  if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
21870 
21871  var attributes = program.getAttributes();
21872 
21873  if ( object.hasPositions ) {
21874 
21875  _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );
21876  _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
21877 
21878  state.enableAttribute( attributes.position );
21879  _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
21880 
21881  }
21882 
21883  if ( object.hasNormals ) {
21884 
21885  _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal );
21886 
21887  if ( material.type !== 'MeshPhongMaterial' && material.shading === THREE.FlatShading ) {
21888 
21889  for ( var i = 0, l = object.count * 3; i < l; i += 9 ) {
21890 
21891  var array = object.normalArray;
21892 
21893  var nx = ( array[ i + 0 ] + array[ i + 3 ] + array[ i + 6 ] ) / 3;
21894  var ny = ( array[ i + 1 ] + array[ i + 4 ] + array[ i + 7 ] ) / 3;
21895  var nz = ( array[ i + 2 ] + array[ i + 5 ] + array[ i + 8 ] ) / 3;
21896 
21897  array[ i + 0 ] = nx;
21898  array[ i + 1 ] = ny;
21899  array[ i + 2 ] = nz;
21900 
21901  array[ i + 3 ] = nx;
21902  array[ i + 4 ] = ny;
21903  array[ i + 5 ] = nz;
21904 
21905  array[ i + 6 ] = nx;
21906  array[ i + 7 ] = ny;
21907  array[ i + 8 ] = nz;
21908 
21909  }
21910 
21911  }
21912 
21913  _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
21914 
21915  state.enableAttribute( attributes.normal );
21916 
21917  _gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
21918 
21919  }
21920 
21921  if ( object.hasUvs && material.map ) {
21922 
21923  _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );
21924  _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
21925 
21926  state.enableAttribute( attributes.uv );
21927 
21928  _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
21929 
21930  }
21931 
21932  if ( object.hasColors && material.vertexColors !== THREE.NoColors ) {
21933 
21934  _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );
21935  _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
21936 
21937  state.enableAttribute( attributes.color );
21938 
21939  _gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
21940 
21941  }
21942 
21943  state.disableUnusedAttributes();
21944 
21945  _gl.drawArrays( _gl.TRIANGLES, 0, object.count );
21946 
21947  object.count = 0;
21948 
21949  };
21950 
21951  this.renderBufferDirect = function ( camera, lights, fog, geometry, material, object, group ) {
21952 
21953  setMaterial( material );
21954 
21955  var program = setProgram( camera, lights, fog, material, object );
21956 
21957  var updateBuffers = false;
21958  var geometryProgram = geometry.id + '_' + program.id + '_' + material.wireframe;
21959 
21960  if ( geometryProgram !== _currentGeometryProgram ) {
21961 
21962  _currentGeometryProgram = geometryProgram;
21963  updateBuffers = true;
21964 
21965  }
21966 
21967  // morph targets
21968 
21969  var morphTargetInfluences = object.morphTargetInfluences;
21970 
21971  if ( morphTargetInfluences !== undefined ) {
21972 
21973  var activeInfluences = [];
21974 
21975  for ( var i = 0, l = morphTargetInfluences.length; i < l; i ++ ) {
21976 
21977  var influence = morphTargetInfluences[ i ];
21978  activeInfluences.push( [ influence, i ] );
21979 
21980  }
21981 
21982  activeInfluences.sort( numericalSort );
21983 
21984  if ( activeInfluences.length > 8 ) {
21985 
21986  activeInfluences.length = 8;
21987 
21988  }
21989 
21990  var morphAttributes = geometry.morphAttributes;
21991 
21992  for ( var i = 0, l = activeInfluences.length; i < l; i ++ ) {
21993 
21994  var influence = activeInfluences[ i ];
21995  morphInfluences[ i ] = influence[ 0 ];
21996 
21997  if ( influence[ 0 ] !== 0 ) {
21998 
21999  var index = influence[ 1 ];
22000 
22001  if ( material.morphTargets === true && morphAttributes.position ) geometry.addAttribute( 'morphTarget' + i, morphAttributes.position[ index ] );
22002  if ( material.morphNormals === true && morphAttributes.normal ) geometry.addAttribute( 'morphNormal' + i, morphAttributes.normal[ index ] );
22003 
22004  } else {
22005 
22006  if ( material.morphTargets === true ) geometry.removeAttribute( 'morphTarget' + i );
22007  if ( material.morphNormals === true ) geometry.removeAttribute( 'morphNormal' + i );
22008 
22009  }
22010 
22011  }
22012 
22013  var uniforms = program.getUniforms();
22014 
22015  if ( uniforms.morphTargetInfluences !== null ) {
22016 
22017  _gl.uniform1fv( uniforms.morphTargetInfluences, morphInfluences );
22018 
22019  }
22020 
22021  updateBuffers = true;
22022 
22023  }
22024 
22025  //
22026 
22027  var index = geometry.index;
22028  var position = geometry.attributes.position;
22029 
22030  if ( material.wireframe === true ) {
22031 
22032  index = objects.getWireframeAttribute( geometry );
22033 
22034  }
22035 
22036  var renderer;
22037 
22038  if ( index !== null ) {
22039 
22040  renderer = indexedBufferRenderer;
22041  renderer.setIndex( index );
22042 
22043  } else {
22044 
22045  renderer = bufferRenderer;
22046 
22047  }
22048 
22049  if ( updateBuffers ) {
22050 
22051  setupVertexAttributes( material, program, geometry );
22052 
22053  if ( index !== null ) {
22054 
22055  _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, objects.getAttributeBuffer( index ) );
22056 
22057  }
22058 
22059  }
22060 
22061  //
22062 
22063  var dataStart = 0;
22064  var dataCount = Infinity;
22065 
22066  if ( index !== null ) {
22067 
22068  dataCount = index.count
22069 
22070  } else if ( position !== undefined ) {
22071 
22072  dataCount = position.count;
22073 
22074  }
22075 
22076  var rangeStart = geometry.drawRange.start;
22077  var rangeCount = geometry.drawRange.count;
22078 
22079  var groupStart = group !== null ? group.start : 0;
22080  var groupCount = group !== null ? group.count : Infinity;
22081 
22082  var drawStart = Math.max( dataStart, rangeStart, groupStart );
22083  var drawEnd = Math.min( dataStart + dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
22084 
22085  var drawCount = Math.max( 0, drawEnd - drawStart + 1 );
22086 
22087  //
22088 
22089  if ( object instanceof THREE.Mesh ) {
22090 
22091  if ( material.wireframe === true ) {
22092 
22093  state.setLineWidth( material.wireframeLinewidth * pixelRatio );
22094  renderer.setMode( _gl.LINES );
22095 
22096  } else {
22097 
22098  renderer.setMode( _gl.TRIANGLES );
22099 
22100  }
22101 
22102  if ( geometry instanceof THREE.InstancedBufferGeometry && geometry.maxInstancedCount > 0 ) {
22103 
22104  renderer.renderInstances( geometry );
22105 
22106  } else {
22107 
22108  renderer.render( drawStart, drawCount );
22109 
22110  }
22111 
22112  } else if ( object instanceof THREE.Line ) {
22113 
22114  var lineWidth = material.linewidth;
22115 
22116  if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
22117 
22118  state.setLineWidth( lineWidth * pixelRatio );
22119 
22120  if ( object instanceof THREE.LineSegments ) {
22121 
22122  renderer.setMode( _gl.LINES );
22123 
22124  } else {
22125 
22126  renderer.setMode( _gl.LINE_STRIP );
22127 
22128  }
22129 
22130  renderer.render( drawStart, drawCount );
22131 
22132  } else if ( object instanceof THREE.Points ) {
22133 
22134  renderer.setMode( _gl.POINTS );
22135  renderer.render( drawStart, drawCount );
22136 
22137  }
22138 
22139  };
22140 
22141  function setupVertexAttributes( material, program, geometry, startIndex ) {
22142 
22143  var extension;
22144 
22145  if ( geometry instanceof THREE.InstancedBufferGeometry ) {
22146 
22147  extension = extensions.get( 'ANGLE_instanced_arrays' );
22148 
22149  if ( extension === null ) {
22150 
22151  console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
22152  return;
22153 
22154  }
22155 
22156  }
22157 
22158  if ( startIndex === undefined ) startIndex = 0;
22159 
22160  state.initAttributes();
22161 
22162  var geometryAttributes = geometry.attributes;
22163 
22164  var programAttributes = program.getAttributes();
22165 
22166  var materialDefaultAttributeValues = material.defaultAttributeValues;
22167 
22168  for ( var name in programAttributes ) {
22169 
22170  var programAttribute = programAttributes[ name ];
22171 
22172  if ( programAttribute >= 0 ) {
22173 
22174  var geometryAttribute = geometryAttributes[ name ];
22175 
22176  if ( geometryAttribute !== undefined ) {
22177 
22178  var size = geometryAttribute.itemSize;
22179  var buffer = objects.getAttributeBuffer( geometryAttribute );
22180 
22181  if ( geometryAttribute instanceof THREE.InterleavedBufferAttribute ) {
22182 
22183  var data = geometryAttribute.data;
22184  var stride = data.stride;
22185  var offset = geometryAttribute.offset;
22186 
22187  if ( data instanceof THREE.InstancedInterleavedBuffer ) {
22188 
22189  state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute, extension );
22190 
22191  if ( geometry.maxInstancedCount === undefined ) {
22192 
22193  geometry.maxInstancedCount = data.meshPerAttribute * data.count;
22194 
22195  }
22196 
22197  } else {
22198 
22199  state.enableAttribute( programAttribute );
22200 
22201  }
22202 
22203  _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
22204  _gl.vertexAttribPointer( programAttribute, size, _gl.FLOAT, false, stride * data.array.BYTES_PER_ELEMENT, ( startIndex * stride + offset ) * data.array.BYTES_PER_ELEMENT );
22205 
22206  } else {
22207 
22208  if ( geometryAttribute instanceof THREE.InstancedBufferAttribute ) {
22209 
22210  state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute, extension );
22211 
22212  if ( geometry.maxInstancedCount === undefined ) {
22213 
22214  geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
22215 
22216  }
22217 
22218  } else {
22219 
22220  state.enableAttribute( programAttribute );
22221 
22222  }
22223 
22224  _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
22225  _gl.vertexAttribPointer( programAttribute, size, _gl.FLOAT, false, 0, startIndex * size * 4 ); // 4 bytes per Float32
22226 
22227  }
22228 
22229  } else if ( materialDefaultAttributeValues !== undefined ) {
22230 
22231  var value = materialDefaultAttributeValues[ name ];
22232 
22233  if ( value !== undefined ) {
22234 
22235  switch ( value.length ) {
22236 
22237  case 2:
22238  _gl.vertexAttrib2fv( programAttribute, value );
22239  break;
22240 
22241  case 3:
22242  _gl.vertexAttrib3fv( programAttribute, value );
22243  break;
22244 
22245  case 4:
22246  _gl.vertexAttrib4fv( programAttribute, value );
22247  break;
22248 
22249  default:
22250  _gl.vertexAttrib1fv( programAttribute, value );
22251 
22252  }
22253 
22254  }
22255 
22256  }
22257 
22258  }
22259 
22260  }
22261 
22262  state.disableUnusedAttributes();
22263 
22264  }
22265 
22266  // Sorting
22267 
22268  function numericalSort ( a, b ) {
22269 
22270  return b[ 0 ] - a[ 0 ];
22271 
22272  }
22273 
22274  function painterSortStable ( a, b ) {
22275 
22276  if ( a.object.renderOrder !== b.object.renderOrder ) {
22277 
22278  return a.object.renderOrder - b.object.renderOrder;
22279 
22280  } else if ( a.material.id !== b.material.id ) {
22281 
22282  return a.material.id - b.material.id;
22283 
22284  } else if ( a.z !== b.z ) {
22285 
22286  return a.z - b.z;
22287 
22288  } else {
22289 
22290  return a.id - b.id;
22291 
22292  }
22293 
22294  }
22295 
22296  function reversePainterSortStable ( a, b ) {
22297 
22298  if ( a.object.renderOrder !== b.object.renderOrder ) {
22299 
22300  return a.object.renderOrder - b.object.renderOrder;
22301 
22302  } if ( a.z !== b.z ) {
22303 
22304  return b.z - a.z;
22305 
22306  } else {
22307 
22308  return a.id - b.id;
22309 
22310  }
22311 
22312  }
22313 
22314  // Rendering
22315 
22316  this.render = function ( scene, camera, renderTarget, forceClear ) {
22317 
22318  if ( camera instanceof THREE.Camera === false ) {
22319 
22320  console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
22321  return;
22322 
22323  }
22324 
22325  var fog = scene.fog;
22326 
22327  // reset caching for this frame
22328 
22329  _currentGeometryProgram = '';
22330  _currentMaterialId = - 1;
22331  _currentCamera = null;
22332  _lightsNeedUpdate = true;
22333 
22334  // update scene graph
22335 
22336  if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
22337 
22338  // update camera matrices and frustum
22339 
22340  if ( camera.parent === null ) camera.updateMatrixWorld();
22341 
22342  camera.matrixWorldInverse.getInverse( camera.matrixWorld );
22343 
22344  _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
22345  _frustum.setFromMatrix( _projScreenMatrix );
22346 
22347  lights.length = 0;
22348 
22349  opaqueObjectsLastIndex = - 1;
22350  transparentObjectsLastIndex = - 1;
22351 
22352  sprites.length = 0;
22353  lensFlares.length = 0;
22354 
22355  projectObject( scene, camera );
22356 
22357  opaqueObjects.length = opaqueObjectsLastIndex + 1;
22358  transparentObjects.length = transparentObjectsLastIndex + 1;
22359 
22360  if ( _this.sortObjects === true ) {
22361 
22362  opaqueObjects.sort( painterSortStable );
22363  transparentObjects.sort( reversePainterSortStable );
22364 
22365  }
22366 
22367  //
22368 
22369  shadowMap.render( scene );
22370 
22371  //
22372 
22373  _infoRender.calls = 0;
22374  _infoRender.vertices = 0;
22375  _infoRender.faces = 0;
22376  _infoRender.points = 0;
22377 
22378  this.setRenderTarget( renderTarget );
22379 
22380  if ( this.autoClear || forceClear ) {
22381 
22382  this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil );
22383 
22384  }
22385 
22386  //
22387 
22388  if ( scene.overrideMaterial ) {
22389 
22390  var overrideMaterial = scene.overrideMaterial;
22391 
22392  renderObjects( opaqueObjects, camera, lights, fog, overrideMaterial );
22393  renderObjects( transparentObjects, camera, lights, fog, overrideMaterial );
22394 
22395  } else {
22396 
22397  // opaque pass (front-to-back order)
22398 
22399  state.setBlending( THREE.NoBlending );
22400  renderObjects( opaqueObjects, camera, lights, fog );
22401 
22402  // transparent pass (back-to-front order)
22403 
22404  renderObjects( transparentObjects, camera, lights, fog );
22405 
22406  }
22407 
22408  // custom render plugins (post pass)
22409 
22410  spritePlugin.render( scene, camera );
22411  lensFlarePlugin.render( scene, camera, _currentWidth, _currentHeight );
22412 
22413  // Generate mipmap if we're using any kind of mipmap filtering
22414 
22415  if ( renderTarget ) {
22416 
22417  var texture = renderTarget.texture;
22418  var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
22419  if ( texture.generateMipmaps && isTargetPowerOfTwo && texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter ) {
22420 
22421  updateRenderTargetMipmap( renderTarget );
22422 
22423  }
22424 
22425  }
22426 
22427  // Ensure depth buffer writing is enabled so it can be cleared on next render
22428 
22429  state.setDepthTest( true );
22430  state.setDepthWrite( true );
22431  state.setColorWrite( true );
22432 
22433  // _gl.finish();
22434 
22435  };
22436 
22437  function pushRenderItem( object, geometry, material, z, group ) {
22438 
22439  var array, index;
22440 
22441  // allocate the next position in the appropriate array
22442 
22443  if ( material.transparent ) {
22444 
22445  array = transparentObjects;
22446  index = ++ transparentObjectsLastIndex;
22447 
22448  } else {
22449 
22450  array = opaqueObjects;
22451  index = ++ opaqueObjectsLastIndex;
22452 
22453  }
22454 
22455  // recycle existing render item or grow the array
22456 
22457  var renderItem = array[ index ];
22458 
22459  if ( renderItem !== undefined ) {
22460 
22461  renderItem.id = object.id;
22462  renderItem.object = object;
22463  renderItem.geometry = geometry;
22464  renderItem.material = material;
22465  renderItem.z = _vector3.z;
22466  renderItem.group = group;
22467 
22468  } else {
22469 
22470  renderItem = {
22471  id: object.id,
22472  object: object,
22473  geometry: geometry,
22474  material: material,
22475  z: _vector3.z,
22476  group: group
22477  };
22478 
22479  // assert( index === array.length );
22480  array.push( renderItem );
22481 
22482  }
22483 
22484  }
22485 
22486  function projectObject( object, camera ) {
22487 
22488  if ( object.visible === false ) return;
22489 
22490  if ( ( object.channels.mask & camera.channels.mask ) !== 0 ) {
22491 
22492  if ( object instanceof THREE.Light ) {
22493 
22494  lights.push( object );
22495 
22496  } else if ( object instanceof THREE.Sprite ) {
22497 
22498  sprites.push( object );
22499 
22500  } else if ( object instanceof THREE.LensFlare ) {
22501 
22502  lensFlares.push( object );
22503 
22504  } else if ( object instanceof THREE.ImmediateRenderObject ) {
22505 
22506  if ( _this.sortObjects === true ) {
22507 
22508  _vector3.setFromMatrixPosition( object.matrixWorld );
22509  _vector3.applyProjection( _projScreenMatrix );
22510 
22511  }
22512 
22513  pushRenderItem( object, null, object.material, _vector3.z, null );
22514 
22515  } else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points ) {
22516 
22517  if ( object instanceof THREE.SkinnedMesh ) {
22518 
22519  object.skeleton.update();
22520 
22521  }
22522 
22523  if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
22524 
22525  var material = object.material;
22526 
22527  if ( material.visible === true ) {
22528 
22529  if ( _this.sortObjects === true ) {
22530 
22531  _vector3.setFromMatrixPosition( object.matrixWorld );
22532  _vector3.applyProjection( _projScreenMatrix );
22533 
22534  }
22535 
22536  var geometry = objects.update( object );
22537 
22538  if ( material instanceof THREE.MeshFaceMaterial ) {
22539 
22540  var groups = geometry.groups;
22541  var materials = material.materials;
22542 
22543  for ( var i = 0, l = groups.length; i < l; i ++ ) {
22544 
22545  var group = groups[ i ];
22546  var groupMaterial = materials[ group.materialIndex ];
22547 
22548  if ( groupMaterial.visible === true ) {
22549 
22550  pushRenderItem( object, geometry, groupMaterial, _vector3.z, group );
22551 
22552  }
22553 
22554  }
22555 
22556  } else {
22557 
22558  pushRenderItem( object, geometry, material, _vector3.z, null );
22559 
22560  }
22561 
22562  }
22563 
22564  }
22565 
22566  }
22567 
22568  }
22569 
22570  var children = object.children;
22571 
22572  for ( var i = 0, l = children.length; i < l; i ++ ) {
22573 
22574  projectObject( children[ i ], camera );
22575 
22576  }
22577 
22578  }
22579 
22580  function renderObjects( renderList, camera, lights, fog, overrideMaterial ) {
22581 
22582  for ( var i = 0, l = renderList.length; i < l; i ++ ) {
22583 
22584  var renderItem = renderList[ i ];
22585 
22586  var object = renderItem.object;
22587  var geometry = renderItem.geometry;
22588  var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
22589  var group = renderItem.group;
22590 
22591  object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
22592  object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
22593 
22594  if ( object instanceof THREE.ImmediateRenderObject ) {
22595 
22596  setMaterial( material );
22597 
22598  var program = setProgram( camera, lights, fog, material, object );
22599 
22600  _currentGeometryProgram = '';
22601 
22602  object.render( function ( object ) {
22603 
22604  _this.renderBufferImmediate( object, program, material );
22605 
22606  } );
22607 
22608  } else {
22609 
22610  _this.renderBufferDirect( camera, lights, fog, geometry, material, object, group );
22611 
22612  }
22613 
22614  }
22615 
22616  }
22617 
22618  function initMaterial( material, lights, fog, object ) {
22619 
22620  var materialProperties = properties.get( material );
22621 
22622  var parameters = programCache.getParameters( material, lights, fog, object );
22623  var code = programCache.getProgramCode( material, parameters );
22624 
22625  var program = materialProperties.program;
22626  var programChange = true;
22627 
22628  if ( program === undefined ) {
22629 
22630  // new material
22631  material.addEventListener( 'dispose', onMaterialDispose );
22632 
22633  } else if ( program.code !== code ) {
22634 
22635  // changed glsl or parameters
22636  releaseMaterialProgramReference( material );
22637 
22638  } else if ( parameters.shaderID !== undefined ) {
22639 
22640  // same glsl and uniform list
22641  return;
22642 
22643  } else {
22644 
22645  // only rebuild uniform list
22646  programChange = false;
22647 
22648  }
22649 
22650  if ( programChange ) {
22651 
22652  if ( parameters.shaderID ) {
22653 
22654  var shader = THREE.ShaderLib[ parameters.shaderID ];
22655 
22656  materialProperties.__webglShader = {
22657  name: material.type,
22658  uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
22659  vertexShader: shader.vertexShader,
22660  fragmentShader: shader.fragmentShader
22661  };
22662 
22663  } else {
22664 
22665  materialProperties.__webglShader = {
22666  name: material.type,
22667  uniforms: material.uniforms,
22668  vertexShader: material.vertexShader,
22669  fragmentShader: material.fragmentShader
22670  };
22671 
22672  }
22673 
22674  material.__webglShader = materialProperties.__webglShader;
22675 
22676  program = programCache.acquireProgram( material, parameters, code );
22677 
22678  materialProperties.program = program;
22679  material.program = program;
22680 
22681  }
22682 
22683  var attributes = program.getAttributes();
22684 
22685  if ( material.morphTargets ) {
22686 
22687  material.numSupportedMorphTargets = 0;
22688 
22689  for ( var i = 0; i < _this.maxMorphTargets; i ++ ) {
22690 
22691  if ( attributes[ 'morphTarget' + i ] >= 0 ) {
22692 
22693  material.numSupportedMorphTargets ++;
22694 
22695  }
22696 
22697  }
22698 
22699  }
22700 
22701  if ( material.morphNormals ) {
22702 
22703  material.numSupportedMorphNormals = 0;
22704 
22705  for ( i = 0; i < _this.maxMorphNormals; i ++ ) {
22706 
22707  if ( attributes[ 'morphNormal' + i ] >= 0 ) {
22708 
22709  material.numSupportedMorphNormals ++;
22710 
22711  }
22712 
22713  }
22714 
22715  }
22716 
22717  materialProperties.uniformsList = [];
22718 
22719  var uniformLocations = materialProperties.program.getUniforms();
22720 
22721  for ( var u in materialProperties.__webglShader.uniforms ) {
22722 
22723  var location = uniformLocations[ u ];
22724 
22725  if ( location ) {
22726 
22727  materialProperties.uniformsList.push( [ materialProperties.__webglShader.uniforms[ u ], location ] );
22728 
22729  }
22730 
22731  }
22732 
22733  }
22734 
22735  function setMaterial( material ) {
22736 
22737  setMaterialFaces( material );
22738 
22739  if ( material.transparent === true ) {
22740 
22741  state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha );
22742 
22743  } else {
22744 
22745  state.setBlending( THREE.NoBlending );
22746 
22747  }
22748 
22749  state.setDepthFunc( material.depthFunc );
22750  state.setDepthTest( material.depthTest );
22751  state.setDepthWrite( material.depthWrite );
22752  state.setColorWrite( material.colorWrite );
22753  state.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
22754 
22755  }
22756 
22757  function setMaterialFaces( material ) {
22758 
22759  material.side !== THREE.DoubleSide ? state.enable( _gl.CULL_FACE ) : state.disable( _gl.CULL_FACE );
22760  state.setFlipSided( material.side === THREE.BackSide );
22761 
22762  }
22763 
22764  function setProgram( camera, lights, fog, material, object ) {
22765 
22766  _usedTextureUnits = 0;
22767 
22768  var materialProperties = properties.get( material );
22769 
22770  if ( material.needsUpdate || ! materialProperties.program ) {
22771 
22772  initMaterial( material, lights, fog, object );
22773  material.needsUpdate = false;
22774 
22775  }
22776 
22777  var refreshProgram = false;
22778  var refreshMaterial = false;
22779  var refreshLights = false;
22780 
22781  var program = materialProperties.program,
22782  p_uniforms = program.getUniforms(),
22783  m_uniforms = materialProperties.__webglShader.uniforms;
22784 
22785  if ( program.id !== _currentProgram ) {
22786 
22787  _gl.useProgram( program.program );
22788  _currentProgram = program.id;
22789 
22790  refreshProgram = true;
22791  refreshMaterial = true;
22792  refreshLights = true;
22793 
22794  }
22795 
22796  if ( material.id !== _currentMaterialId ) {
22797 
22798  if ( _currentMaterialId === - 1 ) refreshLights = true;
22799  _currentMaterialId = material.id;
22800 
22801  refreshMaterial = true;
22802 
22803  }
22804 
22805  if ( refreshProgram || camera !== _currentCamera ) {
22806 
22807  _gl.uniformMatrix4fv( p_uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
22808 
22809  if ( capabilities.logarithmicDepthBuffer ) {
22810 
22811  _gl.uniform1f( p_uniforms.logDepthBufFC, 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
22812 
22813  }
22814 
22815 
22816  if ( camera !== _currentCamera ) _currentCamera = camera;
22817 
22818  // load material specific uniforms
22819  // (shader material also gets them for the sake of genericity)
22820 
22821  if ( material instanceof THREE.ShaderMaterial ||
22822  material instanceof THREE.MeshPhongMaterial ||
22823  material.envMap ) {
22824 
22825  if ( p_uniforms.cameraPosition !== undefined ) {
22826 
22827  _vector3.setFromMatrixPosition( camera.matrixWorld );
22828  _gl.uniform3f( p_uniforms.cameraPosition, _vector3.x, _vector3.y, _vector3.z );
22829 
22830  }
22831 
22832  }
22833 
22834  if ( material instanceof THREE.MeshPhongMaterial ||
22835  material instanceof THREE.MeshLambertMaterial ||
22836  material instanceof THREE.MeshBasicMaterial ||
22837  material instanceof THREE.ShaderMaterial ||
22838  material.skinning ) {
22839 
22840  if ( p_uniforms.viewMatrix !== undefined ) {
22841 
22842  _gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, camera.matrixWorldInverse.elements );
22843 
22844  }
22845 
22846  }
22847 
22848  }
22849 
22850  // skinning uniforms must be set even if material didn't change
22851  // auto-setting of texture unit for bone texture must go before other textures
22852  // not sure why, but otherwise weird things happen
22853 
22854  if ( material.skinning ) {
22855 
22856  if ( object.bindMatrix && p_uniforms.bindMatrix !== undefined ) {
22857 
22858  _gl.uniformMatrix4fv( p_uniforms.bindMatrix, false, object.bindMatrix.elements );
22859 
22860  }
22861 
22862  if ( object.bindMatrixInverse && p_uniforms.bindMatrixInverse !== undefined ) {
22863 
22864  _gl.uniformMatrix4fv( p_uniforms.bindMatrixInverse, false, object.bindMatrixInverse.elements );
22865 
22866  }
22867 
22868  if ( capabilities.floatVertexTextures && object.skeleton && object.skeleton.useVertexTexture ) {
22869 
22870  if ( p_uniforms.boneTexture !== undefined ) {
22871 
22872  var textureUnit = getTextureUnit();
22873 
22874  _gl.uniform1i( p_uniforms.boneTexture, textureUnit );
22875  _this.setTexture( object.skeleton.boneTexture, textureUnit );
22876 
22877  }
22878 
22879  if ( p_uniforms.boneTextureWidth !== undefined ) {
22880 
22881  _gl.uniform1i( p_uniforms.boneTextureWidth, object.skeleton.boneTextureWidth );
22882 
22883  }
22884 
22885  if ( p_uniforms.boneTextureHeight !== undefined ) {
22886 
22887  _gl.uniform1i( p_uniforms.boneTextureHeight, object.skeleton.boneTextureHeight );
22888 
22889  }
22890 
22891  } else if ( object.skeleton && object.skeleton.boneMatrices ) {
22892 
22893  if ( p_uniforms.boneGlobalMatrices !== undefined ) {
22894 
22895  _gl.uniformMatrix4fv( p_uniforms.boneGlobalMatrices, false, object.skeleton.boneMatrices );
22896 
22897  }
22898 
22899  }
22900 
22901  }
22902 
22903  if ( refreshMaterial ) {
22904 
22905  // refresh uniforms common to several materials
22906 
22907  if ( fog && material.fog ) {
22908 
22909  refreshUniformsFog( m_uniforms, fog );
22910 
22911  }
22912 
22913  if ( material instanceof THREE.MeshPhongMaterial ||
22914  material instanceof THREE.MeshLambertMaterial ||
22915  material.lights ) {
22916 
22917  if ( _lightsNeedUpdate ) {
22918 
22919  refreshLights = true;
22920  setupLights( lights, camera );
22921  _lightsNeedUpdate = false;
22922 
22923  }
22924 
22925  if ( refreshLights ) {
22926 
22927  refreshUniformsLights( m_uniforms, _lights );
22928  markUniformsLightsNeedsUpdate( m_uniforms, true );
22929 
22930  } else {
22931 
22932  markUniformsLightsNeedsUpdate( m_uniforms, false );
22933 
22934  }
22935 
22936  }
22937 
22938  if ( material instanceof THREE.MeshBasicMaterial ||
22939  material instanceof THREE.MeshLambertMaterial ||
22940  material instanceof THREE.MeshPhongMaterial ) {
22941 
22942  refreshUniformsCommon( m_uniforms, material );
22943 
22944  }
22945 
22946  // refresh single material specific uniforms
22947 
22948  if ( material instanceof THREE.LineBasicMaterial ) {
22949 
22950  refreshUniformsLine( m_uniforms, material );
22951 
22952  } else if ( material instanceof THREE.LineDashedMaterial ) {
22953 
22954  refreshUniformsLine( m_uniforms, material );
22955  refreshUniformsDash( m_uniforms, material );
22956 
22957  } else if ( material instanceof THREE.PointsMaterial ) {
22958 
22959  refreshUniformsParticle( m_uniforms, material );
22960 
22961  } else if ( material instanceof THREE.MeshPhongMaterial ) {
22962 
22963  refreshUniformsPhong( m_uniforms, material );
22964 
22965  } else if ( material instanceof THREE.MeshDepthMaterial ) {
22966 
22967  m_uniforms.mNear.value = camera.near;
22968  m_uniforms.mFar.value = camera.far;
22969  m_uniforms.opacity.value = material.opacity;
22970 
22971  } else if ( material instanceof THREE.MeshNormalMaterial ) {
22972 
22973  m_uniforms.opacity.value = material.opacity;
22974 
22975  }
22976 
22977  if ( object.receiveShadow && ! material._shadowPass ) {
22978 
22979  refreshUniformsShadow( m_uniforms, lights, camera );
22980 
22981  }
22982 
22983  // load common uniforms
22984 
22985  loadUniformsGeneric( materialProperties.uniformsList );
22986 
22987  }
22988 
22989  loadUniformsMatrices( p_uniforms, object );
22990 
22991  if ( p_uniforms.modelMatrix !== undefined ) {
22992 
22993  _gl.uniformMatrix4fv( p_uniforms.modelMatrix, false, object.matrixWorld.elements );
22994 
22995  }
22996 
22997  return program;
22998 
22999  }
23000 
23001  // Uniforms (refresh uniforms objects)
23002 
23003  function refreshUniformsCommon ( uniforms, material ) {
23004 
23005  uniforms.opacity.value = material.opacity;
23006 
23007  uniforms.diffuse.value = material.color;
23008 
23009  if ( material.emissive ) {
23010 
23011  uniforms.emissive.value = material.emissive;
23012 
23013  }
23014 
23015  uniforms.map.value = material.map;
23016  uniforms.specularMap.value = material.specularMap;
23017  uniforms.alphaMap.value = material.alphaMap;
23018 
23019  if ( material.aoMap ) {
23020 
23021  uniforms.aoMap.value = material.aoMap;
23022  uniforms.aoMapIntensity.value = material.aoMapIntensity;
23023 
23024  }
23025 
23026  // uv repeat and offset setting priorities
23027  // 1. color map
23028  // 2. specular map
23029  // 3. normal map
23030  // 4. bump map
23031  // 5. alpha map
23032  // 6. emissive map
23033 
23034  var uvScaleMap;
23035 
23036  if ( material.map ) {
23037 
23038  uvScaleMap = material.map;
23039 
23040  } else if ( material.specularMap ) {
23041 
23042  uvScaleMap = material.specularMap;
23043 
23044  } else if ( material.displacementMap ) {
23045 
23046  uvScaleMap = material.displacementMap;
23047 
23048  } else if ( material.normalMap ) {
23049 
23050  uvScaleMap = material.normalMap;
23051 
23052  } else if ( material.bumpMap ) {
23053 
23054  uvScaleMap = material.bumpMap;
23055 
23056  } else if ( material.alphaMap ) {
23057 
23058  uvScaleMap = material.alphaMap;
23059 
23060  } else if ( material.emissiveMap ) {
23061 
23062  uvScaleMap = material.emissiveMap;
23063 
23064  }
23065 
23066  if ( uvScaleMap !== undefined ) {
23067 
23068  if ( uvScaleMap instanceof THREE.WebGLRenderTarget ) uvScaleMap = uvScaleMap.texture;
23069  var offset = uvScaleMap.offset;
23070  var repeat = uvScaleMap.repeat;
23071 
23072  uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
23073 
23074  }
23075 
23076  uniforms.envMap.value = material.envMap;
23077  uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : - 1;
23078 
23079  uniforms.reflectivity.value = material.reflectivity;
23080  uniforms.refractionRatio.value = material.refractionRatio;
23081 
23082  }
23083 
23084  function refreshUniformsLine ( uniforms, material ) {
23085 
23086  uniforms.diffuse.value = material.color;
23087  uniforms.opacity.value = material.opacity;
23088 
23089  }
23090 
23091  function refreshUniformsDash ( uniforms, material ) {
23092 
23093  uniforms.dashSize.value = material.dashSize;
23094  uniforms.totalSize.value = material.dashSize + material.gapSize;
23095  uniforms.scale.value = material.scale;
23096 
23097  }
23098 
23099  function refreshUniformsParticle ( uniforms, material ) {
23100 
23101  uniforms.psColor.value = material.color;
23102  uniforms.opacity.value = material.opacity;
23103  uniforms.size.value = material.size;
23104  uniforms.scale.value = _canvas.height / 2.0; // TODO: Cache this.
23105 
23106  uniforms.map.value = material.map;
23107 
23108  if ( material.map !== null ) {
23109 
23110  var offset = material.map.offset;
23111  var repeat = material.map.repeat;
23112 
23113  uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
23114 
23115  }
23116 
23117  }
23118 
23119  function refreshUniformsFog ( uniforms, fog ) {
23120 
23121  uniforms.fogColor.value = fog.color;
23122 
23123  if ( fog instanceof THREE.Fog ) {
23124 
23125  uniforms.fogNear.value = fog.near;
23126  uniforms.fogFar.value = fog.far;
23127 
23128  } else if ( fog instanceof THREE.FogExp2 ) {
23129 
23130  uniforms.fogDensity.value = fog.density;
23131 
23132  }
23133 
23134  }
23135 
23136  function refreshUniformsPhong ( uniforms, material ) {
23137 
23138  uniforms.specular.value = material.specular;
23139  uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
23140 
23141  if ( material.lightMap ) {
23142 
23143  uniforms.lightMap.value = material.lightMap;
23144  uniforms.lightMapIntensity.value = material.lightMapIntensity;
23145 
23146  }
23147 
23148  if ( material.emissiveMap ) {
23149 
23150  uniforms.emissiveMap.value = material.emissiveMap;
23151 
23152  }
23153 
23154  if ( material.bumpMap ) {
23155 
23156  uniforms.bumpMap.value = material.bumpMap;
23157  uniforms.bumpScale.value = material.bumpScale;
23158 
23159  }
23160 
23161  if ( material.normalMap ) {
23162 
23163  uniforms.normalMap.value = material.normalMap;
23164  uniforms.normalScale.value.copy( material.normalScale );
23165 
23166  }
23167 
23168  if ( material.displacementMap ) {
23169 
23170  uniforms.displacementMap.value = material.displacementMap;
23171  uniforms.displacementScale.value = material.displacementScale;
23172  uniforms.displacementBias.value = material.displacementBias;
23173 
23174  }
23175 
23176  }
23177 
23178  function refreshUniformsLights ( uniforms, lights ) {
23179 
23180  uniforms.ambientLightColor.value = lights.ambient;
23181 
23182  uniforms.directionalLightColor.value = lights.directional.colors;
23183  uniforms.directionalLightDirection.value = lights.directional.positions;
23184 
23185  uniforms.pointLightColor.value = lights.point.colors;
23186  uniforms.pointLightPosition.value = lights.point.positions;
23187  uniforms.pointLightDistance.value = lights.point.distances;
23188  uniforms.pointLightDecay.value = lights.point.decays;
23189 
23190  uniforms.spotLightColor.value = lights.spot.colors;
23191  uniforms.spotLightPosition.value = lights.spot.positions;
23192  uniforms.spotLightDistance.value = lights.spot.distances;
23193  uniforms.spotLightDirection.value = lights.spot.directions;
23194  uniforms.spotLightAngleCos.value = lights.spot.anglesCos;
23195  uniforms.spotLightExponent.value = lights.spot.exponents;
23196  uniforms.spotLightDecay.value = lights.spot.decays;
23197 
23198  uniforms.hemisphereLightSkyColor.value = lights.hemi.skyColors;
23199  uniforms.hemisphereLightGroundColor.value = lights.hemi.groundColors;
23200  uniforms.hemisphereLightDirection.value = lights.hemi.positions;
23201 
23202  }
23203 
23204  // If uniforms are marked as clean, they don't need to be loaded to the GPU.
23205 
23206  function markUniformsLightsNeedsUpdate ( uniforms, value ) {
23207 
23208  uniforms.ambientLightColor.needsUpdate = value;
23209 
23210  uniforms.directionalLightColor.needsUpdate = value;
23211  uniforms.directionalLightDirection.needsUpdate = value;
23212 
23213  uniforms.pointLightColor.needsUpdate = value;
23214  uniforms.pointLightPosition.needsUpdate = value;
23215  uniforms.pointLightDistance.needsUpdate = value;
23216  uniforms.pointLightDecay.needsUpdate = value;
23217 
23218  uniforms.spotLightColor.needsUpdate = value;
23219  uniforms.spotLightPosition.needsUpdate = value;
23220  uniforms.spotLightDistance.needsUpdate = value;
23221  uniforms.spotLightDirection.needsUpdate = value;
23222  uniforms.spotLightAngleCos.needsUpdate = value;
23223  uniforms.spotLightExponent.needsUpdate = value;
23224  uniforms.spotLightDecay.needsUpdate = value;
23225 
23226  uniforms.hemisphereLightSkyColor.needsUpdate = value;
23227  uniforms.hemisphereLightGroundColor.needsUpdate = value;
23228  uniforms.hemisphereLightDirection.needsUpdate = value;
23229 
23230  }
23231 
23232  function refreshUniformsShadow ( uniforms, lights, camera ) {
23233 
23234  if ( uniforms.shadowMatrix ) {
23235 
23236  var j = 0;
23237 
23238  for ( var i = 0, il = lights.length; i < il; i ++ ) {
23239 
23240  var light = lights[ i ];
23241 
23242  if ( light.castShadow === true ) {
23243 
23244  if ( light instanceof THREE.PointLight || light instanceof THREE.SpotLight || light instanceof THREE.DirectionalLight ) {
23245 
23246  var shadow = light.shadow;
23247 
23248  if ( light instanceof THREE.PointLight ) {
23249 
23250  // for point lights we set the shadow matrix to be a translation-only matrix
23251  // equal to inverse of the light's position
23252  _vector3.setFromMatrixPosition( light.matrixWorld ).negate();
23253  shadow.matrix.identity().setPosition( _vector3 );
23254 
23255  // for point lights we set the sign of the shadowDarkness uniform to be negative
23256  uniforms.shadowDarkness.value[ j ] = - shadow.darkness;
23257 
23258  } else {
23259 
23260  uniforms.shadowDarkness.value[ j ] = shadow.darkness;
23261 
23262  }
23263 
23264  uniforms.shadowMatrix.value[ j ] = shadow.matrix;
23265  uniforms.shadowMap.value[ j ] = shadow.map;
23266  uniforms.shadowMapSize.value[ j ] = shadow.mapSize;
23267  uniforms.shadowBias.value[ j ] = shadow.bias;
23268 
23269  j ++;
23270 
23271  }
23272 
23273  }
23274 
23275  }
23276 
23277  }
23278 
23279  }
23280 
23281  // Uniforms (load to GPU)
23282 
23283  function loadUniformsMatrices ( uniforms, object ) {
23284 
23285  _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object.modelViewMatrix.elements );
23286 
23287  if ( uniforms.normalMatrix ) {
23288 
23289  _gl.uniformMatrix3fv( uniforms.normalMatrix, false, object.normalMatrix.elements );
23290 
23291  }
23292 
23293  }
23294 
23295  function getTextureUnit() {
23296 
23297  var textureUnit = _usedTextureUnits;
23298 
23299  if ( textureUnit >= capabilities.maxTextures ) {
23300 
23301  console.warn( 'WebGLRenderer: trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures );
23302 
23303  }
23304 
23305  _usedTextureUnits += 1;
23306 
23307  return textureUnit;
23308 
23309  }
23310 
23311  function loadUniformsGeneric ( uniforms ) {
23312 
23313  var texture, textureUnit;
23314 
23315  for ( var j = 0, jl = uniforms.length; j < jl; j ++ ) {
23316 
23317  var uniform = uniforms[ j ][ 0 ];
23318 
23319  // needsUpdate property is not added to all uniforms.
23320  if ( uniform.needsUpdate === false ) continue;
23321 
23322  var type = uniform.type;
23323  var value = uniform.value;
23324  var location = uniforms[ j ][ 1 ];
23325 
23326  switch ( type ) {
23327 
23328  case '1i':
23329  _gl.uniform1i( location, value );
23330  break;
23331 
23332  case '1f':
23333  _gl.uniform1f( location, value );
23334  break;
23335 
23336  case '2f':
23337  _gl.uniform2f( location, value[ 0 ], value[ 1 ] );
23338  break;
23339 
23340  case '3f':
23341  _gl.uniform3f( location, value[ 0 ], value[ 1 ], value[ 2 ] );
23342  break;
23343 
23344  case '4f':
23345  _gl.uniform4f( location, value[ 0 ], value[ 1 ], value[ 2 ], value[ 3 ] );
23346  break;
23347 
23348  case '1iv':
23349  _gl.uniform1iv( location, value );
23350  break;
23351 
23352  case '3iv':
23353  _gl.uniform3iv( location, value );
23354  break;
23355 
23356  case '1fv':
23357  _gl.uniform1fv( location, value );
23358  break;
23359 
23360  case '2fv':
23361  _gl.uniform2fv( location, value );
23362  break;
23363 
23364  case '3fv':
23365  _gl.uniform3fv( location, value );
23366  break;
23367 
23368  case '4fv':
23369  _gl.uniform4fv( location, value );
23370  break;
23371 
23372  case 'Matrix3fv':
23373  _gl.uniformMatrix3fv( location, false, value );
23374  break;
23375 
23376  case 'Matrix4fv':
23377  _gl.uniformMatrix4fv( location, false, value );
23378  break;
23379 
23380  //
23381 
23382  case 'i':
23383 
23384  // single integer
23385  _gl.uniform1i( location, value );
23386 
23387  break;
23388 
23389  case 'f':
23390 
23391  // single float
23392  _gl.uniform1f( location, value );
23393 
23394  break;
23395 
23396  case 'v2':
23397 
23398  // single THREE.Vector2
23399  _gl.uniform2f( location, value.x, value.y );
23400 
23401  break;
23402 
23403  case 'v3':
23404 
23405  // single THREE.Vector3
23406  _gl.uniform3f( location, value.x, value.y, value.z );
23407 
23408  break;
23409 
23410  case 'v4':
23411 
23412  // single THREE.Vector4
23413  _gl.uniform4f( location, value.x, value.y, value.z, value.w );
23414 
23415  break;
23416 
23417  case 'c':
23418 
23419  // single THREE.Color
23420  _gl.uniform3f( location, value.r, value.g, value.b );
23421 
23422  break;
23423 
23424  case 'iv1':
23425 
23426  // flat array of integers (JS or typed array)
23427  _gl.uniform1iv( location, value );
23428 
23429  break;
23430 
23431  case 'iv':
23432 
23433  // flat array of integers with 3 x N size (JS or typed array)
23434  _gl.uniform3iv( location, value );
23435 
23436  break;
23437 
23438  case 'fv1':
23439 
23440  // flat array of floats (JS or typed array)
23441  _gl.uniform1fv( location, value );
23442 
23443  break;
23444 
23445  case 'fv':
23446 
23447  // flat array of floats with 3 x N size (JS or typed array)
23448  _gl.uniform3fv( location, value );
23449 
23450  break;
23451 
23452  case 'v2v':
23453 
23454  // array of THREE.Vector2
23455 
23456  if ( uniform._array === undefined ) {
23457 
23458  uniform._array = new Float32Array( 2 * value.length );
23459 
23460  }
23461 
23462  for ( var i = 0, i2 = 0, il = value.length; i < il; i ++, i2 += 2 ) {
23463 
23464  uniform._array[ i2 + 0 ] = value[ i ].x;
23465  uniform._array[ i2 + 1 ] = value[ i ].y;
23466 
23467  }
23468 
23469  _gl.uniform2fv( location, uniform._array );
23470 
23471  break;
23472 
23473  case 'v3v':
23474 
23475  // array of THREE.Vector3
23476 
23477  if ( uniform._array === undefined ) {
23478 
23479  uniform._array = new Float32Array( 3 * value.length );
23480 
23481  }
23482 
23483  for ( var i = 0, i3 = 0, il = value.length; i < il; i ++, i3 += 3 ) {
23484 
23485  uniform._array[ i3 + 0 ] = value[ i ].x;
23486  uniform._array[ i3 + 1 ] = value[ i ].y;
23487  uniform._array[ i3 + 2 ] = value[ i ].z;
23488 
23489  }
23490 
23491  _gl.uniform3fv( location, uniform._array );
23492 
23493  break;
23494 
23495  case 'v4v':
23496 
23497  // array of THREE.Vector4
23498 
23499  if ( uniform._array === undefined ) {
23500 
23501  uniform._array = new Float32Array( 4 * value.length );
23502 
23503  }
23504 
23505  for ( var i = 0, i4 = 0, il = value.length; i < il; i ++, i4 += 4 ) {
23506 
23507  uniform._array[ i4 + 0 ] = value[ i ].x;
23508  uniform._array[ i4 + 1 ] = value[ i ].y;
23509  uniform._array[ i4 + 2 ] = value[ i ].z;
23510  uniform._array[ i4 + 3 ] = value[ i ].w;
23511 
23512  }
23513 
23514  _gl.uniform4fv( location, uniform._array );
23515 
23516  break;
23517 
23518  case 'm3':
23519 
23520  // single THREE.Matrix3
23521  _gl.uniformMatrix3fv( location, false, value.elements );
23522 
23523  break;
23524 
23525  case 'm3v':
23526 
23527  // array of THREE.Matrix3
23528 
23529  if ( uniform._array === undefined ) {
23530 
23531  uniform._array = new Float32Array( 9 * value.length );
23532 
23533  }
23534 
23535  for ( var i = 0, il = value.length; i < il; i ++ ) {
23536 
23537  value[ i ].flattenToArrayOffset( uniform._array, i * 9 );
23538 
23539  }
23540 
23541  _gl.uniformMatrix3fv( location, false, uniform._array );
23542 
23543  break;
23544 
23545  case 'm4':
23546 
23547  // single THREE.Matrix4
23548  _gl.uniformMatrix4fv( location, false, value.elements );
23549 
23550  break;
23551 
23552  case 'm4v':
23553 
23554  // array of THREE.Matrix4
23555 
23556  if ( uniform._array === undefined ) {
23557 
23558  uniform._array = new Float32Array( 16 * value.length );
23559 
23560  }
23561 
23562  for ( var i = 0, il = value.length; i < il; i ++ ) {
23563 
23564  value[ i ].flattenToArrayOffset( uniform._array, i * 16 );
23565 
23566  }
23567 
23568  _gl.uniformMatrix4fv( location, false, uniform._array );
23569 
23570  break;
23571 
23572  case 't':
23573 
23574  // single THREE.Texture (2d or cube)
23575 
23576  texture = value;
23577  textureUnit = getTextureUnit();
23578 
23579  _gl.uniform1i( location, textureUnit );
23580 
23581  if ( ! texture ) continue;
23582 
23583  if ( texture instanceof THREE.CubeTexture ||
23584  ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {
23585 
23586  // CompressedTexture can have Array in image :/
23587 
23588  setCubeTexture( texture, textureUnit );
23589 
23590  } else if ( texture instanceof THREE.WebGLRenderTargetCube ) {
23591 
23592  setCubeTextureDynamic( texture.texture, textureUnit );
23593 
23594  } else if ( texture instanceof THREE.WebGLRenderTarget ) {
23595 
23596  _this.setTexture( texture.texture, textureUnit );
23597 
23598  } else {
23599 
23600  _this.setTexture( texture, textureUnit );
23601 
23602  }
23603 
23604  break;
23605 
23606  case 'tv':
23607 
23608  // array of THREE.Texture (2d or cube)
23609 
23610  if ( uniform._array === undefined ) {
23611 
23612  uniform._array = [];
23613 
23614  }
23615 
23616  for ( var i = 0, il = uniform.value.length; i < il; i ++ ) {
23617 
23618  uniform._array[ i ] = getTextureUnit();
23619 
23620  }
23621 
23622  _gl.uniform1iv( location, uniform._array );
23623 
23624  for ( var i = 0, il = uniform.value.length; i < il; i ++ ) {
23625 
23626  texture = uniform.value[ i ];
23627  textureUnit = uniform._array[ i ];
23628 
23629  if ( ! texture ) continue;
23630 
23631  if ( texture instanceof THREE.CubeTexture ||
23632  ( texture.image instanceof Array && texture.image.length === 6 ) ) {
23633 
23634  // CompressedTexture can have Array in image :/
23635 
23636  setCubeTexture( texture, textureUnit );
23637 
23638  } else if ( texture instanceof THREE.WebGLRenderTarget ) {
23639 
23640  _this.setTexture( texture.texture, textureUnit );
23641 
23642  } else if ( texture instanceof THREE.WebGLRenderTargetCube ) {
23643 
23644  setCubeTextureDynamic( texture.texture, textureUnit );
23645 
23646  } else {
23647 
23648  _this.setTexture( texture, textureUnit );
23649 
23650  }
23651 
23652  }
23653 
23654  break;
23655 
23656  default:
23657 
23658  console.warn( 'THREE.WebGLRenderer: Unknown uniform type: ' + type );
23659 
23660  }
23661 
23662  }
23663 
23664  }
23665 
23666  function setColorLinear( array, offset, color, intensity ) {
23667 
23668  array[ offset + 0 ] = color.r * intensity;
23669  array[ offset + 1 ] = color.g * intensity;
23670  array[ offset + 2 ] = color.b * intensity;
23671 
23672  }
23673 
23674  function setupLights ( lights, camera ) {
23675 
23676  var l, ll, light,
23677  r = 0, g = 0, b = 0,
23678  color, skyColor, groundColor,
23679  intensity,
23680  distance,
23681 
23682  zlights = _lights,
23683 
23684  viewMatrix = camera.matrixWorldInverse,
23685 
23686  dirColors = zlights.directional.colors,
23687  dirPositions = zlights.directional.positions,
23688 
23689  pointColors = zlights.point.colors,
23690  pointPositions = zlights.point.positions,
23691  pointDistances = zlights.point.distances,
23692  pointDecays = zlights.point.decays,
23693 
23694  spotColors = zlights.spot.colors,
23695  spotPositions = zlights.spot.positions,
23696  spotDistances = zlights.spot.distances,
23697  spotDirections = zlights.spot.directions,
23698  spotAnglesCos = zlights.spot.anglesCos,
23699  spotExponents = zlights.spot.exponents,
23700  spotDecays = zlights.spot.decays,
23701 
23702  hemiSkyColors = zlights.hemi.skyColors,
23703  hemiGroundColors = zlights.hemi.groundColors,
23704  hemiPositions = zlights.hemi.positions,
23705 
23706  dirLength = 0,
23707  pointLength = 0,
23708  spotLength = 0,
23709  hemiLength = 0,
23710 
23711  dirCount = 0,
23712  pointCount = 0,
23713  spotCount = 0,
23714  hemiCount = 0,
23715 
23716  dirOffset = 0,
23717  pointOffset = 0,
23718  spotOffset = 0,
23719  hemiOffset = 0;
23720 
23721  for ( l = 0, ll = lights.length; l < ll; l ++ ) {
23722 
23723  light = lights[ l ];
23724 
23725  color = light.color;
23726  intensity = light.intensity;
23727  distance = light.distance;
23728 
23729  if ( light instanceof THREE.AmbientLight ) {
23730 
23731  if ( ! light.visible ) continue;
23732 
23733  r += color.r;
23734  g += color.g;
23735  b += color.b;
23736 
23737  } else if ( light instanceof THREE.DirectionalLight ) {
23738 
23739  dirCount += 1;
23740 
23741  if ( ! light.visible ) continue;
23742 
23743  _direction.setFromMatrixPosition( light.matrixWorld );
23744  _vector3.setFromMatrixPosition( light.target.matrixWorld );
23745  _direction.sub( _vector3 );
23746  _direction.transformDirection( viewMatrix );
23747 
23748  dirOffset = dirLength * 3;
23749 
23750  dirPositions[ dirOffset + 0 ] = _direction.x;
23751  dirPositions[ dirOffset + 1 ] = _direction.y;
23752  dirPositions[ dirOffset + 2 ] = _direction.z;
23753 
23754  setColorLinear( dirColors, dirOffset, color, intensity );
23755 
23756  dirLength += 1;
23757 
23758  } else if ( light instanceof THREE.PointLight ) {
23759 
23760  pointCount += 1;
23761 
23762  if ( ! light.visible ) continue;
23763 
23764  pointOffset = pointLength * 3;
23765 
23766  setColorLinear( pointColors, pointOffset, color, intensity );
23767 
23768  _vector3.setFromMatrixPosition( light.matrixWorld );
23769  _vector3.applyMatrix4( viewMatrix );
23770 
23771  pointPositions[ pointOffset + 0 ] = _vector3.x;
23772  pointPositions[ pointOffset + 1 ] = _vector3.y;
23773  pointPositions[ pointOffset + 2 ] = _vector3.z;
23774 
23775  // distance is 0 if decay is 0, because there is no attenuation at all.
23776  pointDistances[ pointLength ] = distance;
23777  pointDecays[ pointLength ] = ( light.distance === 0 ) ? 0.0 : light.decay;
23778 
23779  pointLength += 1;
23780 
23781  } else if ( light instanceof THREE.SpotLight ) {
23782 
23783  spotCount += 1;
23784 
23785  if ( ! light.visible ) continue;
23786 
23787  spotOffset = spotLength * 3;
23788 
23789  setColorLinear( spotColors, spotOffset, color, intensity );
23790 
23791  _direction.setFromMatrixPosition( light.matrixWorld );
23792  _vector3.copy( _direction ).applyMatrix4( viewMatrix );
23793 
23794  spotPositions[ spotOffset + 0 ] = _vector3.x;
23795  spotPositions[ spotOffset + 1 ] = _vector3.y;
23796  spotPositions[ spotOffset + 2 ] = _vector3.z;
23797 
23798  spotDistances[ spotLength ] = distance;
23799 
23800  _vector3.setFromMatrixPosition( light.target.matrixWorld );
23801  _direction.sub( _vector3 );
23802  _direction.transformDirection( viewMatrix );
23803 
23804  spotDirections[ spotOffset + 0 ] = _direction.x;
23805  spotDirections[ spotOffset + 1 ] = _direction.y;
23806  spotDirections[ spotOffset + 2 ] = _direction.z;
23807 
23808  spotAnglesCos[ spotLength ] = Math.cos( light.angle );
23809  spotExponents[ spotLength ] = light.exponent;
23810  spotDecays[ spotLength ] = ( light.distance === 0 ) ? 0.0 : light.decay;
23811 
23812  spotLength += 1;
23813 
23814  } else if ( light instanceof THREE.HemisphereLight ) {
23815 
23816  hemiCount += 1;
23817 
23818  if ( ! light.visible ) continue;
23819 
23820  _direction.setFromMatrixPosition( light.matrixWorld );
23821  _direction.transformDirection( viewMatrix );
23822 
23823  hemiOffset = hemiLength * 3;
23824 
23825  hemiPositions[ hemiOffset + 0 ] = _direction.x;
23826  hemiPositions[ hemiOffset + 1 ] = _direction.y;
23827  hemiPositions[ hemiOffset + 2 ] = _direction.z;
23828 
23829  skyColor = light.color;
23830  groundColor = light.groundColor;
23831 
23832  setColorLinear( hemiSkyColors, hemiOffset, skyColor, intensity );
23833  setColorLinear( hemiGroundColors, hemiOffset, groundColor, intensity );
23834 
23835  hemiLength += 1;
23836 
23837  }
23838 
23839  }
23840 
23841  // null eventual remains from removed lights
23842  // (this is to avoid if in shader)
23843 
23844  for ( l = dirLength * 3, ll = Math.max( dirColors.length, dirCount * 3 ); l < ll; l ++ ) dirColors[ l ] = 0.0;
23845  for ( l = pointLength * 3, ll = Math.max( pointColors.length, pointCount * 3 ); l < ll; l ++ ) pointColors[ l ] = 0.0;
23846  for ( l = spotLength * 3, ll = Math.max( spotColors.length, spotCount * 3 ); l < ll; l ++ ) spotColors[ l ] = 0.0;
23847  for ( l = hemiLength * 3, ll = Math.max( hemiSkyColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiSkyColors[ l ] = 0.0;
23848  for ( l = hemiLength * 3, ll = Math.max( hemiGroundColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiGroundColors[ l ] = 0.0;
23849 
23850  zlights.directional.length = dirLength;
23851  zlights.point.length = pointLength;
23852  zlights.spot.length = spotLength;
23853  zlights.hemi.length = hemiLength;
23854 
23855  zlights.ambient[ 0 ] = r;
23856  zlights.ambient[ 1 ] = g;
23857  zlights.ambient[ 2 ] = b;
23858 
23859  }
23860 
23861  // GL state setting
23862 
23863  this.setFaceCulling = function ( cullFace, frontFaceDirection ) {
23864 
23865  if ( cullFace === THREE.CullFaceNone ) {
23866 
23867  state.disable( _gl.CULL_FACE );
23868 
23869  } else {
23870 
23871  if ( frontFaceDirection === THREE.FrontFaceDirectionCW ) {
23872 
23873  _gl.frontFace( _gl.CW );
23874 
23875  } else {
23876 
23877  _gl.frontFace( _gl.CCW );
23878 
23879  }
23880 
23881  if ( cullFace === THREE.CullFaceBack ) {
23882 
23883  _gl.cullFace( _gl.BACK );
23884 
23885  } else if ( cullFace === THREE.CullFaceFront ) {
23886 
23887  _gl.cullFace( _gl.FRONT );
23888 
23889  } else {
23890 
23891  _gl.cullFace( _gl.FRONT_AND_BACK );
23892 
23893  }
23894 
23895  state.enable( _gl.CULL_FACE );
23896 
23897  }
23898 
23899  };
23900 
23901  // Textures
23902 
23903  function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {
23904 
23905  var extension;
23906 
23907  if ( isImagePowerOfTwo ) {
23908 
23909  _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
23910  _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
23911 
23912  _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
23913  _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
23914 
23915  } else {
23916 
23917  _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
23918  _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
23919 
23920  if ( texture.wrapS !== THREE.ClampToEdgeWrapping || texture.wrapT !== THREE.ClampToEdgeWrapping ) {
23921 
23922  console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture );
23923 
23924  }
23925 
23926  _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
23927  _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
23928 
23929  if ( texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter ) {
23930 
23931  console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture );
23932 
23933  }
23934 
23935  }
23936 
23937  extension = extensions.get( 'EXT_texture_filter_anisotropic' );
23938 
23939  if ( extension ) {
23940 
23941  if ( texture.type === THREE.FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
23942  if ( texture.type === THREE.HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return;
23943 
23944  if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
23945 
23946  _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _this.getMaxAnisotropy() ) );
23947  properties.get( texture ).__currentAnisotropy = texture.anisotropy;
23948 
23949  }
23950 
23951  }
23952 
23953  }
23954 
23955  function uploadTexture( textureProperties, texture, slot ) {
23956 
23957  if ( textureProperties.__webglInit === undefined ) {
23958 
23959  textureProperties.__webglInit = true;
23960 
23961  texture.addEventListener( 'dispose', onTextureDispose );
23962 
23963  textureProperties.__webglTexture = _gl.createTexture();
23964 
23965  _infoMemory.textures ++;
23966 
23967  }
23968 
23969  state.activeTexture( _gl.TEXTURE0 + slot );
23970  state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
23971 
23972  _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
23973  _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
23974  _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
23975 
23976  texture.image = clampToMaxSize( texture.image, capabilities.maxTextureSize );
23977 
23978  if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false ) {
23979 
23980  texture.image = makePowerOfTwo( texture.image );
23981 
23982  }
23983 
23984  var image = texture.image,
23985  isImagePowerOfTwo = isPowerOfTwo( image ),
23986  glFormat = paramThreeToGL( texture.format ),
23987  glType = paramThreeToGL( texture.type );
23988 
23989  setTextureParameters( _gl.TEXTURE_2D, texture, isImagePowerOfTwo );
23990 
23991  var mipmap, mipmaps = texture.mipmaps;
23992 
23993  if ( texture instanceof THREE.DataTexture ) {
23994 
23995  // use manually created mipmaps if available
23996  // if there are no manual mipmaps
23997  // set 0 level mipmap and then use GL to generate other mipmap levels
23998 
23999  if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
24000 
24001  for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
24002 
24003  mipmap = mipmaps[ i ];
24004  state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
24005 
24006  }
24007 
24008  texture.generateMipmaps = false;
24009 
24010  } else {
24011 
24012  state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
24013 
24014  }
24015 
24016  } else if ( texture instanceof THREE.CompressedTexture ) {
24017 
24018  for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
24019 
24020  mipmap = mipmaps[ i ];
24021 
24022  if ( texture.format !== THREE.RGBAFormat && texture.format !== THREE.RGBFormat ) {
24023 
24024  if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
24025 
24026  state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
24027 
24028  } else {
24029 
24030  console.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()" );
24031 
24032  }
24033 
24034  } else {
24035 
24036  state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
24037 
24038  }
24039 
24040  }
24041 
24042  } else {
24043 
24044  // regular Texture (image, video, canvas)
24045 
24046  // use manually created mipmaps if available
24047  // if there are no manual mipmaps
24048  // set 0 level mipmap and then use GL to generate other mipmap levels
24049 
24050  if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
24051 
24052  for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
24053 
24054  mipmap = mipmaps[ i ];
24055  state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
24056 
24057  }
24058 
24059  texture.generateMipmaps = false;
24060 
24061  } else {
24062 
24063  state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, texture.image );
24064 
24065  }
24066 
24067  }
24068 
24069  if ( texture.generateMipmaps && isImagePowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
24070 
24071  textureProperties.__version = texture.version;
24072 
24073  if ( texture.onUpdate ) texture.onUpdate( texture );
24074 
24075  }
24076 
24077  this.setTexture = function ( texture, slot ) {
24078 
24079  var textureProperties = properties.get( texture );
24080 
24081  if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24082 
24083  var image = texture.image;
24084 
24085  if ( image === undefined ) {
24086 
24087  console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture );
24088  return;
24089 
24090  }
24091 
24092  if ( image.complete === false ) {
24093 
24094  console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture );
24095  return;
24096 
24097  }
24098 
24099  uploadTexture( textureProperties, texture, slot );
24100 
24101  return;
24102 
24103  }
24104 
24105  state.activeTexture( _gl.TEXTURE0 + slot );
24106  state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
24107 
24108  };
24109 
24110  function clampToMaxSize ( image, maxSize ) {
24111 
24112  if ( image.width > maxSize || image.height > maxSize ) {
24113 
24114  // Warning: Scaling through the canvas will only work with images that use
24115  // premultiplied alpha.
24116 
24117  var scale = maxSize / Math.max( image.width, image.height );
24118 
24119  var canvas = document.createElement( 'canvas' );
24120  canvas.width = Math.floor( image.width * scale );
24121  canvas.height = Math.floor( image.height * scale );
24122 
24123  var context = canvas.getContext( '2d' );
24124  context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height );
24125 
24126  console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
24127 
24128  return canvas;
24129 
24130  }
24131 
24132  return image;
24133 
24134  }
24135 
24136  function isPowerOfTwo( image ) {
24137 
24138  return THREE.Math.isPowerOfTwo( image.width ) && THREE.Math.isPowerOfTwo( image.height );
24139 
24140  }
24141 
24142  function textureNeedsPowerOfTwo( texture ) {
24143 
24144  if ( texture.wrapS !== THREE.ClampToEdgeWrapping || texture.wrapT !== THREE.ClampToEdgeWrapping ) return true;
24145  if ( texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter ) return true;
24146 
24147  return false;
24148 
24149  }
24150 
24151  function makePowerOfTwo( image ) {
24152 
24153  if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement ) {
24154 
24155  var canvas = document.createElement( 'canvas' );
24156  canvas.width = THREE.Math.nearestPowerOfTwo( image.width );
24157  canvas.height = THREE.Math.nearestPowerOfTwo( image.height );
24158 
24159  var context = canvas.getContext( '2d' );
24160  context.drawImage( image, 0, 0, canvas.width, canvas.height );
24161 
24162  console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
24163 
24164  return canvas;
24165 
24166  }
24167 
24168  return image;
24169 
24170  }
24171 
24172  function setCubeTexture ( texture, slot ) {
24173 
24174  var textureProperties = properties.get( texture );
24175 
24176  if ( texture.image.length === 6 ) {
24177 
24178  if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24179 
24180  if ( ! textureProperties.__image__webglTextureCube ) {
24181 
24182  texture.addEventListener( 'dispose', onTextureDispose );
24183 
24184  textureProperties.__image__webglTextureCube = _gl.createTexture();
24185 
24186  _infoMemory.textures ++;
24187 
24188  }
24189 
24190  state.activeTexture( _gl.TEXTURE0 + slot );
24191  state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
24192 
24193  _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
24194 
24195  var isCompressed = texture instanceof THREE.CompressedTexture;
24196  var isDataTexture = texture.image[ 0 ] instanceof THREE.DataTexture;
24197 
24198  var cubeImage = [];
24199 
24200  for ( var i = 0; i < 6; i ++ ) {
24201 
24202  if ( _this.autoScaleCubemaps && ! isCompressed && ! isDataTexture ) {
24203 
24204  cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize );
24205 
24206  } else {
24207 
24208  cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
24209 
24210  }
24211 
24212  }
24213 
24214  var image = cubeImage[ 0 ],
24215  isImagePowerOfTwo = isPowerOfTwo( image ),
24216  glFormat = paramThreeToGL( texture.format ),
24217  glType = paramThreeToGL( texture.type );
24218 
24219  setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isImagePowerOfTwo );
24220 
24221  for ( var i = 0; i < 6; i ++ ) {
24222 
24223  if ( ! isCompressed ) {
24224 
24225  if ( isDataTexture ) {
24226 
24227  state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
24228 
24229  } else {
24230 
24231  state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
24232 
24233  }
24234 
24235  } else {
24236 
24237  var mipmap, mipmaps = cubeImage[ i ].mipmaps;
24238 
24239  for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
24240 
24241  mipmap = mipmaps[ j ];
24242 
24243  if ( texture.format !== THREE.RGBAFormat && texture.format !== THREE.RGBFormat ) {
24244 
24245  if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
24246 
24247  state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
24248 
24249  } else {
24250 
24251  console.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setCubeTexture()" );
24252 
24253  }
24254 
24255  } else {
24256 
24257  state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
24258 
24259  }
24260 
24261  }
24262 
24263  }
24264 
24265  }
24266 
24267  if ( texture.generateMipmaps && isImagePowerOfTwo ) {
24268 
24269  _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
24270 
24271  }
24272 
24273  textureProperties.__version = texture.version;
24274 
24275  if ( texture.onUpdate ) texture.onUpdate( texture );
24276 
24277  } else {
24278 
24279  state.activeTexture( _gl.TEXTURE0 + slot );
24280  state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
24281 
24282  }
24283 
24284  }
24285 
24286  }
24287 
24288  function setCubeTextureDynamic ( texture, slot ) {
24289 
24290  state.activeTexture( _gl.TEXTURE0 + slot );
24291  state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture );
24292 
24293  }
24294 
24295  // Render targets
24296 
24297  function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
24298 
24299  _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
24300  _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
24301 
24302  }
24303 
24304  function setupRenderBuffer ( renderbuffer, renderTarget ) {
24305 
24306  _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
24307 
24308  if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
24309 
24310  _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
24311  _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
24312 
24313  /* For some reason this is not working. Defaulting to RGBA4.
24314  } else if ( ! renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
24315 
24316  _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTarget.width, renderTarget.height );
24317  _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
24318  */
24319 
24320  } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
24321 
24322  _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
24323  _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
24324 
24325  } else {
24326 
24327  _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
24328 
24329  }
24330 
24331  }
24332 
24333  this.setRenderTarget = function ( renderTarget ) {
24334 
24335  var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
24336 
24337  if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
24338 
24339  var renderTargetProperties = properties.get( renderTarget );
24340  var textureProperties = properties.get( renderTarget.texture );
24341 
24342  if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
24343  if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
24344 
24345  renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
24346 
24347  textureProperties.__webglTexture = _gl.createTexture();
24348 
24349  _infoMemory.textures ++;
24350 
24351  // Setup texture, create render and frame buffers
24352 
24353  var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ),
24354  glFormat = paramThreeToGL( renderTarget.texture.format ),
24355  glType = paramThreeToGL( renderTarget.texture.type );
24356 
24357  if ( isCube ) {
24358 
24359  renderTargetProperties.__webglFramebuffer = [];
24360  renderTargetProperties.__webglRenderbuffer = [];
24361 
24362  state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
24363 
24364  setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo );
24365 
24366  for ( var i = 0; i < 6; i ++ ) {
24367 
24368  renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
24369  renderTargetProperties.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
24370  state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
24371 
24372  setupFrameBuffer( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
24373  setupRenderBuffer( renderTargetProperties.__webglRenderbuffer[ i ], renderTarget );
24374 
24375  }
24376 
24377  if ( renderTarget.texture.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
24378 
24379  } else {
24380 
24381  renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
24382 
24383  if ( renderTarget.shareDepthFrom ) {
24384 
24385  renderTargetProperties.__webglRenderbuffer = renderTarget.shareDepthFrom.__webglRenderbuffer;
24386 
24387  } else {
24388 
24389  renderTargetProperties.__webglRenderbuffer = _gl.createRenderbuffer();
24390 
24391  }
24392 
24393  state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
24394  setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo );
24395 
24396  state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
24397 
24398  setupFrameBuffer( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );
24399 
24400  if ( renderTarget.shareDepthFrom ) {
24401 
24402  if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
24403 
24404  _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTargetProperties.__webglRenderbuffer );
24405 
24406  } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
24407 
24408  _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTargetProperties.__webglRenderbuffer );
24409 
24410  }
24411 
24412  } else {
24413 
24414  setupRenderBuffer( renderTargetProperties.__webglRenderbuffer, renderTarget );
24415 
24416  }
24417 
24418  if ( renderTarget.texture.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
24419 
24420  }
24421 
24422  // Release everything
24423 
24424  if ( isCube ) {
24425 
24426  state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
24427 
24428  } else {
24429 
24430  state.bindTexture( _gl.TEXTURE_2D, null );
24431 
24432  }
24433 
24434  _gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
24435  _gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
24436 
24437  }
24438 
24439  var framebuffer, width, height, vx, vy;
24440 
24441  if ( renderTarget ) {
24442 
24443  var renderTargetProperties = properties.get( renderTarget );
24444 
24445  if ( isCube ) {
24446 
24447  framebuffer = renderTargetProperties.__webglFramebuffer[ renderTarget.activeCubeFace ];
24448 
24449  } else {
24450 
24451  framebuffer = renderTargetProperties.__webglFramebuffer;
24452 
24453  }
24454 
24455  width = renderTarget.width;
24456  height = renderTarget.height;
24457 
24458  vx = 0;
24459  vy = 0;
24460 
24461  } else {
24462 
24463  framebuffer = null;
24464 
24465  width = _viewportWidth;
24466  height = _viewportHeight;
24467 
24468  vx = _viewportX;
24469  vy = _viewportY;
24470 
24471  }
24472 
24473  if ( framebuffer !== _currentFramebuffer ) {
24474 
24475  _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
24476  _gl.viewport( vx, vy, width, height );
24477 
24478  _currentFramebuffer = framebuffer;
24479 
24480  }
24481 
24482  if ( isCube ) {
24483 
24484  var textureProperties = properties.get( renderTarget.texture );
24485  _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, 0 );
24486 
24487  }
24488 
24489  _currentWidth = width;
24490  _currentHeight = height;
24491 
24492  };
24493 
24494  this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) {
24495 
24496  if ( renderTarget instanceof THREE.WebGLRenderTarget === false ) {
24497 
24498  console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
24499  return;
24500 
24501  }
24502 
24503  var framebuffer = properties.get( renderTarget ).__webglFramebuffer;
24504 
24505  if ( framebuffer ) {
24506 
24507  var restore = false;
24508 
24509  if ( framebuffer !== _currentFramebuffer ) {
24510 
24511  _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
24512 
24513  restore = true;
24514 
24515  }
24516 
24517  try {
24518 
24519  var texture = renderTarget.texture;
24520 
24521  if ( texture.format !== THREE.RGBAFormat
24522  && paramThreeToGL( texture.format ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
24523 
24524  console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
24525  return;
24526 
24527  }
24528 
24529  if ( texture.type !== THREE.UnsignedByteType
24530  && paramThreeToGL( texture.type ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE )
24531  && ! ( texture.type === THREE.FloatType && extensions.get( 'WEBGL_color_buffer_float' ) )
24532  && ! ( texture.type === THREE.HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) {
24533 
24534  console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
24535  return;
24536 
24537  }
24538 
24539  if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {
24540 
24541  _gl.readPixels( x, y, width, height, paramThreeToGL( texture.format ), paramThreeToGL( texture.type ), buffer );
24542 
24543  } else {
24544 
24545  console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
24546 
24547  }
24548 
24549  } finally {
24550 
24551  if ( restore ) {
24552 
24553  _gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer );
24554 
24555  }
24556 
24557  }
24558 
24559  }
24560 
24561  };
24562 
24563  function updateRenderTargetMipmap( renderTarget ) {
24564 
24565  var target = renderTarget instanceof THREE.WebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
24566  var texture = properties.get( renderTarget.texture ).__webglTexture;
24567 
24568  state.bindTexture( target, texture );
24569  _gl.generateMipmap( target );
24570  state.bindTexture( target, null );
24571 
24572  }
24573 
24574  // Fallback filters for non-power-of-2 textures
24575 
24576  function filterFallback ( f ) {
24577 
24578  if ( f === THREE.NearestFilter || f === THREE.NearestMipMapNearestFilter || f === THREE.NearestMipMapLinearFilter ) {
24579 
24580  return _gl.NEAREST;
24581 
24582  }
24583 
24584  return _gl.LINEAR;
24585 
24586  }
24587 
24588  // Map three.js constants to WebGL constants
24589 
24590  function paramThreeToGL ( p ) {
24591 
24592  var extension;
24593 
24594  if ( p === THREE.RepeatWrapping ) return _gl.REPEAT;
24595  if ( p === THREE.ClampToEdgeWrapping ) return _gl.CLAMP_TO_EDGE;
24596  if ( p === THREE.MirroredRepeatWrapping ) return _gl.MIRRORED_REPEAT;
24597 
24598  if ( p === THREE.NearestFilter ) return _gl.NEAREST;
24599  if ( p === THREE.NearestMipMapNearestFilter ) return _gl.NEAREST_MIPMAP_NEAREST;
24600  if ( p === THREE.NearestMipMapLinearFilter ) return _gl.NEAREST_MIPMAP_LINEAR;
24601 
24602  if ( p === THREE.LinearFilter ) return _gl.LINEAR;
24603  if ( p === THREE.LinearMipMapNearestFilter ) return _gl.LINEAR_MIPMAP_NEAREST;
24604  if ( p === THREE.LinearMipMapLinearFilter ) return _gl.LINEAR_MIPMAP_LINEAR;
24605 
24606  if ( p === THREE.UnsignedByteType ) return _gl.UNSIGNED_BYTE;
24607  if ( p === THREE.UnsignedShort4444Type ) return _gl.UNSIGNED_SHORT_4_4_4_4;
24608  if ( p === THREE.UnsignedShort5551Type ) return _gl.UNSIGNED_SHORT_5_5_5_1;
24609  if ( p === THREE.UnsignedShort565Type ) return _gl.UNSIGNED_SHORT_5_6_5;
24610 
24611  if ( p === THREE.ByteType ) return _gl.BYTE;
24612  if ( p === THREE.ShortType ) return _gl.SHORT;
24613  if ( p === THREE.UnsignedShortType ) return _gl.UNSIGNED_SHORT;
24614  if ( p === THREE.IntType ) return _gl.INT;
24615  if ( p === THREE.UnsignedIntType ) return _gl.UNSIGNED_INT;
24616  if ( p === THREE.FloatType ) return _gl.FLOAT;
24617 
24618  extension = extensions.get( 'OES_texture_half_float' );
24619 
24620  if ( extension !== null ) {
24621 
24622  if ( p === THREE.HalfFloatType ) return extension.HALF_FLOAT_OES;
24623 
24624  }
24625 
24626  if ( p === THREE.AlphaFormat ) return _gl.ALPHA;
24627  if ( p === THREE.RGBFormat ) return _gl.RGB;
24628  if ( p === THREE.RGBAFormat ) return _gl.RGBA;
24629  if ( p === THREE.LuminanceFormat ) return _gl.LUMINANCE;
24630  if ( p === THREE.LuminanceAlphaFormat ) return _gl.LUMINANCE_ALPHA;
24631 
24632  if ( p === THREE.AddEquation ) return _gl.FUNC_ADD;
24633  if ( p === THREE.SubtractEquation ) return _gl.FUNC_SUBTRACT;
24634  if ( p === THREE.ReverseSubtractEquation ) return _gl.FUNC_REVERSE_SUBTRACT;
24635 
24636  if ( p === THREE.ZeroFactor ) return _gl.ZERO;
24637  if ( p === THREE.OneFactor ) return _gl.ONE;
24638  if ( p === THREE.SrcColorFactor ) return _gl.SRC_COLOR;
24639  if ( p === THREE.OneMinusSrcColorFactor ) return _gl.ONE_MINUS_SRC_COLOR;
24640  if ( p === THREE.SrcAlphaFactor ) return _gl.SRC_ALPHA;
24641  if ( p === THREE.OneMinusSrcAlphaFactor ) return _gl.ONE_MINUS_SRC_ALPHA;
24642  if ( p === THREE.DstAlphaFactor ) return _gl.DST_ALPHA;
24643  if ( p === THREE.OneMinusDstAlphaFactor ) return _gl.ONE_MINUS_DST_ALPHA;
24644 
24645  if ( p === THREE.DstColorFactor ) return _gl.DST_COLOR;
24646  if ( p === THREE.OneMinusDstColorFactor ) return _gl.ONE_MINUS_DST_COLOR;
24647  if ( p === THREE.SrcAlphaSaturateFactor ) return _gl.SRC_ALPHA_SATURATE;
24648 
24649  extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
24650 
24651  if ( extension !== null ) {
24652 
24653  if ( p === THREE.RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
24654  if ( p === THREE.RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
24655  if ( p === THREE.RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
24656  if ( p === THREE.RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
24657 
24658  }
24659 
24660  extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
24661 
24662  if ( extension !== null ) {
24663 
24664  if ( p === THREE.RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
24665  if ( p === THREE.RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
24666  if ( p === THREE.RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
24667  if ( p === THREE.RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
24668 
24669  }
24670 
24671  extension = extensions.get( 'EXT_blend_minmax' );
24672 
24673  if ( extension !== null ) {
24674 
24675  if ( p === THREE.MinEquation ) return extension.MIN_EXT;
24676  if ( p === THREE.MaxEquation ) return extension.MAX_EXT;
24677 
24678  }
24679 
24680  return 0;
24681 
24682  }
24683 
24684  // DEPRECATED
24685 
24686  this.supportsFloatTextures = function () {
24687 
24688  console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
24689  return extensions.get( 'OES_texture_float' );
24690 
24691  };
24692 
24693  this.supportsHalfFloatTextures = function () {
24694 
24695  console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
24696  return extensions.get( 'OES_texture_half_float' );
24697 
24698  };
24699 
24700  this.supportsStandardDerivatives = function () {
24701 
24702  console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
24703  return extensions.get( 'OES_standard_derivatives' );
24704 
24705  };
24706 
24707  this.supportsCompressedTextureS3TC = function () {
24708 
24709  console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
24710  return extensions.get( 'WEBGL_compressed_texture_s3tc' );
24711 
24712  };
24713 
24714  this.supportsCompressedTexturePVRTC = function () {
24715 
24716  console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
24717  return extensions.get( 'WEBGL_compressed_texture_pvrtc' );
24718 
24719  };
24720 
24721  this.supportsBlendMinMax = function () {
24722 
24723  console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
24724  return extensions.get( 'EXT_blend_minmax' );
24725 
24726  };
24727 
24728  this.supportsVertexTextures = function () {
24729 
24730  return capabilities.vertexTextures;
24731 
24732  };
24733 
24734  this.supportsInstancedArrays = function () {
24735 
24736  console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
24737  return extensions.get( 'ANGLE_instanced_arrays' );
24738 
24739  };
24740 
24741  //
24742 
24743  this.initMaterial = function () {
24744 
24745  console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
24746 
24747  };
24748 
24749  this.addPrePlugin = function () {
24750 
24751  console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
24752 
24753  };
24754 
24755  this.addPostPlugin = function () {
24756 
24757  console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
24758 
24759  };
24760 
24761  this.updateShadowMap = function () {
24762 
24763  console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
24764 
24765  };
24766 
24767  Object.defineProperties( this, {
24768  shadowMapEnabled: {
24769  get: function () {
24770 
24771  return shadowMap.enabled;
24772 
24773  },
24774  set: function ( value ) {
24775 
24776  console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
24777  shadowMap.enabled = value;
24778 
24779  }
24780  },
24781  shadowMapType: {
24782  get: function () {
24783 
24784  return shadowMap.type;
24785 
24786  },
24787  set: function ( value ) {
24788 
24789  console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
24790  shadowMap.type = value;
24791 
24792  }
24793  },
24794  shadowMapCullFace: {
24795  get: function () {
24796 
24797  return shadowMap.cullFace;
24798 
24799  },
24800  set: function ( value ) {
24801 
24802  console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace is now .shadowMap.cullFace.' );
24803  shadowMap.cullFace = value;
24804 
24805  }
24806  },
24807  shadowMapDebug: {
24808  get: function () {
24809 
24810  return shadowMap.debug;
24811 
24812  },
24813  set: function ( value ) {
24814 
24815  console.warn( 'THREE.WebGLRenderer: .shadowMapDebug is now .shadowMap.debug.' );
24816  shadowMap.debug = value;
24817 
24818  }
24819  }
24820  } );
24821 
24822 };
24823 
24824 // File:src/renderers/WebGLRenderTarget.js
24825 
24831 THREE.WebGLRenderTarget = function ( width, height, options ) {
24832 
24833  this.uuid = THREE.Math.generateUUID();
24834 
24835  this.width = width;
24836  this.height = height;
24837 
24838  options = options || {};
24839 
24840  if ( options.minFilter === undefined ) options.minFilter = THREE.LinearFilter;
24841 
24842  this.texture = new THREE.Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy );
24843 
24844  this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
24845  this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
24846 
24847  this.shareDepthFrom = options.shareDepthFrom !== undefined ? options.shareDepthFrom : null;
24848 
24849 };
24850 
24851 THREE.WebGLRenderTarget.prototype = {
24852 
24853  constructor: THREE.WebGLRenderTarget,
24854 
24855  get wrapS() {
24856 
24857  console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
24858 
24859  return this.texture.wrapS;
24860 
24861  },
24862 
24863  set wrapS( value ) {
24864 
24865  console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
24866 
24867  this.texture.wrapS = value;
24868 
24869  },
24870 
24871  get wrapT() {
24872 
24873  console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
24874 
24875  return this.texture.wrapT;
24876 
24877  },
24878 
24879  set wrapT( value ) {
24880 
24881  console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
24882 
24883  this.texture.wrapT = value;
24884 
24885  },
24886 
24887  get magFilter() {
24888 
24889  console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
24890 
24891  return this.texture.magFilter;
24892 
24893  },
24894 
24895  set magFilter( value ) {
24896 
24897  console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
24898 
24899  this.texture.magFilter = value;
24900 
24901  },
24902 
24903  get minFilter() {
24904 
24905  console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
24906 
24907  return this.texture.minFilter;
24908 
24909  },
24910 
24911  set minFilter( value ) {
24912 
24913  console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
24914 
24915  this.texture.minFilter = value;
24916 
24917  },
24918 
24919  get anisotropy() {
24920 
24921  console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
24922 
24923  return this.texture.anisotropy;
24924 
24925  },
24926 
24927  set anisotropy( value ) {
24928 
24929  console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
24930 
24931  this.texture.anisotropy = value;
24932 
24933  },
24934 
24935  get offset() {
24936 
24937  console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
24938 
24939  return this.texture.offset;
24940 
24941  },
24942 
24943  set offset( value ) {
24944 
24945  console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
24946 
24947  this.texture.offset = value;
24948 
24949  },
24950 
24951  get repeat() {
24952 
24953  console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
24954 
24955  return this.texture.repeat;
24956 
24957  },
24958 
24959  set repeat( value ) {
24960 
24961  console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
24962 
24963  this.texture.repeat = value;
24964 
24965  },
24966 
24967  get format() {
24968 
24969  console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
24970 
24971  return this.texture.format;
24972 
24973  },
24974 
24975  set format( value ) {
24976 
24977  console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
24978 
24979  this.texture.format = value;
24980 
24981  },
24982 
24983  get type() {
24984 
24985  console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
24986 
24987  return this.texture.type;
24988 
24989  },
24990 
24991  set type( value ) {
24992 
24993  console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
24994 
24995  this.texture.type = value;
24996 
24997  },
24998 
24999  get generateMipmaps() {
25000 
25001  console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
25002 
25003  return this.texture.generateMipmaps;
25004 
25005  },
25006 
25007  set generateMipmaps( value ) {
25008 
25009  console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
25010 
25011  this.texture.generateMipmaps = value;
25012 
25013  },
25014 
25015  //
25016 
25017  setSize: function ( width, height ) {
25018 
25019  if ( this.width !== width || this.height !== height ) {
25020 
25021  this.width = width;
25022  this.height = height;
25023 
25024  this.dispose();
25025 
25026  }
25027 
25028  },
25029 
25030  clone: function () {
25031 
25032  return new this.constructor().copy( this );
25033 
25034  },
25035 
25036  copy: function ( source ) {
25037 
25038  this.width = source.width;
25039  this.height = source.height;
25040 
25041  this.texture = source.texture.clone();
25042 
25043  this.depthBuffer = source.depthBuffer;
25044  this.stencilBuffer = source.stencilBuffer;
25045 
25046  this.shareDepthFrom = source.shareDepthFrom;
25047 
25048  return this;
25049 
25050  },
25051 
25052  dispose: function () {
25053 
25054  this.dispatchEvent( { type: 'dispose' } );
25055 
25056  }
25057 
25058 };
25059 
25060 THREE.EventDispatcher.prototype.apply( THREE.WebGLRenderTarget.prototype );
25061 
25062 // File:src/renderers/WebGLRenderTargetCube.js
25063 
25068 THREE.WebGLRenderTargetCube = function ( width, height, options ) {
25069 
25070  THREE.WebGLRenderTarget.call( this, width, height, options );
25071 
25072  this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5
25073 
25074 };
25075 
25076 THREE.WebGLRenderTargetCube.prototype = Object.create( THREE.WebGLRenderTarget.prototype );
25077 THREE.WebGLRenderTargetCube.prototype.constructor = THREE.WebGLRenderTargetCube;
25078 
25079 // File:src/renderers/webgl/WebGLBufferRenderer.js
25080 
25085 THREE.WebGLBufferRenderer = function ( _gl, extensions, _infoRender ) {
25086 
25087  var mode;
25088 
25089  function setMode( value ) {
25090 
25091  mode = value;
25092 
25093  }
25094 
25095  function render( start, count ) {
25096 
25097  _gl.drawArrays( mode, start, count );
25098 
25099  _infoRender.calls ++;
25100  _infoRender.vertices += count;
25101  if ( mode === _gl.TRIANGLES ) _infoRender.faces += count / 3;
25102 
25103  }
25104 
25105  function renderInstances( geometry ) {
25106 
25107  var extension = extensions.get( 'ANGLE_instanced_arrays' );
25108 
25109  if ( extension === null ) {
25110 
25111  console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
25112  return;
25113 
25114  }
25115 
25116  var position = geometry.attributes.position;
25117 
25118  if ( position instanceof THREE.InterleavedBufferAttribute ) {
25119 
25120  extension.drawArraysInstancedANGLE( mode, 0, position.data.count, geometry.maxInstancedCount );
25121 
25122  } else {
25123 
25124  extension.drawArraysInstancedANGLE( mode, 0, position.count, geometry.maxInstancedCount );
25125 
25126  }
25127 
25128  }
25129 
25130  this.setMode = setMode;
25131  this.render = render;
25132  this.renderInstances = renderInstances;
25133 
25134 };
25135 
25136 // File:src/renderers/webgl/WebGLIndexedBufferRenderer.js
25137 
25142 THREE.WebGLIndexedBufferRenderer = function ( _gl, extensions, _infoRender ) {
25143 
25144  var mode;
25145 
25146  function setMode( value ) {
25147 
25148  mode = value;
25149 
25150  }
25151 
25152  var type, size;
25153 
25154  function setIndex( index ) {
25155 
25156  if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) {
25157 
25158  type = _gl.UNSIGNED_INT;
25159  size = 4;
25160 
25161  } else {
25162 
25163  type = _gl.UNSIGNED_SHORT;
25164  size = 2;
25165 
25166  }
25167 
25168  }
25169 
25170  function render( start, count ) {
25171 
25172  _gl.drawElements( mode, count, type, start * size );
25173 
25174  _infoRender.calls ++;
25175  _infoRender.vertices += count;
25176  if ( mode === _gl.TRIANGLES ) _infoRender.faces += count / 3;
25177 
25178  }
25179 
25180  function renderInstances( geometry ) {
25181 
25182  var extension = extensions.get( 'ANGLE_instanced_arrays' );
25183 
25184  if ( extension === null ) {
25185 
25186  console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
25187  return;
25188 
25189  }
25190 
25191  var index = geometry.index;
25192 
25193  extension.drawElementsInstancedANGLE( mode, index.array.length, type, 0, geometry.maxInstancedCount );
25194 
25195  }
25196 
25197  this.setMode = setMode;
25198  this.setIndex = setIndex;
25199  this.render = render;
25200  this.renderInstances = renderInstances;
25201 
25202 };
25203 
25204 // File:src/renderers/webgl/WebGLExtensions.js
25205 
25210 THREE.WebGLExtensions = function ( gl ) {
25211 
25212  var extensions = {};
25213 
25214  this.get = function ( name ) {
25215 
25216  if ( extensions[ name ] !== undefined ) {
25217 
25218  return extensions[ name ];
25219 
25220  }
25221 
25222  var extension;
25223 
25224  switch ( name ) {
25225 
25226  case 'EXT_texture_filter_anisotropic':
25227  extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
25228  break;
25229 
25230  case 'WEBGL_compressed_texture_s3tc':
25231  extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
25232  break;
25233 
25234  case 'WEBGL_compressed_texture_pvrtc':
25235  extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
25236  break;
25237 
25238  default:
25239  extension = gl.getExtension( name );
25240 
25241  }
25242 
25243  if ( extension === null ) {
25244 
25245  console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
25246 
25247  }
25248 
25249  extensions[ name ] = extension;
25250 
25251  return extension;
25252 
25253  };
25254 
25255 };
25256 
25257 // File:src/renderers/webgl/WebGLCapabilities.js
25258 
25259 THREE.WebGLCapabilities = function ( gl, extensions, parameters ) {
25260 
25261  function getMaxPrecision( precision ) {
25262 
25263  if ( precision === 'highp' ) {
25264 
25265  if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 &&
25266  gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) {
25267 
25268  return 'highp';
25269 
25270  }
25271 
25272  precision = 'mediump';
25273 
25274  }
25275 
25276  if ( precision === 'mediump' ) {
25277 
25278  if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 &&
25279  gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) {
25280 
25281  return 'mediump';
25282 
25283  }
25284 
25285  }
25286 
25287  return 'lowp';
25288 
25289  }
25290 
25291  this.getMaxPrecision = getMaxPrecision;
25292 
25293  this.precision = parameters.precision !== undefined ? parameters.precision : 'highp',
25294  this.logarithmicDepthBuffer = parameters.logarithmicDepthBuffer !== undefined ? parameters.logarithmicDepthBuffer : false;
25295 
25296  this.maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
25297  this.maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
25298  this.maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );
25299  this.maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE );
25300 
25301  this.maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
25302  this.maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS );
25303  this.maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS );
25304  this.maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
25305 
25306  this.vertexTextures = this.maxVertexTextures > 0;
25307  this.floatFragmentTextures = !! extensions.get( 'OES_texture_float' );
25308  this.floatVertexTextures = this.vertexTextures && this.floatFragmentTextures;
25309 
25310  var _maxPrecision = getMaxPrecision( this.precision );
25311 
25312  if ( _maxPrecision !== this.precision ) {
25313 
25314  console.warn( 'THREE.WebGLRenderer:', this.precision, 'not supported, using', _maxPrecision, 'instead.' );
25315  this.precision = _maxPrecision;
25316 
25317  }
25318 
25319  if ( this.logarithmicDepthBuffer ) {
25320 
25321  this.logarithmicDepthBuffer = !! extensions.get( 'EXT_frag_depth' );
25322 
25323  }
25324 
25325 };
25326 
25327 // File:src/renderers/webgl/WebGLGeometries.js
25328 
25333 THREE.WebGLGeometries = function ( gl, properties, info ) {
25334 
25335  var geometries = {};
25336 
25337  function get( object ) {
25338 
25339  var geometry = object.geometry;
25340 
25341  if ( geometries[ geometry.id ] !== undefined ) {
25342 
25343  return geometries[ geometry.id ];
25344 
25345  }
25346 
25347  geometry.addEventListener( 'dispose', onGeometryDispose );
25348 
25349  var buffergeometry;
25350 
25351  if ( geometry instanceof THREE.BufferGeometry ) {
25352 
25353  buffergeometry = geometry;
25354 
25355  } else if ( geometry instanceof THREE.Geometry ) {
25356 
25357  if ( geometry._bufferGeometry === undefined ) {
25358 
25359  geometry._bufferGeometry = new THREE.BufferGeometry().setFromObject( object );
25360 
25361  }
25362 
25363  buffergeometry = geometry._bufferGeometry;
25364 
25365  }
25366 
25367  geometries[ geometry.id ] = buffergeometry;
25368 
25369  info.memory.geometries ++;
25370 
25371  return buffergeometry;
25372 
25373  }
25374 
25375  function onGeometryDispose( event ) {
25376 
25377  var geometry = event.target;
25378  var buffergeometry = geometries[ geometry.id ];
25379 
25380  deleteAttributes( buffergeometry.attributes );
25381 
25382  geometry.removeEventListener( 'dispose', onGeometryDispose );
25383 
25384  delete geometries[ geometry.id ];
25385 
25386  var property = properties.get( geometry );
25387  if ( property.wireframe ) deleteAttribute( property.wireframe );
25388 
25389  info.memory.geometries --;
25390 
25391  }
25392 
25393  function getAttributeBuffer( attribute ) {
25394 
25395  if ( attribute instanceof THREE.InterleavedBufferAttribute ) {
25396 
25397  return properties.get( attribute.data ).__webglBuffer;
25398 
25399  }
25400 
25401  return properties.get( attribute ).__webglBuffer;
25402 
25403  }
25404 
25405  function deleteAttribute( attribute ) {
25406 
25407  var buffer = getAttributeBuffer( attribute );
25408 
25409  if ( buffer !== undefined ) {
25410 
25411  gl.deleteBuffer( buffer );
25412  removeAttributeBuffer( attribute );
25413 
25414  }
25415 
25416  }
25417 
25418  function deleteAttributes( attributes ) {
25419 
25420  for ( var name in attributes ) {
25421 
25422  deleteAttribute( attributes[ name ] );
25423 
25424  }
25425 
25426  }
25427 
25428  function removeAttributeBuffer( attribute ) {
25429 
25430  if ( attribute instanceof THREE.InterleavedBufferAttribute ) {
25431 
25432  properties.delete( attribute.data );
25433 
25434  } else {
25435 
25436  properties.delete( attribute );
25437 
25438  }
25439 
25440  }
25441 
25442  this.get = get;
25443 
25444 };
25445 
25446 // File:src/renderers/webgl/WebGLObjects.js
25447 
25452 THREE.WebGLObjects = function ( gl, properties, info ) {
25453 
25454  var geometries = new THREE.WebGLGeometries( gl, properties, info );
25455 
25456  //
25457 
25458  function update( object ) {
25459 
25460  // TODO: Avoid updating twice (when using shadowMap). Maybe add frame counter.
25461 
25462  var geometry = geometries.get( object );
25463 
25464  if ( object.geometry instanceof THREE.Geometry ) {
25465 
25466  geometry.updateFromObject( object );
25467 
25468  }
25469 
25470  var index = geometry.index;
25471  var attributes = geometry.attributes;
25472 
25473  if ( index !== null ) {
25474 
25475  updateAttribute( index, gl.ELEMENT_ARRAY_BUFFER );
25476 
25477  }
25478 
25479  for ( var name in attributes ) {
25480 
25481  updateAttribute( attributes[ name ], gl.ARRAY_BUFFER );
25482 
25483  }
25484 
25485  // morph targets
25486 
25487  var morphAttributes = geometry.morphAttributes;
25488 
25489  for ( var name in morphAttributes ) {
25490 
25491  var array = morphAttributes[ name ];
25492 
25493  for ( var i = 0, l = array.length; i < l; i ++ ) {
25494 
25495  updateAttribute( array[ i ], gl.ARRAY_BUFFER );
25496 
25497  }
25498 
25499  }
25500 
25501  return geometry;
25502 
25503  }
25504 
25505  function updateAttribute( attribute, bufferType ) {
25506 
25507  var data = ( attribute instanceof THREE.InterleavedBufferAttribute ) ? attribute.data : attribute;
25508 
25509  var attributeProperties = properties.get( data );
25510 
25511  if ( attributeProperties.__webglBuffer === undefined ) {
25512 
25513  createBuffer( attributeProperties, data, bufferType );
25514 
25515  } else if ( attributeProperties.version !== data.version ) {
25516 
25517  updateBuffer( attributeProperties, data, bufferType );
25518 
25519  }
25520 
25521  }
25522 
25523  function createBuffer( attributeProperties, data, bufferType ) {
25524 
25525  attributeProperties.__webglBuffer = gl.createBuffer();
25526  gl.bindBuffer( bufferType, attributeProperties.__webglBuffer );
25527 
25528  var usage = data.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;
25529 
25530  gl.bufferData( bufferType, data.array, usage );
25531 
25532  attributeProperties.version = data.version;
25533 
25534  }
25535 
25536  function updateBuffer( attributeProperties, data, bufferType ) {
25537 
25538  gl.bindBuffer( bufferType, attributeProperties.__webglBuffer );
25539 
25540  if ( data.dynamic === false || data.updateRange.count === - 1 ) {
25541 
25542  // Not using update ranges
25543 
25544  gl.bufferSubData( bufferType, 0, data.array );
25545 
25546  } else if ( data.updateRange.count === 0 ) {
25547 
25548  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.' );
25549 
25550  } else {
25551 
25552  gl.bufferSubData( bufferType, data.updateRange.offset * data.array.BYTES_PER_ELEMENT,
25553  data.array.subarray( data.updateRange.offset, data.updateRange.offset + data.updateRange.count ) );
25554 
25555  data.updateRange.count = 0; // reset range
25556 
25557  }
25558 
25559  attributeProperties.version = data.version;
25560 
25561  }
25562 
25563  function getAttributeBuffer( attribute ) {
25564 
25565  if ( attribute instanceof THREE.InterleavedBufferAttribute ) {
25566 
25567  return properties.get( attribute.data ).__webglBuffer;
25568 
25569  }
25570 
25571  return properties.get( attribute ).__webglBuffer;
25572 
25573  }
25574 
25575  function getWireframeAttribute( geometry ) {
25576 
25577  var property = properties.get( geometry );
25578 
25579  if ( property.wireframe !== undefined ) {
25580 
25581  return property.wireframe;
25582 
25583  }
25584 
25585  var indices = [];
25586 
25587  var index = geometry.index;
25588  var attributes = geometry.attributes;
25589  var position = attributes.position;
25590 
25591  // console.time( 'wireframe' );
25592 
25593  if ( index !== null ) {
25594 
25595  var edges = {};
25596  var array = index.array;
25597 
25598  for ( var i = 0, l = array.length; i < l; i += 3 ) {
25599 
25600  var a = array[ i + 0 ];
25601  var b = array[ i + 1 ];
25602  var c = array[ i + 2 ];
25603 
25604  if ( checkEdge( edges, a, b ) ) indices.push( a, b );
25605  if ( checkEdge( edges, b, c ) ) indices.push( b, c );
25606  if ( checkEdge( edges, c, a ) ) indices.push( c, a );
25607 
25608  }
25609 
25610  } else {
25611 
25612  var array = attributes.position.array;
25613 
25614  for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
25615 
25616  var a = i + 0;
25617  var b = i + 1;
25618  var c = i + 2;
25619 
25620  indices.push( a, b, b, c, c, a );
25621 
25622  }
25623 
25624  }
25625 
25626  // console.timeEnd( 'wireframe' );
25627 
25628  var TypeArray = position.count > 65535 ? Uint32Array : Uint16Array;
25629  var attribute = new THREE.BufferAttribute( new TypeArray( indices ), 1 );
25630 
25631  updateAttribute( attribute, gl.ELEMENT_ARRAY_BUFFER );
25632 
25633  property.wireframe = attribute;
25634 
25635  return attribute;
25636 
25637  }
25638 
25639  function checkEdge( edges, a, b ) {
25640 
25641  if ( a > b ) {
25642 
25643  var tmp = a;
25644  a = b;
25645  b = tmp;
25646 
25647  }
25648 
25649  var list = edges[ a ];
25650 
25651  if ( list === undefined ) {
25652 
25653  edges[ a ] = [ b ];
25654  return true;
25655 
25656  } else if ( list.indexOf( b ) === -1 ) {
25657 
25658  list.push( b );
25659  return true;
25660 
25661  }
25662 
25663  return false;
25664 
25665  }
25666 
25667  this.getAttributeBuffer = getAttributeBuffer;
25668  this.getWireframeAttribute = getWireframeAttribute;
25669 
25670  this.update = update;
25671 
25672 };
25673 
25674 // File:src/renderers/webgl/WebGLProgram.js
25675 
25676 THREE.WebGLProgram = ( function () {
25677 
25678  var programIdCount = 0;
25679 
25680  function generateDefines( defines ) {
25681 
25682  var chunks = [];
25683 
25684  for ( var name in defines ) {
25685 
25686  var value = defines[ name ];
25687 
25688  if ( value === false ) continue;
25689 
25690  chunks.push( '#define ' + name + ' ' + value );
25691 
25692  }
25693 
25694  return chunks.join( '\n' );
25695 
25696  }
25697 
25698  function fetchUniformLocations( gl, program, identifiers ) {
25699 
25700  var uniforms = {};
25701 
25702  var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
25703 
25704  for ( var i = 0; i < n; i ++ ) {
25705 
25706  var info = gl.getActiveUniform( program, i );
25707  var name = info.name;
25708  var location = gl.getUniformLocation( program, name );
25709 
25710  // console.log("THREE.WebGLProgram: ACTIVE UNIFORM:", name);
25711 
25712  var suffixPos = name.lastIndexOf( '[0]' );
25713  if ( suffixPos !== - 1 && suffixPos === name.length - 3 ) {
25714 
25715  uniforms[ name.substr( 0, suffixPos ) ] = location;
25716 
25717  }
25718 
25719  uniforms[ name ] = location;
25720 
25721  }
25722 
25723  return uniforms;
25724 
25725  }
25726 
25727  function fetchAttributeLocations( gl, program, identifiers ) {
25728 
25729  var attributes = {};
25730 
25731  var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
25732 
25733  for ( var i = 0; i < n; i ++ ) {
25734 
25735  var info = gl.getActiveAttrib( program, i );
25736  var name = info.name;
25737 
25738  // console.log("THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:", name, i );
25739 
25740  attributes[ name ] = gl.getAttribLocation( program, name );
25741 
25742  }
25743 
25744  return attributes;
25745 
25746  }
25747 
25748  function filterEmptyLine( string ) {
25749 
25750  return string !== '';
25751 
25752  }
25753 
25754  return function WebGLProgram( renderer, code, material, parameters ) {
25755 
25756  var gl = renderer.context;
25757 
25758  var defines = material.defines;
25759 
25760  var vertexShader = material.__webglShader.vertexShader;
25761  var fragmentShader = material.__webglShader.fragmentShader;
25762 
25763  var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
25764 
25765  if ( parameters.shadowMapType === THREE.PCFShadowMap ) {
25766 
25767  shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
25768 
25769  } else if ( parameters.shadowMapType === THREE.PCFSoftShadowMap ) {
25770 
25771  shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
25772 
25773  }
25774 
25775  var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
25776  var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
25777  var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
25778 
25779  if ( parameters.envMap ) {
25780 
25781  switch ( material.envMap.mapping ) {
25782 
25783  case THREE.CubeReflectionMapping:
25784  case THREE.CubeRefractionMapping:
25785  envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
25786  break;
25787 
25788  case THREE.EquirectangularReflectionMapping:
25789  case THREE.EquirectangularRefractionMapping:
25790  envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
25791  break;
25792 
25793  case THREE.SphericalReflectionMapping:
25794  envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
25795  break;
25796 
25797  }
25798 
25799  switch ( material.envMap.mapping ) {
25800 
25801  case THREE.CubeRefractionMapping:
25802  case THREE.EquirectangularRefractionMapping:
25803  envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
25804  break;
25805 
25806  }
25807 
25808  switch ( material.combine ) {
25809 
25810  case THREE.MultiplyOperation:
25811  envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
25812  break;
25813 
25814  case THREE.MixOperation:
25815  envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
25816  break;
25817 
25818  case THREE.AddOperation:
25819  envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
25820  break;
25821 
25822  }
25823 
25824  }
25825 
25826  var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
25827 
25828  // console.log( 'building new program ' );
25829 
25830  //
25831 
25832  var customDefines = generateDefines( defines );
25833 
25834  //
25835 
25836  var program = gl.createProgram();
25837 
25838  var prefixVertex, prefixFragment;
25839 
25840  if ( material instanceof THREE.RawShaderMaterial ) {
25841 
25842  prefixVertex = '';
25843  prefixFragment = '';
25844 
25845  } else {
25846 
25847  prefixVertex = [
25848 
25849  'precision ' + parameters.precision + ' float;',
25850  'precision ' + parameters.precision + ' int;',
25851 
25852  '#define SHADER_NAME ' + material.__webglShader.name,
25853 
25854  customDefines,
25855 
25856  parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
25857 
25858  renderer.gammaInput ? '#define GAMMA_INPUT' : '',
25859  renderer.gammaOutput ? '#define GAMMA_OUTPUT' : '',
25860  '#define GAMMA_FACTOR ' + gammaFactorDefine,
25861 
25862  '#define MAX_DIR_LIGHTS ' + parameters.maxDirLights,
25863  '#define MAX_POINT_LIGHTS ' + parameters.maxPointLights,
25864  '#define MAX_SPOT_LIGHTS ' + parameters.maxSpotLights,
25865  '#define MAX_HEMI_LIGHTS ' + parameters.maxHemiLights,
25866 
25867  '#define MAX_SHADOWS ' + parameters.maxShadows,
25868 
25869  '#define MAX_BONES ' + parameters.maxBones,
25870 
25871  parameters.map ? '#define USE_MAP' : '',
25872  parameters.envMap ? '#define USE_ENVMAP' : '',
25873  parameters.envMap ? '#define ' + envMapModeDefine : '',
25874  parameters.lightMap ? '#define USE_LIGHTMAP' : '',
25875  parameters.aoMap ? '#define USE_AOMAP' : '',
25876  parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
25877  parameters.bumpMap ? '#define USE_BUMPMAP' : '',
25878  parameters.normalMap ? '#define USE_NORMALMAP' : '',
25879  parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
25880  parameters.specularMap ? '#define USE_SPECULARMAP' : '',
25881  parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
25882  parameters.vertexColors ? '#define USE_COLOR' : '',
25883 
25884  parameters.flatShading ? '#define FLAT_SHADED' : '',
25885 
25886  parameters.skinning ? '#define USE_SKINNING' : '',
25887  parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
25888 
25889  parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
25890  parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
25891  parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
25892  parameters.flipSided ? '#define FLIP_SIDED' : '',
25893 
25894  parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
25895  parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
25896  parameters.shadowMapDebug ? '#define SHADOWMAP_DEBUG' : '',
25897  parameters.pointLightShadows > 0 ? '#define POINT_LIGHT_SHADOWS' : '',
25898 
25899  parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
25900 
25901  parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
25902  parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
25903 
25904 
25905  'uniform mat4 modelMatrix;',
25906  'uniform mat4 modelViewMatrix;',
25907  'uniform mat4 projectionMatrix;',
25908  'uniform mat4 viewMatrix;',
25909  'uniform mat3 normalMatrix;',
25910  'uniform vec3 cameraPosition;',
25911 
25912  'attribute vec3 position;',
25913  'attribute vec3 normal;',
25914  'attribute vec2 uv;',
25915 
25916  '#ifdef USE_COLOR',
25917 
25918  ' attribute vec3 color;',
25919 
25920  '#endif',
25921 
25922  '#ifdef USE_MORPHTARGETS',
25923 
25924  ' attribute vec3 morphTarget0;',
25925  ' attribute vec3 morphTarget1;',
25926  ' attribute vec3 morphTarget2;',
25927  ' attribute vec3 morphTarget3;',
25928 
25929  ' #ifdef USE_MORPHNORMALS',
25930 
25931  ' attribute vec3 morphNormal0;',
25932  ' attribute vec3 morphNormal1;',
25933  ' attribute vec3 morphNormal2;',
25934  ' attribute vec3 morphNormal3;',
25935 
25936  ' #else',
25937 
25938  ' attribute vec3 morphTarget4;',
25939  ' attribute vec3 morphTarget5;',
25940  ' attribute vec3 morphTarget6;',
25941  ' attribute vec3 morphTarget7;',
25942 
25943  ' #endif',
25944 
25945  '#endif',
25946 
25947  '#ifdef USE_SKINNING',
25948 
25949  ' attribute vec4 skinIndex;',
25950  ' attribute vec4 skinWeight;',
25951 
25952  '#endif',
25953 
25954  '\n'
25955 
25956  ].filter( filterEmptyLine ).join( '\n' );
25957 
25958  prefixFragment = [
25959 
25960  parameters.bumpMap || parameters.normalMap || parameters.flatShading || material.derivatives ? '#extension GL_OES_standard_derivatives : enable' : '',
25961  parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '',
25962 
25963  'precision ' + parameters.precision + ' float;',
25964  'precision ' + parameters.precision + ' int;',
25965 
25966  '#define SHADER_NAME ' + material.__webglShader.name,
25967 
25968  customDefines,
25969 
25970  '#define MAX_DIR_LIGHTS ' + parameters.maxDirLights,
25971  '#define MAX_POINT_LIGHTS ' + parameters.maxPointLights,
25972  '#define MAX_SPOT_LIGHTS ' + parameters.maxSpotLights,
25973  '#define MAX_HEMI_LIGHTS ' + parameters.maxHemiLights,
25974 
25975  '#define MAX_SHADOWS ' + parameters.maxShadows,
25976 
25977  parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '',
25978 
25979  renderer.gammaInput ? '#define GAMMA_INPUT' : '',
25980  renderer.gammaOutput ? '#define GAMMA_OUTPUT' : '',
25981  '#define GAMMA_FACTOR ' + gammaFactorDefine,
25982 
25983  ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
25984  ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
25985 
25986  parameters.map ? '#define USE_MAP' : '',
25987  parameters.envMap ? '#define USE_ENVMAP' : '',
25988  parameters.envMap ? '#define ' + envMapTypeDefine : '',
25989  parameters.envMap ? '#define ' + envMapModeDefine : '',
25990  parameters.envMap ? '#define ' + envMapBlendingDefine : '',
25991  parameters.lightMap ? '#define USE_LIGHTMAP' : '',
25992  parameters.aoMap ? '#define USE_AOMAP' : '',
25993  parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
25994  parameters.bumpMap ? '#define USE_BUMPMAP' : '',
25995  parameters.normalMap ? '#define USE_NORMALMAP' : '',
25996  parameters.specularMap ? '#define USE_SPECULARMAP' : '',
25997  parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
25998  parameters.vertexColors ? '#define USE_COLOR' : '',
25999 
26000  parameters.flatShading ? '#define FLAT_SHADED' : '',
26001 
26002  parameters.metal ? '#define METAL' : '',
26003  parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
26004  parameters.flipSided ? '#define FLIP_SIDED' : '',
26005 
26006  parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
26007  parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
26008  parameters.shadowMapDebug ? '#define SHADOWMAP_DEBUG' : '',
26009  parameters.pointLightShadows > 0 ? '#define POINT_LIGHT_SHADOWS' : '',
26010 
26011  parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
26012  parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
26013 
26014  'uniform mat4 viewMatrix;',
26015  'uniform vec3 cameraPosition;',
26016 
26017  '\n'
26018 
26019  ].filter( filterEmptyLine ).join( '\n' );
26020 
26021  }
26022 
26023  var vertexGlsl = prefixVertex + vertexShader;
26024  var fragmentGlsl = prefixFragment + fragmentShader;
26025 
26026  var glVertexShader = THREE.WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
26027  var glFragmentShader = THREE.WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
26028 
26029  gl.attachShader( program, glVertexShader );
26030  gl.attachShader( program, glFragmentShader );
26031 
26032  // Force a particular attribute to index 0.
26033 
26034  if ( material.index0AttributeName !== undefined ) {
26035 
26036  gl.bindAttribLocation( program, 0, material.index0AttributeName );
26037 
26038  } else if ( parameters.morphTargets === true ) {
26039 
26040  // programs with morphTargets displace position out of attribute 0
26041  gl.bindAttribLocation( program, 0, 'position' );
26042 
26043  }
26044 
26045  gl.linkProgram( program );
26046 
26047  var programLog = gl.getProgramInfoLog( program );
26048  var vertexLog = gl.getShaderInfoLog( glVertexShader );
26049  var fragmentLog = gl.getShaderInfoLog( glFragmentShader );
26050 
26051  var runnable = true;
26052  var haveDiagnostics = true;
26053 
26054  if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
26055 
26056  runnable = false;
26057 
26058  console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog );
26059 
26060  } else if ( programLog !== '' ) {
26061 
26062  console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
26063 
26064  } else if ( vertexLog === '' || fragmentLog === '' ) {
26065 
26066  haveDiagnostics = false;
26067 
26068  }
26069 
26070  if ( haveDiagnostics ) {
26071 
26072  this.diagnostics = {
26073 
26074  runnable: runnable,
26075  material: material,
26076 
26077  programLog: programLog,
26078 
26079  vertexShader: {
26080 
26081  log: vertexLog,
26082  prefix: prefixVertex
26083 
26084  },
26085 
26086  fragmentShader: {
26087 
26088  log: fragmentLog,
26089  prefix: prefixFragment
26090 
26091  }
26092 
26093  };
26094 
26095  }
26096 
26097  // clean up
26098 
26099  gl.deleteShader( glVertexShader );
26100  gl.deleteShader( glFragmentShader );
26101 
26102  // set up caching for uniform locations
26103 
26104  var cachedUniforms;
26105 
26106  this.getUniforms = function() {
26107 
26108  if ( cachedUniforms === undefined ) {
26109 
26110  cachedUniforms = fetchUniformLocations( gl, program );
26111 
26112  }
26113 
26114  return cachedUniforms;
26115 
26116  };
26117 
26118  // set up caching for attribute locations
26119 
26120  var cachedAttributes;
26121 
26122  this.getAttributes = function() {
26123 
26124  if ( cachedAttributes === undefined ) {
26125 
26126  cachedAttributes = fetchAttributeLocations( gl, program );
26127 
26128  }
26129 
26130  return cachedAttributes;
26131 
26132  };
26133 
26134  // free resource
26135 
26136  this.destroy = function() {
26137 
26138  gl.deleteProgram( program );
26139  this.program = undefined;
26140 
26141  };
26142 
26143  // DEPRECATED
26144 
26145  Object.defineProperties( this, {
26146 
26147  uniforms: {
26148  get: function() {
26149 
26150  console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' );
26151  return this.getUniforms();
26152 
26153  }
26154  },
26155 
26156  attributes: {
26157  get: function() {
26158 
26159  console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' );
26160  return this.getAttributes();
26161 
26162  }
26163  }
26164 
26165  } );
26166 
26167 
26168  //
26169 
26170  this.id = programIdCount ++;
26171  this.code = code;
26172  this.usedTimes = 1;
26173  this.program = program;
26174  this.vertexShader = glVertexShader;
26175  this.fragmentShader = glFragmentShader;
26176 
26177  return this;
26178 
26179  };
26180 
26181 } )();
26182 
26183 // File:src/renderers/webgl/WebGLPrograms.js
26184 
26185 THREE.WebGLPrograms = function ( renderer, capabilities ) {
26186 
26187  var programs = [];
26188 
26189  var shaderIDs = {
26190  MeshDepthMaterial: 'depth',
26191  MeshNormalMaterial: 'normal',
26192  MeshBasicMaterial: 'basic',
26193  MeshLambertMaterial: 'lambert',
26194  MeshPhongMaterial: 'phong',
26195  LineBasicMaterial: 'basic',
26196  LineDashedMaterial: 'dashed',
26197  PointsMaterial: 'points'
26198  };
26199 
26200  var parameterNames = [
26201  "precision", "supportsVertexTextures", "map", "envMap", "envMapMode",
26202  "lightMap", "aoMap", "emissiveMap", "bumpMap", "normalMap", "displacementMap", "specularMap",
26203  "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp",
26204  "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
26205  "maxBones", "useVertexTexture", "morphTargets", "morphNormals",
26206  "maxMorphTargets", "maxMorphNormals", "maxDirLights", "maxPointLights",
26207  "maxSpotLights", "maxHemiLights", "maxShadows", "shadowMapEnabled", "pointLightShadows",
26208  "shadowMapType", "shadowMapDebug", "alphaTest", "metal", "doubleSided",
26209  "flipSided"
26210  ];
26211 
26212 
26213  function allocateBones ( object ) {
26214 
26215  if ( capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture ) {
26216 
26217  return 1024;
26218 
26219  } else {
26220 
26221  // default for when object is not specified
26222  // ( for example when prebuilding shader to be used with multiple objects )
26223  //
26224  // - leave some extra space for other uniforms
26225  // - limit here is ANGLE's 254 max uniform vectors
26226  // (up to 54 should be safe)
26227 
26228  var nVertexUniforms = capabilities.maxVertexUniforms;
26229  var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
26230 
26231  var maxBones = nVertexMatrices;
26232 
26233  if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
26234 
26235  maxBones = Math.min( object.skeleton.bones.length, maxBones );
26236 
26237  if ( maxBones < object.skeleton.bones.length ) {
26238 
26239  console.warn( 'WebGLRenderer: too many bones - ' + object.skeleton.bones.length + ', this GPU supports just ' + maxBones + ' (try OpenGL instead of ANGLE)' );
26240 
26241  }
26242 
26243  }
26244 
26245  return maxBones;
26246 
26247  }
26248 
26249  }
26250 
26251  function allocateLights( lights ) {
26252 
26253  var dirLights = 0;
26254  var pointLights = 0;
26255  var spotLights = 0;
26256  var hemiLights = 0;
26257 
26258  for ( var l = 0, ll = lights.length; l < ll; l ++ ) {
26259 
26260  var light = lights[ l ];
26261 
26262  if ( light.visible === false ) continue;
26263 
26264  if ( light instanceof THREE.DirectionalLight ) dirLights ++;
26265  if ( light instanceof THREE.PointLight ) pointLights ++;
26266  if ( light instanceof THREE.SpotLight ) spotLights ++;
26267  if ( light instanceof THREE.HemisphereLight ) hemiLights ++;
26268 
26269  }
26270 
26271  return { 'directional': dirLights, 'point': pointLights, 'spot': spotLights, 'hemi': hemiLights };
26272 
26273  }
26274 
26275  function allocateShadows( lights ) {
26276 
26277  var maxShadows = 0;
26278  var pointLightShadows = 0;
26279 
26280  for ( var l = 0, ll = lights.length; l < ll; l ++ ) {
26281 
26282  var light = lights[ l ];
26283 
26284  if ( ! light.castShadow ) continue;
26285 
26286  if ( light instanceof THREE.SpotLight || light instanceof THREE.DirectionalLight ) maxShadows ++;
26287  if ( light instanceof THREE.PointLight ) {
26288 
26289  maxShadows ++;
26290  pointLightShadows ++;
26291 
26292  }
26293 
26294  }
26295 
26296  return { 'maxShadows': maxShadows, 'pointLightShadows': pointLightShadows };
26297 
26298  }
26299 
26300  this.getParameters = function ( material, lights, fog, object ) {
26301 
26302  var shaderID = shaderIDs[ material.type ];
26303  // heuristics to create shader parameters according to lights in the scene
26304  // (not to blow over maxLights budget)
26305 
26306  var maxLightCount = allocateLights( lights );
26307  var allocatedShadows = allocateShadows( lights );
26308  var maxBones = allocateBones( object );
26309  var precision = renderer.getPrecision();
26310 
26311  if ( material.precision !== null ) {
26312 
26313  precision = capabilities.getMaxPrecision( material.precision );
26314 
26315  if ( precision !== material.precision ) {
26316 
26317  console.warn( 'THREE.WebGLRenderer.initMaterial:', material.precision, 'not supported, using', precision, 'instead.' );
26318 
26319  }
26320 
26321  }
26322 
26323  var parameters = {
26324 
26325  shaderID: shaderID,
26326 
26327  precision: precision,
26328  supportsVertexTextures: capabilities.vertexTextures,
26329 
26330  map: !! material.map,
26331  envMap: !! material.envMap,
26332  envMapMode: material.envMap && material.envMap.mapping,
26333  lightMap: !! material.lightMap,
26334  aoMap: !! material.aoMap,
26335  emissiveMap: !! material.emissiveMap,
26336  bumpMap: !! material.bumpMap,
26337  normalMap: !! material.normalMap,
26338  displacementMap: !! material.displacementMap,
26339  specularMap: !! material.specularMap,
26340  alphaMap: !! material.alphaMap,
26341 
26342  combine: material.combine,
26343 
26344  vertexColors: material.vertexColors,
26345 
26346  fog: fog,
26347  useFog: material.fog,
26348  fogExp: fog instanceof THREE.FogExp2,
26349 
26350  flatShading: material.shading === THREE.FlatShading,
26351 
26352  sizeAttenuation: material.sizeAttenuation,
26353  logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
26354 
26355  skinning: material.skinning,
26356  maxBones: maxBones,
26357  useVertexTexture: capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture,
26358 
26359  morphTargets: material.morphTargets,
26360  morphNormals: material.morphNormals,
26361  maxMorphTargets: renderer.maxMorphTargets,
26362  maxMorphNormals: renderer.maxMorphNormals,
26363 
26364  maxDirLights: maxLightCount.directional,
26365  maxPointLights: maxLightCount.point,
26366  maxSpotLights: maxLightCount.spot,
26367  maxHemiLights: maxLightCount.hemi,
26368 
26369  maxShadows: allocatedShadows.maxShadows,
26370  pointLightShadows: allocatedShadows.pointLightShadows,
26371  shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && allocatedShadows.maxShadows > 0,
26372  shadowMapType: renderer.shadowMap.type,
26373  shadowMapDebug: renderer.shadowMap.debug,
26374 
26375  alphaTest: material.alphaTest,
26376  metal: material.metal,
26377  doubleSided: material.side === THREE.DoubleSide,
26378  flipSided: material.side === THREE.BackSide
26379 
26380  };
26381 
26382  return parameters;
26383 
26384  };
26385 
26386  this.getProgramCode = function ( material, parameters ) {
26387 
26388  var chunks = [];
26389 
26390  if ( parameters.shaderID ) {
26391 
26392  chunks.push( parameters.shaderID );
26393 
26394  } else {
26395 
26396  chunks.push( material.fragmentShader );
26397  chunks.push( material.vertexShader );
26398 
26399  }
26400 
26401  if ( material.defines !== undefined ) {
26402 
26403  for ( var name in material.defines ) {
26404 
26405  chunks.push( name );
26406  chunks.push( material.defines[ name ] );
26407 
26408  }
26409 
26410  }
26411 
26412  for ( var i = 0; i < parameterNames.length; i ++ ) {
26413 
26414  var parameterName = parameterNames[ i ];
26415  chunks.push( parameterName );
26416  chunks.push( parameters[ parameterName ] );
26417 
26418  }
26419 
26420  return chunks.join();
26421 
26422  };
26423 
26424  this.acquireProgram = function ( material, parameters, code ) {
26425 
26426  var program;
26427 
26428  // Check if code has been already compiled
26429  for ( var p = 0, pl = programs.length; p < pl; p ++ ) {
26430 
26431  var programInfo = programs[ p ];
26432 
26433  if ( programInfo.code === code ) {
26434 
26435  program = programInfo;
26436  ++ program.usedTimes;
26437 
26438  break;
26439 
26440  }
26441 
26442  }
26443 
26444  if ( program === undefined ) {
26445 
26446  program = new THREE.WebGLProgram( renderer, code, material, parameters );
26447  programs.push( program );
26448 
26449  }
26450 
26451  return program;
26452 
26453  };
26454 
26455  this.releaseProgram = function( program ) {
26456 
26457  if ( -- program.usedTimes === 0 ) {
26458 
26459  // Remove from unordered set
26460  var i = programs.indexOf( program );
26461  programs[ i ] = programs[ programs.length - 1 ];
26462  programs.pop();
26463 
26464  // Free WebGL resources
26465  program.destroy();
26466 
26467  }
26468 
26469  };
26470 
26471  // Exposed for resource monitoring & error feedback via renderer.info:
26472  this.programs = programs;
26473 
26474 };
26475 
26476 // File:src/renderers/webgl/WebGLProperties.js
26477 
26482 THREE.WebGLProperties = function () {
26483 
26484  var properties = {};
26485 
26486  this.get = function ( object ) {
26487 
26488  var uuid = object.uuid;
26489  var map = properties[ uuid ];
26490 
26491  if ( map === undefined ) {
26492 
26493  map = {};
26494  properties[ uuid ] = map;
26495 
26496  }
26497 
26498  return map;
26499 
26500  };
26501 
26502  this.delete = function ( object ) {
26503 
26504  delete properties[ object.uuid ];
26505 
26506  };
26507 
26508  this.clear = function () {
26509 
26510  properties = {};
26511 
26512  };
26513 
26514 };
26515 
26516 // File:src/renderers/webgl/WebGLShader.js
26517 
26518 THREE.WebGLShader = ( function () {
26519 
26520  function addLineNumbers( string ) {
26521 
26522  var lines = string.split( '\n' );
26523 
26524  for ( var i = 0; i < lines.length; i ++ ) {
26525 
26526  lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
26527 
26528  }
26529 
26530  return lines.join( '\n' );
26531 
26532  }
26533 
26534  return function WebGLShader( gl, type, string ) {
26535 
26536  var shader = gl.createShader( type );
26537 
26538  gl.shaderSource( shader, string );
26539  gl.compileShader( shader );
26540 
26541  if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) {
26542 
26543  console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' );
26544 
26545  }
26546 
26547  if ( gl.getShaderInfoLog( shader ) !== '' ) {
26548 
26549  console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) );
26550 
26551  }
26552 
26553  // --enable-privileged-webgl-extension
26554  // console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
26555 
26556  return shader;
26557 
26558  };
26559 
26560 } )();
26561 
26562 // File:src/renderers/webgl/WebGLShadowMap.js
26563 
26569 THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
26570 
26571  var _gl = _renderer.context,
26572  _state = _renderer.state,
26573  _frustum = new THREE.Frustum(),
26574  _projScreenMatrix = new THREE.Matrix4(),
26575 
26576  _min = new THREE.Vector3(),
26577  _max = new THREE.Vector3(),
26578 
26579  _lookTarget = new THREE.Vector3(),
26580  _lightPositionWorld = new THREE.Vector3(),
26581 
26582  _renderList = [],
26583 
26584  _MorphingFlag = 1,
26585  _SkinningFlag = 2,
26586 
26587  _NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1,
26588 
26589  _depthMaterials = new Array( _NumberOfMaterialVariants ),
26590  _distanceMaterials = new Array( _NumberOfMaterialVariants );
26591 
26592  var cubeDirections = [
26593  new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( - 1, 0, 0 ), new THREE.Vector3( 0, 0, 1 ),
26594  new THREE.Vector3( 0, 0, - 1 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, - 1, 0 )
26595  ];
26596 
26597  var cubeUps = [
26598  new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 1, 0 ),
26599  new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 0, 0, - 1 )
26600  ];
26601 
26602  var cube2DViewPorts = [
26603  new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4(),
26604  new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4()
26605  ];
26606 
26607  var _vector4 = new THREE.Vector4();
26608 
26609  // init
26610 
26611  var depthShader = THREE.ShaderLib[ "depthRGBA" ];
26612  var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
26613 
26614  var distanceShader = THREE.ShaderLib[ "distanceRGBA" ];
26615  var distanceUniforms = THREE.UniformsUtils.clone( distanceShader.uniforms );
26616 
26617  for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
26618 
26619  var useMorphing = ( i & _MorphingFlag ) !== 0;
26620  var useSkinning = ( i & _SkinningFlag ) !== 0;
26621 
26622  var depthMaterial = new THREE.ShaderMaterial( {
26623  uniforms: depthUniforms,
26624  vertexShader: depthShader.vertexShader,
26625  fragmentShader: depthShader.fragmentShader,
26626  morphTargets: useMorphing,
26627  skinning: useSkinning
26628  } );
26629 
26630  depthMaterial._shadowPass = true;
26631 
26632  _depthMaterials[ i ] = depthMaterial;
26633 
26634  var distanceMaterial = new THREE.ShaderMaterial( {
26635  uniforms: distanceUniforms,
26636  vertexShader: distanceShader.vertexShader,
26637  fragmentShader: distanceShader.fragmentShader,
26638  morphTargets: useMorphing,
26639  skinning: useSkinning
26640  } );
26641 
26642  distanceMaterial._shadowPass = true;
26643 
26644  _distanceMaterials[ i ] = distanceMaterial;
26645 
26646  }
26647 
26648  //
26649 
26650  var scope = this;
26651 
26652  this.enabled = false;
26653 
26654  this.autoUpdate = true;
26655  this.needsUpdate = false;
26656 
26657  this.type = THREE.PCFShadowMap;
26658  this.cullFace = THREE.CullFaceFront;
26659 
26660  this.render = function ( scene ) {
26661 
26662  var faceCount, isPointLight;
26663 
26664  if ( scope.enabled === false ) return;
26665  if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
26666 
26667  // Set GL state for depth map.
26668  _gl.clearColor( 1, 1, 1, 1 );
26669  _state.disable( _gl.BLEND );
26670  _state.enable( _gl.CULL_FACE );
26671  _gl.frontFace( _gl.CCW );
26672  _gl.cullFace( scope.cullFace === THREE.CullFaceFront ? _gl.FRONT : _gl.BACK );
26673  _state.setDepthTest( true );
26674 
26675  // save the existing viewport so it can be restored later
26676  _renderer.getViewport( _vector4 );
26677 
26678  // render depth map
26679 
26680  for ( var i = 0, il = _lights.length; i < il; i ++ ) {
26681 
26682  var light = _lights[ i ];
26683 
26684  if ( light.castShadow === true ) {
26685 
26686  var shadow = light.shadow;
26687  var shadowCamera = shadow.camera;
26688  var shadowMapSize = shadow.mapSize;
26689 
26690  if ( light instanceof THREE.PointLight ) {
26691 
26692  faceCount = 6;
26693  isPointLight = true;
26694 
26695  var vpWidth = shadowMapSize.x / 4.0;
26696  var vpHeight = shadowMapSize.y / 2.0;
26697 
26698  // These viewports map a cube-map onto a 2D texture with the
26699  // following orientation:
26700  //
26701  // xzXZ
26702  // y Y
26703  //
26704  // X - Positive x direction
26705  // x - Negative x direction
26706  // Y - Positive y direction
26707  // y - Negative y direction
26708  // Z - Positive z direction
26709  // z - Negative z direction
26710 
26711  // positive X
26712  cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
26713  // negative X
26714  cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
26715  // positive Z
26716  cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
26717  // negative Z
26718  cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
26719  // positive Y
26720  cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
26721  // negative Y
26722  cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
26723 
26724  } else {
26725 
26726  faceCount = 1;
26727  isPointLight = false;
26728 
26729  }
26730 
26731  if ( shadow.map === null ) {
26732 
26733  var shadowFilter = THREE.LinearFilter;
26734 
26735  if ( scope.type === THREE.PCFSoftShadowMap ) {
26736 
26737  shadowFilter = THREE.NearestFilter;
26738 
26739  }
26740 
26741  var pars = { minFilter: shadowFilter, magFilter: shadowFilter, format: THREE.RGBAFormat };
26742 
26743  shadow.map = new THREE.WebGLRenderTarget( shadowMapSize.x, shadowMapSize.y, pars );
26744  shadow.matrix = new THREE.Matrix4();
26745 
26746  //
26747 
26748  if ( light instanceof THREE.SpotLight ) {
26749 
26750  shadowCamera.aspect = shadowMapSize.x / shadowMapSize.y;
26751 
26752  }
26753 
26754  shadowCamera.updateProjectionMatrix();
26755 
26756  }
26757 
26758  var shadowMap = shadow.map;
26759  var shadowMatrix = shadow.matrix;
26760 
26761  _lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
26762  shadowCamera.position.copy( _lightPositionWorld );
26763 
26764  _renderer.setRenderTarget( shadowMap );
26765  _renderer.clear();
26766 
26767  // render shadow map for each cube face (if omni-directional) or
26768  // run a single pass if not
26769 
26770  for ( var face = 0; face < faceCount; face ++ ) {
26771 
26772  if ( isPointLight ) {
26773 
26774  _lookTarget.copy( shadowCamera.position );
26775  _lookTarget.add( cubeDirections[ face ] );
26776  shadowCamera.up.copy( cubeUps[ face ] );
26777  shadowCamera.lookAt( _lookTarget );
26778  var vpDimensions = cube2DViewPorts[ face ];
26779  _renderer.setViewport( vpDimensions.x, vpDimensions.y, vpDimensions.z, vpDimensions.w );
26780 
26781  } else {
26782 
26783  _lookTarget.setFromMatrixPosition( light.target.matrixWorld );
26784  shadowCamera.lookAt( _lookTarget );
26785 
26786  }
26787 
26788  shadowCamera.updateMatrixWorld();
26789  shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
26790 
26791  // compute shadow matrix
26792 
26793  shadowMatrix.set(
26794  0.5, 0.0, 0.0, 0.5,
26795  0.0, 0.5, 0.0, 0.5,
26796  0.0, 0.0, 0.5, 0.5,
26797  0.0, 0.0, 0.0, 1.0
26798  );
26799 
26800  shadowMatrix.multiply( shadowCamera.projectionMatrix );
26801  shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
26802 
26803  // update camera matrices and frustum
26804 
26805  _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
26806  _frustum.setFromMatrix( _projScreenMatrix );
26807 
26808  // set object matrices & frustum culling
26809 
26810  _renderList.length = 0;
26811 
26812  projectObject( scene, shadowCamera );
26813 
26814  // render shadow map
26815  // render regular objects
26816 
26817  for ( var j = 0, jl = _renderList.length; j < jl; j ++ ) {
26818 
26819  var object = _renderList[ j ];
26820  var geometry = _objects.update( object );
26821  var material = object.material;
26822 
26823  if ( material instanceof THREE.MeshFaceMaterial ) {
26824 
26825  var groups = geometry.groups;
26826  var materials = material.materials;
26827 
26828  for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
26829 
26830  var group = groups[ k ];
26831  var groupMaterial = materials[ group.materialIndex ];
26832 
26833  if ( groupMaterial.visible === true ) {
26834 
26835  var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld );
26836  _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, depthMaterial, object, group );
26837 
26838  }
26839 
26840  }
26841 
26842  } else {
26843 
26844  var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld );
26845  _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, depthMaterial, object, null );
26846 
26847  }
26848 
26849  }
26850 
26851  }
26852 
26853  // We must call _renderer.resetGLState() at the end of each iteration of
26854  // the light loop in order to force material updates for each light.
26855  _renderer.resetGLState();
26856 
26857  }
26858 
26859  }
26860 
26861  _renderer.setViewport( _vector4.x, _vector4.y, _vector4.z, _vector4.w );
26862 
26863  // Restore GL state.
26864  var clearColor = _renderer.getClearColor(),
26865  clearAlpha = _renderer.getClearAlpha();
26866  _renderer.setClearColor( clearColor, clearAlpha );
26867  _state.enable( _gl.BLEND );
26868 
26869  if ( scope.cullFace === THREE.CullFaceFront ) {
26870 
26871  _gl.cullFace( _gl.BACK );
26872 
26873  }
26874 
26875  _renderer.resetGLState();
26876 
26877  scope.needsUpdate = false;
26878 
26879  };
26880 
26881  function getDepthMaterial( object, material, isPointLight, lightPositionWorld ) {
26882 
26883  var geometry = object.geometry;
26884 
26885  var newMaterial = null;
26886 
26887  var materialVariants = _depthMaterials;
26888  var customMaterial = object.customDepthMaterial;
26889 
26890  if ( isPointLight ) {
26891 
26892  materialVariants = _distanceMaterials;
26893  customMaterial = object.customDistanceMaterial;
26894 
26895  }
26896 
26897  if ( ! customMaterial ) {
26898 
26899  var useMorphing = geometry.morphTargets !== undefined &&
26900  geometry.morphTargets.length > 0 && material.morphTargets;
26901 
26902  var useSkinning = object instanceof THREE.SkinnedMesh && material.skinning;
26903 
26904  var variantIndex = 0;
26905 
26906  if ( useMorphing ) variantIndex |= _MorphingFlag;
26907  if ( useSkinning ) variantIndex |= _SkinningFlag;
26908 
26909  newMaterial = materialVariants[ variantIndex ];
26910 
26911  } else {
26912 
26913  newMaterial = customMaterial;
26914 
26915  }
26916 
26917  newMaterial.visible = material.visible;
26918  newMaterial.wireframe = material.wireframe;
26919  newMaterial.wireframeLinewidth = material.wireframeLinewidth;
26920 
26921  if ( isPointLight && newMaterial.uniforms.lightPos !== undefined ) {
26922 
26923  newMaterial.uniforms.lightPos.value.copy( lightPositionWorld );
26924 
26925  }
26926 
26927  return newMaterial;
26928 
26929  }
26930 
26931  function projectObject( object, camera ) {
26932 
26933  if ( object.visible === false ) return;
26934 
26935  if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points ) {
26936 
26937  if ( object.castShadow && ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) ) {
26938 
26939  var material = object.material;
26940 
26941  if ( material.visible === true ) {
26942 
26943  object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
26944  _renderList.push( object );
26945 
26946  }
26947 
26948  }
26949 
26950  }
26951 
26952  var children = object.children;
26953 
26954  for ( var i = 0, l = children.length; i < l; i ++ ) {
26955 
26956  projectObject( children[ i ], camera );
26957 
26958  }
26959 
26960  }
26961 
26962 };
26963 
26964 // File:src/renderers/webgl/WebGLState.js
26965 
26970 THREE.WebGLState = function ( gl, extensions, paramThreeToGL ) {
26971 
26972  var _this = this;
26973 
26974  var newAttributes = new Uint8Array( 16 );
26975  var enabledAttributes = new Uint8Array( 16 );
26976  var attributeDivisors = new Uint8Array( 16 );
26977 
26978  var capabilities = {};
26979 
26980  var compressedTextureFormats = null;
26981 
26982  var currentBlending = null;
26983  var currentBlendEquation = null;
26984  var currentBlendSrc = null;
26985  var currentBlendDst = null;
26986  var currentBlendEquationAlpha = null;
26987  var currentBlendSrcAlpha = null;
26988  var currentBlendDstAlpha = null;
26989 
26990  var currentDepthFunc = null;
26991  var currentDepthWrite = null;
26992 
26993  var currentColorWrite = null;
26994 
26995  var currentFlipSided = null;
26996 
26997  var currentLineWidth = null;
26998 
26999  var currentPolygonOffsetFactor = null;
27000  var currentPolygonOffsetUnits = null;
27001 
27002  var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
27003 
27004  var currentTextureSlot = undefined;
27005  var currentBoundTextures = {};
27006 
27007  this.init = function () {
27008 
27009  gl.clearColor( 0, 0, 0, 1 );
27010  gl.clearDepth( 1 );
27011  gl.clearStencil( 0 );
27012 
27013  this.enable( gl.DEPTH_TEST );
27014  gl.depthFunc( gl.LEQUAL );
27015 
27016  gl.frontFace( gl.CCW );
27017  gl.cullFace( gl.BACK );
27018  this.enable( gl.CULL_FACE );
27019 
27020  this.enable( gl.BLEND );
27021  gl.blendEquation( gl.FUNC_ADD );
27022  gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA );
27023 
27024  };
27025 
27026  this.initAttributes = function () {
27027 
27028  for ( var i = 0, l = newAttributes.length; i < l; i ++ ) {
27029 
27030  newAttributes[ i ] = 0;
27031 
27032  }
27033 
27034  };
27035 
27036  this.enableAttribute = function ( attribute ) {
27037 
27038  newAttributes[ attribute ] = 1;
27039 
27040  if ( enabledAttributes[ attribute ] === 0 ) {
27041 
27042  gl.enableVertexAttribArray( attribute );
27043  enabledAttributes[ attribute ] = 1;
27044 
27045  }
27046 
27047  if ( attributeDivisors[ attribute ] !== 0 ) {
27048 
27049  var extension = extensions.get( 'ANGLE_instanced_arrays' );
27050 
27051  extension.vertexAttribDivisorANGLE( attribute, 0 );
27052  attributeDivisors[ attribute ] = 0;
27053 
27054  }
27055 
27056  };
27057 
27058  this.enableAttributeAndDivisor = function ( attribute, meshPerAttribute, extension ) {
27059 
27060  newAttributes[ attribute ] = 1;
27061 
27062  if ( enabledAttributes[ attribute ] === 0 ) {
27063 
27064  gl.enableVertexAttribArray( attribute );
27065  enabledAttributes[ attribute ] = 1;
27066 
27067  }
27068 
27069  if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
27070 
27071  extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute );
27072  attributeDivisors[ attribute ] = meshPerAttribute;
27073 
27074  }
27075 
27076  };
27077 
27078  this.disableUnusedAttributes = function () {
27079 
27080  for ( var i = 0, l = enabledAttributes.length; i < l; i ++ ) {
27081 
27082  if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
27083 
27084  gl.disableVertexAttribArray( i );
27085  enabledAttributes[ i ] = 0;
27086 
27087  }
27088 
27089  }
27090 
27091  };
27092 
27093  this.enable = function ( id ) {
27094 
27095  if ( capabilities[ id ] !== true ) {
27096 
27097  gl.enable( id );
27098  capabilities[ id ] = true;
27099 
27100  }
27101 
27102  };
27103 
27104  this.disable = function ( id ) {
27105 
27106  if ( capabilities[ id ] !== false ) {
27107 
27108  gl.disable( id );
27109  capabilities[ id ] = false;
27110 
27111  }
27112 
27113  };
27114 
27115  this.getCompressedTextureFormats = function () {
27116 
27117  if ( compressedTextureFormats === null ) {
27118 
27119  compressedTextureFormats = [];
27120 
27121  if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
27122  extensions.get( 'WEBGL_compressed_texture_s3tc' ) ) {
27123 
27124  var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS );
27125 
27126  for ( var i = 0; i < formats.length; i ++ ) {
27127 
27128  compressedTextureFormats.push( formats[ i ] );
27129 
27130  }
27131 
27132  }
27133 
27134  }
27135 
27136  return compressedTextureFormats;
27137 
27138  };
27139 
27140  this.setBlending = function ( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha ) {
27141 
27142  if ( blending !== currentBlending ) {
27143 
27144  if ( blending === THREE.NoBlending ) {
27145 
27146  this.disable( gl.BLEND );
27147 
27148  } else if ( blending === THREE.AdditiveBlending ) {
27149 
27150  this.enable( gl.BLEND );
27151  gl.blendEquation( gl.FUNC_ADD );
27152  gl.blendFunc( gl.SRC_ALPHA, gl.ONE );
27153 
27154  } else if ( blending === THREE.SubtractiveBlending ) {
27155 
27156  // TODO: Find blendFuncSeparate() combination
27157 
27158  this.enable( gl.BLEND );
27159  gl.blendEquation( gl.FUNC_ADD );
27160  gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR );
27161 
27162  } else if ( blending === THREE.MultiplyBlending ) {
27163 
27164  // TODO: Find blendFuncSeparate() combination
27165 
27166  this.enable( gl.BLEND );
27167  gl.blendEquation( gl.FUNC_ADD );
27168  gl.blendFunc( gl.ZERO, gl.SRC_COLOR );
27169 
27170  } else if ( blending === THREE.CustomBlending ) {
27171 
27172  this.enable( gl.BLEND );
27173 
27174  } else {
27175 
27176  this.enable( gl.BLEND );
27177  gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
27178  gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
27179 
27180  }
27181 
27182  currentBlending = blending;
27183 
27184  }
27185 
27186  if ( blending === THREE.CustomBlending ) {
27187 
27188  blendEquationAlpha = blendEquationAlpha || blendEquation;
27189  blendSrcAlpha = blendSrcAlpha || blendSrc;
27190  blendDstAlpha = blendDstAlpha || blendDst;
27191 
27192  if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
27193 
27194  gl.blendEquationSeparate( paramThreeToGL( blendEquation ), paramThreeToGL( blendEquationAlpha ) );
27195 
27196  currentBlendEquation = blendEquation;
27197  currentBlendEquationAlpha = blendEquationAlpha;
27198 
27199  }
27200 
27201  if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
27202 
27203  gl.blendFuncSeparate( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ), paramThreeToGL( blendSrcAlpha ), paramThreeToGL( blendDstAlpha ) );
27204 
27205  currentBlendSrc = blendSrc;
27206  currentBlendDst = blendDst;
27207  currentBlendSrcAlpha = blendSrcAlpha;
27208  currentBlendDstAlpha = blendDstAlpha;
27209 
27210  }
27211 
27212  } else {
27213 
27214  currentBlendEquation = null;
27215  currentBlendSrc = null;
27216  currentBlendDst = null;
27217  currentBlendEquationAlpha = null;
27218  currentBlendSrcAlpha = null;
27219  currentBlendDstAlpha = null;
27220 
27221  }
27222 
27223  };
27224 
27225  this.setDepthFunc = function ( depthFunc ) {
27226 
27227  if ( currentDepthFunc !== depthFunc ) {
27228 
27229  if ( depthFunc ) {
27230 
27231  switch ( depthFunc ) {
27232 
27233  case THREE.NeverDepth:
27234 
27235  gl.depthFunc( gl.NEVER );
27236  break;
27237 
27238  case THREE.AlwaysDepth:
27239 
27240  gl.depthFunc( gl.ALWAYS );
27241  break;
27242 
27243  case THREE.LessDepth:
27244 
27245  gl.depthFunc( gl.LESS );
27246  break;
27247 
27248  case THREE.LessEqualDepth:
27249 
27250  gl.depthFunc( gl.LEQUAL );
27251  break;
27252 
27253  case THREE.EqualDepth:
27254 
27255  gl.depthFunc( gl.EQUAL );
27256  break;
27257 
27258  case THREE.GreaterEqualDepth:
27259 
27260  gl.depthFunc( gl.GEQUAL );
27261  break;
27262 
27263  case THREE.GreaterDepth:
27264 
27265  gl.depthFunc( gl.GREATER );
27266  break;
27267 
27268  case THREE.NotEqualDepth:
27269 
27270  gl.depthFunc( gl.NOTEQUAL );
27271  break;
27272 
27273  default:
27274 
27275  gl.depthFunc( gl.LEQUAL );
27276 
27277  }
27278 
27279  } else {
27280 
27281  gl.depthFunc( gl.LEQUAL );
27282 
27283  }
27284 
27285  currentDepthFunc = depthFunc;
27286 
27287  }
27288 
27289  };
27290 
27291  this.setDepthTest = function ( depthTest ) {
27292 
27293  if ( depthTest ) {
27294 
27295  this.enable( gl.DEPTH_TEST );
27296 
27297  } else {
27298 
27299  this.disable( gl.DEPTH_TEST );
27300 
27301  }
27302 
27303  };
27304 
27305  this.setDepthWrite = function ( depthWrite ) {
27306 
27307  if ( currentDepthWrite !== depthWrite ) {
27308 
27309  gl.depthMask( depthWrite );
27310  currentDepthWrite = depthWrite;
27311 
27312  }
27313 
27314  };
27315 
27316  this.setColorWrite = function ( colorWrite ) {
27317 
27318  if ( currentColorWrite !== colorWrite ) {
27319 
27320  gl.colorMask( colorWrite, colorWrite, colorWrite, colorWrite );
27321  currentColorWrite = colorWrite;
27322 
27323  }
27324 
27325  };
27326 
27327  this.setFlipSided = function ( flipSided ) {
27328 
27329  if ( currentFlipSided !== flipSided ) {
27330 
27331  if ( flipSided ) {
27332 
27333  gl.frontFace( gl.CW );
27334 
27335  } else {
27336 
27337  gl.frontFace( gl.CCW );
27338 
27339  }
27340 
27341  currentFlipSided = flipSided;
27342 
27343  }
27344 
27345  };
27346 
27347  this.setLineWidth = function ( width ) {
27348 
27349  if ( width !== currentLineWidth ) {
27350 
27351  gl.lineWidth( width );
27352 
27353  currentLineWidth = width;
27354 
27355  }
27356 
27357  };
27358 
27359  this.setPolygonOffset = function ( polygonOffset, factor, units ) {
27360 
27361  if ( polygonOffset ) {
27362 
27363  this.enable( gl.POLYGON_OFFSET_FILL );
27364 
27365  } else {
27366 
27367  this.disable( gl.POLYGON_OFFSET_FILL );
27368 
27369  }
27370 
27371  if ( polygonOffset && ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) ) {
27372 
27373  gl.polygonOffset( factor, units );
27374 
27375  currentPolygonOffsetFactor = factor;
27376  currentPolygonOffsetUnits = units;
27377 
27378  }
27379 
27380  };
27381 
27382  this.setScissorTest = function ( scissorTest ) {
27383 
27384  if ( scissorTest ) {
27385 
27386  this.enable( gl.SCISSOR_TEST );
27387 
27388  } else {
27389 
27390  this.disable( gl.SCISSOR_TEST );
27391 
27392  }
27393 
27394  };
27395 
27396  // texture
27397 
27398  this.activeTexture = function ( webglSlot ) {
27399 
27400  if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;
27401 
27402  if ( currentTextureSlot !== webglSlot ) {
27403 
27404  gl.activeTexture( webglSlot );
27405  currentTextureSlot = webglSlot;
27406 
27407  }
27408 
27409  }
27410 
27411  this.bindTexture = function ( webglType, webglTexture ) {
27412 
27413  if ( currentTextureSlot === undefined ) {
27414 
27415  _this.activeTexture();
27416 
27417  }
27418 
27419  var boundTexture = currentBoundTextures[ currentTextureSlot ];
27420 
27421  if ( boundTexture === undefined ) {
27422 
27423  boundTexture = { type: undefined, texture: undefined };
27424  currentBoundTextures[ currentTextureSlot ] = boundTexture;
27425 
27426  }
27427 
27428  if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
27429 
27430  gl.bindTexture( webglType, webglTexture );
27431 
27432  boundTexture.type = webglType;
27433  boundTexture.texture = webglTexture;
27434 
27435  }
27436 
27437  };
27438 
27439  this.compressedTexImage2D = function () {
27440 
27441  try {
27442 
27443  gl.compressedTexImage2D.apply( gl, arguments );
27444 
27445  } catch ( error ) {
27446 
27447  console.error( error );
27448 
27449  }
27450 
27451  };
27452 
27453  this.texImage2D = function () {
27454 
27455  try {
27456 
27457  gl.texImage2D.apply( gl, arguments );
27458 
27459  } catch ( error ) {
27460 
27461  console.error( error );
27462 
27463  }
27464 
27465  };
27466 
27467  //
27468 
27469  this.reset = function () {
27470 
27471  for ( var i = 0; i < enabledAttributes.length; i ++ ) {
27472 
27473  if ( enabledAttributes[ i ] === 1 ) {
27474 
27475  gl.disableVertexAttribArray( i );
27476  enabledAttributes[ i ] = 0;
27477 
27478  }
27479 
27480  }
27481 
27482  capabilities = {};
27483 
27484  compressedTextureFormats = null;
27485 
27486  currentBlending = null;
27487 
27488  currentDepthWrite = null;
27489  currentColorWrite = null;
27490 
27491  currentFlipSided = null;
27492 
27493  };
27494 
27495 };
27496 
27497 // File:src/renderers/webgl/plugins/LensFlarePlugin.js
27498 
27504 THREE.LensFlarePlugin = function ( renderer, flares ) {
27505 
27506  var gl = renderer.context;
27507  var state = renderer.state;
27508 
27509  var vertexBuffer, elementBuffer;
27510  var program, attributes, uniforms;
27511  var hasVertexTexture;
27512 
27513  var tempTexture, occlusionTexture;
27514 
27515  function init() {
27516 
27517  var vertices = new Float32Array( [
27518  - 1, - 1, 0, 0,
27519  1, - 1, 1, 0,
27520  1, 1, 1, 1,
27521  - 1, 1, 0, 1
27522  ] );
27523 
27524  var faces = new Uint16Array( [
27525  0, 1, 2,
27526  0, 2, 3
27527  ] );
27528 
27529  // buffers
27530 
27531  vertexBuffer = gl.createBuffer();
27532  elementBuffer = gl.createBuffer();
27533 
27534  gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
27535  gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );
27536 
27537  gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
27538  gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW );
27539 
27540  // textures
27541 
27542  tempTexture = gl.createTexture();
27543  occlusionTexture = gl.createTexture();
27544 
27545  state.bindTexture( gl.TEXTURE_2D, tempTexture );
27546  gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null );
27547  gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
27548  gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
27549  gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
27550  gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
27551 
27552  state.bindTexture( gl.TEXTURE_2D, occlusionTexture );
27553  gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null );
27554  gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
27555  gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
27556  gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
27557  gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
27558 
27559  hasVertexTexture = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ) > 0;
27560 
27561  var shader;
27562 
27563  if ( hasVertexTexture ) {
27564 
27565  shader = {
27566 
27567  vertexShader: [
27568 
27569  "uniform lowp int renderType;",
27570 
27571  "uniform vec3 screenPosition;",
27572  "uniform vec2 scale;",
27573  "uniform float rotation;",
27574 
27575  "uniform sampler2D occlusionMap;",
27576 
27577  "attribute vec2 position;",
27578  "attribute vec2 uv;",
27579 
27580  "varying vec2 vUV;",
27581  "varying float vVisibility;",
27582 
27583  "void main() {",
27584 
27585  "vUV = uv;",
27586 
27587  "vec2 pos = position;",
27588 
27589  "if ( renderType == 2 ) {",
27590 
27591  "vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );",
27592  "visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );",
27593  "visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );",
27594  "visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );",
27595  "visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );",
27596  "visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );",
27597  "visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );",
27598  "visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );",
27599  "visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );",
27600 
27601  "vVisibility = visibility.r / 9.0;",
27602  "vVisibility *= 1.0 - visibility.g / 9.0;",
27603  "vVisibility *= visibility.b / 9.0;",
27604  "vVisibility *= 1.0 - visibility.a / 9.0;",
27605 
27606  "pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;",
27607  "pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;",
27608 
27609  "}",
27610 
27611  "gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );",
27612 
27613  "}"
27614 
27615  ].join( "\n" ),
27616 
27617  fragmentShader: [
27618 
27619  "uniform lowp int renderType;",
27620 
27621  "uniform sampler2D map;",
27622  "uniform float opacity;",
27623  "uniform vec3 color;",
27624 
27625  "varying vec2 vUV;",
27626  "varying float vVisibility;",
27627 
27628  "void main() {",
27629 
27630  // pink square
27631 
27632  "if ( renderType == 0 ) {",
27633 
27634  "gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );",
27635 
27636  // restore
27637 
27638  "} else if ( renderType == 1 ) {",
27639 
27640  "gl_FragColor = texture2D( map, vUV );",
27641 
27642  // flare
27643 
27644  "} else {",
27645 
27646  "vec4 texture = texture2D( map, vUV );",
27647  "texture.a *= opacity * vVisibility;",
27648  "gl_FragColor = texture;",
27649  "gl_FragColor.rgb *= color;",
27650 
27651  "}",
27652 
27653  "}"
27654 
27655  ].join( "\n" )
27656 
27657  };
27658 
27659  } else {
27660 
27661  shader = {
27662 
27663  vertexShader: [
27664 
27665  "uniform lowp int renderType;",
27666 
27667  "uniform vec3 screenPosition;",
27668  "uniform vec2 scale;",
27669  "uniform float rotation;",
27670 
27671  "attribute vec2 position;",
27672  "attribute vec2 uv;",
27673 
27674  "varying vec2 vUV;",
27675 
27676  "void main() {",
27677 
27678  "vUV = uv;",
27679 
27680  "vec2 pos = position;",
27681 
27682  "if ( renderType == 2 ) {",
27683 
27684  "pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;",
27685  "pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;",
27686 
27687  "}",
27688 
27689  "gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );",
27690 
27691  "}"
27692 
27693  ].join( "\n" ),
27694 
27695  fragmentShader: [
27696 
27697  "precision mediump float;",
27698 
27699  "uniform lowp int renderType;",
27700 
27701  "uniform sampler2D map;",
27702  "uniform sampler2D occlusionMap;",
27703  "uniform float opacity;",
27704  "uniform vec3 color;",
27705 
27706  "varying vec2 vUV;",
27707 
27708  "void main() {",
27709 
27710  // pink square
27711 
27712  "if ( renderType == 0 ) {",
27713 
27714  "gl_FragColor = vec4( texture2D( map, vUV ).rgb, 0.0 );",
27715 
27716  // restore
27717 
27718  "} else if ( renderType == 1 ) {",
27719 
27720  "gl_FragColor = texture2D( map, vUV );",
27721 
27722  // flare
27723 
27724  "} else {",
27725 
27726  "float visibility = texture2D( occlusionMap, vec2( 0.5, 0.1 ) ).a;",
27727  "visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) ).a;",
27728  "visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) ).a;",
27729  "visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) ).a;",
27730  "visibility = ( 1.0 - visibility / 4.0 );",
27731 
27732  "vec4 texture = texture2D( map, vUV );",
27733  "texture.a *= opacity * visibility;",
27734  "gl_FragColor = texture;",
27735  "gl_FragColor.rgb *= color;",
27736 
27737  "}",
27738 
27739  "}"
27740 
27741  ].join( "\n" )
27742 
27743  };
27744 
27745  }
27746 
27747  program = createProgram( shader );
27748 
27749  attributes = {
27750  vertex: gl.getAttribLocation ( program, "position" ),
27751  uv: gl.getAttribLocation ( program, "uv" )
27752  };
27753 
27754  uniforms = {
27755  renderType: gl.getUniformLocation( program, "renderType" ),
27756  map: gl.getUniformLocation( program, "map" ),
27757  occlusionMap: gl.getUniformLocation( program, "occlusionMap" ),
27758  opacity: gl.getUniformLocation( program, "opacity" ),
27759  color: gl.getUniformLocation( program, "color" ),
27760  scale: gl.getUniformLocation( program, "scale" ),
27761  rotation: gl.getUniformLocation( program, "rotation" ),
27762  screenPosition: gl.getUniformLocation( program, "screenPosition" )
27763  };
27764 
27765  }
27766 
27767  /*
27768  * Render lens flares
27769  * Method: renders 16x16 0xff00ff-colored points scattered over the light source area,
27770  * reads these back and calculates occlusion.
27771  */
27772 
27773  this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
27774 
27775  if ( flares.length === 0 ) return;
27776 
27777  var tempPosition = new THREE.Vector3();
27778 
27779  var invAspect = viewportHeight / viewportWidth,
27780  halfViewportWidth = viewportWidth * 0.5,
27781  halfViewportHeight = viewportHeight * 0.5;
27782 
27783  var size = 16 / viewportHeight,
27784  scale = new THREE.Vector2( size * invAspect, size );
27785 
27786  var screenPosition = new THREE.Vector3( 1, 1, 0 ),
27787  screenPositionPixels = new THREE.Vector2( 1, 1 );
27788 
27789  if ( program === undefined ) {
27790 
27791  init();
27792 
27793  }
27794 
27795  gl.useProgram( program );
27796 
27797  state.initAttributes();
27798  state.enableAttribute( attributes.vertex );
27799  state.enableAttribute( attributes.uv );
27800  state.disableUnusedAttributes();
27801 
27802  // loop through all lens flares to update their occlusion and positions
27803  // setup gl and common used attribs/uniforms
27804 
27805  gl.uniform1i( uniforms.occlusionMap, 0 );
27806  gl.uniform1i( uniforms.map, 1 );
27807 
27808  gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
27809  gl.vertexAttribPointer( attributes.vertex, 2, gl.FLOAT, false, 2 * 8, 0 );
27810  gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 );
27811 
27812  gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
27813 
27814  state.disable( gl.CULL_FACE );
27815  gl.depthMask( false );
27816 
27817  for ( var i = 0, l = flares.length; i < l; i ++ ) {
27818 
27819  size = 16 / viewportHeight;
27820  scale.set( size * invAspect, size );
27821 
27822  // calc object screen position
27823 
27824  var flare = flares[ i ];
27825 
27826  tempPosition.set( flare.matrixWorld.elements[ 12 ], flare.matrixWorld.elements[ 13 ], flare.matrixWorld.elements[ 14 ] );
27827 
27828  tempPosition.applyMatrix4( camera.matrixWorldInverse );
27829  tempPosition.applyProjection( camera.projectionMatrix );
27830 
27831  // setup arrays for gl programs
27832 
27833  screenPosition.copy( tempPosition );
27834 
27835  screenPositionPixels.x = screenPosition.x * halfViewportWidth + halfViewportWidth;
27836  screenPositionPixels.y = screenPosition.y * halfViewportHeight + halfViewportHeight;
27837 
27838  // screen cull
27839 
27840  if ( hasVertexTexture || (
27841  screenPositionPixels.x > 0 &&
27842  screenPositionPixels.x < viewportWidth &&
27843  screenPositionPixels.y > 0 &&
27844  screenPositionPixels.y < viewportHeight ) ) {
27845 
27846  // save current RGB to temp texture
27847 
27848  state.activeTexture( gl.TEXTURE0 );
27849  state.bindTexture( gl.TEXTURE_2D, null );
27850  state.activeTexture( gl.TEXTURE1 );
27851  state.bindTexture( gl.TEXTURE_2D, tempTexture );
27852  gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGB, screenPositionPixels.x - 8, screenPositionPixels.y - 8, 16, 16, 0 );
27853 
27854 
27855  // render pink quad
27856 
27857  gl.uniform1i( uniforms.renderType, 0 );
27858  gl.uniform2f( uniforms.scale, scale.x, scale.y );
27859  gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
27860 
27861  state.disable( gl.BLEND );
27862  state.enable( gl.DEPTH_TEST );
27863 
27864  gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
27865 
27866 
27867  // copy result to occlusionMap
27868 
27869  state.activeTexture( gl.TEXTURE0 );
27870  state.bindTexture( gl.TEXTURE_2D, occlusionTexture );
27871  gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, screenPositionPixels.x - 8, screenPositionPixels.y - 8, 16, 16, 0 );
27872 
27873 
27874  // restore graphics
27875 
27876  gl.uniform1i( uniforms.renderType, 1 );
27877  state.disable( gl.DEPTH_TEST );
27878 
27879  state.activeTexture( gl.TEXTURE1 );
27880  state.bindTexture( gl.TEXTURE_2D, tempTexture );
27881  gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
27882 
27883 
27884  // update object positions
27885 
27886  flare.positionScreen.copy( screenPosition );
27887 
27888  if ( flare.customUpdateCallback ) {
27889 
27890  flare.customUpdateCallback( flare );
27891 
27892  } else {
27893 
27894  flare.updateLensFlares();
27895 
27896  }
27897 
27898  // render flares
27899 
27900  gl.uniform1i( uniforms.renderType, 2 );
27901  state.enable( gl.BLEND );
27902 
27903  for ( var j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) {
27904 
27905  var sprite = flare.lensFlares[ j ];
27906 
27907  if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) {
27908 
27909  screenPosition.x = sprite.x;
27910  screenPosition.y = sprite.y;
27911  screenPosition.z = sprite.z;
27912 
27913  size = sprite.size * sprite.scale / viewportHeight;
27914 
27915  scale.x = size * invAspect;
27916  scale.y = size;
27917 
27918  gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
27919  gl.uniform2f( uniforms.scale, scale.x, scale.y );
27920  gl.uniform1f( uniforms.rotation, sprite.rotation );
27921 
27922  gl.uniform1f( uniforms.opacity, sprite.opacity );
27923  gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b );
27924 
27925  state.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst );
27926  renderer.setTexture( sprite.texture, 1 );
27927 
27928  gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
27929 
27930  }
27931 
27932  }
27933 
27934  }
27935 
27936  }
27937 
27938  // restore gl
27939 
27940  state.enable( gl.CULL_FACE );
27941  state.enable( gl.DEPTH_TEST );
27942  gl.depthMask( true );
27943 
27944  renderer.resetGLState();
27945 
27946  };
27947 
27948  function createProgram ( shader ) {
27949 
27950  var program = gl.createProgram();
27951 
27952  var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
27953  var vertexShader = gl.createShader( gl.VERTEX_SHADER );
27954 
27955  var prefix = "precision " + renderer.getPrecision() + " float;\n";
27956 
27957  gl.shaderSource( fragmentShader, prefix + shader.fragmentShader );
27958  gl.shaderSource( vertexShader, prefix + shader.vertexShader );
27959 
27960  gl.compileShader( fragmentShader );
27961  gl.compileShader( vertexShader );
27962 
27963  gl.attachShader( program, fragmentShader );
27964  gl.attachShader( program, vertexShader );
27965 
27966  gl.linkProgram( program );
27967 
27968  return program;
27969 
27970  }
27971 
27972 };
27973 
27974 // File:src/renderers/webgl/plugins/SpritePlugin.js
27975 
27981 THREE.SpritePlugin = function ( renderer, sprites ) {
27982 
27983  var gl = renderer.context;
27984  var state = renderer.state;
27985 
27986  var vertexBuffer, elementBuffer;
27987  var program, attributes, uniforms;
27988 
27989  var texture;
27990 
27991  // decompose matrixWorld
27992 
27993  var spritePosition = new THREE.Vector3();
27994  var spriteRotation = new THREE.Quaternion();
27995  var spriteScale = new THREE.Vector3();
27996 
27997  function init() {
27998 
27999  var vertices = new Float32Array( [
28000  - 0.5, - 0.5, 0, 0,
28001  0.5, - 0.5, 1, 0,
28002  0.5, 0.5, 1, 1,
28003  - 0.5, 0.5, 0, 1
28004  ] );
28005 
28006  var faces = new Uint16Array( [
28007  0, 1, 2,
28008  0, 2, 3
28009  ] );
28010 
28011  vertexBuffer = gl.createBuffer();
28012  elementBuffer = gl.createBuffer();
28013 
28014  gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
28015  gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );
28016 
28017  gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
28018  gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW );
28019 
28020  program = createProgram();
28021 
28022  attributes = {
28023  position: gl.getAttribLocation ( program, 'position' ),
28024  uv: gl.getAttribLocation ( program, 'uv' )
28025  };
28026 
28027  uniforms = {
28028  uvOffset: gl.getUniformLocation( program, 'uvOffset' ),
28029  uvScale: gl.getUniformLocation( program, 'uvScale' ),
28030 
28031  rotation: gl.getUniformLocation( program, 'rotation' ),
28032  scale: gl.getUniformLocation( program, 'scale' ),
28033 
28034  color: gl.getUniformLocation( program, 'color' ),
28035  map: gl.getUniformLocation( program, 'map' ),
28036  opacity: gl.getUniformLocation( program, 'opacity' ),
28037 
28038  modelViewMatrix: gl.getUniformLocation( program, 'modelViewMatrix' ),
28039  projectionMatrix: gl.getUniformLocation( program, 'projectionMatrix' ),
28040 
28041  fogType: gl.getUniformLocation( program, 'fogType' ),
28042  fogDensity: gl.getUniformLocation( program, 'fogDensity' ),
28043  fogNear: gl.getUniformLocation( program, 'fogNear' ),
28044  fogFar: gl.getUniformLocation( program, 'fogFar' ),
28045  fogColor: gl.getUniformLocation( program, 'fogColor' ),
28046 
28047  alphaTest: gl.getUniformLocation( program, 'alphaTest' )
28048  };
28049 
28050  var canvas = document.createElement( 'canvas' );
28051  canvas.width = 8;
28052  canvas.height = 8;
28053 
28054  var context = canvas.getContext( '2d' );
28055  context.fillStyle = 'white';
28056  context.fillRect( 0, 0, 8, 8 );
28057 
28058  texture = new THREE.Texture( canvas );
28059  texture.needsUpdate = true;
28060 
28061  }
28062 
28063  this.render = function ( scene, camera ) {
28064 
28065  if ( sprites.length === 0 ) return;
28066 
28067  // setup gl
28068 
28069  if ( program === undefined ) {
28070 
28071  init();
28072 
28073  }
28074 
28075  gl.useProgram( program );
28076 
28077  state.initAttributes();
28078  state.enableAttribute( attributes.position );
28079  state.enableAttribute( attributes.uv );
28080  state.disableUnusedAttributes();
28081 
28082  state.disable( gl.CULL_FACE );
28083  state.enable( gl.BLEND );
28084 
28085  gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
28086  gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 );
28087  gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 );
28088 
28089  gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
28090 
28091  gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
28092 
28093  state.activeTexture( gl.TEXTURE0 );
28094  gl.uniform1i( uniforms.map, 0 );
28095 
28096  var oldFogType = 0;
28097  var sceneFogType = 0;
28098  var fog = scene.fog;
28099 
28100  if ( fog ) {
28101 
28102  gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b );
28103 
28104  if ( fog instanceof THREE.Fog ) {
28105 
28106  gl.uniform1f( uniforms.fogNear, fog.near );
28107  gl.uniform1f( uniforms.fogFar, fog.far );
28108 
28109  gl.uniform1i( uniforms.fogType, 1 );
28110  oldFogType = 1;
28111  sceneFogType = 1;
28112 
28113  } else if ( fog instanceof THREE.FogExp2 ) {
28114 
28115  gl.uniform1f( uniforms.fogDensity, fog.density );
28116 
28117  gl.uniform1i( uniforms.fogType, 2 );
28118  oldFogType = 2;
28119  sceneFogType = 2;
28120 
28121  }
28122 
28123  } else {
28124 
28125  gl.uniform1i( uniforms.fogType, 0 );
28126  oldFogType = 0;
28127  sceneFogType = 0;
28128 
28129  }
28130 
28131 
28132  // update positions and sort
28133 
28134  for ( var i = 0, l = sprites.length; i < l; i ++ ) {
28135 
28136  var sprite = sprites[ i ];
28137 
28138  sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
28139  sprite.z = - sprite.modelViewMatrix.elements[ 14 ];
28140 
28141  }
28142 
28143  sprites.sort( painterSortStable );
28144 
28145  // render all sprites
28146 
28147  var scale = [];
28148 
28149  for ( var i = 0, l = sprites.length; i < l; i ++ ) {
28150 
28151  var sprite = sprites[ i ];
28152  var material = sprite.material;
28153 
28154  gl.uniform1f( uniforms.alphaTest, material.alphaTest );
28155  gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements );
28156 
28157  sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale );
28158 
28159  scale[ 0 ] = spriteScale.x;
28160  scale[ 1 ] = spriteScale.y;
28161 
28162  var fogType = 0;
28163 
28164  if ( scene.fog && material.fog ) {
28165 
28166  fogType = sceneFogType;
28167 
28168  }
28169 
28170  if ( oldFogType !== fogType ) {
28171 
28172  gl.uniform1i( uniforms.fogType, fogType );
28173  oldFogType = fogType;
28174 
28175  }
28176 
28177  if ( material.map !== null ) {
28178 
28179  gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y );
28180  gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y );
28181 
28182  } else {
28183 
28184  gl.uniform2f( uniforms.uvOffset, 0, 0 );
28185  gl.uniform2f( uniforms.uvScale, 1, 1 );
28186 
28187  }
28188 
28189  gl.uniform1f( uniforms.opacity, material.opacity );
28190  gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
28191 
28192  gl.uniform1f( uniforms.rotation, material.rotation );
28193  gl.uniform2fv( uniforms.scale, scale );
28194 
28195  state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
28196  state.setDepthTest( material.depthTest );
28197  state.setDepthWrite( material.depthWrite );
28198 
28199  if ( material.map && material.map.image && material.map.image.width ) {
28200 
28201  renderer.setTexture( material.map, 0 );
28202 
28203  } else {
28204 
28205  renderer.setTexture( texture, 0 );
28206 
28207  }
28208 
28209  gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
28210 
28211  }
28212 
28213  // restore gl
28214 
28215  state.enable( gl.CULL_FACE );
28216 
28217  renderer.resetGLState();
28218 
28219  };
28220 
28221  function createProgram () {
28222 
28223  var program = gl.createProgram();
28224 
28225  var vertexShader = gl.createShader( gl.VERTEX_SHADER );
28226  var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
28227 
28228  gl.shaderSource( vertexShader, [
28229 
28230  'precision ' + renderer.getPrecision() + ' float;',
28231 
28232  'uniform mat4 modelViewMatrix;',
28233  'uniform mat4 projectionMatrix;',
28234  'uniform float rotation;',
28235  'uniform vec2 scale;',
28236  'uniform vec2 uvOffset;',
28237  'uniform vec2 uvScale;',
28238 
28239  'attribute vec2 position;',
28240  'attribute vec2 uv;',
28241 
28242  'varying vec2 vUV;',
28243 
28244  'void main() {',
28245 
28246  'vUV = uvOffset + uv * uvScale;',
28247 
28248  'vec2 alignedPosition = position * scale;',
28249 
28250  'vec2 rotatedPosition;',
28251  'rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;',
28252  'rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;',
28253 
28254  'vec4 finalPosition;',
28255 
28256  'finalPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );',
28257  'finalPosition.xy += rotatedPosition;',
28258  'finalPosition = projectionMatrix * finalPosition;',
28259 
28260  'gl_Position = finalPosition;',
28261 
28262  '}'
28263 
28264  ].join( '\n' ) );
28265 
28266  gl.shaderSource( fragmentShader, [
28267 
28268  'precision ' + renderer.getPrecision() + ' float;',
28269 
28270  'uniform vec3 color;',
28271  'uniform sampler2D map;',
28272  'uniform float opacity;',
28273 
28274  'uniform int fogType;',
28275  'uniform vec3 fogColor;',
28276  'uniform float fogDensity;',
28277  'uniform float fogNear;',
28278  'uniform float fogFar;',
28279  'uniform float alphaTest;',
28280 
28281  'varying vec2 vUV;',
28282 
28283  'void main() {',
28284 
28285  'vec4 texture = texture2D( map, vUV );',
28286 
28287  'if ( texture.a < alphaTest ) discard;',
28288 
28289  'gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );',
28290 
28291  'if ( fogType > 0 ) {',
28292 
28293  'float depth = gl_FragCoord.z / gl_FragCoord.w;',
28294  'float fogFactor = 0.0;',
28295 
28296  'if ( fogType == 1 ) {',
28297 
28298  'fogFactor = smoothstep( fogNear, fogFar, depth );',
28299 
28300  '} else {',
28301 
28302  'const float LOG2 = 1.442695;',
28303  'fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );',
28304  'fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );',
28305 
28306  '}',
28307 
28308  'gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );',
28309 
28310  '}',
28311 
28312  '}'
28313 
28314  ].join( '\n' ) );
28315 
28316  gl.compileShader( vertexShader );
28317  gl.compileShader( fragmentShader );
28318 
28319  gl.attachShader( program, vertexShader );
28320  gl.attachShader( program, fragmentShader );
28321 
28322  gl.linkProgram( program );
28323 
28324  return program;
28325 
28326  }
28327 
28328  function painterSortStable ( a, b ) {
28329 
28330  if ( a.z !== b.z ) {
28331 
28332  return b.z - a.z;
28333 
28334  } else {
28335 
28336  return b.id - a.id;
28337 
28338  }
28339 
28340  }
28341 
28342 };
28343 
28344 // File:src/extras/CurveUtils.js
28345 
28350 THREE.CurveUtils = {
28351 
28352  tangentQuadraticBezier: function ( t, p0, p1, p2 ) {
28353 
28354  return 2 * ( 1 - t ) * ( p1 - p0 ) + 2 * t * ( p2 - p1 );
28355 
28356  },
28357 
28358  // Puay Bing, thanks for helping with this derivative!
28359 
28360  tangentCubicBezier: function ( t, p0, p1, p2, p3 ) {
28361 
28362  return - 3 * p0 * ( 1 - t ) * ( 1 - t ) +
28363  3 * p1 * ( 1 - t ) * ( 1 - t ) - 6 * t * p1 * ( 1 - t ) +
28364  6 * t * p2 * ( 1 - t ) - 3 * t * t * p2 +
28365  3 * t * t * p3;
28366 
28367  },
28368 
28369  tangentSpline: function ( t, p0, p1, p2, p3 ) {
28370 
28371  // To check if my formulas are correct
28372 
28373  var h00 = 6 * t * t - 6 * t; // derived from 2t^3 − 3t^2 + 1
28374  var h10 = 3 * t * t - 4 * t + 1; // t^3 − 2t^2 + t
28375  var h01 = - 6 * t * t + 6 * t; // − 2t3 + 3t2
28376  var h11 = 3 * t * t - 2 * t; // t3 − t2
28377 
28378  return h00 + h10 + h01 + h11;
28379 
28380  },
28381 
28382  // Catmull-Rom
28383 
28384  interpolate: function( p0, p1, p2, p3, t ) {
28385 
28386  var v0 = ( p2 - p0 ) * 0.5;
28387  var v1 = ( p3 - p1 ) * 0.5;
28388  var t2 = t * t;
28389  var t3 = t * t2;
28390  return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
28391 
28392  }
28393 
28394 };
28395 
28396 // File:src/extras/GeometryUtils.js
28397 
28402 THREE.GeometryUtils = {
28403 
28404  merge: function ( geometry1, geometry2, materialIndexOffset ) {
28405 
28406  console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
28407 
28408  var matrix;
28409 
28410  if ( geometry2 instanceof THREE.Mesh ) {
28411 
28412  geometry2.matrixAutoUpdate && geometry2.updateMatrix();
28413 
28414  matrix = geometry2.matrix;
28415  geometry2 = geometry2.geometry;
28416 
28417  }
28418 
28419  geometry1.merge( geometry2, matrix, materialIndexOffset );
28420 
28421  },
28422 
28423  center: function ( geometry ) {
28424 
28425  console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
28426  return geometry.center();
28427 
28428  }
28429 
28430 };
28431 
28432 // File:src/extras/ImageUtils.js
28433 
28440 THREE.ImageUtils = {
28441 
28442  crossOrigin: undefined,
28443 
28444  loadTexture: function ( url, mapping, onLoad, onError ) {
28445 
28446  console.warn( 'THREE.ImageUtils.loadTexture is being deprecated. Use THREE.TextureLoader() instead.' );
28447 
28448  var loader = new THREE.TextureLoader();
28449  loader.setCrossOrigin( this.crossOrigin );
28450 
28451  var texture = loader.load( url, onLoad, undefined, onError );
28452 
28453  if ( mapping ) texture.mapping = mapping;
28454 
28455  return texture;
28456 
28457  },
28458 
28459  loadTextureCube: function ( urls, mapping, onLoad, onError ) {
28460 
28461  console.warn( 'THREE.ImageUtils.loadTextureCube is being deprecated. Use THREE.CubeTextureLoader() instead.' );
28462 
28463  var loader = new THREE.CubeTextureLoader();
28464  loader.setCrossOrigin( this.crossOrigin );
28465 
28466  var texture = loader.load( urls, onLoad, undefined, onError );
28467 
28468  if ( mapping ) texture.mapping = mapping;
28469 
28470  return texture;
28471 
28472  },
28473 
28474  loadCompressedTexture: function () {
28475 
28476  console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' )
28477 
28478  },
28479 
28480  loadCompressedTextureCube: function () {
28481 
28482  console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' )
28483 
28484  }
28485 
28486 };
28487 
28488 // File:src/extras/SceneUtils.js
28489 
28494 THREE.SceneUtils = {
28495 
28496  createMultiMaterialObject: function ( geometry, materials ) {
28497 
28498  var group = new THREE.Group();
28499 
28500  for ( var i = 0, l = materials.length; i < l; i ++ ) {
28501 
28502  group.add( new THREE.Mesh( geometry, materials[ i ] ) );
28503 
28504  }
28505 
28506  return group;
28507 
28508  },
28509 
28510  detach: function ( child, parent, scene ) {
28511 
28512  child.applyMatrix( parent.matrixWorld );
28513  parent.remove( child );
28514  scene.add( child );
28515 
28516  },
28517 
28518  attach: function ( child, scene, parent ) {
28519 
28520  var matrixWorldInverse = new THREE.Matrix4();
28521  matrixWorldInverse.getInverse( parent.matrixWorld );
28522  child.applyMatrix( matrixWorldInverse );
28523 
28524  scene.remove( child );
28525  parent.add( child );
28526 
28527  }
28528 
28529 };
28530 
28531 // File:src/extras/ShapeUtils.js
28532 
28537 THREE.ShapeUtils = {
28538 
28539  // calculate area of the contour polygon
28540 
28541  area: function ( contour ) {
28542 
28543  var n = contour.length;
28544  var a = 0.0;
28545 
28546  for ( var p = n - 1, q = 0; q < n; p = q ++ ) {
28547 
28548  a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
28549 
28550  }
28551 
28552  return a * 0.5;
28553 
28554  },
28555 
28556  triangulate: ( function () {
28557 
28572  function snip( contour, u, v, w, n, verts ) {
28573 
28574  var p;
28575  var ax, ay, bx, by;
28576  var cx, cy, px, py;
28577 
28578  ax = contour[ verts[ u ] ].x;
28579  ay = contour[ verts[ u ] ].y;
28580 
28581  bx = contour[ verts[ v ] ].x;
28582  by = contour[ verts[ v ] ].y;
28583 
28584  cx = contour[ verts[ w ] ].x;
28585  cy = contour[ verts[ w ] ].y;
28586 
28587  if ( Number.EPSILON > ( ( ( bx - ax ) * ( cy - ay ) ) - ( ( by - ay ) * ( cx - ax ) ) ) ) return false;
28588 
28589  var aX, aY, bX, bY, cX, cY;
28590  var apx, apy, bpx, bpy, cpx, cpy;
28591  var cCROSSap, bCROSScp, aCROSSbp;
28592 
28593  aX = cx - bx; aY = cy - by;
28594  bX = ax - cx; bY = ay - cy;
28595  cX = bx - ax; cY = by - ay;
28596 
28597  for ( p = 0; p < n; p ++ ) {
28598 
28599  px = contour[ verts[ p ] ].x;
28600  py = contour[ verts[ p ] ].y;
28601 
28602  if ( ( ( px === ax ) && ( py === ay ) ) ||
28603  ( ( px === bx ) && ( py === by ) ) ||
28604  ( ( px === cx ) && ( py === cy ) ) ) continue;
28605 
28606  apx = px - ax; apy = py - ay;
28607  bpx = px - bx; bpy = py - by;
28608  cpx = px - cx; cpy = py - cy;
28609 
28610  // see if p is inside triangle abc
28611 
28612  aCROSSbp = aX * bpy - aY * bpx;
28613  cCROSSap = cX * apy - cY * apx;
28614  bCROSScp = bX * cpy - bY * cpx;
28615 
28616  if ( ( aCROSSbp >= - Number.EPSILON ) && ( bCROSScp >= - Number.EPSILON ) && ( cCROSSap >= - Number.EPSILON ) ) return false;
28617 
28618  }
28619 
28620  return true;
28621 
28622  }
28623 
28624  // takes in an contour array and returns
28625 
28626  return function ( contour, indices ) {
28627 
28628  var n = contour.length;
28629 
28630  if ( n < 3 ) return null;
28631 
28632  var result = [],
28633  verts = [],
28634  vertIndices = [];
28635 
28636  /* we want a counter-clockwise polygon in verts */
28637 
28638  var u, v, w;
28639 
28640  if ( THREE.ShapeUtils.area( contour ) > 0.0 ) {
28641 
28642  for ( v = 0; v < n; v ++ ) verts[ v ] = v;
28643 
28644  } else {
28645 
28646  for ( v = 0; v < n; v ++ ) verts[ v ] = ( n - 1 ) - v;
28647 
28648  }
28649 
28650  var nv = n;
28651 
28652  /* remove nv - 2 vertices, creating 1 triangle every time */
28653 
28654  var count = 2 * nv; /* error detection */
28655 
28656  for ( v = nv - 1; nv > 2; ) {
28657 
28658  /* if we loop, it is probably a non-simple polygon */
28659 
28660  if ( ( count -- ) <= 0 ) {
28661 
28662  //** Triangulate: ERROR - probable bad polygon!
28663 
28664  //throw ( "Warning, unable to triangulate polygon!" );
28665  //return null;
28666  // Sometimes warning is fine, especially polygons are triangulated in reverse.
28667  console.warn( 'THREE.ShapeUtils: Unable to triangulate polygon! in triangulate()' );
28668 
28669  if ( indices ) return vertIndices;
28670  return result;
28671 
28672  }
28673 
28674  /* three consecutive vertices in current polygon, <u,v,w> */
28675 
28676  u = v; if ( nv <= u ) u = 0; /* previous */
28677  v = u + 1; if ( nv <= v ) v = 0; /* new v */
28678  w = v + 1; if ( nv <= w ) w = 0; /* next */
28679 
28680  if ( snip( contour, u, v, w, nv, verts ) ) {
28681 
28682  var a, b, c, s, t;
28683 
28684  /* true names of the vertices */
28685 
28686  a = verts[ u ];
28687  b = verts[ v ];
28688  c = verts[ w ];
28689 
28690  /* output Triangle */
28691 
28692  result.push( [ contour[ a ],
28693  contour[ b ],
28694  contour[ c ] ] );
28695 
28696 
28697  vertIndices.push( [ verts[ u ], verts[ v ], verts[ w ] ] );
28698 
28699  /* remove v from the remaining polygon */
28700 
28701  for ( s = v, t = v + 1; t < nv; s ++, t ++ ) {
28702 
28703  verts[ s ] = verts[ t ];
28704 
28705  }
28706 
28707  nv --;
28708 
28709  /* reset error detection counter */
28710 
28711  count = 2 * nv;
28712 
28713  }
28714 
28715  }
28716 
28717  if ( indices ) return vertIndices;
28718  return result;
28719 
28720  }
28721 
28722  } )(),
28723 
28724  triangulateShape: function ( contour, holes ) {
28725 
28726  function point_in_segment_2D_colin( inSegPt1, inSegPt2, inOtherPt ) {
28727 
28728  // inOtherPt needs to be collinear to the inSegment
28729  if ( inSegPt1.x !== inSegPt2.x ) {
28730 
28731  if ( inSegPt1.x < inSegPt2.x ) {
28732 
28733  return ( ( inSegPt1.x <= inOtherPt.x ) && ( inOtherPt.x <= inSegPt2.x ) );
28734 
28735  } else {
28736 
28737  return ( ( inSegPt2.x <= inOtherPt.x ) && ( inOtherPt.x <= inSegPt1.x ) );
28738 
28739  }
28740 
28741  } else {
28742 
28743  if ( inSegPt1.y < inSegPt2.y ) {
28744 
28745  return ( ( inSegPt1.y <= inOtherPt.y ) && ( inOtherPt.y <= inSegPt2.y ) );
28746 
28747  } else {
28748 
28749  return ( ( inSegPt2.y <= inOtherPt.y ) && ( inOtherPt.y <= inSegPt1.y ) );
28750 
28751  }
28752 
28753  }
28754 
28755  }
28756 
28757  function intersect_segments_2D( inSeg1Pt1, inSeg1Pt2, inSeg2Pt1, inSeg2Pt2, inExcludeAdjacentSegs ) {
28758 
28759  var seg1dx = inSeg1Pt2.x - inSeg1Pt1.x, seg1dy = inSeg1Pt2.y - inSeg1Pt1.y;
28760  var seg2dx = inSeg2Pt2.x - inSeg2Pt1.x, seg2dy = inSeg2Pt2.y - inSeg2Pt1.y;
28761 
28762  var seg1seg2dx = inSeg1Pt1.x - inSeg2Pt1.x;
28763  var seg1seg2dy = inSeg1Pt1.y - inSeg2Pt1.y;
28764 
28765  var limit = seg1dy * seg2dx - seg1dx * seg2dy;
28766  var perpSeg1 = seg1dy * seg1seg2dx - seg1dx * seg1seg2dy;
28767 
28768  if ( Math.abs( limit ) > Number.EPSILON ) {
28769 
28770  // not parallel
28771 
28772  var perpSeg2;
28773  if ( limit > 0 ) {
28774 
28775  if ( ( perpSeg1 < 0 ) || ( perpSeg1 > limit ) ) return [];
28776  perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy;
28777  if ( ( perpSeg2 < 0 ) || ( perpSeg2 > limit ) ) return [];
28778 
28779  } else {
28780 
28781  if ( ( perpSeg1 > 0 ) || ( perpSeg1 < limit ) ) return [];
28782  perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy;
28783  if ( ( perpSeg2 > 0 ) || ( perpSeg2 < limit ) ) return [];
28784 
28785  }
28786 
28787  // i.e. to reduce rounding errors
28788  // intersection at endpoint of segment#1?
28789  if ( perpSeg2 === 0 ) {
28790 
28791  if ( ( inExcludeAdjacentSegs ) &&
28792  ( ( perpSeg1 === 0 ) || ( perpSeg1 === limit ) ) ) return [];
28793  return [ inSeg1Pt1 ];
28794 
28795  }
28796  if ( perpSeg2 === limit ) {
28797 
28798  if ( ( inExcludeAdjacentSegs ) &&
28799  ( ( perpSeg1 === 0 ) || ( perpSeg1 === limit ) ) ) return [];
28800  return [ inSeg1Pt2 ];
28801 
28802  }
28803  // intersection at endpoint of segment#2?
28804  if ( perpSeg1 === 0 ) return [ inSeg2Pt1 ];
28805  if ( perpSeg1 === limit ) return [ inSeg2Pt2 ];
28806 
28807  // return real intersection point
28808  var factorSeg1 = perpSeg2 / limit;
28809  return [ { x: inSeg1Pt1.x + factorSeg1 * seg1dx,
28810  y: inSeg1Pt1.y + factorSeg1 * seg1dy } ];
28811 
28812  } else {
28813 
28814  // parallel or collinear
28815  if ( ( perpSeg1 !== 0 ) ||
28816  ( seg2dy * seg1seg2dx !== seg2dx * seg1seg2dy ) ) return [];
28817 
28818  // they are collinear or degenerate
28819  var seg1Pt = ( ( seg1dx === 0 ) && ( seg1dy === 0 ) ); // segment1 is just a point?
28820  var seg2Pt = ( ( seg2dx === 0 ) && ( seg2dy === 0 ) ); // segment2 is just a point?
28821  // both segments are points
28822  if ( seg1Pt && seg2Pt ) {
28823 
28824  if ( ( inSeg1Pt1.x !== inSeg2Pt1.x ) ||
28825  ( inSeg1Pt1.y !== inSeg2Pt1.y ) ) return []; // they are distinct points
28826  return [ inSeg1Pt1 ]; // they are the same point
28827 
28828  }
28829  // segment#1 is a single point
28830  if ( seg1Pt ) {
28831 
28832  if ( ! point_in_segment_2D_colin( inSeg2Pt1, inSeg2Pt2, inSeg1Pt1 ) ) return []; // but not in segment#2
28833  return [ inSeg1Pt1 ];
28834 
28835  }
28836  // segment#2 is a single point
28837  if ( seg2Pt ) {
28838 
28839  if ( ! point_in_segment_2D_colin( inSeg1Pt1, inSeg1Pt2, inSeg2Pt1 ) ) return []; // but not in segment#1
28840  return [ inSeg2Pt1 ];
28841 
28842  }
28843 
28844  // they are collinear segments, which might overlap
28845  var seg1min, seg1max, seg1minVal, seg1maxVal;
28846  var seg2min, seg2max, seg2minVal, seg2maxVal;
28847  if ( seg1dx !== 0 ) {
28848 
28849  // the segments are NOT on a vertical line
28850  if ( inSeg1Pt1.x < inSeg1Pt2.x ) {
28851 
28852  seg1min = inSeg1Pt1; seg1minVal = inSeg1Pt1.x;
28853  seg1max = inSeg1Pt2; seg1maxVal = inSeg1Pt2.x;
28854 
28855  } else {
28856 
28857  seg1min = inSeg1Pt2; seg1minVal = inSeg1Pt2.x;
28858  seg1max = inSeg1Pt1; seg1maxVal = inSeg1Pt1.x;
28859 
28860  }
28861  if ( inSeg2Pt1.x < inSeg2Pt2.x ) {
28862 
28863  seg2min = inSeg2Pt1; seg2minVal = inSeg2Pt1.x;
28864  seg2max = inSeg2Pt2; seg2maxVal = inSeg2Pt2.x;
28865 
28866  } else {
28867 
28868  seg2min = inSeg2Pt2; seg2minVal = inSeg2Pt2.x;
28869  seg2max = inSeg2Pt1; seg2maxVal = inSeg2Pt1.x;
28870 
28871  }
28872 
28873  } else {
28874 
28875  // the segments are on a vertical line
28876  if ( inSeg1Pt1.y < inSeg1Pt2.y ) {
28877 
28878  seg1min = inSeg1Pt1; seg1minVal = inSeg1Pt1.y;
28879  seg1max = inSeg1Pt2; seg1maxVal = inSeg1Pt2.y;
28880 
28881  } else {
28882 
28883  seg1min = inSeg1Pt2; seg1minVal = inSeg1Pt2.y;
28884  seg1max = inSeg1Pt1; seg1maxVal = inSeg1Pt1.y;
28885 
28886  }
28887  if ( inSeg2Pt1.y < inSeg2Pt2.y ) {
28888 
28889  seg2min = inSeg2Pt1; seg2minVal = inSeg2Pt1.y;
28890  seg2max = inSeg2Pt2; seg2maxVal = inSeg2Pt2.y;
28891 
28892  } else {
28893 
28894  seg2min = inSeg2Pt2; seg2minVal = inSeg2Pt2.y;
28895  seg2max = inSeg2Pt1; seg2maxVal = inSeg2Pt1.y;
28896 
28897  }
28898 
28899  }
28900  if ( seg1minVal <= seg2minVal ) {
28901 
28902  if ( seg1maxVal < seg2minVal ) return [];
28903  if ( seg1maxVal === seg2minVal ) {
28904 
28905  if ( inExcludeAdjacentSegs ) return [];
28906  return [ seg2min ];
28907 
28908  }
28909  if ( seg1maxVal <= seg2maxVal ) return [ seg2min, seg1max ];
28910  return [ seg2min, seg2max ];
28911 
28912  } else {
28913 
28914  if ( seg1minVal > seg2maxVal ) return [];
28915  if ( seg1minVal === seg2maxVal ) {
28916 
28917  if ( inExcludeAdjacentSegs ) return [];
28918  return [ seg1min ];
28919 
28920  }
28921  if ( seg1maxVal <= seg2maxVal ) return [ seg1min, seg1max ];
28922  return [ seg1min, seg2max ];
28923 
28924  }
28925 
28926  }
28927 
28928  }
28929 
28930  function isPointInsideAngle( inVertex, inLegFromPt, inLegToPt, inOtherPt ) {
28931 
28932  // The order of legs is important
28933 
28934  // translation of all points, so that Vertex is at (0,0)
28935  var legFromPtX = inLegFromPt.x - inVertex.x, legFromPtY = inLegFromPt.y - inVertex.y;
28936  var legToPtX = inLegToPt.x - inVertex.x, legToPtY = inLegToPt.y - inVertex.y;
28937  var otherPtX = inOtherPt.x - inVertex.x, otherPtY = inOtherPt.y - inVertex.y;
28938 
28939  // main angle >0: < 180 deg.; 0: 180 deg.; <0: > 180 deg.
28940  var from2toAngle = legFromPtX * legToPtY - legFromPtY * legToPtX;
28941  var from2otherAngle = legFromPtX * otherPtY - legFromPtY * otherPtX;
28942 
28943  if ( Math.abs( from2toAngle ) > Number.EPSILON ) {
28944 
28945  // angle != 180 deg.
28946 
28947  var other2toAngle = otherPtX * legToPtY - otherPtY * legToPtX;
28948  // console.log( "from2to: " + from2toAngle + ", from2other: " + from2otherAngle + ", other2to: " + other2toAngle );
28949 
28950  if ( from2toAngle > 0 ) {
28951 
28952  // main angle < 180 deg.
28953  return ( ( from2otherAngle >= 0 ) && ( other2toAngle >= 0 ) );
28954 
28955  } else {
28956 
28957  // main angle > 180 deg.
28958  return ( ( from2otherAngle >= 0 ) || ( other2toAngle >= 0 ) );
28959 
28960  }
28961 
28962  } else {
28963 
28964  // angle == 180 deg.
28965  // console.log( "from2to: 180 deg., from2other: " + from2otherAngle );
28966  return ( from2otherAngle > 0 );
28967 
28968  }
28969 
28970  }
28971 
28972 
28973  function removeHoles( contour, holes ) {
28974 
28975  var shape = contour.concat(); // work on this shape
28976  var hole;
28977 
28978  function isCutLineInsideAngles( inShapeIdx, inHoleIdx ) {
28979 
28980  // Check if hole point lies within angle around shape point
28981  var lastShapeIdx = shape.length - 1;
28982 
28983  var prevShapeIdx = inShapeIdx - 1;
28984  if ( prevShapeIdx < 0 ) prevShapeIdx = lastShapeIdx;
28985 
28986  var nextShapeIdx = inShapeIdx + 1;
28987  if ( nextShapeIdx > lastShapeIdx ) nextShapeIdx = 0;
28988 
28989  var insideAngle = isPointInsideAngle( shape[ inShapeIdx ], shape[ prevShapeIdx ], shape[ nextShapeIdx ], hole[ inHoleIdx ] );
28990  if ( ! insideAngle ) {
28991 
28992  // console.log( "Vertex (Shape): " + inShapeIdx + ", Point: " + hole[inHoleIdx].x + "/" + hole[inHoleIdx].y );
28993  return false;
28994 
28995  }
28996 
28997  // Check if shape point lies within angle around hole point
28998  var lastHoleIdx = hole.length - 1;
28999 
29000  var prevHoleIdx = inHoleIdx - 1;
29001  if ( prevHoleIdx < 0 ) prevHoleIdx = lastHoleIdx;
29002 
29003  var nextHoleIdx = inHoleIdx + 1;
29004  if ( nextHoleIdx > lastHoleIdx ) nextHoleIdx = 0;
29005 
29006  insideAngle = isPointInsideAngle( hole[ inHoleIdx ], hole[ prevHoleIdx ], hole[ nextHoleIdx ], shape[ inShapeIdx ] );
29007  if ( ! insideAngle ) {
29008 
29009  // console.log( "Vertex (Hole): " + inHoleIdx + ", Point: " + shape[inShapeIdx].x + "/" + shape[inShapeIdx].y );
29010  return false;
29011 
29012  }
29013 
29014  return true;
29015 
29016  }
29017 
29018  function intersectsShapeEdge( inShapePt, inHolePt ) {
29019 
29020  // checks for intersections with shape edges
29021  var sIdx, nextIdx, intersection;
29022  for ( sIdx = 0; sIdx < shape.length; sIdx ++ ) {
29023 
29024  nextIdx = sIdx + 1; nextIdx %= shape.length;
29025  intersection = intersect_segments_2D( inShapePt, inHolePt, shape[ sIdx ], shape[ nextIdx ], true );
29026  if ( intersection.length > 0 ) return true;
29027 
29028  }
29029 
29030  return false;
29031 
29032  }
29033 
29034  var indepHoles = [];
29035 
29036  function intersectsHoleEdge( inShapePt, inHolePt ) {
29037 
29038  // checks for intersections with hole edges
29039  var ihIdx, chkHole,
29040  hIdx, nextIdx, intersection;
29041  for ( ihIdx = 0; ihIdx < indepHoles.length; ihIdx ++ ) {
29042 
29043  chkHole = holes[ indepHoles[ ihIdx ]];
29044  for ( hIdx = 0; hIdx < chkHole.length; hIdx ++ ) {
29045 
29046  nextIdx = hIdx + 1; nextIdx %= chkHole.length;
29047  intersection = intersect_segments_2D( inShapePt, inHolePt, chkHole[ hIdx ], chkHole[ nextIdx ], true );
29048  if ( intersection.length > 0 ) return true;
29049 
29050  }
29051 
29052  }
29053  return false;
29054 
29055  }
29056 
29057  var holeIndex, shapeIndex,
29058  shapePt, holePt,
29059  holeIdx, cutKey, failedCuts = [],
29060  tmpShape1, tmpShape2,
29061  tmpHole1, tmpHole2;
29062 
29063  for ( var h = 0, hl = holes.length; h < hl; h ++ ) {
29064 
29065  indepHoles.push( h );
29066 
29067  }
29068 
29069  var minShapeIndex = 0;
29070  var counter = indepHoles.length * 2;
29071  while ( indepHoles.length > 0 ) {
29072 
29073  counter --;
29074  if ( counter < 0 ) {
29075 
29076  console.log( "Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!" );
29077  break;
29078 
29079  }
29080 
29081  // search for shape-vertex and hole-vertex,
29082  // which can be connected without intersections
29083  for ( shapeIndex = minShapeIndex; shapeIndex < shape.length; shapeIndex ++ ) {
29084 
29085  shapePt = shape[ shapeIndex ];
29086  holeIndex = - 1;
29087 
29088  // search for hole which can be reached without intersections
29089  for ( var h = 0; h < indepHoles.length; h ++ ) {
29090 
29091  holeIdx = indepHoles[ h ];
29092 
29093  // prevent multiple checks
29094  cutKey = shapePt.x + ":" + shapePt.y + ":" + holeIdx;
29095  if ( failedCuts[ cutKey ] !== undefined ) continue;
29096 
29097  hole = holes[ holeIdx ];
29098  for ( var h2 = 0; h2 < hole.length; h2 ++ ) {
29099 
29100  holePt = hole[ h2 ];
29101  if ( ! isCutLineInsideAngles( shapeIndex, h2 ) ) continue;
29102  if ( intersectsShapeEdge( shapePt, holePt ) ) continue;
29103  if ( intersectsHoleEdge( shapePt, holePt ) ) continue;
29104 
29105  holeIndex = h2;
29106  indepHoles.splice( h, 1 );
29107 
29108  tmpShape1 = shape.slice( 0, shapeIndex + 1 );
29109  tmpShape2 = shape.slice( shapeIndex );
29110  tmpHole1 = hole.slice( holeIndex );
29111  tmpHole2 = hole.slice( 0, holeIndex + 1 );
29112 
29113  shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 );
29114 
29115  minShapeIndex = shapeIndex;
29116 
29117  // Debug only, to show the selected cuts
29118  // glob_CutLines.push( [ shapePt, holePt ] );
29119 
29120  break;
29121 
29122  }
29123  if ( holeIndex >= 0 ) break; // hole-vertex found
29124 
29125  failedCuts[ cutKey ] = true; // remember failure
29126 
29127  }
29128  if ( holeIndex >= 0 ) break; // hole-vertex found
29129 
29130  }
29131 
29132  }
29133 
29134  return shape; /* shape with no holes */
29135 
29136  }
29137 
29138 
29139  var i, il, f, face,
29140  key, index,
29141  allPointsMap = {};
29142 
29143  // To maintain reference to old shape, one must match coordinates, or offset the indices from original arrays. It's probably easier to do the first.
29144 
29145  var allpoints = contour.concat();
29146 
29147  for ( var h = 0, hl = holes.length; h < hl; h ++ ) {
29148 
29149  Array.prototype.push.apply( allpoints, holes[ h ] );
29150 
29151  }
29152 
29153  //console.log( "allpoints",allpoints, allpoints.length );
29154 
29155  // prepare all points map
29156 
29157  for ( i = 0, il = allpoints.length; i < il; i ++ ) {
29158 
29159  key = allpoints[ i ].x + ":" + allpoints[ i ].y;
29160 
29161  if ( allPointsMap[ key ] !== undefined ) {
29162 
29163  console.warn( "THREE.Shape: Duplicate point", key );
29164 
29165  }
29166 
29167  allPointsMap[ key ] = i;
29168 
29169  }
29170 
29171  // remove holes by cutting paths to holes and adding them to the shape
29172  var shapeWithoutHoles = removeHoles( contour, holes );
29173 
29174  var triangles = THREE.ShapeUtils.triangulate( shapeWithoutHoles, false ); // True returns indices for points of spooled shape
29175  //console.log( "triangles",triangles, triangles.length );
29176 
29177  // check all face vertices against all points map
29178 
29179  for ( i = 0, il = triangles.length; i < il; i ++ ) {
29180 
29181  face = triangles[ i ];
29182 
29183  for ( f = 0; f < 3; f ++ ) {
29184 
29185  key = face[ f ].x + ":" + face[ f ].y;
29186 
29187  index = allPointsMap[ key ];
29188 
29189  if ( index !== undefined ) {
29190 
29191  face[ f ] = index;
29192 
29193  }
29194 
29195  }
29196 
29197  }
29198 
29199  return triangles.concat();
29200 
29201  },
29202 
29203  isClockWise: function ( pts ) {
29204 
29205  return THREE.ShapeUtils.area( pts ) < 0;
29206 
29207  },
29208 
29209  // Bezier Curves formulas obtained from
29210  // http://en.wikipedia.org/wiki/B%C3%A9zier_curve
29211 
29212  // Quad Bezier Functions
29213 
29214  b2: ( function () {
29215 
29216  function b2p0( t, p ) {
29217 
29218  var k = 1 - t;
29219  return k * k * p;
29220 
29221  }
29222 
29223  function b2p1( t, p ) {
29224 
29225  return 2 * ( 1 - t ) * t * p;
29226 
29227  }
29228 
29229  function b2p2( t, p ) {
29230 
29231  return t * t * p;
29232 
29233  }
29234 
29235  return function ( t, p0, p1, p2 ) {
29236 
29237  return b2p0( t, p0 ) + b2p1( t, p1 ) + b2p2( t, p2 );
29238 
29239  };
29240 
29241  } )(),
29242 
29243  // Cubic Bezier Functions
29244 
29245  b3: ( function () {
29246 
29247  function b3p0( t, p ) {
29248 
29249  var k = 1 - t;
29250  return k * k * k * p;
29251 
29252  }
29253 
29254  function b3p1( t, p ) {
29255 
29256  var k = 1 - t;
29257  return 3 * k * k * t * p;
29258 
29259  }
29260 
29261  function b3p2( t, p ) {
29262 
29263  var k = 1 - t;
29264  return 3 * k * t * t * p;
29265 
29266  }
29267 
29268  function b3p3( t, p ) {
29269 
29270  return t * t * t * p;
29271 
29272  }
29273 
29274  return function ( t, p0, p1, p2, p3 ) {
29275 
29276  return b3p0( t, p0 ) + b3p1( t, p1 ) + b3p2( t, p2 ) + b3p3( t, p3 );
29277 
29278  };
29279 
29280  } )()
29281 
29282 };
29283 
29284 // File:src/extras/audio/Audio.js
29285 
29290 THREE.Audio = function ( listener ) {
29291 
29292  THREE.Object3D.call( this );
29293 
29294  this.type = 'Audio';
29295 
29296  this.context = listener.context;
29297  this.source = this.context.createBufferSource();
29298  this.source.onended = this.onEnded.bind( this );
29299 
29300  this.gain = this.context.createGain();
29301  this.gain.connect( this.context.destination );
29302 
29303  this.panner = this.context.createPanner();
29304  this.panner.connect( this.gain );
29305 
29306  this.autoplay = false;
29307 
29308  this.startTime = 0;
29309  this.playbackRate = 1;
29310  this.isPlaying = false;
29311 
29312 };
29313 
29314 THREE.Audio.prototype = Object.create( THREE.Object3D.prototype );
29315 THREE.Audio.prototype.constructor = THREE.Audio;
29316 
29317 THREE.Audio.prototype.load = function ( file ) {
29318 
29319  var scope = this;
29320 
29321  var request = new XMLHttpRequest();
29322  request.open( 'GET', file, true );
29323  request.responseType = 'arraybuffer';
29324  request.onload = function ( e ) {
29325 
29326  scope.context.decodeAudioData( this.response, function ( buffer ) {
29327 
29328  scope.source.buffer = buffer;
29329 
29330  if ( scope.autoplay ) scope.play();
29331 
29332  } );
29333 
29334  };
29335  request.send();
29336 
29337  return this;
29338 
29339 };
29340 
29341 THREE.Audio.prototype.play = function () {
29342 
29343  if ( this.isPlaying === true ) {
29344 
29345  console.warn( 'THREE.Audio: Audio is already playing.' );
29346  return;
29347 
29348  }
29349 
29350  var source = this.context.createBufferSource();
29351 
29352  source.buffer = this.source.buffer;
29353  source.loop = this.source.loop;
29354  source.onended = this.source.onended;
29355  source.start( 0, this.startTime );
29356  source.playbackRate.value = this.playbackRate;
29357 
29358  this.isPlaying = true;
29359 
29360  this.source = source;
29361 
29362  this.connect();
29363 
29364 };
29365 
29366 THREE.Audio.prototype.pause = function () {
29367 
29368  this.source.stop();
29369  this.startTime = this.context.currentTime;
29370 
29371 };
29372 
29373 THREE.Audio.prototype.stop = function () {
29374 
29375  this.source.stop();
29376  this.startTime = 0;
29377 
29378 };
29379 
29380 THREE.Audio.prototype.connect = function () {
29381 
29382  if ( this.filter !== undefined ) {
29383 
29384  this.source.connect( this.filter );
29385  this.filter.connect( this.panner );
29386 
29387  } else {
29388 
29389  this.source.connect( this.panner );
29390 
29391  }
29392 
29393 };
29394 
29395 THREE.Audio.prototype.disconnect = function () {
29396 
29397  if ( this.filter !== undefined ) {
29398 
29399  this.source.disconnect( this.filter );
29400  this.filter.disconnect( this.panner );
29401 
29402  } else {
29403 
29404  this.source.disconnect( this.panner );
29405 
29406  }
29407 
29408 };
29409 
29410 THREE.Audio.prototype.setFilter = function ( value ) {
29411 
29412  if ( this.isPlaying === true ) {
29413 
29414  this.disconnect();
29415  this.filter = value;
29416  this.connect();
29417 
29418  } else {
29419 
29420  this.filter = value;
29421 
29422  }
29423 
29424 };
29425 
29426 THREE.Audio.prototype.getFilter = function () {
29427 
29428  return this.filter;
29429 
29430 };
29431 
29432 THREE.Audio.prototype.setPlaybackRate = function ( value ) {
29433 
29434  this.playbackRate = value;
29435 
29436  if ( this.isPlaying === true ) {
29437 
29438  this.source.playbackRate.value = this.playbackRate;
29439 
29440  }
29441 
29442 };
29443 
29444 THREE.Audio.prototype.getPlaybackRate = function () {
29445 
29446  return this.playbackRate;
29447 
29448 };
29449 
29450 THREE.Audio.prototype.onEnded = function() {
29451 
29452  this.isPlaying = false;
29453 
29454 };
29455 
29456 THREE.Audio.prototype.setLoop = function ( value ) {
29457 
29458  this.source.loop = value;
29459 
29460 };
29461 
29462 THREE.Audio.prototype.getLoop = function () {
29463 
29464  return this.source.loop;
29465 
29466 };
29467 
29468 THREE.Audio.prototype.setRefDistance = function ( value ) {
29469 
29470  this.panner.refDistance = value;
29471 
29472 };
29473 
29474 THREE.Audio.prototype.getRefDistance = function () {
29475 
29476  return this.panner.refDistance;
29477 
29478 };
29479 
29480 THREE.Audio.prototype.setRolloffFactor = function ( value ) {
29481 
29482  this.panner.rolloffFactor = value;
29483 
29484 };
29485 
29486 THREE.Audio.prototype.getRolloffFactor = function () {
29487 
29488  return this.panner.rolloffFactor;
29489 
29490 };
29491 
29492 THREE.Audio.prototype.setVolume = function ( value ) {
29493 
29494  this.gain.gain.value = value;
29495 
29496 };
29497 
29498 THREE.Audio.prototype.getVolume = function () {
29499 
29500  return this.gain.gain.value;
29501 
29502 };
29503 
29504 THREE.Audio.prototype.updateMatrixWorld = ( function () {
29505 
29506  var position = new THREE.Vector3();
29507 
29508  return function updateMatrixWorld( force ) {
29509 
29510  THREE.Object3D.prototype.updateMatrixWorld.call( this, force );
29511 
29512  position.setFromMatrixPosition( this.matrixWorld );
29513 
29514  this.panner.setPosition( position.x, position.y, position.z );
29515 
29516  };
29517 
29518 } )();
29519 
29520 // File:src/extras/audio/AudioListener.js
29521 
29526 THREE.AudioListener = function () {
29527 
29528  THREE.Object3D.call( this );
29529 
29530  this.type = 'AudioListener';
29531 
29532  this.context = new ( window.AudioContext || window.webkitAudioContext )();
29533 
29534 };
29535 
29536 THREE.AudioListener.prototype = Object.create( THREE.Object3D.prototype );
29537 THREE.AudioListener.prototype.constructor = THREE.AudioListener;
29538 
29539 THREE.AudioListener.prototype.updateMatrixWorld = ( function () {
29540 
29541  var position = new THREE.Vector3();
29542  var quaternion = new THREE.Quaternion();
29543  var scale = new THREE.Vector3();
29544 
29545  var orientation = new THREE.Vector3();
29546 
29547  return function updateMatrixWorld( force ) {
29548 
29549  THREE.Object3D.prototype.updateMatrixWorld.call( this, force );
29550 
29551  var listener = this.context.listener;
29552  var up = this.up;
29553 
29554  this.matrixWorld.decompose( position, quaternion, scale );
29555 
29556  orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion );
29557 
29558  listener.setPosition( position.x, position.y, position.z );
29559  listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z );
29560 
29561  };
29562 
29563 } )();
29564 
29565 // File:src/extras/core/Curve.js
29566 
29599 /**************************************************************
29600  * Abstract Curve base class
29601  **************************************************************/
29602 
29603 THREE.Curve = function () {
29604 
29605 };
29606 
29607 THREE.Curve.prototype = {
29608 
29609  constructor: THREE.Curve,
29610 
29611  // Virtual base class method to overwrite and implement in subclasses
29612  // - t [0 .. 1]
29613 
29614  getPoint: function ( t ) {
29615 
29616  console.warn( "THREE.Curve: Warning, getPoint() not implemented!" );
29617  return null;
29618 
29619  },
29620 
29621  // Get point at relative position in curve according to arc length
29622  // - u [0 .. 1]
29623 
29624  getPointAt: function ( u ) {
29625 
29626  var t = this.getUtoTmapping( u );
29627  return this.getPoint( t );
29628 
29629  },
29630 
29631  // Get sequence of points using getPoint( t )
29632 
29633  getPoints: function ( divisions ) {
29634 
29635  if ( ! divisions ) divisions = 5;
29636 
29637  var d, pts = [];
29638 
29639  for ( d = 0; d <= divisions; d ++ ) {
29640 
29641  pts.push( this.getPoint( d / divisions ) );
29642 
29643  }
29644 
29645  return pts;
29646 
29647  },
29648 
29649  // Get sequence of points using getPointAt( u )
29650 
29651  getSpacedPoints: function ( divisions ) {
29652 
29653  if ( ! divisions ) divisions = 5;
29654 
29655  var d, pts = [];
29656 
29657  for ( d = 0; d <= divisions; d ++ ) {
29658 
29659  pts.push( this.getPointAt( d / divisions ) );
29660 
29661  }
29662 
29663  return pts;
29664 
29665  },
29666 
29667  // Get total curve arc length
29668 
29669  getLength: function () {
29670 
29671  var lengths = this.getLengths();
29672  return lengths[ lengths.length - 1 ];
29673 
29674  },
29675 
29676  // Get list of cumulative segment lengths
29677 
29678  getLengths: function ( divisions ) {
29679 
29680  if ( ! divisions ) divisions = ( this.__arcLengthDivisions ) ? ( this.__arcLengthDivisions ) : 200;
29681 
29682  if ( this.cacheArcLengths
29683  && ( this.cacheArcLengths.length === divisions + 1 )
29684  && ! this.needsUpdate ) {
29685 
29686  //console.log( "cached", this.cacheArcLengths );
29687  return this.cacheArcLengths;
29688 
29689  }
29690 
29691  this.needsUpdate = false;
29692 
29693  var cache = [];
29694  var current, last = this.getPoint( 0 );
29695  var p, sum = 0;
29696 
29697  cache.push( 0 );
29698 
29699  for ( p = 1; p <= divisions; p ++ ) {
29700 
29701  current = this.getPoint ( p / divisions );
29702  sum += current.distanceTo( last );
29703  cache.push( sum );
29704  last = current;
29705 
29706  }
29707 
29708  this.cacheArcLengths = cache;
29709 
29710  return cache; // { sums: cache, sum:sum }; Sum is in the last element.
29711 
29712  },
29713 
29714  updateArcLengths: function() {
29715 
29716  this.needsUpdate = true;
29717  this.getLengths();
29718 
29719  },
29720 
29721  // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
29722 
29723  getUtoTmapping: function ( u, distance ) {
29724 
29725  var arcLengths = this.getLengths();
29726 
29727  var i = 0, il = arcLengths.length;
29728 
29729  var targetArcLength; // The targeted u distance value to get
29730 
29731  if ( distance ) {
29732 
29733  targetArcLength = distance;
29734 
29735  } else {
29736 
29737  targetArcLength = u * arcLengths[ il - 1 ];
29738 
29739  }
29740 
29741  //var time = Date.now();
29742 
29743  // binary search for the index with largest value smaller than target u distance
29744 
29745  var low = 0, high = il - 1, comparison;
29746 
29747  while ( low <= high ) {
29748 
29749  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
29750 
29751  comparison = arcLengths[ i ] - targetArcLength;
29752 
29753  if ( comparison < 0 ) {
29754 
29755  low = i + 1;
29756 
29757  } else if ( comparison > 0 ) {
29758 
29759  high = i - 1;
29760 
29761  } else {
29762 
29763  high = i;
29764  break;
29765 
29766  // DONE
29767 
29768  }
29769 
29770  }
29771 
29772  i = high;
29773 
29774  //console.log('b' , i, low, high, Date.now()- time);
29775 
29776  if ( arcLengths[ i ] === targetArcLength ) {
29777 
29778  var t = i / ( il - 1 );
29779  return t;
29780 
29781  }
29782 
29783  // we could get finer grain at lengths, or use simple interpolation between two points
29784 
29785  var lengthBefore = arcLengths[ i ];
29786  var lengthAfter = arcLengths[ i + 1 ];
29787 
29788  var segmentLength = lengthAfter - lengthBefore;
29789 
29790  // determine where we are between the 'before' and 'after' points
29791 
29792  var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
29793 
29794  // add that fractional amount to t
29795 
29796  var t = ( i + segmentFraction ) / ( il - 1 );
29797 
29798  return t;
29799 
29800  },
29801 
29802  // Returns a unit vector tangent at t
29803  // In case any sub curve does not implement its tangent derivation,
29804  // 2 points a small delta apart will be used to find its gradient
29805  // which seems to give a reasonable approximation
29806 
29807  getTangent: function( t ) {
29808 
29809  var delta = 0.0001;
29810  var t1 = t - delta;
29811  var t2 = t + delta;
29812 
29813  // Capping in case of danger
29814 
29815  if ( t1 < 0 ) t1 = 0;
29816  if ( t2 > 1 ) t2 = 1;
29817 
29818  var pt1 = this.getPoint( t1 );
29819  var pt2 = this.getPoint( t2 );
29820 
29821  var vec = pt2.clone().sub( pt1 );
29822  return vec.normalize();
29823 
29824  },
29825 
29826  getTangentAt: function ( u ) {
29827 
29828  var t = this.getUtoTmapping( u );
29829  return this.getTangent( t );
29830 
29831  }
29832 
29833 }
29834 
29835 THREE.Curve.Utils = THREE.CurveUtils; // backwards compatibility
29836 
29837 // TODO: Transformation for Curves?
29838 
29839 /**************************************************************
29840  * 3D Curves
29841  **************************************************************/
29842 
29843 // A Factory method for creating new curve subclasses
29844 
29845 THREE.Curve.create = function ( constructor, getPointFunc ) {
29846 
29847  constructor.prototype = Object.create( THREE.Curve.prototype );
29848  constructor.prototype.constructor = constructor;
29849  constructor.prototype.getPoint = getPointFunc;
29850 
29851  return constructor;
29852 
29853 };
29854 
29855 // File:src/extras/core/CurvePath.js
29856 
29862 /**************************************************************
29863  * Curved Path - a curve path is simply a array of connected
29864  * curves, but retains the api of a curve
29865  **************************************************************/
29866 
29867 THREE.CurvePath = function () {
29868 
29869  this.curves = [];
29870 
29871  this.autoClose = false; // Automatically closes the path
29872 
29873 };
29874 
29875 THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype );
29876 THREE.CurvePath.prototype.constructor = THREE.CurvePath;
29877 
29878 THREE.CurvePath.prototype.add = function ( curve ) {
29879 
29880  this.curves.push( curve );
29881 
29882 };
29883 
29884 /*
29885 THREE.CurvePath.prototype.checkConnection = function() {
29886  // TODO
29887  // If the ending of curve is not connected to the starting
29888  // or the next curve, then, this is not a real path
29889 };
29890 */
29891 
29892 THREE.CurvePath.prototype.closePath = function() {
29893 
29894  // TODO Test
29895  // and verify for vector3 (needs to implement equals)
29896  // Add a line curve if start and end of lines are not connected
29897  var startPoint = this.curves[ 0 ].getPoint( 0 );
29898  var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
29899 
29900  if ( ! startPoint.equals( endPoint ) ) {
29901 
29902  this.curves.push( new THREE.LineCurve( endPoint, startPoint ) );
29903 
29904  }
29905 
29906 };
29907 
29908 // To get accurate point with reference to
29909 // entire path distance at time t,
29910 // following has to be done:
29911 
29912 // 1. Length of each sub path have to be known
29913 // 2. Locate and identify type of curve
29914 // 3. Get t for the curve
29915 // 4. Return curve.getPointAt(t')
29916 
29917 THREE.CurvePath.prototype.getPoint = function( t ) {
29918 
29919  var d = t * this.getLength();
29920  var curveLengths = this.getCurveLengths();
29921  var i = 0;
29922 
29923  // To think about boundaries points.
29924 
29925  while ( i < curveLengths.length ) {
29926 
29927  if ( curveLengths[ i ] >= d ) {
29928 
29929  var diff = curveLengths[ i ] - d;
29930  var curve = this.curves[ i ];
29931 
29932  var u = 1 - diff / curve.getLength();
29933 
29934  return curve.getPointAt( u );
29935 
29936  }
29937 
29938  i ++;
29939 
29940  }
29941 
29942  return null;
29943 
29944  // loop where sum != 0, sum > d , sum+1 <d
29945 
29946 };
29947 
29948 /*
29949 THREE.CurvePath.prototype.getTangent = function( t ) {
29950 };
29951 */
29952 
29953 // We cannot use the default THREE.Curve getPoint() with getLength() because in
29954 // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
29955 // getPoint() depends on getLength
29956 
29957 THREE.CurvePath.prototype.getLength = function() {
29958 
29959  var lens = this.getCurveLengths();
29960  return lens[ lens.length - 1 ];
29961 
29962 };
29963 
29964 // Compute lengths and cache them
29965 // We cannot overwrite getLengths() because UtoT mapping uses it.
29966 
29967 THREE.CurvePath.prototype.getCurveLengths = function() {
29968 
29969  // We use cache values if curves and cache array are same length
29970 
29971  if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
29972 
29973  return this.cacheLengths;
29974 
29975  }
29976 
29977  // Get length of sub-curve
29978  // Push sums into cached array
29979 
29980  var lengths = [], sums = 0;
29981 
29982  for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
29983 
29984  sums += this.curves[ i ].getLength();
29985  lengths.push( sums );
29986 
29987  }
29988 
29989  this.cacheLengths = lengths;
29990 
29991  return lengths;
29992 
29993 };
29994 
29995 
29996 
29997 /**************************************************************
29998  * Create Geometries Helpers
29999  **************************************************************/
30000 
30002 
30003 THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
30004 
30005  var pts = this.getPoints( divisions, true );
30006  return this.createGeometry( pts );
30007 
30008 };
30009 
30010 // Generate geometry from equidistant sampling along the path
30011 
30012 THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
30013 
30014  var pts = this.getSpacedPoints( divisions, true );
30015  return this.createGeometry( pts );
30016 
30017 };
30018 
30019 THREE.CurvePath.prototype.createGeometry = function( points ) {
30020 
30021  var geometry = new THREE.Geometry();
30022 
30023  for ( var i = 0, l = points.length; i < l; i ++ ) {
30024 
30025  var point = points[ i ];
30026  geometry.vertices.push( new THREE.Vector3( point.x, point.y, point.z || 0 ) );
30027 
30028  }
30029 
30030  return geometry;
30031 
30032 };
30033 
30034 // File:src/extras/core/Path.js
30035 
30042 THREE.Path = function ( points ) {
30043 
30044  THREE.CurvePath.call( this );
30045 
30046  this.actions = [];
30047 
30048  if ( points ) {
30049 
30050  this.fromPoints( points );
30051 
30052  }
30053 
30054 };
30055 
30056 THREE.Path.prototype = Object.create( THREE.CurvePath.prototype );
30057 THREE.Path.prototype.constructor = THREE.Path;
30058 
30059 // TODO Clean up PATH API
30060 
30061 // Create path using straight lines to connect all points
30062 // - vectors: array of Vector2
30063 
30064 THREE.Path.prototype.fromPoints = function ( vectors ) {
30065 
30066  this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
30067 
30068  for ( var i = 1, l = vectors.length; i < l; i ++ ) {
30069 
30070  this.lineTo( vectors[ i ].x, vectors[ i ].y );
30071 
30072  }
30073 
30074 };
30075 
30076 // startPath() endPath()?
30077 
30078 THREE.Path.prototype.moveTo = function ( x, y ) {
30079 
30080  this.actions.push( { action: 'moveTo', args: [ x, y ] } );
30081 
30082 };
30083 
30084 THREE.Path.prototype.lineTo = function ( x, y ) {
30085 
30086  var lastargs = this.actions[ this.actions.length - 1 ].args;
30087 
30088  var x0 = lastargs[ lastargs.length - 2 ];
30089  var y0 = lastargs[ lastargs.length - 1 ];
30090 
30091  var curve = new THREE.LineCurve( new THREE.Vector2( x0, y0 ), new THREE.Vector2( x, y ) );
30092  this.curves.push( curve );
30093 
30094  this.actions.push( { action: 'lineTo', args: [ x, y ] } );
30095 
30096 };
30097 
30098 THREE.Path.prototype.quadraticCurveTo = function( aCPx, aCPy, aX, aY ) {
30099 
30100  var lastargs = this.actions[ this.actions.length - 1 ].args;
30101 
30102  var x0 = lastargs[ lastargs.length - 2 ];
30103  var y0 = lastargs[ lastargs.length - 1 ];
30104 
30105  var curve = new THREE.QuadraticBezierCurve(
30106  new THREE.Vector2( x0, y0 ),
30107  new THREE.Vector2( aCPx, aCPy ),
30108  new THREE.Vector2( aX, aY )
30109  );
30110 
30111  this.curves.push( curve );
30112 
30113  this.actions.push( { action: 'quadraticCurveTo', args: [ aCPx, aCPy, aX, aY ] } );
30114 
30115 };
30116 
30117 THREE.Path.prototype.bezierCurveTo = function( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
30118 
30119  var lastargs = this.actions[ this.actions.length - 1 ].args;
30120 
30121  var x0 = lastargs[ lastargs.length - 2 ];
30122  var y0 = lastargs[ lastargs.length - 1 ];
30123 
30124  var curve = new THREE.CubicBezierCurve(
30125  new THREE.Vector2( x0, y0 ),
30126  new THREE.Vector2( aCP1x, aCP1y ),
30127  new THREE.Vector2( aCP2x, aCP2y ),
30128  new THREE.Vector2( aX, aY )
30129  );
30130 
30131  this.curves.push( curve );
30132 
30133  this.actions.push( { action: 'bezierCurveTo', args: [ aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ] } );
30134 
30135 };
30136 
30137 THREE.Path.prototype.splineThru = function( pts /*Array of Vector*/ ) {
30138 
30139  var args = Array.prototype.slice.call( arguments );
30140 
30141  var lastargs = this.actions[ this.actions.length - 1 ].args;
30142 
30143  var x0 = lastargs[ lastargs.length - 2 ];
30144  var y0 = lastargs[ lastargs.length - 1 ];
30145 
30146  var npts = [ new THREE.Vector2( x0, y0 ) ];
30147  Array.prototype.push.apply( npts, pts );
30148 
30149  var curve = new THREE.SplineCurve( npts );
30150  this.curves.push( curve );
30151 
30152  this.actions.push( { action: 'splineThru', args: args } );
30153 
30154 };
30155 
30156 // FUTURE: Change the API or follow canvas API?
30157 
30158 THREE.Path.prototype.arc = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
30159 
30160  var lastargs = this.actions[ this.actions.length - 1 ].args;
30161  var x0 = lastargs[ lastargs.length - 2 ];
30162  var y0 = lastargs[ lastargs.length - 1 ];
30163 
30164  this.absarc( aX + x0, aY + y0, aRadius,
30165  aStartAngle, aEndAngle, aClockwise );
30166 
30167  };
30168 
30169  THREE.Path.prototype.absarc = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
30170 
30171  this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
30172 
30173  };
30174 
30175 THREE.Path.prototype.ellipse = function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
30176 
30177  var lastargs = this.actions[ this.actions.length - 1 ].args;
30178  var x0 = lastargs[ lastargs.length - 2 ];
30179  var y0 = lastargs[ lastargs.length - 1 ];
30180 
30181  this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
30182 
30183  };
30184 
30185 
30186 THREE.Path.prototype.absellipse = function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
30187 
30188  var args = [
30189  aX, aY,
30190  xRadius, yRadius,
30191  aStartAngle, aEndAngle,
30192  aClockwise,
30193  aRotation || 0 // aRotation is optional.
30194  ];
30195 
30196  var curve = new THREE.EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
30197  this.curves.push( curve );
30198 
30199  var lastPoint = curve.getPoint( 1 );
30200  args.push( lastPoint.x );
30201  args.push( lastPoint.y );
30202 
30203  this.actions.push( { action: 'ellipse', args: args } );
30204 
30205  };
30206 
30207 THREE.Path.prototype.getSpacedPoints = function ( divisions, closedPath ) {
30208 
30209  if ( ! divisions ) divisions = 40;
30210 
30211  var points = [];
30212 
30213  for ( var i = 0; i < divisions; i ++ ) {
30214 
30215  points.push( this.getPoint( i / divisions ) );
30216 
30217  //if ( !this.getPoint( i / divisions ) ) throw "DIE";
30218 
30219  }
30220 
30221  // if ( closedPath ) {
30222  //
30223  // points.push( points[ 0 ] );
30224  //
30225  // }
30226 
30227  return points;
30228 
30229 };
30230 
30231 /* Return an array of vectors based on contour of the path */
30232 
30233 THREE.Path.prototype.getPoints = function( divisions, closedPath ) {
30234 
30235  divisions = divisions || 12;
30236 
30237  var b2 = THREE.ShapeUtils.b2;
30238  var b3 = THREE.ShapeUtils.b3;
30239 
30240  var points = [];
30241 
30242  var cpx, cpy, cpx2, cpy2, cpx1, cpy1, cpx0, cpy0,
30243  laste, tx, ty;
30244 
30245  for ( var i = 0, l = this.actions.length; i < l; i ++ ) {
30246 
30247  var item = this.actions[ i ];
30248 
30249  var action = item.action;
30250  var args = item.args;
30251 
30252  switch ( action ) {
30253 
30254  case 'moveTo':
30255 
30256  points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
30257 
30258  break;
30259 
30260  case 'lineTo':
30261 
30262  points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
30263 
30264  break;
30265 
30266  case 'quadraticCurveTo':
30267 
30268  cpx = args[ 2 ];
30269  cpy = args[ 3 ];
30270 
30271  cpx1 = args[ 0 ];
30272  cpy1 = args[ 1 ];
30273 
30274  if ( points.length > 0 ) {
30275 
30276  laste = points[ points.length - 1 ];
30277 
30278  cpx0 = laste.x;
30279  cpy0 = laste.y;
30280 
30281  } else {
30282 
30283  laste = this.actions[ i - 1 ].args;
30284 
30285  cpx0 = laste[ laste.length - 2 ];
30286  cpy0 = laste[ laste.length - 1 ];
30287 
30288  }
30289 
30290  for ( var j = 1; j <= divisions; j ++ ) {
30291 
30292  var t = j / divisions;
30293 
30294  tx = b2( t, cpx0, cpx1, cpx );
30295  ty = b2( t, cpy0, cpy1, cpy );
30296 
30297  points.push( new THREE.Vector2( tx, ty ) );
30298 
30299  }
30300 
30301  break;
30302 
30303  case 'bezierCurveTo':
30304 
30305  cpx = args[ 4 ];
30306  cpy = args[ 5 ];
30307 
30308  cpx1 = args[ 0 ];
30309  cpy1 = args[ 1 ];
30310 
30311  cpx2 = args[ 2 ];
30312  cpy2 = args[ 3 ];
30313 
30314  if ( points.length > 0 ) {
30315 
30316  laste = points[ points.length - 1 ];
30317 
30318  cpx0 = laste.x;
30319  cpy0 = laste.y;
30320 
30321  } else {
30322 
30323  laste = this.actions[ i - 1 ].args;
30324 
30325  cpx0 = laste[ laste.length - 2 ];
30326  cpy0 = laste[ laste.length - 1 ];
30327 
30328  }
30329 
30330 
30331  for ( var j = 1; j <= divisions; j ++ ) {
30332 
30333  var t = j / divisions;
30334 
30335  tx = b3( t, cpx0, cpx1, cpx2, cpx );
30336  ty = b3( t, cpy0, cpy1, cpy2, cpy );
30337 
30338  points.push( new THREE.Vector2( tx, ty ) );
30339 
30340  }
30341 
30342  break;
30343 
30344  case 'splineThru':
30345 
30346  laste = this.actions[ i - 1 ].args;
30347 
30348  var last = new THREE.Vector2( laste[ laste.length - 2 ], laste[ laste.length - 1 ] );
30349  var spts = [ last ];
30350 
30351  var n = divisions * args[ 0 ].length;
30352 
30353  spts = spts.concat( args[ 0 ] );
30354 
30355  var spline = new THREE.SplineCurve( spts );
30356 
30357  for ( var j = 1; j <= n; j ++ ) {
30358 
30359  points.push( spline.getPointAt( j / n ) );
30360 
30361  }
30362 
30363  break;
30364 
30365  case 'arc':
30366 
30367  var aX = args[ 0 ], aY = args[ 1 ],
30368  aRadius = args[ 2 ],
30369  aStartAngle = args[ 3 ], aEndAngle = args[ 4 ],
30370  aClockwise = !! args[ 5 ];
30371 
30372  var deltaAngle = aEndAngle - aStartAngle;
30373  var angle;
30374  var tdivisions = divisions * 2;
30375 
30376  for ( var j = 1; j <= tdivisions; j ++ ) {
30377 
30378  var t = j / tdivisions;
30379 
30380  if ( ! aClockwise ) {
30381 
30382  t = 1 - t;
30383 
30384  }
30385 
30386  angle = aStartAngle + t * deltaAngle;
30387 
30388  tx = aX + aRadius * Math.cos( angle );
30389  ty = aY + aRadius * Math.sin( angle );
30390 
30391  //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
30392 
30393  points.push( new THREE.Vector2( tx, ty ) );
30394 
30395  }
30396 
30397  //console.log(points);
30398 
30399  break;
30400 
30401  case 'ellipse':
30402 
30403  var aX = args[ 0 ], aY = args[ 1 ],
30404  xRadius = args[ 2 ],
30405  yRadius = args[ 3 ],
30406  aStartAngle = args[ 4 ], aEndAngle = args[ 5 ],
30407  aClockwise = !! args[ 6 ],
30408  aRotation = args[ 7 ];
30409 
30410 
30411  var deltaAngle = aEndAngle - aStartAngle;
30412  var angle;
30413  var tdivisions = divisions * 2;
30414 
30415  var cos, sin;
30416  if ( aRotation !== 0 ) {
30417 
30418  cos = Math.cos( aRotation );
30419  sin = Math.sin( aRotation );
30420 
30421  }
30422 
30423  for ( var j = 1; j <= tdivisions; j ++ ) {
30424 
30425  var t = j / tdivisions;
30426 
30427  if ( ! aClockwise ) {
30428 
30429  t = 1 - t;
30430 
30431  }
30432 
30433  angle = aStartAngle + t * deltaAngle;
30434 
30435  tx = aX + xRadius * Math.cos( angle );
30436  ty = aY + yRadius * Math.sin( angle );
30437 
30438  if ( aRotation !== 0 ) {
30439 
30440  var x = tx, y = ty;
30441 
30442  // Rotate the point about the center of the ellipse.
30443  tx = ( x - aX ) * cos - ( y - aY ) * sin + aX;
30444  ty = ( x - aX ) * sin + ( y - aY ) * cos + aY;
30445 
30446  }
30447 
30448  //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
30449 
30450  points.push( new THREE.Vector2( tx, ty ) );
30451 
30452  }
30453 
30454  //console.log(points);
30455 
30456  break;
30457 
30458  } // end switch
30459 
30460  }
30461 
30462 
30463 
30464  // Normalize to remove the closing point by default.
30465  var lastPoint = points[ points.length - 1 ];
30466  if ( Math.abs( lastPoint.x - points[ 0 ].x ) < Number.EPSILON &&
30467  Math.abs( lastPoint.y - points[ 0 ].y ) < Number.EPSILON )
30468  points.splice( points.length - 1, 1 );
30469  if ( closedPath ) {
30470 
30471  points.push( points[ 0 ] );
30472 
30473  }
30474 
30475  return points;
30476 
30477 };
30478 
30479 //
30480 // Breaks path into shapes
30481 //
30482 // Assumptions (if parameter isCCW==true the opposite holds):
30483 // - solid shapes are defined clockwise (CW)
30484 // - holes are defined counterclockwise (CCW)
30485 //
30486 // If parameter noHoles==true:
30487 // - all subPaths are regarded as solid shapes
30488 // - definition order CW/CCW has no relevance
30489 //
30490 
30491 THREE.Path.prototype.toShapes = function( isCCW, noHoles ) {
30492 
30493  function extractSubpaths( inActions ) {
30494 
30495  var subPaths = [], lastPath = new THREE.Path();
30496 
30497  for ( var i = 0, l = inActions.length; i < l; i ++ ) {
30498 
30499  var item = inActions[ i ];
30500 
30501  var args = item.args;
30502  var action = item.action;
30503 
30504  if ( action === 'moveTo' ) {
30505 
30506  if ( lastPath.actions.length !== 0 ) {
30507 
30508  subPaths.push( lastPath );
30509  lastPath = new THREE.Path();
30510 
30511  }
30512 
30513  }
30514 
30515  lastPath[ action ].apply( lastPath, args );
30516 
30517  }
30518 
30519  if ( lastPath.actions.length !== 0 ) {
30520 
30521  subPaths.push( lastPath );
30522 
30523  }
30524 
30525  // console.log(subPaths);
30526 
30527  return subPaths;
30528 
30529  }
30530 
30531  function toShapesNoHoles( inSubpaths ) {
30532 
30533  var shapes = [];
30534 
30535  for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) {
30536 
30537  var tmpPath = inSubpaths[ i ];
30538 
30539  var tmpShape = new THREE.Shape();
30540  tmpShape.actions = tmpPath.actions;
30541  tmpShape.curves = tmpPath.curves;
30542 
30543  shapes.push( tmpShape );
30544 
30545  }
30546 
30547  //console.log("shape", shapes);
30548 
30549  return shapes;
30550 
30551  }
30552 
30553  function isPointInsidePolygon( inPt, inPolygon ) {
30554 
30555  var polyLen = inPolygon.length;
30556 
30557  // inPt on polygon contour => immediate success or
30558  // toggling of inside/outside at every single! intersection point of an edge
30559  // with the horizontal line through inPt, left of inPt
30560  // not counting lowerY endpoints of edges and whole edges on that line
30561  var inside = false;
30562  for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
30563 
30564  var edgeLowPt = inPolygon[ p ];
30565  var edgeHighPt = inPolygon[ q ];
30566 
30567  var edgeDx = edgeHighPt.x - edgeLowPt.x;
30568  var edgeDy = edgeHighPt.y - edgeLowPt.y;
30569 
30570  if ( Math.abs( edgeDy ) > Number.EPSILON ) {
30571 
30572  // not parallel
30573  if ( edgeDy < 0 ) {
30574 
30575  edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
30576  edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
30577 
30578  }
30579  if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue;
30580 
30581  if ( inPt.y === edgeLowPt.y ) {
30582 
30583  if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ?
30584  // continue; // no intersection or edgeLowPt => doesn't count !!!
30585 
30586  } else {
30587 
30588  var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
30589  if ( perpEdge === 0 ) return true; // inPt is on contour ?
30590  if ( perpEdge < 0 ) continue;
30591  inside = ! inside; // true intersection left of inPt
30592 
30593  }
30594 
30595  } else {
30596 
30597  // parallel or collinear
30598  if ( inPt.y !== edgeLowPt.y ) continue; // parallel
30599  // edge lies on the same horizontal line as inPt
30600  if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
30601  ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour !
30602  // continue;
30603 
30604  }
30605 
30606  }
30607 
30608  return inside;
30609 
30610  }
30611 
30612  var isClockWise = THREE.ShapeUtils.isClockWise;
30613 
30614  var subPaths = extractSubpaths( this.actions );
30615  if ( subPaths.length === 0 ) return [];
30616 
30617  if ( noHoles === true ) return toShapesNoHoles( subPaths );
30618 
30619 
30620  var solid, tmpPath, tmpShape, shapes = [];
30621 
30622  if ( subPaths.length === 1 ) {
30623 
30624  tmpPath = subPaths[ 0 ];
30625  tmpShape = new THREE.Shape();
30626  tmpShape.actions = tmpPath.actions;
30627  tmpShape.curves = tmpPath.curves;
30628  shapes.push( tmpShape );
30629  return shapes;
30630 
30631  }
30632 
30633  var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
30634  holesFirst = isCCW ? ! holesFirst : holesFirst;
30635 
30636  // console.log("Holes first", holesFirst);
30637 
30638  var betterShapeHoles = [];
30639  var newShapes = [];
30640  var newShapeHoles = [];
30641  var mainIdx = 0;
30642  var tmpPoints;
30643 
30644  newShapes[ mainIdx ] = undefined;
30645  newShapeHoles[ mainIdx ] = [];
30646 
30647  for ( var i = 0, l = subPaths.length; i < l; i ++ ) {
30648 
30649  tmpPath = subPaths[ i ];
30650  tmpPoints = tmpPath.getPoints();
30651  solid = isClockWise( tmpPoints );
30652  solid = isCCW ? ! solid : solid;
30653 
30654  if ( solid ) {
30655 
30656  if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++;
30657 
30658  newShapes[ mainIdx ] = { s: new THREE.Shape(), p: tmpPoints };
30659  newShapes[ mainIdx ].s.actions = tmpPath.actions;
30660  newShapes[ mainIdx ].s.curves = tmpPath.curves;
30661 
30662  if ( holesFirst ) mainIdx ++;
30663  newShapeHoles[ mainIdx ] = [];
30664 
30665  //console.log('cw', i);
30666 
30667  } else {
30668 
30669  newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
30670 
30671  //console.log('ccw', i);
30672 
30673  }
30674 
30675  }
30676 
30677  // only Holes? -> probably all Shapes with wrong orientation
30678  if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths );
30679 
30680 
30681  if ( newShapes.length > 1 ) {
30682 
30683  var ambiguous = false;
30684  var toChange = [];
30685 
30686  for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
30687 
30688  betterShapeHoles[ sIdx ] = [];
30689 
30690  }
30691 
30692  for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
30693 
30694  var sho = newShapeHoles[ sIdx ];
30695 
30696  for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
30697 
30698  var ho = sho[ hIdx ];
30699  var hole_unassigned = true;
30700 
30701  for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
30702 
30703  if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
30704 
30705  if ( sIdx !== s2Idx ) toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
30706  if ( hole_unassigned ) {
30707 
30708  hole_unassigned = false;
30709  betterShapeHoles[ s2Idx ].push( ho );
30710 
30711  } else {
30712 
30713  ambiguous = true;
30714 
30715  }
30716 
30717  }
30718 
30719  }
30720  if ( hole_unassigned ) {
30721 
30722  betterShapeHoles[ sIdx ].push( ho );
30723 
30724  }
30725 
30726  }
30727 
30728  }
30729  // console.log("ambiguous: ", ambiguous);
30730  if ( toChange.length > 0 ) {
30731 
30732  // console.log("to change: ", toChange);
30733  if ( ! ambiguous ) newShapeHoles = betterShapeHoles;
30734 
30735  }
30736 
30737  }
30738 
30739  var tmpHoles;
30740 
30741  for ( var i = 0, il = newShapes.length; i < il; i ++ ) {
30742 
30743  tmpShape = newShapes[ i ].s;
30744  shapes.push( tmpShape );
30745  tmpHoles = newShapeHoles[ i ];
30746 
30747  for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
30748 
30749  tmpShape.holes.push( tmpHoles[ j ].h );
30750 
30751  }
30752 
30753  }
30754 
30755  //console.log("shape", shapes);
30756 
30757  return shapes;
30758 
30759 };
30760 
30761 // File:src/extras/core/Shape.js
30762 
30768 // STEP 1 Create a path.
30769 // STEP 2 Turn path into shape.
30770 // STEP 3 ExtrudeGeometry takes in Shape/Shapes
30771 // STEP 3a - Extract points from each shape, turn to vertices
30772 // STEP 3b - Triangulate each shape, add faces.
30773 
30774 THREE.Shape = function () {
30775 
30776  THREE.Path.apply( this, arguments );
30777 
30778  this.holes = [];
30779 
30780 };
30781 
30782 THREE.Shape.prototype = Object.create( THREE.Path.prototype );
30783 THREE.Shape.prototype.constructor = THREE.Shape;
30784 
30785 // Convenience method to return ExtrudeGeometry
30786 
30787 THREE.Shape.prototype.extrude = function ( options ) {
30788 
30789  return new THREE.ExtrudeGeometry( this, options );
30790 
30791 };
30792 
30793 // Convenience method to return ShapeGeometry
30794 
30795 THREE.Shape.prototype.makeGeometry = function ( options ) {
30796 
30797  return new THREE.ShapeGeometry( this, options );
30798 
30799 };
30800 
30801 // Get points of holes
30802 
30803 THREE.Shape.prototype.getPointsHoles = function ( divisions ) {
30804 
30805  var holesPts = [];
30806 
30807  for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
30808 
30809  holesPts[ i ] = this.holes[ i ].getPoints( divisions );
30810 
30811  }
30812 
30813  return holesPts;
30814 
30815 };
30816 
30817 
30818 // Get points of shape and holes (keypoints based on segments parameter)
30819 
30820 THREE.Shape.prototype.extractAllPoints = function ( divisions ) {
30821 
30822  return {
30823 
30824  shape: this.getPoints( divisions ),
30825  holes: this.getPointsHoles( divisions )
30826 
30827  };
30828 
30829 };
30830 
30831 THREE.Shape.prototype.extractPoints = function ( divisions ) {
30832 
30833  return this.extractAllPoints( divisions );
30834 
30835 };
30836 
30837 THREE.Shape.Utils = THREE.ShapeUtils; // backwards compatibility
30838 
30839 // File:src/extras/curves/LineCurve.js
30840 
30841 /**************************************************************
30842  * Line
30843  **************************************************************/
30844 
30845 THREE.LineCurve = function ( v1, v2 ) {
30846 
30847  this.v1 = v1;
30848  this.v2 = v2;
30849 
30850 };
30851 
30852 THREE.LineCurve.prototype = Object.create( THREE.Curve.prototype );
30853 THREE.LineCurve.prototype.constructor = THREE.LineCurve;
30854 
30855 THREE.LineCurve.prototype.getPoint = function ( t ) {
30856 
30857  var point = this.v2.clone().sub( this.v1 );
30858  point.multiplyScalar( t ).add( this.v1 );
30859 
30860  return point;
30861 
30862 };
30863 
30864 // Line curve is linear, so we can overwrite default getPointAt
30865 
30866 THREE.LineCurve.prototype.getPointAt = function ( u ) {
30867 
30868  return this.getPoint( u );
30869 
30870 };
30871 
30872 THREE.LineCurve.prototype.getTangent = function( t ) {
30873 
30874  var tangent = this.v2.clone().sub( this.v1 );
30875 
30876  return tangent.normalize();
30877 
30878 };
30879 
30880 // File:src/extras/curves/QuadraticBezierCurve.js
30881 
30882 /**************************************************************
30883  * Quadratic Bezier curve
30884  **************************************************************/
30885 
30886 
30887 THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) {
30888 
30889  this.v0 = v0;
30890  this.v1 = v1;
30891  this.v2 = v2;
30892 
30893 };
30894 
30895 THREE.QuadraticBezierCurve.prototype = Object.create( THREE.Curve.prototype );
30896 THREE.QuadraticBezierCurve.prototype.constructor = THREE.QuadraticBezierCurve;
30897 
30898 
30899 THREE.QuadraticBezierCurve.prototype.getPoint = function ( t ) {
30900 
30901  var b2 = THREE.ShapeUtils.b2;
30902 
30903  return new THREE.Vector2(
30904  b2( t, this.v0.x, this.v1.x, this.v2.x ),
30905  b2( t, this.v0.y, this.v1.y, this.v2.y )
30906  );
30907 
30908 };
30909 
30910 
30911 THREE.QuadraticBezierCurve.prototype.getTangent = function( t ) {
30912 
30913  var tangentQuadraticBezier = THREE.CurveUtils.tangentQuadraticBezier;
30914 
30915  return new THREE.Vector2(
30916  tangentQuadraticBezier( t, this.v0.x, this.v1.x, this.v2.x ),
30917  tangentQuadraticBezier( t, this.v0.y, this.v1.y, this.v2.y )
30918  ).normalize();
30919 
30920 };
30921 
30922 // File:src/extras/curves/CubicBezierCurve.js
30923 
30924 /**************************************************************
30925  * Cubic Bezier curve
30926  **************************************************************/
30927 
30928 THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
30929 
30930  this.v0 = v0;
30931  this.v1 = v1;
30932  this.v2 = v2;
30933  this.v3 = v3;
30934 
30935 };
30936 
30937 THREE.CubicBezierCurve.prototype = Object.create( THREE.Curve.prototype );
30938 THREE.CubicBezierCurve.prototype.constructor = THREE.CubicBezierCurve;
30939 
30940 THREE.CubicBezierCurve.prototype.getPoint = function ( t ) {
30941 
30942  var b3 = THREE.ShapeUtils.b3;
30943 
30944  return new THREE.Vector2(
30945  b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x ),
30946  b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y )
30947  );
30948 
30949 };
30950 
30951 THREE.CubicBezierCurve.prototype.getTangent = function( t ) {
30952 
30953  var tangentCubicBezier = THREE.CurveUtils.tangentCubicBezier;
30954 
30955  return new THREE.Vector2(
30956  tangentCubicBezier( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x ),
30957  tangentCubicBezier( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y )
30958  ).normalize();
30959 
30960 };
30961 
30962 // File:src/extras/curves/SplineCurve.js
30963 
30964 /**************************************************************
30965  * Spline curve
30966  **************************************************************/
30967 
30968 THREE.SplineCurve = function ( points /* array of Vector2 */ ) {
30969 
30970  this.points = ( points == undefined ) ? [] : points;
30971 
30972 };
30973 
30974 THREE.SplineCurve.prototype = Object.create( THREE.Curve.prototype );
30975 THREE.SplineCurve.prototype.constructor = THREE.SplineCurve;
30976 
30977 THREE.SplineCurve.prototype.getPoint = function ( t ) {
30978 
30979  var points = this.points;
30980  var point = ( points.length - 1 ) * t;
30981 
30982  var intPoint = Math.floor( point );
30983  var weight = point - intPoint;
30984 
30985  var point0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
30986  var point1 = points[ intPoint ];
30987  var point2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
30988  var point3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
30989 
30990  var interpolate = THREE.CurveUtils.interpolate;
30991 
30992  return new THREE.Vector2(
30993  interpolate( point0.x, point1.x, point2.x, point3.x, weight ),
30994  interpolate( point0.y, point1.y, point2.y, point3.y, weight )
30995  );
30996 
30997 };
30998 
30999 // File:src/extras/curves/EllipseCurve.js
31000 
31001 /**************************************************************
31002  * Ellipse curve
31003  **************************************************************/
31004 
31005 THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
31006 
31007  this.aX = aX;
31008  this.aY = aY;
31009 
31010  this.xRadius = xRadius;
31011  this.yRadius = yRadius;
31012 
31013  this.aStartAngle = aStartAngle;
31014  this.aEndAngle = aEndAngle;
31015 
31016  this.aClockwise = aClockwise;
31017 
31018  this.aRotation = aRotation || 0;
31019 
31020 };
31021 
31022 THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype );
31023 THREE.EllipseCurve.prototype.constructor = THREE.EllipseCurve;
31024 
31025 THREE.EllipseCurve.prototype.getPoint = function ( t ) {
31026 
31027  var deltaAngle = this.aEndAngle - this.aStartAngle;
31028 
31029  if ( deltaAngle < 0 ) deltaAngle += Math.PI * 2;
31030  if ( deltaAngle > Math.PI * 2 ) deltaAngle -= Math.PI * 2;
31031 
31032  var angle;
31033 
31034  if ( this.aClockwise === true ) {
31035 
31036  angle = this.aEndAngle + ( 1 - t ) * ( Math.PI * 2 - deltaAngle );
31037 
31038  } else {
31039 
31040  angle = this.aStartAngle + t * deltaAngle;
31041 
31042  }
31043 
31044  var x = this.aX + this.xRadius * Math.cos( angle );
31045  var y = this.aY + this.yRadius * Math.sin( angle );
31046 
31047  if ( this.aRotation !== 0 ) {
31048 
31049  var cos = Math.cos( this.aRotation );
31050  var sin = Math.sin( this.aRotation );
31051 
31052  var tx = x, ty = y;
31053 
31054  // Rotate the point about the center of the ellipse.
31055  x = ( tx - this.aX ) * cos - ( ty - this.aY ) * sin + this.aX;
31056  y = ( tx - this.aX ) * sin + ( ty - this.aY ) * cos + this.aY;
31057 
31058  }
31059 
31060  return new THREE.Vector2( x, y );
31061 
31062 };
31063 
31064 // File:src/extras/curves/ArcCurve.js
31065 
31066 /**************************************************************
31067  * Arc curve
31068  **************************************************************/
31069 
31070 THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
31071 
31072  THREE.EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
31073 
31074 };
31075 
31076 THREE.ArcCurve.prototype = Object.create( THREE.EllipseCurve.prototype );
31077 THREE.ArcCurve.prototype.constructor = THREE.ArcCurve;
31078 
31079 // File:src/extras/curves/LineCurve3.js
31080 
31081 /**************************************************************
31082  * Line3D
31083  **************************************************************/
31084 
31085 THREE.LineCurve3 = THREE.Curve.create(
31086 
31087  function ( v1, v2 ) {
31088 
31089  this.v1 = v1;
31090  this.v2 = v2;
31091 
31092  },
31093 
31094  function ( t ) {
31095 
31096  var vector = new THREE.Vector3();
31097 
31098  vector.subVectors( this.v2, this.v1 ); // diff
31099  vector.multiplyScalar( t );
31100  vector.add( this.v1 );
31101 
31102  return vector;
31103 
31104  }
31105 
31106 );
31107 
31108 // File:src/extras/curves/QuadraticBezierCurve3.js
31109 
31110 /**************************************************************
31111  * Quadratic Bezier 3D curve
31112  **************************************************************/
31113 
31114 THREE.QuadraticBezierCurve3 = THREE.Curve.create(
31115 
31116  function ( v0, v1, v2 ) {
31117 
31118  this.v0 = v0;
31119  this.v1 = v1;
31120  this.v2 = v2;
31121 
31122  },
31123 
31124  function ( t ) {
31125 
31126  var b2 = THREE.ShapeUtils.b2;
31127 
31128  return new THREE.Vector3(
31129  b2( t, this.v0.x, this.v1.x, this.v2.x ),
31130  b2( t, this.v0.y, this.v1.y, this.v2.y ),
31131  b2( t, this.v0.z, this.v1.z, this.v2.z )
31132  );
31133 
31134  }
31135 
31136 );
31137 
31138 // File:src/extras/curves/CubicBezierCurve3.js
31139 
31140 /**************************************************************
31141  * Cubic Bezier 3D curve
31142  **************************************************************/
31143 
31144 THREE.CubicBezierCurve3 = THREE.Curve.create(
31145 
31146  function ( v0, v1, v2, v3 ) {
31147 
31148  this.v0 = v0;
31149  this.v1 = v1;
31150  this.v2 = v2;
31151  this.v3 = v3;
31152 
31153  },
31154 
31155  function ( t ) {
31156 
31157  var b3 = THREE.ShapeUtils.b3;
31158 
31159  return new THREE.Vector3(
31160  b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x ),
31161  b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y ),
31162  b3( t, this.v0.z, this.v1.z, this.v2.z, this.v3.z )
31163  );
31164 
31165  }
31166 
31167 );
31168 
31169 // File:src/extras/curves/SplineCurve3.js
31170 
31171 /**************************************************************
31172  * Spline 3D curve
31173  **************************************************************/
31174 
31175 
31176 THREE.SplineCurve3 = THREE.Curve.create(
31177 
31178  function ( points /* array of Vector3 */ ) {
31179 
31180  console.warn( 'THREE.SplineCurve3 will be deprecated. Please use THREE.CatmullRomCurve3' );
31181  this.points = ( points == undefined ) ? [] : points;
31182 
31183  },
31184 
31185  function ( t ) {
31186 
31187  var points = this.points;
31188  var point = ( points.length - 1 ) * t;
31189 
31190  var intPoint = Math.floor( point );
31191  var weight = point - intPoint;
31192 
31193  var point0 = points[ intPoint == 0 ? intPoint : intPoint - 1 ];
31194  var point1 = points[ intPoint ];
31195  var point2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
31196  var point3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
31197 
31198  var interpolate = THREE.CurveUtils.interpolate;
31199 
31200  return new THREE.Vector3(
31201  interpolate( point0.x, point1.x, point2.x, point3.x, weight ),
31202  interpolate( point0.y, point1.y, point2.y, point3.y, weight ),
31203  interpolate( point0.z, point1.z, point2.z, point3.z, weight )
31204  );
31205 
31206  }
31207 
31208 );
31209 
31210 // File:src/extras/curves/CatmullRomCurve3.js
31211 
31223 THREE.CatmullRomCurve3 = ( function() {
31224 
31225  var
31226  tmp = new THREE.Vector3(),
31227  px = new CubicPoly(),
31228  py = new CubicPoly(),
31229  pz = new CubicPoly();
31230 
31231  /*
31232  Based on an optimized c++ solution in
31233  - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
31234  - http://ideone.com/NoEbVM
31235 
31236  This CubicPoly class could be used for reusing some variables and calculations,
31237  but for three.js curve use, it could be possible inlined and flatten into a single function call
31238  which can be placed in CurveUtils.
31239  */
31240 
31241  function CubicPoly() {
31242 
31243  }
31244 
31245  /*
31246  * Compute coefficients for a cubic polynomial
31247  * p(s) = c0 + c1*s + c2*s^2 + c3*s^3
31248  * such that
31249  * p(0) = x0, p(1) = x1
31250  * and
31251  * p'(0) = t0, p'(1) = t1.
31252  */
31253  CubicPoly.prototype.init = function( x0, x1, t0, t1 ) {
31254 
31255  this.c0 = x0;
31256  this.c1 = t0;
31257  this.c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
31258  this.c3 = 2 * x0 - 2 * x1 + t0 + t1;
31259 
31260  };
31261 
31262  CubicPoly.prototype.initNonuniformCatmullRom = function( x0, x1, x2, x3, dt0, dt1, dt2 ) {
31263 
31264  // compute tangents when parameterized in [t1,t2]
31265  var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
31266  var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
31267 
31268  // rescale tangents for parametrization in [0,1]
31269  t1 *= dt1;
31270  t2 *= dt1;
31271 
31272  // initCubicPoly
31273  this.init( x1, x2, t1, t2 );
31274 
31275  };
31276 
31277  // standard Catmull-Rom spline: interpolate between x1 and x2 with previous/following points x1/x4
31278  CubicPoly.prototype.initCatmullRom = function( x0, x1, x2, x3, tension ) {
31279 
31280  this.init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
31281 
31282  };
31283 
31284  CubicPoly.prototype.calc = function( t ) {
31285 
31286  var t2 = t * t;
31287  var t3 = t2 * t;
31288  return this.c0 + this.c1 * t + this.c2 * t2 + this.c3 * t3;
31289 
31290  };
31291 
31292  // Subclass Three.js curve
31293  return THREE.Curve.create(
31294 
31295  function ( p /* array of Vector3 */ ) {
31296 
31297  this.points = p || [];
31298 
31299  },
31300 
31301  function ( t ) {
31302 
31303  var points = this.points,
31304  point, intPoint, weight, l;
31305 
31306  l = points.length;
31307 
31308  if ( l < 2 ) console.log( 'duh, you need at least 2 points' );
31309 
31310  point = ( l - 1 ) * t;
31311  intPoint = Math.floor( point );
31312  weight = point - intPoint;
31313 
31314  if ( weight === 0 && intPoint === l - 1 ) {
31315 
31316  intPoint = l - 2;
31317  weight = 1;
31318 
31319  }
31320 
31321  var p0, p1, p2, p3;
31322 
31323  if ( intPoint === 0 ) {
31324 
31325  // extrapolate first point
31326  tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
31327  p0 = tmp;
31328 
31329  } else {
31330 
31331  p0 = points[ intPoint - 1 ];
31332 
31333  }
31334 
31335  p1 = points[ intPoint ];
31336  p2 = points[ intPoint + 1 ];
31337 
31338  if ( intPoint + 2 < l ) {
31339 
31340  p3 = points[ intPoint + 2 ]
31341 
31342  } else {
31343 
31344  // extrapolate last point
31345  tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 2 ] );
31346  p3 = tmp;
31347 
31348  }
31349 
31350  if ( this.type === undefined || this.type === 'centripetal' || this.type === 'chordal' ) {
31351 
31352  // init Centripetal / Chordal Catmull-Rom
31353  var pow = this.type === 'chordal' ? 0.5 : 0.25;
31354  var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
31355  var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
31356  var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
31357 
31358  // safety check for repeated points
31359  if ( dt1 < 1e-4 ) dt1 = 1.0;
31360  if ( dt0 < 1e-4 ) dt0 = dt1;
31361  if ( dt2 < 1e-4 ) dt2 = dt1;
31362 
31363  px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
31364  py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
31365  pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
31366 
31367  } else if ( this.type === 'catmullrom' ) {
31368 
31369  var tension = this.tension !== undefined ? this.tension : 0.5;
31370  px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, tension );
31371  py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, tension );
31372  pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, tension );
31373 
31374  }
31375 
31376  var v = new THREE.Vector3(
31377  px.calc( weight ),
31378  py.calc( weight ),
31379  pz.calc( weight )
31380  );
31381 
31382  return v;
31383 
31384  }
31385 
31386  );
31387 
31388 } )();
31389 
31390 // File:src/extras/curves/ClosedSplineCurve3.js
31391 
31392 /**************************************************************
31393  * Closed Spline 3D curve
31394  **************************************************************/
31395 
31396 
31397 THREE.ClosedSplineCurve3 = THREE.Curve.create(
31398 
31399  function ( points /* array of Vector3 */ ) {
31400 
31401  this.points = ( points == undefined ) ? [] : points;
31402 
31403  },
31404 
31405  function ( t ) {
31406 
31407  var points = this.points;
31408  var point = ( points.length - 0 ) * t; // This needs to be from 0-length +1
31409 
31410  var intPoint = Math.floor( point );
31411  var weight = point - intPoint;
31412 
31413  intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length;
31414 
31415  var point0 = points[ ( intPoint - 1 ) % points.length ];
31416  var point1 = points[ ( intPoint ) % points.length ];
31417  var point2 = points[ ( intPoint + 1 ) % points.length ];
31418  var point3 = points[ ( intPoint + 2 ) % points.length ];
31419 
31420  var interpolate = THREE.CurveUtils.interpolate;
31421 
31422  return new THREE.Vector3(
31423  interpolate( point0.x, point1.x, point2.x, point3.x, weight ),
31424  interpolate( point0.y, point1.y, point2.y, point3.y, weight ),
31425  interpolate( point0.z, point1.z, point2.z, point3.z, weight )
31426  );
31427 
31428  }
31429 
31430 );
31431 
31432 // File:src/extras/geometries/BoxGeometry.js
31433 
31439 THREE.BoxGeometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {
31440 
31441  THREE.Geometry.call( this );
31442 
31443  this.type = 'BoxGeometry';
31444 
31445  this.parameters = {
31446  width: width,
31447  height: height,
31448  depth: depth,
31449  widthSegments: widthSegments,
31450  heightSegments: heightSegments,
31451  depthSegments: depthSegments
31452  };
31453 
31454  this.widthSegments = widthSegments || 1;
31455  this.heightSegments = heightSegments || 1;
31456  this.depthSegments = depthSegments || 1;
31457 
31458  var scope = this;
31459 
31460  var width_half = width / 2;
31461  var height_half = height / 2;
31462  var depth_half = depth / 2;
31463 
31464  buildPlane( 'z', 'y', - 1, - 1, depth, height, width_half, 0 ); // px
31465  buildPlane( 'z', 'y', 1, - 1, depth, height, - width_half, 1 ); // nx
31466  buildPlane( 'x', 'z', 1, 1, width, depth, height_half, 2 ); // py
31467  buildPlane( 'x', 'z', 1, - 1, width, depth, - height_half, 3 ); // ny
31468  buildPlane( 'x', 'y', 1, - 1, width, height, depth_half, 4 ); // pz
31469  buildPlane( 'x', 'y', - 1, - 1, width, height, - depth_half, 5 ); // nz
31470 
31471  function buildPlane( u, v, udir, vdir, width, height, depth, materialIndex ) {
31472 
31473  var w, ix, iy,
31474  gridX = scope.widthSegments,
31475  gridY = scope.heightSegments,
31476  width_half = width / 2,
31477  height_half = height / 2,
31478  offset = scope.vertices.length;
31479 
31480  if ( ( u === 'x' && v === 'y' ) || ( u === 'y' && v === 'x' ) ) {
31481 
31482  w = 'z';
31483 
31484  } else if ( ( u === 'x' && v === 'z' ) || ( u === 'z' && v === 'x' ) ) {
31485 
31486  w = 'y';
31487  gridY = scope.depthSegments;
31488 
31489  } else if ( ( u === 'z' && v === 'y' ) || ( u === 'y' && v === 'z' ) ) {
31490 
31491  w = 'x';
31492  gridX = scope.depthSegments;
31493 
31494  }
31495 
31496  var gridX1 = gridX + 1,
31497  gridY1 = gridY + 1,
31498  segment_width = width / gridX,
31499  segment_height = height / gridY,
31500  normal = new THREE.Vector3();
31501 
31502  normal[ w ] = depth > 0 ? 1 : - 1;
31503 
31504  for ( iy = 0; iy < gridY1; iy ++ ) {
31505 
31506  for ( ix = 0; ix < gridX1; ix ++ ) {
31507 
31508  var vector = new THREE.Vector3();
31509  vector[ u ] = ( ix * segment_width - width_half ) * udir;
31510  vector[ v ] = ( iy * segment_height - height_half ) * vdir;
31511  vector[ w ] = depth;
31512 
31513  scope.vertices.push( vector );
31514 
31515  }
31516 
31517  }
31518 
31519  for ( iy = 0; iy < gridY; iy ++ ) {
31520 
31521  for ( ix = 0; ix < gridX; ix ++ ) {
31522 
31523  var a = ix + gridX1 * iy;
31524  var b = ix + gridX1 * ( iy + 1 );
31525  var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
31526  var d = ( ix + 1 ) + gridX1 * iy;
31527 
31528  var uva = new THREE.Vector2( ix / gridX, 1 - iy / gridY );
31529  var uvb = new THREE.Vector2( ix / gridX, 1 - ( iy + 1 ) / gridY );
31530  var uvc = new THREE.Vector2( ( ix + 1 ) / gridX, 1 - ( iy + 1 ) / gridY );
31531  var uvd = new THREE.Vector2( ( ix + 1 ) / gridX, 1 - iy / gridY );
31532 
31533  var face = new THREE.Face3( a + offset, b + offset, d + offset );
31534  face.normal.copy( normal );
31535  face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
31536  face.materialIndex = materialIndex;
31537 
31538  scope.faces.push( face );
31539  scope.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );
31540 
31541  face = new THREE.Face3( b + offset, c + offset, d + offset );
31542  face.normal.copy( normal );
31543  face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
31544  face.materialIndex = materialIndex;
31545 
31546  scope.faces.push( face );
31547  scope.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );
31548 
31549  }
31550 
31551  }
31552 
31553  }
31554 
31555  this.mergeVertices();
31556 
31557 };
31558 
31559 THREE.BoxGeometry.prototype = Object.create( THREE.Geometry.prototype );
31560 THREE.BoxGeometry.prototype.constructor = THREE.BoxGeometry;
31561 
31562 THREE.BoxGeometry.prototype.clone = function () {
31563 
31564  var parameters = this.parameters;
31565 
31566  return new THREE.BoxGeometry(
31567  parameters.width,
31568  parameters.height,
31569  parameters.depth,
31570  parameters.widthSegments,
31571  parameters.heightSegments,
31572  parameters.depthSegments
31573  );
31574 
31575 };
31576 
31577 THREE.CubeGeometry = THREE.BoxGeometry; // backwards compatibility
31578 
31579 // File:src/extras/geometries/CircleGeometry.js
31580 
31585 THREE.CircleGeometry = function ( radius, segments, thetaStart, thetaLength ) {
31586 
31587  THREE.Geometry.call( this );
31588 
31589  this.type = 'CircleGeometry';
31590 
31591  this.parameters = {
31592  radius: radius,
31593  segments: segments,
31594  thetaStart: thetaStart,
31595  thetaLength: thetaLength
31596  };
31597 
31598  this.fromBufferGeometry( new THREE.CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );
31599 
31600 };
31601 
31602 THREE.CircleGeometry.prototype = Object.create( THREE.Geometry.prototype );
31603 THREE.CircleGeometry.prototype.constructor = THREE.CircleGeometry;
31604 
31605 THREE.CircleGeometry.prototype.clone = function () {
31606 
31607  var parameters = this.parameters;
31608 
31609  return new THREE.CircleGeometry(
31610  parameters.radius,
31611  parameters.segments,
31612  parameters.thetaStart,
31613  parameters.thetaLength
31614  );
31615 
31616 };
31617 
31618 // File:src/extras/geometries/CircleBufferGeometry.js
31619 
31624 THREE.CircleBufferGeometry = function ( radius, segments, thetaStart, thetaLength ) {
31625 
31626  THREE.BufferGeometry.call( this );
31627 
31628  this.type = 'CircleBufferGeometry';
31629 
31630  this.parameters = {
31631  radius: radius,
31632  segments: segments,
31633  thetaStart: thetaStart,
31634  thetaLength: thetaLength
31635  };
31636 
31637  radius = radius || 50;
31638  segments = segments !== undefined ? Math.max( 3, segments ) : 8;
31639 
31640  thetaStart = thetaStart !== undefined ? thetaStart : 0;
31641  thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
31642 
31643  var vertices = segments + 2;
31644 
31645  var positions = new Float32Array( vertices * 3 );
31646  var normals = new Float32Array( vertices * 3 );
31647  var uvs = new Float32Array( vertices * 2 );
31648 
31649  // center data is already zero, but need to set a few extras
31650  normals[ 2 ] = 1.0;
31651  uvs[ 0 ] = 0.5;
31652  uvs[ 1 ] = 0.5;
31653 
31654  for ( var s = 0, i = 3, ii = 2 ; s <= segments; s ++, i += 3, ii += 2 ) {
31655 
31656  var segment = thetaStart + s / segments * thetaLength;
31657 
31658  positions[ i ] = radius * Math.cos( segment );
31659  positions[ i + 1 ] = radius * Math.sin( segment );
31660 
31661  normals[ i + 2 ] = 1; // normal z
31662 
31663  uvs[ ii ] = ( positions[ i ] / radius + 1 ) / 2;
31664  uvs[ ii + 1 ] = ( positions[ i + 1 ] / radius + 1 ) / 2;
31665 
31666  }
31667 
31668  var indices = [];
31669 
31670  for ( var i = 1; i <= segments; i ++ ) {
31671 
31672  indices.push( i, i + 1, 0 );
31673 
31674  }
31675 
31676  this.setIndex( new THREE.BufferAttribute( new Uint16Array( indices ), 1 ) );
31677  this.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
31678  this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
31679  this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
31680 
31681  this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
31682 
31683 };
31684 
31685 THREE.CircleBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
31686 THREE.CircleBufferGeometry.prototype.constructor = THREE.CircleBufferGeometry;
31687 
31688 THREE.CircleBufferGeometry.prototype.clone = function () {
31689 
31690  var parameters = this.parameters;
31691 
31692  return new THREE.CircleBufferGeometry(
31693  parameters.radius,
31694  parameters.segments,
31695  parameters.thetaStart,
31696  parameters.thetaLength
31697  );
31698 
31699 };
31700 
31701 // File:src/extras/geometries/CylinderGeometry.js
31702 
31707 THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
31708 
31709  THREE.Geometry.call( this );
31710 
31711  this.type = 'CylinderGeometry';
31712 
31713  this.parameters = {
31714  radiusTop: radiusTop,
31715  radiusBottom: radiusBottom,
31716  height: height,
31717  radialSegments: radialSegments,
31718  heightSegments: heightSegments,
31719  openEnded: openEnded,
31720  thetaStart: thetaStart,
31721  thetaLength: thetaLength
31722  };
31723 
31724  radiusTop = radiusTop !== undefined ? radiusTop : 20;
31725  radiusBottom = radiusBottom !== undefined ? radiusBottom : 20;
31726  height = height !== undefined ? height : 100;
31727 
31728  radialSegments = radialSegments || 8;
31729  heightSegments = heightSegments || 1;
31730 
31731  openEnded = openEnded !== undefined ? openEnded : false;
31732  thetaStart = thetaStart !== undefined ? thetaStart : 0;
31733  thetaLength = thetaLength !== undefined ? thetaLength : 2 * Math.PI;
31734 
31735  var heightHalf = height / 2;
31736 
31737  var x, y, vertices = [], uvs = [];
31738 
31739  for ( y = 0; y <= heightSegments; y ++ ) {
31740 
31741  var verticesRow = [];
31742  var uvsRow = [];
31743 
31744  var v = y / heightSegments;
31745  var radius = v * ( radiusBottom - radiusTop ) + radiusTop;
31746 
31747  for ( x = 0; x <= radialSegments; x ++ ) {
31748 
31749  var u = x / radialSegments;
31750 
31751  var vertex = new THREE.Vector3();
31752  vertex.x = radius * Math.sin( u * thetaLength + thetaStart );
31753  vertex.y = - v * height + heightHalf;
31754  vertex.z = radius * Math.cos( u * thetaLength + thetaStart );
31755 
31756  this.vertices.push( vertex );
31757 
31758  verticesRow.push( this.vertices.length - 1 );
31759  uvsRow.push( new THREE.Vector2( u, 1 - v ) );
31760 
31761  }
31762 
31763  vertices.push( verticesRow );
31764  uvs.push( uvsRow );
31765 
31766  }
31767 
31768  var tanTheta = ( radiusBottom - radiusTop ) / height;
31769  var na, nb;
31770 
31771  for ( x = 0; x < radialSegments; x ++ ) {
31772 
31773  if ( radiusTop !== 0 ) {
31774 
31775  na = this.vertices[ vertices[ 0 ][ x ] ].clone();
31776  nb = this.vertices[ vertices[ 0 ][ x + 1 ] ].clone();
31777 
31778  } else {
31779 
31780  na = this.vertices[ vertices[ 1 ][ x ] ].clone();
31781  nb = this.vertices[ vertices[ 1 ][ x + 1 ] ].clone();
31782 
31783  }
31784 
31785  na.setY( Math.sqrt( na.x * na.x + na.z * na.z ) * tanTheta ).normalize();
31786  nb.setY( Math.sqrt( nb.x * nb.x + nb.z * nb.z ) * tanTheta ).normalize();
31787 
31788  for ( y = 0; y < heightSegments; y ++ ) {
31789 
31790  var v1 = vertices[ y ][ x ];
31791  var v2 = vertices[ y + 1 ][ x ];
31792  var v3 = vertices[ y + 1 ][ x + 1 ];
31793  var v4 = vertices[ y ][ x + 1 ];
31794 
31795  var n1 = na.clone();
31796  var n2 = na.clone();
31797  var n3 = nb.clone();
31798  var n4 = nb.clone();
31799 
31800  var uv1 = uvs[ y ][ x ].clone();
31801  var uv2 = uvs[ y + 1 ][ x ].clone();
31802  var uv3 = uvs[ y + 1 ][ x + 1 ].clone();
31803  var uv4 = uvs[ y ][ x + 1 ].clone();
31804 
31805  this.faces.push( new THREE.Face3( v1, v2, v4, [ n1, n2, n4 ] ) );
31806  this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv4 ] );
31807 
31808  this.faces.push( new THREE.Face3( v2, v3, v4, [ n2.clone(), n3, n4.clone() ] ) );
31809  this.faceVertexUvs[ 0 ].push( [ uv2.clone(), uv3, uv4.clone() ] );
31810 
31811  }
31812 
31813  }
31814 
31815  // top cap
31816 
31817  if ( openEnded === false && radiusTop > 0 ) {
31818 
31819  this.vertices.push( new THREE.Vector3( 0, heightHalf, 0 ) );
31820 
31821  for ( x = 0; x < radialSegments; x ++ ) {
31822 
31823  var v1 = vertices[ 0 ][ x ];
31824  var v2 = vertices[ 0 ][ x + 1 ];
31825  var v3 = this.vertices.length - 1;
31826 
31827  var n1 = new THREE.Vector3( 0, 1, 0 );
31828  var n2 = new THREE.Vector3( 0, 1, 0 );
31829  var n3 = new THREE.Vector3( 0, 1, 0 );
31830 
31831  var uv1 = uvs[ 0 ][ x ].clone();
31832  var uv2 = uvs[ 0 ][ x + 1 ].clone();
31833  var uv3 = new THREE.Vector2( uv2.x, 0 );
31834 
31835  this.faces.push( new THREE.Face3( v1, v2, v3, [ n1, n2, n3 ], undefined, 1 ) );
31836  this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3 ] );
31837 
31838  }
31839 
31840  }
31841 
31842  // bottom cap
31843 
31844  if ( openEnded === false && radiusBottom > 0 ) {
31845 
31846  this.vertices.push( new THREE.Vector3( 0, - heightHalf, 0 ) );
31847 
31848  for ( x = 0; x < radialSegments; x ++ ) {
31849 
31850  var v1 = vertices[ heightSegments ][ x + 1 ];
31851  var v2 = vertices[ heightSegments ][ x ];
31852  var v3 = this.vertices.length - 1;
31853 
31854  var n1 = new THREE.Vector3( 0, - 1, 0 );
31855  var n2 = new THREE.Vector3( 0, - 1, 0 );
31856  var n3 = new THREE.Vector3( 0, - 1, 0 );
31857 
31858  var uv1 = uvs[ heightSegments ][ x + 1 ].clone();
31859  var uv2 = uvs[ heightSegments ][ x ].clone();
31860  var uv3 = new THREE.Vector2( uv2.x, 1 );
31861 
31862  this.faces.push( new THREE.Face3( v1, v2, v3, [ n1, n2, n3 ], undefined, 2 ) );
31863  this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3 ] );
31864 
31865  }
31866 
31867  }
31868 
31869  this.computeFaceNormals();
31870 
31871 };
31872 
31873 THREE.CylinderGeometry.prototype = Object.create( THREE.Geometry.prototype );
31874 THREE.CylinderGeometry.prototype.constructor = THREE.CylinderGeometry;
31875 
31876 THREE.CylinderGeometry.prototype.clone = function () {
31877 
31878  var parameters = this.parameters;
31879 
31880  return new THREE.CylinderGeometry(
31881  parameters.radiusTop,
31882  parameters.radiusBottom,
31883  parameters.height,
31884  parameters.radialSegments,
31885  parameters.heightSegments,
31886  parameters.openEnded,
31887  parameters.thetaStart,
31888  parameters.thetaLength
31889  );
31890 
31891 };
31892 
31893 // File:src/extras/geometries/EdgesGeometry.js
31894 
31899 THREE.EdgesGeometry = function ( geometry, thresholdAngle ) {
31900 
31901  THREE.BufferGeometry.call( this );
31902 
31903  thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
31904 
31905  var thresholdDot = Math.cos( THREE.Math.degToRad( thresholdAngle ) );
31906 
31907  var edge = [ 0, 0 ], hash = {};
31908 
31909  function sortFunction( a, b ) {
31910 
31911  return a - b;
31912 
31913  }
31914 
31915  var keys = [ 'a', 'b', 'c' ];
31916 
31917  var geometry2;
31918 
31919  if ( geometry instanceof THREE.BufferGeometry ) {
31920 
31921  geometry2 = new THREE.Geometry();
31922  geometry2.fromBufferGeometry( geometry );
31923 
31924  } else {
31925 
31926  geometry2 = geometry.clone();
31927 
31928  }
31929 
31930  geometry2.mergeVertices();
31931  geometry2.computeFaceNormals();
31932 
31933  var vertices = geometry2.vertices;
31934  var faces = geometry2.faces;
31935 
31936  for ( var i = 0, l = faces.length; i < l; i ++ ) {
31937 
31938  var face = faces[ i ];
31939 
31940  for ( var j = 0; j < 3; j ++ ) {
31941 
31942  edge[ 0 ] = face[ keys[ j ] ];
31943  edge[ 1 ] = face[ keys[ ( j + 1 ) % 3 ] ];
31944  edge.sort( sortFunction );
31945 
31946  var key = edge.toString();
31947 
31948  if ( hash[ key ] === undefined ) {
31949 
31950  hash[ key ] = { vert1: edge[ 0 ], vert2: edge[ 1 ], face1: i, face2: undefined };
31951 
31952  } else {
31953 
31954  hash[ key ].face2 = i;
31955 
31956  }
31957 
31958  }
31959 
31960  }
31961 
31962  var coords = [];
31963 
31964  for ( var key in hash ) {
31965 
31966  var h = hash[ key ];
31967 
31968  if ( h.face2 === undefined || faces[ h.face1 ].normal.dot( faces[ h.face2 ].normal ) <= thresholdDot ) {
31969 
31970  var vertex = vertices[ h.vert1 ];
31971  coords.push( vertex.x );
31972  coords.push( vertex.y );
31973  coords.push( vertex.z );
31974 
31975  vertex = vertices[ h.vert2 ];
31976  coords.push( vertex.x );
31977  coords.push( vertex.y );
31978  coords.push( vertex.z );
31979 
31980  }
31981 
31982  }
31983 
31984  this.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( coords ), 3 ) );
31985 
31986 };
31987 
31988 THREE.EdgesGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
31989 THREE.EdgesGeometry.prototype.constructor = THREE.EdgesGeometry;
31990 
31991 // File:src/extras/geometries/ExtrudeGeometry.js
31992 
32017 THREE.ExtrudeGeometry = function ( shapes, options ) {
32018 
32019  if ( typeof( shapes ) === "undefined" ) {
32020 
32021  shapes = [];
32022  return;
32023 
32024  }
32025 
32026  THREE.Geometry.call( this );
32027 
32028  this.type = 'ExtrudeGeometry';
32029 
32030  shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
32031 
32032  this.addShapeList( shapes, options );
32033 
32034  this.computeFaceNormals();
32035 
32036  // can't really use automatic vertex normals
32037  // as then front and back sides get smoothed too
32038  // should do separate smoothing just for sides
32039 
32040  //this.computeVertexNormals();
32041 
32042  //console.log( "took", ( Date.now() - startTime ) );
32043 
32044 };
32045 
32046 THREE.ExtrudeGeometry.prototype = Object.create( THREE.Geometry.prototype );
32047 THREE.ExtrudeGeometry.prototype.constructor = THREE.ExtrudeGeometry;
32048 
32049 THREE.ExtrudeGeometry.prototype.addShapeList = function ( shapes, options ) {
32050 
32051  var sl = shapes.length;
32052 
32053  for ( var s = 0; s < sl; s ++ ) {
32054 
32055  var shape = shapes[ s ];
32056  this.addShape( shape, options );
32057 
32058  }
32059 
32060 };
32061 
32062 THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) {
32063 
32064  var amount = options.amount !== undefined ? options.amount : 100;
32065 
32066  var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10
32067  var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8
32068  var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
32069 
32070  var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false
32071 
32072  var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
32073 
32074  var steps = options.steps !== undefined ? options.steps : 1;
32075 
32076  var extrudePath = options.extrudePath;
32077  var extrudePts, extrudeByPath = false;
32078 
32079  // Use default WorldUVGenerator if no UV generators are specified.
32080  var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : THREE.ExtrudeGeometry.WorldUVGenerator;
32081 
32082  var splineTube, binormal, normal, position2;
32083  if ( extrudePath ) {
32084 
32085  extrudePts = extrudePath.getSpacedPoints( steps );
32086 
32087  extrudeByPath = true;
32088  bevelEnabled = false; // bevels not supported for path extrusion
32089 
32090  // SETUP TNB variables
32091 
32092  // Reuse TNB from TubeGeomtry for now.
32093  // TODO1 - have a .isClosed in spline?
32094 
32095  splineTube = options.frames !== undefined ? options.frames : new THREE.TubeGeometry.FrenetFrames( extrudePath, steps, false );
32096 
32097  // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
32098 
32099  binormal = new THREE.Vector3();
32100  normal = new THREE.Vector3();
32101  position2 = new THREE.Vector3();
32102 
32103  }
32104 
32105  // Safeguards if bevels are not enabled
32106 
32107  if ( ! bevelEnabled ) {
32108 
32109  bevelSegments = 0;
32110  bevelThickness = 0;
32111  bevelSize = 0;
32112 
32113  }
32114 
32115  // Variables initialization
32116 
32117  var ahole, h, hl; // looping of holes
32118  var scope = this;
32119 
32120  var shapesOffset = this.vertices.length;
32121 
32122  var shapePoints = shape.extractPoints( curveSegments );
32123 
32124  var vertices = shapePoints.shape;
32125  var holes = shapePoints.holes;
32126 
32127  var reverse = ! THREE.ShapeUtils.isClockWise( vertices );
32128 
32129  if ( reverse ) {
32130 
32131  vertices = vertices.reverse();
32132 
32133  // Maybe we should also check if holes are in the opposite direction, just to be safe ...
32134 
32135  for ( h = 0, hl = holes.length; h < hl; h ++ ) {
32136 
32137  ahole = holes[ h ];
32138 
32139  if ( THREE.ShapeUtils.isClockWise( ahole ) ) {
32140 
32141  holes[ h ] = ahole.reverse();
32142 
32143  }
32144 
32145  }
32146 
32147  reverse = false; // If vertices are in order now, we shouldn't need to worry about them again (hopefully)!
32148 
32149  }
32150 
32151 
32152  var faces = THREE.ShapeUtils.triangulateShape( vertices, holes );
32153 
32154  /* Vertices */
32155 
32156  var contour = vertices; // vertices has all points but contour has only points of circumference
32157 
32158  for ( h = 0, hl = holes.length; h < hl; h ++ ) {
32159 
32160  ahole = holes[ h ];
32161 
32162  vertices = vertices.concat( ahole );
32163 
32164  }
32165 
32166 
32167  function scalePt2 ( pt, vec, size ) {
32168 
32169  if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
32170 
32171  return vec.clone().multiplyScalar( size ).add( pt );
32172 
32173  }
32174 
32175  var b, bs, t, z,
32176  vert, vlen = vertices.length,
32177  face, flen = faces.length;
32178 
32179 
32180  // Find directions for point movement
32181 
32182 
32183  function getBevelVec( inPt, inPrev, inNext ) {
32184 
32185  // computes for inPt the corresponding point inPt' on a new contour
32186  // shifted by 1 unit (length of normalized vector) to the left
32187  // if we walk along contour clockwise, this new contour is outside the old one
32188  //
32189  // inPt' is the intersection of the two lines parallel to the two
32190  // adjacent edges of inPt at a distance of 1 unit on the left side.
32191 
32192  var v_trans_x, v_trans_y, shrink_by = 1; // resulting translation vector for inPt
32193 
32194  // good reading for geometry algorithms (here: line-line intersection)
32195  // http://geomalgorithms.com/a05-_intersect-1.html
32196 
32197  var v_prev_x = inPt.x - inPrev.x, v_prev_y = inPt.y - inPrev.y;
32198  var v_next_x = inNext.x - inPt.x, v_next_y = inNext.y - inPt.y;
32199 
32200  var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
32201 
32202  // check for collinear edges
32203  var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
32204 
32205  if ( Math.abs( collinear0 ) > Number.EPSILON ) {
32206 
32207  // not collinear
32208 
32209  // length of vectors for normalizing
32210 
32211  var v_prev_len = Math.sqrt( v_prev_lensq );
32212  var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
32213 
32214  // shift adjacent points by unit vectors to the left
32215 
32216  var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
32217  var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
32218 
32219  var ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
32220  var ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
32221 
32222  // scaling factor for v_prev to intersection point
32223 
32224  var sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
32225  ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
32226  ( v_prev_x * v_next_y - v_prev_y * v_next_x );
32227 
32228  // vector from inPt to intersection point
32229 
32230  v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
32231  v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
32232 
32233  // Don't normalize!, otherwise sharp corners become ugly
32234  // but prevent crazy spikes
32235  var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
32236  if ( v_trans_lensq <= 2 ) {
32237 
32238  return new THREE.Vector2( v_trans_x, v_trans_y );
32239 
32240  } else {
32241 
32242  shrink_by = Math.sqrt( v_trans_lensq / 2 );
32243 
32244  }
32245 
32246  } else {
32247 
32248  // handle special case of collinear edges
32249 
32250  var direction_eq = false; // assumes: opposite
32251  if ( v_prev_x > Number.EPSILON ) {
32252 
32253  if ( v_next_x > Number.EPSILON ) {
32254 
32255  direction_eq = true;
32256 
32257  }
32258 
32259  } else {
32260 
32261  if ( v_prev_x < - Number.EPSILON ) {
32262 
32263  if ( v_next_x < - Number.EPSILON ) {
32264 
32265  direction_eq = true;
32266 
32267  }
32268 
32269  } else {
32270 
32271  if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
32272 
32273  direction_eq = true;
32274 
32275  }
32276 
32277  }
32278 
32279  }
32280 
32281  if ( direction_eq ) {
32282 
32283  // console.log("Warning: lines are a straight sequence");
32284  v_trans_x = - v_prev_y;
32285  v_trans_y = v_prev_x;
32286  shrink_by = Math.sqrt( v_prev_lensq );
32287 
32288  } else {
32289 
32290  // console.log("Warning: lines are a straight spike");
32291  v_trans_x = v_prev_x;
32292  v_trans_y = v_prev_y;
32293  shrink_by = Math.sqrt( v_prev_lensq / 2 );
32294 
32295  }
32296 
32297  }
32298 
32299  return new THREE.Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
32300 
32301  }
32302 
32303 
32304  var contourMovements = [];
32305 
32306  for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
32307 
32308  if ( j === il ) j = 0;
32309  if ( k === il ) k = 0;
32310 
32311  // (j)---(i)---(k)
32312  // console.log('i,j,k', i, j , k)
32313 
32314  contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
32315 
32316  }
32317 
32318  var holesMovements = [], oneHoleMovements, verticesMovements = contourMovements.concat();
32319 
32320  for ( h = 0, hl = holes.length; h < hl; h ++ ) {
32321 
32322  ahole = holes[ h ];
32323 
32324  oneHoleMovements = [];
32325 
32326  for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
32327 
32328  if ( j === il ) j = 0;
32329  if ( k === il ) k = 0;
32330 
32331  // (j)---(i)---(k)
32332  oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
32333 
32334  }
32335 
32336  holesMovements.push( oneHoleMovements );
32337  verticesMovements = verticesMovements.concat( oneHoleMovements );
32338 
32339  }
32340 
32341 
32342  // Loop bevelSegments, 1 for the front, 1 for the back
32343 
32344  for ( b = 0; b < bevelSegments; b ++ ) {
32345 
32346  //for ( b = bevelSegments; b > 0; b -- ) {
32347 
32348  t = b / bevelSegments;
32349  z = bevelThickness * ( 1 - t );
32350 
32351  //z = bevelThickness * t;
32352  bs = bevelSize * ( Math.sin ( t * Math.PI / 2 ) ); // curved
32353  //bs = bevelSize * t; // linear
32354 
32355  // contract shape
32356 
32357  for ( i = 0, il = contour.length; i < il; i ++ ) {
32358 
32359  vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
32360 
32361  v( vert.x, vert.y, - z );
32362 
32363  }
32364 
32365  // expand holes
32366 
32367  for ( h = 0, hl = holes.length; h < hl; h ++ ) {
32368 
32369  ahole = holes[ h ];
32370  oneHoleMovements = holesMovements[ h ];
32371 
32372  for ( i = 0, il = ahole.length; i < il; i ++ ) {
32373 
32374  vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
32375 
32376  v( vert.x, vert.y, - z );
32377 
32378  }
32379 
32380  }
32381 
32382  }
32383 
32384  bs = bevelSize;
32385 
32386  // Back facing vertices
32387 
32388  for ( i = 0; i < vlen; i ++ ) {
32389 
32390  vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
32391 
32392  if ( ! extrudeByPath ) {
32393 
32394  v( vert.x, vert.y, 0 );
32395 
32396  } else {
32397 
32398  // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
32399 
32400  normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
32401  binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
32402 
32403  position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
32404 
32405  v( position2.x, position2.y, position2.z );
32406 
32407  }
32408 
32409  }
32410 
32411  // Add stepped vertices...
32412  // Including front facing vertices
32413 
32414  var s;
32415 
32416  for ( s = 1; s <= steps; s ++ ) {
32417 
32418  for ( i = 0; i < vlen; i ++ ) {
32419 
32420  vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
32421 
32422  if ( ! extrudeByPath ) {
32423 
32424  v( vert.x, vert.y, amount / steps * s );
32425 
32426  } else {
32427 
32428  // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
32429 
32430  normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
32431  binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
32432 
32433  position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
32434 
32435  v( position2.x, position2.y, position2.z );
32436 
32437  }
32438 
32439  }
32440 
32441  }
32442 
32443 
32444  // Add bevel segments planes
32445 
32446  //for ( b = 1; b <= bevelSegments; b ++ ) {
32447  for ( b = bevelSegments - 1; b >= 0; b -- ) {
32448 
32449  t = b / bevelSegments;
32450  z = bevelThickness * ( 1 - t );
32451  //bs = bevelSize * ( 1-Math.sin ( ( 1 - t ) * Math.PI/2 ) );
32452  bs = bevelSize * Math.sin ( t * Math.PI / 2 );
32453 
32454  // contract shape
32455 
32456  for ( i = 0, il = contour.length; i < il; i ++ ) {
32457 
32458  vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
32459  v( vert.x, vert.y, amount + z );
32460 
32461  }
32462 
32463  // expand holes
32464 
32465  for ( h = 0, hl = holes.length; h < hl; h ++ ) {
32466 
32467  ahole = holes[ h ];
32468  oneHoleMovements = holesMovements[ h ];
32469 
32470  for ( i = 0, il = ahole.length; i < il; i ++ ) {
32471 
32472  vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
32473 
32474  if ( ! extrudeByPath ) {
32475 
32476  v( vert.x, vert.y, amount + z );
32477 
32478  } else {
32479 
32480  v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
32481 
32482  }
32483 
32484  }
32485 
32486  }
32487 
32488  }
32489 
32490  /* Faces */
32491 
32492  // Top and bottom faces
32493 
32494  buildLidFaces();
32495 
32496  // Sides faces
32497 
32498  buildSideFaces();
32499 
32500 
32502 
32503  function buildLidFaces() {
32504 
32505  if ( bevelEnabled ) {
32506 
32507  var layer = 0; // steps + 1
32508  var offset = vlen * layer;
32509 
32510  // Bottom faces
32511 
32512  for ( i = 0; i < flen; i ++ ) {
32513 
32514  face = faces[ i ];
32515  f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
32516 
32517  }
32518 
32519  layer = steps + bevelSegments * 2;
32520  offset = vlen * layer;
32521 
32522  // Top faces
32523 
32524  for ( i = 0; i < flen; i ++ ) {
32525 
32526  face = faces[ i ];
32527  f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
32528 
32529  }
32530 
32531  } else {
32532 
32533  // Bottom faces
32534 
32535  for ( i = 0; i < flen; i ++ ) {
32536 
32537  face = faces[ i ];
32538  f3( face[ 2 ], face[ 1 ], face[ 0 ] );
32539 
32540  }
32541 
32542  // Top faces
32543 
32544  for ( i = 0; i < flen; i ++ ) {
32545 
32546  face = faces[ i ];
32547  f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
32548 
32549  }
32550 
32551  }
32552 
32553  }
32554 
32555  // Create faces for the z-sides of the shape
32556 
32557  function buildSideFaces() {
32558 
32559  var layeroffset = 0;
32560  sidewalls( contour, layeroffset );
32561  layeroffset += contour.length;
32562 
32563  for ( h = 0, hl = holes.length; h < hl; h ++ ) {
32564 
32565  ahole = holes[ h ];
32566  sidewalls( ahole, layeroffset );
32567 
32568  //, true
32569  layeroffset += ahole.length;
32570 
32571  }
32572 
32573  }
32574 
32575  function sidewalls( contour, layeroffset ) {
32576 
32577  var j, k;
32578  i = contour.length;
32579 
32580  while ( -- i >= 0 ) {
32581 
32582  j = i;
32583  k = i - 1;
32584  if ( k < 0 ) k = contour.length - 1;
32585 
32586  //console.log('b', i,j, i-1, k,vertices.length);
32587 
32588  var s = 0, sl = steps + bevelSegments * 2;
32589 
32590  for ( s = 0; s < sl; s ++ ) {
32591 
32592  var slen1 = vlen * s;
32593  var slen2 = vlen * ( s + 1 );
32594 
32595  var a = layeroffset + j + slen1,
32596  b = layeroffset + k + slen1,
32597  c = layeroffset + k + slen2,
32598  d = layeroffset + j + slen2;
32599 
32600  f4( a, b, c, d, contour, s, sl, j, k );
32601 
32602  }
32603 
32604  }
32605 
32606  }
32607 
32608 
32609  function v( x, y, z ) {
32610 
32611  scope.vertices.push( new THREE.Vector3( x, y, z ) );
32612 
32613  }
32614 
32615  function f3( a, b, c ) {
32616 
32617  a += shapesOffset;
32618  b += shapesOffset;
32619  c += shapesOffset;
32620 
32621  scope.faces.push( new THREE.Face3( a, b, c, null, null, 0 ) );
32622 
32623  var uvs = uvgen.generateTopUV( scope, a, b, c );
32624 
32625  scope.faceVertexUvs[ 0 ].push( uvs );
32626 
32627  }
32628 
32629  function f4( a, b, c, d, wallContour, stepIndex, stepsLength, contourIndex1, contourIndex2 ) {
32630 
32631  a += shapesOffset;
32632  b += shapesOffset;
32633  c += shapesOffset;
32634  d += shapesOffset;
32635 
32636  scope.faces.push( new THREE.Face3( a, b, d, null, null, 1 ) );
32637  scope.faces.push( new THREE.Face3( b, c, d, null, null, 1 ) );
32638 
32639  var uvs = uvgen.generateSideWallUV( scope, a, b, c, d );
32640 
32641  scope.faceVertexUvs[ 0 ].push( [ uvs[ 0 ], uvs[ 1 ], uvs[ 3 ] ] );
32642  scope.faceVertexUvs[ 0 ].push( [ uvs[ 1 ], uvs[ 2 ], uvs[ 3 ] ] );
32643 
32644  }
32645 
32646 };
32647 
32648 THREE.ExtrudeGeometry.WorldUVGenerator = {
32649 
32650  generateTopUV: function ( geometry, indexA, indexB, indexC ) {
32651 
32652  var vertices = geometry.vertices;
32653 
32654  var a = vertices[ indexA ];
32655  var b = vertices[ indexB ];
32656  var c = vertices[ indexC ];
32657 
32658  return [
32659  new THREE.Vector2( a.x, a.y ),
32660  new THREE.Vector2( b.x, b.y ),
32661  new THREE.Vector2( c.x, c.y )
32662  ];
32663 
32664  },
32665 
32666  generateSideWallUV: function ( geometry, indexA, indexB, indexC, indexD ) {
32667 
32668  var vertices = geometry.vertices;
32669 
32670  var a = vertices[ indexA ];
32671  var b = vertices[ indexB ];
32672  var c = vertices[ indexC ];
32673  var d = vertices[ indexD ];
32674 
32675  if ( Math.abs( a.y - b.y ) < 0.01 ) {
32676 
32677  return [
32678  new THREE.Vector2( a.x, 1 - a.z ),
32679  new THREE.Vector2( b.x, 1 - b.z ),
32680  new THREE.Vector2( c.x, 1 - c.z ),
32681  new THREE.Vector2( d.x, 1 - d.z )
32682  ];
32683 
32684  } else {
32685 
32686  return [
32687  new THREE.Vector2( a.y, 1 - a.z ),
32688  new THREE.Vector2( b.y, 1 - b.z ),
32689  new THREE.Vector2( c.y, 1 - c.z ),
32690  new THREE.Vector2( d.y, 1 - d.z )
32691  ];
32692 
32693  }
32694 
32695  }
32696 };
32697 
32698 // File:src/extras/geometries/ShapeGeometry.js
32699 
32716 THREE.ShapeGeometry = function ( shapes, options ) {
32717 
32718  THREE.Geometry.call( this );
32719 
32720  this.type = 'ShapeGeometry';
32721 
32722  if ( Array.isArray( shapes ) === false ) shapes = [ shapes ];
32723 
32724  this.addShapeList( shapes, options );
32725 
32726  this.computeFaceNormals();
32727 
32728 };
32729 
32730 THREE.ShapeGeometry.prototype = Object.create( THREE.Geometry.prototype );
32731 THREE.ShapeGeometry.prototype.constructor = THREE.ShapeGeometry;
32732 
32736 THREE.ShapeGeometry.prototype.addShapeList = function ( shapes, options ) {
32737 
32738  for ( var i = 0, l = shapes.length; i < l; i ++ ) {
32739 
32740  this.addShape( shapes[ i ], options );
32741 
32742  }
32743 
32744  return this;
32745 
32746 };
32747 
32751 THREE.ShapeGeometry.prototype.addShape = function ( shape, options ) {
32752 
32753  if ( options === undefined ) options = {};
32754  var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
32755 
32756  var material = options.material;
32757  var uvgen = options.UVGenerator === undefined ? THREE.ExtrudeGeometry.WorldUVGenerator : options.UVGenerator;
32758 
32759  //
32760 
32761  var i, l, hole;
32762 
32763  var shapesOffset = this.vertices.length;
32764  var shapePoints = shape.extractPoints( curveSegments );
32765 
32766  var vertices = shapePoints.shape;
32767  var holes = shapePoints.holes;
32768 
32769  var reverse = ! THREE.ShapeUtils.isClockWise( vertices );
32770 
32771  if ( reverse ) {
32772 
32773  vertices = vertices.reverse();
32774 
32775  // Maybe we should also check if holes are in the opposite direction, just to be safe...
32776 
32777  for ( i = 0, l = holes.length; i < l; i ++ ) {
32778 
32779  hole = holes[ i ];
32780 
32781  if ( THREE.ShapeUtils.isClockWise( hole ) ) {
32782 
32783  holes[ i ] = hole.reverse();
32784 
32785  }
32786 
32787  }
32788 
32789  reverse = false;
32790 
32791  }
32792 
32793  var faces = THREE.ShapeUtils.triangulateShape( vertices, holes );
32794 
32795  // Vertices
32796 
32797  for ( i = 0, l = holes.length; i < l; i ++ ) {
32798 
32799  hole = holes[ i ];
32800  vertices = vertices.concat( hole );
32801 
32802  }
32803 
32804  //
32805 
32806  var vert, vlen = vertices.length;
32807  var face, flen = faces.length;
32808 
32809  for ( i = 0; i < vlen; i ++ ) {
32810 
32811  vert = vertices[ i ];
32812 
32813  this.vertices.push( new THREE.Vector3( vert.x, vert.y, 0 ) );
32814 
32815  }
32816 
32817  for ( i = 0; i < flen; i ++ ) {
32818 
32819  face = faces[ i ];
32820 
32821  var a = face[ 0 ] + shapesOffset;
32822  var b = face[ 1 ] + shapesOffset;
32823  var c = face[ 2 ] + shapesOffset;
32824 
32825  this.faces.push( new THREE.Face3( a, b, c, null, null, material ) );
32826  this.faceVertexUvs[ 0 ].push( uvgen.generateTopUV( this, a, b, c ) );
32827 
32828  }
32829 
32830 };
32831 
32832 // File:src/extras/geometries/LatheGeometry.js
32833 
32840 // points - to create a closed torus, one must use a set of points
32841 // like so: [ a, b, c, d, a ], see first is the same as last.
32842 // segments - the number of circumference segments to create
32843 // phiStart - the starting radian
32844 // phiLength - the radian (0 to 2*PI) range of the lathed section
32845 // 2*pi is a closed lathe, less than 2PI is a portion.
32846 
32847 THREE.LatheGeometry = function ( points, segments, phiStart, phiLength ) {
32848 
32849  THREE.Geometry.call( this );
32850 
32851  this.type = 'LatheGeometry';
32852 
32853  this.parameters = {
32854  points: points,
32855  segments: segments,
32856  phiStart: phiStart,
32857  phiLength: phiLength
32858  };
32859 
32860  segments = segments || 12;
32861  phiStart = phiStart || 0;
32862  phiLength = phiLength || 2 * Math.PI;
32863 
32864  var inversePointLength = 1.0 / ( points.length - 1 );
32865  var inverseSegments = 1.0 / segments;
32866 
32867  for ( var i = 0, il = segments; i <= il; i ++ ) {
32868 
32869  var phi = phiStart + i * inverseSegments * phiLength;
32870 
32871  var c = Math.cos( phi ),
32872  s = Math.sin( phi );
32873 
32874  for ( var j = 0, jl = points.length; j < jl; j ++ ) {
32875 
32876  var pt = points[ j ];
32877 
32878  var vertex = new THREE.Vector3();
32879 
32880  vertex.x = c * pt.x - s * pt.y;
32881  vertex.y = s * pt.x + c * pt.y;
32882  vertex.z = pt.z;
32883 
32884  this.vertices.push( vertex );
32885 
32886  }
32887 
32888  }
32889 
32890  var np = points.length;
32891 
32892  for ( var i = 0, il = segments; i < il; i ++ ) {
32893 
32894  for ( var j = 0, jl = points.length - 1; j < jl; j ++ ) {
32895 
32896  var base = j + np * i;
32897  var a = base;
32898  var b = base + np;
32899  var c = base + 1 + np;
32900  var d = base + 1;
32901 
32902  var u0 = i * inverseSegments;
32903  var v0 = j * inversePointLength;
32904  var u1 = u0 + inverseSegments;
32905  var v1 = v0 + inversePointLength;
32906 
32907  this.faces.push( new THREE.Face3( a, b, d ) );
32908 
32909  this.faceVertexUvs[ 0 ].push( [
32910 
32911  new THREE.Vector2( u0, v0 ),
32912  new THREE.Vector2( u1, v0 ),
32913  new THREE.Vector2( u0, v1 )
32914 
32915  ] );
32916 
32917  this.faces.push( new THREE.Face3( b, c, d ) );
32918 
32919  this.faceVertexUvs[ 0 ].push( [
32920 
32921  new THREE.Vector2( u1, v0 ),
32922  new THREE.Vector2( u1, v1 ),
32923  new THREE.Vector2( u0, v1 )
32924 
32925  ] );
32926 
32927 
32928  }
32929 
32930  }
32931 
32932  this.mergeVertices();
32933  this.computeFaceNormals();
32934  this.computeVertexNormals();
32935 
32936 };
32937 
32938 THREE.LatheGeometry.prototype = Object.create( THREE.Geometry.prototype );
32939 THREE.LatheGeometry.prototype.constructor = THREE.LatheGeometry;
32940 
32941 // File:src/extras/geometries/PlaneGeometry.js
32942 
32948 THREE.PlaneGeometry = function ( width, height, widthSegments, heightSegments ) {
32949 
32950  THREE.Geometry.call( this );
32951 
32952  this.type = 'PlaneGeometry';
32953 
32954  this.parameters = {
32955  width: width,
32956  height: height,
32957  widthSegments: widthSegments,
32958  heightSegments: heightSegments
32959  };
32960 
32961  this.fromBufferGeometry( new THREE.PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
32962 
32963 };
32964 
32965 THREE.PlaneGeometry.prototype = Object.create( THREE.Geometry.prototype );
32966 THREE.PlaneGeometry.prototype.constructor = THREE.PlaneGeometry;
32967 
32968 THREE.PlaneGeometry.prototype.clone = function () {
32969 
32970  var parameters = this.parameters;
32971 
32972  return new THREE.PlaneGeometry(
32973  parameters.width,
32974  parameters.height,
32975  parameters.widthSegments,
32976  parameters.heightSegments
32977  );
32978 
32979 };
32980 
32981 // File:src/extras/geometries/PlaneBufferGeometry.js
32982 
32988 THREE.PlaneBufferGeometry = function ( width, height, widthSegments, heightSegments ) {
32989 
32990  THREE.BufferGeometry.call( this );
32991 
32992  this.type = 'PlaneBufferGeometry';
32993 
32994  this.parameters = {
32995  width: width,
32996  height: height,
32997  widthSegments: widthSegments,
32998  heightSegments: heightSegments
32999  };
33000 
33001  var width_half = width / 2;
33002  var height_half = height / 2;
33003 
33004  var gridX = Math.floor( widthSegments ) || 1;
33005  var gridY = Math.floor( heightSegments ) || 1;
33006 
33007  var gridX1 = gridX + 1;
33008  var gridY1 = gridY + 1;
33009 
33010  var segment_width = width / gridX;
33011  var segment_height = height / gridY;
33012 
33013  var vertices = new Float32Array( gridX1 * gridY1 * 3 );
33014  var normals = new Float32Array( gridX1 * gridY1 * 3 );
33015  var uvs = new Float32Array( gridX1 * gridY1 * 2 );
33016 
33017  var offset = 0;
33018  var offset2 = 0;
33019 
33020  for ( var iy = 0; iy < gridY1; iy ++ ) {
33021 
33022  var y = iy * segment_height - height_half;
33023 
33024  for ( var ix = 0; ix < gridX1; ix ++ ) {
33025 
33026  var x = ix * segment_width - width_half;
33027 
33028  vertices[ offset ] = x;
33029  vertices[ offset + 1 ] = - y;
33030 
33031  normals[ offset + 2 ] = 1;
33032 
33033  uvs[ offset2 ] = ix / gridX;
33034  uvs[ offset2 + 1 ] = 1 - ( iy / gridY );
33035 
33036  offset += 3;
33037  offset2 += 2;
33038 
33039  }
33040 
33041  }
33042 
33043  offset = 0;
33044 
33045  var indices = new ( ( vertices.length / 3 ) > 65535 ? Uint32Array : Uint16Array )( gridX * gridY * 6 );
33046 
33047  for ( var iy = 0; iy < gridY; iy ++ ) {
33048 
33049  for ( var ix = 0; ix < gridX; ix ++ ) {
33050 
33051  var a = ix + gridX1 * iy;
33052  var b = ix + gridX1 * ( iy + 1 );
33053  var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
33054  var d = ( ix + 1 ) + gridX1 * iy;
33055 
33056  indices[ offset ] = a;
33057  indices[ offset + 1 ] = b;
33058  indices[ offset + 2 ] = d;
33059 
33060  indices[ offset + 3 ] = b;
33061  indices[ offset + 4 ] = c;
33062  indices[ offset + 5 ] = d;
33063 
33064  offset += 6;
33065 
33066  }
33067 
33068  }
33069 
33070  this.setIndex( new THREE.BufferAttribute( indices, 1 ) );
33071  this.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
33072  this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
33073  this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
33074 
33075 };
33076 
33077 THREE.PlaneBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
33078 THREE.PlaneBufferGeometry.prototype.constructor = THREE.PlaneBufferGeometry;
33079 
33080 THREE.PlaneBufferGeometry.prototype.clone = function () {
33081 
33082  var parameters = this.parameters;
33083 
33084  return new THREE.PlaneBufferGeometry(
33085  parameters.width,
33086  parameters.height,
33087  parameters.widthSegments,
33088  parameters.heightSegments
33089  );
33090 
33091 };
33092 
33093 // File:src/extras/geometries/RingGeometry.js
33094 
33099 THREE.RingGeometry = function ( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
33100 
33101  THREE.Geometry.call( this );
33102 
33103  this.type = 'RingGeometry';
33104 
33105  this.parameters = {
33106  innerRadius: innerRadius,
33107  outerRadius: outerRadius,
33108  thetaSegments: thetaSegments,
33109  phiSegments: phiSegments,
33110  thetaStart: thetaStart,
33111  thetaLength: thetaLength
33112  };
33113 
33114  innerRadius = innerRadius || 0;
33115  outerRadius = outerRadius || 50;
33116 
33117  thetaStart = thetaStart !== undefined ? thetaStart : 0;
33118  thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
33119 
33120  thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;
33121  phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 8;
33122 
33123  var i, o, uvs = [], radius = innerRadius, radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
33124 
33125  for ( i = 0; i < phiSegments + 1; i ++ ) {
33126 
33127  // concentric circles inside ring
33128 
33129  for ( o = 0; o < thetaSegments + 1; o ++ ) {
33130 
33131  // number of segments per circle
33132 
33133  var vertex = new THREE.Vector3();
33134  var segment = thetaStart + o / thetaSegments * thetaLength;
33135  vertex.x = radius * Math.cos( segment );
33136  vertex.y = radius * Math.sin( segment );
33137 
33138  this.vertices.push( vertex );
33139  uvs.push( new THREE.Vector2( ( vertex.x / outerRadius + 1 ) / 2, ( vertex.y / outerRadius + 1 ) / 2 ) );
33140 
33141  }
33142 
33143  radius += radiusStep;
33144 
33145  }
33146 
33147  var n = new THREE.Vector3( 0, 0, 1 );
33148 
33149  for ( i = 0; i < phiSegments; i ++ ) {
33150 
33151  // concentric circles inside ring
33152 
33153  var thetaSegment = i * ( thetaSegments + 1 );
33154 
33155  for ( o = 0; o < thetaSegments ; o ++ ) {
33156 
33157  // number of segments per circle
33158 
33159  var segment = o + thetaSegment;
33160 
33161  var v1 = segment;
33162  var v2 = segment + thetaSegments + 1;
33163  var v3 = segment + thetaSegments + 2;
33164 
33165  this.faces.push( new THREE.Face3( v1, v2, v3, [ n.clone(), n.clone(), n.clone() ] ) );
33166  this.faceVertexUvs[ 0 ].push( [ uvs[ v1 ].clone(), uvs[ v2 ].clone(), uvs[ v3 ].clone() ] );
33167 
33168  v1 = segment;
33169  v2 = segment + thetaSegments + 2;
33170  v3 = segment + 1;
33171 
33172  this.faces.push( new THREE.Face3( v1, v2, v3, [ n.clone(), n.clone(), n.clone() ] ) );
33173  this.faceVertexUvs[ 0 ].push( [ uvs[ v1 ].clone(), uvs[ v2 ].clone(), uvs[ v3 ].clone() ] );
33174 
33175  }
33176 
33177  }
33178 
33179  this.computeFaceNormals();
33180 
33181  this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
33182 
33183 };
33184 
33185 THREE.RingGeometry.prototype = Object.create( THREE.Geometry.prototype );
33186 THREE.RingGeometry.prototype.constructor = THREE.RingGeometry;
33187 
33188 THREE.RingGeometry.prototype.clone = function () {
33189 
33190  var parameters = this.parameters;
33191 
33192  return new THREE.RingGeometry(
33193  parameters.innerRadius,
33194  parameters.outerRadius,
33195  parameters.thetaSegments,
33196  parameters.phiSegments,
33197  parameters.thetaStart,
33198  parameters.thetaLength
33199  );
33200 
33201 };
33202 
33203 // File:src/extras/geometries/SphereGeometry.js
33204 
33209 THREE.SphereGeometry = function ( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
33210 
33211  THREE.Geometry.call( this );
33212 
33213  this.type = 'SphereGeometry';
33214 
33215  this.parameters = {
33216  radius: radius,
33217  widthSegments: widthSegments,
33218  heightSegments: heightSegments,
33219  phiStart: phiStart,
33220  phiLength: phiLength,
33221  thetaStart: thetaStart,
33222  thetaLength: thetaLength
33223  };
33224 
33225  this.fromBufferGeometry( new THREE.SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );
33226 
33227 };
33228 
33229 THREE.SphereGeometry.prototype = Object.create( THREE.Geometry.prototype );
33230 THREE.SphereGeometry.prototype.constructor = THREE.SphereGeometry;
33231 
33232 THREE.SphereGeometry.prototype.clone = function () {
33233 
33234  var parameters = this.parameters;
33235 
33236  return new THREE.SphereGeometry(
33237  parameters.radius,
33238  parameters.widthSegments,
33239  parameters.heightSegments,
33240  parameters.phiStart,
33241  parameters.phiLength,
33242  parameters.thetaStart,
33243  parameters.thetaLength
33244  );
33245 
33246 };
33247 
33248 // File:src/extras/geometries/SphereBufferGeometry.js
33249 
33255 THREE.SphereBufferGeometry = function ( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
33256 
33257  THREE.BufferGeometry.call( this );
33258 
33259  this.type = 'SphereBufferGeometry';
33260 
33261  this.parameters = {
33262  radius: radius,
33263  widthSegments: widthSegments,
33264  heightSegments: heightSegments,
33265  phiStart: phiStart,
33266  phiLength: phiLength,
33267  thetaStart: thetaStart,
33268  thetaLength: thetaLength
33269  };
33270 
33271  radius = radius || 50;
33272 
33273  widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 );
33274  heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 );
33275 
33276  phiStart = phiStart !== undefined ? phiStart : 0;
33277  phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
33278 
33279  thetaStart = thetaStart !== undefined ? thetaStart : 0;
33280  thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
33281 
33282  var thetaEnd = thetaStart + thetaLength;
33283 
33284  var vertexCount = ( ( widthSegments + 1 ) * ( heightSegments + 1 ) );
33285 
33286  var positions = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
33287  var normals = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
33288  var uvs = new THREE.BufferAttribute( new Float32Array( vertexCount * 2 ), 2 );
33289 
33290  var index = 0, vertices = [], normal = new THREE.Vector3();
33291 
33292  for ( var y = 0; y <= heightSegments; y ++ ) {
33293 
33294  var verticesRow = [];
33295 
33296  var v = y / heightSegments;
33297 
33298  for ( var x = 0; x <= widthSegments; x ++ ) {
33299 
33300  var u = x / widthSegments;
33301 
33302  var px = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
33303  var py = radius * Math.cos( thetaStart + v * thetaLength );
33304  var pz = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
33305 
33306  normal.set( px, py, pz ).normalize();
33307 
33308  positions.setXYZ( index, px, py, pz );
33309  normals.setXYZ( index, normal.x, normal.y, normal.z );
33310  uvs.setXY( index, u, 1 - v );
33311 
33312  verticesRow.push( index );
33313 
33314  index ++;
33315 
33316  }
33317 
33318  vertices.push( verticesRow );
33319 
33320  }
33321 
33322  var indices = [];
33323 
33324  for ( var y = 0; y < heightSegments; y ++ ) {
33325 
33326  for ( var x = 0; x < widthSegments; x ++ ) {
33327 
33328  var v1 = vertices[ y ][ x + 1 ];
33329  var v2 = vertices[ y ][ x ];
33330  var v3 = vertices[ y + 1 ][ x ];
33331  var v4 = vertices[ y + 1 ][ x + 1 ];
33332 
33333  if ( y !== 0 || thetaStart > 0 ) indices.push( v1, v2, v4 );
33334  if ( y !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( v2, v3, v4 );
33335 
33336  }
33337 
33338  }
33339 
33340  this.setIndex( new ( positions.count > 65535 ? THREE.Uint32Attribute : THREE.Uint16Attribute )( indices, 1 ) );
33341  this.addAttribute( 'position', positions );
33342  this.addAttribute( 'normal', normals );
33343  this.addAttribute( 'uv', uvs );
33344 
33345  this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
33346 
33347 };
33348 
33349 THREE.SphereBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
33350 THREE.SphereBufferGeometry.prototype.constructor = THREE.SphereBufferGeometry;
33351 
33352 THREE.SphereBufferGeometry.prototype.clone = function () {
33353 
33354  var parameters = this.parameters;
33355 
33356  return new THREE.SphereBufferGeometry(
33357  parameters.radius,
33358  parameters.widthSegments,
33359  parameters.heightSegments,
33360  parameters.phiStart,
33361  parameters.phiLength,
33362  parameters.thetaStart,
33363  parameters.thetaLength
33364  );
33365 
33366 };
33367 
33368 // File:src/extras/geometries/TorusGeometry.js
33369 
33376 THREE.TorusGeometry = function ( radius, tube, radialSegments, tubularSegments, arc ) {
33377 
33378  THREE.Geometry.call( this );
33379 
33380  this.type = 'TorusGeometry';
33381 
33382  this.parameters = {
33383  radius: radius,
33384  tube: tube,
33385  radialSegments: radialSegments,
33386  tubularSegments: tubularSegments,
33387  arc: arc
33388  };
33389 
33390  radius = radius || 100;
33391  tube = tube || 40;
33392  radialSegments = radialSegments || 8;
33393  tubularSegments = tubularSegments || 6;
33394  arc = arc || Math.PI * 2;
33395 
33396  var center = new THREE.Vector3(), uvs = [], normals = [];
33397 
33398  for ( var j = 0; j <= radialSegments; j ++ ) {
33399 
33400  for ( var i = 0; i <= tubularSegments; i ++ ) {
33401 
33402  var u = i / tubularSegments * arc;
33403  var v = j / radialSegments * Math.PI * 2;
33404 
33405  center.x = radius * Math.cos( u );
33406  center.y = radius * Math.sin( u );
33407 
33408  var vertex = new THREE.Vector3();
33409  vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
33410  vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
33411  vertex.z = tube * Math.sin( v );
33412 
33413  this.vertices.push( vertex );
33414 
33415  uvs.push( new THREE.Vector2( i / tubularSegments, j / radialSegments ) );
33416  normals.push( vertex.clone().sub( center ).normalize() );
33417 
33418  }
33419 
33420  }
33421 
33422  for ( var j = 1; j <= radialSegments; j ++ ) {
33423 
33424  for ( var i = 1; i <= tubularSegments; i ++ ) {
33425 
33426  var a = ( tubularSegments + 1 ) * j + i - 1;
33427  var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
33428  var c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
33429  var d = ( tubularSegments + 1 ) * j + i;
33430 
33431  var face = new THREE.Face3( a, b, d, [ normals[ a ].clone(), normals[ b ].clone(), normals[ d ].clone() ] );
33432  this.faces.push( face );
33433  this.faceVertexUvs[ 0 ].push( [ uvs[ a ].clone(), uvs[ b ].clone(), uvs[ d ].clone() ] );
33434 
33435  face = new THREE.Face3( b, c, d, [ normals[ b ].clone(), normals[ c ].clone(), normals[ d ].clone() ] );
33436  this.faces.push( face );
33437  this.faceVertexUvs[ 0 ].push( [ uvs[ b ].clone(), uvs[ c ].clone(), uvs[ d ].clone() ] );
33438 
33439  }
33440 
33441  }
33442 
33443  this.computeFaceNormals();
33444 
33445 };
33446 
33447 THREE.TorusGeometry.prototype = Object.create( THREE.Geometry.prototype );
33448 THREE.TorusGeometry.prototype.constructor = THREE.TorusGeometry;
33449 
33450 THREE.TorusGeometry.prototype.clone = function () {
33451 
33452  var parameters = this.parameters;
33453 
33454  return new THREE.TorusGeometry(
33455  parameters.radius,
33456  parameters.tube,
33457  parameters.radialSegments,
33458  parameters.tubularSegments,
33459  parameters.arc
33460  );
33461 
33462 };
33463 
33464 // File:src/extras/geometries/TorusKnotGeometry.js
33465 
33471 THREE.TorusKnotGeometry = function ( radius, tube, radialSegments, tubularSegments, p, q, heightScale ) {
33472 
33473  THREE.Geometry.call( this );
33474 
33475  this.type = 'TorusKnotGeometry';
33476 
33477  this.parameters = {
33478  radius: radius,
33479  tube: tube,
33480  radialSegments: radialSegments,
33481  tubularSegments: tubularSegments,
33482  p: p,
33483  q: q,
33484  heightScale: heightScale
33485  };
33486 
33487  radius = radius || 100;
33488  tube = tube || 40;
33489  radialSegments = radialSegments || 64;
33490  tubularSegments = tubularSegments || 8;
33491  p = p || 2;
33492  q = q || 3;
33493  heightScale = heightScale || 1;
33494 
33495  var grid = new Array( radialSegments );
33496  var tang = new THREE.Vector3();
33497  var n = new THREE.Vector3();
33498  var bitan = new THREE.Vector3();
33499 
33500  for ( var i = 0; i < radialSegments; ++ i ) {
33501 
33502  grid[ i ] = new Array( tubularSegments );
33503  var u = i / radialSegments * 2 * p * Math.PI;
33504  var p1 = getPos( u, q, p, radius, heightScale );
33505  var p2 = getPos( u + 0.01, q, p, radius, heightScale );
33506  tang.subVectors( p2, p1 );
33507  n.addVectors( p2, p1 );
33508 
33509  bitan.crossVectors( tang, n );
33510  n.crossVectors( bitan, tang );
33511  bitan.normalize();
33512  n.normalize();
33513 
33514  for ( var j = 0; j < tubularSegments; ++ j ) {
33515 
33516  var v = j / tubularSegments * 2 * Math.PI;
33517  var cx = - tube * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
33518  var cy = tube * Math.sin( v );
33519 
33520  var pos = new THREE.Vector3();
33521  pos.x = p1.x + cx * n.x + cy * bitan.x;
33522  pos.y = p1.y + cx * n.y + cy * bitan.y;
33523  pos.z = p1.z + cx * n.z + cy * bitan.z;
33524 
33525  grid[ i ][ j ] = this.vertices.push( pos ) - 1;
33526 
33527  }
33528 
33529  }
33530 
33531  for ( var i = 0; i < radialSegments; ++ i ) {
33532 
33533  for ( var j = 0; j < tubularSegments; ++ j ) {
33534 
33535  var ip = ( i + 1 ) % radialSegments;
33536  var jp = ( j + 1 ) % tubularSegments;
33537 
33538  var a = grid[ i ][ j ];
33539  var b = grid[ ip ][ j ];
33540  var c = grid[ ip ][ jp ];
33541  var d = grid[ i ][ jp ];
33542 
33543  var uva = new THREE.Vector2( i / radialSegments, j / tubularSegments );
33544  var uvb = new THREE.Vector2( ( i + 1 ) / radialSegments, j / tubularSegments );
33545  var uvc = new THREE.Vector2( ( i + 1 ) / radialSegments, ( j + 1 ) / tubularSegments );
33546  var uvd = new THREE.Vector2( i / radialSegments, ( j + 1 ) / tubularSegments );
33547 
33548  this.faces.push( new THREE.Face3( a, b, d ) );
33549  this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );
33550 
33551  this.faces.push( new THREE.Face3( b, c, d ) );
33552  this.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );
33553 
33554  }
33555 
33556  }
33557 
33558  this.computeFaceNormals();
33559  this.computeVertexNormals();
33560 
33561  function getPos( u, in_q, in_p, radius, heightScale ) {
33562 
33563  var cu = Math.cos( u );
33564  var su = Math.sin( u );
33565  var quOverP = in_q / in_p * u;
33566  var cs = Math.cos( quOverP );
33567 
33568  var tx = radius * ( 2 + cs ) * 0.5 * cu;
33569  var ty = radius * ( 2 + cs ) * su * 0.5;
33570  var tz = heightScale * radius * Math.sin( quOverP ) * 0.5;
33571 
33572  return new THREE.Vector3( tx, ty, tz );
33573 
33574  }
33575 
33576 };
33577 
33578 THREE.TorusKnotGeometry.prototype = Object.create( THREE.Geometry.prototype );
33579 THREE.TorusKnotGeometry.prototype.constructor = THREE.TorusKnotGeometry;
33580 
33581 THREE.TorusKnotGeometry.prototype.clone = function () {
33582 
33583  var parameters = this.parameters;
33584 
33585  return new THREE.TorusKnotGeometry(
33586  parameters.radius,
33587  parameters.tube,
33588  parameters.radialSegments,
33589  parameters.tubularSegments,
33590  parameters.p,
33591  parameters.q,
33592  parameters.heightScale
33593  );
33594 
33595 };
33596 
33597 // File:src/extras/geometries/TubeGeometry.js
33598 
33613 THREE.TubeGeometry = function ( path, segments, radius, radialSegments, closed, taper ) {
33614 
33615  THREE.Geometry.call( this );
33616 
33617  this.type = 'TubeGeometry';
33618 
33619  this.parameters = {
33620  path: path,
33621  segments: segments,
33622  radius: radius,
33623  radialSegments: radialSegments,
33624  closed: closed,
33625  taper: taper
33626  };
33627 
33628  segments = segments || 64;
33629  radius = radius || 1;
33630  radialSegments = radialSegments || 8;
33631  closed = closed || false;
33632  taper = taper || THREE.TubeGeometry.NoTaper;
33633 
33634  var grid = [];
33635 
33636  var scope = this,
33637 
33638  tangent,
33639  normal,
33640  binormal,
33641 
33642  numpoints = segments + 1,
33643 
33644  u, v, r,
33645 
33646  cx, cy,
33647  pos, pos2 = new THREE.Vector3(),
33648  i, j,
33649  ip, jp,
33650  a, b, c, d,
33651  uva, uvb, uvc, uvd;
33652 
33653  var frames = new THREE.TubeGeometry.FrenetFrames( path, segments, closed ),
33654  tangents = frames.tangents,
33655  normals = frames.normals,
33656  binormals = frames.binormals;
33657 
33658  // proxy internals
33659  this.tangents = tangents;
33660  this.normals = normals;
33661  this.binormals = binormals;
33662 
33663  function vert( x, y, z ) {
33664 
33665  return scope.vertices.push( new THREE.Vector3( x, y, z ) ) - 1;
33666 
33667  }
33668 
33669  // construct the grid
33670 
33671  for ( i = 0; i < numpoints; i ++ ) {
33672 
33673  grid[ i ] = [];
33674 
33675  u = i / ( numpoints - 1 );
33676 
33677  pos = path.getPointAt( u );
33678 
33679  tangent = tangents[ i ];
33680  normal = normals[ i ];
33681  binormal = binormals[ i ];
33682 
33683  r = radius * taper( u );
33684 
33685  for ( j = 0; j < radialSegments; j ++ ) {
33686 
33687  v = j / radialSegments * 2 * Math.PI;
33688 
33689  cx = - r * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
33690  cy = r * Math.sin( v );
33691 
33692  pos2.copy( pos );
33693  pos2.x += cx * normal.x + cy * binormal.x;
33694  pos2.y += cx * normal.y + cy * binormal.y;
33695  pos2.z += cx * normal.z + cy * binormal.z;
33696 
33697  grid[ i ][ j ] = vert( pos2.x, pos2.y, pos2.z );
33698 
33699  }
33700 
33701  }
33702 
33703 
33704  // construct the mesh
33705 
33706  for ( i = 0; i < segments; i ++ ) {
33707 
33708  for ( j = 0; j < radialSegments; j ++ ) {
33709 
33710  ip = ( closed ) ? ( i + 1 ) % segments : i + 1;
33711  jp = ( j + 1 ) % radialSegments;
33712 
33713  a = grid[ i ][ j ]; // *** NOT NECESSARILY PLANAR ! ***
33714  b = grid[ ip ][ j ];
33715  c = grid[ ip ][ jp ];
33716  d = grid[ i ][ jp ];
33717 
33718  uva = new THREE.Vector2( i / segments, j / radialSegments );
33719  uvb = new THREE.Vector2( ( i + 1 ) / segments, j / radialSegments );
33720  uvc = new THREE.Vector2( ( i + 1 ) / segments, ( j + 1 ) / radialSegments );
33721  uvd = new THREE.Vector2( i / segments, ( j + 1 ) / radialSegments );
33722 
33723  this.faces.push( new THREE.Face3( a, b, d ) );
33724  this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );
33725 
33726  this.faces.push( new THREE.Face3( b, c, d ) );
33727  this.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );
33728 
33729  }
33730 
33731  }
33732 
33733  this.computeFaceNormals();
33734  this.computeVertexNormals();
33735 
33736 };
33737 
33738 THREE.TubeGeometry.prototype = Object.create( THREE.Geometry.prototype );
33739 THREE.TubeGeometry.prototype.constructor = THREE.TubeGeometry;
33740 THREE.TubeGeometry.prototype.clone = function() {
33741 
33742  return new this.constructor( this.parameters.path,
33743  this.parameters.segments, this.parameters.radius, this.parameters.radialSegments,
33744  this.parameters.closed, this.parameters.taper
33745  );
33746 
33747 };
33748 
33749 THREE.TubeGeometry.NoTaper = function ( u ) {
33750 
33751  return 1;
33752 
33753 };
33754 
33755 THREE.TubeGeometry.SinusoidalTaper = function ( u ) {
33756 
33757  return Math.sin( Math.PI * u );
33758 
33759 };
33760 
33761 // For computing of Frenet frames, exposing the tangents, normals and binormals the spline
33762 THREE.TubeGeometry.FrenetFrames = function ( path, segments, closed ) {
33763 
33764  var normal = new THREE.Vector3(),
33765 
33766  tangents = [],
33767  normals = [],
33768  binormals = [],
33769 
33770  vec = new THREE.Vector3(),
33771  mat = new THREE.Matrix4(),
33772 
33773  numpoints = segments + 1,
33774  theta,
33775  smallest,
33776 
33777  tx, ty, tz,
33778  i, u;
33779 
33780 
33781  // expose internals
33782  this.tangents = tangents;
33783  this.normals = normals;
33784  this.binormals = binormals;
33785 
33786  // compute the tangent vectors for each segment on the path
33787 
33788  for ( i = 0; i < numpoints; i ++ ) {
33789 
33790  u = i / ( numpoints - 1 );
33791 
33792  tangents[ i ] = path.getTangentAt( u );
33793  tangents[ i ].normalize();
33794 
33795  }
33796 
33797  initialNormal3();
33798 
33799  /*
33800  function initialNormal1(lastBinormal) {
33801  // fixed start binormal. Has dangers of 0 vectors
33802  normals[ 0 ] = new THREE.Vector3();
33803  binormals[ 0 ] = new THREE.Vector3();
33804  if (lastBinormal===undefined) lastBinormal = new THREE.Vector3( 0, 0, 1 );
33805  normals[ 0 ].crossVectors( lastBinormal, tangents[ 0 ] ).normalize();
33806  binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ).normalize();
33807  }
33808 
33809  function initialNormal2() {
33810 
33811  // This uses the Frenet-Serret formula for deriving binormal
33812  var t2 = path.getTangentAt( epsilon );
33813 
33814  normals[ 0 ] = new THREE.Vector3().subVectors( t2, tangents[ 0 ] ).normalize();
33815  binormals[ 0 ] = new THREE.Vector3().crossVectors( tangents[ 0 ], normals[ 0 ] );
33816 
33817  normals[ 0 ].crossVectors( binormals[ 0 ], tangents[ 0 ] ).normalize(); // last binormal x tangent
33818  binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ).normalize();
33819 
33820  }
33821  */
33822 
33823  function initialNormal3() {
33824 
33825  // select an initial normal vector perpendicular to the first tangent vector,
33826  // and in the direction of the smallest tangent xyz component
33827 
33828  normals[ 0 ] = new THREE.Vector3();
33829  binormals[ 0 ] = new THREE.Vector3();
33830  smallest = Number.MAX_VALUE;
33831  tx = Math.abs( tangents[ 0 ].x );
33832  ty = Math.abs( tangents[ 0 ].y );
33833  tz = Math.abs( tangents[ 0 ].z );
33834 
33835  if ( tx <= smallest ) {
33836 
33837  smallest = tx;
33838  normal.set( 1, 0, 0 );
33839 
33840  }
33841 
33842  if ( ty <= smallest ) {
33843 
33844  smallest = ty;
33845  normal.set( 0, 1, 0 );
33846 
33847  }
33848 
33849  if ( tz <= smallest ) {
33850 
33851  normal.set( 0, 0, 1 );
33852 
33853  }
33854 
33855  vec.crossVectors( tangents[ 0 ], normal ).normalize();
33856 
33857  normals[ 0 ].crossVectors( tangents[ 0 ], vec );
33858  binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
33859 
33860  }
33861 
33862 
33863  // compute the slowly-varying normal and binormal vectors for each segment on the path
33864 
33865  for ( i = 1; i < numpoints; i ++ ) {
33866 
33867  normals[ i ] = normals[ i - 1 ].clone();
33868 
33869  binormals[ i ] = binormals[ i - 1 ].clone();
33870 
33871  vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
33872 
33873  if ( vec.length() > Number.EPSILON ) {
33874 
33875  vec.normalize();
33876 
33877  theta = Math.acos( THREE.Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
33878 
33879  normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
33880 
33881  }
33882 
33883  binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
33884 
33885  }
33886 
33887 
33888  // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
33889 
33890  if ( closed ) {
33891 
33892  theta = Math.acos( THREE.Math.clamp( normals[ 0 ].dot( normals[ numpoints - 1 ] ), - 1, 1 ) );
33893  theta /= ( numpoints - 1 );
33894 
33895  if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ numpoints - 1 ] ) ) > 0 ) {
33896 
33897  theta = - theta;
33898 
33899  }
33900 
33901  for ( i = 1; i < numpoints; i ++ ) {
33902 
33903  // twist a little...
33904  normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
33905  binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
33906 
33907  }
33908 
33909  }
33910 
33911 };
33912 
33913 // File:src/extras/geometries/PolyhedronGeometry.js
33914 
33921 THREE.PolyhedronGeometry = function ( vertices, indices, radius, detail ) {
33922 
33923  THREE.Geometry.call( this );
33924 
33925  this.type = 'PolyhedronGeometry';
33926 
33927  this.parameters = {
33928  vertices: vertices,
33929  indices: indices,
33930  radius: radius,
33931  detail: detail
33932  };
33933 
33934  radius = radius || 1;
33935  detail = detail || 0;
33936 
33937  var that = this;
33938 
33939  for ( var i = 0, l = vertices.length; i < l; i += 3 ) {
33940 
33941  prepare( new THREE.Vector3( vertices[ i ], vertices[ i + 1 ], vertices[ i + 2 ] ) );
33942 
33943  }
33944 
33945  var p = this.vertices;
33946 
33947  var faces = [];
33948 
33949  for ( var i = 0, j = 0, l = indices.length; i < l; i += 3, j ++ ) {
33950 
33951  var v1 = p[ indices[ i ] ];
33952  var v2 = p[ indices[ i + 1 ] ];
33953  var v3 = p[ indices[ i + 2 ] ];
33954 
33955  faces[ j ] = new THREE.Face3( v1.index, v2.index, v3.index, [ v1.clone(), v2.clone(), v3.clone() ], undefined, j );
33956 
33957  }
33958 
33959  var centroid = new THREE.Vector3();
33960 
33961  for ( var i = 0, l = faces.length; i < l; i ++ ) {
33962 
33963  subdivide( faces[ i ], detail );
33964 
33965  }
33966 
33967 
33968  // Handle case when face straddles the seam
33969 
33970  for ( var i = 0, l = this.faceVertexUvs[ 0 ].length; i < l; i ++ ) {
33971 
33972  var uvs = this.faceVertexUvs[ 0 ][ i ];
33973 
33974  var x0 = uvs[ 0 ].x;
33975  var x1 = uvs[ 1 ].x;
33976  var x2 = uvs[ 2 ].x;
33977 
33978  var max = Math.max( x0, x1, x2 );
33979  var min = Math.min( x0, x1, x2 );
33980 
33981  if ( max > 0.9 && min < 0.1 ) {
33982 
33983  // 0.9 is somewhat arbitrary
33984 
33985  if ( x0 < 0.2 ) uvs[ 0 ].x += 1;
33986  if ( x1 < 0.2 ) uvs[ 1 ].x += 1;
33987  if ( x2 < 0.2 ) uvs[ 2 ].x += 1;
33988 
33989  }
33990 
33991  }
33992 
33993 
33994  // Apply radius
33995 
33996  for ( var i = 0, l = this.vertices.length; i < l; i ++ ) {
33997 
33998  this.vertices[ i ].multiplyScalar( radius );
33999 
34000  }
34001 
34002 
34003  // Merge vertices
34004 
34005  this.mergeVertices();
34006 
34007  this.computeFaceNormals();
34008 
34009  this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
34010 
34011 
34012  // Project vector onto sphere's surface
34013 
34014  function prepare( vector ) {
34015 
34016  var vertex = vector.normalize().clone();
34017  vertex.index = that.vertices.push( vertex ) - 1;
34018 
34019  // Texture coords are equivalent to map coords, calculate angle and convert to fraction of a circle.
34020 
34021  var u = azimuth( vector ) / 2 / Math.PI + 0.5;
34022  var v = inclination( vector ) / Math.PI + 0.5;
34023  vertex.uv = new THREE.Vector2( u, 1 - v );
34024 
34025  return vertex;
34026 
34027  }
34028 
34029 
34030  // Approximate a curved face with recursively sub-divided triangles.
34031 
34032  function make( v1, v2, v3, materialIndex ) {
34033 
34034  var face = new THREE.Face3( v1.index, v2.index, v3.index, [ v1.clone(), v2.clone(), v3.clone() ], undefined, materialIndex );
34035  that.faces.push( face );
34036 
34037  centroid.copy( v1 ).add( v2 ).add( v3 ).divideScalar( 3 );
34038 
34039  var azi = azimuth( centroid );
34040 
34041  that.faceVertexUvs[ 0 ].push( [
34042  correctUV( v1.uv, v1, azi ),
34043  correctUV( v2.uv, v2, azi ),
34044  correctUV( v3.uv, v3, azi )
34045  ] );
34046 
34047  }
34048 
34049 
34050  // Analytically subdivide a face to the required detail level.
34051 
34052  function subdivide( face, detail ) {
34053 
34054  var cols = Math.pow( 2, detail );
34055  var a = prepare( that.vertices[ face.a ] );
34056  var b = prepare( that.vertices[ face.b ] );
34057  var c = prepare( that.vertices[ face.c ] );
34058  var v = [];
34059 
34060  var materialIndex = face.materialIndex;
34061 
34062  // Construct all of the vertices for this subdivision.
34063 
34064  for ( var i = 0 ; i <= cols; i ++ ) {
34065 
34066  v[ i ] = [];
34067 
34068  var aj = prepare( a.clone().lerp( c, i / cols ) );
34069  var bj = prepare( b.clone().lerp( c, i / cols ) );
34070  var rows = cols - i;
34071 
34072  for ( var j = 0; j <= rows; j ++ ) {
34073 
34074  if ( j === 0 && i === cols ) {
34075 
34076  v[ i ][ j ] = aj;
34077 
34078  } else {
34079 
34080  v[ i ][ j ] = prepare( aj.clone().lerp( bj, j / rows ) );
34081 
34082  }
34083 
34084  }
34085 
34086  }
34087 
34088  // Construct all of the faces.
34089 
34090  for ( var i = 0; i < cols ; i ++ ) {
34091 
34092  for ( var j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
34093 
34094  var k = Math.floor( j / 2 );
34095 
34096  if ( j % 2 === 0 ) {
34097 
34098  make(
34099  v[ i ][ k + 1 ],
34100  v[ i + 1 ][ k ],
34101  v[ i ][ k ],
34102  materialIndex
34103  );
34104 
34105  } else {
34106 
34107  make(
34108  v[ i ][ k + 1 ],
34109  v[ i + 1 ][ k + 1 ],
34110  v[ i + 1 ][ k ],
34111  materialIndex
34112  );
34113 
34114  }
34115 
34116  }
34117 
34118  }
34119 
34120  }
34121 
34122 
34123  // Angle around the Y axis, counter-clockwise when looking from above.
34124 
34125  function azimuth( vector ) {
34126 
34127  return Math.atan2( vector.z, - vector.x );
34128 
34129  }
34130 
34131 
34132  // Angle above the XZ plane.
34133 
34134  function inclination( vector ) {
34135 
34136  return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
34137 
34138  }
34139 
34140 
34141  // Texture fixing helper. Spheres have some odd behaviours.
34142 
34143  function correctUV( uv, vector, azimuth ) {
34144 
34145  if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) uv = new THREE.Vector2( uv.x - 1, uv.y );
34146  if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) uv = new THREE.Vector2( azimuth / 2 / Math.PI + 0.5, uv.y );
34147  return uv.clone();
34148 
34149  }
34150 
34151 
34152 };
34153 
34154 THREE.PolyhedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
34155 THREE.PolyhedronGeometry.prototype.constructor = THREE.PolyhedronGeometry;
34156 
34157 THREE.PolyhedronGeometry.prototype.clone = function () {
34158 
34159  var parameters = this.parameters;
34160 
34161  return new THREE.PolyhedronGeometry(
34162  parameters.vertices,
34163  parameters.indices,
34164  parameters.radius,
34165  parameters.detail
34166  );
34167 
34168 };
34169 
34170 // File:src/extras/geometries/DodecahedronGeometry.js
34171 
34176 THREE.DodecahedronGeometry = function ( radius, detail ) {
34177 
34178  var t = ( 1 + Math.sqrt( 5 ) ) / 2;
34179  var r = 1 / t;
34180 
34181  var vertices = [
34182 
34183  // (±1, ±1, ±1)
34184  - 1, - 1, - 1, - 1, - 1, 1,
34185  - 1, 1, - 1, - 1, 1, 1,
34186  1, - 1, - 1, 1, - 1, 1,
34187  1, 1, - 1, 1, 1, 1,
34188 
34189  // (0, ±1/φ, ±φ)
34190  0, - r, - t, 0, - r, t,
34191  0, r, - t, 0, r, t,
34192 
34193  // (±1/φ, ±φ, 0)
34194  - r, - t, 0, - r, t, 0,
34195  r, - t, 0, r, t, 0,
34196 
34197  // (±φ, 0, ±1/φ)
34198  - t, 0, - r, t, 0, - r,
34199  - t, 0, r, t, 0, r
34200  ];
34201 
34202  var indices = [
34203  3, 11, 7, 3, 7, 15, 3, 15, 13,
34204  7, 19, 17, 7, 17, 6, 7, 6, 15,
34205  17, 4, 8, 17, 8, 10, 17, 10, 6,
34206  8, 0, 16, 8, 16, 2, 8, 2, 10,
34207  0, 12, 1, 0, 1, 18, 0, 18, 16,
34208  6, 10, 2, 6, 2, 13, 6, 13, 15,
34209  2, 16, 18, 2, 18, 3, 2, 3, 13,
34210  18, 1, 9, 18, 9, 11, 18, 11, 3,
34211  4, 14, 12, 4, 12, 0, 4, 0, 8,
34212  11, 9, 5, 11, 5, 19, 11, 19, 7,
34213  19, 5, 14, 19, 14, 4, 19, 4, 17,
34214  1, 12, 14, 1, 14, 5, 1, 5, 9
34215  ];
34216 
34217  THREE.PolyhedronGeometry.call( this, vertices, indices, radius, detail );
34218 
34219  this.type = 'DodecahedronGeometry';
34220 
34221  this.parameters = {
34222  radius: radius,
34223  detail: detail
34224  };
34225 
34226 };
34227 
34228 THREE.DodecahedronGeometry.prototype = Object.create( THREE.PolyhedronGeometry.prototype );
34229 THREE.DodecahedronGeometry.prototype.constructor = THREE.DodecahedronGeometry;
34230 
34231 THREE.DodecahedronGeometry.prototype.clone = function () {
34232 
34233  var parameters = this.parameters;
34234 
34235  return new THREE.DodecahedronGeometry(
34236  parameters.radius,
34237  parameters.detail
34238  );
34239 
34240 };
34241 
34242 // File:src/extras/geometries/IcosahedronGeometry.js
34243 
34248 THREE.IcosahedronGeometry = function ( radius, detail ) {
34249 
34250  var t = ( 1 + Math.sqrt( 5 ) ) / 2;
34251 
34252  var vertices = [
34253  - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0,
34254  0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t,
34255  t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1
34256  ];
34257 
34258  var indices = [
34259  0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11,
34260  1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
34261  3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9,
34262  4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1
34263  ];
34264 
34265  THREE.PolyhedronGeometry.call( this, vertices, indices, radius, detail );
34266 
34267  this.type = 'IcosahedronGeometry';
34268 
34269  this.parameters = {
34270  radius: radius,
34271  detail: detail
34272  };
34273 
34274 };
34275 
34276 THREE.IcosahedronGeometry.prototype = Object.create( THREE.PolyhedronGeometry.prototype );
34277 THREE.IcosahedronGeometry.prototype.constructor = THREE.IcosahedronGeometry;
34278 
34279 THREE.IcosahedronGeometry.prototype.clone = function () {
34280 
34281  var parameters = this.parameters;
34282 
34283  return new THREE.IcosahedronGeometry(
34284  parameters.radius,
34285  parameters.detail
34286  );
34287 
34288 };
34289 
34290 // File:src/extras/geometries/OctahedronGeometry.js
34291 
34296 THREE.OctahedronGeometry = function ( radius, detail ) {
34297 
34298  var vertices = [
34299  1, 0, 0, - 1, 0, 0, 0, 1, 0, 0, - 1, 0, 0, 0, 1, 0, 0, - 1
34300  ];
34301 
34302  var indices = [
34303  0, 2, 4, 0, 4, 3, 0, 3, 5, 0, 5, 2, 1, 2, 5, 1, 5, 3, 1, 3, 4, 1, 4, 2
34304  ];
34305 
34306  THREE.PolyhedronGeometry.call( this, vertices, indices, radius, detail );
34307 
34308  this.type = 'OctahedronGeometry';
34309 
34310  this.parameters = {
34311  radius: radius,
34312  detail: detail
34313  };
34314 
34315 };
34316 
34317 THREE.OctahedronGeometry.prototype = Object.create( THREE.PolyhedronGeometry.prototype );
34318 THREE.OctahedronGeometry.prototype.constructor = THREE.OctahedronGeometry;
34319 
34320 THREE.OctahedronGeometry.prototype.clone = function () {
34321 
34322  var parameters = this.parameters;
34323 
34324  return new THREE.OctahedronGeometry(
34325  parameters.radius,
34326  parameters.detail
34327  );
34328 
34329 };
34330 
34331 // File:src/extras/geometries/TetrahedronGeometry.js
34332 
34337 THREE.TetrahedronGeometry = function ( radius, detail ) {
34338 
34339  var vertices = [
34340  1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1
34341  ];
34342 
34343  var indices = [
34344  2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1
34345  ];
34346 
34347  THREE.PolyhedronGeometry.call( this, vertices, indices, radius, detail );
34348 
34349  this.type = 'TetrahedronGeometry';
34350 
34351  this.parameters = {
34352  radius: radius,
34353  detail: detail
34354  };
34355 
34356 };
34357 
34358 THREE.TetrahedronGeometry.prototype = Object.create( THREE.PolyhedronGeometry.prototype );
34359 THREE.TetrahedronGeometry.prototype.constructor = THREE.TetrahedronGeometry;
34360 
34361 THREE.TetrahedronGeometry.prototype.clone = function () {
34362 
34363  var parameters = this.parameters;
34364 
34365  return new THREE.TetrahedronGeometry(
34366  parameters.radius,
34367  parameters.detail
34368  );
34369 
34370 };
34371 
34372 // File:src/extras/geometries/ParametricGeometry.js
34373 
34383 THREE.ParametricGeometry = function ( func, slices, stacks ) {
34384 
34385  THREE.Geometry.call( this );
34386 
34387  this.type = 'ParametricGeometry';
34388 
34389  this.parameters = {
34390  func: func,
34391  slices: slices,
34392  stacks: stacks
34393  };
34394 
34395  var verts = this.vertices;
34396  var faces = this.faces;
34397  var uvs = this.faceVertexUvs[ 0 ];
34398 
34399  var i, j, p;
34400  var u, v;
34401 
34402  var sliceCount = slices + 1;
34403 
34404  for ( i = 0; i <= stacks; i ++ ) {
34405 
34406  v = i / stacks;
34407 
34408  for ( j = 0; j <= slices; j ++ ) {
34409 
34410  u = j / slices;
34411 
34412  p = func( u, v );
34413  verts.push( p );
34414 
34415  }
34416 
34417  }
34418 
34419  var a, b, c, d;
34420  var uva, uvb, uvc, uvd;
34421 
34422  for ( i = 0; i < stacks; i ++ ) {
34423 
34424  for ( j = 0; j < slices; j ++ ) {
34425 
34426  a = i * sliceCount + j;
34427  b = i * sliceCount + j + 1;
34428  c = ( i + 1 ) * sliceCount + j + 1;
34429  d = ( i + 1 ) * sliceCount + j;
34430 
34431  uva = new THREE.Vector2( j / slices, i / stacks );
34432  uvb = new THREE.Vector2( ( j + 1 ) / slices, i / stacks );
34433  uvc = new THREE.Vector2( ( j + 1 ) / slices, ( i + 1 ) / stacks );
34434  uvd = new THREE.Vector2( j / slices, ( i + 1 ) / stacks );
34435 
34436  faces.push( new THREE.Face3( a, b, d ) );
34437  uvs.push( [ uva, uvb, uvd ] );
34438 
34439  faces.push( new THREE.Face3( b, c, d ) );
34440  uvs.push( [ uvb.clone(), uvc, uvd.clone() ] );
34441 
34442  }
34443 
34444  }
34445 
34446  // console.log(this);
34447 
34448  // magic bullet
34449  // var diff = this.mergeVertices();
34450  // console.log('removed ', diff, ' vertices by merging');
34451 
34452  this.computeFaceNormals();
34453  this.computeVertexNormals();
34454 
34455 };
34456 
34457 THREE.ParametricGeometry.prototype = Object.create( THREE.Geometry.prototype );
34458 THREE.ParametricGeometry.prototype.constructor = THREE.ParametricGeometry;
34459 
34460 // File:src/extras/geometries/WireframeGeometry.js
34461 
34466 THREE.WireframeGeometry = function ( geometry ) {
34467 
34468  THREE.BufferGeometry.call( this );
34469 
34470  var edge = [ 0, 0 ], hash = {};
34471 
34472  function sortFunction( a, b ) {
34473 
34474  return a - b;
34475 
34476  }
34477 
34478  var keys = [ 'a', 'b', 'c' ];
34479 
34480  if ( geometry instanceof THREE.Geometry ) {
34481 
34482  var vertices = geometry.vertices;
34483  var faces = geometry.faces;
34484  var numEdges = 0;
34485 
34486  // allocate maximal size
34487  var edges = new Uint32Array( 6 * faces.length );
34488 
34489  for ( var i = 0, l = faces.length; i < l; i ++ ) {
34490 
34491  var face = faces[ i ];
34492 
34493  for ( var j = 0; j < 3; j ++ ) {
34494 
34495  edge[ 0 ] = face[ keys[ j ] ];
34496  edge[ 1 ] = face[ keys[ ( j + 1 ) % 3 ] ];
34497  edge.sort( sortFunction );
34498 
34499  var key = edge.toString();
34500 
34501  if ( hash[ key ] === undefined ) {
34502 
34503  edges[ 2 * numEdges ] = edge[ 0 ];
34504  edges[ 2 * numEdges + 1 ] = edge[ 1 ];
34505  hash[ key ] = true;
34506  numEdges ++;
34507 
34508  }
34509 
34510  }
34511 
34512  }
34513 
34514  var coords = new Float32Array( numEdges * 2 * 3 );
34515 
34516  for ( var i = 0, l = numEdges; i < l; i ++ ) {
34517 
34518  for ( var j = 0; j < 2; j ++ ) {
34519 
34520  var vertex = vertices[ edges [ 2 * i + j ] ];
34521 
34522  var index = 6 * i + 3 * j;
34523  coords[ index + 0 ] = vertex.x;
34524  coords[ index + 1 ] = vertex.y;
34525  coords[ index + 2 ] = vertex.z;
34526 
34527  }
34528 
34529  }
34530 
34531  this.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
34532 
34533  } else if ( geometry instanceof THREE.BufferGeometry ) {
34534 
34535  if ( geometry.index !== null ) {
34536 
34537  // Indexed BufferGeometry
34538 
34539  var indices = geometry.index.array;
34540  var vertices = geometry.attributes.position;
34541  var drawcalls = geometry.drawcalls;
34542  var numEdges = 0;
34543 
34544  if ( drawcalls.length === 0 ) {
34545 
34546  geometry.addGroup( 0, indices.length );
34547 
34548  }
34549 
34550  // allocate maximal size
34551  var edges = new Uint32Array( 2 * indices.length );
34552 
34553  for ( var o = 0, ol = drawcalls.length; o < ol; ++ o ) {
34554 
34555  var drawcall = drawcalls[ o ];
34556 
34557  var start = drawcall.start;
34558  var count = drawcall.count;
34559 
34560  for ( var i = start, il = start + count; i < il; i += 3 ) {
34561 
34562  for ( var j = 0; j < 3; j ++ ) {
34563 
34564  edge[ 0 ] = indices[ i + j ];
34565  edge[ 1 ] = indices[ i + ( j + 1 ) % 3 ];
34566  edge.sort( sortFunction );
34567 
34568  var key = edge.toString();
34569 
34570  if ( hash[ key ] === undefined ) {
34571 
34572  edges[ 2 * numEdges ] = edge[ 0 ];
34573  edges[ 2 * numEdges + 1 ] = edge[ 1 ];
34574  hash[ key ] = true;
34575  numEdges ++;
34576 
34577  }
34578 
34579  }
34580 
34581  }
34582 
34583  }
34584 
34585  var coords = new Float32Array( numEdges * 2 * 3 );
34586 
34587  for ( var i = 0, l = numEdges; i < l; i ++ ) {
34588 
34589  for ( var j = 0; j < 2; j ++ ) {
34590 
34591  var index = 6 * i + 3 * j;
34592  var index2 = edges[ 2 * i + j ];
34593 
34594  coords[ index + 0 ] = vertices.getX( index2 );
34595  coords[ index + 1 ] = vertices.getY( index2 );
34596  coords[ index + 2 ] = vertices.getZ( index2 );
34597 
34598  }
34599 
34600  }
34601 
34602  this.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
34603 
34604  } else {
34605 
34606  // non-indexed BufferGeometry
34607 
34608  var vertices = geometry.attributes.position.array;
34609  var numEdges = vertices.length / 3;
34610  var numTris = numEdges / 3;
34611 
34612  var coords = new Float32Array( numEdges * 2 * 3 );
34613 
34614  for ( var i = 0, l = numTris; i < l; i ++ ) {
34615 
34616  for ( var j = 0; j < 3; j ++ ) {
34617 
34618  var index = 18 * i + 6 * j;
34619 
34620  var index1 = 9 * i + 3 * j;
34621  coords[ index + 0 ] = vertices[ index1 ];
34622  coords[ index + 1 ] = vertices[ index1 + 1 ];
34623  coords[ index + 2 ] = vertices[ index1 + 2 ];
34624 
34625  var index2 = 9 * i + 3 * ( ( j + 1 ) % 3 );
34626  coords[ index + 3 ] = vertices[ index2 ];
34627  coords[ index + 4 ] = vertices[ index2 + 1 ];
34628  coords[ index + 5 ] = vertices[ index2 + 2 ];
34629 
34630  }
34631 
34632  }
34633 
34634  this.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
34635 
34636  }
34637 
34638  }
34639 
34640 };
34641 
34642 THREE.WireframeGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
34643 THREE.WireframeGeometry.prototype.constructor = THREE.WireframeGeometry;
34644 
34645 // File:src/extras/helpers/AxisHelper.js
34646 
34652 THREE.AxisHelper = function ( size ) {
34653 
34654  size = size || 1;
34655 
34656  var vertices = new Float32Array( [
34657  0, 0, 0, size, 0, 0,
34658  0, 0, 0, 0, size, 0,
34659  0, 0, 0, 0, 0, size
34660  ] );
34661 
34662  var colors = new Float32Array( [
34663  1, 0, 0, 1, 0.6, 0,
34664  0, 1, 0, 0.6, 1, 0,
34665  0, 0, 1, 0, 0.6, 1
34666  ] );
34667 
34668  var geometry = new THREE.BufferGeometry();
34669  geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
34670  geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
34671 
34672  var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
34673 
34674  THREE.LineSegments.call( this, geometry, material );
34675 
34676 };
34677 
34678 THREE.AxisHelper.prototype = Object.create( THREE.LineSegments.prototype );
34679 THREE.AxisHelper.prototype.constructor = THREE.AxisHelper;
34680 
34681 // File:src/extras/helpers/ArrowHelper.js
34682 
34699 THREE.ArrowHelper = ( function () {
34700 
34701  var lineGeometry = new THREE.Geometry();
34702  lineGeometry.vertices.push( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) );
34703 
34704  var coneGeometry = new THREE.CylinderGeometry( 0, 0.5, 1, 5, 1 );
34705  coneGeometry.translate( 0, - 0.5, 0 );
34706 
34707  return function ArrowHelper( dir, origin, length, color, headLength, headWidth ) {
34708 
34709  // dir is assumed to be normalized
34710 
34711  THREE.Object3D.call( this );
34712 
34713  if ( color === undefined ) color = 0xffff00;
34714  if ( length === undefined ) length = 1;
34715  if ( headLength === undefined ) headLength = 0.2 * length;
34716  if ( headWidth === undefined ) headWidth = 0.2 * headLength;
34717 
34718  this.position.copy( origin );
34719 
34720  if ( headLength < length ) {
34721  this.line = new THREE.Line( lineGeometry, new THREE.LineBasicMaterial( { color: color } ) );
34722  this.line.matrixAutoUpdate = false;
34723  this.add( this.line );
34724  }
34725 
34726  this.cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color: color } ) );
34727  this.cone.matrixAutoUpdate = false;
34728  this.add( this.cone );
34729 
34730  this.setDirection( dir );
34731  this.setLength( length, headLength, headWidth );
34732 
34733  }
34734 
34735 }() );
34736 
34737 THREE.ArrowHelper.prototype = Object.create( THREE.Object3D.prototype );
34738 THREE.ArrowHelper.prototype.constructor = THREE.ArrowHelper;
34739 
34740 THREE.ArrowHelper.prototype.setDirection = ( function () {
34741 
34742  var axis = new THREE.Vector3();
34743  var radians;
34744 
34745  return function setDirection( dir ) {
34746 
34747  // dir is assumed to be normalized
34748 
34749  if ( dir.y > 0.99999 ) {
34750 
34751  this.quaternion.set( 0, 0, 0, 1 );
34752 
34753  } else if ( dir.y < - 0.99999 ) {
34754 
34755  this.quaternion.set( 1, 0, 0, 0 );
34756 
34757  } else {
34758 
34759  axis.set( dir.z, 0, - dir.x ).normalize();
34760 
34761  radians = Math.acos( dir.y );
34762 
34763  this.quaternion.setFromAxisAngle( axis, radians );
34764 
34765  }
34766 
34767  };
34768 
34769 }() );
34770 
34771 THREE.ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {
34772 
34773  if ( headLength === undefined ) headLength = 0.2 * length;
34774  if ( headWidth === undefined ) headWidth = 0.2 * headLength;
34775 
34776  if ( headLength < length ){
34777  this.line.scale.set( 1, length - headLength, 1 );
34778  this.line.updateMatrix();
34779  }
34780 
34781  this.cone.scale.set( headWidth, headLength, headWidth );
34782  this.cone.position.y = length;
34783  this.cone.updateMatrix();
34784 
34785 };
34786 
34787 THREE.ArrowHelper.prototype.setColor = function ( color ) {
34788 
34789  if ( this.line !== undefined ) this.line.material.color.set( color );
34790  this.cone.material.color.set( color );
34791 
34792 };
34793 
34794 // File:src/extras/helpers/BoxHelper.js
34795 
34800 THREE.BoxHelper = function ( object ) {
34801 
34802  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 ] );
34803  var positions = new Float32Array( 8 * 3 );
34804 
34805  var geometry = new THREE.BufferGeometry();
34806  geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
34807  geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
34808 
34809  THREE.LineSegments.call( this, geometry, new THREE.LineBasicMaterial( { color: 0xffff00 } ) );
34810 
34811  if ( object !== undefined ) {
34812 
34813  this.update( object );
34814 
34815  }
34816 
34817 };
34818 
34819 THREE.BoxHelper.prototype = Object.create( THREE.LineSegments.prototype );
34820 THREE.BoxHelper.prototype.constructor = THREE.BoxHelper;
34821 
34822 THREE.BoxHelper.prototype.update = ( function () {
34823 
34824  var box = new THREE.Box3();
34825 
34826  return function ( object ) {
34827 
34828  box.setFromObject( object );
34829 
34830  if ( box.empty() ) return;
34831 
34832  var min = box.min;
34833  var max = box.max;
34834 
34835  /*
34836  5____4
34837  1/___0/|
34838  | 6__|_7
34839  2/___3/
34840 
34841  0: max.x, max.y, max.z
34842  1: min.x, max.y, max.z
34843  2: min.x, min.y, max.z
34844  3: max.x, min.y, max.z
34845  4: max.x, max.y, min.z
34846  5: min.x, max.y, min.z
34847  6: min.x, min.y, min.z
34848  7: max.x, min.y, min.z
34849  */
34850 
34851  var position = this.geometry.attributes.position;
34852  var array = position.array;
34853 
34854  array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
34855  array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
34856  array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
34857  array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
34858  array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
34859  array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
34860  array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
34861  array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
34862 
34863  position.needsUpdate = true;
34864 
34865  this.geometry.computeBoundingSphere();
34866 
34867  }
34868 
34869 } )();
34870 
34871 // File:src/extras/helpers/BoundingBoxHelper.js
34872 
34877 // a helper to show the world-axis-aligned bounding box for an object
34878 
34879 THREE.BoundingBoxHelper = function ( object, hex ) {
34880 
34881  var color = ( hex !== undefined ) ? hex : 0x888888;
34882 
34883  this.object = object;
34884 
34885  this.box = new THREE.Box3();
34886 
34887  THREE.Mesh.call( this, new THREE.BoxGeometry( 1, 1, 1 ), new THREE.MeshBasicMaterial( { color: color, wireframe: true } ) );
34888 
34889 };
34890 
34891 THREE.BoundingBoxHelper.prototype = Object.create( THREE.Mesh.prototype );
34892 THREE.BoundingBoxHelper.prototype.constructor = THREE.BoundingBoxHelper;
34893 
34894 THREE.BoundingBoxHelper.prototype.update = function () {
34895 
34896  this.box.setFromObject( this.object );
34897 
34898  this.box.size( this.scale );
34899 
34900  this.box.center( this.position );
34901 
34902 };
34903 
34904 // File:src/extras/helpers/CameraHelper.js
34905 
34915 THREE.CameraHelper = function ( camera ) {
34916 
34917  var geometry = new THREE.Geometry();
34918  var material = new THREE.LineBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors } );
34919 
34920  var pointMap = {};
34921 
34922  // colors
34923 
34924  var hexFrustum = 0xffaa00;
34925  var hexCone = 0xff0000;
34926  var hexUp = 0x00aaff;
34927  var hexTarget = 0xffffff;
34928  var hexCross = 0x333333;
34929 
34930  // near
34931 
34932  addLine( "n1", "n2", hexFrustum );
34933  addLine( "n2", "n4", hexFrustum );
34934  addLine( "n4", "n3", hexFrustum );
34935  addLine( "n3", "n1", hexFrustum );
34936 
34937  // far
34938 
34939  addLine( "f1", "f2", hexFrustum );
34940  addLine( "f2", "f4", hexFrustum );
34941  addLine( "f4", "f3", hexFrustum );
34942  addLine( "f3", "f1", hexFrustum );
34943 
34944  // sides
34945 
34946  addLine( "n1", "f1", hexFrustum );
34947  addLine( "n2", "f2", hexFrustum );
34948  addLine( "n3", "f3", hexFrustum );
34949  addLine( "n4", "f4", hexFrustum );
34950 
34951  // cone
34952 
34953  addLine( "p", "n1", hexCone );
34954  addLine( "p", "n2", hexCone );
34955  addLine( "p", "n3", hexCone );
34956  addLine( "p", "n4", hexCone );
34957 
34958  // up
34959 
34960  addLine( "u1", "u2", hexUp );
34961  addLine( "u2", "u3", hexUp );
34962  addLine( "u3", "u1", hexUp );
34963 
34964  // target
34965 
34966  addLine( "c", "t", hexTarget );
34967  addLine( "p", "c", hexCross );
34968 
34969  // cross
34970 
34971  addLine( "cn1", "cn2", hexCross );
34972  addLine( "cn3", "cn4", hexCross );
34973 
34974  addLine( "cf1", "cf2", hexCross );
34975  addLine( "cf3", "cf4", hexCross );
34976 
34977  function addLine( a, b, hex ) {
34978 
34979  addPoint( a, hex );
34980  addPoint( b, hex );
34981 
34982  }
34983 
34984  function addPoint( id, hex ) {
34985 
34986  geometry.vertices.push( new THREE.Vector3() );
34987  geometry.colors.push( new THREE.Color( hex ) );
34988 
34989  if ( pointMap[ id ] === undefined ) {
34990 
34991  pointMap[ id ] = [];
34992 
34993  }
34994 
34995  pointMap[ id ].push( geometry.vertices.length - 1 );
34996 
34997  }
34998 
34999  THREE.LineSegments.call( this, geometry, material );
35000 
35001  this.camera = camera;
35002  this.camera.updateProjectionMatrix();
35003 
35004  this.matrix = camera.matrixWorld;
35005  this.matrixAutoUpdate = false;
35006 
35007  this.pointMap = pointMap;
35008 
35009  this.update();
35010 
35011 };
35012 
35013 THREE.CameraHelper.prototype = Object.create( THREE.LineSegments.prototype );
35014 THREE.CameraHelper.prototype.constructor = THREE.CameraHelper;
35015 
35016 THREE.CameraHelper.prototype.update = function () {
35017 
35018  var geometry, pointMap;
35019 
35020  var vector = new THREE.Vector3();
35021  var camera = new THREE.Camera();
35022 
35023  function setPoint( point, x, y, z ) {
35024 
35025  vector.set( x, y, z ).unproject( camera );
35026 
35027  var points = pointMap[ point ];
35028 
35029  if ( points !== undefined ) {
35030 
35031  for ( var i = 0, il = points.length; i < il; i ++ ) {
35032 
35033  geometry.vertices[ points[ i ] ].copy( vector );
35034 
35035  }
35036 
35037  }
35038 
35039  }
35040 
35041  return function () {
35042 
35043  geometry = this.geometry;
35044  pointMap = this.pointMap;
35045 
35046  var w = 1, h = 1;
35047 
35048  // we need just camera projection matrix
35049  // world matrix must be identity
35050 
35051  camera.projectionMatrix.copy( this.camera.projectionMatrix );
35052 
35053  // center / target
35054 
35055  setPoint( "c", 0, 0, - 1 );
35056  setPoint( "t", 0, 0, 1 );
35057 
35058  // near
35059 
35060  setPoint( "n1", - w, - h, - 1 );
35061  setPoint( "n2", w, - h, - 1 );
35062  setPoint( "n3", - w, h, - 1 );
35063  setPoint( "n4", w, h, - 1 );
35064 
35065  // far
35066 
35067  setPoint( "f1", - w, - h, 1 );
35068  setPoint( "f2", w, - h, 1 );
35069  setPoint( "f3", - w, h, 1 );
35070  setPoint( "f4", w, h, 1 );
35071 
35072  // up
35073 
35074  setPoint( "u1", w * 0.7, h * 1.1, - 1 );
35075  setPoint( "u2", - w * 0.7, h * 1.1, - 1 );
35076  setPoint( "u3", 0, h * 2, - 1 );
35077 
35078  // cross
35079 
35080  setPoint( "cf1", - w, 0, 1 );
35081  setPoint( "cf2", w, 0, 1 );
35082  setPoint( "cf3", 0, - h, 1 );
35083  setPoint( "cf4", 0, h, 1 );
35084 
35085  setPoint( "cn1", - w, 0, - 1 );
35086  setPoint( "cn2", w, 0, - 1 );
35087  setPoint( "cn3", 0, - h, - 1 );
35088  setPoint( "cn4", 0, h, - 1 );
35089 
35090  geometry.verticesNeedUpdate = true;
35091 
35092  };
35093 
35094 }();
35095 
35096 // File:src/extras/helpers/DirectionalLightHelper.js
35097 
35104 THREE.DirectionalLightHelper = function ( light, size ) {
35105 
35106  THREE.Object3D.call( this );
35107 
35108  this.light = light;
35109  this.light.updateMatrixWorld();
35110 
35111  this.matrix = light.matrixWorld;
35112  this.matrixAutoUpdate = false;
35113 
35114  size = size || 1;
35115 
35116  var geometry = new THREE.Geometry();
35117  geometry.vertices.push(
35118  new THREE.Vector3( - size, size, 0 ),
35119  new THREE.Vector3( size, size, 0 ),
35120  new THREE.Vector3( size, - size, 0 ),
35121  new THREE.Vector3( - size, - size, 0 ),
35122  new THREE.Vector3( - size, size, 0 )
35123  );
35124 
35125  var material = new THREE.LineBasicMaterial( { fog: false } );
35126  material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
35127 
35128  this.lightPlane = new THREE.Line( geometry, material );
35129  this.add( this.lightPlane );
35130 
35131  geometry = new THREE.Geometry();
35132  geometry.vertices.push(
35133  new THREE.Vector3(),
35134  new THREE.Vector3()
35135  );
35136 
35137  material = new THREE.LineBasicMaterial( { fog: false } );
35138  material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
35139 
35140  this.targetLine = new THREE.Line( geometry, material );
35141  this.add( this.targetLine );
35142 
35143  this.update();
35144 
35145 };
35146 
35147 THREE.DirectionalLightHelper.prototype = Object.create( THREE.Object3D.prototype );
35148 THREE.DirectionalLightHelper.prototype.constructor = THREE.DirectionalLightHelper;
35149 
35150 THREE.DirectionalLightHelper.prototype.dispose = function () {
35151 
35152  this.lightPlane.geometry.dispose();
35153  this.lightPlane.material.dispose();
35154  this.targetLine.geometry.dispose();
35155  this.targetLine.material.dispose();
35156 
35157 };
35158 
35159 THREE.DirectionalLightHelper.prototype.update = function () {
35160 
35161  var v1 = new THREE.Vector3();
35162  var v2 = new THREE.Vector3();
35163  var v3 = new THREE.Vector3();
35164 
35165  return function () {
35166 
35167  v1.setFromMatrixPosition( this.light.matrixWorld );
35168  v2.setFromMatrixPosition( this.light.target.matrixWorld );
35169  v3.subVectors( v2, v1 );
35170 
35171  this.lightPlane.lookAt( v3 );
35172  this.lightPlane.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
35173 
35174  this.targetLine.geometry.vertices[ 1 ].copy( v3 );
35175  this.targetLine.geometry.verticesNeedUpdate = true;
35176  this.targetLine.material.color.copy( this.lightPlane.material.color );
35177 
35178  };
35179 
35180 }();
35181 
35182 // File:src/extras/helpers/EdgesHelper.js
35183 
35194 THREE.EdgesHelper = function ( object, hex, thresholdAngle ) {
35195 
35196  var color = ( hex !== undefined ) ? hex : 0xffffff;
35197 
35198  THREE.LineSegments.call( this, new THREE.EdgesGeometry( object.geometry, thresholdAngle ), new THREE.LineBasicMaterial( { color: color } ) );
35199 
35200  this.matrix = object.matrixWorld;
35201  this.matrixAutoUpdate = false;
35202 
35203 };
35204 
35205 THREE.EdgesHelper.prototype = Object.create( THREE.LineSegments.prototype );
35206 THREE.EdgesHelper.prototype.constructor = THREE.EdgesHelper;
35207 
35208 // File:src/extras/helpers/FaceNormalsHelper.js
35209 
35215 THREE.FaceNormalsHelper = function ( object, size, hex, linewidth ) {
35216 
35217  // FaceNormalsHelper only supports THREE.Geometry
35218 
35219  this.object = object;
35220 
35221  this.size = ( size !== undefined ) ? size : 1;
35222 
35223  var color = ( hex !== undefined ) ? hex : 0xffff00;
35224 
35225  var width = ( linewidth !== undefined ) ? linewidth : 1;
35226 
35227  //
35228 
35229  var nNormals = 0;
35230 
35231  var objGeometry = this.object.geometry;
35232 
35233  if ( objGeometry instanceof THREE.Geometry ) {
35234 
35235  nNormals = objGeometry.faces.length;
35236 
35237  } else {
35238 
35239  console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' );
35240 
35241  }
35242 
35243  //
35244 
35245  var geometry = new THREE.BufferGeometry();
35246 
35247  var positions = new THREE.Float32Attribute( nNormals * 2 * 3, 3 );
35248 
35249  geometry.addAttribute( 'position', positions );
35250 
35251  THREE.LineSegments.call( this, geometry, new THREE.LineBasicMaterial( { color: color, linewidth: width } ) );
35252 
35253  //
35254 
35255  this.matrixAutoUpdate = false;
35256  this.update();
35257 
35258 };
35259 
35260 THREE.FaceNormalsHelper.prototype = Object.create( THREE.LineSegments.prototype );
35261 THREE.FaceNormalsHelper.prototype.constructor = THREE.FaceNormalsHelper;
35262 
35263 THREE.FaceNormalsHelper.prototype.update = ( function () {
35264 
35265  var v1 = new THREE.Vector3();
35266  var v2 = new THREE.Vector3();
35267  var normalMatrix = new THREE.Matrix3();
35268 
35269  return function update() {
35270 
35271  this.object.updateMatrixWorld( true );
35272 
35273  normalMatrix.getNormalMatrix( this.object.matrixWorld );
35274 
35275  var matrixWorld = this.object.matrixWorld;
35276 
35277  var position = this.geometry.attributes.position;
35278 
35279  //
35280 
35281  var objGeometry = this.object.geometry;
35282 
35283  var vertices = objGeometry.vertices;
35284 
35285  var faces = objGeometry.faces;
35286 
35287  var idx = 0;
35288 
35289  for ( var i = 0, l = faces.length; i < l; i ++ ) {
35290 
35291  var face = faces[ i ];
35292 
35293  var normal = face.normal;
35294 
35295  v1.copy( vertices[ face.a ] )
35296  .add( vertices[ face.b ] )
35297  .add( vertices[ face.c ] )
35298  .divideScalar( 3 )
35299  .applyMatrix4( matrixWorld );
35300 
35301  v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
35302 
35303  position.setXYZ( idx, v1.x, v1.y, v1.z );
35304 
35305  idx = idx + 1;
35306 
35307  position.setXYZ( idx, v2.x, v2.y, v2.z );
35308 
35309  idx = idx + 1;
35310 
35311  }
35312 
35313  position.needsUpdate = true;
35314 
35315  return this;
35316 
35317  }
35318 
35319 }() );
35320 
35321 // File:src/extras/helpers/GridHelper.js
35322 
35327 THREE.GridHelper = function ( size, step ) {
35328 
35329  var geometry = new THREE.Geometry();
35330  var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
35331 
35332  this.color1 = new THREE.Color( 0x444444 );
35333  this.color2 = new THREE.Color( 0x888888 );
35334 
35335  for ( var i = - size; i <= size; i += step ) {
35336 
35337  geometry.vertices.push(
35338  new THREE.Vector3( - size, 0, i ), new THREE.Vector3( size, 0, i ),
35339  new THREE.Vector3( i, 0, - size ), new THREE.Vector3( i, 0, size )
35340  );
35341 
35342  var color = i === 0 ? this.color1 : this.color2;
35343 
35344  geometry.colors.push( color, color, color, color );
35345 
35346  }
35347 
35348  THREE.LineSegments.call( this, geometry, material );
35349 
35350 };
35351 
35352 THREE.GridHelper.prototype = Object.create( THREE.LineSegments.prototype );
35353 THREE.GridHelper.prototype.constructor = THREE.GridHelper;
35354 
35355 THREE.GridHelper.prototype.setColors = function( colorCenterLine, colorGrid ) {
35356 
35357  this.color1.set( colorCenterLine );
35358  this.color2.set( colorGrid );
35359 
35360  this.geometry.colorsNeedUpdate = true;
35361 
35362 };
35363 
35364 // File:src/extras/helpers/HemisphereLightHelper.js
35365 
35371 THREE.HemisphereLightHelper = function ( light, sphereSize ) {
35372 
35373  THREE.Object3D.call( this );
35374 
35375  this.light = light;
35376  this.light.updateMatrixWorld();
35377 
35378  this.matrix = light.matrixWorld;
35379  this.matrixAutoUpdate = false;
35380 
35381  this.colors = [ new THREE.Color(), new THREE.Color() ];
35382 
35383  var geometry = new THREE.SphereGeometry( sphereSize, 4, 2 );
35384  geometry.rotateX( - Math.PI / 2 );
35385 
35386  for ( var i = 0, il = 8; i < il; i ++ ) {
35387 
35388  geometry.faces[ i ].color = this.colors[ i < 4 ? 0 : 1 ];
35389 
35390  }
35391 
35392  var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, wireframe: true } );
35393 
35394  this.lightSphere = new THREE.Mesh( geometry, material );
35395  this.add( this.lightSphere );
35396 
35397  this.update();
35398 
35399 };
35400 
35401 THREE.HemisphereLightHelper.prototype = Object.create( THREE.Object3D.prototype );
35402 THREE.HemisphereLightHelper.prototype.constructor = THREE.HemisphereLightHelper;
35403 
35404 THREE.HemisphereLightHelper.prototype.dispose = function () {
35405 
35406  this.lightSphere.geometry.dispose();
35407  this.lightSphere.material.dispose();
35408 
35409 };
35410 
35411 THREE.HemisphereLightHelper.prototype.update = function () {
35412 
35413  var vector = new THREE.Vector3();
35414 
35415  return function () {
35416 
35417  this.colors[ 0 ].copy( this.light.color ).multiplyScalar( this.light.intensity );
35418  this.colors[ 1 ].copy( this.light.groundColor ).multiplyScalar( this.light.intensity );
35419 
35420  this.lightSphere.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() );
35421  this.lightSphere.geometry.colorsNeedUpdate = true;
35422 
35423  }
35424 
35425 }();
35426 
35427 // File:src/extras/helpers/PointLightHelper.js
35428 
35434 THREE.PointLightHelper = function ( light, sphereSize ) {
35435 
35436  this.light = light;
35437  this.light.updateMatrixWorld();
35438 
35439  var geometry = new THREE.SphereGeometry( sphereSize, 4, 2 );
35440  var material = new THREE.MeshBasicMaterial( { wireframe: true, fog: false } );
35441  material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
35442 
35443  THREE.Mesh.call( this, geometry, material );
35444 
35445  this.matrix = this.light.matrixWorld;
35446  this.matrixAutoUpdate = false;
35447 
35448  /*
35449  var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
35450  var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
35451 
35452  this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
35453  this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
35454 
35455  var d = light.distance;
35456 
35457  if ( d === 0.0 ) {
35458 
35459  this.lightDistance.visible = false;
35460 
35461  } else {
35462 
35463  this.lightDistance.scale.set( d, d, d );
35464 
35465  }
35466 
35467  this.add( this.lightDistance );
35468  */
35469 
35470 };
35471 
35472 THREE.PointLightHelper.prototype = Object.create( THREE.Mesh.prototype );
35473 THREE.PointLightHelper.prototype.constructor = THREE.PointLightHelper;
35474 
35475 THREE.PointLightHelper.prototype.dispose = function () {
35476 
35477  this.geometry.dispose();
35478  this.material.dispose();
35479 
35480 };
35481 
35482 THREE.PointLightHelper.prototype.update = function () {
35483 
35484  this.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
35485 
35486  /*
35487  var d = this.light.distance;
35488 
35489  if ( d === 0.0 ) {
35490 
35491  this.lightDistance.visible = false;
35492 
35493  } else {
35494 
35495  this.lightDistance.visible = true;
35496  this.lightDistance.scale.set( d, d, d );
35497 
35498  }
35499  */
35500 
35501 };
35502 
35503 // File:src/extras/helpers/SkeletonHelper.js
35504 
35512 THREE.SkeletonHelper = function ( object ) {
35513 
35514  this.bones = this.getBoneList( object );
35515 
35516  var geometry = new THREE.Geometry();
35517 
35518  for ( var i = 0; i < this.bones.length; i ++ ) {
35519 
35520  var bone = this.bones[ i ];
35521 
35522  if ( bone.parent instanceof THREE.Bone ) {
35523 
35524  geometry.vertices.push( new THREE.Vector3() );
35525  geometry.vertices.push( new THREE.Vector3() );
35526  geometry.colors.push( new THREE.Color( 0, 0, 1 ) );
35527  geometry.colors.push( new THREE.Color( 0, 1, 0 ) );
35528 
35529  }
35530 
35531  }
35532 
35533  geometry.dynamic = true;
35534 
35535  var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors, depthTest: false, depthWrite: false, transparent: true } );
35536 
35537  THREE.LineSegments.call( this, geometry, material );
35538 
35539  this.root = object;
35540 
35541  this.matrix = object.matrixWorld;
35542  this.matrixAutoUpdate = false;
35543 
35544  this.update();
35545 
35546 };
35547 
35548 
35549 THREE.SkeletonHelper.prototype = Object.create( THREE.LineSegments.prototype );
35550 THREE.SkeletonHelper.prototype.constructor = THREE.SkeletonHelper;
35551 
35552 THREE.SkeletonHelper.prototype.getBoneList = function( object ) {
35553 
35554  var boneList = [];
35555 
35556  if ( object instanceof THREE.Bone ) {
35557 
35558  boneList.push( object );
35559 
35560  }
35561 
35562  for ( var i = 0; i < object.children.length; i ++ ) {
35563 
35564  boneList.push.apply( boneList, this.getBoneList( object.children[ i ] ) );
35565 
35566  }
35567 
35568  return boneList;
35569 
35570 };
35571 
35572 THREE.SkeletonHelper.prototype.update = function () {
35573 
35574  var geometry = this.geometry;
35575 
35576  var matrixWorldInv = new THREE.Matrix4().getInverse( this.root.matrixWorld );
35577 
35578  var boneMatrix = new THREE.Matrix4();
35579 
35580  var j = 0;
35581 
35582  for ( var i = 0; i < this.bones.length; i ++ ) {
35583 
35584  var bone = this.bones[ i ];
35585 
35586  if ( bone.parent instanceof THREE.Bone ) {
35587 
35588  boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld );
35589  geometry.vertices[ j ].setFromMatrixPosition( boneMatrix );
35590 
35591  boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld );
35592  geometry.vertices[ j + 1 ].setFromMatrixPosition( boneMatrix );
35593 
35594  j += 2;
35595 
35596  }
35597 
35598  }
35599 
35600  geometry.verticesNeedUpdate = true;
35601 
35602  geometry.computeBoundingSphere();
35603 
35604 };
35605 
35606 // File:src/extras/helpers/SpotLightHelper.js
35607 
35614 THREE.SpotLightHelper = function ( light ) {
35615 
35616  THREE.Object3D.call( this );
35617 
35618  this.light = light;
35619  this.light.updateMatrixWorld();
35620 
35621  this.matrix = light.matrixWorld;
35622  this.matrixAutoUpdate = false;
35623 
35624  var geometry = new THREE.CylinderGeometry( 0, 1, 1, 8, 1, true );
35625 
35626  geometry.translate( 0, - 0.5, 0 );
35627  geometry.rotateX( - Math.PI / 2 );
35628 
35629  var material = new THREE.MeshBasicMaterial( { wireframe: true, fog: false } );
35630 
35631  this.cone = new THREE.Mesh( geometry, material );
35632  this.add( this.cone );
35633 
35634  this.update();
35635 
35636 };
35637 
35638 THREE.SpotLightHelper.prototype = Object.create( THREE.Object3D.prototype );
35639 THREE.SpotLightHelper.prototype.constructor = THREE.SpotLightHelper;
35640 
35641 THREE.SpotLightHelper.prototype.dispose = function () {
35642 
35643  this.cone.geometry.dispose();
35644  this.cone.material.dispose();
35645 
35646 };
35647 
35648 THREE.SpotLightHelper.prototype.update = function () {
35649 
35650  var vector = new THREE.Vector3();
35651  var vector2 = new THREE.Vector3();
35652 
35653  return function () {
35654 
35655  var coneLength = this.light.distance ? this.light.distance : 10000;
35656  var coneWidth = coneLength * Math.tan( this.light.angle );
35657 
35658  this.cone.scale.set( coneWidth, coneWidth, coneLength );
35659 
35660  vector.setFromMatrixPosition( this.light.matrixWorld );
35661  vector2.setFromMatrixPosition( this.light.target.matrixWorld );
35662 
35663  this.cone.lookAt( vector2.sub( vector ) );
35664 
35665  this.cone.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
35666 
35667  };
35668 
35669 }();
35670 
35671 // File:src/extras/helpers/VertexNormalsHelper.js
35672 
35678 THREE.VertexNormalsHelper = function ( object, size, hex, linewidth ) {
35679 
35680  this.object = object;
35681 
35682  this.size = ( size !== undefined ) ? size : 1;
35683 
35684  var color = ( hex !== undefined ) ? hex : 0xff0000;
35685 
35686  var width = ( linewidth !== undefined ) ? linewidth : 1;
35687 
35688  //
35689 
35690  var nNormals = 0;
35691 
35692  var objGeometry = this.object.geometry;
35693 
35694  if ( objGeometry instanceof THREE.Geometry ) {
35695 
35696  nNormals = objGeometry.faces.length * 3;
35697 
35698  } else if ( objGeometry instanceof THREE.BufferGeometry ) {
35699 
35700  nNormals = objGeometry.attributes.normal.count
35701 
35702  }
35703 
35704  //
35705 
35706  var geometry = new THREE.BufferGeometry();
35707 
35708  var positions = new THREE.Float32Attribute( nNormals * 2 * 3, 3 );
35709 
35710  geometry.addAttribute( 'position', positions );
35711 
35712  THREE.LineSegments.call( this, geometry, new THREE.LineBasicMaterial( { color: color, linewidth: width } ) );
35713 
35714  //
35715 
35716  this.matrixAutoUpdate = false;
35717 
35718  this.update();
35719 
35720 };
35721 
35722 THREE.VertexNormalsHelper.prototype = Object.create( THREE.LineSegments.prototype );
35723 THREE.VertexNormalsHelper.prototype.constructor = THREE.VertexNormalsHelper;
35724 
35725 THREE.VertexNormalsHelper.prototype.update = ( function () {
35726 
35727  var v1 = new THREE.Vector3();
35728  var v2 = new THREE.Vector3();
35729  var normalMatrix = new THREE.Matrix3();
35730 
35731  return function update() {
35732 
35733  var keys = [ 'a', 'b', 'c' ];
35734 
35735  this.object.updateMatrixWorld( true );
35736 
35737  normalMatrix.getNormalMatrix( this.object.matrixWorld );
35738 
35739  var matrixWorld = this.object.matrixWorld;
35740 
35741  var position = this.geometry.attributes.position;
35742 
35743  //
35744 
35745  var objGeometry = this.object.geometry;
35746 
35747  if ( objGeometry instanceof THREE.Geometry ) {
35748 
35749  var vertices = objGeometry.vertices;
35750 
35751  var faces = objGeometry.faces;
35752 
35753  var idx = 0;
35754 
35755  for ( var i = 0, l = faces.length; i < l; i ++ ) {
35756 
35757  var face = faces[ i ];
35758 
35759  for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
35760 
35761  var vertex = vertices[ face[ keys[ j ] ] ];
35762 
35763  var normal = face.vertexNormals[ j ];
35764 
35765  v1.copy( vertex ).applyMatrix4( matrixWorld );
35766 
35767  v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
35768 
35769  position.setXYZ( idx, v1.x, v1.y, v1.z );
35770 
35771  idx = idx + 1;
35772 
35773  position.setXYZ( idx, v2.x, v2.y, v2.z );
35774 
35775  idx = idx + 1;
35776 
35777  }
35778 
35779  }
35780 
35781  } else if ( objGeometry instanceof THREE.BufferGeometry ) {
35782 
35783  var objPos = objGeometry.attributes.position;
35784 
35785  var objNorm = objGeometry.attributes.normal;
35786 
35787  var idx = 0;
35788 
35789  // for simplicity, ignore index and drawcalls, and render every normal
35790 
35791  for ( var j = 0, jl = objPos.count; j < jl; j ++ ) {
35792 
35793  v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );
35794 
35795  v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) );
35796 
35797  v2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
35798 
35799  position.setXYZ( idx, v1.x, v1.y, v1.z );
35800 
35801  idx = idx + 1;
35802 
35803  position.setXYZ( idx, v2.x, v2.y, v2.z );
35804 
35805  idx = idx + 1;
35806 
35807  }
35808 
35809  }
35810 
35811  position.needsUpdate = true;
35812 
35813  return this;
35814 
35815  }
35816 
35817 }() );
35818 
35819 // File:src/extras/helpers/WireframeHelper.js
35820 
35825 THREE.WireframeHelper = function ( object, hex ) {
35826 
35827  var color = ( hex !== undefined ) ? hex : 0xffffff;
35828 
35829  THREE.LineSegments.call( this, new THREE.WireframeGeometry( object.geometry ), new THREE.LineBasicMaterial( { color: color } ) );
35830 
35831  this.matrix = object.matrixWorld;
35832  this.matrixAutoUpdate = false;
35833 
35834 };
35835 
35836 THREE.WireframeHelper.prototype = Object.create( THREE.LineSegments.prototype );
35837 THREE.WireframeHelper.prototype.constructor = THREE.WireframeHelper;
35838 
35839 // File:src/extras/objects/ImmediateRenderObject.js
35840 
35845 THREE.ImmediateRenderObject = function ( material ) {
35846 
35847  THREE.Object3D.call( this );
35848 
35849  this.material = material;
35850  this.render = function ( renderCallback ) {};
35851 
35852 };
35853 
35854 THREE.ImmediateRenderObject.prototype = Object.create( THREE.Object3D.prototype );
35855 THREE.ImmediateRenderObject.prototype.constructor = THREE.ImmediateRenderObject;
35856 
35857 // File:src/extras/objects/MorphBlendMesh.js
35858 
35863 THREE.MorphBlendMesh = function( geometry, material ) {
35864 
35865  THREE.Mesh.call( this, geometry, material );
35866 
35867  this.animationsMap = {};
35868  this.animationsList = [];
35869 
35870  // prepare default animation
35871  // (all frames played together in 1 second)
35872 
35873  var numFrames = this.geometry.morphTargets.length;
35874 
35875  var name = "__default";
35876 
35877  var startFrame = 0;
35878  var endFrame = numFrames - 1;
35879 
35880  var fps = numFrames / 1;
35881 
35882  this.createAnimation( name, startFrame, endFrame, fps );
35883  this.setAnimationWeight( name, 1 );
35884 
35885 };
35886 
35887 THREE.MorphBlendMesh.prototype = Object.create( THREE.Mesh.prototype );
35888 THREE.MorphBlendMesh.prototype.constructor = THREE.MorphBlendMesh;
35889 
35890 THREE.MorphBlendMesh.prototype.createAnimation = function ( name, start, end, fps ) {
35891 
35892  var animation = {
35893 
35894  start: start,
35895  end: end,
35896 
35897  length: end - start + 1,
35898 
35899  fps: fps,
35900  duration: ( end - start ) / fps,
35901 
35902  lastFrame: 0,
35903  currentFrame: 0,
35904 
35905  active: false,
35906 
35907  time: 0,
35908  direction: 1,
35909  weight: 1,
35910 
35911  directionBackwards: false,
35912  mirroredLoop: false
35913 
35914  };
35915 
35916  this.animationsMap[ name ] = animation;
35917  this.animationsList.push( animation );
35918 
35919 };
35920 
35921 THREE.MorphBlendMesh.prototype.autoCreateAnimations = function ( fps ) {
35922 
35923  var pattern = /([a-z]+)_?(\d+)/;
35924 
35925  var firstAnimation, frameRanges = {};
35926 
35927  var geometry = this.geometry;
35928 
35929  for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) {
35930 
35931  var morph = geometry.morphTargets[ i ];
35932  var chunks = morph.name.match( pattern );
35933 
35934  if ( chunks && chunks.length > 1 ) {
35935 
35936  var name = chunks[ 1 ];
35937 
35938  if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: - Infinity };
35939 
35940  var range = frameRanges[ name ];
35941 
35942  if ( i < range.start ) range.start = i;
35943  if ( i > range.end ) range.end = i;
35944 
35945  if ( ! firstAnimation ) firstAnimation = name;
35946 
35947  }
35948 
35949  }
35950 
35951  for ( var name in frameRanges ) {
35952 
35953  var range = frameRanges[ name ];
35954  this.createAnimation( name, range.start, range.end, fps );
35955 
35956  }
35957 
35958  this.firstAnimation = firstAnimation;
35959 
35960 };
35961 
35962 THREE.MorphBlendMesh.prototype.setAnimationDirectionForward = function ( name ) {
35963 
35964  var animation = this.animationsMap[ name ];
35965 
35966  if ( animation ) {
35967 
35968  animation.direction = 1;
35969  animation.directionBackwards = false;
35970 
35971  }
35972 
35973 };
35974 
35975 THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward = function ( name ) {
35976 
35977  var animation = this.animationsMap[ name ];
35978 
35979  if ( animation ) {
35980 
35981  animation.direction = - 1;
35982  animation.directionBackwards = true;
35983 
35984  }
35985 
35986 };
35987 
35988 THREE.MorphBlendMesh.prototype.setAnimationFPS = function ( name, fps ) {
35989 
35990  var animation = this.animationsMap[ name ];
35991 
35992  if ( animation ) {
35993 
35994  animation.fps = fps;
35995  animation.duration = ( animation.end - animation.start ) / animation.fps;
35996 
35997  }
35998 
35999 };
36000 
36001 THREE.MorphBlendMesh.prototype.setAnimationDuration = function ( name, duration ) {
36002 
36003  var animation = this.animationsMap[ name ];
36004 
36005  if ( animation ) {
36006 
36007  animation.duration = duration;
36008  animation.fps = ( animation.end - animation.start ) / animation.duration;
36009 
36010  }
36011 
36012 };
36013 
36014 THREE.MorphBlendMesh.prototype.setAnimationWeight = function ( name, weight ) {
36015 
36016  var animation = this.animationsMap[ name ];
36017 
36018  if ( animation ) {
36019 
36020  animation.weight = weight;
36021 
36022  }
36023 
36024 };
36025 
36026 THREE.MorphBlendMesh.prototype.setAnimationTime = function ( name, time ) {
36027 
36028  var animation = this.animationsMap[ name ];
36029 
36030  if ( animation ) {
36031 
36032  animation.time = time;
36033 
36034  }
36035 
36036 };
36037 
36038 THREE.MorphBlendMesh.prototype.getAnimationTime = function ( name ) {
36039 
36040  var time = 0;
36041 
36042  var animation = this.animationsMap[ name ];
36043 
36044  if ( animation ) {
36045 
36046  time = animation.time;
36047 
36048  }
36049 
36050  return time;
36051 
36052 };
36053 
36054 THREE.MorphBlendMesh.prototype.getAnimationDuration = function ( name ) {
36055 
36056  var duration = - 1;
36057 
36058  var animation = this.animationsMap[ name ];
36059 
36060  if ( animation ) {
36061 
36062  duration = animation.duration;
36063 
36064  }
36065 
36066  return duration;
36067 
36068 };
36069 
36070 THREE.MorphBlendMesh.prototype.playAnimation = function ( name ) {
36071 
36072  var animation = this.animationsMap[ name ];
36073 
36074  if ( animation ) {
36075 
36076  animation.time = 0;
36077  animation.active = true;
36078 
36079  } else {
36080 
36081  console.warn( "THREE.MorphBlendMesh: animation[" + name + "] undefined in .playAnimation()" );
36082 
36083  }
36084 
36085 };
36086 
36087 THREE.MorphBlendMesh.prototype.stopAnimation = function ( name ) {
36088 
36089  var animation = this.animationsMap[ name ];
36090 
36091  if ( animation ) {
36092 
36093  animation.active = false;
36094 
36095  }
36096 
36097 };
36098 
36099 THREE.MorphBlendMesh.prototype.update = function ( delta ) {
36100 
36101  for ( var i = 0, il = this.animationsList.length; i < il; i ++ ) {
36102 
36103  var animation = this.animationsList[ i ];
36104 
36105  if ( ! animation.active ) continue;
36106 
36107  var frameTime = animation.duration / animation.length;
36108 
36109  animation.time += animation.direction * delta;
36110 
36111  if ( animation.mirroredLoop ) {
36112 
36113  if ( animation.time > animation.duration || animation.time < 0 ) {
36114 
36115  animation.direction *= - 1;
36116 
36117  if ( animation.time > animation.duration ) {
36118 
36119  animation.time = animation.duration;
36120  animation.directionBackwards = true;
36121 
36122  }
36123 
36124  if ( animation.time < 0 ) {
36125 
36126  animation.time = 0;
36127  animation.directionBackwards = false;
36128 
36129  }
36130 
36131  }
36132 
36133  } else {
36134 
36135  animation.time = animation.time % animation.duration;
36136 
36137  if ( animation.time < 0 ) animation.time += animation.duration;
36138 
36139  }
36140 
36141  var keyframe = animation.start + THREE.Math.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 );
36142  var weight = animation.weight;
36143 
36144  if ( keyframe !== animation.currentFrame ) {
36145 
36146  this.morphTargetInfluences[ animation.lastFrame ] = 0;
36147  this.morphTargetInfluences[ animation.currentFrame ] = 1 * weight;
36148 
36149  this.morphTargetInfluences[ keyframe ] = 0;
36150 
36151  animation.lastFrame = animation.currentFrame;
36152  animation.currentFrame = keyframe;
36153 
36154  }
36155 
36156  var mix = ( animation.time % frameTime ) / frameTime;
36157 
36158  if ( animation.directionBackwards ) mix = 1 - mix;
36159 
36160  if ( animation.currentFrame !== animation.lastFrame ) {
36161 
36162  this.morphTargetInfluences[ animation.currentFrame ] = mix * weight;
36163  this.morphTargetInfluences[ animation.lastFrame ] = ( 1 - mix ) * weight;
36164 
36165  } else {
36166 
36167  this.morphTargetInfluences[ animation.currentFrame ] = weight;
36168 
36169  }
36170 
36171  }
36172 
36173 };
36174