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.