PageSourceSearch

https://g.travelerstoday.com/video/js/videojs-panorama/three.js

js travelerstoday.com collected 2026-09-24 06:29:04 UTC 1,124,356 bytes, 41,506 lines download raw bytes

1// File:src/Three.js
2
3/**
4 * @author mrdoob / http://mrdoob.com/
5 */
6
7var THREE = { REVISION: '76' };
8
9//
10
11if ( 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
23if ( Number.EPSILON === undefined ) {
24
25    Number.EPSILON = Math.pow( 2, - 52 );
26
27}
28
29//
30
31if ( Math.sign === undefined ) {
32
33    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
34
35    Math.sign = function ( x ) {
36
37        return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x;
38
39    };
40
41}
42
43if ( Function.prototype.name === undefined && Object.defineProperty !== undefined ) {
44
45    // Missing in IE9-11.
46    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
47
48    Object.defineProperty( Function.prototype, 'name', {
49
50        get: function () {
51
52            return this.toString().match( /^\s*function\s*(\S*)\s*\(/ )[ 1 ];
53
54        }
55
56    } );
57
58}
59
60if ( Object.assign === undefined ) {
61
62    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
63
64    Object.defineProperty( Object, 'assign', {
65
66        writable: true,
67        configurable: true,
68
69        value: function ( target ) {
70
71            'use strict';
72
73            if ( target === undefined || target === null ) {
74
75                throw new TypeError( "Cannot convert first argument to object" );
76
77            }
78
79            var to = Object( target );
80
81            for ( var i = 1, n = arguments.length; i !== n; ++ i ) {
82
83                var nextSource = arguments[ i ];
84
85                if ( nextSource === undefined || nextSource === null ) continue;
86
87                nextSource = Object( nextSource );
88
89                var keysArray = Object.keys( nextSource );
90
91                for ( var nextIndex = 0, len = keysArray.length; nextIndex !== len; ++ nextIndex ) {
92
93                    var nextKey = keysArray[ nextIndex ];
94                    var desc = Object.getOwnPropertyDescriptor( nextSource, nextKey );
95
96                    if ( desc !== undefined && desc.enumerable ) {
97
98                        to[ nextKey ] = nextSource[ nextKey ];
99
100                    }
101
102                }
103
104            }
105
106            return to;
107
108        }
109
110    } );
111
112}
113
114// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent.button
115
116THREE.MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
117
118// GL STATE CONSTANTS
119
120THREE.CullFaceNone = 0;
121THREE.CullFaceBack = 1;
122THREE.CullFaceFront = 2;
123THREE.CullFaceFrontBack = 3;
124
125THREE.FrontFaceDirectionCW = 0;
126THREE.FrontFaceDirectionCCW = 1;
127
128// SHADOWING TYPES
129
130THREE.BasicShadowMap = 0;
131THREE.PCFShadowMap = 1;
132THREE.PCFSoftShadowMap = 2;
133
134// MATERIAL CONSTANTS
135
136// side
137
138THREE.FrontSide = 0;
139THREE.BackSide = 1;
140THREE.DoubleSide = 2;
141
142// shading
143
144THREE.FlatShading = 1;
145THREE.SmoothShading = 2;
146
147// colors
148
149THREE.NoColors = 0;
150THREE.FaceColors = 1;
151THREE.VertexColors = 2;
152
153// blending modes
154
155THREE.NoBlending = 0;
156THREE.NormalBlending = 1;
157THREE.AdditiveBlending = 2;
158THREE.SubtractiveBlending = 3;
159THREE.MultiplyBlending = 4;
160THREE.CustomBlending = 5;
161
162// custom blending equations
163// (numbers start from 100 not to clash with other
164// mappings to OpenGL constants defined in Texture.js)
165
166THREE.AddEquation = 100;
167THREE.SubtractEquation = 101;
168THREE.ReverseSubtractEquation = 102;
169THREE.MinEquation = 103;
170THREE.MaxEquation = 104;
171
172// custom blending destination factors
173
174THREE.ZeroFactor = 200;
175THREE.OneFactor = 201;
176THREE.SrcColorFactor = 202;
177THREE.OneMinusSrcColorFactor = 203;
178THREE.SrcAlphaFactor = 204;
179THREE.OneMinusSrcAlphaFactor = 205;
180THREE.DstAlphaFactor = 206;
181THREE.OneMinusDstAlphaFactor = 207;
182
183// custom blending source factors
184
185//THREE.ZeroFactor = 200;
186//THREE.OneFactor = 201;
187//THREE.SrcAlphaFactor = 204;
188//THREE.OneMinusSrcAlphaFactor = 205;
189//THREE.DstAlphaFactor = 206;
190//THREE.OneMinusDstAlphaFactor = 207;
191THREE.DstColorFactor = 208;
192THREE.OneMinusDstColorFactor = 209;
193THREE.SrcAlphaSaturateFactor = 210;
194
195// depth modes
196
197THREE.NeverDepth = 0;
198THREE.AlwaysDepth = 1;
199THREE.LessDepth = 2;
200THREE.LessEqualDepth = 3;
201THREE.EqualDepth = 4;
202THREE.GreaterEqualDepth = 5;
203THREE.GreaterDepth = 6;
204THREE.NotEqualDepth = 7;
205
206
207// TEXTURE CONSTANTS
208
209THREE.MultiplyOperation = 0;
210THREE.MixOperation = 1;
211THREE.AddOperation = 2;
212
213// Tone Mapping modes
214
215THREE.NoToneMapping = 0; // do not do any tone mapping, not even exposure (required for special purpose passes.)
216THREE.LinearToneMapping = 1; // only apply exposure.
217THREE.ReinhardToneMapping = 2;
218THREE.Uncharted2ToneMapping = 3; // John Hable
219THREE.CineonToneMapping = 4;  // optimized filmic operator by Jim Hejl and Richard Burgess-Dawson
220
221// Mapping modes
222
223THREE.UVMapping = 300;
224
225THREE.CubeReflectionMapping = 301;
226THREE.CubeRefractionMapping = 302;
227
228THREE.EquirectangularReflectionMapping = 303;
229THREE.EquirectangularRefractionMapping = 304;
230
231THREE.SphericalReflectionMapping = 305;
232THREE.CubeUVReflectionMapping = 306;
233THREE.CubeUVRefractionMapping = 307;
234
235// Wrapping modes
236
237THREE.RepeatWrapping = 1000;
238THREE.ClampToEdgeWrapping = 1001;
239THREE.MirroredRepeatWrapping = 1002;
240
241// Filters
242
243THREE.NearestFilter = 1003;
244THREE.NearestMipMapNearestFilter = 1004;
245THREE.NearestMipMapLinearFilter = 1005;
246THREE.LinearFilter = 1006;
247THREE.LinearMipMapNearestFilter = 1007;
248THREE.LinearMipMapLinearFilter = 1008;
249
250// Data types
251
252THREE.UnsignedByteType = 1009;
253THREE.ByteType = 1010;
254THREE.ShortType = 1011;
255THREE.UnsignedShortType = 1012;
256THREE.IntType = 1013;
257THREE.UnsignedIntType = 1014;
258THREE.FloatType = 1015;
259THREE.HalfFloatType = 1025;
260
261// Pixel types
262
263//THREE.UnsignedByteType = 1009;
264THREE.UnsignedShort4444Type = 1016;
265THREE.UnsignedShort5551Type = 1017;
266THREE.UnsignedShort565Type = 1018;
267
268// Pixel formats
269
270THREE.AlphaFormat = 1019;
271THREE.RGBFormat = 1020;
272THREE.RGBAFormat = 1021;
273THREE.LuminanceFormat = 1022;
274THREE.LuminanceAlphaFormat = 1023;
275// THREE.RGBEFormat handled as THREE.RGBAFormat in shaders
276THREE.RGBEFormat = THREE.RGBAFormat; //1024;
277THREE.DepthFormat = 1026;
278
279// DDS / ST3C Compressed texture formats
280
281THREE.RGB_S3TC_DXT1_Format = 2001;
282THREE.RGBA_S3TC_DXT1_Format = 2002;
283THREE.RGBA_S3TC_DXT3_Format = 2003;
284THREE.RGBA_S3TC_DXT5_Format = 2004;
285
286
287// PVRTC compressed texture formats
288
289THREE.RGB_PVRTC_4BPPV1_Format = 2100;
290THREE.RGB_PVRTC_2BPPV1_Format = 2101;
291THREE.RGBA_PVRTC_4BPPV1_Format = 2102;
292THREE.RGBA_PVRTC_2BPPV1_Format = 2103;
293
294// ETC compressed texture formats
295
296THREE.RGB_ETC1_Format = 2151;
297
298// Loop styles for AnimationAction
299
300THREE.LoopOnce = 2200;
301THREE.LoopRepeat = 2201;
302THREE.LoopPingPong = 2202;
303
304// Interpolation
305
306THREE.InterpolateDiscrete = 2300;
307THREE.InterpolateLinear = 2301;
308THREE.InterpolateSmooth = 2302;
309
310// Interpolant ending modes
311
312THREE.ZeroCurvatureEnding = 2400;
313THREE.ZeroSlopeEnding = 2401;
314THREE.WrapAroundEnding = 2402;
315
316// Triangle Draw modes
317
318THREE.TrianglesDrawMode = 0;
319THREE.TriangleStripDrawMode = 1;
320THREE.TriangleFanDrawMode = 2;
321
322// Texture Encodings
323
324THREE.LinearEncoding = 3000; // No encoding at all.
325THREE.sRGBEncoding = 3001;
326THREE.GammaEncoding = 3007; // uses GAMMA_FACTOR, for backwards compatibility with WebGLRenderer.gammaInput/gammaOutput
327
328// The following Texture Encodings are for RGB-only (no alpha) HDR light emission sources.
329// These encodings should not specified as output encodings except in rare situations.
330THREE.RGBEEncoding = 3002; // AKA Radiance.
331THREE.LogLuvEncoding = 3003;
332THREE.RGBM7Encoding = 3004;
333THREE.RGBM16Encoding = 3005;
334THREE.RGBDEncoding = 3006; // MaxRange is 256.
335
336// Depth packing strategies
337
338THREE.BasicDepthPacking = 3200;  // for writing to float textures for high precision or for visualizing results in RGB buffers
339THREE.RGBADepthPacking = 3201; // for packing into RGBA buffers.
340
341// File:src/math/Color.js
342
343/**
344 * @author mrdoob / http://mrdoob.com/
345 */
346
347THREE.Color = function ( color ) {
348
349    if ( arguments.length === 3 ) {
350
351        return this.fromArray( arguments );
352
353    }
354
355    return this.set( color );
356
357};
358
359THREE.Color.prototype = {
360
361    constructor: THREE.Color,
362
363    r: 1, g: 1, b: 1,
364
365    set: function ( value ) {
366
367        if ( value instanceof THREE.Color ) {
368
369            this.copy( value );
370
371        } else if ( typeof value === 'number' ) {
372
373            this.setHex( value );
374
375        } else if ( typeof value === 'string' ) {
376
377            this.setStyle( value );
378
379        }
380
381        return this;
382
383    },
384
385    setScalar: function ( scalar ) {
386
387        this.r = scalar;
388        this.g = scalar;
389        this.b = scalar;
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
818THREE.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
845/**
846 * @author mikael emtinger / http://gomo.se/
847 * @author alteredq / http://alteredqualia.com/
848 * @author WestLangley / http://github.com/WestLangley
849 * @author bhouston / http://clara.io
850 */
851
852THREE.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
861THREE.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    slerp: function ( qb, t ) {
1245
1246        if ( t === 0 ) return this;
1247        if ( t === 1 ) return this.copy( qb );
1248
1249        var x = this._x, y = this._y, z = this._z, w = this._w;
1250
1251        // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
1252
1253        var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
1254
1255        if ( cosHalfTheta < 0 ) {
1256
1257            this._w = - qb._w;
1258            this._x = - qb._x;
1259            this._y = - qb._y;
1260            this._z = - qb._z;
1261
1262            cosHalfTheta = - cosHalfTheta;
1263
1264        } else {
1265
1266            this.copy( qb );
1267
1268        }
1269
1270        if ( cosHalfTheta >= 1.0 ) {
1271
1272            this._w = w;
1273            this._x = x;
1274            this._y = y;
1275            this._z = z;
1276
1277            return this;
1278
1279        }
1280
1281        var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
1282
1283        if ( Math.abs( sinHalfTheta ) < 0.001 ) {
1284
1285            this._w = 0.5 * ( w + this._w );
1286            this._x = 0.5 * ( x + this._x );
1287            this._y = 0.5 * ( y + this._y );
1288            this._z = 0.5 * ( z + this._z );
1289
1290            return this;
1291
1292        }
1293
1294        var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
1295        var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
1296            ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
1297
1298        this._w = ( w * ratioA + this._w * ratioB );
1299        this._x = ( x * ratioA + this._x * ratioB );
1300        this._y = ( y * ratioA + this._y * ratioB );
1301        this._z = ( z * ratioA + this._z * ratioB );
1302
1303        this.onChangeCallback();
1304
1305        return this;
1306
1307    },
1308
1309    equals: function ( quaternion ) {
1310
1311        return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
1312
1313    },
1314
1315    fromArray: function ( array, offset ) {
1316
1317        if ( offset === undefined ) offset = 0;
1318
1319        this._x = array[ offset ];
1320        this._y = array[ offset + 1 ];
1321        this._z = array[ offset + 2 ];
1322        this._w = array[ offset + 3 ];
1323
1324        this.onChangeCallback();
1325
1326        return this;
1327
1328    },
1329
1330    toArray: function ( array, offset ) {
1331
1332        if ( array === undefined ) array = [];
1333        if ( offset === undefined ) offset = 0;
1334
1335        array[ offset ] = this._x;
1336        array[ offset + 1 ] = this._y;
1337        array[ offset + 2 ] = this._z;
1338        array[ offset + 3 ] = this._w;
1339
1340        return array;
1341
1342    },
1343
1344    onChange: function ( callback ) {
1345
1346        this.onChangeCallback = callback;
1347
1348        return this;
1349
1350    },
1351
1352    onChangeCallback: function () {}
1353
1354};
1355
1356Object.assign( THREE.Quaternion, {
1357
1358    slerp: function( qa, qb, qm, t ) {
1359
1360        return qm.copy( qa ).slerp( qb, t );
1361
1362    },
1363
1364    slerpFlat: function(
1365        dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
1366
1367        // fuzz-free, array-based Quaternion SLERP operation
1368
1369        var x0 = src0[ srcOffset0 + 0 ],
1370            y0 = src0[ srcOffset0 + 1 ],
1371            z0 = src0[ srcOffset0 + 2 ],
1372            w0 = src0[ srcOffset0 + 3 ],
1373
1374            x1 = src1[ srcOffset1 + 0 ],
1375            y1 = src1[ srcOffset1 + 1 ],
1376            z1 = src1[ srcOffset1 + 2 ],
1377            w1 = src1[ srcOffset1 + 3 ];
1378
1379        if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
1380
1381            var s = 1 - t,
1382
1383                cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
1384
1385                dir = ( cos >= 0 ? 1 : - 1 ),
1386                sqrSin = 1 - cos * cos;
1387
1388            // Skip the Slerp for tiny steps to avoid numeric problems:
1389            if ( sqrSin > Number.EPSILON ) {
1390
1391                var sin = Math.sqrt( sqrSin ),
1392                    len = Math.atan2( sin, cos * dir );
1393
1394                s = Math.sin( s * len ) / sin;
1395                t = Math.sin( t * len ) / sin;
1396
1397            }
1398
1399            var tDir = t * dir;
1400
1401            x0 = x0 * s + x1 * tDir;
1402            y0 = y0 * s + y1 * tDir;
1403            z0 = z0 * s + z1 * tDir;
1404            w0 = w0 * s + w1 * tDir;
1405
1406            // Normalize in case we just did a lerp:
1407            if ( s === 1 - t ) {
1408
1409                var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
1410
1411                x0 *= f;
1412                y0 *= f;
1413                z0 *= f;
1414                w0 *= f;
1415
1416            }
1417
1418        }
1419
1420        dst[ dstOffset ] = x0;
1421        dst[ dstOffset + 1 ] = y0;
1422        dst[ dstOffset + 2 ] = z0;
1423        dst[ dstOffset + 3 ] = w0;
1424
1425    }
1426
1427} );
1428
1429// File:src/math/Vector2.js
1430
1431/**
1432 * @author mrdoob / http://mrdoob.com/
1433 * @author philogb / http://blog.thejit.org/
1434 * @author egraether / http://egraether.com/
1435 * @author zz85 / http://www.lab4games.net/zz85/blog
1436 */
1437
1438THREE.Vector2 = function ( x, y ) {
1439
1440    this.x = x || 0;
1441    this.y = y || 0;
1442
1443};
1444
1445THREE.Vector2.prototype = {
1446
1447    constructor: THREE.Vector2,
1448
1449    get width() {
1450
1451        return this.x;
1452
1453    },
1454
1455    set width( value ) {
1456
1457        this.x = value;
1458
1459    },
1460
1461    get height() {
1462
1463        return this.y;
1464
1465    },
1466
1467    set height( value ) {
1468
1469        this.y = value;
1470
1471    },
1472
1473    //
1474
1475    set: function ( x, y ) {
1476
1477        this.x = x;
1478        this.y = y;
1479
1480        return this;
1481
1482    },
1483
1484    setScalar: function ( scalar ) {
1485
1486        this.x = scalar;
1487        this.y = scalar;
1488
1489        return this;
1490
1491    },
1492
1493    setX: function ( x ) {
1494
1495        this.x = x;
1496
1497        return this;
1498
1499    },
1500
1501    setY: function ( y ) {
1502
1503        this.y = y;
1504
1505        return this;
1506
1507    },
1508
1509    setComponent: function ( index, value ) {
1510
1511        switch ( index ) {
1512
1513            case 0: this.x = value; break;
1514            case 1: this.y = value; break;
1515            default: throw new Error( 'index is out of range: ' + index );
1516
1517        }
1518
1519    },
1520
1521    getComponent: function ( index ) {
1522
1523        switch ( index ) {
1524
1525            case 0: return this.x;
1526            case 1: return this.y;
1527            default: throw new Error( 'index is out of range: ' + index );
1528
1529        }
1530
1531    },
1532
1533    clone: function () {
1534
1535        return new this.constructor( this.x, this.y );
1536
1537    },
1538
1539    copy: function ( v ) {
1540
1541        this.x = v.x;
1542        this.y = v.y;
1543
1544        return this;
1545
1546    },
1547
1548    add: function ( v, w ) {
1549
1550        if ( w !== undefined ) {
1551
1552            console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
1553            return this.addVectors( v, w );
1554
1555        }
1556
1557        this.x += v.x;
1558        this.y += v.y;
1559
1560        return this;
1561
1562    },
1563
1564    addScalar: function ( s ) {
1565
1566        this.x += s;
1567        this.y += s;
1568
1569        return this;
1570
1571    },
1572
1573    addVectors: function ( a, b ) {
1574
1575        this.x = a.x + b.x;
1576        this.y = a.y + b.y;
1577
1578        return this;
1579
1580    },
1581
1582    addScaledVector: function ( v, s ) {
1583
1584        this.x += v.x * s;
1585        this.y += v.y * s;
1586
1587        return this;
1588
1589    },
1590
1591    sub: function ( v, w ) {
1592
1593        if ( w !== undefined ) {
1594
1595            console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
1596            return this.subVectors( v, w );
1597
1598        }
1599
1600        this.x -= v.x;
1601        this.y -
1601= v.y;
1602
1603        return this;
1604
1605    },
1606
1607    subScalar: function ( s ) {
1608
1609        this.x -= s;
1610        this.y -= s;
1611
1612        return this;
1613
1614    },
1615
1616    subVectors: function ( a, b ) {
1617
1618        this.x = a.x - b.x;
1619        this.y = a.y - b.y;
1620
1621        return this;
1622
1623    },
1624
1625    multiply: function ( v ) {
1626
1627        this.x *= v.x;
1628        this.y *= v.y;
1629
1630        return this;
1631
1632    },
1633
1634    multiplyScalar: function ( scalar ) {
1635
1636        if ( isFinite( scalar ) ) {
1637
1638            this.x *= scalar;
1639            this.y *= scalar;
1640
1641        } else {
1642
1643            this.x = 0;
1644            this.y = 0;
1645
1646        }
1647
1648        return this;
1649
1650    },
1651
1652    divide: function ( v ) {
1653
1654        this.x /= v.x;
1655        this.y /= v.y;
1656
1657        return this;
1658
1659    },
1660
1661    divideScalar: function ( scalar ) {
1662
1663        return this.multiplyScalar( 1 / scalar );
1664
1665    },
1666
1667    min: function ( v ) {
1668
1669        this.x = Math.min( this.x, v.x );
1670        this.y = Math.min( this.y, v.y );
1671
1672        return this;
1673
1674    },
1675
1676    max: function ( v ) {
1677
1678        this.x = Math.max( this.x, v.x );
1679        this.y = Math.max( this.y, v.y );
1680
1681        return this;
1682
1683    },
1684
1685    clamp: function ( min, max ) {
1686
1687        // This function assumes min < max, if this assumption isn't true it will not operate correctly
1688
1689        this.x = Math.max( min.x, Math.min( max.x, this.x ) );
1690        this.y = Math.max( min.y, Math.min( max.y, this.y ) );
1691
1692        return this;
1693
1694    },
1695
1696    clampScalar: function () {
1697
1698        var min, max;
1699
1700        return function clampScalar( minVal, maxVal ) {
1701
1702            if ( min === undefined ) {
1703
1704                min = new THREE.Vector2();
1705                max = new THREE.Vector2();
1706
1707            }
1708
1709            min.set( minVal, minVal );
1710            max.set( maxVal, maxVal );
1711
1712            return this.clamp( min, max );
1713
1714        };
1715
1716    }(),
1717
1718    clampLength: function ( min, max ) {
1719
1720        var length = this.length();
1721
1722        this.multiplyScalar( Math.max( min, Math.min( max, length ) ) / length );
1723
1724        return this;
1725
1726    },
1727
1728    floor: function () {
1729
1730        this.x = Math.floor( this.x );
1731        this.y = Math.floor( this.y );
1732
1733        return this;
1734
1735    },
1736
1737    ceil: function () {
1738
1739        this.x = Math.ceil( this.x );
1740        this.y = Math.ceil( this.y );
1741
1742        return this;
1743
1744    },
1745
1746    round: function () {
1747
1748        this.x = Math.round( this.x );
1749        this.y = Math.round( this.y );
1750
1751        return this;
1752
1753    },
1754
1755    roundToZero: function () {
1756
1757        this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
1758        this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
1759
1760        return this;
1761
1762    },
1763
1764    negate: function () {
1765
1766        this.x = - this.x;
1767        this.y = - this.y;
1768
1769        return this;
1770
1771    },
1772
1773    dot: function ( v ) {
1774
1775        return this.x * v.x + this.y * v.y;
1776
1777    },
1778
1779    lengthSq: function () {
1780
1781        return this.x * this.x + this.y * this.y;
1782
1783    },
1784
1785    length: function () {
1786
1787        return Math.sqrt( this.x * this.x + this.y * this.y );
1788
1789    },
1790
1791    lengthManhattan: function() {
1792
1793        return Math.abs( this.x ) + Math.abs( this.y );
1794
1795    },
1796
1797    normalize: function () {
1798
1799        return this.divideScalar( this.length() );
1800
1801    },
1802
1803    angle: function () {
1804
1805        // computes the angle in radians with respect to the positive x-axis
1806
1807        var angle = Math.atan2( this.y, this.x );
1808
1809        if ( angle < 0 ) angle += 2 * Math.PI;
1810
1811        return angle;
1812
1813    },
1814
1815    distanceTo: function ( v ) {
1816
1817        return Math.sqrt( this.distanceToSquared( v ) );
1818
1819    },
1820
1821    distanceToSquared: function ( v ) {
1822
1823        var dx = this.x - v.x, dy = this.y - v.y;
1824        return dx * dx + dy * dy;
1825
1826    },
1827
1828    setLength: function ( length ) {
1829
1830        return this.multiplyScalar( length / this.length() );
1831
1832    },
1833
1834    lerp: function ( v, alpha ) {
1835
1836        this.x += ( v.x - this.x ) * alpha;
1837        this.y += ( v.y - this.y ) * alpha;
1838
1839        return this;
1840
1841    },
1842
1843    lerpVectors: function ( v1, v2, alpha ) {
1844
1845        this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
1846
1847        return this;
1848
1849    },
1850
1851    equals: function ( v ) {
1852
1853        return ( ( v.x === this.x ) && ( v.y === this.y ) );
1854
1855    },
1856
1857    fromArray: function ( array, offset ) {
1858
1859        if ( offset === undefined ) offset = 0;
1860
1861        this.x = array[ offset ];
1862        this.y = array[ offset + 1 ];
1863
1864        return this;
1865
1866    },
1867
1868    toArray: function ( array, offset ) {
1869
1870        if ( array === undefined ) array = [];
1871        if ( offset === undefined ) offset = 0;
1872
1873        array[ offset ] = this.x;
1874        array[ offset + 1 ] = this.y;
1875
1876        return array;
1877
1878    },
1879
1880    fromAttribute: function ( attribute, index, offset ) {
1881
1882        if ( offset === undefined ) offset = 0;
1883
1884        index = index * attribute.itemSize + offset;
1885
1886        this.x = attribute.array[ index ];
1887        this.y = attribute.array[ index + 1 ];
1888
1889        return this;
1890
1891    },
1892
1893    rotateAround: function ( center, angle ) {
1894
1895        var c = Math.cos( angle ), s = Math.sin( angle );
1896
1897        var x = this.x - center.x;
1898        var y = this.y - center.y;
1899
1900        this.x = x * c - y * s + center.x;
1901        this.y = x * s + y * c + center.y;
1902
1903        return this;
1904
1905    }
1906
1907};
1908
1909// File:src/math/Vector3.js
1910
1911/**
1912 * @author mrdoob / http://mrdoob.com/
1913 * @author *kile / http://kile.stravaganza.org/
1914 * @author philogb / http://blog.thejit.org/
1915 * @author mikael emtinger / http://gomo.se/
1916 * @author egraether / http://egraether.com/
1917 * @author WestLangley / http://github.com/WestLangley
1918 */
1919
1920THREE.Vector3 = function ( x, y, z ) {
1921
1922    this.x = x || 0;
1923    this.y = y || 0;
1924    this.z = z || 0;
1925
1926};
1927
1928THREE.Vector3.prototype = {
1929
1930    constructor: THREE.Vector3,
1931
1932    set: function ( x, y, z ) {
1933
1934        this.x = x;
1935        this.y = y;
1936        this.z = z;
1937
1938        return this;
1939
1940    },
1941
1942    setScalar: function ( scalar ) {
1943
1944        this.x = scalar;
1945        this.y = scalar;
1946        this.z = scalar;
1947
1948        return this;
1949
1950    },
1951
1952    setX: function ( x ) {
1953
1954        this.x = x;
1955
1956        return this;
1957
1958    },
1959
1960    setY: function ( y ) {
1961
1962        this.y = y;
1963
1964        return this;
1965
1966    },
1967
1968    setZ: function ( z ) {
1969
1970        this.z = z;
1971
1972        return this;
1973
1974    },
1975
1976    setComponent: function ( index, value ) {
1977
1978        switch ( index ) {
1979
1980            case 0: this.x = value; break;
1981            case 1: this.y = value; break;
1982            case 2: this.z = value; break;
1983            default: throw new Error( 'index is out of range: ' + index );
1984
1985        }
1986
1987    },
1988
1989    getComponent: function ( index ) {
1990
1991        switch ( index ) {
1992
1993            case 0: return this.x;
1994            case 1: return this.y;
1995            case 2: return this.z;
1996            default: throw new Error( 'index is out of range: ' + index );
1997
1998        }
1999
2000    },
2001
2002    clone: function () {
2003
2004        return new this.constructor( this.x, this.y, this.z );
2005
2006    },
2007
2008    copy: function ( v ) {
2009
2010        this.x = v.x;
2011        this.y = v.y;
2012        this.z = v.z;
2013
2014        return this;
2015
2016    },
2017
2018    add: function ( v, w ) {
2019
2020        if ( w !== undefined ) {
2021
2022            console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
2023            return this.addVectors( v, w );
2024
2025        }
2026
2027        this.x += v.x;
2028        this.y += v.y;
2029        this.z += v.z;
2030
2031        return this;
2032
2033    },
2034
2035    addScalar: function ( s ) {
2036
2037        this.x += s;
2038        this.y += s;
2039        this.z += s;
2040
2041        return this;
2042
2043    },
2044
2045    addVectors: function ( a, b ) {
2046
2047        this.x = a.x + b.x;
2048        this.y = a.y + b.y;
2049        this.z = a.z + b.z;
2050
2051        return this;
2052
2053    },
2054
2055    addScaledVector: function ( v, s ) {
2056
2057        this.x += v.x * s;
2058        this.y += v.y * s;
2059        this.z += v.z * s;
2060
2061        return this;
2062
2063    },
2064
2065    sub: function ( v, w ) {
2066
2067        if ( w !== undefined ) {
2068
2069            console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
2070            return this.subVectors( v, w );
2071
2072        }
2073
2074        this.x -= v.x;
2075        this.y -= v.y;
2076        this.z -= v.z;
2077
2078        return this;
2079
2080    },
2081
2082    subScalar: function ( s ) {
2083
2084        this.x -= s;
2085        this.y -= s;
2086        this.z -= s;
2087
2088        return this;
2089
2090    },
2091
2092    subVectors: function ( a, b ) {
2093
2094        this.x = a.x - b.x;
2095        this.y = a.y - b.y;
2096        this.z = a.z - b.z;
2097
2098        return this;
2099
2100    },
2101
2102    multiply: function ( v, w ) {
2103
2104        if ( w !== undefined ) {
2105
2106            console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
2107            return this.multiplyVectors( v, w );
2108
2109        }
2110
2111        this.x *= v.x;
2112        this.y *= v.y;
2113        this.z *= v.z;
2114
2115        return this;
2116
2117    },
2118
2119    multiplyScalar: function ( scalar ) {
2120
2121        if ( isFinite( scalar ) ) {
2122
2123            this.x *= scalar;
2124            this.y *= scalar;
2125            this.z *= scalar;
2126
2127        } else {
2128
2129            this.x = 0;
2130            this.y = 0;
2131            this.z = 0;
2132
2133        }
2134
2135        return this;
2136
2137    },
2138
2139    multiplyVectors: function ( a, b ) {
2140
2141        this.x = a.x * b.x;
2142        this.y = a.y * b.y;
2143        this.z = a.z * b.z;
2144
2145        return this;
2146
2147    },
2148
2149    applyEuler: function () {
2150
2151        var quaternion;
2152
2153        return function applyEuler( euler ) {
2154
2155            if ( euler instanceof THREE.Euler === false ) {
2156
2157                console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
2158
2159            }
2160
2161            if ( quaternion === undefined ) quaternion = new THREE.Quaternion();
2162
2163            this.applyQuaternion( quaternion.setFromEuler( euler ) );
2164
2165            return this;
2166
2167        };
2168
2169    }(),
2170
2171    applyAxisAngle: function () {
2172
2173        var quaternion;
2174
2175        return function applyAxisAngle( axis, angle ) {
2176
2177            if ( quaternion === undefined ) quaternion = new THREE.Quaternion();
2178
2179            this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );
2180
2181            return this;
2182
2183        };
2184
2185    }(),
2186
2187    applyMatrix3: function ( m ) {
2188
2189        var x = this.x;
2190        var y = this.y;
2191        var z = this.z;
2192
2193        var e = m.elements;
2194
2195        this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
2196        this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
2197        this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
2198
2199        return this;
2200
2201    },
2202
2203    applyMatrix4: function ( m ) {
2204
2205        // input: THREE.Matrix4 affine matrix
2206
2207        var x = this.x, y = this.y, z = this.z;
2208
2209        var e = m.elements;
2210
2211        this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ]  * z + e[ 12 ];
2212        this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ]  * z + e[ 13 ];
2213        this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ];
2214
2215        return this;
2216
2217    },
2218
2219    applyProjection: function ( m ) {
2220
2221        // input: THREE.Matrix4 projection matrix
2222
2223        var x = this.x, y = this.y, z = this.z;
2224
2225        var e = m.elements;
2226        var d = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); // perspective divide
2227
2228        this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ]  * z + e[ 12 ] ) * d;
2229        this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ]  * z + e[ 13 ] ) * d;
2230        this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * d;
2231
2232        return this;
2233
2234    },
2235
2236    applyQuaternion: function ( q ) {
2237
2238        var x = this.x;
2239        var y = this.y;
2240        var z = this.z;
2241
2242        var qx = q.x;
2243        var qy = q.y;
2244        var qz = q.z;
2245        var qw = q.w;
2246
2247        // calculate quat * vector
2248
2249        var ix =  qw * x + qy * z - qz * y;
2250        var iy =  qw * y + qz * x - qx * z;
2251        var iz =  qw * z + qx * y - qy * x;
2252        var iw = - qx * x - qy * y - qz * z;
2253
2254        // calculate result * inverse quat
2255
2256        this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
2257        this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
2258        this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
2259
2260        return this;
2261
2262    },
2263
2264    project: function () {
2265
2266        var matrix;
2267
2268        return function project( camera ) {
2269
2270            if ( matrix === undefined ) matrix = new THREE.Matrix4();
2271
2272            matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) );
2273            return this.applyProjection( matrix );
2274
2275        };
2276
2277    }(),
2278
2279    unproject: function () {
2280
2281        var matrix;
2282
2283        return function unproject( camera ) {
2284
2285            if ( matrix === undefined ) matrix = new THREE.Matrix4();
2286
2287            matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) );
2288            return this.applyProjection( matrix );
2289
2290        };
2291
2292    }(),
2293
2294    transformDirection: function ( m ) {
2295
2296        // input: THREE.Matrix4 affine matrix
2297        // vector interpreted as a direction
2298
2299        var x = this.x, y = this.y, z = this.z;
2300
2301        var e = m.elements;
2302
2303        this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ]  * z;
2304        this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ]  * z;
2305        this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
2306
2307        this.normalize();
2308
2309        return this;
2310
2311    },
2312
2313    divide: function ( v ) {
2314
2315        this.x /= v.x;
2316        this.y /= v.y;
2317        this.z /= v.z;
2318
2319        return this;
2320
2321    },
2322
2323    divideScalar: function ( scalar ) {
2324
2325        return this.multiplyScalar( 1 / scalar );
2326
2327    },
2328
2329    min: function ( v ) {
2330
2331        this.x = Math.min( this.x, v.x );
2332        this.y = Math.min( this.y, v.y );
2333        this.z = Math.min( this.z, v.z );
2334
2335        return this;
2336
2337    },
2338
2339    max: function ( v ) {
2340
2341        this.x = Math.max( this.x, v.x );
2342        this.y = Math.max( this.y, v.y );
2343        this.z = Math.max( this.z, v.z );
2344
2345        return this;
2346
2347    },
2348
2349    clamp: function ( min, max ) {
2350
2351        // This function assumes min < max, if this assumption isn't true it will not operate correctly
2352
2353        this.x = Math.max( min.x, Math.min( max.x, this.x ) );
2354        this.y = Math.max( min.y, Math.min( max.y, this.y ) );
2355        this.z = Math.max( min.z, Math.min( max.z, this.z ) );
2356
2357        return this;
2358
2359    },
2360
2361    clampScalar: function () {
2362
2363        var min, max;
2364
2365        return function clampScalar( minVal, maxVal ) {
2366
2367            if ( min === undefined ) {
2368
2369                min = new THREE.Vector3();
2370                max = new THREE.Vector3();
2371
2372            }
2373
2374            min.set( minVal, minVal, minVal );
2375            max.set( maxVal, maxVal, maxVal );
2376
2377            return this.clamp( min, max );
2378
2379        };
2380
2381    }(),
2382
2383    clampLength: function ( min, max ) {
2384
2385        var length = this.length();
2386
2387        this.multiplyScalar( Math.max( min, Math.min( max, length ) ) / length );
2388
2389        return this;
2390
2391    },
2392
2393    floor: function () {
2394
2395        this.x = Math.floor( this.x );
2396        this.y = Math.floor( this.y );
2397        this.z = Math.floor( this.z );
2398
2399        return this;
2400
2401    },
2402
2403    ceil: function () {
2404
2405        this.x = Math.ceil( this.x );
2406        this.y = Math.ceil( this.y );
2407        this.z = Math.ceil( this.z );
2408
2409        return this;
2410
2411    },
2412
2413    round: function () {
2414
2415        this.x = Math.round( this.x );
2416        this.y = Math.round( this.y );
2417        this.z = Math.round( this.z );
2418
2419        return this;
2420
2421    },
2422
2423    roundToZero: function () {
2424
2425        this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
2426        this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
2427        this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
2428
2429        return this;
2430
2431    },
2432
2433    negate: function () {
2434
2435        this.x = - this.x;
2436        this.y = - this.y;
2437        this.z = - this.z;
2438
2439        return this;
2440
2441    },
2442
2443    dot: function ( v ) {
2444
2445        return this.x * v.x + this.y * v.y + this.z * v.z;
2446
2447    },
2448
2449    lengthSq: function () {
2450
2451        return this.x * this.x + this.y * this.y + this.z * this.z;
2452
2453    },
2454
2455    length: function () {
2456
2457        return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
2458
2459    },
2460
2461    lengthManhattan: function () {
2462
2463        return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
2464
2465    },
2466
2467    normalize: function () {
2468
2469        return this.divideScalar( this.length() );
2470
2471    },
2472
2473    setLength: function ( length ) {
2474
2475        return this.multiplyScalar( length / this.length() );
2476
2477    },
2478
2479    lerp: function ( v, alpha ) {
2480
2481        this.x += ( v.x - this.x ) * alpha;
2482        this.y += ( v.y - this.y ) * alpha;
2483        this.z += ( v.z - this.z ) * alpha;
2484
2485        return this;
2486
2487    },
2488
2489    lerpVectors: function ( v1, v2, alpha ) {
2490
2491        this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
2492
2493        return this;
2494
2495    },
2496
2497    cross: function ( v, w ) {
2498
2499        if ( w !== undefined ) {
2500
2501            console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
2502            return this.crossVectors( v, w );
2503
2504        }
2505
2506        var x = this.x, y = this.y, z = this.z;
2507
2508        this.x = y * v.z - z * v.y;
2509        this.y = z * v.x - x * v.z;
2510        this.z = x * v.y - y * v.x;
2511
2512        return this;
2513
2514    },
2515
2516    crossVectors: function ( a, b ) {
2517
2518        var ax = a.x, ay = a.y, az = a.z;
2519        var bx = b.x, by = b.y, bz = b.z;
2520
2521        this.x = ay * bz - az * by;
2522        this.y = az * bx - ax * bz;
2523        this.z = ax * by - ay * bx;
2524
2525        return this;
2526
2527    },
2528
2529    projectOnVector: function () {
2530
2531        var v1, dot;
2532
2533        return function projectOnVector( vector ) {
2534
2535            if ( v1 === undefined ) v1 = new THREE.Vector3();
2536
2537            v1.copy( vector ).normalize();
2538
2539            dot = this.dot( v1 );
2540
2541            return this.copy( v1 ).multiplyScalar( dot );
2542
2543        };
2544
2545    }(),
2546
2547    projectOnPlane: function () {
2548
2549        var v1;
2550
2551        return function projectOnPlane( planeNormal ) {
2552
2553            if ( v1 === undefined ) v1 = new THREE.Vector3();
2554
2555            v1.copy( this ).projectOnVector( planeNormal );
2556
2557            return this.sub( v1 );
2558
2559        };
2560
2561    }(),
2562
2563    reflect: function () {
2564
2565        // reflect incident vector off plane orthogonal to normal
2566        // normal is assumed to have unit length
2567
2568        var v1;
2569
2570        return function reflect( normal ) {
2571
2572            if ( v1 === undefined ) v1 = new THREE.Vector3();
2573
2574            return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
2575
2576        };
2577
2578    }(),
2579
2580    angleTo: function ( v ) {
2581
2582        var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
2583
2584        // clamp, to handle numerical problems
2585
2586        return Math.acos( THREE.Math.clamp( theta, - 1, 1 ) );
2587
2588    },
2589
2590    distanceTo: function ( v ) {
2591
2592        return Math.sqrt( this.distanceToSquared( v ) );
2593
2594    },
2595
2596    distanceToSquared: function ( v ) {
2597
2598        var dx = this.x - v.x;
2599        var dy = this.y - v.y;
2600        var dz = this.z - v.z;
2601
2602        return dx * dx + dy * dy + dz * dz;
2603
2604    },
2605
2606    setFromSpherical: function( s ) {
2607
2608        var sinPhiRadius = Math.sin( s.phi ) * s.radius;
2609
2610        this.x = sinPhiRadius * Math.sin( s.theta );
2611        this.y = Math.cos( s.phi ) * s.radius;
2612        this.z = sinPhiRadius * Math.cos( s.theta );
2613
2614        return this;
2615
2616    },
2617
2618    setFromMatrixPosition: function ( m ) {
2619
2620        return this.setFromMatrixColumn( m, 3 );
2621
2622    },
2623
2624    setFromMatrixScale: function ( m ) {
2625
2626        var sx = this.setFromMatrixColumn( m, 0 ).length();
2627        var sy = this.setFromMatrixColumn( m, 1 ).length();
2628        var sz = this.setFromMatrixColumn( m, 2 ).length();
2629
2630        this.x = sx;
2631        this.y = sy;
2632        this.z = sz;
2633
2634        return this;
2635
2636    },
2637
2638    setFromMatrixColumn: function ( m, index ) {
2639
2640        if ( typeof m === 'number' ) {
2641
2642            console.warn( 'THREE.Vector3: setFromMatrixColumn now expects ( matrix, index ).' );
2643
2644            m = arguments[ 1 ];
2645            index = arguments[ 0 ];
2646
2647        }
2648
2649        return this.fromArray( m.elements, index * 4 );
2650
2651    },
2652
2653    equals: function ( v ) {
2654
2655        return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
2656
2657    },
2658
2659    fromArray: function ( array, offset ) {
2660
2661        if ( offset === undefined ) offset = 0;
2662
2663        this.x = array[ offset ];
2664        this.y = array[ offset + 1 ];
2665        this.z = array[ offset + 2 ];
2666
2667        return this;
2668
2669    },
2670
2671    toArray: function ( array, offset ) {
2672
2673        if ( array === undefined ) array = [];
2674        if ( offset === undefined ) offset = 0;
2675
2676        array[ offset ] = this.x;
2677        array[ offset + 1 ] = this.y;
2678        array[ offset + 2 ] = this.z;
2679
2680        return array;
2681
2682    },
2683
2684    fromAttribute: function ( attribute, index, offset ) {
2685
2686        if ( offset === undefined ) offset = 0;
2687
2688        index = index * attribute.itemSize + offset;
2689
2690        this.x = attribute.array[ index ];
2691        this.y = attribute.array[ index + 1 ];
2692        this.z = attribute.array[ index + 2 ];
2693
2694        return this;
2695
2696    }
2697
2698};
2699
2700// File:src/math/Vector4.js
2701
2702/**
2703 * @author supereggbert / http://www.paulbrunt.co.uk/
2704 * @author philogb / http://blog.thejit.org/
2705 * @author mikael emtinger / http://gomo.se/
2706 * @author egraether / http://egraether.com/
2707 * @author WestLangley / http://github.com/WestLangley
2708 */
2709
2710THREE.Vector4 = function ( x, y, z, w ) {
2711
2712    this.x = x || 0;
2713    this.y = y || 0;
2714    this.z = z || 0;
2715    this.w = ( w !== undefined ) ? w : 1;
2716
2717};
2718
2719THREE.Vector4.prototype = {
2720
2721    constructor: THREE.Vector4,
2722
2723    set: function ( x, y, z, w ) {
2724
2725        this.x = x;
2726        this.y = y;
2727        this.z = z;
2728        this.w = w;
2729
2730        return this;
2731
2732    },
2733
2734    setScalar: function ( scalar ) {
2735
2736        this.x = scalar;
2737        this.y = scalar;
2738        this.z = scalar;
2739        this.w = scalar;
2740
2741        return this;
2742
2743    },
2744
2745    setX: function ( x ) {
2746
2747        this.x = x;
2748
2749        return this;
2750
2751    },
2752
2753    setY: function ( y ) {
2754
2755        this.y = y;
2756
2757        return this;
2758
2759    },
2760
2761    setZ: function ( z ) {
2762
2763        this.z = z;
2764
2765        return this;
2766
2767    },
2768
2769    setW: function ( w ) {
2770
2771        this.w = w;
2772
2773        return this;
2774
2775    },
2776
2777    setComponent: function ( index, value ) {
2778
2779        switch ( index ) {
2780
2781            case 0: this.x = value; break;
2782            case 1: this.y = value; break;
2783            case 2: this.z = value; break;
2784            case 3: this.w = value; break;
2785            default: throw new Error( 'index is out of range: ' + index );
2786
2787        }
2788
2789    },
2790
2791    getComponent: function ( index ) {
2792
2793        switch ( index ) {
2794
2795            case 0: return this.x;
2796            case 1: return this.y;
2797            case 2: return this.z;
2798            case 3: return this.w;
2799            default: throw new Error( 'index is out of range: ' + index );
2800
2801        }
2802
2803    },
2804
2805    clone: function () {
2806
2807        return new this.constructor( this.x, this.y, this.z, this.w );
2808
2809    },
2810
2811    copy: function ( v ) {
2812
2813        this.x = v.x;
2814        this.y = v.y;
2815        this.z = v.z;
2816        this.w = ( v.w !== undefined ) ? v.w : 1;
2817
2818        return this;
2819
2820    },
2821
2822    add: function ( v, w ) {
2823
2824        if ( w !== undefined ) {
2825
2826            console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
2827            return this.addVectors( v, w );
2828
2829        }
2830
2831        this.x += v.x;
2832        this.y += v.y;
2833        this.z += v.z;
2834        this.w += v.w;
2835
2836        return this;
2837
2838    },
2839
2840    addScalar: function ( s ) {
2841
2842        this.x += s;
2843        this.y += s;
2844        this.z += s;
2845        this.w += s;
2846
2847        return this;
2848
2849    },
2850
2851    addVectors: function ( a, b ) {
2852
2853        this.x = a.x + b.x;
2854        this.y = a.y + b.y;
2855        this.z = a.z + b.z;
2856        this.w = a.w + b.w;
2857
2858        return this;
2859
2860    },
2861
2862    addScaledVector: function ( v, s ) {
2863
2864        this.x += v.x * s;
2865        this.y += v.y * s;
2866        this.z += v.z * s;
2867        this.w += v.w * s;
2868
2869        return this;
2870
2871    },
2872
2873    sub: function ( v, w ) {
2874
2875        if ( w !== undefined ) {
2876
2877            console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
2878            return this.subVectors( v, w );
2879
2880        }
2881
2882        this.x -= v.x;
2883        this.y -= v.y;
2884        this.z -= v.z;
2885        this.w -= v.w;
2886
2887        return this;
2888
2889    },
2890
2891    subScalar: function ( s ) {
2892
2893        this.x -= s;
2894        this.y -= s;
2895        this.z -= s;
2896        this.w -= s;
2897
2898        return this;
2899
2900    },
2901
2902    subVectors: function ( a, b ) {
2903
2904        this.x = a.x - b.x;
2905        this.y = a.y - b.y;
2906        this.z = a.z - b.z;
2907        this.w = a.w - b.w;
2908
2909        return this;
2910
2911    },
2912
2913    multiplyScalar: function ( scalar ) {
2914
2915        if ( isFinite( scalar ) ) {
2916
2917            this.x *= scalar;
2918            this.y *= scalar;
2919            this.z *= scalar;
2920            this.w *= scalar;
2921
2922        } else {
2923
2924            this.x = 0;
2925            this.y = 0;
2926            this.z = 0;
2927            this.w = 0;
2928
2929        }
2930
2931        return this;
2932
2933    },
2934
2935    applyMatrix4: function ( m ) {
2936
2937        var x = this.x;
2938        var y = this.y;
2939        var z = this.z;
2940        var w = this.w;
2941
2942        var e = m.elements;
2943
2944        this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
2945        this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
2946        this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
2947        this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
2948
2949        return this;
2950
2951    },
2952
2953    divideScalar: function ( scalar ) {
2954
2955        return this.multiplyScalar( 1 / scalar );
2956
2957    },
2958
2959    setAxisAngleFromQuaternion: function ( q ) {
2960
2961        // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
2962
2963        // q is assumed to be normalized
2964
2965        this.w = 2 * Math.acos( q.w );
2966
2967        var s = Math.sqrt( 1 - q.w * q.w );
2968
2969        if ( s < 0.0001 ) {
2970
2971            this.x = 1;
2972            this.y = 0;
2973            this.z = 0;
2974
2975        } else {
2976
2977            this.x = q.x / s;
2978            this.y = q.y / s;
2979            this.z = q.z / s;
2980
2981        }
2982
2983        return this;
2984
2985    },
2986
2987    setAxisAngleFromRotationMatrix: function ( m ) {
2988
2989        // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
2990
2991        // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2992
2993        var angle, x, y, z,		// variables for result
2994            epsilon = 0.01,		// margin to allow for rounding errors
2995            epsilon2 = 0.1,		// margin to distinguish between 0 and 180 degrees
2996
2997            te = m.elements,
2998
2999            m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
3000            m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
3001            m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
3002
3003        if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
3004            ( Math.abs( m13 - m31 ) < epsilon ) &&
3005            ( Math.abs( m23 - m32 ) < epsilon ) ) {
3006
3007            // singularity found
3008            // first check for identity matrix which must have +1 for all terms
3009            // in leading diagonal and zero in other terms
3010
3011            if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
3012                ( Math.abs( m13 + m31 ) < epsilon2 ) &&
3013                ( Math.abs( m23 + m32 ) < epsilon2 ) &&
3014                ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
3015
3016                // this singularity is identity matrix so angle = 0
3017
3018                this.set( 1, 0, 0, 0 );
3019
3020                return this; // zero angle, arbitrary axis
3021
3022            }
3023
3024            // otherwise this singularity is angle = 180
3025
3026            angle = Math.PI;
3027
3028            var xx = ( m11 + 1 ) / 2;
3029            var yy = ( m22 + 1 ) / 2;
3030            var zz = ( m33 + 1 ) / 2;
3031            var xy = ( m12 + m21 ) / 4;
3032            var xz = ( m13 + m31 ) / 4;
3033            var yz = ( m23 + m32 ) / 4;
3034
3035            if ( ( xx > yy ) && ( xx > zz ) ) {
3036
3037                // m11 is the largest diagonal term
3038
3039                if ( xx < epsilon ) {
3040
3041                    x = 0;
3042                    y = 0.707106781;
3043                    z = 0.707106781;
3044
3045                } else {
3046
3047                    x = Math.sqrt( xx );
3048                    y = xy / x;
3049                    z = xz / x;
3050
3051                }
3052
3053            } else if ( yy > zz ) {
3054
3055                // m22 is the largest diagonal term
3056
3057                if ( yy < epsilon ) {
3058
3059                    x = 0.707106781;
3060                    y = 0;
3061                    z = 0.707106781;
3062
3063                } else {
3064
3065                    y = Math.sqrt( yy );
3066                    x = xy / y;
3067                    z = yz / y;
3068
3069                }
3070
3071            } else {
3072
3073                // m33 is the largest diagonal term so base result on this
3074
3075                if ( zz < epsilon ) {
3076
3077                    x = 0.707106781;
3078                    y = 0.707106781;
3079                    z = 0;
3080
3081                } else {
3082
3083                    z = Math.sqrt( zz );
3084                    x = xz / z;
3085                    y = yz / z;
3086
3087                }
3088
3089            }
3090
3091            this.set( x, y, z, angle );
3092
3093            return this; // return 180 deg rotation
3094
3095        }
3096
3097        // as we have reached here there are no singularities so we can handle normally
3098
3099        var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
3100        ( m13 - m31 ) * ( m13 - m31 ) +
3101        ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
3102
3103        if ( Math.abs( s ) < 0.001 ) s = 1;
3104
3105        // prevent divide by zero, should not happen if matrix is orthogonal and should be
3106        // caught by singularity test above, but I've left it in just in case
3107
3108        this.x = ( m32 - m23 ) / s;
3109        this.y = ( m13 - m31 ) / s;
3110        this.z = ( m21 - m12 ) / s;
3111        this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
3112
3113        return this;
3114
3115    },
3116
3117    min: function ( v ) {
3118
3119        this.x = Math.min( this.x, v.x );
3120        this.y = Math.min( this.y, v.y );
3121        this.z = Math.min( this.z, v.z );
3122        this.w = Math.min( this.w, v.w );
3123
3124        return this;
3125
3126    },
3127
3128    max: function ( v ) {
3129
3130        this.x = Math.max( this.x, v.x );
3131        this.y = Math.max( this.y, v.y );
3132        this.z = Math.max( this.z, v.z );
3133        this.w = Math.max( this.w, v.w );
3134
3135        return this;
3136
3137    },
3138
3139    clamp: function ( min, max ) {
3140
3141        // This function assumes min < max, if this assumption isn't true it will not operate correctly
3142
3143        this.x = Math.max( min.x, Math.min( max.x, this.x ) );
3144        this.y = Math.max( min.y, Math.min( max.y, this.y ) );
3145        this.z = Math.max( min.z, Math.min( max.z, this.z ) );
3146        this.w = Math.max( min.w, Math.min( max.w, this.w ) );
3147
3148        return this;
3149
3150    },
3151
3152    clampScalar: function () {
3153
3154        var min, max;
3155
3156        return function clampScalar( minVal, maxVal ) {
3157
3158            if ( min === undefined ) {
3159
3160                min = new THREE.Vector4();
3161                max = new THREE.Vector4();
3162
3163            }
3164
3165            min.set( minVal, minVal, minVal, minVal );
3166            max.set( maxVal, maxVal, maxVal, maxVal );
3167
3168            return this.clamp( min, max );
3169
3170        };
3171
3172    }(),
3173
3174    floor: function () {
3175
3176        this.x = Math.floor( this.x );
3177        this.y = Math.floor( this.y );
3178        this.z = Math.floor( this.z );
3179        this.w = Math.floor( this.w );
3180
3181        return this;
3182
3183    },
3184
3185    ceil: function () {
3186
3187        this.x = Math.ceil( this.x );
3188        this.y = Math.ceil( this.y );
3189        this.z = Math.ceil( this.z );
3190        this.w = Math.ceil( this.w );
3191
3192        return this;
3193
3194    },
3195
3196    round: function () {
3197
3198        this.x = Math.round( this.x );
3199        this.y = Math.round( this.y );
3200        this.z = Math.round( this.z );
3201        this.w = Math.round( this.w );
3202
3203        return this;
3204
3205    },
3206
3207    roundToZero: function () {
3208
3209        this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
3210        this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
3211        this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
3212        this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
3213
3214        return this;
3215
3216    },
3217
3218    negate: function () {
3219
3220        this.x = - this.x;
3221        this.y = - this.y;
3222        this.z = - this.z;
3223        this.w = - this.w;
3224
3225        return this;
3226
3227    },
3228
3229    dot: function ( v ) {
3230
3231        return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
3232
3233    },
3234
3235    lengthSq: function () {
3236
3237        return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
3238
3239    },
3240
3241    length: function () {
3242
3243        return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
3244
3245    },
3246
3247    lengthManhattan: function () {
3248
3249        return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
3250
3251    },
3252
3253    normalize: function () {
3254
3255        return this.divideScalar( this.length() );
3256
3257    },
3258
3259    setLength: function ( length ) {
3260
3261        return this.multiplyScalar( length / this.length() );
3262
3263    },
3264
3265    lerp: function ( v, alpha ) {
3266
3267        this.x += ( v.x - this.x ) * alpha;
3268        this.y += ( v.y - this.y ) * alpha;
3269        this.z += ( v.z - this.z ) * alpha;
3270        this.w += ( v.w - this.w ) * alpha;
3271
3272        return this;
3273
3274    },
3275
3276    lerpVectors: function ( v1, v2, alpha ) {
3277
3278        this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
3279
3280        return this;
3281
3282    },
3283
3284    equals: function ( v ) {
3285
3286        return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
3287
3288    },
3289
3290    fromArray: function ( array, offset ) {
3291
3292        if ( offset === undefined ) offset = 0;
3293
3294        this.x = array[ offset ];
3295        this.y = array[ offset + 1 ];
3296        this.z = array[ offset + 2 ];
3297        this.w = array[ offset + 3 ];
3298
3299        return this;
3300
3301    },
3302
3303    toArray: function ( array, offset ) {
3304
3305        if ( array === undefined ) array = [];
3306        if ( offset === undefined ) offset = 0;
3307
3308        array[ offset ] = this.x;
3309        array[ offset + 1 ] = this.y;
3310        array[ offset + 2 ] = this.z;
3311        array[ offset + 3 ] = this.w;
3312
3313        return array;
3314
3315    },
3316
3317    fromAttribute: function ( attribute, index, offset ) {
3318
3319        if ( offset === undefined ) offset = 0;
3320
3321        index = index * attribute.itemSize + offset;
3322
3323        this.x = attribute.array[ index ];
3324        this.y = attribute.array[ index + 1 ];
3325        this.z = attribute.array[ index + 2 ];
3326        this.w = attribute.array[ index + 3 ];
3327
3328        return this;
3329
3330    }
3331
3332};
3333
3334// File:src/math/Euler.js
3335
3336/**
3337 * @author mrdoob / http://mrdoob.com/
3338 * @author WestLangley / http://github.com/WestLangley
3339 * @author bhouston / http://clara.io
3340 */
3341
3342THREE.Euler = function ( x, y, z, order ) {
3343
3344    this._x = x || 0;
3345    this._y = y || 0;
3346    this._z = z || 0;
3347    this._order = order || THREE.Euler.DefaultOrder;
3348
3349};
3350
3351THREE.Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
3352
3353THREE.Euler.DefaultOrder = 'XYZ';
3354
3355THREE.Euler.prototype = {
3356
3357    constructor: THREE.Euler,
3358
3359    get x () {
3360
3361        return this._x;
3362
3363    },
3364
3365    set x ( value ) {
3366
3367        this._x = value;
3368        this.onChangeCallback();
3369
3370    },
3371
3372    get y () {
3373
3374        return this._y;
3375
3376    },
3377
3378    set y ( value ) {
3379
3380        this._y = value;
3381        this.onChangeCallback();
3382
3383    },
3384
3385    get z () {
3386
3387        return this._z;
3388
3389    },
3390
3391    set z ( value ) {
3392
3393        this._z = value;
3394        this.onChangeCallback();
3395
3396    },
3397
3398    get order () {
3399
3400        return this._order;
3401
3402    },
3403
3404    set order ( value ) {
3405
3406        this._order = value;
3407        this.onChangeCallback();
3408
3409    },
3410
3411    set: function ( x, y, z, order ) {
3412
3413        this._x = x;
3414        this._y = y;
3415        this._z = z;
3416        this._order = order || this._order;
3417
3418        this.onChangeCallback();
3419
3420        return this;
3421
3422    },
3423
3424    clone: function () {
3425
3426        return new this.constructor( this._x, this._y, this._z, this._order );
3427
3428    },
3429
3430    copy: function ( euler ) {
3431
3432        this._x = euler._x;
3433        this._y = euler._y;
3434        this._z = euler._z;
3435        this._order = euler._order;
3436
3437        this.onChangeCallback();
3438
3439        return this;
3440
3441    },
3442
3443    setFromRotationMatrix: function ( m, order, update ) {
3444
3445        var clamp = THREE.Math.clamp;
3446
3447        // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
3448
3449        var te = m.elements;
3450        var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
3451        var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
3452        var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
3453
3454        order = order || this._order;
3455
3456        if ( order === 'XYZ' ) {
3457
3458            this._y = Math.asin( clamp( m13, - 1, 1 ) );
3459
3460            if ( Math.abs( m13 ) < 0.99999 ) {
3461
3462                this._x = Math.atan2( - m23, m33 );
3463                this._z = Math.atan2( - m12, m11 );
3464
3465            } else {
3466
3467                this._x = Math.atan2( m32, m22 );
3468                this._z = 0;
3469
3470            }
3471
3472        } else if ( order === 'YXZ' ) {
3473
3474            this._x = Math.asin( - clamp( m23, - 1, 1 ) );
3475
3476            if ( Math.abs( m23 ) < 0.99999 ) {
3477
3478                this._y = Math.atan2( m13, m33 );
3479                this._z = Math.atan2( m21, m22 );
3480
3481            } else {
3482
3483                this._y = Math.atan2( - m31, m11 );
3484                this._z = 0;
3485
3486            }
3487
3488        } else if ( order === 'ZXY' ) {
3489
3490            this._x = Math.asin( clamp( m32, - 1, 1 ) );
3491
3492            if ( Math.abs( m32 ) < 0.99999 ) {
3493
3494                this._y = Math.atan2( - m31, m33 );
3495                this._z = Math.atan2( - m12, m22 );
3496
3497            } else {
3498
3499                this._y = 0;
3500                this._z = Math.atan2( m21, m11 );
3501
3502            }
3503
3504        } else if ( order === 'ZYX' ) {
3505
3506            this._y = Math.asin( - clamp( m31, - 1, 1 ) );
3507
3508            if ( Math.abs( m31 ) < 0.99999 ) {
3509
3510                this._x = Math.atan2( m32, m33 );
3511                this._z = Math.atan2( m21, m11 );
3512
3513            } else {
3514
3515                this._x = 0;
3516                this._z = Math.atan2( - m12, m22 );
3517
3518            }
3519
3520        } else if ( order === 'YZX' ) {
3521
3522            this._z = Math.asin( clamp( m21, - 1, 1 ) );
3523
3524            if ( Math.abs( m21 ) < 0.99999 ) {
3525
3526                this._x = Math.atan2( - m23, m22 );
3527                this._y = Math.atan2( - m31, m11 );
3528
3529            } else {
3530
3531                this._x = 0;
3532                this._y = Math.atan2( m13, m33 );
3533
3534            }
3535
3536        } else if ( order === 'XZY' ) {
3537
3538            this._z = Math.asin( - clamp( m12, - 1, 1 ) );
3539
3540            if ( Math.abs( m12 ) < 0.99999 ) {
3541
3542                this._x = Math.atan2( m32, m22 );
3543                this._y = Math.atan2( m13, m11 );
3544
3545            } else {
3546
3547                this._x = Math.atan2( - m23, m33 );
3548                this._y = 0;
3549
3550            }
3551
3552        } else {
3553
3554            console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order );
3555
3556        }
3557
3558        this._order = order;
3559
3560        if ( update !== false ) this.onChangeCallback();
3561
3562        return this;
3563
3564    },
3565
3566    setFromQuaternion: function () {
3567
3568        var matrix;
3569
3570        return function ( q, order, update ) {
3571
3572            if ( matrix === undefined ) matrix = new THREE.Matrix4();
3573            matrix.makeRotationFromQuaternion( q );
3574            this.setFromRotationMatrix( matrix, order, update );
3575
3576            return this;
3577
3578        };
3579
3580    }(),
3581
3582    setFromVector3: function ( v, order ) {
3583
3584        return this.set( v.x, v.y, v.z, order || this._order );
3585
3586    },
3587
3588    reorder: function () {
3589
3590        // WARNING: this discards revolution information -bhouston
3591
3592        var q = new THREE.Quaternion();
3593
3594        return function ( newOrder ) {
3595
3596            q.setFromEuler( this );
3597            this.setFromQuaternion( q, newOrder );
3598
3599        };
3600
3601    }(),
3602
3603    equals: function ( euler ) {
3604
3605        return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
3606
3607    },
3608
3609    fromArray: function ( array ) {
3610
3611        this._x = array[ 0 ];
3612        this._y = array[ 1 ];
3613        this._z = array[ 2 ];
3614        if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
3615
3616        this.onChangeCallback();
3617
3618        return this;
3619
3620    },
3621
3622    toArray: function ( array, offset ) {
3623
3624        if ( array === undefined ) array = [];
3625        if ( offset === undefined ) offset = 0;
3626
3627        array[ offset ] = this._x;
3628        array[ offset + 1 ] = this._y;
3629        array[ offset + 2 ] = this._z;
3630        array[ offset + 3 ] = this._order;
3631
3632        return array;
3633
3634    },
3635
3636    toVector3: function ( optionalResult ) {
3637
3638        if ( optionalResult ) {
3639
3640            return optionalResult.set( this._x, this._y, this._z );
3641
3642        } else {
3643
3644            return new THREE.Vector3( this._x, this._y, this._z );
3645
3646        }
3647
3648    },
3649
3650    onChange: function ( callback ) {
3651
3652        this.onChangeCallback = callback;
3653
3654        return this;
3655
3656    },
3657
3658    onChangeCallback: function () {}
3659
3660};
3661
3662// File:src/math/Line3.js
3663
3664/**
3665 * @author bhouston / http://clara.io
3666 */
3667
3668THREE.Line3 = function ( start, end ) {
3669
3670    this.start = ( start !== undefined ) ? start : new THREE.Vector3();
3671    this.end = ( end !== undefined ) ? end : new THREE.Vector3();
3672
3673};
3674
3675THREE.Line3.prototype = {
3676
3677    constructor: THREE.Line3,
3678
3679    set: function ( start, end ) {
3680
3681        this.start.copy( start );
3682        this.end.copy( end );
3683
3684        return this;
3685
3686    },
3687
3688    clone: function () {
3689
3690        return new this.constructor().copy( this );
3691
3692    },
3693
3694    copy: function ( line ) {
3695
3696        this.start.copy( line.start );
3697        this.end.copy( line.end );
3698
3699        return this;
3700
3701    },
3702
3703    center: function ( optionalTarget ) {
3704
3705        var result = optionalTarget || new THREE.Vector3();
3706        return result.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
3707
3708    },
3709
3710    delta: function ( optionalTarget ) {
3711
3712        var result = optionalTarget || new THREE.Vector3();
3713        return result.subVectors( this.end, this.start );
3714
3715    },
3716
3717    distanceSq: function () {
3718
3719        return this.start.distanceToSquared( this.end );
3720
3721    },
3722
3723    distance: function () {
3724
3725        return this.start.distanceTo( this.end );
3726
3727    },
3728
3729    at: function ( t, optionalTarget ) {
3730
3731        var result = optionalTarget || new THREE.Vector3();
3732
3733        return this.delta( result ).multiplyScalar( t ).add( this.start );
3734
3735    },
3736
3737    closestPointToPointParameter: function () {
3738
3739        var startP = new THREE.Vector3();
3740        var startEnd = new THREE.Vector3();
3741
3742        return function ( point, clampToLine ) {
3743
3744            startP.subVectors( point, this.start );
3745            startEnd.subVectors( this.end, this.start );
3746
3747            var startEnd2 = startEnd.dot( startEnd );
3748            var startEnd_startP = startEnd.dot( startP );
3749
3750            var t = startEnd_startP / startEnd2;
3751
3752            if ( clampToLine ) {
3753
3754                t = THREE.Math.clamp( t, 0, 1 );
3755
3756            }
3757
3758            return t;
3759
3760        };
3761
3762    }(),
3763
3764    closestPointToPoint: function ( point, clampToLine, optionalTarget ) {
3765
3766        var t = this.closestPointToPointParameter( point, clampToLine );
3767
3768        var result = optionalTarget || new THREE.Vector3();
3769
3770        return this.delta( result ).multiplyScalar( t ).add( this.start );
3771
3772    },
3773
3774    applyMatrix4: function ( matrix ) {
3775
3776        this.start.applyMatrix4( matrix );
3777        this.end.applyMatrix4( matrix );
3778
3779        return this;
3780
3781    },
3782
3783    equals: function ( line ) {
3784
3785        return line.start.equals( this.start ) && line.end.equals( this.end );
3786
3787    }
3788
3789};
3790
3791// File:src/math/Box2.js
3792
3793/**
3794 * @author bhouston / http://clara.io
3795 */
3796
3797THREE.Box2 = function ( min, max ) {
3798
3799    this.min = ( min !== undefined ) ? min : new THREE.Vector2( + Infinity, + Infinity );
3800    this.max = ( max !== undefined ) ? max : new THREE.Vector2( - Infinity, - Infinity );
3801
3802};
3803
3804THREE.Box2.prototype = {
3805
3806    constructor: THREE.Box2,
3807
3808    set: function ( min, max ) {
3809
3810        this.min.copy( min );
3811        this.max.copy( max );
3812
3813        return this;
3814
3815    },
3816
3817    setFromPoints: function ( points ) {
3818
3819        this.makeEmpty();
3820
3821        for ( var i = 0, il = points.length; i < il; i ++ ) {
3822
3823            this.expandByPoint( points[ i ] );
3824
3825        }
3826
3827        return this;
3828
3829    },
3830
3831    setFromCenterAndSize: function () {
3832
3833        var v1 = new THREE.Vector2();
3834
3835        return function ( center, size ) {
3836
3837            var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
3838            this.min.copy( center ).sub( halfSize );
3839            this.max.copy( center ).add( halfSize );
3840
3841            return this;
3842
3843        };
3844
3845    }(),
3846
3847    clone: function () {
3848
3849        return new this.constructor().copy( this );
3850
3851    },
3852
3853    copy: function ( box ) {
3854
3855        this.min.copy( box.min );
3856        this.max.copy( box.max );
3857
3858        return this;
3859
3860    },
3861
3862    makeEmpty: function () {
3863
3864        this.min.x = this.min.y = + Infinity;
3865        this.max.x = this.max.y = - Infinity;
3866
3867        return this;
3868
3869    },
3870
3871    isEmpty: function () {
3872
3873        // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
3874
3875        return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
3876
3877    },
3878
3879    center: function ( optionalTarget ) {
3880
3881        var result = optionalTarget || new THREE.Vector2();
3882        return result.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
3883
3884    },
3885
3886    size: function ( optionalTarget ) {
3887
3888        var result = optionalTarget || new THREE.Vector2();
3889        return result.subVectors( this.max, this.min );
3890
3891    },
3892
3893    expandByPoint: function ( point ) {
3894
3895        this.min.min( point );
3896        this.max.max( point );
3897
3898        return this;
3899
3900    },
3901
3902    expandByVector: function ( vector ) {
3903
3904        this.min.sub( vector );
3905        this.max.add( vector );
3906
3907        return this;
3908
3909    },
3910
3911    expandByScalar: function ( scalar ) {
3912
3913        this.min.addScalar( - scalar );
3914        this.max.addScalar( scalar );
3915
3916        return this;
3917
3918    },
3919
3920    containsPoint: function ( point ) {
3921
3922        if ( point.x < this.min.x || point.x > this.max.x ||
3923            point.y < this.min.y || point.y > this.max.y ) {
3924
3925            return false;
3926
3927        }
3928
3929        return true;
3930
3931    },
3932
3933    containsBox: function ( box ) {
3934
3935        if ( ( this.min.x <= box.min.x ) && ( box.max.x <= this.max.x ) &&
3936            ( this.min.y <= box.min.y ) && ( box.max.y <= this.max.y ) ) {
3937
3938            return true;
3939
3940        }
3941
3942        return false;
3943
3944    },
3945
3946    getParameter: function ( point, optionalTarget ) {
3947
3948        // This can potentially have a divide by zero if the box
3949        // has a size dimension of 0.
3950
3951        var result = optionalTarget || new THREE.Vector2();
3952
3953        return result.set(
3954            ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
3955            ( point.y - this.min.y ) / ( this.max.y - this.min.y )
3956        );
3957
3958    },
3959
3960    intersectsBox: function ( box ) {
3961
3962        // using 6 splitting planes to rule out intersections.
3963
3964        if ( box.max.x < this.min.x || box.min.x > this.max.x ||
3965            box.max.y < this.min.y || box.min.y > this.max.y ) {
3966
3967            return false;
3968
3969        }
3970
3971        return true;
3972
3973    },
3974
3975    clampPoint: function ( point, optionalTarget ) {
3976
3977        var result = optionalTarget || new THREE.Vector2();
3978        return result.copy( point ).clamp( this.min, this.max );
3979
3980    },
3981
3982    distanceToPoint: function () {
3983
3984        var v1 = new THREE.Vector2();
3985
3986        return function ( point ) {
3987
3988            var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
3989            return clampedPoint.sub( point ).length();
3990
3991        };
3992
3993    }(),
3994
3995    intersect: function ( box ) {
3996
3997        this.min.max( box.min );
3998        this.max.min( box.max );
3999
4000        return this;
4001
4002    },
4003
4004    union: function ( box ) {
4005
4006        this.min.min( box.min );
4007        this.max.max( box.max );
4008
4009        return this;
4010
4011    },
4012
4013    translate: function ( offset ) {
4014
4015        this.min.add( offset );
4016        this.max.add( offset );
4017
4018        return this;
4019
4020    },
4021
4022    equals: function ( box ) {
4023
4024        return box.min.equals( this.min ) && box.max.equals( this.max );
4025
4026    }
4027
4028};
4029
4030// File:src/math/Box3.js
4031
4032/**
4033 * @author bhouston / http://clara.io
4034 * @author WestLangley / http://github.com/WestLangley
4035 */
4036
4037THREE.Box3 = function ( min, max ) {
4038
4039    this.min = ( min !== undefined ) ? min : new THREE.Vector3( + Infinity, + Infinity, + Infinity );
4040    this.max = ( max !== undefined ) ? max : new THREE.Vector3( - Infinity, - Infinity, - Infinity );
4041
4042};
4043
4044THREE.Box3.prototype = {
4045
4046    constructor: THREE.Box3,
4047
4048    set: function ( min, max ) {
4049
4050        this.min.copy( min );
4051        this.max.copy( max );
4052
4053        return this;
4054
4055    },
4056
4057    setFromArray: function ( array ) {
4058
4059        var minX = + Infinity;
4060        var minY = + Infinity;
4061        var minZ = + Infinity;
4062
4063        var maxX = - Infinity;
4064        var maxY = - Infinity;
4065        var maxZ = - Infinity;
4066
4067        for ( var i = 0, l = array.length; i < l; i += 3 ) {
4068
4069            var x = array[ i ];
4070            var y = array[ i + 1 ];
4071            var z = array[ i + 2 ];
4072
4073            if ( x < minX ) minX = x;
4074            if ( y < minY ) minY = y;
4075            if ( z < minZ ) minZ = z;
4076
4077            if ( x > maxX ) maxX = x;
4078            if ( y > maxY ) maxY = y;
4079            if ( z > maxZ ) maxZ = z;
4080
4081        }
4082
4083        this.min.set( minX, minY, minZ );
4084        this.max.set( maxX, maxY, maxZ );
4085
4086    },
4087
4088    setFromPoints: function ( points ) {
4089
4090        this.makeEmpty();
4091
4092        for ( var i = 0, il = points.length; i < il; i ++ ) {
4093
4094            this.expandByPoint( points[ i ] );
4095
4096        }
4097
4098        return this;
4099
4100    },
4101
4102    setFromCenterAndSize: function () {
4103
4104        var v1 = new THREE.Vector3();
4105
4106        return function ( center, size ) {
4107
4108            var halfSize = v1.copy( size ).multiplyScalar( 0.5 );
4109
4110            this.min.copy( center ).sub( halfSize );
4111            this.max.copy( center ).add( halfSize );
4112
4113            return this;
4114
4115        };
4116
4117    }(),
4118
4119    setFromObject: function () {
4120
4121        // Computes the world-axis-aligned bounding box of an object (including its children),
4122        // accounting for both the object's, and children's, world transforms
4123
4124        var v1 = new THREE.Vector3();
4125
4126        return function ( object ) {
4127
4128            var scope = this;
4129
4130            object.updateMatrixWorld( true );
4131
4132            this.makeEmpty();
4133
4134            object.traverse( function ( node ) {
4135
4136                var geometry = node.geometry;
4137
4138                if ( geometry !== undefined ) {
4139
4140                    if ( geometry instanceof THREE.Geometry ) {
4141
4142                        var vertices = geometry.vertices;
4143
4144                        for ( var i = 0, il = vertices.length; i < il; i ++ ) {
4145
4146                            v1.copy( vertices[ i ] );
4147                            v1.applyMatrix4( node.matrixWorld );
4148
4149                            scope.expandByPoint( v1 );
4150
4151                        }
4152
4153                    } else if ( geometry instanceof THREE.BufferGeometry && geometry.attributes[ 'position' ] !== undefined ) {
4154
4155                        var positions = geometry.attributes[ 'position' ].array;
4156
4157                        for ( var i = 0, il = positions.length; i < il; i += 3 ) {
4158
4159                            v1.fromArray( positions, i );
4160                            v1.applyMatrix4( node.matrixWorld );
4161
4162                            scope.expandByPoint( v1 );
4163
4164                        }
4165
4166                    }
4167
4168                }
4169
4170            } );
4171
4172            return this;
4173
4174        };
4175
4176    }(),
4177
4178    clone: function () {
4179
4180        return new this.constructor().copy( this );
4181
4182    },
4183
4184    copy: function ( box ) {
4185
4186        this.min.copy( box.min );
4187        this.max.copy( box.max );
4188
4189        return this;
4190
4191    },
4192
4193    makeEmpty: function () {
4194
4195        this.min.x = this.min.y = this.min.z = + Infinity;
4196        this.max.x = this.max.y = this.max.z = - Infinity;
4197
4198        return this;
4199
4200    },
4201
4202    isEmpty: function () {
4203
4204        // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
4205
4206        return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
4207
4208    },
4209
4210    center: function ( optionalTarget ) {
4211
4212        var result = optionalTarget || new THREE.Vector3();
4213        return result.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
4214
4215    },
4216
4217    size: function ( optionalTarget ) {
4218
4219        var result = optionalTarget || new THREE.Vector3();
4220        return result.subVectors( this.max, this.min );
4221
4222    },
4223
4224    expandByPoint: function ( point ) {
4225
4226        this.min.min( point );
4227        this.max.max( point );
4228
4229        return this;
4230
4231    },
4232
4233    expandByVector: function ( vector ) {
4234
4235        this.min.sub( vector );
4236        this.max.add( vector );
4237
4238        return this;
4239
4240    },
4241
4242    expandByScalar: function ( scalar ) {
4243
4244        this.min.addScalar( - scalar );
4245        this.max.addScalar( scalar );
4246
4247        return this;
4248
4249    },
4250
4251    containsPoint: function ( point ) {
4252
4253        if ( point.x < this.min.x || point.x > this.max.x ||
4254            point.y < this.min.y || point.y > this.max.y ||
4255            point.z < this.min.z || point.z > this.max.z ) {
4256
4257            return false;
4258
4259        }
4260
4261        return true;
4262
4263    },
4264
4265    containsBox: function ( box ) {
4266
4267        if ( ( this.min.x <= box.min.x ) && ( box.max.x <= this.max.x ) &&
4268            ( this.min.y <= box.min.y ) && ( box.max.y <= this.max.y ) &&
4269            ( this.min.z <= box.min.z ) && ( box.max.z <= this.max.z ) ) {
4270
4271            return true;
4272
4273        }
4274
4275        return false;
4276
4277    },
4278
4279    getParameter: function ( point, optionalTarget ) {
4280
4281        // This can potentially have a divide by zero if the box
4282        // has a size dimension of 0.
4283
4284        var result = optionalTarget || new THREE.Vector3();
4285
4286        return result.set(
4287            ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
4288            ( point.y - this.min.y ) / ( this.max.y - this.min.y ),
4289            ( point.z - this.min.z ) / ( this.max.z - this.min.z )
4290        );
4291
4292    },
4293
4294    intersectsBox: function ( box ) {
4295
4296        // using 6 splitting planes to rule out intersections.
4297
4298        if ( box.max.x < this.min.x || box.min.x > this.max.x ||
4299            box.max.y < this.min.y || box.min.y > this.max.y ||
4300            box.max.z < this.min.z || box.min.z > this.max.z ) {
4301
4302            return false;
4303
4304        }
4305
4306        return true;
4307
4308    },
4309
4310    intersectsSphere: ( function () {
4311
4312        var closestPoint;
4313
4314        return function intersectsSphere( sphere ) {
4315
4316            if ( closestPoint === undefined ) closestPoint = new THREE.Vector3();
4317
4318            // Find the point on the AABB closest to the sphere center.
4319            this.clampPoint( sphere.center, closestPoint );
4320
4321            // If that point is inside the sphere, the AABB and sphere intersect.
4322            return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
4323
4324        };
4325
4326    } )(),
4327
4328    intersectsPlane: function ( plane ) {
4329
4330        // We compute the minimum and maximum dot product values. If those values
4331        // are on the same side (back or front) of the plane, then there is no intersection.
4332
4333        var min, max;
4334
4335        if ( plane.normal.x > 0 ) {
4336
4337            min = plane.normal.x * this.min.x;
4338            max = plane.normal.x * this.max.x;
4339
4340        } else {
4341
4342            min = plane.normal.x * this.max.x;
4343            max = plane.normal.x * this.min.x;
4344
4345        }
4346
4347        if ( plane.normal.y > 0 ) {
4348
4349            min += plane.normal.y * this.min.y;
4350            max += plane.normal.y * this.max.y;
4351
4352        } else {
4353
4354            min += plane.normal.y * this.max.y;
4355            max += plane.normal.y * this.min.y;
4356
4357        }
4358
4359        if ( plane.normal.z > 0 ) {
4360
4361            min += plane.normal.z * this.min.z;
4362            max += plane.normal.z * this.max.z;
4363
4364        } else {
4365
4366            min += plane.normal.z * this.max.z;
4367            max += plane.normal.z * this.min.z;
4368
4369        }
4370
4371        return ( min <= plane.constant && max >= plane.constant );
4372
4373    },
4374
4375    clampPoint: function ( point, optionalTarget ) {
4376
4377        var result = optionalTarget || new THREE.Vector3();
4378        return result.copy( point ).clamp( this.min, this.max );
4379
4380    },
4381
4382    distanceToPoint: function () {
4383
4384        var v1 = new THREE.Vector3();
4385
4386        return function ( point ) {
4387
4388            var clampedPoint = v1.copy( point ).clamp( this.min, this.max );
4389            return clampedPoint.sub( point ).length();
4390
4391        };
4392
4393    }(),
4394
4395    getBoundingSphere: function () {
4396
4397        var v1 = new THREE.Vector3();
4398
4399        return function ( optionalTarget ) {
4400
4401            var result = optionalTarget || new THREE.Sphere();
4402
4403            result.center = this.center();
4404            result.radius = this.size( v1 ).length() * 0.5;
4405
4406            return result;
4407
4408        };
4409
4410    }(),
4411
4412    intersect: function ( box ) {
4413
4414        this.min.max( box.min );
4415        this.max.min( box.max );
4416
4417        // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values.
4418        if( this.isEmpty() ) this.makeEmpty();
4419
4420        return this;
4421
4422    },
4423
4424    union: function ( box ) {
4425
4426        this.min.min( box.min );
4427        this.max.max( box.max );
4428
4429        return this;
4430
4431    },
4432
4433    applyMatrix4: function () {
4434
4435        var points = [
4436            new THREE.Vector3(),
4437            new THREE.Vector3(),
4438            new THREE.Vector3(),
4439            new THREE.Vector3(),
4440            new THREE.Vector3(),
4441            new THREE.Vector3(),
4442            new THREE.Vector3(),
4443            new THREE.Vector3()
4444        ];
4445
4446        return function ( matrix ) {
4447
4448            // transform of empty box is an empty box.
4449            if( this.isEmpty() ) return this;
4450
4451            // NOTE: I am using a binary pattern to specify all 2^3 combinations below
4452            points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
4453            points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
4454            points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
4455            points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
4456            points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
4457            points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
4458            points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
4459            points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix );	// 111
4460
4461            this.setFromPoints( points );
4462
4463            return this;
4464
4465        };
4466
4467    }(),
4468
4469    translate: function ( offset ) {
4470
4471        this.min.add( offset );
4472        this.max.add( offset );
4473
4474        return this;
4475
4476    },
4477
4478    equals: function ( box ) {
4479
4480        return box.min.equals( this.min ) && box.max.equals( this.max );
4481
4482    }
4483
4484};
4485
4486// File:src/math/Matrix3.js
4487
4488/**
4489 * @author alteredq / http://alteredqualia.com/
4490 * @author WestLangley / http://github.com/WestLangley
4491 * @author bhouston / http://clara.io
4492 * @author tschw
4493 */
4494
4495THREE.Matrix3 = function () {
4496
4497    this.elements = new Float32Array( [
4498
4499        1, 0, 0,
4500        0, 1, 0,
4501        0, 0, 1
4502
4503    ] );
4504
4505    if ( arguments.length > 0 ) {
4506
4507        console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
4508
4509    }
4510
4511};
4512
4513THREE.Matrix3.prototype = {
4514
4515    constructor: THREE.Matrix3,
4516
4517    set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
4518
4519        var te = this.elements;
4520
4521        te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
4522        te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
4523        te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
4524
4525        return this;
4526
4527    },
4528
4529    identity: function () {
4530
4531        this.set(
4532
4533            1, 0, 0,
4534            0, 1, 0,
4535            0, 0, 1
4536
4537        );
4538
4539        return this;
4540
4541    },
4542
4543    clone: function () {
4544
4545        return new this.constructor().fromArray( this.elements );
4546
4547    },
4548
4549    copy: function ( m ) {
4550
4551        var me = m.elements;
4552
4553        this.set(
4554
4555            me[ 0 ], me[ 3 ], me[ 6 ],
4556            me[ 1 ], me[ 4 ], me[ 7 ],
4557            me[ 2 ], me[ 5 ], me[ 8 ]
4558
4559        );
4560
4561        return this;
4562
4563    },
4564
4565    setFromMatrix4: function( m ) {
4566
4567        var me = m.elements;
4568
4569        this.set(
4570
4571            me[ 0 ], me[ 4 ], me[  8 ],
4572            me[ 1 ], me[ 5 ], me[  9 ],
4573            me[ 2 ], me[ 6 ], me[ 10 ]
4574
4575        );
4576
4577        return this;
4578
4579    },
4580
4581    applyToVector3Array: function () {
4582
4583        var v1;
4584
4585        return function ( array, offset, length ) {
4586
4587            if ( v1 === undefined ) v1 = new THREE.Vector3();
4588            if ( offset === undefined ) offset = 0;
4589            if ( length === undefined ) length = array.length;
4590
4591            for ( var i = 0, j = offset; i < length; i += 3, j += 3 ) {
4592
4593                v1.fromArray( array, j );
4594                v1.applyMatrix3( this );
4595                v1.toArray( array, j );
4596
4597            }
4598
4599            return array;
4600
4601        };
4602
4603    }(),
4604
4605    applyToBuffer: function () {
4606
4607        var v1;
4608
4609        return function applyToBuffer( buffer, offset, length ) {
4610
4611            if ( v1 === undefined ) v1 = new THREE.Vector3();
4612            if ( offset === undefined ) offset = 0;
4613            if ( length === undefined ) length = buffer.length / buffer.itemSize;
4614
4615            for ( var i = 0, j = offset; i < length; i ++, j ++ ) {
4616
4617                v1.x = buffer.getX( j );
4618                v1.y = buffer.getY( j );
4619                v1.z = buffer.getZ( j );
4620
4621                v1.applyMatrix3( this );
4622
4623                buffer.setXYZ( v1.x, v1.y, v1.z );
4624
4625            }
4626
4627            return buffer;
4628
4629        };
4630
4631    }(),
4632
4633    multiplyScalar: function ( s ) {
4634
4635        var te = this.elements;
4636
4637        te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
4638        te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
4639        te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
4640
4641        return this;
4642
4643    },
4644
4645    determinant: function () {
4646
4647        var te = this.elements;
4648
4649        var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
4650            d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
4651            g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
4652
4653        return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
4654
4655    },
4656
4657    getInverse: function ( matrix, throwOnDegenerate ) {
4658
4659        if ( matrix instanceof THREE.Matrix4 ) {
4660
4661            console.error( "THREE.Matrix3.getInverse no longer takes a Matrix4 argument." );
4662
4663        }
4664
4665        var me = matrix.elements,
4666            te = this.elements,
4667
4668            n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],
4669            n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],
4670            n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],
4671
4672            t11 = n33 * n22 - n32 * n23,
4673            t12 = n32 * n13 - n33 * n12,
4674            t13 = n23 * n12 - n22 * n13,
4675
4676            det = n11 * t11 + n21 * t12 + n31 * t13;
4677
4678        if ( det === 0 ) {
4679
4680            var msg = "THREE.Matrix3.getInverse(): can't invert matrix, determinant is 0";
4681
4682            if ( throwOnDegenerate || false ) {
4683
4684                throw new Error( msg );
4685
4686            } else {
4687
4688                console.warn( msg );
4689
4690            }
4691
4692            return this.identity();
4693        }
4694
4695        te[ 0 ] = t11;
4696        te[ 1 ] = n31 * n23 - n33 * n21;
4697        te[ 2 ] = n32 * n21 - n31 * n22;
4698
4699        te[ 3 ] = t12;
4700        te[ 4 ] = n33 * n11 - n31 * n13;
4701        te[ 5 ] = n31 * n12 - n32 * n11;
4702
4703        te[ 6 ] = t13;
4704        te[ 7 ] = n21 * n13 - n23 * n11;
4705        te[ 8 ] = n22 * n11 - n21 * n12;
4706
4707        return this.multiplyScalar( 1 / det );
4708
4709    },
4710
4711    transpose: function () {
4712
4713        var tmp, m = this.elements;
4714
4715        tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
4716        tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
4717        tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
4718
4719        return this;
4720
4721    },
4722
4723    flattenToArrayOffset: function ( array, offset ) {
4724
4725        console.warn( "THREE.Matrix3: .flattenToArrayOffset is deprecated " +
4726        "- just use .toArray instead." );
4727
4728        return this.toArray( array, offset );
4729
4730    },
4731
4732    getNormalMatrix: function ( matrix4 ) {
4733
4734        return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();
4735
4736    },
4737
4738    transposeIntoArray: function ( r ) {
4739
4740        var m = this.elements;
4741
4742        r[ 0 ] = m[ 0 ];
4743        r[ 1 ] = m[ 3 ];
4744        r[ 2 ] = m[ 6 ];
4745        r[ 3 ] = m[ 1 ];
4746        r[ 4 ] = m[ 4 ];
4747        r[ 5 ] = m[ 7 ];
4748        r[ 6 ] = m[ 2 ];
4749        r[ 7 ] = m[ 5 ];
4750        r[ 8 ] = m[ 8 ];
4751
4752        return this;
4753
4754    },
4755
4756    fromArray: function ( array ) {
4757
4758        this.elements.set( array );
4759
4760        return this;
4761
4762    },
4763
4764    toArray: function ( array, offset ) {
4765
4766        if ( array === undefined ) array = [];
4767        if ( offset === undefined ) offset = 0;
4768
4769        var te = this.elements;
4770
4771        array[ offset ] = te[ 0 ];
4772        array[ offset + 1 ] = te[ 1 ];
4773        array[ offset + 2 ] = te[ 2 ];
4774
4775        array[ offset + 3 ] = te[ 3 ];
4776        array[ offset + 4 ] = te[ 4 ];
4777        array[ offset + 5 ] = te[ 5 ];
4778
4779        array[ offset + 6 ] = te[ 6 ];
4780        array[ offset + 7 ] = te[ 7 ];
4781        array[ offset + 8 ]  = te[ 8 ];
4782
4783        return array;
4784
4785    }
4786
4787};
4788
4789// File:src/math/Matrix4.js
4790
4791/**
4792 * @author mrdoob / http://mrdoob.com/
4793 * @author supereggbert / http://www.paulbrunt.co.uk/
4794 * @author philogb / http://blog.thejit.org/
4795 * @author jordi_ros / http://plattsoft.com
4796 * @author D1plo1d / http://github.com/D1plo1d
4797 * @author alteredq / http://alteredqualia.com/
4798 * @author mikael emtinger / http://gomo.se/
4799 * @author timknip / http://www.floorplanner.com/
4800 * @author bhouston / http://clara.io
4801 * @author WestLangley / http://github.com/WestLangley
4802 */
4803
4804THREE.Matrix4 = function () {
4805
4806    this.elements = new Float32Array( [
4807
4808        1, 0, 0, 0,
4809        0, 1, 0, 0,
4810        0, 0, 1, 0,
4811        0, 0, 0, 1
4812
4813    ] );
4814
4815    if ( arguments.length > 0 ) {
4816
4817        console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
4818
4819    }
4820
4821};
4822
4823THREE.Matrix4.prototype = {
4824
4825    constructor: THREE.Matrix4,
4826
4827    set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
4828
4829        var te = this.elements;
4830
4831        te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
4832        te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
4833        te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
4834        te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
4835
4836        return this;
4837
4838    },
4839
4840    identity: function () {
4841
4842        this.set(
4843
4844            1, 0, 0, 0,
4845            0, 1, 0, 0,
4846            0, 0, 1, 0,
4847            0, 0, 0, 1
4848
4849        );
4850
4851        return this;
4852
4853    },
4854
4855    clone: function () {
4856
4857        return new THREE.Matrix4().fromArray( this.elements );
4858
4859    },
4860
4861    copy: function ( m ) {
4862
4863        this.elements.set( m.elements );
4864
4865        return this;
4866
4867    },
4868
4869    copyPosition: function ( m ) {
4870
4871        var te = this.elements;
4872        var me = m.elements;
4873
4874        te[ 12 ] = me[ 12 ];
4875        te[ 13 ] = me[ 13 ];
4876        te[ 14 ] = me[ 14 ];
4877
4878        return this;
4879
4880    },
4881
4882    extractBasis: function ( xAxis, yAxis, zAxis ) {
4883
4884        xAxis.setFromMatrixColumn( this, 0 );
4885        yAxis.setFromMatrixColumn( this, 1 );
4886        zAxis.setFromMatrixColumn( this, 2 );
4887
4888        return this;
4889
4890    },
4891
4892    makeBasis: function ( xAxis, yAxis, zAxis ) {
4893
4894        this.set(
4895            xAxis.x, yAxis.x, zAxis.x, 0,
4896            xAxis.y, yAxis.y, zAxis.y, 0,
4897            xAxis.z, yAxis.z, zAxis.z, 0,
4898            0,       0,       0,       1
4899        );
4900
4901        return this;
4902
4903    },
4904
4905    extractRotation: function () {
4906
4907        var v1;
4908
4909        return function ( m ) {
4910
4911            if ( v1 === undefined ) v1 = new THREE.Vector3();
4912
4913            var te = this.elements;
4914            var me = m.elements;
4915
4916            var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length();
4917            var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length();
4918            var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length();
4919
4920            te[ 0 ] = me[ 0 ] * scaleX;
4921            te[ 1 ] = me[ 1 ] * scaleX;
4922            te[ 2 ] = me[ 2 ] * scaleX;
4923
4924            te[ 4 ] = me[ 4 ] * scaleY;
4925            te[ 5 ] = me[ 5 ] * scaleY;
4926            te[ 6 ] = me[ 6 ] * scaleY;
4927
4928            te[ 8 ] = me[ 8 ] * scaleZ;
4929            te[ 9 ] = me[ 9 ] * scaleZ;
4930            te[ 10 ] = me[ 10 ] * scaleZ;
4931
4932            return this;
4933
4934        };
4935
4936    }(),
4937
4938    makeRotationFromEuler: function ( euler ) {
4939
4940        if ( euler instanceof THREE.Euler === false ) {
4941
4942            console.error( 'THREE.Matrix: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
4943
4944        }
4945
4946        var te = this.elements;
4947
4948        var x = euler.x, y = euler.y, z = euler.z;
4949        var a = Math.cos( x ), b = Math.sin( x );
4950        var c = Math.cos( y ), d = Math.sin( y );
4951        var e = Math.cos( z ), f = Math.sin( z );
4952
4953        if ( euler.order === 'XYZ' ) {
4954
4955            var ae = a * e, af = a * f, be = b * e, bf = b * f;
4956
4957            te[ 0 ] = c * e;
4958            te[ 4 ] = - c * f;
4959            te[ 8 ] = d;
4960
4961            te[ 1 ] = af + be * d;
4962            te[ 5 ] = ae - bf * d;
4963            te[ 9 ] = - b * c;
4964
4965            te[ 2 ] = bf - ae * d;
4966            te[ 6 ] = be + af * d;
4967            te[ 10 ] = a * c;
4968
4969        } else if ( euler.order === 'YXZ' ) {
4970
4971            var ce = c * e, cf = c * f, de = d * e, df = d * f;
4972
4973            te[ 0 ] = ce + df * b;
4974            te[ 4 ] = de * b - cf;
4975            te[ 8 ] = a * d;
4976
4977            te[ 1 ] = a * f;
4978            te[ 5 ] = a * e;
4979            te[ 9 ] = - b;
4980
4981            te[ 2 ] = cf * b - de;
4982            te[ 6 ] = df + ce * b;
4983            te[ 10 ] = a * c;
4984
4985        } else if ( euler.order === 'ZXY' ) {
4986
4987            var ce = c * e, cf = c * f, de = d * e, df = d * f;
4988
4989            te[ 0 ] = ce - df * b;
4990            te[ 4 ] = - a * f;
4991            te[ 8 ] = de + cf * b;
4992
4993            te[ 1 ] = cf + de * b;
4994            te[ 5 ] = a * e;
4995            te[ 9 ] = df - ce * b;
4996
4997            te[ 2 ] = - a * d;
4998            te[ 6 ] = b;
4999            te[ 10 ] = a * c;
5000
5001        } else if ( euler.order === 'ZYX' ) {
5002
5003            var ae = a * e, af = a * f, be = b * e, bf = b * f;
5004
5005            te[ 0 ] = c * e;
5006            te[ 4 ] = be * d - af;
5007            te[ 8 ] = ae * d + bf;
5008
5009            te[ 1 ] = c * f;
5010            te[ 5 ] = bf * d + ae;
5011            te[ 9 ] = af * d - be;
5012
5013            te[ 2 ] = - d;
5014            te[ 6 ] = b * c;
5015            te[ 10 ] = a * c;
5016
5017        } else if ( euler.order === 'YZX' ) {
5018
5019            var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
5020
5021            te[ 0 ] = c * e;
5022            te[ 4 ] = bd - ac * f;
5023            te[ 8 ] = bc * f + ad;
5024
5025            te[ 1 ] = f;
5026            te[ 5 ] = a * e;
5027            te[ 9 ] = - b * e;
5028
5029            te[ 2 ] = - d * e;
5030            te[ 6 ] = ad * f + bc;
5031            te[ 10 ] = ac - bd * f;
5032
5033        } else if ( euler.order === 'XZY' ) {
5034
5035            var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
5036
5037            te[ 0 ] = c * e;
5038            te[ 4 ] = - f;
5039            te[ 8 ] = d * e;
5040
5041            te[ 1 ] = ac * f + bd;
5042            te[ 5 ] = a * e;
5043            te[ 9 ] = ad * f - bc;
5044
5045            te[ 2 ] = bc * f - ad;
5046            te[ 6 ] = b * e;
5047            te[ 10 ] = bd * f + ac;
5048
5049        }
5050
5051        // last column
5052        te[ 3 ] = 0;
5053        te[ 7 ] = 0;
5054        te[ 11 ] = 0;
5055
5056        // bottom row
5057        te[ 12 ] = 0;
5058        te[ 13 ] = 0;
5059        te[ 14 ] = 0;
5060        te[ 15 ] = 1;
5061
5062        return this;
5063
5064    },
5065
5066    makeRotationFromQuaternion: function ( q ) {
5067
5068        var te = this.elements;
5069
5070        var x = q.x, y = q.y, z = q.z, w = q.w;
5071        var x2 = x + x, y2 = y + y, z2 = z + z;
5072        var xx = x * x2, xy = x * y2, xz = x * z2;
5073        var yy = y * y2, yz = y * z2, zz = z * z2;
5074        var wx = w * x2, wy = w * y2, wz = w * z2;
5075
5076        te[ 0 ] = 1 - ( yy + zz );
5077        te[ 4 ] = xy - wz;
5078        te[ 8 ] = xz + wy;
5079
5080        te[ 1 ] = xy + wz;
5081        te[ 5 ] = 1 - ( xx + zz );
5082        te[ 9 ] = yz - wx;
5083
5084        te[ 2 ] = xz - wy;
5085        te[ 6 ] = yz + wx;
5086        te[ 10 ] = 1 - ( xx + yy );
5087
5088        // last column
5089        te[ 3 ] = 0;
5090        te[ 7 ] = 0;
5091        te[ 11 ] = 0;
5092
5093        // bottom row
5094        te[ 12 ] = 0;
5095        te[ 13 ] = 0;
5096        te[ 14 ] = 0;
5097        te[ 15 ] = 1;
5098
5099        return this;
5100
5101    },
5102
5103    lookAt: function () {
5104
5105        var x, y, z;
5106
5107        return function ( eye, target, up ) {
5108
5109            if ( x === undefined ) x = new THREE.Vector3();
5110            if ( y === undefined ) y = new THREE.Vector3();
5111            if ( z === undefined ) z = new THREE.Vector3();
5112
5113            var te = this.elements;
5114
5115            z.subVectors( eye, target ).normalize();
5116
5117            if ( z.lengthSq() === 0 ) {
5118
5119                z.z = 1;
5120
5121            }
5122
5123            x.crossVectors( up, z ).normalize();
5124
5125            if ( x.lengthSq() === 0 ) {
5126
5127                z.x += 0.0001;
5128                x.crossVectors( up, z ).normalize();
5129
5130            }
5131
5132            y.crossVectors( z, x );
5133
5134
5135            te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
5136            te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
5137            te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
5138
5139            return this;
5140
5141        };
5142
5143    }(),
5144
5145    multiply: function ( m, n ) {
5146
5147        if ( n !== undefined ) {
5148
5149            console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
5150            return this.multiplyMatrices( m, n );
5151
5152        }
5153
5154        return this.multiplyMatrices( this, m );
5155
5156    },
5157
5158    premultiply: function ( m ) {
5159
5160        return this.multiplyMatrices( m, this );
5161
5162    },
5163
5164    multiplyMatrices: function ( a, b ) {
5165
5166        var ae = a.elements;
5167        var be = b.elements;
5168        var te = this.elements;
5169
5170        var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
5171        var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
5172        var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
5173        var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
5174
5175        var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
5176        var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
5177        var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
5178        var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
5179
5180        te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
5181        te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
5182        te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
5183        te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
5184
5185        te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
5186        te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
5187        te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
5188        te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
5189
5190        te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
5191        te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
5192        te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
5193        te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
5194
5195        te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
5196        te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
5197        te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
5198        te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
5199
5200        return this;
5201
5202    },
5203
5204    multiplyToArray: function ( a, b, r ) {
5205
5206        var te = this.elements;
5207
5208        this.multiplyMatrices( a, b );
5209
5210        r[ 0 ] = te[ 0 ]; r[ 1 ] = te[ 1 ]; r[ 2 ] = te[ 2 ]; r[ 3 ] = te[ 3 ];
5211        r[ 4 ] = te[ 4 ]; r[ 5 ] = te[ 5 ]; r[ 6 ] = te[ 6 ]; r[ 7 ] = te[ 7 ];
5212        r[ 8 ]  = te[ 8 ]; r[ 9 ]  = te[ 9 ]; r[ 10 ] = te[ 10 ]; r[ 11 ] = te[ 11 ];
5213        r[ 12 ] = te[ 12 ]; r[ 13 ] = te[ 13 ]; r[ 14 ] = te[ 14 ]; r[ 15 ] = te[ 15 ];
5214
5215        return this;
5216
5217    },
5218
5219    multiplyScalar: function ( s ) {
5220
5221        var te = this.elements;
5222
5223        te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s;
5223 te[ 12 ] *= s;
5224        te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
5225        te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
5226        te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
5227
5228        return this;
5229
5230    },
5231
5232    applyToVector3Array: function () {
5233
5234        var v1;
5235
5236        return function ( array, offset, length ) {
5237
5238            if ( v1 === undefined ) v1 = new THREE.Vector3();
5239            if ( offset === undefined ) offset = 0;
5240            if ( length === undefined ) length = array.length;
5241
5242            for ( var i = 0, j = offset; i < length; i += 3, j += 3 ) {
5243
5244                v1.fromArray( array, j );
5245                v1.applyMatrix4( this );
5246                v1.toArray( array, j );
5247
5248            }
5249
5250            return array;
5251
5252        };
5253
5254    }(),
5255
5256    applyToBuffer: function () {
5257
5258        var v1;
5259
5260        return function applyToBuffer( buffer, offset, length ) {
5261
5262            if ( v1 === undefined ) v1 = new THREE.Vector3();
5263            if ( offset === undefined ) offset = 0;
5264            if ( length === undefined ) length = buffer.length / buffer.itemSize;
5265
5266            for ( var i = 0, j = offset; i < length; i ++, j ++ ) {
5267
5268                v1.x = buffer.getX( j );
5269                v1.y = buffer.getY( j );
5270                v1.z = buffer.getZ( j );
5271
5272                v1.applyMatrix4( this );
5273
5274                buffer.setXYZ( v1.x, v1.y, v1.z );
5275
5276            }
5277
5278            return buffer;
5279
5280        };
5281
5282    }(),
5283
5284    determinant: function () {
5285
5286        var te = this.elements;
5287
5288        var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
5289        var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
5290        var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
5291        var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
5292
5293        //TODO: make this more efficient
5294        //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
5295
5296        return (
5297        n41 * (
5298        + n14 * n23 * n32
5299        - n13 * n24 * n32
5300        - n14 * n22 * n33
5301        + n12 * n24 * n33
5302        + n13 * n22 * n34
5303        - n12 * n23 * n34
5304        ) +
5305        n42 * (
5306        + n11 * n23 * n34
5307        - n11 * n24 * n33
5308        + n14 * n21 * n33
5309        - n13 * n21 * n34
5310        + n13 * n24 * n31
5311        - n14 * n23 * n31
5312        ) +
5313        n43 * (
5314        + n11 * n24 * n32
5315        - n11 * n22 * n34
5316        - n14 * n21 * n32
5317        + n12 * n21 * n34
5318        + n14 * n22 * n31
5319        - n12 * n24 * n31
5320        ) +
5321        n44 * (
5322        - n13 * n22 * n31
5323        - n11 * n23 * n32
5324        + n11 * n22 * n33
5325        + n13 * n21 * n32
5326        - n12 * n21 * n33
5327        + n12 * n23 * n31
5328        )
5329
5330        );
5331
5332    },
5333
5334    transpose: function () {
5335
5336        var te = this.elements;
5337        var tmp;
5338
5339        tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
5340        tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
5341        tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
5342
5343        tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
5344        tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
5345        tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
5346
5347        return this;
5348
5349    },
5350
5351    flattenToArrayOffset: function ( array, offset ) {
5352
5353        console.warn( "THREE.Matrix3: .flattenToArrayOffset is deprecated " +
5354        "- just use .toArray instead." );
5355
5356        return this.toArray( array, offset );
5357
5358    },
5359
5360    getPosition: function () {
5361
5362        var v1;
5363
5364        return function () {
5365
5366            if ( v1 === undefined ) v1 = new THREE.Vector3();
5367            console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
5368
5369            return v1.setFromMatrixColumn( this, 3 );
5370
5371        };
5372
5373    }(),
5374
5375    setPosition: function ( v ) {
5376
5377        var te = this.elements;
5378
5379        te[ 12 ] = v.x;
5380        te[ 13 ] = v.y;
5381        te[ 14 ] = v.z;
5382
5383        return this;
5384
5385    },
5386
5387    getInverse: function ( m, throwOnDegenerate ) {
5388
5389        // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
5390        var te = this.elements,
5391            me = m.elements,
5392
5393            n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],
5394            n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],
5395            n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],
5396            n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],
5397
5398            t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
5399            t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 
5399+ n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
5400            t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
5401            t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
5402
5403        var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
5404
5405        if ( det === 0 ) {
5406
5407            var msg = "THREE.Matrix4.getInverse(): can't invert matrix, determinant is 0";
5408
5409            if ( throwOnDegenerate || false ) {
5410
5411                throw new Error( msg );
5412
5413            } else {
5414
5415                console.warn( msg );
5416
5417            }
5418
5419            return this.identity();
5420
5421        }
5422
5423        te[ 0 ] = t11;
5424        te[ 1 ] = n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44;
5425        te[ 2 ] = n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44;
5426        te[ 3 ] = n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43;
5427
5428        te[ 4 ] = t12;
5429        te[ 5 ] = n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44;
5430        te[ 6 ] = n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44;
5431        te[ 7 ] = n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43;
5432
5433        te[ 8 ] = t13;
5434        te[ 9 ] = n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44;
5435        te[ 10 ] = n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44;
5436        te[ 11 ] = n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43;
5437
5438        te[ 12 ] = t14;
5439        te[ 13 ] = n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34;
5440        te[ 14 ] = n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34;
5441        te[ 15 ] = n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33;
5442
5443        return this.multiplyScalar( 1 / det );
5444
5445    },
5446
5447    scale: function ( v ) {
5448
5449        var te = this.elements;
5450        var x = v.x, y = v.y, z = v.z;
5451
5452        te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
5453        te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
5454        te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
5455        te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
5456
5457        return this;
5458
5459    },
5460
5461    getMaxScaleOnAxis: function () {
5462
5463        var te = this.elements;
5464
5465        var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
5466        var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
5467        var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
5468
5469        return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
5470
5471    },
5472
5473    makeTranslation: function ( x, y, z ) {
5474
5475        this.set(
5476
5477            1, 0, 0, x,
5478            0, 1, 0, y,
5479            0, 0, 1, z,
5480            0, 0, 0, 1
5481
5482        );
5483
5484        return this;
5485
5486    },
5487
5488    makeRotationX: function ( theta ) {
5489
5490        var c = Math.cos( theta ), s = Math.sin( theta );
5491
5492        this.set(
5493
5494            1, 0,  0, 0,
5495            0, c, - s, 0,
5496            0, s,  c, 0,
5497            0, 0,  0, 1
5498
5499        );
5500
5501        return this;
5502
5503    },
5504
5505    makeRotationY: function ( theta ) {
5506
5507        var c = Math.cos( theta ), s = Math.sin( theta );
5508
5509        this.set(
5510
5511            c, 0, s, 0,
5512            0, 1, 0, 0,
5513            - s, 0, c, 0,
5514            0, 0, 0, 1
5515
5516        );
5517
5518        return this;
5519
5520    },
5521
5522    makeRotationZ: function ( theta ) {
5523
5524        var c = Math.cos( theta ), s = Math.sin( theta );
5525
5526        this.set(
5527
5528            c, - s, 0, 0,
5529            s,  c, 0, 0,
5530            0,  0, 1, 0,
5531            0,  0, 0, 1
5532
5533        );
5534
5535        return this;
5536
5537    },
5538
5539    makeRotationAxis: function ( axis, angle ) {
5540
5541        // Based on http://www.gamedev.net/reference/articles/article1199.asp
5542
5543        var c = Math.cos( angle );
5544        var s = Math.sin( angle );
5545        var t = 1 - c;
5546        var x = axis.x, y = axis.y, z = axis.z;
5547        var tx = t * x, ty = t * y;
5548
5549        this.set(
5550
5551            tx * x + c, tx * y - s * z, tx * z + s * y, 0,
5552            tx * y + s * z, ty * y + c, ty * z - s * x, 0,
5553            tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
5554            0, 0, 0, 1
5555
5556        );
5557
5558        return this;
5559
5560    },
5561
5562    makeScale: function ( x, y, z ) {
5563
5564        this.set(
5565
5566            x, 0, 0, 0,
5567            0, y, 0, 0,
5568            0, 0, z, 0,
5569            0, 0, 0, 1
5570
5571        );
5572
5573        return this;
5574
5575    },
5576
5577    compose: function ( position, quaternion, scale ) {
5578
5579        this.makeRotationFromQuaternion( quaternion );
5580        this.scale( scale );
5581        this.setPosition( position );
5582
5583        return this;
5584
5585    },
5586
5587    decompose: function () {
5588
5589        var vector, matrix;
5590
5591        return function ( position, quaternion, scale ) {
5592
5593            if ( vector === undefined ) vector = new THREE.Vector3();
5594            if ( matrix === undefined ) matrix = new THREE.Matrix4();
5595
5596            var te = this.elements;
5597
5598            var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
5599            var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
5600            var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
5601
5602            // if determine is negative, we need to invert one scale
5603            var det = this.determinant();
5604            if ( det < 0 ) {
5605
5606                sx = - sx;
5607
5608            }
5609
5610            position.x = te[ 12 ];
5611            position.y = te[ 13 ];
5612            position.z = te[ 14 ];
5613
5614            // scale the rotation part
5615
5616            matrix.elements.set( this.elements ); // at this point matrix is incomplete so we can't use .copy()
5617
5618            var invSX = 1 / sx;
5619            var invSY = 1 / sy;
5620            var invSZ = 1 / sz;
5621
5622            matrix.elements[ 0 ] *= invSX;
5623            matrix.elements[ 1 ] *= invSX;
5624            matrix.elements[ 2 ] *= invSX;
5625
5626            matrix.elements[ 4 ] *= invSY;
5627            matrix.elements[ 5 ] *= invSY;
5628            matrix.elements[ 6 ] *= invSY;
5629
5630            matrix.elements[ 8 ] *= invSZ;
5631            matrix.elements[ 9 ] *= invSZ;
5632            matrix.elements[ 10 ] *= invSZ;
5633
5634            quaternion.setFromRotationMatrix( matrix );
5635
5636            scale.x = sx;
5637            scale.y = sy;
5638            scale.z = sz;
5639
5640            return this;
5641
5642        };
5643
5644    }(),
5645
5646    makeFrustum: function ( left, right, bottom, top, near, far ) {
5647
5648        var te = this.elements;
5649        var x = 2 * near / ( right - left );
5650        var y = 2 * near / ( top - bottom );
5651
5652        var a = ( right + left ) / ( right - left );
5653        var b = ( top + bottom ) / ( top - bottom );
5654        var c = - ( far + near ) / ( far - near );
5655        var d = - 2 * far * near / ( far - near );
5656
5657        te[ 0 ] = x;	te[ 4 ] = 0;	te[ 8 ] = a;	te[ 12 ] = 0;
5658        te[ 1 ] = 0;	te[ 5 ] = y;	te[ 9 ] = b;	te[ 13 ] = 0;
5659        te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = c;	te[ 14 ] = d;
5660        te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = - 1;	te[ 15 ] = 0;
5661
5662        return this;
5663
5664    },
5665
5666    makePerspective: function ( fov, aspect, near, far ) {
5667
5668        var ymax = near * Math.tan( THREE.Math.DEG2RAD * fov * 0.5 );
5669        var ymin = - ymax;
5670        var xmin = ymin * aspect;
5671        var xmax = ymax * aspect;
5672
5673        return this.makeFrustum( xmin, xmax, ymin, ymax, near, far );
5674
5675    },
5676
5677    makeOrthographic: function ( left, right, top, bottom, near, far ) {
5678
5679        var te = this.elements;
5680        var w = 1.0 / ( right - left );
5681        var h = 1.0 / ( top - bottom );
5682        var p = 1.0 / ( far - near );
5683
5684        var x = ( right + left ) * w;
5685        var y = ( top + bottom ) * h;
5686        var z = ( far + near ) * p;
5687
5688        te[ 0 ] = 2 * w;	te[ 4 ] = 0;	te[ 8 ] = 0;	te[ 12 ] = - x;
5689        te[ 1 ] = 0;	te[ 5 ] = 2 * h;	te[ 9 ] = 0;	te[ 13 ] = - y;
5690        te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = - 2 * p;	te[ 14 ] = - z;
5691        te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = 0;	te[ 15 ] = 1;
5692
5693        return this;
5694
5695    },
5696
5697    equals: function ( matrix ) {
5698
5699        var te = this.elements;
5700        var me = matrix.elements;
5701
5702        for ( var i = 0; i < 16; i ++ ) {
5703
5704            if ( te[ i ] !== me[ i ] ) return false;
5705
5706        }
5707
5708        return true;
5709
5710    },
5711
5712    fromArray: function ( array ) {
5713
5714        this.elements.set( array );
5715
5716        return this;
5717
5718    },
5719
5720    toArray: function ( array, offset ) {
5721
5722        if ( array === undefined ) array = [];
5723        if ( offset === undefined ) offset = 0;
5724
5725        var te = this.elements;
5726
5727        array[ offset ] = te[ 0 ];
5728        array[ offset + 1 ] = te[ 1 ];
5729        array[ offset + 2 ] = te[ 2 ];
5730        array[ offset + 3 ] = te[ 3 ];
5731
5732        array[ offset + 4 ] = te[ 4 ];
5733        array[ offset + 5 ] = te[ 5 ];
5734        array[ offset + 6 ] = te[ 6 ];
5735        array[ offset + 7 ] = te[ 7 ];
5736
5737        array[ offset + 8 ]  = te[ 8 ];
5738        array[ offset + 9 ]  = te[ 9 ];
5739        array[ offset + 10 ] = te[ 10 ];
5740        array[ offset + 11 ] = te[ 11 ];
5741
5742        array[ offset + 12 ] = te[ 12 ];
5743        array[ offset + 13 ] = te[ 13 ];
5744        array[ offset + 14 ] = te[ 14 ];
5745        array[ offset + 15 ] = te[ 15 ];
5746
5747        return array;
5748
5749    }
5750
5751};
5752
5753// File:src/math/Ray.js
5754
5755/**
5756 * @author bhouston / http://clara.io
5757 */
5758
5759THREE.Ray = function ( origin, direction ) {
5760
5761    this.origin = ( origin !== undefined ) ? origin : new THREE.Vector3();
5762    this.direction = ( direction !== undefined ) ? direction : new THREE.Vector3();
5763
5764};
5765
5766THREE.Ray.prototype = {
5767
5768    constructor: THREE.Ray,
5769
5770    set: function ( origin, direction ) {
5771
5772        this.origin.copy( origin );
5773        this.direction.copy( direction );
5774
5775        return this;
5776
5777    },
5778
5779    clone: function () {
5780
5781        return new this.constructor().copy( this );
5782
5783    },
5784
5785    copy: function ( ray ) {
5786
5787        this.origin.copy( ray.origin );
5788        this.direction.copy( ray.direction );
5789
5790        return this;
5791
5792    },
5793
5794    at: function ( t, optionalTarget ) {
5795
5796        var result = optionalTarget || new THREE.Vector3();
5797
5798        return result.copy( this.direction ).multiplyScalar( t ).add( this.origin );
5799
5800    },
5801
5802    lookAt: function ( v ) {
5803
5804        this.direction.copy( v ).sub( this.origin ).normalize();
5805
5806    },
5807
5808    recast: function () {
5809
5810        var v1 = new THREE.Vector3();
5811
5812        return function ( t ) {
5813
5814            this.origin.copy( this.at( t, v1 ) );
5815
5816            return this;
5817
5818        };
5819
5820    }(),
5821
5822    closestPointToPoint: function ( point, optionalTarget ) {
5823
5824        var result = optionalTarget || new THREE.Vector3();
5825        result.subVectors( point, this.origin );
5826        var directionDistance = result.dot( this.direction );
5827
5828        if ( directionDistance < 0 ) {
5829
5830            return result.copy( this.origin );
5831
5832        }
5833
5834        return result.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
5835
5836    },
5837
5838    distanceToPoint: function ( point ) {
5839
5840        return Math.sqrt( this.distanceSqToPoint( point ) );
5841
5842    },
5843
5844    distanceSqToPoint: function () {
5845
5846        var v1 = new THREE.Vector3();
5847
5848        return function ( point ) {
5849
5850            var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
5851
5852            // point behind the ray
5853
5854            if ( directionDistance < 0 ) {
5855
5856                return this.origin.distanceToSquared( point );
5857
5858            }
5859
5860            v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
5861
5862            return v1.distanceToSquared( point );
5863
5864        };
5865
5866    }(),
5867
5868    distanceSqToSegment: function () {
5869
5870        var segCenter = new THREE.Vector3();
5871        var segDir = new THREE.Vector3();
5872        var diff = new THREE.Vector3();
5873
5874        return function ( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
5875
5876            // from http://www.geometrictools.com/LibMathematics/Distance/Wm5DistRay3Segment3.cpp
5877            // It returns the min distance between the ray and the segment
5878            // defined by v0 and v1
5879            // It can also set two optional targets :
5880            // - The closest point on the ray
5881            // - The closest point on the segment
5882
5883            segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
5884            segDir.copy( v1 ).sub( v0 ).normalize();
5885            diff.copy( this.origin ).sub( segCenter );
5886
5887            var segExtent = v0.distanceTo( v1 ) * 0.5;
5888            var a01 = - this.direction.dot( segDir );
5889            var b0 = diff.dot( this.direction );
5890            var b1 = - diff.dot( segDir );
5891            var c = diff.lengthSq();
5892            var det = Math.abs( 1 - a01 * a01 );
5893            var s0, s1, sqrDist, extDet;
5894
5895            if ( det > 0 ) {
5896
5897                // The ray and segment are not parallel.
5898
5899                s0 = a01 * b1 - b0;
5900                s1 = a01 * b0 - b1;
5901                extDet = segExtent * det;
5902
5903                if ( s0 >= 0 ) {
5904
5905                    if ( s1 >= - extDet ) {
5906
5907                        if ( s1 <= extDet ) {
5908
5909                            // region 0
5910                            // Minimum at interior points of ray and segment.
5911
5912                            var invDet = 1 / det;
5913                            s0 *= invDet;
5914                            s1 *= invDet;
5915                            sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
5916
5917                        } else {
5918
5919                            // region 1
5920
5921                            s1 = segExtent;
5922                            s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5923                            sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5924
5925                        }
5926
5927                    } else {
5928
5929                        // region 5
5930
5931                        s1 = - segExtent;
5932                        s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5933                        sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5934
5935                    }
5936
5937                } else {
5938
5939                    if ( s1 <= - extDet ) {
5940
5941                        // region 4
5942
5943                        s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
5944                        s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
5945                        sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5946
5947                    } else if ( s1 <= extDet ) {
5948
5949                        // region 3
5950
5951                        s0 = 0;
5952                        s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
5953                        sqrDist = s1 * ( s1 + 2 * b1 ) + c;
5954
5955                    } else {
5956
5957                        // region 2
5958
5959                        s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
5960                        s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
5961                        sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5962
5963                    }
5964
5965                }
5966
5967            } else {
5968
5969                // Ray and segment are parallel.
5970
5971                s1 = ( a01 > 0 ) ? - segExtent : segExtent;
5972                s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5973                sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5974
5975            }
5976
5977            if ( optionalPointOnRay ) {
5978
5979                optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
5980
5981            }
5982
5983            if ( optionalPointOnSegment ) {
5984
5985                optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter );
5986
5987            }
5988
5989            return sqrDist;
5990
5991        };
5992
5993    }(),
5994
5995    intersectSphere: function () {
5996
5997        var v1 = new THREE.Vector3();
5998
5999        return function ( sphere, optionalTarget ) {
6000
6001            v1.subVectors( sphere.center, this.origin );
6002            var tca = v1.dot( this.direction );
6003            var d2 = v1.dot( v1 ) - tca * tca;
6004            var radius2 = sphere.radius * sphere.radius;
6005
6006            if ( d2 > radius2 ) return null;
6007
6008            var thc = Math.sqrt( radius2 - d2 );
6009
6010            // t0 = first intersect point - entrance on front of sphere
6011            var t0 = tca - thc;
6012
6013            // t1 = second intersect point - exit point on back of sphere
6014            var t1 = tca + thc;
6015
6016            // test to see if both t0 and t1 are behind the ray - if so, return null
6017            if ( t0 < 0 && t1 < 0 ) return null;
6018
6019            // test to see if t0 is behind the ray:
6020            // if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
6021            // in order to always return an intersect point that is in front of the ray.
6022            if ( t0 < 0 ) return this.at( t1, optionalTarget );
6023
6024            // else t0 is in front of the ray, so return the first collision point scaled by t0
6025            return this.at( t0, optionalTarget );
6026
6027        };
6028
6029    }(),
6030
6031    intersectsSphere: function ( sphere ) {
6032
6033        return this.distanceToPoint( sphere.center ) <= sphere.radius;
6034
6035    },
6036
6037    distanceToPlane: function ( plane ) {
6038
6039        var denominator = plane.normal.dot( this.direction );
6040
6041        if ( denominator === 0 ) {
6042
6043            // line is coplanar, return origin
6044            if ( plane.distanceToPoint( this.origin ) === 0 ) {
6045
6046                return 0;
6047
6048            }
6049
6050            // Null is preferable to undefined since undefined means.... it is undefined
6051
6052            return null;
6053
6054        }
6055
6056        var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
6057
6058        // Return if the ray never intersects the plane
6059
6060        return t >= 0 ? t :  null;
6061
6062    },
6063
6064    intersectPlane: function ( plane, optionalTarget ) {
6065
6066        var t = this.distanceToPlane( plane );
6067
6068        if ( t === null ) {
6069
6070            return null;
6071
6072        }
6073
6074        return this.at( t, optionalTarget );
6075
6076    },
6077
6078
6079
6080    intersectsPlane: function ( plane ) {
6081
6082        // check if the ray lies on the plane first
6083
6084        var distToPoint = plane.distanceToPoint( this.origin );
6085
6086        if ( distToPoint === 0 ) {
6087
6088            return true;
6089
6090        }
6091
6092        var denominator = plane.normal.dot( this.direction );
6093
6094        if ( denominator * distToPoint < 0 ) {
6095
6096            return true;
6097
6098        }
6099
6100        // ray origin is behind the plane (and is pointing behind it)
6101
6102        return false;
6103
6104    },
6105
6106    intersectBox: function ( box, optionalTarget ) {
6107
6108        var tmin, tmax, tymin, tymax, tzmin, tzmax;
6109
6110        var invdirx = 1 / this.direction.x,
6111            invdiry = 1 / this.direction.y,
6112            invdirz = 1 / this.direction.z;
6113
6114        var origin = this.origin;
6115
6116        if ( invdirx >= 0 ) {
6117
6118            tmin = ( box.min.x - origin.x ) * invdirx;
6119            tmax = ( box.max.x - origin.x ) * invdirx;
6120
6121        } else {
6122
6123            tmin = ( box.max.x - origin.x ) * invdirx;
6124            tmax = ( box.min.x - origin.x ) * invdirx;
6125
6126        }
6127
6128        if ( invdiry >= 0 ) {
6129
6130            tymin = ( box.min.y - origin.y ) * invdiry;
6131            tymax = ( box.max.y - origin.y ) * invdiry;
6132
6133        } else {
6134
6135            tymin = ( box.max.y - origin.y ) * invdiry;
6136            tymax = ( box.min.y - origin.y ) * invdiry;
6137
6138        }
6139
6140        if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
6141
6142        // These lines also handle the case where tmin or tmax is NaN
6143        // (result of 0 * Infinity). x !== x returns true if x is NaN
6144
6145        if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
6146
6147        if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
6148
6149        if ( invdirz >= 0 ) {
6150
6151            tzmin = ( box.min.z - origin.z ) * invdirz;
6152            tzmax = ( box.max.z - origin.z ) * invdirz;
6153
6154        } else {
6155
6156            tzmin = ( box.max.z - origin.z ) * invdirz;
6157            tzmax = ( box.min.z - origin.z ) * invdirz;
6158
6159        }
6160
6161        if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
6162
6163        if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
6164
6165        if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
6166
6167        //return point closest to the ray (positive side)
6168
6169        if ( tmax < 0 ) return null;
6170
6171        return this.at( tmin >= 0 ? tmin : tmax, optionalTarget );
6172
6173    },
6174
6175    intersectsBox: ( function () {
6176
6177        var v = new THREE.Vector3();
6178
6179        return function ( box ) {
6180
6181            return this.intersectBox( box, v ) !== null;
6182
6183        };
6184
6185    } )(),
6186
6187    intersectTriangle: function () {
6188
6189        // Compute the offset origin, edges, and normal.
6190        var diff = new THREE.Vector3();
6191        var edge1 = new THREE.Vector3();
6192        var edge2 = new THREE.Vector3();
6193        var normal = new THREE.Vector3();
6194
6195        return function ( a, b, c, backfaceCulling, optionalTarget ) {
6196
6197            // from http://www.geometrictools.com/LibMathematics/Intersection/Wm5IntrRay3Triangle3.cpp
6198
6199            edge1.subVectors( b, a );
6200            edge2.subVectors( c, a );
6201            normal.crossVectors( edge1, edge2 );
6202
6203            // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
6204            // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
6205            //   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
6206            //   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
6207            //   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
6208            var DdN = this.direction.dot( normal );
6209            var sign;
6210
6211            if ( DdN > 0 ) {
6212
6213                if ( backfaceCulling ) return null;
6214                sign = 1;
6215
6216            } else if ( DdN < 0 ) {
6217
6218                sign = - 1;
6219                DdN = - DdN;
6220
6221            } else {
6222
6223                return null;
6224
6225            }
6226
6227            diff.subVectors( this.origin, a );
6228            var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) );
6229
6230            // b1 < 0, no intersection
6231            if ( DdQxE2 < 0 ) {
6232
6233                return null;
6234
6235            }
6236
6237            var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) );
6238
6239            // b2 < 0, no intersection
6240            if ( DdE1xQ < 0 ) {
6241
6242                return null;
6243
6244            }
6245
6246            // b1+b2 > 1, no intersection
6247            if ( DdQxE2 + DdE1xQ > DdN ) {
6248
6249                return null;
6250
6251            }
6252
6253            // Line intersects triangle, check if ray does.
6254            var QdN = - sign * diff.dot( normal );
6255
6256            // t < 0, no intersection
6257            if ( QdN < 0 ) {
6258
6259                return null;
6260
6261            }
6262
6263            // Ray intersects triangle.
6264            return this.at( QdN / DdN, optionalTarget );
6265
6266        };
6267
6268    }(),
6269
6270    applyMatrix4: function ( matrix4 ) {
6271
6272        this.direction.add( this.origin ).applyMatrix4( matrix4 );
6273        this.origin.applyMatrix4( matrix4 );
6274        this.direction.sub( this.origin );
6275        this.direction.normalize();
6276
6277        return this;
6278
6279    },
6280
6281    equals: function ( ray ) {
6282
6283        return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
6284
6285    }
6286
6287};
6288
6289// File:src/math/Sphere.js
6290
6291/**
6292 * @author bhouston / http://clara.io
6293 * @author mrdoob / http://mrdoob.com/
6294 */
6295
6296THREE.Sphere = function ( center, radius ) {
6297
6298    this.center = ( center !== undefined ) ? center : new THREE.Vector3();
6299    this.radius = ( radius !== undefined ) ? radius : 0;
6300
6301};
6302
6303THREE.Sphere.prototype = {
6304
6305    constructor: THREE.Sphere,
6306
6307    set: function ( center, radius ) {
6308
6309        this.center.copy( center );
6310        this.radius = radius;
6311
6312        return this;
6313
6314    },
6315
6316    setFromPoints: function () {
6317
6318        var box = new THREE.Box3();
6319
6320        return function ( points, optionalCenter ) {
6321
6322            var center = this.center;
6323
6324            if ( optionalCenter !== undefined ) {
6325
6326                center.copy( optionalCenter );
6327
6328            } else {
6329
6330                box.setFromPoints( points ).center( center );
6331
6332            }
6333
6334            var maxRadiusSq = 0;
6335
6336            for ( var i = 0, il = points.length; i < il; i ++ ) {
6337
6338                maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
6339
6340            }
6341
6342            this.radius = Math.sqrt( maxRadiusSq );
6343
6344            return this;
6345
6346        };
6347
6348    }(),
6349
6350    clone: function () {
6351
6352        return new this.constructor().copy( this );
6353
6354    },
6355
6356    copy: function ( sphere ) {
6357
6358        this.center.copy( sphere.center );
6359        this.radius = sphere.radius;
6360
6361        return this;
6362
6363    },
6364
6365    empty: function () {
6366
6367        return ( this.radius <= 0 );
6368
6369    },
6370
6371    containsPoint: function ( point ) {
6372
6373        return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
6374
6375    },
6376
6377    distanceToPoint: function ( point ) {
6378
6379        return ( point.distanceTo( this.center ) - this.radius );
6380
6381    },
6382
6383    intersectsSphere: function ( sphere ) {
6384
6385        var radiusSum = this.radius + sphere.radius;
6386
6387        return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
6388
6389    },
6390
6391    intersectsBox: function ( box ) {
6392
6393        return box.intersectsSphere( this );
6394
6395    },
6396
6397    intersectsPlane: function ( plane ) {
6398
6399        // We use the following equation to compute the signed distance from
6400        // the center of the sphere to the plane.
6401        //
6402        // distance = q * n - d
6403        //
6404        // If this distance is greater than the radius of the sphere,
6405        // then there is no intersection.
6406
6407        return Math.abs( this.center.dot( plane.normal ) - plane.constant ) <= this.radius;
6408
6409    },
6410
6411    clampPoint: function ( point, optionalTarget ) {
6412
6413        var deltaLengthSq = this.center.distanceToSquared( point );
6414
6415        var result = optionalTarget || new THREE.Vector3();
6416
6417        result.copy( point );
6418
6419        if ( deltaLengthSq > ( this.radius * this.radius ) ) {
6420
6421            result.sub( this.center ).normalize();
6422            result.multiplyScalar( this.radius ).add( this.center );
6423
6424        }
6425
6426        return result;
6427
6428    },
6429
6430    getBoundingBox: function ( optionalTarget ) {
6431
6432        var box = optionalTarget || new THREE.Box3();
6433
6434        box.set( this.center, this.center );
6435        box.expandByScalar( this.radius );
6436
6437        return box;
6438
6439    },
6440
6441    applyMatrix4: function ( matrix ) {
6442
6443        this.center.applyMatrix4( matrix );
6444        this.radius = this.radius * matrix.getMaxScaleOnAxis();
6445
6446        return this;
6447
6448    },
6449
6450    translate: function ( offset ) {
6451
6452        this.center.add( offset );
6453
6454        return this;
6455
6456    },
6457
6458    equals: function ( sphere ) {
6459
6460        return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
6461
6462    }
6463
6464};
6465
6466// File:src/math/Frustum.js
6467
6468/**
6469 * @author mrdoob / http://mrdoob.com/
6470 * @author alteredq / http://alteredqualia.com/
6471 * @author bhouston / http://clara.io
6472 */
6473
6474THREE.Frustum = function ( p0, p1, p2, p3, p4, p5 ) {
6475
6476    this.planes = [
6477
6478        ( p0 !== undefined ) ? p0 : new THREE.Plane(),
6479        ( p1 !== undefined ) ? p1 : new THREE.Plane(),
6480        ( p2 !== undefined ) ? p2 : new THREE.Plane(),
6481        ( p3 !== undefined ) ? p3 : new THREE.Plane(),
6482        ( p4 !== undefined ) ? p4 : new THREE.Plane(),
6483        ( p5 !== undefined ) ? p5 : new THREE.Plane()
6484
6485    ];
6486
6487};
6488
6489THREE.Frustum.prototype = {
6490
6491    constructor: THREE.Frustum,
6492
6493    set: function ( p0, p1, p2, p3, p4, p5 ) {
6494
6495        var planes = this.planes;
6496
6497        planes[ 0 ].copy( p0 );
6498        planes[ 1 ].copy( p1 );
6499        planes[ 2 ].copy( p2 );
6500        planes[ 3 ].copy( p3 );
6501        planes[ 4 ].copy( p4 );
6502        planes[ 5 ].copy( p5 );
6503
6504        return this;
6505
6506    },
6507
6508    clone: function () {
6509
6510        return new this.constructor().copy( this );
6511
6512    },
6513
6514    copy: function ( frustum ) {
6515
6516        var planes = this.planes;
6517
6518        for ( var i = 0; i < 6; i ++ ) {
6519
6520            planes[ i ].copy( frustum.planes[ i ] );
6521
6522        }
6523
6524        return this;
6525
6526    },
6527
6528    setFromMatrix: function ( m ) {
6529
6530        var planes = this.planes;
6531        var me = m.elements;
6532        var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
6533        var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
6534        var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
6535        var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
6536
6537        planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
6538        planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
6539        planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
6540        planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
6541        planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
6542        planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
6543
6544        return this;
6545
6546    },
6547
6548    intersectsObject: function () {
6549
6550        var sphere = new THREE.Sphere();
6551
6552        return function ( object ) {
6553
6554            var geometry = object.geometry;
6555
6556            if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
6557
6558            sphere.copy( geometry.boundingSphere );
6559            sphere.applyMatrix4( object.matrixWorld );
6560
6561            return this.intersectsSphere( sphere );
6562
6563        };
6564
6565    }(),
6566
6567    intersectsSphere: function ( sphere ) {
6568
6569        var planes = this.planes;
6570        var center = sphere.center;
6571        var negRadius = - sphere.radius;
6572
6573        for ( var i = 0; i < 6; i ++ ) {
6574
6575            var distance = planes[ i ].distanceToPoint( center );
6576
6577            if ( distance < negRadius ) {
6578
6579                return false;
6580
6581            }
6582
6583        }
6584
6585        return true;
6586
6587    },
6588
6589    intersectsBox: function () {
6590
6591        var p1 = new THREE.Vector3(),
6592            p2 = new THREE.Vector3();
6593
6594        return function ( box ) {
6595
6596            var planes = this.planes;
6597
6598            for ( var i = 0; i < 6 ; i ++ ) {
6599
6600                var plane = planes[ i ];
6601
6602                p1.x = plane.normal.x > 0 ? box.min.x : box.max.x;
6603                p2.x = plane.normal.x > 0 ? box.max.x : box.min.x;
6604                p1.y = plane.normal.y > 0 ? box.min.y : box.max.y;
6605                p2.y = plane.normal.y > 0 ? box.max.y : box.min.y;
6606                p1.z = plane.normal.z > 0 ? box.min.z : box.max.z;
6607                p2.z = plane.normal.z > 0 ? box.max.z : box.min.z;
6608
6609                var d1 = plane.distanceToPoint( p1 );
6610                var d2 = plane.distanceToPoint( p2 );
6611
6612                // if both outside plane, no intersection
6613
6614                if ( d1 < 0 && d2 < 0 ) {
6615
6616                    return false;
6617
6618                }
6619
6620            }
6621
6622            return true;
6623
6624        };
6625
6626    }(),
6627
6628
6629    containsPoint: function ( point ) {
6630
6631        var planes = this.planes;
6632
6633        for ( var i = 0; i < 6; i ++ ) {
6634
6635            if ( planes[ i ].distanceToPoint( point ) < 0 ) {
6636
6637                return false;
6638
6639            }
6640
6641        }
6642
6643        return true;
6644
6645    }
6646
6647};
6648
6649// File:src/math/Plane.js
6650
6651/**
6652 * @author bhouston / http://clara.io
6653 */
6654
6655THREE.Plane = function ( normal, constant ) {
6656
6657    this.normal = ( normal !== undefined ) ? normal : new THREE.Vector3( 1, 0, 0 );
6658    this.constant = ( constant !== undefined ) ? constant : 0;
6659
6660};
6661
6662THREE.Plane.prototype = {
6663
6664    constructor: THREE.Plane,
6665
6666    set: function ( normal, constant ) {
6667
6668        this.normal.copy( normal );
6669        this.constant = constant;
6670
6671        return this;
6672
6673    },
6674
6675    setComponents: function ( x, y, z, w ) {
6676
6677        this.normal.set( x, y, z );
6678        this.constant = w;
6679
6680        return this;
6681
6682    },
6683
6684    setFromNormalAndCoplanarPoint: function ( normal, point ) {
6685
6686        this.normal.copy( normal );
6687        this.constant = - point.dot( this.normal );	// must be this.normal, not normal, as this.normal is normalized
6688
6689        return this;
6690
6691    },
6692
6693    setFromCoplanarPoints: function () {
6694
6695        var v1 = new THREE.Vector3();
6696        var v2 = new THREE.Vector3();
6697
6698        return function ( a, b, c ) {
6699
6700            var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize();
6701
6702            // Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
6703
6704            this.setFromNormalAndCoplanarPoint( normal, a );
6705
6706            return this;
6707
6708        };
6709
6710    }(),
6711
6712    clone: function () {
6713
6714        return new this.constructor().copy( this );
6715
6716    },
6717
6718    copy: function ( plane ) {
6719
6720        this.normal.copy( plane.normal );
6721        this.constant = plane.constant;
6722
6723        return this;
6724
6725    },
6726
6727    normalize: function () {
6728
6729        // Note: will lead to a divide by zero if the plane is invali
6729d.
6730
6731        var inverseNormalLength = 1.0 / this.normal.length();
6732        this.normal.multiplyScalar( inverseNormalLength );
6733        this.constant *= inverseNormalLength;
6734
6735        return this;
6736
6737    },
6738
6739    negate: function () {
6740
6741        this.constant *= - 1;
6742        this.normal.negate();
6743
6744        return this;
6745
6746    },
6747
6748    distanceToPoint: function ( point ) {
6749
6750        return this.normal.dot( point ) + this.constant;
6751
6752    },
6753
6754    distanceToSphere: function ( sphere ) {
6755
6756        return this.distanceToPoint( sphere.center ) - sphere.radius;
6757
6758    },
6759
6760    projectPoint: function ( point, optionalTarget ) {
6761
6762        return this.orthoPoint( point, optionalTarget ).sub( point ).negate();
6763
6764    },
6765
6766    orthoPoint: function ( point, optionalTarget ) {
6767
6768        var perpendicularMagnitude = this.distanceToPoint( point );
6769
6770        var result = optionalTarget || new THREE.Vector3();
6771        return result.copy( this.normal ).multiplyScalar( perpendicularMagnitude );
6772
6773    },
6774
6775    intersectLine: function () {
6776
6777        var v1 = new THREE.Vector3();
6778
6779        return function ( line, optionalTarget ) {
6780
6781            var result = optionalTarget || new THREE.Vector3();
6782
6783            var direction = line.delta( v1 );
6784
6785            var denominator = this.normal.dot( direction );
6786
6787            if ( denominator === 0 ) {
6788
6789                // line is coplanar, return origin
6790                if ( this.distanceToPoint( line.start ) === 0 ) {
6791
6792                    return result.copy( line.start );
6793
6794                }
6795
6796                // Unsure if this is the correct method to handle this case.
6797                return undefined;
6798
6799            }
6800
6801            var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
6802
6803            if ( t < 0 || t > 1 ) {
6804
6805                return undefined;
6806
6807            }
6808
6809            return result.copy( direction ).multiplyScalar( t ).add( line.start );
6810
6811        };
6812
6813    }(),
6814
6815    intersectsLine: function ( line ) {
6816
6817        // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
6818
6819        var startSign = this.distanceToPoint( line.start );
6820        var endSign = this.distanceToPoint( line.end );
6821
6822        return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
6823
6824    },
6825
6826    intersectsBox: function ( box ) {
6827
6828        return box.intersectsPlane( this );
6829
6830    },
6831
6832    intersectsSphere: function ( sphere ) {
6833
6834        return sphere.intersectsPlane( this );
6835
6836    },
6837
6838    coplanarPoint: function ( optionalTarget ) {
6839
6840        var result = optionalTarget || new THREE.Vector3();
6841        return result.copy( this.normal ).multiplyScalar( - this.constant );
6842
6843    },
6844
6845    applyMatrix4: function () {
6846
6847        var v1 = new THREE.Vector3();
6848        var m1 = new THREE.Matrix3();
6849
6850        return function ( matrix, optionalNormalMatrix ) {
6851
6852            var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix );
6853
6854            // transform normal based on theory here:
6855            // http://www.songho.ca/opengl/gl_normaltransform.html
6856            var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix );
6857            var normal = this.normal.applyMatrix3( normalMatrix ).normalize();
6858
6859            // recalculate constant (like in setFromNormalAndCoplanarPoint)
6860            this.constant = - referencePoint.dot( normal );
6861
6862            return this;
6863
6864        };
6865
6866    }(),
6867
6868    translate: function ( offset ) {
6869
6870        this.constant = this.constant - offset.dot( this.normal );
6871
6872        return this;
6873
6874    },
6875
6876    equals: function ( plane ) {
6877
6878        return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
6879
6880    }
6881
6882};
6883
6884// File:src/math/Spherical.js
6885
6886/**
6887 * @author bhouston / http://clara.io
6888 * @author WestLangley / http://github.com/WestLangley
6889 *
6890 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
6891 *
6892 * The poles (phi) are at the positive and negative y axis.
6893 * The equator starts at positive z.
6894 */
6895
6896THREE.Spherical = function ( radius, phi, theta ) {
6897
6898    this.radius = ( radius !== undefined ) ? radius : 1.0;
6899    this.phi = ( phi !== undefined ) ? phi : 0; // up / down towards top and bottom pole
6900    this.theta = ( theta !== undefined ) ? theta : 0; // around the equator of the sphere
6901
6902    return this;
6903
6904};
6905
6906THREE.Spherical.prototype = {
6907
6908    constructor: THREE.Spherical,
6909
6910    set: function ( radius, phi, theta ) {
6911
6912        this.radius = radius;
6913        this.phi = phi;
6914        this.theta = theta;
6915
6916    },
6917
6918    clone: function () {
6919
6920        return new this.constructor().copy( this );
6921
6922    },
6923
6924    copy: function ( other ) {
6925
6926        this.radius.copy( other.radius );
6927        this.phi.copy( other.phi );
6928        this.theta.copy( other.theta );
6929
6930        return this;
6931
6932    },
6933
6934    // restrict phi to be betwee EPS and PI-EPS
6935    makeSafe: function() {
6936
6937        var EPS = 0.000001;
6938        this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
6939
6940    },
6941
6942    setFromVector3: function( vec3 ) {
6943
6944        this.radius = vec3.length();
6945
6946        if ( this.radius === 0 ) {
6947
6948            this.theta = 0;
6949            this.phi = 0;
6950
6951        } else {
6952
6953            this.theta = Math.atan2( vec3.x, vec3.z ); // equator angle around y-up axis
6954            this.phi = Math.acos( THREE.Math.clamp( vec3.y / this.radius, - 1, 1 ) ); // polar angle
6955
6956        }
6957
6958        return this;
6959
6960    },
6961
6962};
6963
6964// File:src/math/Math.js
6965
6966/**
6967 * @author alteredq / http://alteredqualia.com/
6968 * @author mrdoob / http://mrdoob.com/
6969 */
6970
6971THREE.Math = {
6972
6973    DEG2RAD: Math.PI / 180,
6974    RAD2DEG: 180 / Math.PI,
6975
6976    generateUUID: function () {
6977
6978        // http://www.broofa.com/Tools/Math.uuid.htm
6979
6980        var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split( '' );
6981        var uuid = new Array( 36 );
6982        var rnd = 0, r;
6983
6984        return function () {
6985
6986            for ( var i = 0; i < 36; i ++ ) {
6987
6988                if ( i === 8 || i === 13 || i === 18 || i === 23 ) {
6989
6990                    uuid[ i ] = '-';
6991
6992                } else if ( i === 14 ) {
6993
6994                    uuid[ i ] = '4';
6995
6996                } else {
6997
6998                    if ( rnd <= 0x02 ) rnd = 0x2000000 + ( Math.random() * 0x1000000 ) | 0;
6999                    r = rnd & 0xf;
7000                    rnd = rnd >> 4;
7001                    uuid[ i ] = chars[ ( i === 19 ) ? ( r & 0x3 ) | 0x8 : r ];
7002
7003                }
7004
7005            }
7006
7007            return uuid.join( '' );
7008
7009        };
7010
7011    }(),
7012
7013    clamp: function ( value, min, max ) {
7014
7015        return Math.max( min, Math.min( max, value ) );
7016
7017    },
7018
7019    // compute euclidian modulo of m % n
7020    // https://en.wikipedia.org/wiki/Modulo_operation
7021
7022    euclideanModulo: function ( n, m ) {
7023
7024        return ( ( n % m ) + m ) % m;
7025
7026    },
7027
7028    // Linear mapping from range <a1, a2> to range <b1, b2>
7029
7030    mapLinear: function ( x, a1, a2, b1, b2 ) {
7031
7032        return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
7033
7034    },
7035
7036    // http://en.wikipedia.org/wiki/Smoothstep
7037
7038    smoothstep: function ( x, min, max ) {
7039
7040        if ( x <= min ) return 0;
7041        if ( x >= max ) return 1;
7042
7043        x = ( x - min ) / ( max - min );
7044
7045        return x * x * ( 3 - 2 * x );
7046
7047    },
7048
7049    smootherstep: function ( x, min, max ) {
7050
7051        if ( x <= min ) return 0;
7052        if ( x >= max ) return 1;
7053
7054        x = ( x - min ) / ( max - min );
7055
7056        return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
7057
7058    },
7059
7060    random16: function () {
7061
7062        console.warn( 'THREE.Math.random16() has been deprecated. Use Math.random() instead.' );
7063        return Math.random();
7064
7065    },
7066
7067    // Random integer from <low, high> interval
7068
7069    randInt: function ( low, high ) {
7070
7071        return low + Math.floor( Math.random() * ( high - low + 1 ) );
7072
7073    },
7074
7075    // Random float from <low, high> interval
7076
7077    randFloat: function ( low, high ) {
7078
7079        return low + Math.random() * ( high - low );
7080
7081    },
7082
7083    // Random float from <-range/2, range/2> interval
7084
7085    randFloatSpread: function ( range ) {
7086
7087        return range * ( 0.5 - Math.random() );
7088
7089    },
7090
7091    degToRad: function ( degrees ) {
7092
7093        return degrees * THREE.Math.DEG2RAD;
7094
7095    },
7096
7097    radToDeg: function ( radians ) {
7098
7099        return radians * THREE.Math.RAD2DEG;
7100
7101    },
7102
7103    isPowerOfTwo: function ( value ) {
7104
7105        return ( value & ( value - 1 ) ) === 0 && value !== 0;
7106
7107    },
7108
7109    nearestPowerOfTwo: function ( value ) {
7110
7111        return Math.pow( 2, Math.round( Math.log( value ) / Math.LN2 ) );
7112
7113    },
7114
7115    nextPowerOfTwo: function ( value ) {
7116
7117        value --;
7118        value |= value >> 1;
7119        value |= value >> 2;
7120        value |= value >> 4;
7121        value |= value >> 8;
7122        value |= value >> 16;
7123        value ++;
7124
7125        return value;
7126
7127    }
7128
7129};
7130
7131// File:src/math/Spline.js
7132
7133/**
7134 * Spline from Tween.js, slightly optimized (and trashed)
7135 * http://sole.github.com/tween.js/examples/05_spline.html
7136 *
7137 * @author mrdoob / http://mrdoob.com/
7138 * @author alteredq / http://alteredqualia.com/
7139 */
7140
7141THREE.Spline = function ( points ) {
7142
7143    this.points = points;
7144
7145    var c = [], v3 = { x: 0, y: 0, z: 0 },
7146        point, intPoint, weight, w2, w3,
7147        pa, pb, pc, pd;
7148
7149    this.initFromArray = function ( a ) {
7150
7151        this.points = [];
7152
7153        for ( var i = 0; i < a.length; i ++ ) {
7154
7155            this.points[ i ] = { x: a[ i ][ 0 ], y: a[ i ][ 1 ], z: a[ i ][ 2 ] };
7156
7157        }
7158
7159    };
7160
7161    this.getPoint = function ( k ) {
7162
7163        point = ( this.points.length - 1 ) * k;
7164        intPoint = Math.floor( point );
7165        weight = point - intPoint;
7166
7167        c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1;
7168        c[ 1 ] = intPoint;
7169        c[ 2 ] = intPoint  > this.points.length - 2 ? this.points.length - 1 : intPoint + 1;
7170        c[ 3 ] = intPoint  > this.points.length - 3 ? this.points.length - 1 : intPoint + 2;
7171
7172        pa = this.points[ c[ 0 ] ];
7173        pb = this.points[ c[ 1 ] ];
7174        pc = this.points[ c[ 2 ] ];
7175        pd = this.points[ c[ 3 ] ];
7176
7177        w2 = weight * weight;
7178        w3 = weight * w2;
7179
7180        v3.x = interpolate( pa.x, pb.x, pc.x, pd.x, weight, w2, w3 );
7181        v3.y = interpolate( pa.y, pb.y, pc.y, pd.y, weight, w2, w3 );
7182        v3.z = interpolate( pa.z, pb.z, pc.z, pd.z, weight, w2, w3 );
7183
7184        return v3;
7185
7186    };
7187
7188    this.getControlPointsArray = function () {
7189
7190        var i, p, l = this.points.length,
7191            coords = [];
7192
7193        for ( i = 0; i < l; i ++ ) {
7194
7195            p = this.points[ i ];
7196            coords[ i ] = [ p.x, p.y, p.z ];
7197
7198        }
7199
7200        return coords;
7201
7202    };
7203
7204    // approximate length by summing linear segments
7205
7206    this.getLength = function ( nSubDivisions ) {
7207
7208        var i, index, nSamples, position,
7209            point = 0, intPoint = 0, oldIntPoint = 0,
7210            oldPosition = new THREE.Vector3(),
7211            tmpVec = new THREE.Vector3(),
7212            chunkLengths = [],
7213            totalLength = 0;
7214
7215        // first point has 0 length
7216
7217        chunkLengths[ 0 ] = 0;
7218
7219        if ( ! nSubDivisions ) nSubDivisions = 100;
7220
7221        nSamples = this.points.length * nSubDivisions;
7222
7223        oldPosition.copy( this.points[ 0 ] );
7224
7225        for ( i = 1; i < nSamples; i ++ ) {
7226
7227            index = i / nSamples;
7228
7229            position = this.getPoint( index );
7230            tmpVec.copy( position );
7231
7232            totalLength += tmpVec.distanceTo( oldPosition );
7233
7234            oldPosition.copy( position );
7235
7236            point = ( this.points.length - 1 ) * index;
7237            intPoint = Math.floor( point );
7238
7239            if ( intPoint !== oldIntPoint ) {
7240
7241                chunkLengths[ intPoint ] = totalLength;
7242                oldIntPoint = intPoint;
7243
7244            }
7245
7246        }
7247
7248        // last point ends with total length
7249
7250        chunkLengths[ chunkLengths.length ] = totalLength;
7251
7252        return { chunks: chunkLengths, total: totalLength };
7253
7254    };
7255
7256    this.reparametrizeByArcLength = function ( samplingCoef ) {
7257
7258        var i, j,
7259            index, indexCurrent, indexNext,
7260            realDistance,
7261            sampling, position,
7262            newpoints = [],
7263            tmpVec = new THREE.Vector3(),
7264            sl = this.getLength();
7265
7266        newpoints.push( tmpVec.copy( this.points[ 0 ] ).clone() );
7267
7268        for ( i = 1; i < this.points.length; i ++ ) {
7269
7270            //tmpVec.copy( this.points[ i - 1 ] );
7271            //linearDistance = tmpVec.distanceTo( this.points[ i ] );
7272
7273            realDistance = sl.chunks[ i ] - sl.chunks[ i - 1 ];
7274
7275            sampling = Math.ceil( samplingCoef * realDistance / sl.total );
7276
7277            indexCurrent = ( i - 1 ) / ( this.points.length - 1 );
7278            indexNext = i / ( this.points.length - 1 );
7279
7280            for ( j = 1; j < sampling - 1; j ++ ) {
7281
7282                index = indexCurrent + j * ( 1 / sampling ) * ( indexNext - indexCurrent );
7283
7284                position = this.getPoint( index );
7285                newpoints.push( tmpVec.copy( position ).clone() );
7286
7287            }
7288
7289            newpoints.push( tmpVec.copy( this.points[ i ] ).clone() );
7290
7291        }
7292
7293        this.points = newpoints;
7294
7295    };
7296
7297    // Catmull-Rom
7298
7299    function interpolate( p0, p1, p2, p3, t, t2, t3 ) {
7300
7301        var v0 = ( p2 - p0 ) * 0.5,
7302            v1 = ( p3 - p1 ) * 0.5;
7303
7304        return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1;
7305
7306    }
7307
7308};
7309
7310// File:src/math/Triangle.js
7311
7312/**
7313 * @author bhouston / http://clara.io
7314 * @author mrdoob / http://mrdoob.com/
7315 */
7316
7317THREE.Triangle = function ( a, b, c ) {
7318
7319    this.a = ( a !== undefined ) ? a : new THREE.Vector3();
7320    this.b = ( b !== undefined ) ? b : new THREE.Vector3();
7321    this.c = ( c !== undefined ) ? c : new THREE.Vector3();
7322
7323};
7324
7325THREE.Triangle.normal = function () {
7326
7327    var v0 = new THREE.Vector3();
7328
7329    return function ( a, b, c, optionalTarget ) {
7330
7331        var result = optionalTarget || new THREE.Vector3();
7332
7333        result.subVectors( c, b );
7334        v0.subVectors( a, b );
7335        result.cross( v0 );
7336
7337        var resultLengthSq = result.lengthSq();
7338        if ( resultLengthSq > 0 ) {
7339
7340            return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) );
7341
7342        }
7343
7344        return result.set( 0, 0, 0 );
7345
7346    };
7347
7348}();
7349
7350// static/instance method to calculate barycentric coordinates
7351// based on: http://www.blackpawn.com/texts/pointinpoly/default.html
7352THREE.Triangle.barycoordFromPoint = function () {
7353
7354    var v0 = new THREE.Vector3();
7355    var v1 = new THREE.Vector3();
7356    var v2 = new THREE.Vector3();
7357
7358    return function ( point, a, b, c, optionalTarget ) {
7359
7360        v0.subVectors( c, a );
7361        v1.subVectors( b, a );
7362        v2.subVectors( point, a );
7363
7364        var dot00 = v0.dot( v0 );
7365        var dot01 = v0.dot( v1 );
7366        var dot02 = v0.dot( v2 );
7367        var dot11 = v1.dot( v1 );
7368        var dot12 = v1.dot( v2 );
7369
7370        var denom = ( dot00 * dot11 - dot01 * dot01 );
7371
7372        var result = optionalTarget || new THREE.Vector3();
7373
7374        // collinear or singular triangle
7375        if ( denom === 0 ) {
7376
7377            // arbitrary location outside of triangle?
7378            // not sure if this is the best idea, maybe should be returning undefined
7379            return result.set( - 2, - 1, - 1 );
7380
7381        }
7382
7383        var invDenom = 1 / denom;
7384        var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
7385        var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
7386
7387        // barycentric coordinates must always sum to 1
7388        return result.set( 1 - u - v, v, u );
7389
7390    };
7391
7392}();
7393
7394THREE.Triangle.containsPoint = function () {
7395
7396    var v1 = new THREE.Vector3();
7397
7398    return function ( point, a, b, c ) {
7399
7400        var result = THREE.Triangle.barycoordFromPoint( point, a, b, c, v1 );
7401
7402        return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 );
7403
7404    };
7405
7406}();
7407
7408THREE.Triangle.prototype = {
7409
7410    constructor: THREE.Triangle,
7411
7412    set: function ( a, b, c ) {
7413
7414        this.a.copy( a );
7415        this.b.copy( b );
7416        this.c.copy( c );
7417
7418        return this;
7419
7420    },
7421
7422    setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
7423
7424        this.a.copy( points[ i0 ] );
7425        this.b.copy( points[ i1 ] );
7426        this.c.copy( points[ i2 ] );
7427
7428        return this;
7429
7430    },
7431
7432    clone: function () {
7433
7434        return new this.constructor().copy( this );
7435
7436    },
7437
7438    copy: function ( triangle ) {
7439
7440        this.a.copy( triangle.a );
7441        this.b.copy( triangle.b );
7442        this.c.copy( triangle.c );
7443
7444        return this;
7445
7446    },
7447
7448    area: function () {
7449
7450        var v0 = new THREE.Vector3();
7451        var v1 = new THREE.Vector3();
7452
7453        return function () {
7454
7455            v0.subVectors( this.c, this.b );
7456            v1.subVectors( this.a, this.b );
7457
7458            return v0.cross( v1 ).length() * 0.5;
7459
7460        };
7461
7462    }(),
7463
7464    midpoint: function ( optionalTarget ) {
7465
7466        var result = optionalTarget || new THREE.Vector3();
7467        return result.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
7468
7469    },
7470
7471    normal: function ( optionalTarget ) {
7472
7473        return THREE.Triangle.normal( this.a, this.b, this.c, optionalTarget );
7474
7475    },
7476
7477    plane: function ( optionalTarget ) {
7478
7479        var result = optionalTarget || new THREE.Plane();
7480
7481        return result.setFromCoplanarPoints( this.a, this.b, this.c );
7482
7483    },
7484
7485    barycoordFromPoint: function ( point, optionalTarget ) {
7486
7487        return THREE.Triangle.barycoordFromPoint( point, this.a, this.b, this.c, optionalTarget );
7488
7489    },
7490
7491    containsPoint: function ( point ) {
7492
7493        return THREE.Triangle.containsPoint( point, this.a, this.b, this.c );
7494
7495    },
7496
7497    closestPointToPoint: function () {
7498
7499        var plane, edgeList, projectedPoint, closestPoint;
7500
7501        return function closestPointToPoint( point, optionalTarget ) {
7502
7503            if ( plane === undefined ) {
7504
7505                plane = new THREE.Plane();
7506                edgeList = [ new THREE.Line3(), new THREE.Line3(), new THREE.Line3() ];
7507                projectedPoint = new THREE.Vector3();
7508                closestPoint = new THREE.Vector3();
7509
7510            }
7511
7512            var result = optionalTarget || new THREE.Vector3();
7513            var minDistance = Infinity;
7514
7515            // project the point onto the plane of the triangle
7516
7517            plane.setFromCoplanarPoints( this.a, this.b, this.c );
7518            plane.projectPoint( point, projectedPoint );
7519
7520            // check if the projection lies within the triangle
7521
7522            if( this.containsPoint( projectedPoint ) === true ) {
7523
7524                // if so, this is the closest point
7525
7526                result.copy( projectedPoint );
7527
7528            } else {
7529
7530                // if not, the point falls outside the triangle. the result is the closest point to the triangle's edges or vertices
7531
7532                edgeList[ 0 ].set( this.a, this.b );
7533                edgeList[ 1 ].set( this.b, this.c );
7534                edgeList[ 2 ].set( this.c, this.a );
7535
7536                for( var i = 0; i < edgeList.length; i ++ ) {
7537
7538                    edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint );
7539
7540                    var distance = projectedPoint.distanceToSquared( closestPoint );
7541
7542                    if( distance < minDistance ) {
7543
7544                        minDistance = distance;
7545
7546                        result.copy( closestPoint );
7547
7548                    }
7549
7550                }
7551
7552            }
7553
7554            return result;
7555
7556        };
7557
7558    }(),
7559
7560    equals: function ( triangle ) {
7561
7562        return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
7563
7564    }
7565
7566};
7567
7568// File:src/math/Interpolant.js
7569
7570/**
7571 * Abstract base class of interpolants over parametric samples.
7572 *
7573 * The parameter domain is one dimensional, typically the time or a path
7574 * along a curve defined by the data.
7575 *
7576 * The sample values can have any dimensionality and derived classes may
7577 * apply special interpretations to the data.
7578 *
7579 * This class provides the interval seek in a Template Method, deferring
7580 * the actual interpolation to derived classes.
7581 *
7582 * Time complexity is O(1) for linear access crossing at most two points
7583 * and O(log N) for random access, where N is the number of positions.
7584 *
7585 * References:
7586 *
7587 * 		http://www.oodesign.com/template-method-pattern.html
7588 *
7589 * @author tschw
7590 */
7591
7592THREE.Interpolant = function(
7593    parameterPositions, sampleValues, sampleSize, resultBuffer ) {
7594
7595    this.parameterPositions = parameterPositions;
7596    this._cachedIndex = 0;
7597
7598    this.resultBuffer = resultBuffer !== undefined ?
7599        resultBuffer : new sampleValues.constructor( sampleSize );
7600    this.sampleValues = sampleValues;
7601    this.valueSize = sampleSize;
7602
7603};
7604
7605THREE.Interpolant.prototype = {
7606
7607    constructor: THREE.Interpolant,
7608
7609    evaluate: function( t ) {
7610
7611        var pp = this.parameterPositions,
7612            i1 = this._cachedIndex,
7613
7614            t1 = pp[   i1   ],
7615            t0 = pp[ i1 - 1 ];
7616
7617        validate_interval: {
7618
7619            seek: {
7620
7621                var right;
7622
7623                linear_scan: {
7624//- See http://jsperf.com/comparison-to-undefined/3
7625//- slower code:
7626//-
7627//- 				if ( t >= t1 || t1 === undefined ) {
7628                    forward_scan: if ( ! ( t < t1 ) ) {
7629
7630                        for ( var giveUpAt = i1 + 2; ;) {
7631
7632                            if ( t1 === undefined ) {
7633
7634                                if ( t < t0 ) break forward_scan;
7635
7636                                // after end
7637
7638                                i1 = pp.length;
7639                                this._cachedIndex = i1;
7640                                return this.afterEnd_( i1 - 1, t, t0 );
7641
7642                            }
7643
7644                            if ( i1 === giveUpAt ) break; // this loop
7645
7646                            t0 = t1;
7647                            t1 = pp[ ++ i1 ];
7648
7649                            if ( t < t1 ) {
7650
7651                                // we have arrived at the sought interval
7652                                break seek;
7653
7654                            }
7655
7656                        }
7657
7658                        // prepare binary search on the right side of the index
7659                        right = pp.length;
7660                        break linear_scan;
7661
7662                    }
7663
7664//- slower code:
7665//-					if ( t < t0 || t0 === undefined ) {
7666                    if ( ! ( t >= t0 ) ) {
7667
7668                        // looping?
7669
7670                        var t1global = pp[ 1 ];
7671
7672                        if ( t < t1global ) {
7673
7674                            i1 = 2; // + 1, using the scan for the details
7675                            t0 = t1global;
7676
7677                        }
7678
7679                        // linear reverse scan
7680
7681                        for ( var giveUpAt = i1 - 2; ;) {
7682
7683                            if ( t0 === undefined ) {
7684
7685                                // before start
7686
7687                                this._cachedIndex = 0;
7688                                return this.beforeStart_( 0, t, t1 );
7689
7690                            }
7691
7692                            if ( i1 === giveUpAt ) break; // this loop
7693
7694                            t1 = t0;
7695                            t0 = pp[ -- i1 - 1 ];
7696
7697                            if ( t >= t0 ) {
7698
7699                                // we have arrived at the sought interval
7700                                break seek;
7701
7702                            }
7703
7704                        }
7705
7706                        // prepare binary search on the left side of the index
7707                        right = i1;
7708                        i1 = 0;
7709                        break linear_scan;
7710
7711                    }
7712
7713                    // the interval is valid
7714
7715                    break validate_interval;
7716
7717                } // linear scan
7718
7719                // binary search
7720
7721                while ( i1 < right ) {
7722
7723                    var mid = ( i1 + right ) >>> 1;
7724
7725                    if ( t < pp[ mid ] ) {
7726
7727                        right = mid;
7728
7729                    } else {
7730
7731                        i1 = mid + 1;
7732
7733                    }
7734
7735                }
7736
7737                t1 = pp[   i1   ];
7738                t0 = pp[ i1 - 1 ];
7739
7740                // check boundary cases, again
7741
7742                if ( t0 === undefined ) {
7743
7744                    this._cachedIndex = 0;
7745                    return this.beforeStart_( 0, t, t1 );
7746
7747                }
7748
7749                if ( t1 === undefined ) {
7750
7751                    i1 = pp.length;
7752                    this._cachedIndex = i1;
7753                    return this.afterEnd_( i1 - 1, t0, t );
7754
7755                }
7756
7757            } // seek
7758
7759            this._cachedIndex = i1;
7760
7761            this.intervalChanged_( i1, t0, t1 );
7762
7763        } // validate_interval
7764
7765        return this.interpolate_( i1, t0, t, t1 );
7766
7767    },
7768
7769    settings: null, // optional, subclass-specific settings structure
7770    // Note: The indirection allows central control of many interpolants.
7771
7772    // --- Protected interface
7773
7774    DefaultSettings_: {},
7775
7776    getSettings_: function() {
7777
7778        return this.settings || this.DefaultSettings_;
7779
7780    },
7781
7782    copySampleValue_: function( index ) {
7783
7784        // copies a sample value to the result buffer
7785
7786        var result = this.resultBuffer,
7787            values = this.sampleValues,
7788            stride = this.valueSize,
7789            offset = index * stride;
7790
7791        for ( var i = 0; i !== stride; ++ i ) {
7792
7793            result[ i ] = values[ offset + i ];
7794
7795        }
7796
7797        return result;
7798
7799    },
7800
7801    // Template methods for derived classes:
7802
7803    interpolate_: function( i1, t0, t, t1 ) {
7804
7805        throw new Error( "call to abstract method" );
7806        // implementations shall return this.resultBuffer
7807
7808    },
7809
7810    intervalChanged_: function( i1, t0, t1 ) {
7811
7812        // empty
7813
7814    }
7815
7816};
7817
7818Object.assign( THREE.Interpolant.prototype, {
7819
7820    beforeStart_: //( 0, t, t0 ), returns this.resultBuffer
7821        THREE.Interpolant.prototype.copySampleValue_,
7822
7823    afterEnd_: //( N-1, tN-1, t ), returns this.resultBuffer
7824        THREE.Interpolant.prototype.copySampleValue_
7825
7826} );
7827
7828// File:src/math/interpolants/CubicInterpolant.js
7829
7830/**
7831 * Fast and simple cubic spline interpolant.
7832 *
7833 * It was derived from a Hermitian construction setting the first derivative
7834 * at each sample position to the linear slope between neighboring positions
7835 * over their parameter interval.
7836 *
7837 * @author tschw
7838 */
7839
7840THREE.CubicInterpolant = function(
7841    parameterPositions, sampleValues, sampleSize, resultBuffer ) {
7842
7843    THREE.Interpolant.call(
7844        this, parameterPositions, sampleValues, sampleSize, resultBuffer );
7845
7846    this._weightPrev = -0;
7847    this._offsetPrev = -0;
7848    this._weightNext = -0;
7849    this._offsetNext = -0;
7850
7851};
7852
7853THREE.CubicInterpolant.prototype =
7854    Object.assign( Object.create( THREE.Interpolant.prototype ), {
7855
7856        constructor: THREE.CubicInterpolant,
7857
7858        DefaultSettings_: {
7859
7860            endingStart: 	THREE.ZeroCurvatureEnding,
7861            endingEnd:		THREE.ZeroCurvatureEnding
7862
7863        },
7864
7865        intervalChanged_: function( i1, t0, t1 ) {
7866
7867            var pp = this.parameterPositions,
7868                iPrev = i1 - 2,
7869                iNext = i1 + 1,
7870
7871                tPrev = pp[ iPrev ],
7872                tNext = pp[ iNext ];
7873
7874            if ( tPrev === undefined ) {
7875
7876                switch ( this.getSettings_().endingStart ) {
7877
7878                    case THREE.ZeroSlopeEnding:
7879
7880                        // f'(t0) = 0
7881                        iPrev = i1;
7882                        tPrev = 2 * t0 - t1;
7883
7884                        break;
7885
7886                    case THREE.WrapAroundEnding:
7887
7888                        // use the other end of the curve
7889                        iPrev = pp.length - 2;
7890                        tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
7891
7892                        break;
7893
7894                    default: // ZeroCurvatureEnding
7895
7896                        // f''(t0) = 0 a.k.a. Natural Spline
7897                        iPrev = i1;
7898                        tPrev = t1;
7899
7900                }
7901
7902            }
7903
7904            if ( tNext === undefined ) {
7905
7906                switch ( this.getSettings_().endingEnd ) {
7907
7908                    case THREE.ZeroSlopeEnding:
7909
7910                        // f'(tN) = 0
7911                        iNext = i1;
7912                        tNext = 2 * t1 - t0;
7913
7914                        break;
7915
7916                    case THREE.WrapAroundEnding:
7917
7918                        // use the other end of the curve
7919                        iNext = 1;
7920                        tNext = t1 + pp[ 1 ] - pp[ 0 ];
7921
7922                        break;
7923
7924                    default: // ZeroCurvatureEnding
7925
7926                        // f''(tN) = 0, a.k.a. Natural Spline
7927                        iNext = i1 - 1;
7928                        tNext = t0;
7929
7930                }
7931
7932            }
7933
7934            var halfDt = ( t1 - t0 ) * 0.5,
7935                stride = this.valueSize;
7936
7937            this._weightPrev = halfDt / ( t0 - tPrev );
7938            this._weightNext = halfDt / ( tNext - t1 );
7939            this._offsetPrev = iPrev * stride;
7940            this._offsetNext = iNext * stride;
7941
7942        },
7943
7944        interpolate_: function( i1, t0, t, t1 ) {
7945
7946            var result = this.resultBuffer,
7947                values = this.sampleValues,
7948                stride = this.valueSize,
7949
7950                o1 = i1 * stride,		o0 = o1 - stride,
7951                oP = this._offsetPrev, 	oN = this._offsetNext,
7952                wP = this._weightPrev,	wN = this._weightNext,
7953
7954                p = ( t - t0 ) / ( t1 - t0 ),
7955                pp = p * p,
7956                ppp = pp * p;
7957
7958            // evaluate polynomials
7959
7960            var sP =     - wP   * ppp   +         2 * wP    * pp    -          wP   * p;
7961            var s0 = ( 1 + wP ) * ppp   + (-1.5 - 2 * wP )  * pp    + ( -0.5 + wP ) * p     + 1;
7962            var s1 = (-1 - wN ) * ppp   + ( 1.5 +   wN   )  * pp    +    0.5        * p;
7963            var sN =       wN   * ppp   -           wN      * pp;
7964
7965            // combine data linearly
7966
7967            for ( var i = 0; i !== stride; ++ i ) {
7968
7969                result[ i ] =
7970                    sP * values[ oP + i ] +
7971                    s0 * values[ o0 + i ] +
7972                    s1 * values[ o1 + i ] +
7973                    sN * values[ oN + i ];
7974
7975            }
7976
7977            return result;
7978
7979        }
7980
7981    } );
7982
7983// File:src/math/interpolants/DiscreteInterpolant.js
7984
7985/**
7986 *
7987 * Interpolant that evaluates to the sample value at the position preceeding
7988 * the parameter.
7989 *
7990 * @author tschw
7991 */
7992
7993THREE.DiscreteInterpolant = function(
7994    parameterPositions, sampleValues, sampleSize, resultBuffer ) {
7995
7996    THREE.Interpolant.call(
7997        this, parameterPositions, sampleValues, sampleSize, resultBuffer );
7998
7999};
8000
8001THREE.DiscreteInterpolant.prototype =
8002    Object.assign( Object.create( THREE.Interpolant.prototype ), {
8003
8004        constructor: THREE.DiscreteInterpolant,
8005
8006        interpolate_: function( i1, t0, t, t1 ) {
8007
8008            return this.copySampleValue_( i1 - 1 );
8009
8010        }
8011
8012    } );
8013
8014// File:src/math/interpolants/LinearInterpolant.js
8015
8016/**
8017 * @author tschw
8018 */
8019
8020THREE.LinearInterpolant = function(
8021    parameterPositions, sampleValues, sampleSize, resultBuffer ) {
8022
8023    THREE.Interpolant.call(
8024        this, parameterPositions, sampleValues, sampleSize, resultBuffer );
8025
8026};
8027
8028THREE.LinearInterpolant.prototype =
8029    Object.assign( Object.create( THREE.Interpolant.prototype ), {
8030
8031        constructor: THREE.LinearInterpolant,
8032
8033        interpolate_: function( i1, t0, t, t1 ) {
8034
8035            var result = this.resultBuffer,
8036                values = this.sampleValues,
8037                stride = this.valueSize,
8038
8039                offset1 = i1 * stride,
8040                offset0 = offset1 - stride,
8041
8042                weight1 = ( t - t0 ) / ( t1 - t0 ),
8043                weight0 = 1 - weight1;
8044
8045            for ( var i = 0; i !== stride; ++ i ) {
8046
8047                result[ i ] =
8048                    values[ offset0 + i ] * weight0 +
8049                    values[ offset1 + i ] * weight1;
8050
8051            }
8052
8053            return result;
8054
8055        }
8056
8057    } );
8058
8059// File:src/math/interpolants/QuaternionLinearInterpolant.js
8060
8061/**
8062 * Spherical linear unit quaternion interpolant.
8063 *
8064 * @author tschw
8065 */
8066
8067THREE.QuaternionLinearInterpolant = function(
8068    parameterPositions, sampleValues, sampleSize, resultBuffer ) {
8069
8070    THREE.Interpolant.call(
8071        this, parameterPositions, sampleValues, sampleSize, resultBuffer );
8072
8073};
8074
8075THREE.QuaternionLinearInterpolant.prototype =
8076    Object.assign( Object.create( THREE.Interpolant.prototype ), {
8077
8078        constructor: THREE.QuaternionLinearInterpolant,
8079
8080        interpolate_: function( i1, t0, t, t1 ) {
8081
8082            var result = this.resultBuffer,
8083                values = this.sampleValues,
8084                stride = this.valueSize,
8085
8086                offset = i1 * stride,
8087
8088                alpha = ( t - t0 ) / ( t1 - t0 );
8089
8090            for ( var end = offset + stride; offset !== end; offset += 4 ) {
8091
8092                THREE.Quaternion.slerpFlat( result, 0,
8093                    values, offset - stride, values, offset, alpha );
8094
8095            }
8096
8097            return result;
8098
8099        }
8100
8101    } );
8102
8103// File:src/core/Clock.js
8104
8105/**
8106 * @author alteredq / http://alteredqualia.com/
8107 */
8108
8109THREE.Clock = function ( autoStart ) {
8110
8111    this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
8112
8113    this.startTime = 0;
8114    this.oldTime = 0;
8115    this.elapsedTime = 0;
8116
8117    this.running = false;
8118
8119};
8120
8121THREE.Clock.prototype = {
8122
8123    constructor: THREE.Clock,
8124
8125    start: function () {
8126
8127        this.startTime = ( performance || Date ).now();
8128
8129        this.oldTime = this.startTime;
8130        this.running = true;
8131
8132    },
8133
8134    stop: function () {
8135
8136        this.getElapsedTime();
8137        this.running = false;
8138
8139    },
8140
8141    getElapsedTime: function () {
8142
8143        this.getDelta();
8144        return this.elapsedTime;
8145
8146    },
8147
8148    getDelta: function () {
8149
8150        var diff = 0;
8151
8152        if ( this.autoStart && ! this.running ) {
8153
8154            this.start();
8155
8156        }
8157
8158        if ( this.running ) {
8159
8160            var newTime = ( performance || Date ).now();
8161
8162            diff = ( newTime - this.oldTime ) / 1000;
8163            this.oldTime = newTime;
8164
8165            this.elapsedTime += diff;
8166
8167        }
8168
8169        return diff;
8170
8171    }
8172
8173};
8174
8175// File:src/core/EventDispatcher.js
8176
8177/**
8178 * https://github.com/mrdoob/eventdispatcher.js/
8179 */
8180
8181THREE.EventDispatcher = function () {};
8182
8183THREE.EventDispatcher.prototype = {
8184
8185    constructor: THREE.EventDispatcher,
8186
8187    apply: function ( object ) {
8188
8189        object.addEventListener = THREE.EventDispatcher.prototype.addEventListener;
8190        object.hasEventListener = THREE.EventDispatcher.prototype.hasEventListener;
8191        object.removeEventListener = THREE.EventDispatcher.prototype.removeEventListener;
8192        object.dispatchEvent = THREE.EventDispatcher.prototype.dispatchEvent;
8193
8194    },
8195
8196    addEventListener: function ( type, listener ) {
8197
8198        if ( this._listeners === undefined ) this._listeners = {};
8199
8200        var listeners = this._listeners;
8201
8202        if ( listeners[ type ] === undefined ) {
8203
8204            listeners[ type ] = [];
8205
8206        }
8207
8208        if ( listeners[ type ].indexOf( listener ) === - 1 ) {
8209
8210            listeners[ type ].push( listener );
8211
8212        }
8213
8214    },
8215
8216    hasEventListener: function ( type, listener ) {
8217
8218        if ( this._listeners === undefined ) return false;
8219
8220        var listeners = this._listeners;
8221
8222        if ( listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1 ) {
8223
8224            return true;
8225
8226        }
8227
8228        return false;
8229
8230    },
8231
8232    removeEventListener: function ( type, listener ) {
8233
8234        if ( this._listeners === undefined ) return;
8235
8236        var listeners = this._listeners;
8237        var listenerArray = listeners[ type ];
8238
8239        if ( listenerArray !== undefined ) {
8240
8241            var index = listenerArray.indexOf( listener );
8242
8243            if ( index !== - 1 ) {
8244
8245                listenerArray.splice( index, 1 );
8246
8247            }
8248
8249        }
8250
8251    },
8252
8253    dispatchEvent: function ( event ) {
8254
8255        if ( this._listeners === undefined ) return;
8256
8257        var listeners = this._listeners;
8258        var listenerArray = listeners[ event.type ];
8259
8260        if ( listenerArray !== undefined ) {
8261
8262            event.target = this;
8263
8264            var array = [];
8265            var length = listenerArray.length;
8266
8267            for ( var i = 0; i < length; i ++ ) {
8268
8269                array[ i ] = listenerArray[ i ];
8270
8271            }
8272
8273            for ( var i = 0; i < length; i ++ ) {
8274
8275                array[ i ].call( this, event );
8276
8277            }
8278
8279        }
8280
8281    }
8282
8283};
8284
8285// File:src/core/Layers.js
8286
8287/**
8288 * @author mrdoob / http://mrdoob.com/
8289 */
8290
8291THREE.Layers = function () {
8292
8293    this.mask = 1;
8294
8295};
8296
8297THREE.Layers.prototype = {
8298
8299    constructor: THREE.Layers,
8300
8301    set: function ( channel ) {
8302
8303        this.mask = 1 << channel;
8304
8305    },
8306
8307    enable: function ( channel ) {
8308
8309        this.mask |= 1 << channel;
8310
8311    },
8312
8313    toggle: function ( channel ) {
8314
8315        this.mask ^= 1 << channel;
8316
8317    },
8318
8319    disable: function ( channel ) {
8320
8321        this.mask &= ~ ( 1 << channel );
8322
8323    },
8324
8325    test: function ( layers ) {
8326
8327        return ( this.mask & layers.mask ) !== 0;
8328
8329    }
8330
8331};
8332
8333// File:src/core/Raycaster.js
8334
8335/**
8336 * @author mrdoob / http://mrdoob.com/
8337 * @author bhouston / http://clara.io/
8338 * @author stephomi / http://stephaneginier.com/
8339 */
8340
8341( function ( THREE ) {
8342
8343    THREE.Raycaster = function ( origin, direction, near, far ) {
8344
8345        this.ray = new THREE.Ray( origin, direction );
8346        // direction is assumed to be normalized (for accurate distance calculations)
8347
8348        this.near = near || 0;
8349        this.far = far || Infinity;
8350
8351        this.params = {
8352            Mesh: {},
8353            Line: {},
8354            LOD: {},
8355            Points: { threshold: 1 },
8356            Sprite: {}
8357        };
8358
8359        Object.defineProperties( this.params, {
8360            PointCloud: {
8361                get: function () {
8362                    console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );
8363                    return this.Points;
8364                }
8365            }
8366        } );
8367
8368    };
8369
8370    function ascSort( a, b ) {
8371
8372        return a.distance - b.distance;
8373
8374    }
8375
8376    function intersectObject( object, raycaster, intersects, recursive ) {
8377
8378        if ( object.visible === false ) return;
8379
8380        object.raycast( raycaster, intersects );
8381
8382        if ( recursive === true ) {
8383
8384            var children = object.children;
8385
8386            for ( var i = 0, l = children.length; i < l; i ++ ) {
8387
8388                intersectObject( children[ i ], raycaster, intersects, true );
8389
8390            }
8391
8392        }
8393
8394    }
8395
8396    //
8397
8398    THREE.Raycaster.prototype = {
8399
8400        constructor: THREE.Raycaster,
8401
8402        linePrecision: 1,
8403
8404        set: function ( origin, direction ) {
8405
8406            // direction is assumed to be normalized (for accurate distance calculations)
8407
8408            this.ray.set( origin, direction );
8409
8410        },
8411
8412        setFromCamera: function ( coords, camera ) {
8413
8414            if ( camera instanceof THREE.PerspectiveCamera ) {
8415
8416                this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
8417                this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
8418
8419            } else if ( camera instanceof THREE.OrthographicCamera ) {
8420
8421                this.ray.origin.set( coords.x, coords.y, - 1 ).unproject( camera );
8422                this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
8423
8424            } else {
8425
8426                console.error( 'THREE.Raycaster: Unsupported camera type.' );
8427
8428            }
8429
8430        },
8431
8432        intersectObject: function ( object, recursive ) {
8433
8434            var intersects = [];
8435
8436            intersectObject( object, this, intersects, recursive );
8437
8438            intersects.sort( ascSort );
8439
8440            return intersects;
8441
8442        },
8443
8444        intersectObjects: function ( objects, recursive ) {
8445
8446            var intersects = [];
8447
8448            if ( Array.isArray( objects ) === false ) {
8449
8450                console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
8451                return intersects;
8452
8453            }
8454
8455            for ( var i = 0, l = objects.length; i < l; i ++ ) {
8456
8457                intersectObject( objects[ i ], this, intersects, recursive );
8458
8459            }
8460
8461            intersects.sort( ascSort );
8462
8463            return intersects;
8464
8465        }
8466
8467    };
8468
8469}( THREE ) );
8470
8471// File:src/core/Object3D.js
8472
8473/**
8474 * @author mrdoob / http://mrdoob.com/
8475 * @author mikael emtinger / http://gomo.se/
8476 * @author alteredq / http://alteredqualia.com/
8477 * @author WestLangley / http://github.com/WestLangley
8478 * @author elephantatwork / www.elephantatwork.ch
8479 */
8480
8481THREE.Object3D = function () {
8482
8483    Object.defineProperty( this, 'id', { value: THREE.Object3DIdCount ++ } );
8484
8485    this.uuid = THREE.Math.generateUUID();
8486
8487    this.name = '';
8488    this.type = 'Object3D';
8489
8490    this.parent = null;
8491    this.children = [];
8492
8493    this.up = THREE.Object3D.DefaultUp.clone();
8494
8495    var position = new THREE.Vector3();
8496    var rotation = new THREE.Euler();
8497    var quaternion = new THREE.Quaternion();
8498    var scale = new THREE.Vector3( 1, 1, 1 );
8499
8500    function onRotationChange() {
8501
8502        quaternion.setFromEuler( rotation, false );
8503
8504    }
8505
8506    function onQuaternionChange() {
8507
8508        rotation.setFromQuaternion( quaternion, undefined, false );
8509
8510    }
8511
8512    rotation.onChange( onRotationChange );
8513    quaternion.onChange( onQuaternionChange );
8514
8515    Object.defineProperties( this, {
8516        position: {
8517            enumerable: true,
8518            value: position
8519        },
8520        rotation: {
8521            enumerable: true,
8522            value: rotation
8523        },
8524        quaternion: {
8525            enumerable: true,
8526            value: quaternion
8527        },
8528        scale: {
8529            enumerable: true,
8530            value: scale
8531        },
8532        modelViewMatrix: {
8533            value: new THREE.Matrix4()
8534        },
8535        normalMatrix: {
8536            value: new THREE.Matrix3()
8537        }
8538    } );
8539
8540    this.rotationAutoUpdate = true;
8541
8542    this.matrix = new THREE.Matrix4();
8543    this.matrixWorld = new THREE.Matrix4();
8544
8545    this.matrixAutoUpdate = THREE.Object3D.DefaultMatrixAutoUpdate;
8546    this.matrixWorldNeedsUpdate = false;
8547
8548    this.layers = new THREE.Layers();
8549    this.visible = true;
8550
8551    this.castShadow = false;
8552    this.receiveShadow = false;
8553
8554    this.frustumCulled = true;
8555    this.renderOrder = 0;
8556
8557    this.userData = {};
8558
8559};
8560
8561THREE.Object3D.DefaultUp = new THREE.Vector3( 0, 1, 0 );
8562THREE.Object3D.DefaultMatrixAutoUpdate = true;
8563
8564THREE.Object3D.prototype = {
8565
8566    constructor: THREE.Object3D,
8567
8568    applyMatrix: function ( matrix ) {
8569
8570        this.matrix.multiplyMatrices( matrix, this.matrix );
8571
8572        this.matrix.decompose( this.position, this.quaternion, this.scale );
8573
8574    },
8575
8576    setRotationFromAxisAngle: function ( axis, angle ) {
8577
8578        // assumes axis is normalized
8579
8580        this.quaternion.setFromAxisAngle( axis, angle );
8581
8582    },
8583
8584    setRotationFromEuler: function ( euler ) {
8585
8586        this.quaternion.setFromEuler( euler, true );
8587
8588    },
8589
8590    setRotationFromMatrix: function ( m ) {
8591
8592        // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
8593
8594        this.quaternion.setFromRotationMatrix( m );
8595
8596    },
8597
8598    setRotationFromQuaternion: function ( q ) {
8599
8600        // assumes q is normalized
8601
8602        this.quaternion.copy( q );
8603
8604    },
8605
8606    rotateOnAxis: function () {
8607
8608        // rotate object on axis in object space
8609        // axis is assumed to be normalized
8610
8611        var q1 = new THREE.Quaternion();
8612
8613        return function ( axis, angle ) {
8614
8615            q1.setFromAxisAngle( axis, angle );
8616
8617            this.quaternion.multiply( q1 );
8618
8619            return this;
8620
8621        };
8622
8623    }(),
8624
8625    rotateX: function () {
8626
8627        var v1 = new THREE.Vector3( 1, 0, 0 );
8628
8629        return function ( angle ) {
8630
8631            return this.rotateOnAxis( v1, angle );
8632
8633        };
8634
8635    }(),
8636
8637    rotateY: function () {
8638
8639        var v1 = new THREE.Vector3( 0, 1, 0 );
8640
8641        return function ( angle ) {
8642
8643            return this.rotateOnAxis( v1, angle );
8644
8645        };
8646
8647    }(),
8648
8649    rotateZ: function () {
8650
8651        var v1 = new THREE.Vector3( 0, 0, 1 );
8652
8653        return function ( angle ) {
8654
8655            return this.rotateOnAxis( v1, angle );
8656
8657        };
8658
8659    }(),
8660
8661    translateOnAxis: function () {
8662
8663        // translate object by distance along axis in object space
8664        // axis is assumed to be normalized
8665
8666        var v1 = new THREE.Vector3();
8667
8668        return function ( axis, distance ) {
8669
8670            v1.copy( axis ).applyQuaternion( this.quaternion );
8671
8672            this.position.add( v1.multiplyScalar( distance ) );
8673
8674            return this;
8675
8676        };
8677
8678    }(),
8679
8680    translateX: function () {
8681
8682        var v1 = new THREE.Vector3( 1, 0, 0 );
8683
8684        return function ( distance ) {
8685
8686            return this.translateOnAxis( v1, distance );
8687
8688        };
8689
8690    }(),
8691
8692    translateY: function () {
8693
8694        var v1 = new THREE.Vector3( 0, 1, 0 );
8695
8696        return function ( distance ) {
8697
8698            return this.translateOnAxis( v1, distance );
8699
8700        };
8701
8702    }(),
8703
8704    translateZ: function () {
8705
8706        var v1 = new THREE.Vector3( 0, 0, 1 );
8707
8708        return function ( distance ) {
8709
8710            return this.translateOnAxis( v1, distance );
8711
8712        };
8713
8714    }(),
8715
8716    localToWorld: function ( vector ) {
8717
8718        return vector.applyMatrix4( this.matrixWorld );
8719
8720    },
8721
8722    worldToLocal: function () {
8723
8724        var m1 = new THREE.Matrix4();
8725
8726        return function ( vector ) {
8727
8728            return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) );
8729
8730        };
8731
8732    }(),
8733
8734    lookAt: function () {
8735
8736        // This routine does not support objects with rotated and/
8736or translated parent(s)
8737
8738        var m1 = new THREE.Matrix4();
8739
8740        return function ( vector ) {
8741
8742            m1.lookAt( vector, this.position, this.up );
8743
8744            this.quaternion.setFromRotationMatrix( m1 );
8745
8746        };
8747
8748    }(),
8749
8750    add: function ( object ) {
8751
8752        if ( arguments.length > 1 ) {
8753
8754            for ( var i = 0; i < arguments.length; i ++ ) {
8755
8756                this.add( arguments[ i ] );
8757
8758            }
8759
8760            return this;
8761
8762        }
8763
8764        if ( object === this ) {
8765
8766            console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
8767            return this;
8768
8769        }
8770
8771        if ( object instanceof THREE.Object3D ) {
8772
8773            if ( object.parent !== null ) {
8774
8775                object.parent.remove( object );
8776
8777            }
8778
8779            object.parent = this;
8780            object.dispatchEvent( { type: 'added' } );
8781
8782            this.children.push( object );
8783
8784        } else {
8785
8786            console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
8787
8788        }
8789
8790        return this;
8791
8792    },
8793
8794    remove: function ( object ) {
8795
8796        if ( arguments.length > 1 ) {
8797
8798            for ( var i = 0; i < arguments.length; i ++ ) {
8799
8800                this.remove( arguments[ i ] );
8801
8802            }
8803
8804        }
8805
8806        var index = this.children.indexOf( object );
8807
8808        if ( index !== - 1 ) {
8809
8810            object.parent = null;
8811
8812            object.dispatchEvent( { type: 'removed' } );
8813
8814            this.children.splice( index, 1 );
8815
8816        }
8817
8818    },
8819
8820    getObjectById: function ( id ) {
8821
8822        return this.getObjectByProperty( 'id', id );
8823
8824    },
8825
8826    getObjectByName: function ( name ) {
8827
8828        return this.getObjectByProperty( 'name', name );
8829
8830    },
8831
8832    getObjectByProperty: function ( name, value ) {
8833
8834        if ( this[ name ] === value ) return this;
8835
8836        for ( var i = 0, l = this.children.length; i < l; i ++ ) {
8837
8838            var child = this.children[ i ];
8839            var object = child.getObjectByProperty( name, value );
8840
8841            if ( object !== undefined ) {
8842
8843                return object;
8844
8845            }
8846
8847        }
8848
8849        return undefined;
8850
8851    },
8852
8853    getWorldPosition: function ( optionalTarget ) {
8854
8855        var result = optionalTarget || new THREE.Vector3();
8856
8857        this.updateMatrixWorld( true );
8858
8859        return result.setFromMatrixPosition( this.matrixWorld );
8860
8861    },
8862
8863    getWorldQuaternion: function () {
8864
8865        var position = new THREE.Vector3();
8866        var scale = new THREE.Vector3();
8867
8868        return function ( optionalTarget ) {
8869
8870            var result = optionalTarget || new THREE.Quaternion();
8871
8872            this.updateMatrixWorld( true );
8873
8874            this.matrixWorld.decompose( position, result, scale );
8875
8876            return result;
8877
8878        };
8879
8880    }(),
8881
8882    getWorldRotation: function () {
8883
8884        var quaternion = new THREE.Quaternion();
8885
8886        return function ( optionalTarget ) {
8887
8888            var result = optionalTarget || new THREE.Euler();
8889
8890            this.getWorldQuaternion( quaternion );
8891
8892            return result.setFromQuaternion( quaternion, this.rotation.order, false );
8893
8894        };
8895
8896    }(),
8897
8898    getWorldScale: function () {
8899
8900        var position = new THREE.Vector3();
8901        var quaternion = new THREE.Quaternion();
8902
8903        return function ( optionalTarget ) {
8904
8905            var result = optionalTarget || new THREE.Vector3();
8906
8907            this.updateMatrixWorld( true );
8908
8909            this.matrixWorld.decompose( position, quaternion, result );
8910
8911            return result;
8912
8913        };
8914
8915    }(),
8916
8917    getWorldDirection: function () {
8918
8919        var quaternion = new THREE.Quaternion();
8920
8921        return function ( optionalTarget ) {
8922
8923            var result = optionalTarget || new THREE.Vector3();
8924
8925            this.getWorldQuaternion( quaternion );
8926
8927            return result.set( 0, 0, 1 ).applyQuaternion( quaternion );
8928
8929        };
8930
8931    }(),
8932
8933    raycast: function () {},
8934
8935    traverse: function ( callback ) {
8936
8937        callback( this );
8938
8939        var children = this.children;
8940
8941        for ( var i = 0, l = children.length; i < l; i ++ ) {
8942
8943            children[ i ].traverse( callback );
8944
8945        }
8946
8947    },
8948
8949    traverseVisible: function ( callback ) {
8950
8951        if ( this.visible === false ) return;
8952
8953        callback( this );
8954
8955        var children = this.children;
8956
8957        for ( var i = 0, l = children.length; i < l; i ++ ) {
8958
8959            children[ i ].traverseVisible( callback );
8960
8961        }
8962
8963    },
8964
8965    traverseAncestors: function ( callback ) {
8966
8967        var parent = this.parent;
8968
8969        if ( parent !== null ) {
8970
8971            callback( parent );
8972
8973            parent.traverseAncestors( callback );
8974
8975        }
8976
8977    },
8978
8979    updateMatrix: function () {
8980
8981        this.matrix.compose( this.position, this.quaternion, this.scale );
8982
8983        this.matrixWorldNeedsUpdate = true;
8984
8985    },
8986
8987    updateMatrixWorld: function ( force ) {
8988
8989        if ( this.matrixAutoUpdate === true ) this.updateMatrix();
8990
8991        if ( this.matrixWorldNeedsUpdate === true || force === true ) {
8992
8993            if ( this.parent === null ) {
8994
8995                this.matrixWorld.copy( this.matrix );
8996
8997            } else {
8998
8999                this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
9000
9001            }
9002
9003            this.matrixWorldNeedsUpdate = false;
9004
9005            force = true;
9006
9007        }
9008
9009        // update children
9010
9011        for ( var i = 0, l = this.children.length; i < l; i ++ ) {
9012
9013            this.children[ i ].updateMatrixWorld( force );
9014
9015        }
9016
9017    },
9018
9019    toJSON: function ( meta ) {
9020
9021        // meta is '' when called from JSON.stringify
9022        var isRootObject = ( meta === undefined || meta === '' );
9023
9024        var output = {};
9025
9026        // meta is a hash used to collect geometries, materials.
9027        // not providing it implies that this is the root object
9028        // being serialized.
9029        if ( isRootObject ) {
9030
9031            // initialize meta obj
9032            meta = {
9033                geometries: {},
9034                materials: {},
9035                textures: {},
9036                images: {}
9037            };
9038
9039            output.metadata = {
9040                version: 4.4,
9041                type: 'Object',
9042                generator: 'Object3D.toJSON'
9043            };
9044
9045        }
9046
9047        // standard Object3D serialization
9048
9049        var object = {};
9050
9051        object.uuid = this.uuid;
9052        object.type = this.type;
9053
9054        if ( this.name !== '' ) object.name = this.name;
9055        if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
9056        if ( this.castShadow === true ) object.castShadow = true;
9057        if ( this.receiveShadow === true ) object.receiveShadow = true;
9058        if ( this.visible === false ) object.visible = false;
9059
9060        object.matrix = this.matrix.toArray();
9061
9062        //
9063
9064        if ( this.geometry !== undefined ) {
9065
9066            if ( meta.geometries[ this.geometry.uuid ] === undefined ) {
9067
9068                meta.geometries[ this.geometry.uuid ] = this.geometry.toJSON( meta );
9069
9070            }
9071
9072            object.geometry = this.geometry.uuid;
9073
9074        }
9075
9076        if ( this.material !== undefined ) {
9077
9078            if ( meta.materials[ this.material.uuid ] === undefined ) {
9079
9080                meta.materials[ this.material.uuid ] = this.material.toJSON( meta );
9081
9082            }
9083
9084            object.material = this.material.uuid;
9085
9086        }
9087
9088        //
9089
9090        if ( this.children.length > 0 ) {
9091
9092            object.children = [];
9093
9094            for ( var i = 0; i < this.children.length; i ++ ) {
9095
9096                object.children.push( this.children[ i ].toJSON( meta ).object );
9097
9098            }
9099
9100        }
9101
9102        if ( isRootObject ) {
9103
9104            var geometries = extractFromCache( meta.geometries );
9105            var materials = extractFromCache( meta.materials );
9106            var textures = extractFromCache( meta.textures );
9107            var images = extractFromCache( meta.images );
9108
9109            if ( geometries.length > 0 ) output.geometries = geometries;
9110            if ( materials.length > 0 ) output.materials = materials;
9111            if ( textures.length > 0 ) output.textures = textures;
9112            if ( images.length > 0 ) output.images = images;
9113
9114        }
9115
9116        output.object = object;
9117
9118        return output;
9119
9120        // extract data from the cache hash
9121        // remove metadata on each item
9122        // and return as array
9123        function extractFromCache ( cache ) {
9124
9125            var values = [];
9126            for ( var key in cache ) {
9127
9128                var data = cache[ key ];
9129                delete data.metadata;
9130                values.push( data );
9131
9132            }
9133            return values;
9134
9135        }
9136
9137    },
9138
9139    clone: function ( recursive ) {
9140
9141        return new this.constructor().copy( this, recursive );
9142
9143    },
9144
9145    copy: function ( source, recursive ) {
9146
9147        if ( recursive === undefined ) recursive = true;
9148
9149        this.name = source.name;
9150
9151        this.up.copy( source.up );
9152
9153        this.position.copy( source.position );
9154        this.quaternion.copy( source.quaternion );
9155        this.scale.copy( source.scale );
9156
9157        this.rotationAutoUpdate = source.rotationAutoUpdate;
9158
9159        this.matrix.copy( source.matrix );
9160        this.matrixWorld.copy( source.matrixWorld );
9161
9162        this.matrixAutoUpdate = source.matrixAutoUpdate;
9163        this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
9164
9165        this.visible = source.visible;
9166
9167        this.castShadow = source.castShadow;
9168        this.receiveShadow = source.receiveShadow;
9169
9170        this.frustumCulled = source.frustumCulled;
9171        this.renderOrder = source.renderOrder;
9172
9173        this.userData = JSON.parse( JSON.stringify( source.userData ) );
9174
9175        if ( recursive === true ) {
9176
9177            for ( var i = 0; i < source.children.length; i ++ ) {
9178
9179                var child = source.children[ i ];
9180                this.add( child.clone() );
9181
9182            }
9183
9184        }
9185
9186        return this;
9187
9188    }
9189
9190};
9191
9192THREE.EventDispatcher.prototype.apply( THREE.Object3D.prototype );
9193
9194THREE.Object3DIdCount = 0;
9195
9196// File:src/core/Face3.js
9197
9198/**
9199 * @author mrdoob / http://mrdoob.com/
9200 * @author alteredq / http://alteredqualia.com/
9201 */
9202
9203THREE.Face3 = function ( a, b, c, normal, color, materialIndex ) {
9204
9205    this.a = a;
9206    this.b = b;
9207    this.c = c;
9208
9209    this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3();
9210    this.vertexNormals = Array.isArray( normal ) ? normal : [];
9211
9212    this.color = color instanceof THREE.Color ? color : new THREE.Color();
9213    this.vertexColors = Array.isArray( color ) ? color : [];
9214
9215    this.materialIndex = materialIndex !== undefined ? materialIndex : 0;
9216
9217};
9218
9219THREE.Face3.prototype = {
9220
9221    constructor: THREE.Face3,
9222
9223    clone: function () {
9224
9225        return new this.constructor().copy( this );
9226
9227    },
9228
9229    copy: function ( source ) {
9230
9231        this.a = source.a;
9232        this.b = source.b;
9233        this.c = source.c;
9234
9235        this.normal.copy( source.normal );
9236        this.color.copy( source.color );
9237
9238        this.materialIndex = source.materialIndex;
9239
9240        for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
9241
9242            this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
9243
9244        }
9245
9246        for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {
9247
9248            this.vertexColors[ i ] = source.vertexColors[ i ].clone();
9249
9250        }
9251
9252        return this;
9253
9254    }
9255
9256};
9257
9258// File:src/core/BufferAttribute.js
9259
9260/**
9261 * @author mrdoob / http://mrdoob.com/
9262 */
9263
9264THREE.BufferAttribute = function ( array, itemSize, normalized ) {
9265
9266    this.uuid = THREE.Math.generateUUID();
9267
9268    this.array = array;
9269    this.itemSize = itemSize;
9270
9271    this.dynamic = false;
9272    this.updateRange = { offset: 0, count: - 1 };
9273
9274    this.version = 0;
9275    this.normalized = normalized === true;
9276
9277};
9278
9279THREE.BufferAttribute.prototype = {
9280
9281    constructor: THREE.BufferAttribute,
9282
9283    get count() {
9284
9285        return this.array.length / this.itemSize;
9286
9287    },
9288
9289    set needsUpdate( value ) {
9290
9291        if ( value === true ) this.version ++;
9292
9293    },
9294
9295    setDynamic: function ( value ) {
9296
9297        this.dynamic = value;
9298
9299        return this;
9300
9301    },
9302
9303    copy: function ( source ) {
9304
9305        this.array = new source.array.constructor( source.array );
9306        this.itemSize = source.itemSize;
9307
9308        this.dynamic = source.dynamic;
9309
9310        return this;
9311
9312    },
9313
9314    copyAt: function ( index1, attribute, index2 ) {
9315
9316        index1 *= this.itemSize;
9317        index2 *= attribute.itemSize;
9318
9319        for ( var i = 0, l = this.itemSize; i < l; i ++ ) {
9320
9321            this.array[ index1 + i ] = attribute.array[ index2 + i ];
9322
9323        }
9324
9325        return this;
9326
9327    },
9328
9329    copyArray: function ( array ) {
9330
9331        this.array.set( array );
9332
9333        return this;
9334
9335    },
9336
9337    copyColorsArray: function ( colors ) {
9338
9339        var array = this.array, offset = 0;
9340
9341        for ( var i = 0, l = colors.length; i < l; i ++ ) {
9342
9343            var color = colors[ i ];
9344
9345            if ( color === undefined ) {
9346
9347                console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
9348                color = new THREE.Color();
9349
9350            }
9351
9352            array[ offset ++ ] = color.r;
9353            array[ offset ++ ] = color.g;
9354            array[ offset ++ ] = color.b;
9355
9356        }
9357
9358        return this;
9359
9360    },
9361
9362    copyIndicesArray: function ( indices ) {
9363
9364        var array = this.array, offset = 0;
9365
9366        for ( var i = 0, l = indices.length; i < l; i ++ ) {
9367
9368            var index = indices[ i ];
9369
9370            array[ offset ++ ] = index.a;
9371            array[ offset ++ ] = index.b;
9372            array[ offset ++ ] = index.c;
9373
9374        }
9375
9376        return this;
9377
9378    },
9379
9380    copyVector2sArray: function ( vectors ) {
9381
9382        var array = this.array, offset = 0;
9383
9384        for ( var i = 0, l = vectors.length; i < l; i ++ ) {
9385
9386            var vector = vectors[ i ];
9387
9388            if ( vector === undefined ) {
9389
9390                console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
9391                vector = new THREE.Vector2();
9392
9393            }
9394
9395            array[ offset ++ ] = vector.x;
9396            array[ offset ++ ] = vector.y;
9397
9398        }
9399
9400        return this;
9401
9402    },
9403
9404    copyVector3sArray: function ( vectors ) {
9405
9406        var array = this.array, offset = 0;
9407
9408        for ( var i = 0, l = vectors.length; i < l; i ++ ) {
9409
9410            var vector = vectors[ i ];
9411
9412            if ( vector === undefined ) {
9413
9414                console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
9415                vector = new THREE.Vector3();
9416
9417            }
9418
9419            array[ offset ++ ] = vector.x;
9420            array[ offset ++ ] = vector.y;
9421            array[ offset ++ ] = vector.z;
9422
9423        }
9424
9425        return this;
9426
9427    },
9428
9429    copyVector4sArray: function ( vectors ) {
9430
9431        var array = this.array, offset = 0;
9432
9433        for ( var i = 0, l = vectors.length; i < l; i ++ ) {
9434
9435            var vector = vectors[ i ];
9436
9437            if ( vector === undefined ) {
9438
9439                console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
9440                vector = new THREE.Vector4();
9441
9442            }
9443
9444            array[ offset ++ ] = vector.x;
9445            array[ offset ++ ] = vector.y;
9446            array[ offset ++ ] = vector.z;
9447            array[ offset ++ ] = vector.w;
9448
9449        }
9450
9451        return this;
9452
9453    },
9454
9455    set: function ( value, offset ) {
9456
9457        if ( offset === undefined ) offset = 0;
9458
9459        this.array.set( value, offset );
9460
9461        return this;
9462
9463    },
9464
9465    getX: function ( index ) {
9466
9467        return this.array[ index * this.itemSize ];
9468
9469    },
9470
9471    setX: function ( index, x ) {
9472
9473        this.array[ index * this.itemSize ] = x;
9474
9475        return this;
9476
9477    },
9478
9479    getY: function ( index ) {
9480
9481        return this.array[ index * this.itemSize + 1 ];
9482
9483    },
9484
9485    setY: function ( index, y ) {
9486
9487        this.array[ index * this.itemSize + 1 ] = y;
9488
9489        return this;
9490
9491    },
9492
9493    getZ: function ( index ) {
9494
9495        return this.array[ index * this.itemSize + 2 ];
9496
9497    },
9498
9499    setZ: function ( index, z ) {
9500
9501        this.array[ index * this.itemSize + 2 ] = z;
9502
9503        return this;
9504
9505    },
9506
9507    getW: function ( index ) {
9508
9509        return this.array[ index * this.itemSize + 3 ];
9510
9511    },
9512
9513    setW: function ( index, w ) {
9514
9515        this.array[ index * this.itemSize + 3 ] = w;
9516
9517        return this;
9518
9519    },
9520
9521    setXY: function ( index, x, y ) {
9522
9523        index *= this.itemSize;
9524
9525        this.array[ index + 0 ] = x;
9526        this.array[ index + 1 ] = y;
9527
9528        return this;
9529
9530    },
9531
9532    setXYZ: function ( index, x, y, z ) {
9533
9534        index *= this.itemSize;
9535
9536        this.array[ index + 0 ] = x;
9537        this.array[ index + 1 ] = y;
9538        this.array[ index + 2 ] = z;
9539
9540        return this;
9541
9542    },
9543
9544    setXYZW: function ( index, x, y, z, w ) {
9545
9546        index *= this.itemSize;
9547
9548        this.array[ index + 0 ] = x;
9549        this.array[ index + 1 ] = y;
9550        this.array[ index + 2 ] = z;
9551        this.array[ index + 3 ] = w;
9552
9553        return this;
9554
9555    },
9556
9557    clone: function () {
9558
9559        return new this.constructor().copy( this );
9560
9561    }
9562
9563};
9564
9565//
9566
9567THREE.Int8Attribute = function ( array, itemSize ) {
9568
9569    return new THREE.BufferAttribute( new Int8Array( array ), itemSize );
9570
9571};
9572
9573THREE.Uint8Attribute = function ( array, itemSize ) {
9574
9575    return new THREE.BufferAttribute( new Uint8Array( array ), itemSize );
9576
9577};
9578
9579THREE.Uint8ClampedAttribute = function ( array, itemSize ) {
9580
9581    return new THREE.BufferAttribute( new Uint8ClampedArray( array ), itemSize );
9582
9583};
9584
9585THREE.Int16Attribute = function ( array, itemSize ) {
9586
9587    return new THREE.BufferAttribute( new Int16Array( array ), itemSize );
9588
9589};
9590
9591THREE.Uint16Attribute = function ( array, itemSize ) {
9592
9593    return new THREE.BufferAttribute( new Uint16Array( array ), itemSize );
9594
9595};
9596
9597THREE.Int32Attribute = function ( array, itemSize ) {
9598
9599    return new THREE.BufferAttribute( new Int32Array( array ), itemSize );
9600
9601};
9602
9603THREE.Uint32Attribute = function ( array, itemSize ) {
9604
9605    return new THREE.BufferAttribute( new Uint32Array( array ), itemSize );
9606
9607};
9608
9609THREE.Float32Attribute = function ( array, itemSize ) {
9610
9611    return new THREE.BufferAttribute( new Float32Array( array ), itemSize );
9612
9613};
9614
9615THREE.Float64Attribute = function ( array, itemSize ) {
9616
9617    return new THREE.BufferAttribute( new Float64Array( array ), itemSize );
9618
9619};
9620
9621
9622// Deprecated
9623
9624THREE.DynamicBufferAttribute = function ( array, itemSize ) {
9625
9626    console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.' );
9627    return new THREE.BufferAttribute( array, itemSize ).setDynamic( true );
9628
9629};
9630
9631// File:src/core/InstancedBufferAttribute.js
9632
9633/**
9634 * @author benaadams / https://twitter.com/ben_a_adams
9635 */
9636
9637THREE.InstancedBufferAttribute = function ( array, itemSize, meshPerAttribute ) {
9638
9639    THREE.BufferAttribute.call( this, array, itemSize );
9640
9641    this.meshPerAttribute = meshPerAttribute || 1;
9642
9643};
9644
9645THREE.InstancedBufferAttribute.prototype = Object.create( THREE.BufferAttribute.prototype );
9646THREE.InstancedBufferAttribute.prototype.constructor = THREE.InstancedBufferAttribute;
9647
9648THREE.InstancedBufferAttribute.prototype.copy = function ( source ) {
9649
9650    THREE.BufferAttribute.prototype.copy.call( this, source );
9651
9652    this.meshPerAttribute = source.meshPerAttribute;
9653
9654    return this;
9655
9656};
9657
9658// File:src/core/InterleavedBuffer.js
9659
9660/**
9661 * @author benaadams / https://twitter.com/ben_a_adams
9662 */
9663
9664THREE.InterleavedBuffer = function ( array, stride ) {
9665
9666    this.uuid = THREE.Math.generateUUID();
9667
9668    this.array = array;
9669    this.stride = stride;
9670
9671    this.dynamic = false;
9672    this.updateRange = { offset: 0, count: - 1 };
9673
9674    this.version = 0;
9675
9676};
9677
9678THREE.InterleavedBuffer.prototype = {
9679
9680    constructor: THREE.InterleavedBuffer,
9681
9682    get length () {
9683
9684        return this.array.length;
9685
9686    },
9687
9688    get count () {
9689
9690        return this.array.length / this.stride;
9691
9692    },
9693
9694    set needsUpdate( value ) {
9695
9696        if ( value === true ) this.version ++;
9697
9698    },
9699
9700    setDynamic: function ( value ) {
9701
9702        this.dynamic = value;
9703
9704        return this;
9705
9706    },
9707
9708    copy: function ( source ) {
9709
9710        this.array = new source.array.constructor( source.array );
9711        this.stride = source.stride;
9712        this.dynamic = source.dynamic;
9713
9714        return this;
9715
9716    },
9717
9718    copyAt: function ( index1, attribute, index2 ) {
9719
9720        index1 *= this.stride;
9721        index2 *= attribute.stride;
9722
9723        for ( var i = 0, l = this.stride; i < l; i ++ ) {
9724
9725            this.array[ index1 + i ] = attribute.array[ index2 + i ];
9726
9727        }
9728
9729        return this;
9730
9731    },
9732
9733    set: function ( value, offset ) {
9734
9735        if ( offset === undefined ) offset = 0;
9736
9737        this.array.set( value, offset );
9738
9739        return this;
9740
9741    },
9742
9743    clone: function () {
9744
9745        return new this.constructor().copy( this );
9746
9747    }
9748
9749};
9750
9751// File:src/core/InstancedInterleavedBuffer.js
9752
9753/**
9754 * @author benaadams / https://twitter.com/ben_a_adams
9755 */
9756
9757THREE.InstancedInterleavedBuffer = function ( array, stride, meshPerAttribute ) {
9758
9759    THREE.InterleavedBuffer.call( this, array, stride );
9760
9761    this.meshPerAttribute = meshPerAttribute || 1;
9762
9763};
9764
9765THREE.InstancedInterleavedBuffer.prototype = Object.create( THREE.InterleavedBuffer.prototype );
9766THREE.InstancedInterleavedBuffer.prototype.constructor = THREE.InstancedInterleavedBuffer;
9767
9768THREE.InstancedInterleavedBuffer.prototype.copy = function ( source ) {
9769
9770    THREE.InterleavedBuffer.prototype.copy.call( this, source );
9771
9772    this.meshPerAttribute = source.meshPerAttribute;
9773
9774    return this;
9775
9776};
9777
9778// File:src/core/InterleavedBufferAttribute.js
9779
9780/**
9781 * @author benaadams / https://twitter.com/ben_a_adams
9782 */
9783
9784THREE.InterleavedBufferAttribute = function ( interleavedBuffer, itemSize, offset ) {
9785
9786    this.uuid = THREE.Math.generateUUID();
9787
9788    this.data = interleavedBuffer;
9789    this.itemSize = itemSize;
9790    this.offset = offset;
9791
9792};
9793
9794
9795THREE.InterleavedBufferAttribute.prototype = {
9796
9797    constructor: THREE.InterleavedBufferAttribute,
9798
9799    get length() {
9800
9801        console.warn( 'THREE.BufferAttribute: .length has been deprecated. Please use .count.' );
9802        return this.array.length;
9803
9804    },
9805
9806    get count() {
9807
9808        return this.data.count;
9809
9810    },
9811
9812    setX: function ( index, x ) {
9813
9814        this.data.array[ index * this.data.stride + this.offset ] = x;
9815
9816        return this;
9817
9818    },
9819
9820    setY: function ( index, y ) {
9821
9822        this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
9823
9824        return this;
9825
9826    },
9827
9828    setZ: function ( index, z ) {
9829
9830        this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
9831
9832        return this;
9833
9834    },
9835
9836    setW: function ( index, w ) {
9837
9838        this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
9839
9840        return this;
9841
9842    },
9843
9844    getX: function ( index ) {
9845
9846        return this.data.array[ index * this.data.stride + this.offset ];
9847
9848    },
9849
9850    getY: function ( index ) {
9851
9852        return this.data.array[ index * this.data.stride + this.offset + 1 ];
9853
9854    },
9855
9856    getZ: function ( index ) {
9857
9858        return this.data.array[ index * this.data.stride + this.offset + 2 ];
9859
9860    },
9861
9862    getW: function ( index ) {
9863
9864        return this.data.array[ index * this.data.stride + this.offset + 3 ];
9865
9866    },
9867
9868    setXY: function ( index, x, y ) {
9869
9870        index = index * this.data.stride + this.offset;
9871
9872        this.data.array[ index + 0 ] = x;
9873        this.data.array[ index + 1 ] = y;
9874
9875        return this;
9876
9877    },
9878
9879    setXYZ: function ( index, x, y, z ) {
9880
9881        index = index * this.data.stride + this.offset;
9882
9883        this.data.array[ index + 0 ] = x;
9884        this.data.array[ index + 1 ] = y;
9885        this.data.array[ index + 2 ] = z;
9886
9887        return this;
9888
9889    },
9890
9891    setXYZW: function ( index, x, y, z, w ) {
9892
9893        index = index * this.data.stride + this.offset;
9894
9895        this.data.array[ index + 0 ] = x;
9896        this.data.array[ index + 1 ] = y;
9897        this.data.array[ index + 2 ] = z;
9898        this.data.array[ index + 3 ] = w;
9899
9900        return this;
9901
9902    }
9903
9904};
9905
9906// File:src/core/Geometry.js
9907
9908/**
9909 * @author mrdoob / http://mrdoob.com/
9910 * @author kile / http://kile.stravaganza.org/
9911 * @author alteredq / http://alteredqualia.com/
9912 * @author mikael emtinger / http://gomo.se/
9913 * @author zz85 / http://www.lab4games.net/zz85/blog
9914 * @author bhouston / http://clara.io
9915 */
9916
9917THREE.Geometry = function () {
9918
9919    Object.defineProperty( this, 'id', { value: THREE.GeometryIdCount ++ } );
9920
9921    this.uuid = THREE.Math.generateUUID();
9922
9923    this.name = '';
9924    this.type = 'Geometry';
9925
9926    this.vertices = [];
9927    this.colors = [];
9928    this.faces = [];
9929    this.faceVertexUvs = [ [] ];
9930
9931    this.morphTargets = [];
9932    this.morphNormals = [];
9933
9934    this.skinWeights = [];
9935    this.skinIndices = [];
9936
9937    this.lineDistances = [];
9938
9939    this.boundingBox = null;
9940    this.boundingSphere = null;
9941
9942    // update flags
9943
9944    this.verticesNeedUpdate = false;
9945    this.elementsNeedUpdate = false;
9946    this.uvsNeedUpdate = false;
9947    this.normalsNeedUpdate = false;
9948    this.colorsNeedUpdate = false;
9949    this.lineDistancesNeedUpdate = false;
9950    this.groupsNeedUpdate = false;
9951
9952};
9953
9954THREE.Geometry.prototype = {
9955
9956    constructor: THREE.Geometry,
9957
9958    applyMatrix: function ( matrix ) {
9959
9960        var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
9961
9962        for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
9963
9964            var vertex = this.vertices[ i ];
9965            vertex.applyMatrix4( matrix );
9966
9967        }
9968
9969        for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
9970
9971            var face = this.faces[ i ];
9972            face.normal.applyMatrix3( normalMatrix ).normalize();
9973
9974            for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
9975
9976                face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
9977
9978            }
9979
9980        }
9981
9982        if ( this.boundingBox !== null ) {
9983
9984            this.computeBoundingBox();
9985
9986        }
9987
9988        if ( this.boundingSphere !== null ) {
9989
9990            this.computeBoundingSphere();
9991
9992        }
9993
9994        this.verticesNeedUpdate = true;
9995        this.normalsNeedUpdate = true;
9996
9997        return this;
9998
9999    },
10000
10001    rotateX: function () {
10002
10003        // rotate geometry around world x-axis
10004
10005        var m1;
10006
10007        return function rotateX( angle ) {
10008
10009            if ( m1 === undefined ) m1 = new THREE.Matrix4();
10010
10011            m1.makeRotationX( angle );
10012
10013            this.applyMatrix( m1 );
10014
10015            return this;
10016
10017        };
10018
10019    }(),
10020
10021    rotateY: function () {
10022
10023        // rotate geometry around world y-axis
10024
10025        var m1;
10026
10027        return function rotateY( angle ) {
10028
10029            if ( m1 === undefined ) m1 = new THREE.Matrix4();
10030
10031            m1.makeRotationY( angle );
10032
10033            this.applyMatrix( m1 );
10034
10035            return this;
10036
10037        };
10038
10039    }(),
10040
10041    rotateZ: function () {
10042
10043        // rotate geometry around world z-axis
10044
10045        var m1;
10046
10047        return function rotateZ( angle ) {
10048
10049            if ( m1 === undefined ) m1 = new THREE.Matrix4();
10050
10051            m1.makeRotationZ( angle );
10052
10053            this.applyMatrix( m1 );
10054
10055            return this;
10056
10057        };
10058
10059    }(),
10060
10061    translate: function () {
10062
10063        // translate geometry
10064
10065        var m1;
10066
10067        return function translate( x, y, z ) {
10068
10069            if ( m1 === undefined ) m1 = new THREE.Matrix4();
10070
10071            m1.makeTranslation( x, y, z );
10072
10073            this.applyMatrix( m1 );
10074
10075            return this;
10076
10077        };
10078
10079    }(),
10080
10081    scale: function () {
10082
10083        // scale geometry
10084
10085        var m1;
10086
10087        return function scale( x, y, z ) {
10088
10089            if ( m1 === undefined ) m1 = new THREE.Matrix4();
10090
10091            m1.makeScale( x, y, z );
10092
10093            this.applyMatrix( m1 );
10094
10095            return this;
10096
10097        };
10098
10099    }(),
10100
10101    lookAt: function () {
10102
10103        var obj;
10104
10105        return function lookAt( vector ) {
10106
10107            if ( obj === undefined ) obj = new THREE.Object3D();
10108
10109            obj.lookAt( vector );
10110
10111            obj.updateMatrix();
10112
10113            this.applyMatrix( obj.matrix );
10114
10115        };
10116
10117    }(),
10118
10119    fromBufferGeometry: function ( geometry ) {
10120
10121        var scope = this;
10122
10123        var indices = geometry.index !== null ? geometry.index.array : undefined;
10124        var attributes = geometry.attributes;
10125
10126        var positions = attributes.position.array;
10127        var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
10128        var colors = attributes.color !== undefined ? attributes.color.array : undefined;
10129        var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
10130        var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
10131
10132        if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
10133
10134        var tempNormals = [];
10135        var tempUVs = [];
10136        var tempUVs2 = [];
10137
10138        for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) {
10139
10140            scope.vertices.push( new THREE.Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) );
10141
10142            if ( normals !== undefined ) {
10143
10144                tempNormals.push( new THREE.Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) );
10145
10146            }
10147
10148            if ( colors !== undefined ) {
10149
10150                scope.colors.push( new THREE.Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) );
10151
10152            }
10153
10154            if ( uvs !== undefined ) {
10155
10156                tempUVs.push( new THREE.Vector2( uvs[ j ], uvs[ j + 1 ] ) );
10157
10158            }
10159
10160            if ( uvs2 !== undefined ) {
10161
10162                tempUVs2.push( new THREE.Vector2( uvs2[ j ], uvs2[ j + 1 ] ) );
10163
10164            }
10165
10166        }
10167
10168        function addFace( a, b, c, materialIndex ) {
10169
10170            var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].
10170clone(), tempNormals[ c ].clone() ] : [];
10171            var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : [];
10172
10173            var face = new THREE.Face3( a, b, c, vertexNormals, vertexColors, materialIndex );
10174
10175            scope.faces.push( face );
10176
10177            if ( uvs !== undefined ) {
10178
10179                scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] );
10180
10181            }
10182
10183            if ( uvs2 !== undefined ) {
10184
10185                scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] );
10186
10187            }
10188
10189        }
10190
10191        if ( indices !== undefined ) {
10192
10193            var groups = geometry.groups;
10194
10195            if ( groups.length > 0 ) {
10196
10197                for ( var i = 0; i < groups.length; i ++ ) {
10198
10199                    var group = groups[ i ];
10200
10201                    var start = group.start;
10202                    var count = group.count;
10203
10204                    for ( var j = start, jl = start + count; j < jl; j += 3 ) {
10205
10206                        addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex  );
10207
10208                    }
10209
10210                }
10211
10212            } else {
10213
10214                for ( var i = 0; i < indices.length; i += 3 ) {
10215
10216                    addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
10217
10218                }
10219
10220            }
10221
10222        } else {
10223
10224            for ( var i = 0; i < positions.length / 3; i += 3 ) {
10225
10226                addFace( i, i + 1, i + 2 );
10227
10228            }
10229
10230        }
10231
10232        this.computeFaceNormals();
10233
10234        if ( geometry.boundingBox !== null ) {
10235
10236            this.boundingBox = geometry.boundingBox.clone();
10237
10238        }
10239
10240        if ( geometry.boundingSphere !== null ) {
10241
10242            this.boundingSphere = geometry.boundingSphere.clone();
10243
10244        }
10245
10246        return this;
10247
10248    },
10249
10250    center: function () {
10251
10252        this.computeBoundingBox();
10253
10254        var offset = this.boundingBox.center().negate();
10255
10256        this.translate( offset.x, offset.y, offset.z );
10257
10258        return offset;
10259
10260    },
10261
10262    normalize: function () {
10263
10264        this.computeBoundingSphere();
10265
10266        var center = this.boundingSphere.center;
10267        var radius = this.boundingSphere.radius;
10268
10269        var s = radius === 0 ? 1 : 1.0 / radius;
10270
10271        var matrix = new THREE.Matrix4();
10272        matrix.set(
10273            s, 0, 0, - s * center.x,
10274            0, s, 0, - s * center.y,
10275            0, 0, s, - s * center.z,
10276            0, 0, 0, 1
10277        );
10278
10279        this.applyMatrix( matrix );
10280
10281        return this;
10282
10283    },
10284
10285    computeFaceNormals: function () {
10286
10287        var cb = new THREE.Vector3(), ab = new THREE.Vector3();
10288
10289        for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
10290
10291            var face = this.faces[ f ];
10292
10293            var vA = this.vertices[ face.a ];
10294            var vB = this.vertices[ face.b ];
10295            var vC = this.vertices[ face.c ];
10296
10297            cb.subVectors( vC, vB );
10298            ab.subVectors( vA, vB );
10299            cb.cross( ab );
10300
10301            cb.normalize();
10302
10303            face.normal.copy( cb );
10304
10305        }
10306
10307    },
10308
10309    computeVertexNormals: function ( areaWeighted ) {
10310
10311        if ( areaWeighted === undefined ) areaWeighted = true;
10312
10313        var v, vl, f, fl, face, vertices;
10314
10315        vertices = new Array( this.vertices.length );
10316
10317        for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
10318
10319            vertices[ v ] = new THREE.Vector3();
10320
10321        }
10322
10323        if ( areaWeighted ) {
10324
10325            // vertex normals weighted by triangle areas
10326            // http://www.iquilezles.org/www/articles/normals/normals.htm
10327
10328            var vA, vB, vC;
10329            var cb = new THREE.Vector3(), ab = new THREE.Vector3();
10330
10331            for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
10332
10333                face = this.faces[ f ];
10334
10335                vA = this.vertices[ face.a ];
10336                vB = this.vertices[ face.b ];
10337                vC = this.vertices[ face.c ];
10338
10339                cb.subVectors( vC, vB );
10340                ab.subVectors( vA, vB );
10341                cb.cross( ab );
10342
10343                vertices[ face.a ].add( cb );
10344                vertices[ face.b ].add( cb );
10345                vertices[ face.c ].add( cb );
10346
10347            }
10348
10349        } else {
10350
10351            for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
10352
10353                face = this.faces[ f ];
10354
10355                vertices[ face.a ].add( face.normal );
10356                vertices[ face.b ].add( face.normal );
10357                vertices[ face.c ].add( face.normal );
10358
10359            }
10360
10361        }
10362
10363        for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
10364
10365            vertices[ v ].normalize();
10366
10367        }
10368
10369        for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
10370
10371            face = this.faces[ f ];
10372
10373            var vertexNormals = face.vertexNormals;
10374
10375            if ( vertexNormals.length === 3 ) {
10376
10377                vertexNormals[ 0 ].copy( vertices[ face.a ] );
10378                vertexNormals[ 1 ].copy( vertices[ face.b ] );
10379                vertexNormals[ 2 ].copy( vertices[ face.c ] );
10380
10381            } else {
10382
10383                vertexNormals[ 0 ] = vertices[ face.a ].clone();
10384                vertexNormals[ 1 ] = vertices[ face.b ].clone();
10385                vertexNormals[ 2 ] = vertices[ face.c ].clone();
10386
10387            }
10388
10389        }
10390
10391        if ( this.faces.length > 0 ) {
10392
10393            this.normalsNeedUpdate = true;
10394
10395        }
10396
10397    },
10398
10399    computeMorphNormals: function () {
10400
10401        var i, il, f, fl, face;
10402
10403        // save original normals
10404        // - create temp variables on first access
10405        //   otherwise just copy (for faster repeated calls)
10406
10407        for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
10408
10409            face = this.faces[ f ];
10410
10411            if ( ! face.__originalFaceNormal ) {
10412
10413                face.__originalFaceNormal = face.normal.clone();
10414
10415            } else {
10416
10417                face.__originalFaceNormal.copy( face.normal );
10418
10419            }
10420
10421            if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
10422
10423            for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
10424
10425                if ( ! face.__originalVertexNormals[ i ] ) {
10426
10427                    face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
10428
10429                } else {
10430
10431                    face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
10432
10433                }
10434
10435            }
10436
10437        }
10438
10439        // use temp geometry to compute face and vertex normals for each morph
10440
10441        var tmpGeo = new THREE.Geometry();
10442        tmpGeo.faces = this.faces;
10443
10444        for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
10445
10446            // create on first access
10447
10448            if ( ! this.morphNormals[ i ] ) {
10449
10450                this.morphNormals[ i ] = {};
10451                this.morphNormals[ i ].faceNormals = [];
10452                this.morphNormals[ i ].vertexNormals = [];
10453
10454                var dstNormalsFace = this.morphNormals[ i ].faceNormals;
10455                var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
10456
10457                var faceNormal, vertexNormals;
10458
10459                for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
10460
10461                    faceNormal = new THREE.Vector3();
10462                    vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
10463
10464                    dstNormalsFace.push( faceNormal );
10465                    dstNormalsVertex.push( vertexNormals );
10466
10467                }
10468
10469            }
10470
10471            var morphNormals = this.morphNormals[ i ];
10472
10473            // set vertices to morph target
10474
10475            tmpGeo.vertices = this.morphTargets[ i ].vertices;
10476
10477            // compute morph normals
10478
10479            tmpGeo.computeFaceNormals();
10480            tmpGeo.computeVertexNormals();
10481
10482            // store morph normals
10483
10484            var faceNormal, vertexNormals;
10485
10486            for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
10487
10488                face = this.faces[ f ];
10489
10490                faceNormal = morphNormals.faceNormals[ f ];
10491                vertexNormals = morphNormals.vertexNormals[ f ];
10492
10493                faceNormal.copy( face.normal );
10494
10495                vertexNormals.a.copy( face.vertexNormals[ 0 ] );
10496                vertexNormals.b.copy( face.vertexNormals[ 1 ] );
10497                vertexNormals.c.copy( face.vertexNormals[ 2 ] );
10498
10499            }
10500
10501        }
10502
10503        // restore original normals
10504
10505        for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
10506
10507            face = this.faces[ f ];
10508
10509            face.normal = face.__originalFaceNormal;
10510            face.vertexNormals = face.__originalVertexNormals;
10511
10512        }
10513
10514    },
10515
10516    computeTangents: function () {
10517
10518        console.warn( 'THREE.Geometry: .computeTangents() has been removed.' );
10519
10520    },
10521
10522    computeLineDistances: function () {
10523
10524        var d = 0;
10525        var vertices = this.vertices;
10526
10527        for ( var i = 0, il = vertices.length; i < il; i ++ ) {
10528
10529            if ( i > 0 ) {
10530
10531                d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
10532
10533            }
10534
10535            this.lineDistances[ i ] = d;
10536
10537        }
10538
10539    },
10540
10541    computeBoundingBox: function () {
10542
10543        if ( this.boundingBox === null ) {
10544
10545            this.boundingBox = new THREE.Box3();
10546
10547        }
10548
10549        this.boundingBox.setFromPoints( this.vertices );
10550
10551    },
10552
10553    computeBoundingSphere: function () {
10554
10555        if ( this.boundingSphere === null ) {
10556
10557            this.boundingSphere = new THREE.Sphere();
10558
10559        }
10560
10561        this.boundingSphere.setFromPoints( this.vertices );
10562
10563    },
10564
10565    merge: function ( geometry, matrix, materialIndexOffset ) {
10566
10567        if ( geometry instanceof THREE.Geometry === false ) {
10568
10569            console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
10570            return;
10571
10572        }
10573
10574        var normalMatrix,
10575            vertexOffset = this.vertices.length,
10576            vertices1 = this.vertices,
10577            vertices2 = geometry.vertices,
10578            faces1 = this.faces,
10579            faces2 = geometry.faces,
10580            uvs1 = this.faceVertexUvs[ 0 ],
10581            uvs2 = geometry.faceVertexUvs[ 0 ];
10582
10583        if ( materialIndexOffset === undefined ) materialIndexOffset = 0;
10584
10585        if ( matrix !== undefined ) {
10586
10587            normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
10588
10589        }
10590
10591        // vertices
10592
10593        for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
10594
10595            var vertex = vertices2[ i ];
10596
10597            var vertexCopy = vertex.clone();
10598
10599            if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
10600
10601            vertices1.push( vertexCopy );
10602
10603        }
10604
10605        // faces
10606
10607        for ( i = 0, il = faces2.length; i < il; i ++ ) {
10608
10609            var face = faces2[ i ], faceCopy, normal, color,
10610                faceVertexNormals = face.vertexNormals,
10611                faceVertexColors = face.vertexColors;
10612
10613            faceCopy = new THREE.Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
10614            faceCopy.normal.copy( face.normal );
10615
10616            if ( normalMatrix !== undefined ) {
10617
10618                faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
10619
10620            }
10621
10622            for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
10623
10624                normal = faceVertexNormals[ j ].clone();
10625
10626                if ( normalMatrix !== undefined ) {
10627
10628                    normal.applyMatrix3( normalMatrix ).normalize();
10629
10630                }
10631
10632                faceCopy.vertexNormals.push( normal );
10633
10634            }
10635
10636            faceCopy.color.copy( face.color );
10637
10638            for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
10639
10640                color = faceVertexColors[ j ];
10641                faceCopy.vertexColors.push( color.clone() );
10642
10643            }
10644
10645            faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
10646
10647            faces1.push( faceCopy );
10648
10649        }
10650
10651        // uvs
10652
10653        for ( i = 0, il = uvs2.length; i < il; i ++ ) {
10654
10655            var uv = uvs2[ i ], uvCopy = [];
10656
10657            if ( uv === undefined ) {
10658
10659                continue;
10660
10661            }
10662
10663            for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
10664
10665                uvCopy.push( uv[ j ].clone() );
10666
10667            }
10668
10669            uvs1.push( uvCopy );
10670
10671        }
10672
10673    },
10674
10675    mergeMesh: function ( mesh ) {
10676
10677        if ( mesh instanceof THREE.Mesh === false ) {
10678
10679            console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
10680            return;
10681
10682        }
10683
10684        mesh.matrixAutoUpdate && mesh.updateMatrix();
10685
10686        this.merge( mesh.geometry, mesh.matrix );
10687
10688    },
10689
10690    /*
10691     * Checks for duplicate vertices with hashmap.
10692     * Duplicated vertices are removed
10693     * and faces' vertices are updated.
10694     */
10695
10696    mergeVertices: function () {
10697
10698        var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
10699        var unique = [], changes = [];
10700
10701        var v, key;
10702        var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001
10703        var precision = Math.pow( 10, precisionPoints );
10704        var i, il, face;
10705        var indices, j, jl;
10706
10707        for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
10708
10709            v = this.vertices[ i ];
10710            key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
10711
10712            if ( verticesMap[ key ] === undefined ) {
10713
10714                verticesMap[ key ] = i;
10715                unique.push( this.vertices[ i ] );
10716                changes[ i ] = unique.length - 1;
10717
10718            } else {
10719
10720                //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
10721                changes[ i ] = changes[ verticesMap[ key ] ];
10722
10723            }
10724
10725        }
10726
10727
10728        // if faces are completely degenerate after merging vertices, we
10729        // have to remove them from the geometry.
10730        var faceIndicesToRemove = [];
10731
10732        for ( i = 0, il = this.faces.length; i < il; i ++ ) {
10733
10734            face = this.faces[ i ];
10735
10736            face.a = changes[ face.a ];
10737            face.b = changes[ face.b ];
10738            face.c = changes[ face.c ];
10739
10740            indices = [ face.a, face.b, face.c ];
10741
10742            var dupIndex = - 1;
10743
10744            // if any duplicate vertices are found in a Face3
10745            // we have to remove the face as nothing can be saved
10746            for ( var n = 0; n < 3; n ++ ) {
10747
10748                if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
10749
10750                    dupIndex = n;
10751                    faceIndicesToRemove.push( i );
10752                    break;
10753
10754                }
10755
10756            }
10757
10758        }
10759
10760        for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
10761
10762            var idx = faceIndicesToRemove[ i ];
10763
10764            this.faces.splice( idx, 1 );
10765
10766            for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
10767
10768                this.faceVertexUvs[ j ].splice( idx, 1 );
10769
10770            }
10771
10772        }
10773
10774        // Use unique set of vertices
10775
10776        var diff = this.vertices.length - unique.length;
10777        this.vertices = unique;
10778        return diff;
10779
10780    },
10781
10782    sortFacesByMaterialIndex: function () {
10783
10784        var faces = this.faces;
10785        var length = faces.length;
10786
10787        // tag faces
10788
10789        for ( var i = 0; i < length; i ++ ) {
10790
10791            faces[ i ]._id = i;
10792
10793        }
10794
10795        // sort faces
10796
10797        function materialIndexSort( a, b ) {
10798
10799            return a.materialIndex - b.materialIndex;
10800
10801        }
10802
10803        faces.sort( materialIndexSort );
10804
10805        // sort uvs
10806
10807        var uvs1 = this.faceVertexUvs[ 0 ];
10808        var uvs2 = this.faceVertexUvs[ 1 ];
10809
10810        var newUvs1, newUvs2;
10811
10812        if ( uvs1 && uvs1.length === length ) newUvs1 = [];
10813        if ( uvs2 && uvs2.length === length ) newUvs2 = [];
10814
10815        for ( var i = 0; i < length; i ++ ) {
10816
10817            var id = faces[ i ]._id;
10818
10819            if ( newUvs1 ) newUvs1.push( uvs1[ id ] );
10820            if ( newUvs2 ) newUvs2.push( uvs2[ id ] );
10821
10822        }
10823
10824        if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;
10825        if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;
10826
10827    },
10828
10829    toJSON: function () {
10830
10831        var data = {
10832            metadata: {
10833                version: 4.4,
10834                type: 'Geometry',
10835                generator: 'Geometry.toJSON'
10836            }
10837        };
10838
10839        // standard Geometry serialization
10840
10841        data.uuid = this.uuid;
10842        data.type = this.type;
10843        if ( this.name !== '' ) data.name = this.name;
10844
10845        if ( this.parameters !== undefined ) {
10846
10847            var parameters = this.parameters;
10848
10849            for ( var key in parameters ) {
10850
10851                if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
10852
10853            }
10854
10855            return data;
10856
10857        }
10858
10859        var vertices = [];
10860
10861        for ( var i = 0; i < this.vertices.length; i ++ ) {
10862
10863            var vertex = this.vertices[ i ];
10864            vertices.push( vertex.x, vertex.y, vertex.z );
10865
10866        }
10867
10868        var faces = [];
10869        var normals = [];
10870        var normalsHash = {};
10871        var colors = [];
10872        var colorsHash = {};
10873        var uvs = [];
10874        var uvsHash = {};
10875
10876        for ( var i = 0; i < this.faces.length; i ++ ) {
10877
10878            var face = this.faces[ i ];
10879
10880            var hasMaterial = true;
10881            var hasFaceUv = false; // deprecated
10882            var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
10883            var hasFaceNormal = face.normal.length() > 0;
10884            var hasFaceVertexNormal = face.vertexNormals.length > 0;
10885            var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
10886            var hasFaceVertexColor = face.vertexColors.length > 0;
10887
10888            var faceType = 0;
10889
10890            faceType = setBit( faceType, 0, 0 ); // isQuad
10891            faceType = setBit( faceType, 1, hasMaterial );
10892            faceType = setBit( faceType, 2, hasFaceUv );
10893            faceType = setBit( faceType, 3, hasFaceVertexUv );
10894            faceType = setBit( faceType, 4, hasFaceNormal );
10895            faceType = setBit( faceType, 5, hasFaceVertexNormal );
10896            faceType = setBit( faceType, 6, hasFaceColor );
10897            faceType = setBit( faceType, 7, hasFaceVertexColor );
10898
10899            faces.push( faceType );
10900            faces.push( face.a, face.b, face.c );
10901            faces.push( face.materialIndex );
10902
10903            if ( hasFaceVertexUv ) {
10904
10905                var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
10906
10907                faces.push(
10908                    getUvIndex( faceVertexUvs[ 0 ] ),
10909                    getUvIndex( faceVertexUvs[ 1 ] ),
10910                    getUvIndex( faceVertexUvs[ 2 ] )
10911                );
10912
10913            }
10914
10915            if ( hasFaceNormal ) {
10916
10917                faces.push( getNormalIndex( face.normal ) );
10918
10919            }
10920
10921            if ( hasFaceVertexNormal ) {
10922
10923                var vertexNormals = face.vertexNormals;
10924
10925                faces.push(
10926                    getNormalIndex( vertexNormals[ 0 ] ),
10927                    getNormalIndex( vertexNormals[ 1 ] ),
10928                    getNormalIndex( vertexNormals[ 2 ] )
10929                );
10930
10931            }
10932
10933            if ( hasFaceColor ) {
10934
10935                faces.push( getColorIndex( face.color ) );
10936
10937            }
10938
10939            if ( hasFaceVertexColor ) {
10940
10941                var vertexColors = face.vertexColors;
10942
10943                faces.push(
10944                    getColorIndex( vertexColors[ 0 ] ),
10945                    getColorIndex( vertexColors[ 1 ] ),
10946                    getColorIndex( vertexColors[ 2 ] )
10947                );
10948
10949            }
10950
10951        }
10952
10953        function setBit( value, position, enabled ) {
10954
10955            return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
10956
10957        }
10958
10959        function getNormalIndex( normal ) {
10960
10961            var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
10962
10963            if ( normalsHash[ hash ] !== undefined ) {
10964
10965                return normalsHash[ hash ];
10966
10967            }
10968
10969            normalsHash[ hash ] = normals.length / 3;
10970            normals.push( normal.x, normal.y, normal.z );
10971
10972            return normalsHash[ hash ];
10973
10974        }
10975
10976        function getColorIndex( color ) {
10977
10978            var hash = color.r.toString() + color.g.toString() + color.b.toString();
10979
10980            if ( colorsHash[ hash ] !== undefined ) {
10981
10982                return colorsHash[ hash ];
10983
10984            }
10985
10986            colorsHash[ hash ] = colors.length;
10987            colors.push( color.getHex() );
10988
10989            return colorsHash[ hash ];
10990
10991        }
10992
10993        function getUvIndex( uv ) {
10994
10995            var hash = uv.x.toString() + uv.y.toString();
10996
10997            if ( uvsHash[ hash ] !== undefined ) {
10998
10999                return uvsHash[ hash ];
11000
11001            }
11002
11003            uvsHash[ hash ] = uvs.length / 2;
11004            uvs.push( uv.x, uv.y );
11005
11006            return uvsHash[ hash ];
11007
11008        }
11009
11010        data.data = {};
11011
11012        data.data.vertices = vertices;
11013        data.data.normals = normals;
11014        if ( colors.length > 0 ) data.data.colors = colors;
11015        if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
11016        data.data.faces = faces;
11017
11018        return data;
11019
11020    },
11021
11022    clone: function () {
11023
11024        /*
11025         // Handle primitives
11026
11027         var parameters = this.parameters;
11028
11029         if ( parameters !== undefined ) {
11030
11031         var values = [];
11032
11033         for ( var key in parameters ) {
11034
11035         values.push( parameters[ key ] );
11036
11037         }
11038
11039         var geometry = Object.create( this.constructor.prototype );
11040         this.constructor.apply( geometry, values );
11041         return geometry;
11042
11043         }
11044
11045         return new this.constructor().copy( this );
11046         */
11047
11048        return new THREE.Geometry().copy( this );
11049
11050    },
11051
11052    copy: function ( source ) {
11053
11054        this.vertices = [];
11055        this.faces = [];
11056        this.faceVertexUvs = [ [] ];
11057
11058        var vertices = source.vertices;
11059
11060        for ( var i = 0, il = vertices.length; i < il; i ++ ) {
11061
11062            this.vertices.push( vertices[ i ].clone() );
11063
11064        }
11065
11066        var faces = source.faces;
11067
11068        for ( var i = 0, il = faces.length; i < il; i ++ ) {
11069
11070            this.faces.push( faces[ i ].clone() );
11071
11072        }
11073
11074        for ( var i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
11075
11076            var faceVertexUvs = source.faceVertexUvs[ i ];
11077
11078            if ( this.faceVertexUvs[ i ] === undefined ) {
11079
11080                this.faceVertexUvs[ i ] = [];
11081
11082            }
11083
11084            for ( var j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
11085
11086                var uvs = faceVertexUvs[ j ], uvsCopy = [];
11087
11088                for ( var k = 0, kl = uvs.length; k < kl; k ++ ) {
11089
11090                    var uv = uvs[ k ];
11091
11092                    uvsCopy.push( uv.clone() );
11093
11094                }
11095
11096                this.faceVertexUvs[ i ].push( uvsCopy );
11097
11098            }
11099
11100        }
11101
11102        return this;
11103
11104    },
11105
11106    dispose: function () {
11107
11108        this.dispatchEvent( { type: 'dispose' } );
11109
11110    }
11111
11112};
11113
11114THREE.EventDispatcher.prototype.apply( THREE.Geometry.prototype );
11115
11116THREE.GeometryIdCount = 0;
11117
11118// File:src/core/DirectGeometry.js
11119
11120/**
11121 * @author mrdoob / http://mrdoob.com/
11122 */
11123
11124THREE.DirectGeometry = function () {
11125
11126    Object.defineProperty( this, 'id', { value: THREE.GeometryIdCount ++ } );
11127
11128    this.uuid = THREE.Math.generateUUID();
11129
11130    this.name = '';
11131    this.type = 'DirectGeometry';
11132
11133    this.indices = [];
11134    this.vertices = [];
11135    this.normals = [];
11136    this.colors = [];
11137    this.uvs = [];
11138    this.uvs2 = [];
11139
11140    this.groups = [];
11141
11142    this.morphTargets = {};
11143
11144    this.skinWeights = [];
11145    this.skinIndices = [];
11146
11147    // this.lineDistances = [];
11148
11149    this.boundingBox = null;
11150    this.boundingSphere = null;
11151
11152    // update flags
11153
11154    this.verticesNeedUpdate = false;
11155    this.normalsNeedUpdate = false;
11156    this.colorsNeedUpdate = false;
11157    this.uvsNeedUpdate = false;
11158    this.groupsNeedUpdate = false;
11159
11160};
11161
11162THREE.DirectGeometry.prototype = {
11163
11164    constructor: THREE.DirectGeometry,
11165
11166    computeBoundingBox: THREE.Geometry.prototype.computeBoundingBox,
11167    computeBoundingSphere: THREE.Geometry.prototype.computeBoundingSphere,
11168
11169    computeFaceNormals: function () {
11170
11171        console.warn( 'THREE.DirectGeometry: computeFaceNormals() is not a method of this type of geometry.' );
11172
11173    },
11174
11175    computeVertexNormals: function () {
11176
11177        console.warn( 'THREE.DirectGeometry: computeVertexNormals() is not a method of this type of geometry.' );
11178
11179    },
11180
11181    computeGroups: function ( geometry ) {
11182
11183        var group;
11184        var groups = [];
11185        var materialIndex;
11186
11187        var faces = geometry.faces;
11188
11189        for ( var i = 0; i < faces.length; i ++ ) {
11190
11191            var face = faces[ i ];
11192
11193            // materials
11194
11195            if ( face.materialIndex !== materialIndex ) {
11196
11197                materialIndex = face.materialIndex;
11198
11199                if ( group !== undefined ) {
11200
11201                    group.count = ( i * 3 ) - group.start;
11202                    groups.push( group );
11203
11204                }
11205
11206                group = {
11207                    start: i * 3,
11208                    materialIndex: materialIndex
11209                };
11210
11211            }
11212
11213        }
11214
11215        if ( group !== undefined ) {
11216
11217            group.count = ( i * 3 ) - group.start;
11218            groups.push( group );
11219
11220        }
11221
11222        this.groups = groups;
11223
11224    },
11225
11226    fromGeometry: function ( geometry ) {
11227
11228        var faces = geometry.faces;
11229        var vertices = geometry.vertices;
11230        var faceVertexUvs = geometry.faceVertexUvs;
11231
11232        var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
11233        var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
11234
11235        // morphs
11236
11237        var morphTargets = geometry.morphTargets;
11238        var morphTargetsLength = morphTargets.length;
11239
11240        var morphTargetsPosition;
11241
11242        if ( morphTargetsLength > 0 ) {
11243
11244            morphTargetsPosition = [];
11245
11246            for ( var i = 0; i < morphTargetsLength; i ++ ) {
11247
11248                morphTargetsPosition[ i ] = [];
11249
11250            }
11251
11252            this.morphTargets.position = morphTargetsPosition;
11253
11254        }
11255
11256        var morphNormals = geometry.morphNormals;
11257        var morphNormalsLength = morphNormals.length;
11258
11259        var morphTargetsNormal;
11260
11261        if ( morphNormalsLength > 0 ) {
11262
11263            morphTargetsNormal = [];
11264
11265            for ( var i = 0; i < morphNormalsLength; i ++ ) {
11266
11267                morphTargetsNormal[ i ] = [];
11268
11269            }
11270
11271            this.morphTargets.normal = morphTargetsNormal;
11272
11273        }
11274
11275        // skins
11276
11277        var skinIndices = geometry.skinIndices;
11278        var skinWeights = geometry.skinWeights;
11279
11280        var hasSkinIndices = skinIndices.length === vertices.length;
11281        var hasSkinWeights = skinWeights.length === vertices.length;
11282
11283        //
11284
11285        for ( var i = 0; i < faces.length; i ++ ) {
11286
11287            var face = faces[ i ];
11288
11289            this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
11290
11291            var vertexNormals = face.vertexNormals;
11292
11293            if ( vertexNormals.length === 3 ) {
11294
11295                this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
11296
11297            } else {
11298
11299                var normal = face.normal;
11300
11301                this.normals.push( normal, normal, normal );
11302
11303            }
11304
11305            var vertexColors = face.vertexColors;
11306
11307            if ( vertexColors.length === 3 ) {
11308
11309                this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
11310
11311            } else {
11312
11313                var color = face.color;
11314
11315                this.colors.push( color, color, color );
11316
11317            }
11318
11319            if ( hasFaceVertexUv === true ) {
11320
11321                var vertexUvs = faceVertexUvs[ 0 ][ i ];
11322
11323                if ( vertexUvs !== undefined ) {
11324
11325                    this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
11326
11327                } else {
11328
11329                    console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
11330
11331                    this.uvs.push( new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() );
11332
11333                }
11334
11335            }
11336
11337            if ( hasFaceVertexUv2 === true ) {
11338
11339                var vertexUvs = faceVertexUvs[ 1 ][ i ];
11340
11341                if ( vertexUvs !== undefined ) {
11342
11343                    this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
11344
11345                } else {
11346
11347                    console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
11348
11349                    this.uvs2.push( new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() );
11350
11351                }
11352
11353            }
11354
11355            // morphs
11356
11357            for ( var j = 0; j < morphTargetsLength; j ++ ) {
11358
11359                var morphTarget = morphTargets[ j ].vertices;
11360
11361                morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
11362
11363            }
11364
11365            for ( var j = 0; j < morphNormalsLength; j ++ ) {
11366
11367                var morphNormal = morphNormals[ j ].vertexNormals[ i ];
11368
11369                morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c );
11370
11371            }
11372
11373            // skins
11374
11375            if ( hasSkinIndices ) {
11376
11377                this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
11378
11379            }
11380
11381            if ( hasSkinWeights ) {
11382
11383                this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
11384
11385            }
11386
11387        }
11388
11389        this.computeGroups( geometry );
11390
11391        this.verticesNeedUpdate = geometry.verticesNeedUpdate;
11392        this.normalsNeedUpdate = geometry.normalsNeedUpdate;
11393        this.colorsNeedUpdate = geometry.colorsNeedUpdate;
11394        this.uvsNeedUpdate = geometry.uvsNeedUpdate;
11395        this.groupsNeedUpdate = geometry.groupsNeedUpdate;
11396
11397        return this;
11398
11399    },
11400
11401    dispose: function () {
11402
11403        this.dispatchEvent( { type: 'dispose' } );
11404
11405    }
11406
11407};
11408
11409THREE.EventDispatcher.prototype.apply( THREE.DirectGeometry.prototype );
11410
11411// File:src/core/BufferGeometry.js
11412
11413/**
11414 * @author alteredq / http://alteredqualia.com/
11415 * @author mrdoob / http://mrdoob.com/
11416 */
11417
11418THREE.BufferGeometry = function () {
11419
11420    Object.defineProperty( this, 'id', { value: THREE.GeometryIdCount ++ } );
11421
11422    this.uuid = THREE.Math.generateUUID();
11423
11424    this.name = '';
11425    this.type = 'BufferGeometry';
11426
11427    this.index = null;
11428    this.attributes = {};
11429
11430    this.morphAttributes = {};
11431
11432    this.groups = [];
11433
11434    this.boundingBox = null;
11435    this.boundingSphere = null;
11436
11437    this.drawRange = { start: 0, count: Infinity };
11438
11439};
11440
11441THREE.BufferGeometry.prototype = {
11442
11443    constructor: THREE.BufferGeometry,
11444
11445    getIndex: function () {
11446
11447        return this.index;
11448
11449    },
11450
11451    setIndex: function ( index ) {
11452
11453        this.index = index;
11454
11455    },
11456
11457    addAttribute: function ( name, attribute ) {
11458
11459        if ( attribute instanceof THREE.BufferAttribute === false && attribute instanceof THREE.InterleavedBufferAttribute === false ) {
11460
11461            console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
11462
11463            this.addAttribute( name, new THREE.BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
11464
11465            return;
11466
11467        }
11468
11469        if ( name === 'index' ) {
11470
11471            console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
11472            this.setIndex( attribute );
11473
11474            return;
11475
11476        }
11477
11478        this.attributes[ name ] = attribute;
11479
11480        return this;
11481
11482    },
11483
11484    getAttribute: function ( name ) {
11485
11486        return this.attributes[ name ];
11487
11488    },
11489
11490    removeAttribute: function ( name ) {
11491
11492        delete this.attributes[ name ];
11493
11494        return this;
11495
11496    },
11497
11498    addGroup: function ( start, count, materialIndex ) {
11499
11500        this.groups.push( {
11501
11502            start: start,
11503            count: count,
11504            materialIndex: materialIndex !== undefined ? materialIndex : 0
11505
11506        } );
11507
11508    },
11509
11510    clearGroups: function () {
11511
11512        this.groups = [];
11513
11514    },
11515
11516    setDrawRange: function ( start, count ) {
11517
11518        this.drawRange.start = start;
11519        this.drawRange.count = count;
11520
11521    },
11522
11523    applyMatrix: function ( matrix ) {
11524
11525        var position = this.attributes.position;
11526
11527        if ( position !== undefined ) {
11528
11529            matrix.applyToVector3Array( position.array );
11530            position.needsUpdate = true;
11531
11532        }
11533
11534        var normal = this.attributes.normal;
11535
11536        if ( normal !== undefined ) {
11537
11538            var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
11539
11540            normalMatrix.applyToVector3Array( normal.array );
11541            normal.needsUpdate = true;
11542
11543        }
11544
11545        if ( this.boundingBox !== null ) {
11546
11547            this.computeBoundingBox();
11548
11549        }
11550
11551        if ( this.boundingSphere !== null ) {
11552
11553            this.computeBoundingSphere();
11554
11555        }
11556
11557        return this;
11558
11559    },
11560
11561    rotateX: function () {
11562
11563        // rotate geometry around world x-axis
11564
11565        var m1;
11566
11567        return function rotateX( angle ) {
11568
11569            if ( m1 === undefined ) m1 = new THREE.Matrix4();
11570
11571            m1.makeRotationX( angle );
11572
11573            this.applyMatrix( m1 );
11574
11575            return this;
11576
11577        };
11578
11579    }(),
11580
11581    rotateY: function () {
11582
11583        // rotate geometry around world y-axis
11584
11585        var m1;
11586
11587        return function rotateY( angle ) {
11588
11589            if ( m1 === undefined ) m1 = new THREE.Matrix4();
11590
11591            m1.makeRotationY( angle );
11592
11593            this.applyMatrix( m1 );
11594
11595            return this;
11596
11597        };
11598
11599    }(),
11600
11601    rotateZ: function () {
11602
11603        // rotate geometry around world z-axis
11604
11605        var m1;
11606
11607        return function rotateZ( angle ) {
11608
11609            if ( m1 === undefined ) m1 = new THREE.Matrix4();
11610
11611            m1.makeRotationZ( angle );
11612
11613            this.applyMatrix( m1 );
11614
11615            return this;
11616
11617        };
11618
11619    }(),
11620
11621    translate: function () {
11622
11623        // translate geometry
11624
11625        var m1;
11626
11627        return function translate( x, y, z ) {
11628
11629            if ( m1 === undefined ) m1 = new THREE.Matrix4();
11630
11631            m1.makeTranslation( x, y, z );
11632
11633            this.applyMatrix( m1 );
11634
11635            return this;
11636
11637        };
11638
11639    }(),
11640
11641    scale: function () {
11642
11643        // scale geometry
11644
11645        var m1;
11646
11647        return function scale( x, y, z ) {
11648
11649            if ( m1 === undefined ) m1 = new THREE.Matrix4();
11650
11651            m1.makeScale( x, y, z );
11652
11653            this.applyMatrix( m1 );
11654
11655            return this;
11656
11657        };
11658
11659    }(),
11660
11661    lookAt: function () {
11662
11663        var obj;
11664
11665        return function lookAt( vector ) {
11666
11667            if ( obj === undefined ) obj = new THREE.Object3D();
11668
11669            obj.lookAt( vector );
11670
11671            obj.updateMatrix();
11672
11673            this.applyMatrix( obj.matrix );
11674
11675        };
11676
11677    }(),
11678
11679    center: function () {
11680
11681        this.computeBoundingBox();
11682
11683        var offset = this.boundingBox.center().negate();
11684
11685        this.translate( offset.x, offset.y, offset.z );
11686
11687        return offset;
11688
11689    },
11690
11691    setFromObject: function ( object ) {
11692
11693        // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
11694
11695        var geometry = object.geometry;
11696
11697        if ( object instanceof THREE.Points || object instanceof THREE.Line ) {
11698
11699            var positions = new THREE.Float32Attribute( geometry.vertices.length * 3, 3 );
11700            var colors = new THREE.Float32Attribute( geometry.colors.length * 3, 3 );
11701
11702            this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
11703            this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
11704
11705            if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
11706
11707                var lineDistances = new THREE.Float32Attribute( geometry.lineDistances.length, 1 );
11708
11709                this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
11710
11711            }
11712
11713            if ( geometry.boundingSphere !== null ) {
11714
11715                this.boundingSphere = geometry.boundingSphere.clone();
11716
11717            }
11718
11719            if ( geometry.boundingBox !== null ) {
11720
11721                this.boundingBox = geometry.boundingBox.clone();
11722
11723            }
11724
11725        } else if ( object instanceof THREE.Mesh ) {
11726
11727            if ( geometry instanceof THREE.Geometry ) {
11728
11729                this.fromGeometry( geometry );
11730
11731            }
11732
11733        }
11734
11735        return this;
11736
11737    },
11738
11739    updateFromObject: function ( object ) {
11740
11741        var geometry = object.geometry;
11742
11743        if ( object instanceof THREE.Mesh ) {
11744
11745            var direct = geometry.__directGeometry;
11746
11747            if ( direct === undefined ) {
11748
11749                return this.fromGeometry( geometry );
11750
11751            }
11752
11753            direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
11754            direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
11755            direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
11756            direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
11757            direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
11758
11759            geometry.verticesNeedUpdate = false;
11760            geometry.normalsNeedUpdate = false;
11761            geometry.colorsNeedUpdate = false;
11762            geometry.uvsNeedUpdate = false;
11763            geometry.groupsNeedUpdate = false;
11764
11765            geometry = direct;
11766
11767        }
11768
11769        if ( geometry.verticesNeedUpdate === true ) {
11770
11771            var attribute = this.attributes.position;
11772
11773            if ( attribute !== undefined ) {
11774
11775                attribute.copyVector3sArray( geometry.vertices );
11776                attribute.needsUpdate = true;
11777
11778            }
11779
11780            geometry.verticesNeedUpdate = false;
11781
11782        }
11783
11784        if ( geometry.normalsNeedUpdate === true ) {
11785
11786            var attribute = this.attributes.normal;
11787
11788            if ( attribute !== undefined ) {
11789
11790                attribute.copyVector3sArray( geometry.normals );
11791                attribute.needsUpdate = true;
11792
11793            }
11794
11795            geometry.normalsNeedUpdate = false;
11796
11797        }
11798
11799        if ( geometry.colorsNeedUpdate === true ) {
11800
11801            var attribute = this.attributes.color;
11802
11803            if ( attribute !== undefined ) {
11804
11805                attribute.copyColorsArray( geometry.colors );
11806                attribute.needsUpdate = true;
11807
11808            }
11809
11810            geometry.colorsNeedUpdate = false;
11811
11812        }
11813
11814        if ( geometry.uvsNeedUpdate ) {
11815
11816            var attribute = this.attributes.uv;
11817
11818            if ( attribute !== undefined ) {
11819
11820                attribute.copyVector2sArray( geometry.uvs );
11821                attribute.needsUpdate = true;
11822
11823            }
11824
11825            geometry.uvsNeedUpdate = false;
11826
11827        }
11828
11829        if ( geometry.lineDistancesNeedUpdate ) {
11830
11831            var attribute = this.attributes.lineDistance;
11832
11833            if ( attribute !== undefined ) {
11834
11835                attribute.copyArray( geometry.lineDistances );
11836                attribute.needsUpdate = true;
11837
11838            }
11839
11840            geometry.lineDistancesNeedUpdate = false;
11841
11842        }
11843
11844        if ( geometry.groupsNeedUpdate ) {
11845
11846            geometry.computeGroups( object.geometry );
11847            this.groups = geometry.groups;
11848
11849            geometry.groupsNeedUpdate = false;
11850
11851        }
11852
11853        return this;
11854
11855    },
11856
11857    fromGeometry: function ( geometry ) {
11858
11859        geometry.__directGeometry = new THREE.DirectGeometry().fromGeometry( geometry );
11860
11861        return this.fromDirectGeometry( geometry.__directGeometry );
11862
11863    },
11864
11865    fromDirectGeometry: function ( geometry ) {
11866
11867        var positions = new Float32Array( geometry.vertices.length * 3 );
11868        this.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
11869
11870        if ( geometry.normals.length > 0 ) {
11871
11872            var normals = new Float32Array( geometry.normals.length * 3 );
11873            this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
11874
11875        }
11876
11877        if ( geometry.colors.length > 0 ) {
11878
11879            var colors = new Float32Array( geometry.colors.length * 3 );
11880            this.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
11881
11882        }
11883
11884        if ( geometry.uvs.length > 0 ) {
11885
11886            var uvs = new Float32Array( geometry.uvs.length * 2 );
11887            this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
11888
11889        }
11890
11891        if ( geometry.uvs2.length > 0 ) {
11892
11893            var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
11894            this.addAttribute( 'uv2', new THREE.BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
11895
11896        }
11897
11898        if ( geometry.indices.length > 0 ) {
11899
11900            var TypeArray = geometry.vertices.length > 65535 ? Uint32Array : Uint16Array;
11901            var indices = new TypeArray( geometry.indices.length * 3 );
11902            this.setIndex( new THREE.BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) );
11903
11904        }
11905
11906        // groups
11907
11908        this.groups = geometry.groups;
11909
11910        // morphs
11911
11912        for ( var name in geometry.morphTargets ) {
11913
11914            var array = [];
11915            var morphTargets = geometry.morphTargets[ name ];
11916
11917            for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {
11918
11919                var morphTarget = morphTargets[ i ];
11920
11921                var attribute = new THREE.Float32Attribute( morphTarget.length * 3, 3 );
11922
11923                array.push( attribute.copyVector3sArray( morphTarget ) );
11924
11925            }
11926
11927            this.morphAttributes[ name ] = array;
11928
11929        }
11930
11931        // skinning
11932
11933        if ( geometry.skinIndices.length > 0 ) {
11934
11935            var skinIndices = new THREE.Float32Attribute( geometry.skinIndices.length * 4, 4 );
11936            this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
11937
11938        }
11939
11940        if ( geometry.skinWeights.length > 0 ) {
11941
11942            var skinWeights = new THREE.Float32Attribute( geometry.skinWeights.length * 4, 4 );
11943            this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
11944
11945        }
11946
11947        //
11948
11949        if ( geometry.boundingSphere !== null ) {
11950
11951            this.boundingSphere = geometry.boundingSphere.clone();
11952
11953        }
11954
11955        if ( geometry.boundingBox !== null ) {
11956
11957            this.boundingBox = geometry.boundingBox.clone();
11958
11959        }
11960
11961        return this;
11962
11963    },
11964
11965    computeBoundingBox: function () {
11966
11967        if ( this.boundingBox === null ) {
11968
11969            this.boundingBox = new THREE.Box3();
11970
11971        }
11972
11973        var positions = this.attributes.position.array;
11974
11975        if ( positions !== undefined ) {
11976
11977            this.boundingBox.setFromArray( positions );
11978
11979        } else {
11980
11981            this.boundingBox.makeEmpty();
11982
11983        }
11984
11985        if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
11986
11987            console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
11988
11989        }
11990
11991    },
11992
11993    computeBoundingSphere: function () {
11994
11995        var box = new THREE.Box3();
11996        var vector = new THREE.Vector3();
11997
11998        return function () {
11999
12000            if ( this.boundingSphere === null ) {
12001
12002                this.boundingSphere = new THREE.Sphere();
12003
12004            }
12005
12006            var positions = this.attributes.position.array;
12007
12008            if ( positions ) {
12009
12010                var center = this.boundingSphere.center;
12011
12012                box.setFromArray( positions );
12013                box.center( center );
12014
12015                // hoping to find a boundingSphere with a radius smaller than the
12016                // boundingSphere of the boundingBox: sqrt(3) smaller in the best case
12017
12018                var maxRadiusSq = 0;
12019
12020                for ( var i = 0, il = positions.length; i < il; i += 3 ) {
12021
12022                    vector.fromArray( positions, i );
12023                    maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) );
12024
12025                }
12026
12027                this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
12028
12029                if ( isNaN( this.boundingSphere.radius ) ) {
12030
12031                    console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
12032
12033                }
12034
12035            }
12036
12037        };
12038
12039    }(),
12040
12041    computeFaceNormals: function () {
12042
12043        // backwards compatibility
12044
12045    },
12046
12047    computeVertexNormals: function () {
12048
12049        var index = this.index;
12050        var attributes = this.attributes;
12051        var groups = this.groups;
12052
12053        if ( attributes.position ) {
12054
12055            var positions = attributes.position.array;
12056
12057            if ( attributes.normal === undefined ) {
12058
12059                this.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( positions.length ), 3 ) );
12060
12061            } else {
12062
12063                // reset existing normals to zero
12064
12065                var array = attributes.normal.array;
12066
12067                for ( var i = 0, il = array.length; i < il; i ++ ) {
12068
12069                    array[ i ] = 0;
12070
12071                }
12072
12073            }
12074
12075            var normals = attributes.normal.array;
12076
12077            var vA, vB, vC,
12078
12079                pA = new THREE.Vector3(),
12080                pB = new THREE.Vector3(),
12081                pC = new THREE.Vector3(),
12082
12083                cb = new THREE.Vector3(),
12084                ab = new THREE.Vector3();
12085
12086            // indexed elements
12087
12088            if ( index ) {
12089
12090                var indices = index.array;
12091
12092                if ( groups.length === 0 ) {
12093
12094                    this.addGroup( 0, indices.length );
12095
12096                }
12097
12098                for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
12099
12100                    var group = groups[ j ];
12101
12102                    var start = group.start;
12103                    var count = group.count;
12104
12105                    for ( var i = start, il = start + count; i < il; i += 3 ) {
12106
12107                        vA = indices[ i + 0 ] * 3;
12108                        vB = indices[ i + 1 ] * 3;
12109                        vC = indices[ i + 2 ] * 3;
12110
12111                        pA.fromArray( positions, vA );
12112                        pB.fromArray( positions, vB );
12113                        pC.fromArray( positions, vC );
12114
12115                        cb.subVectors( pC, pB );
12116                        ab.subVectors( pA, pB );
12117                        cb.cross( ab );
12118
12119                        normals[ vA ] += cb.x;
12120                        normals[ vA + 1 ] += cb.y;
12121                        normals[ vA + 2 ] += cb.z;
12122
12123                        normals[ vB ] += cb.x;
12124                        normals[ vB + 1 ] += cb.y;
12125                        normals[ vB + 2 ] += cb.z;
12126
12127                        normals[ vC ] += cb.x;
12128                        normals[ vC + 1 ] += cb.y;
12129                        normals[ vC + 2 ] += cb.z;
12130
12131                    }
12132
12133                }
12134
12135            } else {
12136
12137                // non-indexed elements (unconnected triangle soup)
12138
12139                for ( var i = 0, il = positions.length; i < il; i += 9 ) {
12140
12141                    pA.fromArray( positions, i );
12142                    pB.fromArray( positions, i + 3 );
12143                    pC.fromArray( positions, i + 6 );
12144
12145                    cb.subVectors( pC, pB );
12146                    ab.subVectors( pA, pB );
12147                    cb.cross( ab );
12148
12149                    normals[ i ] = cb.x;
12150                    normals[ i + 1 ] = cb.y;
12151                    normals[ i + 2 ] = cb.z;
12152
12153                    normals[ i + 3 ] = cb.x;
12154                    normals[ i + 4 ] = cb.y;
12155                    normals[ i + 5 ] = cb.z;
12156
12157                    normals[ i + 6 ] = cb.x;
12158                    normals[ i + 7 ] = cb.y;
12159                    normals[ i + 8 ] = cb.z;
12160
12161                }
12162
12163            }
12164
12165            this.normalizeNormals();
12166
12167            attributes.normal.needsUpdate = true;
12168
12169        }
12170
12171    },
12172
12173    merge: function ( geometry, offset ) {
12174
12175        if ( geometry instanceof THREE.BufferGeometry === false ) {
12176
12177            console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
12178            return;
12179
12180        }
12181
12182        if ( offset === undefined ) offset = 0;
12183
12184        var attributes = this.attributes;
12185
12186        for ( var key in attributes ) {
12187
12188            if ( geometry.attributes[ key ] === undefined ) continue;
12189
12190            var attribute1 = attributes[ key ];
12191            var attributeArray1 = attribute1.array;
12192
12193            var attribute2 = geometry.attributes[ key ];
12194            var attributeArray2 = attribute2.array;
12195
12196            var attributeSize = attribute2.itemSize;
12197
12198            for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) {
12199
12200                attributeArray1[ j ] = attributeArray2[ i ];
12201
12202            }
12203
12204        }
12205
12206        return this;
12207
12208    },
12209
12210    normalizeNormals: function () {
12211
12212        var normals = this.attributes.normal.array;
12213
12214        var x, y, z, n;
12215
12216        for ( var i = 0, il = normals.length; i < il; i += 3 ) {
12217
12218            x = normals[ i ];
12219            y = normals[ i + 1 ];
12220            z = normals[ i + 2 ];
12221
12222            n = 1.0 / Math.sqrt( x * x + y * y + z * z );
12223
12224            normals[ i ] *= n;
12225            normals[ i + 1 ] *= n;
12226            normals[ i + 2 ] *= n;
12227
12228        }
12229
12230    },
12231
12232    toNonIndexed: function () {
12233
12234        if ( this.index === null ) {
12235
12236            console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
12237            return this;
12238
12239        }
12240
12241        var geometry2 = new THREE.BufferGeometry();
12242
12243        var indices = this.index.array;
12244        var attributes = this.attributes;
12245
12246        for ( var name in attributes ) {
12247
12248            var attribute = attributes[ name ];
12249
12250            var array = attribute.array;
12251            var itemSize = attribute.itemSize;
12252
12253            var array2 = new array.constructor( indices.length * itemSize );
12254
12255            var index = 0, index2 = 0;
12256
12257            for ( var i = 0, l = indices.length; i < l; i ++ ) {
12258
12259                index = indices[ i ] * itemSize;
12260
12261                for ( var j = 0; j < itemSize; j ++ ) {
12262
12263                    array2[ index2 ++ ] = array[ index ++ ];
12264
12265                }
12266
12267            }
12268
12269            geometry2.addAttribute( name, new THREE.BufferAttribute( array2, itemSize ) );
12270
12271        }
12272
12273        return geometry2;
12274
12275    },
12276
12277    toJSON: function () {
12278
12279        var data = {
12280            metadata: {
12281                version: 4.4,
12282                type: 'BufferGeometry',
12283                generator: 'BufferGeometry.toJSON'
12284            }
12285        };
12286
12287        // standard BufferGeometry serialization
12288
12289        data.uuid = this.uuid;
12290        data.type = this.type;
12291        if ( this.name !== '' ) data.name = this.name;
12292
12293        if ( this.parameters !== undefined ) {
12294
12295            var parameters = this.parameters;
12296
12297            for ( var key in parameters ) {
12298
12299                if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
12300
12301            }
12302
12303            return data;
12304
12305        }
12306
12307        data.data = { attributes: {} };
12308
12309        var index = this.index;
12310
12311        if ( index !== null ) {
12312
12313            var array = Array.prototype.slice.call( index.array );
12314
12315            data.data.index = {
12316                type: index.array.constructor.name,
12317                array: array
12318            };
12319
12320        }
12321
12322        var attributes = this.attributes;
12323
12324        for ( var key in attributes ) {
12325
12326            var attribute = attributes[ key ];
12327
12328            var array = Array.prototype.slice.call( attribute.array );
12329
12330            data.data.attributes[ key ] = {
12331                itemSize: attribute.itemSize,
12332                type: attribute.array.constructor.name,
12333                array: array,
12334                normalized: attribute.normalized
12335            };
12336
12337        }
12338
12339        var groups = this.groups;
12340
12341        if ( groups.length > 0 ) {
12342
12343            data.data.groups = JSON.parse( JSON.stringify( groups ) );
12344
12345        }
12346
12347        var boundingSphere = this.boundingSphere;
12348
12349        if ( boundingSphere !== null ) {
12350
12351            data.data.boundingSphere = {
12352                center: boundingSphere.center.toArray(),
12353                radius: boundingSphere.radius
12354            };
12355
12356        }
12357
12358        return data;
12359
12360    },
12361
12362    clone: function () {
12363
12364        /*
12365         // Handle primitives
12366
12367         var parameters = this.parameters;
12368
12369         if ( parameters !== undefined ) {
12370
12371         var values = [];
12372
12373         for ( var key in parameters ) {
12374
12375         values.push( parameters[ key ] );
12376
12377         }
12378
12379         var geometry = Object.create( this.constructor.prototype );
12380         this.constructor.apply( geometry, values );
12381         return geometry;
12382
12383         }
12384
12385         return new this.constructor().copy( this );
12386         */
12387
12388        return new THREE.BufferGeometry().copy( this );
12389
12390    },
12391
12392    copy: function ( source ) {
12393
12394        var index = source.index;
12395
12396        if ( index !== null ) {
12397
12398            this.setIndex( index.clone() );
12399
12400        }
12401
12402        var attributes = source.attributes;
12403
12404        for ( var name in attributes ) {
12405
12406            var attribute = attributes[ name ];
12407            this.addAttribute( name, attribute.clone() );
12408
12409        }
12410
12411        var groups = source.groups;
12412
12413        for ( var i = 0, l = groups.length; i < l; i ++ ) {
12414
12415            var group = groups[ i ];
12416            this.addGroup( group.start, group.count, group.materialIndex );
12417
12418        }
12419
12420        return this;
12421
12422    },
12423
12424    dispose: function () {
12425
12426        this.dispatchEvent( { type: 'dispose' } );
12427
12428    }
12429
12430};
12431
12432THREE.EventDispatcher.prototype.apply( THREE.BufferGeometry.prototype );
12433
12434THREE.BufferGeometry.MaxIndex = 65535;
12435
12436// File:src/core/InstancedBufferGeometry.js
12437
12438/**
12439 * @author benaadams / https://twitter.com/ben_a_adams
12440 */
12441
12442THREE.InstancedBufferGeometry = function () {
12443
12444    THREE.BufferGeometry.call( this );
12445
12446    this.type = 'InstancedBufferGeometry';
12447    this.maxInstancedCount = undefined;
12448
12449};
12450
12451THREE.InstancedBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
12452THREE.InstancedBufferGeometry.prototype.constructor = THREE.InstancedBufferGeometry;
12453
12454THREE.InstancedBufferGeometry.prototype.addGroup = function ( start, count, instances ) {
12455
12456    this.groups.push( {
12457
12458        start: start,
12459        count: count,
12460        instances: instances
12461
12462    } );
12463
12464};
12465
12466THREE.InstancedBufferGeometry.prototype.copy = function ( source ) {
12467
12468    var index = source.index;
12469
12470    if ( index !== null ) {
12471
12472        this.setIndex( index.clone() );
12473
12474    }
12475
12476    var attributes = source.attributes;
12477
12478    for ( var name in attributes ) {
12479
12480        var attribute = attributes[ name ];
12481        this.addAttribute( name, attribute.clone() );
12482
12483    }
12484
12485    var groups = source.groups;
12486
12487    for ( var i = 0, l = groups.length; i < l; i ++ ) {
12488
12489        var group = groups[ i ];
12490        this.addGroup( group.start, group.count, group.instances );
12491
12492    }
12493
12494    return this;
12495
12496};
12497
12498THREE.EventDispatcher.prototype.apply( THREE.InstancedBufferGeometry.prototype );
12499
12500// File:src/core/Uniform.js
12501
12502/**
12503 * @author mrdoob / http://mrdoob.com/
12504 */
12505
12506THREE.Uniform = function ( value ) {
12507
12508    if ( typeof value === 'string' ) {
12509
12510        console.warn( 'THREE.Uniform: Type parameter is no longer needed.' );
12511        value = arguments[ 1 ];
12512
12513    }
12514
12515    this.value = value;
12516
12517    this.dynamic = false;
12518
12519};
12520
12521THREE.Uniform.prototype = {
12522
12523    constructor: THREE.Uniform,
12524
12525    onUpdate: function ( callback ) {
12526
12527        this.dynamic = true;
12528        this.onUpdateCallback = callback;
12529
12530        return this;
12531
12532    }
12533
12534};
12535
12536// File:src/animation/AnimationClip.js
12537
12538/**
12539 *
12540 * Reusable set of Tracks that represent an animation.
12541 *
12542 * @author Ben Houston / http://clara.io/
12543 * @author David Sarno / http://lighthaus.us/
12544 */
12545
12546THREE.AnimationClip = function ( name, duration, tracks ) {
12547
12548    this.name = name || THREE.Math.generateUUID();
12549    this.tracks = tracks;
12550    this.duration = ( duration !== undefined ) ? duration : -1;
12551
12552    // this means it should figure out its duration by scanning the tracks
12553    if ( this.duration < 0 ) {
12554
12555        this.resetDuration();
12556
12557    }
12558
12559    // maybe only do these on demand, as doing them here could potentially slow down loading
12560    // but leaving these here during development as this ensures a lot of testing of these functions
12561    this.trim();
12562    this.optimize();
12563
12564};
12565
12566THREE.AnimationClip.prototype = {
12567
12568    constructor: THREE.AnimationClip,
12569
12570    resetDuration: function() {
12571
12572        var tracks = this.tracks,
12573            duration = 0;
12574
12575        for ( var i = 0, n = tracks.length; i !== n; ++ i ) {
12576
12577            var track = this.tracks[ i ];
12578
12579            duration = Math.max(
12580                duration, track.times[ track.times.length - 1 ] );
12581
12582        }
12583
12584        this.duration = duration;
12585
12586    },
12587
12588    trim: function() {
12589
12590        for ( var i = 0; i < this.tracks.length; i ++ ) {
12591
12592            this.tracks[ i ].trim( 0, this.duration );
12593
12594        }
12595
12596        return this;
12597
12598    },
12599
12600    optimize: function() {
12601
12602        for ( var i = 0; i < this.tracks.length; i ++ ) {
12603
12604            this.tracks[ i ].optimize();
12605
12606        }
12607
12608        return this;
12609
12610    }
12611
12612};
12613
12614// Static methods:
12615
12616Object.assign( THREE.AnimationClip, {
12617
12618    parse: function( json ) {
12619
12620        var tracks = [],
12621            jsonTracks = json.tracks,
12622            frameTime = 1.0 / ( json.fps || 1.0 );
12623
12624        for ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) {
12625
12626            tracks.push( THREE.KeyframeTrack.parse( jsonTracks[ i ] ).scale( frameTime ) );
12627
12628        }
12629
12630        return new THREE.AnimationClip( json.name, json.duration, tracks );
12631
12632    },
12633
12634
12635    toJSON: function( clip ) {
12636
12637        var tracks = [],
12638            clipTracks = clip.tracks;
12639
12640        var json = {
12641
12642            'name': clip.name,
12643            'duration': clip.duration,
12644            'tracks': tracks
12645
12646        };
12647
12648        for ( var i = 0, n = clipTracks.length; i !== n; ++ i ) {
12649
12650            tracks.push( THREE.KeyframeTrack.toJSON( clipTracks[ i ] ) );
12651
12652        }
12653
12654        return json;
12655
12656    },
12657
12658
12659    CreateFromMorphTargetSequence: function( name, morphTargetSequence, fps, noLoop ) {
12660
12661        var numMorphTargets = morphTargetSequence.length;
12662        var tracks = [];
12663
12664        for ( var i = 0; i < numMorphTargets; i ++ ) {
12665
12666            var times = [];
12667            var values = [];
12668
12669            times.push(
12670                ( i + numMorphTargets - 1 ) % numMorphTargets,
12671                i,
12672                ( i + 1 ) % numMorphTargets );
12673
12674            values.push( 0, 1, 0 );
12675
12676            var order = THREE.AnimationUtils.getKeyframeOrder( times );
12677            times = THREE.AnimationUtils.sortedArray( times, 1, order );
12678            values = THREE.AnimationUtils.sortedArray( values, 1, order );
12679
12680            // if there is a key at the first frame, duplicate it as the
12681            // last frame as well for perfect loop.
12682            if ( ! noLoop && times[ 0 ] === 0 ) {
12683
12684                times.push( numMorphTargets );
12685                values.push( values[ 0 ] );
12686
12687            }
12688
12689            tracks.push(
12690                new THREE.NumberKeyframeTrack(
12691                    '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
12692                    times, values
12693                ).scale( 1.0 / fps ) );
12694        }
12695
12696        return new THREE.AnimationClip( name, -1, tracks );
12697
12698    },
12699
12700    findByName: function( clipArray, name ) {
12701
12702        for ( var i = 0; i < clipArray.length; i ++ ) {
12703
12704            if ( clipArray[ i ].name === name ) {
12705
12706                return clipArray[ i ];
12707
12708            }
12709        }
12710
12711        return null;
12712
12713    },
12714
12715    CreateClipsFromMorphTargetSequences: function( morphTargets, fps, noLoop ) {
12716
12717        var animationToMorphTargets = {};
12718
12719        // tested with https://regex101.com/ on trick sequences
12720        // such flamingo_flyA_003, flamingo_run1_003, crdeath0059
12721        var pattern = /^([\w-]*?)([\d]+)$/;
12722
12723        // sort morph target names into animation groups based
12724        // patterns like Walk_001, Walk_002, Run_001, Run_002
12725        for ( var i = 0, il = morphTargets.length; i < il; i ++ ) {
12726
12727            var morphTarget = morphTargets[ i ];
12728            var parts = morphTarget.name.match( pattern );
12729
12730            if ( parts && parts.length > 1 ) {
12731
12732                var name = parts[ 1 ];
12733
12734                var animationMorphTargets = animationToMorphTargets[ name ];
12735                if ( ! animationMorphTargets ) {
12736
12737                    animationToMorphTargets[ name ] = animationMorphTargets = [];
12738
12739                }
12740
12741                animationMorphTargets.push( morphTarget );
12742
12743            }
12744
12745        }
12746
12747        var clips = [];
12748
12749        for ( var name in animationToMorphTargets ) {
12750
12751            clips.push( THREE.AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
12752
12753        }
12754
12755        return clips;
12756
12757    },
12758
12759    // parse the animation.hierarchy format
12760    parseAnimation: function( animation, bones, nodeName ) {
12761
12762        if ( ! animation ) {
12763
12764            console.error( "  no animation in JSONLoader data" );
12765            return null;
12766
12767        }
12768
12769        var addNonemptyTrack = function(
12770            trackType, trackName, animationKeys, propertyName, destTracks ) {
12771
12772            // only return track if there are actually keys.
12773            if ( animationKeys.length !== 0 ) {
12774
12775                var times = [];
12776                var values = [];
12777
12778                THREE.AnimationUtils.flattenJSON(
12779                    animationKeys, times, values, propertyName );
12780
12781                // empty keys are filtered out, so check again
12782                if ( times.length !== 0 ) {
12783
12784                    destTracks.push( new trackType( trackName, times, values ) );
12785
12786                }
12787
12788            }
12789
12790        };
12791
12792        var tracks = [];
12793
12794        var clipName = animation.name || 'default';
12795        // automatic length determination in AnimationClip.
12796        var duration = animation.length || -1;
12797        var fps = animation.fps || 30;
12798
12799        var hierarchyTracks = animation.hierarchy || [];
12800
12801        for ( var h = 0; h < hierarchyTracks.length; h ++ ) {
12802
12803            var animationKeys = hierarchyTracks[ h ].keys;
12804
12805            // skip empty tracks
12806            if ( ! animationKeys || animationKeys.length == 0 ) continue;
12807
12808            // process morph targets in a way exactly compatible
12809            // with AnimationHandler.init( animation )
12810            if ( animationKeys[0].morphTargets ) {
12811
12812                // figure out all morph targets used in this track
12813                var morphTargetNames = {};
12814                for ( var k = 0; k < animationKeys.length; k ++ ) {
12815
12816                    if ( animationKeys[k].morphTargets ) {
12817
12818                        for ( var m = 0; m < animationKeys[k].morphTargets.length; m ++ ) {
12819
12820                            morphTargetNames[ animationKeys[k].morphTargets[m] ] = -1;
12821                        }
12822
12823                    }
12824
12825                }
12826
12827                // create a track for each morph target with all zero
12828                // morphTargetInfluences except for the keys in which
12829                // the morphTarget is named.
12830                for ( var morphTargetName in morphTargetNames ) {
12831
12832                    var times = [];
12833                    var values = [];
12834
12835                    for ( var m = 0;
12836                          m !== animationKeys[k].morphTargets.length; ++ m ) {
12837
12838                        var animationKey = animationKeys[k];
12839
12840                        times.push( animationKey.time );
12841                        values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 )
12842
12843                    }
12844
12845                    tracks.push( new THREE.NumberKeyframeTrack(
12846                        '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
12847
12848                }
12849
12850                duration = morphTargetNames.length * ( fps || 1.0 );
12851
12852            } else {
12853                // ...assume skeletal animation
12854
12855                var boneName = '.bones[' + bones[ h ].name + ']';
12856
12857                addNonemptyTrack(
12858                    THREE.VectorKeyframeTrack, boneName + '.position',
12859                    animationKeys, 'pos', tracks );
12860
12861                addNonemptyTrack(
12862                    THREE.QuaternionKeyframeTrack, boneName + '.quaternion',
12863                    animationKeys, 'rot', tracks );
12864
12865                addNonemptyTrack(
12866                    THREE.VectorKeyframeTrack, boneName + '.scale',
12867                    animationKeys, 'scl', tracks );
12868
12869            }
12870
12871        }
12872
12873        if ( tracks.length === 0 ) {
12874
12875            return null;
12876
12877        }
12878
12879        var clip = new THREE.AnimationClip( clipName, duration, tracks );
12880
12881        return clip;
12882
12883    }
12884
12885} );
12886
12887
12888// File:src/animation/AnimationMixer.js
12889
12890/**
12891 *
12892 * Player for AnimationClips.
12893 *
12894 *
12895 * @author Ben Houston / http://clara.io/
12896 * @author David Sarno / http://lighthaus.us/
12897 * @author tschw
12898 */
12899
12900THREE.AnimationMixer = function( root ) {
12901
12902    this._root = root;
12903    this._initMemoryManager();
12904    this._accuIndex = 0;
12905
12906    this.time = 0;
12907
12908    this.timeScale = 1.0;
12909
12910};
12911
12912THREE.AnimationMixer.prototype = {
12913
12914    constructor: THREE.AnimationMixer,
12915
12916    // return an action for a clip optionally using a custom root target
12917    // object (this method allocates a lot of dynamic memory in case a
12918    // previously unknown clip/root combination is specified)
12919    clipAction: function( clip, optionalRoot ) {
12920
12921        var root = optionalRoot || this._root,
12922            rootUuid = root.uuid,
12923            clipName = ( typeof clip === 'string' ) ? clip : clip.name,
12924            clipObject = ( clip !== clipName ) ? clip : null,
12925
12926            actionsForClip = this._actionsByClip[ clipName ],
12927            prototypeAction;
12928
12929        if ( actionsForClip !== undefined ) {
12930
12931            var existingAction =
12932                actionsForClip.actionByRoot[ rootUuid ];
12933
12934            if ( existingAction !== undefined ) {
12935
12936                return existingAction;
12937
12938            }
12939
12940            // we know the clip, so we don't have to parse all
12941            // the bindings again but can just copy
12942            prototypeAction = actionsForClip.knownActions[ 0 ];
12943
12944            // also, take the clip from the prototype action
12945            clipObject = prototypeAction._clip;
12946
12947            if ( clip !== clipName && clip !== clipObject ) {
12948
12949                throw new Error(
12950                    "Different clips with the same name detected!" );
12951
12952            }
12953
12954        }
12955
12956        // clip must be known when specified via string
12957        if ( clipObject === null ) return null;
12958
12959        // allocate all resources required to run it
12960        var newAction = new THREE.
12961            AnimationMixer._Action( this, clipObject, optionalRoot );
12962
12963        this._bindAction( newAction, prototypeAction );
12964
12965        // and make the action known to the memory manager
12966        this._addInactiveAction( newAction, clipName, rootUuid );
12967
12968        return newAction;
12969
12970    },
12971
12972    // get an existing action
12973    existingAction: function( clip, optionalRoot ) {
12974
12975        var root = optionalRoot || this._root,
12976            rootUuid = root.uuid,
12977            clipName = ( typeof clip === 'string' ) ? clip : clip.name,
12978            actionsForClip = this._actionsByClip[ clipName ];
12979
12980        if ( actionsForClip !== undefined ) {
12981
12982            return actionsForClip.actionByRoot[ rootUuid ] || null;
12983
12984        }
12985
12986        return null;
12987
12988    },
12989
12990    // deactivates all previously scheduled actions
12991    stopAllAction: function() {
12992
12993        var actions = this._actions,
12994            nActions = this._nActiveActions,
12995            bindings = this._bindings,
12996            nBindings = this._nActiveBindings;
12997
12998        this._nActiveActions = 0;
12999        this._nActiveBindings = 0;
13000
13001        for ( var i = 0; i !== nActions; ++ i ) {
13002
13003            actions[ i ].reset();
13004
13005        }
13006
13007        for ( var i = 0; i !== nBindings; ++ i ) {
13008
13009            bindings[ i ].useCount = 0;
13010
13011        }
13012
13013        return this;
13014
13015    },
13016
13017    // advance the time and update apply the animation
13018    update: function( deltaTime ) {
13019
13020        deltaTime *= this.timeScale;
13021
13022        var actions = this._actions,
13023            nActions = this._nActiveActions,
13024
13025            time = this.time += deltaTime,
13026            timeDirection = Math.sign( deltaTime ),
13027
13028            accuIndex = this._accuIndex ^= 1;
13029
13030        // run active actions
13031
13032        for ( var i = 0; i !== nActions; ++ i ) {
13033
13034            var action = actions[ i ];
13035
13036            if ( action.enabled ) {
13037
13038                action._update( time, deltaTime, timeDirection, accuIndex );
13039
13040            }
13041
13042        }
13043
13044        // update scene graph
13045
13046        var bindings = this._bindings,
13047            nBindings = this._nActiveBindings;
13048
13049        for ( var i = 0; i !== nBindings; ++ i ) {
13050
13051            bindings[ i ].apply( accuIndex );
13052
13053        }
13054
13055        return this;
13056
13057    },
13058
13059    // return this mixer's root target object
13060    getRoot: function() {
13061
13062        return this._root;
13063
13064    },
13065
13066    // free all resources specific to a particular clip
13067    uncacheClip: function( clip ) {
13068
13069        var actions = this._actions,
13070            clipName = clip.name,
13071            actionsByClip = this._actionsByClip,
13072            actionsForClip = actionsByClip[ clipName ];
13073
13074        if ( actionsForClip !== undefined ) {
13075
13076            // note: just calling _removeInactiveAction would mess up the
13077            // iteration state and also require updating the state we can
13078            // just throw away
13079
13080            var actionsToRemove = actionsForClip.knownActions;
13081
13082            for ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
13083
13084                var action = actionsToRemove[ i ];
13085
13086                this._deactivateAction( action );
13087
13088                var cacheIndex = action._cacheIndex,
13089                    lastInactiveAction = actions[ actions.length - 1 ];
13090
13091                action._cacheIndex = null;
13092                action._byClipCacheIndex = null;
13093
13094                lastInactiveAction._cacheIndex = cacheIndex;
13095                actions[ cacheIndex ] = lastInactiveAction;
13096                actions.pop();
13097
13098                this._removeInactiveBindingsForAction( action );
13099
13100            }
13101
13102            delete actionsByClip[ clipName ];
13103
13104        }
13105
13106    },
13107
13108    // free all resources specific to a particular root target object
13109    uncacheRoot: function( root ) {
13110
13111        var rootUuid = root.uuid,
13112            actionsByClip = this._actionsByClip;
13113
13114        for ( var clipName in actionsByClip ) {
13115
13116            var actionByRoot = actionsByClip[ clipName ].actionByRoot,
13117                action = actionByRoot[ rootUuid ];
13118
13119            if ( action !== undefined ) {
13120
13121                this._deactivateAction( action );
13122                this._removeInactiveAction( action );
13123
13124            }
13125
13126        }
13127
13128        var bindingsByRoot = this._bindingsByRootAndName,
13129            bindingByName = bindingsByRoot[ rootUuid ];
13130
13131        if ( bindingByName !== undefined ) {
13132
13133            for ( var trackName in bindingByName ) {
13134
13135                var binding = bindingByName[ trackName ];
13136                binding.restoreOriginalState();
13137                this._removeInactiveBinding( binding );
13138
13139            }
13140
13141        }
13142
13143    },
13144
13145    // remove a targeted clip from the cache
13146    uncacheAction: function( clip, optionalRoot ) {
13147
13148        var action = this.existingAction( clip, optionalRoot );
13149
13150        if ( action !== null ) {
13151
13152            this._deactivateAction( action );
13153            this._removeInactiveAction( action );
13154
13155        }
13156
13157    }
13158
13159};
13160
13161THREE.EventDispatcher.prototype.apply( THREE.AnimationMixer.prototype );
13162
13163THREE.AnimationMixer._Action =
13164    function( mixer, clip, localRoot ) {
13165
13166        this._mixer = mixer;
13167        this._clip = clip;
13168        this._localRoot = localRoot || null;
13169
13170        var tracks = clip.tracks,
13171            nTracks = tracks.length,
13172            interpolants = new Array( nTracks );
13173
13174        var interpolantSettings = {
13175            endingStart: 	THREE.ZeroCurvatureEnding,
13176            endingEnd:		THREE.ZeroCurvatureEnding
13177        };
13178
13179        for ( var i = 0; i !== nTracks; ++ i ) {
13180
13181            var interpolant = tracks[ i ].createInterpolant( null );
13182            interpolants[ i ] = interpolant;
13183            interpolant.settings = interpolantSettings
13184
13185        }
13186
13187        this._interpolantSettings = interpolantSettings;
13188
13189        this._interpolants = interpolants;	// bound by the mixer
13190
13191        // inside: PropertyMixer (managed by the mixer)
13192        this._propertyBindings = new Array( nTracks );
13193
13194        this._cacheIndex = null;			// for the memory manager
13195        this._byClipCacheIndex = null;		// for the memory manager
13196
13197        this._timeScaleInterpolant = null;
13198        this._weightInterpolant = null;
13199
13200        this.loop = THREE.LoopRepeat;
13201        this._loopCount = -1;
13202
13203        // global mixer time when the action is to be started
13204        // it's set back to 'null' upon start of the action
13205        this._startTime = null;
13206
13207        // scaled local time of the action
13208        // gets clamped or wrapped to 0..clip.duration according to loop
13209        this.time = 0;
13210
13211        this.timeScale = 1;
13212        this._effectiveTimeScale = 1;
13213
13214        this.weight = 1;
13215        this._effectiveWeight = 1;
13216
13217        this.repetitions = Infinity; 		// no. of repetitions when looping
13218
13219        this.paused = false;				// false -> zero effective time scale
13220        this.enabled = true;				// true -> zero effective weight
13221
13222        this.clampWhenFinished 	= false;	// keep feeding the last frame?
13223
13224        this.zeroSlopeAtStart 	= true;		// for smooth interpolation w/o separate
13225        this.zeroSlopeAtEnd		= true;		// clips for start, loop and end
13226
13227    };
13228
13229THREE.AnimationMixer._Action.prototype = {
13230
13231    constructor: THREE.AnimationMixer._Action,
13232
13233    // State & Scheduling
13234
13235    play: function() {
13236
13237        this._mixer._activateAction( this );
13238
13239        return this;
13240
13241    },
13242
13243    stop: function() {
13244
13245        this._mixer._deactivateAction( this );
13246
13247        return this.reset();
13248
13249    },
13250
13251    reset: function() {
13252
13253        this.paused = false;
13254        this.enabled = true;
13255
13256        this.time = 0;			// restart clip
13257        this._loopCount = -1;	// forget previous loops
13258        this._startTime = null;	// forget scheduling
13259
13260        return this.stopFading().stopWarping();
13261
13262    },
13263
13264    isRunning: function() {
13265
13266        var start = this._startTime;
13267
13268        return this.enabled && ! this.paused && this.timeScale !== 0 &&
13269            this._startTime === null && this._mixer._isActiveAction( this )
13270
13271    },
13272
13273    // return true when play has been called
13274    isScheduled: function() {
13275
13276        return this._mixer._isActiveAction( this );
13277
13278    },
13279
13280    startAt: function( time ) {
13281
13282        this._startTime = time;
13283
13284        return this;
13285
13286    },
13287
13288    setLoop: function( mode, repetitions ) {
13289
13290        this.loop = mode;
13291        this.repetitions = repetitions;
13292
13293        return this;
13294
13295    },
13296
13297    // Weight
13298
13299    // set the weight stopping any scheduled fading
13300    // although .enabled = false yields an effective weight of zero, this
13301    // method does *not* change .enabled, because it would be confusing
13302    setEffectiveWeight: function( weight ) {
13303
13304        this.weight = weight;
13305
13306        // note: same logic as when updated at runtime
13307        this._effectiveWeight = this.enabled ? weight : 0;
13308
13309        return this.stopFading();
13310
13311    },
13312
13313    // return the weight considering fading and .enabled
13314    getEffectiveWeight: function() {
13315
13316        return this._effectiveWeight;
13317
13318    },
13319
13320    fadeIn: function( duration ) {
13321
13322        return this._scheduleFading( duration, 0, 1 );
13323
13324    },
13325
13326    fadeOut: function( duration ) {
13327
13328        return this._scheduleFading( duration, 1, 0 );
13329
13330    },
13331
13332    crossFadeFrom: function( fadeOutAction, duration, warp ) {
13333
13334        var mixer = this._mixer;
13335
13336        fadeOutAction.fadeOut( duration );
13337        this.fadeIn( duration );
13338
13339        if( warp ) {
13340
13341            var fadeInDuration = this._clip.duration,
13342                fadeOutDuration = fadeOutAction._clip.duration,
13343
13344                startEndRatio = fadeOutDuration / fadeInDuration,
13345                endStartRatio = fadeInDuration / fadeOutDuration;
13346
13347            fadeOutAction.warp( 1.0, startEndRatio, duration );
13348            this.warp( endStartRatio, 1.0, duration );
13349
13350        }
13351
13352        return this;
13353
13354    },
13355
13356    crossFadeTo: function( fadeInAction, duration, warp ) {
13357
13358        return fadeInAction.crossFadeFrom( this, duration, warp );
13359
13360    },
13361
13362    stopFading: function() {
13363
13364        var weightInterpolant = this._weightInterpolant;
13365
13366        if ( weightInterpolant !== null ) {
13367
13368            this._weightInterpolant = null;
13369            this._mixer._takeBackControlInterpolant( weightInterpolant );
13370
13371        }
13372
13373        return this;
13374
13375    },
13376
13377    // Time Scale Control
13378
13379    // set the weight stopping any scheduled warping
13380    // although .paused = true yields an effective time scale of zero, this
13381    // method does *not* change .paused, because it would be confusing
13382    setEffectiveTimeScale: function( timeScale ) {
13383
13384        this.timeScale = timeScale;
13385        this._effectiveTimeScale = this.paused ? 0 :timeScale;
13386
13387        return this.stopWarping();
13388
13389    },
13390
13391    // return the time scale considering warping and .paused
13392    getEffectiveTimeScale: function() {
13393
13394        return this._effectiveTimeScale;
13395
13396    },
13397
13398    setDuration: function( duration ) {
13399
13400        this.timeScale = this._clip.duration / duration;
13401
13402        return this.stopWarping();
13403
13404    },
13405
13406    syncWith: function( action ) {
13407
13408        this.time = action.time;
13409        this.timeScale = action.timeScale;
13410
13411        return this.stopWarping();
13412
13413    },
13414
13415    halt: function( duration ) {
13416
13417        return this.warp( this._currentTimeScale, 0, duration );
13418
13419    },
13420
13421    warp: function( startTimeScale, endTimeScale, duration ) {
13422
13423        var mixer = this._mixer, now = mixer.time,
13424            interpolant = this._timeScaleInterpolant,
13425
13426            timeScale = this.timeScale;
13427
13428        if ( interpolant === null ) {
13429
13430            interpolant = mixer._lendControlInterpolant(),
13431                this._timeScaleInterpolant = interpolant;
13432
13433        }
13434
13435        var times = interpolant.parameterPositions,
13436            values = interpolant.sampleValues;
13437
13438        times[ 0 ] = now;
13439        times[ 1 ] = now + duration;
13440
13441        values[ 0 ] = startTimeScale / timeScale;
13442        values[ 1 ] = endTimeScale / timeScale;
13443
13444        return this;
13445
13446    },
13447
13448    stopWarping: function() {
13449
13450        var timeScaleInterpolant = this._timeScaleInterpolant;
13451
13452        if ( timeScaleInterpolant !== null ) {
13453
13454            this._timeScaleInterpolant = null;
13455            this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
13456
13457        }
13458
13459        return this;
13460
13461    },
13462
13463    // Object Accessors
13464
13465    getMixer: function() {
13466
13467        return this._mixer;
13468
13469    },
13470
13471    getClip: function() {
13472
13473        return this._clip;
13474
13475    },
13476
13477    getRoot: function() {
13478
13479        return this._localRoot || this._mixer._root;
13480
13481    },
13482
13483    // Interna
13484
13485    _update: function( time, deltaTime, timeDirection, accuIndex ) {
13486        // called by the mixer
13487
13488        var startTime = this._startTime;
13489
13490        if ( startTime !== null ) {
13491
13492            // check for scheduled start of action
13493
13494            var timeRunning = ( time - startTime ) * timeDirection;
13495            if ( timeRunning < 0 || timeDirection === 0 ) {
13496
13497                return; // yet to come / don't decide when delta = 0
13498
13499            }
13500
13501            // start
13502
13503            this._startTime = null; // unschedule
13504            deltaTime = timeDirection * timeRunning;
13505
13506        }
13507
13508        // apply time scale and advance time
13509
13510        deltaTime *= this._updateTimeScale( time );
13511        var clipTime = this._updateTime( deltaTime );
13512
13513        // note: _updateTime may disable the action resulting in
13514        // an effective weight of 0
13515
13516        var weight = this._updateWeight( time );
13517
13518        if ( weight > 0 ) {
13519
13520            var interpolants = this._interpolants;
13521            var propertyMixers = this._propertyBindings;
13522
13523            for ( var j = 0, m = interpolants.length; j !== m; ++ j ) {
13524
13525                interpolants[ j ].evaluate( clipTime );
13526                propertyMixers[ j ].accumulate( accuIndex, weight );
13527
13528            }
13529
13530        }
13531
13532    },
13533
13534    _updateWeight: function( time ) {
13535
13536        var weight = 0;
13537
13538        if ( this.enabled ) {
13539
13540            weight = this.weight;
13541            var interpolant = this._weightInterpolant;
13542
13543            if ( interpolant !== null ) {
13544
13545                var interpolantValue = interpolant.evaluate( time )[ 0 ];
13546
13547                weight *= interpolantValue;
13548
13549                if ( time > interpolant.parameterPositions[ 1 ] ) {
13550
13551                    this.stopFading();
13552
13553                    if ( interpolantValue === 0 ) {
13554
13555                        // faded out, disable
13556                        this.enabled = false;
13557
13558                    }
13559
13560                }
13561
13562            }
13563
13564        }
13565
13566        this._effectiveWeight = weight;
13567        return weight;
13568
13569    },
13570
13571    _updateTimeScale: function( time ) {
13572
13573        var timeScale = 0;
13574
13575        if ( ! this.paused ) {
13576
13577            timeScale = this.timeScale;
13578
13579            var interpolant = this._timeScaleInterpolant;
13580
13581            if ( interpolant !== null ) {
13582
13583                var interpolantValue = interpolant.evaluate( time )[ 0 ];
13584
13585                timeScale *= interpolantValue;
13586
13587                if ( time > interpolant.parameterPositions[ 1 ] ) {
13588
13589                    this.stopWarping();
13590
13591                    if ( timeScale === 0 ) {
13592
13593                        // motion has halted, pause
13594                        this.pause = true;
13595
13596                    } else {
13597
13598                        // warp done - apply final time scale
13599                        this.timeScale = timeScale;
13600
13601                    }
13602
13603                }
13604
13605            }
13606
13607        }
13608
13609        this._effectiveTimeScale = timeScale;
13610        return timeScale;
13611
13612    },
13613
13614    _updateTime: function( deltaTime ) {
13615
13616        var time = this.time + deltaTime;
13617
13618        if ( deltaTime === 0 ) return time;
13619
13620        var duration = this._clip.duration,
13621
13622            loop = this.loop,
13623            loopCount = this._loopCount,
13624
13625            pingPong = false;
13626
13627        switch ( loop ) {
13628
13629            case THREE.LoopOnce:
13630
13631                if ( loopCount === -1 ) {
13632
13633                    // just started
13634
13635                    this.loopCount = 0;
13636                    this._setEndings( true, true, false );
13637
13638                }
13639
13640                if ( time >= duration ) {
13641
13642                    time = duration;
13643
13644                } else if ( time < 0 ) {
13645
13646                    time = 0;
13647
13648                } else break;
13649
13650                // reached the end
13651
13652                if ( this.clampWhenFinished ) this.pause = true;
13653                else this.enabled = false;
13654
13655                this._mixer.dispatchEvent( {
13656                    type: 'finished', action: this,
13657                    direction: deltaTime < 0 ? -1 : 1
13658                } );
13659
13660                break;
13661
13662            case THREE.LoopPingPong:
13663
13664                pingPong = true;
13665
13666            case THREE.LoopRepeat:
13667
13668                if ( loopCount === -1 ) {
13669
13670                    // just started
13671
13672                    if ( deltaTime > 0 ) {
13673
13674                        loopCount = 0;
13675
13676                        this._setEndings(
13677                            true, this.repetitions === 0, pingPong );
13678
13679                    } else {
13680
13681                        // when looping in reverse direction, the initial
13682                        // transition through zero counts as a repetition,
13683                        // so leave loopCount at -1
13684
13685                        this._setEndings(
13686                            this.repetitions === 0, true, pingPong );
13687
13688                    }
13689
13690                }
13691
13692                if ( time >= duration || time < 0 ) {
13693
13694                    // wrap around
13695
13696                    var loopDelta = Math.floor( time / duration ); // signed
13697                    time -= duration * loopDelta;
13698
13699                    loopCount += Math.abs( loopDelta );
13700
13701                    var pending = this.repetitions - loopCount;
13702
13703                    if ( pending < 0 ) {
13704
13705                        // stop (switch state, clamp time, fire event)
13706
13707                        if ( this.clampWhenFinished ) this.paused = true;
13708                        else this.enabled = false;
13709
13710                        time = deltaTime > 0 ? duration : 0;
13711
13712                        this._mixer.dispatchEvent( {
13713                            type: 'finished', action: this,
13714                            direction: deltaTime > 0 ? 1 : -1
13715                        } );
13716
13717                        break;
13718
13719                    } else if ( pending === 0 ) {
13720
13721                        // transition to last round
13722
13723                        var atStart = deltaTime < 0;
13724                        this._setEndings( atStart, ! atStart, pingPong );
13725
13726                    } else {
13727
13728                        this._setEndings( false, false, pingPong );
13729
13730                    }
13731
13732                    this._loopCount = loopCount;
13733
13734                    this._mixer.dispatchEvent( {
13735                        type: 'loop', action: this, loopDelta: loopDelta
13736                    } );
13737
13738                }
13739
13740                if ( loop === THREE.LoopPingPong && ( loopCount & 1 ) === 1 ) {
13741
13742                    // invert time for the "pong round"
13743
13744                    this.time = time;
13745
13746                    return duration - time;
13747
13748                }
13749
13750                break;
13751
13752        }
13753
13754        this.time = time;
13755
13756        return time;
13757
13758    },
13759
13760    _setEndings: function( atStart, atEnd, pingPong ) {
13761
13762        var settings = this._interpolantSettings;
13763
13764        if ( pingPong ) {
13765
13766            settings.endingStart 	= THREE.ZeroSlopeEnding;
13767            settings.endingEnd		= THREE.ZeroSlopeEnding;
13768
13769        } else {
13770
13771            // assuming for LoopOnce atStart == atEnd == true
13772
13773            if ( atStart ) {
13774
13775                settings.endingStart = this.zeroSlopeAtStart ?
13776                    THREE.ZeroSlopeEnding : THREE.ZeroCurvatureEnding;
13777
13778            } else {
13779
13780                settings.endingStart = THREE.WrapAroundEnding;
13781
13782            }
13783
13784            if ( atEnd ) {
13785
13786                settings.endingEnd = this.zeroSlopeAtEnd ?
13787                    THREE.ZeroSlopeEnding : THREE.ZeroCurvatureEnding;
13788
13789            } else {
13790
13791                settings.endingEnd 	 = THREE.WrapAroundEnding;
13792
13793            }
13794
13795        }
13796
13797    },
13798
13799    _scheduleFading: function( duration, weightNow, weightThen ) {
13800
13801        var mixer = this._mixer, now = mixer.time,
13802            interpolant = this._weightInterpolant;
13803
13804        if ( interpolant === null ) {
13805
13806            interpolant = mixer._lendControlInterpolant(),
13807                this._weightInterpolant = interpolant;
13808
13809        }
13810
13811        var times = interpolant.parameterPositions,
13812            values = interpolant.sampleValues;
13813
13814        times[ 0 ] = now; 				values[ 0 ] = weightNow;
13815        times[ 1 ] = now + duration;	values[ 1 ] = weightThen;
13816
13817        return this;
13818
13819    }
13820
13821};
13822
13823// Implementation details:
13824
13825Object.assign( THREE.AnimationMixer.prototype, {
13826
13827    _bindAction: function( action, prototypeAction ) {
13828
13829        var root = action._localRoot || this._root,
13830            tracks = action._clip.tracks,
13831            nTracks = tracks.length,
13832            bindings = action._propertyBindings,
13833            interpolants = action._interpolants,
13834            rootUuid = root.uuid,
13835            bindingsByRoot = this._bindingsByRootAndName,
13836            bindingsByName = bindingsByRoot[ rootUuid ];
13837
13838        if ( bindingsByName === undefined ) {
13839
13840            bindingsByName = {};
13841            bindingsByRoot[ rootUuid ] = bindingsByName;
13842
13843        }
13844
13845        for ( var i = 0; i !== nTracks; ++ i ) {
13846
13847            var track = tracks[ i ],
13848                trackName = track.name,
13849                binding = bindingsByName[ trackName ];
13850
13851            if ( binding !== undefined ) {
13852
13853                bindings[ i ] = binding;
13854
13855            } else {
13856
13857                binding = bindings[ i ];
13858
13859                if ( binding !== undefined ) {
13860
13861                    // existing binding, make sure the cache knows
13862
13863                    if ( binding._cacheIndex === null ) {
13864
13865                        ++ binding.referenceCount;
13866                        this._addInactiveBinding( binding, rootUuid, trackName );
13867
13868                    }
13869
13870                    continue;
13871
13872                }
13873
13874                var path = prototypeAction && prototypeAction.
13875                        _propertyBindings[ i ].binding.parsedPath;
13876
13877                binding = new THREE.PropertyMixer(
13878                    THREE.PropertyBinding.create( root, trackName, path ),
13879                    track.ValueTypeName, track.getValueSize() );
13880
13881                ++ binding.referenceCount;
13882                this._addInactiveBinding( binding, rootUuid, trackName );
13883
13884                bindings[ i ] = binding;
13885
13886            }
13887
13888            interpolants[ i ].resultBuffer = binding.buffer;
13889
13890        }
13891
13892    },
13893
13894    _activateAction: function( action ) {
13895
13896        if ( ! this._isActiveAction( action ) ) {
13897
13898            if ( action._cacheIndex === null ) {
13899
13900                // this action has been forgotten by the cache, but the user
13901                // appears to be still using it -> rebind
13902
13903                var rootUuid = ( action._localRoot || this._root ).uuid,
13904                    clipName = action._clip.name,
13905                    actionsForClip = this._actionsByClip[ clipName ];
13906
13907                this._bindAction( action,
13908                    actionsForClip && actionsForClip.knownActions[ 0 ] );
13909
13910                this._addInactiveAction( action, clipName, rootUuid );
13911
13912            }
13913
13914            var bindings = action._propertyBindings;
13915
13916            // increment reference counts / sort out state
13917            for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
13918
13919                var binding = bindings[ i ];
13920
13921                if ( binding.useCount ++ === 0 ) {
13922
13923                    this._lendBinding( binding );
13924                    binding.saveOriginalState();
13925
13926                }
13927
13928            }
13929
13930            this._lendAction( action );
13931
13932        }
13933
13934    },
13935
13936    _deactivateAction: function( action ) {
13937
13938        if ( this._isActiveAction( action ) ) {
13939
13940            var bindings = action._propertyBindings;
13941
13942            // decrement reference counts / sort out state
13943            for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
13944
13945                var binding = bindings[ i ];
13946
13947                if ( -- binding.useCount === 0 ) {
13948
13949                    binding.restoreOriginalState();
13950                    this._takeBackBinding( binding );
13951
13952                }
13953
13954            }
13955
13956            this._takeBackAction( action );
13957
13958        }
13959
13960    },
13961
13962    // Memory manager
13963
13964    _initMemoryManager: function() {
13965
13966        this._actions = []; // 'nActiveActions' followed by inactive ones
13967        this._nActiveActions = 0;
13968
13969        this._actionsByClip = {};
13970        // inside:
13971        // {
13972        // 		knownActions: Array< _Action >	- used as prototypes
13973        // 		actionByRoot: _Action			- lookup
13974        // }
13975
13976
13977        this._bindings = []; // 'nActiveBindings' followed by inactive ones
13978        this._nActiveBindings = 0;
13979
13980        this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
13981
13982
13983        this._controlInterpolants = []; // same game as above
13984        this._nActiveControlInterpolants = 0;
13985
13986        var scope = this;
13987
13988        this.stats = {
13989
13990            actions: {
13991                get total() { return scope._actions.length; },
13992                get inUse() { return scope._nActiveActions; }
13993            },
13994            bindings: {
13995                get total() { return scope._bindings.length; },
13996                get inUse() { return scope._nActiveBindings; }
13997            },
13998            controlInterpolants: {
13999                get total() { return scope._controlInterpolants.length; },
14000                get inUse() { return scope._nActiveControlInterpolants; }
14001            }
14002
14003        };
14004
14005    },
14006
14007    // Memory management for _Action objects
14008
14009    _isActiveAction: function( action ) {
14010
14011        var index = action._cacheIndex;
14012        return index !== null && index < this._nActiveActions;
14013
14014    },
14015
14016    _addInactiveAction: function( action, clipName, rootUuid ) {
14017
14018        var actions = this._actions,
14019            actionsByClip = this._actionsByClip,
14020            actionsForClip = actionsByClip[ clipName ];
14021
14022        if ( actionsForClip === undefined ) {
14023
14024            actionsForClip = {
14025
14026                knownActions: [ action ],
14027                actionByRoot: {}
14028
14029            };
14030
14031            action._byClipCacheIndex = 0;
14032
14033            actionsByClip[ clipName ] = actionsForClip;
14034
14035        } else {
14036
14037            var knownActions = actionsForClip.knownActions;
14038
14039            action._byClipCacheIndex = knownActions.length;
14040            knownActions.push( action );
14041
14042        }
14043
14044        action._cacheIndex = actions.length;
14045        actions.push( action );
14046
14047        actionsForClip.actionByRoot[ rootUuid ] = action;
14048
14049    },
14050
14051    _removeInactiveAction: function( action ) {
14052
14053        var actions = this._actions,
14054            lastInactiveAction = actions[ actions.length - 1 ],
14055            cacheIndex = action._cacheIndex;
14056
14057        lastInactiveAction._cacheIndex = cacheIndex;
14058        actions[ cacheIndex ] = lastInactiveAction;
14059        actions.pop();
14060
14061        action._cacheIndex = null;
14062
14063
14064        var clipName = action._clip.name,
14065            actionsByClip = this._actionsByClip,
14066            actionsForClip = actionsByClip[ clipName ],
14067            knownActionsForClip = actionsForClip.knownActions,
14068
14069            lastKnownAction =
14070                knownActionsForClip[ knownActionsForClip.length - 1 ],
14071
14072            byClipCacheIndex = action._byClipCacheIndex;
14073
14074        lastKnownAction._byClipCacheIndex = byClipCacheIndex;
14075        knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
14076        knownActionsForClip.pop();
14077
14078        action._byClipCacheIndex = null;
14079
14080
14081        var actionByRoot = actionsForClip.actionByRoot,
14082            rootUuid = ( actions._localRoot || this._root ).uuid;
14083
14084        delete actionByRoot[ rootUuid ];
14085
14086        if ( knownActionsForClip.length === 0 ) {
14087
14088            delete actionsByClip[ clipName ];
14089
14090        }
14091
14092        this._removeInactiveBindingsForAction( action );
14093
14094    },
14095
14096    _removeInactiveBindingsForAction: function( action ) {
14097
14098        var bindings = action._propertyBindings;
14099        for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
14100
14101            var binding = bindings[ i ];
14102
14103            if ( -- binding.referenceCount === 0 ) {
14104
14105                this._removeInactiveBinding( binding );
14106
14107            }
14108
14109        }
14110
14111    },
14112
14113    _lendAction: function( action ) {
14114
14115        // [ active actions |  inactive actions  ]
14116        // [  active actions >| inactive actions ]
14117        //                 s        a
14118        //                  <-swap->
14119        //                 a        s
14120
14121        var actions = this._actions,
14122            prevIndex = action._cacheIndex,
14123
14124            lastActiveIndex = this._nActiveActions ++,
14125
14126            firstInactiveAction = actions[ lastActiveIndex ];
14127
14128        action._cacheIndex = lastActiveIndex;
14129        actions[ lastActiveIndex ] = action;
14130
14131        firstInactiveAction._cacheIndex = prevIndex;
14132        actions[ prevIndex ] = firstInactiveAction;
14133
14134    },
14135
14136    _takeBackAction: function( action ) {
14137
14138        // [  active actions  | inactive actions ]
14139        // [ active actions |< inactive actions  ]
14140        //        a        s
14141        //         <-swap->
14142        //        s        a
14143
14144        var actions = this._actions,
14145            prevIndex = action._cacheIndex,
14146
14147            firstInactiveIndex = -- this._nActiveActions,
14148
14149            lastActiveAction = actions[ firstInactiveIndex ];
14150
14151        action._cacheIndex = firstInactiveIndex;
14152        actions[ firstInactiveIndex ] = action;
14153
14154        lastActiveAction._cacheIndex = prevIndex;
14155        actions[ prevIndex ] = lastActiveAction;
14156
14157    },
14158
14159    // Memory management for PropertyMixer objects
14160
14161    _addInactiveBinding: function( binding, rootUuid, trackName ) {
14162
14163        var bindingsByRoot = this._bindingsByRootAndName,
14164            bindingByName = bindingsByRoot[ rootUuid ],
14165
14166            bindings = this._bindings;
14167
14168        if ( bindingByName === undefined ) {
14169
14170            bindingByName = {};
14171            bindingsByRoot[ rootUuid ] = bindingByName;
14172
14173        }
14174
14175        bindingByName[ trackName ] = binding;
14176
14177        binding._cacheIndex = bindings.length;
14178        bindings.push( binding );
14179
14180    },
14181
14182    _removeInactiveBinding: function( binding ) {
14183
14184        var bindings = this._bindings,
14185            propBinding = binding.binding,
14186            rootUuid = propBinding.rootNode.uuid,
14187            trackName = propBinding.path,
14188            bindingsByRoot = this._bindingsByRootAndName,
14189            bindingByName = bindingsByRoot[ rootUuid ],
14190
14191            lastInactiveBinding = bindings[ bindings.length - 1 ],
14192            cacheIndex = binding._cacheIndex;
14193
14194        lastInactiveBinding._cacheIndex = cacheIndex;
14195        bindings[ cacheIndex ] = lastInactiveBinding;
14196        bindings.pop();
14197
14198        delete bindingByName[ trackName ];
14199
14200        remove_empty_map: {
14201
14202            for ( var _ in bindingByName ) break remove_empty_map;
14203
14204            delete bindingsByRoot[ rootUuid ];
14205
14206        }
14207
14208    },
14209
14210    _lendBinding: function( binding ) {
14211
14212        var bindings = this._bindings,
14213            prevIndex = binding._cacheIndex,
14214
14215            lastActiveIndex = this._nActiveBindings ++,
14216
14217            firstInactiveBinding = bindings[ lastActiveIndex ];
14218
14219        binding._cacheIndex = lastActiveIndex;
14220        bindings[ lastActiveIndex ] = binding;
14221
14222        firstInactiveBinding._cacheIndex = prevIndex;
14223        bindings[ prevIndex ] = firstInactiveBinding;
14224
14225    },
14226
14227    _takeBackBinding: function( binding ) {
14228
14229        var bindings = this._bindings,
14230            prevIndex = binding._cacheIndex,
14231
14232            firstInactiveIndex = -- this._nActiveBindings,
14233
14234            lastActiveBinding = bindings[ firstInactiveIndex ];
14235
14236        binding._cacheIndex = firstInactiveIndex;
14237        bindings[ firstInactiveIndex ] = binding;
14238
14239        lastActiveBinding._cacheIndex = prevIndex;
14240        bindings[ prevIndex ] = lastActiveBinding;
14241
14242    },
14243
14244
14245    // Memory management of Interpolants for weight and time scale
14246
14247    _lendControlInterpolant: function() {
14248
14249        var interpolants = this._controlInterpolants,
14250            lastActiveIndex = this._nActiveControlInterpolants ++,
14251            interpolant = interpolants[ lastActiveIndex ];
14252
14253        if ( interpolant === undefined ) {
14254
14255            interpolant = new THREE.LinearInterpolant(
14256                new Float32Array( 2 ), new Float32Array( 2 ),
14257                1, this._controlInterpolantsResultBuffer );
14258
14259            interpolant.__cacheIndex = lastActiveIndex;
14260            interpolants[ lastActiveIndex ] = interpolant;
14261
14262        }
14263
14264        return interpolant;
14265
14266    },
14267
14268    _takeBackControlInterpolant: function( interpolant ) {
14269
14270        var interpolants = this._controlInterpolants,
14271            prevIndex = interpolant.__cacheIndex,
14272
14273            firstInactiveIndex = -- this._nActiveControlInterpolants,
14274
14275            lastActiveInterpolant = interpolants[ firstInactiveIndex ];
14276
14277        interpolant.__cacheIndex = firstInactiveIndex;
14278        interpolants[ firstInactiveIndex ] = interpolant;
14279
14280        lastActiveInterpolant.__cacheIndex = prevIndex;
14281        interpolants[ prevIndex ] = lastActiveInterpolant;
14282
14283    },
14284
14285    _controlInterpolantsResultBuffer: new Float32Array( 1 )
14286
14287}
14287 );
14288
14289
14290// File:src/animation/AnimationObjectGroup.js
14291
14292/**
14293 *
14294 * A group of objects that receives a shared animation state.
14295 *
14296 * Usage:
14297 *
14298 * 	-	Add objects you would otherwise pass as 'root' to the
14299 * 		constructor or the .clipAction method of AnimationMixer.
14300 *
14301 * 	-	Instead pass this object as 'root'.
14302 *
14303 * 	-	You can also add and remove objects later when the mixer
14304 * 		is running.
14305 *
14306 * Note:
14307 *
14308 *  	Objects of this class appear as one object to the mixer,
14309 *  	so cache control of the individual objects must be done
14310 *  	on the group.
14311 *
14312 * Limitation:
14313 *
14314 * 	- 	The animated properties must be compatible among the
14315 * 		all objects in the group.
14316 *
14317 *  -	A single property can either be controlled through a
14318 *  	target group or directly, but not both.
14319 *
14320 * @author tschw
14321 */
14322
14323THREE.AnimationObjectGroup = function( var_args ) {
14324
14325    this.uuid = THREE.Math.generateUUID();
14326
14327    // cached objects followed by the active ones
14328    this._objects = Array.prototype.slice.call( arguments );
14329
14330    this.nCachedObjects_ = 0;			// threshold
14331    // note: read by PropertyBinding.Composite
14332
14333    var indices = {};
14334    this._indicesByUUID = indices;		// for bookkeeping
14335
14336    for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
14337
14338        indices[ arguments[ i ].uuid ] = i;
14339
14340    }
14341
14342    this._paths = [];					// inside: string
14343    this._parsedPaths = [];				// inside: { we don't care, here }
14344    this._bindings = []; 				// inside: Array< PropertyBinding >
14345    this._bindingsIndicesByPath = {}; 	// inside: indices in these arrays
14346
14347    var scope = this;
14348
14349    this.stats = {
14350
14351        objects: {
14352            get total() { return scope._objects.length; },
14353            get inUse() { return this.total - scope.nCachedObjects_;  }
14354        },
14355
14356        get bindingsPerObject() { return scope._bindings.length; }
14357
14358    };
14359
14360};
14361
14362THREE.AnimationObjectGroup.prototype = {
14363
14364    constructor: THREE.AnimationObjectGroup,
14365
14366    add: function( var_args ) {
14367
14368        var objects = this._objects,
14369            nObjects = objects.length,
14370            nCachedObjects = this.nCachedObjects_,
14371            indicesByUUID = this._indicesByUUID,
14372            paths = this._paths,
14373            parsedPaths = this._parsedPaths,
14374            bindings = this._bindings,
14375            nBindings = bindings.length;
14376
14377        for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
14378
14379            var object = arguments[ i ],
14380                uuid = object.uuid,
14381                index = indicesByUUID[ uuid ];
14382
14383            if ( index === undefined ) {
14384
14385                // unknown object -> add it to the ACTIVE region
14386
14387                index = nObjects ++;
14388                indicesByUUID[ uuid ] = index;
14389                objects.push( object );
14390
14391                // accounting is done, now do the same for all bindings
14392
14393                for ( var j = 0, m = nBindings; j !== m; ++ j ) {
14394
14395                    bindings[ j ].push(
14396                        new THREE.PropertyBinding(
14397                            object, paths[ j ], parsedPaths[ j ] ) );
14398
14399                }
14400
14401            } else if ( index < nCachedObjects ) {
14402
14403                var knownObject = objects[ index ];
14404
14405                // move existing object to the ACTIVE region
14406
14407                var firstActiveIndex = -- nCachedObjects,
14408                    lastCachedObject = objects[ firstActiveIndex ];
14409
14410                indicesByUUID[ lastCachedObject.uuid ] = index;
14411                objects[ index ] = lastCachedObject;
14412
14413                indicesByUUID[ uuid ] = firstActiveIndex;
14414                objects[ firstActiveIndex ] = object;
14415
14416                // accounting is done, now do the same for all bindings
14417
14418                for ( var j = 0, m = nBindings; j !== m; ++ j ) {
14419
14420                    var bindingsForPath = bindings[ j ],
14421                        lastCached = bindingsForPath[ firstActiveIndex ],
14422                        binding = bindingsForPath[ index ];
14423
14424                    bindingsForPath[ index ] = lastCached;
14425
14426                    if ( binding === undefined ) {
14427
14428                        // since we do not bother to create new bindings
14429                        // for objects that are cached, the binding may
14430                        // or may not exist
14431
14432                        binding = new THREE.PropertyBinding(
14433                            object, paths[ j ], parsedPaths[ j ] );
14434
14435                    }
14436
14437                    bindingsForPath[ firstActiveIndex ] = binding;
14438
14439                }
14440
14441            } else if ( objects[ index ] !== knownObject) {
14442
14443                console.error( "Different objects with the same UUID " +
14444                "detected. Clean the caches or recreate your " +
14445                "infrastructure when reloading scenes..." );
14446
14447            } // else the object is already where we want it to be
14448
14449        } // for arguments
14450
14451        this.nCachedObjects_ = nCachedObjects;
14452
14453    },
14454
14455    remove: function( var_args ) {
14456
14457        var objects = this._objects,
14458            nObjects = objects.length,
14459            nCachedObjects = this.nCachedObjects_,
14460            indicesByUUID = this._indicesByUUID,
14461            bindings = this._bindings,
14462            nBindings = bindings.length;
14463
14464        for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
14465
14466            var object = arguments[ i ],
14467                uuid = object.uuid,
14468                index = indicesByUUID[ uuid ];
14469
14470            if ( index !== undefined && index >= nCachedObjects ) {
14471
14472                // move existing object into the CACHED region
14473
14474                var lastCachedIndex = nCachedObjects ++,
14475                    firstActiveObject = objects[ lastCachedIndex ];
14476
14477                indicesByUUID[ firstActiveObject.uuid ] = index;
14478                objects[ index ] = firstActiveObject;
14479
14480                indicesByUUID[ uuid ] = lastCachedIndex;
14481                objects[ lastCachedIndex ] = object;
14482
14483                // accounting is done, now do the same for all bindings
14484
14485                for ( var j = 0, m = nBindings; j !== m; ++ j ) {
14486
14487                    var bindingsForPath = bindings[ j ],
14488                        firstActive = bindingsForPath[ lastCachedIndex ],
14489                        binding = bindingsForPath[ index ];
14490
14491                    bindingsForPath[ index ] = firstActive;
14492                    bindingsForPath[ lastCachedIndex ] = binding;
14493
14494                }
14495
14496            }
14497
14498        } // for arguments
14499
14500        this.nCachedObjects_ = nCachedObjects;
14501
14502    },
14503
14504    // remove & forget
14505    uncache: function( var_args ) {
14506
14507        var objects = this._objects,
14508            nObjects = objects.length,
14509            nCachedObjects = this.nCachedObjects_,
14510            indicesByUUID = this._indicesByUUID,
14511            bindings = this._bindings,
14512            nBindings = bindings.length;
14513
14514        for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
14515
14516            var object = arguments[ i ],
14517                uuid = object.uuid,
14518                index = indicesByUUID[ uuid ];
14519
14520            if ( index !== undefined ) {
14521
14522                delete indicesByUUID[ uuid ];
14523
14524                if ( index < nCachedObjects ) {
14525
14526                    // object is cached, shrink the CACHED region
14527
14528                    var firstActiveIndex = -- nCachedObjects,
14529                        lastCachedObject = objects[ firstActiveIndex ],
14530                        lastIndex = -- nObjects,
14531                        lastObject = objects[ lastIndex ];
14532
14533                    // last cached object takes this object's place
14534                    indicesByUUID[ lastCachedObject.uuid ] = index;
14535                    objects[ index ] = lastCachedObject;
14536
14537                    // last object goes to the activated slot and pop
14538                    indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
14539                    objects[ firstActiveIndex ] = lastObject;
14540                    objects.pop();
14541
14542                    // accounting is done, now do the same for all bindings
14543
14544                    for ( var j = 0, m = nBindings; j !== m; ++ j ) {
14545
14546                        var bindingsForPath = bindings[ j ],
14547                            lastCached = bindingsForPath[ firstActiveIndex ],
14548                            last = bindingsForPath[ lastIndex ];
14549
14550                        bindingsForPath[ index ] = lastCached;
14551                        bindingsForPath[ firstActiveIndex ] = last;
14552                        bindingsForPath.pop();
14553
14554                    }
14555
14556                } else {
14557
14558                    // object is active, just swap with the last and pop
14559
14560                    var lastIndex = -- nObjects,
14561                        lastObject = objects[ lastIndex ];
14562
14563                    indicesByUUID[ lastObject.uuid ] = index;
14564                    objects[ index ] = lastObject;
14565                    objects.pop();
14566
14567                    // accounting is done, now do the same for all bindings
14568
14569                    for ( var j = 0, m = nBindings; j !== m; ++ j ) {
14570
14571                        var bindingsForPath = bindings[ j ];
14572
14573                        bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
14574                        bindingsForPath.pop();
14575
14576                    }
14577
14578                } // cached or active
14579
14580            } // if object is known
14581
14582        } // for arguments
14583
14584        this.nCachedObjects_ = nCachedObjects;
14585
14586    },
14587
14588    // Internal interface used by befriended PropertyBinding.Composite:
14589
14590    subscribe_: function( path, parsedPath ) {
14591        // returns an array of bindings for the given path that is changed
14592        // according to the contained objects in the group
14593
14594        var indicesByPath = this._bindingsIndicesByPath,
14595            index = indicesByPath[ path ],
14596            bindings = this._bindings;
14597
14598        if ( index !== undefined ) return bindings[ index ];
14599
14600        var paths = this._paths,
14601            parsedPaths = this._parsedPaths,
14602            objects = this._objects,
14603            nObjects = objects.length,
14604            nCachedObjects = this.nCachedObjects_,
14605            bindingsForPath = new Array( nObjects );
14606
14607        index = bindings.length;
14608
14609        indicesByPath[ path ] = index;
14610
14611        paths.push( path );
14612        parsedPaths.push( parsedPath );
14613        bindings.push( bindingsForPath );
14614
14615        for ( var i = nCachedObjects,
14616                  n = objects.length; i !== n; ++ i ) {
14617
14618            var object = objects[ i ];
14619
14620            bindingsForPath[ i ] =
14621                new THREE.PropertyBinding( object, path, parsedPath );
14622
14623        }
14624
14625        return bindingsForPath;
14626
14627    },
14628
14629    unsubscribe_: function( path ) {
14630        // tells the group to forget about a property path and no longer
14631        // update the array previously obtained with 'subscribe_'
14632
14633        var indicesByPath = this._bindingsIndicesByPath,
14634            index = indicesByPath[ path ];
14635
14636        if ( index !== undefined ) {
14637
14638            var paths = this._paths,
14639                parsedPaths = this._parsedPaths,
14640                bindings = this._bindings,
14641                lastBindingsIndex = bindings.length - 1,
14642                lastBindings = bindings[ lastBindingsIndex ],
14643                lastBindingsPath = path[ lastBindingsIndex ];
14644
14645            indicesByPath[ lastBindingsPath ] = index;
14646
14647            bindings[ index ] = lastBindings;
14648            bindings.pop();
14649
14650            parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
14651            parsedPaths.pop();
14652
14653            paths[ index ] = paths[ lastBindingsIndex ];
14654            paths.pop();
14655
14656        }
14657
14658    }
14659
14660};
14661
14662
14663// File:src/animation/AnimationUtils.js
14664
14665/**
14666 * @author tschw
14667 * @author Ben Houston / http://clara.io/
14668 * @author David Sarno / http://lighthaus.us/
14669 */
14670
14671THREE.AnimationUtils = {
14672
14673    // same as Array.prototype.slice, but also works on typed arrays
14674    arraySlice: function( array, from, to ) {
14675
14676        if ( THREE.AnimationUtils.isTypedArray( array ) ) {
14677
14678            return new array.constructor( array.subarray( from, to ) );
14679
14680        }
14681
14682        return array.slice( from, to );
14683
14684    },
14685
14686    // converts an array to a specific type
14687    convertArray: function( array, type, forceClone ) {
14688
14689        if ( ! array || // let 'undefined' and 'null' pass
14690            ! forceClone && array.constructor === type ) return array;
14691
14692        if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
14693
14694            return new type( array ); // create typed array
14695
14696        }
14697
14698        return Array.prototype.slice.call( array ); // create Array
14699
14700    },
14701
14702    isTypedArray: function( object ) {
14703
14704        return ArrayBuffer.isView( object ) &&
14705            ! ( object instanceof DataView );
14706
14707    },
14708
14709    // returns an array by which times and values can be sorted
14710    getKeyframeOrder: function( times ) {
14711
14712        function compareTime( i, j ) {
14713
14714            return times[ i ] - times[ j ];
14715
14716        }
14717
14718        var n = times.length;
14719        var result = new Array( n );
14720        for ( var i = 0; i !== n; ++ i ) result[ i ] = i;
14721
14722        result.sort( compareTime );
14723
14724        return result;
14725
14726    },
14727
14728    // uses the array previously returned by 'getKeyframeOrder' to sort data
14729    sortedArray: function( values, stride, order ) {
14730
14731        var nValues = values.length;
14732        var result = new values.constructor( nValues );
14733
14734        for ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
14735
14736            var srcOffset = order[ i ] * stride;
14737
14738            for ( var j = 0; j !== stride; ++ j ) {
14739
14740                result[ dstOffset ++ ] = values[ srcOffset + j ];
14741
14742            }
14743
14744        }
14745
14746        return result;
14747
14748    },
14749
14750    // function for parsing AOS keyframe formats
14751    flattenJSON: function( jsonKeys, times, values, valuePropertyName ) {
14752
14753        var i = 1, key = jsonKeys[ 0 ];
14754
14755        while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
14756
14757            key = jsonKeys[ i ++ ];
14758
14759        }
14760
14761        if ( key === undefined ) return; // no data
14762
14763        var value = key[ valuePropertyName ];
14764        if ( value === undefined ) return; // no data
14765
14766        if ( Array.isArray( value ) ) {
14767
14768            do {
14769
14770                value = key[ valuePropertyName ];
14771
14772                if ( value !== undefined ) {
14773
14774                    times.push( key.time );
14775                    values.push.apply( values, value ); // push all elements
14776
14777                }
14778
14779                key = jsonKeys[ i ++ ];
14780
14781            } while ( key !== undefined );
14782
14783        } else if ( value.toArray !== undefined ) {
14784            // ...assume THREE.Math-ish
14785
14786            do {
14787
14788                value = key[ valuePropertyName ];
14789
14790                if ( value !== undefined ) {
14791
14792                    times.push( key.time );
14793                    value.toArray( values, values.length );
14794
14795                }
14796
14797                key = jsonKeys[ i ++ ];
14798
14799            } while ( key !== undefined );
14800
14801        } else {
14802            // otherwise push as-is
14803
14804            do {
14805
14806                value = key[ valuePropertyName ];
14807
14808                if ( value !== undefined ) {
14809
14810                    times.push( key.time );
14811                    values.push( value );
14812
14813                }
14814
14815                key = jsonKeys[ i ++ ];
14816
14817            } while ( key !== undefined );
14818
14819        }
14820
14821    }
14822
14823};
14824
14825// File:src/animation/KeyframeTrack.js
14826
14827/**
14828 *
14829 * A timed sequence of keyframes for a specific property.
14830 *
14831 *
14832 * @author Ben Houston / http://clara.io/
14833 * @author David Sarno / http://lighthaus.us/
14834 * @author tschw
14835 */
14836
14837THREE.KeyframeTrack = function ( name, times, values, interpolation ) {
14838
14839    if( name === undefined ) throw new Error( "track name is undefined" );
14840
14841    if( times === undefined || times.length === 0 ) {
14842
14843        throw new Error( "no keyframes in track named " + name );
14844
14845    }
14846
14847    this.name = name;
14848
14849    this.times = THREE.AnimationUtils.convertArray( times, this.TimeBufferType );
14850    this.values = THREE.AnimationUtils.convertArray( values, this.ValueBufferType );
14851
14852    this.setInterpolation( interpolation || this.DefaultInterpolation );
14853
14854    this.validate();
14855    this.optimize();
14856
14857};
14858
14859THREE.KeyframeTrack.prototype = {
14860
14861    constructor: THREE.KeyframeTrack,
14862
14863    TimeBufferType: Float32Array,
14864    ValueBufferType: Float32Array,
14865
14866    DefaultInterpolation: THREE.InterpolateLinear,
14867
14868    InterpolantFactoryMethodDiscrete: function( result ) {
14869
14870        return new THREE.DiscreteInterpolant(
14871            this.times, this.values, this.getValueSize(), result );
14872
14873    },
14874
14875    InterpolantFactoryMethodLinear: function( result ) {
14876
14877        return new THREE.LinearInterpolant(
14878            this.times, this.values, this.getValueSize(), result );
14879
14880    },
14881
14882    InterpolantFactoryMethodSmooth: function( result ) {
14883
14884        return new THREE.CubicInterpolant(
14885            this.times, this.values, this.getValueSize(), result );
14886
14887    },
14888
14889    setInterpolation: function( interpolation ) {
14890
14891        var factoryMethod = undefined;
14892
14893        switch ( interpolation ) {
14894
14895            case THREE.InterpolateDiscrete:
14896
14897                factoryMethod = this.InterpolantFactoryMethodDiscrete;
14898
14899                break;
14900
14901            case THREE.InterpolateLinear:
14902
14903                factoryMethod = this.InterpolantFactoryMethodLinear;
14904
14905                break;
14906
14907            case THREE.InterpolateSmooth:
14908
14909                factoryMethod = this.InterpolantFactoryMethodSmooth;
14910
14911                break;
14912
14913        }
14914
14915        if ( factoryMethod === undefined ) {
14916
14917            var message = "unsupported interpolation for " +
14918                this.ValueTypeName + " keyframe track named " + this.name;
14919
14920            if ( this.createInterpolant === undefined ) {
14921
14922                // fall back to default, unless the default itself is messed up
14923                if ( interpolation !== this.DefaultInterpolation ) {
14924
14925                    this.setInterpolation( this.DefaultInterpolation );
14926
14927                } else {
14928
14929                    throw new Error( message ); // fatal, in this case
14930
14931                }
14932
14933            }
14934
14935            console.warn( message );
14936            return;
14937
14938        }
14939
14940        this.createInterpolant = factoryMethod;
14941
14942    },
14943
14944    getInterpolation: function() {
14945
14946        switch ( this.createInterpolant ) {
14947
14948            case this.InterpolantFactoryMethodDiscrete:
14949
14950                return THREE.InterpolateDiscrete;
14951
14952            case this.InterpolantFactoryMethodLinear:
14953
14954                return THREE.InterpolateLinear;
14955
14956            case this.InterpolantFactoryMethodSmooth:
14957
14958                return THREE.InterpolateSmooth;
14959
14960        }
14961
14962    },
14963
14964    getValueSize: function() {
14965
14966        return this.values.length / this.times.length;
14967
14968    },
14969
14970    // move all keyframes either forwards or backwards in time
14971    shift: function( timeOffset ) {
14972
14973        if( timeOffset !== 0.0 ) {
14974
14975            var times = this.times;
14976
14977            for( var i = 0, n = times.length; i !== n; ++ i ) {
14978
14979                times[ i ] += timeOffset;
14980
14981            }
14982
14983        }
14984
14985        return this;
14986
14987    },
14988
14989    // scale all keyframe times by a factor (useful for frame <-> seconds conversions)
14990    scale: function( timeScale ) {
14991
14992        if( timeScale !== 1.0 ) {
14993
14994            var times = this.times;
14995
14996            for( var i = 0, n = times.length; i !== n; ++ i ) {
14997
14998                times[ i ] *= timeScale;
14999
15000            }
15001
15002        }
15003
15004        return this;
15005
15006    },
15007
15008    // removes keyframes before and after animation without changing any values within the range [startTime, endTime].
15009    // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
15010    trim: function( startTime, endTime ) {
15011
15012        var times = this.times,
15013            nKeys = times.length,
15014            from = 0,
15015            to = nKeys - 1;
15016
15017        while ( from !== nKeys && times[ from ] < startTime ) ++ from;
15018        while ( to !== -1 && times[ to ] > endTime ) -- to;
15019
15020        ++ to; // inclusive -> exclusive bound
15021
15022        if( from !== 0 || to !== nKeys ) {
15023
15024            // empty tracks are forbidden, so keep at least one keyframe
15025            if ( from >= to ) to = Math.max( to , 1 ), from = to - 1;
15026
15027            var stride = this.getValueSize();
15028            this.times = THREE.AnimationUtils.arraySlice( times, from, to );
15029            this.values = THREE.AnimationUtils.
15030                arraySlice( this.values, from * stride, to * stride );
15031
15032        }
15033
15034        return this;
15035
15036    },
15037
15038    // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
15039    validate: function() {
15040
15041        var valid = true;
15042
15043        var valueSize = this.getValueSize();
15044        if ( valueSize - Math.floor( valueSize ) !== 0 ) {
15045
15046            console.error( "invalid value size in track", this );
15047            valid = false;
15048
15049        }
15050
15051        var times = this.times,
15052            values = this.values,
15053
15054            nKeys = times.length;
15055
15056        if( nKeys === 0 ) {
15057
15058            console.error( "track is empty", this );
15059            valid = false;
15060
15061        }
15062
15063        var prevTime = null;
15064
15065        for( var i = 0; i !== nKeys; i ++ ) {
15066
15067            var currTime = times[ i ];
15068
15069            if ( typeof currTime === 'number' && isNaN( currTime ) ) {
15070
15071                console.error( "time is not a valid number", this, i, currTime );
15072                valid = false;
15073                break;
15074
15075            }
15076
15077            if( prevTime !== null && prevTime > currTime ) {
15078
15079                console.error( "out of order keys", this, i, currTime, prevTime );
15080                valid = false;
15081                break;
15082
15083            }
15084
15085            prevTime = currTime;
15086
15087        }
15088
15089        if ( values !== undefined ) {
15090
15091            if ( THREE.AnimationUtils.isTypedArray( values ) ) {
15092
15093                for ( var i = 0, n = values.length; i !== n; ++ i ) {
15094
15095                    var value = values[ i ];
15096
15097                    if ( isNaN( value ) ) {
15098
15099                        console.error( "value is not a valid number", this, i, value );
15100                        valid = false;
15101                        break;
15102
15103                    }
15104
15105                }
15106
15107            }
15108
15109        }
15110
15111        return valid;
15112
15113    },
15114
15115    // removes equivalent sequential keys as common in morph target sequences
15116    // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
15117    optimize: function() {
15118
15119        var times = this.times,
15120            values = this.values,
15121            stride = this.getValueSize(),
15122
15123            writeIndex = 1;
15124
15125        for( var i = 1, n = times.length - 1; i <= n; ++ i ) {
15126
15127            var keep = false;
15128
15129            var time = times[ i ];
15130            var timeNext = times[ i + 1 ];
15131
15132            // remove adjacent keyframes scheduled at the same time
15133
15134            if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {
15135
15136                // remove unnecessary keyframes same as their neighbors
15137                var offset = i * stride,
15138                    offsetP = offset - stride,
15139                    offsetN = offset + stride;
15140
15141                for ( var j = 0; j !== stride; ++ j ) {
15142
15143                    var value = values[ offset + j ];
15144
15145                    if ( value !== values[ offsetP + j ] ||
15146                        value !== values[ offsetN + j ] ) {
15147
15148                        keep = true;
15149                        break;
15150
15151                    }
15152
15153                }
15154
15155            }
15156
15157            // in-place compaction
15158
15159            if ( keep ) {
15160
15161                if ( i !== writeIndex ) {
15162
15163                    times[ writeIndex ] = times[ i ];
15164
15165                    var readOffset = i * stride,
15166                        writeOffset = writeIndex * stride;
15167
15168                    for ( var j = 0; j !== stride; ++ j ) {
15169
15170                        values[ writeOffset + j ] = values[ readOffset + j ];
15171
15172                    }
15173
15174
15175                }
15176
15177                ++ writeIndex;
15178
15179            }
15180
15181        }
15182
15183        if ( writeIndex !== times.length ) {
15184
15185            this.times = THREE.AnimationUtils.arraySlice( times, 0, writeIndex );
15186            this.values = THREE.AnimationUtils.arraySlice( values, 0, writeIndex * stride );
15187
15188        }
15189
15190        return this;
15191
15192    }
15193
15194};
15195
15196// Static methods:
15197
15198Object.assign( THREE.KeyframeTrack, {
15199
15200    // Serialization (in static context, because of constructor invocation
15201    // and automatic invocation of .toJSON):
15202
15203    parse: function( json ) {
15204
15205        if( json.type === undefined ) {
15206
15207            throw new Error( "track type undefined, can not parse" );
15208
15209        }
15210
15211        var trackType = THREE.KeyframeTrack._getTrackTypeForValueTypeName( json.type );
15212
15213        if ( json.times === undefined ) {
15214
15215            console.warn( "legacy JSON format detected, converting" );
15216
15217            var times = [], values = [];
15218
15219            THREE.AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
15220
15221            json.times = times;
15222            json.values = values;
15223
15224        }
15225
15226        // derived classes can define a static parse method
15227        if ( trackType.parse !== undefined ) {
15228
15229            return trackType.parse( json );
15230
15231        } else {
15232
15233            // by default, we asssume a constructor compatible with the base
15234            return new trackType(
15235                json.name, json.times, json.values, json.interpolation );
15236
15237        }
15238
15239    },
15240
15241    toJSON: function( track ) {
15242
15243        var trackType = track.constructor;
15244
15245        var json;
15246
15247        // derived classes can define a static toJSON method
15248        if ( trackType.toJSON !== undefined ) {
15249
15250            json = trackType.toJSON( track );
15251
15252        } else {
15253
15254            // by default, we assume the data can be serialized as-is
15255            json = {
15256
15257                'name': track.name,
15258                'times': THREE.AnimationUtils.convertArray( track.times, Array ),
15259                'values': THREE.AnimationUtils.convertArray( track.values, Array )
15260
15261            };
15262
15263            var interpolation = track.getInterpolation();
15264
15265            if ( interpolation !== track.DefaultInterpolation ) {
15266
15267                json.interpolation = interpolation;
15268
15269            }
15270
15271        }
15272
15273        json.type = track.ValueTypeName; // mandatory
15274
15275        return json;
15276
15277    },
15278
15279    _getTrackTypeForValueTypeName: function( typeName ) {
15280
15281        switch( typeName.toLowerCase() ) {
15282
15283            case "scalar":
15284            case "double":
15285            case "float":
15286            case "number":
15287            case "integer":
15288
15289                return THREE.NumberKeyframeTrack;
15290
15291            case "vector":
15292            case "vector2":
15293            case "vector3":
15294            case "vector4":
15295
15296                return THREE.VectorKeyframeTrack;
15297
15298            case "color":
15299
15300                return THREE.ColorKeyframeTrack;
15301
15302            case "quaternion":
15303
15304                return THREE.QuaternionKeyframeTrack;
15305
15306            case "bool":
15307            case "boolean":
15308
15309                return THREE.BooleanKeyframeTrack;
15310
15311            case "string":
15312
15313                return THREE.StringKeyframeTrack;
15314
15315        };
15316
15317        throw new Error( "Unsupported typeName: " + typeName );
15318
15319    }
15320
15321} );
15322
15323// File:src/animation/PropertyBinding.js
15324
15325/**
15326 *
15327 * A reference to a real property in the scene graph.
15328 *
15329 *
15330 * @author Ben Houston / http://clara.io/
15331 * @author David Sarno / http://lighthaus.us/
15332 * @author tschw
15333 */
15334
15335THREE.PropertyBinding = function ( rootNode, path, parsedPath ) {
15336
15337    this.path = path;
15338    this.parsedPath = parsedPath ||
15339    THREE.PropertyBinding.parseTrackName( path );
15340
15341    this.node = THREE.PropertyBinding.findNode(
15342        rootNode, this.parsedPath.nodeName ) || rootNode;
15343
15344    this.rootNode = rootNode;
15345
15346};
15347
15348THREE.PropertyBinding.prototype = {
15349
15350    constructor: THREE.PropertyBinding,
15351
15352    getValue: function getValue_unbound( targetArray, offset ) {
15353
15354        this.bind();
15355        this.getValue( targetArray, offset );
15356
15357        // Note: This class uses a State pattern on a per-method basis:
15358        // 'bind' sets 'this.getValue' / 'setValue' and shadows the
15359        // prototype version of these methods with one that represents
15360        // the bound state. When the property is not found, the methods
15361        // become no-ops.
15362
15363    },
15364
15365    setValue: function getValue_unbound( sourceArray, offset ) {
15366
15367        this.bind();
15368        this.setValue( sourceArray, offset );
15369
15370    },
15371
15372    // create getter / setter pair for a property in the scene graph
15373    bind: function() {
15374
15375        var targetObject = this.node,
15376            parsedPath = this.parsedPath,
15377
15378            objectName = parsedPath.objectName,
15379            propertyName = parsedPath.propertyName,
15380            propertyIndex = parsedPath.propertyIndex;
15381
15382        if ( ! targetObject ) {
15383
15384            targetObject = THREE.PropertyBinding.findNode(
15385                this.rootNode, parsedPath.nodeName ) || this.rootNode;
15386
15387            this.node = targetObject;
15388
15389        }
15390
15391        // set fail state so we can just 'return' on error
15392        this.getValue = this._getValue_unavailable;
15393        this.setValue = this._setValue_unavailable;
15394
15395        // ensure there is a value node
15396        if ( ! targetObject ) {
15397
15398            console.error( "  trying to update node for track: " + this.path + " but it wasn't found." );
15399            return;
15400
15401        }
15402
15403        if( objectName ) {
15404
15405            var objectIndex = parsedPath.objectIndex;
15406
15407            // special cases were we need to reach deeper into the hierarchy to get the face materials....
15408            switch ( objectName ) {
15409
15410                case 'materials':
15411
15412                    if( ! targetObject.material ) {
15413
15414                        console.error( '  can not bind to material as node does not have a material', this );
15415                        return;
15416
15417                    }
15418
15419                    if( ! targetObject.material.materials ) {
15420
15421                        console.error( '  can not bind to material.materials as node.material does not have a materials array', this );
15422                        return;
15423
15424                    }
15425
15426                    targetObject = targetObject.material.materials;
15427
15428                    break;
15429
15430                case 'bones':
15431
15432                    if( ! targetObject.skeleton ) {
15433
15434                        console.error( '  can not bind to bones as node does not have a skeleton', this );
15435                        return;
15436
15437                    }
15438
15439                    // potential future optimization: skip this if propertyIndex is already an integer
15440                    // and convert the integer string to a true integer.
15441
15442                    targetObject = targetObject.skeleton.bones;
15443
15444                    // support resolving morphTarget names into indices.
15445                    for ( var i = 0; i < targetObject.length; i ++ ) {
15446
15447                        if ( targetObject[i].name === objectIndex ) {
15448
15449                            objectIndex = i;
15450                            break;
15451
15452                        }
15453
15454                    }
15455
15456                    break;
15457
15458                default:
15459
15460                    if ( targetObject[ objectName ] === undefined ) {
15461
15462                        console.error( '  can not bind to objectName of node, undefined', this );
15463                        return;
15464
15465                    }
15466
15467                    targetObject = targetObject[ objectName ];
15468
15469            }
15470
15471
15472            if ( objectIndex !== undefined ) {
15473
15474                if( targetObject[ objectIndex ] === undefined ) {
15475
15476                    console.error( "  trying to bind to objectIndex of objectName, but is undefined:", this, targetObject );
15477                    return;
15478
15479                }
15480
15481                targetObject = targetObject[ objectIndex ];
15482
15483            }
15484
15485        }
15486
15487        // resolve property
15488        var nodeProperty = targetObject[ propertyName ];
15489
15490        if ( ! nodeProperty ) {
15491
15492            var nodeName = parsedPath.nodeName;
15493
15494            console.error( "  trying to update property for track: " + nodeName +
15495            '.' + propertyName + " but it wasn't found.", targetObject );
15496            return;
15497
15498        }
15499
15500        // determine versioning scheme
15501        var versioning = this.Versioning.None;
15502
15503        if ( targetObject.needsUpdate !== undefined ) { // material
15504
15505            versioning = this.Versioning.NeedsUpdate;
15506            this.targetObject = targetObject;
15507
15508        } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
15509
15510            versioning = this.Versioning.MatrixWorldNeedsUpdate;
15511            this.targetObject = targetObject;
15512
15513        }
15514
15515        // determine how the property gets bound
15516        var bindingType = this.BindingType.Direct;
15517
15518        if ( propertyIndex !== undefined ) {
15519            // access a sub element of the property array (only primitives are supported right now)
15520
15521            if ( propertyName === "morphTargetInfluences" ) {
15522                // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
15523
15524                // support resolving morphTarget names into indices.
15525                if ( ! targetObject.geometry ) {
15526
15527                    console.error( '  can not bind to morphTargetInfluences becasuse node does not have a geometry', this );
15528                    return;
15529
15530                }
15531
15532                if ( ! targetObject.geometry.morphTargets ) {
15533
15534                    console.error( '  can not bind to morphTargetInfluences becasuse node does not have a geometry.morphTargets', this );
15535                    return;
15536
15537                }
15538
15539                for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) {
15540
15541                    if ( targetObject.geometry.morphTargets[i].name === propertyIndex ) {
15542
15543                        propertyIndex = i;
15544                        break;
15545
15546                    }
15547
15548                }
15549
15550            }
15551
15552            bindingType = this.BindingType.ArrayElement;
15553
15554            this.resolvedProperty = nodeProperty;
15555            this.propertyIndex = propertyIndex;
15556
15557        } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
15558            // must use copy for Object3D.Euler/Quaternion
15559
15560            bindingType = this.BindingType.HasFromToArray;
15561
15562            this.resolvedProperty = nodeProperty;
15563
15564        } else if ( nodeProperty.length !== undefined ) {
15565
15566            bindingType = this.BindingType.EntireArray;
15567
15568            this.resolvedProperty = nodeProperty;
15569
15570        } else {
15571
15572            this.propertyName = propertyName;
15573
15574        }
15575
15576        // select getter / setter
15577        this.getValue = this.GetterByBindingType[ bindingType ];
15578        this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
15579
15580    },
15581
15582    unbind: function() {
15583
15584        this.node = null;
15585
15586        // back to the prototype version of getValue / setValue
15587        // note: avoiding to mutate the shape of 'this' via 'delete'
15588        this.getValue = this._getValue_unbound;
15589        this.setValue = this._setValue_unbound;
15590
15591    }
15592
15593};
15594
15595Object.assign( THREE.PropertyBinding.prototype, { // prototype, continued
15596
15597    // these are used to "bind" a nonexistent property
15598    _getValue_unavailable: function() {},
15599    _setValue_unavailable: function() {},
15600
15601    // initial state of these methods that calls 'bind'
15602    _getValue_unbound: THREE.PropertyBinding.prototype.getValue,
15603    _setValue_unbound: THREE.PropertyBinding.prototype.setValue,
15604
15605    BindingType: {
15606        Direct: 0,
15607        EntireArray: 1,
15608        ArrayElement: 2,
15609        HasFromToArray: 3
15610    },
15611
15612    Versioning: {
15613        None: 0,
15614        NeedsUpdate: 1,
15615        MatrixWorldNeedsUpdate: 2
15616    },
15617
15618    GetterByBindingType: [
15619
15620        function getValue_direct( buffer, offset ) {
15621
15622            buffer[ offset ] = this.node[ this.propertyName ];
15623
15624        },
15625
15626        function getValue_array( buffer, offset ) {
15627
15628            var source = this.resolvedProperty;
15629
15630            for ( var i = 0, n = source.length; i !== n; ++ i ) {
15631
15632                buffer[ offset ++ ] = source[ i ];
15633
15634            }
15635
15636        },
15637
15638        function getValue_arrayElement( buffer, offset ) {
15639
15640            buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
15641
15642        },
15643
15644        function getValue_toArray( buffer, offset ) {
15645
15646            this.resolvedProperty.toArray( buffer, offset );
15647
15648        }
15649
15650    ],
15651
15652    SetterByBindingTypeAndVersioning: [
15653
15654        [
15655            // Direct
15656
15657            function setValue_direct( buffer, offset ) {
15658
15659                this.node[ this.propertyName ] = buffer[ offset ];
15660
15661            },
15662
15663            function setValue_direct_setNeedsUpdate( buffer, offset ) {
15664
15665                this.node[ this.propertyName ] = buffer[ offset ];
15666                this.targetObject.needsUpdate = true;
15667
15668            },
15669
15670            function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
15671
15672                this.node[ this.propertyName ] = buffer[ offset ];
15673                this.targetObject.matrixWorldNeedsUpdate = true;
15674
15675            }
15676
15677        ], [
15678
15679            // EntireArray
15680
15681            function setValue_array( buffer, offset ) {
15682
15683                var dest = this.resolvedProperty;
15684
15685                for ( var i = 0, n = dest.length; i !== n; ++ i ) {
15686
15687                    dest[ i ] = buffer[ offset ++ ];
15688
15689                }
15690
15691            },
15692
15693            function setValue_array_setNeedsUpdate( buffer, offset ) {
15694
15695                var dest = this.resolvedProperty;
15696
15697                for ( var i = 0, n = dest.length; i !== n; ++ i ) {
15698
15699                    dest[ i ] = buffer[ offset ++ ];
15700
15701                }
15702
15703                this.targetObject.needsUpdate = true;
15704
15705            },
15706
15707            function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
15708
15709                var dest = this.resolvedProperty;
15710
15711                for ( var i = 0, n = dest.length; i !== n; ++ i ) {
15712
15713                    dest[ i ] = buffer[ offset ++ ];
15714
15715                }
15716
15717                this.targetObject.matrixWorldNeedsUpdate = true;
15718
15719            }
15720
15721        ], [
15722
15723            // ArrayElement
15724
15725            function setValue_arrayElement( buffer, offset ) {
15726
15727                this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
15728
15729            },
15730
15731            function setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
15732
15733                this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
15734                this.targetObject.needsUpdate = true;
15735
15736            },
15737
15738            function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
15739
15740                this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
15741                this.targetObject.matrixWorldNeedsUpdate = true;
15742
15743            }
15744
15745        ], [
15746
15747            // HasToFromArray
15748
15749            function setValue_fromArray( buffer, offset ) {
15750
15751                this.resolvedProperty.fromArray( buffer, offset );
15752
15753            },
15754
15755            function setValue_fromArray_setNeedsUpdate( buffer, offset ) {
15756
15757                this.resolvedProperty.fromArray( buffer, offset );
15758                this.targetObject.needsUpdate = true;
15759
15760            },
15761
15762            function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
15763
15764                this.resolvedProperty.fromArray( buffer, offset );
15765                this.targetObject.matrixWorldNeedsUpdate = true;
15766
15767            }
15768
15769        ]
15770
15771    ]
15772
15773} );
15774
15775THREE.PropertyBinding.Composite =
15776    function( targetGroup, path, optionalParsedPath ) {
15777
15778        var parsedPath = optionalParsedPath ||
15779            THREE.PropertyBinding.parseTrackName( path );
15780
15781        this._targetGroup = targetGroup;
15782        this._bindings = targetGroup.subscribe_( path, parsedPath );
15783
15784    };
15785
15786THREE.PropertyBinding.Composite.prototype = {
15787
15788    constructor: THREE.PropertyBinding.Composite,
15789
15790    getValue: function( array, offset ) {
15791
15792        this.bind(); // bind all binding
15793
15794        var firstValidIndex = this._targetGroup.nCachedObjects_,
15795            binding = this._bindings[ firstValidIndex ];
15796
15797        // and only call .getValue on the first
15798        if ( binding !== undefined ) binding.getValue( array, offset );
15799
15800    },
15801
15802    setValue: function( array, offset ) {
15803
15804        var bindings = this._bindings;
15805
15806        for ( var i = this._targetGroup.nCachedObjects_,
15807                  n = bindings.length; i !== n; ++ i ) {
15808
15809            bindings[ i ].setValue( array, offset );
15810
15811        }
15812
15813    },
15814
15815    bind: function() {
15816
15817        var bindings = this._bindings;
15818
15819        for ( var i = this._targetGroup.nCachedObjects_,
15820                  n = bindings.length; i !== n; ++ i ) {
15821
15822            bindings[ i ].bind();
15823
15824        }
15825
15826    },
15827
15828    unbind: function() {
15829
15830        var bindings = this._bindings;
15831
15832        for ( var i = this._targetGroup.nCachedObjects_,
15833                  n = bindings.length; i !== n; ++ i ) {
15834
15835            bindings[ i ].unbind();
15836
15837        }
15838
15839    }
15840
15841};
15842
15843THREE.PropertyBinding.create = function( root, path, parsedPath ) {
15844
15845    if ( ! ( root instanceof THREE.AnimationObjectGroup ) ) {
15846
15847        return new THREE.PropertyBinding( root, path, parsedPath );
15848
15849    } else {
15850
15851        return new THREE.PropertyBinding.Composite( root, path, parsedPath );
15852
15853    }
15854
15855};
15856
15857THREE.PropertyBinding.parseTrackName = function( trackName ) {
15858
15859    // matches strings in the form of:
15860    //    nodeName.property
15861    //    nodeName.property[accessor]
15862    //    nodeName.material.property[accessor]
15863    //    uuid.property[accessor]
15864    //    uuid.objectName[objectIndex].propertyName[propertyIndex]
15865    //    parentName/nodeName.property
15866    //    parentName/parentName/nodeName.property[index]
15867    //	  .bone[Armature.DEF_cog].position
15868    // created and tested via https://regex101.com/#javascript
15869
15870    var re = /^(([\w]+\/)*)([\w-\d]+)?(\.([\w]+)(\[([\w\d\[\]\_.:\- ]+)\])?)?(\.([\w.]+)(\[([\w\d\[\]\_. ]+)\])?)$/;
15871    var matches = re.exec(trackName);
15872
15873    if( ! matches ) {
15874        throw new Error( "cannot parse trackName at all: " + trackName );
15875    }
15876
15877    if (matches.index === re.lastIndex) {
15878        re.lastIndex++;
15879    }
15880
15881    var results = {
15882        // directoryName: matches[1], // (tschw) currently unused
15883        nodeName: matches[3], 	// allowed to be null, specified root node.
15884        objectName: matches[5],
15885        objectIndex: matches[7],
15886        propertyName: matches[9],
15887        propertyIndex: matches[11]	// allowed to be null, specifies that the whole property is set.
15888    };
15889
15890    if( results.propertyName === null || results.propertyName.length === 0 ) {
15891        throw new Error( "can not parse propertyName from trackName: " + trackName );
15892    }
15893
15894    return results;
15895
15896};
15897
15898THREE.PropertyBinding.findNode = function( root, nodeName ) {
15899
15900    if( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === -1 || nodeName === root.name || nodeName === root.uuid ) {
15901
15902        return root;
15903
15904    }
15905
15906    // search into skeleton bones.
15907    if( root.skeleton ) {
15908
15909        var searchSkeleton = function( skeleton ) {
15910
15911            for( var i = 0; i < skeleton.bones.length; i ++ ) {
15912
15913                var bone = skeleton.bones[i];
15914
15915                if( bone.name === nodeName ) {
15916
15917                    return bone;
15918
15919                }
15920            }
15921
15922            return null;
15923
15924        };
15925
15926        var bone = searchSkeleton( root.skeleton );
15927
15928        if( bone ) {
15929
15930            return bone;
15931
15932        }
15933    }
15934
15935    // search into node subtree.
15936    if( root.children ) {
15937
15938        var searchNodeSubtree = function( children ) {
15939
15940            for( var i = 0; i < children.length; i ++ ) {
15941
15942                var childNode = children[i];
15943
15944                if( childNode.name === nodeName || childNode.uuid === nodeName ) {
15945
15946                    return childNode;
15947
15948                }
15949
15950                var result = searchNodeSubtree( childNode.children );
15951
15952                if( result ) return result;
15953
15954            }
15955
15956            return null;
15957
15958        };
15959
15960        var subTreeNode = searchNodeSubtree( root.children );
15961
15962        if( subTreeNode ) {
15963
15964            return subTreeNode;
15965
15966        }
15967
15968    }
15969
15970    return null;
15971
15972}
15973
15974// File:src/animation/PropertyMixer.js
15975
15976/**
15977 *
15978 * Buffered scene graph property that allows weighted accumulation.
15979 *
15980 *
15981 * @author Ben Houston / http://clara.io/
15982 * @author David Sarno / http://lighthaus.us/
15983 * @author tschw
15984 */
15985
15986THREE.PropertyMixer = function ( binding, typeName, valueSize ) {
15987
15988    this.binding = binding;
15989    this.valueSize = valueSize;
15990
15991    var bufferType = Float64Array,
15992        mixFunction;
15993
15994    switch ( typeName ) {
15995
15996        case 'quaternion':			mixFunction = this._slerp;		break;
15997
15998        case 'string':
15999        case 'bool':
16000
16001            bufferType = Array,		mixFunction = this._select;		break;
16002
16003        default:					mixFunction = this._lerp;
16004
16005    }
16006
16007    this.buffer = new bufferType( valueSize * 4 );
16008    // layout: [ incoming | accu0 | accu1 | orig ]
16009    //
16010    // interpolators can use .buffer as their .result
16011    // the data then goes to 'incoming'
16012    //
16013    // 'accu0' and 'accu1' are used frame-interleaved for
16014    // the cumulative result and are compared to detect
16015    // changes
16016    //
16017    // 'orig' stores the original state of the property
16018
16019    this._mixBufferRegion = mixFunction;
16020
16021    this.cumulativeWeight = 0;
16022
16023    this.useCount = 0;
16024    this.referenceCount = 0;
16025
16026};
16027
16028THREE.PropertyMixer.prototype = {
16029
16030    constructor: THREE.PropertyMixer,
16031
16032    // accumulate data in the 'incoming' region into 'accu<i>'
16033    accumulate: function( accuIndex, weight ) {
16034
16035        // note: happily accumulating nothing when weight = 0, the caller knows
16036        // the weight and shouldn't have made the call in the first place
16037
16038        var buffer = this.buffer,
16039            stride = this.valueSize,
16040            offset = accuIndex * stride + stride,
16041
16042            currentWeight = this.cumulativeWeight;
16043
16044        if ( currentWeight === 0 ) {
16045
16046            // accuN := incoming * weight
16047
16048            for ( var i = 0; i !== stride; ++ i ) {
16049
16050                buffer[ offset + i ] = buffer[ i ];
16051
16052            }
16053
16054            currentWeight = weight;
16055
16056        } else {
16057
16058            // accuN := accuN + incoming * weight
16059
16060            currentWeight += weight;
16061            var mix = weight / currentWeight;
16062            this._mixBufferRegion( buffer, offset, 0, mix, stride );
16063
16064        }
16065
16066        this.cumulativeWeight = currentWeight;
16067
16068    },
16069
16070    // apply the state of 'accu<i>' to the binding when accus differ
16071    apply: function( accuIndex ) {
16072
16073        var stride = this.valueSize,
16074            buffer = this.buffer,
16075            offset = accuIndex * stride + stride,
16076
16077            weight = this.cumulativeWeight,
16078
16079            binding = this.binding;
16080
16081        this.cumulativeWeight = 0;
16082
16083        if ( weight < 1 ) {
16084
16085            // accuN := accuN + original * ( 1 - cumulativeWeight )
16086
16087            var originalValueOffset = stride * 3;
16088
16089            this._mixBufferRegion(
16090                buffer, offset, originalValueOffset, 1 - weight, stride );
16091
16092        }
16093
16094        for ( var i = stride, e = stride + stride; i !== e; ++ i ) {
16095
16096            if ( buffer[ i ] !== buffer[ i + stride ] ) {
16097
16098                // value has changed -> update scene graph
16099
16100                binding.setValue( buffer, offset );
16101                break;
16102
16103            }
16104
16105        }
16106
16107    },
16108
16109    // remember the state of the bound property and copy it to both accus
16110    saveOriginalState: function() {
16111
16112        var binding = this.binding;
16113
16114        var buffer = this.buffer,
16115            stride = this.valueSize,
16116
16117            originalValueOffset = stride * 3;
16118
16119        binding.getValue( buffer, originalValueOffset );
16120
16121        // accu[0..1] := orig -- initially detect changes against the original
16122        for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) {
16123
16124            buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
16125
16126        }
16127
16128        this.cumulativeWeight = 0;
16129
16130    },
16131
16132    // apply the state previously taken via 'saveOriginalState' to the binding
16133    restoreOriginalState: function() {
16134
16135        var originalValueOffset = this.valueSize * 3;
16136        this.binding.setValue( this.buffer, originalValueOffset );
16137
16138    },
16139
16140
16141    // mix functions
16142
16143    _select: function( buffer, dstOffset, srcOffset, t, stride ) {
16144
16145        if ( t >= 0.5 ) {
16146
16147            for ( var i = 0; i !== stride; ++ i ) {
16148
16149                buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
16150
16151            }
16152
16153        }
16154
16155    },
16156
16157    _slerp: function( buffer, dstOffset, srcOffset, t, stride ) {
16158
16159        THREE.Quaternion.slerpFlat( buffer, dstOffset,
16160            buffer, dstOffset, buffer, srcOffset, t );
16161
16162    },
16163
16164    _lerp: function( buffer, dstOffset, srcOffset, t, stride ) {
16165
16166        var s = 1 - t;
16167
16168        for ( var i = 0; i !== stride; ++ i ) {
16169
16170            var j = dstOffset + i;
16171
16172            buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
16173
16174        }
16175
16176    }
16177
16178};
16179
16180// File:src/animation/tracks/BooleanKeyframeTrack.js
16181
16182/**
16183 *
16184 * A Track of Boolean keyframe values.
16185 *
16186 *
16187 * @author Ben Houston / http://clara.io/
16188 * @author David Sarno / http://lighthaus.us/
16189 * @author tschw
16190 */
16191
16192THREE.BooleanKeyframeTrack = function ( name, times, values ) {
16193
16194    THREE.KeyframeTrack.call( this, name, times, values );
16195
16196};
16197
16198THREE.BooleanKeyframeTrack.prototype =
16199    Object.assign( Object.create( THREE.KeyframeTrack.prototype ), {
16200
16201        constructor: THREE.BooleanKeyframeTrack,
16202
16203        ValueTypeName: 'bool',
16204        ValueBufferType: Array,
16205
16206        DefaultInterpolation: THREE.InterpolateDiscrete,
16207
16208        InterpolantFactoryMethodLinear: undefined,
16209        InterpolantFactoryMethodSmooth: undefined
16210
16211        // Note: Actually this track could have a optimized / compressed
16212        // representation of a single value and a custom interpolant that
16213        // computes "firstValue ^ isOdd( index )".
16214
16215    } );
16216
16217// File:src/animation/tracks/ColorKeyframeTrack.js
16218
16219/**
16220 *
16221 * A Track of keyframe values that represent color.
16222 *
16223 *
16224 * @author Ben Houston / http://clara.io/
16225 * @author David Sarno / http://lighthaus.us/
16226 * @author tschw
16227 */
16228
16229THREE.ColorKeyframeTrack = function ( name, times, values, interpolation ) {
16230
16231    THREE.KeyframeTrack.call( this, name, times, values, interpolation );
16232
16233};
16234
16235THREE.ColorKeyframeTrack.prototype =
16236    Object.assign( Object.create( THREE.KeyframeTrack.prototype ), {
16237
16238        constructor: THREE.ColorKeyframeTrack,
16239
16240        ValueTypeName: 'color'
16241
16242        // ValueBufferType is inherited
16243
16244        // DefaultInterpolation is inherited
16245
16246
16247        // Note: Very basic implementation and nothing special yet.
16248        // However, this is the place for color space parameterization.
16249
16250    } );
16251
16252// File:src/animation/tracks/NumberKeyframeTrack.js
16253
16254/**
16255 *
16256 * A Track of numeric keyframe values.
16257 *
16258 * @author Ben Houston / http://clara.io/
16259 * @author David Sarno / http://lighthaus.us/
16260 * @author tschw
16261 */
16262
16263THREE.NumberKeyframeTrack = function ( name, times, values, interpolation ) {
16264
16265    THREE.KeyframeTrack.call( this, name, times, values, interpolation );
16266
16267};
16268
16269THREE.NumberKeyframeTrack.prototype =
16270    Object.assign( Object.create( THREE.KeyframeTrack.prototype ), {
16271
16272        constructor: THREE.NumberKeyframeTrack,
16273
16274        ValueTypeName: 'number',
16275
16276        // ValueBufferType is inherited
16277
16278        // DefaultInterpolation is inherited
16279
16280    } );
16281
16282// File:src/animation/tracks/QuaternionKeyframeTrack.js
16283
16284/**
16285 *
16286 * A Track of quaternion keyframe values.
16287 *
16288 * @author Ben Houston / http://clara.io/
16289 * @author David Sarno / http://lighthaus.us/
16290 * @author tschw
16291 */
16292
16293THREE.QuaternionKeyframeTrack = function ( name, times, values, interpolation ) {
16294
16295    THREE.KeyframeTrack.call( this, name, times, values, interpolation );
16296
16297};
16298
16299THREE.QuaternionKeyframeTrack.prototype =
16300    Object.assign( Object.create( THREE.KeyframeTrack.prototype ), {
16301
16302        constructor: THREE.QuaternionKeyframeTrack,
16303
16304        ValueTypeName: 'quaternion',
16305
16306        // ValueBufferType is inherited
16307
16308        DefaultInterpolation: THREE.InterpolateLinear,
16309
16310        InterpolantFactoryMethodLinear: function( result ) {
16311
16312            return new THREE.QuaternionLinearInterpolant(
16313                this.times, this.values, this.getValueSize(), result );
16314
16315        },
16316
16317        InterpolantFactoryMethodSmooth: undefined // not yet implemented
16318
16319    } );
16320
16321// File:src/animation/tracks/StringKeyframeTrack.js
16322
16323/**
16324 *
16325 * A Track that interpolates Strings
16326 *
16327 *
16328 * @author Ben Houston / http://clara.io/
16329 * @author David Sarno / http://lighthaus.us/
16330 * @author tschw
16331 */
16332
16333THREE.StringKeyframeTrack = function ( name, times, values, interpolation ) {
16334
16335    THREE.KeyframeTrack.call( this, name, times, values, interpolation );
16336
16337};
16338
16339THREE.StringKeyframeTrack.prototype =
16340    Object.assign( Object.create( THREE.KeyframeTrack.prototype ), {
16341
16342        constructor: THREE.StringKeyframeTrack,
16343
16344        ValueTypeName: 'string',
16345        ValueBufferType: Array,
16346
16347        DefaultInterpolation: THREE.InterpolateDiscrete,
16348
16349        InterpolantFactoryMethodLinear: undefined,
16350
16351        InterpolantFactoryMethodSmooth: undefined
16352
16353    } );
16354
16355// File:src/animation/tracks/VectorKeyframeTrack.js
16356
16357/**
16358 *
16359 * A Track of vectored keyframe values.
16360 *
16361 *
16362 * @author Ben Houston / http://clara.io/
16363 * @author David Sarno / http://lighthaus.us/
16364 * @author tschw
16365 */
16366
16367THREE.VectorKeyframeTrack = function ( name, times, values, interpolation ) {
16368
16369    THREE.KeyframeTrack.call( this, name, times, values, interpolation );
16370
16371};
16372
16373THREE.VectorKeyframeTrack.prototype =
16374    Object.assign( Object.create( THREE.KeyframeTrack.prototype ), {
16375
16376        constructor: THREE.VectorKeyframeTrack,
16377
16378        ValueTypeName: 'vector'
16379
16380        // ValueBufferType is inherited
16381
16382        // DefaultInterpolation is inherited
16383
16384    } );
16385
16386// File:src/audio/Audio.js
16387
16388/**
16389 * @author mrdoob / http://mrdoob.com/
16390 * @author Reece Aaron Lecrivain / http://reecenotes.com/
16391 */
16392
16393THREE.Audio = function ( listener ) {
16394
16395    THREE.Object3D.call( this );
16396
16397    this.type = 'Audio';
16398
16399    this.context = listener.context;
16400    this.source = this.context.createBufferSource();
16401    this.source.onended = this.onEnded.bind( this );
16402
16403    this.gain = this.context.createGain();
16404    this.gain.connect( listener.getInput() );
16405
16406    this.autoplay = false;
16407
16408    this.startTime = 0;
16409    this.playbackRate = 1;
16410    this.isPlaying = false;
16411    this.hasPlaybackControl = true;
16412    this.sourceType = 'empty';
16413
16414    this.filter = null;
16415
16416};
16417
16418THREE.Audio.prototype = Object.create( THREE.Object3D.prototype );
16419THREE.Audio.prototype.constructor = THREE.Audio;
16420
16421THREE.Audio.prototype.getOutput = function () {
16422
16423    return this.gain;
16424
16425};
16426
16427THREE.Audio.prototype.setNodeSource = function ( audioNode ) {
16428
16429    this.hasPlaybackControl = false;
16430    this.sourceType = 'audioNode';
16431    this.source = audioNode;
16432    this.connect();
16433
16434    return this;
16435
16436};
16437
16438THREE.Audio.prototype.setBuffer = function ( audioBuffer ) {
16439
16440    var scope = this;
16441
16442    scope.source.buffer = audioBuffer;
16443    scope.sourceType = 'buffer';
16444    if ( scope.autoplay ) scope.play();
16445
16446    return this;
16447
16448};
16449
16450THREE.Audio.prototype.play = function () {
16451
16452    if ( this.isPlaying === true ) {
16453
16454        console.warn( 'THREE.Audio: Audio is already playing.' );
16455        return;
16456
16457    }
16458
16459    if ( this.hasPlaybackControl === false ) {
16460
16461        console.warn( 'THREE.Audio: this Audio has no playback control.' );
16462        return;
16463
16464    }
16465
16466    var source = this.context.createBufferSource();
16467
16468    source.buffer = this.source.buffer;
16469    source.loop = this.source.loop;
16470    source.onended = this.source.onended;
16471    source.start( 0, this.startTime );
16472    source.playbackRate.value = this.playbackRate;
16473
16474    this.isPlaying = true;
16475
16476    this.source = source;
16477
16478    this.connect();
16479
16480};
16481
16482THREE.Audio.prototype.pause = function () {
16483
16484    if ( this.hasPlaybackControl === false ) {
16485
16486        console.warn( 'THREE.Audio: this Audio has no playback control.' );
16487        return;
16488
16489    }
16490
16491    this.source.stop();
16492    this.startTime = this.context.currentTime;
16493
16494};
16495
16496THREE.Audio.prototype.stop = function () {
16497
16498    if ( this.hasPlaybackControl === false ) {
16499
16500        console.warn( 'THREE.Audio: this Audio has no playback control.' );
16501        return;
16502
16503    }
16504
16505    this.source.stop();
16506    this.startTime = 0;
16507
16508};
16509
16510THREE.Audio.prototype.connect = function () {
16511
16512    if ( this.filter !== null ) {
16513
16514        this.source.connect( this.filter );
16515        this.filter.connect( this.getOutput() );
16516
16517    } else {
16518
16519        this.source.connect( this.getOutput() );
16520
16521    }
16522
16523};
16524
16525THREE.Audio.prototype.disconnect = function () {
16526
16527    if ( this.filter !== null ) {
16528
16529        this.source.disconnect( this.filter );
16530        this.filter.disconnect( this.getOutput() );
16531
16532    } else {
16533
16534        this.source.disconnect( this.getOutput() );
16535
16536    }
16537
16538};
16539
16540THREE.Audio.prototype.getFilter = function () {
16541
16542    return this.filter;
16543
16544};
16545
16546THREE.Audio.prototype.setFilter = function ( value ) {
16547
16548    if ( value === undefined ) value = null;
16549
16550    if ( this.isPlaying === true ) {
16551
16552        this.disconnect();
16553        this.filter = value;
16554        this.connect();
16555
16556    } else {
16557
16558        this.filter = value;
16559
16560    }
16561
16562};
16563
16564THREE.Audio.prototype.setPlaybackRate = function ( value ) {
16565
16566    if ( this.hasPlaybackControl === false ) {
16567
16568        console.warn( 'THREE.Audio: this Audio has no playback control.' );
16569        return;
16570
16571    }
16572
16573    this.playbackRate = value;
16574
16575    if ( this.isPlaying === true ) {
16576
16577        this.source.playbackRate.value = this.playbackRate;
16578
16579    }
16580
16581};
16582
16583THREE.Audio.prototype.getPlaybackRate = function () {
16584
16585    return this.playbackRate;
16586
16587};
16588
16589THREE.Audio.prototype.onEnded = function () {
16590
16591    this.isPlaying = false;
16592
16593};
16594
16595THREE.Audio.prototype.setLoop = function ( value ) {
16596
16597    if ( this.hasPlaybackControl === false ) {
16598
16599        console.warn( 'THREE.Audio: this Audio has no playback control.' );
16600        return;
16601
16602    }
16603
16604    this.source.loop = value;
16605
16606};
16607
16608THREE.Audio.prototype.getLoop = function () {
16609
16610    if ( this.hasPlaybackControl === false ) {
16611
16612        console.warn( 'THREE.Audio: this Audio has no playback control.' );
16613        return false;
16614
16615    }
16616
16617    return this.source.loop;
16618
16619};
16620
16621
16622THREE.Audio.prototype.setVolume = function ( value ) {
16623
16624    this.gain.gain.value = value;
16625
16626};
16627
16628THREE.Audio.prototype.getVolume = function () {
16629
16630    return this.gain.gain.value;
16631
16632};
16633
16634// File:src/audio/AudioAnalyser.js
16635
16636/**
16637 * @author mrdoob / http://mrdoob.com/
16638 */
16639
16640THREE.AudioAnalyser = function ( audio, fftSize ) {
16641
16642    this.analyser = audio.context.createAnalyser();
16643    this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;
16644
16645    this.data = new Uint8Array( this.analyser.frequencyBinCount );
16646
16647    audio.getOutput().connect( this.analyser );
16648
16649};
16650
16651THREE.AudioAnalyser.prototype = {
16652
16653    constructor: THREE.AudioAnalyser,
16654
16655    getData: function () {
16656
16657        this.analyser.getByteFrequencyData( this.data );
16658        return this.data;
16659
16660    }
16661
16662};
16663
16664// File:src/audio/AudioContext.js
16665
16666/**
16667 * @author mrdoob / http://mrdoob.com/
16668 */
16669
16670Object.defineProperty( THREE, 'AudioContext', {
16671
16672    get: ( function () {
16673
16674        var context;
16675
16676        return function () {
16677
16678            if ( context === undefined ) {
16679
16680                context = new ( window.AudioContext || window.webkitAudioContext )();
16681
16682            }
16683
16684            return context;
16685
16686        };
16687
16688    } )()
16689
16690} );
16691
16692// File:src/audio/PositionalAudio.js
16693
16694/**
16695 * @author mrdoob / http://mrdoob.com/
16696 */
16697
16698THREE.PositionalAudio = function ( listener ) {
16699
16700    THREE.Audio.call( this, listener );
16701
16702    this.panner = this.context.createPanner();
16703    this.panner.connect( this.gain );
16704
16705};
16706
16707THREE.PositionalAudio.prototype = Object.create( THREE.Audio.prototype );
16708THREE.PositionalAudio.prototype.constructor = THREE.PositionalAudio;
16709
16710THREE.PositionalAudio.prototype.getOutput = function () {
16711
16712    return this.panner;
16713
16714};
16715
16716THREE.PositionalAudio.prototype.setRefDistance = function ( value ) {
16717
16718    this.panner.refDistance = value;
16719
16720};
16721
16722THREE.PositionalAudio.prototype.getRefDistance = function () {
16723
16724    return this.panner.refDistance;
16725
16726};
16727
16728THREE.PositionalAudio.prototype.setRolloffFactor = function ( value ) {
16729
16730    this.panner.rolloffFactor = value;
16731
16732};
16733
16734THREE.PositionalAudio.prototype.getRolloffFactor = function () {
16735
16736    return this.panner.rolloffFactor;
16737
16738};
16739
16740THREE.PositionalAudio.prototype.setDistanceModel = function ( value ) {
16741
16742    this.panner.distanceModel = value;
16743
16744};
16745
16746THREE.PositionalAudio.prototype.getDistanceModel = function () {
16747
16748    return this.panner.distanceModel;
16749
16750};
16751
16752THREE.PositionalAudio.prototype.setMaxDistance = function ( value ) {
16753
16754    this.panner.maxDistance = value;
16755
16756};
16757
16758THREE.PositionalAudio.prototype.getMaxDistance = function () {
16759
16760    return this.panner.maxDistance;
16761
16762};
16763
16764THREE.PositionalAudio.prototype.updateMatrixWorld = ( function () {
16765
16766    var position = new THREE.Vector3();
16767
16768    return function updateMatrixWorld( force ) {
16769
16770        THREE.Object3D.prototype.updateMatrixWorld.call( this, force );
16771
16772        position.setFromMatrixPosition( this.matrixWorld );
16773
16774        this.panner.setPosition( position.x, position.y, position.z );
16775
16776    };
16777
16778} )();
16779
16780// File:src/audio/AudioListener.js
16781
16782/**
16783 * @author mrdoob / http://mrdoob.com/
16784 */
16785
16786THREE.AudioListener = function () {
16787
16788    THREE.Object3D.call( this );
16789
16790    this.type = 'AudioListener';
16791
16792    this.context = THREE.AudioContext;
16793
16794    this.gain = this.context.createGain();
16795    this.gain.connect( this.context.destination );
16796
16797    this.filter = null;
16798
16799};
16800
16801THREE.AudioListener.prototype = Object.create( THREE.Object3D.prototype );
16802THREE.AudioListener.prototype.constructor = THREE.AudioListener;
16803
16804THREE.AudioListener.prototype.getInput = function () {
16805
16806    return this.gain;
16807
16808};
16809
16810THREE.AudioListener.prototype.removeFilter = function ( ) {
16811
16812    if ( this.filter !== null ) {
16813
16814        this.gain.disconnect( this.filter );
16815        this.filter.disconnect( this.context.destination );
16816        this.gain.connect( this.context.destination );
16817        this.filter = null;
16818
16819    }
16820
16821};
16822
16823THREE.AudioListener.prototype.setFilter = function ( value ) {
16824
16825    if ( this.filter !== null ) {
16826
16827        this.gain.disconnect( this.filter );
16828        this.filter.disconnect( this.context.destination );
16829
16830    } else {
16831
16832        this.gain.disconnect( this.context.destination );
16833
16834    }
16835
16836    this.filter = value;
16837    this.gain.connect( this.filter );
16838    this.filter.connect( this.context.destination );
16839
16840};
16841
16842THREE.AudioListener.prototype.getFilter = function () {
16843
16844    return this.filter;
16845
16846};
16847
16848THREE.AudioListener.prototype.setMasterVolume = function ( value ) {
16849
16850    this.gain.gain.value = value;
16851
16852};
16853
16854THREE.AudioListener.prototype.getMasterVolume = function () {
16855
16856    return this.gain.gain.value;
16857
16858};
16859
16860
16861THREE.AudioListener.prototype.updateMatrixWorld = ( function () {
16862
16863    var position = new THREE.Vector3();
16864    var quaternion = new THREE.Quaternion();
16865    var scale = new THREE.Vector3();
16866
16867    var orientation = new THREE.Vector3();
16868
16869    return function updateMatrixWorld( force ) {
16870
16871        THREE.Object3D.prototype.updateMatrixWorld.call( this, force );
16872
16873        var listener = this.context.listener;
16874        var up = this.up;
16875
16876        this.matrixWorld.decompose( position, quaternion, scale );
16877
16878        orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion );
16879
16880        listener.setPosition( position.x, position.y, position.z );
16881        listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z );
16882
16883    };
16884
16885} )();
16886
16887// File:src/cameras/Camera.js
16888
16889/**
16890 * @author mrdoob / http://mrdoob.com/
16891 * @author mikael emtinger / http://gomo.se/
16892 * @author WestLangley / http://github.com/WestLangley
16893 */
16894
16895THREE.Camera = function () {
16896
16897    THREE.Object3D.call( this );
16898
16899    this.type = 'Camera';
16900
16901    this.matrixWorldInverse = new THREE.Matrix4();
16902    this.projectionMatrix = new THREE.Matrix4();
16903
16904};
16905
16906THREE.Camera.prototype = Object.create( THREE.Object3D.prototype );
16907THREE.Camera.prototype.constructor = THREE.Camera;
16908
16909THREE.Camera.prototype.getWorldDirection = function () {
16910
16911    var quaternion = new THREE.Quaternion();
16912
16913    return function ( optionalTarget ) {
16914
16915        var result = optionalTarget || new THREE.Vector3();
16916
16917        this.getWorldQuaternion( quaternion );
16918
16919        return result.set( 0, 0, - 1 ).applyQuaternion( quaternion );
16920
16921    };
16922
16923}();
16924
16925THREE.Camera.prototype.lookAt = function () {
16926
16927    // This routine does not support cameras with rotated and/or translated parent(s)
16928
16929    var m1 = new THREE.Matrix4();
16930
16931    return function ( vector ) {
16932
16933        m1.lookAt( this.position, vector, this.up );
16934
16935        this.quaternion.setFromRotationMatrix( m1 );
16936
16937    };
16938
16939}();
16940
16941THREE.Camera.prototype.clone = function () {
16942
16943    return new this.constructor().copy( this );
16944
16945};
16946
16947THREE.Camera.prototype.copy = function ( source ) {
16948
16949    THREE.Object3D.prototype.copy.call( this, source );
16950
16951    this.matrixWorldInverse.copy( source.matrixWorldInverse );
16952    this.projectionMatrix.copy( source.projectionMatrix );
16953
16954    return this;
16955
16956};
16957
16958// File:src/cameras/CubeCamera.js
16959
16960/**
16961 * Camera for rendering cube maps
16962 *	- renders scene into axis-aligned cube
16963 *
16964 * @author alteredq / http://alteredqualia.com/
16965 */
16966
16967THREE.CubeCamera = function ( near, far, cubeResolution ) {
16968
16969    THREE.Object3D.call( this );
16970
16971    this.type = 'CubeCamera';
16972
16973    var fov = 90, aspect = 1;
16974
16975    var cameraPX = new THREE.PerspectiveCamera( fov, aspect, near, far );
16976    cameraPX.up.set( 0, - 1, 0 );
16977    cameraPX.lookAt( new THREE.Vector3( 1, 0, 0 ) );
16978    this.add( cameraPX );
16979
16980    var cameraNX = new THREE.PerspectiveCamera( fov, aspect, near, far );
16981    cameraNX.up.set( 0, - 1, 0 );
16982    cameraNX.lookAt( new THREE.Vector3( - 1, 0, 0 ) );
16983    this.add( cameraNX );
16984
16985    var cameraPY = new THREE.PerspectiveCamera( fov, aspect, near, far );
16986    cameraPY.up.set( 0, 0, 1 );
16987    cameraPY.lookAt( new THREE.Vector3( 0, 1, 0 ) );
16988    this.add( cameraPY );
16989
16990    var cameraNY = new THREE.PerspectiveCamera( fov, aspect, near, far );
16991    cameraNY.up.set( 0, 0, - 1 );
16992    cameraNY.lookAt( new THREE.Vector3( 0, - 1, 0 ) );
16993    this.add( cameraNY );
16994
16995    var cameraPZ = new THREE.PerspectiveCamera( fov, aspect, near, far );
16996    cameraPZ.up.set( 0, - 1, 0 );
16997    cameraPZ.lookAt( new THREE.Vector3( 0, 0, 1 ) );
16998    this.add( cameraPZ );
16999
17000    var cameraNZ = new THREE.PerspectiveCamera( fov, aspect, near, far );
17001    cameraNZ.up.set( 0, - 1, 0 );
17002    cameraNZ.lookAt( new THREE.Vector3( 0, 0, - 1 ) );
17003    this.add( cameraNZ );
17004
17005    var options = { format: THREE.RGBFormat, magFilter: THREE.LinearFilter, minFilter: THREE.LinearFilter };
17006
17007    this.renderTarget = new THREE.WebGLRenderTargetCube( cubeResolution, cubeResolution, options );
17008
17009    this.updateCubeMap = function ( renderer, scene ) {
17010
17011        if ( this.parent === null ) this.updateMatrixWorld();
17012
17013        var renderTarget = this.renderTarget;
17014        var generateMipmaps = renderTarget.texture.generateMipmaps;
17015
17016        renderTarget.texture.generateMipmaps = false;
17017
17018        renderTarget.activeCubeFace = 0;
17019        renderer.render( scene, cameraPX, renderTarget );
17020
17021        renderTarget.activeCubeFace = 1;
17022        renderer.render( scene, cameraNX, renderTarget );
17023
17024        renderTarget.activeCubeFace = 2;
17025        renderer.render( scene, cameraPY, renderTarget );
17026
17027        renderTarget.activeCubeFace = 3;
17028        renderer.render( scene, cameraNY, renderTarget );
17029
17030        renderTarget.activeCubeFace = 4;
17031        renderer.render( scene, cameraPZ, renderTarget );
17032
17033        renderTarget.texture.generateMipmaps = generateMipmaps;
17034
17035        renderTarget.activeCubeFace = 5;
17036        renderer.render( scene, cameraNZ, renderTarget );
17037
17038        renderer.setRenderTarget( null );
17039
17040    };
17041
17042};
17043
17044THREE.CubeCamera.prototype = Object.create( THREE.Object3D.prototype );
17045THREE.CubeCamera.prototype.constructor = THREE.CubeCamera;
17046
17047// File:src/cameras/OrthographicCamera.js
17048
17049/**
17050 * @author alteredq / http://alteredqualia.com/
17051 */
17052
17053THREE.OrthographicCamera = function ( left, right, top, bottom, near, far ) {
17054
17055    THREE.Camera.call( this );
17056
17057    this.type = 'OrthographicCamera';
17058
17059    this.zoom = 1;
17060
17061    this.left = left;
17062    this.right = right;
17063    this.top = top;
17064    this.bottom = bottom;
17065
17066    this.near = ( near !== undefined ) ? near : 0.1;
17067    this.far = ( far !== undefined ) ? far : 2000;
17068
17069    this.updateProjectionMatrix();
17070
17071};
17072
17073THREE.OrthographicCamera.prototype = Object.create( THREE.Camera.prototype );
17074THREE.OrthographicCamera.prototype.constructor = THREE.OrthographicCamera;
17075
17076THREE.OrthographicCamera.prototype.updateProjectionMatrix = function () {
17077
17078    var dx = ( this.right - this.left ) / ( 2 * this.zoom );
17079    var dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
17080    var cx = ( this.right + this.left ) / 2;
17081    var cy = ( this.top + this.bottom ) / 2;
17082
17083    this.projectionMatrix.makeOrthographic( cx - dx, cx + dx, cy + dy, cy - dy, this.near, this.far );
17084
17085};
17086
17087THREE.OrthographicCamera.prototype.copy = function ( source ) {
17088
17089    THREE.Camera.prototype.copy.call( this, source );
17090
17091    this.left = source.left;
17092    this.right = source.right;
17093    this.top = source.top;
17094    this.bottom = source.bottom;
17095    this.near = source.near;
17096    this.far = source.far;
17097
17098    this.zoom = source.zoom;
17099
17100    return this;
17101
17102};
17103
17104THREE.OrthographicCamera.prototype.toJSON = function ( meta ) {
17105
17106    var data = THREE.Object3D.prototype.toJSON.call( this, meta );
17107
17108    data.object.zoom = this.zoom;
17109    data.object.left = this.left;
17110    data.object.right = this.right;
17111    data.object.top = this.top;
17112    data.object.bottom = this.bottom;
17113    data.object.near = this.near;
17114    data.object.far = this.far;
17115
17116    return data;
17117
17118};
17119
17120// File:src/cameras/PerspectiveCamera.js
17121
17122/**
17123 * @author mrdoob / http://mrdoob.com/
17124 * @author greggman / http://games.greggman.com/
17125 * @author zz85 / http://www.lab4games.net/zz85/blog
17126 * @author tschw
17127 */
17128
17129THREE.PerspectiveCamera = function( fov, aspect, near, far ) {
17130
17131    THREE.Camera.call( this );
17132
17133    this.type = 'PerspectiveCamera';
17134
17135    this.fov = fov !== undefined ? fov : 50;
17136    this.zoom = 1;
17137
17138    this.near = near !== undefined ? near : 0.1;
17139    this.far = far !== undefined ? far : 2000;
17140    this.focus = 10;
17141
17142    this.aspect = aspect !== undefined ? aspect : 1;
17143    this.view = null;
17144
17145    this.filmGauge = 35;	// width of the film (default in millimeters)
17146    this.filmOffset = 0;	// horizontal film offset (same unit as gauge)
17147
17148    this.updateProjectionMatrix();
17149
17150};
17151
17152THREE.PerspectiveCamera.prototype = Object.create( THREE.Camera.prototype );
17153THREE.PerspectiveCamera.prototype.constructor = THREE.PerspectiveCamera;
17154
17155
17156/**
17157 * Sets the FOV by focal length (DEPRECATED).
17158 *
17159 * Optionally also sets .filmGauge, otherwise uses it. See .setFocalLength.
17160 */
17161THREE.PerspectiveCamera.prototype.setLens = function( focalLength, filmGauge ) {
17162
17163    console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " +
17164    "Use .setFocalLength and .filmGauge for a photographic setup." );
17165
17166    if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
17167    this.setFocalLength( focalLength );
17168
17169};
17170
17171/**
17172 * Sets the FOV by focal length in respect to the current .filmGauge.
17173 *
17174 * The default film gauge is 35, so that the focal length can be specified for
17175 * a 35mm (full frame) camera.
17176 *
17177 * Values for focal length and film gauge must have the same unit.
17178 */
17179THREE.PerspectiveCamera.prototype.setFocalLength = function( focalLength ) {
17180
17181    // see http://www.bobatkins.com/photography/technical/field_of_view.html
17182    var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
17183
17184    this.fov = THREE.Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
17185    this.updateProjectionMatrix();
17186
17187};
17188
17189
17190/**
17191 * Calculates the focal length from the current .fov and .filmGauge.
17192 */
17193THREE.PerspectiveCamera.prototype.getFocalLength = function() {
17194
17195    var vExtentSlope = Math.tan( THREE.Math.DEG2RAD * 0.5 * this.fov );
17196
17197    return 0.5 * this.getFilmHeight() / vExtentSlope;
17198
17199};
17200
17201THREE.PerspectiveCamera.prototype.getEffectiveFOV = function() {
17202
17203    return THREE.Math.RAD2DEG * 2 * Math.atan(
17204            Math.tan( THREE.Math.DEG2RAD * 0.5 * this.fov ) / this.zoom );
17205
17206};
17207
17208THREE.PerspectiveCamera.prototype.getFilmWidth = function() {
17209
17210    // film not completely covered in portrait format (aspect < 1)
17211    return this.filmGauge * Math.min( this.aspect, 1 );
17212
17213};
17214
17215THREE.PerspectiveCamera.prototype.getFilmHeight = function() {
17216
17217    // film not completely covered in landscape format (aspect > 1)
17218    return this.filmGauge / Math.max( this.aspect, 1 );
17219
17220};
17221
17222
17223
17224/**
17225 * Sets an offset in a larger frustum. This is useful for multi-window or
17226 * multi-monitor/multi-machine setups.
17227 *
17228 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
17229 * the monitors are in grid like this
17230 *
17231 *   +---+---+---+
17232 *   | A | B | C |
17233 *   +---+---+---+
17234 *   | D | E | F |
17235 *   +---+---+---+
17236 *
17237 * then for each monitor you would call it like this
17238 *
17239 *   var w = 1920;
17240 *   var h = 1080;
17241 *   var fullWidth = w * 3;
17242 *   var fullHeight = h * 2;
17243 *
17244 *   --A--
17245 *   camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
17246 *   --B--
17247 *   camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
17248 *   --C--
17249 *   camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
17250 *   --D--
17251 *   camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
17252 *   --E--
17253 *   camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
17254 *   --F--
17255 *   camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
17256 *
17257 *   Note there is no reason monitors have to be the same size or in a grid.
17258 */
17259THREE.PerspectiveCamera.prototype.setViewOffset = function( fullWidth, fullHeight, x, y, width, height ) {
17260
17261    this.aspect = fullWidth / fullHeight;
17262
17263    this.view = {
17264        fullWidth: fullWidth,
17265        fullHeight: fullHeight,
17266        offsetX: x,
17267        offsetY: y,
17268        width: width,
17269        height: height
17270    };
17271
17272    this.updateProjectionMatrix();
17273
17274};
17275
17276THREE.PerspectiveCamera.prototype.updateProjectionMatrix = function() {
17277
17278    var near = this.near,
17279        top = near * Math.tan(
17280                THREE.Math.DEG2RAD * 0.5 * this.fov ) / this.zoom,
17281        height = 2 * top,
17282        width = this.aspect * height,
17283        left = - 0.5 * width,
17284        view = this.view;
17285
17286    if ( view !== null ) {
17287
17288        var fullWidth = view.fullWidth,
17289            fullHeight = view.fullHeight;
17290
17291        left += view.offsetX * width / fullWidth;
17292        top -= view.offsetY * height / fullHeight;
17293        width *= view.width / fullWidth;
17294        height *= view.height / fullHeight;
17295
17296    }
17297
17298    var skew = this.filmOffset;
17299    if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
17300
17301    this.projectionMatrix.makeFrustum(
17302        left, left + width, top - height, top, near, this.far );
17303
17304};
17305
17306THREE.PerspectiveCamera.prototype.copy = function( source ) {
17307
17308    THREE.Camera.prototype.copy.call( this, source );
17309
17310    this.fov = source.fov;
17311    this.zoom = source.zoom;
17312
17313    this.near = source.near;
17314    this.far = source.far;
17315    this.focus = source.focus;
17316
17317    this.aspect = source.aspect;
17318    this.view = source.view === null ? null : Object.assign( {}, source.view );
17319
17320    this.filmGauge = source.filmGauge;
17321    this.filmOffset = source.filmOffset;
17322
17323    return this;
17324
17325};
17326
17327THREE.PerspectiveCamera.prototype.toJSON = function( meta ) {
17328
17329    var data = THREE.Object3D.prototype.toJSON.call( this, meta );
17330
17331    data.object.fov = this.fov;
17332    data.object.zoom = this.zoom;
17333
17334    data.object.near = this.near;
17335    data.object.far = this.far;
17336    data.object.focus = this.focus;
17337
17338    data.object.aspect = this.aspect;
17339
17340    if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
17341
17342    data.object.filmGauge = this.filmGauge;
17343    data.object.filmOffset = this.filmOffset;
17344
17345    return data;
17346
17347};
17348
17349// File:src/cameras/StereoCamera.js
17350
17351/**
17352 * @author mrdoob / http://mrdoob.com/
17353 */
17354
17355THREE.StereoCamera = function () {
17356
17357    this.type = 'StereoCamera';
17358
17359    this.aspect = 1;
17360
17361    this.cameraL = new THREE.PerspectiveCamera();
17362    this.cameraL.layers.enable( 1 );
17363    this.cameraL.matrixAutoUpdate = false;
17364
17365    this.cameraR = new THREE.PerspectiveCamera();
17366    this.cameraR.layers.enable( 2 );
17367    this.cameraR.matrixAutoUpdate = false;
17368
17369};
17370
17371THREE.StereoCamera.prototype = {
17372
17373    constructor: THREE.StereoCamera,
17374
17375    update: ( function () {
17376
17377        var focus, fov, aspect, near, far;
17378
17379        var eyeRight = new THREE.Matrix4();
17380        var eyeLeft = new THREE.Matrix4();
17381
17382        return function update ( camera ) {
17383
17384            var needsUpdate = focus !== camera.focus || fov !== camera.fov ||
17385                aspect !== camera.aspect * this.aspect || near !== camera.near ||
17386                far !== camera.far;
17387
17388            if ( needsUpdate ) {
17389
17390                focus = camera.focus;
17391                fov = camera.fov;
17392                aspect = camera.aspect * this.aspect;
17393                near = camera.near;
17394                far = camera.far;
17395
17396                // Off-axis stereoscopic effect based on
17397                // http://paulbourke.net/stereographics/stereorender/
17398
17399                var projectionMatrix = camera.projectionMatrix.clone();
17400                var eyeSep = 0.064 / 2;
17401                var eyeSepOnProjection = eyeSep * near / focus;
17402                var ymax = near * Math.tan( THREE.Math.DEG2RAD * fov * 0.5 );
17403                var xmin, xmax;
17404
17405                // translate xOffset
17406
17407                eyeLeft.elements[ 12 ] = - eyeSep;
17408                eyeRight.elements[ 12 ] = eyeSep;
17409
17410                // for left eye
17411
17412                xmin = - ymax * aspect + eyeSepOnProjection;
17413                xmax = ymax * aspect + eyeSepOnProjection;
17414
17415                projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
17416                projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
17417
17418                this.cameraL.projectionMatrix.copy( projectionMatrix );
17419
17420                // for right eye
17421
17422                xmin = - ymax * aspect - eyeSepOnProjection;
17423                xmax = ymax * aspect - eyeSepOnProjection;
17424
17425                projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
17426                projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
17427
17428                this.cameraR.projectionMatrix.copy( projectionMatrix );
17429
17430            }
17431
17432            this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft );
17433            this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight );
17434
17435        };
17436
17437    } )()
17438
17439};
17440
17441// File:src/lights/Light.js
17442
17443/**
17444 * @author mrdoob / http://mrdoob.com/
17445 * @author alteredq / http://alteredqualia.com/
17446 */
17447
17448THREE.Light = function ( color, intensity ) {
17449
17450    THREE.Object3D.call( this );
17451
17452    this.type = 'Light';
17453
17454    this.color = new THREE.Color( color );
17455    this.intensity = intensity !== undefined ? intensity : 1;
17456
17457    this.receiveShadow = undefined;
17458
17459};
17460
17461THREE.Light.prototype = Object.create( THREE.Object3D.prototype );
17462THREE.Light.prototype.constructor = THREE.Light;
17463
17464THREE.Light.prototype.copy = function ( source ) {
17465
17466    THREE.Object3D.prototype.copy.call( this, source );
17467
17468    this.color.copy( source.color );
17469    this.intensity = source.intensity;
17470
17471    return this;
17472
17473};
17474
17475THREE.Light.prototype.toJSON = function ( meta ) {
17476
17477    var data = THREE.Object3D.prototype.toJSON.call( this, meta );
17478
17479    data.object.color = this.color.getHex();
17480    data.object.intensity = this.intensity;
17481
17482    if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
17483
17484    if ( this.distance !== undefined ) data.object.distance = this.distance;
17485    if ( this.angle !== undefined ) data.object.angle = this.angle;
17486    if ( this.decay !== undefined ) data.object.decay = this.decay;
17487    if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
17488
17489    return data;
17490
17491};
17492
17493// File:src/lights/LightShadow.js
17494
17495/**
17496 * @author mrdoob / http://mrdoob.com/
17497 */
17498
17499THREE.LightShadow = function ( camera ) {
17500
17501    this.camera = camera;
17502
17503    this.bias = 0;
17504    this.radius = 1;
17505
17506    this.mapSize = new THREE.Vector2( 512, 512 );
17507
17508    this.map = null;
17509    this.matrix = new THREE.Matrix4();
17510
17511};
17512
17513THREE.LightShadow.prototype = {
17514
17515    constructor: THREE.LightShadow,
17516
17517    copy: function ( source ) {
17518
17519        this.camera = source.camera.clone();
17520
17521        this.bias = source.bias;
17522        this.radius = source.radius;
17523
17524        this.mapSize.copy( source.mapSize );
17525
17526        return this;
17527
17528    },
17529
17530    clone: function () {
17531
17532        return new this.constructor().copy( this );
17533
17534    }
17535
17536};
17537
17538// File:src/lights/AmbientLight.js
17539
17540/**
17541 * @author mrdoob / http://mrdoob.com/
17542 */
17543
17544THREE.AmbientLight = function ( color, intensity ) {
17545
17546    THREE.Light.call( this, color, intensity );
17547
17548    this.type = 'AmbientLight';
17549
17550    this.castShadow = undefined;
17551
17552};
17553
17554THREE.AmbientLight.prototype = Object.create( THREE.Light.prototype );
17555THREE.AmbientLight.prototype.constructor = THREE.AmbientLight;
17556
17557// File:src/lights/DirectionalLight.js
17558
17559/**
17560 * @author mrdoob / http://mrdoob.com/
17561 * @author alteredq / http://alteredqualia.com/
17562 */
17563
17564THREE.DirectionalLight = function ( color, intensity ) {
17565
17566    THREE.Light.call( this, color, intensity );
17567
17568    this.type = 'DirectionalLight';
17569
17570    this.position.set( 0, 1, 0 );
17571    this.updateMatrix();
17572
17573    this.target = new THREE.Object3D();
17574
17575    this.shadow = new THREE.DirectionalLightShadow();
17576
17577};
17578
17579THREE.DirectionalLight.prototype = Object.create( THREE.Light.prototype );
17580THREE.DirectionalLight.prototype.constructor = THREE.DirectionalLight;
17581
17582THREE.DirectionalLight.prototype.copy = function ( source ) {
17583
17584    THREE.Light.prototype.copy.call( this, source );
17585
17586    this.target = source.target.clone();
17587
17588    this.shadow = source.shadow.clone();
17589
17590    return this;
17591
17592};
17593
17594// File:src/lights/DirectionalLightShadow.js
17595
17596/**
17597 * @author mrdoob / http://mrdoob.com/
17598 */
17599
17600THREE.DirectionalLightShadow = function ( light ) {
17601
17602    THREE.LightShadow.call( this, new THREE.OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
17603
17604};
17605
17606THREE.DirectionalLightShadow.prototype = Object.create( THREE.LightShadow.prototype );
17607THREE.DirectionalLightShadow.prototype.constructor = THREE.DirectionalLightShadow;
17608
17609// File:src/lights/HemisphereLight.js
17610
17611/**
17612 * @author alteredq / http://alteredqualia.com/
17613 */
17614
17615THREE.HemisphereLight = function ( skyColor, groundColor, intensity ) {
17616
17617    THREE.Light.call( this, skyColor, intensity );
17618
17619    this.type = 'HemisphereLight';
17620
17621    this.castShadow = undefined;
17622
17623    this.position.set( 0, 1, 0 );
17624    this.updateMatrix();
17625
17626    this.groundColor = new THREE.Color( groundColor );
17627
17628};
17629
17630THREE.HemisphereLight.prototype = Object.create( THREE.Light.prototype );
17631THREE.HemisphereLight.prototype.constructor = THREE.HemisphereLight;
17632
17633THREE.HemisphereLight.prototype.copy = function ( source ) {
17634
17635    THREE.Light.prototype.copy.call( this, source );
17636
17637    this.groundColor.copy( source.groundColor );
17638
17639    return this;
17640
17641};
17642
17643// File:src/lights/PointLight.js
17644
17645/**
17646 * @author mrdoob / http://mrdoob.com/
17647 */
17648
17649
17650THREE.PointLight = function ( color, intensity, distance, decay ) {
17651
17652    THREE.Light.call( this, color, intensity );
17653
17654    this.type = 'PointLight';
17655
17656    this.distance = ( distance !== undefined ) ? distance : 0;
17657    this.decay = ( decay !== undefined ) ? decay : 1;	// for physically correct lights, should be 2.
17658
17659    this.shadow = new THREE.LightShadow( new THREE.PerspectiveCamera( 90, 1, 0.5, 500 ) );
17660
17661};
17662
17663THREE.PointLight.prototype = Object.create( THREE.Light.prototype );
17664THREE.PointLight.prototype.constructor = THREE.PointLight;
17665
17666Object.defineProperty( THREE.PointLight.prototype, "power", {
17667
17668    get: function () {
17669
17670        // intensity = power per solid angle.
17671        // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
17672        return this.intensity * 4 * Math.PI;
17673
17674    },
17675
17676    set: function ( power ) {
17677
17678        // intensity = power per solid angle.
17679        // ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
17680        this.intensity = power / ( 4 * Math.PI );
17681
17682    }
17683
17684} );
17685
17686THREE.PointLight.prototype.copy = function ( source ) {
17687
17688    THREE.Light.prototype.copy.call( this, source );
17689
17690    this.distance = source.distance;
17691    this.decay = source.decay;
17692
17693    this.shadow = source.shadow.clone();
17694
17695    return this;
17696
17697};
17698
17699// File:src/lights/SpotLight.js
17700
17701/**
17702 * @author alteredq / http://alteredqualia.com/
17703 */
17704
17705THREE.SpotLight = function ( color, intensity, distance, angle, penumbra, decay ) {
17706
17707    THREE.Light.call( this, color, intensity );
17708
17709    this.type = 'SpotLight';
17710
17711    this.position.set( 0, 1, 0 );
17712    this.updateMatrix();
17713
17714    this.target = new THREE.Object3D();
17715
17716    this.distance = ( distance !== undefined ) ? distance : 0;
17717    this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
17718    this.penumbra = ( penumbra !== undefined ) ? penumbra : 0;
17719    this.decay = ( decay !== undefined ) ? decay : 1;	// for physically correct lights, should be 2.
17720
17721    this.shadow = new THREE.SpotLightShadow();
17722
17723};
17724
17725THREE.SpotLight.prototype = Object.create( THREE.Light.prototype );
17726THREE.SpotLight.prototype.constructor = THREE.SpotLight;
17727
17728Object.defineProperty( THREE.SpotLight.prototype, "power", {
17729
17730    get: function () {
17731
17732        // intensity = power per solid angle.
17733        // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
17734        return this.intensity * Math.PI;
17735
17736    },
17737
17738    set: function ( power ) {
17739
17740        // intensity = power per solid angle.
17741        // ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
17742        this.intensity = power / Math.PI;
17743
17744    }
17745
17746} );
17747
17748THREE.SpotLight.prototype.copy = function ( source ) {
17749
17750    THREE.Light.prototype.copy.call( this, source );
17751
17752    this.distance = source.distance;
17753    this.angle = source.angle;
17754    this.penumbra = source.penumbra;
17755    this.decay = source.decay;
17756
17757    this.target = source.target.clone();
17758
17759    this.shadow = source.shadow.clone();
17760
17761    return this;
17762
17763};
17764
17765// File:src/lights/SpotLightShadow.js
17766
17767/**
17768 * @author mrdoob / http://mrdoob.com/
17769 */
17770
17771THREE.SpotLightShadow = function () {
17772
17773    THREE.LightShadow.call( this, new THREE.PerspectiveCamera( 50, 1, 0.5, 500 ) );
17774
17775};
17776
17777THREE.SpotLightShadow.prototype = Object.create( THREE.LightShadow.prototype );
17778THREE.SpotLightShadow.prototype.constructor = THREE.SpotLightShadow;
17779
17780THREE.SpotLightShadow.prototype.update = function ( light ) {
17781
17782    var fov = THREE.Math.RAD2DEG * 2 * light.angle;
17783    var aspect = this.mapSize.width / this.mapSize.height;
17784    var far = light.distance || 500;
17785
17786    var camera = this.camera;
17787
17788    if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
17789
17790        camera.fov = fov;
17791        camera.aspect = aspect;
17792        camera.far = far;
17793        camera.updateProjectionMatrix();
17794
17795    }
17796
17797};
17798
17799// File:src/loaders/AudioLoader.js
17800
17801/**
17802 * @author Reece Aaron Lecrivain / http://reecenotes.com/
17803 */
17804
17805THREE.AudioLoader = function ( manager ) {
17806
17807    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
17808
17809};
17810
17811THREE.AudioLoader.prototype = {
17812
17813    constructor: THREE.AudioLoader,
17814
17815    load: function ( url, onLoad, onProgress, onError ) {
17816
17817        var loader = new THREE.XHRLoader( this.manager );
17818        loader.setResponseType( 'arraybuffer' );
17819        loader.load( url, function ( buffer ) {
17820
17821            var context = THREE.AudioContext;
17822
17823            context.decodeAudioData( buffer, function ( audioBuffer ) {
17824
17825                onLoad( audioBuffer );
17826
17827            } );
17828
17829        }, onProgress, onError );
17830
17831    }
17832
17833};
17834
17835// File:src/loaders/Cache.js
17836
17837/**
17838 * @author mrdoob / http://mrdoob.com/
17839 */
17840
17841THREE.Cache = {
17842
17843    enabled: false,
17844
17845    files: {},
17846
17847    add: function ( key, file ) {
17848
17849        if ( this.enabled === false ) return;
17850
17851        // console.log( 'THREE.Cache', 'Adding key:', key );
17852
17853        this.files[ key ] = file;
17854
17855    },
17856
17857    get: function ( key ) {
17858
17859        if ( this.enabled === false ) return;
17860
17861        // console.log( 'THREE.Cache', 'Checking key:', key );
17862
17863        return this.files[ key ];
17864
17865    },
17866
17867    remove: function ( key ) {
17868
17869        delete this.files[ key ];
17870
17871    },
17872
17873    clear: function () {
17874
17875        this.files = {};
17876
17877    }
17878
17879};
17880
17881// File:src/loaders/Loader.js
17882
17883/**
17884 * @author alteredq / http://alteredqualia.com/
17885 */
17886
17887THREE.Loader = function () {
17888
17889    this.onLoadStart = function () {};
17890    this.onLoadProgress = function () {};
17891    this.onLoadComplete = function () {};
17892
17893};
17894
17895THREE.Loader.prototype = {
17896
17897    constructor: THREE.Loader,
17898
17899    crossOrigin: undefined,
17900
17901    extractUrlBase: function ( url ) {
17902
17903        var parts = url.split( '/' );
17904
17905        if ( parts.length === 1 ) return './';
17906
17907        parts.pop();
17908
17909        return parts.join( '/' ) + '/';
17910
17911    },
17912
17913    initMaterials: function ( materials, texturePath, crossOrigin ) {
17914
17915        var array = [];
17916
17917        for ( var i = 0; i < materials.length; ++ i ) {
17918
17919            array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin );
17920
17921        }
17922
17923        return array;
17924
17925    },
17926
17927    createMaterial: ( function () {
17928
17929        var color, textureLoader, materialLoader;
17930
17931        return function ( m, texturePath, crossOrigin ) {
17932
17933            if ( color === undefined ) color = new THREE.Color();
17934            if ( textureLoader === undefined ) textureLoader = new THREE.TextureLoader();
17935            if ( materialLoader === undefined ) materialLoader = new THREE.MaterialLoader();
17936
17937            // convert from old material format
17938
17939            var textures = {};
17940
17941            function loadTexture( path, repeat, offset, wrap, anisotropy ) {
17942
17943                var fullPath = texturePath + path;
17944                var loader = THREE.Loader.Handlers.get( fullPath );
17945
17946                var texture;
17947
17948                if ( loader !== null ) {
17949
17950                    texture = loader.load( fullPath );
17951
17952                } else {
17953
17954                    textureLoader.setCrossOrigin( crossOrigin );
17955                    texture = textureLoader.load( fullPath );
17956
17957                }
17958
17959                if ( repeat !== undefined ) {
17960
17961                    texture.repeat.fromArray( repeat );
17962
17963                    if ( repeat[ 0 ] !== 1 ) texture.wrapS = THREE.RepeatWrapping;
17964                    if ( repeat[ 1 ] !== 1 ) texture.wrapT = THREE.RepeatWrapping;
17965
17966                }
17967
17968                if ( offset !== undefined ) {
17969
17970                    texture.offset.fromArray( offset );
17971
17972                }
17973
17974                if ( wrap !== undefined ) {
17975
17976                    if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = THREE.RepeatWrapping;
17977                    if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = THREE.MirroredRepeatWrapping;
17978
17979                    if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = THREE.RepeatWrapping;
17980                    if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = THREE.MirroredRepeatWrapping;
17981
17982                }
17983
17984                if ( anisotropy !== undefined ) {
17985
17986                    texture.anisotropy = anisotropy;
17987
17988                }
17989
17990                var uuid = THREE.Math.generateUUID();
17991
17992                textures[ uuid ] = texture;
17993
17994                return uuid;
17995
17996            }
17997
17998            //
17999
18000            var json = {
18001                uuid: THREE.Math.generateUUID(),
18002                type: 'MeshLambertMaterial'
18003            };
18004
18005            for ( var name in m ) {
18006
18007                var value = m[ name ];
18008
18009                switch ( name ) {
18010                    case 'DbgColor':
18011                    case 'DbgIndex':
18012                    case 'opticalDensity':
18013                    case 'illumination':
18014                        break;
18015                    case 'DbgName':
18016                        json.name = value;
18017                        break;
18018                    case 'blending':
18019                        json.blending = THREE[ value ];
18020                        break;
18021                    case 'colorAmbient':
18022                    case 'mapAmbient':
18023                        console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' );
18024                        break;
18025                    case 'colorDiffuse':
18026                        json.color = color.fromArray( value ).getHex();
18027                        break;
18028                    case 'colorSpecular':
18029                        json.specular = color.fromArray( value ).getHex();
18030                        break;
18031                    case 'colorEmissive':
18032                        json.emissive = color.fromArray( value ).getHex();
18033                        break;
18034                    case 'specularCoef':
18035                        json.shininess = value;
18036                        break;
18037                    case 'shading':
18038                        if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial';
18039                        if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial';
18040                        break;
18041                    case 'mapDiffuse':
18042                        json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
18043                        break;
18044                    case 'mapDiffuseRepeat':
18045                    case 'mapDiffuseOffset':
18046                    case 'mapDiffuseWrap':
18047                    case 'mapDiffuseAnisotropy':
18048                        break;
18049                    case 'mapLight':
18050                        json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
18051                        break;
18052                    case 'mapLightRepeat':
18053                    case 'mapLightOffset':
18054                    case 'mapLightWrap':
18055                    case 'mapLightAnisotropy':
18056                        break;
18057                    case 'mapAO':
18058                        json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy );
18059                        break;
18060                    case 'mapAORepeat':
18061                    case 'mapAOOffset':
18062                    case 'mapAOWrap':
18063                    case 'mapAOAnisotropy':
18064                        break;
18065                    case 'mapBump':
18066                        json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
18067                        break;
18068                    case 'mapBumpScale':
18069                        json.bumpScale = value;
18070                        break;
18071                    case 'mapBumpRepeat':
18072                    case 'mapBumpOffset':
18073                    case 'mapBumpWrap':
18074                    case 'mapBumpAnisotropy':
18075                        break;
18076                    case 'mapNormal':
18077                        json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
18078                        break;
18079                    case 'mapNormalFactor':
18080                        json.normalScale = [ value, value ];
18081                        break;
18082                    case 'mapNormalRepeat':
18083                    case 'mapNormalOffset':
18084                    case 'mapNormalWrap':
18085                    case 'mapNormalAnisotropy':
18086                        break;
18087                    case 'mapSpecular':
18088                        json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
18089                        break;
18090                    case 'mapSpecularRepeat':
18091                    case 'mapSpecularOffset':
18092                    case 'mapSpecularWrap':
18093                    case 'mapSpecularAnisotropy':
18094                        break;
18095                    case 'mapAlpha':
18096                        json.alphaMap = loadTexture( value, m.mapAlpha
18096Repeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
18097                        break;
18098                    case 'mapAlphaRepeat':
18099                    case 'mapAlphaOffset':
18100                    case 'mapAlphaWrap':
18101                    case 'mapAlphaAnisotropy':
18102                        break;
18103                    case 'flipSided':
18104                        json.side = THREE.BackSide;
18105                        break;
18106                    case 'doubleSided':
18107                        json.side = THREE.DoubleSide;
18108                        break;
18109                    case 'transparency':
18110                        console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' );
18111                        json.opacity = value;
18112                        break;
18113                    case 'depthTest':
18114                    case 'depthWrite':
18115                    case 'colorWrite':
18116                    case 'opacity':
18117                    case 'reflectivity':
18118                    case 'transparent':
18119                    case 'visible':
18120                    case 'wireframe':
18121                        json[ name ] = value;
18122                        break;
18123                    case 'vertexColors':
18124                        if ( value === true ) json.vertexColors = THREE.VertexColors;
18125                        if ( value === 'face' ) json.vertexColors = THREE.FaceColors;
18126                        break;
18127                    default:
18128                        console.error( 'THREE.Loader.createMaterial: Unsupported', name, value );
18129                        break;
18130                }
18131
18132            }
18133
18134            if ( json.type === 'MeshBasicMaterial' ) delete json.emissive;
18135            if ( json.type !== 'MeshPhongMaterial' ) delete json.specular;
18136
18137            if ( json.opacity < 1 ) json.transparent = true;
18138
18139            materialLoader.setTextures( textures );
18140
18141            return materialLoader.parse( json );
18142
18143        };
18144
18145    } )()
18146
18147};
18148
18149THREE.Loader.Handlers = {
18150
18151    handlers: [],
18152
18153    add: function ( regex, loader ) {
18154
18155        this.handlers.push( regex, loader );
18156
18157    },
18158
18159    get: function ( file ) {
18160
18161        var handlers = this.handlers;
18162
18163        for ( var i = 0, l = handlers.length; i < l; i += 2 ) {
18164
18165            var regex = handlers[ i ];
18166            var loader  = handlers[ i + 1 ];
18167
18168            if ( regex.test( file ) ) {
18169
18170                return loader;
18171
18172            }
18173
18174        }
18175
18176        return null;
18177
18178    }
18179
18180};
18181
18182// File:src/loaders/XHRLoader.js
18183
18184/**
18185 * @author mrdoob / http://mrdoob.com/
18186 */
18187
18188THREE.XHRLoader = function ( manager ) {
18189
18190    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
18191
18192};
18193
18194THREE.XHRLoader.prototype = {
18195
18196    constructor: THREE.XHRLoader,
18197
18198    load: function ( url, onLoad, onProgress, onError ) {
18199
18200        if ( this.path !== undefined ) url = this.path + url;
18201
18202        var scope = this;
18203
18204        var cached = THREE.Cache.get( url );
18205
18206        if ( cached !== undefined ) {
18207
18208            if ( onLoad ) {
18209
18210                setTimeout( function () {
18211
18212                    onLoad( cached );
18213
18214                }, 0 );
18215
18216            }
18217
18218            return cached;
18219
18220        }
18221
18222        var request = new XMLHttpRequest();
18223        request.overrideMimeType( 'text/plain' );
18224        request.open( 'GET', url, true );
18225
18226        request.addEventListener( 'load', function ( event ) {
18227
18228            var response = event.target.response;
18229
18230            THREE.Cache.add( url, response );
18231
18232            if ( this.status === 200 ) {
18233
18234                if ( onLoad ) onLoad( response );
18235
18236                scope.manager.itemEnd( url );
18237
18238            } else if ( this.status === 0 ) {
18239
18240                // Some browsers return HTTP Status 0 when using non-http protocol
18241                // e.g. 'file://' or 'data://'. Handle as success.
18242
18243                console.warn( 'THREE.XHRLoader: HTTP Status 0 received.' );
18244
18245                if ( onLoad ) onLoad( response );
18246
18247                scope.manager.itemEnd( url );
18248
18249            } else {
18250
18251                if ( onError ) onError( event );
18252
18253                scope.manager.itemError( url );
18254
18255            }
18256
18257        }, false );
18258
18259        if ( onProgress !== undefined ) {
18260
18261            request.addEventListener( 'progress', function ( event ) {
18262
18263                onProgress( event );
18264
18265            }, false );
18266
18267        }
18268
18269        request.addEventListener( 'error', function ( event ) {
18270
18271            if ( onError ) onError( event );
18272
18273            scope.manager.itemError( url );
18274
18275        }, false );
18276
18277        if ( this.responseType !== undefined ) request.responseType = this.responseType;
18278        if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
18279
18280        request.send( null );
18281
18282        scope.manager.itemStart( url );
18283
18284        return request;
18285
18286    },
18287
18288    setPath: function ( value ) {
18289
18290        this.path = value;
18291
18292    },
18293
18294    setResponseType: function ( value ) {
18295
18296        this.responseType = value;
18297
18298    },
18299
18300    setWithCredentials: function ( value ) {
18301
18302        this.withCredentials = value;
18303
18304    }
18305
18306};
18307
18308// File:src/loaders/FontLoader.js
18309
18310/**
18311 * @author mrdoob / http://mrdoob.com/
18312 */
18313
18314THREE.FontLoader = function ( manager ) {
18315
18316    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
18317
18318};
18319
18320THREE.FontLoader.prototype = {
18321
18322    constructor: THREE.FontLoader,
18323
18324    load: function ( url, onLoad, onProgress, onError ) {
18325
18326        var loader = new THREE.XHRLoader( this.manager );
18327        loader.load( url, function ( text ) {
18328
18329            onLoad( new THREE.Font( JSON.parse( text.substring( 65, text.length - 2 ) ) ) );
18330
18331        }, onProgress, onError );
18332
18333    }
18334
18335};
18336
18337// File:src/loaders/ImageLoader.js
18338
18339/**
18340 * @author mrdoob / http://mrdoob.com/
18341 */
18342
18343THREE.ImageLoader = function ( manager ) {
18344
18345    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
18346
18347};
18348
18349THREE.ImageLoader.prototype = {
18350
18351    constructor: THREE.ImageLoader,
18352
18353    load: function ( url, onLoad, onProgress, onError ) {
18354
18355        if ( this.path !== undefined ) url = this.path + url;
18356
18357        var scope = this;
18358
18359        var cached = THREE.Cache.get( url );
18360
18361        if ( cached !== undefined ) {
18362
18363            scope.manager.itemStart( url );
18364
18365            if ( onLoad ) {
18366
18367                setTimeout( function () {
18368
18369                    onLoad( cached );
18370
18371                    scope.manager.itemEnd( url );
18372
18373                }, 0 );
18374
18375            } else {
18376
18377                scope.manager.itemEnd( url );
18378
18379            }
18380
18381            return cached;
18382
18383        }
18384
18385        var image = document.createElement( 'img' );
18386
18387        image.addEventListener( 'load', function ( event ) {
18388
18389            THREE.Cache.add( url, this );
18390
18391            if ( onLoad ) onLoad( this );
18392
18393            scope.manager.itemEnd( url );
18394
18395        }, false );
18396
18397        if ( onProgress !== undefined ) {
18398
18399            image.addEventListener( 'progress', function ( event ) {
18400
18401                onProgress( event );
18402
18403            }, false );
18404
18405        }
18406
18407        image.addEventListener( 'error', function ( event ) {
18408
18409            if ( onError ) onError( event );
18410
18411            scope.manager.itemError( url );
18412
18413        }, false );
18414
18415        if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
18416
18417        scope.manager.itemStart( url );
18418
18419        image.src = url;
18420
18421        return image;
18422
18423    },
18424
18425    setCrossOrigin: function ( value ) {
18426
18427        this.crossOrigin = value;
18428
18429    },
18430
18431    setPath: function ( value ) {
18432
18433        this.path = value;
18434
18435    }
18436
18437};
18438
18439// File:src/loaders/JSONLoader.js
18440
18441/**
18442 * @author mrdoob / http://mrdoob.com/
18443 * @author alteredq / http://alteredqualia.com/
18444 */
18445
18446THREE.JSONLoader = function ( manager ) {
18447
18448    if ( typeof manager === 'boolean' ) {
18449
18450        console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' );
18451        manager = undefined;
18452
18453    }
18454
18455    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
18456
18457    this.withCredentials = false;
18458
18459};
18460
18461THREE.JSONLoader.prototype = {
18462
18463    constructor: THREE.JSONLoader,
18464
18465    // Deprecated
18466
18467    get statusDomElement () {
18468
18469        if ( this._statusDomElement === undefined ) {
18470
18471            this._statusDomElement = document.createElement( 'div' );
18472
18473        }
18474
18475        console.warn( 'THREE.JSONLoader: .statusDomElement has been removed.' );
18476        return this._statusDomElement;
18477
18478    },
18479
18480    load: function( url, onLoad, onProgress, onError ) {
18481
18482        var scope = this;
18483
18484        var texturePath = this.texturePath && ( typeof this.texturePath === "string" ) ? this.texturePath : THREE.Loader.prototype.extractUrlBase( url );
18485
18486        var loader = new THREE.XHRLoader( this.manager );
18487        loader.setWithCredentials( this.withCredentials );
18488        loader.load( url, function ( text ) {
18489
18490            var json = JSON.parse( text );
18491            var metadata = json.metadata;
18492
18493            if ( metadata !== undefined ) {
18494
18495                var type = metadata.type;
18496
18497                if ( type !== undefined ) {
18498
18499                    if ( type.toLowerCase() === 'object' ) {
18500
18501                        console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
18502                        return;
18503
18504                    }
18505
18506                    if ( type.toLowerCase() === 'scene' ) {
18507
18508                        console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.SceneLoader instead.' );
18509                        return;
18510
18511                    }
18512
18513                }
18514
18515            }
18516
18517            var object = scope.parse( json, texturePath );
18518            onLoad( object.geometry, object.materials );
18519
18520        }, onProgress, onError );
18521
18522    },
18523
18524    setTexturePath: function ( value ) {
18525
18526        this.texturePath = value;
18527
18528    },
18529
18530    parse: function ( json, texturePath ) {
18531
18532        var geometry = new THREE.Geometry(),
18533            scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
18534
18535        parseModel( scale );
18536
18537        parseSkin();
18538        parseMorphing( scale );
18539        parseAnimations();
18540
18541        geometry.computeFaceNormals();
18542        geometry.computeBoundingSphere();
18543
18544        function parseModel( scale ) {
18545
18546            function isBitSet( value, position ) {
18547
18548                return value & ( 1 << position );
18549
18550            }
18551
18552            var i, j, fi,
18553
18554                offset, zLength,
18555
18556                colorIndex, normalIndex, uvIndex, materialIndex,
18557
18558                type,
18559                isQuad,
18560                hasMaterial,
18561                hasFaceVertexUv,
18562                hasFaceNormal, hasFaceVertexNormal,
18563                hasFaceColor, hasFaceVertexColor,
18564
18565                vertex, face, faceA, faceB, hex, normal,
18566
18567                uvLayer, uv, u, v,
18568
18569                faces = json.faces,
18570                vertices = json.vertices,
18571                normals = json.normals,
18572                colors = json.colors,
18573
18574                nUvLayers = 0;
18575
18576            if ( json.uvs !== undefined ) {
18577
18578                // disregard empty arrays
18579
18580                for ( i = 0; i < json.uvs.length; i ++ ) {
18581
18582                    if ( json.uvs[ i ].length ) nUvLayers ++;
18583
18584                }
18585
18586                for ( i = 0; i < nUvLayers; i ++ ) {
18587
18588                    geometry.faceVertexUvs[ i ] = [];
18589
18590                }
18591
18592            }
18593
18594            offset = 0;
18595            zLength = vertices.length;
18596
18597            while ( offset < zLength ) {
18598
18599                vertex = new THREE.Vector3();
18600
18601                vertex.x = vertices[ offset ++ ] * scale;
18602                vertex.y = vertices[ offset ++ ] * scale;
18603                vertex.z = vertices[ offset ++ ] * scale;
18604
18605                geometry.vertices.push( vertex );
18606
18607            }
18608
18609            offset = 0;
18610            zLength = faces.length;
18611
18612            while ( offset < zLength ) {
18613
18614                type = faces[ offset ++ ];
18615
18616
18617                isQuad              = isBitSet( type, 0 );
18618                hasMaterial         = isBitSet( type, 1 );
18619                hasFaceVertexUv     = isBitSet( type, 3 );
18620                hasFaceNormal       = isBitSet( type, 4 );
18621                hasFaceVertexNormal = isBitSet( type, 5 );
18622                hasFaceColor	     = isBitSet( type, 6 );
18623                hasFaceVertexColor  = isBitSet( type, 7 );
18624
18625                // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
18626
18627                if ( isQuad ) {
18628
18629                    faceA = new THREE.Face3();
18630                    faceA.a = faces[ offset ];
18631                    faceA.b = faces[ offset + 1 ];
18632                    faceA.c = faces[ offset + 3 ];
18633
18634                    faceB = new THREE.Face3();
18635                    faceB.a = faces[ offset + 1 ];
18636                    faceB.b = faces[ offset + 2 ];
18637                    faceB.c = faces[ offset + 3 ];
18638
18639                    offset += 4;
18640
18641                    if ( hasMaterial ) {
18642
18643                        materialIndex = faces[ offset ++ ];
18644                        faceA.materialIndex = materialIndex;
18645                        faceB.materialIndex = materialIndex;
18646
18647                    }
18648
18649                    // to get face <=> uv index correspondence
18650
18651                    fi = geometry.faces.length;
18652
18653                    if ( hasFaceVertexUv ) {
18654
18655                        for ( i = 0; i < nUvLayers; i ++ ) {
18656
18657                            uvLayer = json.uvs[ i ];
18658
18659                            geometry.faceVertexUvs[ i ][ fi ] = [];
18660                            geometry.faceVertexUvs[ i ][ fi + 1 ] = [];
18661
18662                            for ( j = 0; j < 4; j ++ ) {
18663
18664                                uvIndex = faces[ offset ++ ];
18665
18666                                u = uvLayer[ uvIndex * 2 ];
18667                                v = uvLayer[ uvIndex * 2 + 1 ];
18668
18669                                uv = new THREE.Vector2( u, v );
18670
18671                                if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
18672                                if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
18673
18674                            }
18675
18676                        }
18677
18678                    }
18679
18680                    if ( hasFaceNormal ) {
18681
18682                        normalIndex = faces[ offset ++ ] * 3;
18683
18684                        faceA.normal.set(
18685                            normals[ normalIndex ++ ],
18686                            normals[ normalIndex ++ ],
18687                            normals[ normalIndex ]
18688                        );
18689
18690                        faceB.normal.copy( faceA.normal );
18691
18692                    }
18693
18694                    if ( hasFaceVertexNormal ) {
18695
18696                        for ( i = 0; i < 4; i ++ ) {
18697
18698                            normalIndex = faces[ offset ++ ] * 3;
18699
18700                            normal = new THREE.Vector3(
18701                                normals[ normalIndex ++ ],
18702                                normals[ normalIndex ++ ],
18703                                normals[ normalIndex ]
18704                            );
18705
18706
18707                            if ( i !== 2 ) faceA.vertexNormals.push( normal );
18708                            if ( i !== 0 ) faceB.vertexNormals.push( normal );
18709
18710                        }
18711
18712                    }
18713
18714
18715                    if ( hasFaceColor ) {
18716
18717                        colorIndex = faces[ offset ++ ];
18718                        hex = colors[ colorIndex ];
18719
18720                        faceA.color.setHex( hex );
18721                        faceB.color.setHex( hex );
18722
18723                    }
18724
18725
18726                    if ( hasFaceVertexColor ) {
18727
18728                        for ( i = 0; i < 4; i ++ ) {
18729
18730                            colorIndex = faces[ offset ++ ];
18731                            hex = colors[ colorIndex ];
18732
18733                            if ( i !== 2 ) faceA.vertexColors.push( new THREE.Color( hex ) );
18734                            if ( i !== 0 ) faceB.vertexColors.push( new THREE.Color( hex ) );
18735
18736                        }
18737
18738                    }
18739
18740                    geometry.faces.push( faceA );
18741                    geometry.faces.push( faceB );
18742
18743                } else {
18744
18745                    face = new THREE.Face3();
18746                    face.a = faces[ offset ++ ];
18747                    face.b = faces[ offset ++ ];
18748                    face.c = faces[ offset ++ ];
18749
18750                    if ( hasMaterial ) {
18751
18752                        materialIndex = faces[ offset ++ ];
18753                        face.materialIndex = materialIndex;
18754
18755                    }
18756
18757                    // to get face <=> uv index correspondence
18758
18759                    fi = geometry.faces.length;
18760
18761                    if ( hasFaceVertexUv ) {
18762
18763                        for ( i = 0; i < nUvLayers; i ++ ) {
18764
18765                            uvLayer = json.uvs[ i ];
18766
18767                            geometry.faceVertexUvs[ i ][ fi ] = [];
18768
18769                            for ( j = 0; j < 3; j ++ ) {
18770
18771                                uvIndex = faces[ offset ++ ];
18772
18773                                u = uvLayer[ uvIndex * 2 ];
18774                                v = uvLayer[ uvIndex * 2 + 1 ];
18775
18776                                uv = new THREE.Vector2( u, v );
18777
18778                                geometry.faceVertexUvs[ i ][ fi ].push( uv );
18779
18780                            }
18781
18782                        }
18783
18784                    }
18785
18786                    if ( hasFaceNormal ) {
18787
18788                        normalIndex = faces[ offset ++ ] * 3;
18789
18790                        face.normal.set(
18791                            normals[ normalIndex ++ ],
18792                            normals[ normalIndex ++ ],
18793                            normals[ normalIndex ]
18794                        );
18795
18796                    }
18797
18798                    if ( hasFaceVertexNormal ) {
18799
18800                        for ( i = 0; i < 3; i ++ ) {
18801
18802                            normalIndex = faces[ offset ++ ] * 3;
18803
18804                            normal = new THREE.Vector3(
18805                                normals[ normalIndex ++ ],
18806                                normals[ normalIndex ++ ],
18807                                normals[ normalIndex ]
18808                            );
18809
18810                            face.vertexNormals.push( normal );
18811
18812                        }
18813
18814                    }
18815
18816
18817                    if ( hasFaceColor ) {
18818
18819                        colorIndex = faces[ offset ++ ];
18820                        face.color.setHex( colors[ colorIndex ] );
18821
18822                    }
18823
18824
18825                    if ( hasFaceVertexColor ) {
18826
18827                        for ( i = 0; i < 3; i ++ ) {
18828
18829                            colorIndex = faces[ offset ++ ];
18830                            face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );
18831
18832                        }
18833
18834                    }
18835
18836                    geometry.faces.push( face );
18837
18838                }
18839
18840            }
18841
18842        };
18843
18844        function parseSkin() {
18845
18846            var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
18847
18848            if ( json.skinWeights ) {
18849
18850                for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
18851
18852                    var x =                               json.skinWeights[ i ];
18853                    var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
18854                    var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
18855                    var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
18856
18857                    geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
18858
18859                }
18860
18861            }
18862
18863            if ( json.skinIndices ) {
18864
18865                for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
18866
18867                    var a =                               json.skinIndices[ i ];
18868                    var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
18869                    var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
18870                    var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
18871
18872                    geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
18873
18874                }
18875
18876            }
18877
18878            geometry.bones = json.bones;
18879
18880            if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
18881
18882                console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
18883                geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
18884
18885            }
18886
18887        };
18888
18889        function parseMorphing( scale ) {
18890
18891            if ( json.morphTargets !== undefined ) {
18892
18893                for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) {
18894
18895                    geometry.morphTargets[ i ] = {};
18896                    geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
18897                    geometry.morphTargets[ i ].vertices = [];
18898
18899                    var dstVertices = geometry.morphTargets[ i ].vertices;
18900                    var srcVertices = json.morphTargets[ i ].vertices;
18901
18902                    for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
18903
18904                        var vertex = new THREE.Vector3();
18905                        vertex.x = srcVertices[ v ] * scale;
18906                        vertex.y = srcVertices[ v + 1 ] * scale;
18907                        vertex.z = srcVertices[ v + 2 ] * scale;
18908
18909                        dstVertices.push( vertex );
18910
18911                    }
18912
18913                }
18914
18915            }
18916
18917            if ( json.morphColors !== undefined && json.morphColors.length > 0 ) {
18918
18919                console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' );
18920
18921                var faces = geometry.faces;
18922                var morphColors = json.morphColors[ 0 ].colors;
18923
18924                for ( var i = 0, l = faces.length; i < l; i ++ ) {
18925
18926                    faces[ i ].color.fromArray( morphColors, i * 3 );
18927
18928                }
18929
18930            }
18931
18932        }
18933
18934        function parseAnimations() {
18935
18936            var outputAnimations = [];
18937
18938            // parse old style Bone/Hierarchy animations
18939            var animations = [];
18940
18941            if ( json.animation !== undefined ) {
18942
18943                animations.push( json.animation );
18944
18945            }
18946
18947            if ( json.animations !== undefined ) {
18948
18949                if ( json.animations.length ) {
18950
18951                    animations = animations.concat( json.animations );
18952
18953                } else {
18954
18955                    animations.push( json.animations );
18956
18957                }
18958
18959            }
18960
18961            for ( var i = 0; i < animations.length; i ++ ) {
18962
18963                var clip = THREE.AnimationClip.parseAnimation( animations[ i ], geometry.bones );
18964                if ( clip ) outputAnimations.push( clip );
18965
18966            }
18967
18968            // parse implicit morph animations
18969            if ( geometry.morphTargets ) {
18970
18971                // TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary.
18972                var morphAnimationClips = THREE.AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 );
18973                outputAnimations = outputAnimations.concat( morphAnimationClips );
18974
18975            }
18976
18977            if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations;
18978
18979        };
18980
18981        if ( json.materials === undefined || json.materials.length === 0 ) {
18982
18983            return { geometry: geometry };
18984
18985        } else {
18986
18987            var materials = THREE.Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin );
18988
18989            return { geometry: geometry, materials: materials };
18990
18991        }
18992
18993    }
18994
18995};
18996
18997// File:src/loaders/LoadingManager.js
18998
18999/**
19000 * @author mrdoob / http://mrdoob.com/
19001 */
19002
19003THREE.LoadingManager = function ( onLoad, onProgress, onError ) {
19004
19005    var scope = this;
19006
19007    var isLoading = false, itemsLoaded = 0, itemsTotal = 0;
19008
19009    this.onStart = undefined;
19010    this.onLoad = onLoad;
19011    this.onProgress = onProgress;
19012    this.onError = onError;
19013
19014    this.itemStart = function ( url ) {
19015
19016        itemsTotal ++;
19017
19018        if ( isLoading === false ) {
19019
19020            if ( scope.onStart !== undefined ) {
19021
19022                scope.onStart( url, itemsLoaded, itemsTotal );
19023
19024            }
19025
19026        }
19027
19028        isLoading = true;
19029
19030    };
19031
19032    this.itemEnd = function ( url ) {
19033
19034        itemsLoaded ++;
19035
19036        if ( scope.onProgress !== undefined ) {
19037
19038            scope.onProgress( url, itemsLoaded, itemsTotal );
19039
19040        }
19041
19042        if ( itemsLoaded === itemsTotal ) {
19043
19044            isLoading = false;
19045
19046            if ( scope.onLoad !== undefined ) {
19047
19048                scope.onLoad();
19049
19050            }
19051
19052        }
19053
19054    };
19055
19056    this.itemError = function ( url ) {
19057
19058        if ( scope.onError !== undefined ) {
19059
19060            scope.onError( url );
19061
19062        }
19063
19064    };
19065
19066};
19067
19068THREE.DefaultLoadingManager = new THREE.LoadingManager();
19069
19070// File:src/loaders/BufferGeometryLoader.js
19071
19072/**
19073 * @author mrdoob / http://mrdoob.com/
19074 */
19075
19076THREE.BufferGeometryLoader = function ( manager ) {
19077
19078    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
19079
19080};
19081
19082THREE.BufferGeometryLoader.prototype = {
19083
19084    constructor: THREE.BufferGeometryLoader,
19085
19086    load: function ( url, onLoad, onProgress, onError ) {
19087
19088        var scope = this;
19089
19090        var loader = new THREE.XHRLoader( scope.manager );
19091        loader.load( url, function ( text ) {
19092
19093            onLoad( scope.parse( JSON.parse( text ) ) );
19094
19095        }, onProgress, onError );
19096
19097    },
19098
19099    parse: function ( json ) {
19100
19101        var geometry = new THREE.BufferGeometry();
19102
19103        var index = json.data.index;
19104
19105        var TYPED_ARRAYS = {
19106            'Int8Array': Int8Array,
19107            'Uint8Array': Uint8Array,
19108            'Uint8ClampedArray': Uint8ClampedArray,
19109            'Int16Array': Int16Array,
19110            'Uint16Array': Uint16Array,
19111            'Int32Array': Int32Array,
19112            'Uint32Array': Uint32Array,
19113            'Float32Array': Float32Array,
19114            'Float64Array': Float64Array
19115        };
19116
19117        if ( index !== undefined ) {
19118
19119            var typedArray = new TYPED_ARRAYS[ index.type ]( index.array );
19120            geometry.setIndex( new THREE.BufferAttribute( typedArray, 1 ) );
19121
19122        }
19123
19124        var attributes = json.data.attributes;
19125
19126        for ( var key in attributes ) {
19127
19128            var attribute = attributes[ key ];
19129            var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
19130
19131            geometry.addAttribute( key, new THREE.BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ) );
19132
19133        }
19134
19135        var groups = json.data.groups || json.data.drawcalls || json.data.offsets;
19136
19137        if ( groups !== undefined ) {
19138
19139            for ( var i = 0, n = groups.length; i !== n; ++ i ) {
19140
19141                var group = groups[ i ];
19142
19143                geometry.addGroup( group.start, group.count, group.materialIndex );
19144
19145            }
19146
19147        }
19148
19149        var boundingSphere = json.data.boundingSphere;
19150
19151        if ( boundingSphere !== undefined ) {
19152
19153            var center = new THREE.Vector3();
19154
19155            if ( boundingSphere.center !== undefined ) {
19156
19157                center.fromArray( boundingSphere.center );
19158
19159            }
19160
19161            geometry.boundingSphere = new THREE.Sphere( center, boundingSphere.radius );
19162
19163        }
19164
19165        return geometry;
19166
19167    }
19168
19169};
19170
19171// File:src/loaders/MaterialLoader.js
19172
19173/**
19174 * @author mrdoob / http://mrdoob.com/
19175 */
19176
19177THREE.MaterialLoader = function ( manager ) {
19178
19179    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
19180    this.textures = {};
19181
19182};
19183
19184THREE.MaterialLoader.prototype = {
19185
19186    constructor: THREE.MaterialLoader,
19187
19188    load: function ( url, onLoad, onProgress, onError ) {
19189
19190        var scope = this;
19191
19192        var loader = new THREE.XHRLoader( scope.manager );
19193        loader.load( url, function ( text ) {
19194
19195            onLoad( scope.parse( JSON.parse( text ) ) );
19196
19197        }, onProgress, onError );
19198
19199    },
19200
19201    setTextures: function ( value ) {
19202
19203        this.textures = value;
19204
19205    },
19206
19207    getTexture: function ( name ) {
19208
19209        var textures = this.textures;
19210
19211        if ( textures[ name ] === undefined ) {
19212
19213            console.warn( 'THREE.MaterialLoader: Undefined texture', name );
19214
19215        }
19216
19217        return textures[ name ];
19218
19219    },
19220
19221    parse: function ( json ) {
19222
19223        var material = new THREE[ json.type ];
19224
19225        if ( json.uuid !== undefined ) material.uuid = json.uuid;
19226        if ( json.name !== undefined ) material.name = json.name;
19227        if ( json.color !== undefined ) material.color.setHex( json.color );
19228        if ( json.roughness !== undefined ) material.roughness = json.roughness;
19229        if ( json.metalness !== undefined ) material.metalness = json.metalness;
19230        if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive );
19231        if ( json.specular !== undefined ) material.specular.setHex( json.specular );
19232        if ( json.shininess !== undefined ) material.shininess = json.shininess;
19233        if ( json.uniforms !== undefined ) material.uniforms = json.uniforms;
19234        if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
19235        if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
19236        if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors;
19237        if ( json.shading !== undefined ) material.shading = json.shading;
19238        if ( json.blending !== undefined ) material.blending = json.blending;
19239        if ( json.side !== undefined ) material.side = json.side;
19240        if ( json.opacity !== undefined ) material.opacity = json.opacity;
19241        if ( json.transparent !== undefined ) material.transparent = json.transparent;
19242        if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
19243        if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
19244        if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
19245        if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
19246        if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
19247        if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
19248
19249        // for PointsMaterial
19250        if ( json.size !== undefined ) material.size = json.size;
19251        if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
19252
19253        // maps
19254
19255        if ( json.map !== undefined ) material.map = this.getTexture( json.map );
19256
19257        if ( json.alphaMap !== undefined ) {
19258
19259            material.alphaMap = this.getTexture( json.alphaMap );
19260            material.transparent = true;
19261
19262        }
19263
19264        if ( json.bumpMap !== undefined ) material.bumpMap = this.getTexture( json.bumpMap );
19265        if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
19266
19267        if ( json.normalMap !== undefined ) material.normalMap = this.getTexture( json.normalMap );
19268        if ( json.normalScale !== undefined ) {
19269
19270            var normalScale = json.normalScale;
19271
19272            if ( Array.isArray( normalScale ) === false ) {
19273
19274                // Blender exporter used to export a scalar. See #7459
19275
19276                normalScale = [ normalScale, normalScale ];
19277
19278            }
19279
19280            material.normalScale = new THREE.Vector2().fromArray( normalScale );
19281
19282        }
19283
19284        if ( json.displacementMap !== undefined ) material.displacementMap = this.getTexture( json.displacementMap );
19285        if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
19286        if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
19287
19288        if ( json.roughnessMap !== undefined ) material.roughnessMap = this.getTexture( json.roughnessMap );
19289        if ( json.metalnessMap !== undefined ) material.metalnessMap = this.getTexture( json.metalnessMap );
19290
19291        if ( json.emissiveMap !== undefined ) material.emissiveMap = this.getTexture( json.emissiveMap );
19292        if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
19293
19294        if ( json.specularMap !== undefined ) material.specularMap = this.getTexture( json.specularMap );
19295
19296        if ( json.envMap !== undefined ) {
19297
19298            material.envMap = this.getTexture( json.envMap );
19299            material.combine = THREE.MultiplyOperation;
19300
19301        }
19302
19303        if ( json.reflectivity ) material.reflectivity = json.reflectivity;
19304
19305        if ( json.lightMap !== undefined ) material.lightMap = this.getTexture( json.lightMap );
19306        if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
19307
19308        if ( json.aoMap !== undefined ) material.aoMap = this.getTexture( json.aoMap );
19309        if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
19310
19311        // MultiMaterial
19312
19313        if ( json.materials !== undefined ) {
19314
19315            for ( var i = 0, l = json.materials.length; i < l; i ++ ) {
19316
19317                material.materials.push( this.parse( json.materials[ i ] ) );
19318
19319            }
19320
19321        }
19322
19323        return material;
19324
19325    }
19326
19327};
19328
19329// File:src/loaders/ObjectLoader.js
19330
19331/**
19332 * @author mrdoob / http://mrdoob.com/
19333 */
19334
19335THREE.ObjectLoader = function ( manager ) {
19336
19337    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
19338    this.texturePath = '';
19339
19340};
19341
19342THREE.ObjectLoader.prototype = {
19343
19344    constructor: THREE.ObjectLoader,
19345
19346    load: function ( url, onLoad, onProgress, onError ) {
19347
19348        if ( this.texturePath === '' ) {
19349
19350            this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );
19351
19352        }
19353
19354        var scope = this;
19355
19356        var loader = new THREE.XHRLoader( scope.manager );
19357        loader.load( url, function ( text ) {
19358
19359            scope.parse( JSON.parse( text ), onLoad );
19360
19361        }, onProgress, onError );
19362
19363    },
19364
19365    setTexturePath: function ( value ) {
19366
19367        this.texturePath = value;
19368
19369    },
19370
19371    setCrossOrigin: function ( value ) {
19372
19373        this.crossOrigin = value;
19374
19375    },
19376
19377    parse: function ( json, onLoad ) {
19378
19379        var geometries = this.parseGeometries( json.geometries );
19380
19381        var images = this.parseImages( json.images, function () {
19382
19383            if ( onLoad !== undefined ) onLoad( object );
19384
19385        } );
19386
19387        var textures  = this.parseTextures( json.textures, images );
19388        var materials = this.parseMaterials( json.materials, textures );
19389
19390        var object = this.parseObject( json.object, geometries, materials );
19391
19392        if ( json.animations ) {
19393
19394            object.animations = this.parseAnimations( json.animations );
19395
19396        }
19397
19398        if ( json.images === undefined || json.images.length === 0 ) {
19399
19400            if ( onLoad !== undefined ) onLoad( object );
19401
19402        }
19403
19404        return object;
19405
19406    },
19407
19408    parseGeometries: function ( json ) {
19409
19410        var geometries = {};
19411
19412        if ( json !== undefined ) {
19413
19414            var geometryLoader = new THREE.JSONLoader();
19415            var bufferGeometryLoader = new THREE.BufferGeometryLoader();
19416
19417            for ( var i = 0, l = json.length; i < l; i ++ ) {
19418
19419                var geometry;
19420                var data = json[ i ];
19421
19422                switch ( data.type ) {
19423
19424                    case 'PlaneGeometry':
19425                    case 'PlaneBufferGeometry':
19426
19427                        geometry = new THREE[ data.type ](
19428                            data.width,
19429                            data.height,
19430                            data.widthSegments,
19431                            data.heightSegments
19432                        );
19433
19434                        break;
19435
19436                    case 'BoxGeometry':
19437                    case 'BoxBufferGeometry':
19438                    case 'CubeGeometry': // backwards compatible
19439
19440                        geometry = new THREE[ data.type ](
19441                            data.width,
19442                            data.height,
19443                            data.depth,
19444                            data.widthSegments,
19445                            data.heightSegments,
19446                            data.depthSegments
19447                        );
19448
19449                        break;
19450
19451                    case 'CircleGeometry':
19452                    case 'CircleBufferGeometry':
19453
19454                        geometry = new THREE[ data.type ](
19455                            data.radius,
19456                            data.segments,
19457                            data.thetaStart,
19458                            data.thetaLength
19459                        );
19460
19461                        break;
19462
19463                    case 'CylinderGeometry':
19464                    case 'CylinderBufferGeometry':
19465
19466                        geometry = new THREE[ data.type ](
19467                            data.radiusTop,
19468                            data.radiusBottom,
19469                            data.height,
19470                            data.radialSegments,
19471                            data.heightSegments,
19472                            data.openEnded,
19473                            data.thetaStart,
19474                            data.thetaLength
19475                        );
19476
19477                        break;
19478
19479                    case 'SphereGeometry':
19480                    case 'SphereBufferGeometry':
19481
19482                        geometry = new THREE[ data.type ](
19483                            data.radius,
19484                            data.widthSegments,
19485                            data.heightSegments,
19486                            data.phiStart,
19487                            data.phiLength,
19488                            data.thetaStart,
19489                            data.thetaLength
19490                        );
19491
19492                        break;
19493
19494                    case 'DodecahedronGeometry':
19495
19496                        geometry = new THREE.DodecahedronGeometry(
19497                            data.radius,
19498                            data.detail
19499                        );
19500
19501                        break;
19502
19503                    case 'IcosahedronGeometry':
19504
19505                        geometry = new THREE.IcosahedronGeometry(
19506                            data.radius,
19507                            data.detail
19508                        );
19509
19510                        break;
19511
19512                    case 'OctahedronGeometry':
19513
19514                        geometry = new THREE.OctahedronGeometry(
19515                            data.radius,
19516                            data.detail
19517                        );
19518
19519                        break;
19520
19521                    case 'TetrahedronGeometry':
19522
19523                        geometry = new THREE.TetrahedronGeometry(
19524                            data.radius,
19525                            data.detail
19526                        );
19527
19528                        break;
19529
19530                    case 'RingGeometry':
19531                    case 'RingBufferGeometry':
19532
19533                        geometry = new THREE[ data.type ](
19534                            data.innerRadius,
19535                            data.outerRadius,
19536                            data.thetaSegments,
19537                            data.phiSegments,
19538                            data.thetaStart,
19539                            data.thetaLength
19540                        );
19541
19542                        break;
19543
19544                    case 'TorusGeometry':
19545                    case 'TorusBufferGeometry':
19546
19547                        geometry = new THREE[ data.type ](
19548                            data.radius,
19549                            data.tube,
19550                            data.radialSegments,
19551                            data.tubularSegments,
19552                            data.arc
19553                        );
19554
19555                        break;
19556
19557                    case 'TorusKnotGeometry':
19558                    case 'TorusKnotBufferGeometry':
19559
19560                        geometry = new THREE[ data.type ](
19561                            data.radius,
19562                            data.tube,
19563                            data.tubularSegments,
19564                            data.radialSegments,
19565                            data.p,
19566                            data.q
19567                        );
19568
19569                        break;
19570
19571                    case 'LatheGeometry':
19572                    case 'LatheBufferGeometry':
19573
19574                        geometry = new THREE[ data.type ](
19575                            data.points,
19576                            data.segments,
19577                            data.phiStart,
19578                            data.phiLength
19579                        );
19580
19581                        break;
19582
19583                    case 'BufferGeometry':
19584
19585                        geometry = bufferGeometryLoader.parse( data );
19586
19587                        break;
19588
19589                    case 'Geometry':
19590
19591                        geometry = geometryLoader.parse( data.data, this.texturePath ).geometry;
19592
19593                        break;
19594
19595                    default:
19596
19597                        console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
19598
19599                        continue;
19600
19601                }
19602
19603                geometry.uuid = data.uuid;
19604
19605                if ( data.name !== undefined ) geometry.name = data.name;
19606
19607                geometries[ data.uuid ] = geometry;
19608
19609            }
19610
19611        }
19612
19613        return geometries;
19614
19615    },
19616
19617    parseMaterials: function ( json, textures ) {
19618
19619        var materials = {};
19620
19621        if ( json !== undefined ) {
19622
19623            var loader = new THREE.MaterialLoader();
19624            loader.setTextures( textures );
19625
19626            for ( var i = 0, l = json.length; i < l; i ++ ) {
19627
19628                var material = loader.parse( json[ i ] );
19629                materials[ material.uuid ] = material;
19630
19631            }
19632
19633        }
19634
19635        return materials;
19636
19637    },
19638
19639    parseAnimations: function ( json ) {
19640
19641        var animations = [];
19642
19643        for ( var i = 0; i < json.length; i ++ ) {
19644
19645            var clip = THREE.AnimationClip.parse( json[ i ] );
19646
19647            animations.push( clip );
19648
19649        }
19650
19651        return animations;
19652
19653    },
19654
19655    parseImages: function ( json, onLoad ) {
19656
19657        var scope = this;
19658        var images = {};
19659
19660        function loadImage( url ) {
19661
19662            scope.manager.itemStart( url );
19663
19664            return loader.load( url, function () {
19665
19666                scope.manager.itemEnd( url );
19667
19668            } );
19669
19670        }
19671
19672        if ( json !== undefined && json.length > 0 ) {
19673
19674            var manager = new THREE.LoadingManager( onLoad );
19675
19676            var loader = new THREE.ImageLoader( manager );
19677            load
19677er.setCrossOrigin( this.crossOrigin );
19678
19679            for ( var i = 0, l = json.length; i < l; i ++ ) {
19680
19681                var image = json[ i ];
19682                var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url;
19683
19684                images[ image.uuid ] = loadImage( path );
19685
19686            }
19687
19688        }
19689
19690        return images;
19691
19692    },
19693
19694    parseTextures: function ( json, images ) {
19695
19696        function parseConstant( value ) {
19697
19698            if ( typeof( value ) === 'number' ) return value;
19699
19700            console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
19701
19702            return THREE[ value ];
19703
19704        }
19705
19706        var textures = {};
19707
19708        if ( json !== undefined ) {
19709
19710            for ( var i = 0, l = json.length; i < l; i ++ ) {
19711
19712                var data = json[ i ];
19713
19714                if ( data.image === undefined ) {
19715
19716                    console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
19717
19718                }
19719
19720                if ( images[ data.image ] === undefined ) {
19721
19722                    console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
19723
19724                }
19725
19726                var texture = new THREE.Texture( images[ data.image ] );
19727                texture.needsUpdate = true;
19728
19729                texture.uuid = data.uuid;
19730
19731                if ( data.name !== undefined ) texture.name = data.name;
19732                if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping );
19733                if ( data.offset !== undefined ) texture.offset = new THREE.Vector2( data.offset[ 0 ], data.offset[ 1 ] );
19734                if ( data.repeat !== undefined ) texture.repeat = new THREE.Vector2( data.repeat[ 0 ], data.repeat[ 1 ] );
19735                if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter );
19736                if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter );
19737                if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
19738                if ( Array.isArray( data.wrap ) ) {
19739
19740                    texture.wrapS = parseConstant( data.wrap[ 0 ] );
19741                    texture.wrapT = parseConstant( data.wrap[ 1 ] );
19742
19743                }
19744
19745                textures[ data.uuid ] = texture;
19746
19747            }
19748
19749        }
19750
19751        return textures;
19752
19753    },
19754
19755    parseObject: function () {
19756
19757        var matrix = new THREE.Matrix4();
19758
19759        return function ( data, geometries, materials ) {
19760
19761            var object;
19762
19763            function getGeometry( name ) {
19764
19765                if ( geometries[ name ] === undefined ) {
19766
19767                    console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
19768
19769                }
19770
19771                return geometries[ name ];
19772
19773            }
19774
19775            function getMaterial( name ) {
19776
19777                if ( name === undefined ) return undefined;
19778
19779                if ( materials[ name ] === undefined ) {
19780
19781                    console.warn( 'THREE.ObjectLoader: Undefined material', name );
19782
19783                }
19784
19785                return materials[ name ];
19786
19787            }
19788
19789            switch ( data.type ) {
19790
19791                case 'Scene':
19792
19793                    object = new THREE.Scene();
19794
19795                    break;
19796
19797                case 'PerspectiveCamera':
19798
19799                    object = new THREE.PerspectiveCamera(
19800                        data.fov, data.aspect, data.near, data.far );
19801
19802                    if ( data.focus !== undefined ) object.focus = data.focus;
19803                    if ( data.zoom !== undefined ) object.zoom = data.zoom;
19804                    if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
19805                    if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
19806                    if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
19807
19808                    break;
19809
19810                case 'OrthographicCamera':
19811
19812                    object = new THREE.OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
19813
19814                    break;
19815
19816                case 'AmbientLight':
19817
19818                    object = new THREE.AmbientLight( data.color, data.intensity );
19819
19820                    break;
19821
19822                case 'DirectionalLight':
19823
19824                    object = new THREE.DirectionalLight( data.color, data.intensity );
19825
19826                    break;
19827
19828                case 'PointLight':
19829
19830                    object = new THREE.PointLight( data.color, data.intensity, data.distance, data.decay );
19831
19832                    break;
19833
19834                case 'SpotLight':
19835
19836                    object = new THREE.SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
19837
19838                    break;
19839
19840                case 'HemisphereLight':
19841
19842                    object = new THREE.HemisphereLight( data.color, data.groundColor, data.intensity );
19843
19844                    break;
19845
19846                case 'Mesh':
19847
19848                    var geometry = getGeometry( data.geometry );
19849                    var material = getMaterial( data.material );
19850
19851                    if ( geometry.bones && geometry.bones.length > 0 ) {
19852
19853                        object = new THREE.SkinnedMesh( geometry, material );
19854
19855                    } else {
19856
19857                        object = new THREE.Mesh( geometry, material );
19858
19859                    }
19860
19861                    break;
19862
19863                case 'LOD':
19864
19865                    object = new THREE.LOD();
19866
19867                    break;
19868
19869                case 'Line':
19870
19871                    object = new THREE.Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
19872
19873                    break;
19874
19875                case 'PointCloud':
19876                case 'Points':
19877
19878                    object = new THREE.Points( getGeometry( data.geometry ), getMaterial( data.material ) );
19879
19880                    break;
19881
19882                case 'Sprite':
19883
19884                    object = new THREE.Sprite( getMaterial( data.material ) );
19885
19886                    break;
19887
19888                case 'Group':
19889
19890                    object = new THREE.Group();
19891
19892                    break;
19893
19894                default:
19895
19896                    object = new THREE.Object3D();
19897
19898            }
19899
19900            object.uuid = data.uuid;
19901
19902            if ( data.name !== undefined ) object.name = data.name;
19903            if ( data.matrix !== undefined ) {
19904
19905                matrix.fromArray( data.matrix );
19906                matrix.decompose( object.position, object.quaternion, object.scale );
19907
19908            } else {
19909
19910                if ( data.position !== undefined ) object.position.fromArray( data.position );
19911                if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
19912                if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
19913
19914            }
19915
19916            if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
19917            if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
19918
19919            if ( data.visible !== undefined ) object.visible = data.visible;
19920            if ( data.userData !== undefined ) object.userData = data.userData;
19921
19922            if ( data.children !== undefined ) {
19923
19924                for ( var child in data.children ) {
19925
19926                    object.add( this.parseObject( data.children[ child ], geometries, materials ) );
19927
19928                }
19929
19930            }
19931
19932            if ( data.type === 'LOD' ) {
19933
19934                var levels = data.levels;
19935
19936                for ( var l = 0; l < levels.length; l ++ ) {
19937
19938                    var level = levels[ l ];
19939                    var child = object.getObjectByProperty( 'uuid', level.object );
19940
19941                    if ( child !== undefined ) {
19942
19943                        object.addLevel( child, level.distance );
19944
19945                    }
19946
19947                }
19948
19949            }
19950
19951            return object;
19952
19953        };
19954
19955    }()
19956
19957};
19958
19959// File:src/loaders/TextureLoader.js
19960
19961/**
19962 * @author mrdoob / http://mrdoob.com/
19963 */
19964
19965THREE.TextureLoader = function ( manager ) {
19966
19967    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
19968
19969};
19970
19971THREE.TextureLoader.prototype = {
19972
19973    constructor: THREE.TextureLoader,
19974
19975    load: function ( url, onLoad, onProgress, onError ) {
19976
19977        var texture = new THREE.Texture();
19978
19979        var loader = new THREE.ImageLoader( this.manager );
19980        loader.setCrossOrigin( this.crossOrigin );
19981        loader.setPath( this.path );
19982        loader.load( url, function ( image ) {
19983
19984            texture.image = image;
19985            texture.needsUpdate = true;
19986
19987            if ( onLoad !== undefined ) {
19988
19989                onLoad( texture );
19990
19991            }
19992
19993        }, onProgress, onError );
19994
19995        return texture;
19996
19997    },
19998
19999    setCrossOrigin: function ( value ) {
20000
20001        this.crossOrigin = value;
20002
20003    },
20004
20005    setPath: function ( value ) {
20006
20007        this.path = value;
20008
20009    }
20010
20011};
20012
20013// File:src/loaders/CubeTextureLoader.js
20014
20015/**
20016 * @author mrdoob / http://mrdoob.com/
20017 */
20018
20019THREE.CubeTextureLoader = function ( manager ) {
20020
20021    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
20022
20023};
20024
20025THREE.CubeTextureLoader.prototype = {
20026
20027    constructor: THREE.CubeTextureLoader,
20028
20029    load: function ( urls, onLoad, onProgress, onError ) {
20030
20031        var texture = new THREE.CubeTexture();
20032
20033        var loader = new THREE.ImageLoader( this.manager );
20034        loader.setCrossOrigin( this.crossOrigin );
20035        loader.setPath( this.path );
20036
20037        var loaded = 0;
20038
20039        function loadTexture( i ) {
20040
20041            loader.load( urls[ i ], function ( image ) {
20042
20043                texture.images[ i ] = image;
20044
20045                loaded ++;
20046
20047                if ( loaded === 6 ) {
20048
20049                    texture.needsUpdate = true;
20050
20051                    if ( onLoad ) onLoad( texture );
20052
20053                }
20054
20055            }, undefined, onError );
20056
20057        }
20058
20059        for ( var i = 0; i < urls.length; ++ i ) {
20060
20061            loadTexture( i );
20062
20063        }
20064
20065        return texture;
20066
20067    },
20068
20069    setCrossOrigin: function ( value ) {
20070
20071        this.crossOrigin = value;
20072
20073    },
20074
20075    setPath: function ( value ) {
20076
20077        this.path = value;
20078
20079    }
20080
20081};
20082
20083// File:src/loaders/BinaryTextureLoader.js
20084
20085/**
20086 * @author Nikos M. / https://github.com/foo123/
20087 *
20088 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
20089 */
20090
20091THREE.DataTextureLoader = THREE.BinaryTextureLoader = function ( manager ) {
20092
20093    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
20094
20095    // override in sub classes
20096    this._parser = null;
20097
20098};
20099
20100THREE.BinaryTextureLoader.prototype = {
20101
20102    constructor: THREE.BinaryTextureLoader,
20103
20104    load: function ( url, onLoad, onProgress, onError ) {
20105
20106        var scope = this;
20107
20108        var texture = new THREE.DataTexture();
20109
20110        var loader = new THREE.XHRLoader( this.manager );
20111        loader.setResponseType( 'arraybuffer' );
20112
20113        loader.load( url, function ( buffer ) {
20114
20115            var texData = scope._parser( buffer );
20116
20117            if ( ! texData ) return;
20118
20119            if ( undefined !== texData.image ) {
20120
20121                texture.image = texData.image;
20122
20123            } else if ( undefined !== texData.data ) {
20124
20125                texture.image.width = texData.width;
20126                texture.image.height = texData.height;
20127                texture.image.data = texData.data;
20128
20129            }
20130
20131            texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : THREE.ClampToEdgeWrapping;
20132            texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : THREE.ClampToEdgeWrapping;
20133
20134            texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : THREE.LinearFilter;
20135            texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : THREE.LinearMipMapLinearFilter;
20136
20137            texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1;
20138
20139            if ( undefined !== texData.format ) {
20140
20141                texture.format = texData.format;
20142
20143            }
20144            if ( undefined !== texData.type ) {
20145
20146                texture.type = texData.type;
20147
20148            }
20149
20150            if ( undefined !== texData.mipmaps ) {
20151
20152                texture.mipmaps = texData.mipmaps;
20153
20154            }
20155
20156            if ( 1 === texData.mipmapCount ) {
20157
20158                texture.minFilter = THREE.LinearFilter;
20159
20160            }
20161
20162            texture.needsUpdate = true;
20163
20164            if ( onLoad ) onLoad( texture, texData );
20165
20166        }, onProgress, onError );
20167
20168
20169        return texture;
20170
20171    }
20172
20173};
20174
20175// File:src/loaders/CompressedTextureLoader.js
20176
20177/**
20178 * @author mrdoob / http://mrdoob.com/
20179 *
20180 * Abstract Base class to block based textures loader (dds, pvr, ...)
20181 */
20182
20183THREE.CompressedTextureLoader = function ( manager ) {
20184
20185    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
20186
20187    // override in sub classes
20188    this._parser = null;
20189
20190};
20191
20192
20193THREE.CompressedTextureLoader.prototype = {
20194
20195    constructor: THREE.CompressedTextureLoader,
20196
20197    load: function ( url, onLoad, onProgress, onError ) {
20198
20199        var scope = this;
20200
20201        var images = [];
20202
20203        var texture = new THREE.CompressedTexture();
20204        texture.image = images;
20205
20206        var loader = new THREE.XHRLoader( this.manager );
20207        loader.setPath( this.path );
20208        loader.setResponseType( 'arraybuffer' );
20209
20210        function loadTexture( i ) {
20211
20212            loader.load( url[ i ], function ( buffer ) {
20213
20214                var texDatas = scope._parser( buffer, true );
20215
20216                images[ i ] = {
20217                    width: texDatas.width,
20218                    height: texDatas.height,
20219                    format: texDatas.format,
20220                    mipmaps: texDatas.mipmaps
20221                };
20222
20223                loaded += 1;
20224
20225                if ( loaded === 6 ) {
20226
20227                    if ( texDatas.mipmapCount === 1 )
20228                        texture.minFilter = THREE.LinearFilter;
20229
20230                    texture.format = texDatas.format;
20231                    texture.needsUpdate = true;
20232
20233                    if ( onLoad ) onLoad( texture );
20234
20235                }
20236
20237            }, onProgress, onError );
20238
20239        }
20240
20241        if ( Array.isArray( url ) ) {
20242
20243            var loaded = 0;
20244
20245            for ( var i = 0, il = url.length; i < il; ++ i ) {
20246
20247                loadTexture( i );
20248
20249            }
20250
20251        } else {
20252
20253            // compressed cubemap texture stored in a single DDS file
20254
20255            loader.load( url, function ( buffer ) {
20256
20257                var texDatas = scope._parser( buffer, true );
20258
20259                if ( texDatas.isCubemap ) {
20260
20261                    var faces = texDatas.mipmaps.length / texDatas.mipmapCount;
20262
20263                    for ( var f = 0; f < faces; f ++ ) {
20264
20265                        images[ f ] = { mipmaps : [] };
20266
20267                        for ( var i = 0; i < texDatas.mipmapCount; i ++ ) {
20268
20269                            images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
20270                            images[ f ].format = texDatas.format;
20271                            images[ f ].width = texDatas.width;
20272                            images[ f ].height = texDatas.height;
20273
20274                        }
20275
20276                    }
20277
20278                } else {
20279
20280                    texture.image.width = texDatas.width;
20281                    texture.image.height = texDatas.height;
20282                    texture.mipmaps = texDatas.mipmaps;
20283
20284                }
20285
20286                if ( texDatas.mipmapCount === 1 ) {
20287
20288                    texture.minFilter = THREE.LinearFilter;
20289
20290                }
20291
20292                texture.format = texDatas.format;
20293                texture.needsUpdate = true;
20294
20295                if ( onLoad ) onLoad( texture );
20296
20297            }, onProgress, onError );
20298
20299        }
20300
20301        return texture;
20302
20303    },
20304
20305    setPath: function ( value ) {
20306
20307        this.path = value;
20308
20309    }
20310
20311};
20312
20313// File:src/materials/Material.js
20314
20315/**
20316 * @author mrdoob / http://mrdoob.com/
20317 * @author alteredq / http://alteredqualia.com/
20318 */
20319
20320THREE.Material = function () {
20321
20322    Object.defineProperty( this, 'id', { value: THREE.MaterialIdCount ++ } );
20323
20324    this.uuid = THREE.Math.generateUUID();
20325
20326    this.name = '';
20327    this.type = 'Material';
20328
20329    this.side = THREE.FrontSide;
20330
20331    this.opacity = 1;
20332    this.transparent = false;
20333
20334    this.blending = THREE.NormalBlending;
20335
20336    this.blendSrc = THREE.SrcAlphaFactor;
20337    this.blendDst = THREE.OneMinusSrcAlphaFactor;
20338    this.blendEquation = THREE.AddEquation;
20339    this.blendSrcAlpha = null;
20340    this.blendDstAlpha = null;
20341    this.blendEquationAlpha = null;
20342
20343    this.depthFunc = THREE.LessEqualDepth;
20344    this.depthTest = true;
20345    this.depthWrite = true;
20346
20347    this.clippingPlanes = null;
20348    this.clipShadows = false;
20349
20350    this.colorWrite = true;
20351
20352    this.precision = null; // override the renderer's default precision for this material
20353
20354    this.polygonOffset = false;
20355    this.polygonOffsetFactor = 0;
20356    this.polygonOffsetUnits = 0;
20357
20358    this.alphaTest = 0;
20359    this.premultipliedAlpha = false;
20360
20361    this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer
20362
20363    this.visible = true;
20364
20365    this._needsUpdate = true;
20366
20367};
20368
20369THREE.Material.prototype = {
20370
20371    constructor: THREE.Material,
20372
20373    get needsUpdate () {
20374
20375        return this._needsUpdate;
20376
20377    },
20378
20379    set needsUpdate ( value ) {
20380
20381        if ( value === true ) this.update();
20382
20383        this._needsUpdate = value;
20384
20385    },
20386
20387    setValues: function ( values ) {
20388
20389        if ( values === undefined ) return;
20390
20391        for ( var key in values ) {
20392
20393            var newValue = values[ key ];
20394
20395            if ( newValue === undefined ) {
20396
20397                console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
20398                continue;
20399
20400            }
20401
20402            var currentValue = this[ key ];
20403
20404            if ( currentValue === undefined ) {
20405
20406                console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
20407                continue;
20408
20409            }
20410
20411            if ( currentValue instanceof THREE.Color ) {
20412
20413                currentValue.set( newValue );
20414
20415            } else if ( currentValue instanceof THREE.Vector3 && newValue instanceof THREE.Vector3 ) {
20416
20417                currentValue.copy( newValue );
20418
20419            } else if ( key === 'overdraw' ) {
20420
20421                // ensure overdraw is backwards-compatible with legacy boolean type
20422                this[ key ] = Number( newValue );
20423
20424            } else {
20425
20426                this[ key ] = newValue;
20427
20428            }
20429
20430        }
20431
20432    },
20433
20434    toJSON: function ( meta ) {
20435
20436        var isRoot = meta === undefined;
20437
20438        if ( isRoot ) {
20439
20440            meta = {
20441                textures: {},
20442                images: {}
20443            };
20444
20445        }
20446
20447        var data = {
20448            metadata: {
20449                version: 4.4,
20450                type: 'Material',
20451                generator: 'Material.toJSON'
20452            }
20453        };
20454
20455        // standard Material serialization
20456        data.uuid = this.uuid;
20457        data.type = this.type;
20458        if ( this.name !== '' ) data.name = this.name;
20459
20460        if ( this.color instanceof THREE.Color ) data.color = this.color.getHex();
20461
20462        if ( this.roughness !== 0.5 ) data.roughness = this.roughness;
20463        if ( this.metalness !== 0.5 ) data.metalness = this.metalness;
20464
20465        if ( this.emissive instanceof THREE.Color ) data.emissive = this.emissive.getHex();
20466        if ( this.specular instanceof THREE.Color ) data.specular = this.specular.getHex();
20467        if ( this.shininess !== undefined ) data.shininess = this.shininess;
20468
20469        if ( this.map instanceof THREE.Texture ) data.map = this.map.toJSON( meta ).uuid;
20470        if ( this.alphaMap instanceof THREE.Texture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
20471        if ( this.lightMap instanceof THREE.Texture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
20472        if ( this.bumpMap instanceof THREE.Texture ) {
20473
20474            data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
20475            data.bumpScale = this.bumpScale;
20476
20477        }
20478        if ( this.normalMap instanceof THREE.Texture ) {
20479
20480            data.normalMap = this.normalMap.toJSON( meta ).uuid;
20481            data.normalScale = this.normalScale.toArray();
20482
20483        }
20484        if ( this.displacementMap instanceof THREE.Texture ) {
20485
20486            data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
20487            data.displacementScale = this.displacementScale;
20488            data.displacementBias = this.displacementBias;
20489
20490        }
20491        if ( this.roughnessMap instanceof THREE.Texture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
20492        if ( this.metalnessMap instanceof THREE.Texture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
20493
20494        if ( this.emissiveMap instanceof THREE.Texture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
20495        if ( this.specularMap instanceof THREE.Texture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
20496
20497        if ( this.envMap instanceof THREE.Texture ) {
20498
20499            data.envMap = this.envMap.toJSON( meta ).uuid;
20500            data.reflectivity = this.reflectivity; // Scale behind envMap
20501
20502        }
20503
20504        if ( this.size !== undefined ) data.size = this.size;
20505        if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
20506
20507        if ( this.vertexColors !== undefined && this.vertexColors !== THREE.NoColors ) data.vertexColors = this.vertexColors;
20508        if ( this.shading !== undefined && this.shading !== THREE.SmoothShading ) data.shading = this.shading;
20509        if ( this.blending !== undefined && this.blending !== THREE.NormalBlending ) data.blending = this.blending;
20510        if ( this.side !== undefined && this.side !== THREE.FrontSide ) data.side = this.side;
20511
20512        if ( this.opacity < 1 ) data.opacity = this.opacity;
20513        if ( this.transparent === true ) data.transparent = this.transparent;
20514        if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
20515        if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
20516        if ( this.wireframe === true ) data.wireframe = this.wireframe;
20517        if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
20518
20519        // TODO: Copied from Object3D.toJSON
20520
20521        function extractFromCache ( cache ) {
20522
20523            var values = [];
20524
20525            for ( var key in cache ) {
20526
20527                var data = cache[ key ];
20528                delete data.metadata;
20529                values.push( data );
20530
20531            }
20532
20533            return values;
20534
20535        }
20536
20537        if ( isRoot ) {
20538
20539            var textures = extractFromCache( meta.textures );
20540            var images = extractFromCache( meta.images );
20541
20542            if ( textures.length > 0 ) data.textures = textures;
20543            if ( images.length > 0 ) data.images = images;
20544
20545        }
20546
20547        return data;
20548
20549    },
20550
20551    clone: function () {
20552
20553        return new this.constructor().copy( this );
20554
20555    },
20556
20557    copy: function ( source ) {
20558
20559        this.name = source.name;
20560
20561        this.side = source.side;
20562
20563        this.opacity = source.opacity;
20564        this.transparent = source.transparent;
20565
20566        this.blending = source.blending;
20567
20568        this.blendSrc = source.blendSrc;
20569        this.blendDst = source.blendDst;
20570        this.blendEquation = source.blendEquation;
20571        this.blendSrcAlpha = source.blendSrcAlpha;
20572        this.blendDstAlpha = source.blendDstAlpha;
20573        this.blendEquationAlpha = source.blendEquationAlpha;
20574
20575        this.depthFunc = source.depthFunc;
20576        this.depthTest = source.depthTest;
20577        this.depthWrite = source.depthWrite;
20578
20579        this.colorWrite = source.colorWrite;
20580
20581        this.precision = source.precision;
20582
20583        this.polygonOffset = source.polygonOffset;
20584        this.polygonOffsetFactor = source.polygonOffsetFactor;
20585        this.polygonOffsetUnits = source.polygonOffsetUnits;
20586
20587        this.alphaTest = source.alphaTest;
20588
20589        this.premultipliedAlpha = source.premultipliedAlpha;
20590
20591        this.overdraw = source.overdraw;
20592
20593        this.visible = source.visible;
20594        this.clipShadows = source.clipShadows;
20595
20596        var srcPlanes = source.clippingPlanes,
20597            dstPlanes = null;
20598
20599        if ( srcPlanes !== null ) {
20600
20601            var n = srcPlanes.length;
20602            dstPlanes = new Array( n );
20603
20604            for ( var i = 0; i !== n; ++ i )
20605                dstPlanes[ i ] = srcPlanes[ i ].clone();
20606
20607        }
20608
20609        this.clippingPlanes = dstPlanes;
20610
20611        return this;
20612
20613    },
20614
20615    update: function () {
20616
20617        this.dispatchEvent( { type: 'update' } );
20618
20619    },
20620
20621    dispose: function () {
20622
20623        this.dispatchEvent( { type: 'dispose' } );
20624
20625    }
20626
20627};
20628
20629THREE.EventDispatcher.prototype.apply( THREE.Material.prototype );
20630
20631THREE.MaterialIdCount = 0;
20632
20633// File:src/materials/LineBasicMaterial.js
20634
20635/**
20636 * @author mrdoob / http://mrdoob.com/
20637 * @author alteredq / http://alteredqualia.com/
20638 *
20639 * parameters = {
20640 *  color: <hex>,
20641 *  opacity: <float>,
20642 *
20643 *  linewidth: <float>,
20644 *  linecap: "round",
20645 *  linejoin: "round",
20646 *
20647 *  blending: THREE.NormalBlending,
20648 *  depthTest: <bool>,
20649 *  depthWrite: <bool>,
20650 *
20651 *  vertexColors: <bool>
20652 *
20653 *  fog: <bool>
20654 * }
20655 */
20656
20657THREE.LineBasicMaterial = function ( parameters ) {
20658
20659    THREE.Material.call( this );
20660
20661    this.type = 'LineBasicMaterial';
20662
20663    this.color = new THREE.Color( 0xffffff );
20664
20665    this.linewidth = 1;
20666    this.linecap = 'round';
20667    this.linejoin = 'round';
20668
20669    this.blending = THREE.NormalBlending;
20670
20671    this.vertexColors = THREE.NoColors;
20672
20673    this.fog = true;
20674
20675    this.setValues( parameters );
20676
20677};
20678
20679THREE.LineBasicMaterial.prototype = Object.create( THREE.Material.prototype );
20680THREE.LineBasicMaterial.prototype.constructor = THREE.LineBasicMaterial;
20681
20682THREE.LineBasicMaterial.prototype.copy = function ( source ) {
20683
20684    THREE.Material.prototype.copy.call( this, source );
20685
20686    this.color.copy( source.color );
20687
20688    this.linewidth = source.linewidth;
20689    this.linecap = source.linecap;
20690    this.linejoin = source.linejoin;
20691
20692    this.vertexColors = source.vertexColors;
20693
20694    this.fog = source.fog;
20695
20696    return this;
20697
20698};
20699
20700// File:src/materials/LineDashedMaterial.js
20701
20702/**
20703 * @author alteredq / http://alteredqualia.com/
20704 *
20705 * parameters = {
20706 *  color: <hex>,
20707 *  opacity: <float>,
20708 *
20709 *  linewidth: <float>,
20710 *
20711 *  scale: <float>,
20712 *  dashSize: <float>,
20713 *  gapSize: <float>,
20714 *
20715 *  blending: THREE.NormalBlending,
20716 *  depthTest: <bool>,
20717 *  depthWrite: <bool>,
20718 *
20719 *  vertexColors: THREE.NoColors / THREE.FaceColors / THREE.VertexColors
20720 *
20721 *  fog: <bool>
20722 * }
20723 */
20724
20725THREE.LineDashedMaterial = function ( parameters ) {
20726
20727    THREE.Material.call( this );
20728
20729    this.type = 'LineDashedMaterial';
20730
20731    this.color = new THREE.Color( 0xffffff );
20732
20733    this.linewidth = 1;
20734
20735    this.scale = 1;
20736    this.dashSize = 3;
20737    this.gapSize = 1;
20738
20739    this.blending = THREE.NormalBlending;
20740
20741    this.vertexColors = THREE.NoColors;
20742
20743    this.fog = true;
20744
20745    this.setValues( parameters );
20746
20747};
20748
20749THREE.LineDashedMaterial.prototype = Object.create( THREE.Material.prototype );
20750THREE.LineDashedMaterial.prototype.constructor = THREE.LineDashedMaterial;
20751
20752THREE.LineDashedMaterial.prototype.copy = function ( source ) {
20753
20754    THREE.Material.prototype.copy.call( this, source );
20755
20756    this.color.copy( source.color );
20757
20758    this.linewidth = source.linewidth;
20759
20760    this.scale = source.scale;
20761    this.dashSize = source.dashSize;
20762    this.gapSize = source.gapSize;
20763
20764    this.vertexColors = source.vertexColors;
20765
20766    this.fog = source.fog;
20767
20768    return this;
20769
20770};
20771
20772// File:src/materials/MeshBasicMaterial.js
20773
20774/**
20775 * @author mrdoob / http://mrdoob.com/
20776 * @author alteredq / http://alteredqualia.com/
20777 *
20778 * parameters = {
20779 *  color: <hex>,
20780 *  opacity: <float>,
20781 *  map: new THREE.Texture( <Image> ),
20782 *
20783 *  aoMap: new THREE.Texture( <Image> ),
20784 *  aoMapIntensity: <float>
20785 *
20786 *  specularMap: new THREE.Texture( <Image> ),
20787 *
20788 *  alphaMap: new THREE.Texture( <Image> ),
20789 *
20790 *  envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
20791 *  combine: THREE.Multiply,
20792 *  reflectivity: <float>,
20793 *  refractionRatio: <float>,
20794 *
20795 *  shading: THREE.SmoothShading,
20796 *  blending: THREE.NormalBlending,
20797 *  depthTest: <bool>,
20798 *  depthWrite: <bool>,
20799 *
20800 *  wireframe: <boolean>,
20801 *  wireframeLinewidth: <float>,
20802 *
20803 *  vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
20804 *
20805 *  skinning: <bool>,
20806 *  morphTargets: <bool>,
20807 *
20808 *  fog: <bool>
20809 * }
20810 */
20811
20812THREE.MeshBasicMaterial = function ( parameters ) {
20813
20814    THREE.Material.call( this );
20815
20816    this.type = 'MeshBasicMaterial';
20817
20818    this.color = new THREE.Color( 0xffffff ); // emissive
20819
20820    this.map = null;
20821
20822    this.aoMap = null;
20823    this.aoMapIntensity = 1.0;
20824
20825    this.specularMap = null;
20826
20827    this.alphaMap = null;
20828
20829    this.envMap = null;
20830    this.combine = THREE.MultiplyOperation;
20831    this.reflectivity = 1;
20832    this.refractionRatio = 0.98;
20833
20834    this.fog = true;
20835
20836    this.shading = THREE.SmoothShading;
20837    this.blending = THREE.NormalBlending;
20838
20839    this.wireframe = false;
20840    this.wireframeLinewidth = 1;
20841    this.wireframeLinecap = 'round';
20842    this.wireframeLinejoin = 'round';
20843
20844    this.vertexColors = THREE.NoColors;
20845
20846    this.skinning = false;
20847    this.morphTargets = false;
20848
20849    this.setValues( parameters );
20850
20851};
20852
20853THREE.MeshBasicMaterial.prototype = Object.create( THREE.Material.prototype );
20854THREE.MeshBasicMaterial.prototype.constructor = THREE.MeshBasicMaterial;
20855
20856THREE.MeshBasicMaterial.prototype.copy = function ( source ) {
20857
20858    THREE.Material.prototype.copy.call( this, source );
20859
20860    this.color.copy( source.color );
20861
20862    this.map = source.map;
20863
20864    this.aoMap = source.aoMap;
20865    this.aoMapIntensity = source.aoMapIntensity;
20866
20867    this.specularMap = source.specularMap;
20868
20869    this.alphaMap = source.alphaMap;
20870
20871    this.envMap = source.envMap;
20872    this.combine = source.combine;
20873    this.reflectivity = source.reflectivity;
20874    this.refractionRatio = source.refractionRatio;
20875
20876    this.fog = source.fog;
20877
20878    this.shading = source.shading;
20879
20880    this.wireframe = source.wireframe;
20881    this.wireframeLinewidth = source.wireframeLinewidth;
20882    this.wireframeLinecap = source.wireframeLinecap;
20883    this.wireframeLinejoin = source.wireframeLinejoin;
20884
20885    this.vertexColors = source.vertexColors;
20886
20887    this.skinning = source.skinning;
20888    this.morphTargets = source.morphTargets;
20889
20890    return this;
20891
20892};
20893
20894// File:src/materials/MeshDepthMaterial.js
20895
20896/**
20897 * @author mrdoob / http://mrdoob.com/
20898 * @author alteredq / http://alteredqualia.com/
20899 * @author bhouston / https://clara.io
20900 * @author WestLangley / http://github.com/WestLangley
20901 *
20902 * parameters = {
20903 *
20904 *  opacity: <float>,
20905 *
20906 *  map: new THREE.Texture( <Image> ),
20907 *
20908 *  alphaMap: new THREE.Texture( <Image> ),
20909 *
20910 *  displacementMap: new THREE.Texture( <Image> ),
20911 *  displacementScale: <float>,
20912 *  displacementBias: <float>,
20913 *
20914 *  wireframe: <boolean>,
20915 *  wireframeLinewidth: <float>
20916 * }
20917 */
20918
20919THREE.MeshDepthMaterial = function ( parameters ) {
20920
20921    THREE.Material.call( this );
20922
20923    this.type = 'MeshDepthMaterial';
20924
20925    this.depthPacking = THREE.BasicDepthPacking;
20926
20927    this.skinning = false;
20928    this.morphTargets = false;
20929
20930    this.map = null;
20931
20932    this.alphaMap = null;
20933
20934    this.displacementMap = null;
20935    this.displacementScale = 1;
20936    this.displacementBias = 0;
20937
20938    this.wireframe = false;
20939    this.wireframeLinewidth = 1;
20940
20941    this.setValues( parameters );
20942
20943};
20944
20945THREE.MeshDepthMaterial.prototype = Object.create( THREE.Material.prototype );
20946THREE.MeshDepthMaterial.prototype.constructor = THREE.MeshDepthMaterial;
20947
20948THREE.MeshDepthMaterial.prototype.copy = function ( source ) {
20949
20950    THREE.Material.prototype.copy.call( this, source );
20951
20952    this.depthPacking = source.depthPacking;
20953
20954    this.skinning = source.skinning;
20955    this.morphTargets = source.morphTargets;
20956
20957    this.map = source.map;
20958
20959    this.alphaMap = source.alphaMap;
20960
20961    this.displacementMap = source.displacementMap;
20962    this.displacementScale = source.displacementScale;
20963    this.displacementBias = source.displacementBias;
20964
20965    this.wireframe = source.wireframe;
20966    this.wireframeLinewidth = source.wireframeLinewidth;
20967
20968    return this;
20969
20970};
20971
20972// File:src/materials/MeshLambertMaterial.js
20973
20974/**
20975 * @author mrdoob / http://mrdoob.com/
20976 * @author alteredq / http://alteredqualia.com/
20977 *
20978 * parameters = {
20979 *  color: <hex>,
20980 *  opacity: <float>,
20981 *
20982 *  map: new THREE.Texture( <Image> ),
20983 *
20984 *  lightMap: new THREE.Texture( <Image> ),
20985 *  lightMapIntensity: <float>
20986 *
20987 *  aoMap: new THREE.Texture( <Image> ),
20988 *  aoMapIntensity: <float>
20989 *
20990 *  emissive: <hex>,
20991 *  emissiveIntensity: <float>
20992 *  emissiveMap: new THREE.Texture( <Image> ),
20993 *
20994 *  specularMap: new THREE.Texture( <Image> ),
20995 *
20996 *  alphaMap: new THREE.Texture( <Image> ),
20997 *
20998 *  envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
20999 *  combine: THREE.Multiply,
21000 *  reflectivity: <float>,
21001 *  refractionRatio: <float>,
21002 *
21003 *  blending: THREE.NormalBlending,
21004 *  depthTest: <bool>,
21005 *  depthWrite: <bool>,
21006 *
21007 *  wireframe: <boolean>,
21008 *  wireframeLinewidth: <float>,
21009 *
21010 *  vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
21011 *
21012 *  skinning: <bool>,
21013 *  morphTargets: <bool>,
21014 *  morphNormals: <bool>,
21015 *
21016 *	fog: <bool>
21017 * }
21018 */
21019
21020THREE.MeshLambertMaterial = function ( parameters ) {
21021
21022    THREE.Material.call( this );
21023
21024    this.type = 'MeshLambertMaterial';
21025
21026    this.color = new THREE.Color( 0xffffff ); // diffuse
21027
21028    this.map = null;
21029
21030    this.lightMap = null;
21031    this.lightMapIntensity = 1.0;
21032
21033    this.aoMap = null;
21034    this.aoMapIntensity = 1.0;
21035
21036    this.emissive = new THREE.Color( 0x000000 );
21037    this.emissiveIntensity = 1.0;
21038    this.emissiveMap = null;
21039
21040    this.specularMap = null;
21041
21042    this.alphaMap = null;
21043
21044    this.envMap = null;
21045    this.combine = THREE.MultiplyOperation;
21046    this.reflectivity = 1;
21047    this.refractionRatio = 0.98;
21048
21049    this.fog = true;
21050
21051    this.blending = THREE.NormalBlending;
21052
21053    this.wireframe = false;
21054    this.wireframeLinewidth = 1;
21055    this.wireframeLinecap = 'round';
21056    this.wireframeLinejoin = 'round';
21057
21058    this.vertexColors = THREE.NoColors;
21059
21060    this.skinning = false;
21061    this.morphTargets = false;
21062    this.morphNormals = false;
21063
21064    this.setValues( parameters );
21065
21066};
21067
21068THREE.MeshLambertMaterial.prototype = Object.create( THREE.Material.prototype );
21069THREE.MeshLambertMaterial.prototype.constructor = THREE.MeshLambertMaterial;
21070
21071THREE.MeshLambertMaterial.prototype.copy = function ( source ) {
21072
21073    THREE.Material.prototype.copy.call( this, source );
21074
21075    this.color.copy( source.color );
21076
21077    this.map = source.map;
21078
21079    this.lightMap = source.lightMap;
21080    this.lightMapIntensity = source.lightMapIntensity;
21081
21082    this.aoMap = source.aoMap;
21083    this.aoMapIntensity = source.aoMapIntensity;
21084
21085    this.emissive.copy( source.emissive );
21086    this.emissiveMap = source.emissiveMap;
21087    this.emissiveIntensity = source.emissiveIntensity;
21088
21089    this.specularMap = source.specularMap;
21090
21091    this.alphaMap = source.alphaMap;
21092
21093    this.envMap = source.envMap;
21094    this.combine = source.combine;
21095    this.reflectivity = source.reflectivity;
21096    this.refractionRatio = source.refractionRatio;
21097
21098    this.fog = source.fog;
21099
21100    this.wireframe = source.wireframe;
21101    this.wireframeLinewidth = source.wireframeLinewidth;
21102    this.wireframeLinecap = source.wireframeLinecap;
21103    this.wireframeLinejoin = source.wireframeLinejoin;
21104
21105    this.vertexColors = source.vertexColors;
21106
21107    this.skinning = source.skinning;
21108    this.morphTargets = source.morphTargets;
21109    this.morphNormals = source.morphNormals;
21110
21111    return this;
21112
21113};
21114
21115// File:src/materials/MeshNormalMaterial.js
21116
21117/**
21118 * @author mrdoob / http://mrdoob.com/
21119 *
21120 * parameters = {
21121 *  opacity: <float>,
21122 *
21123 *  wireframe: <boolean>,
21124 *  wireframeLinewidth: <float>
21125 * }
21126 */
21127
21128THREE.MeshNormalMaterial = function ( parameters ) {
21129
21130    THREE.Material.call( this, parameters );
21131
21132    this.type = 'MeshNormalMaterial';
21133
21134    this.wireframe = false;
21135    this.wireframeLinewidth = 1;
21136
21137    this.morphTargets = false;
21138
21139    this.setValues( parameters );
21140
21141};
21142
21143THREE.MeshNormalMaterial.prototype = Object.create( THREE.Material.prototype );
21144THREE.MeshNormalMaterial.prototype.constructor = THREE.MeshNormalMaterial;
21145
21146THREE.MeshNormalMaterial.prototype.copy = function ( source ) {
21147
21148    THREE.Material.prototype.copy.call( this, source );
21149
21150    this.wireframe = source.wireframe;
21151    this.wireframeLinewidth = source.wireframeLinewidth;
21152
21153    return this;
21154
21155};
21156
21157// File:src/materials/MeshPhongMaterial.js
21158
21159/**
21160 * @author mrdoob / http://mrdoob.com/
21161 * @author alteredq / http://alteredqualia.com/
21162 *
21163 * parameters = {
21164 *  color: <hex>,
21165 *  specular: <hex>,
21166 *  shininess: <float>,
21167 *  opacity: <float>,
21168 *
21169 *  map: new THREE.Texture( <Image> ),
21170 *
21171 *  lightMap: new THREE.Texture( <Image> ),
21172 *  lightMapIntensity: <float>
21173 *
21174 *  aoMap: new THREE.Texture( <Image> ),
21175 *  aoMapIntensity: <float>
21176 *
21177 *  emissive: <hex>,
21178 *  emissiveIntensity: <float>
21179 *  emissiveMap: new THREE.Texture( <Image> ),
21180 *
21181 *  bumpMap: new THREE.Texture( <Image> ),
21182 *  bumpScale: <float>,
21183 *
21184 *  normalMap: new THREE.Texture( <Image> ),
21185 *  normalScale: <Vector2>,
21186 *
21187 *  displacementMap: new THREE.Texture( <Image> ),
21188 *  displacementScale: <float>,
21189 *  displacementBias: <float>,
21190 *
21191 *  specularMap: new THREE.Texture( <Image> ),
21192 *
21193 *  alphaMap: new THREE.Texture( <Image> ),
21194 *
21195 *  envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
21196 *  combine: THREE.Multiply,
21197 *  reflectivity: <float>,
21198 *  refractionRatio: <float>,
21199 *
21200 *  shading: THREE.SmoothShading,
21201 *  blending: THREE.NormalBlending,
21202 *  depthTest: <bool>,
21203 *  depthWrite: <bool>,
21204 *
21205 *  wireframe: <boolean>,
21206 *  wireframeLinewidth: <float>,
21207 *
21208 *  vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
21209 *
21210 *  skinning: <bool>,
21211 *  morphTargets: <bool>,
21212 *  morphNormals: <bool>,
21213 *
21214 *	fog: <bool>
21215 * }
21216 */
21217
21218THREE.MeshPhongMaterial = function ( parameters ) {
21219
21220    THREE.Material.call( this );
21221
21222    this.type = 'MeshPhongMaterial';
21223
21224    this.color = new THREE.Color( 0xffffff ); // diffuse
21225    this.specular = new THREE.Color( 0x111111 );
21226    this.shininess = 30;
21227
21228    this.map = null;
21229
21230    this.lightMap = null;
21231    this.lightMapIntensity = 1.0;
21232
21233    this.aoMap = null;
21234    this.aoMapIntensity = 1.0;
21235
21236    this.emissive = new THREE.Color( 0x000000 );
21237    this.emissiveIntensity = 1.0;
21238    this.emissiveMap = null;
21239
21240    this.bumpMap = null;
21241    this.bumpScale = 1;
21242
21243    this.normalMap = null;
21244    this.normalScale = new THREE.Vector2( 1, 1 );
21245
21246    this.displacementMap = null;
21247    this.displacementScale = 1;
21248    this.displacementBias = 0;
21249
21250    this.specularMap = null;
21251
21252    this.alphaMap = null;
21253
21254    this.envMap = null;
21255    this.combine = THREE.MultiplyOperation;
21256    this.reflectivity = 1;
21257    this.refractionRatio = 0.98;
21258
21259    this.fog = true;
21260
21261    this.shading = THREE.SmoothShading;
21262    this.blending = THREE.NormalBlending;
21263
21264    this.wireframe = false;
21265    this.wireframeLinewidth = 1;
21266    this.wireframeLinecap = 'round';
21267    this.wireframeLinejoin = 'round';
21268
21269    this.vertexColors = THREE.NoColors;
21270
21271    this.skinning = false;
21272    this.morphTargets = false;
21273    this.morphNormals = false;
21274
21275    this.setValues( parameters );
21276
21277};
21278
21279THREE.MeshPhongMaterial.prototype = Object.create( THREE.Material.prototype );
21280THREE.MeshPhongMaterial.prototype.constructor = THREE.MeshPhongMaterial;
21281
21282THREE.MeshPhongMaterial.prototype.copy = function ( source ) {
21283
21284    THREE.Material.prototype.copy.call( this, source );
21285
21286    this.color.copy( source.color );
21287    this.specular.copy( source.specular );
21288    this.shininess = source.shininess;
21289
21290    this.map = source.map;
21291
21292    this.lightMap = source.lightMap;
21293    this.lightMapIntensity = source.lightMapIntensity;
21294
21295    this.aoMap = source.aoMap;
21296    this.aoMapIntensity = source.aoMapIntensity;
21297
21298    this.emissive.copy( source.emissive );
21299    this.emissiveMap = source.emissiveMap;
21300    this.emissiveIntensity = source.emissiveIntensity;
21301
21302    this.bumpMap = source.bumpMap;
21303    this.bumpScale = source.bumpScale;
21304
21305    this.normalMap = source.normalMap;
21306    this.normalScale.copy( source.normalScale );
21307
21308    this.displacementMap = source.displacementMap;
21309    this.displacementScale = source.displacementScale;
21310    this.displacementBias = source.displacementBias;
21311
21312    this.specularMap = source.specularMap;
21313
21314    this.alphaMap = source.alphaMap;
21315
21316    this.envMap = source.envMap;
21317    this.combine = source.combine;
21318    this.reflectivity = source.reflectivity;
21319    this.refractionRatio = source.refractionRatio;
21320
21321    this.fog = source.fog;
21322
21323    this.shading = source.shading;
21324
21325    this.wireframe = source.wireframe;
21326    this.wireframeLinewidth = source.wireframeLinewidth;
21327    this.wireframeLinecap = source.wireframeLinecap;
21328    this.wireframeLinejoin = source.wireframeLinejoin;
21329
21330    this.vertexColors = source.vertexColors;
21331
21332    this.skinning = source.skinning;
21333    this.morphTargets = source.morphTargets;
21334    this.morphNormals = source.morphNormals;
21335
21336    return this;
21337
21338};
21339
21340// File:src/materials/MeshStandardMaterial.js
21341
21342/**
21343 * @author WestLangley / http://github.com/WestLangley
21344 *
21345 * parameters = {
21346 *  color: <hex>,
21347 *  roughness: <float>,
21348 *  metalness: <float>,
21349 *  opacity: <float>,
21350 *
21351 *  map: new THREE.Texture( <Image> ),
21352 *
21353 *  lightMap: new THREE.Texture( <Image> ),
21354 *  lightMapIntensity: <float>
21355 *
21356 *  aoMap: new THREE.Texture( <Image> ),
21357 *  aoMapIntensity: <float>
21358 *
21359 *  emissive: <hex>,
21360 *  emissiveIntensity: <float>
21361 *  emissiveMap: new THREE.Texture( <Image> ),
21362 *
21363 *  bumpMap: new THREE.Texture( <Image> ),
21364 *  bumpScale: <float>,
21365 *
21366 *  normalMap: new THREE.Texture( <Image> ),
21367 *  normalScale: <Vector2>,
21368 *
21369 *  displacementMap: new THREE.Texture( <Image> ),
21370 *  displacementScale: <float>,
21371 *  displacementBias: <float>,
21372 *
21373 *  roughnessMap: new THREE.Texture( <Image> ),
21374 *
21375 *  metalnessMap: new THREE.Texture( <Image> ),
21376 *
21377 *  alphaMap: new THREE.Texture( <Image> ),
21378 *
21379 *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
21380 *  envMapIntensity: <float>
21381 *
21382 *  refractionRatio: <float>,
21383 *
21384 *  shading: THREE.SmoothShading,
21385 *  blending: THREE.NormalBlending,
21386 *  depthTest: <bool>,
21387 *  depthWrite: <bool>,
21388 *
21389 *  wireframe: <boolean>,
21390 *  wireframeLinewidth: <float>,
21391 *
21392 *  vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
21393 *
21394 *  skinning: <bool>,
21395 *  morphTargets: <bool>,
21396 *  morphNormals: <bool>,
21397 *
21398 *	fog: <bool>
21399 * }
21400 */
21401
21402THREE.MeshStandardMaterial = function ( parameters ) {
21403
21404    THREE.Material.call( this );
21405
21406    this.defines = { 'STANDARD': '' };
21407
21408    this.type = 'MeshStandardMaterial';
21409
21410    this.color = new THREE.Color( 0xffffff ); // diffuse
21411    this.roughness = 0.5;
21412    this.metalness = 0.5;
21413
21414    this.map = null;
21415
21416    this.lightMap = null;
21417    this.lightMapIntensity = 1.0;
21418
21419    this.aoMap = null;
21420    this.aoMapIntensity = 1.0;
21421
21422    this.emissive = new THREE.Color( 0x000000 );
21423    this.emissiveIntensity = 1.0;
21424    this.emissiveMap = null;
21425
21426    this.bumpMap = null;
21427    this.bumpScale = 1;
21428
21429    this.normalMap = null;
21430    this.normalScale = new THREE.Vector2( 1, 1 );
21431
21432    this.displacementMap = null;
21433    this.displacementScale = 1;
21434    this.displacementBias = 0;
21435
21436    this.roughnessMap = null;
21437
21438    this.metalnessMap = null;
21439
21440    this.alphaMap = null;
21441
21442    this.envMap = null;
21443    this.envMapIntensity = 1.0;
21444
21445    this.refractionRatio = 0.98;
21446
21447    this.fog = true;
21448
21449    this.shading = THREE.SmoothShading;
21450    this.blending = THREE.NormalBlending;
21451
21452    this.wireframe = false;
21453    this.wireframeLinewidth = 1;
21454    this.wireframeLinecap = 'round';
21455    this.wireframeLinejoin = 'round';
21456
21457    this.vertexColors = THREE.NoColors;
21458
21459    this.skinning = false;
21460    this.morphTargets = false;
21461    this.morphNormals = false;
21462
21463    this.setValues( parameters );
21464
21465};
21466
21467THREE.MeshStandardMaterial.prototype = Object.create( THREE.Material.prototype );
21468THREE.MeshStandardMaterial.prototype.constructor = THREE.MeshStandardMaterial;
21469
21470THREE.MeshStandardMaterial.prototype.copy = function ( source ) {
21471
21472    THREE.Material.prototype.copy.call( this, source );
21473
21474    this.defines = { 'STANDARD': '' };
21475
21476    this.color.copy( source.color );
21477    this.roughness = source.roughness;
21478    this.metalness = source.metalness;
21479
21480    this.map = source.map;
21481
21482    this.lightMap = source.lightMap;
21483    this.lightMapIntensity = source.lightMapIntensity;
21484
21485    this.aoMap = source.aoMap;
21486    this.aoMapIntensity = source.aoMapIntensity;
21487
21488    this.emissive.copy( source.emissive );
21489    this.emissiveMap = source.emissiveMap;
21490    this.emissiveIntensity = source.emissiveIntensity;
21491
21492    this.bumpMap = source.bumpMap;
21493    this.bumpScale = source.bumpScale;
21494
21495    this.normalMap = source.normalMap;
21496    this.normalScale.copy( source.normalScale );
21497
21498    this.displacementMap = source.displacementMap;
21499    this.displacementScale = source.displacementScale;
21500    this.displacementBias = source.displacementBias;
21501
21502    this.roughnessMap = source.roughnessMap;
21503
21504    this.metalnessMap = source.metalnessMap;
21505
21506    this.alphaMap = source.alphaMap;
21507
21508    this.envMap = source.envMap;
21509    this.envMapIntensity = source.envMapIntensity;
21510
21511    this.refractionRatio = source.refractionRatio;
21512
21513    this.fog = source.fog;
21514
21515    this.shading = source.shading;
21516
21517    this.wireframe = source.wireframe;
21518    this.wireframeLinewidth = source.wireframeLinewidth;
21519    this.wireframeLinecap = source.wireframeLinecap;
21520    this.wireframeLinejoin = source.wireframeLinejoin;
21521
21522    this.vertexColors = source.vertexColors;
21523
21524    this.skinning = source.skinning;
21525    this.morphTargets = source.morphTargets;
21526    this.morphNormals = source.morphNormals;
21527
21528    return this;
21529
21530};
21531
21532// File:src/materials/MeshPhysicalMaterial.js
21533
21534/**
21535 * @author WestLangley / http://github.com/WestLangley
21536 *
21537 * parameters = {
21538 *  reflectivity: <float>
21539 * }
21540 */
21541
21542THREE.MeshPhysicalMaterial = function ( parameters ) {
21543
21544    THREE.MeshStandardMaterial.call( this );
21545
21546    this.defines = { 'PHYSICAL': '' };
21547
21548    this.type = 'MeshPhysicalMaterial';
21549
21550    this.reflectivity = 0.5; // maps to F0 = 0.04
21551
21552    this.setValues( parameters );
21553
21554};
21555
21556THREE.MeshPhysicalMaterial.prototype = Object.create( THREE.MeshStandardMaterial.prototype );
21557THREE.MeshPhysicalMaterial.prototype.constructor = THREE.MeshPhysicalMaterial;
21558
21559THREE.MeshPhysicalMaterial.prototype.copy = function ( source ) {
21560
21561    THREE.MeshStandardMaterial.prototype.copy.call( this, source );
21562
21563    this.defines = { 'PHYSICAL': '' };
21564
21565    this.reflectivity = source.reflectivity;
21566
21567    return this;
21568
21569};
21570
21571// File:src/materials/MultiMaterial.js
21572
21573/**
21574 * @author mrdoob / http://mrdoob.com/
21575 */
21576
21577THREE.MultiMaterial = function ( materials ) {
21578
21579    this.uuid = THREE.Math.generateUUID();
21580
21581    this.type = 'MultiMaterial';
21582
21583    this.materials = materials instanceof Array ? materials : [];
21584
21585    this.visible = true;
21586
21587};
21588
21589THREE.MultiMaterial.prototype = {
21590
21591    constructor: THREE.MultiMaterial,
21592
21593    toJSON: function ( meta ) {
21594
21595        var output = {
21596            metadata: {
21597                version: 4.2,
21598                type: 'material',
21599                generator: 'MaterialExporter'
21600            },
21601            uuid: this.uuid,
21602            type: this.type,
21603            materials: []
21604        };
21605
21606        var materials = this.materials;
21607
21608        for ( var i = 0, l = materials.length; i < l; i ++ ) {
21609
21610            var material = materials[ i ].toJSON( meta );
21611            delete material.metadata;
21612
21613            output.materials.push( material );
21614
21615        }
21616
21617        output.visible = this.visible;
21618
21619        return output;
21620
21621    },
21622
21623    clone: function () {
21624
21625        var material = new this.constructor();
21626
21627        for ( var i = 0; i < this.materials.length; i ++ ) {
21628
21629            material.materials.push( this.materials[ i ].clone() );
21630
21631        }
21632
21633        material.visible = this.visible;
21634
21635        return material;
21636
21637    }
21638
21639};
21640
21641// File:src/materials/PointsMaterial.js
21642
21643/**
21644 * @author mrdoob / http://mrdoob.com/
21645 * @author alteredq / http://alteredqualia.com/
21646 *
21647 * parameters = {
21648 *  color: <hex>,
21649 *  opacity: <float>,
21650 *  map: new THREE.Texture( <Image> ),
21651 *
21652 *  size: <float>,
21653 *  sizeAttenuation: <bool>,
21654 *
21655 *  blending: THREE.NormalBlending,
21656 *  depthTest: <bool>,
21657 *  depthWrite: <bool>,
21658 *
21659 *  vertexColors: <bool>,
21660 *
21661 *  fog: <bool>
21662 * }
21663 */
21664
21665THREE.PointsMaterial = function ( parameters ) {
21666
21667    THREE.Material.call( this );
21668
21669    this.type = 'PointsMaterial';
21670
21671    this.color = new THREE.Color( 0xffffff );
21672
21673    this.map = null;
21674
21675    this.size = 1;
21676    this.sizeAttenuation = true;
21677
21678    this.blending = THREE.NormalBlending;
21679
21680    this.vertexColors = THREE.NoColors;
21681
21682    this.fog = true;
21683
21684    this.setValues( parameters );
21685
21686};
21687
21688THREE.PointsMaterial.prototype = Object.create( THREE.Material.prototype );
21689THREE.PointsMaterial.prototype.constructor = THREE.PointsMaterial;
21690
21691THREE.PointsMaterial.prototype.copy = function ( source ) {
21692
21693    THREE.Material.prototype.copy.call( this, source );
21694
21695    this.color.copy( source.color );
21696
21697    this.map = source.map;
21698
21699    this.size = source.size;
21700    this.sizeAttenuation = source.sizeAttenuation;
21701
21702    this.vertexColors = source.vertexColors;
21703
21704    this.fog = source.fog;
21705
21706    return this;
21707
21708};
21709
21710// File:src/materials/ShaderMaterial.js
21711
21712/**
21713 * @author alteredq / http://alteredqualia.com/
21714 *
21715 * parameters = {
21716 *  defines: { "label" : "value" },
21717 *  uniforms: { "parameter1": { type: "1f", value: 1.0 }, "parameter2": { type: "1i" value2: 2 } },
21718 *
21719 *  fragmentShader: <string>,
21720 *  vertexShader: <string>,
21721 *
21722 *  shading: THREE.SmoothShading,
21723 *
21724 *  wireframe: <boolean>,
21725 *  wireframeLinewidth: <float>,
21726 *
21727 *  lights: <bool>,
21728 *
21729 *  vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
21730 *
21731 *  skinning: <bool>,
21732 *  morphTargets: <bool>,
21733 *  morphNormals: <bool>,
21734 *
21735 *	fog: <bool>
21736 * }
21737 */
21738
21739THREE.ShaderMaterial = function ( parameters ) {
21740
21741    THREE.Material.call( this );
21742
21743    this.type = 'ShaderMaterial';
21744
21745    this.defines = {};
21746    this.uniforms = {};
21747
21748    this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}';
21749    this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}';
21750
21751    this.shading = THREE.SmoothShading;
21752
21753    this.linewidth = 1;
21754
21755    this.wireframe = false;
21756    this.wireframeLinewidth = 1;
21757
21758    this.fog = false; // set to use scene fog
21759
21760    this.lights = false; // set to use scene lights
21761    this.clipping = false; // set to use user-defined clipping planes
21762
21763    this.vertexColors = THREE.NoColors; // set to use "color" attribute stream
21764
21765    this.skinning = false; // set to use skinning attribute streams
21766
21767    this.morphTargets = false; // set to use morph targets
21768    this.morphNormals = false; // set to use morph normals
21769
21770    this.extensions = {
21771        derivatives: false, // set to use derivatives
21772        fragDepth: false, // set to use fragment depth values
21773        drawBuffers: false, // set to use draw buffers
21774        shaderTextureLOD: false // set to use shader texture LOD
21775    };
21776
21777    // When rendered geometry doesn't include these attributes but the material does,
21778    // use these default values in WebGL. This avoids errors when buffer data is missing.
21779    this.defaultAttributeValues = {
21780        'color': [ 1, 1, 1 ],
21781        'uv': [ 0, 0 ],
21782        'uv2': [ 0, 0 ]
21783    };
21784
21785    this.index0AttributeName = undefined;
21786
21787    if ( parameters !== undefined ) {
21788
21789        if ( parameters.attributes !== undefined ) {
21790
21791            console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
21792
21793        }
21794
21795        this.setValues( parameters );
21796
21797    }
21798
21799};
21800
21801THREE.ShaderMaterial.prototype = Object.create( THREE.Material.prototype );
21802THREE.ShaderMaterial.prototype.constructor = THREE.ShaderMaterial;
21803
21804THREE.ShaderMaterial.prototype.copy = function ( source ) {
21805
21806    THREE.Material.prototype.copy.call( this, source );
21807
21808    this.fragmentShader = source.fragmentShader;
21809    this.vertexShader = source.vertexShader;
21810
21811    this.uniforms = THREE.UniformsUtils.clone( source.uniforms );
21812
21813    this.defines = source.defines;
21814
21815    this.shading = source.shading;
21816
21817    this.wireframe = source.wireframe;
21818    this.wireframeLinewidth = source.wireframeLinewidth;
21819
21820    this.fog = source.fog;
21821
21822    this.lights = source.lights;
21823    this.clipping = source.clipping;
21824
21825    this.vertexColors = source.vertexColors;
21826
21827    this.skinning = source.skinning;
21828
21829    this.morphTargets = source.morphTargets;
21830    this.morphNormals = source.morphNormals;
21831
21832    this.extensions = source.extensions;
21833
21834    return this;
21835
21836};
21837
21838THREE.ShaderMaterial.prototype.toJSON = function ( meta ) {
21839
21840    var data = THREE.Material.prototype.toJSON.call( this, meta );
21841
21842    data.uniforms = this.uniforms;
21843    data.vertexShader = this.vertexShader;
21844    data.fragmentShader = this.fragmentShader;
21845
21846    return data;
21847
21848};
21849
21850// File:src/materials/RawShaderMaterial.js
21851
21852/**
21853 * @author mrdoob / http://mrdoob.com/
21854 */
21855
21856THREE.RawShaderMaterial = function ( parameters ) {
21857
21858    THREE.ShaderMaterial.call( this, parameters );
21859
21860    this.type = 'RawShaderMaterial';
21861
21862};
21863
21864THREE.RawShaderMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype );
21865THREE.RawShaderMaterial.prototype.constructor = THREE.RawShaderMaterial;
21866
21867// File:src/materials/SpriteMaterial.js
21868
21869/**
21870 * @author alteredq / http://alteredqualia.com/
21871 *
21872 * parameters = {
21873 *  color: <hex>,
21874 *  opacity: <float>,
21875 *  map: new THREE.Texture( <Image> ),
21876 *
21877 *	uvOffset: new THREE.Vector2(),
21878 *	uvScale: new THREE.Vector2(),
21879 *
21880 *  fog: <bool>
21881 * }
21882 */
21883
21884THREE.SpriteMaterial = function ( parameters ) {
21885
21886    THREE.Material.call( this );
21887
21888    this.type = 'SpriteMaterial';
21889
21890    this.color = new THREE.Color( 0xffffff );
21891    this.map = null;
21892
21893    this.rotation = 0;
21894
21895    this.fog = false;
21896
21897    // set parameters
21898
21899    this.setValues( parameters );
21900
21901};
21902
21903THREE.SpriteMaterial.prototype = Object.create( THREE.Material.prototype );
21904THREE.SpriteMaterial.prototype.constructor = THREE.SpriteMaterial;
21905
21906THREE.SpriteMaterial.prototype.copy = function ( source ) {
21907
21908    THREE.Material.prototype.copy.call( this, source );
21909
21910    this.color.copy( source.color );
21911    this.map = source.map;
21912
21913    this.rotation = source.rotation;
21914
21915    this.fog = source.fog;
21916
21917    return this;
21918
21919};
21920
21921// File:src/textures/Texture.js
21922
21923/**
21924 * @author mrdoob / http://mrdoob.com/
21925 * @author alteredq / http://alteredqualia.com/
21926 * @author szimek / https://github.com/szimek/
21927 */
21928
21929THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
21930
21931    Object.defineProperty( this, 'id', { value: THREE.TextureIdCount ++ } );
21932
21933    this.uuid = THREE.Math.generateUUID();
21934
21935    this.name = '';
21936    this.sourceFile = '';
21937
21938    this.image = image !== undefined ? image : THREE.Texture.DEFAULT_IMAGE;
21939    this.mipmaps = [];
21940
21941    this.mapping = mapping !== undefined ? mapping : THREE.Texture.DEFAULT_MAPPING;
21942
21943    this.wrapS = wrapS !== undefined ? wrapS : THREE.ClampToEdgeWrapping;
21944    this.wrapT = wrapT !== undefined ? wrapT : THREE.ClampToEdgeWrapping;
21945
21946    this.magFilter = magFilter !== undefined ? magFilter : THREE.LinearFilter;
21947    this.minFilter = minFilter !== undefined ? minFilter : THREE.LinearMipMapLinearFilter;
21948
21949    this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
21950
21951    this.format = format !== undefined ? format : THREE.RGBAFormat;
21952    this.type = type !== undefined ? type : THREE.UnsignedByteType;
21953
21954    this.offset = new THREE.Vector2( 0, 0 );
21955    this.repeat = new THREE.Vector2( 1, 1 );
21956
21957    this.generateMipmaps = true;
21958    this.premultiplyAlpha = false;
21959    this.flipY = true;
21960    this.unpackAlignment = 4;	// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
21961
21962
21963    // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
21964    //
21965    // Also changing the encoding after already used by a Material will not automatically make the Material
21966    // update.  You need to explicitly call Material.needsUpdate to trigger it to recompile.
21967    this.encoding = encoding !== undefined ? encoding :  THREE.LinearEncoding;
21968
21969    this.version = 0;
21970    this.onUpdate = null;
21971
21972};
21973
21974THREE.Texture.DEFAULT_IMAGE = undefined;
21975THREE.Texture.DEFAULT_MAPPING = THREE.UVMapping;
21976
21977THREE.Texture.prototype = {
21978
21979    constructor: THREE.Texture,
21980
21981    set needsUpdate ( value ) {
21982
21983        if ( value === true ) this.version ++;
21984
21985    },
21986
21987    clone: function () {
21988
21989        return new this.constructor().copy( this );
21990
21991    },
21992
21993    copy: function ( source ) {
21994
21995        this.image = source.image;
21996        this.mipmaps = source.mipmaps.slice( 0 );
21997
21998        this.mapping = source.mapping;
21999
22000        this.wrapS = source.wrapS;
22001        this.wrapT = source.wrapT;
22002
22003        this.magFilter = source.magFilter;
22004        this.minFilter = source.minFilter;
22005
22006        this.anisotropy = source.anisotropy;
22007
22008        this.format = source.format;
22009        this.type = source.type;
22010
22011        this.offset.copy( source.offset );
22012        this.repeat.copy( source.repeat );
22013
22014        this.generateMipmaps = source.generateMipmaps;
22015        this.premultiplyAlpha = source.premultiplyAlpha;
22016        this.flipY = source.flipY;
22017        this.unpackAlignment = source.unpackAlignment;
22018        this.encoding = source.encoding;
22019
22020        return this;
22021
22022    },
22023
22024    toJSON: function ( meta ) {
22025
22026        if ( meta.textures[ this.uuid ] !== undefined ) {
22027
22028            return meta.textures[ this.uuid ];
22029
22030        }
22031
22032        function getDataURL( image ) {
22033
22034            var canvas;
22035
22036            if ( image.toDataURL !== undefined ) {
22037
22038                canvas = image;
22039
22040            } else {
22041
22042                canvas = document.createElement( 'canvas' );
22043                canvas.width = image.width;
22044                canvas.height = image.height;
22045
22046                canvas.getContext( '2d' ).drawImage( image, 0, 0, image.width, image.height );
22047
22048            }
22049
22050            if ( canvas.width > 2048 || canvas.height > 2048 ) {
22051
22052                return canvas.toDataURL( 'image/jpeg', 0.6 );
22053
22054            } else {
22055
22056                return canvas.toDataURL( 'image/png' );
22057
22058            }
22059
22060        }
22061
22062        var output = {
22063            metadata: {
22064                version: 4.4,
22065                type: 'Texture',
22066                generator: 'Texture.toJSON'
22067            },
22068
22069            uuid: this.uuid,
22070            name: this.name,
22071
22072            mapping: this.mapping,
22073
22074            repeat: [ this.repeat.x, this.repeat.y ],
22075            offset: [ this.offset.x, this.offset.y ],
22076            wrap: [ this.wrapS, this.wrapT ],
22077
22078            minFilter: this.minFilter,
22079            magFilter: this.magFilter,
22080            anisotropy: this.anisotropy
22081        };
22082
22083        if ( this.image !== undefined ) {
22084
22085            // TODO: Move to THREE.Image
22086
22087            var image = this.image;
22088
22089            if ( image.uuid === undefined ) {
22090
22091                image.uuid = THREE.Math.generateUUID(); // UGH
22092
22093            }
22094
22095            if ( meta.images[ image.uuid ] === undefined ) {
22096
22097                meta.images[ image.uuid ] = {
22098                    uuid: image.uuid,
22099                    url: getDataURL( image )
22100                };
22101
22102            }
22103
22104            output.image = image.uuid;
22105
22106        }
22107
22108        meta.textures[ this.uuid ] = output;
22109
22110        return output;
22111
22112    },
22113
22114    dispose: function () {
22115
22116        this.dispatchEvent( { type: 'dispose' } );
22117
22118    },
22119
22120    transformUv: function ( uv ) {
22121
22122        if ( this.mapping !== THREE.UVMapping )  return;
22123
22124        uv.multiply( this.repeat );
22125        uv.add( this.offset );
22126
22127        if ( uv.x < 0 || uv.x > 1 ) {
22128
22129            switch ( this.wrapS ) {
22130
22131                case THREE.RepeatWrapping:
22132
22133                    uv.x = uv.x - Math.floor( uv.x );
22134                    break;
22135
22136                case THREE.ClampToEdgeWrapping:
22137
22138                    uv.x = uv.x < 0 ? 0 : 1;
22139                    break;
22140
22141                case THREE.MirroredRepeatWrapping:
22142
22143                    if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
22144
22145                        uv.x = Math.ceil( uv.x ) - uv.x;
22146
22147                    } else {
22148
22149                        uv.x = uv.x - Math.floor( uv.x );
22150
22151                    }
22152                    break;
22153
22154            }
22155
22156        }
22157
22158        if ( uv.y < 0 || uv.y > 1 ) {
22159
22160            switch ( this.wrapT ) {
22161
22162                case THREE.RepeatWrapping:
22163
22164                    uv.y = uv.y - Math.floor( uv.y );
22165                    break;
22166
22167                case THREE.ClampToEdgeWrapping:
22168
22169                    uv.y = uv.y < 0 ? 0 : 1;
22170                    break;
22171
22172                case THREE.MirroredRepeatWrapping:
22173
22174                    if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
22175
22176                        uv.y = Math.ceil( uv.y ) - uv.y;
22177
22178                    } else {
22179
22180                        uv.y = uv.y - Math.floor( uv.y );
22181
22182                    }
22183                    break;
22184
22185            }
22186
22187        }
22188
22189        if ( this.flipY ) {
22190
22191            uv.y = 1 - uv.y;
22192
22193        }
22194
22195    }
22196
22197};
22198
22199THREE.EventDispatcher.prototype.apply( THREE.Texture.prototype );
22200
22201THREE.TextureIdCount = 0;
22202
22203// File:src/textures/DepthTexture.js
22204
22205/**
22206 * @author Matt DesLauriers / @mattdesl
22207 */
22208
22209THREE.DepthTexture = function ( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy ) {
22210
22211    THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, THREE.DepthFormat, type, anisotropy );
22212
22213    this.image = { width: width, height: height };
22214
22215    this.type = type !== undefined ? type : THREE.UnsignedShortType;
22216
22217    this.magFilter = magFilter !== undefined ? magFilter : THREE.NearestFilter;
22218    this.minFilter = minFilter !== undefined ? minFilter : THREE.NearestFilter;
22219
22220    this.flipY = false;
22221    this.generateMipmaps  = false;
22222
22223};
22224
22225THREE.DepthTexture.prototype = Object.create( THREE.Texture.prototype );
22226THREE.DepthTexture.prototype.constructor = THREE.DepthTexture;
22227
22228// File:src/textures/CanvasTexture.js
22229
22230/**
22231 * @author mrdoob / http://mrdoob.com/
22232 */
22233
22234THREE.CanvasTexture = function ( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
22235
22236    THREE.Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
22237
22238    this.needsUpdate = true;
22239
22240};
22241
22242THREE.CanvasTexture.prototype = Object.create( THREE.Texture.prototype );
22243THREE.CanvasTexture.prototype.constructor = THREE.CanvasTexture;
22244
22245// File:src/textures/CubeTexture.js
22246
22247/**
22248 * @author mrdoob / http://mrdoob.com/
22249 */
22250
22251THREE.CubeTexture = function ( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
22252
22253    images = images !== undefined ? images : [];
22254    mapping = mapping !== undefined ? mapping : THREE.CubeReflectionMapping;
22255
22256    THREE.Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
22257
22258    this.flipY = false;
22259
22260};
22261
22262THREE.CubeTexture.prototype = Object.create( THREE.Texture.prototype );
22263THREE.CubeTexture.prototype.constructor = THREE.CubeTexture;
22264
22265Object.defineProperty( THREE.CubeTexture.prototype, 'images', {
22266
22267    get: function () {
22268
22269        return this.image;
22270
22271    },
22272
22273    set: function ( value ) {
22274
22275        this.image = value;
22276
22277    }
22278
22279} );
22280
22281// File:src/textures/CompressedTexture.js
22282
22283/**
22284 * @author alteredq / http://alteredqualia.com/
22285 */
22286
22287THREE.CompressedTexture = function ( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
22288
22289    THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
22290
22291    this.image = { width: width, height: height };
22292    this.mipmaps = mipmaps;
22293
22294    // no flipping for cube textures
22295    // (also flipping doesn't work for compressed textures )
22296
22297    this.flipY = false;
22298
22299    // can't generate mipmaps for compressed textures
22300    // mips must be embedded in DDS files
22301
22302    this.generateMipmaps = false;
22303
22304};
22305
22306THREE.CompressedTexture.prototype = Object.create( THREE.Texture.prototype );
22307THREE.CompressedTexture.prototype.constructor = THREE.CompressedTexture;
22308
22309// File:src/textures/DataTexture.js
22310
22311/**
22312 * @author alteredq / http://alteredqualia.com/
22313 */
22314
22315THREE.DataTexture = function ( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
22316
22317    THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
22318
22319    this.image = { data: data, width: width, height: height };
22320
22321    this.magFilter = magFilter !== undefined ? magFilter : THREE.NearestFilter;
22322    this.minFilter = minFilter !== undefined ? minFilter : THREE.NearestFilter;
22323
22324    this.flipY = false;
22325    this.generateMipmaps  = false;
22326
22327};
22328
22329THREE.DataTexture.prototype = Object.create( THREE.Texture.prototype );
22330THREE.DataTexture.prototype.constructor = THREE.DataTexture;
22331
22332// File:src/textures/VideoTexture.js
22333
22334/**
22335 * @author mrdoob / http://mrdoob.com/
22336 */
22337
22338THREE.VideoTexture = function ( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
22339
22340    THREE.Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
22341
22342    this.generateMipmaps = false;
22343
22344    var scope = this;
22345
22346    function update() {
22347
22348        requestAnimationFrame( update );
22349
22350        if ( video.readyState >= video.HAVE_CURRENT_DATA ) {
22351
22352            scope.needsUpdate = true;
22353
22354        }
22355
22356    }
22357
22358    update();
22359
22360};
22361
22362THREE.VideoTexture.prototype = Object.create( THREE.Texture.prototype );
22363THREE.VideoTexture.prototype.constructor = THREE.VideoTexture;
22364
22365// File:src/objects/Group.js
22366
22367/**
22368 * @author mrdoob / http://mrdoob.com/
22369 */
22370
22371THREE.Group = function () {
22372
22373    THREE.Object3D.call( this );
22374
22375    this.type = 'Group';
22376
22377};
22378
22379THREE.Group.prototype = Object.create( THREE.Object3D.prototype );
22380THREE.Group.prototype.constructor = THREE.Group;
22381
22382// File:src/objects/Points.js
22383
22384/**
22385 * @author alteredq / http://alteredqualia.com/
22386 */
22387
22388THREE.Points = function ( geometry, material ) {
22389
22390    THREE.Object3D.call( this );
22391
22392    this.type = 'Points';
22393
22394    this.geometry = geometry !== undefined ? geometry : new THREE.Geometry();
22395    this.material = material !== undefined ? material : new THREE.PointsMaterial( { color: Math.random() * 0xffffff } );
22396
22397};
22398
22399THREE.Points.prototype = Object.create( THREE.Object3D.prototype );
22400THREE.Points.prototype.constructor = THREE.Points;
22401
22402THREE.Points.prototype.raycast = ( function () {
22403
22404    var inverseMatrix = new THREE.Matrix4();
22405    var ray = new THREE.Ray();
22406    var sphere = new THREE.Sphere();
22407
22408    return function raycast( raycaster, intersects ) {
22409
22410        var object = this;
22411        var geometry = this.geometry;
22412        var matrixWorld = this.matrixWorld;
22413        var threshold = raycaster.params.Points.threshold;
22414
22415        // Checking boundingSphere distance to ray
22416
22417        if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
22418
22419        sphere.copy( geometry.boundingSphere );
22420        sphere.applyMatrix4( matrixWorld );
22421
22422        if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
22423
22424        //
22425
22426        inverseMatrix.getInverse( matrixWorld );
22427        ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
22428
22429        var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
22430        var localThresholdSq = localThreshold * localThreshold;
22431        var position = new THREE.Vector3();
22432
22433        function testPoint( point, index ) {
22434
22435            var rayPointDistanceSq = ray.distanceSqToPoint( point );
22436
22437            if ( rayPointDistanceSq < localThresholdSq ) {
22438
22439                var intersectPoint = ray.closestPointToPoint( point );
22440                intersectPoint.applyMatrix4( matrixWorld );
22441
22442                var distance = raycaster.ray.origin.distanceTo( intersectPoint );
22443
22444                if ( distance < raycaster.near || distance > raycaster.far ) return;
22445
22446                intersects.push( {
22447
22448                    distance: distance,
22449                    distanceToRay: Math.sqrt( rayPointDistanceSq ),
22450                    point: intersectPoint.clone(),
22451                    index: index,
22452                    face: null,
22453                    object: object
22454
22455                } );
22456
22457            }
22458
22459        }
22460
22461        if ( geometry instanceof THREE.BufferGeometry ) {
22462
22463            var index = geometry.index;
22464            var attributes = geometry.attributes;
22465            var positions = attributes.position.array;
22466
22467            if ( index !== null ) {
22468
22469                var indices = index.array;
22470
22471                for ( var i = 0, il = indices.length; i < il; i ++ ) {
22472
22473                    var a = indices[ i ];
22474
22475                    position.fromArray( positions, a * 3 );
22476
22477                    testPoint( position, a );
22478
22479                }
22480
22481            } else {
22482
22483                for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
22484
22485                    position.fromArray( positions, i * 3 );
22486
22487                    testPoint( position, i );
22488
22489                }
22490
22491            }
22492
22493        } else {
22494
22495            var vertices = geometry.vertices;
22496
22497            for ( var i = 0, l = vertices.length; i < l; i ++ ) {
22498
22499                testPoint( vertices[ i ], i );
22500
22501            }
22502
22503        }
22504
22505    };
22506
22507}() );
22508
22509THREE.Points.prototype.clone = function () {
22510
22511    return new this.constructor( this.geometry, this.material ).copy( this );
22512
22513};
22514
22515// File:src/objects/Line.js
22516
22517/**
22518 * @author mrdoob / http://mrdoob.com/
22519 */
22520
22521THREE.Line = function ( geometry, material, mode ) {
22522
22523    if ( mode === 1 ) {
22524
22525        console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' );
22526        return new THREE.LineSegments( geometry, material );
22527
22528    }
22529
22530    THREE.Object3D.call( this );
22531
22532    this.type = 'Line';
22533
22534    this.geometry = geometry !== undefined ? geometry : new THREE.Geometry();
22535    this.material = material !== undefined ? material : new THREE.LineBasicMaterial( { color: Math.random() * 0xffffff } );
22536
22537};
22538
22539THREE.Line.prototype = Object.create( THREE.Object3D.prototype );
22540THREE.Line.prototype.constructor = THREE.Line;
22541
22542THREE.Line.prototype.raycast = ( function () {
22543
22544    var inverseMatrix = new THREE.Matrix4();
22545    var ray = new THREE.Ray();
22546    var sphere = new THREE.Sphere();
22547
22548    return function raycast( raycaster, intersects ) {
22549
22550        var precision = raycaster.linePrecision;
22551        var precisionSq = precision * precision;
22552
22553        var geometry = this.geometry;
22554        var matrixWorld = this.matrixWorld;
22555
22556        // Checking boundingSphere distance to ray
22557
22558        if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
22559
22560        sphere.copy( geometry.boundingSphere );
22561        sphere.applyMatrix4( matrixWorld );
22562
22563        if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
22564
22565        //
22566
22567        inverseMatrix.getInverse( matrixWorld );
22568        ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
22569
22570        var vStart = new THREE.Vector3();
22571        var vEnd = new THREE.Vector3();
22572        var interSegment = new THREE.Vector3();
22573        var interRay = new THREE.Vector3();
22574        var step = this instanceof THREE.LineSegments ? 2 : 1;
22575
22576        if ( geometry instanceof THREE.BufferGeometry ) {
22577
22578            var index = geometry.index;
22579            var attributes = geometry.attributes;
22580            var positions = attributes.position.array;
22581
22582            if ( index !== null ) {
22583
22584                var indices = index.array;
22585
22586                for ( var i = 0, l = indices.length - 1; i < l; i += step ) {
22587
22588                    var a = indices[ i ];
22589                    var b = indices[ i + 1 ];
22590
22591                    vStart.fromArray( positions, a * 3 );
22592                    vEnd.fromArray( positions, b * 3 );
22593
22594                    var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
22595
22596                    if ( distSq > precisionSq ) continue;
22597
22598                    interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
22599
22600                    var distance = raycaster.ray.origin.distanceTo( interRay );
22601
22602                    if ( distance < raycaster.near || distance > raycaster.far ) continue;
22603
22604                    intersects.push( {
22605
22606                        distance: distance,
22607                        // What do we want? intersection point on the ray or on the segment??
22608                        // point: raycaster.ray.at( distance ),
22609                        point: interSegment.clone().applyMatrix4( this.matrixWorld ),
22610                        index: i,
22611                        face: null,
22612                        faceIndex: null,
22613                        object: this
22614
22615                    } );
22616
22617                }
22618
22619            } else {
22620
22621                for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {
22622
22623                    vStart.fromArray( positions, 3 * i );
22624                    vEnd.fromArray( positions, 3 * i + 3 );
22625
22626                    var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
22627
22628                    if ( distSq > precisionSq ) continue;
22629
22630                    interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
22631
22632                    var distance = raycaster.ray.origin.distanceTo( interRay );
22633
22634                    if ( distance < raycaster.near || distance > raycaster.far ) continue;
22635
22636                    intersects.push( {
22637
22638                        distance: distance,
22639                        // What do we want? intersection point on the ray or on the segment??
22640                        // point: raycaster.ray.at( distance ),
22641                        point: interSegment.clone().applyMatrix4( this.matrixWorld ),
22642                        index: i,
22643                        face: null,
22644                        faceIndex: null,
22645                        object: this
22646
22647                    } );
22648
22649                }
22650
22651            }
22652
22653        } else if ( geometry instanceof THREE.Geometry ) {
22654
22655            var vertices = geometry.vertices;
22656            var nbVertices = vertices.length;
22657
22658            for ( var i = 0; i < nbVertices - 1; i += step ) {
22659
22660                var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
22661
22662                if ( distSq > precisionSq ) continue;
22663
22664                interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
22665
22666                var distance = raycaster.ray.origin.distanceTo( interRay );
22667
22668                if ( distance < raycaster.near || distance > raycaster.far ) continue;
22669
22670                intersects.push( {
22671
22672                    distance: distance,
22673                    // What do we want? intersection point on the ray or on the segment??
22674                    // point: raycaster.ray.at( distance ),
22675                    point: interSegment.clone().applyMatrix4( this.matrixWorld ),
22676                    index: i,
22677                    face: null,
22678                    faceIndex: null,
22679                    object: this
22680
22681                } );
22682
22683            }
22684
22685        }
22686
22687    };
22688
22689}() );
22690
22691THREE.Line.prototype.clone = function () {
22692
22693    return new this.constructor( this.geometry, this.material ).copy( this );
22694
22695};
22696
22697// DEPRECATED
22698
22699THREE.LineStrip = 0;
22700THREE.LinePieces = 1;
22701
22702// File:src/objects/LineSegments.js
22703
22704/**
22705 * @author mrdoob / http://mrdoob.com/
22706 */
22707
22708THREE.LineSegments = function ( geometry, material ) {
22709
22710    THREE.Line.call( this, geometry, material );
22711
22712    this.type = 'LineSegments';
22713
22714};
22715
22716THREE.LineSegments.prototype = Object.create( THREE.Line.prototype );
22717THREE.LineSegments.prototype.constructor = THREE.LineSegments;
22718
22719// File:src/objects/Mesh.js
22720
22721/**
22722 * @author mrdoob / http://mrdoob.com/
22723 * @author alteredq / http://alteredqualia.com/
22724 * @author mikael emtinger / http://gomo.se/
22725 * @author jonobr1 / http://jonobr1.com/
22726 */
22727
22728THREE.Mesh = function ( geometry, material ) {
22729
22730    THREE.Object3D.call( this );
22731
22732    this.type = 'Mesh';
22733
22734    this.geometry = geometry !== undefined ? geometry : new THREE.Geometry();
22735    this.material = material !== undefined ? material : new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } );
22736
22737    this.drawMode = THREE.TrianglesDrawMode;
22738
22739    this.updateMorphTargets();
22740
22741};
22742
22743THREE.Mesh.prototype = Object.create( THREE.Object3D.prototype );
22744THREE.Mesh.prototype.constructor = THREE.Mesh;
22745
22746THREE.Mesh.prototype.setDrawMode = function ( value ) {
22747
22748    this.drawMode = value;
22749
22750};
22751
22752THREE.Mesh.prototype.updateMorphTargets = function () {
22753
22754    if ( this.geometry.morphTargets !== undefined && this.geometry.morphTargets.length > 0 ) {
22755
22756        this.morphTargetBase = - 1;
22757        this.morphTargetInfluences = [];
22758        this.morphTargetDictionary = {};
22759
22760        for ( var m = 0, ml = this.geometry.morphTargets.length; m < ml; m ++ ) {
22761
22762            this.morphTargetInfluences.push( 0 );
22763            this.morphTargetDictionary[ this.geometry.morphTargets[ m ].name ] = m;
22764
22765        }
22766
22767    }
22768
22769};
22770
22771THREE.Mesh.prototype.getMorphTargetIndexByName = function ( name ) {
22772
22773    if ( this.morphTargetDictionary[ name ] !== undefined ) {
22774
22775        return this.morphTargetDictionary[ name ];
22776
22777    }
22778
22779    console.warn( 'THREE.Mesh.getMorphTargetIndexByName: morph target ' + name + ' does not exist. Returning 0.' );
22780
22781    return 0;
22782
22783};
22784
22785
22786THREE.Mesh.prototype.raycast = ( function () {
22787
22788    var inverseMatrix = new THREE.Matrix4();
22789    var ray = new THREE.Ray();
22790    var sphere = new THREE.Sphere();
22791
22792    var vA = new THREE.Vector3();
22793    var vB = new THREE.Vector3();
22794    var vC = new THREE.Vector3();
22795
22796    var tempA = new THREE.Vector3();
22797    var tempB = new THREE.Vector3();
22798    var tempC = new THREE.Vector3();
22799
22800    var uvA = new THREE.Vector2();
22801    var uvB = new THREE.Vector2();
22802    var uvC = new THREE.Vector2();
22803
22804    var barycoord = new THREE.Vector3();
22805
22806    var intersectionPoint = new THREE.Vector3();
22807    var intersectionPointWorld = new THREE.Vector3();
22808
22809    function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) {
22810
22811        THREE.Triangle.barycoordFromPoint( point, p1, p2, p3, barycoord );
22812
22813        uv1.multiplyScalar( barycoord.x );
22814        uv2.multiplyScalar( barycoord.y );
22815        uv3.multiplyScalar( barycoord.z );
22816
22817        uv1.add( uv2 ).add( uv3 );
22818
22819        return uv1.clone();
22820
22821    }
22822
22823    function checkIntersection( object, raycaster, ray, pA, pB, pC, point ) {
22824
22825        var intersect;
22826        var material = object.material;
22827
22828        if ( material.side === THREE.BackSide ) {
22829
22830            intersect = ray.intersectTriangle( pC, pB, pA, true, point );
22831
22832        } else {
22833
22834            intersect = ray.intersectTriangle( pA, pB, pC, material.side !== THREE.DoubleSide, point );
22835
22836        }
22837
22838        if ( intersect === null ) return null;
22839
22840        intersectionPointWorld.copy( point );
22841        intersectionPointWorld.applyMatrix4( object.matrixWorld );
22842
22843        var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld );
22844
22845        if ( distance < raycaster.near || distance > raycaster.far ) return null;
22846
22847        return {
22848            distance: distance,
22849            point: intersectionPointWorld.clone(),
22850            object: object
22851        };
22852
22853    }
22854
22855    function checkBufferGeometryIntersection( object, raycaster, ray, positions, uvs, a, b, c ) {
22856
22857        vA.fromArray( positions, a * 3 );
22858        vB.fromArray( posit
22858ions, b * 3 );
22859        vC.fromArray( positions, c * 3 );
22860
22861        var intersection = checkIntersection( object, raycaster, ray, vA, vB, vC, intersectionPoint );
22862
22863        if ( intersection ) {
22864
22865            if ( uvs ) {
22866
22867                uvA.fromArray( uvs, a * 2 );
22868                uvB.fromArray( uvs, b * 2 );
22869                uvC.fromArray( uvs, c * 2 );
22870
22871                intersection.uv = uvIntersection( intersectionPoint,  vA, vB, vC,  uvA, uvB, uvC );
22872
22873            }
22874
22875            intersection.face = new THREE.Face3( a, b, c, THREE.Triangle.normal( vA, vB, vC ) );
22876            intersection.faceIndex = a;
22877
22878        }
22879
22880        return intersection;
22881
22882    }
22883
22884    return function raycast( raycaster, intersects ) {
22885
22886        var geometry = this.geometry;
22887        var material = this.material;
22888        var matrixWorld = this.matrixWorld;
22889
22890        if ( material === undefined ) return;
22891
22892        // Checking boundingSphere distance to ray
22893
22894        if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
22895
22896        sphere.copy( geometry.boundingSphere );
22897        sphere.applyMatrix4( matrixWorld );
22898
22899        if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
22900
22901        //
22902
22903        inverseMatrix.getInverse( matrixWorld );
22904        ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix );
22905
22906        // Check boundingBox before continuing
22907
22908        if ( geometry.boundingBox !== null ) {
22909
22910            if ( ray.intersectsBox( geometry.boundingBox ) === false ) return;
22911
22912        }
22913
22914        var uvs, intersection;
22915
22916        if ( geometry instanceof THREE.BufferGeometry ) {
22917
22918            var a, b, c;
22919            var index = geometry.index;
22920            var attributes = geometry.attributes;
22921            var positions = attributes.position.array;
22922
22923            if ( attributes.uv !== undefined ) {
22924
22925                uvs = attributes.uv.array;
22926
22927            }
22928
22929            if ( index !== null ) {
22930
22931                var indices = index.array;
22932
22933                for ( var i = 0, l = indices.length; i < l; i += 3 ) {
22934
22935                    a = indices[ i ];
22936                    b = indices[ i + 1 ];
22937                    c = indices[ i + 2 ];
22938
22939                    intersection = checkBufferGeometryIntersection( this, raycaster, ray, positions, uvs, a, b, c );
22940
22941                    if ( intersection ) {
22942
22943                        intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indices buffer semantics
22944                        intersects.push( intersection );
22945
22946                    }
22947
22948                }
22949
22950            } else {
22951
22952
22953                for ( var i = 0, l = positions.length; i < l; i += 9 ) {
22954
22955                    a = i / 3;
22956                    b = a + 1;
22957                    c = a + 2;
22958
22959                    intersection = checkBufferGeometryIntersection( this, raycaster, ray, positions, uvs, a, b, c );
22960
22961                    if ( intersection ) {
22962
22963                        intersection.index = a; // triangle number in positions buffer semantics
22964                        intersects.push( intersection );
22965
22966                    }
22967
22968                }
22969
22970            }
22971
22972        } else if ( geometry instanceof THREE.Geometry ) {
22973
22974            var fvA, fvB, fvC;
22975            var isFaceMaterial = material instanceof THREE.MultiMaterial;
22976            var materials = isFaceMaterial === true ? material.materials : null;
22977
22978            var vertices = geometry.vertices;
22979            var faces = geometry.faces;
22980            var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
22981            if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
22982
22983            for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
22984
22985                var face = faces[ f ];
22986                var faceMaterial = isFaceMaterial === true ? materials[ face.materialIndex ] : material;
22987
22988                if ( faceMaterial === undefined ) continue;
22989
22990                fvA = vertices[ face.a ];
22991                fvB = vertices[ face.b ];
22992                fvC = vertices[ face.c ];
22993
22994                if ( faceMaterial.morphTargets === true ) {
22995
22996                    var morphTargets = geometry.morphTargets;
22997                    var morphInfluences = this.morphTargetInfluences;
22998
22999                    vA.set( 0, 0, 0 );
23000                    vB.set( 0, 0, 0 );
23001                    vC.set( 0, 0, 0 );
23002
23003                    for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {
23004
23005                        var influence = morphInfluences[ t ];
23006
23007                        if ( influence === 0 ) continue;
23008
23009                        var targets = morphTargets[ t ].vertices;
23010
23011                        vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence );
23012                        vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence );
23013                        vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence );
23014
23015                    }
23016
23017                    vA.add( fvA );
23018                    vB.add( fvB );
23019                    vC.add( fvC );
23020
23021                    fvA = vA;
23022                    fvB = vB;
23023                    fvC = vC;
23024
23025                }
23026
23027                intersection = checkIntersection( this, raycaster, ray, fvA, fvB, fvC, intersectionPoint );
23028
23029                if ( intersection ) {
23030
23031                    if ( uvs ) {
23032
23033                        var uvs_f = uvs[ f ];
23034                        uvA.copy( uvs_f[ 0 ] );
23035                        uvB.copy( uvs_f[ 1 ] );
23036                        uvC.copy( uvs_f[ 2 ] );
23037
23038                        intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC );
23039
23040                    }
23041
23042                    intersection.face = face;
23043                    intersection.faceIndex = f;
23044                    intersects.push( intersection );
23045
23046                }
23047
23048            }
23049
23050        }
23051
23052    };
23053
23054}() );
23055
23056THREE.Mesh.prototype.clone = function () {
23057
23058    return new this.constructor( this.geometry, this.material ).copy( this );
23059
23060};
23061
23062// File:src/objects/Bone.js
23063
23064/**
23065 * @author mikael emtinger / http://gomo.se/
23066 * @author alteredq / http://alteredqualia.com/
23067 * @author ikerr / http://verold.com
23068 */
23069
23070THREE.Bone = function ( skin ) {
23071
23072    THREE.Object3D.call( this );
23073
23074    this.type = 'Bone';
23075
23076    this.skin = skin;
23077
23078};
23079
23080THREE.Bone.prototype = Object.create( THREE.Object3D.prototype );
23081THREE.Bone.prototype.constructor = THREE.Bone;
23082
23083THREE.Bone.prototype.copy = function ( source ) {
23084
23085    THREE.Object3D.prototype.copy.call( this, source );
23086
23087    this.skin = source.skin;
23088
23089    return this;
23090
23091};
23092
23093// File:src/objects/Skeleton.js
23094
23095/**
23096 * @author mikael emtinger / http://gomo.se/
23097 * @author alteredq / http://alteredqualia.com/
23098 * @author michael guerrero / http://realitymeltdown.com
23099 * @author ikerr / http://verold.com
23100 */
23101
23102THREE.Skeleton = function ( bones, boneInverses, useVertexTexture ) {
23103
23104    this.useVertexTexture = useVertexTexture !== undefined ? useVertexTexture : true;
23105
23106    this.identityMatrix = new THREE.Matrix4();
23107
23108    // copy the bone array
23109
23110    bones = bones || [];
23111
23112    this.bones = bones.slice( 0 );
23113
23114    // create a bone texture or an array of floats
23115
23116    if ( this.useVertexTexture ) {
23117
23118        // layout (1 matrix = 4 pixels)
23119        //      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
23120        //  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
23121        //       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
23122        //       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
23123        //       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
23124
23125
23126        var size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix
23127        size = THREE.Math.nextPowerOfTwo( Math.ceil( size ) );
23128        size = Math.max( size, 4 );
23129
23130        this.boneTextureWidth = size;
23131        this.boneTextureHeight = size;
23132
23133        this.boneMatrices = new Float32Array( this.boneTextureWidth * this.boneTextureHeight * 4 ); // 4 floats per RGBA pixel
23134        this.boneTexture = new THREE.DataTexture( this.boneMatrices, this.boneTextureWidth, this.boneTextureHeight, THREE.RGBAFormat, THREE.FloatType );
23135
23136    } else {
23137
23138        this.boneMatrices = new Float32Array( 16 * this.bones.length );
23139
23140    }
23141
23142    // use the supplied bone inverses or calculate the inverses
23143
23144    if ( boneInverses === undefined ) {
23145
23146        this.calculateInverses();
23147
23148    } else {
23149
23150        if ( this.bones.length === boneInverses.length ) {
23151
23152            this.boneInverses = boneInverses.slice( 0 );
23153
23154        } else {
23155
23156            console.warn( 'THREE.Skeleton bonInverses is the wrong length.' );
23157
23158            this.boneInverses = [];
23159
23160            for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
23161
23162                this.boneInverses.push( new THREE.Matrix4() );
23163
23164            }
23165
23166        }
23167
23168    }
23169
23170};
23171
23172THREE.Skeleton.prototype.calculateInverses = function () {
23173
23174    this.boneInverses = [];
23175
23176    for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
23177
23178        var inverse = new THREE.Matrix4();
23179
23180        if ( this.bones[ b ] ) {
23181
23182            inverse.getInverse( this.bones[ b ].matrixWorld );
23183
23184        }
23185
23186        this.boneInverses.push( inverse );
23187
23188    }
23189
23190};
23191
23192THREE.Skeleton.prototype.pose = function () {
23193
23194    var bone;
23195
23196    // recover the bind-time world matrices
23197
23198    for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
23199
23200        bone = this.bones[ b ];
23201
23202        if ( bone ) {
23203
23204            bone.matrixWorld.getInverse( this.boneInverses[ b ] );
23205
23206        }
23207
23208    }
23209
23210    // compute the local matrices, positions, rotations and scales
23211
23212    for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
23213
23214        bone = this.bones[ b ];
23215
23216        if ( bone ) {
23217
23218            if ( bone.parent ) {
23219
23220                bone.matrix.getInverse( bone.parent.matrixWorld );
23221                bone.matrix.multiply( bone.matrixWorld );
23222
23223            } else {
23224
23225                bone.matrix.copy( bone.matrixWorld );
23226
23227            }
23228
23229            bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
23230
23231        }
23232
23233    }
23234
23235};
23236
23237THREE.Skeleton.prototype.update = ( function () {
23238
23239    var offsetMatrix = new THREE.Matrix4();
23240
23241    return function update() {
23242
23243        // flatten bone matrices to array
23244
23245        for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
23246
23247            // compute the offset between the current and the original transform
23248
23249            var matrix = this.bones[ b ] ? this.bones[ b ].matrixWorld : this.identityMatrix;
23250
23251            offsetMatrix.multiplyMatrices( matrix, this.boneInverses[ b ] );
23252            offsetMatrix.toArray( this.boneMatrices, b * 16 );
23253
23254        }
23255
23256        if ( this.useVertexTexture ) {
23257
23258            this.boneTexture.needsUpdate = true;
23259
23260        }
23261
23262    };
23263
23264} )();
23265
23266THREE.Skeleton.prototype.clone = function () {
23267
23268    return new THREE.Skeleton( this.bones, this.boneInverses, this.useVertexTexture );
23269
23270};
23271
23272// File:src/objects/SkinnedMesh.js
23273
23274/**
23275 * @author mikael emtinger / http://gomo.se/
23276 * @author alteredq / http://alteredqualia.com/
23277 * @author ikerr / http://verold.com
23278 */
23279
23280THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) {
23281
23282    THREE.Mesh.call( this, geometry, material );
23283
23284    this.type = 'SkinnedMesh';
23285
23286    this.bindMode = "attached";
23287    this.bindMatrix = new THREE.Matrix4();
23288    this.bindMatrixInverse = new THREE.Matrix4();
23289
23290    // init bones
23291
23292    // TODO: remove bone creation as there is no reason (other than
23293    // convenience) for THREE.SkinnedMesh to do this.
23294
23295    var bones = [];
23296
23297    if ( this.geometry && this.geometry.bones !== undefined ) {
23298
23299        var bone, gbone;
23300
23301        for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
23302
23303            gbone = this.geometry.bones[ b ];
23304
23305            bone = new THREE.Bone( this );
23306            bones.push( bone );
23307
23308            bone.name = gbone.name;
23309            bone.position.fromArray( gbone.pos );
23310            bone.quaternion.fromArray( gbone.rotq );
23311            if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
23312
23313        }
23314
23315        for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
23316
23317            gbone = this.geometry.bones[ b ];
23318
23319            if ( gbone.parent !== - 1 && gbone.parent !== null &&
23320                bones[ gbone.parent ] !== undefined ) {
23321
23322                bones[ gbone.parent ].add( bones[ b ] );
23323
23324            } else {
23325
23326                this.add( bones[ b ] );
23327
23328            }
23329
23330        }
23331
23332    }
23333
23334    this.normalizeSkinWeights();
23335
23336    this.updateMatrixWorld( true );
23337    this.bind( new THREE.Skeleton( bones, undefined, useVertexTexture ), this.matrixWorld );
23338
23339};
23340
23341
23342THREE.SkinnedMesh.prototype = Object.create( THREE.Mesh.prototype );
23343THREE.SkinnedMesh.prototype.constructor = THREE.SkinnedMesh;
23344
23345THREE.SkinnedMesh.prototype.bind = function( skeleton, bindMatrix ) {
23346
23347    this.skeleton = skeleton;
23348
23349    if ( bindMatrix === undefined ) {
23350
23351        this.updateMatrixWorld( true );
23352
23353        this.skeleton.calculateInverses();
23354
23355        bindMatrix = this.matrixWorld;
23356
23357    }
23358
23359    this.bindMatrix.copy( bindMatrix );
23360    this.bindMatrixInverse.getInverse( bindMatrix );
23361
23362};
23363
23364THREE.SkinnedMesh.prototype.pose = function () {
23365
23366    this.skeleton.pose();
23367
23368};
23369
23370THREE.SkinnedMesh.prototype.normalizeSkinWeights = function () {
23371
23372    if ( this.geometry instanceof THREE.Geometry ) {
23373
23374        for ( var i = 0; i < this.geometry.skinWeights.length; i ++ ) {
23375
23376            var sw = this.geometry.skinWeights[ i ];
23377
23378            var scale = 1.0 / sw.lengthManhattan();
23379
23380            if ( scale !== Infinity ) {
23381
23382                sw.multiplyScalar( scale );
23383
23384            } else {
23385
23386                sw.set( 1, 0, 0, 0 );
23386 // do something reasonable
23387
23388            }
23389
23390        }
23391
23392    } else if ( this.geometry instanceof THREE.BufferGeometry ) {
23393
23394        var vec = new THREE.Vector4();
23395
23396        var skinWeight = this.geometry.attributes.skinWeight;
23397
23398        for ( var i = 0; i < skinWeight.count; i ++ ) {
23399
23400            vec.x = skinWeight.getX( i );
23401            vec.y = skinWeight.getY( i );
23402            vec.z = skinWeight.getZ( i );
23403            vec.w = skinWeight.getW( i );
23404
23405            var scale = 1.0 / vec.lengthManhattan();
23406
23407            if ( scale !== Infinity ) {
23408
23409                vec.multiplyScalar( scale );
23410
23411            } else {
23412
23413                vec.set( 1, 0, 0, 0 ); // do something reasonable
23414
23415            }
23416
23417            skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w );
23418
23419        }
23420
23421    }
23422
23423};
23424
23425THREE.SkinnedMesh.prototype.updateMatrixWorld = function( force ) {
23426
23427    THREE.Mesh.prototype.updateMatrixWorld.call( this, true );
23428
23429    if ( this.bindMode === "attached" ) {
23430
23431        this.bindMatrixInverse.getInverse( this.matrixWorld );
23432
23433    } else if ( this.bindMode === "detached" ) {
23434
23435        this.bindMatrixInverse.getInverse( this.bindMatrix );
23436
23437    } else {
23438
23439        console.warn( 'THREE.SkinnedMesh unrecognized bindMode: ' + this.bindMode );
23440
23441    }
23442
23443};
23444
23445THREE.SkinnedMesh.prototype.clone = function() {
23446
23447    return new this.constructor( this.geometry, this.material, this.useVertexTexture ).copy( this );
23448
23449};
23450
23451// File:src/objects/LOD.js
23452
23453/**
23454 * @author mikael emtinger / http://gomo.se/
23455 * @author alteredq / http://alteredqualia.com/
23456 * @author mrdoob / http://mrdoob.com/
23457 */
23458
23459THREE.LOD = function () {
23460
23461    THREE.Object3D.call( this );
23462
23463    this.type = 'LOD';
23464
23465    Object.defineProperties( this, {
23466        levels: {
23467            enumerable: true,
23468            value: []
23469        }
23470    } );
23471
23472};
23473
23474
23475THREE.LOD.prototype = Object.create( THREE.Object3D.prototype );
23476THREE.LOD.prototype.constructor = THREE.LOD;
23477
23478THREE.LOD.prototype.addLevel = function ( object, distance ) {
23479
23480    if ( distance === undefined ) distance = 0;
23481
23482    distance = Math.abs( distance );
23483
23484    var levels = this.levels;
23485
23486    for ( var l = 0; l < levels.length; l ++ ) {
23487
23488        if ( distance < levels[ l ].distance ) {
23489
23490            break;
23491
23492        }
23493
23494    }
23495
23496    levels.splice( l, 0, { distance: distance, object: object } );
23497
23498    this.add( object );
23499
23500};
23501
23502THREE.LOD.prototype.getObjectForDistance = function ( distance ) {
23503
23504    var levels = this.levels;
23505
23506    for ( var i = 1, l = levels.length; i < l; i ++ ) {
23507
23508        if ( distance < levels[ i ].distance ) {
23509
23510            break;
23511
23512        }
23513
23514    }
23515
23516    return levels[ i - 1 ].object;
23517
23518};
23519
23520THREE.LOD.prototype.raycast = ( function () {
23521
23522    var matrixPosition = new THREE.Vector3();
23523
23524    return function raycast( raycaster, intersects ) {
23525
23526        matrixPosition.setFromMatrixPosition( this.matrixWorld );
23527
23528        var distance = raycaster.ray.origin.distanceTo( matrixPosition );
23529
23530        this.getObjectForDistance( distance ).raycast( raycaster, intersects );
23531
23532    };
23533
23534}() );
23535
23536THREE.LOD.prototype.update = function () {
23537
23538    var v1 = new THREE.Vector3();
23539    var v2 = new THREE.Vector3();
23540
23541    return function update( camera ) {
23542
23543        var levels = this.levels;
23544
23545        if ( levels.length > 1 ) {
23546
23547            v1.setFromMatrixPosition( camera.matrixWorld );
23548            v2.setFromMatrixPosition( this.matrixWorld );
23549
23550            var distance = v1.distanceTo( v2 );
23551
23552            levels[ 0 ].object.visible = true;
23553
23554            for ( var i = 1, l = levels.length; i < l; i ++ ) {
23555
23556                if ( distance >= levels[ i ].distance ) {
23557
23558                    levels[ i - 1 ].object.visible = false;
23559                    levels[ i ].object.visible = true;
23560
23561                } else {
23562
23563                    break;
23564
23565                }
23566
23567            }
23568
23569            for ( ; i < l; i ++ ) {
23570
23571                levels[ i ].object.visible = false;
23572
23573            }
23574
23575        }
23576
23577    };
23578
23579}();
23580
23581THREE.LOD.prototype.copy = function ( source ) {
23582
23583    THREE.Object3D.prototype.copy.call( this, source, false );
23584
23585    var levels = source.levels;
23586
23587    for ( var i = 0, l = levels.length; i < l; i ++ ) {
23588
23589        var level = levels[ i ];
23590
23591        this.addLevel( level.object.clone(), level.distance );
23592
23593    }
23594
23595    return this;
23596
23597};
23598
23599THREE.LOD.prototype.toJSON = function ( meta ) {
23600
23601    var data = THREE.Object3D.prototype.toJSON.call( this, meta );
23602
23603    data.object.levels = [];
23604
23605    var levels = this.levels;
23606
23607    for ( var i = 0, l = levels.length; i < l; i ++ ) {
23608
23609        var level = levels[ i ];
23610
23611        data.object.levels.push( {
23612            object: level.object.uuid,
23613            distance: level.distance
23614        } );
23615
23616    }
23617
23618    return data;
23619
23620};
23621
23622// File:src/objects/Sprite.js
23623
23624/**
23625 * @author mikael emtinger / http://gomo.se/
23626 * @author alteredq / http://alteredqualia.com/
23627 */
23628
23629THREE.Sprite = ( function () {
23630
23631    var indices = new Uint16Array( [ 0, 1, 2,  0, 2, 3 ] );
23632    var vertices = new Float32Array( [ - 0.5, - 0.5, 0,   0.5, - 0.5, 0,   0.5, 0.5, 0,   - 0.5, 0.5, 0 ] );
23633    var uvs = new Float32Array( [ 0, 0,   1, 0,   1, 1,   0, 1 ] );
23634
23635    var geometry = new THREE.BufferGeometry();
23636    geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
23637    geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
23638    geometry.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
23639
23640    return function Sprite( material ) {
23641
23642        THREE.Object3D.call( this );
23643
23644        this.type = 'Sprite';
23645
23646        this.geometry = geometry;
23647        this.material = ( material !== undefined ) ? material : new THREE.SpriteMaterial();
23648
23649    };
23650
23651} )();
23652
23653THREE.Sprite.prototype = Object.create( THREE.Object3D.prototype );
23654THREE.Sprite.prototype.constructor = THREE.Sprite;
23655
23656THREE.Sprite.prototype.raycast = ( function () {
23657
23658    var matrixPosition = new THREE.Vector3();
23659
23660    return function raycast( raycaster, intersects ) {
23661
23662        matrixPosition.setFromMatrixPosition( this.matrixWorld );
23663
23664        var distanceSq = raycaster.ray.distanceSqToPoint( matrixPosition );
23665        var guessSizeSq = this.scale.x * this.scale.y / 4;
23666
23667        if ( distanceSq > guessSizeSq ) {
23668
23669            return;
23670
23671        }
23672
23673        intersects.push( {
23674
23675            distance: Math.sqrt( distanceSq ),
23676            point: this.position,
23677            face: null,
23678            object: this
23679
23680        } );
23681
23682    };
23683
23684}() );
23685
23686THREE.Sprite.prototype.clone = function () {
23687
23688    return new this.constructor( this.material ).copy( this );
23689
23690};
23691
23692// Backwards compatibility
23693
23694THREE.Particle = THREE.Sprite;
23695
23696// File:src/objects/LensFlare.js
23697
23698/**
23699 * @author mikael emtinger / http://gomo.se/
23700 * @author alteredq / http://alteredqualia.com/
23701 */
23702
23703THREE.LensFlare = function ( texture, size, distance, blending, color ) {
23704
23705    THREE.Object3D.call( this );
23706
23707    this.lensFlares = [];
23708
23709    this.positionScreen = new THREE.Vector3();
23710    this.customUpdateCallback = undefined;
23711
23712    if ( texture !== undefined ) {
23713
23714        this.add( texture, size, distance, blending, color );
23715
23716    }
23717
23718};
23719
23720THREE.LensFlare.prototype = Object.create( THREE.Object3D.prototype );
23721THREE.LensFlare.prototype.constructor = THREE.LensFlare;
23722
23723
23724/*
23725 * Add: adds another flare
23726 */
23727
23728THREE.LensFlare.prototype.add = function ( texture, size, distance, blending, color, opacity ) {
23729
23730    if ( size === undefined ) size = - 1;
23731    if ( distance === undefined ) distance = 0;
23732    if ( opacity === undefined ) opacity = 1;
23733    if ( color === undefined ) color = new THREE.Color( 0xffffff );
23734    if ( blending === undefined ) blending = THREE.NormalBlending;
23735
23736    distance = Math.min( distance, Math.max( 0, distance ) );
23737
23738    this.lensFlares.push( {
23739        texture: texture,	// THREE.Texture
23740        size: size, 		// size in pixels (-1 = use texture.width)
23741        distance: distance, 	// distance (0-1) from light source (0=at light source)
23742        x: 0, y: 0, z: 0,	// screen position (-1 => 1) z = 0 is in front z = 1 is back
23743        scale: 1, 		// scale
23744        rotation: 0, 		// rotation
23745        opacity: opacity,	// opacity
23746        color: color,		// color
23747        blending: blending	// blending
23748    } );
23749
23750};
23751
23752/*
23753 * Update lens flares update positions on all flares based on the screen position
23754 * Set myLensFlare.customUpdateCallback to alter the flares in your project specific way.
23755 */
23756
23757THREE.LensFlare.prototype.updateLensFlares = function () {
23758
23759    var f, fl = this.lensFlares.length;
23760    var flare;
23761    var vecX = - this.positionScreen.x * 2;
23762    var vecY = - this.positionScreen.y * 2;
23763
23764    for ( f = 0; f < fl; f ++ ) {
23765
23766        flare = this.lensFlares[ f ];
23767
23768        flare.x = this.positionScreen.x + vecX * flare.distance;
23769        flare.y = this.positionScreen.y + vecY * flare.distance;
23770
23771        flare.wantedRotation = flare.x * Math.PI * 0.25;
23772        flare.rotation += ( flare.wantedRotation - flare.rotation ) * 0.25;
23773
23774    }
23775
23776};
23777
23778THREE.LensFlare.prototype.copy = function ( source ) {
23779
23780    THREE.Object3D.prototype.copy.call( this, source );
23781
23782    this.positionScreen.copy( source.positionScreen );
23783    this.customUpdateCallback = source.customUpdateCallback;
23784
23785    for ( var i = 0, l = source.lensFlares.length; i < l; i ++ ) {
23786
23787        this.lensFlares.push( source.lensFlares[ i ] );
23788
23789    }
23790
23791    return this;
23792
23793};
23794
23795// File:src/scenes/Scene.js
23796
23797/**
23798 * @author mrdoob / http://mrdoob.com/
23799 */
23800
23801THREE.Scene = function () {
23802
23803    THREE.Object3D.call( this );
23804
23805    this.type = 'Scene';
23806
23807    this.fog = null;
23808    this.overrideMaterial = null;
23809
23810    this.autoUpdate = true; // checked by the renderer
23811
23812};
23813
23814THREE.Scene.prototype = Object.create( THREE.Object3D.prototype );
23815THREE.Scene.prototype.constructor = THREE.Scene;
23816
23817THREE.Scene.prototype.copy = function ( source, recursive ) {
23818
23819    THREE.Object3D.prototype.copy.call( this, source, recursive );
23820
23821    if ( source.fog !== null ) this.fog = source.fog.clone();
23822    if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
23823
23824    this.autoUpdate = source.autoUpdate;
23825    this.matrixAutoUpdate = source.matrixAutoUpdate;
23826
23827    return this;
23828
23829};
23830
23831// File:src/scenes/Fog.js
23832
23833/**
23834 * @author mrdoob / http://mrdoob.com/
23835 * @author alteredq / http://alteredqualia.com/
23836 */
23837
23838THREE.Fog = function ( color, near, far ) {
23839
23840    this.name = '';
23841
23842    this.color = new THREE.Color( color );
23843
23844    this.near = ( near !== undefined ) ? near : 1;
23845    this.far = ( far !== undefined ) ? far : 1000;
23846
23847};
23848
23849THREE.Fog.prototype.clone = function () {
23850
23851    return new THREE.Fog( this.color.getHex(), this.near, this.far );
23852
23853};
23854
23855// File:src/scenes/FogExp2.js
23856
23857/**
23858 * @author mrdoob / http://mrdoob.com/
23859 * @author alteredq / http://alteredqualia.com/
23860 */
23861
23862THREE.FogExp2 = function ( color, density ) {
23863
23864    this.name = '';
23865
23866    this.color = new THREE.Color( color );
23867    this.density = ( density !== undefined ) ? density : 0.00025;
23868
23869};
23870
23871THREE.FogExp2.prototype.clone = function () {
23872
23873    return new THREE.FogExp2( this.color.getHex(), this.density );
23874
23875};
23876
23877// File:src/renderers/shaders/ShaderChunk.js
23878
23879THREE.ShaderChunk = {};
23880
23881// File:src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl
23882
23883THREE.ShaderChunk[ 'alphamap_fragment' ] = "#ifdef USE_ALPHAMAP\n	diffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n";
23884
23885// File:src/renderers/shaders/ShaderChunk/alphamap_pars_fragment.glsl
23886
23887THREE.ShaderChunk[ 'alphamap_pars_fragment' ] = "#ifdef USE_ALPHAMAP\n	uniform sampler2D alphaMap;\n#endif\n";
23888
23889// File:src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl
23890
23891THREE.ShaderChunk[ 'alphatest_fragment' ] = "#ifdef ALPHATEST\n	if ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n";
23892
23893// File:src/renderers/shaders/ShaderChunk/aomap_fragment.glsl
23894
23895THREE.ShaderChunk[ 'aomap_fragment' ] = "#ifdef USE_AOMAP\n	float ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n	reflectedLight.indirectDiffuse *= ambientOcclusion;\n	#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n		float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n		reflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n	#endif\n#endif\n";
23896
23897// File:src/renderers/shaders/ShaderChunk/aomap_pars_fragment.glsl
23898
23899THREE.ShaderChunk[ 'aomap_pars_fragment' ] = "#ifdef USE_AOMAP\n	uniform sampler2D aoMap;\n	uniform float aoMapIntensity;\n#endif";
23900
23901// File:src/renderers/shaders/ShaderChunk/begin_vertex.glsl
23902
23903THREE.ShaderChunk[ 'begin_vertex' ] = "\nvec3 transformed = vec3( position );\n";
23904
23905// File:src/renderers/shaders/ShaderChunk/beginnormal_vertex.glsl
23906
23907THREE.ShaderChunk[ 'beginnormal_vertex' ] = "\nvec3 objectNormal = vec3( normal );\n";
23908
23909// File:src/renderers/shaders/ShaderChunk/bsdfs.glsl
23910
23911THREE.ShaderChunk[ 'bsdfs' ] = "bool testLightInRange( const in float lightDistance, const in float cutoffDistance ) {\n	return any( bvec2( cutoffDistance == 0.0, lightDistance < cutoffDistance ) );\n}\nfloat punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n		if( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n			float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n			float maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n			return distanceFalloff * maxDistanceCutoffFactor;
23911\n#else\n			return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n		}\n		return 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n	return RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n	float fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n	return ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n	float a2 = pow2( alpha );\n	float gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n	float gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n	return 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n	float a2 = pow2( alpha );\n	float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n	float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n	return 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n	float a2 = pow2( alpha );\n	float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n	return RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n	float alpha = pow2( roughness );\n	vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n	float dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n	float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n	float dotNH = saturate( dot( geometry.normal, halfDir ) );\n	float dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n	vec3 F = F_Schlick( specularColor, dotLH );
23911\n	float G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n	float D = D_GGX( alpha, dotNH );\n	return F * ( G * D );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n	float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n	const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n	const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n	vec4 r = roughness * c0 + c1;\n	float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n	vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n	return specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n	return 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n	return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n	vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n	float dotNH = saturate( dot( geometry.normal, halfDir ) );\n	float dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n	vec3 F = F_Schlick( specularColor, dotLH );\n	float G = G_BlinnPhong_Implicit( );\n	float D = D_BlinnPhong( shininess, dotNH );\n	return F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n	return ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n	return sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";
23912
23913// File:src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl
23914
23915THREE.ShaderChunk[ 'bumpmap_pars_fragment' ] = "#ifdef USE_BUMPMAP\n	uniform sampler2D bumpMap;\n	uniform float bumpScale;\n	vec2 dHdxy_fwd() {\n		vec2 dSTdx = dFdx( vUv );\n		vec2 dSTdy = dFdy( vUv );\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		return vec2( dBx, dBy );\n	}\n	vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\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		float fDet = dot( vSigmaX, R1 );\n		vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n		return normalize( abs( fDet ) * surf_norm - vGrad );\n	}\n#endif\n";
23916
23917// File:src/renderers/shaders/ShaderChunk/clipping_planes_fragment.glsl
23918
23919THREE.ShaderChunk[ 'clipping_planes_fragment' ] = "#if NUM_CLIPPING_PLANES > 0\n	for ( int i = 0; i < NUM_CLIPPING_PLANES; ++ i ) {\n		vec4 plane = clippingPlanes[ i ];\n		if ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n	}\n#endif\n";
23920
23921// File:src/renderers/shaders/ShaderChunk/clipping_planes_pars_fragment.glsl
23922
23923THREE.ShaderChunk[ 'clipping_planes_pars_fragment' ] = "#if NUM_CLIPPING_PLANES > 0\n	#if ! defined( PHYSICAL ) && ! defined( PHONG )\n		varying vec3 vViewPosition;\n	#endif\n	uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n";
23924
23925// File:src/renderers/shaders/ShaderChunk/clipping_planes_pars_vertex.glsl
23926
23927THREE.ShaderChunk[ 'clipping_planes_pars_vertex' ] = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n	varying vec3 vViewPosition;\n#endif\n";
23928
23929// File:src/renderers/shaders/ShaderChunk/clipping_planes_vertex.glsl
23930
23931THREE.ShaderChunk[ 'clipping_planes_vertex' ] = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n	vViewPosition = - mvPosition.xyz;\n#endif\n";
23932
23933// File:src/renderers/shaders/ShaderChunk/color_fragment.glsl
23934
23935THREE.ShaderChunk[ 'color_fragment' ] = "#ifdef USE_COLOR\n	diffuseColor.rgb *= vColor;\n#endif";
23936
23937// File:src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl
23938
23939THREE.ShaderChunk[ 'color_pars_fragment' ] = "#ifdef USE_COLOR\n	varying vec3 vColor;\n#endif\n";
23940
23941// File:src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl
23942
23943THREE.ShaderChunk[ 'color_pars_vertex' ] = "#ifdef USE_COLOR\n	varying vec3 vColor;\n#endif";
23944
23945// File:src/renderers/shaders/ShaderChunk/color_vertex.glsl
23946
23947THREE.ShaderChunk[ 'color_vertex' ] = "#ifdef USE_COLOR\n	vColor.xyz = color.xyz;\n#endif";
23948
23949// File:src/renderers/shaders/ShaderChunk/common.glsl
23950
23951THREE.ShaderChunk[ 'common' ] = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n	const highp float a = 12.9898, b = 78.233, c = 43758.5453;\n	highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n	return fract(sin(sn) * c);\n}\nstruct IncidentLight {\n	vec3 color;\n	vec3 direction;\n	bool visible;\n};\nstruct ReflectedLight {\n	vec3 directDiffuse;\n	vec3 directSpecular;\n	vec3 indirectDiffuse;\n	vec3 indirectSpecular;\n};\nstruct GeometricContext {\n	vec3 position;\n	vec3 normal;\n	vec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n	return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n	return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n	float distance = dot( planeNormal, point - pointOnPlane );\n	return - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n	return sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n	return lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\n";
23952
23953// File:src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl
23954
23955THREE.ShaderChunk[ 'cube_uv_reflection_fragment' ] = "#ifdef ENVMAP_TYPE_CUBE_UV\nconst float cubeUV_textureSize = 1024.0;\nint getFaceFromDirection(vec3 direction) {\n	vec3 absDirection = abs(direction);\n	int face = -1;\n	if( absDirection.x > absDirection.z ) {\n		if(absDirection.x > absDirection.y )\n			face = direction.x > 0.0 ? 0 : 3;\n		else\n			face = direction.y > 0.0 ? 1 : 4;\n	}\n	else {\n		if(absDirection.z > absDirection.y )\n			face = direction.z > 0.0 ? 2 : 5;\n		else\n			face = direction.y > 0.0 ? 1 : 4;\n	}\n	return face;\n}\nfloat cubeUV_maxLods1 = log2(cubeUV_textureSize*0.25) - 1.0;\nfloat cubeUV_rangeClamp = exp2((6.0 - 1.0) * 2.0);\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n	float scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n	float dxRoughness = dFdx(roughness);\n	float dyRoughness = dFdy(roughness);\n	vec3 dx = dFdx( vec * scale * dxRoughness );\n	vec3 dy = dFdy( vec * scale * dyRoughness );\n	float d = max( dot( dx, dx ), dot( dy, dy ) );\n	d = clamp(d, 1.0, cubeUV_rangeClamp);
23955\n	float mipLevel = 0.5 * log2(d);\n	return vec2(floor(mipLevel), fract(mipLevel));\n}\nfloat cubeUV_maxLods2 = log2(cubeUV_textureSize*0.25) - 2.0;\nconst float cubeUV_rcpTextureSize = 1.0 / cubeUV_textureSize;\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n	mipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n	float a = 16.0 * cubeUV_rcpTextureSize;\n	vec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n	vec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n	float powScale = exp2_packed.x * exp2_packed.y;\n	float scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n	float mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n	bool bRes = mipLevel == 0.0;\n	scale =  bRes && (scale < a) ? a : scale;\n	vec3 r;\n	vec2 offset;\n	int face = getFaceFromDirection(direction);\n	float rcpPowScale = 1.0 / powScale;\n	if( face == 0) {\n		r = vec3(direction.x, -direction.z, direction.y);\n		offset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n		offset.y = bRes && (offset.y < 2.0*a) ?  a : offset.y;\n	}\n	else if( face == 1) {\n		r = vec3(direction.y, direction.x, direction.z);\n		offset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n		offset.y = bRes && (offset.y < 2.0*a) ?  a : offset.y;\n	}\n	else if( face == 2) {\n		r = vec3(direction.z, direction.x, direction.y);\n		offset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n		offset.y = bRes && (offset.y < 2.0*a) ?  a : offset.y;\n	}\n	else if( face == 3) {\n		r = vec3(direction.x, direction.z, direction.y);\n		offset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n		offset.y = bRes && (offset.y < 2.0*a) ?  0.0 : offset.y;\n	}\n	else if( face == 4) {\n		r = vec3(direction.y, direction.x, -direction.z);\n		offset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n		offset.y = bRes && (offset.y < 2.0*a) ?  0.0 : offset.y;\n	}\n	else {\n		r = vec3(direction.z, -direction.x, direction.y);\n		offset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n		offset.y = bRes && (offset.y < 2.0*a) ?  0.0 : offset.y;\n	}\n	r = normalize(r);\n	float texelOffset = 0.5 * cubeUV_rcpTextureSize;\n	vec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n	vec2 base = offset + vec2( texelOffset );\n	return base + s * ( scale - 2.0 * texelOffset );\n}\nfloat cubeUV_maxLods3 = log2(cubeUV_textureSize*0.25) - 3.0;\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n	float roughnessVal = roughness* cubeUV_maxLods3;\n	float r1 = floor(roughnessVal);\n	float r2 = r1 + 1.0;\n	float t = fract(roughnessVal);\n	vec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n	float s = mipInfo.y;\n	float level0 = mipInfo.x;\n	float level1 = level0 + 1.0;\n	level1 = level1 > 5.0 ? 5.0 : level1;\n	level0 += min( floor( s + 0.5 ), 5.0 );\n	vec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n	vec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n	vec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n	vec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n	vec4 result = mix(color10, color20, t);\n	return vec4(result.rgb, 1.0);\n}\n#endif\n";
23956
23957// File:src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl
23958
23959THREE.ShaderChunk[ 'defaultnormal_vertex' ] = "#ifdef FLIP_SIDED\n	objectNormal = -objectNormal;\n#endif\nvec3 transformedNormal = normalMatrix * objectNormal;\n";
23960
23961// File:src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl
23962
23963THREE.ShaderChunk[ 'displacementmap_vertex' ] = "#ifdef USE_DISPLACEMENTMAP\n	transformed += normal * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n";
23964
23965// File:src/renderers/shaders/ShaderChunk/displacementmap_pars_vertex.glsl
23966
23967THREE.ShaderChunk[ 'displacementmap_pars_vertex' ] = "#ifdef USE_DISPLACEMENTMAP\n	uniform sampler2D displacementMap;\n	uniform float displacementScale;\n	uniform float displacementBias;\n#endif\n";
23968
23969// File:src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl
23970
23971THREE.ShaderChunk[ 'emissivemap_fragment' ] = "#ifdef USE_EMISSIVEMAP\n	vec4 emissiveColor = texture2D( emissiveMap, vUv );\n	emissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n	totalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n";
23972
23973// File:src/renderers/shaders/ShaderChunk/emissivemap_pars_fragment.glsl
23974
23975THREE.ShaderChunk[ 'emissivemap_pars_fragment' ] = "#ifdef USE_EMISSIVEMAP\n	uniform sampler2D emissiveMap;\n#endif\n";
23976
23977// File:src/renderers/shaders/ShaderChunk/encodings_pars_fragment.glsl
23978
23979THREE.ShaderChunk[ 'encodings_pars_fragment' ] = "\nvec4 LinearToLinear( in vec4 value ) {\n  return value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n  return vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n  return vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n  return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n  return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n  return vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}
23979\nvec4 LinearToRGBE( in vec4 value ) {\n  float maxComponent = max( max( value.r, value.g ), value.b );\n  float fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n  return vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n  return vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n  float maxRGB = max( value.x, max( value.g, value.b ) );\n  float M      = clamp( maxRGB / maxRange, 0.0, 1.0 );\n  M            = ceil( M * 255.0 ) / 255.0;\n  return vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n    return vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n    float maxRGB = max( value.x, max( value.g, value.b ) );\n    float D      = max( maxRange / maxRGB, 1.0 );\n    D            = min( floor( D ) / 255.0, 1.0 );\n    return vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value )  {\n  vec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n  Xp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n  vec4 vResult;\n  vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n  float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n  vResult.w = fract(Le);\n  vResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n  return vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n  float Le = value.z * 255.0 + value.w;\n  vec3 Xp_Y_XYZp;\n  Xp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n  Xp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n  Xp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n  vec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n  return vec4( max(vRGB, 0.0), 1.0 );\n}\n";
23980
23981// File:src/renderers/shaders/ShaderChunk/encodings_fragment.glsl
23982
23983THREE.ShaderChunk[ 'encodings_fragment' ] = "  gl_FragColor = linearToOutputTexel( gl_FragColor );\n";
23984
23985// File:src/renderers/shaders/ShaderChunk/envmap_fragment.glsl
23986
23987THREE.ShaderChunk[ 'envmap_fragment' ] = "#ifdef USE_ENVMAP\n	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n		vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n		vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n		#ifdef ENVMAP_MODE_REFLECTION\n			vec3 reflectVec = reflect( cameraToVertex, worldNormal );\n		#else\n			vec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n		#endif\n	#else\n		vec3 reflectVec = vReflect;\n	#endif\n	#ifdef DOUBLE_SIDED\n		float flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n	#else\n		float flipNormal = 1.0;\n	#endif\n	#ifdef ENVMAP_TYPE_CUBE\n		vec4 envColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\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	#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	envColor = envMapTexelToLinear( envColor );\n	#ifdef ENVMAP_BLENDING_MULTIPLY\n		outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n	#elif defined( ENVMAP_BLENDING_MIX )\n		outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n	#elif defined( ENVMAP_BLENDING_ADD )\n		outgoingLight += envColor.xyz * specularStrength * reflectivity;\n	#endif\n#endif\n";
23988
23989// File:src/renderers/shaders/ShaderChunk/envmap_pars_fragment.glsl
23990
23991THREE.ShaderChunk[ 'envmap_pars_fragment' ] = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n	uniform float reflectivity;\n	uniform float envMapIntenstiy;\n#endif\n#ifdef USE_ENVMAP\n	#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n		varying vec3 vWorldPosition;\n	#endif\n	#ifdef ENVMAP_TYPE_CUBE\n		uniform samplerCube envMap;\n	#else\n		uniform sampler2D envMap;\n	#endif\n	uniform float flipEnvMap;\n	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n		uniform float refractionRatio;\n	#else\n		varying vec3 vReflect;\n	#endif\n#endif\n";
23992
23993// File:src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl
23994
23995THREE.ShaderChunk[ 'envmap_pars_vertex' ] = "#ifdef USE_ENVMAP\n	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n		varying vec3 vWorldPosition;\n	#else\n		varying vec3 vReflect;\n		uniform float refractionRatio;\n	#endif\n#endif\n";
23996
23997// File:src/renderers/shaders/ShaderChunk/envmap_vertex.glsl
23998
23999THREE.ShaderChunk[ 'envmap_vertex' ] = "#ifdef USE_ENVMAP\n	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n		vWorldPosition = worldPosition.xyz;
23999\n	#else\n		vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n		vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n		#ifdef ENVMAP_MODE_REFLECTION\n			vReflect = reflect( cameraToVertex, worldNormal );\n		#else\n			vReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n		#endif\n	#endif\n#endif\n";
24000
24001// File:src/renderers/shaders/ShaderChunk/fog_fragment.glsl
24002
24003THREE.ShaderChunk[ 'fog_fragment' ] = "#ifdef USE_FOG\n	#ifdef USE_LOGDEPTHBUF_EXT\n		float depth = gl_FragDepthEXT / gl_FragCoord.w;\n	#else\n		float depth = gl_FragCoord.z / gl_FragCoord.w;\n	#endif\n	#ifdef FOG_EXP2\n		float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );\n	#else\n		float fogFactor = smoothstep( fogNear, fogFar, depth );\n	#endif\n	gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n";
24004
24005// File:src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl
24006
24007THREE.ShaderChunk[ 'fog_pars_fragment' ] = "#ifdef USE_FOG\n	uniform vec3 fogColor;\n	#ifdef FOG_EXP2\n		uniform float fogDensity;\n	#else\n		uniform float fogNear;\n		uniform float fogFar;\n	#endif\n#endif";
24008
24009// File:src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl
24010
24011THREE.ShaderChunk[ 'lightmap_fragment' ] = "#ifdef USE_LIGHTMAP\n	reflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n";
24012
24013// File:src/renderers/shaders/ShaderChunk/lightmap_pars_fragment.glsl
24014
24015THREE.ShaderChunk[ 'lightmap_pars_fragment' ] = "#ifdef USE_LIGHTMAP\n	uniform sampler2D lightMap;\n	uniform float lightMapIntensity;\n#endif";
24016
24017// File:src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl
24018
24019THREE.ShaderChunk[ 'lights_lambert_vertex' ] = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n	vLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n	for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n		getPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n		dotNL = dot( geometry.normal, directLight.direction );\n		directLightColor_Diffuse = PI * directLight.color;\n		vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n		#ifdef DOUBLE_SIDED\n			vLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n		#endif\n	}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n	for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n		getSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n		dotNL = dot( geometry.normal, directLight.direction );\n		directLightColor_Diffuse = PI * directLight.color;\n		vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n		#ifdef DOUBLE_SIDED\n			vLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n		#endif\n	}\n#endif\n#if NUM_DIR_LIGHTS > 0\n	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n		getDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n		dotNL = dot( geometry.normal, directLight.direction );\n		directLightColor_Diffuse = PI * directLight.color;\n		vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n		#ifdef DOUBLE_SIDED\n			vLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n		#endif\n	}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n	for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n		vLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n		#ifdef DOUBLE_SIDED\n			vLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n		#endif\n	}\n#endif\n";
24020
24021// File:src/renderers/shaders/ShaderChunk/lights_pars.glsl
24022
24023THREE.ShaderChunk[ 'lights_pars' ] = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n	vec3 irradiance = ambientLightColor;\n	#ifndef PHYSICALLY_CORRECT_LIGHTS\n		irradiance *= PI;\n	#endif\n	return irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n	struct DirectionalLight {\n		vec3 direction;\n		vec3 color;\n		int shadow;\n		float shadowBias;\n		float shadowRadius;\n		vec2 shadowMapSize;\n	};\n	uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n	void getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n		directLight.color = directionalLight.color;\n		directLight.direction = directionalLight.direction;\n		directLight.visible = true;\n	}\n#endif\n#if NUM_POINT_LIGHTS > 0\n	struct PointLight {\n		vec3 position;\n		vec3 color;\n		float distance;\n		float decay;\n		int shadow;\n		float shadowBias;\n		float shadowRadius;\n		vec2 shadowMapSize;\n	};\n	uniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n	void getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n		vec3 lVector = pointLight.position - geometry.position;\n		directLight.direction = normalize( lVector );\n		float lightDistance = length( lVector );\n		if ( testLightInRange( lightDistance, pointLight.distance ) ) {\n			directLight.color = pointLight.color;\n			directLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n			directLight.visible = true;\n		} else {\n			directLight.color = vec3( 0.0 );\n			directLight.visible = false;\n		}\n	}
24023\n#endif\n#if NUM_SPOT_LIGHTS > 0\n	struct SpotLight {\n		vec3 position;\n		vec3 direction;\n		vec3 color;\n		float distance;\n		float decay;\n		float coneCos;\n		float penumbraCos;\n		int shadow;\n		float shadowBias;\n		float shadowRadius;\n		vec2 shadowMapSize;\n	};\n	uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n	void getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight  ) {\n		vec3 lVector = spotLight.position - geometry.position;\n		directLight.direction = normalize( lVector );\n		float lightDistance = length( lVector );\n		float angleCos = dot( directLight.direction, spotLight.direction );\n		if ( all( bvec2( angleCos > spotLight.coneCos, testLightInRange( lightDistance, spotLight.distance ) ) ) ) {\n			float spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n			directLight.color = spotLight.color;\n			directLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n			directLight.visible = true;\n		} else {\n			directLight.color = vec3( 0.0 );\n			directLight.visible = false;\n		}\n	}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n	struct HemisphereLight {\n		vec3 direction;\n		vec3 skyColor;\n		vec3 groundColor;\n	};\n	uniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n	vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n		float dotNL = dot( geometry.normal, hemiLight.direction );\n		float hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n		vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n		#ifndef PHYSICALLY_CORRECT_LIGHTS\n			irradiance *= PI;\n		#endif\n		return irradiance;\n	}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n	vec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n		#ifdef DOUBLE_SIDED\n			float flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n		#else\n			float flipNormal = 1.0;\n		#endif\n		vec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n		#ifdef ENVMAP_TYPE_CUBE\n			vec3 queryVec = flipNormal * vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n			#ifdef TEXTURE_LOD_EXT\n				vec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n			#else\n				vec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n			#endif\n			envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n		#elif defined( ENVMAP_TYPE_CUBE_UV )\n			vec3 queryVec = flipNormal * vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n			vec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n		#else\n			vec4 envMapColor = vec4( 0.0 );\n		#endif\n		return PI * envMapColor.rgb * envMapIntensity;\n	}\n	float getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n		float maxMIPLevelScalar = float( maxMIPLevel );\n		float desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n		return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n	}\n	vec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n		#ifdef ENVMAP_MODE_REFLECTION\n			vec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n		#else\n			vec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n		#endif\n		#ifdef DOUBLE_SIDED\n			float flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n		#else\n			float flipNormal = 1.0;\n		#endif\n		reflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n		float specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n		#ifdef ENVMAP_TYPE_CUBE\n			vec3 queryReflectVec = flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n			#ifdef TEXTURE_LOD_EXT\n				vec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n			#else\n				vec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n			#endif\n			envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n		#elif defined( ENVMAP_TYPE_CUBE_UV )\n			vec3 queryReflectVec = flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n			vec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShinine
24023ssExponent));\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			#ifdef TEXTURE_LOD_EXT\n				vec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n			#else\n				vec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n			#endif\n			envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\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			#ifdef TEXTURE_LOD_EXT\n				vec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n			#else\n				vec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n			#endif\n			envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n		#endif\n		return envMapColor.rgb * envMapIntensity;\n	}\n#endif\n";
24024
24025// File:src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl
24026
24027THREE.ShaderChunk[ 'lights_phong_fragment' ] = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n";
24028
24029// File:src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl
24030
24031THREE.ShaderChunk[ 'lights_phong_pars_fragment' ] = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n	varying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n	vec3	diffuseColor;\n	vec3	specularColor;\n	float	specularShininess;\n	float	specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n	float dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n	vec3 irradiance = dotNL * directLight.color;\n	#ifndef PHYSICALLY_CORRECT_LIGHTS\n		irradiance *= PI;\n	#endif\n	reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n	reflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n	reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct				RE_Direct_BlinnPhong\n#define RE_IndirectDiffuse		RE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )	(0)\n";
24032
24033// File:src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl
24034
24035THREE.ShaderChunk[ 'lights_physical_fragment' ] = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n	material.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n#else\n	material.specularColor = mix( vec3( 0.16 * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n#endif\n";
24036
24037// File:src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl
24038
24039THREE.ShaderChunk[ 'lights_physical_pars_fragment' ] = "struct PhysicalMaterial {\n	vec3	diffuseColor;\n	float	specularRoughness;\n	vec3	specularColor;\n	#ifndef STANDARD\n	#endif\n};\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n	float dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n	vec3 irradiance = dotNL * directLight.color;\n	#ifndef PHYSICALLY_CORRECT_LIGHTS\n		irradiance *= PI;\n	#endif\n	reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n	reflectedLight.directSpecular += irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n	reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n	reflectedLight.indirectSpecular += radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n}\n#define RE_Direct				RE_Direct_Physical\n#define RE_IndirectDiffuse		RE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular		RE_IndirectSpecular_Physical\n#define Material_BlinnShinine
24039ssExponent( material )   GGXRoughnessToBlinnExponent( material.specularRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n	return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n";
24040
24041// File:src/renderers/shaders/ShaderChunk/lights_template.glsl
24042
24043THREE.ShaderChunk[ 'lights_template' ] = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n	PointLight pointLight;\n	for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n		pointLight = pointLights[ i ];\n		getPointDirectLightIrradiance( pointLight, geometry, directLight );\n		#ifdef USE_SHADOWMAP\n		directLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ] ) : 1.0;\n		#endif\n		RE_Direct( directLight, geometry, material, reflectedLight );\n	}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n	SpotLight spotLight;\n	for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n		spotLight = spotLights[ i ];\n		getSpotDirectLightIrradiance( spotLight, geometry, directLight );\n		#ifdef USE_SHADOWMAP\n		directLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n		#endif\n		RE_Direct( directLight, geometry, material, reflectedLight );\n	}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n	DirectionalLight directionalLight;\n	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n		directionalLight = directionalLights[ i ];\n		getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n		#ifdef USE_SHADOWMAP\n		directLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n		#endif\n		RE_Direct( directLight, geometry, material, reflectedLight );\n	}\n#endif\n#if defined( RE_IndirectDiffuse )\n	vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n	#ifdef USE_LIGHTMAP\n		vec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n		#ifndef PHYSICALLY_CORRECT_LIGHTS\n			lightMapIrradiance *= PI;\n		#endif\n		irradiance += lightMapIrradiance;\n	#endif\n	#if ( NUM_HEMI_LIGHTS > 0 )\n		for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n			irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n		}\n	#endif\n	#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n	 	irradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n	#endif\n	RE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n	vec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n	RE_IndirectSpecular( radiance, geometry, material, reflectedLight );\n#endif\n";
24044
24045// File:src/renderers/shaders/ShaderChunk/logdepthbuf_fragment.glsl
24046
24047THREE.ShaderChunk[ 'logdepthbuf_fragment' ] = "#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)\n	gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;\n#endif";
24048
24049// File:src/renderers/shaders/ShaderChunk/logdepthbuf_pars_fragment.glsl
24050
24051THREE.ShaderChunk[ 'logdepthbuf_pars_fragment' ] = "#ifdef USE_LOGDEPTHBUF\n	uniform float logDepthBufFC;\n	#ifdef USE_LOGDEPTHBUF_EXT\n		varying float vFragDepth;\n	#endif\n#endif\n";
24052
24053// File:src/renderers/shaders/ShaderChunk/logdepthbuf_pars_vertex.glsl
24054
24055THREE.ShaderChunk[ 'logdepthbuf_pars_vertex' ] = "#ifdef USE_LOGDEPTHBUF\n	#ifdef USE_LOGDEPTHBUF_EXT\n		varying float vFragDepth;\n	#endif\n	uniform float logDepthBufFC;\n#endif";
24056
24057// File:src/renderers/shaders/ShaderChunk/logdepthbuf_vertex.glsl
24058
24059THREE.ShaderChunk[ 'logdepthbuf_vertex' ] = "#ifdef USE_LOGDEPTHBUF\n	gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;\n	#ifdef USE_LOGDEPTHBUF_EXT\n		vFragDepth = 1.0 + gl_Position.w;\n	#else\n		gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;\n	#endif\n#endif\n";
24060
24061// File:src/renderers/shaders/ShaderChunk/map_fragment.glsl
24062
24063THREE.ShaderChunk[ 'map_fragment' ] = "#ifdef USE_MAP\n	vec4 texelColor = texture2D( map, vUv );\n	texelColor = mapTexelToLinear( texelColor );\n	diffuseColor *= texelColor;\n#endif\n";
24064
24065// File:src/renderers/shaders/ShaderChunk/map_pars_fragment.glsl
24066
24067THREE.ShaderChunk[ 'map_pars_fragment' ] = "#ifdef USE_MAP\n	uniform sampler2D map;\n#endif\n";
24068
24069// File:src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl
24070
24071THREE.ShaderChunk[ 'map_particle_fragment' ] = "#ifdef USE_MAP\n	vec4 mapTexel = texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) * offsetRepeat.zw + offsetRepeat.xy );\n	diffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n";
24072
24073// File:src/renderers/shaders/ShaderChunk/map_particle_pars_fragment.glsl
24074
24075THREE.ShaderChunk[ 'map_particle_pars_fragment' ] = "#ifdef USE_MAP\n	uniform vec4 offsetRepeat;\n	uniform sampler2D map;\n#endif\n";
24076
24077// File:src/renderers/shaders/ShaderChunk/metalnessmap_fragment.glsl
24078
24079THREE.ShaderChunk[ 'metalnessmap_fragment' ] = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n	vec4 texelMetalness = texture2D( metalnessMap, vUv );\n	metalnessFactor *= texelMetalness.r;\n#endif\n";
24080
24081// File:src/renderers/shaders/ShaderChunk/metalnessmap_pars_fragment.glsl
24082
24083THREE.ShaderChunk[ 'metalnessmap_pars_fragment' ] = "#ifdef USE_METALNESSMAP\n	uniform sampler2D metalnessMap;\n#endif";
24084
24085// File:src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl
24086
24087THREE.ShaderChunk[ 'morphnormal_vertex' ] = "#ifdef USE_MORPHNORMALS\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#endif\n";
24088
24089// File:src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl
24090
24091THREE.ShaderChunk[ 'morphtarget_pars_vertex' ] = "#ifdef USE_MORPHTARGETS\n	#ifndef USE_MORPHNORMALS\n	uniform float morphTargetInfluences[ 8 ];\n	#else\n	uniform float morphTargetInfluences[ 4 ];\n	#endif\n#endif";
24092
24093// File:src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl
24094
24095THREE.ShaderChunk[ 'morphtarget_vertex' ] = "#ifdef USE_MORPHTARGETS\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	#ifndef USE_MORPHNORMALS\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	#endif\n#endif\n";
24096
24097// File:src/renderers/shaders/ShaderChunk/normal_fragment.glsl
24098
24099THREE.ShaderChunk[ 'normal_fragment' ] = "#ifdef FLAT_SHADED\n	vec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n	vec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n	vec3 normal = normalize( cross( fdx, fdy ) );\n#else\n	vec3 normal = normalize( vNormal );\n	#ifdef DOUBLE_SIDED\n		normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );
24099\n	#endif\n#endif\n#ifdef USE_NORMALMAP\n	normal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n	normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n";
24100
24101// File:src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl
24102
24103THREE.ShaderChunk[ 'normalmap_pars_fragment' ] = "#ifdef USE_NORMALMAP\n	uniform sampler2D normalMap;\n	uniform vec2 normalScale;\n	vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\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		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		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#endif\n";
24104
24105// File:src/renderers/shaders/ShaderChunk/packing.glsl
24106
24107THREE.ShaderChunk[ 'packing' ] = "vec3 packNormalToRGB( const in vec3 normal ) {\n  return normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n  return 1.0 - 2.0 * rgb.xyz;\n}\nvec4 packDepthToRGBA( const in float value ) {\n	const vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );\n	const vec4 bit_mask = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );\n	vec4 res = mod( value * bit_shift * vec4( 255 ), vec4( 256 ) ) / vec4( 255 );\n	res -= res.xxyz * bit_mask;\n	return res;\n}\nfloat unpackRGBAToDepth( const in vec4 rgba ) {\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	return dot( rgba, bitSh );\n}\nfloat viewZToOrthoDepth( const in float viewZ, const in float near, const in float far ) {\n  return ( viewZ + near ) / ( near - far );\n}\nfloat OrthoDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n  return linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n  return (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n  return ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n";
24108
24109// File:src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl
24110
24111THREE.ShaderChunk[ 'premultiplied_alpha_fragment' ] = "#ifdef PREMULTIPLIED_ALPHA\n	gl_FragColor.rgb *= gl_FragColor.a;\n#endif\n";
24112
24113// File:src/renderers/shaders/ShaderChunk/project_vertex.glsl
24114
24115THREE.ShaderChunk[ 'project_vertex' ] = "#ifdef USE_SKINNING\n	vec4 mvPosition = modelViewMatrix * skinned;\n#else\n	vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\n#endif\ngl_Position = projectionMatrix * mvPosition;\n";
24116
24117// File:src/renderers/shaders/ShaderChunk/roughnessmap_fragment.glsl
24118
24119THREE.ShaderChunk[ 'roughnessmap_fragment' ] = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n	vec4 texelRoughness = texture2D( roughnessMap, vUv );\n	roughnessFactor *= texelRoughness.r;\n#endif\n";
24120
24121// File:src/renderers/shaders/ShaderChunk/roughnessmap_pars_fragment.glsl
24122
24123THREE.ShaderChunk[ 'roughnessmap_pars_fragment' ] = "#ifdef USE_ROUGHNESSMAP\n	uniform sampler2D roughnessMap;\n#endif";
24124
24125// File:src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl
24126
24127THREE.ShaderChunk[ 'shadowmap_pars_fragment' ] = "#ifdef USE_SHADOWMAP\n	#if NUM_DIR_LIGHTS > 0\n		uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n		varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n	#endif\n	#if NUM_SPOT_LIGHTS > 0\n		uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n		varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n	#endif\n	#if NUM_POINT_LIGHTS > 0\n		uniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n		varying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n	#endif\n	float texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n		return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n	}\n	float texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n		const vec2 offset = vec2( 0.0, 1.0 );\n		vec2 texelSize = vec2( 1.0 ) / size;\n		vec2 centroidUV = floor( uv * size + 0.5 ) / size;\n		float lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n		float lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n		float rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n		float rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n		vec2 f = fract( uv * size + 0.5 );\n		float a = mix( lb, lt, f.y );\n		float b = mix( rb, rt, f.y );\n		float c = mix( a, b, f.x );\n		return c;\n	}\n	float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n		shadowCoord.xyz /= shadowCoord.w;\n		shadowCoord.z += shadowBias;\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		bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n		bool frustumTest = all( frustumTestVec );\n		if ( frustumTest ) {\n		#if defined( SHADOWMAP_TYPE_PCF )\n			vec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n			float dx0 = - texelSize.x * shadowRadius;\n			float dy0 = - texelSize.y * shadowRadius;\n			float dx1 = + texelSize.x * shadowRadius;\n			float dy1 = + texelSize.y * shadowRadius;\n			return (\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n			) * ( 1.0 / 9.0 );\n		#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n			vec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n			float dx0 = - texelSize.x * shadowRadius;\n			float dy0 = - texelSize.y * shadowRadius;\n			float dx1 = + texelSize.x * shadowRadius;\n			float dy1 = + texelSize.y * shadowRadius;\n			return (\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n			) * ( 1.0 / 9.0 );\n		#else\n			return texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n		#endif\n		}\n		return 1.0;\n	}\n	vec2 cubeToUV( vec3 v, float texelSizeY ) {\n		vec3 absV = abs( v );\n		float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n		absV *= scaleToCube;\n		v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n		vec2 planar = v.xy;\n		float almostATexel = 1.5 * texelSizeY;\n		float almostOne = 1.0 - almostATexel;\n		if ( absV.z >= almostOne ) {\n			if ( v.z > 0.0 )\n				planar.x = 4.0 - v.x;\n		} else if ( absV.x >= almostOne ) {\n			float signX = sign( v.x );\n			planar.x = v.z * signX + 2.0 * signX;\n		} else if ( absV.y >= almostOne ) {\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		return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n	}\n	float getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n		vec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n		vec3 lightToPosition = shadowCoord.xyz;\n		vec3 bd3D = normalize( lightToPosition );\n		float dp = ( length( lightToPosition ) - shadowBias ) / 1000.0;\n		#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n			vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n			return (\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n			) * ( 1.0 / 9.0 );\n		#else\n			return texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n		#endif\n	}\n#endif\n";
24128
24129// File:src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl
24130
24131THREE.ShaderChunk[ 'shadowmap_pars_vertex' ] = "#ifdef USE_SHADOWMAP\n	#if NUM_DIR_LIGHTS > 0\n		uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n		varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];
24131\n	#endif\n	#if NUM_SPOT_LIGHTS > 0\n		uniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n		varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n	#endif\n	#if NUM_POINT_LIGHTS > 0\n		uniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n		varying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n	#endif\n#endif\n";
24132
24133// File:src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl
24134
24135THREE.ShaderChunk[ 'shadowmap_vertex' ] = "#ifdef USE_SHADOWMAP\n	#if NUM_DIR_LIGHTS > 0\n	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n		vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n	}\n	#endif\n	#if NUM_SPOT_LIGHTS > 0\n	for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n		vSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n	}\n	#endif\n	#if NUM_POINT_LIGHTS > 0\n	for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n		vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n	}\n	#endif\n#endif\n";
24136
24137// File:src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl
24138
24139THREE.ShaderChunk[ 'shadowmask_pars_fragment' ] = "float getShadowMask() {\n	float shadow = 1.0;\n	#ifdef USE_SHADOWMAP\n	#if NUM_DIR_LIGHTS > 0\n	DirectionalLight directionalLight;\n	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n		directionalLight = directionalLights[ i ];\n		shadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n	}\n	#endif\n	#if NUM_SPOT_LIGHTS > 0\n	SpotLight spotLight;\n	for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n		spotLight = spotLights[ i ];\n		shadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n	}\n	#endif\n	#if NUM_POINT_LIGHTS > 0\n	PointLight pointLight;\n	for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n		pointLight = pointLights[ i ];\n		shadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ] ) : 1.0;\n	}\n	#endif\n	#endif\n	return shadow;\n}\n";
24140
24141// File:src/renderers/shaders/ShaderChunk/skinbase_vertex.glsl
24142
24143THREE.ShaderChunk[ 'skinbase_vertex' ] = "#ifdef USE_SKINNING\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#endif";
24144
24145// File:src/renderers/shaders/ShaderChunk/skinning_pars_vertex.glsl
24146
24147THREE.ShaderChunk[ 'skinning_pars_vertex' ] = "#ifdef USE_SKINNING\n	uniform mat4 bindMatrix;\n	uniform mat4 bindMatrixInverse;\n	#ifdef BONE_TEXTURE\n		uniform sampler2D boneTexture;\n		uniform int boneTextureWidth;\n		uniform int boneTextureHeight;\n		mat4 getBoneMatrix( const in float i ) {\n			float j = i * 4.0;\n			float x = mod( j, float( boneTextureWidth ) );\n			float y = floor( j / float( boneTextureWidth ) );\n			float dx = 1.0 / float( boneTextureWidth );\n			float dy = 1.0 / float( boneTextureHeight );\n			y = dy * ( y + 0.5 );\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			mat4 bone = mat4( v1, v2, v3, v4 );\n			return bone;\n		}\n	#else\n		uniform mat4 boneMatrices[ MAX_BONES ];\n		mat4 getBoneMatrix( const in float i ) {\n			mat4 bone = boneMatrices[ int(i) ];\n			return bone;\n		}\n	#endif\n#endif\n";
24148
24149// File:src/renderers/shaders/ShaderChunk/skinning_vertex.glsl
24150
24151THREE.ShaderChunk[ 'skinning_vertex' ] = "#ifdef USE_SKINNING\n	vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\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#endif\n";
24152
24153// File:src/renderers/shaders/ShaderChunk/skinnormal_vertex.glsl
24154
24155THREE.ShaderChunk[ 'skinnormal_vertex' ] = "#ifdef USE_SKINNING\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;
24155\n	skinMatrix  = bindMatrixInverse * skinMatrix * bindMatrix;\n	objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n";
24156
24157// File:src/renderers/shaders/ShaderChunk/specularmap_fragment.glsl
24158
24159THREE.ShaderChunk[ 'specularmap_fragment' ] = "float specularStrength;\n#ifdef USE_SPECULARMAP\n	vec4 texelSpecular = texture2D( specularMap, vUv );\n	specularStrength = texelSpecular.r;\n#else\n	specularStrength = 1.0;\n#endif";
24160
24161// File:src/renderers/shaders/ShaderChunk/specularmap_pars_fragment.glsl
24162
24163THREE.ShaderChunk[ 'specularmap_pars_fragment' ] = "#ifdef USE_SPECULARMAP\n	uniform sampler2D specularMap;\n#endif";
24164
24165// File:src/renderers/shaders/ShaderChunk/tonemapping_fragment.glsl
24166
24167THREE.ShaderChunk[ 'tonemapping_fragment' ] = "#if defined( TONE_MAPPING )\n  gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n";
24168
24169// File:src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl
24170
24171THREE.ShaderChunk[ 'tonemapping_pars_fragment' ] = "#define saturate(a) clamp( a, 0.0, 1.0 )\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n  return toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n  color *= toneMappingExposure;\n  return saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n  color *= toneMappingExposure;\n  return saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n  color *= toneMappingExposure;\n  color = max( vec3( 0.0 ), color - 0.004 );\n  return pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n";
24172
24173// File:src/renderers/shaders/ShaderChunk/uv2_pars_fragment.glsl
24174
24175THREE.ShaderChunk[ 'uv2_pars_fragment' ] = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n	varying vec2 vUv2;\n#endif";
24176
24177// File:src/renderers/shaders/ShaderChunk/uv2_pars_vertex.glsl
24178
24179THREE.ShaderChunk[ 'uv2_pars_vertex' ] = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n	attribute vec2 uv2;\n	varying vec2 vUv2;\n#endif";
24180
24181// File:src/renderers/shaders/ShaderChunk/uv2_vertex.glsl
24182
24183THREE.ShaderChunk[ 'uv2_vertex' ] = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n	vUv2 = uv2;\n#endif";
24184
24185// File:src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl
24186
24187THREE.ShaderChunk[ 'uv_pars_fragment' ] = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n	varying vec2 vUv;\n#endif";
24188
24189// File:src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl
24190
24191THREE.ShaderChunk[ 'uv_pars_vertex' ] = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n	varying vec2 vUv;\n	uniform vec4 offsetRepeat;\n#endif\n";
24192
24193// File:src/renderers/shaders/ShaderChunk/uv_vertex.glsl
24194
24195THREE.ShaderChunk[ 'uv_vertex' ] = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n	vUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n#endif";
24196
24197// File:src/renderers/shaders/ShaderChunk/worldpos_vertex.glsl
24198
24199THREE.ShaderChunk[ 'worldpos_vertex' ] = "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( PHYSICAL ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n	#ifdef USE_SKINNING\n		vec4 worldPosition = modelMatrix * skinned;\n	#else\n		vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n	#endif\n#endif\n";
24200
24201// File:src/renderers/shaders/UniformsUtils.js
24202
24203/**
24204 * Uniform Utilities
24205 */
24206
24207THREE.UniformsUtils = {
24208
24209    merge: function ( uniforms ) {
24210
24211        var merged = {};
24212
24213        for ( var u = 0; u < uniforms.length; u ++ ) {
24214
24215            var tmp = this.clone( uniforms[ u ] );
24216
24217            for ( var p in tmp ) {
24218
24219                merged[ p ] = tmp[ p ];
24220
24221            }
24222
24223        }
24224
24225        return merged;
24226
24227    },
24228
24229    clone: function ( uniforms_src ) {
24230
24231        var uniforms_dst = {};
24232
24233        for ( var u in uniforms_src ) {
24234
24235            uniforms_dst[ u ] = {};
24236
24237            for ( var p in uniforms_src[ u ] ) {
24238
24239                var parameter_src = uniforms_src[ u ][ p ];
24240
24241                if ( parameter_src instanceof THREE.Color ||
24242                    parameter_src instanceof THREE.Vector2 ||
24243                    parameter_src instanceof THREE.Vector3 ||
24244                    parameter_src instanceof THREE.Vector4 ||
24245                    parameter_src instanceof THREE.Matrix3 ||
24246                    parameter_src instanceof THREE.Matrix4 ||
24247                    parameter_src instanceof THREE.Texture ) {
24248
24249                    uniforms_dst[ u ][ p ] = parameter_src.clone();
24250
24251                } else if ( Array.isArray( parameter_src ) ) {
24252
24253                    uniforms_dst[ u ][ p ] = parameter_src.slice();
24254
24255                } else {
24256
24257                    uniforms_dst[ u ][ p ] = parameter_src;
24258
24259                }
24260
24261            }
24262
24263        }
24264
24265        return uniforms_dst;
24266
24267    }
24268
24269};
24270
24271// File:src/renderers/shaders/UniformsLib.js
24272
24273/**
24274 * Uniforms library for shared webgl shaders
24275 */
24276
24277THREE.UniformsLib = {
24278
24279    common: {
24280
24281        "diffuse": { type: "c", value: new THREE.Color( 0xeeeeee ) },
24282        "opacity": { type: "1f", value: 1.0 },
24283
24284        "map": { type: "t", value: null },
24285        "offsetRepeat": { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
24286
24287        "specularMap": { type: "t", value: null },
24288        "alphaMap": { type: "t", value: null },
24289
24290        "envMap": { type: "t", value: null },
24291        "flipEnvMap": { type: "1f", value: - 1 },
24292        "reflectivity": { type: "1f", value: 1.0 },
24293        "refractionRatio": { type: "1f", value: 0.98 }
24294
24295    },
24296
24297    aomap: {
24298
24299        "aoMap": { type: "t", value: null },
24300        "aoMapIntensity": { type: "1f", value: 1 }
24301
24302    },
24303
24304    lightmap: {
24305
24306        "lightMap": { type: "t", value: null },
24307        "lightMapIntensity": { type: "1f", value: 1 }
24308
24309    },
24310
24311    emissivemap: {
24312
24313        "emissiveMap": { type: "t", value: null }
24314
24315    },
24316
24317    bumpmap: {
24318
24319        "bumpMap": { type: "t", value: null },
24320        "bumpScale": { type: "1f", value: 1 }
24321
24322    },
24323
24324    normalmap: {
24325
24326        "normalMap": { type: "t", value: null },
24327        "normalScale": { type: "v2", value: new THREE.Vector2( 1, 1 ) }
24328
24329    },
24330
24331    displacementmap: {
24332
24333        "displacementMap": { type: "t", value: null },
24334        "displacementScale": { type: "1f", value: 1 },
24335        "displacementBias": { type: "1f", value: 0 }
24336
24337    },
24338
24339    roughnessmap: {
24340
24341        "roughnessMap": { type: "t", value: null }
24342
24343    },
24344
24345    metalnessmap: {
24346
24347        "metalnessMap": { type: "t", value: null }
24348
24349    },
24350
24351    fog: {
24352
24353        "fogDensity": { type: "1f", value: 0.00025 },
24354        "fogNear": { type: "1f", value: 1 },
24355        "fogFar": { type: "1f", value: 2000 },
24356        "fogColor": { type: "c", value: new THREE.Color( 0xffffff ) }
24357
24358    },
24359
24360    lights: {
24361
24362        "ambientLightColor": { type: "3fv", value: [] },
24363
24364        "directionalLights": { type: "sa", value: [], properties: {
24365            "direction": { type: "v3" },
24366            "color": { type: "c" },
24367
24368            "shadow": { type: "1i" },
24369            "shadowBias": { type: "1f" },
24370            "shadowRadius": { type: "1f" },
24371            "shadowMapSize": { type: "v2" }
24372        } },
24373
24374        "directionalShadowMap": { type: "tv", value: [] },
24375        "directionalShadowMatrix": { type: "m4v", value: [] },
24376
24377        "spotLights": { type: "sa", value: [], properties: {
24378            "color": { type: "c" },
24379            "position": { type: "v3" },
24380            "direction": { type: "v3" },
24381            "distance": { type: "1f" },
24382            "coneCos": { type: "1f" },
24383            "penumbraCos": { type: "1f" },
24384            "decay": { type: "1f" },
24385
24386            "shadow": { type: "1i" },
24387            "shadowBias": { type: "1f" },
24388            "shadowRadius": { type: "1f" },
24389            "shadowMapSize": { type: "v2" }
24390        } },
24391
24392        "spotShadowMap": { type: "tv", value: [] },
24393        "spotShadowMatrix": { type: "m4v", value: [] },
24394
24395        "pointLights": { type: "sa", value: [], properties: {
24396            "color": { type: "c" },
24397            "position": { type: "v3" },
24398            "decay": { type: "1f" },
24399            "distance": { type: "1f" },
24400
24401            "shadow": { type: "1i" },
24402            "shadowBias": { type: "1f" },
24403            "shadowRadius": { type: "1f" },
24404            "shadowMapSize": { type: "v2" }
24405        } },
24406
24407        "pointShadowMap": { type: "tv", value: [] },
24408        "pointShadowMatrix": { type: "m4v", value: [] },
24409
24410        "hemisphereLights": { type: "sa", value: [], properties: {
24411            "direction": { type: "v3" },
24412            "skyColor": { type: "c" },
24413            "groundColor": { type: "c" }
24414        } }
24415
24416    },
24417
24418    points: {
24419
24420        "diffuse": { type: "c", value: new THREE.Color( 0xeeeeee ) },
24421        "opacity": { type: "1f", value: 1.0 },
24422        "size": { type: "1f", value: 1.0 },
24423        "scale": { type: "1f", value: 1.0 },
24424        "map": { type: "t", value: null },
24425        "offsetRepeat": { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) }
24426
24427    }
24428
24429};
24430
24431// File:src/renderers/shaders/ShaderLib/cube_frag.glsl
24432
24433THREE.ShaderChunk[ 'cube_frag' ] = "uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	gl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n	#include <logdepthbuf_fragment>\n}\n";
24434
24435// File:src/renderers/shaders/ShaderLib/cube_vert.glsl
24436
24437THREE.ShaderChunk[ 'cube_vert' ] = "varying vec3 vWorldPosition;\n#include <common>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	vWorldPosition = transformDirection( position, modelMatrix );\n	#include <begin_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n}\n";
24438
24439// File:src/renderers/shaders/ShaderLib/depth_frag.glsl
24440
24441THREE.ShaderChunk[ 'depth_frag' ] = "#if DEPTH_PACKING == 3200\n	uniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec4 diffuseColor = vec4( 1.0 );\n	#if DEPTH_PACKING == 3200\n		diffuseColor.a = opacity;\n	#endif\n	#include <map_fragment>\n	#include <alphamap_fragment>\n	#include <alphatest_fragment>\n	#include <logdepthbuf_fragment>\n	#if DEPTH_PACKING == 3200\n		gl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n	#elif DEPTH_PACKING == 3201\n		gl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n	#endif\n}\n";
24442
24443// File:src/renderers/shaders/ShaderLib/depth_vert.glsl
24444
24445THREE.ShaderChunk[ 'depth_vert' ] = "#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <uv_vertex>\n	#include <skinbase_vertex>\n	#include <begin_vertex>\n	#include <displacementmap_vertex>\n	#include <morphtarget_vertex>\n	#include <skinning_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n}\n";
24446
24447// File:src/renderers/shaders/ShaderLib/distanceRGBA_frag.glsl
24448
24449THREE.ShaderChunk[ 'distanceRGBA_frag' ] = "uniform vec3 lightPos;\nvarying vec4 vWorldPosition;\n#include <common>\n#include <packing>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n	#include <clipping_planes_fragment>\n	gl_FragColor = packDepthToRGBA( length( vWorldPosition.xyz - lightPos.xyz ) / 1000.0 );\n}\n";
24450
24451// File:src/renderers/shaders/ShaderLib/distanceRGBA_vert.glsl
24452
24453THREE.ShaderChunk[ 'distanceRGBA_vert' ] = "varying vec4 vWorldPosition;\n#include <common>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <skinbase_vertex>\n	#include <begin_vertex>\n	#include <morphtarget_vertex>\n	#include <skinning_vertex>\n	#include <project_vertex>\n	#include <worldpos_vertex>\n	#include <clipping_planes_vertex>\n	vWorldPosition = worldPosition;\n}\n";
24454
24455// File:src/renderers/shaders/ShaderLib/equirect_frag.glsl
24456
24457THREE.ShaderChunk[ 'equirect_frag' ] = "uniform sampler2D tEquirect;\nuniform float tFlip;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec3 direction = normalize( vWorldPosition );\n	vec2 sampleUV;
24457\n	sampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );\n	sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n	gl_FragColor = texture2D( tEquirect, sampleUV );\n	#include <logdepthbuf_fragment>\n}\n";
24458
24459// File:src/renderers/shaders/ShaderLib/equirect_vert.glsl
24460
24461THREE.ShaderChunk[ 'equirect_vert' ] = "varying vec3 vWorldPosition;\n#include <common>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	vWorldPosition = transformDirection( position, modelMatrix );\n	#include <begin_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n}\n";
24462
24463// File:src/renderers/shaders/ShaderLib/linedashed_frag.glsl
24464
24465THREE.ShaderChunk[ 'linedashed_frag' ] = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	if ( mod( vLineDistance, totalSize ) > dashSize ) {\n		discard;\n	}\n	vec3 outgoingLight = vec3( 0.0 );\n	vec4 diffuseColor = vec4( diffuse, opacity );\n	#include <logdepthbuf_fragment>\n	#include <color_fragment>\n	outgoingLight = diffuseColor.rgb;\n	gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n	#include <premultiplied_alpha_fragment>\n	#include <tonemapping_fragment>\n	#include <encodings_fragment>\n	#include <fog_fragment>\n}\n";
24466
24467// File:src/renderers/shaders/ShaderLib/linedashed_vert.glsl
24468
24469THREE.ShaderChunk[ 'linedashed_vert' ] = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <color_vertex>\n	vLineDistance = scale * lineDistance;\n	vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n	gl_Position = projectionMatrix * mvPosition;\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n}\n";
24470
24471// File:src/renderers/shaders/ShaderLib/meshbasic_frag.glsl
24472
24473THREE.ShaderChunk[ 'meshbasic_frag' ] = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n	varying vec3 vNormal;\n#endif\n#include <common>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec4 diffuseColor = vec4( diffuse, opacity );\n	#include <logdepthbuf_fragment>\n	#include <map_fragment>\n	#include <color_fragment>\n	#include <alphamap_fragment>\n	#include <alphatest_fragment>\n	#include <specularmap_fragment>\n	ReflectedLight reflectedLight;\n	reflectedLight.directDiffuse = vec3( 0.0 );\n	reflectedLight.directSpecular = vec3( 0.0 );\n	reflectedLight.indirectDiffuse = diffuseColor.rgb;\n	reflectedLight.indirectSpecular = vec3( 0.0 );\n	#include <aomap_fragment>\n	vec3 outgoingLight = reflectedLight.indirectDiffuse;\n	#include <envmap_fragment>\n	gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n	#include <premultiplied_alpha_fragment>\n	#include <tonemapping_fragment>\n	#include <encodings_fragment>\n	#include <fog_fragment>\n}\n";
24474
24475// File:src/renderers/shaders/ShaderLib/meshbasic_vert.glsl
24476
24477THREE.ShaderChunk[ 'meshbasic_vert' ] = "#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <uv_vertex>\n	#include <uv2_vertex>\n	#include <color_vertex>\n	#include <skinbase_vertex>\n	#ifdef USE_ENVMAP\n	#include <beginnormal_vertex>\n	#include <morphnormal_vertex>\n	#include <skinnormal_vertex>\n	#include <defaultnormal_vertex>\n	#endif\n	#include <begin_vertex>\n	#include <morphtarget_vertex>\n	#include <skinning_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <worldpos_vertex>\n	#include <clipping_planes_vertex>\n	#include <envmap_vertex>\n}\n";
24478
24479// File:src/renderers/shaders/ShaderLib/meshlambert_frag.glsl
24480
24481THREE.ShaderChunk[ 'meshlambert_frag' ] = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n	varying vec3 vLightBack;\n#endif\n#include <common>\n#include <packing>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <bsdfs>\n#include <lights_pars>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec4 diffuseColor = vec4( diffuse, opacity );\n	ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n	vec3 totalEmissiveRadiance = emissive;\n	#include <logdepthbuf_fragment>\n	#include <map_fragment>\n	#include <color_fragment>\n	#include <alphamap_fragment>\n	#include <alphatest_fragment>\n	#include <specularmap_fragment>\n	#include <emissivemap_fragment>\n	reflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n	#include <lightmap_fragment>\n	reflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n	#ifdef DOUBLE_SIDED\n		reflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n	#else\n		reflectedLight.directDiffuse = vLightFront;\n	#endif\n	reflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n	#include <aomap_fragment>\n	vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n	#include <envmap_fragment>\n	gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n	#include <premultiplied_alpha_fragment>\n	#include <tonemapping_fragment>\n	#include <encodings_fragment>\n	#include <fog_fragment>\n}\n";
24482
24483// File:src/renderers/shaders/ShaderLib/meshlambert_vert.glsl
24484
24485THREE.ShaderChunk[ 'meshlambert_vert' ] = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n	varying vec3 vLightBack;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <bsdfs>\n#include <lights_pars>\n#include <color_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <uv_vertex>\n	#include <uv2_vertex>\n	#include <color_vertex>\n	#include <beginnormal_vertex>\n	#include <morphnormal_vertex>\n	#include <skinbase_vertex>\n	#include <skinnormal_vertex>\n	#include <defaultnormal_vertex>\n	#include <begin_vertex>\n	#include <morphtarget_vertex>\n	#include <skinning_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n	#include <worldpos_vertex>\n	#include <envmap_vertex>\n	#include <lights_lambert_vertex>\n	#include <shadowmap_vertex>\n}\n";
24486
24487// File:src/renderers/shaders/ShaderLib/meshphong_frag.glsl
24488
24489THREE.ShaderChunk[ 'meshphong_frag' ] = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec4 diffuseColor = vec4( diffuse, opacity );\n	ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n	vec3 totalEmissiveRadiance = emissive;\n	#include <logdepthbuf_fragment>\n	#include <map_fragment>\n	#include <color_fragment>\n	#include <alphamap_fragment>\n	#include <alphatest_fragment>\n	#include <specularmap_fragment>\n	#include <normal_fragment>\n	#include <emissivemap_fragment>\n	#include <lights_phong_fragment>\n	#include <lights_template>\n	#include <aomap_fragment>\n	vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n	#include <envmap_fragment>\n	gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n	#include <premultiplied_alpha_fragment>\n	#include <tonemapping_fragment>\n	#include <encodings_fragment>\n	#include <fog_fragment>\n}\n";
24490
24491// File:src/renderers/shaders/ShaderLib/meshphong_vert.glsl
24492
24493THREE.ShaderChunk[ 'meshphong_vert' ] = "#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n	varying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <uv_vertex>\n	#include <uv2_vertex>\n	#include <color_vertex>\n	#include <beginnormal_vertex>\n	#include <morphnormal_vertex>\n	#include <skinbase_vertex>\n	#include <skinnormal_vertex>\n	#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n	vNormal = normalize( transformedNormal );\n#endif\n	#include <begin_vertex>\n	#include <displacementmap_vertex>\n	#include <morphtarget_vertex>\n	#include <skinning_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n	vViewPosition = - mvPosition.xyz;\n	#include <worldpos_vertex>\n	#include <envmap_vertex>\n	#include <shadowmap_vertex>\n}\n";
24494
24495// File:src/renderers/shaders/ShaderLib/meshphysical_frag.glsl
24496
24497THREE.ShaderChunk[ 'meshphysical_frag' ] = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\nuniform float envMapIntensity;\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n	varying vec3 vNormal;\n#endif\n#include <common>\n#include <packing>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <lights_pars>\n#include <lights_physical_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec4 diffuseColor = vec4( diffuse, opacity );\n	ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n	vec3 totalEmissiveRadiance = emissive;\n	#include <logdepthbuf_fragment>\n	#include <map_fragment>\n	#include <color_fragment>\n	#include <alphamap_fragment>\n	#include <alphatest_fragment>\n	#include <specularmap_fragment>\n	#include <roughnessmap_fragment>\n	#include <metalnessmap_fragment>\n	#include <normal_fragment>\n	#include <emissivemap_fragment>\n	#include <lights_physical_fragment>\n	#include <lights_template>\n	#include <aomap_fragment>\n	vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n	gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n	#include <premultiplied_alpha_fragment>\n	#include <tonemapping_fragment>\n	#include <encodings_fragment>\n	#include <fog_fragment>\n}\n";
24498
24499// File:src/renderers/shaders/ShaderLib/meshphysical_vert.glsl
24500
24501THREE.ShaderChunk[ 'meshphysical_vert' ] = "#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n	varying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <uv_vertex>\n	#include <uv2_vertex>\n	#include <color_vertex>\n	#include <beginnormal_vertex>\n	#include <morphnormal_vertex>\n	#include <skinbase_vertex>\n	#include <skinnormal_vertex>\n	#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n	vNormal = normalize( transformedNormal );\n#endif\n	#include <begin_vertex>\n	#include <displacementmap_vertex>\n	#include <morphtarget_vertex>\n	#include <skinning_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n	vViewPosition = - mvPosition.xyz;\n	#include <worldpos_vertex>\n	#include <shadowmap_vertex>\n}\n";
24502
24503// File:src/renderers/shaders/ShaderLib/normal_frag.glsl
24504
24505THREE.ShaderChunk[ 'normal_frag' ] = "uniform float opacity;\nvarying vec3 vNormal;\n#include <common>\n#include <packing>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	gl_FragColor = vec4( packNormalToRGB( vNormal ), opacity );\n	#include <logdepthbuf_fragment>\n}\n";
24506
24507// File:src/renderers/shaders/ShaderLib/normal_vert.glsl
24508
24509THREE.ShaderChunk[ 'normal_vert' ] = "varying vec3 vNormal;\n#include <common>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	vNormal = normalize( normalMatrix * normal );\n	#include <begin_vertex>\n	#include <morphtarget_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n}\n";
24510
24511// File:src/renderers/shaders/ShaderLib/points_frag.glsl
24512
24513THREE.ShaderChunk[ 'points_frag' ] = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec3 outgoingLight = vec3( 0.0 );\n	vec4 diffuseColor = vec4( diffuse, opacity );\n	#include <logdepthbuf_fragment>\n	#include <map_particle_fragment>\n	#include <color_fragment>\n	#include <alphatest_fragment>\n	outgoingLight = diffuseColor.rgb;\n	gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n	#include <premultiplied_alpha_fragment>\n	#include <tonemapping_fragment>\n	#include <encodings_fragment>\n	#include <fog_fragment>\n}\n";
24514
24515// File:src/renderers/shaders/ShaderLib/points_vert.glsl
24516
24517THREE.ShaderChunk[ 'points_vert' ] = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <color_vertex>\n	#include <begin_vertex>\n	#include <project_vertex>\n	#ifdef USE_SIZEATTENUATION\n		gl_PointSize = si
24517ze * ( scale / - mvPosition.z );\n	#else\n		gl_PointSize = size;\n	#endif\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n	#include <worldpos_vertex>\n	#include <shadowmap_vertex>\n}\n";
24518
24519// File:src/renderers/shaders/ShaderLib.js
24520
24521/**
24522 * Webgl Shader Library for three.js
24523 *
24524 * @author alteredq / http://alteredqualia.com/
24525 * @author mrdoob / http://mrdoob.com/
24526 * @author mikael emtinger / http://gomo.se/
24527 */
24528
24529
24530THREE.ShaderLib = {
24531
24532    'basic': {
24533
24534        uniforms: THREE.UniformsUtils.merge( [
24535
24536            THREE.UniformsLib[ 'common' ],
24537            THREE.UniformsLib[ 'aomap' ],
24538            THREE.UniformsLib[ 'fog' ]
24539
24540        ] ),
24541
24542        vertexShader: THREE.ShaderChunk[ 'meshbasic_vert' ],
24543        fragmentShader: THREE.ShaderChunk[ 'meshbasic_frag' ]
24544
24545    },
24546
24547    'lambert': {
24548
24549        uniforms: THREE.UniformsUtils.merge( [
24550
24551            THREE.UniformsLib[ 'common' ],
24552            THREE.UniformsLib[ 'aomap' ],
24553            THREE.UniformsLib[ 'lightmap' ],
24554            THREE.UniformsLib[ 'emissivemap' ],
24555            THREE.UniformsLib[ 'fog' ],
24556            THREE.UniformsLib[ 'lights' ],
24557
24558            {
24559                "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) }
24560            }
24561
24562        ] ),
24563
24564        vertexShader: THREE.ShaderChunk[ 'meshlambert_vert' ],
24565        fragmentShader: THREE.ShaderChunk[ 'meshlambert_frag' ]
24566
24567    },
24568
24569    'phong': {
24570
24571        uniforms: THREE.UniformsUtils.merge( [
24572
24573            THREE.UniformsLib[ 'common' ],
24574            THREE.UniformsLib[ 'aomap' ],
24575            THREE.UniformsLib[ 'lightmap' ],
24576            THREE.UniformsLib[ 'emissivemap' ],
24577            THREE.UniformsLib[ 'bumpmap' ],
24578            THREE.UniformsLib[ 'normalmap' ],
24579            THREE.UniformsLib[ 'displacementmap' ],
24580            THREE.UniformsLib[ 'fog' ],
24581            THREE.UniformsLib[ 'lights' ],
24582
24583            {
24584                "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
24585                "specular" : { type: "c", value: new THREE.Color( 0x111111 ) },
24586                "shininess": { type: "1f", value: 30 }
24587            }
24588
24589        ] ),
24590
24591        vertexShader: THREE.ShaderChunk[ 'meshphong_vert' ],
24592        fragmentShader: THREE.ShaderChunk[ 'meshphong_frag' ]
24593
24594    },
24595
24596    'standard': {
24597
24598        uniforms: THREE.UniformsUtils.merge( [
24599
24600            THREE.UniformsLib[ 'common' ],
24601            THREE.UniformsLib[ 'aomap' ],
24602            THREE.UniformsLib[ 'lightmap' ],
24603            THREE.UniformsLib[ 'emissivemap' ],
24604            THREE.UniformsLib[ 'bumpmap' ],
24605            THREE.UniformsLib[ 'normalmap' ],
24606            THREE.UniformsLib[ 'displacementmap' ],
24607            THREE.UniformsLib[ 'roughnessmap' ],
24608            THREE.UniformsLib[ 'metalnessmap' ],
24609            THREE.UniformsLib[ 'fog' ],
24610            THREE.UniformsLib[ 'lights' ],
24611
24612            {
24613                "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
24614                "roughness": { type: "1f", value: 0.5 },
24615                "metalness": { type: "1f", value: 0 },
24616                "envMapIntensity" : { type: "1f", value: 1 } // temporary
24617            }
24618
24619        ] ),
24620
24621        vertexShader: THREE.ShaderChunk[ 'meshphysical_vert' ],
24622        fragmentShader: THREE.ShaderChunk[ 'meshphysical_frag' ]
24623
24624    },
24625
24626    'points': {
24627
24628        uniforms: THREE.UniformsUtils.merge( [
24629
24630            THREE.UniformsLib[ 'points' ],
24631            THREE.UniformsLib[ 'fog' ]
24632
24633        ] ),
24634
24635        vertexShader: THREE.ShaderChunk[ 'points_vert' ],
24636        fragmentShader: THREE.ShaderChunk[ 'points_frag' ]
24637
24638    },
24639
24640    'dashed': {
24641
24642        uniforms: THREE.UniformsUtils.merge( [
24643
24644            THREE.UniformsLib[ 'common' ],
24645            THREE.UniformsLib[ 'fog' ],
24646
24647            {
24648                "scale"    : { type: "1f", value: 1 },
24649                "dashSize" : { type: "1f", value: 1 },
24650                "totalSize": { type: "1f", value: 2 }
24651            }
24652
24653        ] ),
24654
24655        vertexShader: THREE.ShaderChunk[ 'linedashed_vert' ],
24656        fragmentShader: THREE.ShaderChunk[ 'linedashed_frag' ]
24657
24658    },
24659
24660    'depth': {
24661
24662        uniforms: THREE.UniformsUtils.merge( [
24663
24664            THREE.UniformsLib[ 'common' ],
24665            THREE.UniformsLib[ 'displacementmap' ]
24666
24667        ] ),
24668
24669        vertexShader: THREE.ShaderChunk[ 'depth_vert' ],
24670        fragmentShader: THREE.ShaderChunk[ 'depth_frag' ]
24671
24672    },
24673
24674    'normal': {
24675
24676        uniforms: {
24677
24678            "opacity" : { type: "1f", value: 1.0 }
24679
24680        },
24681
24682        vertexShader: THREE.ShaderChunk[ 'normal_vert' ],
24683        fragmentShader: THREE.ShaderChunk[ 'normal_frag' ]
24684
24685    },
24686
24687    /* -------------------------------------------------------------------------
24688     //	Cube map shader
24689     ------------------------------------------------------------------------- */
24690
24691    'cube': {
24692
24693        uniforms: {
24694            "tCube": { type: "t", value: null },
24695            "tFlip": { type: "1f", value: - 1 }
24696        },
24697
24698        vertexShader: THREE.ShaderChunk[ 'cube_vert' ],
24699        fragmentShader: THREE.ShaderChunk[ 'cube_frag' ]
24700
24701    },
24702
24703    /* -------------------------------------------------------------------------
24704     //	Cube map shader
24705     ------------------------------------------------------------------------- */
24706
24707    'equirect': {
24708
24709        uniforms: {
24710            "tEquirect": { type: "t", value: null },
24711            "tFlip": { type: "1f", value: - 1 }
24712        },
24713
24714        vertexShader: THREE.ShaderChunk[ 'equirect_vert' ],
24715        fragmentShader: THREE.ShaderChunk[ 'equirect_frag' ]
24716
24717    },
24718
24719    'distanceRGBA': {
24720
24721        uniforms: {
24722
24723            "lightPos": { type: "v3", value: new THREE.Vector3() }
24724
24725        },
24726
24727        vertexShader: THREE.ShaderChunk[ 'distanceRGBA_vert' ],
24728        fragmentShader: THREE.ShaderChunk[ 'distanceRGBA_frag' ]
24729
24730    }
24731
24732};
24733
24734THREE.ShaderLib[ 'physical' ] = {
24735
24736    uniforms: THREE.UniformsUtils.merge( [
24737
24738        THREE.ShaderLib[ 'standard' ].uniforms,
24739
24740        {
24741            // future
24742        }
24743
24744    ] ),
24745
24746    vertexShader: THREE.ShaderChunk[ 'meshphysical_vert' ],
24747    fragmentShader: THREE.ShaderChunk[ 'meshphysical_frag' ]
24748
24749};
24750
24751
24752// File:src/renderers/WebGLRenderer.js
24753
24754/**
24755 * @author supereggbert / http://www.paulbrunt.co.uk/
24756 * @author mrdoob / http://mrdoob.com/
24757 * @author alteredq / http://alteredqualia.com/
24758 * @author szimek / https://github.com/szimek/
24759 * @author tschw
24760 */
24761
24762THREE.WebGLRenderer = function ( parameters ) {
24763
24764    console.log( 'THREE.WebGLRenderer', THREE.REVISION );
24765
24766    parameters = parameters || {};
24767
24768    var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
24769        _context = parameters.context !== undefined ? parameters.context : null,
24770
24771        _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
24772        _depth = parameters.depth !== undefined ? parameters.depth : true,
24773        _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
24774        _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
24775        _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
24776        _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false;
24777
24778    var lights = [];
24779
24780    var opaqueObjects = [];
24781    var opaqueObjectsLastIndex = - 1;
24782    var transparentObjects = [];
24783    var transparentObjectsLastIndex = - 1;
24784
24785    var morphInfluences = new Float32Array( 8 );
24786
24787    var sprites = [];
24788    var lensFlares = [];
24789
24790    // public properties
24791
24792    this.domElement = _canvas;
24793    this.context = null;
24794
24795    // clearing
24796
24797    this.autoClear = true;
24798    this.autoClearColor = true;
24799    this.autoClearDepth = true;
24800    this.autoClearStencil = true;
24801
24802    // scene graph
24803
24804    this.sortObjects = true;
24805
24806    // user-defined clipping
24807
24808    this.clippingPlanes = [];
24809    this.localClippingEnabled = false;
24810
24811    // physically based shading
24812
24813    this.gammaFactor = 2.0;	// for backwards compatibility
24814    this.gammaInput = false;
24815    this.gammaOutput = false;
24816
24817    // physical lights
24818
24819    this.physicallyCorrectLights = false;
24820
24821    // tone mapping
24822
24823    this.toneMapping = THREE.LinearToneMapping;
24824    this.toneMappingExposure = 1.0;
24825    this.toneMappingWhitePoint = 1.0;
24826
24827    // morphs
24828
24829    this.maxMorphTargets = 8;
24830    this.maxMorphNormals = 4;
24831
24832    // flags
24833
24834    this.autoScaleCubemaps = true;
24835
24836    // internal properties
24837
24838    var _this = this,
24839
24840    // internal state cache
24841
24842        _currentProgram = null,
24843        _currentRenderTarget = null,
24844        _currentFramebuffer = null,
24845        _currentMaterialId = - 1,
24846        _currentGeometryProgram = '',
24847        _currentCamera = null,
24848
24849        _currentScissor = new THREE.Vector4(),
24850        _currentScissorTest = null,
24851
24852        _currentViewport = new THREE.Vector4(),
24853
24854    //
24855
24856        _usedTextureUnits = 0,
24857
24858    //
24859
24860        _clearColor = new THREE.Color( 0x000000 ),
24861        _clearAlpha = 0,
24862
24863        _width = _canvas.width,
24864        _height = _canvas.height,
24865
24866        _pixelRatio = 1,
24867
24868        _scissor = new THREE.Vector4( 0, 0, _width, _height ),
24869        _scissorTest = false,
24870
24871        _viewport = new THREE.Vector4( 0, 0, _width, _height ),
24872
24873    // frustum
24874
24875        _frustum = new THREE.Frustum(),
24876
24877    // clipping
24878
24879        _clippingEnabled = false,
24880        _localClippingEnabled = false,
24881        _clipRenderingShadows = false,
24882
24883        _numClippingPlanes = 0,
24884        _clippingPlanesUniform = {
24885            type: '4fv', value: null, needsUpdate: false },
24886
24887        _globalClippingState = null,
24888        _numGlobalClippingPlanes = 0,
24889
24890        _matrix3 = new THREE.Matrix3(),
24891        _sphere = new THREE.Sphere(),
24892        _plane = new THREE.Plane(),
24893
24894
24895    // camera matrices cache
24896
24897        _projScreenMatrix = new THREE.Matrix4(),
24898
24899        _vector3 = new THREE.Vector3(),
24900
24901    // light arrays cache
24902
24903        _lights = {
24904
24905            hash: '',
24906
24907            ambient: [ 0, 0, 0 ],
24908            directional: [],
24909            directionalShadowMap: [],
24910            directionalShadowMatrix: [],
24911            spot: [],
24912            spotShadowMap: [],
24913            spotShadowMatrix: [],
24914            point: [],
24915            pointShadowMap: [],
24916            pointShadowMatrix: [],
24917            hemi: [],
24918
24919            shadows: []
24920
24921        },
24922
24923    // info
24924
24925        _infoMemory = {
24926
24927            geometries: 0,
24928            textures: 0
24929
24930        },
24931
24932        _infoRender = {
24933
24934            calls: 0,
24935            vertices: 0,
24936            faces: 0,
24937            points: 0
24938
24939        };
24940
24941    this.info = {
24942
24943        render: _infoRender,
24944        memory: _infoMemory,
24945        programs: null
24946
24947    };
24948
24949
24950    // initialize
24951
24952    var _gl;
24953
24954    try {
24955
24956        var attributes = {
24957            alpha: _alpha,
24958            depth: _depth,
24959            stencil: _stencil,
24960            antialias: _antialias,
24961            premultipliedAlpha: _premultipliedAlpha,
24962            preserveDrawingBuffer: _preserveDrawingBuffer
24963        };
24964
24965        _gl = _context || _canvas.getContext( 'webgl', attributes ) || _canvas.getContext( 'experimental-webgl', attributes );
24966
24967        if ( _gl === null ) {
24968
24969            if ( _canvas.getContext( 'webgl' ) !== null ) {
24970
24971                throw 'Error creating WebGL context with your selected attributes.';
24972
24973            } else {
24974
24975                throw 'Error creating WebGL context.';
24976
24977            }
24978
24979        }
24980
24981        // Some experimental-webgl implementations do not have getShaderPrecisionFormat
24982
24983        if ( _gl.getShaderPrecisionFormat === undefined ) {
24984
24985            _gl.getShaderPrecisionFormat = function () {
24986
24987                return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
24988
24989            };
24990
24991        }
24992
24993        _canvas.addEventListener( 'webglcontextlost', onContextLost, false );
24994
24995    } catch ( error ) {
24996
24997        console.error( 'THREE.WebGLRenderer: ' + error );
24998
24999    }
25000
25001    var _isWebGL2 = (typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext);
25002    var extensions = new THREE.WebGLExtensions( _gl );
25003
25004    extensions.get( 'WEBGL_depth_texture' );
25005    extensions.get( 'OES_texture_float' );
25006    extensions.get( 'OES_texture_float_linear' );
25007    extensions.get( 'OES_texture_half_float' );
25008    extensions.get( 'OES_texture_half_float_linear' );
25009    extensions.get( 'OES_standard_derivatives' );
25010    extensions.get( 'ANGLE_instanced_arrays' );
25011
25012    if ( extensions.get( 'OES_element_index_uint' ) ) {
25013
25014        THREE.BufferGeometry.MaxIndex = 4294967296;
25015
25016    }
25017
25018    var capabilities = new THREE.WebGLCapabilities( _gl, extensions, parameters );
25019
25020    var state = new THREE.WebGLState( _gl, extensions, paramThreeToGL );
25021    var properties = new THREE.WebGLProperties();
25022    var objects = new THREE.WebGLObjects( _gl, properties, this.info );
25023    var programCache = new THREE.WebGLPrograms( this, capabilities );
25024    var lightCache = new THREE.WebGLLights();
25025
25026    this.info.programs = programCache.programs;
25027
25028    var bufferRenderer = new THREE.WebGLBufferRenderer( _gl, extensions, _infoRender );
25029    var indexedBufferRenderer = new THREE.WebGLIndexedBufferRenderer( _gl, extensions, _infoRender );
25030
25031    //
25032
25033    function getTargetPixelRatio() {
25034
25035        return _currentRenderTarget === null ? _pixelRatio : 1;
25036
25037    }
25038
25039    function glClearColor( r, g, b, a ) {
25040
25041        if ( _premultipliedAlpha === true ) {
25042
25043            r *= a; g *= a; b *= a;
25044
25045        }
25046
25047        state.clearColor( r, g, b, a );
25048
25049    }
25050
25051    function setDefaultGLState() {
25052
25053        state.init();
25054
25055        state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
25056        state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
25057
25058        glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
25059
25060    }
25061
25062    function resetGLState() {
25063
25064        _currentProgram = null;
25065        _currentCamera = null;
25066
25067        _currentGeometryProgram = '';
25068        _currentMaterialId = - 1;
25069
25070        state.reset();
25071
25072    }
25073
25074    setDefaultGLState();
25075
25076    this.context = _gl;
25077    this.capabilities = capabilities;
25078    this.extensions = extensions;
25079    this.properties = properties;
25080    this.state = state;
25081
25082    // shadow map
25083
25084    var shadowMap = new THREE.WebGLShadowMap( this, _lights, objects );
25085
25086    this.shadowMap = shadowMap;
25087
25088
25089    // Plugins
25090
25091    var spritePlugin = new THREE.SpritePlugin( this, sprites );
25092    var lensFlarePlugin = new THREE.LensFlarePlugin( this, lensFlares );
25093
25094    // API
25095
25096    this.getContext = function () {
25097
25098        return _gl;
25099
25100    };
25101
25102    this.getContextAttributes = function () {
25103
25104        return _gl.getContextAttributes();
25105
25106    };
25107
25108    this.forceContextLoss = function () {
25109
25110        extensions.get( 'WEBGL_lose_context' ).loseContext();
25111
25112    };
25113
25114    this.getMaxAnisotropy = ( function () {
25115
25116        var value;
25117
25118        return function getMaxAnisotropy() {
25119
25120            if ( value !== undefined ) return value;
25121
25122            var extension = extensions.get( 'EXT_texture_filter_anisotropic' );
25123
25124            if ( extension !== null ) {
25125
25126                value = _gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
25127
25128            } else {
25129
25130                value = 0;
25131
25132            }
25133
25134            return value;
25135
25136        };
25137
25138    } )();
25139
25140    this.getPrecision = function () {
25141
25142        return capabilities.precision;
25143
25144    };
25145
25146    this.getPixelRatio = function () {
25147
25148        return _pixelRatio;
25149
25150    };
25151
25152    this.setPixelRatio = function ( value ) {
25153
25154        if ( value === undefined ) return;
25155
25156        _pixelRatio = value;
25157
25158        this.setSize( _viewport.z, _viewport.w, false );
25159
25160    };
25161
25162    this.getSize = function () {
25163
25164        return {
25165            width: _width,
25166            height: _height
25167        };
25168
25169    };
25170
25171    this.setSize = function ( width, height, updateStyle ) {
25172
25173        _width = width;
25174        _height = height;
25175
25176        _canvas.width = width * _pixelRatio;
25177        _canvas.height = height * _pixelRatio;
25178
25179        if ( updateStyle !== false ) {
25180
25181            _canvas.style.width = width + 'px';
25182            _canvas.style.height = height + 'px';
25183
25184        }
25185
25186        this.setViewport( 0, 0, width, height );
25187
25188    };
25189
25190    this.setViewport = function ( x, y, width, height ) {
25191
25192        state.viewport( _viewport.set( x, y, width, height ) );
25193
25194    };
25195
25196    this.setScissor = function ( x, y, width, height ) {
25197
25198        state.scissor( _scissor.set( x, y, width, height ) );
25199
25200    };
25201
25202    this.setScissorTest = function ( boolean ) {
25203
25204        state.setScissorTest( _scissorTest = boolean );
25205
25206    };
25207
25208    // Clearing
25209
25210    this.getClearColor = function () {
25211
25212        return _clearColor;
25213
25214    };
25215
25216    this.setClearColor = function ( color, alpha ) {
25217
25218        _clearColor.set( color );
25219
25220        _clearAlpha = alpha !== undefined ? alpha : 1;
25221
25222        glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
25223
25224    };
25225
25226    this.getClearAlpha = function () {
25227
25228        return _clearAlpha;
25229
25230    };
25231
25232    this.setClearAlpha = function ( alpha ) {
25233
25234        _clearAlpha = alpha;
25235
25236        glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
25237
25238    };
25239
25240    this.clear = function ( color, depth, stencil ) {
25241
25242        var bits = 0;
25243
25244        if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
25245        if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
25246        if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
25247
25248        _gl.clear( bits );
25249
25250    };
25251
25252    this.clearColor = function () {
25253
25254        this.clear( true, false, false );
25255
25256    };
25257
25258    this.clearDepth = function () {
25259
25260        this.clear( false, true, false );
25261
25262    };
25263
25264    this.clearStencil = function () {
25265
25266        this.clear( false, false, true );
25267
25268    };
25269
25270    this.clearTarget = function ( renderTarget, color, depth, stencil ) {
25271
25272        this.setRenderTarget( renderTarget );
25273        this.clear( color, depth, stencil );
25274
25275    };
25276
25277    // Reset
25278
25279    this.resetGLState = resetGLState;
25280
25281    this.dispose = function() {
25282
25283        _canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
25284
25285    };
25286
25287    // Events
25288
25289    function onContextLost( event ) {
25290
25291        event.preventDefault();
25292
25293        resetGLState();
25294        setDefaultGLState();
25295
25296        properties.clear();
25297
25298    }
25299
25300    function onTextureDispose( event ) {
25301
25302        var texture = event.target;
25303
25304        texture.removeEventListener( 'dispose', onTextureDispose );
25305
25306        deallocateTexture( texture );
25307
25308        _infoMemory.textures --;
25309
25310
25311    }
25312
25313    function onRenderTargetDispose( event ) {
25314
25315        var renderTarget = event.target;
25316
25317        renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
25318
25319        deallocateRenderTarget( renderTarget );
25320
25321        _infoMemory.textures --;
25322
25323    }
25324
25325    function onMaterialDispose( event ) {
25326
25327        var material = event.target;
25328
25329        material.removeEventListener( 'dispose', onMaterialDispose );
25330
25331        deallocateMaterial( material );
25332
25333    }
25334
25335    // Buffer deallocation
25336
25337    function deallocateTexture( texture ) {
25338
25339        var textureProperties = properties.get( texture );
25340
25341        if ( texture.image && textureProperties.__image__webglTextureCube ) {
25342
25343            // cube texture
25344
25345            _gl.deleteTexture( textureProperties.__image__webglTextureCube );
25346
25347        } else {
25348
25349            // 2D texture
25350
25351            if ( textureProperties.__webglInit === undefined ) return;
25352
25353            _gl.deleteTexture( textureProperties.__webglTexture );
25354
25355        }
25356
25357        // remove all webgl properties
25358        properties.delete( texture );
25359
25360    }
25361
25362    function deallocateRenderTarget( renderTarget ) {
25363
25364        var renderTargetProperties = properties.get( renderTarget );
25365        var textureProperties = properties.get( renderTarget.texture );
25366
25367        if ( ! renderTarget ) return;
25368
25369        if ( textureProperties.__webglTexture !== undefined ) {
25370
25371            _gl.deleteTexture( textureProperties.__webglTexture );
25372
25373        }
25374
25375        if ( renderTarget.depthTexture ) {
25376
25377            renderTarget.depthTexture.dispose();
25378
25379        }
25380
25381        if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
25382
25383            for ( var i = 0; i < 6; i ++ ) {
25384
25385                _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
25386                if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
25387
25388            }
25389
25390        } else {
25391
25392            _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
25393            if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
25394
25395        }
25396
25397        properties.delete( renderTarget.texture );
25398        properties.delete( renderTarget );
25399
25400    }
25401
25402    function deallocateMaterial( material ) {
25403
25404        releaseMaterialProgramReference( material );
25405
25406        properties.delete( material );
25407
25408    }
25409
25410
25411    function releaseMaterialProgramReference( material ) {
25412
25413        var programInfo = properties.get( material ).program;
25414
25415        material.program = undefined;
25416
25417        if ( programInfo !== undefined ) {
25418
25419            programCache.releaseProgram( programInfo );
25420
25421        }
25422
25423    }
25424
25425    // Buffer rendering
25426
25427    this.renderBufferImmediate = function ( object, program, material ) {
25428
25429        state.initAttributes();
25430
25431        var buffers = properties.get( object );
25432
25433        if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
25434        if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
25435        if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
25436        if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
25437
25438        var attributes = program.getAttributes();
25439
25440        if ( object.hasPositions ) {
25441
25442            _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );
25443            _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
25444
25445            state.enableAttribute( attributes.position );
25446            _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
25447
25448        }
25449
25450        if ( object.hasNormals ) {
25451
25452            _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal );
25453
25454            if ( material.type !== 'MeshPhongMaterial' && material.type !== 'MeshStandardMaterial' && material.type !== 'MeshPhysicalMaterial' && material.shading === THREE.FlatShading ) {
25455
25456                for ( var i = 0, l = object.count * 3; i < l; i += 9 ) {
25457
25458                    var array = object.normalArray;
25459
25460                    var nx = ( array[ i + 0 ] + array[ i + 3 ] + array[ i + 6 ] ) / 3;
25461                    var ny = ( array[ i + 1 ] + array[ i + 4 ] + array[ i + 7 ] ) / 3;
25462                    var nz = ( array[ i + 2 ] + array[ i + 5 ] + array[ i + 8 ] ) / 3;
25463
25464                    array[ i + 0 ] = nx;
25465                    array[ i + 1 ] = ny;
25466                    array[ i + 2 ] = nz;
25467
25468                    array[ i + 3 ] = nx;
25469                    array[ i + 4 ] = ny;
25470                    array[ i + 5 ] = nz;
25471
25472                    array[ i + 6 ] = nx;
25473                    array[ i + 7 ] = ny;
25474                    array[ i + 8 ] = nz;
25475
25476                }
25477
25478            }
25479
25480            _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
25481
25482            state.enableAttribute( attributes.normal );
25483
25484            _gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
25485
25486        }
25487
25488        if ( object.hasUvs && material.map ) {
25489
25490            _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );
25491            _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
25492
25493            state.enableAttribute( attributes.uv );
25494
25495            _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
25496
25497        }
25498
25499        if ( object.hasColors && material.vertexColors !== THREE.NoColors ) {
25500
25501            _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );
25502            _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
25503
25504            state.enableAttribute( attributes.color );
25505
25506            _gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
25507
25508        }
25509
25510        state.disableUnusedAttributes();
25511
25512        _gl.drawArrays( _gl.TRIANGLES, 0, object.count );
25513
25514        object.count = 0;
25515
25516    };
25517
25518    this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) {
25519
25520        setMaterial( material );
25521
25522        var program = setProgram( camera, fog, material, object );
25523
25524        var updateBuffers = false;
25525        var geometryProgram = geometry.id + '_' + program.id + '_' + material.wireframe;
25526
25527        if ( geometryProgram !== _currentGeometryProgram ) {
25528
25529            _currentGeometryProgram = geometryProgram;
25530            updateBuffers = true;
25531
25532        }
25533
25534        // morph targets
25535
25536        var morphTargetInfluences = object.morphTargetInfluences;
25537
25538        if ( morphTargetInfluences !== undefined ) {
25539
25540            var activeInfluences = [];
25541
25542            for ( var i = 0, l = morphTargetInfluences.length; i < l; i ++ ) {
25543
25544                var influence = morphTargetInfluences[ i ];
25545                activeInfluences.push( [ influence, i ] );
25546
25547            }
25548
25549            activeInfluences.sort( absNumericalSort );
25550
25551            if ( activeInfluences.length > 8 ) {
25552
25553                activeInfluences.length = 8;
25554
25555            }
25556
25557            var morphAttributes = geometry.morphAttributes;
25558
25559            for ( var i = 0, l = activeInfluences.length; i < l; i ++ ) {
25560
25561                var influence = activeInfluences[ i ];
25562                morphInfluences[ i ] = influence[ 0 ];
25563
25564                if ( influence[ 0 ] !== 0 ) {
25565
25566                    var index = influence[ 1 ];
25567
25568                    if ( material.morphTargets === true && morphAttributes.position ) geometry.addAttribute( 'morphTarget' + i, morphAttributes.position[ index ] );
25569                    if ( material.morphNormals === true && morphAttributes.normal ) geometry.addAttribute( 'morphNormal' + i, morphAttributes.normal[ index ] );
25570
25571                } else {
25572
25573                    if ( material.morphTargets === true ) geometry.removeAttribute( 'morphTarget' + i );
25574                    if ( material.morphNormals === true ) geometry.removeAttribute( 'morphNormal' + i );
25575
25576                }
25577
25578            }
25579
25580            program.getUniforms().setValue(
25581                _gl, 'morphTargetInfluences', morphInfluences );
25582
25583            updateBuffers = true;
25584
25585        }
25586
25587        //
25588
25589        var index = geometry.index;
25590        var position = geometry.attributes.position;
25591
25592        if ( material.wireframe === true ) {
25593
25594            index = objects.getWireframeAttribute( geometry );
25595
25596        }
25597
25598        var renderer;
25599
25600        if ( index !== null ) {
25601
25602            renderer = indexedBufferRenderer;
25603            renderer.setIndex( index );
25604
25605        } else {
25606
25607            renderer = bufferRenderer;
25608
25609        }
25610
25611        if ( updateBuffers ) {
25612
25613            setupVertexAttributes( material, program, geometry );
25614
25615            if ( index !== null ) {
25616
25617                _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, objects.getAttributeBuffer( index ) );
25618
25619            }
25620
25621        }
25622
25623        //
25624
25625        var dataStart = 0;
25626        var dataCount = Infinity;
25627
25628        if ( index !== null ) {
25629
25630            dataCount = index.count;
25631
25632        } else if ( position !== undefined ) {
25633
25634            dataCount = position.count;
25635
25636        }
25637
25638        var rangeStart = geometry.drawRange.start;
25639        var rangeCount = geometry.drawRange.count;
25640
25641        var groupStart = group !== null ? group.start : 0;
25642        var groupCount = group !== null ? group.count : Infinity;
25643
25644        var drawStart = Math.max( dataStart, rangeStart, groupStart );
25645        var drawEnd = Math.min( dataStart + dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
25646
25647        var drawCount = Math.max( 0, drawEnd - drawStart + 1 );
25648
25649        //
25650
25651        if ( object instanceof THREE.Mesh ) {
25652
25653            if ( material.wireframe === true ) {
25654
25655                state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
25656                renderer.setMode( _gl.LINES );
25657
25658            } else {
25659
25660                switch ( object.drawMode ) {
25661
25662                    case THREE.TrianglesDrawMode:
25663                        renderer.setMode( _gl.TRIANGLES );
25664                        break;
25665
25666                    case THREE.TriangleStripDrawMode:
25667                        renderer.setMode( _gl.TRIANGLE_STRIP );
25668                        break;
25669
25670                    case THREE.TriangleFanDrawMode:
25671                        renderer.setMode( _gl.TRIANGLE_FAN );
25672                        break;
25673
25674                }
25675
25676            }
25677
25678
25679        } else if ( object instanceof THREE.Line ) {
25680
25681            var lineWidth = material.linewidth;
25682
25683            if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
25684
25685            state.setLineWidth( lineWidth * getTargetPixelRatio() );
25686
25687            if ( object instanceof THREE.LineSegments ) {
25688
25689                renderer.setMode( _gl.LINES );
25690
25691            } else {
25692
25693                renderer.setMode( _gl.LINE_STRIP );
25694
25695            }
25696
25697        } else if ( object instanceof THREE.Points ) {
25698
25699            renderer.setMode( _gl.POINTS );
25700
25701        }
25702
25703        if ( geometry instanceof THREE.InstancedBufferGeometry ) {
25704
25705            if ( geometry.maxInstancedCount > 0 ) {
25706
25707                renderer.renderInstances( geometry, drawStart, drawCount );
25708
25709            }
25710
25711        } else {
25712
25713            renderer.render( drawStart, drawCount );
25714
25715        }
25716
25717    };
25718
25719    function setupVertexAttributes( material, program, geometry, startIndex ) {
25720
25721        var extension;
25722
25723        if ( geometry instanceof THREE.InstancedBufferGeometry ) {
25724
25725            extension = extensions.get( 'ANGLE_instanced_arrays' );
25726
25727            if ( extension === null ) {
25728
25729                console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
25730                return;
25731
25732            }
25733
25734        }
25735
25736        if ( startIndex === undefined ) startIndex = 0;
25737
25738        state.initAttributes();
25739
25740        var geometryAttributes = geometry.attributes;
25741
25742        var programAttributes = program.getAttributes();
25743
25744        var materialDefaultAttributeValues = material.defaultAttributeValues;
25745
25746        for ( var name in programAttributes ) {
25747
25748            var programAttribute = programAttributes[ name ];
25749
25750            if ( programAttribute >= 0 ) {
25751
25752                var geometryAttribute = geometryAttributes[ name ];
25753
25754                if ( geometryAttribute !== undefined ) {
25755
25756                    var type = _gl.FLOAT;
25757                    var array = geometryAttribute.array;
25758                    var normalized = geometryAttribute.normalized;
25759
25760                    if ( array instanceof Float32Array ) {
25761
25762                        type = _gl.FLOAT;
25763
25764                    } else if ( array instanceof Float64Array ) {
25765
25766                        console.warn("Unsupported data buffer format: Float64Array");
25767
25768                    } else if ( array instanceof Uint16Array ) {
25769
25770                        type = _gl.UNSIGNED_SHORT;
25771
25772                    } else if ( array instanceof Int16Array ) {
25773
25774                        type = _gl.SHORT;
25775
25776                    } else if ( array instanceof Uint32Array ) {
25777
25778                        type = _gl.UNSIGNED_INT;
25779
25780                    } else if ( array instanceof Int32Array ) {
25781
25782                        type = _gl.INT;
25783
25784                    } else if ( array instanceof Int8Array ) {
25785
25786                        type = _gl.BYTE;
25787
25788                    } else if ( array instanceof Uint8Array ) {
25789
25790                        type = _gl.UNSIGNED_BYTE;
25791
25792                    }
25793
25794                    var size = geometryAttribute.itemSize;
25795                    var buffer = objects.getAttributeBuffer( geometryAttribute );
25796
25797                    if ( geometryAttribute instanceof THREE.InterleavedBufferAttribute ) {
25798
25799                        var data = geometryAttribute.data;
25800                        var stride = data.stride;
25801                        var offset = geometryAttribute.offset;
25802
25803                        if ( data instanceof THREE.InstancedInterleavedBuffer ) {
25804
25805                            state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute, extension );
25806
25807                            if ( geometry.maxInstancedCount === undefined ) {
25808
25809                                geometry.maxInstancedCount = data.meshPerAttribute * data.count;
25810
25811                            }
25812
25813                        } else {
25814
25815                            state.enableAttribute( programAttribute );
25816
25817                        }
25818
25819                        _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
25820                        _gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * data.array.BYTES_PER_ELEMENT, ( startIndex * stride + offset ) * data.array.BYTES_PER_ELEMENT );
25821
25822                    } else {
25823
25824                        if ( geometryAttribute instanceof THREE.InstancedBufferAttribute ) {
25825
25826                            state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute, extension );
25827
25828                            if ( geometry.maxInstancedCount === undefined ) {
25829
25830                                geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
25831
25832                            }
25833
25834                        } else {
25835
25836                            state.enableAttribute( programAttribute );
25837
25838                        }
25839
25840                        _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
25841                        _gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, startIndex * size * geometryAttribute.array.BYTES_PER_ELEMENT );
25842
25843                    }
25844
25845                } else if ( materialDefaultAttributeValues !== undefined ) {
25846
25847                    var value = materialDefaultAttributeValues[ name ];
25848
25849                    if ( value !== undefined ) {
25850
25851                        switch ( value.length ) {
25852
25853                            case 2:
25854                                _gl.vertexAttrib2fv( programAttribute, value );
25855                                break;
25856
25857                            case 3:
25858                                _gl.vertexAttrib3fv( programAttribute, value );
25859                                break;
25860
25861                            case 4:
25862                                _gl.vertexAttrib4fv( programAttribute, value );
25863                                break;
25864
25865                            default:
25866                                _gl.vertexAttrib1fv( programAttribute, value );
25867
25868                        }
25869
25870                    }
25871
25872                }
25873
25874            }
25875
25876        }
25877
25878        state.disableUnusedAttributes();
25879
25880    }
25881
25882    // Sorting
25883
25884    function absNumericalSort( a, b ) {
25885
25886        return Math.abs( b[ 0 ] ) - Math.abs( a[ 0 ] );
25887
25888    }
25889
25890    function painterSortStable ( a, b ) {
25891
25892        if ( a.object.renderOrder !== b.object.renderOrder ) {
25893
25894            return a.object.renderOrder - b.object.renderOrder;
25895
25896        } else if ( a.material.id !== b.material.id ) {
25897
25898            return a.material.id - b.material.id;
25899
25900        } else if ( a.z !== b.z ) {
25901
25902            return a.z - b.z;
25903
25904        } else {
25905
25906            return a.id - b.id;
25907
25908        }
25909
25910    }
25911
25912    function reversePainterSortStable ( a, b ) {
25913
25914        if ( a.object.renderOrder !== b.object.renderOrder ) {
25915
25916            return a.object.renderOrder - b.object.renderOrder;
25917
25918        } if ( a.z !== b.z ) {
25919
25920            return b.z - a.z;
25921
25922        } else {
25923
25924            return a.id - b.id;
25925
25926        }
25927
25928    }
25929
25930    // Rendering
25931
25932    this.render = function ( scene, camera, renderTarget, forceClear ) {
25933
25934        if ( camera instanceof THREE.Camera === false ) {
25935
25936            console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
25937            return;
25938
25939        }
25940
25941        var fog = scene.fog;
25942
25943        // reset caching for this frame
25944
25945        _currentGeometryProgram = '';
25946        _currentMaterialId = - 1;
25947        _currentCamera = null;
25948
25949        // update scene graph
25950
25951        if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
25952
25953        // update camera matrices and frustum
25954
25955        if ( camera.parent === null ) camera.updateMatrixWorld();
25956
25957        camera.matrixWorldInverse.getInverse( camera.matrixWorld );
25958
25959        _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
25960        _frustum.setFromMatrix( _projScreenMatrix );
25961
25962        lights.length = 0;
25963
25964        opaqueObjectsLastIndex = - 1;
25965        transparentObjectsLastIndex = - 1;
25966
25967        sprites.length = 0;
25968        lensFlares.length = 0;
25969
25970        setupGlobalClippingPlanes( this.clippingPlanes, camera );
25971
25972        projectObject( scene, camera );
25973
25974
25975        opaqueObjects.length = opaqueObjectsLastIndex + 1;
25976        transparentObjects.length = transparentObjectsLastIndex + 1;
25977
25978        if ( _this.sortObjects === true ) {
25979
25980            opaqueObjects.sort( painterSortStable );
25981            transparentObjects.sort( reversePainterSortStable );
25982
25983        }
25984
25985        //
25986
25987        if ( _clippingEnabled ) {
25988
25989            _clipRenderingShadows = true;
25990            setupClippingPlanes( null );
25991
25992        }
25993
25994        setupShadows( lights );
25995
25996        shadowMap.render( scene, camera );
25997
25998        setupLights( lights, camera );
25999
26000        if ( _clippingEnabled ) {
26001
26002            _clipRenderingShadows = false;
26003            resetGlobalClippingState();
26004
26005        }
26006
26007        //
26008
26009        _infoRender.calls = 0;
26010        _infoRender.vertices = 0;
26011        _infoRender.faces = 0;
26012        _infoRender.points = 0;
26013
26014        if ( renderTarget === undefined ) {
26015
26016            renderTarget = null;
26017
26018        }
26019
26020        this.setRenderTarget( renderTarget );
26021
26022        if ( this.autoClear || forceClear ) {
26023
26024            this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil );
26025
26026        }
26027
26028        //
26029
26030        if ( scene.overrideMaterial ) {
26031
26032            var overrideMaterial = scene.overrideMaterial;
26033
26034            renderObjects( opaqueObjects, camera, fog, overrideMaterial );
26035            renderObjects( transparentObjects, camera, fog, overrideMaterial );
26036
26037        } else {
26038
26039            // opaque pass (front-to-back order)
26040
26041            state.setBlending( THREE.NoBlending );
26042            renderObjects( opaqueObjects, camera, fog );
26043
26044            // transparent pass (back-to-front order)
26045
26046            renderObjects( transparentObjects, camera, fog );
26047
26048        }
26049
26050        // custom render plugins (post pass)
26051
26052        spritePlugin.render( scene, camera );
26053        lensFlarePlugin.render( scene, camera, _currentViewport );
26054
26055        // Generate mipmap if we're using any kind of mipmap filtering
26056
26057        if ( renderTarget ) {
26058
26059            var texture = renderTarget.texture;
26060
26061            if ( texture.generateMipmaps && isPowerOfTwo( renderTarget ) &&
26062                texture.minFilter !== THREE.NearestFilter &&
26063                texture.minFilter !== THREE.LinearFilter ) {
26064
26065                updateRenderTargetMipmap( renderTarget );
26066
26067            }
26068
26069        }
26070
26071        // Ensure depth buffer writing is enabled so it can be cleared on next render
26072
26073        state.setDepthTest( true );
26074        state.setDepthWrite( true );
26075        state.setColorWrite( true );
26076
26077        // _gl.finish();
26078
26079    };
26080
26081    function pushRenderItem( object, geometry, material, z, group ) {
26082
26083        var array, index;
26084
26085        // allocate the next position in the appropriate array
26086
26087        if ( material.transparent ) {
26088
26089            array = transparentObjects;
26090            index = ++ transparentObjectsLastIndex;
26091
26092        } else {
26093
26094            array = opaqueObjects;
26095            index = ++ opaqueObjectsLastIndex;
26096
26097        }
26098
26099        // recycle existing render item or grow the array
26100
26101        var renderItem = array[ index ];
26102
26103        if ( renderItem !== undefined ) {
26104
26105            renderItem.id = object.id;
26106            renderItem.object = object;
26107            renderItem.geometry = geometry;
26108            renderItem.material = material;
26109            renderItem.z = _vector3.z;
26110            renderItem.group = group;
26111
26112        } else {
26113
26114            renderItem = {
26115                id: object.id,
26116                object: object,
26117                geometry: geometry,
26118                material: material,
26119                z: _vector3.z,
26120                group: group
26121            };
26122
26123            // assert( index === array.length );
26124            array.push( renderItem );
26125
26126        }
26127
26128    }
26129
26130    function isObjectViewable( object ) {
26131
26132        var geometry = object.geometry;
26133
26134        if ( geometry.boundingSphere === null )
26135            geometry.computeBoundingSphere();
26136
26137        var sphere = _sphere.
26138            copy( geometry.boundingSphere ).
26139            applyMatrix4( object.matrixWorld );
26140
26141        if ( ! _frustum.intersectsSphere( sphere ) ) return false;
26142        if ( _numClippingPlanes === 0 ) return true;
26143
26144        var planes = _this.clippingPlanes,
26145
26146            center = sphere.center,
26147            negRad = - sphere.radius,
26148            i = 0;
26149
26150        do {
26151
26152            // out when deeper than radius in the negative halfspace
26153            if ( planes[ i ].distanceToPoint( center ) < negRad ) return false;
26154
26155        } while ( ++ i !== _numClippingPlanes );
26156
26157        return true;
26158
26159    }
26160
26161    function projectObject( object, camera ) {
26162
26163        if ( object.visible === false ) return;
26164
26165        if ( object.layers.test( camera.layers ) ) {
26166
26167            if ( object instanceof THREE.Light ) {
26168
26169                lights.push( object );
26170
26171            } else if ( object instanceof THREE.Sprite ) {
26172
26173                if ( object.frustumCulled === false || isObjectViewable( object ) === true ) {
26174
26175                    sprites.push( object );
26176
26177                }
26178
26179            } else if ( object instanceof THREE.LensFlare ) {
26180
26181                lensFlares.push( object );
26182
26183            } else if ( object instanceof THREE.ImmediateRenderObject ) {
26184
26185                if ( _this.sortObjects === true ) {
26186
26187                    _vector3.setFromMatrixPosition( object.matrixWorld );
26188                    _vector3.applyProjection( _projScreenMatrix );
26189
26190                }
26191
26192                pushRenderItem( object, null, object.material, _vector3.z, null );
26193
26194            } else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points ) {
26195
26196                if ( object instanceof THREE.SkinnedMesh ) {
26197
26198                    object.skeleton.update();
26199
26200                }
26201
26202                if ( object.frustumCulled === false || isObjectViewable( object ) === true ) {
26203
26204                    var material = object.material;
26205
26206                    if ( material.visible === true ) {
26207
26208                        if ( _this.sortObjects === true ) {
26209
26210                            _vector3.setFromMatrixPosition( object.matrixWorld );
26211                            _vector3.applyProjection( _projScreenMatrix );
26212
26213                        }
26214
26215                        var geometry = objects.update( object );
26216
26217                        if ( material instanceof THREE.MultiMaterial ) {
26218
26219                            var groups = geometry.groups;
26220                            var materials = material.materials;
26221
26222                            for ( var i = 0, l = groups.length; i < l; i ++ ) {
26223
26224                                var group = groups[ i ];
26225                                var groupMaterial = materials[ group.materialIndex ];
26226
26227                                if ( groupMaterial.visible === true ) {
26228
26229                                    pushRenderItem( object, geometry, groupMaterial, _vector3.z, group );
26230
26231                                }
26232
26233                            }
26234
26235                        } else {
26236
26237                            pushRenderItem( object, geometry, material, _vector3.z, null );
26238
26239                        }
26240
26241                    }
26242
26243                }
26244
26245            }
26246
26247        }
26248
26249        var children = object.children;
26250
26251        for ( var i = 0, l = children.length; i < l; i ++ ) {
26252
26253            projectObject( children[ i ], camera );
26254
26255        }
26256
26257    }
26258
26259    function renderObjects( renderList, camera, fog, overrideMaterial ) {
26260
26261        for ( var i = 0, l = renderList.length; i < l; i ++ ) {
26262
26263            var renderItem = renderList[ i ];
26264
26265            var object = renderItem.object;
26266            var geometry = renderItem.geometry;
26267            var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
26268            var group = renderItem.group;
26269
26270            object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
26271            object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
26272
26273            if ( object instanceof THREE.ImmediateRenderObject ) {
26274
26275                setMaterial( material );
26276
26277                var program = setProgram( camera, fog, material, object );
26278
26279                _currentGeometryProgram = '';
26280
26281                object.render( function ( object ) {
26282
26283                    _this.renderBufferImmediate( object, program, material );
26284
26285                } );
26286
26287            } else {
26288
26289                _this.renderBufferDirect( camera, fog, geometry, material, object, group );
26290
26291            }
26292
26293        }
26294
26295    }
26296
26297    function initMaterial( material, fog, object ) {
26298
26299        var materialProperties = properties.get( material );
26300
26301        var parameters = programCache.getParameters(
26302            material, _lights, fog, _numClippingPlanes, object );
26303
26304        var code = programCache.getProgramCode( material, parameters );
26305
26306        var program = materialProperties.program;
26307        var programChange = true;
26308
26309        if ( program === undefined ) {
26310
26311            // new material
26312            material.addEventListener( 'dispose', onMaterialDispose );
26313
26314        } else if ( program.code !== code ) {
26315
26316            // changed glsl or parameters
26317            releaseMaterialProgramReference( material );
26318
26319        } else if ( parameters.shaderID !== undefined ) {
26320
26321            // same glsl and uniform list
26322            return;
26323
26324        } else {
26325
26326            // only rebuild uniform list
26327            programChange = false;
26328
26329        }
26330
26331        if ( programChange ) {
26332
26333            if ( parameters.shaderID ) {
26334
26335                var shader = THREE.ShaderLib[ parameters.shaderID ];
26336
26337                materialProperties.__webglShader = {
26338                    name: material.type,
26339                    uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
26340                    vertexShader: shader.vertexShader,
26341                    fragmentShader: shader.fragmentShader
26342                };
26343
26344            } else {
26345
26346                materialProperties.__webglShader = {
26347                    name: material.type,
26348                    uniforms: material.uniforms,
26349                    vertexShader: material.vertexShader,
26350                    fragmentShader: material.fragmentShader
26351                };
26352
26353            }
26354
26355            material.__webglShader = materialProperties.__webglShader;
26356
26357            program = programCache.acquireProgram( material, parameters, code );
26358
26359            materialProperties.program = program;
26360            material.program = program;
26361
26362        }
26363
26364        var attributes = program.getAttributes();
26365
26366        if ( material.morphTargets ) {
26367
26368            material.numSupportedMorphTargets = 0;
26369
26370            for ( var i = 0; i < _this.maxMorphTargets; i ++ ) {
26371
26372                if ( attributes[ 'morphTarget' + i ] >= 0 ) {
26373
26374                    material.numSupportedMorphTargets ++;
26375
26376                }
26377
26378            }
26379
26380        }
26381
26382        if ( material.morphNormals ) {
26383
26384            material.numSupportedMorphNormals = 0;
26385
26386            for ( var i = 0; i < _this.maxMorphNormals; i ++ ) {
26387
26388                if ( attributes[ 'morphNormal' + i ] >= 0 ) {
26389
26390                    material.numSupportedMorphNormals ++;
26391
26392                }
26393
26394            }
26395
26396        }
26397
26398        var uniforms = materialProperties.__webglShader.uniforms;
26399
26400        if ( ! ( material instanceof THREE.ShaderMaterial ) &&
26401            ! ( material instanceof THREE.RawShaderMaterial ) ||
26402            material.clipping === true ) {
26403
26404            materialProperties.numClippingPlanes = _numClippingPlanes;
26405            uniforms.clippingPlanes = _clippingPlanesUniform;
26406
26407        }
26408
26409        if ( material instanceof THREE.MeshPhongMaterial ||
26410            material instanceof THREE.MeshLambertMaterial ||
26411            material instanceof THREE.MeshStandardMaterial ||
26412            material.lights ) {
26413
26414            // store the light setup it was created for
26415
26416            materialProperties.lightsHash = _lights.hash;
26417
26418            // wire up the material to this renderer's lighting state
26419
26420            uniforms.ambientLightColor.value = _lights.ambient;
26421            uniforms.directionalLights.value = _lights.directional;
26422            uniforms.spotLights.value = _lights.spot;
26423            uniforms.pointLights.value = _lights.point;
26424            uniforms.hemisphereLights.value = _lights.hemi;
26425
26426            uniforms.directionalShadowMap.value = _lights.directionalShadowMap;
26427            uniforms.directionalShadowMatrix.value = _lights.directionalShadowMatrix;
26428            uniforms.spotShadowMap.value = _lights.spotShadowMap;
26429            uniforms.spotShadowMatrix.value = _lights.spotShadowMatrix;
26430            uniforms.pointShadowMap.value = _lights.pointShadowMap;
26431            uniforms.pointShadowMatrix.value = _lights.pointShadowMatrix;
26432
26433        }
26434
26435        var progUniforms = materialProperties.program.getUniforms(),
26436            uniformsList =
26437                THREE.WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
26438
26439        materialProperties.uniformsList = uniformsList;
26440        materialProperties.dynamicUniforms =
26441            THREE.WebGLUniforms.splitDynamic( uniformsList, uniforms );
26442
26443    }
26444
26445    function setMaterial( material ) {
26446
26447        setMaterialFaces( material );
26448
26449        if ( material.transparent === true ) {
26450
26451            state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
26452
26453        } else {
26454
26455            state.setBlending( THREE.NoBlending );
26456
26457        }
26458
26459        state.setDepthFunc( material.depthFunc );
26460        state.setDepthTest( material.depthTest );
26461        state.setDepthWrite( material.depthWrite );
26462        state.setColorWrite( material.colorWrite );
26463        state.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
26464
26465    }
26466
26467    function setMaterialFaces( material ) {
26468
26469        material.side !== THREE.DoubleSide ? state.enable( _gl.CULL_FACE ) : state.disable( _gl.CULL_FACE );
26470        state.setFlipSided( material.side === THREE.BackSide );
26471
26472    }
26473
26474    function setProgram( camera, fog, material, object ) {
26475
26476        _usedTextureUnits = 0;
26477
26478        var materialProperties = properties.get( material );
26479
26480        if ( _clippingEnabled ) {
26481
26482            if ( _localClippingEnabled || camera !== _currentCamera ) {
26483
26484                var useCache =
26485                    camera === _currentCamera &&
26486                    material.id === _currentMaterialId;
26487
26488                // we might want to call this function with some ClippingGroup
26489                // object instead of the material, once it becomes feasible
26490                // (#8465, #8379)
26491                setClippingState(
26492                    material.clippingPlanes, material.clipShadows,
26493                    camera, materialProperties, useCache );
26494
26495            }
26496
26497            if ( materialProperties.numClippingPlanes !== undefined &&
26498                materialProperties.numClippingPlanes !== _numClippingPlanes ) {
26499
26500                material.needsUpdate = true;
26501
26502            }
26503
26504        }
26505
26506        if ( materialProperties.program === undefined ) {
26507
26508            material.needsUpdate = true;
26509
26510        }
26511
26512        if ( materialProperties.lightsHash !== undefined &&
26513            materialProperties.lightsHash !== _lights.hash ) {
26514
26515            material.needsUpdate = true;
26516
26517        }
26518
26519        if ( material.needsUpdate ) {
26520
26521            initMaterial( material, fog, object );
26522            material.needsUpdate = false;
26523
26524        }
26525
26526        var refreshProgram = false;
26527        var refreshMaterial = false;
26528        var refreshLights = false;
26529
26530        var program = materialProperties.program,
26531            p_uniforms = program.getUniforms(),
26532            m_uniforms = materialProperties.__webglShader.uniforms;
26533
26534        if ( program.id !== _currentProgram ) {
26535
26536            _gl.useProgram( program.program );
26537            _currentProgram = program.id;
26538
26539            refreshProgram = true;
26540            refreshMaterial = true;
26541            refreshLights = true;
26542
26543        }
26544
26545        if ( material.id !== _currentMaterialId ) {
26546
26547            _currentMaterialId = material.id;
26548
26549            refreshMaterial = true;
26550
26551        }
26552
26553        if ( refreshProgram || camera !== _currentCamera ) {
26554
26555            p_uniforms.set( _gl, camera, 'projectionMatrix' );
26556
26557            if ( capabilities.logarithmicDepthBuffer ) {
26558
26559                p_uniforms.setValue( _gl, 'logDepthBufFC',
26560                    2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
26561
26562            }
26563
26564
26565            if ( camera !== _currentCamera ) {
26566
26567                _currentCamera = camera;
26568
26569                // lighting uniforms depend on the camera so enforce an update
26570                // now, in case this material supports lights - or later, when
26571                // the next material that does gets activated:
26572
26573                refreshMaterial = true;		// set to true on material change
26574                refreshLights = true;		// remains set until update done
26575
26576            }
26577
26578            // load material specific uniforms
26579            // (shader material also gets them for the sake of genericity)
26580
26581            if ( material instanceof THREE.ShaderMaterial ||
26582                material instanceof THREE.MeshPhongMaterial ||
26583                material instanceof THREE.MeshStandardMaterial ||
26584                material.envMap ) {
26585
26586                var uCamPos = p_uniforms.map.cameraPosition;
26587
26588                if ( uCamPos !== undefined ) {
26589
26590                    uCamPos.setValue( _gl,
26591                        _vector3.setFromMatrixPosition( camera.matrixWorld ) );
26592
26593                }
26594
26595            }
26596
26597            if ( material instanceof THREE.MeshPhongMaterial ||
26598                material instanceof THREE.MeshLambertMaterial ||
26599                material instanceof THREE.MeshBasicMaterial ||
26600                material instanceof THREE.MeshStandardMaterial ||
26601                material instanceof THREE.ShaderMaterial ||
26602                material.skinning ) {
26603
26604                p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
26605
26606            }
26607
26608            p_uniforms.set( _gl, _this, 'toneMappingExposure' );
26609            p_uniforms.set( _gl, _this, 'toneMappingWhitePoint' );
26610
26611        }
26612
26613        // skinning uniforms must be set even if material didn't change
26614        // auto-setting of texture unit for bone texture must go before other textures
26615        // not sure why, but otherwise weird things happen
26616
26617        if ( material.skinning ) {
26618
26619            p_uniforms.setOptional( _gl, object, 'bindMatrix' );
26620            p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
26621
26622            var skeleton = object.skeleton;
26623
26624            if ( skeleton ) {
26625
26626                if ( capabilities.floatVertexTextures && skeleton.useVertexTexture ) {
26627
26628                    p_uniforms.set( _gl, skeleton, 'boneTexture' );
26629                    p_uniforms.set( _gl, skeleton, 'boneTextureWidth' );
26630                    p_uniforms.set( _gl, skeleton, 'boneTextureHeight' );
26631
26632                } else {
26633
26634                    p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );
26635
26636                }
26637
26638            }
26639
26640        }
26641
26642        if ( refreshMaterial ) {
26643
26644            if ( material instanceof THREE.MeshPhongMaterial ||
26645                material instanceof THREE.MeshLambertMaterial ||
26646                material instanceof THREE.MeshStandardMaterial ||
26647                material.lights ) {
26648
26649                // the current material requires lighting info
26650
26651                // note: all lighting uniforms are always set correctly
26652                // they simply reference the renderer's state for their
26653                // values
26654                //
26655                // use the current material's .needsUpdate flags to set
26656                // the GL state when required
26657
26658                markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
26659
26660            }
26661
26662            // refresh uniforms common to several materials
26663
26664            if ( fog && material.fog ) {
26665
26666                refreshUniformsFog( m_uniforms, fog );
26667
26668            }
26669
26670            if ( material instanceof THREE.MeshBasicMaterial ||
26671                material instanceof THREE.MeshLambertMaterial ||
26672                material instanceof THREE.MeshPhongMaterial ||
26673                material instanceof THREE.MeshStandardMaterial ||
26674                material instanceof THREE.MeshDepthMaterial ) {
26675
26676                refreshUniformsCommon( m_uniforms, material );
26677
26678            }
26679
26680            // refresh single material specific uniforms
26681
26682            if ( material instanceof THREE.LineBasicMaterial ) {
26683
26684                refreshUniformsLine( m_uniforms, material );
26685
26686            } else if ( material instanceof THREE.LineDashedMaterial ) {
26687
26688                refreshUniformsLine( m_uniforms, material );
26689                refreshUniformsDash( m_uniforms, material );
26690
26691            } else if ( material instanceof THREE.PointsMaterial ) {
26692
26693                refreshUniformsPoints( m_uniforms, material );
26694
26695            } else if ( material instanceof THREE.MeshLambertMaterial ) {
26696
26697                refreshUniformsLambert( m_uniforms, material );
26698
26699            } else if ( material instanceof THREE.MeshPhongMaterial ) {
26700
26701                refreshUniformsPhong( m_uniforms, material );
26702
26703            } else if ( material instanceof THREE.MeshPhysicalMaterial ) {
26704
26705                refreshUniformsPhysical( m_uniforms, material );
26706
26707            } else if ( material instanceof THREE.MeshStandardMaterial ) {
26708
26709                refreshUniformsStandard( m_uniforms, material );
26710
26711            } else if ( material instanceof THREE.MeshDepthMaterial ) {
26712
26713                if ( material.displacementMap ) {
26714
26715                    m_uniforms.displacementMap.value = material.displacementMap;
26716                    m_uniforms.displacementScale.value = material.displacementScale;
26717                    m_uniforms.displacementBias.value = material.displacementBias;
26718
26719                }
26720
26721            } else if ( material instanceof THREE.MeshNormalMaterial ) {
26722
26723                m_uniforms.opacity.value = material.opacity;
26724
26725            }
26726
26727            THREE.WebGLUniforms.upload(
26728                _gl, materialProperties.uniformsList, m_uniforms, _this );
26729
26730        }
26731
26732
26733        // common matrices
26734
26735        p_uniforms.set( _gl, object, 'modelViewMatrix' );
26736        p_uniforms.set( _gl, object, 'normalMatrix' );
26737        p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
26738
26739
26740        // dynamic uniforms
26741
26742        var dynUniforms = materialProperties.dynamicUniforms;
26743
26744        if ( dynUniforms !== null ) {
26745
26746            THREE.WebGLUniforms.evalDynamic(
26747                dynUniforms, m_uniforms, object, camera );
26748
26749            THREE.WebGLUniforms.upload( _gl, dynUniforms, m_uniforms, _this );
26750
26751        }
26752
26753        return program;
26754
26755    }
26756
26757    // Uniforms (refresh uniforms objects)
26758
26759    function refreshUniformsCommon ( uniforms, material ) {
26760
26761        uniforms.opacity.value = material.opacity;
26762
26763        uniforms.diffuse.value = material.color;
26764
26765        if ( material.emissive ) {
26766
26767            uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
26768
26769        }
26770
26771        uniforms.map.value = material.map;
26772        uniforms.specularMap.value = material.specularMap;
26773        uniforms.alphaMap.value = material.alphaMap;
26774
26775        if ( material.aoMap ) {
26776
26777            uniforms.aoMap.value = material.aoMap;
26778            uniforms.aoMapIntensity.value = material.aoMapIntensity;
26779
26780        }
26781
26782        // uv repeat and offset setting priorities
26783        // 1. color map
26784        // 2. specular map
26785        // 3. normal map
26786        // 4. bump map
26787        // 5. alpha map
26788        // 6. emissive map
26789
26790        var uvScaleMap;
26791
26792        if ( material.map ) {
26793
26794            uvScaleMap = material.map;
26795
26796        } else if ( material.specularMap ) {
26797
26798            uvScaleMap = material.specularMap;
26799
26800        } else if ( material.displacementMap ) {
26801
26802            uvScaleMap = material.displacementMap;
26803
26804        } else if ( material.normalMap ) {
26805
26806            uvScaleMap = material.normalMap;
26807
26808        } else if ( material.bumpMap ) {
26809
26810            uvScaleMap = material.bumpMap;
26811
26812        } else if ( material.roughnessMap ) {
26813
26814            uvScaleMap = material.roughnessMap;
26815
26816        } else if ( material.metalnessMap ) {
26817
26818            uvScaleMap = material.metalnessMap;
26819
26820        } else if ( material.alphaMap ) {
26821
26822            uvScaleMap = material.alphaMap;
26823
26824        } else if ( material.emissiveMap ) {
26825
26826            uvScaleMap = material.emissiveMap;
26827
26828        }
26829
26830        if ( uvScaleMap !== undefined ) {
26831
26832            if ( uvScaleMap instanceof THREE.WebGLRenderTarget ) {
26833
26834                uvScaleMap = uvScaleMap.texture;
26835
26836            }
26837
26838            var offset = uvScaleMap.offset;
26839            var repeat = uvScaleMap.repeat;
26840
26841            uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
26842
26843        }
26844
26845        uniforms.envMap.value = material.envMap;
26846        uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : - 1;
26847
26848        uniforms.reflectivity.value = material.reflectivity;
26849        uniforms.refractionRatio.value = material.refractionRatio;
26850
26851    }
26852
26853    function refreshUniformsLine ( uniforms, material ) {
26854
26855        uniforms.diffuse.value = material.color;
26856        uniforms.opacity.value = material.opacity;
26857
26858    }
26859
26860    function refreshUniformsDash ( uniforms, material ) {
26861
26862        uniforms.dashSize.value = material.dashSize;
26863        uniforms.totalSize.value = material.dashSize + material.gapSize;
26864        uniforms.scale.value = material.scale;
26865
26866    }
26867
26868    function refreshUniformsPoints ( uniforms, material ) {
26869
26870        uniforms.diffuse.value = material.color;
26871        uniforms.opacity.value = material.opacity;
26872        uniforms.size.value = material.size * _pixelRatio;
26873        uniforms.scale.value = _canvas.clientHeight * 0.5;
26874
26875        uniforms.map.value = material.map;
26876
26877        if ( material.map !== null ) {
26878
26879            var offset = material.map.offset;
26880            var repeat = material.map.repeat;
26881
26882            uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
26883
26884        }
26885
26886    }
26887
26888    function refreshUniformsFog ( uniforms, fog ) {
26889
26890        uniforms.fogColor.value = fog.color;
26891
26892        if ( fog instanceof THREE.Fog ) {
26893
26894            uniforms.fogNear.value = fog.near;
26895            uniforms.fogFar.value = fog.far;
26896
26897        } else if ( fog instanceof THREE.FogExp2 ) {
26898
26899            uniforms.fogDensity.value = fog.density;
26900
26901        }
26902
26903    }
26904
26905    function refreshUniformsLambert ( uniforms, material ) {
26906
26907        if ( material.lightMap ) {
26908
26909            uniforms.lightMap.value = material.lightMap;
26910            uniforms.lightMapIntensity.value = material.lightMapIntensity;
26911
26912        }
26913
26914        if ( material.emissiveMap ) {
26915
26916            uniforms.emissiveMap.value = material.emissiveMap;
26917
26918        }
26919
26920    }
26921
26922    function refreshUniformsPhong ( uniforms, material ) {
26923
26924        uniforms.specular.value = material.specular;
26925        uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
26926
26927        if ( material.lightMap ) {
26928
26929            uniforms.lightMap.value = material.lightMap;
26930            uniforms.lightMapIntensity.value = material.lightMapIntensity;
26931
26932        }
26933
26934        if ( material.emissiveMap ) {
26935
26936            uniforms.emissiveMap.value = material.emissiveMap;
26937
26938        }
26939
26940        if ( material.bumpMap ) {
26941
26942            uniforms.bumpMap.value = material.bumpMap;
26943            uniforms.bumpScale.value = material.bumpScale;
26944
26945        }
26946
26947        if ( material.normalMap ) {
26948
26949            uniforms.normalMap.value = material.normalMap;
26950            uniforms.normalScale.value.copy( material.normalScale );
26951
26952        }
26953
26954        if ( material.displacementMap ) {
26955
26956            uniforms.displacementMap.value = material.displacementMap;
26957            uniforms.displacementScale.value = material.displacementScale;
26958            uniforms.displacementBias.value = material.displacementBias;
26959
26960        }
26961
26962    }
26963
26964    function refreshUniformsStandard ( uniforms, material ) {
26965
26966        uniforms.roughness.value = material.roughness;
26967        uniforms.metalness.value = material.metalness;
26968
26969        if ( material.roughnessMap ) {
26970
26971            uniforms.roughnessMap.value = material.roughnessMap;
26972
26973        }
26974
26975        if ( material.metalnessMap ) {
26976
26977            uniforms.metalnessMap.value = material.metalnessMap;
26978
26979        }
26980
26981        if ( material.lightMap ) {
26982
26983            uniforms.lightMap.value = material.lightMap;
26984            uniforms.lightMapIntensity.value = material.lightMapIntensity;
26985
26986        }
26987
26988        if ( material.emissiveMap ) {
26989
26990            uniforms.emissiveMap.value = material.emissiveMap;
26991
26992        }
26993
26994        if ( material.bumpMap ) {
26995
26996            uniforms.bumpMap.value = material.bumpMap;
26997            uniforms.bumpScale.value = material.bumpScale;
26998
26999        }
27000
27001        if ( material.normalMap ) {
27002
27003            uniforms.normalMap.value = material.normalMap;
27004            uniforms.normalScale.value.copy( material.normalScale );
27005
27006        }
27007
27008        if ( material.displacementMap ) {
27009
27010            uniforms.displacementMap.value = material.displacementMap;
27011            uniforms.displacementScale.value = material.displacementScale;
27012            uniforms.displacementBias.value = material.displacementBias;
27013
27014        }
27015
27016        if ( material.envMap ) {
27017
27018            //uniforms.envMap.value = material.envMap; // part of uniforms common
27019            uniforms.envMapIntensity.value = material.envMapIntensity;
27020
27021        }
27022
27023    }
27024
27025    function refreshUniformsPhysical ( uniforms, material ) {
27026
27027        refreshUniformsStandard( uniforms, material );
27028
27029    }
27030
27031    // If uniforms are marked as clean, they don't need to be loaded to the GPU.
27032
27033    function markUniformsLightsNeedsUpdate ( uniforms, value ) {
27034
27035        uniforms.ambientLightColor.needsUpdate = value;
27036
27037        uniforms.directionalLights.needsUpdate = value;
27038        uniforms.pointLights.needsUpdate = value;
27039        uniforms.spotLights.needsUpdate = value;
27040        uniforms.hemisphereLights.needsUpdate = value;
27041
27042    }
27043
27044    // Lighting
27045
27046    function setupShadows ( lights ) {
27047
27048        var lightShadowsLength = 0;
27049
27050        for ( var i = 0, l = lights.length; i < l; i ++ ) {
27051
27052            var light = lights[ i ];
27053
27054            if ( light.castShadow ) {
27055
27056                _lights.shadows[ lightShadowsLength ++ ] = light;
27057
27058            }
27059
27060        }
27061
27062        _lights.shadows.length = lightShadowsLength;
27063
27064    }
27065
27066    function setupLights ( lights, camera ) {
27067
27068        var l, ll, light,
27069            r = 0, g = 0, b = 0,
27070            color,
27071            intensity,
27072            distance,
27073
27074            v
27074iewMatrix = camera.matrixWorldInverse,
27075
27076            directionalLength = 0,
27077            pointLength = 0,
27078            spotLength = 0,
27079            hemiLength = 0;
27080
27081        for ( l = 0, ll = lights.length; l < ll; l ++ ) {
27082
27083            light = lights[ l ];
27084
27085            color = light.color;
27086            intensity = light.intensity;
27087            distance = light.distance;
27088
27089            if ( light instanceof THREE.AmbientLight ) {
27090
27091                r += color.r * intensity;
27092                g += color.g * intensity;
27093                b += color.b * intensity;
27094
27095            } else if ( light instanceof THREE.DirectionalLight ) {
27096
27097                var uniforms = lightCache.get( light );
27098
27099                uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
27100                uniforms.direction.setFromMatrixPosition( light.matrixWorld );
27101                _vector3.setFromMatrixPosition( light.target.matrixWorld );
27102                uniforms.direction.sub( _vector3 );
27103                uniforms.direction.transformDirection( viewMatrix );
27104
27105                uniforms.shadow = light.castShadow;
27106
27107                if ( light.castShadow ) {
27108
27109                    uniforms.shadowBias = light.shadow.bias;
27110                    uniforms.shadowRadius = light.shadow.radius;
27111                    uniforms.shadowMapSize = light.shadow.mapSize;
27112
27113                }
27114
27115                _lights.directionalShadowMap[ directionalLength ] = light.shadow.map;
27116                _lights.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
27117                _lights.directional[ directionalLength ++ ] = uniforms;
27118
27119            } else if ( light instanceof THREE.SpotLight ) {
27120
27121                var uniforms = lightCache.get( light );
27122
27123                uniforms.position.setFromMatrixPosition( light.matrixWorld );
27124                uniforms.position.applyMatrix4( viewMatrix );
27125
27126                uniforms.color.copy( color ).multiplyScalar( intensity );
27127                uniforms.distance = distance;
27128
27129                uniforms.direction.setFromMatrixPosition( light.matrixWorld );
27130                _vector3.setFromMatrixPosition( light.target.matrixWorld );
27131                uniforms.direction.sub( _vector3 );
27132                uniforms.direction.transformDirection( viewMatrix );
27133
27134                uniforms.coneCos = Math.cos( light.angle );
27135                uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
27136                uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
27137
27138                uniforms.shadow = light.castShadow;
27139
27140                if ( light.castShadow ) {
27141
27142                    uniforms.shadowBias = light.shadow.bias;
27143                    uniforms.shadowRadius = light.shadow.radius;
27144                    uniforms.shadowMapSize = light.shadow.mapSize;
27145
27146                }
27147
27148                _lights.spotShadowMap[ spotLength ] = light.shadow.map;
27149                _lights.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
27150                _lights.spot[ spotLength ++ ] = uniforms;
27151
27152            } else if ( light instanceof THREE.PointLight ) {
27153
27154                var uniforms = lightCache.get( light );
27155
27156                uniforms.position.setFromMatrixPosition( light.matrixWorld );
27157                uniforms.position.applyMatrix4( viewMatrix );
27158
27159                uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
27160                uniforms.distance = light.distance;
27161                uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
27162
27163                uniforms.shadow = light.castShadow;
27164
27165                if ( light.castShadow ) {
27166
27167                    uniforms.shadowBias = light.shadow.bias;
27168                    uniforms.shadowRadius = light.shadow.radius;
27169                    uniforms.shadowMapSize = light.shadow.mapSize;
27170
27171                }
27172
27173                _lights.pointShadowMap[ pointLength ] = light.shadow.map;
27174
27175                if ( _lights.pointShadowMatrix[ pointLength ] === undefined ) {
27176
27177                    _lights.pointShadowMatrix[ pointLength ] = new THREE.Matrix4();
27178
27179                }
27180
27181                // for point lights we set the shadow matrix to be a translation-only matrix
27182                // equal to inverse of the light's position
27183                _vector3.setFromMatrixPosition( light.matrixWorld ).negate();
27184                _lights.pointShadowMatrix[ pointLength ].identity().setPosition( _vector3 );
27185
27186                _lights.point[ pointLength ++ ] = uniforms;
27187
27188            } else if ( light instanceof THREE.HemisphereLight ) {
27189
27190                var uniforms = lightCache.get( light );
27191
27192                uniforms.direction.setFromMatrixPosition( light.matrixWorld );
27193                uniforms.direction.transformDirection( viewMatrix );
27194                uniforms.direction.normalize();
27195
27196                uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
27197                uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
27198
27199                _lights.hemi[ hemiLength ++ ] = uniforms;
27200
27201            }
27202
27203        }
27204
27205        _lights.ambient[ 0 ] = r;
27206        _lights.ambient[ 1 ] = g;
27207        _lights.ambient[ 2 ] = b;
27208
27209        _lights.directional.length = directionalLength;
27210        _lights.spot.length = spotLength;
27211        _lights.point.length = pointLength;
27212        _lights.hemi.length = hemiLength;
27213
27214        _lights.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + hemiLength + ',' + _lights.shadows.length;
27215
27216    }
27217
27218    // Clipping
27219
27220    function setupGlobalClippingPlanes( planes, camera ) {
27221
27222        _clippingEnabled =
27223            _this.clippingPlanes.length !== 0 ||
27224            _this.localClippingEnabled ||
27225                // enable state of previous frame - the clipping code has to
27226                // run another frame in order to reset the state:
27227            _numGlobalClippingPlanes !== 0 ||
27228            _localClippingEnabled;
27229
27230        _localClippingEnabled = _this.localClippingEnabled;
27231
27232        _globalClippingState = setupClippingPlanes( planes, camera, 0 );
27233        _numGlobalClippingPlanes = planes !== null ? planes.length : 0;
27234
27235    }
27236
27237    function setupClippingPlanes( planes, camera, dstOffset, skipTransform ) {
27238
27239        var nPlanes = planes !== null ? planes.length : 0,
27240            dstArray = null;
27241
27242        if ( nPlanes !== 0 ) {
27243
27244            dstArray = _clippingPlanesUniform.value;
27245
27246            if ( skipTransform !== true || dstArray === null ) {
27247
27248                var flatSize = dstOffset + nPlanes * 4,
27249                    viewMatrix = camera.matrixWorldInverse,
27250                    viewNormalMatrix = _matrix3.getNormalMatrix( viewMatrix );
27251
27252                if ( dstArray === null || dstArray.length < flatSize ) {
27253
27254                    dstArray = new Float32Array( flatSize );
27255
27256                }
27257
27258                for ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
27259
27260                    var plane = _plane.copy( planes[ i ] ).
27261                        applyMatrix4( viewMatrix, viewNormalMatrix );
27262
27263                    plane.normal.toArray( dstArray, i4 );
27264                    dstArray[ i4 + 3 ] = plane.constant;
27265
27266                }
27267
27268            }
27269
27270            _clippingPlanesUniform.value = dstArray;
27271            _clippingPlanesUniform.needsUpdate = true;
27272
27273        }
27274
27275        _numClippingPlanes = nPlanes;
27276        return dstArray;
27277
27278    }
27279
27280    function resetGlobalClippingState() {
27281
27282        if ( _clippingPlanesUniform.value !== _globalClippingState ) {
27283
27284            _clippingPlanesUniform.value = _globalClippingState;
27285            _clippingPlanesUniform.needsUpdate = _numGlobalClippingPlanes > 0;
27286
27287        }
27288
27289        _numClippingPlanes = _numGlobalClippingPlanes;
27290
27291    }
27292
27293    function setClippingState( planes, clipShadows, camera, cache, fromCache ) {
27294
27295        if ( ! _localClippingEnabled ||
27296            planes === null || planes.length === 0 ||
27297            _clipRenderingShadows && ! clipShadows ) {
27298            // there's no local clipping
27299
27300            if ( _clipRenderingShadows ) {
27301                // there's no global clipping
27302
27303                setupClippingPlanes( null );
27304
27305            } else {
27306
27307                resetGlobalClippingState();
27308            }
27309
27310        } else {
27311
27312            var nGlobal = _clipRenderingShadows ? 0 : _numGlobalClippingPlanes,
27313                lGlobal = nGlobal * 4,
27314
27315                dstArray = cache.clippingState || null;
27316
27317            _clippingPlanesUniform.value = dstArray; // ensure unique state
27318
27319            dstArray = setupClippingPlanes(
27320                planes, camera, lGlobal, fromCache );
27321
27322            for ( var i = 0; i !== lGlobal; ++ i ) {
27323
27324                dstArray[ i ] = _globalClippingState[ i ];
27325
27326            }
27327
27328            cache.clippingState = dstArray;
27329            _numClippingPlanes += nGlobal;
27330
27331        }
27332
27333    }
27334
27335
27336    // GL state setting
27337
27338    this.setFaceCulling = function ( cullFace, frontFaceDirection ) {
27339
27340        if ( cullFace === THREE.CullFaceNone ) {
27341
27342            state.disable( _gl.CULL_FACE );
27343
27344        } else {
27345
27346            if ( frontFaceDirection === THREE.FrontFaceDirectionCW ) {
27347
27348                _gl.frontFace( _gl.CW );
27349
27350            } else {
27351
27352                _gl.frontFace( _gl.CCW );
27353
27354            }
27355
27356            if ( cullFace === THREE.CullFaceBack ) {
27357
27358                _gl.cullFace( _gl.BACK );
27359
27360            } else if ( cullFace === THREE.CullFaceFront ) {
27361
27362                _gl.cullFace( _gl.FRONT );
27363
27364            } else {
27365
27366                _gl.cullFace( _gl.FRONT_AND_BACK );
27367
27368            }
27369
27370            state.enable( _gl.CULL_FACE );
27371
27372        }
27373
27374    };
27375
27376    // Textures
27377
27378    function allocTextureUnit() {
27379
27380        var textureUnit = _usedTextureUnits;
27381
27382        if ( textureUnit >= capabilities.maxTextures ) {
27383
27384            console.warn( 'WebGLRenderer: trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures );
27385
27386        }
27387
27388        _usedTextureUnits += 1;
27389
27390        return textureUnit;
27391
27392    }
27393
27394    function setTextureParameters ( textureType, texture, isPowerOfTwoImage ) {
27395
27396        var extension;
27397
27398        if ( isPowerOfTwoImage ) {
27399
27400            _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
27401            _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
27402
27403            _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
27404            _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
27405
27406        } else {
27407
27408            _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
27409            _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
27410
27411            if ( texture.wrapS !== THREE.ClampToEdgeWrapping || texture.wrapT !== THREE.ClampToEdgeWrapping ) {
27412
27413                console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture );
27414
27415            }
27416
27417            _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
27418            _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
27419
27420            if ( texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter ) {
27421
27422                console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture );
27423
27424            }
27425
27426        }
27427
27428        extension = extensions.get( 'EXT_texture_filter_anisotropic' );
27429
27430        if ( extension ) {
27431
27432            if ( texture.type === THREE.FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
27433            if ( texture.type === THREE.HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return;
27434
27435            if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
27436
27437                _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _this.getMaxAnisotropy() ) );
27438                properties.get( texture ).__currentAnisotropy = texture.anisotropy;
27439
27440            }
27441
27442        }
27443
27444    }
27445
27446    function uploadTexture( textureProperties, texture, slot ) {
27447
27448        if ( textureProperties.__webglInit === undefined ) {
27449
27450            textureProperties.__webglInit = true;
27451
27452            texture.addEventListener( 'dispose', onTextureDispose );
27453
27454            textureProperties.__webglTexture = _gl.createTexture();
27455
27456            _infoMemory.textures ++;
27457
27458        }
27459
27460        state.activeTexture( _gl.TEXTURE0 + slot );
27461        state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
27462
27463        _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
27464        _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
27465        _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
27466
27467        var image = clampToMaxSize( texture.image, capabilities.maxTextureSize );
27468
27469        if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( image ) === false ) {
27470
27471            image = makePowerOfTwo( image );
27472
27473        }
27474
27475        var isPowerOfTwoImage = isPowerOfTwo( image ),
27476            glFormat = paramThreeToGL( texture.format ),
27477            glType = paramThreeToGL( texture.type );
27478
27479        setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage );
27480
27481        var mipmap, mipmaps = texture.mipmaps;
27482
27483        if ( texture instanceof THREE.DepthTexture ) {
27484
27485            // populate depth texture with dummy data
27486
27487            var internalFormat = _gl.DEPTH_COMPONENT;
27488
27489            if ( texture.type === THREE.FloatType ) {
27490
27491                if ( !_isWebGL2 ) throw new Error('Float Depth Texture only supported in WebGL2.0');
27492                internalFormat = _gl.DEPTH_COMPONENT32F;
27493
27494            }
27494 else if ( _isWebGL2 ) {
27495
27496                // WebGL 2.0 requires signed internalformat for glTexImage2D
27497                internalFormat = _gl.DEPTH_COMPONENT16;
27498
27499            }
27500
27501            state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null );
27502
27503        } else if ( texture instanceof THREE.DataTexture ) {
27504
27505            // use manually created mipmaps if available
27506            // if there are no manual mipmaps
27507            // set 0 level mipmap and then use GL to generate other mipmap levels
27508
27509            if ( mipmaps.length > 0 && isPowerOfTwoImage ) {
27510
27511                for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
27512
27513                    mipmap = mipmaps[ i ];
27514                    state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
27515
27516                }
27517
27518                texture.generateMipmaps = false;
27519
27520            } else {
27521
27522                state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
27523
27524            }
27525
27526        } else if ( texture instanceof THREE.CompressedTexture ) {
27527
27528            for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
27529
27530                mipmap = mipmaps[ i ];
27531
27532                if ( texture.format !== THREE.RGBAFormat && texture.format !== THREE.RGBFormat ) {
27533
27534                    if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
27535
27536                        state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
27537
27538                    } else {
27539
27540                        console.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()" );
27541
27542                    }
27543
27544                } else {
27545
27546                    state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
27547
27548                }
27549
27550            }
27551
27552        } else {
27553
27554            // regular Texture (image, video, canvas)
27555
27556            // use manually created mipmaps if available
27557            // if there are no manual mipmaps
27558            // set 0 level mipmap and then use GL to generate other mipmap levels
27559
27560            if ( mipmaps.length > 0 && isPowerOfTwoImage ) {
27561
27562                for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
27563
27564                    mipmap = mipmaps[ i ];
27565                    state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
27566
27567                }
27568
27569                texture.generateMipmaps = false;
27570
27571            } else {
27572
27573                state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image );
27574
27575            }
27576
27577        }
27578
27579        if ( texture.generateMipmaps && isPowerOfTwoImage ) _gl.generateMipmap( _gl.TEXTURE_2D );
27580
27581        textureProperties.__version = texture.version;
27582
27583        if ( texture.onUpdate ) texture.onUpdate( texture );
27584
27585    }
27586
27587    function setTexture2D( texture, slot ) {
27588
27589        if ( texture instanceof THREE.WebGLRenderTarget ) texture = texture.texture;
27590
27591        var textureProperties = properties.get( texture );
27592
27593        if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
27594
27595            var image = texture.image;
27596
27597            if ( image === undefined ) {
27598
27599                console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture );
27600                return;
27601
27602            }
27603
27604            if ( image.complete === false ) {
27605
27606                console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture );
27607                return;
27608
27609            }
27610
27611            uploadTexture( textureProperties, texture, slot );
27612
27613            return;
27614
27615        }
27616
27617        state.activeTexture( _gl.TEXTURE0 + slot );
27618        state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
27619
27620    }
27621
27622    function clampToMaxSize ( image, maxSize ) {
27623
27624        if ( image.width > maxSize || image.height > maxSize ) {
27625
27626            // Warning: Scaling through the canvas will only work with images that use
27627            // premultiplied alpha.
27628
27629            var scale = maxSize / Math.max( image.width, image.height );
27630
27631            var canvas = document.createElement( 'canvas' );
27632            canvas.width = Math.floor( image.width * scale );
27633            canvas.height = Math.floor( image.height * scale );
27634
27635            var context = canvas.getContext( '2d' );
27636            context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height );
27637
27638            console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
27639
27640            return canvas;
27641
27642        }
27643
27644        return image;
27645
27646    }
27647
27648    function isPowerOfTwo( image ) {
27649
27650        return THREE.Math.isPowerOfTwo( image.width ) && THREE.Math.isPowerOfTwo( image.height );
27651
27652    }
27653
27654    function textureNeedsPowerOfTwo( texture ) {
27655
27656        if ( texture.wrapS !== THREE.ClampToEdgeWrapping || texture.wrapT !== THREE.ClampToEdgeWrapping ) return true;
27657        if ( texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter ) return true;
27658
27659        return false;
27660
27661    }
27662
27663    function makePowerOfTwo( image ) {
27664
27665        if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement ) {
27666
27667            var canvas = document.createElement( 'canvas' );
27668            canvas.width = THREE.Math.nearestPowerOfTwo( image.width );
27669            canvas.height = THREE.Math.nearestPowerOfTwo( image.height );
27670
27671            var context = canvas.getContext( '2d' );
27672            context.drawImage( image, 0, 0, canvas.width, canvas.height );
27673
27674            console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
27675
27676            return canvas;
27677
27678        }
27679
27680        return image;
27681
27682    }
27683
27684    function setCubeTexture ( texture, slot ) {
27685
27686        var textureProperties = properties.get( texture );
27687
27688        if ( texture.image.length === 6 ) {
27689
27690            if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
27691
27692                if ( ! textureProperties.__image__webglTextureCube ) {
27693
27694                    texture.addEventListener( 'dispose', onTextureDispose );
27695
27696                    textureProperties.__image__webglTextureCube = _gl.createTexture();
27697
27698                    _infoMemory.textures ++;
27699
27700                }
27701
27702                state.activeTexture( _gl.TEXTURE0 + slot );
27703                state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
27704
27705                _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
27706
27707                var isCompressed = texture instanceof THREE.CompressedTexture;
27708                var isDataTexture = texture.image[ 0 ] instanceof THREE.DataTexture;
27709
27710                var cubeImage = [];
27711
27712                for ( var i = 0; i < 6; i ++ ) {
27713
27714                    if ( _this.autoScaleCubemaps && ! isCompressed && ! isDataTexture ) {
27715
27716                        cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize );
27717
27718                    } else {
27719
27720                        cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
27721
27722                    }
27723
27724                }
27725
27726                var image = cubeImage[ 0 ],
27727                    isPowerOfTwoImage = isPowerOfTwo( image ),
27728                    glFormat = paramThreeToGL( texture.format ),
27729                    glType = paramThreeToGL( texture.type );
27730
27731                setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );
27732
27733                for ( var i = 0; i < 6; i ++ ) {
27734
27735                    if ( ! isCompressed ) {
27736
27737                        if ( isDataTexture ) {
27738
27739                            state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
27740
27741                        } else {
27742
27743                            state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
27744
27745                        }
27746
27747                    } else {
27748
27749                        var mipmap, mipmaps = cubeImage[ i ].mipmaps;
27750
27751                        for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
27752
27753                            mipmap = mipmaps[ j ];
27754
27755                            if ( texture.format !== THREE.RGBAFormat && texture.format !== THREE.RGBFormat ) {
27756
27757                                if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
27758
27759                                    state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
27760
27761                                } else {
27762
27763                                    console.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setCubeTexture()" );
27764
27765                                }
27766
27767                            } else {
27768
27769                                state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
27770
27771                            }
27772
27773                        }
27774
27775                    }
27776
27777                }
27778
27779                if ( texture.generateMipmaps && isPowerOfTwoImage ) {
27780
27781                    _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
27782
27783                }
27784
27785                textureProperties.__version = texture.version;
27786
27787                if ( texture.onUpdate ) texture.onUpdate( texture );
27788
27789            } else {
27790
27791                state.activeTexture( _gl.TEXTURE0 + slot );
27792                state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
27793
27794            }
27795
27796        }
27797
27798    }
27799
27800    function setCubeTextureDynamic ( texture, slot ) {
27801
27802        state.activeTexture( _gl.TEXTURE0 + slot );
27803        state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture );
27804
27805    }
27806
27807    var setTextureWarned = false;
27808    this.setTexture = function( texture, slot ) {
27809
27810        if ( ! setTextureWarned ) {
27811
27812            console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, " +
27813            "use setTexture2D instead." );
27814            setTextureWarned = true;
27815
27816        }
27817
27818        setTexture2D( texture, slot );
27819
27820    };
27821
27822    this.allocTextureUnit = allocTextureUnit;
27823    this.setTexture2D = setTexture2D;
27824    this.setTextureCube = function( texture, slot ) {
27825
27826        if ( texture instanceof THREE.CubeTexture ||
27827            ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {
27828
27829            // CompressedTexture can have Array in image :/
27830
27831            setCubeTexture( texture, slot );
27832
27833        } else {
27834            // assumed: texture instanceof THREE.WebGLRenderTargetCube
27835
27836            setCubeTextureDynamic( texture.texture, slot );
27837
27838        }
27839
27840    };
27841
27842    // Render targets
27843
27844    // Setup storage for target texture and bind it to correct framebuffer
27845    function setupFrameBufferTexture ( framebuffer, renderTarget, attachment, textureTarget ) {
27846
27847        var glFormat = paramThreeToGL( renderTarget.texture.format );
27848        var glType = paramThreeToGL( renderTarget.texture.type );
27849        state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
27850        _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
27851        _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
27852        _gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
27853
27854    }
27855
27856    // Setup storage for internal depth/stencil buffers and bind to correct framebuffer
27857    function setupRenderBufferStorage ( renderbuffer, renderTarget ) {
27858
27859        _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
27860
27861        if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
27862
27863            _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
27864            _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
27865
27866        } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
27867
27868            _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
27869            _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
27870
27871        } else {
27872
27873            // FIXME: We don't support !depth !stencil
27874            _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
27875
27876        }
27877
27878        _gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
27879
27880    }
27881
27882    // Setup resources for a Depth Texture for a FBO (needs an extension)
27883    function setupDepthTexture ( framebuffer, renderTarget ) {
27884
27885        var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
27886        if ( isCube ) throw new Error('Depth Texture with cube render targets is not supported!');
27887
27888        _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
27889
27890        if ( !( renderTarget.depthTexture instanceof THREE.DepthTexture ) ) {
27891
27892            throw new Error('renderTarget.depthTexture must be an instance of THREE.DepthTexture');
27893
27894        }
27895
27896        // upload an empty depth texture with framebuffer size
27897        if ( !properties.get( renderTarget.depthTexture ).__webglTexture ||
27898            renderTarget.depthTexture.image.width !== renderTarget.width ||
27899            renderTarget.depthTexture.image.height !== renderTarget.height ) {
27900            renderTarget.depthTexture.image.width = renderTarget.width;
27901            renderTarget.depthTexture.image.height = renderTarget.height;
27902            renderTarget.depthTexture.needsUpdate = true;
27903        }
27904
27905        _this.setTexture( renderTarget.depthTexture, 0 );
27906
27907        var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
27908        _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
27909
27910    }
27911
27912    // Setup GL resources for a non-texture depth buffer
27913    function setupDepthRenderbuffer( renderTarget ) {
27914
27915        var renderTargetProperties = properties.get( renderTarget );
27916
27917        var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
27918
27919        if ( renderTarget.depthTexture ) {
27920
27921            if ( isCube ) throw new Error('target.depthTexture not supported in Cube render targets');
27922
27923            setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
27924
27925        } else {
27926
27927            if ( isCube ) {
27928
27929                renderTargetProperties.__webglDepthbuffer = [];
27930
27931                for ( var i = 0; i < 6; i ++ ) {
27932
27933                    _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] );
27934                    renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
27935                    setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget );
27936
27937                }
27938
27939            } else {
27940
27941                _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
27942                renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
27943                setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget );
27944
27945            }
27946
27947        }
27948
27949        _gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
27950
27951    }
27952
27953    // Set up GL resources for the render target
27954    function setupRenderTarget( renderTarget ) {
27955
27956        var renderTargetProperties = properties.get( renderTarget );
27957        var textureProperties = properties.get( renderTarget.texture );
27958
27959        renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
27960
27961        textureProperties.__webglTexture = _gl.createTexture();
27962
27963        _infoMemory.textures ++;
27964
27965        var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
27966        var isTargetPowerOfTwo = THREE.Math.isPowerOfTwo( renderTarget.width ) && THREE.Math.isPowerOfTwo( renderTarget.height );
27967
27968        // Setup framebuffer
27969
27970        if ( isCube ) {
27971
27972            renderTargetProperties.__webglFramebuffer = [];
27973
27974            for ( var i = 0; i < 6; i ++ ) {
27975
27976                renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
27977
27978            }
27979
27980        } else {
27981
27982            renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
27983
27984        }
27985
27986        // Setup color buffer
27987
27988        if ( isCube ) {
27989
27990            state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
27991            setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo );
27992
27993            for ( var i = 0; i < 6; i ++ ) {
27994
27995                setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
27996
27997            }
27998
27999            if ( renderTarget.texture.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
28000            state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
28001
28002        } else {
28003
28004            state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
28005            setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo );
28006            setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D );
28007
28008            if ( renderTarget.texture.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
28009            state.bindTexture( _gl.TEXTURE_2D, null );
28010
28011        }
28012
28013        // Setup depth and stencil buffers
28014
28015        if ( renderTarget.depthBuffer ) {
28016
28017            setupDepthRenderbuffer( renderTarget );
28018
28019        }
28020
28021    }
28022
28023    this.getCurrentRenderTarget = function() {
28024
28025        return _currentRenderTarget;
28026
28027    };
28028
28029    this.setRenderTarget = function ( renderTarget ) {
28030
28031        _currentRenderTarget = renderTarget;
28032
28033        if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
28034
28035            setupRenderTarget( renderTarget );
28036
28037        }
28038
28039        var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
28040        var framebuffer;
28041
28042        if ( renderTarget ) {
28043
28044            var renderTargetProperties = properties.get( renderTarget );
28045
28046            if ( isCube ) {
28047
28048                framebuffer = renderTargetProperties.__webglFramebuffer[ renderTarget.activeCubeFace ];
28049
28050            } else {
28051
28052                framebuffer = renderTargetProperties.__webglFramebuffer;
28053
28054            }
28055
28056            _currentScissor.copy( renderTarget.scissor );
28057            _currentScissorTest = renderTarget.scissorTest;
28058
28059            _currentViewport.copy( renderTarget.viewport );
28060
28061        } else {
28062
28063            framebuffer = null;
28064
28065            _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio );
28066            _currentScissorTest = _scissorTest;
28067
28068            _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio );
28069
28070        }
28071
28072        if ( _currentFramebuffer !== framebuffer ) {
28073
28074            _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
28075            _currentFramebuffer = framebuffer;
28076
28077        }
28078
28079        state.scissor( _currentScissor );
28080        state.setScissorTest( _currentScissorTest );
28081
28082        state.viewport( _currentViewport );
28083
28084        if ( isCube ) {
28085
28086            var textureProperties = properties.get( renderTarget.texture );
28087            _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, renderTarget.activeMipMapLevel );
28088
28089        }
28090
28091    };
28092
28093    this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) {
28094
28095        if ( renderTarget instanceof THREE.WebGLRenderTarget === false ) {
28096
28097            console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
28098            return;
28099
28100        }
28101
28102        var framebuffer = properties.get( renderTarget ).__webglFramebuffer;
28103
28104        if ( framebuffer ) {
28105
28106            var restore = false;
28107
28108            if ( framebuffer !== _currentFramebuffer ) {
28109
28110                _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
28111
28112                restore = true;
28113
28114            }
28115
28116            try {
28117
28118                var texture = renderTarget.texture;
28119
28120                if ( texture.format !== THREE.RGBAFormat && paramThreeToGL( texture.format ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
28121
28122                    console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
28123                    return;
28124
28125                }
28126
28127                if ( texture.type !== THREE.UnsignedByteType &&
28128                    paramThreeToGL( texture.type ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) &&
28129                    ! ( texture.type === THREE.FloatType && extensions.get( 'WEBGL_color_buffer_float' ) ) &&
28130                    ! ( texture.type === THREE.HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) {
28131
28132                    console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
28133                    return;
28134
28135                }
28136
28137                if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {
28138
28139                    // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
28140
28141                    if ( ( x > 0 && x <= ( renderTarget.width - width ) ) && ( y > 0 && y <= ( renderTarget.height - height ) ) ) {
28142
28143                        _gl.readPixels( x, y, width, height, paramThreeToGL( texture.format ), paramThreeToGL( texture.type ), buffer );
28144
28145                    }
28146
28147                } else {
28148
28149                    console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
28150
28151                }
28152
28153            } finally {
28154
28155                if ( restore ) {
28156
28157                    _gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer );
28158
28159                }
28160
28161            }
28162
28163        }
28164
28165    };
28166
28167    function updateRenderTargetMipmap( renderTarget ) {
28168
28169        var target = renderTarget instanceof THREE.WebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
28170        var texture = properties.get( renderTarget.texture ).__webglTexture;
28171
28172        state.bindTexture( target, texture );
28173        _gl.generateMipmap( target );
28174        state.bindTexture( target, null );
28175
28176    }
28177
28178    // Fallback filters for non-power-of-2 textures
28179
28180    function filterFallback ( f ) {
28181
28182        if ( f === THREE.NearestFilter || f === THREE.NearestMipMapNearestFilter || f === THREE.NearestMipMapLinearFilter ) {
28183
28184            return _gl.NEAREST;
28185
28186        }
28187
28188        return _gl.LINEAR;
28189
28190    }
28191
28192    // Map three.js constants to WebGL constants
28193
28194    function paramThreeToGL ( p ) {
28195
28196        var extension;
28197
28198        if ( p === THREE.RepeatWrapping ) return _gl.REPEAT;
28199        if ( p === THREE.ClampToEdgeWrapping ) return _gl.CLAMP_TO_EDGE;
28200        if ( p === THREE.MirroredRepeatWrapping ) return _gl.MIRRORED_REPEAT;
28201
28202        if ( p === THREE.NearestFilter ) return _gl.NEAREST;
28203        if ( p === THREE.NearestMipMapNearestFilter ) return _gl.NEAREST_MIPMAP_NEAREST;
28204        if ( p === THREE.NearestMipMapLinearFilter ) return _gl.NEAREST_MIPMAP_LINEAR;
28205
28206        if ( p === THREE.LinearFilter ) return _gl.LINEAR;
28207        if ( p === THREE.LinearMipMapNearestFilter ) return _gl.LINEAR_MIPMAP_NEAREST;
28208        if ( p === THREE.LinearMipMapLinearFilter ) return _gl.LINEAR_MIPMAP_LINEAR;
28209
28210        if ( p === THREE.UnsignedByteType ) return _gl.UNSIGNED_BYTE;
28211        if ( p === THREE.UnsignedShort4444Type ) return _gl.UNSIGNED_SHORT_4_4_4_4;
28212        if ( p === THREE.UnsignedShort5551Type ) return _gl.UNSIGNED_SHORT_5_5_5_1;
28213        if ( p === THREE.UnsignedShort565Type ) return _gl.UNSIGNED_SHORT_5_6_5;
28214
28215        if ( p === THREE.ByteType ) return _gl.BYTE;
28216        if ( p === THREE.ShortType ) return _gl.SHORT;
28217        if ( p === THREE.UnsignedShortType ) return _gl.UNSIGNED_SHORT;
28218        if ( p === THREE.IntType ) return _gl.INT;
28219        if ( p === THREE.UnsignedIntType ) return _gl.UNSIGNED_INT;
28220        if ( p === THREE.FloatType ) return _gl.FLOAT;
28221
28222        extension = extensions.get( 'OES_texture_half_float' );
28223
28224        if ( extension !== null ) {
28225
28226            if ( p === THREE.HalfFloatType ) return extension.HALF_FLOAT_OES;
28227
28228        }
28229
28230        if ( p === THREE.AlphaFormat ) return _gl.ALPHA;
28231        if ( p === THREE.RGBFormat ) return _gl.RGB;
28232        if ( p === THREE.RGBAFormat ) return _gl.RGBA;
28233        if ( p === THREE.LuminanceFormat ) return _gl.LUMINANCE;
28234        if ( p === THREE.LuminanceAlphaFormat ) return _gl.LUMINANCE_ALPHA;
28235        if ( p === THREE.DepthFormat ) return _gl.DEPTH_COMPONENT;
28236
28237        if ( p === THREE.AddEquation ) return _gl.FUNC_ADD;
28238        if ( p === THREE.SubtractEquation ) return _gl.FUNC_SUBTRACT;
28239        if ( p === THREE.ReverseSubtractEquation ) return _gl.FUNC_REVERSE_SUBTRACT;
28240
28241        if ( p === THREE.ZeroFactor ) return _gl.ZERO;
28242        if ( p === THREE.OneFactor ) return _gl.ONE;
28243        if ( p === THREE.SrcColorFactor ) return _gl.SRC_COLOR;
28244        if ( p === THREE.OneMinusSrcColorFactor ) return _gl.ONE_MINUS_SRC_COLOR;
28245        if ( p === THREE.SrcAlphaFactor ) return _gl.SRC_ALPHA;
28246        if ( p === THREE.OneMinusSrcAlphaFactor ) return _gl.ONE_MINUS_SRC_ALPHA;
28247        if ( p === THREE.DstAlphaFactor ) return _gl.DST_ALPHA;
28248        if ( p === THREE.OneMinusDstAlphaFactor ) return _gl.ONE_MINUS_DST_ALPHA;
28249
28250        if ( p === THREE.DstColorFactor ) return _gl.DST_COLOR;
28251        if ( p === THREE.OneMinusDstColorFactor ) return _gl.ONE_MINUS_DST_COLOR;
28252        if ( p === THREE.SrcAlphaSaturateFactor ) return _gl.SRC_ALPHA_SATURATE;
28253
28254        extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
28255
28256        if ( extension !== null ) {
28257
28258            if ( p === THREE.RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
28259            if ( p === THREE.RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
28260            if ( p === THREE.RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
28261            if ( p === THREE.RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
28262
28263        }
28264
28265        extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
28266
28267        if ( extension !== null ) {
28268
28269            if ( p === THREE.RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
28270            if ( p === THREE.RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
28271            if ( p === THREE.RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
28272            if ( p === THREE.RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
28273
28274        }
28275
28276        extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
28277
28278        if ( extension !== null ) {
28279
28280            if ( p === THREE.RGB_ETC1_Format ) return extension.COMPRESSED_RGB_ETC1_WEBGL;
28281
28282        }
28283
28284        extension = extensions.get( 'EXT_blend_minmax' );
28285
28286        if ( extension !== null ) {
28287
28288            if ( p === THREE.MinEquation ) return extension.MIN_EXT;
28289            if ( p === THREE.MaxEquation ) return extension.MAX_EXT;
28290
28291        }
28292
28293        return 0;
28294
28295    }
28296
28297};
28298
28299// File:src/renderers/WebGLRenderTarget.js
28300
28301/**
28302 * @author szimek / https://github.com/szimek/
28303 * @author alteredq / http://alteredqualia.com/
28304 * @author Marius Kintel / https://github.com/kintel
28305 */
28306
28307/*
28308 In options, we can specify:
28309 * Texture parameters for an auto-generated target texture
28310 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
28311 */
28312THREE.WebGLRenderTarget = function ( width, height, options ) {
28313
28314    this.uuid = THREE.Math.generateUUID();
28315
28316    this.width = width;
28317    this.height = height;
28318
28319    this.scissor = new THREE.Vector4( 0, 0, width, height );
28320    this.scissorTest = false;
28321
28322    this.viewport = new THREE.Vector4( 0, 0, width, height );
28323
28324    options = options || {};
28325
28326    if ( options.minFilter === undefined ) options.minFilter = THREE.LinearFilter;
28327
28328    this.texture = new THREE.Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
28329
28330    this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
28331    this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
28332    this.depthTexture = null;
28333
28334};
28335
28336THREE.WebGLRenderTarget.prototype = {
28337
28338    constructor: THREE.WebGLRenderTarget,
28339
28340    setSize: function ( width, height ) {
28341
28342        if ( this.width !== width || this.height !== height ) {
28343
28344            this.width = width;
28345            this.height = height;
28346
28347            this.dispose();
28348
28349        }
28350
28351        this.viewport.set( 0, 0, width, height );
28352        this.scissor.set( 0, 0, width, height );
28353
28354    },
28355
28356    clone: function () {
28357
28358        return new this.constructor().copy( this );
28359
28360    },
28361
28362    copy: function ( source ) {
28363
28364        this.width = source.width;
28365        this.height = source.height;
28366
28367        this.viewport.copy( source.viewport );
28368
28369        this.texture = source.texture.clone();
28370
28371        this.depthBuffer = source.depthBuffer;
28372        this.stencilBuffer = source.stencilBuffer;
28373        this.depthTexture = source.depthTexture;
28374
28375        return this;
28376
28377    },
28378
28379    dispose: function () {
28380
28381        this.dispatchEvent( { type: 'dispose' } );
28382
28383    }
28384
28385};
28386
28387THREE.EventDispatcher.prototype.apply( THREE.WebGLRenderTarget.prototype );
28388
28389// File:src/renderers/WebGLRenderTargetCube.js
28390
28391/**
28392 * @author alteredq / http://alteredqualia.com
28393 */
28394
28395THREE.WebGLRenderTargetCube = function ( width, height, options ) {
28396
28397    THREE.WebGLRenderTarget.call( this, width, height, options );
28398
28399    this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5
28400    this.activeMipMapLevel = 0;
28401
28402};
28403
28404THREE.WebGLRenderTargetCube.prototype = Object.create( THREE.WebGLRenderTarget.prototype );
28405THREE.WebGLRenderTargetCube.prototype.constructor = THREE.WebGLRenderTargetCube;
28406
28407// File:src/renderers/webgl/WebGLBufferRenderer.js
28408
28409/**
28410 * @author mrdoob / http://mrdoob.com/
28411 */
28412
28413THREE.WebGLBufferRenderer = function ( _gl, extensions, _infoRender ) {
28414
28415    var mode;
28416
28417    function setMode( value ) {
28418
28419        mode = value;
28420
28421    }
28422
28423    function render( start, count ) {
28424
28425        _gl.drawArrays( mode, start, count );
28426
28427        _infoRender.calls ++;
28428        _infoRender.vertices += count;
28429        if ( mode === _gl.TRIANGLES ) _infoRender.faces += count / 3;
28430
28431    }
28432
28433    function renderInstances( geometry ) {
28434
28435        var extension = extensions.get( 'ANGLE_instanced_arrays' );
28436
28437        if ( extension === null ) {
28438
28439            console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
28440            return;
28441
28442        }
28443
28444        var position = geometry.attributes.position;
28445
28446        var count = 0;
28447
28448        if ( position instanceof THREE.InterleavedBufferAttribute ) {
28449
28450            count = position.data.count;
28451
28452            extension.drawArraysInstancedANGLE( mode, 0, count, geometry.maxInstancedCount );
28453
28454        } else {
28455
28456            count = position.count;
28457
28458            extension.drawArraysInstancedANGLE( mode, 0, count, geometry.maxInstancedCount );
28459
28460        }
28461
28462        _infoRender.calls ++;
28463        _infoRender.vertices += count * geometry.maxInstancedCount;
28464        if ( mode === _gl.TRIANGLES ) _infoRender.faces += geometry.maxInstancedCount * count / 3;
28465
28466    }
28467
28468    this.setMode = setMode;
28469    this.render = render;
28470    this.renderInstances = renderInstances;
28471
28472};
28473
28474// File:src/renderers/webgl/WebGLIndexedBufferRenderer.js
28475
28476/**
28477 * @author mrdoob / http://mrdoob.com/
28478 */
28479
28480THREE.WebGLIndexedBufferRenderer = function ( _gl, extensions, _infoRender ) {
28481
28482    var mode;
28483
28484    function setMode( value ) {
28485
28486        mode = value;
28487
28488    }
28489
28490    var type, size;
28491
28492    function setIndex( index ) {
28493
28494        if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) {
28495
28496            type = _gl.UNSIGNED_INT;
28497            size = 4;
28498
28499        } else {
28500
28501            type = _gl.UNSIGNED_SHORT;
28502            size = 2;
28503
28504        }
28505
28506    }
28507
28508    function render( start, count ) {
28509
28510        _gl.drawElements( mode, count, type, start * size );
28511
28512        _infoRender.calls ++;
28513        _infoRender.vertices += count;
28514        if ( mode === _gl.TRIANGLES ) _infoRender.faces += count / 3;
28515
28516    }
28517
28518    function renderInstances( geometry, start, count ) {
28519
28520        var extension = extensions.get( 'ANGLE_instanced_arrays' );
28521
28522        if ( extension === null ) {
28523
28524            console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
28525            return;
28526
28527        }
28528
28529        extension.drawElementsInstancedANGLE( mode, count, type, start * size, geometry.maxInstancedCount );
28530
28531        _infoRender.calls ++;
28532        _infoRender.vertices += count * geometry.maxInstancedCount;
28533        if ( mode === _gl.TRIANGLES ) _infoRender.faces += geometry.maxInstancedCount * count / 3;
28534    }
28535
28536    this.setMode = setMode;
28537    this.setIndex = setIndex;
28538    this.render = render;
28539    this.renderInstances = renderInstances;
28540
28541};
28542
28543// File:src/renderers/webgl/WebGLExtensions.js
28544
28545/**
28546 * @author mrdoob / http://mrdoob.com/
28547 */
28548
28549THREE.WebGLExtensions = function ( gl ) {
28550
28551    var extensions = {};
28552
28553    this.get = function ( name ) {
28554
28555        if ( extensions[ name ] !== undefined ) {
28556
28557            return extensions[ name ];
28558
28559        }
28560
28561        var extension;
28562
28563        switch ( name ) {
28564
28565            case 'WEBGL_depth_texture':
28566                extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
28567
28568            case 'EXT_texture_filter_anisotropic':
28569                extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
28570                break;
28571
28572            case 'WEBGL_compressed_texture_s3tc':
28573                extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
28574                break;
28575
28576            case 'WEBGL_compressed_texture_pvrtc':
28577                extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
28578                break;
28579
28580            case 'WEBGL_compressed_texture_etc1':
28581                extension = gl.getExtension( 'WEBGL_compressed_texture_etc1' );
28582                break;
28583
28584            default:
28585                extension = gl.getExtension( name );
28586
28587        }
28588
28589        if ( extension === null ) {
28590
28591            console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
28592
28593        }
28594
28595        extensions[ name ] = extension;
28596
28597        return extension;
28598
28599    };
28600
28601};
28602
28603// File:src/renderers/webgl/WebGLCapabilities.js
28604
28605THREE.WebGLCapabilities = function ( gl, extensions, parameters ) {
28606
28607    function getMaxPrecision( precision ) {
28608
28609        if ( precision === 'highp' ) {
28610
28611            if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 &&
28612                gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) {
28613
28614                return 'highp';
28615
28616            }
28617
28618            precision = 'mediump';
28619
28620        }
28621
28622        if ( precision === 'mediump' ) {
28623
28624            if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 &&
28625                gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) {
28626
28627                return 'mediump';
28628
28629            }
28630
28631        }
28632
28633        return 'lowp';
28634
28635    }
28636
28637    this.getMaxPrecision = getMaxPrecision;
28638
28639    this.precision = parameters.precision !== undefined ? parameters.precision : 'highp',
28640        this.logarithmicDepthBuffer = parameters.logarithmicDepthBuffer !== undefined ? parameters.logarithmicDepthBuffer : false;
28641
28642    this.maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
28643    this.maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
28644    this.maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );
28645    this.maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE );
28646
28647    this.maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
28648    this.maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS );
28649    this.maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS );
28650    this.maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
28651
28652    this.vertexTextures = this.maxVertexTextures > 0;
28653    this.floatFragmentTextures = !! extensions.get( 'OES_texture_float' );
28654    this.floatVertexTextures = this.vertexTextures && this.floatFragmentTextures;
28655
28656    var _maxPrecision = getMaxPrecision( this.precision );
28657
28658    if ( _maxPrecision !== this.precision ) {
28659
28660        console.warn( 'THREE.WebGLRenderer:', this.precision, 'not supported, using', _maxPrecision, 'instead.' );
28661        this.precision = _maxPrecision;
28662
28663    }
28664
28665    if ( this.logarithmicDepthBuffer ) {
28666
28667        this.logarithmicDepthBuffer = !! extensions.get( 'EXT_frag_depth' );
28668
28669    }
28670
28671};
28672
28673// File:src/renderers/webgl/WebGLGeometries.js
28674
28675/**
28676 * @author mrdoob / http://mrdoob.com/
28677 */
28678
28679THREE.WebGLGeometries = function ( gl, properties, info ) {
28680
28681    var geometries = {};
28682
28683    function get( object ) {
28684
28685        var geometry = object.geometry;
28686
28687        if ( geometries[ geometry.id ] !== undefined ) {
28688
28689            return geometries[ geometry.id ];
28690
28691        }
28692
28693        geometry.addEventListener( 'dispose', onGeometryDispose );
28694
28695        var buffergeometry;
28696
28697        if ( geometry instanceof THREE.BufferGeometry ) {
28698
28699            buffergeometry = geometry;
28700
28701        } else if ( geometry instanceof THREE.Geometry ) {
28702
28703            if ( geometry._bufferGeometry === undefined ) {
28704
28705                geometry._bufferGeometry = new THREE.BufferGeometry().setFromObject( object );
28706
28707            }
28708
28709            buffergeometry = geometry._bufferGeometry;
28710
28711        }
28712
28713        geometries[ geometry.id ] = buffergeometry;
28714
28715        info.memory.geometries ++;
28716
28717        return buffergeometry;
28718
28719    }
28720
28721    function onGeometryDispose( event ) {
28722
28723        var geometry = event.target;
28724        var buffergeometry = geometries[ geometry.id ];
28725
28726        if ( buffergeometry.index !== null ) {
28727
28728            deleteAttribute( buffergeometry.index );
28729
28730        }
28731
28732        deleteAttributes( buffergeometry.attributes );
28733
28734        geometry.removeEventListener( 'dispose', onGeometryDispose );
28735
28736        delete geometries[ geometry.id ];
28737
28738        // TODO
28739
28740        var property = properties.get( geometry );
28741
28742        if ( property.wireframe ) {
28743
28744            deleteAttribute( property.wireframe );
28745
28746        }
28747
28748        properties.delete( geometry );
28749
28750        var bufferproperty = properties.get( buffergeometry );
28751
28752        if ( bufferproperty.wireframe ) {
28753
28754            deleteAttribute( bufferproperty.wireframe );
28755
28756        }
28757
28758        properties.delete( buffergeometry );
28759
28760        //
28761
28762        info.memory.geometries --;
28763
28764    }
28765
28766    function getAttributeBuffer( attribute ) {
28767
28768        if ( attribute instanceof THREE.InterleavedBufferAttribute ) {
28769
28770            return properties.get( attribute.data ).__webglBuffer;
28771
28772        }
28773
28774        return properties.get( attribute ).__webglBuffer;
28775
28776    }
28777
28778    function deleteAttribute( attribute ) {
28779
28780        var buffer = getAttributeBuffer( attribute );
28781
28782        if ( buffer !== undefined ) {
28783
28784            gl.deleteBuffer( buffer );
28785            removeAttributeBuffer( attribute );
28786
28787        }
28788
28789    }
28790
28791    function deleteAttributes( attributes ) {
28792
28793        for ( var name in attributes ) {
28794
28795            deleteAttribute( attributes[ name ] );
28796
28797        }
28798
28799    }
28800
28801    function removeAttributeBuffer( attribute ) {
28802
28803        if ( attribute instanceof THREE.InterleavedBufferAttribute ) {
28804
28805            properties.delete( attribute.data );
28806
28807        } else {
28808
28809            properties.delete( attribute );
28810
28811        }
28812
28813    }
28814
28815    this.get = get;
28816
28817};
28818
28819// File:src/renderers/webgl/WebGLLights.js
28820
28821/**
28822 * @author mrdoob / http://mrdoob.com/
28823 */
28824
28825THREE.WebGLLights = function () {
28826
28827    var lights = {};
28828
28829    this.get = function ( light ) {
28830
28831        if ( lights[ light.id ] !== undefined ) {
28832
28833            return lights[ light.id ];
28834
28835        }
28836
28837        var uniforms;
28838
28839        switch ( light.type ) {
28840
28841            case 'DirectionalLight':
28842                uniforms = {
28843                    direction: new THREE.Vector3(),
28844                    color: new THREE.Color(),
28845
28846                    shadow: false,
28847                    shadowBias: 0,
28848                    shadowRadius: 1,
28849                    shadowMapSize: new THREE.Vector2()
28850                };
28851                break;
28852
28853            case 'SpotLight':
28854                uniforms = {
28855                    position: new THREE.Vector3(),
28856                    direction: new THREE.Vector3(),
28857                    color: new THREE.Color(),
28858                    distance: 0,
28859                    coneCos: 0,
28860                    penumbraCos: 0,
28861                    decay: 0,
28862
28863                    shadow: false,
28864                    shadowBias: 0,
28865                    shadowRadius: 1,
28866                    shadowMapSize: new THREE.Vector2()
28867                };
28868                break;
28869
28870            case 'PointLight':
28871                uniforms = {
28872                    position: new THREE.Vector3(),
28873                    color: new THREE.Color(),
28874                    distance: 0,
28875                    decay: 0,
28876
28877                    shadow: false,
28878                    shadowBias: 0,
28879                    shadowRadius: 1,
28880                    shadowMapSize: new THREE.Vector2()
28881                };
28882                break;
28883
28884            case 'HemisphereLight':
28885                uniforms = {
28886                    direction: new THREE.Vector3(),
28887                    skyColor: new THREE.Color(),
28888                    groundColor: new THREE.Color()
28889                };
28890                break;
28891
28892        }
28893
28894        lights[ light.id ] = uniforms;
28895
28896        return uniforms;
28897
28898    };
28899
28900};
28901
28902// File:src/renderers/webgl/WebGLObjects.js
28903
28904/**
28905 * @author mrdoob / http://mrdoob.com/
28906 */
28907
28908THREE.WebGLObjects = function ( gl, properties, info ) {
28909
28910    var geometries = new THREE.WebGLGeometries( gl, properties, info );
28911
28912    //
28913
28914    function update( object ) {
28915
28916        // TODO: Avoid updating twice (when using shadowMap). Maybe add frame counter.
28917
28918        var geometry = geometries.get( object );
28919
28920        if ( object.geometry instanceof THREE.Geometry ) {
28921
28922            geometry.updateFromObject( object );
28923
28924        }
28925
28926        var index = geometry.index;
28927        var attributes = geometry.attributes;
28928
28929        if ( index !== null ) {
28930
28931            updateAttribute( index, gl.ELEMENT_ARRAY_BUFFER );
28932
28933        }
28934
28935        for ( var name in attributes ) {
28936
28937            updateAttribute( attributes[ name ], gl.ARRAY_BUFFER );
28938
28939        }
28940
28941        // morph targets
28942
28943        var morphAttributes = geometry.morphAttributes;
28944
28945        for ( var name in morphAttributes ) {
28946
28947            var array = morphAttributes[ name ];
28948
28949            for ( var i = 0, l = array.length; i < l; i ++ ) {
28950
28951                updateAttribute( array[ i ], gl.ARRAY_BUFFER );
28952
28953            }
28954
28955        }
28956
28957        return geometry;
28958
28959    }
28960
28961    function updateAttribute( attribute, bufferType ) {
28962
28963        var data = ( attribute instanceof THREE.InterleavedBufferAttribute ) ? attribute.data : attribute;
28964
28965        var attributeProperties = properties.get( data );
28966
28967        if ( attributeProperties.__webglBuffer === undefined ) {
28968
28969            createBuffer( attributeProperties, data, bufferType );
28970
28971        } else if ( attributeProperties.version !== data.version ) {
28972
28973            updateBuffer( attributeProperties, data, bufferType );
28974
28975        }
28976
28977    }
28978
28979    function createBuffer( attributeProperties, data, bufferType ) {
28980
28981        attributeProperties.__webglBuffer = gl.createBuffer();
28982        gl.bindBuffer( bufferType, attributeProperties.__webglBuffer );
28983
28984        var usage = data.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;
28985
28986        gl.bufferData( bufferType, data.array, usage );
28987
28988        attributeProperties.version = data.version;
28989
28990    }
28991
28992    function updateBuffer( attributeProperties, data, bufferType ) {
28993
28994        gl.bindBuffer( bufferType, attributeProperties.__webglBuffer );
28995
28996        if ( data.dynamic === false || data.updateRange.count === - 1 ) {
28997
28998            // Not using update ranges
28999
29000            gl.bufferSubData( bufferType, 0, data.array );
29001
29002        } else if ( data.updateRange.count === 0 ) {
29003
29004            console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as 
29004needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' );
29005
29006        } else {
29007
29008            gl.bufferSubData( bufferType, data.updateRange.offset * data.array.BYTES_PER_ELEMENT,
29009                data.array.subarray( data.updateRange.offset, data.updateRange.offset + data.updateRange.count ) );
29010
29011            data.updateRange.count = 0; // reset range
29012
29013        }
29014
29015        attributeProperties.version = data.version;
29016
29017    }
29018
29019    function getAttributeBuffer( attribute ) {
29020
29021        if ( attribute instanceof THREE.InterleavedBufferAttribute ) {
29022
29023            return properties.get( attribute.data ).__webglBuffer;
29024
29025        }
29026
29027        return properties.get( attribute ).__webglBuffer;
29028
29029    }
29030
29031    function getWireframeAttribute( geometry ) {
29032
29033        var property = properties.get( geometry );
29034
29035        if ( property.wireframe !== undefined ) {
29036
29037            return property.wireframe;
29038
29039        }
29040
29041        var indices = [];
29042
29043        var index = geometry.index;
29044        var attributes = geometry.attributes;
29045        var position = attributes.position;
29046
29047        // console.time( 'wireframe' );
29048
29049        if ( index !== null ) {
29050
29051            var edges = {};
29052            var array = index.array;
29053
29054            for ( var i = 0, l = array.length; i < l; i += 3 ) {
29055
29056                var a = array[ i + 0 ];
29057                var b = array[ i + 1 ];
29058                var c = array[ i + 2 ];
29059
29060                if ( checkEdge( edges, a, b ) ) indices.push( a, b );
29061                if ( checkEdge( edges, b, c ) ) indices.push( b, c );
29062                if ( checkEdge( edges, c, a ) ) indices.push( c, a );
29063
29064            }
29065
29066        } else {
29067
29068            var array = attributes.position.array;
29069
29070            for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
29071
29072                var a = i + 0;
29073                var b = i + 1;
29074                var c = i + 2;
29075
29076                indices.push( a, b, b, c, c, a );
29077
29078            }
29079
29080        }
29081
29082        // console.timeEnd( 'wireframe' );
29083
29084        var TypeArray = position.count > 65535 ? Uint32Array : Uint16Array;
29085        var attribute = new THREE.BufferAttribute( new TypeArray( indices ), 1 );
29086
29087        updateAttribute( attribute, gl.ELEMENT_ARRAY_BUFFER );
29088
29089        property.wireframe = attribute;
29090
29091        return attribute;
29092
29093    }
29094
29095    function checkEdge( edges, a, b ) {
29096
29097        if ( a > b ) {
29098
29099            var tmp = a;
29100            a = b;
29101            b = tmp;
29102
29103        }
29104
29105        var list = edges[ a ];
29106
29107        if ( list === undefined ) {
29108
29109            edges[ a ] = [ b ];
29110            return true;
29111
29112        } else if ( list.indexOf( b ) === -1 ) {
29113
29114            list.push( b );
29115            return true;
29116
29117        }
29118
29119        return false;
29120
29121    }
29122
29123    this.getAttributeBuffer = getAttributeBuffer;
29124    this.getWireframeAttribute = getWireframeAttribute;
29125
29126    this.update = update;
29127
29128};
29129
29130// File:src/renderers/webgl/WebGLProgram.js
29131
29132THREE.WebGLProgram = ( function () {
29133
29134    var programIdCount = 0;
29135
29136    function getEncodingComponents( encoding ) {
29137
29138        switch ( encoding ) {
29139
29140            case THREE.LinearEncoding:
29141                return [ 'Linear','( value )' ];
29142            case THREE.sRGBEncoding:
29143                return [ 'sRGB','( value )' ];
29144            case THREE.RGBEEncoding:
29145                return [ 'RGBE','( value )' ];
29146            case THREE.RGBM7Encoding:
29147                return [ 'RGBM','( value, 7.0 )' ];
29148            case THREE.RGBM16Encoding:
29149                return [ 'RGBM','( value, 16.0 )' ];
29150            case THREE.RGBDEncoding:
29151                return [ 'RGBD','( value, 256.0 )' ];
29152            case THREE.GammaEncoding:
29153                return [ 'Gamma','( value, float( GAMMA_FACTOR ) )' ];
29154            default:
29155                throw new Error( 'unsupported encoding: ' + encoding );
29156
29157        }
29158
29159    }
29160
29161    function getTexelDecodingFunction( functionName, encoding ) {
29162
29163        var components = getEncodingComponents( encoding );
29164        return "vec4 " + functionName + "( vec4 value ) { return " + components[ 0 ] + "ToLinear" + components[ 1 ] + "; }";
29165
29166    }
29167
29168    function getTexelEncodingFunction( functionName, encoding ) {
29169
29170        var components = getEncodingComponents( encoding );
29171        return "vec4 " + functionName + "( vec4 value ) { return LinearTo" + components[ 0 ] + components[ 1 ] + "; }";
29172
29173    }
29174
29175    function getToneMappingFunction( functionName, toneMapping ) {
29176
29177        var toneMappingName;
29178
29179        switch ( toneMapping ) {
29180
29181            case THREE.LinearToneMapping:
29182                toneMappingName = "Linear";
29183                break;
29184
29185            case THREE.ReinhardToneMapping:
29186                toneMappingName = "Reinhard";
29187                break;
29188
29189            case THREE.Uncharted2ToneMapping:
29190                toneMappingName = "Uncharted2";
29191                break;
29192
29193            case THREE.CineonToneMapping:
29194                toneMappingName = "OptimizedCineon";
29195                break;
29196
29197            default:
29198                throw new Error( 'unsupported toneMapping: ' + toneMapping );
29199
29200        }
29201
29202        return "vec3 " + functionName + "( vec3 color ) { return " + toneMappingName + "ToneMapping( color ); }";
29203
29204    }
29205
29206    function generateExtensions( extensions, parameters, rendererExtensions ) {
29207
29208        extensions = extensions || {};
29209
29210        var chunks = [
29211            ( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',
29212            ( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '',
29213            ( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '',
29214            ( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : '',
29215        ];
29216
29217        return chunks.filter( filterEmptyLine ).join( '\n' );
29218
29219    }
29220
29221    function generateDefines( defines ) {
29222
29223        var chunks = [];
29224
29225        for ( var name in defines ) {
29226
29227            var value = defines[ name ];
29228
29229            if ( value === false ) continue;
29230
29231            chunks.push( '#define ' + name + ' ' + value );
29232
29233        }
29234
29235        return chunks.join( '\n' );
29236
29237    }
29238
29239    function fetchAttributeLocations( gl, program, identifiers ) {
29240
29241        var attributes = {};
29242
29243        var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
29244
29245        for ( var i = 0; i < n; i ++ ) {
29246
29247            var info = gl.getActiveAttrib( program, i );
29248            var name = info.name;
29249
29250            // console.log("THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:", name, i );
29251
29252            attributes[ name ] = gl.getAttribLocation( program, name );
29253
29254        }
29255
29256        return attributes;
29257
29258    }
29259
29260    function filterEmptyLine( string ) {
29261
29262        return string !== '';
29263
29264    }
29265
29266    function replaceLightNums( string, parameters ) {
29267
29268        return string
29269            .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
29270            .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
29271            .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
29272            .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights );
29273
29274    }
29275
29276    function parseIncludes( string ) {
29277
29278        var pattern = /#include +<([\w\d.]+)>/g;
29279
29280        function replace( match, include ) {
29281
29282            var replace = THREE.ShaderChunk[ include ];
29283
29284            if ( replace === undefined ) {
29285
29286                throw new Error( 'Can not resolve #include <' + include + '>' );
29287
29288            }
29289
29290            return parseIncludes( replace );
29291
29292        }
29293
29294        return string.replace( pattern, replace );
29295
29296    }
29297
29298    function unrollLoops( string ) {
29299
29300        var pattern = /for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
29301
29302        function replace( match, start, end, snippet ) {
29303
29304            var unroll = '';
29305
29306            for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {
29307
29308                unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' );
29309
29310            }
29311
29312            return unroll;
29313
29314        }
29315
29316        return string.replace( pattern, replace );
29317
29318    }
29319
29320    return function WebGLProgram( renderer, code, material, parameters ) {
29321
29322        var gl = renderer.context;
29323
29324        var extensions = material.extensions;
29325        var defines = material.defines;
29326
29327        var vertexShader = material.__webglShader.vertexShader;
29328        var fragmentShader = material.__webglShader.fragmentShader;
29329
29330        var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
29331
29332        if ( parameters.shadowMapType === THREE.PCFShadowMap ) {
29333
29334            shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
29335
29336        } else if ( parameters.shadowMapType === THREE.PCFSoftShadowMap ) {
29337
29338            shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
29339
29340        }
29341
29342        var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
29343        var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
29344        var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
29345
29346        if ( parameters.envMap ) {
29347
29348            switch ( material.envMap.mapping ) {
29349
29350                case THREE.CubeReflectionMapping:
29351                case THREE.CubeRefractionMapping:
29352                    envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
29353                    break;
29354
29355                case THREE.CubeUVReflectionMapping:
29356                case THREE.CubeUVRefractionMapping:
29357                    envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
29358                    break;
29359
29360                case THREE.EquirectangularReflectionMapping:
29361                case THREE.EquirectangularRefractionMapping:
29362                    envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
29363                    break;
29364
29365                case THREE.SphericalReflectionMapping:
29366                    envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
29367                    break;
29368
29369            }
29370
29371            switch ( material.envMap.mapping ) {
29372
29373                case THREE.CubeRefractionMapping:
29374                case THREE.EquirectangularRefractionMapping:
29375                    envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
29376                    break;
29377
29378            }
29379
29380            switch ( material.combine ) {
29381
29382                case THREE.MultiplyOperation:
29383                    envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
29384                    break;
29385
29386                case THREE.MixOperation:
29387                    envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
29388                    break;
29389
29390                case THREE.AddOperation:
29391                    envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
29392                    break;
29393
29394            }
29395
29396        }
29397
29398        var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
29399
29400        // console.log( 'building new program ' );
29401
29402        //
29403
29404        var customExtensions = generateExtensions( extensions, parameters, renderer.extensions );
29405
29406        var customDefines = generateDefines( defines );
29407
29408        //
29409
29410        var program = gl.createProgram();
29411
29412        var prefixVertex, prefixFragment;
29413
29414        if ( material instanceof THREE.RawShaderMaterial ) {
29415
29416            prefixVertex = '';
29417            prefixFragment = '';
29418
29419        } else {
29420
29421            prefixVertex = [
29422
29423                'precision ' + parameters.precision + ' float;',
29424                'precision ' + parameters.precision + ' int;',
29425
29426                '#define SHADER_NAME ' + material.__webglShader.name,
29427
29428                customDefines,
29429
29430                parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
29431
29432                '#define GAMMA_FACTOR ' + gammaFactorDefine,
29433
29434                '#define MAX_BONES ' + parameters.maxBones,
29435
29436                parameters.map ? '#define USE_MAP' : '',
29437                parameters.envMap ? '#define USE_ENVMAP' : '',
29438                parameters.envMap ? '#define ' + envMapModeDefine : '',
29439                parameters.lightMap ? '#define USE_LIGHTMAP' : '',
29440                parameters.aoMap ? '#define USE_AOMAP' : '',
29441                parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
29442                parameters.bumpMap ? '#define USE_BUMPMAP' : '',
29443                parameters.normalMap ? '#define USE_NORMALMAP' : '',
29444                parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
29445                parameters.specularMap ? '#define USE_SPECULARMAP' : '',
29446                parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
29447                parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
29448                parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
29449                parameters.vertexColors ? '#define USE_COLOR' : '',
29450
29451                parameters.flatShading ? '#define FLAT_SHADED' : '',
29452
29453                parameters.skinning ? '#define USE_SKINNING' : '',
29454                parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
29455
29456                parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
29457                parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
29458                parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
29459                parameters.flipSided ? '#define FLIP_SIDED' : '',
29460
29461                '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes,
29462
29463                parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
29464                parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
29465
29466                parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
29467
29468                parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
29469                parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
29470
29471                'uniform mat4 modelMatrix;',
29472                'uniform mat4 modelViewMatrix;',
29473                'uniform mat4 projectionMatrix;',
29474                'uniform mat4 viewMatrix;',
29475                'uniform mat3 normalMatrix;',
29476                'uniform vec3 cameraPosition;',
29477
29478                'attribute vec3 position;',
29479                'attribute vec3 normal;',
29480                'attribute vec2 uv;',
29481
29482                '#ifdef USE_COLOR',
29483
29484                '	attribute vec3 color;',
29485
29486                '#endif',
29487
29488                '#ifdef USE_MORPHTARGETS',
29489
29490                '	attribute vec3 morphTarget0;',
29491                '	attribute vec3 morphTarget1;',
29492                '	attribute vec3 morphTarget2;',
29493                '	attribute vec3 morphTarget3;',
29494
29495                '	#ifdef USE_MORPHNORMALS',
29496
29497                '		attribute vec3 morphNormal0;',
29498                '		attribute vec3 morphNormal1;',
29499                '		attribute vec3 morphNormal2;',
29500                '		attribute vec3 morphNormal3;',
29501
29502                '	#else',
29503
29504                '		attribute vec3 morphTarget4;',
29505                '		attribute vec3 morphTarget5;',
29506                '		attribute vec3 morphTarget6;',
29507                '		attribute vec3 morphTarget7;',
29508
29509                '	#endif',
29510
29511                '#endif',
29512
29513                '#ifdef USE_SKINNING',
29514
29515                '	attribute vec4 skinIndex;',
29516                '	attribute vec4 skinWeight;',
29517
29518                '#endif',
29519
29520                '\n'
29521
29522            ].filter( filterEmptyLine ).join( '\n' );
29523
29524            prefixFragment = [
29525
29526                customExtensions,
29527
29528                'precision ' + parameters.precision + ' float;',
29529                'precision ' + parameters.precision + ' int;',
29530
29531                '#define SHADER_NAME ' + material.__webglShader.name,
29532
29533                customDefines,
29534
29535                parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '',
29536
29537                '#define GAMMA_FACTOR ' + gammaFactorDefine,
29538
29539                ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
29540                ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',
29541
29542                parameters.map ? '#define USE_MAP' : '',
29543                parameters.envMap ? '#define USE_ENVMAP' : '',
29544                parameters.envMap ? '#define ' + envMapTypeDefine : '',
29545                parameters.envMap ? '#define ' + envMapModeDefine : '',
29546                parameters.envMap ? '#define ' + envMapBlendingDefine : '',
29547                parameters.lightMap ? '#define USE_LIGHTMAP' : '',
29548                parameters.aoMap ? '#define USE_AOMAP' : '',
29549                parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
29550                parameters.bumpMap ? '#define USE_BUMPMAP' : '',
29551                parameters.normalMap ? '#define USE_NORMALMAP' : '',
29552                parameters.specularMap ? '#define USE_SPECULARMAP' : '',
29553                parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
29554                parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
29555                parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
29556                parameters.vertexColors ? '#define USE_COLOR' : '',
29557
29558                parameters.flatShading ? '#define FLAT_SHADED' : '',
29559
29560                parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
29561                parameters.flipSided ? '#define FLIP_SIDED' : '',
29562
29563                '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes,
29564
29565                parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
29566                parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
29567
29568                parameters.premultipliedAlpha ? "#define PREMULTIPLIED_ALPHA" : '',
29569
29570                parameters.physicallyCorrectLights ? "#define PHYSICALLY_CORRECT_LIGHTS" : '',
29571
29572                parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
29573                parameters.logarithmicDepthBuffer && renderer.extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
29574
29575                parameters.envMap && renderer.extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '',
29576
29577                'uniform mat4 viewMatrix;',
29578                'uniform vec3 cameraPosition;',
29579
29580                ( parameters.toneMapping !== THREE.NoToneMapping ) ? "#define TONE_MAPPING" : '',
29581                ( parameters.toneMapping !== THREE.NoToneMapping ) ? THREE.ShaderChunk[ 'tonemapping_pars_fragment' ] : '',  // this code is required here because it is used by the toneMapping() function defined below
29582                ( parameters.toneMapping !== THREE.NoToneMapping ) ? getToneMappingFunction( "toneMapping", parameters.toneMapping ) : '',
29583
29584                ( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? THREE.ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below
29585                parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
29586                parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
29587                parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
29588                parameters.outputEncoding ? getTexelEncodingFunction( "linearToOutputTexel", parameters.outputEncoding ) : '',
29589
29590                parameters.depthPacking ? "#define DEPTH_PACKING " + material.depthPacking : '',
29591
29592                '\n'
29593
29594            ].filter( filterEmptyLine ).join( '\n' );
29595
29596        }
29597
29598        vertexShader = parseIncludes( vertexShader, parameters );
29599        vertexShader = replaceLightNums( vertexShader, parameters );
29600
29601        fragmentShader = parseIncludes( fragmentShader, parameters );
29602        fragmentShader = replaceLightNums( fragmentShader, parameters );
29603
29604        if ( material instanceof THREE.ShaderMaterial === false ) {
29605
29606            vertexShader = unrollLoops( vertexShader );
29607            fragmentShader = unrollLoops( fragmentShader );
29608
29609        }
29610
29611        var vertexGlsl = prefixVertex + vertexShader;
29612        var fragmentGlsl = prefixFragment + fragmentShader;
29613
29614        // console.log( '*VERTEX*', vertexGlsl );
29615        // console.log( '*FRAGMENT*', fragmentGlsl );
29616
29617        var glVertexShader = THREE.WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
29618        var glFragmentShader = THREE.WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
29619
29620        gl.attachShader( program, glVertexShader );
29621        gl.attachShader( program, glFragmentShader );
29622
29623        // Force a particular attribute to index 0.
29624
29625        if ( material.index0AttributeName !== undefined ) {
29626
29627            gl.bindAttribLocation( program, 0, material.index0AttributeName );
29628
29629        } else if ( parameters.morphTargets === true ) {
29630
29631            // programs with morphTargets displace position out of attribute 0
29632            gl.bindAttribLocation( program, 0, 'position' );
29633
29634        }
29635
29636        gl.linkProgram( program );
29637
29638        var programLog = gl.getProgramInfoLog( program );
29639        var vertexLog = gl.getShaderInfoLog( glVertexShader );
29640        var fragmentLog = gl.getShaderInfoLog( glFragmentShader );
29641
29642        var runnable = true;
29643        var haveDiagnostics = true;
29644
29645        // console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) );
29646        // console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) );
29647
29648        if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
29649
29650            runnable = false;
29651
29652            console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog );
29653
29654        } else if ( programLog !== '' ) {
29655
29656            console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
29657
29658        } else if ( vertexLog === '' || fragmentLog === '' ) {
29659
29660            haveDiagnostics = false;
29661
29662        }
29663
29664        if ( haveDiagnostics ) {
29665
29666            this.diagnostics = {
29667
29668                runnable: runnable,
29669                material: material,
29670
29671                programLog: programLog,
29672
29673                vertexShader: {
29674
29675                    log: vertexLog,
29676                    prefix: prefixVertex
29677
29678                },
29679
29680                fragmentShader: {
29681
29682                    log: fragmentLog,
29683                    prefix: prefixFragment
29684
29685                }
29686
29687            };
29688
29689        }
29690
29691        // clean up
29692
29693        gl.deleteShader( glVertexShader );
29694        gl.deleteShader( glFragmentShader );
29695
29696        // set up caching for uniform locations
29697
29698        var cachedUniforms;
29699
29700        this.getUniforms = function() {
29701
29702            if ( cachedUniforms === undefined ) {
29703
29704                cachedUniforms =
29705                    new THREE.WebGLUniforms( gl, program, renderer );
29706
29707            }
29708
29709            return cachedUniforms;
29710
29711        };
29712
29713        // set up caching for attribute locations
29714
29715        var cachedAttributes;
29716
29717        this.getAttributes = function() {
29718
29719            if ( cachedAttributes === undefined ) {
29720
29721                cachedAttributes = fetchAttributeLocations( gl, program );
29722
29723            }
29724
29725            return cachedAttributes;
29726
29727        };
29728
29729        // free resource
29730
29731        this.destroy = function() {
29732
29733            gl.deleteProgram( program );
29734            this.program = undefined;
29735
29736        };
29737
29738        // DEPRECATED
29739
29740        Object.defineProperties( this, {
29741
29742            uniforms: {
29743                get: function() {
29744
29745                    console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' );
29746                    return this.getUniforms();
29747
29748                }
29749            },
29750
29751            attributes: {
29752                get: function() {
29753
29754                    console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' );
29755                    return this.getAttributes();
29756
29757                }
29758            }
29759
29760        } );
29761
29762
29763        //
29764
29765        this.id = programIdCount ++;
29766        this.code = code;
29767        this.usedTimes = 1;
29768        this.program = program;
29769        this.vertexShader = glVertexShader;
29770        this.fragmentShader = glFragmentShader;
29771
29772        return this;
29773
29774    };
29775
29776} )();
29777
29778// File:src/renderers/webgl/WebGLPrograms.js
29779
29780THREE.WebGLPrograms = function ( renderer, capabilities ) {
29781
29782    var programs = [];
29783
29784    var shaderIDs = {
29785        MeshDepthMaterial: 'depth',
29786        MeshNormalMaterial: 'normal',
29787        MeshBasicMaterial: 'basic',
29788        MeshLambertMaterial: 'lambert',
29789        MeshPhongMaterial: 'phong',
29790        MeshStandardMaterial: 'physical',
29791        MeshPhysicalMaterial: 'physical',
29792        LineBasicMaterial: 'basic',
29793        LineDashedMaterial: 'dashed',
29794        PointsMaterial: 'points'
29795    };
29796
29797    var parameterNames = [
29798        "precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding",
29799        "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap",
29800        "roughnessMap", "metalnessMap",
29801        "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp",
29802        "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
29803        "maxBones", "useVertexTexture", "morphTargets", "morphNormals",
29804        "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
29805        "numDirLights", "numPointLights", "numSpotLights", "numHemiLights",
29806        "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
29807        "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "depthPacking"
29808    ];
29809
29810
29811    function allocateBones ( object ) {
29812
29813        if ( capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture ) {
29814
29815            return 1024;
29816
29817        } else {
29818
29819            // default for when object is not specified
29820            // ( for example when prebuilding shader to be used with multiple objects )
29821            //
29822            //  - leave some extra space for other uniforms
29823            //  - limit here is ANGLE's 254 max uniform vectors
29824            //    (up to 54 should be safe)
29825
29826            var nVertexUniforms = capabilities.maxVertexUniforms;
29827            var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
29828
29829            var maxBones = nVertexMatrices;
29830
29831            if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
29832
29833                maxBones = Math.min( object.skeleton.bones.length, maxBones );
29834
29835                if ( maxBones < object.skeleton.bones.length ) {
29836
29837                    console.warn( 'WebGLRenderer: too many bones - ' + object.skeleton.bones.length + ', this GPU supports just ' + maxBones + ' (try OpenGL instead of ANGLE)' );
29838
29839                }
29840
29841            }
29842
29843            return maxBones;
29844
29845        }
29846
29847    }
29848
29849    function getTextureEncodingFromMap( map, gammaOverrideLinear ) {
29850
29851        var encoding;
29852
29853        if ( ! map ) {
29854
29855            encoding = THREE.LinearEncoding;
29856
29857        } else if ( map instanceof THREE.Texture ) {
29858
29859            encoding = map.encoding;
29860
29861        } else if ( map instanceof THREE.WebGLRenderTarget ) {
29862
29863            encoding = map.texture.encoding;
29864
29865        }
29866
29867        // add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point.
29868        if ( encoding === THREE.LinearEncoding && gammaOverrideLinear ) {
29869
29870            encoding = THREE.GammaEncoding;
29871
29872        }
29873
29874        return encoding;
29875
29876    }
29877
29878    this.getParameters = function ( material, lights, fog, nClipPlanes, object ) {
29879
29880        var shaderID = shaderIDs[ material.type ];
29881
29882        // heuristics to create shader parameters according to lights in the scene
29883        // (not to blow over maxLights budget)
29884
29885        var maxBones = allocateBones( object );
29886        var precision = renderer.getPrecision();
29887
29888        if ( material.precision !== null ) {
29889
29890            precision = capabilities.getMaxPrecision( material.precision );
29891
29892            if ( precision !== material.precision ) {
29893
29894                console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
29895
29896            }
29897
29898        }
29899
29900        var parameters = {
29901
29902            shaderID: shaderID,
29903
29904            precision: precision,
29905            supportsVertexTextures: capabilities.vertexTextures,
29906            outputEncoding: getTextureEncodingFromMap( renderer.getCurrentRenderTarget(), renderer.gammaOutput ),
29907            map: !! material.map,
29908            mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ),
29909            envMap: !! material.envMap,
29910            envMapMode: material.envMap && material.envMap.mapping,
29911            envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ),
29912            envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === THREE.CubeUVReflectionMapping ) || ( material.envMap.mapping === THREE.CubeUVRefractionMapping ) ),
29913            lightMap: !! material.lightMap,
29914            aoMap: !! material.aoMap,
29915            emissiveMap: !! material.emissiveMap,
29916            emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ),
29917            bumpMap: !! material.bumpMap,
29918            normalMap: !! material.normalMap,
29919            displacementMap: !! material.displacementMap,
29920            roughnessMap: !! material.roughnessMap,
29921            metalnessMap: !! material.metalnessMap,
29922            specularMap: !! material.specularMap,
29923            alphaMap: !! material.alphaMap,
29924
29925            combine: material.combine,
29926
29927            vertexColors: material.vertexColors,
29928
29929            fog: fog,
29930            useFog: material.fog,
29931            fogExp: fog instanceof THREE.FogExp2,
29932
29933            flatShading: material.shading === THREE.FlatShading,
29934
29935            sizeAttenuation: material.sizeAttenuation,
29936            logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
29937
29938            skinning: material.skinning,
29939            maxBones: maxBones,
29940            useVertexTexture: capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture,
29941
29942            morphTargets: material.morphTargets,
29943            morphNormals: material.morphNormals,
29944            maxMorphTargets: renderer.maxMorphTargets,
29945            maxMorphNormals: renderer.maxMorphNormals,
29946
29947            numDirLights: lights.directional.length,
29948            numPointLights: lights.point.length,
29949            numSpotLights: lights.spot.length,
29950            numHemiLights: lights.hemi.length,
29951
29952            numClippingPlanes: nClipPlanes,
29953
29954            shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && lights.shadows.length > 0,
29955            shadowMapType: renderer.shadowMap.type,
29956
29957            toneMapping: renderer.toneMapping,
29958            physicallyCorrectLights: renderer.physicallyCorrectLights,
29959
29960            premultipliedAlpha: material.premultipliedAlpha,
29961
29962            alphaTest: material.alphaTest,
29963            doubleSided: material.side === THREE.DoubleSide,
29964            flipSided: material.side === THREE.BackSide,
29965
29966            depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false
29967
29968        };
29969
29970        return parameters;
29971
29972    };
29973
29974    this.getProgramCode = function ( material, parameters ) {
29975
29976        var array = [];
29977
29978        if ( parameters.shaderID ) {
29979
29980            array.push( parameters.shaderID );
29981
29982        } else {
29983
29984            array.push( material.fragmentShader );
29985            array.push( material.vertexShader );
29986
29987        }
29988
29989        if ( material.defines !== undefined ) {
29990
29991            for ( var name in material.defines ) {
29992
29993                array.push( name );
29994                array.push( material.defines[ name ] );
29995
29996            }
29997
29998        }
29999
30000        for ( var i = 0; i < parameterNames.length; i ++ ) {
30001
30002            array.push( parameters[ parameterNames[ i ] ] );
30003
30004        }
30005
30006        return array.join();
30007
30008    };
30009
30010    this.acquireProgram = function ( material, parameters, code ) {
30011
30012        var program;
30013
30014        // Check if code has been already compiled
30015        for ( var p = 0, pl = programs.length; p < pl; p ++ ) {
30016
30017            var programInfo = programs[ p ];
30018
30019            if ( programInfo.code === code ) {
30020
30021                program = programInfo;
30022                ++ program.usedTimes;
30023
30024                break;
30025
30026            }
30027
30028        }
30029
30030        if ( program === undefined ) {
30031
30032            program = new THREE.WebGLProgram( renderer, code, material, parameters );
30033            programs.push( program );
30034
30035        }
30036
30037        return program;
30038
30039    };
30040
30041    this.releaseProgram = function( program ) {
30042
30043        if ( -- program.usedTimes === 0 ) {
30044
30045            // Remove from unordered set
30046            var i = programs.indexOf( program );
30047            programs[ i ] = programs[ programs.length - 1 ];
30048            programs.pop();
30049
30050            // Free WebGL resources
30051            program.destroy();
30052
30053        }
30054
30055    };
30056
30057    // Exposed for resource monitoring & error feedback via renderer.info:
30058    this.programs = programs;
30059
30060};
30061
30062// File:src/renderers/webgl/WebGLProperties.js
30063
30064/**
30065 * @author fordacious / fordacious.github.io
30066 */
30067
30068THREE.WebGLProperties = function () {
30069
30070    var properties = {};
30071
30072    this.get = function ( object ) {
30073
30074        var uuid = object.uuid;
30075        var map = properties[ uuid ];
30076
30077        if ( map === undefined ) {
30078
30079            map = {};
30080            properties[ uuid ] = map;
30081
30082        }
30083
30084        return map;
30085
30086    };
30087
30088    this.delete = function ( object ) {
30089
30090        delete properties[ object.uuid ];
30091
30092    };
30093
30094    this.clear = function () {
30095
30096        properties = {};
30097
30098    };
30099
30100};
30101
30102// File:src/renderers/webgl/WebGLShader.js
30103
30104THREE.WebGLShader = ( function () {
30105
30106    function addLineNumbers( string ) {
30107
30108        var lines = string.split( '\n' );
30109
30110        for ( var i = 0; i < lines.length; i ++ ) {
30111
30112            lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
30113
30114        }
30115
30116        return lines.join( '\n' );
30117
30118    }
30119
30120    return function WebGLShader( gl, type, string ) {
30121
30122        var shader = gl.createShader( type );
30123
30124        gl.shaderSource( shader, string );
30125        gl.compileShader( shader );
30126
30127        if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) {
30128
30129            console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' );
30130
30131        }
30132
30133        if ( gl.getShaderInfoLog( shader ) !== '' ) {
30134
30135            console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) );
30136
30137        }
30138
30139        // --enable-privileged-webgl-extension
30140        // console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
30141
30142        return shader;
30143
30144    };
30145
30146} )();
30147
30148// File:src/renderers/webgl/WebGLShadowMap.js
30149
30150/**
30151 * @author alteredq / http://alteredqualia.com/
30152 * @author mrdoob / http://mrdoob.com/
30153 */
30154
30155THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
30156
30157    var _gl = _renderer.context,
30158        _state = _renderer.state,
30159        _frustum = new THREE.Frustum(),
30160        _projScreenMatrix = new THREE.Matrix4(),
30161
30162        _lightShadows = _lights.shadows,
30163
30164        _shadowMapSize = new THREE.Vector2(),
30165
30166        _lookTarget = new THREE.Vector3(),
30167        _lightPositionWorld = new THREE.Vector3(),
30168
30169        _renderList = [],
30170
30171        _MorphingFlag = 1,
30172        _SkinningFlag = 2,
30173
30174        _NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1,
30175
30176        _depthMaterials = new Array( _NumberOfMaterialVariants ),
30177        _distanceMaterials = new Array( _NumberOfMaterialVariants ),
30178
30179        _materialCache = {};
30180
30181    var cubeDirections = [
30182        new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( - 1, 0, 0 ), new THREE.Vector3( 0, 0, 1 ),
30183        new THREE.Vector3( 0, 0, - 1 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, - 1, 0 )
30184    ];
30185
30186    var cubeUps = [
30187        new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 1, 0 ),
30188        new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ),	new THREE.Vector3( 0, 0, - 1 )
30189    ];
30190
30191    var cube2DViewPorts = [
30192        new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4(),
30193        new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4()
30194    ];
30195
30196    // init
30197
30198    var depthMaterialTemplate = new THREE.MeshDepthMaterial();
30199    depthMaterialTemplate.depthPacking = THREE.RGBADepthPacking;
30200    depthMaterialTemplate.clipping = true;
30201
30202    var distanceShader = THREE.ShaderLib[ "distanceRGBA" ];
30203    var distanceUniforms = THREE.UniformsUtils.clone( distanceShader.uniforms );
30204
30205    for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {
30206
30207        var useMorphing = ( i & _MorphingFlag ) !== 0;
30208        var useSkinning = ( i & _SkinningFlag ) !== 0;
30209
30210        var depthMaterial = depthMaterialTemplate.clone();
30211        depthMaterial.morphTargets = useMorphing;
30212        depthMaterial.skinning = useSkinning;
30213
30214        _depthMaterials[ i ] = depthMaterial;
30215
30216        var distanceMaterial = new THREE.ShaderMaterial( {
30217            defines: {
30218                'USE_SHADOWMAP': ''
30219            },
30220            uniforms: distanceUniforms,
30221            vertexShader: distanceShader.vertexShader,
30222            fragmentShader: distanceShader.fragmentShader,
30223            morphTargets: useMorphing,
30224            skinning: useSkinning,
30225            clipping: true
30226        } );
30227
30228        _distanceMaterials[ i ] = distanceMaterial;
30229
30230    }
30231
30232    //
30233
30234    var scope = this;
30235
30236    this.enabled = false;
30237
30238    this.autoUpdate = true;
30239    this.needsUpdate = false;
30240
30241    this.type = THREE.PCFShadowMap;
30242    this.cullFace = THREE.CullFaceFront;
30243
30244    this.render = function ( scene, camera ) {
30245
30246        if ( scope.enabled === false ) return;
30247        if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
30248
30249        if ( _lightShadows.length === 0 ) return;
30250
30251        // Set GL state for depth map.
30252        _state.clearColor( 1, 1, 1, 1 );
30253        _state.disable( _gl.BLEND );
30254        _state.enable( _gl.CULL_FACE );
30255        _gl.frontFace( _gl.CCW );
30256        _gl.cullFace( scope.cullFace === THREE.CullFaceFront ? _gl.FRONT : _gl.BACK );
30257        _state.setDepthTest( true );
30258        _state.setScissorTest( false );
30259
30260        // render depth map
30261
30262        var faceCount, isPointLight;
30263
30264        for ( var i = 0, il = _lightShadows.length; i < il; i ++ ) {
30265
30266            var light = _lightShadows[ i ];
30267
30268            var shadow = light.shadow;
30269            var shadowCamera = shadow.camera;
30270
30271            _shadowMapSize.copy( shadow.mapSize );
30272
30273            if ( light instanceof THREE.PointLight ) {
30274
30275                faceCount = 6;
30276                isPointLight = true;
30277
30278                var vpWidth = _shadowMapSize.x;
30279                var vpHeight = _shadowMapSize.y;
30280
30281                // These viewports map a cube-map onto a 2D texture with the
30282                // following orientation:
30283                //
30284                //  xzXZ
30285                //   y Y
30286                //
30287                // X - Positive x direction
30288                // x - Negative x direction
30289                // Y - Positive y direction
30290                // y - Negative y direction
30291                // Z - Positive z direction
30292                // z - Negative z direction
30293
30294                // positive X
30295                cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
30296                // negative X
30297                cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
30298                // positive Z
30299                cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
30300                // negative Z
30301                cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
30302                // positive Y
30303                cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
30304                // negative Y
30305                cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
30306
30307                _shadowMapSize.x *= 4.0;
30308                _shadowMapSize.y *= 2.0;
30309
30310            } else {
30311
30312                faceCount = 1;
30313                isPointLight = false;
30314
30315            }
30316
30317            if ( shadow.map === null ) {
30318
30319                var pars = { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat };
30320
30321                shadow.map = new THREE.WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
30322
30323                shadowCamera.updateProjectionMatrix();
30324
30325            }
30326
30327            if ( shadow instanceof THREE.SpotLightShadow ) {
30328
30329                shadow.update( light );
30330
30331            }
30332
30333            var shadowMap = shadow.map;
30334            var shadowMatrix = shadow.matrix;
30335
30336            _lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
30337            shadowCamera.position.copy( _lightPositionWorld );
30338
30339            _renderer.setRenderTarget( shadowMap );
30340            _renderer.clear();
30341
30342            // render shadow map for each cube face (if omni-directional) or
30343            // run a single pass if not
30344
30345            for ( var face = 0; face < faceCount; face ++ ) {
30346
30347                if ( isPointLight ) {
30348
30349                    _lookTarget.copy( shadowCamera.position );
30350                    _lookTarget.add( cubeDirections[ face ] );
30351                    shadowCamera.up.copy( cubeUps[ face ] );
30352                    shadowCamera.lookAt( _lookTarget );
30353
30354                    var vpDimensions = cube2DViewPorts[ face ];
30355                    _state.viewport( vpDimensions );
30356
30357                } else {
30358
30359                    _lookTarget.setFromMatrixPosition( light.target.matrixWorld );
30360                    shadowCamera.lookAt( _lookTarget );
30361
30362                }
30363
30364                shadowCamera.updateMatrixWorld();
30365                shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
30366
30367                // compute shadow matrix
30368
30369                shadowMatrix.set(
30370                    0.5, 0.0, 0.0, 0.5,
30371                    0.0, 0.5, 0.0, 0.5,
30372                    0.0, 0.0, 0.5, 0.5,
30373                    0.0, 0.0, 0.0, 1.0
30374                );
30375
30376                shadowMatrix.multiply( shadowCamera.projectionMatrix );
30377                shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
30378
30379                // update camera matrices and frustum
30380
30381                _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
30382                _frustum.setFromMatrix( _projScreenMatrix );
30383
30384                // set object matrices & frustum culling
30385
30386                _renderList.length = 0;
30387
30388                projectObject( scene, camera, shadowCamera );
30389
30390                // render shadow map
30391                // render regular objects
30392
30393                for ( var j = 0, jl = _renderList.length; j < jl; j ++ ) {
30394
30395                    var object = _renderList[ j ];
30396                    var geometry = _objects.update( object );
30397                    var material = object.material;
30398
30399                    if ( material instanceof THREE.MultiMaterial ) {
30400
30401                        var groups = geometry.groups;
30402                        var materials = material.materials;
30403
30404                        for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
30405
30406                            var group = groups[ k ];
30407                            var groupMaterial = materials[ group.materialIndex ];
30408
30409                            if ( groupMaterial.visible === true ) {
30410
30411                                var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld );
30412                                _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
30413
30414                            }
30415
30416                        }
30417
30418                    } else {
30419
30420                        var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld );
30421                        _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
30422
30423                    }
30424
30425                }
30426
30427            }
30428
30429        }
30430
30431        // Restore GL state.
30432        var clearColor = _renderer.getClearColor(),
30433            clearAlpha = _renderer.getClearAlpha();
30434        _renderer.setClearColor( clearColor, clearAlpha );
30435
30436        _state.enable( _gl.BLEND );
30437
30438        if ( scope.cullFace === THREE.CullFaceFront ) {
30439
30440            _gl.cullFace( _gl.BACK );
30441
30442        }
30443
30444        scope.needsUpdate = false;
30445
30446    };
30447
30448    function getDepthMaterial( object, material, isPointLight, lightPositionWorld ) {
30449
30450        var geometry = object.geometry;
30451
30452        var result = null;
30453
30454        var materialVariants = _depthMaterials;
30455        var customMaterial = object.customDepthMaterial;
30456
30457        if ( isPointLight ) {
30458
30459            materialVariants = _distanceMaterials;
30460            customMaterial = object.customDistanceMaterial;
30461
30462        }
30463
30464        if ( ! customMaterial ) {
30465
30466            var useMorphing = geometry.morphTargets !== undefined &&
30467                geometry.morphTargets.length > 0 && material.morphTargets;
30468
30469            var useSkinning = object instanceof THREE.SkinnedMesh && material.skinning;
30470
30471            var variantIndex = 0;
30472
30473            if ( useMorphing ) variantIndex |= _MorphingFlag;
30474            if ( useSkinning ) variantIndex |= _SkinningFlag;
30475
30476            result = materialVariants[ variantIndex ];
30477
30478        } else {
30479
30480            result = customMaterial;
30481
30482        }
30483
30484        if ( _renderer.localClippingEnabled &&
30485            material.clipSh
30485adows === true &&
30486            material.clippingPlanes.length !== 0 ) {
30487
30488            // in this case we need a unique material instance reflecting the
30489            // appropriate state
30490
30491            var keyA = result.uuid, keyB = material.uuid;
30492
30493            var materialsForVariant = _materialCache[ keyA ];
30494
30495            if ( materialsForVariant === undefined ) {
30496
30497                materialsForVariant = {};
30498                _materialCache[ keyA ] = materialsForVariant;
30499
30500            }
30501
30502            var cachedMaterial = materialsForVariant[ keyB ];
30503
30504            if ( cachedMaterial === undefined ) {
30505
30506                cachedMaterial = result.clone();
30507                materialsForVariant[ keyB ] = cachedMaterial;
30508
30509            }
30510
30511            result = cachedMaterial;
30512
30513        }
30514
30515        result.visible = material.visible;
30516        result.wireframe = material.wireframe;
30517        result.side = material.side;
30518        result.clipShadows = material.clipShadows;
30519        result.clippingPlanes = material.clippingPlanes;
30520        result.wireframeLinewidth = material.wireframeLinewidth;
30521        result.linewidth = material.linewidth;
30522
30523        if ( isPointLight && result.uniforms.lightPos !== undefined ) {
30524
30525            result.uniforms.lightPos.value.copy( lightPositionWorld );
30526
30527        }
30528
30529        return result;
30530
30531    }
30532
30533    function projectObject( object, camera, shadowCamera ) {
30534
30535        if ( object.visible === false ) return;
30536
30537        if ( object.layers.test( camera.layers ) && ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points ) ) {
30538
30539            if ( object.castShadow && ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) ) {
30540
30541                var material = object.material;
30542
30543                if ( material.visible === true ) {
30544
30545                    object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
30546                    _renderList.push( object );
30547
30548                }
30549
30550            }
30551
30552        }
30553
30554        var children = object.children;
30555
30556        for ( var i = 0, l = children.length; i < l; i ++ ) {
30557
30558            projectObject( children[ i ], camera, shadowCamera );
30559
30560        }
30561
30562    }
30563
30564};
30565
30566// File:src/renderers/webgl/WebGLState.js
30567
30568/**
30569 * @author mrdoob / http://mrdoob.com/
30570 */
30571
30572THREE.WebGLState = function ( gl, extensions, paramThreeToGL ) {
30573
30574    var _this = this;
30575
30576    var color = new THREE.Vector4();
30577
30578    var maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
30579    var newAttributes = new Uint8Array( maxVertexAttributes );
30580    var enabledAttributes = new Uint8Array( maxVertexAttributes );
30581    var attributeDivisors = new Uint8Array( maxVertexAttributes );
30582
30583    var capabilities = {};
30584
30585    var compressedTextureFormats = null;
30586
30587    var currentBlending = null;
30588    var currentBlendEquation = null;
30589    var currentBlendSrc = null;
30590    var currentBlendDst = null;
30591    var currentBlendEquationAlpha = null;
30592    var currentBlendSrcAlpha = null;
30593    var currentBlendDstAlpha = null;
30594    var currentPremultipledAlpha = false;
30595
30596    var currentDepthFunc = null;
30597    var currentDepthWrite = null;
30598
30599    var currentColorWrite = null;
30600
30601    var currentStencilWrite = null;
30602    var currentStencilFunc = null;
30603    var currentStencilRef = null;
30604    var currentStencilMask = null;
30605    var currentStencilFail  = null;
30606    var currentStencilZFail = null;
30607    var currentStencilZPass = null;
30608
30609    var currentFlipSided = null;
30610
30611    var currentLineWidth = null;
30612
30613    var currentPolygonOffsetFactor = null;
30614    var currentPolygonOffsetUnits = null;
30615
30616    var currentScissorTest = null;
30617
30618    var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
30619
30620    var currentTextureSlot = undefined;
30621    var currentBoundTextures = {};
30622
30623    var currentClearColor = new THREE.Vector4();
30624    var currentClearDepth = null;
30625    var currentClearStencil = null;
30626
30627    var currentScissor = new THREE.Vector4();
30628    var currentViewport = new THREE.Vector4();
30629
30630    this.init = function () {
30631
30632        this.clearColor( 0, 0, 0, 1 );
30633        this.clearDepth( 1 );
30634        this.clearStencil( 0 );
30635
30636        this.enable( gl.DEPTH_TEST );
30637        gl.depthFunc( gl.LEQUAL );
30638
30639        gl.frontFace( gl.CCW );
30640        gl.cullFace( gl.BACK );
30641        this.enable( gl.CULL_FACE );
30642
30643        this.enable( gl.BLEND );
30644        gl.blendEquation( gl.FUNC_ADD );
30645        gl.blendFunc( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA );
30646
30647    };
30648
30649    this.initAttributes = function () {
30650
30651        for ( var i = 0, l = newAttributes.length; i < l; i ++ ) {
30652
30653            newAttributes[ i ] = 0;
30654
30655        }
30656
30657    };
30658
30659    this.enableAttribute = function ( attribute ) {
30660
30661        newAttributes[ attribute ] = 1;
30662
30663        if ( enabledAttributes[ attribute ] === 0 ) {
30664
30665            gl.enableVertexAttribArray( attribute );
30666            enabledAttributes[ attribute ] = 1;
30667
30668        }
30669
30670        if ( attributeDivisors[ attribute ] !== 0 ) {
30671
30672            var extension = extensions.get( 'ANGLE_instanced_arrays' );
30673
30674            extension.vertexAttribDivisorANGLE( attribute, 0 );
30675            attributeDivisors[ attribute ] = 0;
30676
30677        }
30678
30679    };
30680
30681    this.enableAttributeAndDivisor = function ( attribute, meshPerAttribute, extension ) {
30682
30683        newAttributes[ attribute ] = 1;
30684
30685        if ( enabledAttributes[ attribute ] === 0 ) {
30686
30687            gl.enableVertexAttribArray( attribute );
30688            enabledAttributes[ attribute ] = 1;
30689
30690        }
30691
30692        if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
30693
30694            extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute );
30695            attributeDivisors[ attribute ] = meshPerAttribute;
30696
30697        }
30698
30699    };
30700
30701    this.disableUnusedAttributes = function () {
30702
30703        for ( var i = 0, l = enabledAttributes.length; i < l; i ++ ) {
30704
30705            if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
30706
30707                gl.disableVertexAttribArray( i );
30708                enabledAttributes[ i ] = 0;
30709
30710            }
30711
30712        }
30713
30714    };
30715
30716    this.enable = function ( id ) {
30717
30718        if ( capabilities[ id ] !== true ) {
30719
30720            gl.enable( id );
30721            capabilities[ id ] = true;
30722
30723        }
30724
30725    };
30726
30727    this.disable = function ( id ) {
30728
30729        if ( capabilities[ id ] !== false ) {
30730
30731            gl.disable( id );
30732            capabilities[ id ] = false;
30733
30734        }
30735
30736    };
30737
30738    this.getCompressedTextureFormats = function () {
30739
30740        if ( compressedTextureFormats === null ) {
30741
30742            compressedTextureFormats = [];
30743
30744            if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
30745                extensions.get( 'WEBGL_compressed_texture_s3tc' ) ||
30746                extensions.get( 'WEBGL_compressed_texture_etc1' ) ) {
30747
30748                var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS );
30749
30750                for ( var i = 0; i < formats.length; i ++ ) {
30751
30752                    compressedTextureFormats.push( formats[ i ] );
30753
30754                }
30755
30756            }
30757
30758        }
30759
30760        return compressedTextureFormats;
30761
30762    };
30763
30764    this.setBlending = function ( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
30765
30766        if ( blending === THREE.NoBlending ) {
30767
30768            this.disable( gl.BLEND );
30769
30770        } else {
30771
30772            this.enable( gl.BLEND );
30773
30774        }
30775
30776        if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
30777
30778            if ( blending === THREE.AdditiveBlending ) {
30779
30780                if ( premultipliedAlpha ) {
30781
30782                    gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
30783                    gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE );
30784
30785                } else {
30786
30787                    gl.blendEquation( gl.FUNC_ADD );
30788                    gl.blendFunc( gl.SRC_ALPHA, gl.ONE );
30789
30790                }
30791
30792            } else if ( blending === THREE.SubtractiveBlending ) {
30793
30794                if ( premultipliedAlpha ) {
30795
30796                    gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
30797                    gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA );
30798
30799                } else {
30800
30801                    gl.blendEquation( gl.FUNC_ADD );
30802                    gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR );
30803
30804                }
30805
30806            } else if ( blending === THREE.MultiplyBlending ) {
30807
30808                if ( premultipliedAlpha ) {
30809
30810                    gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
30811                    gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.SRC_COLOR, gl.SRC_ALPHA );
30812
30813                } else {
30814
30815                    gl.blendEquation( gl.FUNC_ADD );
30816                    gl.blendFunc( gl.ZERO, gl.SRC_COLOR );
30817
30818                }
30819
30820            } else {
30821
30822                if ( premultipliedAlpha ) {
30823
30824                    gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
30825                    gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
30826
30827                } else {
30828
30829                    gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
30830                    gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
30831
30832                }
30833
30834            }
30835
30836            currentBlending = blending;
30837            currentPremultipledAlpha = premultipliedAlpha;
30838
30839        }
30840
30841        if ( blending === THREE.CustomBlending ) {
30842
30843            blendEquationAlpha = blendEquationAlpha || blendEquation;
30844            blendSrcAlpha = blendSrcAlpha || blendSrc;
30845            blendDstAlpha = blendDstAlpha || blendDst;
30846
30847            if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
30848
30849                gl.blendEquationSeparate( paramThreeToGL( blendEquation ), paramThreeToGL( blendEquationAlpha ) );
30850
30851                currentBlendEquation = blendEquation;
30852                currentBlendEquationAlpha = blendEquationAlpha;
30853
30854            }
30855
30856            if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
30857
30858                gl.blendFuncSeparate( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ), paramThreeToGL( blendSrcAlpha ), paramThreeToGL( blendDstAlpha ) );
30859
30860                currentBlendSrc = blendSrc;
30861                currentBlendDst = blendDst;
30862                currentBlendSrcAlpha = blendSrcAlpha;
30863                currentBlendDstAlpha = blendDstAlpha;
30864
30865            }
30866
30867        } else {
30868
30869            currentBlendEquation = null;
30870            currentBlendSrc = null;
30871            currentBlendDst = null;
30872            currentBlendEquationAlpha = null;
30873            currentBlendSrcAlpha = null;
30874            currentBlendDstAlpha = null;
30875
30876        }
30877
30878    };
30879
30880    this.setDepthFunc = function ( depthFunc ) {
30881
30882        if ( currentDepthFunc !== depthFunc ) {
30883
30884            if ( depthFunc ) {
30885
30886                switch ( depthFunc ) {
30887
30888                    case THREE.NeverDepth:
30889
30890                        gl.depthFunc( gl.NEVER );
30891                        break;
30892
30893                    case THREE.AlwaysDepth:
30894
30895                        gl.depthFunc( gl.ALWAYS );
30896                        break;
30897
30898                    case THREE.LessDepth:
30899
30900                        gl.depthFunc( gl.LESS );
30901                        break;
30902
30903                    case THREE.LessEqualDepth:
30904
30905                        gl.depthFunc( gl.LEQUAL );
30906                        break;
30907
30908                    case THREE.EqualDepth:
30909
30910                        gl.depthFunc( gl.EQUAL );
30911                        break;
30912
30913                    case THREE.GreaterEqualDepth:
30914
30915                        gl.depthFunc( gl.GEQUAL );
30916                        break;
30917
30918                    case THREE.GreaterDepth:
30919
30920                        gl.depthFunc( gl.GREATER );
30921                        break;
30922
30923                    case THREE.NotEqualDepth:
30924
30925                        gl.depthFunc( gl.NOTEQUAL );
30926                        break;
30927
30928                    default:
30929
30930                        gl.depthFunc( gl.LEQUAL );
30931
30932                }
30933
30934            } else {
30935
30936                gl.depthFunc( gl.LEQUAL );
30937
30938            }
30939
30940            currentDepthFunc = depthFunc;
30941
30942        }
30943
30944    };
30945
30946    this.setDepthTest = function ( depthTest ) {
30947
30948        if ( depthTest ) {
30949
30950            this.enable( gl.DEPTH_TEST );
30951
30952        } else {
30953
30954            this.disable( gl.DEPTH_TEST );
30955
30956        }
30957
30958    };
30959
30960    this.setDepthWrite = function ( depthWrite ) {
30961
30962        // TODO: Rename to setDepthMask
30963
30964        if ( currentDepthWrite !== depthWrite ) {
30965
30966            gl.depthMask( depthWrite );
30967            currentDepthWrite = depthWrite;
30968
30969        }
30970
30971    };
30972
30973    this.setColorWrite = function ( colorWrite ) {
30974
30975        // TODO: Rename to setColorMask
30976
30977        if ( currentColorWrite !== colorWrite ) {
30978
30979            gl.colorMask( colorWrite, colorWrite, colorWrite, colorWrite );
30980            currentColorWrite = colorWrite;
30981
30982        }
30983
30984    };
30985
30986    this.setStencilFunc = function ( stencilFunc, stencilRef, stencilMask ) {
30987
30988        if ( currentStencilFunc !== stencilFunc ||
30989            currentStencilRef 	!== stencilRef 	||
30990            currentStencilMask !== stencilMask ) {
30991
30992            gl.stencilFunc( stencilFunc,  stencilRef, stencilMask );
30993
30994            currentStencilFunc = stencilFunc;
30995            currentStencilRef  = stencilRef;
30996            currentStencilMask = stencilMask;
30997
30998        }
30999
31000    };
31001
31002    this.setStencilOp = function ( stencilFail, stencilZFail, stencilZPass ) {
31003
31004        if ( currentStencilFail	 !== stencilFail 	||
31005            currentStencilZFail !== stencilZFail ||
31006            currentStencilZPass !== stencilZPass ) {
31007
31008            gl.stencilOp( stencilFail,  stencilZFail, stencilZPass );
31009
31010            currentStencilFail  = stencilFail;
31011            currentStencilZFail = stencilZFail;
31012            currentStencilZPass = stencilZPass;
31013
31014        }
31015
31016    };
31017
31018    this.setStencilTest = function ( stencilTest ) {
31019
31020        if ( stencilTest ) {
31021
31022            this.enable( gl.STENCIL_TEST );
31023
31024        } else {
31025
31026            this.disable( gl.STENCIL_TEST );
31027
31028        }
31029
31030    };
31031
31032    this.setStencilWrite = function ( stencilWrite ) {
31033
31034        // TODO: Rename to setStencilMask
31035
31036        if ( currentStencilWrite !== stencilWrite ) {
31037
31038            gl.stencilMask( stencilWrite );
31039            currentStencilWrite = stencilWrite;
31040
31041        }
31042
31043    };
31044
31045    this.setFlipSided = function ( flipSided ) {
31046
31047        if ( currentFlipSided !== flipSided ) {
31048
31049            if ( flipSided ) {
31050
31051                gl.frontFace( gl.CW );
31052
31053            } else {
31054
31055                gl.frontFace( gl.CCW );
31056
31057            }
31058
31059            currentFlipSided = flipSided;
31060
31061        }
31062
31063    };
31064
31065    this.setLineWidth = function ( width ) {
31066
31067        if ( width !== currentLineWidth ) {
31068
31069            gl.lineWidth( width );
31070
31071            currentLineWidth = width;
31072
31073        }
31074
31075    };
31076
31077    this.setPolygonOffset = function ( polygonOffset, factor, units ) {
31078
31079        if ( polygonOffset ) {
31080
31081            this.enable( gl.POLYGON_OFFSET_FILL );
31082
31083        } else {
31084
31085            this.disable( gl.POLYGON_OFFSET_FILL );
31086
31087        }
31088
31089        if ( polygonOffset && ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) ) {
31090
31091            gl.polygonOffset( factor, units );
31092
31093            currentPolygonOffsetFactor = factor;
31094            currentPolygonOffsetUnits = units;
31095
31096        }
31097
31098    };
31099
31100    this.getScissorTest = function () {
31101
31102        return currentScissorTest;
31103
31104    };
31105
31106    this.setScissorTest = function ( scissorTest ) {
31107
31108        currentScissorTest = scissorTest;
31109
31110        if ( scissorTest ) {
31111
31112            this.enable( gl.SCISSOR_TEST );
31113
31114        } else {
31115
31116            this.disable( gl.SCISSOR_TEST );
31117
31118        }
31119
31120    };
31121
31122    // texture
31123
31124    this.activeTexture = function ( webglSlot ) {
31125
31126        if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;
31127
31128        if ( currentTextureSlot !== webglSlot ) {
31129
31130            gl.activeTexture( webglSlot );
31131            currentTextureSlot = webglSlot;
31132
31133        }
31134
31135    };
31136
31137    this.bindTexture = function ( webglType, webglTexture ) {
31138
31139        if ( currentTextureSlot === undefined ) {
31140
31141            _this.activeTexture();
31142
31143        }
31144
31145        var boundTexture = currentBoundTextures[ currentTextureSlot ];
31146
31147        if ( boundTexture === undefined ) {
31148
31149            boundTexture = { type: undefined, texture: undefined };
31150            currentBoundTextures[ currentTextureSlot ] = boundTexture;
31151
31152        }
31153
31154        if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
31155
31156            gl.bindTexture( webglType, webglTexture );
31157
31158            boundTexture.type = webglType;
31159            boundTexture.texture = webglTexture;
31160
31161        }
31162
31163    };
31164
31165    this.compressedTexImage2D = function () {
31166
31167        try {
31168
31169            gl.compressedTexImage2D.apply( gl, arguments );
31170
31171        } catch ( error ) {
31172
31173            console.error( error );
31174
31175        }
31176
31177    };
31178
31179    this.texImage2D = function () {
31180
31181        try {
31182
31183            gl.texImage2D.apply( gl, arguments );
31184
31185        } catch ( error ) {
31186
31187            console.error( error );
31188
31189        }
31190
31191    };
31192
31193    // clear values
31194
31195    this.clearColor = function ( r, g, b, a ) {
31196
31197        color.set( r, g, b, a );
31198
31199        if ( currentClearColor.equals( color ) === false ) {
31200
31201            gl.clearColor( r, g, b, a );
31202            currentClearColor.copy( color );
31203
31204        }
31205
31206    };
31207
31208    this.clearDepth = function ( depth ) {
31209
31210        if ( currentClearDepth !== depth ) {
31211
31212            gl.clearDepth( depth );
31213            currentClearDepth = depth;
31214
31215        }
31216
31217    };
31218
31219    this.clearStencil = function ( stencil ) {
31220
31221        if ( currentClearStencil !== stencil ) {
31222
31223            gl.clearStencil( stencil );
31224            currentClearStencil = stencil;
31225
31226        }
31227
31228    };
31229
31230    //
31231
31232    this.scissor = function ( scissor ) {
31233
31234        if ( currentScissor.equals( scissor ) === false ) {
31235
31236            gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
31237            currentScissor.copy( scissor );
31238
31239        }
31240
31241    };
31242
31243    this.viewport = function ( viewport ) {
31244
31245        if ( currentViewport.equals( viewport ) === false ) {
31246
31247            gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
31248            currentViewport.copy( viewport );
31249
31250        }
31251
31252    };
31253
31254    //
31255
31256    this.reset = function () {
31257
31258        for ( var i = 0; i < enabledAttributes.length; i ++ ) {
31259
31260            if ( enabledAttributes[ i ] === 1 ) {
31261
31262                gl.disableVertexAttribArray( i );
31263                enabledAttributes[ i ] = 0;
31264
31265            }
31266
31267        }
31268
31269        capabilities = {};
31270
31271        compressedTextureFormats = null;
31272
31273        currentTextureSlot = undefined;
31274        currentBoundTextures = {};
31275
31276        currentBlending = null;
31277
31278        currentColorWrite = null;
31279        currentDepthWrite = null;
31280        currentStencilWrite = null;
31281
31282        currentFlipSided = null;
31283
31284    };
31285
31286};
31287
31288// File:src/renderers/webgl/WebGLUniforms.js
31289
31290/**
31291 *
31292 * Uniforms of a program.
31293 * Those form a tree structure with a special top-level container for the root,
31294 * which you get by calling 'new WebGLUniforms( gl, program, renderer )'.
31295 *
31296 *
31297 * Properties of inner nodes including the top-level container:
31298 *
31299 * .seq - array of nested uniforms
31300 * .map - nested uniforms by name
31301 *
31302 *
31303 * Methods of all nodes except the top-level container:
31304 *
31305 * .setValue( gl, value, [renderer] )
31306 *
31307 * 		uploads a uniform value(s)
31308 *  	the 'renderer' parameter is needed for sampler uniforms
31309 *
31310 *
31311 * Static methods of the top-level container (renderer factorizations):
31312 *
31313 * .upload( gl, seq, values, renderer )
31314 *
31315 * 		sets uniforms in 'seq' to 'values[id].value'
31316 *
31317 * .seqWithValue( seq, values ) : filteredSeq
31318 *
31319 * 		filters 'seq' entries with corresponding entry in values
31320 *
31321 * .splitDynamic( seq, values ) : filteredSeq
31322 *
31323 * 		filters 'seq' entries with dynamic entry and removes them from 'seq'
31324 *
31325 *
31326 * Methods of the top-level container (renderer factorizations):
31327 *
31328 * .setValue( gl, name, value )
31329 *
31330 * 		sets uniform with  name 'name' to 'value'
31331 *
31332 * .set( gl, obj, prop )
31333 *
31334 * 		sets uniform from object and property with same name than uniform
31335 *
31336 * .setOptional( gl, obj, prop )
31337 *
31338 * 		like .set for an optional property of the object
31339 *
31340 *
31341 * @author tschw
31342 *
31343 */
31344
31345THREE.WebGLUniforms = ( function() { // scope
31346
31347    // --- Base for inner nodes (including the root) ---
31348
31349    var UniformContainer = function() {
31350
31351            this.seq = [];
31352            this.map = {};
31353
31354        },
31355
31356    // --- Utilities ---
31357
31358    // Array Caches (provide typed arrays for temporary by size)
31359
31360        arrayCacheF32 = [],
31361        arrayCacheI32 = [],
31362
31363        uncacheTemporaryArrays = function() {
31364
31365            arrayCacheF32.length = 0;
31366            arrayCacheI32.length = 0;
31367
31368        },
31369
31370    // Flattening for arrays of vectors and matrices
31371
31372        flatten = function( array, nBlocks, blockSize ) {
31373
31374            var firstElem = array[ 0 ];
31375
31376            if ( firstElem <= 0 || firstElem > 0 ) return array;
31377            // unoptimized: ! isNaN( firstElem )
31378            // see http://jacksondunstan.com/articles/983
31379
31380            var n = nBlocks * blockSize,
31381                r = arrayCacheF32[ n ];
31382
31383            if ( r === undefined ) {
31384
31385                r = new Float32Array( n );
31386                arrayCacheF32[ n ] = r;
31387
31388            }
31389
31390            if ( nBlocks !== 0 ) {
31391
31392                firstElem.toArray( r, 0 );
31393
31394                for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) {
31395
31396                    offset += blockSize;
31397                    array[ i ].toArray( r, offset );
31398
31399                }
31400
31401            }
31402
31403            return r;
31404
31405        },
31406
31407    // Texture unit allocation
31408
31409        allocTexUnits = function( renderer, n ) {
31410
31411            var r = arrayCacheI32[ n ];
31412
31413            if ( r === undefined ) {
31414
31415                r = new Int32Array( n );
31416                arrayCacheI32[ n ] = r;
31417
31418            }
31419
31420            for ( var i = 0; i !== n; ++ i )
31421                r[ i ] = renderer.allocTextureUnit();
31422
31423            return r;
31424
31425        },
31426
31427    // --- Setters ---
31428
31429    // Note: Defining these methods externally, because they come in a bunch
31430    // and this way their names minify.
31431
31432    // Single scalar
31433
31434        setValue1f = function( gl, v ) { gl.uniform1f( this.addr, v ); },
31435        setValue1i = function( gl, v ) { gl.uniform1i( this.addr, v ); },
31436
31437    // Single float vector (from flat array or THREE.VectorN)
31438
31439        setValue2fv = function( gl, v ) {
31440
31441            if ( v.x === undefined ) gl.uniform2fv( this.addr, v );
31442            else gl.uniform2f( this.addr, v.x, v.y );
31443
31444        },
31445
31446        setValue3fv = function( gl, v ) {
31447
31448            if ( v.x !== undefined )
31449                gl.uniform3f( this.addr, v.x, v.y, v.z );
31450            else if ( v.r !== undefined )
31451                gl.uniform3f( this.addr, v.r, v.g, v.b );
31452            else
31453                gl.uniform3fv( this.addr, v );
31454
31455        },
31456
31457        setValue4fv = function( gl, v ) {
31458
31459            if ( v.x === undefined ) gl.uniform4fv( this.addr, v );
31460            else gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
31461
31462        },
31463
31464    // Single matrix (from flat array or MatrixN)
31465
31466        setValue2fm = function( gl, v ) {
31467
31468            gl.uniformMatrix2fv( this.addr, false, v.elements || v );
31469
31470        },
31471
31472        setValue3fm = function( gl, v ) {
31473
31474            gl.uniformMatrix3fv( this.addr, false, v.elements || v );
31475
31476        },
31477
31478        setValue4fm = function( gl, v ) {
31479
31480            gl.uniformMatrix4fv( this.addr, false, v.elements || v );
31481
31482        },
31483
31484    // Single texture (2D / Cube)
31485
31486        setValueT1 = function( gl, v, renderer ) {
31487
31488            var unit = renderer.allocTextureUnit();
31489            gl.uniform1i( this.addr, unit );
31490            if ( v ) renderer.setTexture2D( v, unit );
31491
31492        },
31493
31494        setValueT6 = function( gl, v, renderer ) {
31495
31496            var unit = renderer.allocTextureUnit();
31497            gl.uniform1i( this.addr, unit );
31498            if ( v ) renderer.setTextureCube( v, unit );
31499
31500        },
31501
31502    // Integer / Boolean vectors or arrays thereof (always flat arrays)
31503
31504        setValue2iv = function( gl, v ) { gl.uniform2iv( this.addr, v ); },
31505        setValue3iv = function( gl, v ) { gl.uniform3iv( this.addr, v ); },
31506        setValue4iv = function( gl, v ) { gl.uniform4iv( this.addr, v ); },
31507
31508    // Helper to pick the right setter for the singular case
31509
31510        getSingularSetter = function( type ) {
31511
31512            switch ( type ) {
31513
31514                case 0x1406: return setValue1f; // FLOAT
31515                case 0x8b50: return setValue2fv; // _VEC2
31516                case 0x8b51: return setValue3fv; // _VEC3
31517                case 0x8b52: return setValue4fv; // _VEC4
31518
31519                case 0x8b5a: return setValue2fm; // _MAT2
31520                case 0x8b5b: return setValue3fm; // _MAT3
31521                case 0x8b5c: return setValue4fm; // _MAT4
31522
31523                case 0x8b5e: return setValueT1; // SAMPLER_2D
31524                case 0x8b60: return setValueT6; // SAMPLER_CUBE
31525
31526                case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL
31527                case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
31528                case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
31529                case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
31530
31531            }
31532
31533        },
31534
31535    // Array of scalars
31536
31537        setValue1fv = function( gl, v ) { gl.uniform1fv( this.addr, v ); },
31538        setValue1iv = function( gl, v ) { gl.uniform1iv( this.addr, v ); },
31539
31540    // Array of vectors (flat or from THREE classes)
31541
31542        setValueV2a = function( gl, v ) {
31543
31544            gl.uniform2fv( this.addr, flatten( v, this.size, 2 ) );
31545
31546        },
31547
31548        setValueV3a = function( gl, v ) {
31549
31550            gl.uniform3fv( this.addr, flatten( v, this.size, 3 ) );
31551
31552        },
31553
31554        setValueV4a = function( gl, v ) {
31555
31556            gl.uniform4fv( this.addr, flatten( v, this.size, 4 ) );
31557
31558        },
31559
31560    // Array of matrices (flat or from THREE clases)
31561
31562        setValueM2a = function( gl, v ) {
31563
31564            gl.uniformMatrix2fv( this.addr, false, flatten( v, this.size, 4 ) );
31565
31566        },
31567
31568        setValueM3a = function( gl, v ) {
31569
31570            gl.uniformMatrix3fv( this.addr, false, flatten( v, this.size, 9 ) );
31571
31572        },
31573
31574        setValueM4a = function( gl, v ) {
31575
31576            gl.uniformMatrix4fv( this.addr, false, flatten( v, this.size, 16 ) );
31577
31578        },
31579
31580    // Array of textures (2D / Cube)
31581
31582        setValueT1a = function( gl, v, renderer ) {
31583
31584            var n = v.length,
31585                units = allocTexUnits( renderer, n );
31586
31587            gl.uniform1iv( this.addr, units );
31588
31589            for ( var i = 0; i !== n; ++ i ) {
31590
31591                var tex = v[ i ];
31592                if ( tex ) renderer.setTexture2D( tex, units[ i ] );
31593
31594            }
31595
31596        },
31597
31598        setValueT6a = function( gl, v, renderer ) {
31599
31600            var n = v.length,
31601                units = allocTexUnits( renderer, n );
31602
31603            gl.uniform1iv( this.addr, units );
31604
31605            for ( var i = 0; i !== n; ++ i ) {
31606
31607                var tex = v[ i ];
31608                if ( tex ) renderer.setTextureCube( tex, units[ i ] );
31609
31610            }
31611
31612        },
31613
31614
31615    // Helper to pick the right setter for a pure (bottom-level) array
31616
31617        getPureArraySetter = function( type ) {
31618
31619            switch ( type ) {
31620
31621                case 0x1406: return setValue1fv; // FLOAT
31622                case 0x8b50: return setValueV2a; // _VEC2
31623                case 0x8b51: return setValueV3a; // _VEC3
31624                case 0x8b52: return setValueV4a; // _VEC4
31625
31626                case 0x8b5a: return setValueM2a; // _MAT2
31627                case 0x8b5b: return setValueM3a; // _MAT3
31628                case 0x8b5c: return setValueM4a; // _MAT4
31629
31630                case 0x8b5e: return setValueT1a; // SAMPLER_2D
31631                case 0x8b60: return setValueT6a; // SAMPLER_CUBE
31632
31633                case 0x1404: case 0x8b56: return setValue1iv; // INT, BOOL
31634                case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2
31635                case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3
31636                case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4
31637
31638            }
31639
31640        },
31641
31642    // --- Uniform Classes ---
31643
31644        SingleUniform = function SingleUniform( id, activeInfo, addr ) {
31645
31646            this.id = id;
31647            this.addr = addr;
31648            this.setValue = getSingularSetter( activeInfo.type );
31649
31650            // this.path = activeInfo.name; // DEBUG
31651
31652        },
31653
31654        PureArrayUniform = function( id, activeInfo, addr ) {
31655
31656            this.id = id;
31657            this.addr = addr;
31658            this.size = activeInfo.size;
31659            this.setValue = getPureArraySetter( activeInfo.type );
31660
31661            // this.path = activeInfo.name; // DEBUG
31662
31663        },
31664
31665        StructuredUniform = function( id ) {
31666
31667            this.id = id;
31668
31669            UniformContainer.call( this ); // mix-in
31670
31671        };
31672
31673    StructuredUniform.prototype.setValue = function( gl, value ) {
31674
31675        // Note: Don't need an extra 'renderer' parameter, since samplers
31676        // are not allowed in structured uniforms.
31677
31678        var seq = this.seq;
31679
31680        for ( var i = 0, n = seq.length; i !== n; ++ i ) {
31681
31682            var u = seq[ i ];
31683            u.setValue( gl, value[ u.id ] );
31684
31685        }
31686
31687    };
31688
31689    // --- Top-level ---
31690
31691    // Parser - builds up the property tree from the path strings
31692
31693    var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g,
31694    // extracts
31695    // 	- the identifier (member name or array index)
31696    //  - followed by an optional right bracket (found when array index)
31697    //  - followed by an optional left bracket or dot (type of subscript)
31698    //
31699    // Note: These portions can be read in a non-overlapping fashion and
31700    // allow straightforward parsing of the hierarchy that WebGL encodes
31701    // in the uniform names.
31702
31703        addUniform = function( container, uniformObject ) {
31704
31705            container.seq.push( uniformObject );
31706            container.map[ uniformObject.id ] = uniformObject;
31707
31708        },
31709
31710        parseUniform = function( activeInfo, addr, container ) {
31711
31712            var path = activeInfo.name,
31713                pathLength = path.length;
31714
31715            // reset RegExp object, because of the early exit of a previous run
31716            RePathPart.lastIndex = 0;
31717
31718            for (; ;) {
31719
31720                var match = RePathPart.exec( path ),
31721                    matchEnd = RePathPart.lastIndex,
31722
31723                    id = match[ 1 ],
31724                    idIsIndex = match[ 2 ] === ']',
31725                    subscript = match[ 3 ];
31726
31727                if ( idIsIndex ) id = id | 0; // convert to integer
31728
31729                if ( subscript === undefined ||
31730                    subscript === '[' && matchEnd + 2 === pathLength ) {
31731                    // bare name or "pure" bottom-level array "[0]" suffix
31732
31733                    addUniform( container, subscript === undefined ?
31734                        new SingleUniform( id, activeInfo, addr ) :
31735                        new PureArrayUniform( id, activeInfo, addr ) );
31736
31737                    break;
31738
31739                } else {
31740                    // step into inner node / create it in case it doesn't exist
31741
31742                    var map = container.map,
31743                        next = map[ id ];
31744
31745                    if ( next === undefined ) {
31746
31747                        next = new StructuredUniform( id );
31748                        addUniform( container, next );
31749
31750                    }
31751
31752                    container = next;
31753
31754                }
31755
31756            }
31757
31758        },
31759
31760    // Root Container
31761
31762        WebGLUniforms = function WebGLUniforms( gl, program, renderer ) {
31763
31764            UniformContainer.call( this );
31765
31766            this.renderer = renderer;
31767
31768            var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
31769
31770            for ( var i = 0; i !== n; ++ i ) {
31771
31772                var info = gl.getActiveUniform( program, i ),
31773                    path = info.name,
31774                    addr = gl.getUniformLocation( program, path );
31775
31776                parseUniform( info, addr, this );
31777
31778            }
31779
31780        };
31781
31782
31783    WebGLUniforms.prototype.setValue = function( gl, name, value ) {
31784
31785        var u = this.map[ name ];
31786
31787        if ( u !== undefined ) u.setValue( gl, value, this.renderer );
31788
31789    };
31790
31791    WebGLUniforms.prototype.set = function( gl, object, name ) {
31792
31793        var u = this.map[ name ];
31794
31795        if ( u !== undefined ) u.setValue( gl, object[ name ], this.renderer );
31796
31797    };
31798
31799    WebGLUniforms.prototype.setOptional = function( gl, object, name ) {
31800
31801        var v = object[ name ];
31802
31803        if ( v !== undefined ) this.setValue( gl, name, v );
31804
31805    };
31806
31807
31808    // Static interface
31809
31810    WebGLUniforms.upload = function( gl, seq, values, renderer ) {
31811
31812        for ( var i = 0, n = seq.length; i !== n; ++ i ) {
31813
31814            var u = seq[ i ],
31815                v = values[ u.id ];
31816
31817            if ( v.needsUpdate !== false ) {
31818                // note: always updating when .needsUpdate is undefined
31819
31820                u.setValue( gl, v.value, renderer );
31821
31822            }
31823
31824        }
31825
31826    };
31827
31828    WebGLUniforms.seqWithValue = function( seq, values ) {
31829
31830        var r = [];
31831
31832        for ( var i = 0, n = seq.length; i !== n; ++ i ) {
31833
31834            var u = seq[ i ];
31835            if ( u.id in values ) r.push( u );
31836
31837        }
31838
31839        return r;
31840
31841    };
31842
31843    WebGLUniforms.splitDynamic = function( seq, values ) {
31844
31845        var r = null,
31846            n = seq.length,
31847            w = 0;
31848
31849        for ( var i = 0; i !== n; ++ i ) {
31850
31851            var u = seq[ i ],
31852                v = values[ u.id ];
31853
31854            if ( v && v.dynamic === true ) {
31855
31856                if ( r === null ) r = [];
31857                r.push( u );
31858
31859            } else {
31860
31861                // in-place compact 'seq', removing the matches
31862                if ( w < i ) seq[ w ] = u;
31863                ++ w;
31864
31865            }
31866
31867        }
31868
31869        if ( w < n ) seq.length = w;
31870
31871        return r;
31872
31873    };
31874
31875    WebGLUniforms.evalDynamic = function( seq, values, object, camera ) {
31876
31877        for ( var i = 0, n = seq.length; i !== n; ++ i ) {
31878
31879            var v = values[ seq[ i ].id ],
31880                f = v.onUpdateCallback;
31881
31882            if ( f !== undefined ) f.call( v, object, camera );
31883
31884        }
31885
31886    };
31887
31888    return WebGLUniforms;
31889
31890} )();
31891
31892
31893// File:src/renderers/webgl/plugins/LensFlarePlugin.js
31894
31895/**
31896 * @author mikael emtinger / http://gomo.se/
31897 * @author alteredq / http://alteredqualia.com/
31898 */
31899
31900THREE.LensFlarePlugin = function ( renderer, flares ) {
31901
31902    var gl = renderer.context;
31903    var state = renderer.state;
31904
31905    var vertexBuffer, elementBuffer;
31906    var shader, program, attributes, uniforms;
31907
31908    var tempTexture, occlusionTexture;
31909
vendor: 4,331 bytes, lines 31910-32035
31910    function init() {
31911
31912        var vertices = new Float32Array( [
31913            - 1, - 1,  0, 0,
31914            1, - 1,  1, 0,
31915            1,  1,  1, 1,
31916            - 1,  1,  0, 1
31917        ] );
31918
31919        var faces = new Uint16Array( [
31920            0, 1, 2,
31921            0, 2, 3
31922        ] );
31923
31924        // buffers
31925
31926        vertexBuffer     = gl.createBuffer();
31927        elementBuffer    = gl.createBuffer();
31928
31929        gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
31930        gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );
31931
31932        gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
31933        gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW );
31934
31935        // textures
31936
31937        tempTexture      = gl.createTexture();
31938        occlusionTexture = gl.createTexture();
31939
31940        state.bindTexture( gl.TEXTURE_2D, tempTexture );
31941        gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null );
31942        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
31943        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
31944        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
31945        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
31946
31947        state.bindTexture( gl.TEXTURE_2D, occlusionTexture );
31948        gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null );
31949        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
31950        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
31951        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
31952        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
31953
31954        shader = {
31955
31956            vertexShader: [
31957
31958                "uniform lowp int renderType;",
31959
31960                "uniform vec3 screenPosition;",
31961                "uniform vec2 scale;",
31962                "uniform float rotation;",
31963
31964                "uniform sampler2D occlusionMap;",
31965
31966                "attribute vec2 position;",
31967                "attribute vec2 uv;",
31968
31969                "varying vec2 vUV;",
31970                "varying float vVisibility;",
31971
31972                "void main() {",
31973
31974                "vUV = uv;",
31975
31976                "vec2 pos = position;",
31977
31978                "if ( renderType == 2 ) {",
31979
31980                "vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );",
31981                "visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );",
31982                "visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );",
31983                "visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );",
31984                "visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );",
31985                "visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );",
31986                "visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );",
31987                "visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );",
31988                "visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );",
31989
31990                "vVisibility =        visibility.r / 9.0;",
31991                "vVisibility *= 1.0 - visibility.g / 9.0;",
31992                "vVisibility *=       visibility.b / 9.0;",
31993                "vVisibility *= 1.0 - visibility.a / 9.0;",
31994
31995                "pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;",
31996                "pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;",
31997
31998                "}",
31999
32000                "gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );",
32001
32002                "}"
32003
32004            ].join( "\n" ),
32005
32006            fragmentShader: [
32007
32008                "uniform lowp int renderType;",
32009
32010                "uniform sampler2D map;",
32011                "uniform float opacity;",
32012                "uniform vec3 color;",
32013
32014                "varying vec2 vUV;",
32015                "varying float vVisibility;",
32016
32017                "void main() {",
32018
32019                // pink square
32020
32021                "if ( renderType == 0 ) {",
32022
32023                "gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );",
32024
32025                // restore
32026
32027                "} else if ( renderType == 1 ) {",
32028
32029                "gl_FragColor = texture2D( map, vUV );",
32030
32031                // flare
32032
32033                "} else {",
32034
32035                "vec4 texture = texture2D( map, vUV );",
32036                "texture.a *= opacity * vVisibility;",
32037                "gl_FragColor = texture;",
32038                "gl_FragColor.rgb *= color;",
32039
32040                "}",
32041
32042                "}"
32043
32044            ].join( "\n" )
32045
32046        };
32047
32048        program = createProgram( shader );
32049
32050        attributes = {
32051            vertex: gl.getAttribLocation ( program, "position" ),
32052            uv:     gl.getAttribLocation ( program, "uv" )
32053        };
32054
32055        uniforms = {
32056            renderType:     gl.getUniformLocation( program, "renderType" ),
32057            map:            gl.getUniformLocation( program, "map" ),
32058            occlusionMap:   gl.getUniformLocation( program, "occlusionMap" ),
32059            opacity:        gl.getUniformLocation( program, "opacity" ),
32060            color:          gl.getUniformLocation( program, "color" ),
32061            scale:          gl.getUniformLocation( program, "scale" ),
32062            rotation:       gl.getUniformLocation( program, "rotation" ),
32063            screenPosition: gl.getUniformLocation( program, "screenPosition" )
32064        };
32065
32066    }
32067
32068    /*
32069     * Render lens flares
32070     * Method: renders 16x16 0xff00ff-colored points scattered over the light source area,
32071     *         reads these back and calculates occlusion.
32072     */
32073
32074    this.render = function ( scene, camera, viewport ) {
32075
32076        if ( flares.length === 0 ) return;
32077
32078        var tempPosition = new THREE.Vector3();
32079
32080        var invAspect = viewport.w / viewport.z,
32081            halfViewportWidth = viewport.z * 0.5,
32082            halfViewportHeight = viewport.w * 0.5;
32083
32084        var size = 16 / viewport.w,
32085            scale = new THREE.Vector2( size * invAspect, size );
32086
32087        var screenPosition = new THREE.Vector3( 1, 1, 0 ),
32088            screenPositionPixels = new THREE.Vector2( 1, 1 );
32089
32090        var validArea = new THREE.Box2();
32091
32092        validArea.min.set( 0, 0 );
32093        validArea.max.set( viewport.z - 16, viewport.w - 16 );
32094
32095        if ( program === undefined ) {
32096
32097            init();
32098
32099        }
32100
32101        gl.useProgram( program );
32102
32103        state.initAttributes();
32104        state.enableAttribute( attributes.vertex );
32105        state.enableAttribute( attributes.uv );
32106        state.disableUnusedAttributes();
32107
32108        // loop through all lens flares to update their occlusion and positions
32109        // setup gl and common used attribs/uniforms
32110
32111        gl.uniform1i( uniforms.occlusionMap, 0 );
32112        gl.uniform1i( uniforms.map, 1 );
32113
32114        gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
32115        gl.vertexAttribPointer( attributes.vertex, 2, gl.FLOAT, false, 2 * 8, 0 );
32116        gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 );
32117
32118        gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
32119
32120        state.disable( gl.CULL_FACE );
32121        state.setDepthWrite( false );
32122
32123        for ( var i = 0, l = flares.length; i < l; i ++ ) {
32124
32125            size = 16 / viewport.w;
32126            scale.set( size * invAspect, size );
32127
32128            // calc object screen position
32129
32130            var flare = flares[ i ];
32131
32132            tempPosition.set( flare.matrixWorld.elements[ 12 ], flare.matrixWorld.elements[ 13 ], flare.matrixWorld.elements[ 14 ] );
32133
32134            tempPosition.applyMatrix4( camera.matrixWorldInverse );
32135            tempPosition.applyProjection( camera.projectionMatrix );
32136
32137            // setup arrays for gl programs
32138
32139            screenPosition.copy( tempPosition );
32140
32141            // horizontal and vertical coordinate of the lower left corner of the pixels to copy
32142
32143            screenPositionPixels.x = viewport.x + ( screenPosition.x * halfViewportWidth ) + halfViewportWidth - 8;
32144            screenPositionPixels.y = viewport.y + ( screenPosition.y * halfViewportHeight ) + halfViewportHeight - 8;
32145
32146            // screen cull
32147
32148            if ( validArea.containsPoint( screenPositionPixels ) === true ) {
32149
32150                // save current RGB to temp texture
32151
32152                state.activeTexture( gl.TEXTURE0 );
32153                state.bindTexture( gl.TEXTURE_2D, null );
32154                state.activeTexture( gl.TEXTURE1 );
32155                state.bindTexture( gl.TEXTURE_2D, tempTexture );
32156                gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGB, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 );
32157
32158
32159                // render pink quad
32160
32161                gl.uniform1i( uniforms.renderType, 0 );
32162                gl.uniform2f( uniforms.scale, scale.x, scale.y );
32163                gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
32164
32165                state.disable( gl.BLEND );
32166                state.enable( gl.DEPTH_TEST );
32167
32168                gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
32169
32170
32171                // copy result to occlusionMap
32172
32173                state.activeTexture( gl.TEXTURE0 );
32174                state.bindTexture( gl.TEXTURE_2D, occlusionTexture );
32175                gl.copyTexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0 );
32176
32177
32178                // restore graphics
32179
32180                gl.uniform1i( uniforms.renderType, 1 );
32181                state.disable( gl.DEPTH_TEST );
32182
32183                state.activeTexture( gl.TEXTURE1 );
32184                state.bindTexture( gl.TEXTURE_2D, tempTexture );
32185                gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
32186
32187
32188                // update object positions
32189
32190                flare.positionScreen.copy( screenPosition );
32191
32192                if ( flare.customUpdateCallback ) {
32193
32194                    flare.customUpdateCallback( flare );
32195
32196                } else {
32197
32198                    flare.updateLensFlares();
32199
32200                }
32201
32202                // render flares
32203
32204                gl.uniform1i( uniforms.renderType, 2 );
32205                state.enable( gl.BLEND );
32206
32207                for ( var j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) {
32208
32209                    var sprite = flare.lensFlares[ j ];
32210
32211                    if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) {
32212
32213                        screenPosition.x = sprite.x;
32214                        screenPosition.y = sprite.y;
32215                        screenPosition.z = sprite.z;
32216
32217                        size = sprite.size * sprite.scale / viewport.w;
32218
32219                        scale.x = size * invAspect;
32220                        scale.y = size;
32221
32222                        gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
32223                        gl.uniform2f( uniforms.scale, scale.x, scale.y );
32224                        gl.uniform1f( uniforms.rotation, sprite.rotation );
32225
32226                        gl.uniform1f( uniforms.opacity, sprite.opacity );
32227                        gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b );
32228
32229                        state.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst );
32230                        renderer.setTexture2D( sprite.texture, 1 );
32231
32232                        gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
32233
32234                    }
32235
32236                }
32237
32238            }
32239
32240        }
32241
32242        // restore gl
32243
32244        state.enable( gl.CULL_FACE );
32245        state.enable( gl.DEPTH_TEST );
32246        state.setDepthWrite( true );
32247
32248        renderer.resetGLState();
32249
32250    };
32251
32252    function createProgram ( shader ) {
32253
32254        var program = gl.createProgram();
32255
32256        var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
32257        var vertexShader = gl.createShader( gl.VERTEX_SHADER );
32258
32259        var prefix = "precision " + renderer.getPrecision() + " float;\n";
32260
32261        gl.shaderSource( fragmentShader, prefix + shader.fragmentShader );
32262        gl.shaderSource( vertexShader, prefix + shader.vertexShader );
32263
32264        gl.compileShader( fragmentShader );
32265        gl.compileShader( vertexShader );
32266
32267        gl.attachShader( program, fragmentShader );
32268        gl.attachShader( program, vertexShader );
32269
32270        gl.linkProgram( program );
32271
32272        return program;
32273
32274    }
32275
32276};
32277
32278// File:src/renderers/webgl/plugins/SpritePlugin.js
32279
32280/**
32281 * @author mikael emtinger / http://gomo.se/
32282 * @author alteredq / http://alteredqualia.com/
32283 */
32284
32285THREE.SpritePlugin = function ( renderer, sprites ) {
32286
32287    var gl = renderer.context;
32288    var state = renderer.state;
32289
32290    var vertexBuffer, elementBuffer;
32291    var program, attributes, uniforms;
32292
32293    var texture;
32294
32295    // decompose matrixWorld
32296
32297    var spritePosition = new THREE.Vector3();
32298    var spriteRotation = new THREE.Quaternion();
32299    var spriteScale = new THREE.Vector3();
32300
32301    function init() {
32302
32303        var vertices = new Float32Array( [
32304            - 0.5, - 0.5,  0, 0,
32305            0.5, - 0.5,  1, 0,
32306            0.5,   0.5,  1, 1,
32307            - 0.5,   0.5,  0, 1
32308        ] );
32309
32310        var faces = new Uint16Array( [
32311            0, 1, 2,
32312            0, 2, 3
32313        ] );
32314
32315        vertexBuffer  = gl.createBuffer();
32316        elementBuffer = gl.createBuffer();
32317
32318        gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
32319        gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW );
32320
32321        gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
32322        gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW );
32323
32324        program = createProgram();
32325
32326        attributes = {
32327            position:			gl.getAttribLocation ( program, 'position' ),
32328            uv:					gl.getAttribLocation ( program, 'uv' )
32329        };
32330
32331        uniforms = {
32332            uvOffset:			gl.getUniformLocation( program, 'uvOffset' ),
32333            uvScale:			gl.getUniformLocation( program, 'uvScale' ),
32334
32335            rotation:			gl.getUniformLocation( program, 'rotation' ),
32336            scale:				gl.getUniformLocation( program, 'scale' ),
32337
32338            color:				gl.getUniformLocation( program, 'color' ),
32339            map:				gl.getUniformLocation( program, 'map' ),
32340            opacity:			gl.getUniformLocation( program, 'opacity' ),
32341
32342            modelViewMatrix: 	gl.getUniformLocation( program, 'modelViewMatrix' ),
32343            projectionMatrix:	gl.getUniformLocation( program, 'projectionMatrix' ),
32344
32345            fogType:			gl.getUniformLocation( program, 'fogType' ),
32346            fogDensity:			gl.getUniformLocation( program, 'fogDensity' ),
32347            fogNear:			gl.getUniformLocation( program, 'fogNear' ),
32348            fogFar:				gl.getUniformLocation( program, 'fogFar' ),
32349            fogColor:			gl.getUniformLocation( program, 'fogColor' ),
32350
32351            alphaTest:			gl.getUniformLocation( program, 'alphaTest' )
32352        };
32353
32354        var canvas = document.createElement( 'canvas' );
32355        canvas.width = 8;
32356        canvas.height = 8;
32357
32358        var context = canvas.getContext( '2d' );
32359        context.fillStyle = 'white';
32360        context.fillRect( 0, 0, 8, 8 );
32361
32362        texture = new THREE.Texture( canvas );
32363        texture.needsUpdate = true;
32364
32365    }
32366
32367    this.render = function ( scene, camera ) {
32368
32369        if ( sprites.length === 0 ) return;
32370
32371        // setup gl
32372
32373        if ( program === undefined ) {
32374
32375            init();
32376
32377        }
32378
32379        gl.useProgram( program );
32380
32381        state.initAttributes();
32382        state.enableAttribute( attributes.position );
32383        state.enableAttribute( attributes.uv );
32384        state.disableUnusedAttributes();
32385
32386        state.disable( gl.CULL_FACE );
32387        state.enable( gl.BLEND );
32388
32389        gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer );
32390        gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 );
32391        gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 );
32392
32393        gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
32394
32395        gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements );
32396
32397        state.activeTexture( gl.TEXTURE0 );
32398        gl.uniform1i( uniforms.map, 0 );
32399
32400        var oldFogType = 0;
32401        var sceneFogType = 0;
32402        var fog = scene.fog;
32403
32404        if ( fog ) {
32405
32406            gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b );
32407
32408            if ( fog instanceof THREE.Fog ) {
32409
32410                gl.uniform1f( uniforms.fogNear, fog.near );
32411                gl.uniform1f( uniforms.fogFar, fog.far );
32412
32413                gl.uniform1i( uniforms.fogType, 1 );
32414                oldFogType = 1;
32415                sceneFogType = 1;
32416
32417            } else if ( fog instanceof THREE.FogExp2 ) {
32418
32419                gl.uniform1f( uniforms.fogDensity, fog.density );
32420
32421                gl.uniform1i( uniforms.fogType, 2 );
32422                oldFogType = 2;
32423                sceneFogType = 2;
32424
32425            }
32426
32427        } else {
32428
32429            gl.uniform1i( uniforms.fogType, 0 );
32430            oldFogType = 0;
32431            sceneFogType = 0;
32432
32433        }
32434
32435
32436        // update positions and sort
32437
32438        for ( var i = 0, l = sprites.length; i < l; i ++ ) {
32439
32440            var sprite = sprites[ i ];
32441
32442            sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
32443            sprite.z = - sprite.modelViewMatrix.elements[ 14 ];
32444
32445        }
32446
32447        sprites.sort( painterSortStable );
32448
32449        // render all sprites
32450
32451        var scale = [];
32452
32453        for ( var i = 0, l = sprites.length; i < l; i ++ ) {
32454
32455            var sprite = sprites[ i ];
32456            var material = sprite.material;
32457
32458            gl.uniform1f( uniforms.alphaTest, material.alphaTest );
32459            gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements );
32460
32461            sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale );
32462
32463            scale[ 0 ] = spriteScale.x;
32464            scale[ 1 ] = spriteScale.y;
32465
32466            var fogType = 0;
32467
32468            if ( scene.fog && material.fog ) {
32469
32470                fogType = sceneFogType;
32471
32472            }
32473
32474            if ( oldFogType !== fogType ) {
32475
32476                gl.uniform1i( uniforms.fogType, fogType );
32477                oldFogType = fogType;
32478
32479            }
32480
32481            if ( material.map !== null ) {
32482
32483                gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y );
32484                gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y );
32485
32486            } else {
32487
32488                gl.uniform2f( uniforms.uvOffset, 0, 0 );
32489                gl.uniform2f( uniforms.uvScale, 1, 1 );
32490
32491            }
32492
32493            gl.uniform1f( uniforms.opacity, material.opacity );
32494            gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b );
32495
32496            gl.uniform1f( uniforms.rotation, material.rotation );
32497            gl.uniform2fv( uniforms.scale, scale );
32498
32499            state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
32500            state.setDepthTest( material.depthTest );
32501            state.setDepthWrite( material.depthWrite );
32502
32503            if ( material.map ) {
32504
32505                renderer.setTexture2D( material.map, 0 );
32506
32507            } else {
32508
32509                renderer.setTexture2D( texture, 0 );
32510
32511            }
32512
32513            gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 );
32514
32515        }
32516
32517        // restore gl
32518
32519        state.enable( gl.CULL_FACE );
32520
32521        renderer.resetGLState();
32522
32523    };
32524
32525    function createProgram () {
32526
32527        var program = gl.createProgram();
32528
32529        var vertexShader = gl.createShader( gl.VERTEX_SHADER );
32530        var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER );
32531
32532        gl.shaderSource( vertexShader, [
32533
32534            'precision ' + renderer.getPrecision() + ' float;',
32535
32536            'uniform mat4 modelViewMatrix;',
32537            'uniform mat4 projectionMatrix;',
32538            'uniform float rotation;',
32539            'uniform vec2 scale;',
32540            'uniform vec2 uvOffset;',
32541            'uniform vec2 uvScale;',
32542
32543            'attribute vec2 position;',
32544            'attribute vec2 uv;',
32545
32546            'varying vec2 vUV;',
32547
32548            'void main() {',
32549
32550            'vUV = uvOffset + uv * uvScale;',
32551
32552            'vec2 alignedPosition = position * scale;',
32553
32554            'vec2 rotatedPosition;',
32555            'rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;',
32556            'rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;',
32557
32558            'vec4 finalPosition;',
32559
32560            'finalPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );',
32561            'finalPosition.xy += rotatedPosition;',
32562            'finalPosition = projectionMatrix * finalPosition;',
32563
32564            'gl_Position = finalPosition;',
32565
32566            '}'
32567
32568        ].join( '\n' ) );
32569
32570        gl.shaderSource( fragmentShader, [
32571
32572            'precision ' + renderer.getPrecision() + ' float;',
32573
32574            'uniform vec3 color;',
32575            'uniform sampler2D map;',
32576            'uniform float opacity;',
32577
32578            'uniform int fogType;',
32579            'uniform vec3 fogColor;',
32580            'uniform float fogDensity;',
32581            'uniform float fogNear;',
32582            'uniform float fogFar;',
32583            'uniform float alphaTest;',
32584
32585            'varying vec2 vUV;',
32586
32587            'void main() {',
32588
32589            'vec4 texture = texture2D( map, vUV );',
32590
32591            'if ( texture.a < alphaTest ) discard;',
32592
32593            'gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );',
32594
32595            'if ( fogType > 0 ) {',
32596
32597            'float depth = gl_FragCoord.z / gl_FragCoord.w;',
32598            'float fogFactor = 0.0;',
32599
32600            'if ( fogType == 1 ) {',
32601
32602            'fogFactor = smoothstep( fogNear, fogFar, depth );',
32603
32604            '} else {',
32605
32606            'const float LOG2 = 1.442695;',
32607            'fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );',
32608            'fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );',
32609
32610            '}',
32611
32612            'gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );',
32613
32614            '}',
32615
32616            '}'
32617
32618        ].join( '\n' ) );
32619
32620        gl.compileShader( vertexShader );
32621        gl.compileShader( fragmentShader );
32622
32623        gl.attachShader( program, vertexShader );
32624        gl.attachShader( program, fragmentShader );
32625
32626        gl.linkProgram( program );
32627
32628        return program;
32629
32630    }
32631
32632    function painterSortStable ( a, b ) {
32633
32634        if ( a.renderOrder !== b.renderOrder ) {
32635
32636            return a.renderOrder - b.renderOrder;
32637
32638        } else if ( a.z !== b.z ) {
32639
32640            return b.z - a.z;
32641
32642        } else {
32643
32644            return b.id - a.id;
32645
32646        }
32647
32648    }
32649
32650};
32651
32652// File:src/Three.Legacy.js
32653
32654/**
32655 * @author mrdoob / http://mrdoob.com/
32656 */
32657
32658Object.defineProperties( THREE.Box2.prototype, {
32659    empty: {
32660        value: function () {
32661            console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );
32662            return this.isEmpty();
32663        }
32664    },
32665    isIntersectionBox: {
32666        value: function ( box ) {
32667            console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );
32668            return this.intersectsBox( box );
32669        }
32670    }
32671} );
32672
32673Object.defineProperties( THREE.Box3.prototype, {
32674    empty: {
32675        value: function () {
32676            console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );
32677            return this.isEmpty();
32678        }
32679    },
32680    isIntersectionBox: {
32681        value: function ( box ) {
32682            console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );
32683            return this.intersectsBox( box );
32684        }
32685    },
32686    isIntersectionSphere: {
32687        value: function ( sphere ) {
32688            console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
32689            return this.intersectsSphere( sphere );
32690        }
32691    }
32692} );
32693
32694Object.defineProperties( THREE.Matrix3.prototype, {
32695    multiplyVector3: {
32696        value: function ( vector ) {
32697            console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
32698            return vector.applyMatrix3( this );
32699        }
32700    },
32701    multiplyVector3Array: {
32702        value: function ( a ) {
32703            console.warn( 'THREE.Matrix3: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' );
32704            return this.applyToVector3Array( a );
32705        }
32706    }
32707} );
32708
32709Object.defineProperties( THREE.Matrix4.prototype, {
32710    extractPosition: {
32711        value: function ( m ) {
32712            console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
32713            return this.copyPosition( m );
32714        }
32715    },
32716    setRotationFromQuaternion: {
32717        value: function ( q ) {
32718            console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
32719            return this.makeRotationFromQuaternion( q );
32720        }
32721    },
32722    multiplyVector3: {
32723        value: function ( vector ) {
32724            console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) or vector.applyProjection( matrix ) instead.' );
32725            return vector.applyProjection( this );
32726        }
32727    },
32728    multiplyVector4: {
32729        value: function ( vector ) {
32730            console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
32731            return vector.applyMatrix4( this );
32732        }
32733    },
32734    multiplyVector3Array: {
32735        value: function ( a ) {
32736            console.warn( 'THREE.Matrix4: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.' );
32737            return this.applyToVector3Array( a );
32738        }
32739    },
32740    rotateAxis: {
32741        value: function ( v ) {
32742            console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
32743            v.transformDirection( this );
32744        }
32745    },
32746    crossVector: {
32747        value: function ( vector ) {
32748            console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
32749            return vector.applyMatrix4( this );
32750        }
32751    },
32752    translate: {
32753        value: function ( v ) {
32754            console.error( 'THREE.Matrix4: .translate() has been removed.' );
32755        }
32756    },
32757    rotateX: {
32758        value: function ( angle ) {
32759            console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
32760        }
32761    },
32762    rotateY: {
32763        value: function ( angle ) {
32764            console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
32765        }
32766    },
32767    rotateZ: {
32768        value: function ( angle ) {
32769            console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
32770        }
32771    },
32772    rotateByAxis: {
32773        value: function ( axis, angle ) {
32774            console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
32775        }
32776    }
32777} );
32778
32779Object.defineProperties( THREE.Plane.prototype, {
32780    isIntersectionLine: {
32781        value: function ( line ) {
32782            console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );
32783            return this.intersectsLine( line );
32784        }
32785    }
32786} );
32787
32788Object.defineProperties( THREE.Quaternion.prototype, {
32789    multiplyVector3: {
32790        value: function ( vector ) {
32791            console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
32792            return vector.applyQuaternion( this );
32793        }
32794    }
32795} );
32796
32797Object.defineProperties( THREE.Ray.prototype, {
32798    isIntersectionBox: {
32799        value: function ( box ) {
32800            console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );
32801            return this.intersectsBox( box );
32802        }
32803    },
32804    isIntersectionPlane: {
32805        value: function ( plane ) {
32806            console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );
32807            return this.intersectsPlane( plane );
32808        }
32809    },
32810    isIntersectionSphere: {
32811        value: function ( sphere ) {
32812            console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
32813            return this.intersectsSphere( sphere );
32814        }
32815    }
32816} );
32817
32818Object.defineProperties( THREE.Vector3.prototype, {
32819    setEulerFromRotationMatrix: {
32820        value: function () {
32821            console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
32822        }
32823    },
32824    setEulerFromQuaternion: {
32825        value: function () {
32826            console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
32827        }
32828    },
32829    getPositionFromMatrix: {
32830        value: function ( m ) {
32831            console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
32832            return this.setFromMatrixPosition( m );
32833        }
32834    },
32835    getScaleFromMatrix: {
32836        value: function ( m ) {
32837            console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
32838            return this.setFromMatrixScale( m );
32839        }
32840    },
32841    getColumnFromMatrix: {
32842        value: function ( index, matrix ) {
32843            console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
32844            return this.setFromMatrixColumn( index, matrix );
32845        }
32846    }
32847} );
32848
32849//
32850
32851THREE.Face4 = function ( a, b, c, d, normal, color, materialIndex ) {
32852
32853    console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );
32854    return new THREE.Face3( a, b, c, normal, color, materialIndex );
32855
32856};
32857
32858THREE.Vertex = function ( x, y, z ) {
32859
32860    console.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' );
32861    return new THREE.Vector3( x, y, z );
32862
32863};
32864
32865//
32866
32867Object.defineProperties( THREE.Object3D.prototype, {
32868    eulerOrder: {
32869        get: function () {
32870            console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
32871            return this.rotation.order;
32872        },
32873        set: function ( value ) {
32874            console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
32875            this.rotation.order = value;
32876        }
32877    },
32878    getChildByName: {
32879        value: function ( name ) {
32880            console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
32881            return this.getObjectByName( name );
32882        }
32883    },
32884    renderDepth: {
32885        set: function ( value ) {
32886            console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
32887        }
32888    },
32889    translate: {
32890        value: function ( distance, axis ) {
32891            console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
32892            return this.translateOnAxis( axis, distance );
32893        }
32894    },
32895    useQuaternion: {
32896        get: function () {
32897            console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
32898        },
32899        set: function ( value ) {
32900            console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
32901        }
32902    }
32903} );
32904
32905//
32906
32907Object.defineProperties( THREE, {
32908    PointCloud: {
32909        value: function ( geometry, material ) {
32910            console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );
32911            return new THREE.Points( geometry, material );
32912        }
32913    },
32914    ParticleSystem: {
32915        value: function ( geometry, material ) {
32916            console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );
32917            return new THREE.Points( geometry, material );
32918        }
32919    }
32920} );
32921
32922//
32923
32924Object.defineProperties( THREE.Light.prototype, {
32925    onlyShadow: {
32926        set: function ( value ) {
32927            console.warn( 'THREE.Light: .onlyShadow has been removed.' );
32928        }
32929    },
32930    shadowCameraFov: {
32931        set: function ( value ) {
32932            console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );
32933            this.shadow.camera.fov = value;
32934        }
32935    },
32936    shadowCameraLeft: {
32937        set: function ( value ) {
32938            console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );
32939            this.shadow.camera.left = value;
32940        }
32941    },
32942    shadowCameraRight: {
32943        set: function ( value ) {
32944            console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );
32945            this.shadow.camera.right = value;
32946        }
32947    },
32948    shadowCameraTop: {
32949        set: function ( value ) {
32950            console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );
32951            this.shadow.camera.top = value;
32952        }
32953    },
32954    shadowCameraBottom: {
32955        set: function ( value ) {
32956            console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );
32957            this.shadow.camera.bottom = value;
32958        }
32959    },
32960    shadowCameraNear: {
32961        set: function ( value ) {
32962            console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );
32963            this.shadow.camera.near = value;
32964        }
32965    },
32966    shadowCameraFar: {
32967        set: function ( value ) {
32968            console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );
32969            this.shadow.camera.far = value;
32970        }
32971    },
32972    shadowCameraVisible: {
32973        set: function ( value ) {
32974            console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );
32975        }
32976    },
32977    shadowBias: {
32978        set: function ( value ) {
32979            console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );
32980            this.shadow.bias = value;
32981        }
32982    },
32983    shadowDarkness: {
32984        set: function ( value ) {
32985            console.warn( 'THREE.Light: .shadowDarkness has been removed.' );
32986        }
32987    },
32988    shadowMapWidth: {
32989        set: function ( value ) {
32990            console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );
32991            this.shadow.mapSize.width = value;
32992        }
32993    },
32994    shadowMapHeight: {
32995        set: function ( value ) {
32996            console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );
32997            this.shadow.mapSize.height = value;
32998        }
32999    }
33000} );
33001
33002//
33003
33004Object.defineProperties( THREE.BufferAttribute.prototype, {
33005    length: {
33006        get: function () {
33007            console.warn( 'THREE.BufferAttribute: .length has been deprecated. Please use .count.' );
33008            return this.array.length;
33009        }
33010    }
33011} );
33012
33013Object.defineProperties( THREE.BufferGeometry.prototype, {
33014    drawcalls: {
33015        get: function () {
33016            console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
33017            return this.groups;
33018        }
33019    },
33020    offsets: {
33021        get: function () {
33022            console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
33023            return this.groups;
33024        }
33025    },
33026    addIndex: {
33027        value: function ( index ) {
33028            console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
33029            this.setIndex( index );
33030        }
33031    },
33032    addDrawCall: {
33033        value: function ( start, count, indexOffset ) {
33034            if ( indexOffset !== undefined ) {
33035                console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
33036            }
33037            console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
33038            this.addGroup( start, count );
33039        }
33040    },
33041    clearDrawCalls: {
33042        value: function () {
33043            console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
33044            this.clearGroups();
33045        }
33046    },
33047    computeTangents: {
33048        value: function () {
33049            console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );
33050        }
33051    },
33052    computeOffsets: {
33053        value: function () {
33054            console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );
33055        }
33056    }
33057} );
33058
33059//
33060
33061Object.defineProperties( THREE.Material.prototype, {
33062    wrapAround: {
33063        get: function () {
33064            console.warn( 'THREE.' + this.type + ': .wrapAround has been removed.' );
33065        },
33066        set: function ( value ) {
33067            console.warn( 'THREE.' + this.type + ': .wrapAround has been removed.' );
33068        }
33069    },
33070    wrapRGB: {
33071        get: function () {
33072            console.warn( 'THREE.' + this.type + ': .wrapRGB has been removed.' );
33073            return new THREE.Color();
33074        }
33075    }
33076} );
33077
33078Object.defineProperties( THREE, {
33079    PointCloudMaterial: {
33080        value: function ( parameters ) {
33081            console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );
33082            return new THREE.PointsMaterial( parameters );
33083        }
33084    },
33085    ParticleBasicMaterial: {
33086        value: function ( parameters ) {
33087            console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );
33088            return new THREE.PointsMaterial( parameters );
33089        }
33090    },
33091    ParticleSystemMaterial:{
33092        value: function ( parameters ) {
33093            console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );
33094            return new THREE.PointsMaterial( parameters );
33095        }
33096    }
33097} );
33098
33099Object.defineProperties( THREE.MeshPhongMaterial.prototype, {
33100    metal: {
33101        get: function () {
33102            console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );
33103            return false;
33104        },
33105        set: function ( value ) {
33106            console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );
33107        }
33108    }
33109} );
33110
33111Object.defineProperties( THREE.ShaderMaterial.prototype, {
33112    derivatives: {
33113        get: function () {
33114            console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
33115            return this.extensions.derivatives;
33116        },
33117        set: function ( value ) {
33118            console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
33119            this.extensions.derivatives = value;
33120        }
33121    }
33122} );
33123
33124//
33125
33126Object.defineProperties( THREE.WebGLRenderer.prototype, {
33127    supportsFloatTextures: {
33128        value: function () {
33129            console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
33130            return this.extensions.get( 'OES_texture_float' );
33131        }
33132    },
33133    supportsHalfFloatTextures: {
33134        value: function () {
33135            console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
33136            return this.extensions.get( 'OES_texture_half_float' );
33137        }
33138    },
33139    supportsStandardDerivatives: {
33140        value: function () {
33141            console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
33142            return this.extensions.get( 'OES_standard_derivatives' );
33143        }
33144    },
33145    supportsCompressedTextureS3TC: {
33146        value: function () {
33147            console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
33148            return this.extensions.get( 'WEBGL_compressed_texture_s3tc' );
33149        }
33150    },
33151    supportsCompressedTexturePVRTC: {
33152        value: function () {
33153            console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
33154            return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );
33155        }
33156    },
33157    supportsBlendMinMax: {
33158        value: function () {
33159            console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
33160            return this.extensions.get( 'EXT_blend_minmax' );
33161        }
33162    },
33163    supportsVertexTextures: {
33164        value: function () {
33165            return this.capabilities.vertexTextures;
33166        }
33167    },
33168    supportsInstancedArrays: {
33169        value: function () {
33170            console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
33171            return this.extensions.get( 'ANGLE_instanced_arrays' );
33172        }
33173    },
33174    enableScissorTest: {
33175        value: function ( boolean ) {
33176            console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );
33177            this.setScissorTest( boolean );
33178        }
33179    },
33180    initMaterial: {
33181        value: function () {
33182            console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
33183        }
33184    },
33185    addPrePlugin: {
33186        value: function () {
33187            console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
33188        }
33189    },
33190    addPostPlugin: {
33191        value: function () {
33192            console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
33193        }
33194    },
33195    updateShadowMap: {
33196        value: function () {
33197            console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
33198        }
33199    },
33200    shadowMapEnabled: {
33201        get: function () {
33202            return this.shadowMap.enabled;
33203        },
33204        set: function ( value ) {
33205            console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
33206            this.shadowMap.enabled = value;
33207        }
33208    },
33209    shadowMapType: {
33210        get: function () {
33211            return this.shadowMap.type;
33212        },
33213        set: function ( value ) {
33214            console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
33215            this.shadowMap.type = value;
33216        }
33217    },
33218    shadowMapCullFace: {
33219        get: function () {
33220            return this.shadowMap.cullFace;
33221        },
33222        set: function ( value ) {
33223            console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace is now .shadowMap.cullFace.' );
33224            this.shadowMap.cullFace = value;
33225        }
33226    }
33227} );
33228
33229//
33230
33231Object.defineProperties( THREE.WebGLRenderTarget.prototype, {
33232    wrapS: {
33233        get: function () {
33234            console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
33235            return this.texture.wrapS;
33236        },
33237        set: function ( value ) {
33238            console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
33239            this.texture.wrapS = value;
33240        }
33241    },
33242    wrapT: {
33243        get: function () {
33244            console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
33245            return this.texture.wrapT;
33246        },
33247        set: function ( value ) {
33248            console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
33249            this.texture.wrapT = value;
33250        }
33251    },
33252    magFilter: {
33253        get: function () {
33254            console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
33255            return this.texture.magFilter;
33256        },
33257        set: function ( value ) {
33258            console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
33259            this.texture.magFilter = value;
33260        }
33261    },
33262    minFilter: {
33263        get: function () {
33264            console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
33265            return this.texture.minFilter;
33266        },
33267        set: function ( value ) {
33268            console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
33269            this.texture.minFilter = value;
33270        }
33271    },
33272    anisotropy: {
33273        get: function () {
33274            console.warn( 'THREE.WebGLRenderTarget: .anisotropy 
33274is now .texture.anisotropy.' );
33275            return this.texture.anisotropy;
33276        },
33277        set: function ( value ) {
33278            console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
33279            this.texture.anisotropy = value;
33280        }
33281    },
33282    offset: {
33283        get: function () {
33284            console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
33285            return this.texture.offset;
33286        },
33287        set: function ( value ) {
33288            console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
33289            this.texture.offset = value;
33290        }
33291    },
33292    repeat: {
33293        get: function () {
33294            console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
33295            return this.texture.repeat;
33296        },
33297        set: function ( value ) {
33298            console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
33299            this.texture.repeat = value;
33300        }
33301    },
33302    format: {
33303        get: function () {
33304            console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
33305            return this.texture.format;
33306        },
33307        set: function ( value ) {
33308            console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
33309            this.texture.format = value;
33310        }
33311    },
33312    type: {
33313        get: function () {
33314            console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
33315            return this.texture.type;
33316        },
33317        set: function ( value ) {
33318            console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
33319            this.texture.type = value;
33320        }
33321    },
33322    generateMipmaps: {
33323        get: function () {
33324            console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
33325            return this.texture.generateMipmaps;
33326        },
33327        set: function ( value ) {
33328            console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
33329            this.texture.generateMipmaps = value;
33330        }
33331    }
33332} );
33333
33334//
33335
33336Object.defineProperties( THREE.Audio.prototype, {
33337    load: {
33338        value: function ( file ) {
33339
33340            console.warn( 'THREE.Audio: .load has been deprecated. Please use THREE.AudioLoader.' );
33341
33342            var scope = this;
33343
33344            var audioLoader = new THREE.AudioLoader();
33345
33346            audioLoader.load( file, function ( buffer ) {
33347
33348                scope.setBuffer( buffer );
33349
33350            } );
33351
33352            return this;
33353
33354        }
33355    }
33356} );
33357
33358//
33359
33360THREE.GeometryUtils = {
33361
33362    merge: function ( geometry1, geometry2, materialIndexOffset ) {
33363
33364        console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
33365
33366        var matrix;
33367
33368        if ( geometry2 instanceof THREE.Mesh ) {
33369
33370            geometry2.matrixAutoUpdate && geometry2.updateMatrix();
33371
33372            matrix = geometry2.matrix;
33373            geometry2 = geometry2.geometry;
33374
33375        }
33376
33377        geometry1.merge( geometry2, matrix, materialIndexOffset );
33378
33379    },
33380
33381    center: function ( geometry ) {
33382
33383        console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
33384        return geometry.center();
33385
33386    }
33387
33388};
33389
33390THREE.ImageUtils = {
33391
33392    crossOrigin: undefined,
33393
33394    loadTexture: function ( url, mapping, onLoad, onError ) {
33395
33396        console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );
33397
33398        var loader = new THREE.TextureLoader();
33399        loader.setCrossOrigin( this.crossOrigin );
33400
33401        var texture = loader.load( url, onLoad, undefined, onError );
33402
33403        if ( mapping ) texture.mapping = mapping;
33404
33405        return texture;
33406
33407    },
33408
33409    loadTextureCube: function ( urls, mapping, onLoad, onError ) {
33410
33411        console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );
33412
33413        var loader = new THREE.CubeTextureLoader();
33414        loader.setCrossOrigin( this.crossOrigin );
33415
33416        var texture = loader.load( urls, onLoad, undefined, onError );
33417
33418        if ( mapping ) texture.mapping = mapping;
33419
33420        return texture;
33421
33422    },
33423
33424    loadCompressedTexture: function () {
33425
33426        console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );
33427
33428    },
33429
33430    loadCompressedTextureCube: function () {
33431
33432        console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );
33433
33434    }
33435
33436};
33437
33438//
33439
33440THREE.Projector = function () {
33441
33442    console.error( 'THREE.Projector has been moved to /examples/js/renderers/Projector.js.' );
33443
33444    this.projectVector = function ( vector, camera ) {
33445
33446        console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );
33447        vector.project( camera );
33448
33449    };
33450
33451    this.unprojectVector = function ( vector, camera ) {
33452
33453        console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
33454        vector.unproject( camera );
33455
33456    };
33457
33458    this.pickingRay = function ( vector, camera ) {
33459
33460        console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
33461
33462    };
33463
33464};
33465
33466//
33467
33468THREE.CanvasRenderer = function () {
33469
33470    console.error( 'THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js' );
33471
33472    this.domElement = document.createElement( 'canvas' );
33473    this.clear = function () {};
33474    this.render = function () {};
33475    this.setClearColor = function () {};
33476    this.setSize = function () {};
33477
33478};
33479
33480//
33481
33482THREE.MeshFaceMaterial = THREE.MultiMaterial;
33483
33484//
33485
33486Object.defineProperties( THREE.LOD.prototype, {
33487    objects: {
33488        get: function () {
33489
33490            console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
33491            return this.levels;
33492
33493        }
33494    }
33495} );
33496
33497// File:src/extras/CurveUtils.js
33498
33499/**
33500 * @author zz85 / http://www.lab4games.net/zz85/blog
33501 */
33502
33503THREE.CurveUtils = {
33504
33505    tangentQuadraticBezier: function ( t, p0, p1, p2 ) {
33506
33507        return 2 * ( 1 - t ) * ( p1 - p0 ) + 2 * t * ( p2 - p1 );
33508
33509    },
33510
33511    // Puay Bing, thanks for helping with this derivative!
33512
33513    tangentCubicBezier: function ( t, p0, p1, p2, p3 ) {
33514
33515        return - 3 * p0 * ( 1 - t ) * ( 1 - t )  +
33516            3 * p1 * ( 1 - t ) * ( 1 - t ) - 6 * t * p1 * ( 1 - t ) +
33517            6 * t *  p2 * ( 1 - t ) - 3 * t * t * p2 +
33518            3 * t * t * p3;
33519
33520    },
33521
33522    tangentSpline: function ( t, p0, p1, p2, p3 ) {
33523
33524        // To check if my formulas are correct
33525
33526        var h00 = 6 * t * t - 6 * t; 	// derived from 2t^3 − 3t^2 + 1
33527        var h10 = 3 * t * t - 4 * t + 1; // t^3 − 2t^2 + t
33528        var h01 = - 6 * t * t + 6 * t; 	// − 2t3 + 3t2
33529        var h11 = 3 * t * t - 2 * t;	// t3 − t2
33530
33531        return h00 + h10 + h01 + h11;
33532
33533    },
33534
33535    // Catmull-Rom
33536
33537    interpolate: function( p0, p1, p2, p3, t ) {
33538
33539        var v0 = ( p2 - p0 ) * 0.5;
33540        var v1 = ( p3 - p1 ) * 0.5;
33541        var t2 = t * t;
33542        var t3 = t * t2;
33543        return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
33544
33545    }
33546
33547};
33548
33549// File:src/extras/SceneUtils.js
33550
33551/**
33552 * @author alteredq / http://alteredqualia.com/
33553 */
33554
33555THREE.SceneUtils = {
33556
33557    createMultiMaterialObject: function ( geometry, materials ) {
33558
33559        var group = new THREE.Group();
33560
33561        for ( var i = 0, l = materials.length; i < l; i ++ ) {
33562
33563            group.add( new THREE.Mesh( geometry, materials[ i ] ) );
33564
33565        }
33566
33567        return group;
33568
33569    },
33570
33571    detach: function ( child, parent, scene ) {
33572
33573        child.applyMatrix( parent.matrixWorld );
33574        parent.remove( child );
33575        scene.add( child );
33576
33577    },
33578
33579    attach: function ( child, scene, parent ) {
33580
33581        var matrixWorldInverse = new THREE.Matrix4();
33582        matrixWorldInverse.getInverse( parent.matrixWorld );
33583        child.applyMatrix( matrixWorldInverse );
33584
33585        scene.remove( child );
33586        parent.add( child );
33587
33588    }
33589
33590};
33591
33592// File:src/extras/ShapeUtils.js
33593
33594/**
33595 * @author zz85 / http://www.lab4games.net/zz85/blog
33596 */
33597
33598THREE.ShapeUtils = {
33599
33600    // calculate area of the contour polygon
33601
33602    area: function ( contour ) {
33603
33604        var n = contour.length;
33605        var a = 0.0;
33606
33607        for ( var p = n - 1, q = 0; q < n; p = q ++ ) {
33608
33609            a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
33610
33611        }
33612
33613        return a * 0.5;
33614
33615    },
33616
33617    triangulate: ( function () {
33618
33619        /**
33620         * This code is a quick port of code written in C++ which was submitted to
33621         * flipcode.com by John W. Ratcliff  // July 22, 2000
33622         * See original code and more information here:
33623         * http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml
33624         *
33625         * ported to actionscript by Zevan Rosser
33626         * www.actionsnippet.com
33627         *
33628         * ported to javascript by Joshua Koo
33629         * http://www.lab4games.net/zz85/blog
33630         *
33631         */
33632
33633        function snip( contour, u, v, w, n, verts ) {
33634
33635            var p;
33636            var ax, ay, bx, by;
33637            var cx, cy, px, py;
33638
33639            ax = contour[ verts[ u ] ].x;
33640            ay = contour[ verts[ u ] ].y;
33641
33642            bx = contour[ verts[ v ] ].x;
33643            by = contour[ verts[ v ] ].y;
33644
33645            cx = contour[ verts[ w ] ].x;
33646            cy = contour[ verts[ w ] ].y;
33647
33648            if ( Number.EPSILON > ( ( ( bx - ax ) * ( cy - ay ) ) - ( ( by - ay ) * ( cx - ax ) ) ) ) return false;
33649
33650            var aX, aY, bX, bY, cX, cY;
33651            var apx, apy, bpx, bpy, cpx, cpy;
33652            var cCROSSap, bCROSScp, aCROSSbp;
33653
33654            aX = cx - bx;  aY = cy - by;
33655            bX = ax - cx;  bY = ay - cy;
33656            cX = bx - ax;  cY = by - ay;
33657
33658            for ( p = 0; p < n; p ++ ) {
33659
33660                px = contour[ verts[ p ] ].x;
33661                py = contour[ verts[ p ] ].y;
33662
33663                if ( ( ( px === ax ) && ( py === ay ) ) ||
33664                    ( ( px === bx ) && ( py === by ) ) ||
33665                    ( ( px === cx ) && ( py === cy ) ) )	continue;
33666
33667                apx = px - ax;  apy = py - ay;
33668                bpx = px - bx;  bpy = py - by;
33669                cpx = px - cx;  cpy = py - cy;
33670
33671                // see if p is inside triangle abc
33672
33673                aCROSSbp = aX * bpy - aY * bpx;
33674                cCROSSap = cX * apy - cY * apx;
33675                bCROSScp = bX * cpy - bY * cpx;
33676
33677                if ( ( aCROSSbp >= - Number.EPSILON ) && ( bCROSScp >= - Number.EPSILON ) && ( cCROSSap >= - Number.EPSILON ) ) return false;
33678
33679            }
33680
33681            return true;
33682
33683        }
33684
33685        // takes in an contour array and returns
33686
33687        return function ( contour, indices ) {
33688
33689            var n = contour.length;
33690
33691            if ( n < 3 ) return null;
33692
33693            var result = [],
33694                verts = [],
33695                vertIndices = [];
33696
33697            /* we want a counter-clockwise polygon in verts */
33698
33699            var u, v, w;
33700
33701            if ( THREE.ShapeUtils.area( contour ) > 0.0 ) {
33702
33703                for ( v = 0; v < n; v ++ ) verts[ v ] = v;
33704
33705            } else {
33706
33707                for ( v = 0; v < n; v ++ ) verts[ v ] = ( n - 1 ) - v;
33708
33709            }
33710
33711            var nv = n;
33712
33713            /*  remove nv - 2 vertices, creating 1 triangle every time */
33714
33715            var count = 2 * nv;   /* error detection */
33716
33717            for ( v = nv - 1; nv > 2; ) {
33718
33719                /* if we loop, it is probably a non-simple polygon */
33720
33721                if ( ( count -- ) <= 0 ) {
33722
33723                    //** Triangulate: ERROR - probable bad polygon!
33724
33725                    //throw ( "Warning, unable to triangulate polygon!" );
33726                    //return null;
33727                    // Sometimes warning is fine, especially polygons are triangulated in reverse.
33728                    console.warn( 'THREE.ShapeUtils: Unable to triangulate polygon! in triangulate()' );
33729
33730                    if ( indices ) return vertIndices;
33731                    return result;
33732
33733                }
33734
33735                /* three consecutive vertices in current polygon, <u,v,w> */
33736
33737                u = v; 	 	if ( nv <= u ) u = 0;     /* previous */
33738                v = u + 1;  if ( nv <= v ) v = 0;     /* new v    */
33739                w = v + 1;  if ( nv <= w ) w = 0;     /* next     */
33740
33741                if ( snip( contour, u, v, w, nv, verts ) ) {
33742
33743                    var a, b, c, s, t;
33744
33745                    /* true names of the vertices */
33746
33747                    a = verts[ u ];
33748                    b = verts[ v ];
33749                    c = verts[ w ];
33750
33751                    /* output Triangle */
33752
33753                    result.push( [ contour[ a ],
33754                        contour[ b ],
33755                        contour[ c ] ] );
33756
33757
33758                    vertIndices.push( [ verts[ u ], verts[ v ], verts[ w ] ] );
33759
33760                    /* remove v from the remaining polygon */
33761
33762                    for ( s = v, t = v + 1; t < nv; s ++, t ++ ) {
33763
33764                        verts[ s ] = verts[ t ];
33765
33766                    }
33767
33768                    nv --;
33769
33770                    /* reset error detection counter */
33771
33772                    count = 2 * nv;
33773
33774                }
33775
33776            }
33777
33778            if ( indices ) return vertIndices;
33779            return result;
33780
33781        }
33782
33783    } )(),
33784
33785    triangulateShape: function ( contour, holes ) {
33786
33787        function point_in_segment_2D_colin( inSegPt1, inSegPt2, inOtherPt ) {
33788
33789            // inOtherPt needs to be collinear to the inSegment
33790            if ( inSegPt1.x !== inSegPt2.x ) {
33791
33792                if ( inSegPt1.x < inSegPt2.x ) {
33793
33794                    return	( ( inSegPt1.x <= inOtherPt.x ) && ( inOtherPt.x <= inSegPt2.x ) );
33795
33796                } else {
33797
33798                    return	( ( inSegPt2.x <= inOtherPt.x ) && ( inOtherPt.x <= inSegPt1.x ) );
33799
33800                }
33801
33802            } else {
33803
33804                if ( inSegPt1.y < inSegPt2.y ) {
33805
33806                    return	( ( inSegPt1.y <= inOtherPt.y ) && ( inOtherPt.y <= inSegPt2.y ) );
33807
33808                } else {
33809
33810                    return	( ( inSegPt2.y <= inOtherPt.y ) && ( inOtherPt.y <= inSegPt1.y ) );
33811
33812                }
33813
33814            }
33815
33816        }
33817
33818        function intersect_segments_2D( inSeg1Pt1, inSeg1Pt2, inSeg2Pt1, inSeg2Pt2, inExcludeAdjacentSegs ) {
33819
33820            var seg1dx = inSeg1Pt2.x - inSeg1Pt1.x,   seg1dy = inSeg1Pt2.y - inSeg1Pt1.y;
33821            var seg2dx = inSeg2Pt2.x - inSeg2Pt1.x,   seg2dy = inSeg2Pt2.y - inSeg2Pt1.y;
33822
33823            var seg1seg2dx = inSeg1Pt1.x - inSeg2Pt1.x;
33824            var seg1seg2dy = inSeg1Pt1.y - inSeg2Pt1.y;
33825
33826            var limit		= seg1dy * seg2dx - seg1dx * seg2dy;
33827            var perpSeg1	= seg1dy * seg1seg2dx - seg1dx * seg1seg2dy;
33828
33829            if ( Math.abs( limit ) > Number.EPSILON ) {
33830
33831                // not parallel
33832
33833                var perpSeg2;
33834                if ( limit > 0 ) {
33835
33836                    if ( ( perpSeg1 < 0 ) || ( perpSeg1 > limit ) ) 		return [];
33837                    perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy;
33838                    if ( ( perpSeg2 < 0 ) || ( perpSeg2 > limit ) ) 		return [];
33839
33840                } else {
33841
33842                    if ( ( perpSeg1 > 0 ) || ( perpSeg1 < limit ) ) 		return [];
33843                    perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy;
33844                    if ( ( perpSeg2 > 0 ) || ( perpSeg2 < limit ) ) 		return [];
33845
33846                }
33847
33848                // i.e. to reduce rounding errors
33849                // intersection at endpoint of segment#1?
33850                if ( perpSeg2 === 0 ) {
33851
33852                    if ( ( inExcludeAdjacentSegs ) &&
33853                        ( ( perpSeg1 === 0 ) || ( perpSeg1 === limit ) ) )		return [];
33854                    return [ inSeg1Pt1 ];
33855
33856                }
33857                if ( perpSeg2 === limit ) {
33858
33859                    if ( ( inExcludeAdjacentSegs ) &&
33860                        ( ( perpSeg1 === 0 ) || ( perpSeg1 === limit ) ) )		return [];
33861                    return [ inSeg1Pt2 ];
33862
33863                }
33864                // intersection at endpoint of segment#2?
33865                if ( perpSeg1 === 0 )		return [ inSeg2Pt1 ];
33866                if ( perpSeg1 === limit )	return [ inSeg2Pt2 ];
33867
33868                // return real intersection point
33869                var factorSeg1 = perpSeg2 / limit;
33870                return	[ { x: inSeg1Pt1.x + factorSeg1 * seg1dx,
33871                    y: inSeg1Pt1.y + factorSeg1 * seg1dy } ];
33872
33873            } else {
33874
33875                // parallel or collinear
33876                if ( ( perpSeg1 !== 0 ) ||
33877                    ( seg2dy * seg1seg2dx !== seg2dx * seg1seg2dy ) ) 			return [];
33878
33879                // they are collinear or degenerate
33880                var seg1Pt = ( ( seg1dx === 0 ) && ( seg1dy === 0 ) );	// segment1 is just a point?
33881                var seg2Pt = ( ( seg2dx === 0 ) && ( seg2dy === 0 ) );	// segment2 is just a point?
33882                // both segments are points
33883                if ( seg1Pt && seg2Pt ) {
33884
33885                    if ( ( inSeg1Pt1.x !== inSeg2Pt1.x ) ||
33886                        ( inSeg1Pt1.y !== inSeg2Pt1.y ) )		return [];	// they are distinct  points
33887                    return [ inSeg1Pt1 ];                 						// they are the same point
33888
33889                }
33890                // segment#1  is a single point
33891                if ( seg1Pt ) {
33892
33893                    if ( ! point_in_segment_2D_colin( inSeg2Pt1, inSeg2Pt2, inSeg1Pt1 ) )		return [];		// but not in segment#2
33894                    return [ inSeg1Pt1 ];
33895
33896                }
33897                // segment#2  is a single point
33898                if ( seg2Pt ) {
33899
33900                    if ( ! point_in_segment_2D_colin( inSeg1Pt1, inSeg1Pt2, inSeg2Pt1 ) )		return [];		// but not in segment#1
33901                    return [ inSeg2Pt1 ];
33902
33903                }
33904
33905                // they are collinear segments, which might overlap
33906                var seg1min, seg1max, seg1minVal, seg1maxVal;
33907                var seg2min, seg2max, seg2minVal, seg2maxVal;
33908                if ( seg1dx !== 0 ) {
33909
33910                    // the segments are NOT on a vertical line
33911                    if ( inSeg1Pt1.x < inSeg1Pt2.x ) {
33912
33913                        seg1min = inSeg1Pt1; seg1minVal = inSeg1Pt1.x;
33914                        seg1max = inSeg1Pt2; seg1maxVal = inSeg1Pt2.x;
33915
33916                    } else {
33917
33918                        seg1min = inSeg1Pt2; seg1minVal = inSeg1Pt2.x;
33919                        seg1max = inSeg1Pt1; seg1maxVal = inSeg1Pt1.x;
33920
33921                    }
33922                    if ( inSeg2Pt1.x < inSeg2Pt2.x ) {
33923
33924                        seg2min = inSeg2Pt1; seg2minVal = inSeg2Pt1.x;
33925                        seg2max = inSeg2Pt2; seg2maxVal = inSeg2Pt2.x;
33926
33927                    } else {
33928
33929                        seg2min = inSeg2Pt2; seg2minVal = inSeg2Pt2.x;
33930                        seg2max = inSeg2Pt1; seg2maxVal = inSeg2Pt1.x;
33931
33932                    }
33933
33934                } else {
33935
33936                    // the segments are on a vertical line
33937                    if ( inSeg1Pt1.y < inSeg1Pt2.y ) {
33938
33939                        seg1min = inSeg1Pt1; seg1minVal = inSeg1Pt1.y;
33940                        seg1max = inSeg1Pt2; seg1maxVal = inSeg1Pt2.y;
33941
33942                    } else {
33943
33944                        seg1min = inSeg1Pt2; seg1minVal = inSeg1Pt2.y;
33945                        seg1max = inSeg1Pt1; seg1maxVal = inSeg1Pt1.y;
33946
33947                    }
33948                    if ( inSeg2Pt1.y < inSeg2Pt2.y ) {
33949
33950                        seg2min = inSeg2Pt1; seg2minVal = inSeg2Pt1.y;
33951                        seg2max = inSeg2Pt2; seg2maxVal = inSeg2Pt2.y;
33952
33953                    } else {
33954
33955                        seg2min = inSeg2Pt2; seg2minVal = inSeg2Pt2.y;
33956                        seg2max = inSeg2Pt1; seg2maxVal = inSeg2Pt1.y;
33957
33958                    }
33959
33960                }
33961                if ( seg1minVal <= seg2minVal ) {
33962
33963                    if ( seg1maxVal <  seg2minVal )	return [];
33964                    if ( seg1maxVal === seg2minVal )	{
33965
33966                        if ( inExcludeAdjacentSegs )		return [];
33967                        return [ seg2min ];
33968
33969                    }
33970                    if ( seg1maxVal <= seg2maxVal )	return [ seg2min, seg1max ];
33971                    return	[ seg2min, seg2max ];
33972
33973                } else {
33974
33975                    if ( seg1minVal >  seg2maxVal )	return [];
33976                    if ( seg1minVal === seg2maxVal )	{
33977
33978                        if ( inExcludeAdjacentSegs )		return [];
33979                        return [ seg1min ];
33980
33981                    }
33982                    if ( seg1maxVal <= seg2maxVal )	return [ seg1min, seg1max ];
33983                    return	[ seg1min, seg2max ];
33984
33985                }
33986
33987            }
33988
33989        }
33990
33991        function isPointInsideAngle( inVertex, inLegFromPt, inLegToPt, inOtherPt ) {
33992
33993            // The order of legs is important
33994
33995            // translation of all points, so that Vertex is at (0,0)
33996            var legFromPtX	= inLegFromPt.x - inVertex.x,  legFromPtY	= inLegFromPt.y - inVertex.y;
33997            var legToPtX	= inLegToPt.x	- inVertex.x,  legToPtY		= inLegToPt.y	- inVertex.y;
33998            var otherPtX	= inOtherPt.x	- inVertex.x,  otherPtY		= inOtherPt.y	- inVertex.y;
33999
34000            // main angle >0: < 180 deg.; 0: 180 deg.; <0: > 180 deg.
34001            var from2toAngle	= legFromPtX * legToPtY - legFromPtY * legToPtX;
34002            var from2otherAngle	= legFromPtX * otherPtY - legFromPtY * otherPtX;
34003
34004            if ( Math.abs( from2toAngle ) > Number.EPSILON ) {
34005
34006                // angle != 180 deg.
34007
34008                var other2toAngle		= otherPtX * legToPtY - otherPtY * legToPtX;
34009                // console.log( "from2to: " + from2toAngle + ", from2other: " + from2otherAngle + ", other2to: " + other2toAngle );
34010
34011                if ( from2toAngle > 0 ) {
34012
34013                    // main angle < 180 deg.
34014                    return	( ( from2otherAngle >= 0 ) && ( other2toAngle >= 0 ) );
34015
34016                } else {
34017
34018                    // main angle > 180 deg.
34019                    return	( ( from2otherAngle >= 0 ) || ( other2toAngle >= 0 ) );
34020
34021                }
34022
34023            } else {
34024
34025                // angle == 180 deg.
34026                // console.log( "from2to: 180 deg., from2other: " + from2otherAngle  );
34027                return	( from2otherAngle > 0 );
34028
34029            }
34030
34031        }
34032
34033
34034        function removeHoles( contour, holes ) {
34035
34036            var shape = contour.concat(); // work on this shape
34037            var hole;
34038
34039            function isCutLineInsideAngles( inShapeIdx, inHoleIdx ) {
34040
34041                // Check if hole point lies within angle around shape point
34042                var lastShapeIdx = shape.length - 1;
34043
34044                var prevShapeIdx = inShapeIdx - 1;
34045                if ( prevShapeIdx < 0 )			prevShapeIdx = lastShapeIdx;
34046
34047                var nextShapeIdx = inShapeIdx + 1;
34048                if ( nextShapeIdx > lastShapeIdx )	nextShapeIdx = 0;
34049
34050                var insideAngle = isPointInsideAngle( shape[ inShapeIdx ], shape[ prevShapeIdx ], shape[ nextShapeIdx ], hole[ inHoleIdx ] );
34051                if ( ! insideAngle ) {
34052
34053                    // console.log( "Vertex (Shape): " + inShapeIdx + ", Point: " + hole[inHoleIdx].x + "/" + hole[inHoleIdx].y );
34054                    return	false;
34055
34056                }
34057
34058                // Check if shape point lies within angle around hole point
34059                var lastHoleIdx = hole.length - 1;
34060
34061                var prevHoleIdx = inHoleIdx - 1;
34062                if ( prevHoleIdx < 0 )			prevHoleIdx = lastHoleIdx;
34063
34064                var nextHoleIdx = inHoleIdx + 1;
34065                if ( nextHoleIdx > lastHoleIdx )	nextHoleIdx = 0;
34066
34067                insideAngle = isPointInsideAngle( hole[ inHoleIdx ], hole[ prevHoleIdx ], hole[ nextHoleIdx ], shape[ inShapeIdx ] );
34068                if ( ! insideAngle ) {
34069
34070                    // console.log( "Vertex (Hole): " + inHoleIdx + ", Point: " + shape[inShapeIdx].x + "/" + shape[inShapeIdx].y );
34071                    return	false;
34072
34073                }
34074
34075                return	true;
34076
34077            }
34078
34079            function intersectsShapeEdge( inShapePt, inHolePt ) {
34080
34081                // checks for intersections with shape edges
34082                var sIdx, nextIdx, intersection;
34083                for ( sIdx = 0; sIdx < shape.length; sIdx ++ ) {
34084
34085                    nextIdx = sIdx + 1; nextIdx %= shape.length;
34086                    intersection = intersect_segments_2D( inShapePt, inHolePt, shape[ sIdx ], shape[ nextIdx ], true );
34087                    if ( intersection.length > 0 )		return	true;
34088
34089                }
34090
34091                return	false;
34092
34093            }
34094
34095            var indepHoles = [];
34096
34097            function intersectsHoleEdge( inShapePt, inHolePt ) {
34098
34099                // checks for intersections with hole edges
34100                var ihIdx, chkHole,
34101                    hIdx, nextIdx, intersection;
34102                for ( ihIdx = 0; ihIdx < indepHoles.length; ihIdx ++ ) {
34103
34104                    chkHole = holes[ indepHoles[ ihIdx ]];
34105                    for ( hIdx = 0; hIdx < chkHole.length; hIdx ++ ) {
34106
34107                        nextIdx = hIdx + 1; nextIdx %= chkHole.length;
34108                        intersection = intersect_segments_2D( inShapePt, inHolePt, chkHole[ hIdx ], chkHole[ nextIdx ], true );
34109                        if ( intersection.length > 0 )		return	true;
34110
34111                    }
34112
34113                }
34114                return	false;
34115
34116            }
34117
34118            var holeIndex, shapeIndex,
34119                shapePt, holePt,
34120                holeIdx, cutKey, failedCuts = [],
34121                tmpShape1, tmpShape2,
34122                tmpHole1, tmpHole2;
34123
34124            for ( var h = 0, hl = holes.length; h < hl; h ++ ) {
34125
34126                indepHoles.push( h );
34127
34128            }
34129
34130            var minShapeIndex = 0;
34131            var counter = indepHoles.length * 2;
34132            while ( indepHoles.length > 0 ) {
34133
34134                counter --;
34135                if ( counter < 0 ) {
34136
34137                    console.log( "Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!" );
34138                    break;
34139
34140                }
34141
34142                // search for shape-vertex and hole-vertex,
34143                // which can be connected without intersections
34144                for ( shapeIndex = minShapeIndex; shapeIndex < shape.length; shapeIndex ++ ) {
34145
34146                    shapePt = shape[ shapeIndex ];
34147                    holeIndex	= - 1;
34148
34149                    // search for hole which can be reached without intersections
34150                    for ( var h = 0; h < indepHoles.length; h ++ ) {
34151
34152                        holeIdx = indepHoles[ h ];
34153
34154                        // prevent multiple checks
34155                        cutKey = shapePt.x + ":" + shapePt.y + ":" + holeIdx;
34156                        if ( failedCuts[ cutKey ] !== undefined )			continue;
34157
34158                        hole = holes[ holeIdx ];
34159                        for ( var h2 = 0; h2 < hole.length; h2 ++ ) {
34160
34161                            holePt = hole[ h2 ];
34162                            if ( ! isCutLineInsideAngles( shapeIndex, h2 ) )		continue;
34163                            if ( intersectsShapeEdge( shapePt, holePt ) )		continue;
34164                            if ( intersectsHoleEdge( shapePt, holePt ) )		continue;
34165
34166                            holeIndex = h2;
34167                            indepHoles.splice( h, 1 );
34168
34169                            tmpShape1 = shape.slice( 0, shapeIndex + 1 );
34170                            tmpShape2 = shape.slice( shapeIndex );
34171                            tmpHole1 = hole.slice( holeIndex );
34172                            tmpHole2 = hole.slice( 0, holeIndex + 1 );
34173
34174                            shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 );
34175
34176                            minShapeIndex = shapeIndex;
34177
34178                            // Debug only, to show the selected cuts
34179                            // glob_CutLines.push( [ shapePt, holePt ] );
34180
34181                            break;
34182
34183                        }
34184                        if ( holeIndex >= 0 )	break;		// hole-vertex found
34185
34186                        failedCuts[ cutKey ] = true;			// remember failure
34187
34188                    }
34189                    if ( holeIndex >= 0 )	break;		// hole-vertex found
34190
34191                }
34192
34193            }
34194
34195            return shape; 			/* shape with no holes */
34196
34197        }
34198
34199
34200        var i, il, f, face,
34201            key, index,
34202            allPointsMap = {};
34203
34204        // 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.
34205
34206        var allpoints = contour.concat();
34207
34208        for ( var h = 0, hl = holes.length; h < hl; h ++ ) {
34209
34210            Array.prototype.push.apply( allpoints, holes[ h ] );
34211
34212        }
34213
34214        //console.log( "allpoints",allpoints, allpoints.length );
34215
34216        // prepare all points map
34217
34218        for ( i = 0, il = allpoints.length; i < il; i ++ ) {
34219
34220            key = allpoints[ i ].x + ":" + allpoints[ i ].y;
34221
34222            if ( allPointsMap[ key ] !== undefined ) {
34223
34224                console.warn( "THREE.Shape: Duplicate point", key );
34225
34226            }
34227
34228            allPointsMap[ key ] = i;
34229
34230        }
34231
34232        // remove holes by cutting paths to holes and adding them to the shape
34233        var shapeWithoutHoles = removeHoles( contour, holes );
34234
34235        var triangles = THREE.ShapeUtils.triangulate( shapeWithoutHoles, false ); // True returns indices for points of spooled shape
34236        //console.log( "triangles",triangles, triangles.length );
34237
34238        // check all face vertices against all points map
34239
34240        for ( i = 0, il = triangles.length; i < il; i ++ ) {
34241
34242            face = triangles[ i ];
34243
34244            for ( f = 0; f < 3; f ++ ) {
34245
34246                key = face[ f ].x + ":" + face[ f ].y;
34247
34248                index = allPointsMap[ key ];
34249
34250                if ( index !== undefined ) {
34251
34252                    face[ f ] = index;
34253
34254                }
34255
34256            }
34257
34258        }
34259
34260        return triangles.concat();
34261
34262    },
34263
34264    isClockWise: function ( pts ) {
34265
34266        return THREE.ShapeUtils.area( pts ) < 0;
34267
34268    },
34269
34270    // Bezier Curves formulas obtained from
34271    // http://en.wikipedia.org/wiki/B%C3%A9zier_curve
34272
34273    // Quad Bezier Functions
34274
34275    b2: ( function () {
34276
34277        function b2p0( t, p ) {
34278
34279            var k = 1 - t;
34280            return k * k * p;
34281
34282        }
34283
34284        function b2p1( t, p ) {
34285
34286            return 2 * ( 1 - t ) * t * p;
34287
34288        }
34289
34290        function b2p2( t, p ) {
34291
34292            return t * t * p;
34293
34294        }
34295
34296        return function ( t, p0, p1, p2 ) {
34297
34298            return b2p0( t, p0 ) + b2p1( t, p1 ) + b2p2( t, p2 );
34299
34300        };
34301
34302    } )(),
34303
34304    // Cubic Bezier Functions
34305
34306    b3: ( function () {
34307
34308        function b3p0( t, p ) {
34309
34310            var k = 1 - t;
34311            return k * k * k * p;
34312
34313        }
34314
34315        function b3p1( t, p ) {
34316
34317            var k = 1 - t;
34318            return 3 * k * k * t * p;
34319
34320        }
34321
34322        function b3p2( t, p ) {
34323
34324            var k = 1 - t;
34325            return 3 * k * t * t * p;
34326
34327        }
34328
34329        function b3p3( t, p ) {
34330
34331            return t * t * t * p;
34332
34333        }
34334
34335        return function ( t, p0, p1, p2, p3 ) {
34336
34337            return b3p0( t, p0 ) + b3p1( t, p1 ) + b3p2( t, p2 ) + b3p3( t, p3 );
34338
34339        };
34340
34341    } )()
34342
34343};
34344
34345// File:src/extras/core/Curve.js
34346
34347/**
34348 * @author zz85 / http://www.lab4games.net/zz85/blog
34349 * Extensible curve object
34350 *
34351 * Some common of Curve methods
34352 * .getPoint(t), getTangent(t)
34353 * .getPointAt(u), getTagentAt(u)
34354 * .getPoints(), .getSpacedPoints()
34355 * .getLength()
34356 * .updateArcLengths()
34357 *
34358 * This following classes subclasses THREE.Curve:
34359 *
34360 * -- 2d classes --
34361 * THREE.LineCurve
34362 * THREE.QuadraticBezierCurve
34363 * THREE.CubicBezierCurve
34364 * THREE.SplineCurve
34365 * THREE.ArcCurve
34366 * THREE.EllipseCurve
34367 *
34368 * -- 3d classes --
34369 * THREE.LineCurve3
34370 * THREE.QuadraticBezierCurve3
34371 * THREE.CubicBezierCurve3
34372 * THREE.SplineCurve3
34373 *
34374 * A series of curves can be represented as a THREE.CurvePath
34375 *
34376 **/
34377
34378/**************************************************************
34379 *	Abstract Curve base class
34380 **************************************************************/
34381
34382THREE.Curve = function () {
34383
34384};
34385
34386THREE.Curve.prototype = {
34387
34388    constructor: THREE.Curve,
34389
34390    // Virtual base class method to overwrite and implement in subclasses
34391    //	- t [0 .. 1]
34392
34393    getPoint: function ( t ) {
34394
34395        console.warn( "THREE.Curve: Warning, getPoint() not implemented!" );
34396        return null;
34397
34398    },
34399
34400    // Get point at relative position in curve according to arc length
34401    // - u [0 .. 1]
34402
34403    getPointAt: function ( u ) {
34404
34405        var t = this.getUtoTmapping( u );
34406        return this.getPoint( t );
34407
34408    },
34409
34410    // Get sequence of points using getPoint( t )
34411
34412    getPoints: function ( divisions ) {
34413
34414        if ( ! divisions ) divisions = 5;
34415
34416        var d, pts = [];
34417
34418        for ( d = 0; d <= divisions; d ++ ) {
34419
34420            pts.push( this.getPoint( d / divisions ) );
34421
34422        }
34423
34424        return pts;
34425
34426    },
34427
34428    // Get sequence of points using getPointAt( u )
34429
34430    getSpacedPoints: function ( divisions ) {
34431
34432        if ( ! divisions ) divisions = 5;
34433
34434        var d, pts = [];
34435
34436        for ( d = 0; d <= divisions; d ++ ) {
34437
34438            pts.push( this.getPointAt( d / divisions ) );
34439
34440        }
34441
34442        return pts;
34443
34444    },
34445
34446    // Get total curve arc length
34447
34448    getLength: function () {
34449
34450        var lengths = this.getLengths();
34451        return lengths[ lengths.length - 1 ];
34452
34453    },
34454
34455    // Get list of cumulative segment lengths
34456
34457    getLengths: function ( divisions ) {
34458
34459        if ( ! divisions ) divisions = ( this.__arcLengthDivisions ) ? ( this.__arcLengthDivisions ) : 200;
34460
34461        if ( this.cacheArcLengths
34462            && ( this.cacheArcLengths.length === divisions + 1 )
34463            && ! this.needsUpdate ) {
34464
34465            //console.log( "cached", this.cacheArcLengths );
34466            return this.cacheArcLengths;
34467
34468        }
34469
34470        this.needsUpdate = false;
34471
34472        var cache = [];
34473        var current, last = this.getPoint( 0 );
34474        var p, sum = 0;
34475
34476        cache.push( 0 );
34477
34478        for ( p = 1; p <= divisions; p ++ ) {
34479
34480            current = this.getPoint ( p / divisions );
34481            sum += current.distanceTo( last );
34482            cache.push( sum );
34483            last = current;
34484
34485        }
34486
34487        this.cacheArcLengths = cache;
34488
34489        return cache; // { sums: cache, sum:sum }; Sum is in the last element.
34490
34491    },
34492
34493    updateArcLengths: function() {
34494
34495        this.needsUpdate = true;
34496        this.getLengths();
34497
34498    },
34499
34500    // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
34501
34502    getUtoTmapping: function ( u, distance ) {
34503
34504        var arcLengths = this.getLengths();
34505
34506        var i = 0, il = arcLengths.length;
34507
34508        var targetArcLength; // The targeted u distance value to get
34509
34510        if ( distance ) {
34511
34512            targetArcLength = distance;
34513
34514        } else {
34515
34516            targetArcLength = u * arcLengths[ il - 1 ];
34517
34518        }
34519
34520        //var time = Date.now();
34521
34522        // binary search for the index with largest value smaller than target u distance
34523
34524        var low = 0, high = il - 1, comparison;
34525
34526        while ( low <= high ) {
34527
34528            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
34529
34530            comparison = arcLengths[ i ] - targetArcLength;
34531
34532            if ( comparison < 0 ) {
34533
34534                low = i + 1;
34535
34536            } else if ( comparison > 0 ) {
34537
34538                high = i - 1;
34539
34540            } else {
34541
34542                high = i;
34543                break;
34544
34545                // DONE
34546
34547            }
34548
34549        }
34550
34551        i = high;
34552
34553        //console.log('b' , i, low, high, Date.now()- time);
34554
34555        if ( arcLengths[ i ] === targetArcLength ) {
34556
34557            var t = i / ( il - 1 );
34558            return t;
34559
34560        }
34561
34562        // we could get finer grain at lengths, or use simple interpolation between two points
34563
34564        var lengthBefore = arcLengths[ i ];
34565        var lengthAfter = arcLengths[ i + 1 ];
34566
34567        var segmentLength = lengthAfter - lengthBefore;
34568
34569        // determine where we are between the 'before' and 'after' points
34570
34571        var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
34572
34573        // add that fractional amount to t
34574
34575        var t = ( i + segmentFraction ) / ( il - 1 );
34576
34577        return t;
34578
34579    },
34580
34581    // Returns a unit vector tangent at t
34582    // In case any sub curve does not implement its tangent derivation,
34583    // 2 points a small delta apart will be used to find its gradient
34584    // which seems to give a reasonable approximation
34585
34586    getTangent: function( t ) {
34587
34588        var delta = 0.0001;
34589        var t1 = t - delta;
34590        var t2 = t + delta;
34591
34592        // Capping in case of danger
34593
34594        if ( t1 < 0 ) t1 = 0;
34595        if ( t2 > 1 ) t2 = 1;
34596
34597        var pt1 = this.getPoint( t1 );
34598        var pt2 = this.getPoint( t2 );
34599
34600        var vec = pt2.clone().sub( pt1 );
34601        return vec.normalize();
34602
34603    },
34604
34605    getTangentAt: function ( u ) {
34606
34607        var t = this.getUtoTmapping( u );
34608        return this.getTangent( t );
34609
34610    }
34611
34612};
34613
34614// TODO: Transformation for Curves?
34615
34616/**************************************************************
34617 *	3D Curves
34618 **************************************************************/
34619
34620// A Factory method for creating new curve subclasses
34621
34622THREE.Curve.create = function ( constructor, getPointFunc ) {
34623
34624    constructor.prototype = Object.create( THREE.Curve.prototype );
34625    constructor.prototype.constructor = constructor;
34626    constructor.prototype.getPoint = getPointFunc;
34627
34628    return constructor;
34629
34630};
34631
34632// File:src/extras/core/CurvePath.js
34633
34634/**
34635 * @author zz85 / http://www.lab4games.net/zz85/blog
34636 *
34637 **/
34638
34639/**************************************************************
34640 *	Curved Path - a curve path is simply a array of connected
34641 *  curves, but retains the api of a curve
34642 **************************************************************/
34643
34644THREE.CurvePath = function () {
34645
34646    this.curves = [];
34647
34648    this.autoClose = false; // Automatically closes the path
34649
34650};
34651
34652THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype );
34653THREE.CurvePath.prototype.constructor = THREE.CurvePath;
34654
34655THREE.CurvePath.prototype.add = function ( curve ) {
34656
34657    this.curves.push( curve );
34658
34659};
34660
34661/*
34662 THREE.CurvePath.prototype.checkConnection = function() {
34663 // TODO
34664 // If the ending of curve is not connected to the starting
34665 // or the next curve, then, this is not a real path
34666 };
34667 */
34668
34669THREE.CurvePath.prototype.closePath = function() {
34670
34671    // TODO Test
34672    // and verify for vector3 (needs to implement equals)
34673    // Add a line curve if start and end of lines are not connected
34674    var startPoint = this.curves[ 0 ].getPoint( 0 );
34675    var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
34676
34677    if ( ! startPoint.equals( endPoint ) ) {
34678
34679        this.curves.push( new THREE.LineCurve( endPoint, startPoint ) );
34680
34681    }
34682
34683};
34684
34685// To get accurate point with reference to
34686// entire path distance at time t,
34687// following has to be done:
34688
34689// 1. Length of each sub path have to be known
34690// 2. Locate and identify type of curve
34691// 3. Get t for the curve
34692// 4. Return curve.getPointAt(t')
34693
34694THREE.CurvePath.prototype.getPoint = function( t ) {
34695
34696    var d = t * this.getLength();
34697    var curveLengths = this.getCurveLengths();
34698    var i = 0;
34699
34700    // To think about boundaries points.
34701
34702    while ( i < curveLengths.length ) {
34703
34704        if ( curveLengths[ i ] >= d ) {
34705
34706            var diff = curveLengths[ i ] - d;
34707            var curve = this.curves[ i ];
34708
34709            var u = 1 - diff / curve.getLength();
34710
34711            return curve.getPointAt( u );
34712
34713        }
34714
34715        i ++;
34716
34717    }
34718
34719    return null;
34720
34721    // loop where sum != 0, sum > d , sum+1 <d
34722
34723};
34724
34725/*
34726 THREE.CurvePath.prototype.getTangent = function( t ) {
34727 };
34728 */
34729
34730// We cannot use the default THREE.Curve getPoint() with getLength() because in
34731// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
34732// getPoint() depends on getLength
34733
34734THREE.CurvePath.prototype.getLength = function() {
34735
34736    var lens = this.getCurveLengths();
34737    return lens[ lens.length - 1 ];
34738
34739};
34740
34741// Compute lengths and cache them
34742// We cannot overwrite getLengths() because UtoT mapping uses it.
34743
34744THREE.CurvePath.prototype.getCurveLengths = function() {
34745
34746    // We use cache values if curves and cache array are same length
34747
34748    if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
34749
34750        return this.cacheLengths;
34751
34752    }
34753
34754    // Get length of sub-curve
34755    // Push sums into cached array
34756
34757    var lengths = [], sums = 0;
34758
34759    for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
34760
34761        sums += this.curves[ i ].getLength();
34762        lengths.push( sums );
34763
34764    }
34765
34766    this.cacheLengths = lengths;
34767
34768    return lengths;
34769
34770};
34771
34772
34773
34774/**************************************************************
34775 *	Create Geometries Helpers
34776 **************************************************************/
34777
34778/// Generate geometry from path points (for Line or Points objects)
34779
34780THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
34781
34782    var pts = this.getPoints( divisions );
34783    return this.createGeometry( pts );
34784
34785};
34786
34787// Generate geometry from equidistant sampling along the path
34788
34789THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
34790
34791    var pts = this.getSpacedPoints( divisions );
34792    return this.createGeometry( pts );
34793
34794};
34795
34796THREE.CurvePath.prototype.createGeometry = function( points ) {
34797
34798    var geometry = new THREE.Geometry();
34799
34800    for ( var i = 0, l = points.length; i < l; i ++ ) {
34801
34802        var point = points[ i ];
34803        geometry.vertices.push( new THREE.Vector3( point.x, point.y, point.z || 0 ) );
34804
34805    }
34806
34807    return geometry;
34808
34809};
34810
34811// File:src/extras/core/Font.js
34812
34813/**
34814 * @author zz85 / http://www.lab4games.net/zz85/blog
34815 * @author mrdoob / http://mrdoob.com/
34816 */
34817
34818THREE.Font = function ( data ) {
34819
34820    this.data = data;
34821
34822};
34823
34824THREE.Font.prototype = {
34825
34826    constructor: THREE.Font,
34827
34828    generateShapes: function ( text, size, divisions ) {
34829
34830        function createPaths( text ) {
34831
34832            var chars = String( text ).split( '' );
34833            var scale = size / data.resolution;
34834            var offset = 0;
34835
34836            var paths = [];
34837
34838            for ( var i = 0; i < chars.length; i ++ ) {
34839
34840                var ret = createPath( chars[ i ], scale, offset );
34841                offset += ret.offset;
34842
34843                paths.push( ret.path );
34844
34845            }
34846
34847            return paths;
34848
34849        }
34850
34851        function createPath( c, scale, offset ) {
34852
34853            var glyph = data.glyphs[ c ] || data.glyphs[ '?' ];
34854
34855            if ( ! glyph ) return;
34856
34857            var path = new THREE.Path();
34858
34859            var pts = [], b2 = THREE.ShapeUtils.b2, b3 = THREE.ShapeUtils.b3;
34860            var x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2, laste;
34861
34862            if ( glyph.o ) {
34863
34864                var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
34865
34866                for ( var i = 0, l = outline.length; i < l; ) {
34867
34868                    var action = outline[ i ++ ];
34869
34870                    switch ( action ) {
34871
34872                        case 'm': // moveTo
34873
34874                            x = outline[ i ++ ] * scale + offset;
34875                            y = outline[ i ++ ] * scale;
34876
34877                            path.moveTo( x, y );
34878
34879                            break;
34880
34881                        case 'l': // lineTo
34882
34883                            x = outline[ i ++ ] * scale + offset;
34884                            y = outline[ i ++ ] * scale;
34885
34886                            path.lineTo( x, y );
34887
34888                            break;
34889
34890                        case 'q': // quadraticCurveTo
34891
34892                            cpx  = outline[ i ++ ] * scale + offset;
34893                            cpy  = outline[ i ++ ] * scale;
34894                            cpx1 = outline[ i ++ ] * scale + offset;
34895                            cpy1 = outline[ i ++ ] * scale;
34896
34897                            path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
34898
34899                            laste = pts[ pts.length - 1 ];
34900
34901                            if ( laste ) {
34902
34903                                cpx0 = laste.x;
34904                                cpy0 = laste.y;
34905
34906                                for ( var i2 = 1; i2 <= divisions; i2 ++ ) {
34907
34908                                    var t = i2 / divisions;
34909                                    b2( t, cpx0, cpx1, cpx );
34910                                    b2( t, cpy0, cpy1, cpy );
34911
34912                                }
34913
34914                            }
34915
34916                            break;
34917
34918                        case 'b': // bezierCurveTo
34919
34920                            cpx  = outline[ i ++ ] * scale + offset;
34921                            cpy  = outline[ i ++ ] * scale;
34922                            cpx1 = outline[ i ++ ] * scale + offset;
34923                            cpy1 = outline[ i ++ ] * scale;
34924                            cpx2 = outline[ i ++ ] * scale + offset;
34925                            cpy2 = outline[ i ++ ] * scale;
34926
34927                            path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
34928
34929                            laste = pts[ pts.length - 1 ];
34930
34931                            if ( laste ) {
34932
34933                                cpx0 = laste.x;
34934                                cpy0 = laste.y;
34935
34936                                for ( var i2 = 1; i2 <= divisions; i2 ++ ) {
34937
34938                                    var t = i2 / divisions;
34939                                    b3( t, cpx0, cpx1, cpx2, cpx );
34940                                    b3( t, cpy0, cpy1, cpy2, cpy );
34941
34942                                }
34943
34944                            }
34945
34946                            break;
34947
34948                    }
34949
34950                }
34951
34952            }
34953
34954            return { offset: glyph.ha * scale, path: path };
34955
34956        }
34957
34958        //
34959
34960        if ( size === undefined ) size = 100;
34961        if ( divisions === undefined ) divisions = 4;
34962
34963        var data = this.data;
34964
34965        var paths = createPaths( text );
34966        var shapes = [];
34967
34968        for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
34969
34970            Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
34971
34972        }
34973
34974        return shapes;
34975
34976    }
34977
34978};
34979
34980// File:src/extras/core/Path.js
34981
34982/**
34983 * @author zz85 / http://www.lab4games.net/zz85/blog
34984 * Creates free form 2d path using series of points, lines or curves.
34985 *
34986 **/
34987
34988THREE.Path = function ( points ) {
34989
34990    THREE.CurvePath.call( this );
34991
34992    this.actions = [];
34993
34994    if ( points ) {
34995
34996        this.fromPoints( points );
34997
34998    }
34999
35000};
35001
35002THREE.Path.prototype = Object.create( THREE.CurvePath.prototype );
35003THREE.Path.prototype.constructor = THREE.Path;
35004
35005// TODO Clean up PATH API
35006
35007// Create path using straight lines to connect all points
35008// - vectors: array of Vector2
35009
35010THREE.Path.prototype.fromPoints = function ( vectors ) {
35011
35012    this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
35013
35014    for ( var i = 1, l = vectors.length; i < l; i ++ ) {
35015
35016        this.lineTo( vectors[ i ].x, vectors[ i ].y );
35017
35018    }
35019
35020};
35021
35022// startPath() endPath()?
35023
35024THREE.Path.prototype.moveTo = function ( x, y ) {
35025
35026    this.actions.push( { action: 'moveTo', args: [ x, y ] } );
35027
35028};
35029
35030THREE.Path.prototype.lineTo = function ( x, y ) {
35031
35032    var lastargs = this.actions[ this.actions.length - 1 ].args;
35033
35034    var x0 = lastargs[ lastargs.length - 2 ];
35035    var y0 = lastargs[ lastargs.length - 1 ];
35036
35037    var curve = new THREE.LineCurve( new THREE.Vector2( x0, y0 ), new THREE.Vector2( x, y ) );
35038    this.curves.push( curve );
35039
35040    this.actions.push( { action: 'lineTo', args: [ x, y ] } );
35041
35042};
35043
35044THREE.Path.prototype.quadraticCurveTo = function( aCPx, aCPy, aX, aY ) {
35045
35046    var lastargs = this.actions[ this.actions.length - 1 ].args;
35047
35048    var x0 = lastargs[ lastargs.length - 2 ];
35049    var y0 = lastargs[ lastargs.length - 1 ];
35050
35051    var curve = new THREE.QuadraticBezierCurve(
35052        new THREE.Vector2( x0, y0 ),
35053        new THREE.Vector2( aCPx, aCPy ),
35054        new THREE.Vector2( aX, aY )
35055    );
35056
35057    this.curves.push( curve );
35058
35059    this.actions.push( { action: 'quadraticCurveTo', args: [ aCPx, aCPy, aX, aY ] } );
35060
35061};
35062
35063THREE.Path.prototype.bezierCurveTo = function( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
35064
35065    var lastargs = this.actions[ this.actions.length - 1 ].args;
35066
35067    var x0 = lastargs[ lastargs.length - 2 ];
35068    var y0 = lastargs[ lastargs.length - 1 ];
35069
35070    var curve = new THREE.CubicBezierCurve(
35071        new THREE.Vector2( x0, y0 ),
35072        new THREE.Vector2( aCP1x, aCP1y ),
35073        new THREE.Vector2( aCP2x, aCP2y ),
35074        new THREE.Vector2( aX, aY )
35075    );
35076
35077    this.curves.push( curve );
35078
35079    this.actions.push( { action: 'bezierCurveTo', args: [ aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ] } );
35080
35081};
35082
35083THREE.Path.prototype.splineThru = function( pts /*Array of Vector*/ ) {
35084
35085    var args = Array.prototype.slice.call( arguments );
35086
35087    var lastargs = this.actions[ this.actions.length - 1 ].args;
35088
35089    var x0 = lastargs[ lastargs.length - 2 ];
35090    var y0 = lastargs[ lastargs.length - 1 ];
35091
35092    var npts = [ new THREE.Vector2( x0, y0 ) ];
35093    Array.prototype.push.apply( npts, pts );
35094
35095    var curve = new THREE.SplineCurve( npts );
35096    this.curves.push( curve );
35097
35098    this.actions.push( { action: 'splineThru', args: args } );
35099
35100};
35101
35102// FUTURE: Change the API or follow canvas API?
35103
35104THREE.Path.prototype.arc = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
35105
35106    var lastargs = this.actions[ this.actions.length - 1 ].args;
35107    var x0 = lastargs[ lastargs.length - 2 ];
35108    var y0 = lastargs[ lastargs.length - 1 ];
35109
35110    this.absarc( aX + x0, aY + y0, aRadius,
35111        aStartAngle, aEndAngle, aClockwise );
35112
35113};
35114
35115THREE.Path.prototype.absarc = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
35116
35117    this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
35118
35119};
35120
35121THREE.Path.prototype.ellipse = function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
35122
35123    var lastargs = this.actions[ this.actions.length - 1 ].args;
35124    var x0 = lastargs[ lastargs.length - 2 ];
35125    var y0 = lastargs[ lastargs.length - 1 ];
35126
35127    this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
35128
35129};
35130
35131
35132THREE.Path.prototype.absellipse = function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
35133
35134    var args = [
35135        aX, aY,
35136        xRadius, yRadius,
35137        aStartAngle, aEndAngle,
35138        aClockwise,
35139        aRotation || 0 // aRotation is optional.
35140    ];
35141
35142    var curve = new THREE.EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
35143    this.curves.push( curve );
35144
35145    var lastPoint = curve.getPoint( 1 );
35146    args.push( lastPoint.x );
35147    args.push( lastPoint.y );
35148
35149    this.actions.push( { action: 'ellipse', args: args } );
35150
35151};
35152
35153THREE.Path.prototype.getSpacedPoints = function ( divisions ) {
35154
35155    if ( ! divisions ) divisions = 40;
35156
35157    var points = [];
35158
35159    for ( var i = 0; i < divisions; i ++ ) {
35160
35161        points.push( this.getPoint( i / divisions ) );
35162
35163        //if ( !this.getPoint( i / divisions ) ) throw "DIE";
35164
35165    }
35166
35167    if ( this.autoClose ) {
35168
35169        points.push( points[ 0 ] );
35170
35171    }
35172
35173    return points;
35174
35175};
35176
35177/* Return an array of vectors based on contour of the path */
35178
35179THREE.Path.prototype.getPoints = function( divisions ) {
35180
35181    divisions = divisions || 12;
35182
35183    var b2 = THREE.ShapeUtils.b2;
35184    var b3 = THREE.ShapeUtils.b3;
35185
35186    var points = [];
35187
35188    var cpx, cpy, cpx2, cpy2, cpx1, cpy1, cpx0, cpy0,
35189        laste, tx, ty;
35190
35191    for ( var i = 0, l = this.actions.length; i < l; i ++ ) {
35192
35193        var item = this.actions[ i ];
35194
35195        var action = item.action;
35196        var args = item.args;
35197
35198        switch ( action ) {
35199
35200            case 'moveTo':
35201
35202                points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
35203
35204                break;
35205
35206            case 'lineTo':
35207
35208                points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
35209
35210                break;
35211
35212            case 'quadraticCurveTo':
35213
35214                cpx  = args[ 2 ];
35215                cpy  = args[ 3 ];
35216
35217                cpx1 = args[ 0 ];
35218                cpy1 = args[ 1 ];
35219
35220                if ( points.length > 0 ) {
35221
35222                    laste = points[ points.length - 1 ];
35223
35224                    cpx0 = laste.x;
35225                    cpy0 = laste.y;
35226
35227                } else {
35228
35229                    laste = this.actions[ i - 1 ].args;
35230
35231                    cpx0 = laste[ laste.length - 2 ];
35232                    cpy0 = laste[ laste.length - 1 ];
35233
35234                }
35235
35236                for ( var j = 1; j <= divisions; j ++ ) {
35237
35238                    var t = j / divisions;
35239
35240                    tx = b2( t, cpx0, cpx1, cpx );
35241                    ty = b2( t, cpy0, cpy1, cpy );
35242
35243                    points.push( new THREE.Vector2( tx, ty ) );
35244
35245                }
35246
35247                break;
35248
35249            case 'bezierCurveTo':
35250
35251                cpx  = args[ 4 ];
35252                cpy  = args[ 5 ];
35253
35254                cpx1 = args[ 0 ];
35255                cpy1 = args[ 1 ];
35256
35257                cpx2 = args[ 2 ];
35258                cpy2 = args[ 3 ];
35259
35260                if ( points.length > 0 ) {
35261
35262                    laste = points[ points.length - 1 ];
35263
35264                    cpx0 = laste.x;
35265                    cpy0 = laste.y;
35266
35267                } else {
35268
35269                    laste = this.actions[ i - 1 ].args;
35270
35271                    cpx0 = laste[ laste.length - 2 ];
35272                    cpy0 = laste[ laste.length - 1 ];
35273
35274                }
35275
35276
35277                for ( var j = 1; j <= divisions; j ++ ) {
35278
35279                    var t = j / divisions;
35280
35281                    tx = b3( t, cpx0, cpx1, cpx2, cpx );
35282                    ty = b3( t, cpy0, cpy1, cpy2, cpy );
35283
35284                    points.push( new THREE.Vector2( tx, ty ) );
35285
35286                }
35287
35288                break;
35289
35290            case 'splineThru':
35291
35292                laste = this.actions[ i - 1 ].args;
35293
35294                var last = new THREE.Vector2( laste[ laste.length - 2 ], laste[ laste.length - 1 ] );
35295                var spts = [ last ];
35296
35297                var n = divisions * args[ 0 ].length;
35298
35299                spts = spts.concat( args[ 0 ] );
35300
35301                var spline = new THREE.SplineCurve( spts );
35302
35303                for ( var j = 1; j <= n; j ++ ) {
35304
35305                    points.push( spline.getPointAt( j / n ) );
35306
35307                }
35308
35309                break;
35310
35311            case 'arc':
35312
35313                var aX = args[ 0 ], aY = args[ 1 ],
35314                    aRadius = args[ 2 ],
35315                    aStartAngle = args[ 3 ], aEndAngle = args[ 4 ],
35316                    aClockwise = !! args[ 5 ];
35317
35318                var deltaAngle = aEndAngle - aStartAngle;
35319                var angle;
35320                var tdivisions = divisions * 2;
35321
35322                for ( var j = 1; j <= tdivisions; j ++ ) {
35323
35324                    var t = j / tdivisions;
35325
35326                    if ( ! aClockwise ) {
35327
35328                        t = 1 - t;
35329
35330                    }
35331
35332                    angle = aStartAngle + t * deltaAngle;
35333
35334                    tx = aX + aRadius * Math.cos( angle );
35335                    ty = aY + aRadius * Math.sin( angle );
35336
35337                    //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
35338
35339                    points.push( new THREE.Vector2( tx, ty ) );
35340
35341                }
35342
35343                //console.log(points);
35344
35345                break;
35346
35347            case 'ellipse':
35348
35349                var aX = args[ 0 ], aY = args[ 1 ],
35350                    xRadius = args[ 2 ],
35351                    yRadius = args[ 3 ],
35352                    aStartAngle = args[ 4 ], aEndAngle = args[ 5 ],
35353                    aClockwise = !! args[ 6 ],
35354                    aRotation = args[ 7 ];
35355
35356
35357                var deltaAngle = aEndAngle - aStartAngle;
35358                var angle;
35359                var tdivisions = divisions * 2;
35360
35361                var cos, sin;
35362                if ( aRotation !== 0 ) {
35363
35364                    cos = Math.cos( aRotation );
35365                    sin = Math.sin( aRotation );
35366
35367                }
35368
35369                for ( var j = 1; j <= tdivisions; j ++ ) {
35370
35371                    var t = j / tdivisions;
35372
35373                    if ( ! aClockwise ) {
35374
35375                        t = 1 - t;
35376
35377                    }
35378
35379                    angle = aStartAngle + t * deltaAngle;
35380
35381                    tx = aX + xRadius * Math.cos( angle );
35382                    ty = aY + yRadi
35382us * Math.sin( angle );
35383
35384                    if ( aRotation !== 0 ) {
35385
35386                        var x = tx, y = ty;
35387
35388                        // Rotate the point about the center of the ellipse.
35389                        tx = ( x - aX ) * cos - ( y - aY ) * sin + aX;
35390                        ty = ( x - aX ) * sin + ( y - aY ) * cos + aY;
35391
35392                    }
35393
35394                    //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
35395
35396                    points.push( new THREE.Vector2( tx, ty ) );
35397
35398                }
35399
35400                //console.log(points);
35401
35402                break;
35403
35404        } // end switch
35405
35406    }
35407
35408
35409
35410    // Normalize to remove the closing point by default.
35411    var lastPoint = points[ points.length - 1 ];
35412    if ( Math.abs( lastPoint.x - points[ 0 ].x ) < Number.EPSILON &&
35413        Math.abs( lastPoint.y - points[ 0 ].y ) < Number.EPSILON )
35414        points.splice( points.length - 1, 1 );
35415
35416    if ( this.autoClose ) {
35417
35418        points.push( points[ 0 ] );
35419
35420    }
35421
35422    return points;
35423
35424};
35425
35426//
35427// Breaks path into shapes
35428//
35429//	Assumptions (if parameter isCCW==true the opposite holds):
35430//	- solid shapes are defined clockwise (CW)
35431//	- holes are defined counterclockwise (CCW)
35432//
35433//	If parameter noHoles==true:
35434//  - all subPaths are regarded as solid shapes
35435//  - definition order CW/CCW has no relevance
35436//
35437
35438THREE.Path.prototype.toShapes = function( isCCW, noHoles ) {
35439
35440    function extractSubpaths( inActions ) {
35441
35442        var subPaths = [], lastPath = new THREE.Path();
35443
35444        for ( var i = 0, l = inActions.length; i < l; i ++ ) {
35445
35446            var item = inActions[ i ];
35447
35448            var args = item.args;
35449            var action = item.action;
35450
35451            if ( action === 'moveTo' ) {
35452
35453                if ( lastPath.actions.length !== 0 ) {
35454
35455                    subPaths.push( lastPath );
35456                    lastPath = new THREE.Path();
35457
35458                }
35459
35460            }
35461
35462            lastPath[ action ].apply( lastPath, args );
35463
35464        }
35465
35466        if ( lastPath.actions.length !== 0 ) {
35467
35468            subPaths.push( lastPath );
35469
35470        }
35471
35472        // console.log(subPaths);
35473
35474        return	subPaths;
35475
35476    }
35477
35478    function toShapesNoHoles( inSubpaths ) {
35479
35480        var shapes = [];
35481
35482        for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) {
35483
35484            var tmpPath = inSubpaths[ i ];
35485
35486            var tmpShape = new THREE.Shape();
35487            tmpShape.actions = tmpPath.actions;
35488            tmpShape.curves = tmpPath.curves;
35489
35490            shapes.push( tmpShape );
35491
35492        }
35493
35494        //console.log("shape", shapes);
35495
35496        return shapes;
35497
35498    }
35499
35500    function isPointInsidePolygon( inPt, inPolygon ) {
35501
35502        var polyLen = inPolygon.length;
35503
35504        // inPt on polygon contour => immediate success    or
35505        // toggling of inside/outside at every single! intersection point of an edge
35506        //  with the horizontal line through inPt, left of inPt
35507        //  not counting lowerY endpoints of edges and whole edges on that line
35508        var inside = false;
35509        for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
35510
35511            var edgeLowPt  = inPolygon[ p ];
35512            var edgeHighPt = inPolygon[ q ];
35513
35514            var edgeDx = edgeHighPt.x - edgeLowPt.x;
35515            var edgeDy = edgeHighPt.y - edgeLowPt.y;
35516
35517            if ( Math.abs( edgeDy ) > Number.EPSILON ) {
35518
35519                // not parallel
35520                if ( edgeDy < 0 ) {
35521
35522                    edgeLowPt  = inPolygon[ q ]; edgeDx = - edgeDx;
35523                    edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
35524
35525                }
35526                if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) 		continue;
35527
35528                if ( inPt.y === edgeLowPt.y ) {
35529
35530                    if ( inPt.x === edgeLowPt.x )		return	true;		// inPt is on contour ?
35531                    // continue;				// no intersection or edgeLowPt => doesn't count !!!
35532
35533                } else {
35534
35535                    var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
35536                    if ( perpEdge === 0 )				return	true;		// inPt is on contour ?
35537                    if ( perpEdge < 0 ) 				continue;
35538                    inside = ! inside;		// true intersection left of inPt
35539
35540                }
35541
35542            } else {
35543
35544                // parallel or collinear
35545                if ( inPt.y !== edgeLowPt.y ) 		continue;			// parallel
35546                // edge lies on the same horizontal line as inPt
35547                if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
35548                    ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )		return	true;	// inPt: Point on contour !
35549                // continue;
35550
35551            }
35552
35553        }
35554
35555        return	inside;
35556
35557    }
35558
35559    var isClockWise = THREE.ShapeUtils.isClockWise;
35560
35561    var subPaths = extractSubpaths( this.actions );
35562    if ( subPaths.length === 0 ) return [];
35563
35564    if ( noHoles === true )	return	toShapesNoHoles( subPaths );
35565
35566
35567    var solid, tmpPath, tmpShape, shapes = [];
35568
35569    if ( subPaths.length === 1 ) {
35570
35571        tmpPath = subPaths[ 0 ];
35572        tmpShape = new THREE.Shape();
35573        tmpShape.actions = tmpPath.actions;
35574        tmpShape.curves = tmpPath.curves;
35575        shapes.push( tmpShape );
35576        return shapes;
35577
35578    }
35579
35580    var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
35581    holesFirst = isCCW ? ! holesFirst : holesFirst;
35582
35583    // console.log("Holes first", holesFirst);
35584
35585    var betterShapeHoles = [];
35586    var newShapes = [];
35587    var newShapeHoles = [];
35588    var mainIdx = 0;
35589    var tmpPoints;
35590
35591    newShapes[ mainIdx ] = undefined;
35592    newShapeHoles[ mainIdx ] = [];
35593
35594    for ( var i = 0, l = subPaths.length; i < l; i ++ ) {
35595
35596        tmpPath = subPaths[ i ];
35597        tmpPoints = tmpPath.getPoints();
35598        solid = isClockWise( tmpPoints );
35599        solid = isCCW ? ! solid : solid;
35600
35601        if ( solid ) {
35602
35603            if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )	mainIdx ++;
35604
35605            newShapes[ mainIdx ] = { s: new THREE.Shape(), p: tmpPoints };
35606            newShapes[ mainIdx ].s.actions = tmpPath.actions;
35607            newShapes[ mainIdx ].s.curves = tmpPath.curves;
35608
35609            if ( holesFirst )	mainIdx ++;
35610            newShapeHoles[ mainIdx ] = [];
35611
35612            //console.log('cw', i);
35613
35614        } else {
35615
35616            newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
35617
35618            //console.log('ccw', i);
35619
35620        }
35621
35622    }
35623
35624    // only Holes? -> probably all Shapes with wrong orientation
35625    if ( ! newShapes[ 0 ] )	return	toShapesNoHoles( subPaths );
35626
35627
35628    if ( newShapes.length > 1 ) {
35629
35630        var ambiguous = false;
35631        var toChange = [];
35632
35633        for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
35634
35635            betterShapeHoles[ sIdx ] = [];
35636
35637        }
35638
35639        for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
35640
35641            var sho = newShapeHoles[ sIdx ];
35642
35643            for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
35644
35645                var ho = sho[ hIdx ];
35646                var hole_unassigned = true;
35647
35648                for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
35649
35650                    if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
35651
35652                        if ( sIdx !== s2Idx )	toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
35653                        if ( hole_unassigned ) {
35654
35655                            hole_unassigned = false;
35656                            betterShapeHoles[ s2Idx ].push( ho );
35657
35658                        } else {
35659
35660                            ambiguous = true;
35661
35662                        }
35663
35664                    }
35665
35666                }
35667                if ( hole_unassigned ) {
35668
35669                    betterShapeHoles[ sIdx ].push( ho );
35670
35671                }
35672
35673            }
35674
35675        }
35676        // console.log("ambiguous: ", ambiguous);
35677        if ( toChange.length > 0 ) {
35678
35679            // console.log("to change: ", toChange);
35680            if ( ! ambiguous )	newShapeHoles = betterShapeHoles;
35681
35682        }
35683
35684    }
35685
35686    var tmpHoles;
35687
35688    for ( var i = 0, il = newShapes.length; i < il; i ++ ) {
35689
35690        tmpShape = newShapes[ i ].s;
35691        shapes.push( tmpShape );
35692        tmpHoles = newShapeHoles[ i ];
35693
35694        for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
35695
35696            tmpShape.holes.push( tmpHoles[ j ].h );
35697
35698        }
35699
35700    }
35701
35702    //console.log("shape", shapes);
35703
35704    return shapes;
35705
35706};
35707
35708// File:src/extras/core/Shape.js
35709
35710/**
35711 * @author zz85 / http://www.lab4games.net/zz85/blog
35712 * Defines a 2d shape plane using paths.
35713 **/
35714
35715// STEP 1 Create a path.
35716// STEP 2 Turn path into shape.
35717// STEP 3 ExtrudeGeometry takes in Shape/Shapes
35718// STEP 3a - Extract points from each shape, turn to vertices
35719// STEP 3b - Triangulate each shape, add faces.
35720
35721THREE.Shape = function () {
35722
35723    THREE.Path.apply( this, arguments );
35724
35725    this.holes = [];
35726
35727};
35728
35729THREE.Shape.prototype = Object.create( THREE.Path.prototype );
35730THREE.Shape.prototype.constructor = THREE.Shape;
35731
35732// Convenience method to return ExtrudeGeometry
35733
35734THREE.Shape.prototype.extrude = function ( options ) {
35735
35736    return new THREE.ExtrudeGeometry( this, options );
35737
35738};
35739
35740// Convenience method to return ShapeGeometry
35741
35742THREE.Shape.prototype.makeGeometry = function ( options ) {
35743
35744    return new THREE.ShapeGeometry( this, options );
35745
35746};
35747
35748// Get points of holes
35749
35750THREE.Shape.prototype.getPointsHoles = function ( divisions ) {
35751
35752    var holesPts = [];
35753
35754    for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
35755
35756        holesPts[ i ] = this.holes[ i ].getPoints( divisions );
35757
35758    }
35759
35760    return holesPts;
35761
35762};
35763
35764
35765// Get points of shape and holes (keypoints based on segments parameter)
35766
35767THREE.Shape.prototype.extractAllPoints = function ( divisions ) {
35768
35769    return {
35770
35771        shape: this.getPoints( divisions ),
35772        holes: this.getPointsHoles( divisions )
35773
35774    };
35775
35776};
35777
35778THREE.Shape.prototype.extractPoints = function ( divisions ) {
35779
35780    return this.extractAllPoints( divisions );
35781
35782};
35783
35784// File:src/extras/curves/LineCurve.js
35785
35786/**************************************************************
35787 *	Line
35788 **************************************************************/
35789
35790THREE.LineCurve = function ( v1, v2 ) {
35791
35792    this.v1 = v1;
35793    this.v2 = v2;
35794
35795};
35796
35797THREE.LineCurve.prototype = Object.create( THREE.Curve.prototype );
35798THREE.LineCurve.prototype.constructor = THREE.LineCurve;
35799
35800THREE.LineCurve.prototype.getPoint = function ( t ) {
35801
35802    var point = this.v2.clone().sub( this.v1 );
35803    point.multiplyScalar( t ).add( this.v1 );
35804
35805    return point;
35806
35807};
35808
35809// Line curve is linear, so we can overwrite default getPointAt
35810
35811THREE.LineCurve.prototype.getPointAt = function ( u ) {
35812
35813    return this.getPoint( u );
35814
35815};
35816
35817THREE.LineCurve.prototype.getTangent = function( t ) {
35818
35819    var tangent = this.v2.clone().sub( this.v1 );
35820
35821    return tangent.normalize();
35822
35823};
35824
35825// File:src/extras/curves/QuadraticBezierCurve.js
35826
35827/**************************************************************
35828 *	Quadratic Bezier curve
35829 **************************************************************/
35830
35831
35832THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) {
35833
35834    this.v0 = v0;
35835    this.v1 = v1;
35836    this.v2 = v2;
35837
35838};
35839
35840THREE.QuadraticBezierCurve.prototype = Object.create( THREE.Curve.prototype );
35841THREE.QuadraticBezierCurve.prototype.constructor = THREE.QuadraticBezierCurve;
35842
35843
35844THREE.QuadraticBezierCurve.prototype.getPoint = function ( t ) {
35845
35846    var b2 = THREE.ShapeUtils.b2;
35847
35848    return new THREE.Vector2(
35849        b2( t, this.v0.x, this.v1.x, this.v2.x ),
35850        b2( t, this.v0.y, this.v1.y, this.v2.y )
35851    );
35852
35853};
35854
35855
35856THREE.QuadraticBezierCurve.prototype.getTangent = function( t ) {
35857
35858    var tangentQuadraticBezier = THREE.CurveUtils.tangentQuadraticBezier;
35859
35860    return new THREE.Vector2(
35861        tangentQuadraticBezier( t, this.v0.x, this.v1.x, this.v2.x ),
35862        tangentQuadraticBezier( t, this.v0.y, this.v1.y, this.v2.y )
35863    ).normalize();
35864
35865};
35866
35867// File:src/extras/curves/CubicBezierCurve.js
35868
35869/**************************************************************
35870 *	Cubic Bezier curve
35871 **************************************************************/
35872
35873THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
35874
35875    this.v0 = v0;
35876    this.v1 = v1;
35877    this.v2 = v2;
35878    this.v3 = v3;
35879
35880};
35881
35882THREE.CubicBezierCurve.prototype = Object.create( THREE.Curve.prototype );
35883THREE.CubicBezierCurve.prototype.constructor = THREE.CubicBezierCurve;
35884
35885THREE.CubicBezierCurve.prototype.getPoint = function ( t ) {
35886
35887    var b3 = THREE.ShapeUtils.b3;
35888
35889    return new THREE.Vector2(
35890        b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x ),
35891        b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y )
35892    );
35893
35894};
35895
35896THREE.CubicBezierCurve.prototype.getTangent = function( t ) {
35897
35898    var tangentCubicBezier = THREE.CurveUtils.tangentCubicBezier;
35899
35900    return new THREE.Vector2(
35901        tangentCubicBezier( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x ),
35902        tangentCubicBezier( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y )
35903    ).normalize();
35904
35905};
35906
35907// File:src/extras/curves/SplineCurve.js
35908
35909/**************************************************************
35910 *	Spline curve
35911 **************************************************************/
35912
35913THREE.SplineCurve = function ( points /* array of Vector2 */ ) {
35914
35915    this.points = ( points == undefined ) ? [] : points;
35916
35917};
35918
35919THREE.SplineCurve.prototype = Object.create( THREE.Curve.prototype );
35920THREE.SplineCurve.prototype.constructor = THREE.SplineCurve;
35921
35922THREE.SplineCurve.prototype.getPoint = function ( t ) {
35923
35924    var points = this.points;
35925    var point = ( points.length - 1 ) * t;
35926
35927    var intPoint = Math.floor( point );
35928    var weight = point - intPoint;
35929
35930    var point0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
35931    var point1 = points[ intPoint ];
35932    var point2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
35933    var point3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
35934
35935    var interpolate = THREE.CurveUtils.interpolate;
35936
35937    return new THREE.Vector2(
35938        interpolate( point0.x, point1.x, point2.x, point3.x, weight ),
35939        interpolate( point0.y, point1.y, point2.y, point3.y, weight )
35940    );
35941
35942};
35943
35944// File:src/extras/curves/EllipseCurve.js
35945
35946/**************************************************************
35947 *	Ellipse curve
35948 **************************************************************/
35949
35950THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
35951
35952    this.aX = aX;
35953    this.aY = aY;
35954
35955    this.xRadius = xRadius;
35956    this.yRadius = yRadius;
35957
35958    this.aStartAngle = aStartAngle;
35959    this.aEndAngle = aEndAngle;
35960
35961    this.aClockwise = aClockwise;
35962
35963    this.aRotation = aRotation || 0;
35964
35965};
35966
35967THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype );
35968THREE.EllipseCurve.prototype.constructor = THREE.EllipseCurve;
35969
35970THREE.EllipseCurve.prototype.getPoint = function ( t ) {
35971
35972    var deltaAngle = this.aEndAngle - this.aStartAngle;
35973
35974    if ( deltaAngle < 0 ) deltaAngle += Math.PI * 2;
35975    if ( deltaAngle > Math.PI * 2 ) deltaAngle -= Math.PI * 2;
35976
35977    var angle;
35978
35979    if ( this.aClockwise === true ) {
35980
35981        angle = this.aEndAngle + ( 1 - t ) * ( Math.PI * 2 - deltaAngle );
35982
35983    } else {
35984
35985        angle = this.aStartAngle + t * deltaAngle;
35986
35987    }
35988
35989    var x = this.aX + this.xRadius * Math.cos( angle );
35990    var y = this.aY + this.yRadius * Math.sin( angle );
35991
35992    if ( this.aRotation !== 0 ) {
35993
35994        var cos = Math.cos( this.aRotation );
35995        var sin = Math.sin( this.aRotation );
35996
35997        var tx = x, ty = y;
35998
35999        // Rotate the point about the center of the ellipse.
36000        x = ( tx - this.aX ) * cos - ( ty - this.aY ) * sin + this.aX;
36001        y = ( tx - this.aX ) * sin + ( ty - this.aY ) * cos + this.aY;
36002
36003    }
36004
36005    return new THREE.Vector2( x, y );
36006
36007};
36008
36009// File:src/extras/curves/ArcCurve.js
36010
36011/**************************************************************
36012 *	Arc curve
36013 **************************************************************/
36014
36015THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
36016
36017    THREE.EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
36018
36019};
36020
36021THREE.ArcCurve.prototype = Object.create( THREE.EllipseCurve.prototype );
36022THREE.ArcCurve.prototype.constructor = THREE.ArcCurve;
36023
36024// File:src/extras/curves/LineCurve3.js
36025
36026/**************************************************************
36027 *	Line3D
36028 **************************************************************/
36029
36030THREE.LineCurve3 = THREE.Curve.create(
36031
36032    function ( v1, v2 ) {
36033
36034        this.v1 = v1;
36035        this.v2 = v2;
36036
36037    },
36038
36039    function ( t ) {
36040
36041        var vector = new THREE.Vector3();
36042
36043        vector.subVectors( this.v2, this.v1 ); // diff
36044        vector.multiplyScalar( t );
36045        vector.add( this.v1 );
36046
36047        return vector;
36048
36049    }
36050
36051);
36052
36053// File:src/extras/curves/QuadraticBezierCurve3.js
36054
36055/**************************************************************
36056 *	Quadratic Bezier 3D curve
36057 **************************************************************/
36058
36059THREE.QuadraticBezierCurve3 = THREE.Curve.create(
36060
36061    function ( v0, v1, v2 ) {
36062
36063        this.v0 = v0;
36064        this.v1 = v1;
36065        this.v2 = v2;
36066
36067    },
36068
36069    function ( t ) {
36070
36071        var b2 = THREE.ShapeUtils.b2;
36072
36073        return new THREE.Vector3(
36074            b2( t, this.v0.x, this.v1.x, this.v2.x ),
36075            b2( t, this.v0.y, this.v1.y, this.v2.y ),
36076            b2( t, this.v0.z, this.v1.z, this.v2.z )
36077        );
36078
36079    }
36080
36081);
36082
36083// File:src/extras/curves/CubicBezierCurve3.js
36084
36085/**************************************************************
36086 *	Cubic Bezier 3D curve
36087 **************************************************************/
36088
36089THREE.CubicBezierCurve3 = THREE.Curve.create(
36090
36091    function ( v0, v1, v2, v3 ) {
36092
36093        this.v0 = v0;
36094        this.v1 = v1;
36095        this.v2 = v2;
36096        this.v3 = v3;
36097
36098    },
36099
36100    function ( t ) {
36101
36102        var b3 = THREE.ShapeUtils.b3;
36103
36104        return new THREE.Vector3(
36105            b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x ),
36106            b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y ),
36107            b3( t, this.v0.z, this.v1.z, this.v2.z, this.v3.z )
36108        );
36109
36110    }
36111
36112);
36113
36114// File:src/extras/curves/SplineCurve3.js
36115
36116/**************************************************************
36117 *	Spline 3D curve
36118 **************************************************************/
36119
36120
36121THREE.SplineCurve3 = THREE.Curve.create(
36122
36123    function ( points /* array of Vector3 */ ) {
36124
36125        console.warn( 'THREE.SplineCurve3 will be deprecated. Please use THREE.CatmullRomCurve3' );
36126        this.points = ( points == undefined ) ? [] : points;
36127
36128    },
36129
36130    function ( t ) {
36131
36132        var points = this.points;
36133        var point = ( points.length - 1 ) * t;
36134
36135        var intPoint = Math.floor( point );
36136        var weight = point - intPoint;
36137
36138        var point0 = points[ intPoint == 0 ? intPoint : intPoint - 1 ];
36139        var point1 = points[ intPoint ];
36140        var point2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
36141        var point3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
36142
36143        var interpolate = THREE.CurveUtils.interpolate;
36144
36145        return new THREE.Vector3(
36146            interpolate( point0.x, point1.x, point2.x, point3.x, weight ),
36147            interpolate( point0.y, point1.y, point2.y, point3.y, weight ),
36148            interpolate( point0.z, point1.z, point2.z, point3.z, weight )
36149        );
36150
36151    }
36152
36153);
36154
36155// File:src/extras/curves/CatmullRomCurve3.js
36156
36157/**
36158 * @author zz85 https://github.com/zz85
36159 *
36160 * Centripetal CatmullRom Curve - which is useful for avoiding
36161 * cusps and self-intersections in non-uniform catmull rom curves.
36162 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
36163 *
36164 * curve.type accepts centripetal(default), chordal and catmullrom
36165 * curve.tension is used for catmullrom which defaults to 0.5
36166 */
36167
36168THREE.CatmullRomCurve3 = ( function() {
36169
36170    var
36171        tmp = new THREE.Vector3(),
36172        px = new CubicPoly(),
36173        py = new CubicPoly(),
36174        pz = new CubicPoly();
36175
36176    /*
36177     Based on an optimized c++ solution in
36178     - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
36179     - http://ideone.com/NoEbVM
36180
36181     This CubicPoly class could be used for reusing some variables and calculations,
36182     but for three.js curve use, it could be possible inlined and flatten into a single function call
36183     which can be placed in CurveUtils.
36184     */
36185
36186    function CubicPoly() {
36187
36188    }
36189
36190    /*
36191     * Compute coefficients for a cubic polynomial
36192     *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
36193     * such that
36194     *   p(0) = x0, p(1) = x1
36195     *  and
36196     *   p'(0) = t0, p'(1) = t1.
36197     */
36198    CubicPoly.prototype.init = function( x0, x1, t0, t1 ) {
36199
36200        this.c0 = x0;
36201        this.c1 = t0;
36202        this.c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
36203        this.c3 = 2 * x0 - 2 * x1 + t0 + t1;
36204
36205    };
36206
36207    CubicPoly.prototype.initNonuniformCatmullRom = function( x0, x1, x2, x3, dt0, dt1, dt2 ) {
36208
36209        // compute tangents when parameterized in [t1,t2]
36210        var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
36211        var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
36212
36213        // rescale tangents for parametrization in [0,1]
36214        t1 *= dt1;
36215        t2 *= dt1;
36216
36217        // initCubicPoly
36218        this.init( x1, x2, t1, t2 );
36219
36220    };
36221
36222    // standard Catmull-Rom spline: interpolate between x1 and x2 with previous/following points x1/x4
36223    CubicPoly.prototype.initCatmullRom = function( x0, x1, x2, x3, tension ) {
36224
36225        this.init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
36226
36227    };
36228
36229    CubicPoly.prototype.calc = function( t ) {
36230
36231        var t2 = t * t;
36232        var t3 = t2 * t;
36233        return this.c0 + this.c1 * t + this.c2 * t2 + this.c3 * t3;
36234
36235    };
36236
36237    // Subclass Three.js curve
36238    return THREE.Curve.create(
36239
36240        function ( p /* array of Vector3 */ ) {
36241
36242            this.points = p || [];
36243            this.closed = false;
36244
36245        },
36246
36247        function ( t ) {
36248
36249            var points = this.points,
36250                point, intPoint, weight, l;
36251
36252            l = points.length;
36253
36254            if ( l < 2 ) console.log( 'duh, you need at least 2 points' );
36255
36256            point = ( l - ( this.closed ? 0 : 1 ) ) * t;
36257            intPoint = Math.floor( point );
36258            weight = point - intPoint;
36259
36260            if ( this.closed ) {
36261
36262                intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length;
36263
36264            } else if ( weight === 0 && intPoint === l - 1 ) {
36265
36266                intPoint = l - 2;
36267                weight = 1;
36268
36269            }
36270
36271            var p0, p1, p2, p3; // 4 points
36272
36273            if ( this.closed || intPoint > 0 ) {
36274
36275                p0 = points[ ( intPoint - 1 ) % l ];
36276
36277            } else {
36278
36279                // extrapolate first point
36280                tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
36281                p0 = tmp;
36282
36283            }
36284
36285            p1 = points[ intPoint % l ];
36286            p2 = points[ ( intPoint + 1 ) % l ];
36287
36288            if ( this.closed || intPoint + 2 < l ) {
36289
36290                p3 = points[ ( intPoint + 2 ) % l ];
36291
36292            } else {
36293
36294                // extrapolate last point
36295                tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
36296                p3 = tmp;
36297
36298            }
36299
36300            if ( this.type === undefined || this.type === 'centripetal' || this.type === 'chordal' ) {
36301
36302                // init Centripetal / Chordal Catmull-Rom
36303                var pow = this.type === 'chordal' ? 0.5 : 0.25;
36304                var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
36305                var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
36306                var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
36307
36308                // safety check for repeated points
36309                if ( dt1 < 1e-4 ) dt1 = 1.0;
36310                if ( dt0 < 1e-4 ) dt0 = dt1;
36311                if ( dt2 < 1e-4 ) dt2 = dt1;
36312
36313                px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
36314                py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
36315                pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
36316
36317            } else if ( this.type === 'catmullrom' ) {
36318
36319                var tension = this.tension !== undefined ? this.tension : 0.5;
36320                px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, tension );
36321                py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, tension );
36322                pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, tension );
36323
36324            }
36325
36326            var v = new THREE.Vector3(
36327                px.calc( weight ),
36328                py.calc( weight ),
36329                pz.calc( weight )
36330            );
36331
36332            return v;
36333
36334        }
36335
36336    );
36337
36338} )();
36339
36340// File:src/extras/curves/ClosedSplineCurve3.js
36341
36342/**************************************************************
36343 *	Closed Spline 3D curve
36344 **************************************************************/
36345
36346
36347THREE.ClosedSplineCurve3 = function ( points ) {
36348
36349    console.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Please use THREE.CatmullRomCurve3.' );
36350
36351    THREE.CatmullRomCurve3.call( this, points );
36352    this.type = 'catmullrom';
36353    this.closed = true;
36354
36355};
36356
36357THREE.ClosedSplineCurve3.prototype = Object.create( THREE.CatmullRomCurve3.prototype );
36358
36359// File:src/extras/geometries/BoxGeometry.js
36360
36361/**
36362 * @author mrdoob / http://mrdoob.com/
36363 * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Cube.as
36364 */
36365
36366THREE.BoxGeometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {
36367
36368    THREE.Geometry.call( this );
36369
36370    this.type = 'BoxGeometry';
36371
36372    this.parameters = {
36373        width: width,
36374        height: height,
36375        depth: depth,
36376        widthSegments: widthSegments,
36377        heightSegments: heightSegments,
36378        depthSegments: depthSegments
36379    };
36380
36381    this.fromBufferGeometry( new THREE.BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
36382    this.mergeVertices();
36383
36384};
36385
36386THREE.BoxGeometry.prototype = Object.create( THREE.Geometry.prototype );
36387THREE.BoxGeometry.prototype.constructor = THREE.BoxGeometry;
36388
36389THREE.CubeGeometry = THREE.BoxGeometry;
36390
36391// File:src/extras/geometries/BoxBufferGeometry.js
36392
36393/**
36394 * @author Mugen87 / https://github.com/Mugen87
36395 */
36396
36397THREE.BoxBufferGeometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {
36398
36399    THREE.BufferGeometry.call( this );
36400
36401    this.type = 'BoxBufferGeometry';
36402
36403    this.parameters = {
36404        width: width,
36405        height: height,
36406        depth: depth,
36407        widthSegments: widthSegments,
36408        heightSegments: heightSegments,
36409        depthSegments: depthSegments
36410    };
36411
36412    var scope = this;
36413
36414    // segments
36415    widthSegments = Math.floor( widthSegments ) || 1;
36416    heightSegments = Math.floor( heightSegments ) || 1;
36417    depthSegments = Math.floor( depthSegments ) || 1;
36418
36419    // these are used to calculate buffer length
36420    var vertexCount = calculateVertexCount( widthSegments, heightSegments, depthSegments );
36421    var indexCount = ( vertexCount / 4 ) * 6;
36422
36423    // buffers
36424    var indices = new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount );
36425    var vertices = new Float32Array( vertexCount * 3 );
36426    var normals = new Float32Array( vertexCount * 3 );
36427    var uvs = new Float32Array( vertexCount * 2 );
36428
36429    // offset variables
36430    var vertexBufferOffset = 0;
36431    var uvBufferOffset = 0;
36432    var indexBufferOffset = 0;
36433    var numberOfVertices = 0;
36434
36435    // group variables
36436    var groupStart = 0;
36437
36438    // build each side of the box geometry
36439    buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height,   width,  depthSegments, heightSegments, 0 ); // px
36440    buildPlane( 'z', 'y', 'x',   1, - 1, depth, height, - width,  depthSegments, heightSegments, 1 ); // nx
36441    buildPlane( 'x', 'z', 'y',   1,   1, width, depth,    height, widthSegments, depthSegments,  2 ); // py
36442    buildPlane( 'x', 'z', 'y',   1, - 1, width, depth,  - height, widthSegments, depthSegments,  3 ); // ny
36443    buildPlane( 'x', 'y', 'z',   1, - 1, width, height,   depth,  widthSegments, heightSegments, 4 ); // pz
36444    buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth,  widthSegments, heightSegments, 5 ); // nz
36445
36446    // build geometry
36447    this.setIndex( new THREE.BufferAttribute( indices, 1 ) );
36448    this.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
36449    this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
36450    this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
36451
36452    // helper functions
36453
36454    function calculateVertexCount ( w, h, d ) {
36455
36456        var segments = 0;
36457
36458        // calculate the amount of segments for each side
36459        segments += w * h * 2; // xy
36460        segments += w * d * 2; // xz
36461        segments += d * h * 2; // zy
36462
36463        return segments * 4; // four vertices per segments
36464
36465    }
36466
36467    function buildPlane ( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
36468
36469        var segmentWidth	= width / gridX;
36470        var segmentHeight = height / gridY;
36471
36472        var widthHalf = width / 2;
36473        var heightHalf = height / 2;
36474        var depthHalf = depth / 2;
36475
36476        var gridX1 = gridX + 1;
36477        var gridY1 = gridY + 1;
36478
36479        var vertexCounter = 0;
36480        var groupCount = 0;
36481
36482        var vector = new THREE.Vector3();
36483
36484        // generate vertices, normals and uvs
36485
36486        for ( var iy = 0; iy < gridY1; iy ++ ) {
36487
36488            var y = iy * segmentHeight - heightHalf;
36489
36490            for ( var ix = 0; ix < gridX1; ix ++ ) {
36491
36492                var x = ix * segmentWidth - widthHalf;
36493
36494                // set values to correct vector component
36495                vector[ u ] = x * udir;
36496                vector[ v ] = y * vdir;
36497                vector[ w ] = depthHalf;
36498
36499                // now apply vector to vertex buffer
36500                vertices[ vertexBufferOffset ] = vector.x;
36501                vertices[ vertexBufferOffset + 1 ] = vector.y;
36502                vertices[ vertexBufferOffset + 2 ] = vector.z;
36503
36504                // set values to correct vector component
36505                vector[ u ] = 0;
36506                vector[ v ] = 0;
36507                vector[ w ] = depth > 0 ? 1 : - 1;
36508
36509                // now apply vector to normal buffer
36510                normals[ vertexBufferOffset ] = vector.x;
36511                normals[ vertexBufferOffset + 1 ] = vector.y;
36512                normals[ vertexBufferOffset + 2 ] = vector.z;
36513
36514                // uvs
36515                uvs[ uvBufferOffset ] = ix / gridX;
36516                uvs[ uvBufferOffset + 1 ] = 1 - ( iy / gridY );
36517
36518                // update offsets and counters
36519                vertexBufferOffset += 3;
36520                uvBufferOffset += 2;
36521                vertexCounter += 1;
36522
36523            }
36524
36525        }
36526
36527        // 1. you need three indices to draw a single face
36528        // 2. a single segment consists of two faces
36529        // 3. so we need to generate six (2*3) indices per segment
36530
36531        for ( iy = 0; iy < gridY; iy ++ ) {
36532
36533            for ( ix = 0; ix < gridX; ix ++ ) {
36534
36535                // indices
36536                var a = numberOfVertices + ix + gridX1 * iy;
36537                var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
36538                var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
36539                var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
36540
36541                // face one
36542                indices[ indexBufferOffset ] = a;
36543                indices[ indexBufferOffset + 1 ] = b;
36544                indices[ indexBufferOffset + 2 ] = d;
36545
36546                // face two
36547                indices[ indexBufferOffset + 3 ] = b;
36548                indices[ indexBufferOffset + 4 ] = c;
36549                indices[ indexBufferOffset + 5 ] = d;
36550
36551                // update offsets and counters
36552                indexBufferOffset += 6;
36553                groupCount += 6;
36554
36555            }
36556
36557        }
36558
36559        // add a group to the geometry. this will ensure multi material support
36560        scope.addGroup( groupStart, groupCount, materialIndex );
36561
36562        // calculate new start value for groups
36563        groupStart += groupCount;
36564
36565        // update total number of vertices
36566        numberOfVertices += vertexCounter;
36567
36568    }
36569
36570};
36571
36572THREE.BoxBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
36573THREE.BoxBufferGeometry.prototype.constructor = THREE.BoxBufferGeometry;
36574
36575// File:src/extras/geometries/CircleGeometry.js
36576
36577/**
36578 * @author hughes
36579 */
36580
36581THREE.CircleGeometry = function ( radius, segments, thetaStart, thetaLength ) {
36582
36583    THREE.Geometry.call( this );
36584
36585    this.type = 'CircleGeometry';
36586
36587    this.parameters = {
36588        radius: radius,
36589        segments: segments,
36590        thetaStart: thetaStart,
36591        thetaLength: thetaLength
36592    };
36593
36594    this.fromBufferGeometry( new THREE.CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );
36595
36596};
36597
36598THREE.CircleGeometry.prototype = Object.create( THREE.Geometry.prototype );
36599THREE.CircleGeometry.prototype.constructor = THREE.CircleGeometry;
36600
36601// File:src/extras/geometries/CircleBufferGeometry.js
36602
36603/**
36604 * @author benaadams / https://twitter.com/ben_a_adams
36605 */
36606
36607THREE.CircleBufferGeometry = function ( radius, segments, thetaStart, thetaLength ) {
36608
36609    THREE.BufferGeometry.call( this );
36610
36611    this.type = 'CircleBufferGeometry';
36612
36613    this.parameters = {
36614        radius: radius,
36615        segments: segments,
36616        thetaStart: thetaStart,
36617        thetaLength: thetaLength
36618    };
36619
36620    radius = radius || 50;
36621    segments = segments !== undefined ? Math.max( 3, segments ) : 8;
36622
36623    thetaStart = thetaStart !== undefined ? thetaStart : 0;
36624    thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
36625
36626    var vertices = segments + 2;
36627
36628    var positions = new Float32Array( vertices * 3 );
36629    var normals = new Float32Array( vertices * 3 );
36630    var uvs = new Float32Array( vertices * 2 );
36631
36632    // center data is already zero, but need to set a few extras
36633    normals[ 2 ] = 1.0;
36634    uvs[ 0 ] = 0.5;
36635    uvs[ 1 ] = 0.5;
36636
36637    for ( var s = 0, i = 3, ii = 2 ; s <= segments; s ++, i += 3, ii += 2 ) {
36638
36639        var segment = thetaStart + s / segments * thetaLength;
36640
36641        positions[ i ] = radius * Math.cos( segment );
36642        positions[ i + 1 ] = radius * Math.sin( segment );
36643
36644        normals[ i + 2 ] = 1; // normal z
36645
36646        uvs[ ii ] = ( positions[ i ] / radius + 1 ) / 2;
36647        uvs[ ii + 1 ] = ( positions[ i + 1 ] / radius + 1 ) / 2;
36648
36649    }
36650
36651    var indices = [];
36652
36653    for ( var i = 1; i <= segments; i ++ ) {
36654
36655        indices.push( i, i + 1, 0 );
36656
36657    }
36658
36659    this.setIndex( new THREE.BufferAttribute( new Uint16Array( indices ), 1 ) );
36660    this.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
36661    this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
36662    this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
36663
36664    this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
36665
36666};
36667
36668THREE.CircleBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
36669THREE.CircleBufferGeometry.prototype.constructor = THREE.CircleBufferGeometry;
36670
36671// File:src/extras/geometries/CylinderBufferGeometry.js
36672
36673/**
36674 * @author Mugen87 / https://github.com/Mugen87
36675 */
36676
36677THREE.CylinderBufferGeometry = function( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
36678
36679    THREE.BufferGeometry.call( this );
36680
36681    this.type = 'CylinderBufferGeometry';
36682
36683    this.parameters = {
36684        radiusTop: radiusTop,
36685        radiusBottom: radiusBottom,
36686        height: height,
36687        radialSegments: radialSegments,
36688        heightSegments: heightSegments,
36689        openEnded: openEnded,
36690        thetaStart: thetaStart,
36691        thetaLength: thetaLength
36692    };
36693
36694    var scope = this;
36695
36696    radiusTop = radiusTop !== undefined ? radiusTop : 20;
36697    radiusBottom = radiusBottom !== undefined ? radiusBottom : 20;
36698    height = height !== undefined ? height : 100;
36699
36700    radialSegments = Math.floor( radialSegments ) || 8;
36701    heightSegments = Math.floor( heightSegments ) || 1;
36702
36703    openEnded = openEnded !== undefined ? openEnded : false;
36704    thetaStart = thetaStart !== undefined ? thetaStart : 0;
36705    thetaLength = thetaLength !== undefined ? thetaLength : 2 * Math.PI;
36706
36707    // used to calculate buffer length
36708
36709    var vertexCount = calculateVertexCount();
36710    var indexCount = calculateIndexCount();
36711
36712    // buffers
36713
36714    var indices = new THREE.BufferAttribute( new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount ), 1 );
36715    var vertices = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
36716    var normals = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
36717    var uvs = new THREE.BufferAttribute( new Float32Array( vertexCount * 2 ), 2 );
36718
36719    // helper variables
36720
36721    var index = 0, indexOffset = 0, indexArray = [], halfHeight = height / 2;
36722
36723    // group variables
36724    var groupStart = 0;
36725
36726    // generate geometry
36727
36728    generateTorso();
36729
36730    if ( openEnded === false ) {
36731
36732        if ( radiusTop > 0 ) generateCap( true );
36733        if ( radiusBottom > 0 ) generateCap( false );
36734
36735    }
36736
36737    // build geometry
36738
36739    this.setIndex( indices );
36740    this.addAttribute( 'position', vertices );
36741    this.addAttribute( 'normal', normals );
36742    this.addAttribute( 'uv', uvs );
36743
36744    // helper functions
36745
36746    function calculateVertexCount() {
36747
36748        var count = ( radialSegments + 1 ) * ( heightSegments + 1 );
36749
36750        if ( openEnded === false ) {
36751
36752            count += ( ( radialSegments + 1 ) * 2 ) + ( radialSegments * 2 );
36753
36754        }
36755
36756        return count;
36757
36758    }
36759
36760    function calculateIndexCount() {
36761
36762        var count = radialSegments * heightSegments * 2 * 3;
36763
36764        if ( openEnded === false ) {
36765
36766            count += radialSegments * 2 * 3;
36767
36768        }
36769
36770        return count;
36771
36772    }
36773
36774    function generateTorso() {
36775
36776        var x, y;
36777        var normal = new THREE.Vector3();
36778        var vertex = new THREE.Vector3();
36779
36780        var groupCount = 0;
36781
36782        // this will be used to calculate the normal
36783        var tanTheta = ( radiusBottom - radiusTop ) / height;
36784
36785        // generate vertices, normals and uvs
36786
36787        for ( y = 0; y <= heightSegments; y ++ ) {
36788
36789            var indexRow = [];
36790
36791            var v = y / heightSegments;
36792
36793            // calculate the radius of the current row
36794            var radius = v * ( radiusBottom - radiusTop ) + radiusTop;
36795
36796            for ( x = 0; x <= radialSegments; x ++ ) {
36797
36798                var u = x / radialSegments;
36799
36800                // vertex
36801                vertex.x = radius * Math.sin( u * thetaLength + thetaStart );
36802                vertex.y = - v * height + halfHeight;
36803                vertex.z = radius * Math.cos( u * thetaLength + thetaStart );
36804                vertices.setXYZ( index, vertex.x, vertex.y, vertex.z );
36805
36806                // normal
36807                normal.copy( vertex );
36808
36809                // handle special case if radiusTop/radiusBottom is zero
36810                if ( ( radiusTop === 0 && y === 0 ) || ( radiusBottom === 0 && y === heightSegments ) ) {
36811
36812                    normal.x = Math.sin( u * thetaLength + thetaStart );
36813                    normal.z = Math.cos( u * thetaLength + thetaStart );
36814
36815                }
36816
36817                normal.setY( Math.sqrt( normal.x * normal.x + normal.z * normal.z ) * tanTheta ).normalize();
36818                normals.setXYZ( index, normal.x, normal.y, normal.z );
36819
36820                // uv
36821                uvs.setXY( index, u, 1 - v );
36822
36823                // save index of vertex in respective row
36824                indexRow.push( index );
36825
36826                // increase index
36827                index ++;
36828
36829            }
36830
36831            // now save vertices of the row in our index array
36832            indexArray.push( indexRow );
36833
36834        }
36835
36836        // generate indices
36837
36838        for ( x = 0; x < radialSegments; x ++ ) {
36839
36840            for ( y = 0; y < heightSegments; y ++ ) {
36841
36842                // we use the index array to access the correct indices
36843                var i1 = indexArray[ y ][ x ];
36844                var i2 = indexArray[ y + 1 ][ x ];
36845                var i3 = indexArray[ y + 1 ][ x + 1 ];
36846                var i4 = indexArray[ y ][ x + 1 ];
36847
36848                // face one
36849                indices.setX( indexOffset, i1 ); indexOffset ++;
36850                indices.setX( indexOffset, i2 ); indexOffset ++;
36851                indices.setX( indexOffset, i4 ); indexOffset ++;
36852
36853                // face two
36854                indices.setX( indexOffset, i2 ); indexOffset ++;
36855                indices.setX( indexOffset, i3 ); indexOffset ++;
36856                indices.setX( indexOffset, i4 ); indexOffset ++;
36857
36858                // update counters
36859                groupCount += 6;
36860
36861            }
36862
36863        }
36864
36865        // add a group to the geometry. this will ensure multi material support
36866        scope.addGroup( groupStart, groupCount, 0 );
36867
36868        // calculate new start value for groups
36869        groupStart += groupCount;
36870
36871    }
36872
36873    function generateCap( top ) {
36874
36875        var x, centerIndexStart, centerIndexEnd;
36876        var uv = new THREE.Vector2();
36877        var vertex = new THREE.Vector3();
36878
36879        var groupCount = 0;
36880
36881        var radius = ( top === true ) ? radiusTop : radiusBottom;
36882        var sign = ( top === true ) ? 1 : - 1;
36883
36884        // save the index of the first center vertex
36885        centerIndexStart = index;
36886
36887        // first we generate the center vertex data of the cap.
36888        // because the geometry needs one set of uvs per face,
36889        // we must generate a center vertex per face/segment
36890
36891        for ( x = 1; x <= radialSegments; x ++ ) {
36892
36893            // vertex
36894            vertices.setXYZ( index, 0, halfHeight * sign, 0 );
36895
36896            // normal
36897            normals.setXYZ( index, 0, sign, 0 );
36898
36899            // uv
36900            if ( top === true ) {
36901
36902                uv.x = x / radialSegments;
36903                uv.y = 0;
36904
36905            } else {
36906
36907                uv.x = ( x - 1 ) / radialSegments;
36908                uv.y = 1;
36909
36910            }
36911
36912            uvs.setXY( index, uv.x, uv.y );
36913
36914            // increase index
36915            index ++;
36916
36917        }
36918
36919        // save the index of the last center vertex
36920        centerIndexEnd = index;
36921
36922        // now we generate the surrounding vertices, normals and uvs
36923
36924        for ( x = 0; x <= radialSegments; x ++ ) {
36925
36926            var u = x / radialSegments;
36927
36928            // vertex
36929            vertex.x = radius * Math.sin( u * thetaLength + thetaStart );
36930            vertex.y = halfHeight * sign;
36931            vertex.z = radius * Math.cos( u * thetaLength + thetaStart );
36932            vertices.setXYZ( index, vertex.x, vertex.y, vertex.z );
36933
36934            // normal
36935            normals.setXYZ( index, 0, sign, 0 );
36936
36937            // uv
36938            uvs.setXY( index, u, ( top === true ) ? 1 : 0 );
36939
36940            // increase index
36941            index ++;
36942
36943        }
36944
36945        // generate indices
36946
36947        for ( x = 0; x < radialSegments; x ++ ) {
36948
36949            var c = centerIndexStart + x;
36950            var i = centerIndexEnd + x;
36951
36952            if ( top === true ) {
36953
36954                // face top
36955                indices.setX( indexOffset, i ); indexOffset ++;
36956                indices.setX( indexOffset, i + 1 ); indexOffset ++;
36957                indices.setX( indexOffset, c ); indexOffset ++;
36958
36959            } else {
36960
36961                // face bottom
36962                indices.setX( indexOffset, i + 1 ); indexOffset ++;
36963                indices.setX( indexOffset, i ); indexOffset ++;
36964                indices.setX( indexOffset, c ); indexOffset ++;
36965
36966            }
36967
36968            // update counters
36969            groupCount += 3;
36970
36971        }
36972
36973        // add a group to the geometry. this will ensure multi material support
36974        scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
36975
36976        // calculate new start value for groups
36977        groupStart += groupCount;
36978
36979    }
36980
36981};
36982
36983THREE.CylinderBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
36984THREE.CylinderBufferGeometry.prototype.constructor = THREE.CylinderBufferGeometry;
36985
36986// File:src/extras/geometries/CylinderGeometry.js
36987
36988/**
36989 * @author mrdoob / http://mrdoob.com/
36990 */
36991
36992THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
36993
36994    THREE.Geometry.call( this );
36995
36996    this.type = 'CylinderGeometry';
36997
36998    this.parameters = {
36999        radiusTop: radiusTop,
37000        radiusBottom: radiusBottom,
37001        height: height,
37002        radialSegments: radialSegments,
37003        heightSegments: heightSegments,
37004        openEnded: openEnded,
37005        thetaStart: thetaStart,
37006        thetaLength: thetaLength
37007    };
37008
37009    this.fromBufferGeometry( new THREE.CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );
37010    this.mergeVertices();
37011
37012};
37013
37014THREE.CylinderGeometry.prototype = Object.create( THREE.Geometry.prototype );
37015THREE.CylinderGeometry.prototype.constructor = THREE.CylinderGeometry;
37016
37017// File:src/extras/geometries/EdgesGeometry.js
37018
37019/**
37020 * @author WestLangley / http://github.com/WestLangley
37021 */
37022
37023THREE.EdgesGeometry = function ( geometry, thresholdAngle ) {
37024
37025    THREE.BufferGeometry.call( this );
37026
37027    thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
37028
37029    var thresholdDot = Math.cos( THREE.Math.DEG2RAD * thresholdAngle );
37030
37031    var edge = [ 0, 0 ], hash = {};
37032
37033    function sortFunction( a, b ) {
37034
37035        return a - b;
37036
37037    }
37038
37039    var keys = [ 'a', 'b', 'c' ];
37040
37041    var geometry2;
37042
37043    if ( geometry instanceof THREE.BufferGeometry ) {
37044
37045        geometry2 = new THREE.Geometry();
37046        geometry2.fromBufferGeometry( geometry );
37047
37048    } else {
37049
37050        geometry2 = geometry.clone();
37051
37052    }
37053
37054    geometry2.mergeVertices();
37055    geometry2.computeFaceNormals();
37056
37057    var vertices = geometry2.vertices;
37058    var faces = geometry2.faces;
37059
37060    for ( var i = 0, l = faces.length; i < l; i ++ ) {
37061
37062        var face = faces[ i ];
37063
37064        for ( var j = 0; j < 3; j ++ ) {
37065
37066            edge[ 0 ] = face[ keys[ j ] ];
37067            edge[ 1 ] = face[ keys[ ( j + 1 ) % 3 ] ];
37068            edge.sort( sortFunction );
37069
37070            var key = edge.toString();
37071
37072            if ( hash[ key ] === undefined ) {
37073
37074                hash[ key ] = { vert1: edge[ 0 ], vert2: edge[ 1 ], face1: i, face2: undefined };
37075
37076            } else {
37077
37078                hash[ key ].face2 = i;
37079
37080            }
37081
37082        }
37083
37084    }
37085
37086    var coords = [];
37087
37088    for ( var key in hash ) {
37089
37090        var h = hash[ key ];
37091
37092        if ( h.face2 === undefined || faces[ h.face1 ].normal.dot( faces[ h.face2 ].normal ) <= thresholdDot ) {
37093
37094            var vertex = vertices[ h.vert1 ];
37095            coords.push( vertex.x );
37096            coords.push( vertex.y );
37097            coords.push( vertex.z );
37098
37099            vertex = vertices[ h.vert2 ];
37100            coords.push( vertex.x );
37101            coords.push( vertex.y );
37102            coords.push( vertex.z );
37103
37104        }
37105
37106    }
37107
37108    this.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( coords ), 3 ) );
37109
37110};
37111
37112THREE.EdgesGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
37113THREE.EdgesGeometry.prototype.constructor = THREE.EdgesGeometry;
37114
37115// File:src/extras/geometries/ExtrudeGeometry.js
37116
37117/**
37118 * @author zz85 / http://www.lab4games.net/zz85/blog
37119 *
37120 * Creates extruded geometry from a path shape.
37121 *
37122 * parameters = {
37123 *
37124 *  curveSegments: <int>, // number of points on the curves
37125 *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
37126 *  amount: <int>, // Depth to extrude the shape
37127 *
37128 *  bevelEnabled: <bool>, // turn on bevel
37129 *  bevelThickness: <float>, // how deep into the original shape bevel goes
37130 *  bevelSize: <float>, // how far from shape outline is bevel
37131 *  bevelSegments: <int>, // number of bevel layers
37132 *
37133 *  extrudePath: <THREE.CurvePath> // 3d spline path to extrude shape along. (creates Frames if .frames aren't defined)
37134 *  frames: <THREE.TubeGeometry.FrenetFrames> // containing arrays of tangents, normals, binormals
37135 *
37136 *  uvGenerator: <Object> // object that provides UV generator functions
37137 *
37138 * }
37139 **/
37140
37141THREE.ExtrudeGeometry = function ( shapes, options ) {
37142
37143    if ( typeof( shapes ) === "undefined" ) {
37144
37145        shapes = [];
37146        return;
37147
37148    }
37149
37150    THREE.Geometry.call( this );
37151
37152    this.type = 'ExtrudeGeometry';
37153
37154    shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
37155
37156    this.addShapeList( shapes, options );
37157
37158    this.computeFaceNormals();
37159
37160    // can't really use automatic vertex normals
37161    // as then front and back sides get smoothed too
37162    // should do separate smoothing just for sides
37163
37164    //this.computeVertexNormals();
37165
37166    //console.log( "took", ( Date.now() - startTime ) );
37167
37168};
37169
37170THREE.ExtrudeGeometry.prototype = Object.create( THREE.Geometry.prototype );
37171THREE.ExtrudeGeometry.prototype.constructor = THREE.ExtrudeGeometry;
37172
37173THREE.ExtrudeGeometry.prototype.addShapeList = function ( shapes, options ) {
37174
37175    var sl = shapes.length;
37176
37177    for ( var s = 0; s < sl; s ++ ) {
37178
37179        var shape = shapes[ s ];
37180        this.addShape( shape, options );
37181
37182    }
37183
37184};
37185
37186THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) {
37187
37188    var amount = options.amount !== undefined ? options.amount : 100;
37189
37190    var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10
37191    var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8
37192    var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
37193
37194    var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false
37195
37196    var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
37197
37198    var steps = options.steps !== undefined ? options.steps : 1;
37199
37200    var extrudePath = options.extrudePath;
37201    var extrudePts, extrudeByPath = false;
37202
37203    // Use default WorldUVGenerator if no UV generators are specified.
37204    var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : THREE.ExtrudeGeometry.WorldUVGenerator;
37205
37206    var splineTube, binormal, normal, position2;
37207    if ( extrudePath ) {
37208
37209        extrudePts = extrudePath.getSpacedPoints( steps );
37210
37211        extrudeByPath = true;
37212        bevelEnabled = false; // bevels not supported for path extrusion
37213
37214        // SETUP TNB variables
37215
37216        // Reuse TNB from TubeGeomtry for now.
37217        // TODO1 - have a .isClosed in spline?
37218
37219        splineTube = options.frames !== undefined ? options.frames : new THREE.TubeGeometry.FrenetFrames( extrudePath, steps, false );
37220
37221        // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
37222
37223        binormal = new THREE.Vector3();
37224        normal = new THREE.Vector3();
37225        position2 = new THREE.Vector3();
37226
37227    }
37228
37229    // Safeguards if bevels are not enabled
37230
37231    if ( ! bevelEnabled ) {
37232
37233        bevelSegments = 0;
37234        bevelThickness = 0;
37235        bevelSize = 0;
37236
37237    }
37238
37239    // Variables initialization
37240
37241    var ahole, h, hl; // looping of holes
37242    var scope = this;
37243
37244    var shapesOffset = this.vertices.length;
37245
37246    var shapePoints = shape.extractPoints( curveSegments );
37247
37248    var vertices = shapePoints.shape;
37249    var holes = shapePoints.holes;
37250
37251    var reverse = ! THREE.ShapeUtils.isClockWise( vertices );
37252
37253    if ( reverse ) {
37254
37255        vertices = vertices.reverse();
37256
37257        // Maybe we should also check if holes are in the opposite direction, just to be safe ...
37258
37259        for ( h = 0, hl = holes.length; h < hl; h ++ ) {
37260
37261            ahole = holes[ h ];
37262
37263            if ( THREE.ShapeUtils.isClockWise( ahole ) ) {
37264
37265                holes[ h ] = ahole.reverse();
37266
37267            }
37268
37269        }
37270
37271        reverse = false; // If vertices are in order now, we shouldn't need to worry about them again (hopefully)!
37272
37273    }
37274
37275
37276    var faces = THREE.ShapeUtils.triangulateShape( vertices, holes );
37277
37278    /* Vertices */
37279
37280    var contour = vertices; // vertices has all points but contour has only points of circumference
37281
37282    for ( h = 0, hl = holes.length; h < hl; h ++ ) {
37283
37284        ahole = holes[ h ];
37285
37286        vertices = vertices.concat( ahole );
37287
37288    }
37289
37290
37291    function scalePt2 ( pt, vec, size ) {
37292
37293        if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
37294
37295        return vec.clone().multiplyScalar( size ).add( pt );
37296
37297    }
37298
37299    var b, bs, t, z,
37300        vert, vlen = vertices.length,
37301        face, flen = faces.length;
37302
37303
37304    // Find directions for point movement
37305
37306
37307    function getBevelVec( inPt, inPrev, inNext ) {
37308
37309        // computes for inPt the corresponding point inPt' on a new contour
37310        //   shifted by 1 unit (length of normalized vector) to the left
37311        // if we walk along contour clockwise, this new contour is outside the old one
37312        //
37313        // inPt' is the intersection of the two lines parallel to the two
37314        //  adjacent edges of inPt at a distance of 1 unit on the left side.
37315
37316        var v_trans_x, v_trans_y, shrink_by = 1;		// resulting translation vector for inPt
37317
37318        // good reading for geometry algorithms (here: line-line intersection)
37319        // http://geomalgorithms.com/a05-_intersect-1.html
37320
37321        var v_prev_x = inPt.x - inPrev.x, v_prev_y = inPt.y - inPrev.y;
37322        var v_next_x = inNext.x - inPt.x, v_next_y = inNext.y - inPt.y;
37323
37324        var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
37325
37326        // check for collinear edges
37327        var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
37328
37329        if ( Math.abs( collinear0 ) > Number.EPSILON ) {
37330
37331            // not collinear
37332
37333            // length of vectors for normalizing
37334
37335            var v_prev_len = Math.sqrt( v_prev_lensq );
37336            var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
37337
37338            // shift adjacent points by unit vectors to the left
37339
37340            var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
37341            var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
37342
37343            var ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
37344            var ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
37345
37346            // scaling factor for v_prev to intersection point
37347
37348            var sf = (  ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
37349                ( ptNextShift_y - ptPrevShift_y ) * v_next_x    ) /
37350                ( v_prev_x * v_next_y - v_prev_y * v_next_x );
37351
37352            // vector from inPt to intersection point
37353
37354            v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
37355            v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
37356
37357            // Don't normalize!, otherwise sharp corners become ugly
37358            //  but prevent crazy spikes
37359            var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
37360            if ( v_trans_lensq <= 2 ) {
37361
37362                return	new THREE.Vector2( v_trans_x, v_trans_y );
37363
37364            } else {
37365
37366                shrink_by = Math.sqrt( v_trans_lensq / 2 );
37367
37368            }
37369
37370        } else {
37371
37372            // handle special case of collinear edges
37373
37374            var direction_eq = false;		// assumes: opposite
37375            if ( v_prev_x > Number.EPSILON ) {
37376
37377                if ( v_next_x > Number.EPSILON ) {
37378
37379                    direction_eq = true;
37380
37381                }
37382
37383            } else {
37384
37385                if ( v_prev_x < - Number.EPSILON ) {
37386
37387                    if ( v_next_x < - Number.EPSILON ) {
37388
37389                        direction_eq = true;
37390
37391                    }
37392
37393                } else {
37394
37395                    if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
37396
37397                        direction_eq = true;
37398
37399                    }
37400
37401                }
37402
37403            }
37404
37405            if ( direction_eq ) {
37406
37407                // console.log("Warning: lines are a straight sequence");
37408                v_trans_x = - v_prev_y;
37409                v_trans_y =  v_prev_x;
37410                shrink_by = Math.sqrt( v_prev_lensq );
37411
37412            } else {
37413
37414                // console.log("Warning: lines are a straight spike");
37415                v_trans_x = v_prev_x;
37416                v_trans_y = v_prev_y;
37417                shrink_by = Math.sqrt( v_prev_lensq / 2 );
37418
37419            }
37420
37421        }
37422
37423        return	new THREE.Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
37424
37425    }
37426
37427
37428    var contourMovements = [];
37429
37430    for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
37431
37432        if ( j === il ) j = 0;
37433        if ( k === il ) k = 0;
37434
37435        //  (j)---(i)---(k)
37436        // console.log('i,j,k', i, j , k)
37437
37438        contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
37439
37440    }
37441
37442    var holesMovements = [], oneHoleMovements, verticesMovements = contourMovements.concat();
37443
37444    for ( h = 0, hl = holes.length; h < hl; h ++ ) {
37445
37446        ahole = holes[ h ];
37447
37448        oneHoleMovements = [];
37449
37450        for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
37451
37452            if ( j === il ) j = 0;
37453            if ( k === il ) k = 0;
37454
37455            //  (j)---(i)---(k)
37456            oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
37457
37458        }
37459
37460        holesMovements.push( oneHoleMovements );
37461        verticesMovements = verticesMovements.concat( oneHoleMovements );
37462
37463    }
37464
37465
37466    // Loop bevelSegments, 1 for the front, 1 for the back
37467
37468    for ( b = 0; b < bevelSegments; b ++ ) {
37469
37470        //for ( b = bevelSegments; b > 0; b -- ) {
37471
37472        t = b / bevelSegments;
37473        z = bevelThickness * ( 1 - t );
37474
37475        //z = bevelThickness * t;
37476        bs = bevelSize * ( Math.sin ( t * Math.PI / 2 ) ); // curved
37477        //bs = bevelSize * t; // linear
37478
37479        // contract shape
37480
37481        for ( i = 0, il = contour.length; i < il; i ++ ) {
37482
37483            vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
37484
37485            v( vert.x, vert.y,  - z );
37486
37487        }
37488
37489        // expand holes
37490
37491        for ( h = 0, hl = holes.length; h < hl; h ++ ) {
37492
37493            ahole = holes[ h ];
37494            oneHoleMovements = holesMovements[ h ];
37495
37496            for ( i = 0, il = ahole.length; i < il; i ++ ) {
37497
37498                vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
37499
37500                v( vert.x, vert.y,  - z );
37501
37502            }
37503
37504        }
37505
37506    }
37507
37508    bs = bevelSize;
37509
37510    // Back facing vertices
37511
37512    for ( i = 0; i < vlen; i ++ ) {
37513
37514        vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
37515
37516        if ( ! extrudeByPath ) {
37517
37518            v( vert.x, vert.y, 0 );
37519
37520        } else {
37521
37522            // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
37523
37524            normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
37525            binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
37526
37527            position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
37528
37529            v( position2.x, position2.y, position2.z );
37530
37531        }
37532
37533    }
37534
37535    // Add stepped vertices...
37536    // Including front facing vertices
37537
37538    var s;
37539
37540    for ( s = 1; s <= steps; s ++ ) {
37541
37542        for ( i = 0; i < vlen; i ++ ) {
37543
37544            vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
37545
37546            if ( ! extrudeByPath ) {
37547
37548                v( vert.x, vert.y, amount / steps * s );
37549
37550            } else {
37551
37552                // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
37553
37554                normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
37555                binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
37556
37557                position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
37558
37559                v( position2.x, position2.y, position2.z );
37560
37561            }
37562
37563        }
37564
37565    }
37566
37567
37568    // Add bevel segments planes
37569
37570    //for ( b = 1; b <= bevelSegments; b ++ ) {
37571    for ( b = bevelSegments - 1; b >= 0; b -- ) {
37572
37573        t = b / bevelSegments;
37574        z = bevelThickness * ( 1 - t );
37575        //bs = bevelSize * ( 1-Math.sin ( ( 1 - t ) * Math.PI/2 ) );
37576        bs = bevelSize * Math.sin ( t * Math.PI / 2 );
37577
37578        // contract shape
37579
37580        for ( i = 0, il = contour.length; i < il; i ++ ) {
37581
37582            vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
37583            v( vert.x, vert.y,  amount + z );
37584
37585        }
37586
37587        // expand holes
37588
37589        for ( h = 0, hl = holes.length; h < hl; h ++ ) {
37590
37591            ahole = holes[ h ];
37592            oneHoleMovements = holesMovements[ h ];
37593
37594            for ( i = 0, il = ahole.length; i < il; i ++ ) {
37595
37596                vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
37597
37598                if ( ! extrudeByPath ) {
37599
37600                    v( vert.x, vert.y,  amount + z );
37601
37602                } else {
37603
37604                    v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
37605
37606                }
37607
37608            }
37609
37610        }
37611
37612    }
37613
37614    /* Faces */
37615
37616    // Top and bottom faces
37617
37618    buildLidFaces();
37619
37620    // Sides faces
37621
37622    buildSideFaces();
37623
37624
37625    /////  Internal functions
37626
37627    function buildLidFaces() {
37628
37629        if ( bevelEnabled ) {
37630
37631            var layer = 0; // steps + 1
37632            var offset = vlen * layer;
37633
37634            // Bottom faces
37635
37636            for ( i = 0; i < flen; i ++ ) {
37637
37638                face = faces[ i ];
37639                f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
37640
37641            }
37642
37643            layer = steps + bevelSegments * 2;
37644            offset = vlen * layer;
37645
37646            // Top faces
37647
37648            for ( i = 0; i < flen; i ++ ) {
37649
37650                face = faces[ i ];
37651                f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
37652
37653            }
37654
37655        } else {
37656
37657            // Bottom faces
37658
37659            for ( i = 0; i < flen; i ++ ) {
37660
37661                face = faces[ i ];
37662                f3( face[ 2 ], face[ 1 ], face[ 0 ] );
37663
37664            }
37665
37666            // Top faces
37667
37668            for ( i = 0; i < flen; i ++ ) {
37669
37670                face = faces[ i ];
37671                f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
37672
37673            }
37674
37675        }
37676
37677    }
37678
37679    // Create faces for the z-sides of the shape
37680
37681    function buildSideFaces() {
37682
37683        var layeroffset = 0;
37684        sidewalls( contour, layeroffset );
37685        layeroffset += contour.length;
37686
37687        for ( h = 0, hl = holes.length; h < hl; h ++ ) {
37688
37689            ahole = holes[ h ];
37690            sidewalls( ahole, layeroffset );
37691
37692            //, true
37693            layeroffset += ahole.length;
37694
37695        }
37696
37697    }
37698
37699    function sidewalls( contour, layeroffset ) {
37700
37701        var j, k;
37702        i = contour.length;
37703
37704        while ( -- i >= 0 ) {
37705
37706            j = i;
37707            k = i - 1;
37708            if ( k < 0 ) k = contour.length - 1;
37709
37710            //console.log('b', i,j, i-1, k,vertices.length);
37711
37712            var s = 0, sl = steps  + bevelSegments * 2;
37713
37714            for ( s = 0; s < sl; s ++ ) {
37715
37716                var slen1 = vlen * s;
37717                var slen2 = vlen * ( s + 1 );
37718
37719                var a = layeroffset + j + slen1,
37720                    b = layeroffset + k + slen1,
37721                    c = layeroffset + k + slen2,
37722                    d = layeroffset + j + slen2;
37723
37724                f4( a, b, c, d, contour, s, sl, j, k );
37725
37726            }
37727
37728        }
37729
37730    }
37731
37732
37733    function v( x, y, z ) {
37734
37735        scope.vertices.push( new THREE.Vector3( x, y, z ) );
37736
37737    }
37738
37739    function f3( a, b, c ) {
37740
37741        a += shapesOffset;
37742        b += shapesOffset;
37743        c += shapesOffset;
37744
37745        scope.faces.push( new THREE.Face3( a, b, c, null, null, 0 ) );
37746
37747        var uvs = uvgen.generateTopUV( scope, a, b, c );
37748
37749        scope.faceVertexUvs[ 0 ].push( uvs );
37750
37751    }
37752
37753    function f4( a, b, c, d, wallContour, stepIndex, stepsLength, contourIndex1, contourIndex2 ) {
37754
37755        a += shapesOffset;
37756        b += shapesOffset;
37757        c += shapesOffset;
37758        d += shapesOffset;
37759
37760        scope.faces.push( new THREE.Face3( a, b, d, null, null, 1 ) );
37761        scope.faces.push( new THREE.Face3( b, c, d, null, null, 1 ) );
37762
37763        var uvs = uvgen.generateSideWallUV( scope, a, b, c, d );
37764
37765        scope.faceVertexUvs[ 0 ].push( [ uvs[ 0 ], uvs[ 1 ], uvs[ 3 ] ] );
37766        scope.faceVertexUvs[ 0 ].push( [ uvs[ 1 ], uvs[ 2 ], uvs[ 3 ] ] );
37767
37768    }
37769
37770};
37771
37772THREE.ExtrudeGeometry.WorldUVGenerator = {
37773
37774    generateTopUV: function ( geometry, indexA, indexB, indexC ) {
37775
37776        var vertices = geometry.vertices;
37777
37778        var a = vertices[ indexA ];
37779        var b = vertices[ indexB ];
37780        var c = vertices[ indexC ];
37781
37782        return [
37783            new THREE.Vector2( a.x, a.y ),
37784            new THREE.Vector2( b.x, b.y ),
37785            new THREE.Vector2( c.x, c.y )
37786        ];
37787
37788    },
37789
37790    generateSideWallUV: function ( geometry, indexA, indexB, indexC, indexD ) {
37791
37792        var vertices = geometry.vertices;
37793
37794        var a = vertices[ indexA ];
37795        var b = vertices[ indexB ];
37796        var c = vertices[ indexC ];
37797        var d = vertices[ indexD ];
37798
37799        if ( Math.abs( a.y - b.y ) < 0.01 ) {
37800
37801            return [
37802                new THREE.Vector2( a.x, 1 - a.z ),
37803                new THREE.Vector2( b.x, 1 - b.z ),
37804                new THREE.Vector2( c.x, 1 - c.z ),
37805                new THREE.Vector2( d.x, 1 - d.z )
37806            ];
37807
37808        } else {
37809
37810            return [
37811                new THREE.Vector2( a.y, 1 - a.z ),
37812                new THREE.Vector2( b.y, 1 - b.z ),
37813                new THREE.Vector2( c.y, 1 - c.z ),
37814                new THREE.Vector2( d.y, 1 - d.z )
37815            ];
37816
37817        }
37818
37819    }
37820};
37821
37822// File:src/extras/geometries/ShapeGeometry.js
37823
37824/**
37825 * @author jonobr1 / http://jonobr1.com
37826 *
37827 * Creates a one-sided polygonal geometry from a path shape. Similar to
37828 * ExtrudeGeometry.
37829 *
37830 * parameters = {
37831 *
37832 *	curveSegments: <int>, // number of points on the curves. NOT USED AT THE MOMENT.
37833 *
37834 *	material: <int> // material index for front and back faces
37835 *	uvGenerator: <Object> // object that provides UV generator functions
37836 *
37837 * }
37838 **/
37839
37840THREE.ShapeGeometry = function ( shapes, options ) {
37841
37842    THREE.Geometry.call( this );
37843
37844    this.type = 'ShapeGeometry';
37845
37846    if ( Array.isArray( shapes ) === false ) shapes = [ shapes ];
37847
37848    this.addShapeList( shapes, options );
37849
37850    this.computeFaceNormals();
37851
37852};
37853
37854THREE.ShapeGeometry.prototype = Object.create( THREE.Geometry.prototype );
37855THREE.ShapeGeometry.prototype.constructor = THREE.ShapeGeometry;
37856
37857/**
37858 * Add an array of shapes to THREE.ShapeGeometry.
37859 */
37860THREE.ShapeGeometry.prototype.addShapeList = function ( shapes, options ) {
37861
37862    for ( var i = 0, l = shapes.length; i < l; i ++ ) {
37863
37864        this.addShape( shapes[ i ], options );
37865
37866    }
37867
37868    return this;
37869
37870};
37871
37872/**
37873 * Adds a shape to THREE.ShapeGeometry, based on THREE.ExtrudeGeometry.
37874 */
37875THREE.ShapeGeometry.prototype.addShape = function ( shape, options ) {
37876
37877    if ( options === undefined ) options = {};
37878    var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
37879
37880    var material = options.material;
37881    var uvgen = options.UVGenerator === undefined ? THREE.ExtrudeGeometry.WorldUVGenerator : options.UVGenerator;
37882
37883    //
37884
37885    var i, l, hole;
37886
37887    var shapesOffset = this.vertices.length;
37888    var shapePoints = shape.extractPoints( curveSegments );
37889
37890    var vertices = shapePoints.shape;
37891    var holes = shapePoints.holes;
37892
37893    var reverse = ! THREE.ShapeUtils.isClockWise( vertices );
37894
37895    if ( reverse ) {
37896
37897        vertices = vertices.reverse();
37898
37899        // Maybe we should also check if holes are in the opposite direction, just to be safe...
37900
37901        for ( i = 0, l = holes.length; i < l; i ++ ) {
37902
37903            hole = holes[ i ];
37904
37905            if ( THREE.ShapeUtils.isClockWise( hole ) ) {
37906
37907                holes[ i ] = hole.reverse();
37908
37909            }
37910
37911        }
37912
37913        reverse = false;
37914
37915    }
37916
37917    var faces = THREE.ShapeUtils.triangulateShape( vertices, holes );
37918
37919    // Vertices
37920
37921    for ( i = 0, l = holes.length; i < l; i ++ ) {
37922
37923        hole = holes[ i ];
37924        vertices = vertices.concat( hole );
37925
37926    }
37927
37928    //
37929
37930    var vert, vlen = vertices.length;
37931    var face, flen = faces.length;
37932
37933    for ( i = 0; i < vlen; i ++ ) {
37934
37935        vert = vertices[ i ];
37936
37937        this.vertices.push( new THREE.Vector3( vert.x, vert.y, 0 ) );
37938
37939    }
37940
37941    for ( i = 0; i < flen; i ++ ) {
37942
37943        face = faces[ i ];
37944
37945        var a = face[ 0 ] + shapesOffset;
37946        var b = face[ 1 ] + shapesOffset;
37947        var c = face[ 2 ] + shapesOffset;
37948
37949        this.faces.push( new THREE.Face3( a, b, c, null, null, material ) );
37950        this.faceVertexUvs[ 0 ].push( uvgen.generateTopUV( this, a, b, c ) );
37951
37952    }
37953
37954};
37955
37956// File:src/extras/geometries/LatheBufferGeometry.js
37957
37958/**
37959 * @author Mugen87 / https://github.com/Mugen87
37960 */
37961
37962    // points - to create a closed torus, one must use a set of points
37963    //    like so: [ a, b, c, d, a ], see first is the same as last.
37964    // segments - the number of circumference segments to create
37965    // phiStart - the starting radian
37966    // phiLength - the radian (0 to 2PI) range of the lathed section
37967    //    2PI is a closed lathe, less than 2PI is a portion.
37968
37969THREE.LatheBufferGeometry = function ( points, segments, phiStart, phiLength ) {
37970
37971    THREE.BufferGeometry.call( this );
37972
37973    this.type = 'LatheBufferGeometry';
37974
37975    this.parameters = {
37976        points: points,
37977        segments: segments,
37978        phiStart: phiStart,
37979        phiLength: phiLength
37980    };
37981
37982    segments = Math.floor( segments ) || 12;
37983    phiStart = phiStart || 0;
37984    phiLength = phiLength || Math.PI * 2;
37985
37986    // clamp phiLength so it's in range of [ 0, 2PI ]
37987    phiLength = THREE.Math.clamp( phiLength, 0, Math.PI * 2 );
37988
37989    // these are used to calculate buffer length
37990    var vertexCount = ( segments + 1 ) * points.length;
37991    var indexCount = segments * points.length * 2 * 3;
37992
37993    // buffers
37994    var indices = new THREE.BufferAttribute( new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount ) , 1 );
37995    var vertices = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
37996    var uvs = new THREE.BufferAttribute( new Float32Array( vertexCount * 2 ), 2 );
37997
37998    // helper variables
37999    var index = 0, indexOffset = 0, base;
38000    var inversePointLength = 1.0 / ( points.length - 1 );
38001    var inverseSegments = 1.0 / segments;
38002    var vertex = new THREE.Vector3();
38003    var uv = new THREE.Vector2();
38004    var i, j;
38005
38006    // generate vertices and uvs
38007
38008    for ( i = 0; i <= segments; i ++ ) {
38009
38010        var phi = phiStart + i * inverseSegments * phiLength;
38011
38012        var sin = Math.sin( phi );
38013        var cos = Math.cos( phi );
38014
38015        for ( j = 0; j <= ( points.length - 1 ); j ++ ) {
38016
38017            // vertex
38018            vertex.x = points[ j ].x * sin;
38019            vertex.y = points[ j ].y;
38020            vertex.z = points[ j ].x * cos;
38021            vertices.setXYZ( index, vertex.x, vertex.y, vertex.z );
38022
38023            // uv
38024            uv.x = i / segments;
38025            uv.y = j / ( points.length - 1 );
38026            uvs.setXY( index, uv.x, uv.y );
38027
38028            // increase index
38029            index ++;
38030
38031        }
38032
38033    }
38034
38035    // generate indices
38036
38037    for ( i = 0; i < segments; i ++ ) {
38038
38039        for ( j = 0; j < ( points.length - 1 ); j ++ ) {
38040
38041            base = j + i * points.length;
38042
38043            // indices
38044            var a = base;
38045            var b = base + points.length;
38046            var c = base + points.length + 1;
38047            var d = base + 1;
38048
38049            // face one
38050            indices.setX( indexOffset, a ); indexOffset++;
38051            indices.setX( indexOffset, b ); indexOffset++;
38052            indices.setX( indexOffset, d ); indexOffset++;
38053
38054            // face two
38055            indices.setX( indexOffset, b ); indexOffset++;
38056            indices.setX( indexOffset, c ); indexOffset++;
38057            indices.setX( indexOffset, d ); indexOffset++;
38058
38059        }
38060
38061    }
38062
38063    // build geometry
38064
38065    this.setIndex( indices );
38066    this.addAttribute( 'position', vertices );
38067    this.addAttribute( 'uv', uvs );
38068
38069    // generate normals
38070
38071    this.computeVertexNormals();
38072
38073    // if the geometry is closed, we need to average the normals along the seam.
38074    // because the corresponding vertices are identical (but still have different UVs).
38075
38076    if( phiLength === Math.PI * 2 ) {
38077
38078        var normals = this.attributes.normal.array;
38079        var n1 = new THREE.Vector3();
38080        var n2 = new THREE.Vector3();
38081        var n = new THREE.Vector3();
38082
38083        // this is the buffer offset for the last line of vertices
38084        base = segments * points.length * 3;
38085
38086        for( i = 0, j = 0; i < points.length; i ++, j += 3 ) {
38087
38088            // select the normal of the vertex in the first line
38089            n1.x = normals[ j + 0 ];
38090            n1.y = normals[ j + 1 ];
38091            n1.z = normals[ j + 2 ];
38092
38093            // select the normal of the vertex in the last line
38094            n2.x = normals[ base + j + 0 ];
38095            n2.y = normals[ base + j + 1 ];
38096            n2.z = normals[ base + j + 2 ];
38097
38098            // average normals
38099            n.addVectors( n1, n2 ).normalize();
38100
38101            // assign the new values to both normals
38102            normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
38103            normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
38104            normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
38105
38106        } // next row
38107
38108    }
38109
38110};
38111
38112THREE.LatheBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
38113THREE.LatheBufferGeometry.prototype.constructor = THREE.LatheBufferGeometry;
38114
38115// File:src/extras/geometries/LatheGeometry.js
38116
38117/**
38118 * @author astrodud / http://astrodud.isgreat.org/
38119 * @author zz85 / https://github.com/zz85
38120 * @author bhouston / http://clara.io
38121 */
38122
38123// points - to create a closed torus, one must use a set of points
38124//    like so: [ a, b, c, d, a ], see first is the same as last.
38125// segments - the number of circumference segments to create
38126// phiStart - the starting radian
38127// phiLength - the radian (0 to 2PI) range of the lathed section
38128//    2PI is a closed lathe, less than 2PI is a portion.
38129
38130THREE.LatheGeometry = function ( points, segments, phiStart, phiLength ) {
38131
38132    THREE.Geometry.call( this );
38133
38134    this.type = 'LatheGeometry';
38135
38136    this.parameters = {
38137        points: points,
38138        segments: segments,
38139        phiStart: phiStart,
38140        phiLength: phiLength
38141    };
38142
38143    this.fromBufferGeometry( new THREE.LatheBufferGeometry( points, segments, phiStart, phiLength ) );
38144    this.mergeVertices();
38145
38146};
38147
38148THREE.LatheGeometry.prototype = Object.create( THREE.Geometry.prototype );
38149THREE.LatheGeometry.prototype.constructor = THREE.LatheGeometry;
38150
38151// File:src/extras/geometries/PlaneGeometry.js
38152
38153/**
38154 * @author mrdoob / http://mrdoob.com/
38155 * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Plane.as
38156 */
38157
38158THREE.PlaneGeometry = function ( width, height, widthSegments, heightSegments ) {
38159
38160    THREE.Geometry.call( this );
38161
38162    this.type = 'PlaneGeometry';
38163
38164    this.parameters = {
38165        width: width,
38166        height: height,
38167        widthSegments: widthSegments,
38168        heightSegments: heightSegments
38169    };
38170
38171    this.fromBufferGeometry( new THREE.PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
38172
38173};
38174
38175THREE.PlaneGeometry.prototype = Object.create( THREE.Geometry.prototype );
38176THREE.PlaneGeometry.prototype.constructor = THREE.PlaneGeometry;
38177
38178// File:src/extras/geometries/PlaneBufferGeometry.js
38179
38180/**
38181 * @author mrdoob / http://mrdoob.com/
38182 * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Plane.as
38183 */
38184
38185THREE.PlaneBufferGeometry = function ( width, height, widthSegments, heightSegments ) {
38186
38187    THREE.BufferGeometry.call( this );
38188
38189    this.type = 'PlaneBufferGeometry';
38190
38191    this.parameters = {
38192        width: width,
38193        height: height,
38194        widthSegments: widthSegments,
38195        heightSegments: heightSegments
38196    };
38197
38198    var width_half = width / 2;
38199    var height_half = height / 2;
38200
38201    var gridX = Math.floor( widthSegments ) || 1;
38202    var gridY = Math.floor( heightSegments ) || 1;
38203
38204    var gridX1 = gridX + 1;
38205    var gridY1 = gridY + 1;
38206
38207    var segment_width = width / gridX;
38208    var segment_height = height / gridY;
38209
38210    var vertices = new Float32Array( gridX1 * gridY1 * 3 );
38211    var normals = new Float32Array( gridX1 * gridY1 * 3 );
38212    var uvs = new Float32Array( gridX1 * gridY1 * 2 );
38213
38214    var offset = 0;
38215    var offset2 = 0;
38216
38217    for ( var iy = 0; iy < gridY1; iy ++ ) {
38218
38219        var y = iy * segment_height - height_half;
38220
38221        for ( var ix = 0; ix < gridX1; ix ++ ) {
38222
38223            var x = ix * segment_width - width_half;
38224
38225            vertices[ offset ] = x;
38226            vertices[ offset + 1 ] = - y;
38227
38228            normals[ offset + 2 ] = 1;
38229
38230            uvs[ offset2 ] = ix / gridX;
38231            uvs[ offset2 + 1 ] = 1 - ( iy / gridY );
38232
38233            offset += 3;
38234            offset2 += 2;
38235
38236        }
38237
38238    }
38239
38240    offset = 0;
38241
38242    var indices = new ( ( vertices.length / 3 ) > 65535 ? Uint32Array : Uint16Array )( gridX * gridY * 6 );
38243
38244    for ( var iy = 0; iy < gridY; iy ++ ) {
38245
38246        for ( var ix = 0; ix < gridX; ix ++ ) {
38247
38248            var a = ix + gridX1 * iy;
38249            var b = ix + gridX1 * ( iy + 1 );
38250            var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
38251            var d = ( ix + 1 ) + gridX1 * iy;
38252
38253            indices[ offset ] = a;
38254            indices[ offset + 1 ] = b;
38255            indices[ offset + 2 ] = d;
38256
38257            indices[ offset + 3 ] = b;
38258            indices[ offset + 4 ] = c;
38259            indices[ offset + 5 ] = d;
38260
38261            offset += 6;
38262
38263        }
38264
38265    }
38266
38267    this.setIndex( new THREE.BufferAttribute( indices, 1 ) );
38268    this.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
38269    this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
38270    this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
38271
38272};
38273
38274THREE.PlaneBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
38275THREE.PlaneBufferGeometry.prototype.constructor = THREE.PlaneBufferGeometry;
38276
38277// File:src/extras/geometries/RingBufferGeometry.js
38278
38279/**
38280 * @author Mugen87 / https://github.com/Mugen87
38281 */
38282
38283THREE.RingBufferGeometry = function ( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
38284
38285    THREE.BufferGeometry.call( this );
38286
38287    this.type = 'RingBufferGeometry';
38288
38289    this.parameters = {
38290        innerRadius: innerRadius,
38291        outerRadius: outerRadius,
38292        thetaSegments: thetaSegments,
38293        phiSegments: phiSegments,
38294        thetaStart: thetaStart,
38295        thetaLength: thetaLength
38296    };
38297
38298    innerRadius = innerRadius || 20;
38299    outerRadius = outerRadius || 50;
38300
38301    thetaStart = thetaStart !== undefined ? thetaStart : 0;
38302    thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
38303
38304    thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;
38305    phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1;
38306
38307    // these are used to calculate buffer length
38308    var vertexCount = ( thetaSegments + 1 ) * ( phiSegments + 1 );
38309    var indexCount = thetaSegments * phiSegments * 2 * 3;
38310
38311    // buffers
38312    var indices = new THREE.BufferAttribute( new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount ) , 1 );
38313    var vertices = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
38314    var normals = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
38315    var uvs = new THREE.BufferAttribute( new Float32Array( vertexCount * 2 ), 2 );
38316
38317    // some helper variables
38318    var index = 0, indexOffset = 0, segment;
38319    var radius = innerRadius;
38320    var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
38321    var vertex = new THREE.Vector3();
38322    var uv = new THREE.Vector2();
38323    var j, i;
38324
38325    // generate vertices, normals and uvs
38326
38327    // values are generate from the inside of the ring to the outside
38328
38329    for ( j = 0; j <= phiSegments; j ++ ) {
38330
38331        for ( i = 0; i <= thetaSegments; i ++ ) {
38332
38333            segment = thetaStart + i / thetaSegments * thetaLength;
38334
38335            // vertex
38336            vertex.x = radius * Math.cos( segment );
38337            vertex.y = radius * Math.sin( segment );
38338            vertices.setXYZ( index, vertex.x, vertex.y, vertex.z );
38339
38340            // normal
38341            normals.setXYZ( index, 0, 0, 1 );
38342
38343            // uv
38344            uv.x = ( vertex.x / outerRadius + 1 ) / 2;
38345            uv.y = ( vertex.y / outerRadius + 1 ) / 2;
38346            uvs.setXY( index, uv.x, uv.y );
38347
38348            // increase index
38349            index++;
38350
38351        }
38352
38353        // increase the radius for next row of vertices
38354        radius += radiusStep;
38355
38356    }
38357
38358    // generate indices
38359
38360    for ( j = 0; j < phiSegments; j ++ ) {
38361
38362        var thetaSegmentLevel = j * ( thetaSegments + 1 );
38363
38364        for ( i = 0; i < thetaSegments; i ++ ) {
38365
38366            segment = i + thetaSegmentLevel;
38367
38368            // indices
38369            var a = segment;
38370            var b = segment + thetaSegments + 1;
38371            var c = segment + thetaSegments + 2;
38372            var d = segment + 1;
38373
38374            // face one
38375            indices.setX( indexOffset, a ); indexOffset++;
38376            indices.setX( indexOffset, b ); indexOffset++;
38377            indices.setX( indexOffset, c ); indexOffset++;
38378
38379            // face two
38380            indices.setX( indexOffset, a ); indexOffset++;
38381            indices.setX( indexOffset, c ); indexOffset++;
38382            indices.setX( indexOffset, d ); indexOffset++;
38383
38384        }
38385
38386    }
38387
38388    // build geometry
38389
38390    this.setIndex( indices );
38391    this.addAttribute( 'position', vertices );
38392    this.addAttribute( 'normal', normals );
38393    this.addAttribute( 'uv', uvs );
38394
38395};
38396
38397THREE.RingBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
38398THREE.RingBufferGeometry.prototype.constructor = THREE.RingBufferGeometry;
38399
38400// File:src/extras/geometries/RingGeometry.js
38401
38402/**
38403 * @author Kaleb Murphy
38404 */
38405
38406THREE.RingGeometry = function ( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
38407
38408    THREE.Geometry.call( this );
38409
38410    this.type = 'RingGeometry';
38411
38412    this.parameters = {
38413        innerRadius: innerRadius,
38414        outerRadius: outerRadius,
38415        thetaSegments: thetaSegments,
38416        phiSegments: phiSegments,
38417        thetaStart: thetaStart,
38418        thetaLength: thetaLength
38419    };
38420
38421    this.fromBufferGeometry( new THREE.RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );
38422
38423};
38424
38425THREE.RingGeometry.prototype = Object.create( THREE.Geometry.prototype );
38426THREE.RingGeometry.prototype.constructor = THREE.RingGeometry;
38427
38428// File:src/extras/geometries/SphereGeometry.js
38429
38430/**
38431 * @author mrdoob / http://mrdoob.com/
38432 */
38433
38434THREE.SphereGeometry = function ( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
38435
38436    THREE.Geometry.call( this );
38437
38438    this.type = 'SphereGeometry';
38439
38440    this.parameters = {
38441        radius: radius,
38442        widthSegments: widthSegments,
38443        heightSegments: heightSegments,
38444        phiStart: phiStart,
38445        phiLength: phiLength,
38446        thetaStart: thetaStart,
38447        thetaLength: thetaLength
38448    };
38449
38450    this.fromBufferGeometry( new THREE.SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );
38451
38452};
38453
38454THREE.SphereGeometry.prototype = Object.create( THREE.Geometry.prototype );
38455THREE.SphereGeometry.prototype.constructor = THREE.SphereGeometry;
38456
38457// File:src/extras/geometries/SphereBufferGeometry.js
38458
38459/**
38460 * @author benaadams / https://twitter.com/ben_a_adams
38461 * based on THREE.SphereGeometry
38462 */
38463
38464THREE.SphereBufferGeometry = function ( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
38465
38466    THREE.BufferGeometry.call( this );
38467
38468    this.type = 'SphereBufferGeometry';
38469
38470    this.parameters = {
38471        radius: radius,
38472        widthSegments: widthSegments,
38473        heightSegments: heightSegments,
38474        phiStart: phiStart,
38475        phiLength: phiLength,
38476        thetaStart: thetaStart,
38477        thetaLength: thetaLength
38478    };
38479
38480    radius = radius || 50;
38481
38482    widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 );
38483    heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 );
38484
38485    phiStart = phiStart !== undefined ? phiStart : 0;
38486    phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
38487
38488    thetaStart = thetaStart !== undefined ? thetaStart : 0;
38489    thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
38490
38491    var thetaEnd = thetaStart + thetaLength;
38492
38493    var vertexCount = ( ( widthSegments + 1 ) * ( heightSegments + 1 ) );
38494
38495    var positions = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
38496    var normals = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
38497    var uvs = new THREE.BufferAttribute( new Float32Array( vertexCount * 2 ), 2 );
38498
38499    var index = 0, vertices = [], normal = new THREE.Vector3();
38500
38501    for ( var y = 0; y <= heightSegments; y ++ ) {
38502
38503        var verticesRow = [];
38504
38505        var v = y / heightSegments;
38506
38507        for ( var x = 0;
38507 x <= widthSegments; x ++ ) {
38508
38509            var u = x / widthSegments;
38510
38511            var px = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
38512            var py = radius * Math.cos( thetaStart + v * thetaLength );
38513            var pz = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
38514
38515            normal.set( px, py, pz ).normalize();
38516
38517            positions.setXYZ( index, px, py, pz );
38518            normals.setXYZ( index, normal.x, normal.y, normal.z );
38519            uvs.setXY( index, u, 1 - v );
38520
38521            verticesRow.push( index );
38522
38523            index ++;
38524
38525        }
38526
38527        vertices.push( verticesRow );
38528
38529    }
38530
38531    var indices = [];
38532
38533    for ( var y = 0; y < heightSegments; y ++ ) {
38534
38535        for ( var x = 0; x < widthSegments; x ++ ) {
38536
38537            var v1 = vertices[ y ][ x + 1 ];
38538            var v2 = vertices[ y ][ x ];
38539            var v3 = vertices[ y + 1 ][ x ];
38540            var v4 = vertices[ y + 1 ][ x + 1 ];
38541
38542            if ( y !== 0 || thetaStart > 0 ) indices.push( v1, v2, v4 );
38543            if ( y !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( v2, v3, v4 );
38544
38545        }
38546
38547    }
38548
38549    this.setIndex( new ( positions.count > 65535 ? THREE.Uint32Attribute : THREE.Uint16Attribute )( indices, 1 ) );
38550    this.addAttribute( 'position', positions );
38551    this.addAttribute( 'normal', normals );
38552    this.addAttribute( 'uv', uvs );
38553
38554    this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
38555
38556};
38557
38558THREE.SphereBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
38559THREE.SphereBufferGeometry.prototype.constructor = THREE.SphereBufferGeometry;
38560
38561// File:src/extras/geometries/TextGeometry.js
38562
38563/**
38564 * @author zz85 / http://www.lab4games.net/zz85/blog
38565 * @author alteredq / http://alteredqualia.com/
38566 *
38567 * Text = 3D Text
38568 *
38569 * parameters = {
38570 *  font: <THREE.Font>, // font
38571 *
38572 *  size: <float>, // size of the text
38573 *  height: <float>, // thickness to extrude text
38574 *  curveSegments: <int>, // number of points on the curves
38575 *
38576 *  bevelEnabled: <bool>, // turn on bevel
38577 *  bevelThickness: <float>, // how deep into text bevel goes
38578 *  bevelSize: <float> // how far from text outline is bevel
38579 * }
38580 */
38581
38582THREE.TextGeometry = function ( text, parameters ) {
38583
38584    parameters = parameters || {};
38585
38586    var font = parameters.font;
38587
38588    if ( font instanceof THREE.Font === false ) {
38589
38590        console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );
38591        return new THREE.Geometry();
38592
38593    }
38594
38595    var shapes = font.generateShapes( text, parameters.size, parameters.curveSegments );
38596
38597    // translate parameters to ExtrudeGeometry API
38598
38599    parameters.amount = parameters.height !== undefined ? parameters.height : 50;
38600
38601    // defaults
38602
38603    if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
38604    if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
38605    if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
38606
38607    THREE.ExtrudeGeometry.call( this, shapes, parameters );
38608
38609    this.type = 'TextGeometry';
38610
38611};
38612
38613THREE.TextGeometry.prototype = Object.create( THREE.ExtrudeGeometry.prototype );
38614THREE.TextGeometry.prototype.constructor = THREE.TextGeometry;
38615
38616// File:src/extras/geometries/TorusBufferGeometry.js
38617
38618/**
38619 * @author Mugen87 / https://github.com/Mugen87
38620 */
38621
38622THREE.TorusBufferGeometry = function ( radius, tube, radialSegments, tubularSegments, arc ) {
38623
38624    THREE.BufferGeometry.call( this );
38625
38626    this.type = 'TorusBufferGeometry';
38627
38628    this.parameters = {
38629        radius: radius,
38630        tube: tube,
38631        radialSegments: radialSegments,
38632        tubularSegments: tubularSegments,
38633        arc: arc
38634    };
38635
38636    radius = radius || 100;
38637    tube = tube || 40;
38638    radialSegments = Math.floor( radialSegments ) || 8;
38639    tubularSegments = Math.floor( tubularSegments ) || 6;
38640    arc = arc || Math.PI * 2;
38641
38642    // used to calculate buffer length
38643    var vertexCount = ( ( radialSegments + 1 ) * ( tubularSegments + 1 ) );
38644    var indexCount = radialSegments * tubularSegments * 2 * 3;
38645
38646    // buffers
38647    var indices = new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount );
38648    var vertices = new Float32Array( vertexCount * 3 );
38649    var normals = new Float32Array( vertexCount * 3 );
38650    var uvs = new Float32Array( vertexCount * 2 );
38651
38652    // offset variables
38653    var vertexBufferOffset = 0;
38654    var uvBufferOffset = 0;
38655    var indexBufferOffset = 0;
38656
38657    // helper variables
38658    var center = new THREE.Vector3();
38659    var vertex = new THREE.Vector3();
38660    var normal = new THREE.Vector3();
38661
38662    var j, i;
38663
38664    // generate vertices, normals and uvs
38665
38666    for ( j = 0; j <= radialSegments; j ++ ) {
38667
38668        for ( i = 0; i <= tubularSegments; i ++ ) {
38669
38670            var u = i / tubularSegments * arc;
38671            var v = j / radialSegments * Math.PI * 2;
38672
38673            // vertex
38674            vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
38675            vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
38676            vertex.z = tube * Math.sin( v );
38677
38678            vertices[ vertexBufferOffset ] = vertex.x;
38679            vertices[ vertexBufferOffset + 1 ] = vertex.y;
38680            vertices[ vertexBufferOffset + 2 ] = vertex.z;
38681
38682            // this vector is used to calculate the normal
38683            center.x = radius * Math.cos( u );
38684            center.y = radius * Math.sin( u );
38685
38686            // normal
38687            normal.subVectors( vertex, center ).normalize();
38688
38689            normals[ vertexBufferOffset ] = normal.x;
38690            normals[ vertexBufferOffset + 1 ] = normal.y;
38691            normals[ vertexBufferOffset + 2 ] = normal.z;
38692
38693            // uv
38694            uvs[ uvBufferOffset ] = i / tubularSegments;
38695            uvs[ uvBufferOffset + 1 ] = j / radialSegments;
38696
38697            // update offsets
38698            vertexBufferOffset += 3;
38699            uvBufferOffset += 2;
38700
38701        }
38702
38703    }
38704
38705    // generate indices
38706
38707    for ( j = 1; j <= radialSegments; j ++ ) {
38708
38709        for ( i = 1; i <= tubularSegments; i ++ ) {
38710
38711            // indices
38712            var a = ( tubularSegments + 1 ) * j + i - 1;
38713            var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
38714            var c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
38715            var d = ( tubularSegments + 1 ) * j + i;
38716
38717            // face one
38718            indices[ indexBufferOffset ] = a;
38719            indices[ indexBufferOffset + 1 ] = b;
38720            indices[ indexBufferOffset + 2 ] = d;
38721
38722            // face two
38723            indices[ indexBufferOffset + 3 ] = b;
38724            indices[ indexBufferOffset + 4 ] = c;
38725            indices[ indexBufferOffset + 5 ] = d;
38726
38727            // update offset
38728            indexBufferOffset += 6;
38729
38730        }
38731
38732    }
38733
38734    // build geometry
38735    this.setIndex( new THREE.BufferAttribute( indices, 1 ) );
38736    this.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
38737    this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
38738    this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
38739
38740};
38741
38742THREE.TorusBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
38743THREE.TorusBufferGeometry.prototype.constructor = THREE.TorusBufferGeometry;
38744
38745// File:src/extras/geometries/TorusGeometry.js
38746
38747/**
38748 * @author oosmoxiecode
38749 * @author mrdoob / http://mrdoob.com/
38750 * based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3DLite/src/away3dlite/primitives/Torus.as?r=2888
38751 */
38752
38753THREE.TorusGeometry = function ( radius, tube, radialSegments, tubularSegments, arc ) {
38754
38755    THREE.Geometry.call( this );
38756
38757    this.type = 'TorusGeometry';
38758
38759    this.parameters = {
38760        radius: radius,
38761        tube: tube,
38762        radialSegments: radialSegments,
38763        tubularSegments: tubularSegments,
38764        arc: arc
38765    };
38766
38767    this.fromBufferGeometry( new THREE.TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );
38768
38769};
38770
38771THREE.TorusGeometry.prototype = Object.create( THREE.Geometry.prototype );
38772THREE.TorusGeometry.prototype.constructor = THREE.TorusGeometry;
38773
38774// File:src/extras/geometries/TorusKnotBufferGeometry.js
38775
38776/**
38777 * @author Mugen87 / https://github.com/Mugen87
38778 *
38779 * see: http://www.blackpawn.com/texts/pqtorus/
38780 */
38781THREE.TorusKnotBufferGeometry = function ( radius, tube, tubularSegments, radialSegments, p, q ) {
38782
38783    THREE.BufferGeometry.call( this );
38784
38785    this.type = 'TorusKnotBufferGeometry';
38786
38787    this.parameters = {
38788        radius: radius,
38789        tube: tube,
38790        tubularSegments: tubularSegments,
38791        radialSegments: radialSegments,
38792        p: p,
38793        q: q
38794    };
38795
38796    radius = radius || 100;
38797    tube = tube || 40;
38798    tubularSegments = Math.floor( tubularSegments ) || 64;
38799    radialSegments = Math.floor( radialSegments ) || 8;
38800    p = p || 2;
38801    q = q || 3;
38802
38803    // used to calculate buffer length
38804    var vertexCount = ( ( radialSegments + 1 ) * ( tubularSegments + 1 ) );
38805    var indexCount = radialSegments * tubularSegments * 2 * 3;
38806
38807    // buffers
38808    var indices = new THREE.BufferAttribute( new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount ) , 1 );
38809    var vertices = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
38810    var normals = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
38811    var uvs = new THREE.BufferAttribute( new Float32Array( vertexCount * 2 ), 2 );
38812
38813    // helper variables
38814    var i, j, index = 0, indexOffset = 0;
38815
38816    var vertex = new THREE.Vector3();
38817    var normal = new THREE.Vector3();
38818    var uv = new THREE.Vector2();
38819
38820    var P1 = new THREE.Vector3();
38821    var P2 = new THREE.Vector3();
38822
38823    var B = new THREE.Vector3();
38824    var T = new THREE.Vector3();
38825    var N = new THREE.Vector3();
38826
38827    // generate vertices, normals and uvs
38828
38829    for ( i = 0; i <= tubularSegments; ++ i ) {
38830
38831        // the radian "u" is used to calculate the position on the torus curve of the current tubular segement
38832
38833        var u = i / tubularSegments * p * Math.PI * 2;
38834
38835        // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
38836        // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
38837
38838        calculatePositionOnCurve( u, p, q, radius, P1 );
38839        calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
38840
38841        // calculate orthonormal basis
38842
38843        T.subVectors( P2, P1 );
38844        N.addVectors( P2, P1 );
38845        B.crossVectors( T, N );
38846        N.crossVectors( B, T );
38847
38848        // normalize B, N. T can be ignored, we don't use it
38849
38850        B.normalize();
38851        N.normalize();
38852
38853        for ( j = 0; j <= radialSegments; ++ j ) {
38854
38855            // now calculate the vertices. they are nothing more than an extrusion of the torus curve.
38856            // because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
38857
38858            var v = j / radialSegments * Math.PI * 2;
38859            var cx = - tube * Math.cos( v );
38860            var cy = tube * Math.sin( v );
38861
38862            // now calculate the final vertex position.
38863            // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
38864
38865            vertex.x = P1.x + ( cx * N.x + cy * B.x );
38866            vertex.y = P1.y + ( cx * N.y + cy * B.y );
38867            vertex.z = P1.z + ( cx * N.z + cy * B.z );
38868
38869            // vertex
38870            vertices.setXYZ( index, vertex.x, vertex.y, vertex.z );
38871
38872            // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
38873            normal.subVectors( vertex, P1 ).normalize();
38874            normals.setXYZ( index, normal.x, normal.y, normal.z );
38875
38876            // uv
38877            uv.x = i / tubularSegments;
38878            uv.y = j / radialSegments;
38879            uvs.setXY( index, uv.x, uv.y );
38880
38881            // increase index
38882            index ++;
38883
38884        }
38885
38886    }
38887
38888    // generate indices
38889
38890    for ( j = 1; j <= tubularSegments; j ++ ) {
38891
38892        for ( i = 1; i <= radialSegments; i ++ ) {
38893
38894            // indices
38895            var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
38896            var b = ( radialSegments + 1 ) * j + ( i - 1 );
38897            var c = ( radialSegments + 1 ) * j + i;
38898            var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
38899
38900            // face one
38901            indices.setX( indexOffset, a ); indexOffset++;
38902            indices.setX( indexOffset, b ); indexOffset++;
38903            indices.setX( indexOffset, d ); indexOffset++;
38904
38905            // face two
38906            indices.setX( indexOffset, b ); indexOffset++;
38907            indices.setX( indexOffset, c ); indexOffset++;
38908            indices.setX( indexOffset, d ); indexOffset++;
38909
38910        }
38911
38912    }
38913
38914    // build geometry
38915
38916    this.setIndex( indices );
38917    this.addAttribute( 'position', vertices );
38918    this.addAttribute( 'normal', normals );
38919    this.addAttribute( 'uv', uvs );
38920
38921    // this function calculates the current position on the torus curve
38922
38923    function calculatePositionOnCurve( u, p, q, radius, position ) {
38924
38925        var cu = Math.cos( u );
38926        var su = Math.sin( u );
38927        var quOverP = q / p * u;
38928        var cs = Math.cos( quOverP );
38929
38930        position.x = radius * ( 2 + cs ) * 0.5 * cu;
38931        position.y = radius * ( 2 + cs ) * su * 0.5;
38932        position.z = radius * Math.sin( quOverP ) * 0.5;
38933
38934    }
38935
38936};
38937
38938THREE.TorusKnotBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
38939THREE.TorusKnotBufferGeometry.prototype.constructor = THREE.TorusKnotBufferGeometry;
38940
38941// File:src/extras/geometries/TorusKnotGeometry.js
38942
38943/**
38944 * @author oosmoxiecode
38945 */
38946
38947THREE.TorusKnotGeometry = function ( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {
38948
38949    THREE.Geometry.call( this );
38950
38951    this.type = 'TorusKnotGeometry';
38952
38953    this.parameters = {
38954        radius: radius,
38955        tube: tube,
38956        tubularSegments: tubularSegments,
38957        radialSegments: radialSegments,
38958        p: p,
38959        q: q
38960    };
38961
38962    if( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' );
38963
38964    this.fromBufferGeometry( new THREE.TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );
38965    this.mergeVertices();
38966
38967};
38968
38969THREE.TorusKnotGeometry.prototype = Object.create( THREE.Geometry.prototype );
38970THREE.TorusKnotGeometry.prototype.constructor = THREE.TorusKnotGeometry;
38971
38972// File:src/extras/geometries/TubeGeometry.js
38973
38974/**
38975 * @author WestLangley / https://github.com/WestLangley
38976 * @author zz85 / https://github.com/zz85
38977 * @author miningold / https://github.com/miningold
38978 * @author jonobr1 / https://github.com/jonobr1
38979 *
38980 * Modified from the TorusKnotGeometry by @oosmoxiecode
38981 *
38982 * Creates a tube which extrudes along a 3d spline
38983 *
38984 * Uses parallel transport frames as described in
38985 * http://www.cs.indiana.edu/pub/techreports/TR425.pdf
38986 */
38987
38988THREE.TubeGeometry = function ( path, segments, radius, radialSegments, closed, taper ) {
38989
38990    THREE.Geometry.call( this );
38991
38992    this.type = 'TubeGeometry';
38993
38994    this.parameters = {
38995        path: path,
38996        segments: segments,
38997        radius: radius,
38998        radialSegments: radialSegments,
38999        closed: closed,
39000        taper: taper
39001    };
39002
39003    segments = segments || 64;
39004    radius = radius || 1;
39005    radialSegments = radialSegments || 8;
39006    closed = closed || false;
39007    taper = taper || THREE.TubeGeometry.NoTaper;
39008
39009    var grid = [];
39010
39011    var scope = this,
39012
39013        tangent,
39014        normal,
39015        binormal,
39016
39017        numpoints = segments + 1,
39018
39019        u, v, r,
39020
39021        cx, cy,
39022        pos, pos2 = new THREE.Vector3(),
39023        i, j,
39024        ip, jp,
39025        a, b, c, d,
39026        uva, uvb, uvc, uvd;
39027
39028    var frames = new THREE.TubeGeometry.FrenetFrames( path, segments, closed ),
39029        tangents = frames.tangents,
39030        normals = frames.normals,
39031        binormals = frames.binormals;
39032
39033    // proxy internals
39034    this.tangents = tangents;
39035    this.normals = normals;
39036    this.binormals = binormals;
39037
39038    function vert( x, y, z ) {
39039
39040        return scope.vertices.push( new THREE.Vector3( x, y, z ) ) - 1;
39041
39042    }
39043
39044    // construct the grid
39045
39046    for ( i = 0; i < numpoints; i ++ ) {
39047
39048        grid[ i ] = [];
39049
39050        u = i / ( numpoints - 1 );
39051
39052        pos = path.getPointAt( u );
39053
39054        tangent = tangents[ i ];
39055        normal = normals[ i ];
39056        binormal = binormals[ i ];
39057
39058        r = radius * taper( u );
39059
39060        for ( j = 0; j < radialSegments; j ++ ) {
39061
39062            v = j / radialSegments * 2 * Math.PI;
39063
39064            cx = - r * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
39065            cy = r * Math.sin( v );
39066
39067            pos2.copy( pos );
39068            pos2.x += cx * normal.x + cy * binormal.x;
39069            pos2.y += cx * normal.y + cy * binormal.y;
39070            pos2.z += cx * normal.z + cy * binormal.z;
39071
39072            grid[ i ][ j ] = vert( pos2.x, pos2.y, pos2.z );
39073
39074        }
39075
39076    }
39077
39078
39079    // construct the mesh
39080
39081    for ( i = 0; i < segments; i ++ ) {
39082
39083        for ( j = 0; j < radialSegments; j ++ ) {
39084
39085            ip = ( closed ) ? ( i + 1 ) % segments : i + 1;
39086            jp = ( j + 1 ) % radialSegments;
39087
39088            a = grid[ i ][ j ];		// *** NOT NECESSARILY PLANAR ! ***
39089            b = grid[ ip ][ j ];
39090            c = grid[ ip ][ jp ];
39091            d = grid[ i ][ jp ];
39092
39093            uva = new THREE.Vector2( i / segments, j / radialSegments );
39094            uvb = new THREE.Vector2( ( i + 1 ) / segments, j / radialSegments );
39095            uvc = new THREE.Vector2( ( i + 1 ) / segments, ( j + 1 ) / radialSegments );
39096            uvd = new THREE.Vector2( i / segments, ( j + 1 ) / radialSegments );
39097
39098            this.faces.push( new THREE.Face3( a, b, d ) );
39099            this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );
39100
39101            this.faces.push( new THREE.Face3( b, c, d ) );
39102            this.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );
39103
39104        }
39105
39106    }
39107
39108    this.computeFaceNormals();
39109    this.computeVertexNormals();
39110
39111};
39112
39113THREE.TubeGeometry.prototype = Object.create( THREE.Geometry.prototype );
39114THREE.TubeGeometry.prototype.constructor = THREE.TubeGeometry;
39115
39116THREE.TubeGeometry.NoTaper = function ( u ) {
39117
39118    return 1;
39119
39120};
39121
39122THREE.TubeGeometry.SinusoidalTaper = function ( u ) {
39123
39124    return Math.sin( Math.PI * u );
39125
39126};
39127
39128// For computing of Frenet frames, exposing the tangents, normals and binormals the spline
39129THREE.TubeGeometry.FrenetFrames = function ( path, segments, closed ) {
39130
39131    var	normal = new THREE.Vector3(),
39132
39133        tangents = [],
39134        normals = [],
39135        binormals = [],
39136
39137        vec = new THREE.Vector3(),
39138        mat = new THREE.Matrix4(),
39139
39140        numpoints = segments + 1,
39141        theta,
39142        smallest,
39143
39144        tx, ty, tz,
39145        i, u;
39146
39147
39148    // expose internals
39149    this.tangents = tangents;
39150    this.normals = normals;
39151    this.binormals = binormals;
39152
39153    // compute the tangent vectors for each segment on the path
39154
39155    for ( i = 0; i < numpoints; i ++ ) {
39156
39157        u = i / ( numpoints - 1 );
39158
39159        tangents[ i ] = path.getTangentAt( u );
39160        tangents[ i ].normalize();
39161
39162    }
39163
39164    initialNormal3();
39165
39166    /*
39167     function initialNormal1(lastBinormal) {
39168     // fixed start binormal. Has dangers of 0 vectors
39169     normals[ 0 ] = new THREE.Vector3();
39170     binormals[ 0 ] = new THREE.Vector3();
39171     if (lastBinormal===undefined) lastBinormal = new THREE.Vector3( 0, 0, 1 );
39172     normals[ 0 ].crossVectors( lastBinormal, tangents[ 0 ] ).normalize();
39173     binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ).normalize();
39174     }
39175
39176     function initialNormal2() {
39177
39178     // This uses the Frenet-Serret formula for deriving binormal
39179     var t2 = path.getTangentAt( epsilon );
39180
39181     normals[ 0 ] = new THREE.Vector3().subVectors( t2, tangents[ 0 ] ).normalize();
39182     binormals[ 0 ] = new THREE.Vector3().crossVectors( tangents[ 0 ], normals[ 0 ] );
39183
39184     normals[ 0 ].crossVectors( binormals[ 0 ], tangents[ 0 ] ).normalize(); // last binormal x tangent
39185     binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ).normalize();
39186
39187     }
39188     */
39189
39190    function initialNormal3() {
39191
39192        // select an initial normal vector perpendicular to the first tangent vector,
39193        // and in the direction of the smallest tangent xyz component
39194
39195        normals[ 0 ] = new THREE.Vector3();
39196        binormals[ 0 ] = new THREE.Vector3();
39197        smallest = Number.MAX_VALUE;
39198        tx = Math.abs( tangents[ 0 ].x );
39199        ty = Math.abs( tangents[ 0 ].y );
39200        tz = Math.abs( tangents[ 0 ].z );
39201
39202        if ( tx <= smallest ) {
39203
39204            smallest = tx;
39205            normal.set( 1, 0, 0 );
39206
39207        }
39208
39209        if ( ty <= smallest ) {
39210
39211            smallest = ty;
39212            normal.set( 0, 1, 0 );
39213
39214        }
39215
39216        if ( tz <= smallest ) {
39217
39218            normal.set( 0, 0, 1 );
39219
39220        }
39221
39222        vec.crossVectors( tangents[ 0 ], normal ).normalize();
39223
39224        normals[ 0 ].crossVectors( tangents[ 0 ], vec );
39225        binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
39226
39227    }
39228
39229
39230    // compute the slowly-varying normal and binormal vectors for each segment on the path
39231
39232    for ( i = 1; i < numpoints; i ++ ) {
39233
39234        normals[ i ] = normals[ i - 1 ].clone();
39235
39236        binormals[ i ] = binormals[ i - 1 ].clone();
39237
39238        vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
39239
39240        if ( vec.length() > Number.EPSILON ) {
39241
39242            vec.normalize();
39243
39244            theta = Math.acos( THREE.Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
39245
39246            normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
39247
39248        }
39249
39250        binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
39251
39252    }
39253
39254
39255    // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
39256
39257    if ( closed ) {
39258
39259        theta = Math.acos( THREE.Math.clamp( normals[ 0 ].dot( normals[ numpoints - 1 ] ), - 1, 1 ) );
39260        theta /= ( numpoints - 1 );
39261
39262        if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ numpoints - 1 ] ) ) > 0 ) {
39263
39264            theta = - theta;
39265
39266        }
39267
39268        for ( i = 1; i < numpoints; i ++ ) {
39269
39270            // twist a little...
39271            normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
39272            binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
39273
39274        }
39275
39276    }
39277
39278};
39279
39280// File:src/extras/geometries/PolyhedronGeometry.js
39281
39282/**
39283 * @author clockworkgeek / https://github.com/clockworkgeek
39284 * @author timothypratley / https://github.com/timothypratley
39285 * @author WestLangley / http://github.com/WestLangley
39286 */
39287
39288THREE.PolyhedronGeometry = function ( vertices, indices, radius, detail ) {
39289
39290    THREE.Geometry.call( this );
39291
39292    this.type = 'PolyhedronGeometry';
39293
39294    this.parameters = {
39295        vertices: vertices,
39296        indices: indices,
39297        radius: radius,
39298        detail: detail
39299    };
39300
39301    radius = radius || 1;
39302    detail = detail || 0;
39303
39304    var that = this;
39305
39306    for ( var i = 0, l = vertices.length; i < l; i += 3 ) {
39307
39308        prepare( new THREE.Vector3( vertices[ i ], vertices[ i + 1 ], vertices[ i + 2 ] ) );
39309
39310    }
39311
39312    var p = this.vertices;
39313
39314    var faces = [];
39315
39316    for ( var i = 0, j = 0, l = indices.length; i < l; i += 3, j ++ ) {
39317
39318        var v1 = p[ indices[ i ] ];
39319        var v2 = p[ indices[ i + 1 ] ];
39320        var v3 = p[ indices[ i + 2 ] ];
39321
39322        faces[ j ] = new THREE.Face3( v1.index, v2.index, v3.index, [ v1.clone(), v2.clone(), v3.clone() ], undefined, j );
39323
39324    }
39325
39326    var centroid = new THREE.Vector3();
39327
39328    for ( var i = 0, l = faces.length; i < l; i ++ ) {
39329
39330        subdivide( faces[ i ], detail );
39331
39332    }
39333
39334
39335    // Handle case when face straddles the seam
39336
39337    for ( var i = 0, l = this.faceVertexUvs[ 0 ].length; i < l; i ++ ) {
39338
39339        var uvs = this.faceVertexUvs[ 0 ][ i ];
39340
39341        var x0 = uvs[ 0 ].x;
39342        var x1 = uvs[ 1 ].x;
39343        var x2 = uvs[ 2 ].x;
39344
39345        var max = Math.max( x0, x1, x2 );
39346        var min = Math.min( x0, x1, x2 );
39347
39348        if ( max > 0.9 && min < 0.1 ) {
39349
39350            // 0.9 is somewhat arbitrary
39351
39352            if ( x0 < 0.2 ) uvs[ 0 ].x += 1;
39353            if ( x1 < 0.2 ) uvs[ 1 ].x += 1;
39354            if ( x2 < 0.2 ) uvs[ 2 ].x += 1;
39355
39356        }
39357
39358    }
39359
39360
39361    // Apply radius
39362
39363    for ( var i = 0, l = this.vertices.length; i < l; i ++ ) {
39364
39365        this.vertices[ i ].multiplyScalar( radius );
39366
39367    }
39368
39369
39370    // Merge vertices
39371
39372    this.mergeVertices();
39373
39374    this.computeFaceNormals();
39375
39376    this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
39377
39378
39379    // Project vector onto sphere's surface
39380
39381    function prepare( vector ) {
39382
39383        var vertex = vector.normalize().clone();
39384        vertex.index = that.vertices.push( vertex ) - 1;
39385
39386        // Texture coords are equivalent to map coords, calculate angle and convert to fraction of a circle.
39387
39388        var u = azimuth( vector ) / 2 / Math.PI + 0.5;
39389        var v = inclination( vector ) / Math.PI + 0.5;
39390        vertex.uv = new THREE.Vector2( u, 1 - v );
39391
39392        return vertex;
39393
39394    }
39395
39396
39397    // Approximate a curved face with recursively sub-divided triangles.
39398
39399    function make( v1, v2, v3, materialIndex ) {
39400
39401        var face = new THREE.Face3( v1.index, v2.index, v3.index, [ v1.clone(), v2.clone(), v3.clone() ], undefined, materialIndex );
39402        that.faces.push( face );
39403
39404        centroid.copy( v1 ).add( v2 ).add( v3 ).divideScalar( 3 );
39405
39406        var azi = azimuth( centroid );
39407
39408        that.faceVertexUvs[ 0 ].push( [
39409            correctUV( v1.uv, v1, azi ),
39410            correctUV( v2.uv, v2, azi ),
39411            correctUV( v3.uv, v3, azi )
39412        ] );
39413
39414    }
39415
39416
39417    // Analytically subdivide a face to the required detail level.
39418
39419    function subdivide( face, detail ) {
39420
39421        var cols = Math.pow( 2, detail );
39422        var a = prepare( that.vertices[ face.a ] );
39423        var b = prepare( that.vertices[ face.b ] );
39424        var c = prepare( that.vertices[ face.c ] );
39425        var v = [];
39426
39427        var materialIndex = face.materialIndex;
39428
39429        // Construct all of the vertices for this subdivision.
39430
39431        for ( var i = 0 ; i <= cols; i ++ ) {
39432
39433            v[ i ] = [];
39434
39435            var aj = prepare( a.clone().lerp( c, i / cols ) );
39436            var bj = prepare( b.clone().lerp( c, i / cols ) );
39437            var rows = cols - i;
39438
39439            for ( var j = 0; j <= rows; j ++ ) {
39440
39441                if ( j === 0 && i === cols ) {
39442
39443                    v[ i ][ j ] = aj;
39444
39445                } else {
39446
39447                    v[ i ][ j ] = prepare( aj.clone().lerp( bj, j / rows ) );
39448
39449                }
39450
39451            }
39452
39453        }
39454
39455        // Construct all of the faces.
39456
39457        for ( var i = 0; i < cols ; i ++ ) {
39458
39459            for ( var j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
39460
39461                var k = Math.floor( j / 2 );
39462
39463                if ( j % 2 === 0 ) {
39464
39465                    make(
39466                        v[ i ][ k + 1 ],
39467                        v[ i + 1 ][ k ],
39468                        v[ i ][ k ],
39469                        materialIndex
39470                    );
39471
39472                } else {
39473
39474                    make(
39475                        v[ i ][ k + 1 ],
39476                        v[ i + 1 ][ k + 1 ],
39477                        v[ i + 1 ][ k ],
39478                        materialIndex
39479                    );
39480
39481                }
39482
39483            }
39484
39485        }
39486
39487    }
39488
39489
39490    // Angle around the Y axis, counter-clockwise when looking from above.
39491
39492    function azimuth( vector ) {
39493
39494        return Math.atan2( vector.z, - vector.x );
39495
39496    }
39497
39498
39499    // Angle above the XZ plane.
39500
39501    function inclination( vector ) {
39502
39503        return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
39504
39505    }
39506
39507
39508    // Texture fixing helper. Spheres have some odd behaviours.
39509
39510    function correctUV( uv, vector, azimuth ) {
39511
39512        if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) uv = new THREE.Vector2( uv.x - 1, uv.y );
39513        if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) uv = new THREE.Vector2( azimuth / 2 / Math.PI + 0.5, uv.y );
39514        return uv.clone();
39515
39516    }
39517
39518
39519};
39520
39521THREE.PolyhedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
39522THREE.PolyhedronGeometry.prototype.constructor = THREE.PolyhedronGeometry;
39523
39524// File:src/extras/geometries/DodecahedronGeometry.js
39525
39526/**
39527 * @author Abe Pazos / https://hamoid.com
39528 */
39529
39530THREE.DodecahedronGeometry = function ( radius, detail ) {
39531
39532    var t = ( 1 + Math.sqrt( 5 ) ) / 2;
39533    var r = 1 / t;
39534
39535    var vertices = [
39536
39537        // (±1, ±1, ±1)
39538        - 1, - 1, - 1,    - 1, - 1,  1,
39539        - 1,  1, - 1,    - 1,  1,  1,
39540        1, - 1, - 1,     1, - 1,  1,
39541        1,  1, - 1,     1,  1,  1,
39542
39543        // (0, ±1/φ, ±φ)
39544        0, - r, - t,     0, - r,  t,
39545        0,  r, - t,     0,  r,  t,
39546
39547        // (±1/φ, ±φ, 0)
39548        - r, - t,  0,    - r,  t,  0,
39549        r, - t,  0,     r,  t,  0,
39550
39551        // (±φ, 0, ±1/φ)
39552        - t,  0, - r,     t,  0, - r,
39553        - t,  0,  r,     t,  0,  r
39554    ];
39555
39556    var indices = [
39557        3, 11,  7,      3,  7, 15,      3, 15, 13,
39558        7, 19, 17,      7, 17,  6,      7,  6, 15,
39559        17,  4,  8,     17,  8, 10,     17, 10,  6,
39560        8,  0, 16,      8, 16,  2,      8,  2, 10,
39561        0, 12,  1,      0,  1, 18,      0, 18, 16,
39562        6, 10,  2,      6,  2, 13,      6, 13, 15,
39563        2, 16, 18,      2, 18,  3,      2,  3, 13,
39564        18,  1,  9,     18,  9, 11,     18, 11,  3,
39565        4, 14, 12,      4, 12,  0,      4,  0,  8,
39566        11,  9,  5,     11,  5, 19,     11, 19,  7,
39567        19,  5, 14,     19, 14,  4,     19,  4, 17,
39568        1, 12, 14,      1, 14,  5,      1,  5,  9
39569    ];
39570
39571    THREE.PolyhedronGeometry.call( this, vertices, indices, radius, detail );
39572
39573    this.type = 'DodecahedronGeometry';
39574
39575    this.parameters = {
39576        radius: radius,
39577        detail: detail
39578    };
39579
39580};
39581
39582THREE.DodecahedronGeometry.prototype = Object.create( THREE.PolyhedronGeometry.prototype );
39583THREE.DodecahedronGeometry.prototype.constructor = THREE.DodecahedronGeometry;
39584
39585// File:src/extras/geometries/IcosahedronGeometry.js
39586
39587/**
39588 * @author timothypratley / https://github.com/timothypratley
39589 */
39590
39591THREE.IcosahedronGeometry = function ( radius, detail ) {
39592
39593    var t = ( 1 + Math.sqrt( 5 ) ) / 2;
39594
39595    var vertices = [
39596        - 1,  t,  0,    1,  t,  0,   - 1, - t,  0,    1, - t,  0,
39597        0, - 1,  t,    0,  1,  t,    0, - 1, - t,    0,  1, - t,
39598        t,  0, - 1,    t,  0,  1,   - t,  0, - 1,   - t,  0,  1
39599    ];
39600
39601    var indices = [
39602        0, 11,  5,    0,  5,  1,    0,  1,  7,    0,  7, 10,    0, 10, 11,
39603        1,  5,  9,    5, 11,  4,   11, 10,  2,   10,  7,  6,    7,  1,  8,
39604        3,  9,  4,    3,  4,  2,    3,  2,  6,    3,  6,  8,    3,  8,  9,
39605        4,  9,  5,    2,  4, 11,    6,  2, 10,    8,  6,  7,    9,  8,  1
39606    ];
39607
39608    THREE.PolyhedronGeometry.call( this, vertices, indices, radius, detail );
39609
39610    this.type = 'IcosahedronGeometry';
39611
39612    this.parameters = {
39613        radius: radius,
39614        detail: detail
39615    };
39616
39617};
39618
39619THREE.IcosahedronGeometry.prototype = Object.create( THREE.PolyhedronGeometry.prototype );
39620THREE.IcosahedronGeometry.prototype.constructor = THREE.IcosahedronGeometry;
39621
39622// File:src/extras/geometries/OctahedronGeometry.js
39623
39624/**
39625 * @author timothypratley / https://github.com/timothypratley
39626 */
39627
39628THREE.OctahedronGeometry = function ( radius, detail ) {
39629
39630    var vertices = [
39631        1, 0, 0,   - 1, 0, 0,    0, 1, 0,    0, - 1, 0,    0, 0, 1,    0, 0, - 1
39632    ];
39633
39634    var indices = [
39635        0, 2, 4,    0, 4, 3,    0, 3, 5,    0, 5, 2,    1, 2, 5,    1, 5, 3,    1, 3, 4,    1, 4, 2
39636    ];
39637
39638    THREE.PolyhedronGeometry.call( this, vertices, indices, radius, detail );
39639
39640    this.type = 'OctahedronGeometry';
39641
39642    this.parameters = {
39643        radius: radius,
39644        detail: detail
39645    };
39646
39647};
39648
39649THREE.OctahedronGeometry.prototype = Object.create( THREE.PolyhedronGeometry.prototype );
39650THREE.OctahedronGeometry.prototype.constructor = THREE.OctahedronGeometry;
39651
39652// File:src/extras/geometries/TetrahedronGeometry.js
39653
39654/**
39655 * @author timothypratley / https://github.com/timothypratley
39656 */
39657
39658THREE.TetrahedronGeometry = function ( radius, detail ) {
39659
39660    var vertices = [
39661        1,  1,  1,   - 1, - 1,  1,   - 1,  1, - 1,    1, - 1, - 1
39662    ];
39663
39664    var indices = [
39665        2,  1,  0,    0,  3,  2,    1,  3,  0,    2,  3,  1
39666    ];
39667
39668    THREE.PolyhedronGeometry.call( this, vertices, indices, radius, detail );
39669
39670    this.type = 'TetrahedronGeometry';
39671
39672    this.parameters = {
39673        radius: radius,
39674        detail: detail
39675    };
39676
39677};
39678
39679THREE.TetrahedronGeometry.prototype = Object.create( THREE.PolyhedronGeometry.prototype );
39680THREE.TetrahedronGeometry.prototype.constructor = THREE.TetrahedronGeometry;
39681
39682// File:src/extras/geometries/ParametricGeometry.js
39683
39684/**
39685 * @author zz85 / https://github.com/zz85
39686 * Parametric Surfaces Geometry
39687 * based on the brilliant article by @prideout http://prideout.net/blog/?p=44
39688 *
39689 * new THREE.ParametricGeometry( parametricFunction, uSegments, ySegements );
39690 *
39691 */
39692
39693THREE.ParametricGeometry = function ( func, slices, stacks ) {
39694
39695    THREE.Geometry.call( this );
39696
39697    this.type = 'ParametricGeometry';
39698
39699    this.parameters = {
39700        func: func,
39701        slices: slices,
39702        stacks: stacks
39703    };
39704
39705    var verts = this.vertices;
39706    var faces = this.faces;
39707    var uvs = this.faceVertexUvs[ 0 ];
39708
39709    var i, j, p;
39710    var u, v;
39711
39712    var sliceCount = slices + 1;
39713
39714    for ( i = 0; i <= stacks; i ++ ) {
39715
39716        v = i / stacks;
39717
39718        for ( j = 0; j <= slices; j ++ ) {
39719
39720            u = j / slices;
39721
39722            p = func( u, v );
39723            verts.push( p );
39724
39725        }
39726
39727    }
39728
39729    var a, b, c, d;
39730    var uva, uvb, uvc, uvd;
39731
39732    for ( i = 0; i < stacks; i ++ ) {
39733
39734        for ( j = 0; j < slices; j ++ ) {
39735
39736            a = i * sliceCount + j;
39737            b = i * sliceCount + j + 1;
39738            c = ( i + 1 ) * sliceCount + j + 1;
39739            d = ( i + 1 ) * sliceCount + j;
39740
39741            uva = new THREE.Vector2( j / slices, i / stacks );
39742            uvb = new THREE.Vector2( ( j + 1 ) / slices, i / stacks );
39743            uvc = new THREE.Vector2( ( j + 1 ) / slices, ( i + 1 ) / stacks );
39744            uvd = new THREE.Vector2( j / slices, ( i + 1 ) / stacks );
39745
39746            faces.push( new THREE.Face3( a, b, d ) );
39747            uvs.push( [ uva, uvb, uvd ] );
39748
39749            faces.push( new THREE.Face3( b, c, d ) );
39750            uvs.push( [ uvb.clone(), uvc, uvd.clone() ] );
39751
39752        }
39753
39754    }
39755
39756    // console.log(this);
39757
39758    // magic bullet
39759    // var diff = this.mergeVertices();
39760    // console.log('removed ', diff, ' vertices by merging');
39761
39762    this.computeFaceNormals();
39763    this.computeVertexNormals();
39764
39765};
39766
39767THREE.ParametricGeometry.prototype = Object.create( THREE.Geometry.prototype );
39768THREE.ParametricGeometry.prototype.constructor = THREE.ParametricGeometry;
39769
39770// File:src/extras/geometries/WireframeGeometry.js
39771
39772/**
39773 * @author mrdoob / http://mrdoob.com/
39774 */
39775
39776THREE.WireframeGeometry = function ( geometry ) {
39777
39778    THREE.BufferGeometry.call( this );
39779
39780    var edge = [ 0, 0 ], hash = {};
39781
39782    function sortFunction( a, b ) {
39783
39784        return a - b;
39785
39786    }
39787
39788    var keys = [ 'a', 'b', 'c' ];
39789
39790    if ( geometry instanceof THREE.Geometry ) {
39791
39792        var vertices = geometry.vertices;
39793        var faces = geometry.faces;
39794        var numEdges = 0;
39795
39796        // allocate maximal size
39797        var edges = new Uint32Array( 6 * faces.length );
39798
39799        for ( var i = 0, l = faces.length; i < l; i ++ ) {
39800
39801            var face = faces[ i ];
39802
39803            for ( var j = 0; j < 3; j ++ ) {
39804
39805                edge[ 0 ] = face[ keys[ j ] ];
39806                edge[ 1 ] = face[ keys[ ( j + 1 ) % 3 ] ];
39807                edge.sort( sortFunction );
39808
39809                var key = edge.toString();
39810
39811                if ( hash[ key ] === undefined ) {
39812
39813                    edges[ 2 * numEdges ] = edge[ 0 ];
39814                    edges[ 2 * numEdges + 1 ] = edge[ 1 ];
39815                    hash[ key ] = true;
39816                    numEdges ++;
39817
39818                }
39819
39820            }
39821
39822        }
39823
39824        var coords = new Float32Array( numEdges * 2 * 3 );
39825
39826        for ( var i = 0, l = numEdges; i < l; i ++ ) {
39827
39828            for ( var j = 0; j < 2; j ++ ) {
39829
39830                var vertex = vertices[ edges [ 2 * i + j ] ];
39831
39832                var index = 6 * i + 3 * j;
39833                coords[ index + 0 ] = vertex.x;
39834                coords[ index + 1 ] = vertex.y;
39835                coords[ index + 2 ] = vertex.z;
39836
39837            }
39838
39839        }
39840
39841        this.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
39842
39843    } else if ( geometry instanceof THREE.BufferGeometry ) {
39844
39845        if ( geometry.index !== null ) {
39846
39847            // Indexed BufferGeometry
39848
39849            var indices = geometry.index.array;
39850            var vertices = geometry.attributes.position;
39851            var groups = geometry.groups;
39852            var numEdges = 0;
39853
39854            if ( groups.length === 0 ) {
39855
39856                geometry.addGroup( 0, indices.length );
39857
39858            }
39859
39860            // allocate maximal size
39861            var edges = new Uint32Array( 2 * indices.length );
39862
39863            for ( var o = 0, ol = groups.length; o < ol; ++ o ) {
39864
39865                var group = groups[ o ];
39866
39867                var start = group.start;
39868                var count = group.count;
39869
39870                for ( var i = start, il = start + count; i < il; i += 3 ) {
39871
39872                    for ( var j = 0; j < 3; j ++ ) {
39873
39874                        edge[ 0 ] = indices[ i + j ];
39875                        edge[ 1 ] = indices[ i + ( j + 1 ) % 3 ];
39876                        edge.sort( sortFunction );
39877
39878                        var key = edge.toString();
39879
39880                        if ( hash[ key ] === undefined ) {
39881
39882                            edges[ 2 * numEdges ] = edge[ 0 ];
39883                            edges[ 2 * numEdges + 1 ] = edge[ 1 ];
39884                            hash[ key ] = true;
39885                            numEdges ++;
39886
39887                        }
39888
39889                    }
39890
39891                }
39892
39893            }
39894
39895            var coords = new Float32Array( numEdges * 2 * 3 );
39896
39897            for ( var i = 0, l = numEdges; i < l; i ++ ) {
39898
39899                for ( var j = 0; j < 2; j ++ ) {
39900
39901                    var index = 6 * i + 3 * j;
39902                    var index2 = edges[ 2 * i + j ];
39903
39904                    coords[ index + 0 ] = vertices.getX( index2 );
39905                    coords[ index + 1 ] = vertices.getY( index2 );
39906                    coords[ index + 2 ] = vertices.getZ( index2 );
39907
39908                }
39909
39910            }
39911
39912            this.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
39913
39914        } else {
39915
39916            // non-indexed BufferGeometry
39917
39918            var vertices = geometry.attributes.position.array;
39919            var numEdges = vertices.length / 3;
39920            var numTris = numEdges / 3;
39921
39922            var coords = new Float32Array( numEdges * 2 * 3 );
39923
39924            for ( var i = 0, l = numTris; i < l; i ++ ) {
39925
39926                for ( var j = 0; j < 3; j ++ ) {
39927
39928                    var index = 18 * i + 6 * j;
39929
39930                    var index1 = 9 * i + 3 * j;
39931                    coords[ index + 0 ] = vertices[ index1 ];
39932                    coords[ index + 1 ] = vertices[ index1 + 1 ];
39933                    coords[ index + 2 ] = vertices[ index1 + 2 ];
39934
39935                    var index2 = 9 * i + 3 * ( ( j + 1 ) % 3 );
39936                    coords[ index + 3 ] = vertices[ index2 ];
39937                    coords[ index + 4 ] = vertices[ index2 + 1 ];
39938                    coords[ index + 5 ] = vertices[ index2 + 2 ];
39939
39940                }
39941
39942            }
39943
39944            this.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
39945
39946        }
39947
39948    }
39949
39950};
39951
39952THREE.WireframeGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
39953THREE.WireframeGeometry.prototype.constructor = THREE.WireframeGeometry;
39954
39955// File:src/extras/helpers/AxisHelper.js
39956
39957/**
39958 * @author sroucheray / http://sroucheray.org/
39959 * @author mrdoob / http://mrdoob.com/
39960 */
39961
39962THREE.AxisHelper = function ( size ) {
39963
39964    size = size || 1;
39965
39966    var vertices = new Float32Array( [
39967        0, 0, 0,  size, 0, 0,
39968        0, 0, 0,  0, size, 0,
39969        0, 0, 0,  0, 0, size
39970    ] );
39971
39972    var colors = new Float32Array( [
39973        1, 0, 0,  1, 0.6, 0,
39974        0, 1, 0,  0.6, 1, 0,
39975        0, 0, 1,  0, 0.6, 1
39976    ] );
39977
39978    var geometry = new THREE.BufferGeometry();
39979    geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
39980    geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
39981
39982    var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
39983
39984    THREE.LineSegments.call( this, geometry, material );
39985
39986};
39987
39988THREE.AxisHelper.prototype = Object.create( THREE.LineSegments.prototype );
39989THREE.AxisHelper.prototype.constructor = THREE.AxisHelper;
39990
39991// File:src/extras/helpers/ArrowHelper.js
39992
39993/**
39994 * @author WestLangley / http://github.com/WestLangley
39995 * @author zz85 / http://github.com/zz85
39996 * @author bhouston / http://clara.io
39997 *
39998 * Creates an arrow for visualizing directions
39999 *
40000 * Parameters:
40001 *  dir - Vector3
40002 *  origin - Vector3
40003 *  length - Number
40004 *  color - color in hex value
40005 *  headLength - Number
40006 *  headWidth - Number
40007 */
40008
40009THREE.ArrowHelper = ( function () {
40010
40011    var lineGeometry = new THREE.Geometry();
40012    lineGeometry.vertices.push( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) );
40013
40014    var coneGeometry = new THREE.CylinderGeometry( 0, 0.5, 1, 5, 1 );
40015    coneGeometry.translate( 0, - 0.5, 0 );
40016
40017    return function ArrowHelper( dir, origin, length, color, headLength, headWidth ) {
40018
40019        // dir is assumed to be normalized
40020
40021        THREE.Object3D.call( this );
40022
40023        if ( color === undefined ) color = 0xffff00;
40024        if ( length === undefined ) length = 1;
40025        if ( headLength === undefined ) headLength = 0.2 * length;
40026        if ( headWidth === undefined ) headWidth = 0.2 * headLength;
40027
40028        this.position.copy( origin );
40029
40030        this.line = new THREE.Line( lineGeometry, new THREE.LineBasicMaterial( { color: color } ) );
40031        this.line.matrixAutoUpdate = false;
40032        this.add( this.line );
40033
40034        this.cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color: color } ) );
40035        this.cone.matrixAutoUpdate = false;
40036        this.add( this.cone );
40037
40038        this.setDirection( dir );
40039        this.setLength( length, headLength, headWidth );
40040
40041    }
40042
40043}() );
40044
40045THREE.ArrowHelper.prototype = Object.create( THREE.Object3D.prototype );
40046THREE.ArrowHelper.prototype.constructor = THREE.ArrowHelper;
40047
40048THREE.ArrowHelper.prototype.setDirection = ( function () {
40049
40050    var axis = new THREE.Vector3();
40051    var radians;
40052
40053    return function setDirection( dir ) {
40054
40055        // dir is assumed to be normalized
40056
40057        if ( dir.y > 0.99999 ) {
40058
40059            this.quaternion.set( 0, 0, 0, 1 );
40060
40061        } else if ( dir.y < - 0.99999 ) {
40062
40063            this.quaternion.set( 1, 0, 0, 0 );
40064
40065        } else {
40066
40067            axis.set( dir.z, 0, - dir.x ).normalize();
40068
40069            radians = Math.acos( dir.y );
40070
40071            this.quaternion.setFromAxisAngle( axis, radians );
40072
40073        }
40074
40075    };
40076
40077}() );
40078
40079THREE.ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {
40080
40081    if ( headLength === undefined ) headLength = 0.2 * length;
40082    if ( headWidth === undefined ) headWidth = 0.2 * headLength;
40083
40084    this.line.scale.set( 1, Math.max( 0, length - headLength ), 1 );
40085    this.line.updateMatrix();
40086
40087    this.cone.scale.set( headWidth, headLength, headWidth );
40088    this.cone.position.y = length;
40089    this.cone.updateMatrix();
40090
40091};
40092
40093THREE.ArrowHelper.prototype.setColor = function ( color ) {
40094
40095    this.line.material.color.set( color );
40096    this.cone.material.color.set( color );
40097
40098};
40099
40100// File:src/extras/helpers/BoxHelper.js
40101
40102/**
40103 * @author mrdoob / http://mrdoob.com/
40104 */
40105
40106THREE.BoxHelper = function ( object ) {
40107
40108    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 ] );
40109    var positions = new Float32Array( 8 * 3 );
40110
40111    var geometry = new THREE.BufferGeometry();
40112    geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
40113    geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
40114
40115    THREE.LineSegments.call( this, geometry, new THREE.LineBasicMaterial( { color: 0xffff00 } ) );
40116
40117    if ( object !== undefined ) {
40118
40119        this.update( object );
40120
40121    }
40122
40123};
40124
40125THREE.BoxHelper.prototype = Object.create( THREE.LineSegments.prototype );
40126THREE.BoxHelper.prototype.constructor = THREE.BoxHelper;
40127
40128THREE.BoxHelper.prototype.update = ( function () {
40129
40130    var box = new THREE.Box3();
40131
40132    return function ( object ) {
40133
40134        if ( object instanceof THREE.Box3 ) {
40135
40136            box.copy( object );
40137
40138        } else {
40139
40140            box.setFromObject( object );
40141
40142        }
40143
40144        if ( box.isEmpty() ) return;
40145
40146        var min = box.min;
40147        var max = box.max;
40148
40149        /*
40150         5____4
40151         1/___0/|
40152         | 6__|_7
40153         2/___3/
40154
40155         0: max.x, max.y, max.z
40156         1: min.x, max.y, max.z
40157         2: min.x, min.y, max.z
40158         3: max.x, min.y, max.z
40159         4: max.x, max.y, min.z
40160         5: min.x, max.y, min.z
40161         6: min.x, min.y, min.z
40162         7: max.x, min.y, min.z
40163         */
40164
40165        var position = this.geometry.attributes.position;
40166        var array = position.array;
40167
40168        array[  0 ] = max.x; array[  1 ] = max.y; array[  2 ] = max.z;
40169        array[  3 ] = min.x; array[  4 ] = max.y; array[  5 ] = max.z;
40170        array[  6 ] = min.x; array[  7 ] = min.y; array[  8 ] = max.z;
40171        array[  9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
40172        array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
40173        array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
40174        array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
40175        array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
40176
40177        position.needsUpdate = true;
40178
40179        this.geometry.computeBoundingSphere();
40180
40181    };
40182
40183} )();
40184
40185// File:src/extras/helpers/BoundingBoxHelper.js
40186
40187/**
40188 * @author WestLangley / http://github.com/WestLangley
40189 */
40190
40191// a helper to show the world-axis-aligned bounding box for an object
40192
40193THREE.BoundingBoxHelper = function ( object, hex ) {
40194
40195    var color = ( hex !== undefined ) ? hex : 0x888888;
40196
40197    this.object = object;
40198
40199    this.box = new THREE.Box3();
40200
40201    THREE.Mesh.call( this, new THREE.BoxGeometry( 1, 1, 1 ), new THREE.MeshBasicMaterial( { color: color, wireframe: true } ) );
40202
40203};
40204
40205THREE.BoundingBoxHelper.prototype = Object.create( THREE.Mesh.prototype );
40206THREE.BoundingBoxHelper.prototype.constructor = THREE.BoundingBoxHelper;
40207
40208THREE.BoundingBoxHelper.prototype.update = function () {
40209
40210    this.box.setFromObject( this.object );
40211
40212    this.box.size( this.scale );
40213
40214    this.box.center( this.position );
40215
40216};
40217
40218// File:src/extras/helpers/CameraHelper.js
40219
40220/**
40221 * @author alteredq / http://alteredqualia.com/
40222 *
40223 *	- shows frustum, line of sight and up of the camera
40224 *	- suitable for fast updates
40225 * 	- based on frustum visualization in lightgl.js shadowmap example
40226 *		http://evanw.github.com/lightgl.js/tests/shadowmap.html
40227 */
40228
40229THREE.CameraHelper = function ( camera ) {
40230
40231    var geometry = new THREE.Geometry();
40232    var material = new THREE.LineBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors } );
40233
40234    var pointMap = {};
40235
40236    // colors
40237
40238    var hexFrustum = 0xffaa00;
40239    var hexCone = 0xff0000;
40240    var hexUp = 0x00aaff;
40241    var hexTarget = 0xffffff;
40242    var hexCross = 0x333333;
40243
40244    // near
40245
40246    addLine( "n1", "n2", hexFrustum );
40247    addLine( "n2", "n4", hexFrustum );
40248    addLine( "n4", "n3", hexFrustum );
40249    addLine( "n3", "n1", hexFrustum );
40250
40251    // far
40252
40253    addLine( "f1", "f2", hexFrustum );
40254    addLine( "f2", "f4", hexFrustum );
40255    addLine( "f4", "f3", hexFrustum );
40256    addLine( "f3", "f1", hexFrustum );
40257
40258    // sides
40259
40260    addLine( "n1", "f1", hexFrustum );
40261    addLine( "n2", "f2", hexFrustum );
40262    addLine( "n3", "f3", hexFrustum );
40263    addLine( "n4", "f4", hexFrustum );
40264
40265    // cone
40266
40267    addLine( "p", "n1", hexCone );
40268    addLine( "p", "n2", hexCone );
40269    addLine( "p", "n3", hexCone );
40270    addLine( "p", "n4", hexCone );
40271
40272    // up
40273
40274    addLine( "u1", "u2", hexUp );
40275    addLine( "u2", "u3", hexUp );
40276    addLine( "u3", "u1", hexUp );
40277
40278    // target
40279
40280    addLine( "c", "t", hexTarget );
40281    addLine( "p", "c", hexCross );
40282
40283    // cross
40284
40285    addLine( "cn1", "cn2", hexCross );
40286    addLine( "cn3", "cn4", hexCross );
40287
40288    addLine( "cf1", "cf2", hexCross );
40289    addLine( "cf3", "cf4", hexCross );
40290
40291    function addLine( a, b, hex ) {
40292
40293        addPoint( a, hex );
40294        addPoint( b, hex );
40295
40296    }
40297
40298    function addPoint( id, hex ) {
40299
40300        geometry.vertices.push( new THREE.Vector3() );
40301        geometry.colors.push( new THREE.Color( hex ) );
40302
40303        if ( pointMap[ id ] === undefined ) {
40304
40305            pointMap[ id ] = [];
40306
40307        }
40308
40309        pointMap[ id ].push( geometry.vertices.length - 1 );
40310
40311    }
40312
40313    THREE.LineSegments.call( this, geometry, material );
40314
40315    this.camera = camera;
40316    this.camera.updateProjectionMatrix();
40317
40318    this.matrix = camera.matrixWorld;
40319    this.matrixAutoUpdate = false;
40320
40321    this.pointMap = pointMap;
40322
40323    this.update();
40324
40325};
40326
40327THREE.CameraHelper.prototype = Object.create( THREE.LineSegments.prototype );
40328THREE.CameraHelper.prototype.constructor = THREE.CameraHelper;
40329
40330THREE.CameraHelper.prototype.update = function () {
40331
40332    var geometry, pointMap;
40333
40334    var vector = new THREE.Vector3();
40335    var camera = new THREE.Camera();
40336
40337    function setPoint( point, x, y, z ) {
40338
40339        vector.set( x, y, z ).unproject( camera );
40340
40341        var points = pointMap[ point ];
40342
40343        if ( points !== undefined ) {
40344
40345            for ( var i = 0, il = points.length; i < il; i ++ ) {
40346
40347                geometry.vertices[ points[ i ] ].copy( vector );
40348
40349            }
40350
40351        }
40352
40353    }
40354
40355    return function () {
40356
40357        geometry = this.geometry;
40358        pointMap = this.pointMap;
40359
40360        var w = 1, h = 1;
40361
40362        // we need just camera projection matrix
40363        // world matrix must be identity
40364
40365        camera.projectionMatrix.copy( this.camera.projectionMatrix );
40366
40367        // center / target
40368
40369        setPoint( "c", 0, 0, - 1 );
40370        setPoint( "t", 0, 0,  1 );
40371
40372        // near
40373
40374        setPoint( "n1", - w, - h, - 1 );
40375        setPoint( "n2",   w, - h, - 1 );
40376        setPoint( "n3", - w,   h, - 1 );
40377        setPoint( "n4",   w,   h, - 1 );
40378
40379        // far
40380
40381        setPoint( "f1", - w, - h, 1 );
40382        setPoint( "f2",   w, - h, 1 );
40383        setPoint( "f3", - w,   h, 1 );
40384        setPoint( "f4",   w,   h, 1 );
40385
40386        // up
40387
40388        setPoint( "u1",   w * 0.7, h * 1.1, - 1 );
40389        setPoint( "u2", - w * 0.7, h * 1.1, - 1 );
40390        setPoint( "u3",         0, h * 2,   - 1 );
40391
40392        // cross
40393
40394        setPoint( "cf1", - w,   0, 1 );
40395        setPoint( "cf2",   w,   0, 1 );
40396        setPoint( "cf3",   0, - h, 1 );
40397        setPoint( "cf4",   0,   h, 1 );
40398
40399        setPoint( "cn1", - w,   0, - 1 );
40400        setPoint( "cn2",   w,   0, - 1 );
40401        setPoint( "cn3",   0, - h, - 1 );
40402        setPoint( "cn4",   0,   h, - 1 );
40403
40404        geometry.verticesNeedUpdate = true;
40405
40406    };
40407
40408}();
40409
40410// File:src/extras/helpers/DirectionalLightHelper.js
40411
40412/**
40413 * @author alteredq / http://alteredqualia.com/
40414 * @author mrdoob / http://mrdoob.com/
40415 * @author WestLangley / http://github.com/WestLangley
40416 */
40417
40418THREE.DirectionalLightHelper = function ( light, size ) {
40419
40420    THREE.Object3D.call( this );
40421
40422    this.light = light;
40423    this.light.updateMatrixWorld();
40424
40425    this.matrix = light.matrixWorld;
40426    this.matrixAutoUpdate = false;
40427
40428    size = size || 1;
40429
40430    var geometry = new THREE.Geometry();
40431    geometry.vertices.push(
40432        new THREE.Vector3( - size,   size, 0 ),
40433        new THREE.Vector3(   size,   size, 0 ),
40434        new THREE.Vector3(   size, - size, 0 ),
40435        new THREE.Vector3( - size, - size, 0 ),
40436        new THREE.Vector3( - size,   size, 0 )
40437    );
40438
40439    var material = new THREE.LineBasicMaterial( { fog: false } );
40440    material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
40441
40442    this.lightPlane = new THREE.Line( geometry, material );
40443    this.add( this.lightPlane );
40444
40445    geometry = new THREE.Geometry();
40446    geometry.vertices.push(
40447        new THREE.Vector3(),
40448        new THREE.Vector3()
40449    );
40450
40451    material = new THREE.LineBasicMaterial( { fog: false } );
40452    material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
40453
40454    this.targetLine = new THREE.Line( geometry, material );
40455    this.add( this.targetLine );
40456
40457    this.update();
40458
40459};
40460
40461THREE.DirectionalLightHelper.prototype = Object.create( THREE.Object3D.prototype );
40462THREE.DirectionalLightHelper.prototype.constructor = THREE.DirectionalLightHelper;
40463
40464THREE.DirectionalLightHelper.prototype.dispose = function () {
40465
40466    this.lightPlane.geometry.dispose();
40467    this.lightPlane.material.dispose();
40468    this.targetLine.geometry.dispose();
40469    this.targetLine.material.dispose();
40470
40471};
40472
40473THREE.DirectionalLightHelper.prototype.update = function () {
40474
40475    var v1 = new THREE.Vector3();
40476    var v2 = new THREE.Vector3();
40477    var v3 = new THREE.Vector3();
40478
40479    return function () {
40480
40481        v1.setFromMatrixPosition( this.light.matrixWorld );
40482        v2.setFromMatrixPosition( this.light.target.matrixWorld );
40483        v3.subVectors( v2, v1 );
40484
40485        this.lightPlane.lookAt( v3 );
40486        this.lightPlane.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
40487
40488        this.targetLine.geometry.vertices[ 1 ].copy( v3 );
40489        this.targetLine.geometry.verticesNeedUpdate = true;
40490        this.targetLine.material.color.copy( this.lightPlane.material.color );
40491
40492    };
40493
40494}();
40495
40496// File:src/extras/helpers/EdgesHelper.js
40497
40498/**
40499 * @author WestLangley / http://github.com/WestLangley
40500 * @param object THREE.Mesh whose geometry will be used
40501 * @param hex line color
40502 * @param thresholdAngle the minimum angle (in degrees),
40503 * between the face normals of adjacent faces,
40504 * that is required to render an edge. A value of 10 means
40505 * an edge is only rendered if the angle is at least 10 degrees.
40506 */
40507
40508THREE.EdgesHelper = function ( object, hex, thresholdAngle ) {
40509
40510    var color = ( hex !== undefined ) ? hex : 0xffffff;
40511
40512    THREE.LineSegments.call( this, new THREE.EdgesGeometry( object.geometry, thresholdAngle ), new THREE.LineBasicMaterial( { color: color } ) );
40513
40514    this.matrix = object.matrixWorld;
40515    this.matrixAutoUpdate = false;
40516
40517};
40518
40519THREE.EdgesHelper.prototype = Object.create( THREE.LineSegments.prototype );
40520THREE.EdgesHelper.prototype.constructor = THREE.EdgesHelper;
40521
40522// File:src/extras/helpers/FaceNormalsHelper.js
40523
40524/**
40525 * @author mrdoob / http://mrdoob.com/
40526 * @author WestLangley / http://github.com/WestLangley
40527 */
40528
40529THREE.FaceNormalsHelper = function ( object, size, hex, linewidth ) {
40530
40531    // FaceNormalsHelper only supports THREE.Geometry
40532
40533    this.object = object;
40534
40535    this.size = ( size !== undefined ) ? size : 1;
40536
40537    var color = ( hex !== undefined ) ? hex : 0xffff00;
40538
40539    var width = ( linewidth !== undefined ) ? linewidth : 1;
40540
40541    //
40542
40543    var nNormals = 0;
40544
40545    var objGeometry = this.object.geometry;
40546
40547    if ( objGeometry instanceof THREE.Geometry ) {
40548
40549        nNormals = objGeometry.faces.length;
40550
40551    } else {
40552
40553        console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' );
40554
40555    }
40556
40557    //
40558
40559    var geometry = new THREE.BufferGeometry();
40560
40561    var positions = new THREE.Float32Attribute( nNormals * 2 * 3, 3 );
40562
40563    geometry.addAttribute( 'position', positions );
40564
40565    THREE.LineSegments.call( this, geometry, new THREE.LineBasicMaterial( { color: color, linewidth: width } ) );
40566
40567    //
40568
40569    this.matrixAutoUpdate = false;
40570    this.update();
40571
40572};
40573
40574THREE.FaceNormalsHelper.prototype = Object.create( THREE.LineSegments.prototype );
40575THREE.FaceNormalsHelper.prototype.constructor = THREE.FaceNormalsHelper;
40576
40577THREE.FaceNormalsHelper.prototype.update = ( function () {
40578
40579    var v1 = new THREE.Vector3();
40580    var v2 = new THREE.Vector3();
40581    var normalMatrix = new THREE.Matrix3();
40582
40583    return function update() {
40584
40585        this.object.updateMatrixWorld( true );
40586
40587        normalMatrix.getNormalMatrix( this.object.matrixWorld );
40588
40589        var matrixWorld = this.object.matrixWorld;
40590
40591        var position = this.geometry.attributes.position;
40592
40593        //
40594
40595        var objGeometry = this.object.geometry;
40596
40597        var vertices = objGeometry.vertices;
40598
40599        var faces = objGeometry.faces;
40600
40601        var idx = 0;
40602
40603        for ( var i = 0, l = faces.length; i < l; i ++ ) {
40604
40605            var face = faces[ i ];
40606
40607            var normal = face.normal;
40608
40609            v1.copy( vertices[ face.a ] )
40610                .add( vertices[ face.b ] )
40611                .add( vertices[ face.c ] )
40612                .divideScalar( 3 )
40613                .applyMatrix4( matrixWorld );
40614
40615            v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
40616
40617            position.setXYZ( idx, v1.x, v1.y, v1.z );
40618
40619            idx = idx + 1;
40620
40621            position.setXYZ( idx, v2.x, v2.y, v2.z );
40622
40623            idx = idx + 1;
40624
40625        }
40626
40627        position.needsUpdate = true;
40628
40629        return this;
40630
40631    }
40632
40633}() );
40634
40635// File:src/extras/helpers/GridHelper.js
40636
40637/**
40638 * @author mrdoob / http://mrdoob.com/
40639 */
40640
40641THREE.GridHelper = function ( size, step ) {
40642
40643    var geometry = new THREE.Geometry();
40644    var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors } );
40645
40646    this.color1 = new THREE.Color( 0x444444 );
40647    this.color2 = new THREE.Color( 0x888888 );
40648
40649    for ( var i = - size; i <= size; i += step ) {
40650
40651        geometry.vertices.push(
40652            new THREE.Vector3( - size, 0, i ), new THREE.Vector3( size, 0, i ),
40653            new THREE.Vector3( i, 0, - size ), new THREE.Vector3( i, 0, size )
40654        );
40655
40656        var color = i === 0 ? this.color1 : this.color2;
40657
40658        geometry.colors.push( color, color, color, color );
40659
40660    }
40661
40662    THREE.LineSegments.call( this, geometry, material );
40663
40664};
40665
40666THREE.GridHelper.prototype = Object.create( THREE.LineSegments.prototype );
40667THREE.GridHelper.prototype.constructor = THREE.GridHelper;
40668
40669THREE.GridHelper.prototype.setColors = function( colorCenterLine, colorGrid ) {
40670
40671    this.color1.set( colorCenterLine );
40672    this.color2.set( colorGrid );
40673
40674    this.geometry.colorsNeedUpdate = true;
40675
40676};
40677
40678// File:src/extras/helpers/HemisphereLightHelper.js
40679
40680/**
40681 * @author alteredq / http://alteredqualia.com/
40682 * @author mrdoob / http://mrdoob.com/
40683 */
40684
40685THREE.HemisphereLightHelper = function ( light, sphereSize ) {
40686
40687    THREE.Object3D.call( this );
40688
40689    this.light = light;
40690    this.light.updateMatrixWorld();
40691
40692    this.matrix = light.matrixWorld;
40693    this.matrixAutoUpdate = false;
40694
40695    this.colors = [ new THREE.Color(), new THREE.Color() ];
40696
40697    var geometry = new THREE.SphereGeometry( sphereSize, 4, 2 );
40698    geometry.rotateX( - Math.PI / 2 );
40699
40700    for ( var i = 0, il = 8; i < il; i ++ ) {
40701
40702        geometry.faces[ i ].color = this.colors[ i < 4 ? 0 : 1 ];
40703
40704    }
40705
40706    var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, wireframe: true } );
40707
40708    this.lightSphere = new THREE.Mesh( geometry, material );
40709    this.add( this.lightSphere );
40710
40711    this.update();
40712
40713};
40714
40715THREE.HemisphereLightHelper.prototype = Object.create( THREE.Object3D.prototype );
40716THREE.HemisphereLightHelper.prototype.constructor = THREE.HemisphereLightHelper;
40717
40718THREE.HemisphereLightHelper.prototype.dispose = function () {
40719
40720    this.lightSphere.geometry.dispose();
40721    this.lightSphere.material.dispose();
40722
40723};
40724
40725THREE.HemisphereLightHelper.prototype.update = function () {
40726
40727    var vector = new THREE.Vector3();
40728
40729    return function () {
40730
40731        this.colors[ 0 ].copy( this.light.color ).multiplyScalar( this.light.intensity );
40732        this.colors[ 1 ].copy( this.light.groundColor ).multiplyScalar( this.light.intensity );
40733
40734        this.lightSphere.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() );
40735        this.lightSphere.geometry.colorsNeedUpdate = true;
40736
40737    }
40738
40739}();
40740
40741// File:src/extras/helpers/PointLightHelper.js
40742
40743/**
40744 * @author alteredq / http://alteredqualia.com/
40745 * @author mrdoob / http://mrdoob.com/
40746 */
40747
40748THREE.PointLightHelper = function ( light, sphereSize ) {
40749
40750    this.light = light;
40751    this.light.updateMatrixWorld();
40752
40753    var geometry = new THREE.SphereGeometry( sphereSize, 4, 2 );
40754    var material = new THREE.MeshBasicMaterial( { wireframe: true, fog: false } );
40755    material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
40756
40757    THREE.Mesh.call( this, geometry, material );
40758
40759    this.matrix = this.light.matrixWorld;
40760    this.matrixAutoUpdate = false;
40761
40762    /*
40763     var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
40764     var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
40765
40766     this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
40767     this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
40768
40769     var d = light.distance;
40770
40771     if ( d === 0.0 ) {
40772
40773     this.lightDistance.visible = false;
40774
40775     } else {
40776
40777     this.lightDistance.scale.set( d, d, d );
40778
40779     }
40780
40781     this.add( this.lightDistance );
40782     */
40783
40784};
40785
40786THREE.PointLightHelper.prototype = Object.create( THREE.Mesh.prototype );
40787THREE.PointLightHelper.prototype.constructor = THREE.PointLightHelper;
40788
40789THREE.PointLightHelper.prototype.dispose = function () {
40790
40791    this.geometry.dispose();
40792    this.material.dispose();
40793
40794};
40795
40796THREE.PointLightHelper.prototype.update = function () {
40797
40798    this.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
40799
40800    /*
40801     var d = this.light.distance;
40802
40803     if ( d === 0.0 ) {
40804
40805     this.lightDistance.visible = false;
40806
40807     } else {
40808
40809     this.lightDistance.visible = true;
40810     this.lightDistance.scale.set( d, d, d );
40811
40812     }
40813     */
40814
40815};
40816
40817// File:src/extras/helpers/SkeletonHelper.js
40818
40819/**
40820 * @author Sean Griffin / http://twitter.com/sgrif
40821 * @author Michael Guerrero / http://realitymeltdown.com
40822 * @author mrdoob / http://mrdoob.com/
40823 * @author ikerr / http://verold.com
40824 */
40825
40826THREE.SkeletonHelper = function ( object ) {
40827
40828    this.bones = this.getBoneList( object );
40829
40830    var geometry = new THREE.Geometry();
40831
40832    for ( var i = 0; i < this.bones.length; i ++ ) {
40833
40834        var bone = this.bones[ i ];
40835
40836        if ( bone.parent instanceof THREE.Bone ) {
40837
40838            geometry.vertices.push( new THREE.Vector3() );
40839            geometry.vertices.push( new THREE.Vector3() );
40840            geometry.colors.push( new THREE.Color( 0, 0, 1 ) );
40841            geometry.colors.push( new THREE.Color( 0, 1, 0 ) );
40842
40843        }
40844
40845    }
40846
40847    geometry.dynamic = true;
40848
40849    var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors, depthTest: false, depthWrite: false, transparent: true } );
40850
40851    THREE.LineSegments.call( this, geometry, material );
40852
40853    this.root = object;
40854
40855    this.matrix = object.matrixWorld;
40856    this.matrixAutoUpdate = false;
40857
40858    this.update();
40859
40860};
40861
40862
40863THREE.SkeletonHelper.prototype = Object.create( THREE.LineSegments.prototype );
40864THREE.SkeletonHelper.prototype.constructor = THREE.SkeletonHelper;
40865
40866THREE.SkeletonHelper.prototype.getBoneList = function( object ) {
40867
40868    var boneList = [];
40869
40870    if ( object instanceof THREE.Bone ) {
40871
40872        boneList.push( object );
40873
40874    }
40875
40876    for ( var i = 0; i < object.children.length; i ++ ) {
40877
40878        boneList.push.apply( boneList, this.getBoneList( object.children[ i ] ) );
40879
40880    }
40881
40882    return boneList;
40883
40884};
40885
40886THREE.SkeletonHelper.prototype.update = function () {
40887
40888    var geometry = this.geometry;
40889
40890    var matrixWorldInv = new THREE.Matrix4().getInverse( this.root.matrixWorld );
40891
40892    var boneMatrix = new THREE.Matrix4();
40893
40894    var j = 0;
40895
40896    for ( var i = 0; i < this.bones.length; i ++ ) {
40897
40898        var bone = this.bones[ i ];
40899
40900        if ( bone.parent instanceof THREE.Bone ) {
40901
40902            boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld );
40903            geometry.vertices[ j ].setFromMatrixPosition( boneMatrix );
40904
40905            boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld );
40906            geometry.vertices[ j + 1 ].setFromMatrixPosition( boneMatrix );
40907
40908            j += 2;
40909
40910        }
40911
40912    }
40913
40914    geometry.verticesNeedUpdate = true;
40915
40916    geometry.computeBoundingSphere();
40917
40918};
40919
40920// File:src/extras/helpers/SpotLightHelper.js
40921
40922/**
40923 * @author alteredq / http://alteredqualia.com/
40924 * @author mrdoob / http://mrdoob.com/
40925 * @author WestLangley / http://github.com/WestLangley
40926 */
40927
40928THREE.SpotLightHelper = function ( light ) {
40929
40930    THREE.Object3D.call( this );
40931
40932    this.light = light;
40933    this.light.updateMatrixWorld();
40934
40935    this.matrix = light.matrixWorld;
40936    this.matrixAutoUpdate = false;
40937
40938    var geometry = new THREE.BufferGeometry();
40939
40940    var positions = [
40941        0, 0, 0,   0,   0,   1,
40942        0, 0, 0,   1,   0,   1,
40943        0, 0, 0, - 1,   0,   1,
40944        0, 0, 0,   0,   1,   1,
40945        0, 0, 0,   0, - 1,   1
40946    ];
40947
40948    for ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
40949
40950        var p1 = ( i / l ) * Math.PI * 2;
40951        var p2 = ( j / l ) * Math.PI * 2;
40952
40953        positions.push(
40954            Math.cos( p1 ), Math.sin( p1 ), 1,
40955            Math.cos( p2 ), Math.sin( p2 ), 1
40956        );
40957
40958    }
40959
40960    geometry.addAttribute( 'position', new THREE.Float32Attribute( positions, 3 ) );
40961
40962    var material = new THREE.LineBasicMaterial( { fog: false } );
40963
40964    this.cone = new THREE.LineSegments( geometry, material );
40965    this.add( this.cone );
40966
40967    this.update();
40968
40969};
40970
40971THREE.SpotLightHelper.prototype = Object.create( THREE.Object3D.prototype );
40972THREE.SpotLightHelper.prototype.constructor = THREE.SpotLightHelper;
40973
40974THREE.SpotLightHelper.prototype.dispose = function () {
40975
40976    this.cone.geometry.dispose();
40977    this.cone.material.dispose();
40978
40979};
40980
40981THREE.SpotLightHelper.prototype.update = function () {
40982
40983    var vector = new THREE.Vector3();
40984    var vector2 = new THREE.Vector3();
40985
40986    return function () {
40987
40988        var coneLength = this.light.distance ? this.light.distance : 1000;
40989        var coneWidth = coneLength * Math.tan( this.light.angle );
40990
40991        this.cone.scale.set( coneWidth, coneWidth, coneLength );
40992
40993        vector.setFromMatrixPosition( this.light.matrixWorld );
40994        vector2.setFromMatrixPosition( this.light.target.matrixWorld );
40995
40996        this.cone.lookAt( vector2.sub( vector ) );
40997
40998        this.cone.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );
40999
41000    };
41001
41002}();
41003
41004// File:src/extras/helpers/VertexNormalsHelper.js
41005
41006/**
41007 * @author mrdoob / http://mrdoob.com/
41008 * @author WestLangley / http://github.com/WestLangley
41009 */
41010
41011THREE.VertexNormalsHelper = function ( object, size, hex, linewidth ) {
41012
41013    this.object = object;
41014
41015    this.size = ( size !== undefined ) ? size : 1;
41016
41017    var color = ( hex !== undefined ) ? hex : 0xff0000;
41018
41019    var width = ( linewidth !== undefined ) ? linewidth : 1;
41020
41021    //
41022
41023    var nNormals = 0;
41024
41025    var objGeometry = this.object.geometry;
41026
41027    if ( objGeometry instanceof THREE.Geometry ) {
41028
41029        nNormals = objGeometry.faces.length * 3;
41030
41031    } else if ( objGeometry instanceof THREE.BufferGeometry ) {
41032
41033        nNormals = objGeometry.attributes.normal.count
41034
41035    }
41036
41037    //
41038
41039    var geometry = new THREE.BufferGeometry();
41040
41041    var positions = new THREE.Float32Attribute( nNormals * 2 * 3, 3 );
41042
41043    geometry.addAttribute( 'position', positions );
41044
41045    THREE.LineSegments.call( this, geometry, new THREE.LineBasicMaterial( { color: color, linewidth: width } ) );
41046
41047    //
41048
41049    this.matrixAutoUpdate = false;
41050
41051    this.update();
41052
41053};
41054
41055THREE.VertexNormalsHelper.prototype = Object.create( THREE.LineSegments.prototype );
41056THREE.VertexNormalsHelper.prototype.constructor = THREE.VertexNormalsHelper;
41057
41058THREE.VertexNormalsHelper.prototype.update = ( function () {
41059
41060    var v1 = new THREE.Vector3();
41061    var v2 = new THREE.Vector3();
41062    var normalMatrix = new THREE.Matrix3();
41063
41064    return function update() {
41065
41066        var keys = [ 'a', 'b', 'c' ];
41067
41068        this.object.updateMatrixWorld( true );
41069
41070        normalMatrix.getNormalMatrix( this.object.matrixWorld );
41071
41072        var matrixWorld = this.object.matrixWorld;
41073
41074        var position = this.geometry.attributes.position;
41075
41076        //
41077
41078        var objGeometry = this.object.geometry;
41079
41080        if ( objGeometry instanceof THREE.Geometry ) {
41081
41082            var vertices = objGeometry.vertices;
41083
41084            var faces = objGeometry.faces;
41085
41086            var idx = 0;
41087
41088            for ( var i = 0, l = faces.length; i < l; i ++ ) {
41089
41090                var face = faces[ i ];
41091
41092                for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
41093
41094                    var vertex = vertices[ face[ keys[ j ] ] ];
41095
41096                    var normal = face.vertexNormals[ j ];
41097
41098                    v1.copy( vertex ).applyMatrix4( matrixWorld );
41099
41100                    v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
41101
41102                    position.setXYZ( idx, v1.x, v1.y, v1.z );
41103
41104                    idx = idx + 1;
41105
41106                    position.setXYZ( idx, v2.x, v2.y, v2.z );
41107
41108                    idx = idx + 1;
41109
41110                }
41111
41112            }
41113
41114        } else if ( objGeometry instanceof THREE.BufferGeometry ) {
41115
41116            var objPos = objGeometry.attributes.position;
41117
41118            var objNorm = objGeometry.attributes.normal;
41119
41120            var idx = 0;
41121
41122            // for simplicity, ignore index and drawcalls, and render every normal
41123
41124            for ( var j = 0, jl = objPos.count; j < jl; j ++ ) {
41125
41126                v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );
41127
41128                v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) );
41129
41130                v2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 );
41131
41132                position.setXYZ( idx, v1.x, v1.y, v1.z );
41133
41134                idx = idx + 1;
41135
41136                position.setXYZ( idx, v2.x, v2.y, v2.z );
41137
41138                idx = idx + 1;
41139
41140            }
41141
41142        }
41143
41144        position.needsUpdate = true;
41145
41146        return this;
41147
41148    }
41149
41150}() );
41151
41152// File:src/extras/helpers/WireframeHelper.js
41153
41154/**
41155 * @author mrdoob / http://mrdoob.com/
41156 */
41157
41158THREE.WireframeHelper = function ( object, hex ) {
41159
41160    var color = ( hex !== undefined ) ? hex : 0xffffff;
41161
41162    THREE.LineSegments.call( this, new THREE.WireframeGeometry( object.geometry ), new THREE.LineBasicMaterial( { color: color } ) );
41163
41164    this.matrix = object.matrixWorld;
41165    this.matrixAutoUpdate = false;
41166
41167};
41168
41169THREE.WireframeHelper.prototype = Object.create( THREE.LineSegments.prototype );
41170THREE.WireframeHelper.prototype.constructor = THREE.WireframeHelper;
41171
41172// File:src/extras/objects/ImmediateRenderObject.js
41173
41174/**
41175 * @author alteredq / http://alteredqualia.com/
41176 */
41177
41178THREE.ImmediateRenderObject = function ( material ) {
41179
41180    THREE.Object3D.call( this );
41181
41182    this.material = material;
41183    this.render = function ( renderCallback ) {};
41184
41185};
41186
41187THREE.ImmediateRenderObject.prototype = Object.create( THREE.Object3D.prototype );
41188THREE.ImmediateRenderObject.prototype.constructor = THREE.ImmediateRenderObject;
41189
41190// File:src/extras/objects/MorphBlendMesh.js
41191
41192/**
41193 * @author alteredq / http://alteredqualia.com/
41194 */
41195
41196THREE.MorphBlendMesh = function( geometry, material ) {
41197
41198    THREE.Mesh.call( this, geometry, material );
41199
41200    this.animationsMap = {};
41201    this.animationsList = [];
41202
41203    // prepare default animation
41204    // (all frames played together in 1 second)
41205
41206    var numFrames = this.geometry.morphTargets.length;
41207
41208    var name = "__default";
41209
41210    var startFrame = 0;
41211    var endFrame = numFrames - 1;
41212
41213    var fps = numFrames / 1;
41214
41215    this.createAnimation( name, startFrame, endFrame, fps );
41216    this.setAnimationWeight( name, 1 );
41217
41218};
41219
41220THREE.MorphBlendMesh.prototype = Object.create( THREE.Mesh.prototype );
41221THREE.MorphBlendMesh.prototype.constructor = THREE.MorphBlendMesh;
41222
41223THREE.MorphBlendMesh.prototype.createAnimation = function ( name, start, end, fps ) {
41224
41225    var animation = {
41226
41227        start: start,
41228        end: end,
41229
41230        length: end - start + 1,
41231
41232        fps: fps,
41233        duration: ( end - start ) / fps,
41234
41235        lastFrame: 0,
41236        currentFrame: 0,
41237
41238        active: false,
41239
41240        time: 0,
41241        direction: 1,
41242        weight: 1,
41243
41244        directionBackwards: false,
41245        mirroredLoop: false
41246
41247    };
41248
41249    this.animationsMap[ name ] = animation;
41250    this.animationsList.push( animation );
41251
41252};
41253
41254THREE.MorphBlendMesh.prototype.autoCreateAnimations = function ( fps ) {
41255
41256    var pattern = /([a-z]+)_?(\d+)/i;
41257
41258    var firstAnimation, frameRanges = {};
41259
41260    var geometry = this.geometry;
41261
41262    for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) {
41263
41264        var morph = geometry.morphTargets[ i ];
41265        var chunks = morph.name.match( pattern );
41266
41267        if ( chunks && chunks.length > 1 ) {
41268
41269            var name = chunks[ 1 ];
41270
41271            if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: - Infinity };
41272
41273            var range = frameRanges[ name ];
41274
41275            if ( i < range.start ) range.start = i;
41276            if ( i > range.end ) range.end = i;
41277
41278            if ( ! firstAnimation ) firstAnimation = name;
41279
41280        }
41281
41282    }
41283
41284    for ( var name in frameRanges ) {
41285
41286        var range = frameRanges[ name ];
41287        this.createAnimation( name, range.start, range.end, fps );
41288
41289    }
41290
41291    this.firstAnimation = firstAnimation;
41292
41293};
41294
41295THREE.MorphBlendMesh.prototype.setAnimationDirectionForward = function ( name ) {
41296
41297    var animation = this.animationsMap[ name ];
41298
41299    if ( animation ) {
41300
41301        animation.direction = 1;
41302        animation.directionBackwards = false;
41303
41304    }
41305
41306};
41307
41308THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward = function ( name ) {
41309
41310    var animation = this.animationsMap[ name ];
41311
41312    if ( animation ) {
41313
41314        animation.direction = - 1;
41315        animation.directionBackwards = true;
41316
41317    }
41318
41319};
41320
41321THREE.MorphBlendMesh.prototype.setAnimationFPS = function ( name, fps ) {
41322
41323    var animation = this.animationsMap[ name ];
41324
41325    if ( animation ) {
41326
41327        animation.fps = fps;
41328        animation.duration = ( animation.end - animation.start ) / animation.fps;
41329
41330    }
41331
41332};
41333
41334THREE.MorphBlendMesh.prototype.setAnimationDuration = function ( name, duration ) {
41335
41336    var animation = this.animationsMap[ name ];
41337
41338    if ( animation ) {
41339
41340        animation.duration = duration;
41341        animation.fps = ( animation.end - animation.start ) / animation.duration;
41342
41343    }
41344
41345};
41346
41347THREE.MorphBlendMesh.prototype.setAnimationWeight = function ( name, weight ) {
41348
41349    var animation = this.animationsMap[ name ];
41350
41351    if ( animation ) {
41352
41353        animation.weight = weight;
41354
41355    }
41356
41357};
41358
41359THREE.MorphBlendMesh.prototype.setAnimationTime = function ( name, time ) {
41360
41361    var animation = this.animationsMap[ name ];
41362
41363    if ( animation ) {
41364
41365        animation.time = time;
41366
41367    }
41368
41369};
41370
41371THREE.MorphBlendMesh.prototype.getAnimationTime = function ( name ) {
41372
41373    var time = 0;
41374
41375    var animation = this.animationsMap[ name ];
41376
41377    if ( animation ) {
41378
41379        time = animation.time;
41380
41381    }
41382
41383    return time;
41384
41385};
41386
41387THREE.MorphBlendMesh.prototype.getAnimationDuration = function ( name ) {
41388
41389    var duration = - 1;
41390
41391    var animation = this.animationsMap[ name ];
41392
41393    if ( animation ) {
41394
41395        duration = animation.duration;
41396
41397    }
41398
41399    return duration;
41400
41401};
41402
41403THREE.MorphBlendMesh.prototype.playAnimation = function ( name ) {
41404
41405    var animation = this.animationsMap[ name ];
41406
41407    if ( animation ) {
41408
41409        animation.time = 0;
41410        animation.active = true;
41411
41412    } else {
41413
41414        console.warn( "THREE.MorphBlendMesh: animation[" + name + "] undefined in .playAnimation()" );
41415
41416    }
41417
41418};
41419
41420THREE.MorphBlendMesh.prototype.stopAnimation = function ( name ) {
41421
41422    var animation = this.animationsMap[ name ];
41423
41424    if ( animation ) {
41425
41426        animation.active = false;
41427
41428    }
41429
41430};
41431
41432THREE.MorphBlendMesh.prototype.update = function ( delta ) {
41433
41434    for ( var i = 0, il = this.animationsList.length; i < il; i ++ ) {
41435
41436        var animation = this.animationsList[ i ];
41437
41438        if ( ! animation.active ) continue;
41439
41440        var frameTime = animation.duration / animation.length;
41441
41442        animation.time += animation.direction * delta;
41443
41444        if ( animation.mirroredLoop ) {
41445
41446            if ( animation.time > animation.duration || animation.time < 0 ) {
41447
41448                animation.direction *= - 1;
41449
41450                if ( animation.time > animation.duration ) {
41451
41452                    animation.time = animation.duration;
41453                    animation.directionBackwards = true;
41454
41455                }
41456
41457                if ( animation.time < 0 ) {
41458
41459                    animation.time = 0;
41460                    animation.directionBackwards = false;
41461
41462                }
41463
41464            }
41465
41466        } else {
41467
41468            animation.time = animation.time % animation.duration;
41469
41470            if ( animation.time < 0 ) animation.time += animation.duration;
41471
41472        }
41473
41474        var keyframe = animation.start + THREE.Math.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 );
41475        var weight = animation.weight;
41476
41477        if ( keyframe !== animation.currentFrame ) {
41478
41479            this.morphTargetInfluences[ animation.lastFrame ] = 0;
41480            this.morphTargetInfluences[ animation.currentFrame ] = 1 * weight;
41481
41482            this.morphTargetInfluences[ keyframe ] = 0;
41483
41484            animation.lastFrame = animation.currentFrame;
41485            animation.currentFrame = keyframe;
41486
41487        }
41488
41489        var mix = ( animation.time % frameTime ) / frameTime;
41490
41491        if ( animation.directionBackwards ) mix = 1 - mix;
41492
41493        if ( animation.currentFrame !== animation.lastFrame ) {
41494
41495            this.morphTargetInfluences[ animation.currentFrame ] = mix * weight;
41496            this.morphTargetInfluences[ animation.lastFrame ] = ( 1 - mix ) * weight;
41497
41498        } else {
41499
41500            this.morphTargetInfluences[ animation.currentFrame ] = weight;
41501
41502        }
41503
41504    }
41505
41506};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.