1/** 2 * @license 3 * Copyright 2010-2023 Three.js Authors 4 * SPDX-License-Identifier: MIT 5 */ 6const REVISION = '150'; 7const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; 8const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; 9const CullFaceNone = 0; 10const CullFaceBack = 1; 11const CullFaceFront = 2; 12const CullFaceFrontBack = 3; 13const BasicShadowMap = 0; 14const PCFShadowMap = 1; 15const PCFSoftShadowMap = 2; 16const VSMShadowMap = 3; 17const FrontSide = 0; 18const BackSide = 1; 19const DoubleSide = 2; 20const TwoPassDoubleSide = 2; // r149 21const NoBlending = 0; 22const NormalBlending = 1; 23const AdditiveBlending = 2; 24const SubtractiveBlending = 3; 25const MultiplyBlending = 4; 26const CustomBlending = 5; 27const AddEquation = 100; 28const SubtractEquation = 101; 29const ReverseSubtractEquation = 102; 30const MinEquation = 103; 31const MaxEquation = 104; 32const ZeroFactor = 200; 33const OneFactor = 201; 34const SrcColorFactor = 202; 35const OneMinusSrcColorFactor = 203; 36const SrcAlphaFactor = 204; 37const OneMinusSrcAlphaFactor = 205; 38const DstAlphaFactor = 206; 39const OneMinusDstAlphaFactor = 207; 40const DstColorFactor = 208; 41const OneMinusDstColorFactor = 209; 42const SrcAlphaSaturateFactor = 210; 43const NeverDepth = 0; 44const AlwaysDepth = 1; 45const LessDepth = 2; 46const LessEqualDepth = 3; 47const EqualDepth = 4; 48const GreaterEqualDepth = 5; 49const GreaterDepth = 6; 50const NotEqualDepth = 7; 51const MultiplyOperation = 0; 52const MixOperation = 1; 53const AddOperation = 2; 54const NoToneMapping = 0; 55const LinearToneMapping = 1; 56const ReinhardToneMapping = 2; 57const CineonToneMapping = 3; 58const ACESFilmicToneMapping = 4; 59const CustomToneMapping = 5; 60 61const UVMapping = 300; 62const CubeReflectionMapping = 301; 63const CubeRefractionMapping = 302; 64const EquirectangularReflectionMapping = 303; 65const EquirectangularRefractionMapping = 304; 66const CubeUVReflectionMapping = 306; 67const RepeatWrapping = 1000; 68const ClampToEdgeWrapping = 1001; 69const MirroredRepeatWrapping = 1002; 70const NearestFilter = 1003; 71const NearestMipmapNearestFilter = 1004; 72const NearestMipMapNearestFilter = 1004; 73const NearestMipmapLinearFilter = 1005; 74const NearestMipMapLinearFilter = 1005; 75const LinearFilter = 1006; 76const LinearMipmapNearestFilter = 1007; 77const LinearMipMapNearestFilter = 1007; 78const LinearMipmapLinearFilter = 1008; 79const LinearMipMapLinearFilter = 1008; 80const UnsignedByteType = 1009; 81const ByteType = 1010; 82const ShortType = 1011; 83const UnsignedShortType = 1012; 84const IntType = 1013; 85const UnsignedIntType = 1014; 86const FloatType = 1015; 87const HalfFloatType = 1016; 88const UnsignedShort4444Type = 1017; 89const UnsignedShort5551Type = 1018; 90const UnsignedInt248Type = 1020; 91const AlphaFormat = 1021; 92const RGBAFormat = 1023; 93const LuminanceFormat = 1024; 94const LuminanceAlphaFormat = 1025; 95const DepthFormat = 1026; 96const DepthStencilFormat = 1027; 97const RedFormat = 1028; 98const RedIntegerFormat = 1029; 99const RGFormat = 1030; 100const RGIntegerFormat = 1031; 101const RGBAIntegerFormat = 1033; 102 103const RGB_S3TC_DXT1_Format = 33776; 104const RGBA_S3TC_DXT1_Format = 33777; 105const RGBA_S3TC_DXT3_Format = 33778; 106const RGBA_S3TC_DXT5_Format = 33779; 107const RGB_PVRTC_4BPPV1_Format = 35840; 108const RGB_PVRTC_2BPPV1_Format = 35841; 109const RGBA_PVRTC_4BPPV1_Format = 35842; 110const RGBA_PVRTC_2BPPV1_Format = 35843; 111const RGB_ETC1_Format = 36196; 112const RGB_ETC2_Format = 37492; 113const RGBA_ETC2_EAC_Format = 37496; 114const RGBA_ASTC_4x4_Format = 37808; 115const RGBA_ASTC_5x4_Format = 37809; 116const RGBA_ASTC_5x5_Format = 37810; 117const RGBA_ASTC_6x5_Format = 37811; 118const RGBA_ASTC_6x6_Format = 37812; 119const RGBA_ASTC_8x5_Format = 37813; 120const RGBA_ASTC_8x6_Format = 37814; 121const RGBA_ASTC_8x8_Format = 37815; 122const RGBA_ASTC_10x5_Format = 37816; 123const RGBA_ASTC_10x6_Format = 37817; 124const RGBA_ASTC_10x8_Format = 37818; 125const RGBA_ASTC_10x10_Format = 37819; 126const RGBA_ASTC_12x10_Format = 37820; 127const RGBA_ASTC_12x12_Format = 37821; 128const RGBA_BPTC_Format = 36492; 129const RED_RGTC1_Format = 36283; 130const SIGNED_RED_RGTC1_Format = 36284; 131const RED_GREEN_RGTC2_Format = 36285; 132const SIGNED_RED_GREEN_RGTC2_Format = 36286; 133const LoopOnce = 2200; 134const LoopRepeat = 2201; 135const LoopPingPong = 2202; 136const InterpolateDiscrete = 2300; 137const InterpolateLinear = 2301; 138const InterpolateSmooth = 2302; 139const ZeroCurvatureEnding = 2400; 140const ZeroSlopeEnding = 2401; 141const WrapAroundEnding = 2402; 142const NormalAnimationBlendMode = 2500; 143const AdditiveAnimationBlendMode = 2501; 144const TrianglesDrawMode = 0; 145const TriangleStripDrawMode = 1; 146const TriangleFanDrawMode = 2; 147const LinearEncoding = 3000; 148const sRGBEncoding = 3001; 149const BasicDepthPacking = 3200; 150const RGBADepthPacking = 3201; 151const TangentSpaceNormalMap = 0; 152const ObjectSpaceNormalMap = 1; 153 154// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU n
vendor: 6,946 bytes, lines 154-403
154ames where available. 155const NoColorSpace = ''; 156const SRGBColorSpace = 'srgb'; 157const LinearSRGBColorSpace = 'srgb-linear'; 158const DisplayP3ColorSpace = 'display-p3'; 159 160const ZeroStencilOp = 0; 161const KeepStencilOp = 7680; 162const ReplaceStencilOp = 7681; 163const IncrementStencilOp = 7682; 164const DecrementStencilOp = 7683; 165const IncrementWrapStencilOp = 34055; 166const DecrementWrapStencilOp = 34056; 167const InvertStencilOp = 5386; 168 169const NeverStencilFunc = 512; 170const LessStencilFunc = 513; 171const EqualStencilFunc = 514; 172const LessEqualStencilFunc = 515; 173const GreaterStencilFunc = 516; 174const NotEqualStencilFunc = 517; 175const GreaterEqualStencilFunc = 518; 176const AlwaysStencilFunc = 519; 177 178const StaticDrawUsage = 35044; 179const DynamicDrawUsage = 35048; 180const StreamDrawUsage = 35040; 181const StaticReadUsage = 35045; 182const DynamicReadUsage = 35049; 183const StreamReadUsage = 35041; 184const StaticCopyUsage = 35046; 185const DynamicCopyUsage = 35050; 186const StreamCopyUsage = 35042; 187 188const GLSL1 = '100'; 189const GLSL3 = '300 es'; 190 191const _SRGBAFormat = 1035; // fallback for WebGL 1 192 193/** 194 * https://github.com/mrdoob/eventdispatcher.js/ 195 */ 196 197class EventDispatcher { 198 199 addEventListener( type, listener ) { 200 201 if ( this._listeners === undefined ) this._listeners = {}; 202 203 const listeners = this._listeners; 204 205 if ( listeners[ type ] === undefined ) { 206 207 listeners[ type ] = []; 208 209 } 210 211 if ( listeners[ type ].indexOf( listener ) === - 1 ) { 212 213 listeners[ type ].push( listener ); 214 215 } 216 217 } 218 219 hasEventListener( type, listener ) { 220 221 if ( this._listeners === undefined ) return false; 222 223 const listeners = this._listeners; 224 225 return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1; 226 227 } 228 229 removeEventListener( type, listener ) { 230 231 if ( this._listeners === undefined ) return; 232 233 const listeners = this._listeners; 234 const listenerArray = listeners[ type ]; 235 236 if ( listenerArray !== undefined ) { 237 238 const index = listenerArray.indexOf( listener ); 239 240 if ( index !== - 1 ) { 241 242 listenerArray.splice( index, 1 ); 243 244 } 245 246 } 247 248 } 249 250 dispatchEvent( event ) { 251 252 if ( this._listeners === undefined ) return; 253 254 const listeners = this._listeners; 255 const listenerArray = listeners[ event.type ]; 256 257 if ( listenerArray !== undefined ) { 258 259 event.target = this; 260 261 // Make a copy, in case listeners are removed while iterating. 262 const array = listenerArray.slice( 0 ); 263 264 for ( let i = 0, l = array.length; i < l; i ++ ) { 265 266 array[ i ].call( this, event ); 267 268 } 269 270 event.target = null; 271 272 } 273 274 } 275 276} 277 278const _lut = [ '00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf', 'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df', 'e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef', 'f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff' ]; 279 280let _seed = 1234567; 281 282 283const DEG2RAD = Math.PI / 180; 284const RAD2DEG = 180 / Math.PI; 285 286// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 287function generateUUID() { 288 289 const d0 = Math.random() * 0xffffffff | 0; 290 const d1 = Math.random() * 0xffffffff | 0; 291 const d2 = Math.random() * 0xffffffff | 0; 292 const d3 = Math.random() * 0xffffffff | 0; 293 const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' + 294 _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' + 295 _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] + 296 _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ]; 297 298 // .toLowerCase() here flattens concatenated strings to save heap memory space. 299 return uuid.toLowerCase(); 300 301} 302 303function clamp( value, min, max ) { 304 305 return Math.max( min, Math.min( max, value ) ); 306 307} 308 309// compute euclidean modulo of m % n 310// https://en.wikipedia.org/wiki/Modulo_operation 311function euclideanModulo( n, m ) { 312 313 return ( ( n % m ) + m ) % m; 314 315} 316 317// Linear mapping from range <a1, a2> to range <b1, b2> 318function mapLinear( x, a1, a2, b1, b2 ) { 319 320 return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); 321 322} 323 324// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/ 325function inverseLerp( x, y, value ) { 326 327 if ( x !== y ) { 328 329 return ( value - x ) / ( y - x ); 330 331 } else { 332 333 return 0; 334 335 } 336 337} 338 339// https://en.wikipedia.org/wiki/Linear_interpolation 340function lerp( x, y, t ) { 341 342 return ( 1 - t ) * x + t * y; 343 344} 345 346// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ 347function damp( x, y, lambda, dt ) { 348 349 return lerp( x, y, 1 - Math.exp( - lambda * dt ) ); 350 351} 352 353// https://www.desmos.com/calculator/vcsjnyz7x4 354function pingpong( x, length = 1 ) { 355 356 return length - Math.abs( euclideanModulo( x, length * 2 ) - length ); 357 358} 359 360// http://en.wikipedia.org/wiki/Smoothstep 361function smoothstep( x, min, max ) { 362 363 if ( x <= min ) return 0; 364 if ( x >= max ) return 1; 365 366 x = ( x - min ) / ( max - min ); 367 368 return x * x * ( 3 - 2 * x ); 369 370} 371 372function smootherstep( x, min, max ) { 373 374 if ( x <= min ) return 0; 375 if ( x >= max ) return 1; 376 377 x = ( x - min ) / ( max - min ); 378 379 return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); 380 381} 382 383// Random integer from <low, high> interval 384function randInt( low, high ) { 385 386 return low + Math.floor( Math.random() * ( high - low + 1 ) ); 387 388} 389 390// Random float from <low, high> interval 391function randFloat( low, high ) { 392 393 return low + Math.random() * ( high - low ); 394 395} 396 397// Random float from <-range/2, range/2> interval 398function randFloatSpread( range ) { 399 400 return range * ( 0.5 - Math.random() ); 401 402} 403
vendor: 8,542 bytes, lines 404-1028
404// Deterministic pseudo-random float in the interval [ 0, 1 ] 405function seededRandom( s ) { 406 407 if ( s !== undefined ) _seed = s; 408 409 // Mulberry32 generator 410 411 let t = _seed += 0x6D2B79F5; 412 413 t = Math.imul( t ^ t >>> 15, t | 1 ); 414 415 t ^= t + Math.imul( t ^ t >>> 7, t | 61 ); 416 417 return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296; 418 419} 420 421function degToRad( degrees ) { 422 423 return degrees * DEG2RAD; 424 425} 426 427function radToDeg( radians ) { 428 429 return radians * RAD2DEG; 430 431} 432 433function isPowerOfTwo( value ) { 434 435 return ( value & ( value - 1 ) ) === 0 && value !== 0; 436 437} 438 439function ceilPowerOfTwo( value ) { 440 441 return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); 442 443} 444 445function floorPowerOfTwo( value ) { 446 447 return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); 448 449} 450 451function setQuaternionFromProperEuler( q, a, b, c, order ) { 452 453 // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles 454 455 // rotations are applied to the axes in the order specified by 'order' 456 // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c' 457 // angles are in radians 458 459 const cos = Math.cos; 460 const sin = Math.sin; 461 462 const c2 = cos( b / 2 ); 463 const s2 = sin( b / 2 ); 464 465 const c13 = cos( ( a + c ) / 2 ); 466 const s13 = sin( ( a + c ) / 2 ); 467 468 const c1_3 = cos( ( a - c ) / 2 ); 469 const s1_3 = sin( ( a - c ) / 2 ); 470 471 const c3_1 = cos( ( c - a ) / 2 ); 472 const s3_1 = sin( ( c - a ) / 2 ); 473 474 switch ( order ) { 475 476 case 'XYX': 477 q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 ); 478 break; 479 480 case 'YZY': 481 q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 ); 482 break; 483 484 case 'ZXZ': 485 q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 ); 486 break; 487 488 case 'XZX': 489 q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 ); 490 break; 491 492 case 'YXY': 493 q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 ); 494 break; 495 496 case 'ZYZ': 497 q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 ); 498 break; 499 500 default: 501 console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order ); 502 503 } 504 505} 506 507function denormalize( value, array ) { 508 509 switch ( array.constructor ) { 510 511 case Float32Array: 512 513 return value; 514 515 case Uint16Array: 516 517 return value / 65535.0; 518 519 case Uint8Array: 520 521 return value / 255.0; 522 523 case Int16Array: 524 525 return Math.max( value / 32767.0, - 1.0 ); 526 527 case Int8Array: 528 529 return Math.max( value / 127.0, - 1.0 ); 530 531 default: 532 533 throw new Error( 'Invalid component type.' ); 534 535 } 536 537} 538 539function normalize( value, array ) { 540 541 switch ( array.constructor ) { 542 543 case Float32Array: 544 545 return value; 546 547 case Uint16Array: 548 549 return Math.round( value * 65535.0 ); 550 551 case Uint8Array: 552 553 return Math.round( value * 255.0 ); 554 555 case Int16Array: 556 557 return Math.round( value * 32767.0 ); 558 559 case Int8Array: 560 561 return Math.round( value * 127.0 ); 562 563 default: 564 565 throw new Error( 'Invalid component type.' ); 566 567 } 568 569} 570 571const MathUtils = { 572 DEG2RAD: DEG2RAD, 573 RAD2DEG: RAD2DEG, 574 generateUUID: generateUUID, 575 clamp: clamp, 576 euclideanModulo: euclideanModulo, 577 mapLinear: mapLinear, 578 inverseLerp: inverseLerp, 579 lerp: lerp, 580 damp: damp, 581 pingpong: pingpong, 582 smoothstep: smoothstep, 583 smootherstep: smootherstep, 584 randInt: randInt, 585 randFloat: randFloat, 586 randFloatSpread: randFloatSpread, 587 seededRandom: seededRandom, 588 degToRad: degToRad, 589 radToDeg: radToDeg, 590 isPowerOfTwo: isPowerOfTwo, 591 ceilPowerOfTwo: ceilPowerOfTwo, 592 floorPowerOfTwo: floorPowerOfTwo, 593 setQuaternionFromProperEuler: setQuaternionFromProperEuler, 594 normalize: normalize, 595 denormalize: denormalize 596}; 597 598class Vector2 { 599 600 constructor( x = 0, y = 0 ) { 601 602 Vector2.prototype.isVector2 = true; 603 604 this.x = x; 605 this.y = y; 606 607 } 608 609 get width() { 610 611 return this.x; 612 613 } 614 615 set width( value ) { 616 617 this.x = value; 618 619 } 620 621 get height() { 622 623 return this.y; 624 625 } 626 627 set height( value ) { 628 629 this.y = value; 630 631 } 632 633 set( x, y ) { 634 635 this.x = x; 636 this.y = y; 637 638 return this; 639 640 } 641 642 setScalar( scalar ) { 643 644 this.x = scalar; 645 this.y = scalar; 646 647 return this; 648 649 } 650 651 setX( x ) { 652 653 this.x = x; 654 655 return this; 656 657 } 658 659 setY( y ) { 660 661 this.y = y; 662 663 return this; 664 665 } 666 667 setComponent( index, value ) { 668 669 switch ( index ) { 670 671 case 0: this.x = value; break; 672 case 1: this.y = value; break; 673 default: throw new Error( 'index is out of range: ' + index ); 674 675 } 676 677 return this; 678 679 } 680 681 getComponent( index ) { 682 683 switch ( index ) { 684 685 case 0: return this.x; 686 case 1: return this.y; 687 default: throw new Error( 'index is out of range: ' + index ); 688 689 } 690 691 } 692 693 clone() { 694 695 return new this.constructor( this.x, this.y ); 696 697 } 698 699 copy( v ) { 700 701 this.x = v.x; 702 this.y = v.y; 703 704 return this; 705 706 } 707 708 add( v ) { 709 710 this.x += v.x; 711 this.y += v.y; 712 713 return this; 714 715 } 716 717 addScalar( s ) { 718 719 this.x += s; 720 this.y += s; 721 722 return this; 723 724 } 725 726 addVectors( a, b ) { 727 728 this.x = a.x + b.x; 729 this.y = a.y + b.y; 730 731 return this; 732 733 } 734 735 addScaledVector( v, s ) { 736 737 this.x += v.x * s; 738 this.y += v.y * s; 739 740 return this; 741 742 } 743 744 sub( v ) { 745 746 this.x -= v.x; 747 this.y -= v.y; 748 749 return this; 750 751 } 752 753 subScalar( s ) { 754 755 this.x -= s; 756 this.y -= s; 757 758 return this; 759 760 } 761 762 subVectors( a, b ) { 763 764 this.x = a.x - b.x; 765 this.y = a.y - b.y; 766 767 return this; 768 769 } 770 771 multiply( v ) { 772 773 this.x *= v.x; 774 this.y *= v.y; 775 776 return this; 777 778 } 779 780 multiplyScalar( scalar ) { 781 782 this.x *= scalar; 783 this.y *= scalar; 784 785 return this; 786 787 } 788 789 divide( v ) { 790 791 this.x /= v.x; 792 this.y /= v.y; 793 794 return this; 795 796 } 797 798 divideScalar( scalar ) { 799 800 return this.multiplyScalar( 1 / scalar ); 801 802 } 803 804 applyMatrix3( m ) { 805 806 const x = this.x, y = this.y; 807 const e = m.elements; 808 809 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ]; 810 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ]; 811 812 return this; 813 814 } 815 816 min( v ) { 817 818 this.x = Math.min( this.x, v.x ); 819 this.y = Math.min( this.y, v.y ); 820 821 return this; 822 823 } 824 825 max( v ) { 826 827 this.x = Math.max( this.x, v.x ); 828 this.y = Math.max( this.y, v.y ); 829 830 return this; 831 832 } 833 834 clamp( min, max ) { 835 836 // assumes min < max, componentwise 837 838 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 839 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 840 841 return this; 842 843 } 844 845 clampScalar( minVal, maxVal ) { 846 847 this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); 848 this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); 849 850 return this; 851 852 } 853 854 clampLength( min, max ) { 855 856 const length = this.length(); 857 858 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 859 860 } 861 862 floor() { 863 864 this.x = Math.floor( this.x ); 865 this.y = Math.floor( this.y ); 866 867 return this; 868 869 } 870 871 ceil() { 872 873 this.x = Math.ceil( this.x ); 874 this.y = Math.ceil( this.y ); 875 876 return this; 877 878 } 879 880 round() { 881 882 this.x = Math.round( this.x ); 883 this.y = Math.round( this.y ); 884 885 return this; 886 887 } 888 889 roundToZero() { 890 891 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); 892 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); 893 894 return this; 895 896 } 897 898 negate() { 899 900 this.x = - this.x; 901 this.y = - this.y; 902 903 return this; 904 905 } 906 907 dot( v ) { 908 909 return this.x * v.x + this.y * v.y; 910 911 } 912 913 cross( v ) { 914 915 return this.x * v.y - this.y * v.x; 916 917 } 918 919 lengthSq() { 920 921 return this.x * this.x + this.y * this.y; 922 923 } 924 925 length() { 926 927 return Math.sqrt( this.x * this.x + this.y * this.y ); 928 929 } 930 931 manhattanLength() { 932 933 return Math.abs( this.x ) + Math.abs( this.y ); 934 935 } 936 937 normalize() { 938 939 return this.divideScalar( this.length() || 1 ); 940 941 } 942 943 angle() { 944 945 // computes the angle in radians with respect to the positive x-axis 946 947 const angle = Math.atan2( - this.y, - this.x ) + Math.PI; 948 949 return angle; 950 951 } 952 953 distanceTo( v ) { 954 955 return Math.sqrt( this.distanceToSquared( v ) ); 956 957 } 958 959 distanceToSquared( v ) { 960 961 const dx = this.x - v.x, dy = this.y - v.y; 962 return dx * dx + dy * dy; 963 964 } 965 966 manhattanDistanceTo( v ) { 967 968 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ); 969 970 } 971 972 setLength( length ) { 973 974 return this.normalize().multiplyScalar( length ); 975 976 } 977 978 lerp( v, alpha ) { 979 980 this.x += ( v.x - this.x ) * alpha; 981 this.y += ( v.y - this.y ) * alpha; 982 983 return this; 984 985 } 986 987 lerpVectors( v1, v2, alpha ) { 988 989 this.x = v1.x + ( v2.x - v1.x ) * alpha; 990 this.y = v1.y + ( v2.y - v1.y ) * alpha; 991 992 return this; 993 994 } 995 996 equals( v ) { 997 998 return ( ( v.x === this.x ) && ( v.y === this.y ) ); 999 1000 } 1001 1002 fromArray( array, offset = 0 ) { 1003 1004 this.x = array[ offset ]; 1005 this.y = array[ offset + 1 ]; 1006 1007 return this; 1008 1009 } 1010 1011 toArray( array = [], offset = 0 ) { 1012 1013 array[ offset ] = this.x; 1014 array[ offset + 1 ] = this.y; 1015 1016 return array; 1017 1018 } 1019 1020 fromBufferAttribute( attribute, index ) { 1021 1022 this.x = attribute.getX( index ); 1023 this.y = attribute.getY( index ); 1024 1025 return this; 1026 1027 } 1028
vendor: 4,496 bytes, lines 1029-1284
1029 rotateAround( center, angle ) { 1030 1031 const c = Math.cos( angle ), s = Math.sin( angle ); 1032 1033 const x = this.x - center.x; 1034 const y = this.y - center.y; 1035 1036 this.x = x * c - y * s + center.x; 1037 this.y = x * s + y * c + center.y; 1038 1039 return this; 1040 1041 } 1042 1043 random() { 1044 1045 this.x = Math.random(); 1046 this.y = Math.random(); 1047 1048 return this; 1049 1050 } 1051 1052 *[ Symbol.iterator ]() { 1053 1054 yield this.x; 1055 yield this.y; 1056 1057 } 1058 1059} 1060 1061class Matrix3 { 1062 1063 constructor() { 1064 1065 Matrix3.prototype.isMatrix3 = true; 1066 1067 this.elements = [ 1068 1069 1, 0, 0, 1070 0, 1, 0, 1071 0, 0, 1 1072 1073 ]; 1074 1075 } 1076 1077 set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { 1078 1079 const te = this.elements; 1080 1081 te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31; 1082 te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32; 1083 te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33; 1084 1085 return this; 1086 1087 } 1088 1089 identity() { 1090 1091 this.set( 1092 1093 1, 0, 0, 1094 0, 1, 0, 1095 0, 0, 1 1096 1097 ); 1098 1099 return this; 1100 1101 } 1102 1103 copy( m ) { 1104 1105 const te = this.elements; 1106 const me = m.elements; 1107 1108 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; 1109 te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; 1110 te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ]; 1111 1112 return this; 1113 1114 } 1115 1116 extractBasis( xAxis, yAxis, zAxis ) { 1117 1118 xAxis.setFromMatrix3Column( this, 0 ); 1119 yAxis.setFromMatrix3Column( this, 1 ); 1120 zAxis.setFromMatrix3Column( this, 2 ); 1121 1122 return this; 1123 1124 } 1125 1126 setFromMatrix4( m ) { 1127 1128 const me = m.elements; 1129 1130 this.set( 1131 1132 me[ 0 ], me[ 4 ], me[ 8 ], 1133 me[ 1 ], me[ 5 ], me[ 9 ], 1134 me[ 2 ], me[ 6 ], me[ 10 ] 1135 1136 ); 1137 1138 return this; 1139 1140 } 1141 1142 multiply( m ) { 1143 1144 return this.multiplyMatrices( this, m ); 1145 1146 } 1147 1148 premultiply( m ) { 1149 1150 return this.multiplyMatrices( m, this ); 1151 1152 } 1153 1154 multiplyMatrices( a, b ) { 1155 1156 const ae = a.elements; 1157 const be = b.elements; 1158 const te = this.elements; 1159 1160 const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ]; 1161 const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ]; 1162 const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ]; 1163 1164 const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ]; 1165 const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ]; 1166 const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ]; 1167 1168 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; 1169 te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; 1170 te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; 1171 1172 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; 1173 te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; 1174 te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; 1175 1176 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31; 1177 te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32; 1178 te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33; 1179 1180 return this; 1181 1182 } 1183 1184 multiplyScalar( s ) { 1185 1186 const te = this.elements; 1187 1188 te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s; 1189 te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s; 1190 te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s; 1191 1192 return this; 1193 1194 } 1195 1196 determinant() { 1197 1198 const te = this.elements; 1199 1200 const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], 1201 d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], 1202 g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; 1203 1204 return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; 1205 1206 } 1207 1208 invert() { 1209 1210 const te = this.elements, 1211 1212 n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], 1213 n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ], 1214 n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ], 1215 1216 t11 = n33 * n22 - n32 * n23, 1217 t12 = n32 * n13 - n33 * n12, 1218 t13 = n23 * n12 - n22 * n13, 1219 1220 det = n11 * t11 + n21 * t12 + n31 * t13; 1221 1222 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); 1223 1224 const detInv = 1 / det; 1225 1226 te[ 0 ] = t11 * detInv; 1227 te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; 1228 te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; 1229 1230 te[ 3 ] = t12 * detInv; 1231 te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; 1232 te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; 1233 1234 te[ 6 ] = t13 * detInv; 1235 te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; 1236 te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; 1237 1238 return this; 1239 1240 } 1241 1242 transpose() { 1243 1244 let tmp; 1245 const m = this.elements; 1246 1247 tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp; 1248 tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp; 1249 tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp; 1250 1251 return this; 1252 1253 } 1254 1255 getNormalMatrix( matrix4 ) { 1256 1257 return this.setFromMatrix4( matrix4 ).invert().transpose(); 1258 1259 } 1260 1261 transposeIntoArray( r ) { 1262 1263 const m = this.elements; 1264 1265 r[ 0 ] = m[ 0 ]; 1266 r[ 1 ] = m[ 3 ]; 1267 r[ 2 ] = m[ 6 ]; 1268 r[ 3 ] = m[ 1 ]; 1269 r[ 4 ] = m[ 4 ]; 1270 r[ 5 ] = m[ 7 ]; 1271 r[ 6 ] = m[ 2 ]; 1272 r[ 7 ] = m[ 5 ]; 1273 r[ 8 ] = m[ 8 ]; 1274 1275 return this; 1276 1277 } 1278 1279 setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) { 1280 1281 const c = Math.cos( rotation ); 1282 const s = Math.sin( rotation ); 1283 1284 this.set(
vendor: 16,384 bytes, lines 1285-2286
1285 sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, 1286 - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, 1287 0, 0, 1 1288 ); 1289 1290 return this; 1291 1292 } 1293 1294 // 1295 1296 scale( sx, sy ) { 1297 1298 this.premultiply( _m3.makeScale( sx, sy ) ); 1299 1300 return this; 1301 1302 } 1303 1304 rotate( theta ) { 1305 1306 this.premultiply( _m3.makeRotation( - theta ) ); 1307 1308 return this; 1309 1310 } 1311 1312 translate( tx, ty ) { 1313 1314 this.premultiply( _m3.makeTranslation( tx, ty ) ); 1315 1316 return this; 1317 1318 } 1319 1320 // for 2D Transforms 1321 1322 makeTranslation( x, y ) { 1323 1324 this.set( 1325 1326 1, 0, x, 1327 0, 1, y, 1328 0, 0, 1 1329 1330 ); 1331 1332 return this; 1333 1334 } 1335 1336 makeRotation( theta ) { 1337 1338 // counterclockwise 1339 1340 const c = Math.cos( theta ); 1341 const s = Math.sin( theta ); 1342 1343 this.set( 1344 1345 c, - s, 0, 1346 s, c, 0, 1347 0, 0, 1 1348 1349 ); 1350 1351 return this; 1352 1353 } 1354 1355 makeScale( x, y ) { 1356 1357 this.set( 1358 1359 x, 0, 0, 1360 0, y, 0, 1361 0, 0, 1 1362 1363 ); 1364 1365 return this; 1366 1367 } 1368 1369 // 1370 1371 equals( matrix ) { 1372 1373 const te = this.elements; 1374 const me = matrix.elements; 1375 1376 for ( let i = 0; i < 9; i ++ ) { 1377 1378 if ( te[ i ] !== me[ i ] ) return false; 1379 1380 } 1381 1382 return true; 1383 1384 } 1385 1386 fromArray( array, offset = 0 ) { 1387 1388 for ( let i = 0; i < 9; i ++ ) { 1389 1390 this.elements[ i ] = array[ i + offset ]; 1391 1392 } 1393 1394 return this; 1395 1396 } 1397 1398 toArray( array = [], offset = 0 ) { 1399 1400 const te = this.elements; 1401 1402 array[ offset ] = te[ 0 ]; 1403 array[ offset + 1 ] = te[ 1 ]; 1404 array[ offset + 2 ] = te[ 2 ]; 1405 1406 array[ offset + 3 ] = te[ 3 ]; 1407 array[ offset + 4 ] = te[ 4 ]; 1408 array[ offset + 5 ] = te[ 5 ]; 1409 1410 array[ offset + 6 ] = te[ 6 ]; 1411 array[ offset + 7 ] = te[ 7 ]; 1412 array[ offset + 8 ] = te[ 8 ]; 1413 1414 return array; 1415 1416 } 1417 1418 clone() { 1419 1420 return new this.constructor().fromArray( this.elements ); 1421 1422 } 1423 1424} 1425 1426const _m3 = /*@__PURE__*/ new Matrix3(); 1427 1428function arrayNeedsUint32( array ) { 1429 1430 // assumes larger values usually on last 1431 1432 for ( let i = array.length - 1; i >= 0; -- i ) { 1433 1434 if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 1435 1436 } 1437 1438 return false; 1439 1440} 1441 1442const TYPED_ARRAYS = { 1443 Int8Array: Int8Array, 1444 Uint8Array: Uint8Array, 1445 Uint8ClampedArray: Uint8ClampedArray, 1446 Int16Array: Int16Array, 1447 Uint16Array: Uint16Array, 1448 Int32Array: Int32Array, 1449 Uint32Array: Uint32Array, 1450 Float32Array: Float32Array, 1451 Float64Array: Float64Array 1452}; 1453 1454function getTypedArray( type, buffer ) { 1455 1456 return new TYPED_ARRAYS[ type ]( buffer ); 1457 1458} 1459 1460function createElementNS( name ) { 1461 1462 return document.createElementNS( 'http://www.w3.org/1999/xhtml', name ); 1463 1464} 1465 1466class Quaternion { 1467 1468 constructor( x = 0, y = 0, z = 0, w = 1 ) { 1469 1470 this.isQuaternion = true; 1471 1472 this._x = x; 1473 this._y = y; 1474 this._z = z; 1475 this._w = w; 1476 1477 } 1478 1479 static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { 1480 1481 // fuzz-free, array-based Quaternion SLERP operation 1482 1483 let x0 = src0[ srcOffset0 + 0 ], 1484 y0 = src0[ srcOffset0 + 1 ], 1485 z0 = src0[ srcOffset0 + 2 ], 1486 w0 = src0[ srcOffset0 + 3 ]; 1487 1488 const x1 = src1[ srcOffset1 + 0 ], 1489 y1 = src1[ srcOffset1 + 1 ], 1490 z1 = src1[ srcOffset1 + 2 ], 1491 w1 = src1[ srcOffset1 + 3 ]; 1492 1493 if ( t === 0 ) { 1494 1495 dst[ dstOffset + 0 ] = x0; 1496 dst[ dstOffset + 1 ] = y0; 1497 dst[ dstOffset + 2 ] = z0; 1498 dst[ dstOffset + 3 ] = w0; 1499 return; 1500 1501 } 1502 1503 if ( t === 1 ) { 1504 1505 dst[ dstOffset + 0 ] = x1; 1506 dst[ dstOffset + 1 ] = y1; 1507 dst[ dstOffset + 2 ] = z1; 1508 dst[ dstOffset + 3 ] = w1; 1509 return; 1510 1511 } 1512 1513 if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { 1514 1515 let s = 1 - t; 1516 const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, 1517 dir = ( cos >= 0 ? 1 : - 1 ), 1518 sqrSin = 1 - cos * cos; 1519 1520 // Skip the Slerp for tiny steps to avoid numeric problems: 1521 if ( sqrSin > Number.EPSILON ) { 1522 1523 const sin = Math.sqrt( sqrSin ), 1524 len = Math.atan2( sin, cos * dir ); 1525 1526 s = Math.sin( s * len ) / sin; 1527 t = Math.sin( t * len ) / sin; 1528 1529 } 1530 1531 const tDir = t * dir; 1532 1533 x0 = x0 * s + x1 * tDir; 1534 y0 = y0 * s + y1 * tDir; 1535 z0 = z0 * s + z1 * tDir; 1536 w0 = w0 * s + w1 * tDir; 1537 1538 // Normalize in case we just did a lerp: 1539 if ( s === 1 - t ) { 1540 1541 const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); 1542 1543 x0 *= f; 1544 y0 *= f; 1545 z0 *= f; 1546 w0 *= f; 1547 1548 } 1549 1550 } 1551 1552 dst[ dstOffset ] = x0; 1553 dst[ dstOffset + 1 ] = y0; 1554 dst[ dstOffset + 2 ] = z0; 1555 dst[ dstOffset + 3 ] = w0; 1556 1557 } 1558 1559 static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { 1560 1561 const x0 = src0[ srcOffset0 ]; 1562 const y0 = src0[ srcOffset0 + 1 ]; 1563 const z0 = src0[ srcOffset0 + 2 ]; 1564 const w0 = src0[ srcOffset0 + 3 ]; 1565 1566 const x1 = src1[ srcOffset1 ]; 1567 const y1 = src1[ srcOffset1 + 1 ]; 1568 const z1 = src1[ srcOffset1 + 2 ]; 1569 const w1 = src1[ srcOffset1 + 3 ]; 1570 1571 dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; 1572 dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; 1573 dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; 1574 dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; 1575 1576 return dst; 1577 1578 } 1579 1580 get x() { 1581 1582 return this._x; 1583 1584 } 1585 1586 set x( value ) { 1587 1588 this._x = value; 1589 this._onChangeCallback(); 1590 1591 } 1592 1593 get y() { 1594 1595 return this._y; 1596 1597 } 1598 1599 set y( value ) { 1600 1601 this._y = value; 1602 this._onChangeCallback(); 1603 1604 } 1605 1606 get z() { 1607 1608 return this._z; 1609 1610 } 1611 1612 set z( value ) { 1613 1614 this._z = value; 1615 this._onChangeCallback(); 1616 1617 } 1618 1619 get w() { 1620 1621 return this._w; 1622 1623 } 1624 1625 set w( value ) { 1626 1627 this._w = value; 1628 this._onChangeCallback(); 1629 1630 } 1631 1632 set( x, y, z, w ) { 1633 1634 this._x = x; 1635 this._y = y; 1636 this._z = z; 1637 this._w = w; 1638 1639 this._onChangeCallback(); 1640 1641 return this; 1642 1643 } 1644 1645 clone() { 1646 1647 return new this.constructor( this._x, this._y, this._z, this._w ); 1648 1649 } 1650 1651 copy( quaternion ) { 1652 1653 this._x = quaternion.x; 1654 this._y = quaternion.y; 1655 this._z = quaternion.z; 1656 this._w = quaternion.w; 1657 1658 this._onChangeCallback(); 1659 1660 return this; 1661 1662 } 1663 1664 setFromEuler( euler, update ) { 1665 1666 const x = euler._x, y = euler._y, z = euler._z, order = euler._order; 1667 1668 // http://www.mathworks.com/matlabcentral/fileexchange/ 1669 // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ 1670 // content/SpinCalc.m 1671 1672 const cos = Math.cos; 1673 const sin = Math.sin; 1674 1675 const c1 = cos( x / 2 ); 1676 const c2 = cos( y / 2 ); 1677 const c3 = cos( z / 2 ); 1678 1679 const s1 = sin( x / 2 ); 1680 const s2 = sin( y / 2 ); 1681 const s3 = sin( z / 2 ); 1682 1683 switch ( order ) { 1684 1685 case 'XYZ': 1686 this._x = s1 * c2 * c3 + c1 * s2 * s3; 1687 this._y = c1 * s2 * c3 - s1 * c2 * s3; 1688 this._z = c1 * c2 * s3 + s1 * s2 * c3; 1689 this._w = c1 * c2 * c3 - s1 * s2 * s3; 1690 break; 1691 1692 case 'YXZ': 1693 this._x = s1 * c2 * c3 + c1 * s2 * s3; 1694 this._y = c1 * s2 * c3 - s1 * c2 * s3; 1695 this._z = c1 * c2 * s3 - s1 * s2 * c3; 1696 this._w = c1 * c2 * c3 + s1 * s2 * s3; 1697 break; 1698 1699 case 'ZXY': 1700 this._x = s1 * c2 * c3 - c1 * s2 * s3; 1701 this._y = c1 * s2 * c3 + s1 * c2 * s3; 1702 this._z = c1 * c2 * s3 + s1 * s2 * c3; 1703 this._w = c1 * c2 * c3 - s1 * s2 * s3; 1704 break; 1705 1706 case 'ZYX': 1707 this._x = s1 * c2 * c3 - c1 * s2 * s3; 1708 this._y = c1 * s2 * c3 + s1 * c2 * s3; 1709 this._z = c1 * c2 * s3 - s1 * s2 * c3; 1710 this._w = c1 * c2 * c3 + s1 * s2 * s3; 1711 break; 1712 1713 case 'YZX': 1714 this._x = s1 * c2 * c3 + c1 * s2 * s3; 1715 this._y = c1 * s2 * c3 + s1 * c2 * s3; 1716 this._z = c1 * c2 * s3 - s1 * s2 * c3; 1717 this._w = c1 * c2 * c3 - s1 * s2 * s3; 1718 break; 1719 1720 case 'XZY': 1721 this._x = s1 * c2 * c3 - c1 * s2 * s3; 1722 this._y = c1 * s2 * c3 - s1 * c2 * s3; 1723 this._z = c1 * c2 * s3 + s1 * s2 * c3; 1724 this._w = c1 * c2 * c3 + s1 * s2 * s3; 1725 break; 1726 1727 default: 1728 console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); 1729 1730 } 1731 1732 if ( update !== false ) this._onChangeCallback(); 1733 1734 return this; 1735 1736 } 1737 1738 setFromAxisAngle( axis, angle ) { 1739 1740 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm 1741 1742 // assumes axis is normalized 1743 1744 const halfAngle = angle / 2, s = Math.sin( halfAngle ); 1745 1746 this._x = axis.x * s; 1747 this._y = axis.y * s; 1748 this._z = axis.z * s; 1749 this._w = Math.cos( halfAngle ); 1750 1751 this._onChangeCallback(); 1752 1753 return this; 1754 1755 } 1756 1757 setFromRotationMatrix( m ) { 1758 1759 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm 1760 1761 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 1762 1763 const te = m.elements, 1764 1765 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], 1766 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], 1767 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], 1768 1769 trace = m11 + m22 + m33; 1770 1771 if ( trace > 0 ) { 1772 1773 const s = 0.5 / Math.sqrt( trace + 1.0 ); 1774 1775 this._w = 0.25 / s; 1776 this._x = ( m32 - m23 ) * s; 1777 this._y = ( m13 - m31 ) * s; 1778 this._z = ( m21 - m12 ) * s; 1779 1780 } else if ( m11 > m22 && m11 > m33 ) { 1781 1782 const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); 1783 1784 this._w = ( m32 - m23 ) / s; 1785 this._x = 0.25 * s; 1786 this._y = ( m12 + m21 ) / s; 1787 this._z = ( m13 + m31 ) / s; 1788 1789 } else if ( m22 > m33 ) { 1790 1791 const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); 1792 1793 this._w = ( m13 - m31 ) / s; 1794 this._x = ( m12 + m21 ) / s; 1795 this._y = 0.25 * s; 1796 this._z = ( m23 + m32 ) / s; 1797 1798 } else { 1799 1800 const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); 1801 1802 this._w = ( m21 - m12 ) / s; 1803 this._x = ( m13 + m31 ) / s; 1804 this._y = ( m23 + m32 ) / s; 1805 this._z = 0.25 * s; 1806 1807 } 1808 1809 this._onChangeCallback(); 1810 1811 return this; 1812 1813 } 1814 1815 setFromUnitVectors( vFrom, vTo ) { 1816 1817 // assumes direction vectors vFrom and vTo are normalized 1818 1819 let r = vFrom.dot( vTo ) + 1; 1820 1821 if ( r < Number.EPSILON ) { 1822 1823 // vFrom and vTo point in opposite directions 1824 1825 r = 0; 1826 1827 if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { 1828 1829 this._x = - vFrom.y; 1830 this._y = vFrom.x; 1831 this._z = 0; 1832 this._w = r; 1833 1834 } else { 1835 1836 this._x = 0; 1837 this._y = - vFrom.z; 1838 this._z = vFrom.y; 1839 this._w = r; 1840 1841 } 1842 1843 } else { 1844 1845 // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 1846 1847 this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; 1848 this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; 1849 this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; 1850 this._w = r; 1851 1852 } 1853 1854 return this.normalize(); 1855 1856 } 1857 1858 angleTo( q ) { 1859 1860 return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); 1861 1862 } 1863 1864 rotateTowards( q, step ) { 1865 1866 const angle = this.angleTo( q ); 1867 1868 if ( angle === 0 ) return this; 1869 1870 const t = Math.min( 1, step / angle ); 1871 1872 this.slerp( q, t ); 1873 1874 return this; 1875 1876 } 1877 1878 identity() { 1879 1880 return this.set( 0, 0, 0, 1 ); 1881 1882 } 1883 1884 invert() { 1885 1886 // quaternion is assumed to have unit length 1887 1888 return this.conjugate(); 1889 1890 } 1891 1892 conjugate() { 1893 1894 this._x *= - 1; 1895 this._y *= - 1; 1896 this._z *= - 1; 1897 1898 this._onChangeCallback(); 1899 1900 return this; 1901 1902 } 1903 1904 dot( v ) { 1905 1906 return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; 1907 1908 } 1909 1910 lengthSq() { 1911 1912 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; 1913 1914 } 1915 1916 length() { 1917 1918 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); 1919 1920 } 1921 1922 normalize() { 1923 1924 let l = this.length(); 1925 1926 if ( l === 0 ) { 1927 1928 this._x = 0; 1929 this._y = 0; 1930 this._z = 0; 1931 this._w = 1; 1932 1933 } else { 1934 1935 l = 1 / l; 1936 1937 this._x = this._x * l; 1938 this._y = this._y * l; 1939 this._z = this._z * l; 1940 this._w = this._w * l; 1941 1942 } 1943 1944 this._onChangeCallback(); 1945 1946 return this; 1947 1948 } 1949 1950 multiply( q ) { 1951 1952 return this.multiplyQuaternions( this, q ); 1953 1954 } 1955 1956 premultiply( q ) { 1957 1958 return this.multiplyQuaternions( q, this ); 1959 1960 } 1961 1962 multiplyQuaternions( a, b ) { 1963 1964 // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm 1965 1966 const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; 1967 const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; 1968 1969 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; 1970 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; 1971 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; 1972 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; 1973 1974 this._onChangeCallback(); 1975 1976 return this; 1977 1978 } 1979 1980 slerp( qb, t ) { 1981 1982 if ( t === 0 ) return this; 1983 if ( t === 1 ) return this.copy( qb ); 1984 1985 const x = this._x, y = this._y, z = this._z, w = this._w; 1986 1987 // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ 1988 1989 let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; 1990 1991 if ( cosHalfTheta < 0 ) { 1992 1993 this._w = - qb._w; 1994 this._x = - qb._x; 1995 this._y = - qb._y; 1996 this._z = - qb._z; 1997 1998 cosHalfTheta = - cosHalfTheta; 1999 2000 } else { 2001 2002 this.copy( qb ); 2003 2004 } 2005 2006 if ( cosHalfTheta >= 1.0 ) { 2007 2008 this._w = w; 2009 this._x = x; 2010 this._y = y; 2011 this._z = z; 2012 2013 return this; 2014 2015 } 2016 2017 const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; 2018 2019 if ( sqrSinHalfTheta <= Number.EPSILON ) { 2020 2021 const s = 1 - t; 2022 this._w = s * w + t * this._w; 2023 this._x = s * x + t * this._x; 2024 this._y = s * y + t * this._y; 2025 this._z = s * z + t * this._z; 2026 2027 this.normalize(); 2028 this._onChangeCallback(); 2029 2030 return this; 2031 2032 } 2033 2034 const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); 2035 const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); 2036 const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, 2037 ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; 2038 2039 this._w = ( w * ratioA + this._w * ratioB ); 2040 this._x = ( x * ratioA + this._x * ratioB ); 2041 this._y = ( y * ratioA + this._y * ratioB ); 2042 this._z = ( z * ratioA + this._z * ratioB ); 2043 2044 this._onChangeCallback(); 2045 2046 return this; 2047 2048 } 2049 2050 slerpQuaternions( qa, qb, t ) { 2051 2052 return this.copy( qa ).slerp( qb, t ); 2053 2054 } 2055 2056 random() { 2057 2058 // Derived from http://planning.cs.uiuc.edu/node198.html 2059 // Note, this source uses w, x, y, z ordering, 2060 // so we swap the order below. 2061 2062 const u1 = Math.random(); 2063 const sqrt1u1 = Math.sqrt( 1 - u1 ); 2064 const sqrtu1 = Math.sqrt( u1 ); 2065 2066 const u2 = 2 * Math.PI * Math.random(); 2067 2068 const u3 = 2 * Math.PI * Math.random(); 2069 2070 return this.set( 2071 sqrt1u1 * Math.cos( u2 ), 2072 sqrtu1 * Math.sin( u3 ), 2073 sqrtu1 * Math.cos( u3 ), 2074 sqrt1u1 * Math.sin( u2 ), 2075 ); 2076 2077 } 2078 2079 equals( quaternion ) { 2080 2081 return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); 2082 2083 } 2084 2085 fromArray( array, offset = 0 ) { 2086 2087 this._x = array[ offset ]; 2088 this._y = array[ offset + 1 ]; 2089 this._z = array[ offset + 2 ]; 2090 this._w = array[ offset + 3 ]; 2091 2092 this._onChangeCallback(); 2093 2094 return this; 2095 2096 } 2097 2098 toArray( array = [], offset = 0 ) { 2099 2100 array[ offset ] = this._x; 2101 array[ offset + 1 ] = this._y; 2102 array[ offset + 2 ] = this._z; 2103 array[ offset + 3 ] = this._w; 2104 2105 return array; 2106 2107 } 2108 2109 fromBufferAttribute( attribute, index ) { 2110 2111 this._x = attribute.getX( index ); 2112 this._y = attribute.getY( index ); 2113 this._z = attribute.getZ( index ); 2114 this._w = attribute.getW( index ); 2115 2116 return this; 2117 2118 } 2119 2120 _onChange( callback ) { 2121 2122 this._onChangeCallback = callback; 2123 2124 return this; 2125 2126 } 2127 2128 _onChangeCallback() {} 2129 2130 *[ Symbol.iterator ]() { 2131 2132 yield this._x; 2133 yield this._y; 2134 yield this._z; 2135 yield this._w; 2136 2137 } 2138 2139} 2140 2141class Vector3 { 2142 2143 constructor( x = 0, y = 0, z = 0 ) { 2144 2145 Vector3.prototype.isVector3 = true; 2146 2147 this.x = x; 2148 this.y = y; 2149 this.z = z; 2150 2151 } 2152 2153 set( x, y, z ) { 2154 2155 if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) 2156 2157 this.x = x; 2158 this.y = y; 2159 this.z = z; 2160 2161 return this; 2162 2163 } 2164 2165 setScalar( scalar ) { 2166 2167 this.x = scalar; 2168 this.y = scalar; 2169 this.z = scalar; 2170 2171 return this; 2172 2173 } 2174 2175 setX( x ) { 2176 2177 this.x = x; 2178 2179 return this; 2180 2181 } 2182 2183 setY( y ) { 2184 2185 this.y = y; 2186 2187 return this; 2188 2189 } 2190 2191 setZ( z ) { 2192 2193 this.z = z; 2194 2195 return this; 2196 2197 } 2198 2199 setComponent( index, value ) { 2200 2201 switch ( index ) { 2202 2203 case 0: this.x = value; break; 2204 case 1: this.y = value; break; 2205 case 2: this.z = value; break; 2206 default: throw new Error( 'index is out of range: ' + index ); 2207 2208 } 2209 2210 return this; 2211 2212 } 2213 2214 getComponent( index ) { 2215 2216 switch ( index ) { 2217 2218 case 0: return this.x; 2219 case 1: return this.y; 2220 case 2: return this.z; 2221 default: throw new Error( 'index is out of range: ' + index ); 2222 2223 } 2224 2225 } 2226 2227 clone() { 2228 2229 return new this.constructor( this.x, this.y, this.z ); 2230 2231 } 2232 2233 copy( v ) { 2234 2235 this.x = v.x; 2236 this.y = v.y; 2237 this.z = v.z; 2238 2239 return this; 2240 2241 } 2242 2243 add( v ) { 2244 2245 this.x += v.x; 2246 this.y += v.y; 2247 this.z += v.z; 2248 2249 return this; 2250 2251 } 2252 2253 addScalar( s ) { 2254 2255 this.x += s; 2256 this.y += s; 2257 this.z += s; 2258 2259 return this; 2260 2261 } 2262 2263 addVectors( a, b ) { 2264 2265 this.x = a.x + b.x; 2266 this.y = a.y + b.y; 2267 this.z = a.z + b.z; 2268 2269 return this; 2270 2271 } 2272 2273 addScaledVector( v, s ) { 2274 2275 this.x += v.x * s; 2276 this.y += v.y * s; 2277 this.z += v.z * s; 2278 2279 return this; 2280 2281 } 2282 2283 sub( v ) { 2284 2285 this.x -= v.x; 2286 t
vendor: 7,286 bytes, lines 2286-2720
2286his.y -= v.y; 2287 this.z -= v.z; 2288 2289 return this; 2290 2291 } 2292 2293 subScalar( s ) { 2294 2295 this.x -= s; 2296 this.y -= s; 2297 this.z -= s; 2298 2299 return this; 2300 2301 } 2302 2303 subVectors( a, b ) { 2304 2305 this.x = a.x - b.x; 2306 this.y = a.y - b.y; 2307 this.z = a.z - b.z; 2308 2309 return this; 2310 2311 } 2312 2313 multiply( 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 multiplyScalar( scalar ) { 2324 2325 this.x *= scalar; 2326 this.y *= scalar; 2327 this.z *= scalar; 2328 2329 return this; 2330 2331 } 2332 2333 multiplyVectors( a, b ) { 2334 2335 this.x = a.x * b.x; 2336 this.y = a.y * b.y; 2337 this.z = a.z * b.z; 2338 2339 return this; 2340 2341 } 2342 2343 applyEuler( euler ) { 2344 2345 return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); 2346 2347 } 2348 2349 applyAxisAngle( axis, angle ) { 2350 2351 return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); 2352 2353 } 2354 2355 applyMatrix3( m ) { 2356 2357 const x = this.x, y = this.y, z = this.z; 2358 const e = m.elements; 2359 2360 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; 2361 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; 2362 this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; 2363 2364 return this; 2365 2366 } 2367 2368 applyNormalMatrix( m ) { 2369 2370 return this.applyMatrix3( m ).normalize(); 2371 2372 } 2373 2374 applyMatrix4( m ) { 2375 2376 const x = this.x, y = this.y, z = this.z; 2377 const e = m.elements; 2378 2379 const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); 2380 2381 this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; 2382 this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; 2383 this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; 2384 2385 return this; 2386 2387 } 2388 2389 applyQuaternion( q ) { 2390 2391 const x = this.x, y = this.y, z = this.z; 2392 const qx = q.x, qy = q.y, qz = q.z, qw = q.w; 2393 2394 // calculate quat * vector 2395 2396 const ix = qw * x + qy * z - qz * y; 2397 const iy = qw * y + qz * x - qx * z; 2398 const iz = qw * z + qx * y - qy * x; 2399 const iw = - qx * x - qy * y - qz * z; 2400 2401 // calculate result * inverse quat 2402 2403 this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy; 2404 this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz; 2405 this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx; 2406 2407 return this; 2408 2409 } 2410 2411 project( camera ) { 2412 2413 return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); 2414 2415 } 2416 2417 unproject( camera ) { 2418 2419 return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); 2420 2421 } 2422 2423 transformDirection( m ) { 2424 2425 // input: THREE.Matrix4 affine matrix 2426 // vector interpreted as a direction 2427 2428 const x = this.x, y = this.y, z = this.z; 2429 const e = m.elements; 2430 2431 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; 2432 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; 2433 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; 2434 2435 return this.normalize(); 2436 2437 } 2438 2439 divide( v ) { 2440 2441 this.x /= v.x; 2442 this.y /= v.y; 2443 this.z /= v.z; 2444 2445 return this; 2446 2447 } 2448 2449 divideScalar( scalar ) { 2450 2451 return this.multiplyScalar( 1 / scalar ); 2452 2453 } 2454 2455 min( v ) { 2456 2457 this.x = Math.min( this.x, v.x ); 2458 this.y = Math.min( this.y, v.y ); 2459 this.z = Math.min( this.z, v.z ); 2460 2461 return this; 2462 2463 } 2464 2465 max( v ) { 2466 2467 this.x = Math.max( this.x, v.x ); 2468 this.y = Math.max( this.y, v.y ); 2469 this.z = Math.max( this.z, v.z ); 2470 2471 return this; 2472 2473 } 2474 2475 clamp( min, max ) { 2476 2477 // assumes min < max, componentwise 2478 2479 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 2480 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 2481 this.z = Math.max( min.z, Math.min( max.z, this.z ) ); 2482 2483 return this; 2484 2485 } 2486 2487 clampScalar( minVal, maxVal ) { 2488 2489 this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); 2490 this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); 2491 this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); 2492 2493 return this; 2494 2495 } 2496 2497 clampLength( min, max ) { 2498 2499 const length = this.length(); 2500 2501 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 2502 2503 } 2504 2505 floor() { 2506 2507 this.x = Math.floor( this.x ); 2508 this.y = Math.floor( this.y ); 2509 this.z = Math.floor( this.z ); 2510 2511 return this; 2512 2513 } 2514 2515 ceil() { 2516 2517 this.x = Math.ceil( this.x ); 2518 this.y = Math.ceil( this.y ); 2519 this.z = Math.ceil( this.z ); 2520 2521 return this; 2522 2523 } 2524 2525 round() { 2526 2527 this.x = Math.round( this.x ); 2528 this.y = Math.round( this.y ); 2529 this.z = Math.round( this.z ); 2530 2531 return this; 2532 2533 } 2534 2535 roundToZero() { 2536 2537 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); 2538 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); 2539 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); 2540 2541 return this; 2542 2543 } 2544 2545 negate() { 2546 2547 this.x = - this.x; 2548 this.y = - this.y; 2549 this.z = - this.z; 2550 2551 return this; 2552 2553 } 2554 2555 dot( v ) { 2556 2557 return this.x * v.x + this.y * v.y + this.z * v.z; 2558 2559 } 2560 2561 // TODO lengthSquared? 2562 2563 lengthSq() { 2564 2565 return this.x * this.x + this.y * this.y + this.z * this.z; 2566 2567 } 2568 2569 length() { 2570 2571 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); 2572 2573 } 2574 2575 manhattanLength() { 2576 2577 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); 2578 2579 } 2580 2581 normalize() { 2582 2583 return this.divideScalar( this.length() || 1 ); 2584 2585 } 2586 2587 setLength( length ) { 2588 2589 return this.normalize().multiplyScalar( length ); 2590 2591 } 2592 2593 lerp( v, alpha ) { 2594 2595 this.x += ( v.x - this.x ) * alpha; 2596 this.y += ( v.y - this.y ) * alpha; 2597 this.z += ( v.z - this.z ) * alpha; 2598 2599 return this; 2600 2601 } 2602 2603 lerpVectors( v1, v2, alpha ) { 2604 2605 this.x = v1.x + ( v2.x - v1.x ) * alpha; 2606 this.y = v1.y + ( v2.y - v1.y ) * alpha; 2607 this.z = v1.z + ( v2.z - v1.z ) * alpha; 2608 2609 return this; 2610 2611 } 2612 2613 cross( v ) { 2614 2615 return this.crossVectors( this, v ); 2616 2617 } 2618 2619 crossVectors( a, b ) { 2620 2621 const ax = a.x, ay = a.y, az = a.z; 2622 const bx = b.x, by = b.y, bz = b.z; 2623 2624 this.x = ay * bz - az * by; 2625 this.y = az * bx - ax * bz; 2626 this.z = ax * by - ay * bx; 2627 2628 return this; 2629 2630 } 2631 2632 projectOnVector( v ) { 2633 2634 const denominator = v.lengthSq(); 2635 2636 if ( denominator === 0 ) return this.set( 0, 0, 0 ); 2637 2638 const scalar = v.dot( this ) / denominator; 2639 2640 return this.copy( v ).multiplyScalar( scalar ); 2641 2642 } 2643 2644 projectOnPlane( planeNormal ) { 2645 2646 _vector$d.copy( this ).projectOnVector( planeNormal ); 2647 2648 return this.sub( _vector$d ); 2649 2650 } 2651 2652 reflect( normal ) { 2653 2654 // reflect incident vector off plane orthogonal to normal 2655 // normal is assumed to have unit length 2656 2657 return this.sub( _vector$d.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); 2658 2659 } 2660 2661 angleTo( v ) { 2662 2663 const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); 2664 2665 if ( denominator === 0 ) return Math.PI / 2; 2666 2667 const theta = this.dot( v ) / denominator; 2668 2669 // clamp, to handle numerical problems 2670 2671 return Math.acos( clamp( theta, - 1, 1 ) ); 2672 2673 } 2674 2675 distanceTo( v ) { 2676 2677 return Math.sqrt( this.distanceToSquared( v ) ); 2678 2679 } 2680 2681 distanceToSquared( v ) { 2682 2683 const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; 2684 2685 return dx * dx + dy * dy + dz * dz; 2686 2687 } 2688 2689 manhattanDistanceTo( v ) { 2690 2691 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); 2692 2693 } 2694 2695 setFromSpherical( s ) { 2696 2697 return this.setFromSphericalCoords( s.radius, s.phi, s.theta ); 2698 2699 } 2700 2701 setFromSphericalCoords( radius, phi, theta ) { 2702 2703 const sinPhiRadius = Math.sin( phi ) * radius; 2704 2705 this.x = sinPhiRadius * Math.sin( theta ); 2706 this.y = Math.cos( phi ) * radius; 2707 this.z = sinPhiRadius * Math.cos( theta ); 2708 2709 return this; 2710 2711 } 2712 2713 setFromCylindrical( c ) { 2714 2715 return this.setFromCylindricalCoords( c.radius, c.theta, c.y ); 2716 2717 } 2718 2719 setFromCylindricalCoords( radius, theta, y ) { 2720
2721 this.x = radius * Math.sin( theta ); 2722 this.y = y; 2723 this.z = radius * Math.cos( theta ); 2724 2725 return this; 2726 2727 } 2728 2729 setFromMatrixPosition( m ) { 2730 2731 const e = m.elements; 2732 2733 this.x = e[ 12 ]; 2734 this.y = e[ 13 ]; 2735 this.z = e[ 14 ]; 2736 2737 return this; 2738 2739 } 2740 2741 setFromMatrixScale( m ) { 2742 2743 const sx = this.setFromMatrixColumn( m, 0 ).length(); 2744 const sy = this.setFromMatrixColumn( m, 1 ).length(); 2745 const sz = this.setFromMatrixColumn( m, 2 ).length(); 2746 2747 this.x = sx; 2748 this.y = sy; 2749 this.z = sz; 2750 2751 return this; 2752 2753 } 2754 2755 setFromMatrixColumn( m, index ) { 2756 2757 return this.fromArray( m.elements, index * 4 ); 2758 2759 } 2760 2761 setFromMatrix3Column( m, index ) { 2762 2763 return this.fromArray( m.elements, index * 3 ); 2764 2765 } 2766 2767 setFromEuler( e ) { 2768 2769 this.x = e._x; 2770 this.y = e._y; 2771 this.z = e._z; 2772 2773 return this; 2774 2775 } 2776 2777 equals( v ) { 2778 2779 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); 2780 2781 } 2782 2783 fromArray( array, offset = 0 ) { 2784 2785 this.x = array[ offset ]; 2786 this.y = array[ offset + 1 ]; 2787 this.z = array[ offset + 2 ]; 2788 2789 return this; 2790 2791 } 2792 2793 toArray( array = [], offset = 0 ) { 2794 2795 array[ offset ] = this.x; 2796 array[ offset + 1 ] = this.y; 2797 array[ offset + 2 ] = this.z; 2798 2799 return array; 2800 2801 } 2802 2803 fromBufferAttribute( attribute, index ) { 2804 2805 this.x = attribute.getX( index ); 2806 this.y = attribute.getY( index ); 2807 this.z = attribute.getZ( index ); 2808 2809 return this; 2810 2811 } 2812 2813 random() { 2814 2815 this.x = Math.random(); 2816 this.y = Math.random(); 2817 this.z = Math.random(); 2818 2819 return this; 2820 2821 } 2822 2823 randomDirection() { 2824 2825 // Derived from https://mathworld.wolfram.com/SpherePointPicking.html 2826 2827 const u = ( Math.random() - 0.5 ) * 2; 2828 const t = Math.random() * Math.PI * 2; 2829 const f = Math.sqrt( 1 - u ** 2 ); 2830 2831 this.x = f * Math.cos( t ); 2832 this.y = f * Math.sin( t ); 2833 this.z = u; 2834 2835 return this; 2836 2837 } 2838 2839 *[ Symbol.iterator ]() { 2840 2841 yield this.x; 2842 yield this.y; 2843 yield this.z; 2844 2845 } 2846 2847} 2848 2849const _vector$d = /*@__PURE__*/ new Vector3(); 2850const _quaternion$4 = /*@__PURE__*/ new Quaternion(); 2851 2852function SRGBToLinear( c ) { 2853 2854 return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 ); 2855 2856} 2857 2858function LinearToSRGB( c ) { 2859 2860 return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055; 2861 2862} 2863 2864 2865/** 2866 * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping 2867 * or clipping. Based on W3C specifications for sRGB and Display P3, 2868 * and ICC specifications for the D50 connection space. Values in/out 2869 * are _linear_ sRGB and _linear_ Display P3. 2870 * 2871 * Note that both sRGB and Display P3 use the sRGB transfer functions. 2872 * 2873 * Reference: 2874 * - http://www.russellcottrell.com/photo/matrixCalculator.htm 2875 */ 2876 2877const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = new Matrix3().fromArray( [ 2878 0.8224621, 0.0331941, 0.0170827, 2879 0.1775380, 0.9668058, 0.0723974, 2880 - 0.0000001, 0.0000001, 0.9105199 2881] ); 2882 2883const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = new Matrix3().fromArray( [ 2884 1.2249401, - 0.0420569, - 0.0196376, 2885 - 0.2249404, 1.0420571, - 0.0786361, 2886 0.0000001, 0.0000000, 1.0982735 2887] ); 2888 2889const _vector$c = new Vector3(); 2890 2891function DisplayP3ToLinearSRGB( color ) { 2892 2893 color.convertSRGBToLinear(); 2894 2895 _vector$c.set( color.r, color.g, color.b ).applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ); 2896 2897 return color.setRGB( _vector$c.x, _vector$c.y, _vector$c.z ); 2898 2899} 2900 2901function LinearSRGBToDisplayP3( color ) { 2902 2903 _vector$c.set( color.r, color.g, color.b ).applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ); 2904 2905 return color.setRGB( _vector$c.x, _vector$c.y, _vector$c.z ).convertLinearToSRGB(); 2906 2907} 2908 2909// Conversions from <source> to Linear-sRGB reference space. 2910const TO_LINEAR = { 2911 [ LinearSRGBColorSpace ]: ( color ) => color, 2912 [ SRGBColorSpace ]: ( color ) => color.convertSRGBToLinear(), 2913 [ DisplayP3ColorSpace ]: DisplayP3ToLinearSRGB, 2914}; 2915 2916// Conversions to <target> from Linear-sRGB reference space. 2917const FROM_LINEAR = { 2918 [ LinearSRGBColorSpace ]: ( color ) => color, 2919 [ SRGBColorSpace ]: ( color ) => color.convertLinearToSRGB(), 2920 [ DisplayP3ColorSpace ]: LinearSRGBToDisplayP3, 2921}; 2922 2923const ColorManagement = { 2924 2925 enabled: false, 2926 2927 get legacyMode() { 2928 2929 console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' ); 2930 2931 return ! this.enabled; 2932 2933 }, 2934 2935 set legacyMode( legacyMode ) { 2936 2937 console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' ); 2938 2939 this.enabled = ! legacyMode; 2940 2941 }, 2942 2943 get workingColorSpace() { 2944 2945 return LinearSRGBColorSpace; 2946 2947 }, 2948 2949 set workingColorSpace( colorSpace ) { 2950 2951 console.warn( 'THREE.ColorManagement: .workingColorSpace is readonly.' ); 2952 2953 }, 2954 2955 convert: function ( color, sourceColorSpace, targetColorSpace ) { 2956 2957 if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { 2958 2959 return color; 2960 2961 } 2962 2963 const sourceToLinear = TO_LINEAR[ sourceColorSpace ]; 2964 const targetFromLinear = FROM_LINEAR[ targetColorSpace ]; 2965 2966 if ( sourceToLinear === undefined || targetFromLinear === undefined ) { 2967 2968 throw new Error( `Unsupported color space conversion, "${ sourceColorSpace }" to "${ targetColorSpace }".` ); 2969 2970 } 2971 2972 return targetFromLinear( sourceToLinear( color ) ); 2973 2974 }, 2975 2976 fromWorkingColorSpace: function ( color, targetColorSpace ) { 2977 2978 return this.convert( color, this.workingColorSpace, targetColorSpace ); 2979 2980 }, 2981 2982 toWorkingColorSpace: function ( color, sourceColorSpace ) { 2983 2984 return this.convert( color, sourceColorSpace, this.workingColorSpace ); 2985 2986 }, 2987 2988}; 2989 2990let _canvas; 2991 2992class ImageUtils { 2993 2994 static getDataURL( image ) { 2995 2996 if ( /^data:/i.test( image.src ) ) { 2997 2998 return image.src; 2999 3000 } 3001 3002 if ( typeof HTMLCanvasElement == 'undefined' ) { 3003 3004 return image.src; 3005 3006 } 3007 3008 let canvas; 3009 3010 if ( image instanceof HTMLCanvasElement ) { 3011 3012 canvas = image; 3013 3014 } else { 3015
vendor: 19,905 bytes, lines 3016-4174
3016 if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); 3017 3018 _canvas.width = image.width; 3019 _canvas.height = image.height; 3020 3021 const context = _canvas.getContext( '2d' ); 3022 3023 if ( image instanceof ImageData ) { 3024 3025 context.putImageData( image, 0, 0 ); 3026 3027 } else { 3028 3029 context.drawImage( image, 0, 0, image.width, image.height ); 3030 3031 } 3032 3033 canvas = _canvas; 3034 3035 } 3036 3037 if ( canvas.width > 2048 || canvas.height > 2048 ) { 3038 3039 console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); 3040 3041 return canvas.toDataURL( 'image/jpeg', 0.6 ); 3042 3043 } else { 3044 3045 return canvas.toDataURL( 'image/png' ); 3046 3047 } 3048 3049 } 3050 3051 static sRGBToLinear( image ) { 3052 3053 if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || 3054 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || 3055 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { 3056 3057 const canvas = createElementNS( 'canvas' ); 3058 3059 canvas.width = image.width; 3060 canvas.height = image.height; 3061 3062 const context = canvas.getContext( '2d' ); 3063 context.drawImage( image, 0, 0, image.width, image.height ); 3064 3065 const imageData = context.getImageData( 0, 0, image.width, image.height ); 3066 const data = imageData.data; 3067 3068 for ( let i = 0; i < data.length; i ++ ) { 3069 3070 data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; 3071 3072 } 3073 3074 context.putImageData( imageData, 0, 0 ); 3075 3076 return canvas; 3077 3078 } else if ( image.data ) { 3079 3080 const data = image.data.slice( 0 ); 3081 3082 for ( let i = 0; i < data.length; i ++ ) { 3083 3084 if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { 3085 3086 data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); 3087 3088 } else { 3089 3090 // assuming float 3091 3092 data[ i ] = SRGBToLinear( data[ i ] ); 3093 3094 } 3095 3096 } 3097 3098 return { 3099 data: data, 3100 width: image.width, 3101 height: image.height 3102 }; 3103 3104 } else { 3105 3106 console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); 3107 return image; 3108 3109 } 3110 3111 } 3112 3113} 3114 3115class Source { 3116 3117 constructor( data = null ) { 3118 3119 this.isSource = true; 3120 3121 this.uuid = generateUUID(); 3122 3123 this.data = data; 3124 3125 this.version = 0; 3126 3127 } 3128 3129 set needsUpdate( value ) { 3130 3131 if ( value === true ) this.version ++; 3132 3133 } 3134 3135 toJSON( meta ) { 3136 3137 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 3138 3139 if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { 3140 3141 return meta.images[ this.uuid ]; 3142 3143 } 3144 3145 const output = { 3146 uuid: this.uuid, 3147 url: '' 3148 }; 3149 3150 const data = this.data; 3151 3152 if ( data !== null ) { 3153 3154 let url; 3155 3156 if ( Array.isArray( data ) ) { 3157 3158 // cube texture 3159 3160 url = []; 3161 3162 for ( let i = 0, l = data.length; i < l; i ++ ) { 3163 3164 if ( data[ i ].isDataTexture ) { 3165 3166 url.push( serializeImage( data[ i ].image ) ); 3167 3168 } else { 3169 3170 url.push( serializeImage( data[ i ] ) ); 3171 3172 } 3173 3174 } 3175 3176 } else { 3177 3178 // texture 3179 3180 url = serializeImage( data ); 3181 3182 } 3183 3184 output.url = url; 3185 3186 } 3187 3188 if ( ! isRootObject ) { 3189 3190 meta.images[ this.uuid ] = output; 3191 3192 } 3193 3194 return output; 3195 3196 } 3197 3198} 3199 3200function serializeImage( image ) { 3201 3202 if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || 3203 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || 3204 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { 3205 3206 // default images 3207 3208 return ImageUtils.getDataURL( image ); 3209 3210 } else { 3211 3212 if ( image.data ) { 3213 3214 // images of DataTexture 3215 3216 return { 3217 data: Array.from( image.data ), 3218 width: image.width, 3219 height: image.height, 3220 type: image.data.constructor.name 3221 }; 3222 3223 } else { 3224 3225 console.warn( 'THREE.Texture: Unable to serialize Texture.' ); 3226 return {}; 3227 3228 } 3229 3230 } 3231 3232} 3233 3234let textureId = 0; 3235 3236class Texture extends EventDispatcher { 3237 3238 constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, encoding = LinearEncoding ) { 3239 3240 super(); 3241 3242 this.isTexture = true; 3243 3244 Object.defineProperty( this, 'id', { value: textureId ++ } ); 3245 3246 this.uuid = generateUUID(); 3247 3248 this.name = ''; 3249 3250 this.source = new Source( image ); 3251 this.mipmaps = []; 3252 3253 this.mapping = mapping; 3254 3255 this.wrapS = wrapS; 3256 this.wrapT = wrapT; 3257 3258 this.magFilter = magFilter; 3259 this.minFilter = minFilter; 3260 3261 this.anisotropy = anisotropy; 3262 3263 this.format = format; 3264 this.internalFormat = null; 3265 this.type = type; 3266 3267 this.offset = new Vector2( 0, 0 ); 3268 this.repeat = new Vector2( 1, 1 ); 3269 this.center = new Vector2( 0, 0 ); 3270 this.rotation = 0; 3271 3272 this.matrixAutoUpdate = true; 3273 this.matrix = new Matrix3(); 3274 3275 this.generateMipmaps = true; 3276 this.premultiplyAlpha = false; 3277 this.flipY = true; 3278 this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) 3279 3280 // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. 3281 // 3282 // Also changing the encoding after already used by a Material will not automatically make the Material 3283 // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. 3284 this.encoding = encoding; 3285 3286 this.userData = {}; 3287 3288 this.version = 0; 3289 this.onUpdate = null; 3290 3291 this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not 3292 this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) 3293 3294 } 3295 3296 get image() { 3297 3298 return this.source.data; 3299 3300 } 3301 3302 set image( value = null ) { 3303 3304 this.source.data = value; 3305 3306 } 3307 3308 updateMatrix() { 3309 3310 this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); 3311 3312 } 3313 3314 clone() { 3315 3316 return new this.constructor().copy( this ); 3317 3318 } 3319 3320 copy( source ) { 3321 3322 this.name = source.name; 3323 3324 this.source = source.source; 3325 this.mipmaps = source.mipmaps.slice( 0 ); 3326 3327 this.mapping = source.mapping; 3328 3329 this.wrapS = source.wrapS; 3330 this.wrapT = source.wrapT; 3331 3332 this.magFilter = source.magFilter; 3333 this.minFilter = source.minFilter; 3334 3335 this.anisotropy = source.anisotropy; 3336 3337 this.format = source.format; 3338 this.internalFormat = source.internalFormat; 3339 this.type = source.type; 3340 3341 this.offset.copy( source.offset ); 3342 this.repeat.copy( source.repeat ); 3343 this.center.copy( source.center ); 3344 this.rotation = source.rotation; 3345 3346 this.matrixAutoUpdate = source.matrixAutoUpdate; 3347 this.matrix.copy( source.matrix ); 3348 3349 this.generateMipmaps = source.generateMipmaps; 3350 this.premultiplyAlpha = source.premultiplyAlpha; 3351 this.flipY = source.flipY; 3352 this.unpackAlignment = source.unpackAlignment; 3353 this.encoding = source.encoding; 3354 3355 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 3356 3357 this.needsUpdate = true; 3358 3359 return this; 3360 3361 } 3362 3363 toJSON( meta ) { 3364 3365 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 3366 3367 if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { 3368 3369 return meta.textures[ this.uuid ]; 3370 3371 } 3372 3373 const output = { 3374 3375 metadata: { 3376 version: 4.5, 3377 type: 'Texture', 3378 generator: 'Texture.toJSON' 3379 }, 3380 3381 uuid: this.uuid, 3382 name: this.name, 3383 3384 image: this.source.toJSON( meta ).uuid, 3385 3386 mapping: this.mapping, 3387 3388 repeat: [ this.repeat.x, this.repeat.y ], 3389 offset: [ this.offset.x, this.offset.y ], 3390 center: [ this.center.x, this.center.y ], 3391 rotation: this.rotation, 3392 3393 wrap: [ this.wrapS, this.wrapT ], 3394 3395 format: this.format, 3396 internalFormat: this.internalFormat, 3397 type: this.type, 3398 encoding: this.encoding, 3399 3400 minFilter: this.minFilter, 3401 magFilter: this.magFilter, 3402 anisotropy: this.anisotropy, 3403 3404 flipY: this.flipY, 3405 3406 generateMipmaps: this.generateMipmaps, 3407 premultiplyAlpha: this.premultiplyAlpha, 3408 unpackAlignment: this.unpackAlignment 3409 3410 }; 3411 3412 if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; 3413 3414 if ( ! isRootObject ) { 3415 3416 meta.textures[ this.uuid ] = output; 3417 3418 } 3419 3420 return output; 3421 3422 } 3423 3424 dispose() { 3425 3426 this.dispatchEvent( { type: 'dispose' } ); 3427 3428 } 3429 3430 transformUv( uv ) { 3431 3432 if ( this.mapping !== UVMapping ) return uv; 3433 3434 uv.applyMatrix3( this.matrix ); 3435 3436 if ( uv.x < 0 || uv.x > 1 ) { 3437 3438 switch ( this.wrapS ) { 3439 3440 case RepeatWrapping: 3441 3442 uv.x = uv.x - Math.floor( uv.x ); 3443 break; 3444 3445 case ClampToEdgeWrapping: 3446 3447 uv.x = uv.x < 0 ? 0 : 1; 3448 break; 3449 3450 case MirroredRepeatWrapping: 3451 3452 if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { 3453 3454 uv.x = Math.ceil( uv.x ) - uv.x; 3455 3456 } else { 3457 3458 uv.x = uv.x - Math.floor( uv.x ); 3459 3460 } 3461 3462 break; 3463 3464 } 3465 3466 } 3467 3468 if ( uv.y < 0 || uv.y > 1 ) { 3469 3470 switch ( this.wrapT ) { 3471 3472 case RepeatWrapping: 3473 3474 uv.y = uv.y - Math.floor( uv.y ); 3475 break; 3476 3477 case ClampToEdgeWrapping: 3478 3479 uv.y = uv.y < 0 ? 0 : 1; 3480 break; 3481 3482 case MirroredRepeatWrapping: 3483 3484 if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { 3485 3486 uv.y = Math.ceil( uv.y ) - uv.y; 3487 3488 } else { 3489 3490 uv.y = uv.y - Math.floor( uv.y ); 3491 3492 } 3493 3494 break; 3495 3496 } 3497 3498 } 3499 3500 if ( this.flipY ) { 3501 3502 uv.y = 1 - uv.y; 3503 3504 } 3505 3506 return uv; 3507 3508 } 3509 3510 set needsUpdate( value ) { 3511 3512 if ( value === true ) { 3513 3514 this.version ++; 3515 this.source.needsUpdate = true; 3516 3517 } 3518 3519 } 3520 3521} 3522 3523Texture.DEFAULT_IMAGE = null; 3524Texture.DEFAULT_MAPPING = UVMapping; 3525Texture.DEFAULT_ANISOTROPY = 1; 3526 3527class Vector4 { 3528 3529 constructor( x = 0, y = 0, z = 0, w = 1 ) { 3530 3531 Vector4.prototype.isVector4 = true; 3532 3533 this.x = x; 3534 this.y = y; 3535 this.z = z; 3536 this.w = w; 3537 3538 } 3539 3540 get width() { 3541 3542 return this.z; 3543 3544 } 3545 3546 set width( value ) { 3547 3548 this.z = value; 3549 3550 } 3551 3552 get height() { 3553 3554 return this.w; 3555 3556 } 3557 3558 set height( value ) { 3559 3560 this.w = value; 3561 3562 } 3563 3564 set( x, y, z, w ) { 3565 3566 this.x = x; 3567 this.y = y; 3568 this.z = z; 3569 this.w = w; 3570 3571 return this; 3572 3573 } 3574 3575 setScalar( scalar ) { 3576 3577 this.x = scalar; 3578 this.y = scalar; 3579 this.z = scalar; 3580 this.w = scalar; 3581 3582 return this; 3583 3584 } 3585 3586 setX( x ) { 3587 3588 this.x = x; 3589 3590 return this; 3591 3592 } 3593 3594 setY( y ) { 3595 3596 this.y = y; 3597 3598 return this; 3599 3600 } 3601 3602 setZ( z ) { 3603 3604 this.z = z; 3605 3606 return this; 3607 3608 } 3609 3610 setW( w ) { 3611 3612 this.w = w; 3613 3614 return this; 3615 3616 } 3617 3618 setComponent( index, value ) { 3619 3620 switch ( index ) { 3621 3622 case 0: this.x = value; break; 3623 case 1: this.y = value; break; 3624 case 2: this.z = value; break; 3625 case 3: this.w = value; break; 3626 default: throw new Error( 'index is out of range: ' + index ); 3627 3628 } 3629 3630 return this; 3631 3632 } 3633 3634 getComponent( index ) { 3635 3636 switch ( index ) { 3637 3638 case 0: return this.x; 3639 case 1: return this.y; 3640 case 2: return this.z; 3641 case 3: return this.w; 3642 default: throw new Error( 'index is out of range: ' + index ); 3643 3644 } 3645 3646 } 3647 3648 clone() { 3649 3650 return new this.constructor( this.x, this.y, this.z, this.w ); 3651 3652 } 3653 3654 copy( v ) { 3655 3656 this.x = v.x; 3657 this.y = v.y; 3658 this.z = v.z; 3659 this.w = ( v.w !== undefined ) ? v.w : 1; 3660 3661 return this; 3662 3663 } 3664 3665 add( v ) { 3666 3667 this.x += v.x; 3668 this.y += v.y; 3669 this.z += v.z; 3670 this.w += v.w; 3671 3672 return this; 3673 3674 } 3675 3676 addScalar( s ) { 3677 3678 this.x += s; 3679 this.y += s; 3680 this.z += s; 3681 this.w += s; 3682 3683 return this; 3684 3685 } 3686 3687 addVectors( a, b ) { 3688 3689 this.x = a.x + b.x; 3690 this.y = a.y + b.y; 3691 this.z = a.z + b.z; 3692 this.w = a.w + b.w; 3693 3694 return this; 3695 3696 } 3697 3698 addScaledVector( v, s ) { 3699 3700 this.x += v.x * s; 3701 this.y += v.y * s; 3702 this.z += v.z * s; 3703 this.w += v.w * s; 3704 3705 return this; 3706 3707 } 3708 3709 sub( v ) { 3710 3711 this.x -= v.x; 3712 this.y -= v.y; 3713 this.z -= v.z; 3714 this.w -= v.w; 3715 3716 return this; 3717 3718 } 3719 3720 subScalar( s ) { 3721 3722 this.x -= s; 3723 this.y -= s; 3724 this.z -= s; 3725 this.w -= s; 3726 3727 return this; 3728 3729 } 3730 3731 subVectors( a, b ) { 3732 3733 this.x = a.x - b.x; 3734 this.y = a.y - b.y; 3735 this.z = a.z - b.z; 3736 this.w = a.w - b.w; 3737 3738 return this; 3739 3740 } 3741 3742 multiply( v ) { 3743 3744 this.x *= v.x; 3745 this.y *= v.y; 3746 this.z *= v.z; 3747 this.w *= v.w; 3748 3749 return this; 3750 3751 } 3752 3753 multiplyScalar( scalar ) { 3754 3755 this.x *= scalar; 3756 this.y *= scalar; 3757 this.z *= scalar; 3758 this.w *= scalar; 3759 3760 return this; 3761 3762 } 3763 3764 applyMatrix4( m ) { 3765 3766 const x = this.x, y = this.y, z = this.z, w = this.w; 3767 const e = m.elements; 3768 3769 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; 3770 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; 3771 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; 3772 this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; 3773 3774 return this; 3775 3776 } 3777 3778 divideScalar( scalar ) { 3779 3780 return this.multiplyScalar( 1 / scalar ); 3781 3782 } 3783 3784 setAxisAngleFromQuaternion( q ) { 3785 3786 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm 3787 3788 // q is assumed to be normalized 3789 3790 this.w = 2 * Math.acos( q.w ); 3791 3792 const s = Math.sqrt( 1 - q.w * q.w ); 3793 3794 if ( s < 0.0001 ) { 3795 3796 this.x = 1; 3797 this.y = 0; 3798 this.z = 0; 3799 3800 } else { 3801 3802 this.x = q.x / s; 3803 this.y = q.y / s; 3804 this.z = q.z / s; 3805 3806 } 3807 3808 return this; 3809 3810 } 3811 3812 setAxisAngleFromRotationMatrix( m ) { 3813 3814 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm 3815 3816 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 3817 3818 let angle, x, y, z; // variables for result 3819 const epsilon = 0.01, // margin to allow for rounding errors 3820 epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees 3821 3822 te = m.elements, 3823 3824 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], 3825 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], 3826 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; 3827 3828 if ( ( Math.abs( m12 - m21 ) < epsilon ) && 3829 ( Math.abs( m13 - m31 ) < epsilon ) && 3830 ( Math.abs( m23 - m32 ) < epsilon ) ) { 3831 3832 // singularity found 3833 // first check for identity matrix which must have +1 for all terms 3834 // in leading diagonal and zero in other terms 3835 3836 if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && 3837 ( Math.abs( m13 + m31 ) < epsilon2 ) && 3838 ( Math.abs( m23 + m32 ) < epsilon2 ) && 3839 ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { 3840 3841 // this singularity is identity matrix so angle = 0 3842 3843 this.set( 1, 0, 0, 0 ); 3844 3845 return this; // zero angle, arbitrary axis 3846 3847 } 3848 3849 // otherwise this singularity is angle = 180 3850 3851 angle = Math.PI; 3852 3853 const xx = ( m11 + 1 ) / 2; 3854 const yy = ( m22 + 1 ) / 2; 3855 const zz = ( m33 + 1 ) / 2; 3856 const xy = ( m12 + m21 ) / 4; 3857 const xz = ( m13 + m31 ) / 4; 3858 const yz = ( m23 + m32 ) / 4; 3859 3860 if ( ( xx > yy ) && ( xx > zz ) ) { 3861 3862 // m11 is the largest diagonal term 3863 3864 if ( xx < epsilon ) { 3865 3866 x = 0; 3867 y = 0.707106781; 3868 z = 0.707106781; 3869 3870 } else { 3871 3872 x = Math.sqrt( xx ); 3873 y = xy / x; 3874 z = xz / x; 3875 3876 } 3877 3878 } else if ( yy > zz ) { 3879 3880 // m22 is the largest diagonal term 3881 3882 if ( yy < epsilon ) { 3883 3884 x = 0.707106781; 3885 y = 0; 3886 z = 0.707106781; 3887 3888 } else { 3889 3890 y = Math.sqrt( yy ); 3891 x = xy / y; 3892 z = yz / y; 3893 3894 } 3895 3896 } else { 3897 3898 // m33 is the largest diagonal term so base result on this 3899 3900 if ( zz < epsilon ) { 3901 3902 x = 0.707106781; 3903 y = 0.707106781; 3904 z = 0; 3905 3906 } else { 3907 3908 z = Math.sqrt( zz ); 3909 x = xz / z; 3910 y = yz / z; 3911 3912 } 3913 3914 } 3915 3916 this.set( x, y, z, angle ); 3917 3918 return this; // return 180 deg rotation 3919 3920 } 3921 3922 // as we have reached here there are no singularities so we can handle normally 3923 3924 let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + 3925 ( m13 - m31 ) * ( m13 - m31 ) + 3926 ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize 3927 3928 if ( Math.abs( s ) < 0.001 ) s = 1; 3929 3930 // prevent divide by zero, should not happen if matrix is orthogonal and should be 3931 // caught by singularity test above, but I've left it in just in case 3932 3933 this.x = ( m32 - m23 ) / s; 3934 this.y = ( m13 - m31 ) / s; 3935 this.z = ( m21 - m12 ) / s; 3936 this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); 3937 3938 return this; 3939 3940 } 3941 3942 min( v ) { 3943 3944 this.x = Math.min( this.x, v.x ); 3945 this.y = Math.min( this.y, v.y ); 3946 this.z = Math.min( this.z, v.z ); 3947 this.w = Math.min( this.w, v.w ); 3948 3949 return this; 3950 3951 } 3952 3953 max( v ) { 3954 3955 this.x = Math.max( this.x, v.x ); 3956 this.y = Math.max( this.y, v.y ); 3957 this.z = Math.max( this.z, v.z ); 3958 this.w = Math.max( this.w, v.w ); 3959 3960 return this; 3961 3962 } 3963 3964 clamp( min, max ) { 3965 3966 // assumes min < max, componentwise 3967 3968 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 3969 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 3970 this.z = Math.max( min.z, Math.min( max.z, this.z ) ); 3971 this.w = Math.max( min.w, Math.min( max.w, this.w ) ); 3972 3973 return this; 3974 3975 } 3976 3977 clampScalar( minVal, maxVal ) { 3978 3979 this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); 3980 this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); 3981 this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); 3982 this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); 3983 3984 return this; 3985 3986 } 3987 3988 clampLength( min, max ) { 3989 3990 const length = this.length(); 3991 3992 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 3993 3994 } 3995 3996 floor() { 3997 3998 this.x = Math.floor( this.x ); 3999 this.y = Math.floor( this.y ); 4000 this.z = Math.floor( this.z ); 4001 this.w = Math.floor( this.w ); 4002 4003 return this; 4004 4005 } 4006 4007 ceil() { 4008 4009 this.x = Math.ceil( this.x ); 4010 this.y = Math.ceil( this.y ); 4011 this.z = Math.ceil( this.z ); 4012 this.w = Math.ceil( this.w ); 4013 4014 return this; 4015 4016 } 4017 4018 round() { 4019 4020 this.x = Math.round( this.x ); 4021 this.y = Math.round( this.y ); 4022 this.z = Math.round( this.z ); 4023 this.w = Math.round( this.w ); 4024 4025 return this; 4026 4027 } 4028 4029 roundToZero() { 4030 4031 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); 4032 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); 4033 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); 4034 this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); 4035 4036 return this; 4037 4038 } 4039 4040 negate() { 4041 4042 this.x = - this.x; 4043 this.y = - this.y; 4044 this.z = - this.z; 4045 this.w = - this.w; 4046 4047 return this; 4048 4049 } 4050 4051 dot( v ) { 4052 4053 return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; 4054 4055 } 4056 4057 lengthSq() { 4058 4059 return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; 4060 4061 } 4062 4063 length() { 4064 4065 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); 4066 4067 } 4068 4069 manhattanLength() { 4070 4071 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); 4072 4073 } 4074 4075 normalize() { 4076 4077 return this.divideScalar( this.length() || 1 ); 4078 4079 } 4080 4081 setLength( length ) { 4082 4083 return this.normalize().multiplyScalar( length ); 4084 4085 } 4086 4087 lerp( v, alpha ) { 4088 4089 this.x += ( v.x - this.x ) * alpha; 4090 this.y += ( v.y - this.y ) * alpha; 4091 this.z += ( v.z - this.z ) * alpha; 4092 this.w += ( v.w - this.w ) * alpha; 4093 4094 return this; 4095 4096 } 4097 4098 lerpVectors( v1, v2, alpha ) { 4099 4100 this.x = v1.x + ( v2.x - v1.x ) * alpha; 4101 this.y = v1.y + ( v2.y - v1.y ) * alpha; 4102 this.z = v1.z + ( v2.z - v1.z ) * alpha; 4103 this.w = v1.w + ( v2.w - v1.w ) * alpha; 4104 4105 return this; 4106 4107 } 4108 4109 equals( v ) { 4110 4111 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); 4112 4113 } 4114 4115 fromArray( array, offset = 0 ) { 4116 4117 this.x = array[ offset ]; 4118 this.y = array[ offset + 1 ]; 4119 this.z = array[ offset + 2 ]; 4120 this.w = array[ offset + 3 ]; 4121 4122 return this; 4123 4124 } 4125 4126 toArray( array = [], offset = 0 ) { 4127 4128 array[ offset ] = this.x; 4129 array[ offset + 1 ] = this.y; 4130 array[ offset + 2 ] = this.z; 4131 array[ offset + 3 ] = this.w; 4132 4133 return array; 4134 4135 } 4136 4137 fromBufferAttribute( attribute, index ) { 4138 4139 this.x = attribute.getX( index ); 4140 this.y = attribute.getY( index ); 4141 this.z = attribute.getZ( index ); 4142 this.w = attribute.getW( index ); 4143 4144 return this; 4145 4146 } 4147 4148 random() { 4149 4150 this.x = Math.random(); 4151 this.y = Math.random(); 4152 this.z = Math.random(); 4153 this.w = Math.random(); 4154 4155 return this; 4156 4157 } 4158 4159 *[ Symbol.iterator ]() { 4160 4161 yield this.x; 4162 yield this.y; 4163 yield this.z; 4164 yield this.w; 4165 4166 } 4167 4168} 4169 4170/* 4171 In options, we can specify: 4172 * Texture parameters for an auto-generated target texture 4173 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers 4174*/
4175class WebGLRenderTarget extends EventDispatcher { 4176 4177 constructor( width = 1, height = 1, options = {} ) { 4178 4179 super(); 4180 4181 this.isWebGLRenderTarget = true; 4182 4183 this.width = width; 4184 this.height = height; 4185 this.depth = 1; 4186 4187 this.scissor = new Vector4( 0, 0, width, height ); 4188 this.scissorTest = false; 4189 4190 this.viewport = new Vector4( 0, 0, width, height ); 4191 4192 const image = { width: width, height: height, depth: 1 }; 4193 4194 this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); 4195 this.texture.isRenderTargetTexture = true; 4196 4197 this.texture.flipY = false; 4198 this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; 4199 this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null; 4200 this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; 4201 4202 this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; 4203 this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false; 4204 4205 this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; 4206 4207 this.samples = options.samples !== undefined ? options.samples : 0; 4208 4209 } 4210 4211 setSize( width, height, depth = 1 ) { 4212 4213 if ( this.width !== width || this.height !== height || this.depth !== depth ) { 4214 4215 this.width = width; 4216 this.height = height; 4217 this.depth = depth; 4218 4219 this.texture.image.width = width; 4220 this.texture.image.height = height; 4221 this.texture.image.depth = depth; 4222 4223 this.dispose(); 4224 4225 } 4226 4227 this.viewport.set( 0, 0, width, height ); 4228 this.scissor.set( 0, 0, width, height ); 4229 4230 } 4231 4232 clone() { 4233 4234 return new this.constructor().copy( this ); 4235 4236 } 4237 4238 copy( source ) { 4239 4240 this.width = source.width; 4241 this.height = source.height; 4242 this.depth = source.depth; 4243 4244 this.viewport.copy( source.viewport ); 4245 4246 this.texture = source.texture.clone(); 4247 this.texture.isRenderTargetTexture = true; 4248 4249 // ensure image object is not shared, see #20328 4250 4251 const image = Object.assign( {}, source.texture.image ); 4252 this.texture.source = new Source( image ); 4253 4254 this.depthBuffer = source.depthBuffer; 4255 this.stencilBuffer = source.stencilBuffer; 4256 4257 if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); 4258 4259 this.samples = source.samples; 4260 4261 return this; 4262 4263 } 4264 4265 dispose() { 4266 4267 this.dispatchEvent( { type: 'dispose' } ); 4268 4269 } 4270 4271} 4272 4273class DataArrayTexture extends Texture { 4274 4275 constructor( data = null, width = 1, height = 1, depth = 1 ) { 4276 4277 super( null ); 4278 4279 this.isDataArrayTexture = true; 4280 4281 this.image = { data, width, height, depth }; 4282 4283 this.magFilter = NearestFilter; 4284 this.minFilter = NearestFilter; 4285 4286 this.wrapR = ClampToEdgeWrapping; 4287 4288 this.generateMipmaps = false; 4289 this.flipY = false; 4290 this.unpackAlignment = 1; 4291 4292 } 4293 4294} 4295 4296class WebGLArrayRenderTarget extends WebGLRenderTarget { 4297 4298 constructor( width = 1, height = 1, depth = 1 ) { 4299 4300 super( width, height ); 4301 4302 this.isWebGLArrayRenderTarget = true; 4303 4304 this.depth = depth; 4305 4306 this.texture = new DataArrayTexture( null, width, height, depth ); 4307 4308 this.texture.isRenderTargetTexture = true; 4309 4310 } 4311 4312} 4313 4314class Data3DTexture extends Texture { 4315 4316 constructor( data = null, width = 1, height = 1, depth = 1 ) { 4317 4318 // We're going to add .setXXX() methods for setting properties later. 4319 // Users can still set in DataTexture3D directly. 4320 // 4321 // const texture = new THREE.DataTexture3D( data, width, height, depth ); 4322 // texture.anisotropy = 16; 4323 // 4324 // See #14839 4325 4326 super( null ); 4327 4328 this.isData3DTexture = true; 4329 4330 this.image = { data, width, height, depth }; 4331 4332 this.magFilter = NearestFilter; 4333 this.minFilter = NearestFilter; 4334 4335 this.wrapR = ClampToEdgeWrapping; 4336 4337 this.generateMipmaps = false; 4338 this.flipY = false; 4339 this.unpackAlignment = 1; 4340 4341 } 4342 4343} 4344 4345class WebGL3DRenderTarget extends WebGLRenderTarget { 4346 4347 constructor( width = 1, height = 1, depth = 1 ) { 4348 4349 super( width, height ); 4350 4351 this.isWebGL3DRenderTarget = true; 4352 4353 this.depth = depth; 4354 4355 this.texture = new Data3DTexture( null, width, height, depth ); 4356 4357 this.texture.isRenderTargetTexture = true; 4358 4359 } 4360 4361} 4362 4363class WebGLMultipleRenderTargets extends WebGLRenderTarget { 4364 4365 constructor( width = 1, height = 1, count = 1, options = {} ) { 4366 4367 super( width, height, options ); 4368
vendor: 4,588 bytes, lines 4369-4633
4369 this.isWebGLMultipleRenderTargets = true; 4370 4371 const texture = this.texture; 4372 4373 this.texture = []; 4374 4375 for ( let i = 0; i < count; i ++ ) { 4376 4377 this.texture[ i ] = texture.clone(); 4378 this.texture[ i ].isRenderTargetTexture = true; 4379 4380 } 4381 4382 } 4383 4384 setSize( width, height, depth = 1 ) { 4385 4386 if ( this.width !== width || this.height !== height || this.depth !== depth ) { 4387 4388 this.width = width; 4389 this.height = height; 4390 this.depth = depth; 4391 4392 for ( let i = 0, il = this.texture.length; i < il; i ++ ) { 4393 4394 this.texture[ i ].image.width = width; 4395 this.texture[ i ].image.height = height; 4396 this.texture[ i ].image.depth = depth; 4397 4398 } 4399 4400 this.dispose(); 4401 4402 } 4403 4404 this.viewport.set( 0, 0, width, height ); 4405 this.scissor.set( 0, 0, width, height ); 4406 4407 return this; 4408 4409 } 4410 4411 copy( source ) { 4412 4413 this.dispose(); 4414 4415 this.width = source.width; 4416 this.height = source.height; 4417 this.depth = source.depth; 4418 4419 this.viewport.set( 0, 0, this.width, this.height ); 4420 this.scissor.set( 0, 0, this.width, this.height ); 4421 4422 this.depthBuffer = source.depthBuffer; 4423 this.stencilBuffer = source.stencilBuffer; 4424 4425 if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); 4426 4427 this.texture.length = 0; 4428 4429 for ( let i = 0, il = source.texture.length; i < il; i ++ ) { 4430 4431 this.texture[ i ] = source.texture[ i ].clone(); 4432 this.texture[ i ].isRenderTargetTexture = true; 4433 4434 } 4435 4436 return this; 4437 4438 } 4439 4440} 4441 4442class Box3 { 4443 4444 constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) { 4445 4446 this.isBox3 = true; 4447 4448 this.min = min; 4449 this.max = max; 4450 4451 } 4452 4453 set( min, max ) { 4454 4455 this.min.copy( min ); 4456 this.max.copy( max ); 4457 4458 return this; 4459 4460 } 4461 4462 setFromArray( array ) { 4463 4464 let minX = + Infinity; 4465 let minY = + Infinity; 4466 let minZ = + Infinity; 4467 4468 let maxX = - Infinity; 4469 let maxY = - Infinity; 4470 let maxZ = - Infinity; 4471 4472 for ( let i = 0, l = array.length; i < l; i += 3 ) { 4473 4474 const x = array[ i ]; 4475 const y = array[ i + 1 ]; 4476 const z = array[ i + 2 ]; 4477 4478 if ( x < minX ) minX = x; 4479 if ( y < minY ) minY = y; 4480 if ( z < minZ ) minZ = z; 4481 4482 if ( x > maxX ) maxX = x; 4483 if ( y > maxY ) maxY = y; 4484 if ( z > maxZ ) maxZ = z; 4485 4486 } 4487 4488 this.min.set( minX, minY, minZ ); 4489 this.max.set( maxX, maxY, maxZ ); 4490 4491 return this; 4492 4493 } 4494 4495 setFromBufferAttribute( attribute ) { 4496 4497 let minX = + Infinity; 4498 let minY = + Infinity; 4499 let minZ = + Infinity; 4500 4501 let maxX = - Infinity; 4502 let maxY = - Infinity; 4503 let maxZ = - Infinity; 4504 4505 for ( let i = 0, l = attribute.count; i < l; i ++ ) { 4506 4507 const x = attribute.getX( i ); 4508 const y = attribute.getY( i ); 4509 const z = attribute.getZ( i ); 4510 4511 if ( x < minX ) minX = x; 4512 if ( y < minY ) minY = y; 4513 if ( z < minZ ) minZ = z; 4514 4515 if ( x > maxX ) maxX = x; 4516 if ( y > maxY ) maxY = y; 4517 if ( z > maxZ ) maxZ = z; 4518 4519 } 4520 4521 this.min.set( minX, minY, minZ ); 4522 this.max.set( maxX, maxY, maxZ ); 4523 4524 return this; 4525 4526 } 4527 4528 setFromPoints( points ) { 4529 4530 this.makeEmpty(); 4531 4532 for ( let i = 0, il = points.length; i < il; i ++ ) { 4533 4534 this.expandByPoint( points[ i ] ); 4535 4536 } 4537 4538 return this; 4539 4540 } 4541 4542 setFromCenterAndSize( center, size ) { 4543 4544 const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); 4545 4546 this.min.copy( center ).sub( halfSize ); 4547 this.max.copy( center ).add( halfSize ); 4548 4549 return this; 4550 4551 } 4552 4553 setFromObject( object, precise = false ) { 4554 4555 this.makeEmpty(); 4556 4557 return this.expandByObject( object, precise ); 4558 4559 } 4560 4561 clone() { 4562 4563 return new this.constructor().copy( this ); 4564 4565 } 4566 4567 copy( box ) { 4568 4569 this.min.copy( box.min ); 4570 this.max.copy( box.max ); 4571 4572 return this; 4573 4574 } 4575 4576 makeEmpty() { 4577 4578 this.min.x = this.min.y = this.min.z = + Infinity; 4579 this.max.x = this.max.y = this.max.z = - Infinity; 4580 4581 return this; 4582 4583 } 4584 4585 isEmpty() { 4586 4587 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes 4588 4589 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); 4590 4591 } 4592 4593 getCenter( target ) { 4594 4595 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); 4596 4597 } 4598 4599 getSize( target ) { 4600 4601 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min ); 4602 4603 } 4604 4605 expandByPoint( point ) { 4606 4607 this.min.min( point ); 4608 this.max.max( point ); 4609 4610 return this; 4611 4612 } 4613 4614 expandByVector( vector ) { 4615 4616 this.min.sub( vector ); 4617 this.max.add( vector ); 4618 4619 return this; 4620 4621 } 4622 4623 expandByScalar( scalar ) { 4624 4625 this.min.addScalar( - scalar ); 4626 this.max.addScalar( scalar ); 4627 4628 return this; 4629 4630 } 4631 4632 expandByObject( object, precise = false ) { 4633
vendor: 12,498 bytes, lines 4634-5227
4634 // Computes the world-axis-aligned bounding box of an object (including its children), 4635 // accounting for both the object's, and children's, world transforms 4636 4637 object.updateWorldMatrix( false, false ); 4638 4639 const geometry = object.geometry; 4640 4641 if ( geometry !== undefined ) { 4642 4643 if ( precise && geometry.attributes != undefined && geometry.attributes.position !== undefined ) { 4644 4645 const position = geometry.attributes.position; 4646 for ( let i = 0, l = position.count; i < l; i ++ ) { 4647 4648 _vector$b.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld ); 4649 this.expandByPoint( _vector$b ); 4650 4651 } 4652 4653 } else { 4654 4655 if ( geometry.boundingBox === null ) { 4656 4657 geometry.computeBoundingBox(); 4658 4659 } 4660 4661 _box$3.copy( geometry.boundingBox ); 4662 _box$3.applyMatrix4( object.matrixWorld ); 4663 4664 this.union( _box$3 ); 4665 4666 } 4667 4668 } 4669 4670 const children = object.children; 4671 4672 for ( let i = 0, l = children.length; i < l; i ++ ) { 4673 4674 this.expandByObject( children[ i ], precise ); 4675 4676 } 4677 4678 return this; 4679 4680 } 4681 4682 containsPoint( point ) { 4683 4684 return point.x < this.min.x || point.x > this.max.x || 4685 point.y < this.min.y || point.y > this.max.y || 4686 point.z < this.min.z || point.z > this.max.z ? false : true; 4687 4688 } 4689 4690 containsBox( box ) { 4691 4692 return this.min.x <= box.min.x && box.max.x <= this.max.x && 4693 this.min.y <= box.min.y && box.max.y <= this.max.y && 4694 this.min.z <= box.min.z && box.max.z <= this.max.z; 4695 4696 } 4697 4698 getParameter( point, target ) { 4699 4700 // This can potentially have a divide by zero if the box 4701 // has a size dimension of 0. 4702 4703 return target.set( 4704 ( point.x - this.min.x ) / ( this.max.x - this.min.x ), 4705 ( point.y - this.min.y ) / ( this.max.y - this.min.y ), 4706 ( point.z - this.min.z ) / ( this.max.z - this.min.z ) 4707 ); 4708 4709 } 4710 4711 intersectsBox( box ) { 4712 4713 // using 6 splitting planes to rule out intersections. 4714 return box.max.x < this.min.x || box.min.x > this.max.x || 4715 box.max.y < this.min.y || box.min.y > this.max.y || 4716 box.max.z < this.min.z || box.min.z > this.max.z ? false : true; 4717 4718 } 4719 4720 intersectsSphere( sphere ) { 4721 4722 // Find the point on the AABB closest to the sphere center. 4723 this.clampPoint( sphere.center, _vector$b ); 4724 4725 // If that point is inside the sphere, the AABB and sphere intersect. 4726 return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); 4727 4728 } 4729 4730 intersectsPlane( plane ) { 4731 4732 // We compute the minimum and maximum dot product values. If those values 4733 // are on the same side (back or front) of the plane, then there is no intersection. 4734 4735 let min, max; 4736 4737 if ( plane.normal.x > 0 ) { 4738 4739 min = plane.normal.x * this.min.x; 4740 max = plane.normal.x * this.max.x; 4741 4742 } else { 4743 4744 min = plane.normal.x * this.max.x; 4745 max = plane.normal.x * this.min.x; 4746 4747 } 4748 4749 if ( plane.normal.y > 0 ) { 4750 4751 min += plane.normal.y * this.min.y; 4752 max += plane.normal.y * this.max.y; 4753 4754 } else { 4755 4756 min += plane.normal.y * this.max.y; 4757 max += plane.normal.y * this.min.y; 4758 4759 } 4760 4761 if ( plane.normal.z > 0 ) { 4762 4763 min += plane.normal.z * this.min.z; 4764 max += plane.normal.z * this.max.z; 4765 4766 } else { 4767 4768 min += plane.normal.z * this.max.z; 4769 max += plane.normal.z * this.min.z; 4770 4771 } 4772 4773 return ( min <= - plane.constant && max >= - plane.constant ); 4774 4775 } 4776 4777 intersectsTriangle( triangle ) { 4778 4779 if ( this.isEmpty() ) { 4780 4781 return false; 4782 4783 } 4784 4785 // compute box center and extents 4786 this.getCenter( _center ); 4787 _extents.subVectors( this.max, _center ); 4788 4789 // translate triangle to aabb origin 4790 _v0$2.subVectors( triangle.a, _center ); 4791 _v1$7.subVectors( triangle.b, _center ); 4792 _v2$4.subVectors( triangle.c, _center ); 4793 4794 // compute edge vectors for triangle 4795 _f0.subVectors( _v1$7, _v0$2 ); 4796 _f1.subVectors( _v2$4, _v1$7 ); 4797 _f2.subVectors( _v0$2, _v2$4 ); 4798 4799 // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb 4800 // make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation 4801 // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned) 4802 let axes = [ 4803 0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y, 4804 _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x, 4805 - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0 4806 ]; 4807 if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) { 4808 4809 return false; 4810 4811 } 4812 4813 // test 3 face normals from the aabb 4814 axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; 4815 if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) { 4816 4817 return false; 4818 4819 } 4820 4821 // finally testing the face normal of the triangle 4822 // use already existing triangle edge vectors here 4823 _triangleNormal.crossVectors( _f0, _f1 ); 4824 axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ]; 4825 4826 return satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ); 4827 4828 } 4829 4830 clampPoint( point, target ) { 4831 4832 return target.copy( point ).clamp( this.min, this.max ); 4833 4834 } 4835 4836 distanceToPoint( point ) { 4837 4838 return this.clampPoint( point, _vector$b ).distanceTo( point ); 4839 4840 } 4841 4842 getBoundingSphere( target ) { 4843 4844 if ( this.isEmpty() ) { 4845 4846 target.makeEmpty(); 4847 4848 } else { 4849 4850 this.getCenter( target.center ); 4851 4852 target.radius = this.getSize( _vector$b ).length() * 0.5; 4853 4854 } 4855 4856 return target; 4857 4858 } 4859 4860 intersect( box ) { 4861 4862 this.min.max( box.min ); 4863 this.max.min( box.max ); 4864 4865 // 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. 4866 if ( this.isEmpty() ) this.makeEmpty(); 4867 4868 return this; 4869 4870 } 4871 4872 union( box ) { 4873 4874 this.min.min( box.min ); 4875 this.max.max( box.max ); 4876 4877 return this; 4878 4879 } 4880 4881 applyMatrix4( matrix ) { 4882 4883 // transform of empty box is an empty box. 4884 if ( this.isEmpty() ) return this; 4885 4886 // NOTE: I am using a binary pattern to specify all 2^3 combinations below 4887 _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 4888 _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 4889 _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 4890 _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 4891 _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 4892 _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 4893 _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 4894 _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 4895 4896 this.setFromPoints( _points ); 4897 4898 return this; 4899 4900 } 4901 4902 translate( offset ) { 4903 4904 this.min.add( offset ); 4905 this.max.add( offset ); 4906 4907 return this; 4908 4909 } 4910 4911 equals( box ) { 4912 4913 return box.min.equals( this.min ) && box.max.equals( this.max ); 4914 4915 } 4916 4917} 4918 4919const _points = [ 4920 /*@__PURE__*/ new Vector3(), 4921 /*@__PURE__*/ new Vector3(), 4922 /*@__PURE__*/ new Vector3(), 4923 /*@__PURE__*/ new Vector3(), 4924 /*@__PURE__*/ new Vector3(), 4925 /*@__PURE__*/ new Vector3(), 4926 /*@__PURE__*/ new Vector3(), 4927 /*@__PURE__*/ new Vector3() 4928]; 4929 4930const _vector$b = /*@__PURE__*/ new Vector3(); 4931 4932const _box$3 = /*@__PURE__*/ new Box3(); 4933 4934// triangle centered vertices 4935 4936const _v0$2 = /*@__PURE__*/ new Vector3(); 4937const _v1$7 = /*@__PURE__*/ new Vector3(); 4938const _v2$4 = /*@__PURE__*/ new Vector3(); 4939 4940// triangle edge vectors 4941 4942const _f0 = /*@__PURE__*/ new Vector3(); 4943const _f1 = /*@__PURE__*/ new Vector3(); 4944const _f2 = /*@__PURE__*/ new Vector3(); 4945 4946const _center = /*@__PURE__*/ new Vector3(); 4947const _extents = /*@__PURE__*/ new Vector3(); 4948const _triangleNormal = /*@__PURE__*/ new Vector3(); 4949const _testAxis = /*@__PURE__*/ new Vector3(); 4950 4951function satForAxes( axes, v0, v1, v2, extents ) { 4952 4953 for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) { 4954 4955 _testAxis.fromArray( axes, i ); 4956 // project the aabb onto the separating axis 4957 const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z ); 4958 // project all 3 vertices of the triangle onto the separating axis 4959 const p0 = v0.dot( _testAxis ); 4960 const p1 = v1.dot( _testAxis ); 4961 const p2 = v2.dot( _testAxis ); 4962 // actual test, basically see if either of the most extreme of the triangle points intersects r 4963 if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) { 4964 4965 // points of the projected triangle are outside the projected half-length of the aabb 4966 // the axis is separating and we can exit 4967 return false; 4968 4969 } 4970 4971 } 4972 4973 return true; 4974 4975} 4976 4977const _box$2 = /*@__PURE__*/ new Box3(); 4978const _v1$6 = /*@__PURE__*/ new Vector3(); 4979const _v2$3 = /*@__PURE__*/ new Vector3(); 4980 4981class Sphere { 4982 4983 constructor( center = new Vector3(), radius = - 1 ) { 4984 4985 this.center = center; 4986 this.radius = radius; 4987 4988 } 4989 4990 set( center, radius ) { 4991 4992 this.center.copy( center ); 4993 this.radius = radius; 4994 4995 return this; 4996 4997 } 4998 4999 setFromPoints( points, optionalCenter ) { 5000 5001 const center = this.center; 5002 5003 if ( optionalCenter !== undefined ) { 5004 5005 center.copy( optionalCenter ); 5006 5007 } else { 5008 5009 _box$2.setFromPoints( points ).getCenter( center ); 5010 5011 } 5012 5013 let maxRadiusSq = 0; 5014 5015 for ( let i = 0, il = points.length; i < il; i ++ ) { 5016 5017 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); 5018 5019 } 5020 5021 this.radius = Math.sqrt( maxRadiusSq ); 5022 5023 return this; 5024 5025 } 5026 5027 copy( sphere ) { 5028 5029 this.center.copy( sphere.center ); 5030 this.radius = sphere.radius; 5031 5032 return this; 5033 5034 } 5035 5036 isEmpty() { 5037 5038 return ( this.radius < 0 ); 5039 5040 } 5041 5042 makeEmpty() { 5043 5044 this.center.set( 0, 0, 0 ); 5045 this.radius = - 1; 5046 5047 return this; 5048 5049 } 5050 5051 containsPoint( point ) { 5052 5053 return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); 5054 5055 } 5056 5057 distanceToPoint( point ) { 5058 5059 return ( point.distanceTo( this.center ) - this.radius ); 5060 5061 } 5062 5063 intersectsSphere( sphere ) { 5064 5065 const radiusSum = this.radius + sphere.radius; 5066 5067 return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); 5068 5069 } 5070 5071 intersectsBox( box ) { 5072 5073 return box.intersectsSphere( this ); 5074 5075 } 5076 5077 intersectsPlane( plane ) { 5078 5079 return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; 5080 5081 } 5082 5083 clampPoint( point, target ) { 5084 5085 const deltaLengthSq = this.center.distanceToSquared( point ); 5086 5087 target.copy( point ); 5088 5089 if ( deltaLengthSq > ( this.radius * this.radius ) ) { 5090 5091 target.sub( this.center ).normalize(); 5092 target.multiplyScalar( this.radius ).add( this.center ); 5093 5094 } 5095 5096 return target; 5097 5098 } 5099 5100 getBoundingBox( target ) { 5101 5102 if ( this.isEmpty() ) { 5103 5104 // Empty sphere produces empty bounding box 5105 target.makeEmpty(); 5106 return target; 5107 5108 } 5109 5110 target.set( this.center, this.center ); 5111 target.expandByScalar( this.radius ); 5112 5113 return target; 5114 5115 } 5116 5117 applyMatrix4( matrix ) { 5118 5119 this.center.applyMatrix4( matrix ); 5120 this.radius = this.radius * matrix.getMaxScaleOnAxis(); 5121 5122 return this; 5123 5124 } 5125 5126 translate( offset ) { 5127 5128 this.center.add( offset ); 5129 5130 return this; 5131 5132 } 5133 5134 expandByPoint( point ) { 5135 5136 if ( this.isEmpty() ) { 5137 5138 this.center.copy( point ); 5139 5140 this.radius = 0; 5141 5142 return this; 5143 5144 } 5145 5146 _v1$6.subVectors( point, this.center ); 5147 5148 const lengthSq = _v1$6.lengthSq(); 5149 5150 if ( lengthSq > ( this.radius * this.radius ) ) { 5151 5152 // calculate the minimal sphere 5153 5154 const length = Math.sqrt( lengthSq ); 5155 5156 const delta = ( length - this.radius ) * 0.5; 5157 5158 this.center.addScaledVector( _v1$6, delta / length ); 5159 5160 this.radius += delta; 5161 5162 } 5163 5164 return this; 5165 5166 } 5167 5168 union( sphere ) { 5169 5170 if ( sphere.isEmpty() ) { 5171 5172 return this; 5173 5174 } 5175 5176 if ( this.isEmpty() ) { 5177 5178 this.copy( sphere ); 5179 5180 return this; 5181 5182 } 5183 5184 if ( this.center.equals( sphere.center ) === true ) { 5185 5186 this.radius = Math.max( this.radius, sphere.radius ); 5187 5188 } else { 5189 5190 _v2$3.subVectors( sphere.center, this.center ).setLength( sphere.radius ); 5191 5192 this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) ); 5193 5194 this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) ); 5195 5196 } 5197 5198 return this; 5199 5200 } 5201 5202 equals( sphere ) { 5203 5204 return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); 5205 5206 } 5207 5208 clone() { 5209 5210 return new this.constructor().copy( this ); 5211 5212 } 5213 5214} 5215 5216const _vector$a = /*@__PURE__*/ new Vector3(); 5217const _segCenter = /*@__PURE__*/ new Vector3(); 5218const _segDir = /*@__PURE__*/ new Vector3(); 5219const _diff = /*@__PURE__*/ new Vector3(); 5220 5221const _edge1 = /*@__PURE__*/ new Vector3(); 5222const _edge2 = /*@__PURE__*/ new Vector3(); 5223const _normal$1 = /*@__PURE__*/ new Vector3(); 5224 5225class Ray { 5226 5227 constructor( origin = new Vector3(), direction = new Vector3( 0, 0, -
vendor: 8,510 bytes, lines 5227-5633
52271 ) ) { 5228 5229 this.origin = origin; 5230 this.direction = direction; 5231 5232 } 5233 5234 set( origin, direction ) { 5235 5236 this.origin.copy( origin ); 5237 this.direction.copy( direction ); 5238 5239 return this; 5240 5241 } 5242 5243 copy( ray ) { 5244 5245 this.origin.copy( ray.origin ); 5246 this.direction.copy( ray.direction ); 5247 5248 return this; 5249 5250 } 5251 5252 at( t, target ) { 5253 5254 return target.copy( this.origin ).addScaledVector( this.direction, t ); 5255 5256 } 5257 5258 lookAt( v ) { 5259 5260 this.direction.copy( v ).sub( this.origin ).normalize(); 5261 5262 return this; 5263 5264 } 5265 5266 recast( t ) { 5267 5268 this.origin.copy( this.at( t, _vector$a ) ); 5269 5270 return this; 5271 5272 } 5273 5274 closestPointToPoint( point, target ) { 5275 5276 target.subVectors( point, this.origin ); 5277 5278 const directionDistance = target.dot( this.direction ); 5279 5280 if ( directionDistance < 0 ) { 5281 5282 return target.copy( this.origin ); 5283 5284 } 5285 5286 return target.copy( this.origin ).addScaledVector( this.direction, directionDistance ); 5287 5288 } 5289 5290 distanceToPoint( point ) { 5291 5292 return Math.sqrt( this.distanceSqToPoint( point ) ); 5293 5294 } 5295 5296 distanceSqToPoint( point ) { 5297 5298 const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); 5299 5300 // point behind the ray 5301 5302 if ( directionDistance < 0 ) { 5303 5304 return this.origin.distanceToSquared( point ); 5305 5306 } 5307 5308 _vector$a.copy( this.origin ).addScaledVector( this.direction, directionDistance ); 5309 5310 return _vector$a.distanceToSquared( point ); 5311 5312 } 5313 5314 distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { 5315 5316 // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h 5317 // It returns the min distance between the ray and the segment 5318 // defined by v0 and v1 5319 // It can also set two optional targets : 5320 // - The closest point on the ray 5321 // - The closest point on the segment 5322 5323 _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); 5324 _segDir.copy( v1 ).sub( v0 ).normalize(); 5325 _diff.copy( this.origin ).sub( _segCenter ); 5326 5327 const segExtent = v0.distanceTo( v1 ) * 0.5; 5328 const a01 = - this.direction.dot( _segDir ); 5329 const b0 = _diff.dot( this.direction ); 5330 const b1 = - _diff.dot( _segDir ); 5331 const c = _diff.lengthSq(); 5332 const det = Math.abs( 1 - a01 * a01 ); 5333 let s0, s1, sqrDist, extDet; 5334 5335 if ( det > 0 ) { 5336 5337 // The ray and segment are not parallel. 5338 5339 s0 = a01 * b1 - b0; 5340 s1 = a01 * b0 - b1; 5341 extDet = segExtent * det; 5342 5343 if ( s0 >= 0 ) { 5344 5345 if ( s1 >= - extDet ) { 5346 5347 if ( s1 <= extDet ) { 5348 5349 // region 0 5350 // Minimum at interior points of ray and segment. 5351 5352 const invDet = 1 / det; 5353 s0 *= invDet; 5354 s1 *= invDet; 5355 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; 5356 5357 } else { 5358 5359 // region 1 5360 5361 s1 = segExtent; 5362 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 5363 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5364 5365 } 5366 5367 } else { 5368 5369 // region 5 5370 5371 s1 = - segExtent; 5372 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 5373 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5374 5375 } 5376 5377 } else { 5378 5379 if ( s1 <= - extDet ) { 5380 5381 // region 4 5382 5383 s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) ); 5384 s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); 5385 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5386 5387 } else if ( s1 <= extDet ) { 5388 5389 // region 3 5390 5391 s0 = 0; 5392 s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); 5393 sqrDist = s1 * ( s1 + 2 * b1 ) + c; 5394 5395 } else { 5396 5397 // region 2 5398 5399 s0 = Math.max( 0, - ( a01 * segExtent + b0 ) ); 5400 s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); 5401 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5402 5403 } 5404 5405 } 5406 5407 } else { 5408 5409 // Ray and segment are parallel. 5410 5411 s1 = ( a01 > 0 ) ? - segExtent : segExtent; 5412 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 5413 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5414 5415 } 5416 5417 if ( optionalPointOnRay ) { 5418 5419 optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 ); 5420 5421 } 5422 5423 if ( optionalPointOnSegment ) { 5424 5425 optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 ); 5426 5427 } 5428 5429 return sqrDist; 5430 5431 } 5432 5433 intersectSphere( sphere, target ) { 5434 5435 _vector$a.subVectors( sphere.center, this.origin ); 5436 const tca = _vector$a.dot( this.direction ); 5437 const d2 = _vector$a.dot( _vector$a ) - tca * tca; 5438 const radius2 = sphere.radius * sphere.radius; 5439 5440 if ( d2 > radius2 ) return null; 5441 5442 const thc = Math.sqrt( radius2 - d2 ); 5443 5444 // t0 = first intersect point - entrance on front of sphere 5445 const t0 = tca - thc; 5446 5447 // t1 = second intersect point - exit point on back of sphere 5448 const t1 = tca + thc; 5449 5450 // test to see if t1 is behind the ray - if so, return null 5451 if ( t1 < 0 ) return null; 5452 5453 // test to see if t0 is behind the ray: 5454 // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, 5455 // in order to always return an intersect point that is in front of the ray. 5456 if ( t0 < 0 ) return this.at( t1, target ); 5457 5458 // else t0 is in front of the ray, so return the first collision point scaled by t0 5459 return this.at( t0, target ); 5460 5461 } 5462 5463 intersectsSphere( sphere ) { 5464 5465 return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius ); 5466 5467 } 5468 5469 distanceToPlane( plane ) { 5470 5471 const denominator = plane.normal.dot( this.direction ); 5472 5473 if ( denominator === 0 ) { 5474 5475 // line is coplanar, return origin 5476 if ( plane.distanceToPoint( this.origin ) === 0 ) { 5477 5478 return 0; 5479 5480 } 5481 5482 // Null is preferable to undefined since undefined means.... it is undefined 5483 5484 return null; 5485 5486 } 5487 5488 const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; 5489 5490 // Return if the ray never intersects the plane 5491 5492 return t >= 0 ? t : null; 5493 5494 } 5495 5496 intersectPlane( plane, target ) { 5497 5498 const t = this.distanceToPlane( plane ); 5499 5500 if ( t === null ) { 5501 5502 return null; 5503 5504 } 5505 5506 return this.at( t, target ); 5507 5508 } 5509 5510 intersectsPlane( plane ) { 5511 5512 // check if the ray lies on the plane first 5513 5514 const distToPoint = plane.distanceToPoint( this.origin ); 5515 5516 if ( distToPoint === 0 ) { 5517 5518 return true; 5519 5520 } 5521 5522 const denominator = plane.normal.dot( this.direction ); 5523 5524 if ( denominator * distToPoint < 0 ) { 5525 5526 return true; 5527 5528 } 5529 5530 // ray origin is behind the plane (and is pointing behind it) 5531 5532 return false; 5533 5534 } 5535 5536 intersectBox( box, target ) { 5537 5538 let tmin, tmax, tymin, tymax, tzmin, tzmax; 5539 5540 const invdirx = 1 / this.direction.x, 5541 invdiry = 1 / this.direction.y, 5542 invdirz = 1 / this.direction.z; 5543 5544 const origin = this.origin; 5545 5546 if ( invdirx >= 0 ) { 5547 5548 tmin = ( box.min.x - origin.x ) * invdirx; 5549 tmax = ( box.max.x - origin.x ) * invdirx; 5550 5551 } else { 5552 5553 tmin = ( box.max.x - origin.x ) * invdirx; 5554 tmax = ( box.min.x - origin.x ) * invdirx; 5555 5556 } 5557 5558 if ( invdiry >= 0 ) { 5559 5560 tymin = ( box.min.y - origin.y ) * invdiry; 5561 tymax = ( box.max.y - origin.y ) * invdiry; 5562 5563 } else { 5564 5565 tymin = ( box.max.y - origin.y ) * invdiry; 5566 tymax = ( box.min.y - origin.y ) * invdiry; 5567 5568 } 5569 5570 if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; 5571 5572 if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin; 5573 5574 if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax; 5575 5576 if ( invdirz >= 0 ) { 5577 5578 tzmin = ( box.min.z - origin.z ) * invdirz; 5579 tzmax = ( box.max.z - origin.z ) * invdirz; 5580 5581 } else { 5582 5583 tzmin = ( box.max.z - origin.z ) * invdirz; 5584 tzmax = ( box.min.z - origin.z ) * invdirz; 5585 5586 } 5587 5588 if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; 5589 5590 if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; 5591 5592 if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; 5593 5594 //return point closest to the ray (positive side) 5595 5596 if ( tmax < 0 ) return null; 5597 5598 return this.at( tmin >= 0 ? tmin : tmax, target ); 5599 5600 } 5601 5602 intersectsBox( box ) { 5603 5604 return this.intersectBox( box, _vector$a ) !== null; 5605 5606 } 5607 5608 intersectTriangle( a, b, c, backfaceCulling, target ) { 5609 5610 // Compute the offset origin, edges, and normal. 5611 5612 // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h 5613 5614 _edge1.subVectors( b, a ); 5615 _edge2.subVectors( c, a ); 5616 _normal$1.crossVectors( _edge1, _edge2 ); 5617 5618 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, 5619 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by 5620 // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) 5621 // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) 5622 // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) 5623 let DdN = this.direction.dot( _normal$1 ); 5624 let sign; 5625 5626 if ( DdN > 0 ) { 5627 5628 if ( backfaceCulling ) return null; 5629 sign = 1; 5630 5631 } else if ( DdN < 0 ) { 5632 5633 sign = -
5633 1; 5634 DdN = - DdN; 5635 5636 } else { 5637 5638 return null; 5639 5640 } 5641 5642 _diff.subVectors( this.origin, a ); 5643 const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) ); 5644 5645 // b1 < 0, no intersection 5646 if ( DdQxE2 < 0 ) { 5647 5648 return null; 5649 5650 } 5651 5652 const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) ); 5653 5654 // b2 < 0, no intersection 5655 if ( DdE1xQ < 0 ) { 5656 5657 return null; 5658 5659 } 5660 5661 // b1+b2 > 1, no intersection 5662 if ( DdQxE2 + DdE1xQ > DdN ) { 5663 5664 return null; 5665 5666 } 5667 5668 // Line intersects triangle, check if ray does.
vendor: 661 bytes, lines 5669-5719
5669 const QdN = - sign * _diff.dot( _normal$1 ); 5670 5671 // t < 0, no intersection 5672 if ( QdN < 0 ) { 5673 5674 return null; 5675 5676 } 5677 5678 // Ray intersects triangle. 5679 return this.at( QdN / DdN, target ); 5680 5681 } 5682 5683 applyMatrix4( matrix4 ) { 5684 5685 this.origin.applyMatrix4( matrix4 ); 5686 this.direction.transformDirection( matrix4 ); 5687 5688 return this; 5689 5690 } 5691 5692 equals( ray ) { 5693 5694 return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); 5695 5696 } 5697 5698 clone() { 5699 5700 return new this.constructor().copy( this ); 5701 5702 } 5703 5704} 5705 5706class Matrix4 { 5707 5708 constructor() { 5709 5710 Matrix4.prototype.isMatrix4 = true; 5711 5712 this.elements = [ 5713 5714 1, 0, 0, 0, 5715 0, 1, 0, 0, 5716 0, 0, 1, 0, 5717 0, 0, 0, 1 5718 5719 ];
vendor: 12,702 bytes, lines 5719-6260
5719 5720 5721 } 5722 5723 set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { 5724 5725 const te = this.elements; 5726 5727 te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14; 5728 te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24; 5729 te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34; 5730 te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44; 5731 5732 return this; 5733 5734 } 5735 5736 identity() { 5737 5738 this.set( 5739 5740 1, 0, 0, 0, 5741 0, 1, 0, 0, 5742 0, 0, 1, 0, 5743 0, 0, 0, 1 5744 5745 ); 5746 5747 return this; 5748 5749 } 5750 5751 clone() { 5752 5753 return new Matrix4().fromArray( this.elements ); 5754 5755 } 5756 5757 copy( m ) { 5758 5759 const te = this.elements; 5760 const me = m.elements; 5761 5762 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ]; 5763 te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; 5764 te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ]; 5765 te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ]; 5766 5767 return this; 5768 5769 } 5770 5771 copyPosition( m ) { 5772 5773 const te = this.elements, me = m.elements; 5774 5775 te[ 12 ] = me[ 12 ]; 5776 te[ 13 ] = me[ 13 ]; 5777 te[ 14 ] = me[ 14 ]; 5778 5779 return this; 5780 5781 } 5782 5783 setFromMatrix3( m ) { 5784 5785 const me = m.elements; 5786 5787 this.set( 5788 5789 me[ 0 ], me[ 3 ], me[ 6 ], 0, 5790 me[ 1 ], me[ 4 ], me[ 7 ], 0, 5791 me[ 2 ], me[ 5 ], me[ 8 ], 0, 5792 0, 0, 0, 1 5793 5794 ); 5795 5796 return this; 5797 5798 } 5799 5800 extractBasis( xAxis, yAxis, zAxis ) { 5801 5802 xAxis.setFromMatrixColumn( this, 0 ); 5803 yAxis.setFromMatrixColumn( this, 1 ); 5804 zAxis.setFromMatrixColumn( this, 2 ); 5805 5806 return this; 5807 5808 } 5809 5810 makeBasis( xAxis, yAxis, zAxis ) { 5811 5812 this.set( 5813 xAxis.x, yAxis.x, zAxis.x, 0, 5814 xAxis.y, yAxis.y, zAxis.y, 0, 5815 xAxis.z, yAxis.z, zAxis.z, 0, 5816 0, 0, 0, 1 5817 ); 5818 5819 return this; 5820 5821 } 5822 5823 extractRotation( m ) { 5824 5825 // this method does not support reflection matrices 5826 5827 const te = this.elements; 5828 const me = m.elements; 5829 5830 const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length(); 5831 const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length(); 5832 const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length(); 5833 5834 te[ 0 ] = me[ 0 ] * scaleX; 5835 te[ 1 ] = me[ 1 ] * scaleX; 5836 te[ 2 ] = me[ 2 ] * scaleX; 5837 te[ 3 ] = 0; 5838 5839 te[ 4 ] = me[ 4 ] * scaleY; 5840 te[ 5 ] = me[ 5 ] * scaleY; 5841 te[ 6 ] = me[ 6 ] * scaleY; 5842 te[ 7 ] = 0; 5843 5844 te[ 8 ] = me[ 8 ] * scaleZ; 5845 te[ 9 ] = me[ 9 ] * scaleZ; 5846 te[ 10 ] = me[ 10 ] * scaleZ; 5847 te[ 11 ] = 0; 5848 5849 te[ 12 ] = 0; 5850 te[ 13 ] = 0; 5851 te[ 14 ] = 0; 5852 te[ 15 ] = 1; 5853 5854 return this; 5855 5856 } 5857 5858 makeRotationFromEuler( euler ) { 5859 5860 const te = this.elements; 5861 5862 const x = euler.x, y = euler.y, z = euler.z; 5863 const a = Math.cos( x ), b = Math.sin( x ); 5864 const c = Math.cos( y ), d = Math.sin( y ); 5865 const e = Math.cos( z ), f = Math.sin( z ); 5866 5867 if ( euler.order === 'XYZ' ) { 5868 5869 const ae = a * e, af = a * f, be = b * e, bf = b * f; 5870 5871 te[ 0 ] = c * e; 5872 te[ 4 ] = - c * f; 5873 te[ 8 ] = d; 5874 5875 te[ 1 ] = af + be * d; 5876 te[ 5 ] = ae - bf * d; 5877 te[ 9 ] = - b * c; 5878 5879 te[ 2 ] = bf - ae * d; 5880 te[ 6 ] = be + af * d; 5881 te[ 10 ] = a * c; 5882 5883 } else if ( euler.order === 'YXZ' ) { 5884 5885 const ce = c * e, cf = c * f, de = d * e, df = d * f; 5886 5887 te[ 0 ] = ce + df * b; 5888 te[ 4 ] = de * b - cf; 5889 te[ 8 ] = a * d; 5890 5891 te[ 1 ] = a * f; 5892 te[ 5 ] = a * e; 5893 te[ 9 ] = - b; 5894 5895 te[ 2 ] = cf * b - de; 5896 te[ 6 ] = df + ce * b; 5897 te[ 10 ] = a * c; 5898 5899 } else if ( euler.order === 'ZXY' ) { 5900 5901 const ce = c * e, cf = c * f, de = d * e, df = d * f; 5902 5903 te[ 0 ] = ce - df * b; 5904 te[ 4 ] = - a * f; 5905 te[ 8 ] = de + cf * b; 5906 5907 te[ 1 ] = cf + de * b; 5908 te[ 5 ] = a * e; 5909 te[ 9 ] = df - ce * b; 5910 5911 te[ 2 ] = - a * d; 5912 te[ 6 ] = b; 5913 te[ 10 ] = a * c; 5914 5915 } else if ( euler.order === 'ZYX' ) { 5916 5917 const ae = a * e, af = a * f, be = b * e, bf = b * f; 5918 5919 te[ 0 ] = c * e; 5920 te[ 4 ] = be * d - af; 5921 te[ 8 ] = ae * d + bf; 5922 5923 te[ 1 ] = c * f; 5924 te[ 5 ] = bf * d + ae; 5925 te[ 9 ] = af * d - be; 5926 5927 te[ 2 ] = - d; 5928 te[ 6 ] = b * c; 5929 te[ 10 ] = a * c; 5930 5931 } else if ( euler.order === 'YZX' ) { 5932 5933 const ac = a * c, ad = a * d, bc = b * c, bd = b * d; 5934 5935 te[ 0 ] = c * e; 5936 te[ 4 ] = bd - ac * f; 5937 te[ 8 ] = bc * f + ad; 5938 5939 te[ 1 ] = f; 5940 te[ 5 ] = a * e; 5941 te[ 9 ] = - b * e; 5942 5943 te[ 2 ] = - d * e; 5944 te[ 6 ] = ad * f + bc; 5945 te[ 10 ] = ac - bd * f; 5946 5947 } else if ( euler.order === 'XZY' ) { 5948 5949 const ac = a * c, ad = a * d, bc = b * c, bd = b * d; 5950 5951 te[ 0 ] = c * e; 5952 te[ 4 ] = - f; 5953 te[ 8 ] = d * e; 5954 5955 te[ 1 ] = ac * f + bd; 5956 te[ 5 ] = a * e; 5957 te[ 9 ] = ad * f - bc; 5958 5959 te[ 2 ] = bc * f - ad; 5960 te[ 6 ] = b * e; 5961 te[ 10 ] = bd * f + ac; 5962 5963 } 5964 5965 // bottom row 5966 te[ 3 ] = 0; 5967 te[ 7 ] = 0; 5968 te[ 11 ] = 0; 5969 5970 // last column 5971 te[ 12 ] = 0; 5972 te[ 13 ] = 0; 5973 te[ 14 ] = 0; 5974 te[ 15 ] = 1; 5975 5976 return this; 5977 5978 } 5979 5980 makeRotationFromQuaternion( q ) { 5981 5982 return this.compose( _zero, q, _one ); 5983 5984 } 5985 5986 lookAt( eye, target, up ) { 5987 5988 const te = this.elements; 5989 5990 _z.subVectors( eye, target ); 5991 5992 if ( _z.lengthSq() === 0 ) { 5993 5994 // eye and target are in the same position 5995 5996 _z.z = 1; 5997 5998 } 5999 6000 _z.normalize(); 6001 _x.crossVectors( up, _z ); 6002 6003 if ( _x.lengthSq() === 0 ) { 6004 6005 // up and z are parallel 6006 6007 if ( Math.abs( up.z ) === 1 ) { 6008 6009 _z.x += 0.0001; 6010 6011 } else { 6012 6013 _z.z += 0.0001; 6014 6015 } 6016 6017 _z.normalize(); 6018 _x.crossVectors( up, _z ); 6019 6020 } 6021 6022 _x.normalize(); 6023 _y.crossVectors( _z, _x ); 6024 6025 te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x; 6026 te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y; 6027 te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z; 6028 6029 return this; 6030 6031 } 6032 6033 multiply( m ) { 6034 6035 return this.multiplyMatrices( this, m ); 6036 6037 } 6038 6039 premultiply( m ) { 6040 6041 return this.multiplyMatrices( m, this ); 6042 6043 } 6044 6045 multiplyMatrices( a, b ) { 6046 6047 const ae = a.elements; 6048 const be = b.elements; 6049 const te = this.elements; 6050 6051 const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ]; 6052 const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ]; 6053 const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ]; 6054 const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ]; 6055 6056 const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ]; 6057 const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ]; 6058 const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ]; 6059 const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ]; 6060 6061 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; 6062 te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; 6063 te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; 6064 te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; 6065 6066 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; 6067 te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; 6068 te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; 6069 te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; 6070 6071 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; 6072 te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; 6073 te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; 6074 te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; 6075 6076 te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; 6077 te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; 6078 te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; 6079 te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; 6080 6081 return this; 6082 6083 } 6084 6085 multiplyScalar( s ) { 6086 6087 const te = this.elements; 6088 6089 te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s; 6090 te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s; 6091 te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s; 6092 te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s; 6093 6094 return this; 6095 6096 } 6097 6098 determinant() { 6099 6100 const te = this.elements; 6101 6102 const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ]; 6103 const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ]; 6104 const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ]; 6105 const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ]; 6106 6107 //TODO: make this more efficient 6108 //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) 6109 6110 return ( 6111 n41 * ( 6112 + n14 * n23 * n32 6113 - n13 * n24 * n32 6114 - n14 * n22 * n33 6115 + n12 * n24 * n33 6116 + n13 * n22 * n34 6117 - n12 * n23 * n34 6118 ) + 6119 n42 * ( 6120 + n11 * n23 * n34 6121 - n11 * n24 * n33 6122 + n14 * n21 * n33 6123 - n13 * n21 * n34 6124 + n13 * n24 * n31 6125 - n14 * n23 * n31 6126 ) + 6127 n43 * ( 6128 + n11 * n24 * n32 6129 - n11 * n22 * n34 6130 - n14 * n21 * n32 6131 + n12 * n21 * n34 6132 + n14 * n22 * n31 6133 - n12 * n24 * n31 6134 ) + 6135 n44 * ( 6136 - n13 * n22 * n31 6137 - n11 * n23 * n32 6138 + n11 * n22 * n33 6139 + n13 * n21 * n32 6140 - n12 * n21 * n33 6141 + n12 * n23 * n31 6142 ) 6143 6144 ); 6145 6146 } 6147 6148 transpose() { 6149 6150 const te = this.elements; 6151 let tmp; 6152 6153 tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp; 6154 tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp; 6155 tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp; 6156 6157 tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp; 6158 tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp; 6159 tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp; 6160 6161 return this; 6162 6163 } 6164 6165 setPosition( x, y, z ) { 6166 6167 const te = this.elements; 6168 6169 if ( x.isVector3 ) { 6170 6171 te[ 12 ] = x.x; 6172 te[ 13 ] = x.y; 6173 te[ 14 ] = x.z; 6174 6175 } else { 6176 6177 te[ 12 ] = x; 6178 te[ 13 ] = y; 6179 te[ 14 ] = z; 6180 6181 } 6182 6183 return this; 6184 6185 } 6186 6187 invert() { 6188 6189 // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm 6190 const te = this.elements, 6191 6192 n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ], 6193 n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ], 6194 n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ], 6195 n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ], 6196 6197 t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44, 6198 t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44, 6199 t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44, 6200 t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34; 6201 6202 const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; 6203 6204 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); 6205 6206 const detInv = 1 / det; 6207 6208 te[ 0 ] = t11 * detInv; 6209 te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv; 6210 te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv; 6211 te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv; 6212 6213 te[ 4 ] = t12 * detInv; 6214 te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv; 6215 te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv; 6216 te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv; 6217 6218 te[ 8 ] = t13 * detInv; 6219 te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv; 6220 te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv; 6221 te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv; 6222 6223 te[ 12 ] = t14 * detInv; 6224 te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv; 6225 te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv; 6226 te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv; 6227 6228 return this; 6229 6230 } 6231 6232 scale( v ) { 6233 6234 const te = this.elements; 6235 const x = v.x, y = v.y, z = v.z; 6236 6237 te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; 6238 te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; 6239 te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; 6240 te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; 6241 6242 return this; 6243 6244 } 6245 6246 getMaxScaleOnAxis() { 6247 6248 const te = this.elements; 6249 6250 const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ]; 6251 const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ]; 6252 const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ]; 6253 6254 return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); 6255 6256 } 6257 6258 makeTranslation( x, y, z ) { 6259 6260
vendor: 2,013 bytes, lines 6260-6398
6260this.set( 6261 6262 1, 0, 0, x, 6263 0, 1, 0, y, 6264 0, 0, 1, z, 6265 0, 0, 0, 1 6266 6267 ); 6268 6269 return this; 6270 6271 } 6272 6273 makeRotationX( theta ) { 6274 6275 const c = Math.cos( theta ), s = Math.sin( theta ); 6276 6277 this.set( 6278 6279 1, 0, 0, 0, 6280 0, c, - s, 0, 6281 0, s, c, 0, 6282 0, 0, 0, 1 6283 6284 ); 6285 6286 return this; 6287 6288 } 6289 6290 makeRotationY( theta ) { 6291 6292 const c = Math.cos( theta ), s = Math.sin( theta ); 6293 6294 this.set( 6295 6296 c, 0, s, 0, 6297 0, 1, 0, 0, 6298 - s, 0, c, 0, 6299 0, 0, 0, 1 6300 6301 ); 6302 6303 return this; 6304 6305 } 6306 6307 makeRotationZ( theta ) { 6308 6309 const c = Math.cos( theta ), s = Math.sin( theta ); 6310 6311 this.set( 6312 6313 c, - s, 0, 0, 6314 s, c, 0, 0, 6315 0, 0, 1, 0, 6316 0, 0, 0, 1 6317 6318 ); 6319 6320 return this; 6321 6322 } 6323 6324 makeRotationAxis( axis, angle ) { 6325 6326 // Based on http://www.gamedev.net/reference/articles/article1199.asp 6327 6328 const c = Math.cos( angle ); 6329 const s = Math.sin( angle ); 6330 const t = 1 - c; 6331 const x = axis.x, y = axis.y, z = axis.z; 6332 const tx = t * x, ty = t * y; 6333 6334 this.set( 6335 6336 tx * x + c, tx * y - s * z, tx * z + s * y, 0, 6337 tx * y + s * z, ty * y + c, ty * z - s * x, 0, 6338 tx * z - s * y, ty * z + s * x, t * z * z + c, 0, 6339 0, 0, 0, 1 6340 6341 ); 6342 6343 return this; 6344 6345 } 6346 6347 makeScale( x, y, z ) { 6348 6349 this.set( 6350 6351 x, 0, 0, 0, 6352 0, y, 0, 0, 6353 0, 0, z, 0, 6354 0, 0, 0, 1 6355 6356 ); 6357 6358 return this; 6359 6360 } 6361 6362 makeShear( xy, xz, yx, yz, zx, zy ) { 6363 6364 this.set( 6365 6366 1, yx, zx, 0, 6367 xy, 1, zy, 0, 6368 xz, yz, 1, 0, 6369 0, 0, 0, 1 6370 6371 ); 6372 6373 return this; 6374 6375 } 6376 6377 compose( position, quaternion, scale ) { 6378 6379 const te = this.elements; 6380 6381 const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w; 6382 const x2 = x + x, y2 = y + y, z2 = z + z; 6383 const xx = x * x2, xy = x * y2, xz = x * z2; 6384 const yy = y * y2, yz = y * z2, zz = z * z2; 6385 const wx = w * x2, wy = w * y2, wz = w * z2; 6386 6387 const sx = scale.x, sy = scale.y, sz = scale.z; 6388 6389 te[ 0 ] = ( 1 - ( yy + zz ) ) * sx; 6390 te[ 1 ] = ( xy + wz ) * sx; 6391 te[ 2 ] = ( xz - wy ) * sx; 6392 te[ 3 ] = 0; 6393 6394 te[ 4 ] = ( xy - wz ) * sy; 6395 te[ 5 ] = ( 1 - ( xx + zz ) ) * sy; 6396 te[ 6 ] = ( yz + wx ) * sy; 6397 te[ 7 ] = 0; 6398
vendor: 4,294 bytes, lines 6399-6620
6399 te[ 8 ] = ( xz + wy ) * sz; 6400 te[ 9 ] = ( yz - wx ) * sz; 6401 te[ 10 ] = ( 1 - ( xx + yy ) ) * sz; 6402 te[ 11 ] = 0; 6403 6404 te[ 12 ] = position.x; 6405 te[ 13 ] = position.y; 6406 te[ 14 ] = position.z; 6407 te[ 15 ] = 1; 6408 6409 return this; 6410 6411 } 6412 6413 decompose( position, quaternion, scale ) { 6414 6415 const te = this.elements; 6416 6417 let sx = _v1$5.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); 6418 const sy = _v1$5.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); 6419 const sz = _v1$5.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); 6420 6421 // if determine is negative, we need to invert one scale 6422 const det = this.determinant(); 6423 if ( det < 0 ) sx = - sx; 6424 6425 position.x = te[ 12 ]; 6426 position.y = te[ 13 ]; 6427 position.z = te[ 14 ]; 6428 6429 // scale the rotation part 6430 _m1$2.copy( this ); 6431 6432 const invSX = 1 / sx; 6433 const invSY = 1 / sy; 6434 const invSZ = 1 / sz; 6435 6436 _m1$2.elements[ 0 ] *= invSX; 6437 _m1$2.elements[ 1 ] *= invSX; 6438 _m1$2.elements[ 2 ] *= invSX; 6439 6440 _m1$2.elements[ 4 ] *= invSY; 6441 _m1$2.elements[ 5 ] *= invSY; 6442 _m1$2.elements[ 6 ] *= invSY; 6443 6444 _m1$2.elements[ 8 ] *= invSZ; 6445 _m1$2.elements[ 9 ] *= invSZ; 6446 _m1$2.elements[ 10 ] *= invSZ; 6447 6448 quaternion.setFromRotationMatrix( _m1$2 ); 6449 6450 scale.x = sx; 6451 scale.y = sy; 6452 scale.z = sz; 6453 6454 return this; 6455 6456 } 6457 6458 makePerspective( left, right, top, bottom, near, far ) { 6459 6460 const te = this.elements; 6461 const x = 2 * near / ( right - left ); 6462 const y = 2 * near / ( top - bottom ); 6463 6464 const a = ( right + left ) / ( right - left ); 6465 const b = ( top + bottom ) / ( top - bottom ); 6466 const c = - ( far + near ) / ( far - near ); 6467 const d = - 2 * far * near / ( far - near ); 6468 6469 te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; 6470 te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; 6471 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; 6472 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; 6473 6474 return this; 6475 6476 } 6477 6478 makeOrthographic( left, right, top, bottom, near, far ) { 6479 6480 const te = this.elements; 6481 const w = 1.0 / ( right - left ); 6482 const h = 1.0 / ( top - bottom ); 6483 const p = 1.0 / ( far - near ); 6484 6485 const x = ( right + left ) * w; 6486 const y = ( top + bottom ) * h; 6487 const z = ( far + near ) * p; 6488 6489 te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; 6490 te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; 6491 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 * p; te[ 14 ] = - z; 6492 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; 6493 6494 return this; 6495 6496 } 6497 6498 equals( matrix ) { 6499 6500 const te = this.elements; 6501 const me = matrix.elements; 6502 6503 for ( let i = 0; i < 16; i ++ ) { 6504 6505 if ( te[ i ] !== me[ i ] ) return false; 6506 6507 } 6508 6509 return true; 6510 6511 } 6512 6513 fromArray( array, offset = 0 ) { 6514 6515 for ( let i = 0; i < 16; i ++ ) { 6516 6517 this.elements[ i ] = array[ i + offset ]; 6518 6519 } 6520 6521 return this; 6522 6523 } 6524 6525 toArray( array = [], offset = 0 ) { 6526 6527 const te = this.elements; 6528 6529 array[ offset ] = te[ 0 ]; 6530 array[ offset + 1 ] = te[ 1 ]; 6531 array[ offset + 2 ] = te[ 2 ]; 6532 array[ offset + 3 ] = te[ 3 ]; 6533 6534 array[ offset + 4 ] = te[ 4 ]; 6535 array[ offset + 5 ] = te[ 5 ]; 6536 array[ offset + 6 ] = te[ 6 ]; 6537 array[ offset + 7 ] = te[ 7 ]; 6538 6539 array[ offset + 8 ] = te[ 8 ]; 6540 array[ offset + 9 ] = te[ 9 ]; 6541 array[ offset + 10 ] = te[ 10 ]; 6542 array[ offset + 11 ] = te[ 11 ]; 6543 6544 array[ offset + 12 ] = te[ 12 ]; 6545 array[ offset + 13 ] = te[ 13 ]; 6546 array[ offset + 14 ] = te[ 14 ]; 6547 array[ offset + 15 ] = te[ 15 ]; 6548 6549 return array; 6550 6551 } 6552 6553} 6554 6555const _v1$5 = /*@__PURE__*/ new Vector3(); 6556const _m1$2 = /*@__PURE__*/ new Matrix4(); 6557const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 ); 6558const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 ); 6559const _x = /*@__PURE__*/ new Vector3(); 6560const _y = /*@__PURE__*/ new Vector3(); 6561const _z = /*@__PURE__*/ new Vector3(); 6562 6563const _matrix$1 = /*@__PURE__*/ new Matrix4(); 6564const _quaternion$3 = /*@__PURE__*/ new Quaternion(); 6565 6566class Euler { 6567 6568 constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) { 6569 6570 this.isEuler = true; 6571 6572 this._x = x; 6573 this._y = y; 6574 this._z = z; 6575 this._order = order; 6576 6577 } 6578 6579 get x() { 6580 6581 return this._x; 6582 6583 } 6584 6585 set x( value ) { 6586 6587 this._x = value; 6588 this._onChangeCallback(); 6589 6590 } 6591 6592 get y() { 6593 6594 return this._y; 6595 6596 } 6597 6598 set y( value ) { 6599 6600 this._y = value; 6601 this._onChangeCallback(); 6602 6603 } 6604 6605 get z() { 6606 6607 return this._z; 6608 6609 } 6610 6611 set z( value ) { 6612 6613 this._z = value; 6614 this._onChangeCallback(); 6615 6616 } 6617 6618 get order() { 6619 6620 return this._order;
vendor: 23,201 bytes, lines 6621-7937
6621 6622 } 6623 6624 set order( value ) { 6625 6626 this._order = value; 6627 this._onChangeCallback(); 6628 6629 } 6630 6631 set( x, y, z, order = this._order ) { 6632 6633 this._x = x; 6634 this._y = y; 6635 this._z = z; 6636 this._order = order; 6637 6638 this._onChangeCallback(); 6639 6640 return this; 6641 6642 } 6643 6644 clone() { 6645 6646 return new this.constructor( this._x, this._y, this._z, this._order ); 6647 6648 } 6649 6650 copy( euler ) { 6651 6652 this._x = euler._x; 6653 this._y = euler._y; 6654 this._z = euler._z; 6655 this._order = euler._order; 6656 6657 this._onChangeCallback(); 6658 6659 return this; 6660 6661 } 6662 6663 setFromRotationMatrix( m, order = this._order, update = true ) { 6664 6665 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 6666 6667 const te = m.elements; 6668 const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ]; 6669 const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ]; 6670 const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; 6671 6672 switch ( order ) { 6673 6674 case 'XYZ': 6675 6676 this._y = Math.asin( clamp( m13, - 1, 1 ) ); 6677 6678 if ( Math.abs( m13 ) < 0.9999999 ) { 6679 6680 this._x = Math.atan2( - m23, m33 ); 6681 this._z = Math.atan2( - m12, m11 ); 6682 6683 } else { 6684 6685 this._x = Math.atan2( m32, m22 ); 6686 this._z = 0; 6687 6688 } 6689 6690 break; 6691 6692 case 'YXZ': 6693 6694 this._x = Math.asin( - clamp( m23, - 1, 1 ) ); 6695 6696 if ( Math.abs( m23 ) < 0.9999999 ) { 6697 6698 this._y = Math.atan2( m13, m33 ); 6699 this._z = Math.atan2( m21, m22 ); 6700 6701 } else { 6702 6703 this._y = Math.atan2( - m31, m11 ); 6704 this._z = 0; 6705 6706 } 6707 6708 break; 6709 6710 case 'ZXY': 6711 6712 this._x = Math.asin( clamp( m32, - 1, 1 ) ); 6713 6714 if ( Math.abs( m32 ) < 0.9999999 ) { 6715 6716 this._y = Math.atan2( - m31, m33 ); 6717 this._z = Math.atan2( - m12, m22 ); 6718 6719 } else { 6720 6721 this._y = 0; 6722 this._z = Math.atan2( m21, m11 ); 6723 6724 } 6725 6726 break; 6727 6728 case 'ZYX': 6729 6730 this._y = Math.asin( - clamp( m31, - 1, 1 ) ); 6731 6732 if ( Math.abs( m31 ) < 0.9999999 ) { 6733 6734 this._x = Math.atan2( m32, m33 ); 6735 this._z = Math.atan2( m21, m11 ); 6736 6737 } else { 6738 6739 this._x = 0; 6740 this._z = Math.atan2( - m12, m22 ); 6741 6742 } 6743 6744 break; 6745 6746 case 'YZX': 6747 6748 this._z = Math.asin( clamp( m21, - 1, 1 ) ); 6749 6750 if ( Math.abs( m21 ) < 0.9999999 ) { 6751 6752 this._x = Math.atan2( - m23, m22 ); 6753 this._y = Math.atan2( - m31, m11 ); 6754 6755 } else { 6756 6757 this._x = 0; 6758 this._y = Math.atan2( m13, m33 ); 6759 6760 } 6761 6762 break; 6763 6764 case 'XZY': 6765 6766 this._z = Math.asin( - clamp( m12, - 1, 1 ) ); 6767 6768 if ( Math.abs( m12 ) < 0.9999999 ) { 6769 6770 this._x = Math.atan2( m32, m22 ); 6771 this._y = Math.atan2( m13, m11 ); 6772 6773 } else { 6774 6775 this._x = Math.atan2( - m23, m33 ); 6776 this._y = 0; 6777 6778 } 6779 6780 break; 6781 6782 default: 6783 6784 console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order ); 6785 6786 } 6787 6788 this._order = order; 6789 6790 if ( update === true ) this._onChangeCallback(); 6791 6792 return this; 6793 6794 } 6795 6796 setFromQuaternion( q, order, update ) { 6797 6798 _matrix$1.makeRotationFromQuaternion( q ); 6799 6800 return this.setFromRotationMatrix( _matrix$1, order, update ); 6801 6802 } 6803 6804 setFromVector3( v, order = this._order ) { 6805 6806 return this.set( v.x, v.y, v.z, order ); 6807 6808 } 6809 6810 reorder( newOrder ) { 6811 6812 // WARNING: this discards revolution information -bhouston 6813 6814 _quaternion$3.setFromEuler( this ); 6815 6816 return this.setFromQuaternion( _quaternion$3, newOrder ); 6817 6818 } 6819 6820 equals( euler ) { 6821 6822 return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); 6823 6824 } 6825 6826 fromArray( array ) { 6827 6828 this._x = array[ 0 ]; 6829 this._y = array[ 1 ]; 6830 this._z = array[ 2 ]; 6831 if ( array[ 3 ] !== undefined ) this._order = array[ 3 ]; 6832 6833 this._onChangeCallback(); 6834 6835 return this; 6836 6837 } 6838 6839 toArray( array = [], offset = 0 ) { 6840 6841 array[ offset ] = this._x; 6842 array[ offset + 1 ] = this._y; 6843 array[ offset + 2 ] = this._z; 6844 array[ offset + 3 ] = this._order; 6845 6846 return array; 6847 6848 } 6849 6850 _onChange( callback ) { 6851 6852 this._onChangeCallback = callback; 6853 6854 return this; 6855 6856 } 6857 6858 _onChangeCallback() {} 6859 6860 *[ Symbol.iterator ]() { 6861 6862 yield this._x; 6863 yield this._y; 6864 yield this._z; 6865 yield this._order; 6866 6867 } 6868 6869} 6870 6871Euler.DEFAULT_ORDER = 'XYZ'; 6872 6873class Layers { 6874 6875 constructor() { 6876 6877 this.mask = 1 | 0; 6878 6879 } 6880 6881 set( channel ) { 6882 6883 this.mask = ( 1 << channel | 0 ) >>> 0; 6884 6885 } 6886 6887 enable( channel ) { 6888 6889 this.mask |= 1 << channel | 0; 6890 6891 } 6892 6893 enableAll() { 6894 6895 this.mask = 0xffffffff | 0; 6896 6897 } 6898 6899 toggle( channel ) { 6900 6901 this.mask ^= 1 << channel | 0; 6902 6903 } 6904 6905 disable( channel ) { 6906 6907 this.mask &= ~ ( 1 << channel | 0 ); 6908 6909 } 6910 6911 disableAll() { 6912 6913 this.mask = 0; 6914 6915 } 6916 6917 test( layers ) { 6918 6919 return ( this.mask & layers.mask ) !== 0; 6920 6921 } 6922 6923 isEnabled( channel ) { 6924 6925 return ( this.mask & ( 1 << channel | 0 ) ) !== 0; 6926 6927 } 6928 6929} 6930 6931let _object3DId = 0; 6932 6933const _v1$4 = /*@__PURE__*/ new Vector3(); 6934const _q1 = /*@__PURE__*/ new Quaternion(); 6935const _m1$1 = /*@__PURE__*/ new Matrix4(); 6936const _target = /*@__PURE__*/ new Vector3(); 6937 6938const _position$3 = /*@__PURE__*/ new Vector3(); 6939const _scale$2 = /*@__PURE__*/ new Vector3(); 6940const _quaternion$2 = /*@__PURE__*/ new Quaternion(); 6941 6942const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 ); 6943const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 ); 6944const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 ); 6945 6946const _addedEvent = { type: 'added' }; 6947const _removedEvent = { type: 'removed' }; 6948 6949class Object3D extends EventDispatcher { 6950 6951 constructor() { 6952 6953 super(); 6954 6955 this.isObject3D = true; 6956 6957 Object.defineProperty( this, 'id', { value: _object3DId ++ } ); 6958 6959 this.uuid = generateUUID(); 6960 6961 this.name = ''; 6962 this.type = 'Object3D'; 6963 6964 this.parent = null; 6965 this.children = []; 6966 6967 this.up = Object3D.DEFAULT_UP.clone(); 6968 6969 const position = new Vector3(); 6970 const rotation = new Euler(); 6971 const quaternion = new Quaternion(); 6972 const scale = new Vector3( 1, 1, 1 ); 6973 6974 function onRotationChange() { 6975 6976 quaternion.setFromEuler( rotation, false ); 6977 6978 } 6979 6980 function onQuaternionChange() { 6981 6982 rotation.setFromQuaternion( quaternion, undefined, false ); 6983 6984 } 6985 6986 rotation._onChange( onRotationChange ); 6987 quaternion._onChange( onQuaternionChange ); 6988 6989 Object.defineProperties( this, { 6990 position: { 6991 configurable: true, 6992 enumerable: true, 6993 value: position 6994 }, 6995 rotation: { 6996 configurable: true, 6997 enumerable: true, 6998 value: rotation 6999 }, 7000 quaternion: { 7001 configurable: true, 7002 enumerable: true, 7003 value: quaternion 7004 }, 7005 scale: { 7006 configurable: true, 7007 enumerable: true, 7008 value: scale 7009 }, 7010 modelViewMatrix: { 7011 value: new Matrix4() 7012 }, 7013 normalMatrix: { 7014 value: new Matrix3() 7015 } 7016 } ); 7017 7018 this.matrix = new Matrix4(); 7019 this.matrixWorld = new Matrix4(); 7020 7021 this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE; 7022 this.matrixWorldNeedsUpdate = false; 7023 7024 this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer 7025 7026 this.layers = new Layers(); 7027 this.visible = true; 7028 7029 this.castShadow = false; 7030 this.receiveShadow = false; 7031 7032 this.frustumCulled = true; 7033 this.renderOrder = 0; 7034 7035 this.animations = []; 7036 7037 this.userData = {}; 7038 7039 } 7040 7041 onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {} 7042 7043 onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {} 7044 7045 applyMatrix4( matrix ) { 7046 7047 if ( this.matrixAutoUpdate ) this.updateMatrix(); 7048 7049 this.matrix.premultiply( matrix ); 7050 7051 this.matrix.decompose( this.position, this.quaternion, this.scale ); 7052 7053 } 7054 7055 applyQuaternion( q ) { 7056 7057 this.quaternion.premultiply( q ); 7058 7059 return this; 7060 7061 } 7062 7063 setRotationFromAxisAngle( axis, angle ) { 7064 7065 // assumes axis is normalized 7066 7067 this.quaternion.setFromAxisAngle( axis, angle ); 7068 7069 } 7070 7071 setRotationFromEuler( euler ) { 7072 7073 this.quaternion.setFromEuler( euler, true ); 7074 7075 } 7076 7077 setRotationFromMatrix( m ) { 7078 7079 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 7080 7081 this.quaternion.setFromRotationMatrix( m ); 7082 7083 } 7084 7085 setRotationFromQuaternion( q ) { 7086 7087 // assumes q is normalized 7088 7089 this.quaternion.copy( q ); 7090 7091 } 7092 7093 rotateOnAxis( axis, angle ) { 7094 7095 // rotate object on axis in object space 7096 // axis is assumed to be normalized 7097 7098 _q1.setFromAxisAngle( axis, angle ); 7099 7100 this.quaternion.multiply( _q1 ); 7101 7102 return this; 7103 7104 } 7105 7106 rotateOnWorldAxis( axis, angle ) { 7107 7108 // rotate object on axis in world space 7109 // axis is assumed to be normalized 7110 // method assumes no rotated parent 7111 7112 _q1.setFromAxisAngle( axis, angle ); 7113 7114 this.quaternion.premultiply( _q1 ); 7115 7116 return this; 7117 7118 } 7119 7120 rotateX( angle ) { 7121 7122 return this.rotateOnAxis( _xAxis, angle ); 7123 7124 } 7125 7126 rotateY( angle ) { 7127 7128 return this.rotateOnAxis( _yAxis, angle ); 7129 7130 } 7131 7132 rotateZ( angle ) { 7133 7134 return this.rotateOnAxis( _zAxis, angle ); 7135 7136 } 7137 7138 translateOnAxis( axis, distance ) { 7139 7140 // translate object by distance along axis in object space 7141 // axis is assumed to be normalized 7142 7143 _v1$4.copy( axis ).applyQuaternion( this.quaternion ); 7144 7145 this.position.add( _v1$4.multiplyScalar( distance ) ); 7146 7147 return this; 7148 7149 } 7150 7151 translateX( distance ) { 7152 7153 return this.translateOnAxis( _xAxis, distance ); 7154 7155 } 7156 7157 translateY( distance ) { 7158 7159 return this.translateOnAxis( _yAxis, distance ); 7160 7161 } 7162 7163 translateZ( distance ) { 7164 7165 return this.translateOnAxis( _zAxis, distance ); 7166 7167 } 7168 7169 localToWorld( vector ) { 7170 7171 this.updateWorldMatrix( true, false ); 7172 7173 return vector.applyMatrix4( this.matrixWorld ); 7174 7175 } 7176 7177 worldToLocal( vector ) { 7178 7179 this.updateWorldMatrix( true, false ); 7180 7181 return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() ); 7182 7183 } 7184 7185 lookAt( x, y, z ) { 7186 7187 // This method does not support objects having non-uniformly-scaled parent(s) 7188 7189 if ( x.isVector3 ) { 7190 7191 _target.copy( x ); 7192 7193 } else { 7194 7195 _target.set( x, y, z ); 7196 7197 } 7198 7199 const parent = this.parent; 7200 7201 this.updateWorldMatrix( true, false ); 7202 7203 _position$3.setFromMatrixPosition( this.matrixWorld ); 7204 7205 if ( this.isCamera || this.isLight ) { 7206 7207 _m1$1.lookAt( _position$3, _target, this.up ); 7208 7209 } else { 7210 7211 _m1$1.lookAt( _target, _position$3, this.up ); 7212 7213 } 7214 7215 this.quaternion.setFromRotationMatrix( _m1$1 ); 7216 7217 if ( parent ) { 7218 7219 _m1$1.extractRotation( parent.matrixWorld ); 7220 _q1.setFromRotationMatrix( _m1$1 ); 7221 this.quaternion.premultiply( _q1.invert() ); 7222 7223 } 7224 7225 } 7226 7227 add( object ) { 7228 7229 if ( arguments.length > 1 ) { 7230 7231 for ( let i = 0; i < arguments.length; i ++ ) { 7232 7233 this.add( arguments[ i ] ); 7234 7235 } 7236 7237 return this; 7238 7239 } 7240 7241 if ( object === this ) { 7242 7243 console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object ); 7244 return this; 7245 7246 } 7247 7248 if ( object && object.isObject3D ) { 7249 7250 if ( object.parent !== null ) { 7251 7252 object.parent.remove( object ); 7253 7254 } 7255 7256 object.parent = this; 7257 this.children.push( object ); 7258 7259 object.dispatchEvent( _addedEvent ); 7260 7261 } else { 7262 7263 console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object ); 7264 7265 } 7266 7267 return this; 7268 7269 } 7270 7271 remove( object ) { 7272 7273 if ( arguments.length > 1 ) { 7274 7275 for ( let i = 0; i < arguments.length; i ++ ) { 7276 7277 this.remove( arguments[ i ] ); 7278 7279 } 7280 7281 return this; 7282 7283 } 7284 7285 const index = this.children.indexOf( object ); 7286 7287 if ( index !== - 1 ) { 7288 7289 object.parent = null; 7290 this.children.splice( index, 1 ); 7291 7292 object.dispatchEvent( _removedEvent ); 7293 7294 } 7295 7296 return this; 7297 7298 } 7299 7300 removeFromParent() { 7301 7302 const parent = this.parent; 7303 7304 if ( parent !== null ) { 7305 7306 parent.remove( this ); 7307 7308 } 7309 7310 return this; 7311 7312 } 7313 7314 clear() { 7315 7316 for ( let i = 0; i < this.children.length; i ++ ) { 7317 7318 const object = this.children[ i ]; 7319 7320 object.parent = null; 7321 7322 object.dispatchEvent( _removedEvent ); 7323 7324 } 7325 7326 this.children.length = 0; 7327 7328 return this; 7329 7330 7331 } 7332 7333 attach( object ) { 7334 7335 // adds object as a child of this, while maintaining the object's world transform 7336 7337 // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s) 7338 7339 this.updateWorldMatrix( true, false ); 7340 7341 _m1$1.copy( this.matrixWorld ).invert(); 7342 7343 if ( object.parent !== null ) { 7344 7345 object.parent.updateWorldMatrix( true, false ); 7346 7347 _m1$1.multiply( object.parent.matrixWorld ); 7348 7349 } 7350 7351 object.applyMatrix4( _m1$1 ); 7352 7353 this.add( object ); 7354 7355 object.updateWorldMatrix( false, true ); 7356 7357 return this; 7358 7359 } 7360 7361 getObjectById( id ) { 7362 7363 return this.getObjectByProperty( 'id', id ); 7364 7365 } 7366 7367 getObjectByName( name ) { 7368 7369 return this.getObjectByProperty( 'name', name ); 7370 7371 } 7372 7373 getObjectByProperty( name, value ) { 7374 7375 if ( this[ name ] === value ) return this; 7376 7377 for ( let i = 0, l = this.children.length; i < l; i ++ ) { 7378 7379 const child = this.children[ i ]; 7380 const object = child.getObjectByProperty( name, value ); 7381 7382 if ( object !== undefined ) { 7383 7384 return object; 7385 7386 } 7387 7388 } 7389 7390 return undefined; 7391 7392 } 7393 7394 getObjectsByProperty( name, value ) { 7395 7396 let result = []; 7397 7398 if ( this[ name ] === value ) result.push( this ); 7399 7400 for ( let i = 0, l = this.children.length; i < l; i ++ ) { 7401 7402 const childResult = this.children[ i ].getObjectsByProperty( name, value ); 7403 7404 if ( childResult.length > 0 ) { 7405 7406 result = result.concat( childResult ); 7407 7408 } 7409 7410 } 7411 7412 return result; 7413 7414 } 7415 7416 getWorldPosition( target ) { 7417 7418 this.updateWorldMatrix( true, false ); 7419 7420 return target.setFromMatrixPosition( this.matrixWorld ); 7421 7422 } 7423 7424 getWorldQuaternion( target ) { 7425 7426 this.updateWorldMatrix( true, false ); 7427 7428 this.matrixWorld.decompose( _position$3, target, _scale$2 ); 7429 7430 return target; 7431 7432 } 7433 7434 getWorldScale( target ) { 7435 7436 this.updateWorldMatrix( true, false ); 7437 7438 this.matrixWorld.decompose( _position$3, _quaternion$2, target ); 7439 7440 return target; 7441 7442 } 7443 7444 getWorldDirection( target ) { 7445 7446 this.updateWorldMatrix( true, false ); 7447 7448 const e = this.matrixWorld.elements; 7449 7450 return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize(); 7451 7452 } 7453 7454 raycast( /* raycaster, intersects */ ) {} 7455 7456 traverse( callback ) { 7457 7458 callback( this ); 7459 7460 const children = this.children; 7461 7462 for ( let i = 0, l = children.length; i < l; i ++ ) { 7463 7464 children[ i ].traverse( callback ); 7465 7466 } 7467 7468 } 7469 7470 traverseVisible( callback ) { 7471 7472 if ( this.visible === false ) return; 7473 7474 callback( this ); 7475 7476 const children = this.children; 7477 7478 for ( let i = 0, l = children.length; i < l; i ++ ) { 7479 7480 children[ i ].traverseVisible( callback ); 7481 7482 } 7483 7484 } 7485 7486 traverseAncestors( callback ) { 7487 7488 const parent = this.parent; 7489 7490 if ( parent !== null ) { 7491 7492 callback( parent ); 7493 7494 parent.traverseAncestors( callback ); 7495 7496 } 7497 7498 } 7499 7500 updateMatrix() { 7501 7502 this.matrix.compose( this.position, this.quaternion, this.scale ); 7503 7504 this.matrixWorldNeedsUpdate = true; 7505 7506 } 7507 7508 updateMatrixWorld( force ) { 7509 7510 if ( this.matrixAutoUpdate ) this.updateMatrix(); 7511 7512 if ( this.matrixWorldNeedsUpdate || force ) { 7513 7514 if ( this.parent === null ) { 7515 7516 this.matrixWorld.copy( this.matrix ); 7517 7518 } else { 7519 7520 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); 7521 7522 } 7523 7524 this.matrixWorldNeedsUpdate = false; 7525 7526 force = true; 7527 7528 } 7529 7530 // update children 7531 7532 const children = this.children; 7533 7534 for ( let i = 0, l = children.length; i < l; i ++ ) { 7535 7536 const child = children[ i ]; 7537 7538 if ( child.matrixWorldAutoUpdate === true || force === true ) { 7539 7540 child.updateMatrixWorld( force ); 7541 7542 } 7543 7544 } 7545 7546 } 7547 7548 updateWorldMatrix( updateParents, updateChildren ) { 7549 7550 const parent = this.parent; 7551 7552 if ( updateParents === true && parent !== null && parent.matrixWorldAutoUpdate === true ) { 7553 7554 parent.updateWorldMatrix( true, false ); 7555 7556 } 7557 7558 if ( this.matrixAutoUpdate ) this.updateMatrix(); 7559 7560 if ( this.parent === null ) { 7561 7562 this.matrixWorld.copy( this.matrix ); 7563 7564 } else { 7565 7566 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); 7567 7568 } 7569 7570 // update children 7571 7572 if ( updateChildren === true ) { 7573 7574 const children = this.children; 7575 7576 for ( let i = 0, l = children.length; i < l; i ++ ) { 7577 7578 const child = children[ i ]; 7579 7580 if ( child.matrixWorldAutoUpdate === true ) { 7581 7582 child.updateWorldMatrix( false, true ); 7583 7584 } 7585 7586 } 7587 7588 } 7589 7590 } 7591 7592 toJSON( meta ) { 7593 7594 // meta is a string when called from JSON.stringify 7595 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 7596 7597 const output = {}; 7598 7599 // meta is a hash used to collect geometries, materials. 7600 // not providing it implies that this is the root object 7601 // being serialized. 7602 if ( isRootObject ) { 7603 7604 // initialize meta obj 7605 meta = { 7606 geometries: {}, 7607 materials: {}, 7608 textures: {}, 7609 images: {}, 7610 shapes: {}, 7611 skeletons: {}, 7612 animations: {}, 7613 nodes: {} 7614 }; 7615 7616 output.metadata = { 7617 version: 4.5, 7618 type: 'Object', 7619 generator: 'Object3D.toJSON' 7620 }; 7621 7622 } 7623 7624 // standard Object3D serialization 7625 7626 const object = {}; 7627 7628 object.uuid = this.uuid; 7629 object.type = this.type; 7630 7631 if ( this.name !== '' ) object.name = this.name; 7632 if ( this.castShadow === true ) object.castShadow = true; 7633 if ( this.receiveShadow === true ) object.receiveShadow = true; 7634 if ( this.visible === false ) object.visible = false; 7635 if ( this.frustumCulled === false ) object.frustumCulled = false; 7636 if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder; 7637 if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData; 7638 7639 object.layers = this.layers.mask; 7640 object.matrix = this.matrix.toArray(); 7641 7642 if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; 7643 7644 // object specific properties 7645 7646 if ( this.isInstancedMesh ) { 7647 7648 object.type = 'InstancedMesh'; 7649 object.count = this.count; 7650 object.instanceMatrix = this.instanceMatrix.toJSON(); 7651 if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON(); 7652 7653 } 7654 7655 // 7656 7657 function serialize( library, element ) { 7658 7659 if ( library[ element.uuid ] === undefined ) { 7660 7661 library[ element.uuid ] = element.toJSON( meta ); 7662 7663 } 7664 7665 return element.uuid; 7666 7667 } 7668 7669 if ( this.isScene ) { 7670 7671 if ( this.background ) { 7672 7673 if ( this.background.isColor ) { 7674 7675 object.background = this.background.toJSON(); 7676 7677 } else if ( this.background.isTexture ) { 7678 7679 object.background = this.background.toJSON( meta ).uuid; 7680 7681 } 7682 7683 } 7684 7685 if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) { 7686 7687 object.environment = this.environment.toJSON( meta ).uuid; 7688 7689 } 7690 7691 } else if ( this.isMesh || this.isLine || this.isPoints ) { 7692 7693 object.geometry = serialize( meta.geometries, this.geometry ); 7694 7695 const parameters = this.geometry.parameters; 7696 7697 if ( parameters !== undefined && parameters.shapes !== undefined ) { 7698 7699 const shapes = parameters.shapes; 7700 7701 if ( Array.isArray( shapes ) ) { 7702 7703 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 7704 7705 const shape = shapes[ i ]; 7706 7707 serialize( meta.shapes, shape ); 7708 7709 } 7710 7711 } else { 7712 7713 serialize( meta.shapes, shapes ); 7714 7715 } 7716 7717 } 7718 7719 } 7720 7721 if ( this.isSkinnedMesh ) { 7722 7723 object.bindMode = this.bindMode; 7724 object.bindMatrix = this.bindMatrix.toArray(); 7725 7726 if ( this.skeleton !== undefined ) { 7727 7728 serialize( meta.skeletons, this.skeleton ); 7729 7730 object.skeleton = this.skeleton.uuid; 7731 7732 } 7733 7734 } 7735 7736 if ( this.material !== undefined ) { 7737 7738 if ( Array.isArray( this.material ) ) { 7739 7740 const uuids = []; 7741 7742 for ( let i = 0, l = this.material.length; i < l; i ++ ) { 7743 7744 uuids.push( serialize( meta.materials, this.material[ i ] ) ); 7745 7746 } 7747 7748 object.material = uuids; 7749 7750 } else { 7751 7752 object.material = serialize( meta.materials, this.material ); 7753 7754 } 7755 7756 } 7757 7758 // 7759 7760 if ( this.children.length > 0 ) { 7761 7762 object.children = []; 7763 7764 for ( let i = 0; i < this.children.length; i ++ ) { 7765 7766 object.children.push( this.children[ i ].toJSON( meta ).object ); 7767 7768 } 7769 7770 } 7771 7772 // 7773 7774 if ( this.animations.length > 0 ) { 7775 7776 object.animations = []; 7777 7778 for ( let i = 0; i < this.animations.length; i ++ ) { 7779 7780 const animation = this.animations[ i ]; 7781 7782 object.animations.push( serialize( meta.animations, animation ) ); 7783 7784 } 7785 7786 } 7787 7788 if ( isRootObject ) { 7789 7790 const geometries = extractFromCache( meta.geometries ); 7791 const materials = extractFromCache( meta.materials ); 7792 const textures = extractFromCache( meta.textures ); 7793 const images = extractFromCache( meta.images ); 7794 const shapes = extractFromCache( meta.shapes ); 7795 const skeletons = extractFromCache( meta.skeletons ); 7796 const animations = extractFromCache( meta.animations ); 7797 const nodes = extractFromCache( meta.nodes ); 7798 7799 if ( geometries.length > 0 ) output.geometries = geometries; 7800 if ( materials.length > 0 ) output.materials = materials; 7801 if ( textures.length > 0 ) output.textures = textures; 7802 if ( images.length > 0 ) output.images = images; 7803 if ( shapes.length > 0 ) output.shapes = shapes; 7804 if ( skeletons.length > 0 ) output.skeletons = skeletons; 7805 if ( animations.length > 0 ) output.animations = animations; 7806 if ( nodes.length > 0 ) output.nodes = nodes; 7807 7808 } 7809 7810 output.object = object; 7811 7812 return output; 7813 7814 // extract data from the cache hash 7815 // remove metadata on each item 7816 // and return as array 7817 function extractFromCache( cache ) { 7818 7819 const values = []; 7820 for ( const key in cache ) { 7821 7822 const data = cache[ key ]; 7823 delete data.metadata; 7824 values.push( data ); 7825 7826 } 7827 7828 return values; 7829 7830 } 7831 7832 } 7833 7834 clone( recursive ) { 7835 7836 return new this.constructor().copy( this, recursive ); 7837 7838 } 7839 7840 copy( source, recursive = true ) { 7841 7842 this.name = source.name; 7843 7844 this.up.copy( source.up ); 7845 7846 this.position.copy( source.position ); 7847 this.rotation.order = source.rotation.order; 7848 this.quaternion.copy( source.quaternion ); 7849 this.scale.copy( source.scale ); 7850 7851 this.matrix.copy( source.matrix ); 7852 this.matrixWorld.copy( source.matrixWorld ); 7853 7854 this.matrixAutoUpdate = source.matrixAutoUpdate; 7855 this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; 7856 7857 this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate; 7858 7859 this.layers.mask = source.layers.mask; 7860 this.visible = source.visible; 7861 7862 this.castShadow = source.castShadow; 7863 this.receiveShadow = source.receiveShadow; 7864 7865 this.frustumCulled = source.frustumCulled; 7866 this.renderOrder = source.renderOrder; 7867 7868 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 7869 7870 if ( recursive === true ) { 7871 7872 for ( let i = 0; i < source.children.length; i ++ ) { 7873 7874 const child = source.children[ i ]; 7875 this.add( child.clone() ); 7876 7877 } 7878 7879 } 7880 7881 return this; 7882 7883 } 7884 7885} 7886 7887Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 ); 7888Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true; 7889Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true; 7890 7891const _v0$1 = /*@__PURE__*/ new Vector3(); 7892const _v1$3 = /*@__PURE__*/ new Vector3(); 7893const _v2$2 = /*@__PURE__*/ new Vector3(); 7894const _v3$1 = /*@__PURE__*/ new Vector3(); 7895 7896const _vab = /*@__PURE__*/ new Vector3(); 7897const _vac = /*@__PURE__*/ new Vector3(); 7898const _vbc = /*@__PURE__*/ new Vector3(); 7899const _vap = /*@__PURE__*/ new Vector3(); 7900const _vbp = /*@__PURE__*/ new Vector3(); 7901const _vcp = /*@__PURE__*/ new Vector3(); 7902 7903class Triangle { 7904 7905 constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { 7906 7907 this.a = a; 7908 this.b = b; 7909 this.c = c; 7910 7911 } 7912 7913 static getNormal( a, b, c, target ) { 7914 7915 target.subVectors( c, b ); 7916 _v0$1.subVectors( a, b ); 7917 target.cross( _v0$1 ); 7918 7919 const targetLengthSq = target.lengthSq(); 7920 if ( targetLengthSq > 0 ) { 7921 7922 return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) ); 7923 7924 } 7925 7926 return target.set( 0, 0, 0 ); 7927 7928 } 7929 7930 // static/instance method to calculate barycentric coordinates 7931 // based on: http://www.blackpawn.com/texts/pointinpoly/default.html 7932 static getBarycoord( point, a, b, c, target ) { 7933 7934 _v0$1.subVectors( c, a ); 7935 _v1$3.subVectors( b, a ); 7936 _v2$2.subVectors( point, a ); 7937
vendor: 4,192 bytes, lines 7938-8140
7938 const dot00 = _v0$1.dot( _v0$1 ); 7939 const dot01 = _v0$1.dot( _v1$3 ); 7940 const dot02 = _v0$1.dot( _v2$2 ); 7941 const dot11 = _v1$3.dot( _v1$3 ); 7942 const dot12 = _v1$3.dot( _v2$2 ); 7943 7944 const denom = ( dot00 * dot11 - dot01 * dot01 ); 7945 7946 // collinear or singular triangle 7947 if ( denom === 0 ) { 7948 7949 // arbitrary location outside of triangle? 7950 // not sure if this is the best idea, maybe should be returning undefined 7951 return target.set( - 2, - 1, - 1 ); 7952 7953 } 7954 7955 const invDenom = 1 / denom; 7956 const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; 7957 const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; 7958 7959 // barycentric coordinates must always sum to 1 7960 return target.set( 1 - u - v, v, u ); 7961 7962 } 7963 7964 static containsPoint( point, a, b, c ) { 7965 7966 this.getBarycoord( point, a, b, c, _v3$1 ); 7967 7968 return ( _v3$1.x >= 0 ) && ( _v3$1.y >= 0 ) && ( ( _v3$1.x + _v3$1.y ) <= 1 ); 7969 7970 } 7971 7972 static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { 7973 7974 this.getBarycoord( point, p1, p2, p3, _v3$1 ); 7975 7976 target.set( 0, 0 ); 7977 target.addScaledVector( uv1, _v3$1.x ); 7978 target.addScaledVector( uv2, _v3$1.y ); 7979 target.addScaledVector( uv3, _v3$1.z ); 7980 7981 return target; 7982 7983 } 7984 7985 static isFrontFacing( a, b, c, direction ) { 7986 7987 _v0$1.subVectors( c, b ); 7988 _v1$3.subVectors( a, b ); 7989 7990 // strictly front facing 7991 return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false; 7992 7993 } 7994 7995 set( a, b, c ) { 7996 7997 this.a.copy( a ); 7998 this.b.copy( b ); 7999 this.c.copy( c ); 8000 8001 return this; 8002 8003 } 8004 8005 setFromPointsAndIndices( points, i0, i1, i2 ) { 8006 8007 this.a.copy( points[ i0 ] ); 8008 this.b.copy( points[ i1 ] ); 8009 this.c.copy( points[ i2 ] ); 8010 8011 return this; 8012 8013 } 8014 8015 setFromAttributeAndIndices( attribute, i0, i1, i2 ) { 8016 8017 this.a.fromBufferAttribute( attribute, i0 ); 8018 this.b.fromBufferAttribute( attribute, i1 ); 8019 this.c.fromBufferAttribute( attribute, i2 ); 8020 8021 return this; 8022 8023 } 8024 8025 clone() { 8026 8027 return new this.constructor().copy( this ); 8028 8029 } 8030 8031 copy( triangle ) { 8032 8033 this.a.copy( triangle.a ); 8034 this.b.copy( triangle.b ); 8035 this.c.copy( triangle.c ); 8036 8037 return this; 8038 8039 } 8040 8041 getArea() { 8042 8043 _v0$1.subVectors( this.c, this.b ); 8044 _v1$3.subVectors( this.a, this.b ); 8045 8046 return _v0$1.cross( _v1$3 ).length() * 0.5; 8047 8048 } 8049 8050 getMidpoint( target ) { 8051 8052 return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); 8053 8054 } 8055 8056 getNormal( target ) { 8057 8058 return Triangle.getNormal( this.a, this.b, this.c, target ); 8059 8060 } 8061 8062 getPlane( target ) { 8063 8064 return target.setFromCoplanarPoints( this.a, this.b, this.c ); 8065 8066 } 8067 8068 getBarycoord( point, target ) { 8069 8070 return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); 8071 8072 } 8073 8074 getUV( point, uv1, uv2, uv3, target ) { 8075 8076 return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target ); 8077 8078 } 8079 8080 containsPoint( point ) { 8081 8082 return Triangle.containsPoint( point, this.a, this.b, this.c ); 8083 8084 } 8085 8086 isFrontFacing( direction ) { 8087 8088 return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); 8089 8090 } 8091 8092 intersectsBox( box ) { 8093 8094 return box.intersectsTriangle( this ); 8095 8096 } 8097 8098 closestPointToPoint( p, target ) { 8099 8100 const a = this.a, b = this.b, c = this.c; 8101 let v, w; 8102 8103 // algorithm thanks to Real-Time Collision Detection by Christer Ericson, 8104 // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., 8105 // under the accompanying license; see chapter 5.1.5 for detailed explanation. 8106 // basically, we're distinguishing which of the voronoi regions of the triangle 8107 // the point lies in with the minimum amount of redundant computation. 8108 8109 _vab.subVectors( b, a ); 8110 _vac.subVectors( c, a ); 8111 _vap.subVectors( p, a ); 8112 const d1 = _vab.dot( _vap ); 8113 const d2 = _vac.dot( _vap ); 8114 if ( d1 <= 0 && d2 <= 0 ) { 8115 8116 // vertex region of A; barycentric coords (1, 0, 0) 8117 return target.copy( a ); 8118 8119 } 8120 8121 _vbp.subVectors( p, b ); 8122 const d3 = _vab.dot( _vbp ); 8123 const d4 = _vac.dot( _vbp ); 8124 if ( d3 >= 0 && d4 <= d3 ) { 8125 8126 // vertex region of B; barycentric coords (0, 1, 0) 8127 return target.copy( b ); 8128 8129 } 8130 8131 const vc = d1 * d4 - d3 * d2; 8132 if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { 8133 8134 v = d1 / ( d1 - d3 ); 8135 // edge region of AB; barycentric coords (1-v, v, 0) 8136 return target.copy( a ).addScaledVector( _vab, v ); 8137 8138 } 8139 8140 _vcp.subVectors( p, c );
vendor: 12,126 bytes, lines 8141-8540
8141 const d5 = _vab.dot( _vcp ); 8142 const d6 = _vac.dot( _vcp ); 8143 if ( d6 >= 0 && d5 <= d6 ) { 8144 8145 // vertex region of C; barycentric coords (0, 0, 1) 8146 return target.copy( c ); 8147 8148 } 8149 8150 const vb = d5 * d2 - d1 * d6; 8151 if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { 8152 8153 w = d2 / ( d2 - d6 ); 8154 // edge region of AC; barycentric coords (1-w, 0, w) 8155 return target.copy( a ).addScaledVector( _vac, w ); 8156 8157 } 8158 8159 const va = d3 * d6 - d5 * d4; 8160 if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { 8161 8162 _vbc.subVectors( c, b ); 8163 w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); 8164 // edge region of BC; barycentric coords (0, 1-w, w) 8165 return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC 8166 8167 } 8168 8169 // face region 8170 const denom = 1 / ( va + vb + vc ); 8171 // u = va * denom 8172 v = vb * denom; 8173 w = vc * denom; 8174 8175 return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); 8176 8177 } 8178 8179 equals( triangle ) { 8180 8181 return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); 8182 8183 } 8184 8185} 8186 8187let materialId = 0; 8188 8189class Material extends EventDispatcher { 8190 8191 constructor() { 8192 8193 super(); 8194 8195 this.isMaterial = true; 8196 8197 Object.defineProperty( this, 'id', { value: materialId ++ } ); 8198 8199 this.uuid = generateUUID(); 8200 8201 this.name = ''; 8202 this.type = 'Material'; 8203 8204 this.blending = NormalBlending; 8205 this.side = FrontSide; 8206 this.vertexColors = false; 8207 8208 this.opacity = 1; 8209 this.transparent = false; 8210 8211 this.blendSrc = SrcAlphaFactor; 8212 this.blendDst = OneMinusSrcAlphaFactor; 8213 this.blendEquation = AddEquation; 8214 this.blendSrcAlpha = null; 8215 this.blendDstAlpha = null; 8216 this.blendEquationAlpha = null; 8217 8218 this.depthFunc = LessEqualDepth; 8219 this.depthTest = true; 8220 this.depthWrite = true; 8221 8222 this.stencilWriteMask = 0xff; 8223 this.stencilFunc = AlwaysStencilFunc; 8224 this.stencilRef = 0; 8225 this.stencilFuncMask = 0xff; 8226 this.stencilFail = KeepStencilOp; 8227 this.stencilZFail = KeepStencilOp; 8228 this.stencilZPass = KeepStencilOp; 8229 this.stencilWrite = false; 8230 8231 this.clippingPlanes = null; 8232 this.clipIntersection = false; 8233 this.clipShadows = false; 8234 8235 this.shadowSide = null; 8236 8237 this.colorWrite = true; 8238 8239 this.precision = null; // override the renderer's default precision for this material 8240 8241 this.polygonOffset = false; 8242 this.polygonOffsetFactor = 0; 8243 this.polygonOffsetUnits = 0; 8244 8245 this.dithering = false; 8246 8247 this.alphaToCoverage = false; 8248 this.premultipliedAlpha = false; 8249 this.forceSinglePass = false; 8250 8251 this.visible = true; 8252 8253 this.toneMapped = true; 8254 8255 this.userData = {}; 8256 8257 this.version = 0; 8258 8259 this._alphaTest = 0; 8260 8261 } 8262 8263 get alphaTest() { 8264 8265 return this._alphaTest; 8266 8267 } 8268 8269 set alphaTest( value ) { 8270 8271 if ( this._alphaTest > 0 !== value > 0 ) { 8272 8273 this.version ++; 8274 8275 } 8276 8277 this._alphaTest = value; 8278 8279 } 8280 8281 onBuild( /* shaderobject, renderer */ ) {} 8282 8283 onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} 8284 8285 onBeforeCompile( /* shaderobject, renderer */ ) {} 8286 8287 customProgramCacheKey() { 8288 8289 return this.onBeforeCompile.toString(); 8290 8291 } 8292 8293 setValues( values ) { 8294 8295 if ( values === undefined ) return; 8296 8297 for ( const key in values ) { 8298 8299 const newValue = values[ key ]; 8300 8301 if ( newValue === undefined ) { 8302 8303 console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' ); 8304 continue; 8305 8306 } 8307 8308 const currentValue = this[ key ]; 8309 8310 if ( currentValue === undefined ) { 8311 8312 console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' ); 8313 continue; 8314 8315 } 8316 8317 if ( currentValue && currentValue.isColor ) { 8318 8319 currentValue.set( newValue ); 8320 8321 } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { 8322 8323 currentValue.copy( newValue ); 8324 8325 } else { 8326 8327 this[ key ] = newValue; 8328 8329 } 8330 8331 } 8332 8333 } 8334 8335 toJSON( meta ) { 8336 8337 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 8338 8339 if ( isRootObject ) { 8340 8341 meta = { 8342 textures: {}, 8343 images: {} 8344 }; 8345 8346 } 8347 8348 const data = { 8349 metadata: { 8350 version: 4.5, 8351 type: 'Material', 8352 generator: 'Material.toJSON' 8353 } 8354 }; 8355 8356 // standard Material serialization 8357 data.uuid = this.uuid; 8358 data.type = this.type; 8359 8360 if ( this.name !== '' ) data.name = this.name; 8361 8362 if ( this.color && this.color.isColor ) data.color = this.color.getHex(); 8363 8364 if ( this.roughness !== undefined ) data.roughness = this.roughness; 8365 if ( this.metalness !== undefined ) data.metalness = this.metalness; 8366 8367 if ( this.sheen !== undefined ) data.sheen = this.sheen; 8368 if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); 8369 if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; 8370 if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); 8371 if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; 8372 8373 if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); 8374 if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; 8375 if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); 8376 if ( this.shininess !== undefined ) data.shininess = this.shininess; 8377 if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; 8378 if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; 8379 8380 if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { 8381 8382 data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; 8383 8384 } 8385 8386 if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { 8387 8388 data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; 8389 8390 } 8391 8392 if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { 8393 8394 data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; 8395 data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); 8396 8397 } 8398 8399 if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; 8400 if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; 8401 if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; 8402 8403 if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { 8404 8405 data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; 8406 8407 } 8408 8409 if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { 8410 8411 data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; 8412 8413 } 8414 8415 if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; 8416 if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; 8417 if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; 8418 8419 if ( this.lightMap && this.lightMap.isTexture ) { 8420 8421 data.lightMap = this.lightMap.toJSON( meta ).uuid; 8422 data.lightMapIntensity = this.lightMapIntensity; 8423 8424 } 8425 8426 if ( this.aoMap && this.aoMap.isTexture ) { 8427 8428 data.aoMap = this.aoMap.toJSON( meta ).uuid; 8429 data.aoMapIntensity = this.aoMapIntensity; 8430 8431 } 8432 8433 if ( this.bumpMap && this.bumpMap.isTexture ) { 8434 8435 data.bumpMap = this.bumpMap.toJSON( meta ).uuid; 8436 data.bumpScale = this.bumpScale; 8437 8438 } 8439 8440 if ( this.normalMap && this.normalMap.isTexture ) { 8441 8442 data.normalMap = this.normalMap.toJSON( meta ).uuid; 8443 data.normalMapType = this.normalMapType; 8444 data.normalScale = this.normalScale.toArray(); 8445 8446 } 8447 8448 if ( this.displacementMap && this.displacementMap.isTexture ) { 8449 8450 data.displacementMap = this.displacementMap.toJSON( meta ).uuid; 8451 data.displacementScale = this.displacementScale; 8452 data.displacementBias = this.displacementBias; 8453 8454 } 8455 8456 if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; 8457 if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; 8458 8459 if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; 8460 if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; 8461 if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; 8462 if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; 8463 8464 if ( this.envMap && this.envMap.isTexture ) { 8465 8466 data.envMap = this.envMap.toJSON( meta ).uuid; 8467 8468 if ( this.combine !== undefined ) data.combine = this.combine; 8469 8470 } 8471 8472 if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; 8473 if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; 8474 if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; 8475 8476 if ( this.gradientMap && this.gradientMap.isTexture ) { 8477 8478 data.gradientMap = this.gradientMap.toJSON( meta ).uuid; 8479 8480 } 8481 8482 if ( this.transmission !== undefined ) data.transmission = this.transmission; 8483 if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; 8484 if ( this.thickness !== undefined ) data.thickness = this.thickness; 8485 if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; 8486 if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; 8487 if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); 8488 8489 if ( this.size !== undefined ) data.size = this.size; 8490 if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; 8491 if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; 8492 8493 if ( this.blending !== NormalBlending ) data.blending = this.blending; 8494 if ( this.side !== FrontSide ) data.side = this.side; 8495 if ( this.vertexColors ) data.vertexColors = true; 8496 8497 if ( this.opacity < 1 ) data.opacity = this.opacity; 8498 if ( this.transparent === true ) data.transparent = this.transparent; 8499 8500 data.depthFunc = this.depthFunc; 8501 data.depthTest = this.depthTest; 8502 data.depthWrite = this.depthWrite; 8503 data.colorWrite = this.colorWrite; 8504 8505 data.stencilWrite = this.stencilWrite; 8506 data.stencilWriteMask = this.stencilWriteMask; 8507 data.stencilFunc = this.stencilFunc; 8508 data.stencilRef = this.stencilRef; 8509 data.stencilFuncMask = this.stencilFuncMask; 8510 data.stencilFail = this.stencilFail; 8511 data.stencilZFail = this.stencilZFail; 8512 data.stencilZPass = this.stencilZPass; 8513 8514 // rotation (SpriteMaterial) 8515 if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; 8516 8517 if ( this.polygonOffset === true ) data.polygonOffset = true; 8518 if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; 8519 if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; 8520 8521 if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; 8522 if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; 8523 if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; 8524 if ( this.scale !== undefined ) data.scale = this.scale; 8525 8526 if ( this.dithering === true ) data.dithering = true; 8527 8528 if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; 8529 if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage; 8530 if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha; 8531 if ( this.forceSinglePass === true ) data.forceSinglePass = this.forceSinglePass; 8532 8533 if ( this.wireframe === true ) data.wireframe = this.wireframe; 8534 if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; 8535 if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; 8536 if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; 8537 8538 if ( this.flatShading === true ) data.flatShading = this.flatShading; 8539 8540 if ( this.visible === false ) data.visible = false;
vendor: 5,795 bytes, lines 8541-8697
8541 8542 if ( this.toneMapped === false ) data.toneMapped = false; 8543 8544 if ( this.fog === false ) data.fog = false; 8545 8546 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; 8547 8548 // TODO: Copied from Object3D.toJSON 8549 8550 function extractFromCache( cache ) { 8551 8552 const values = []; 8553 8554 for ( const key in cache ) { 8555 8556 const data = cache[ key ]; 8557 delete data.metadata; 8558 values.push( data ); 8559 8560 } 8561 8562 return values; 8563 8564 } 8565 8566 if ( isRootObject ) { 8567 8568 const textures = extractFromCache( meta.textures ); 8569 const images = extractFromCache( meta.images ); 8570 8571 if ( textures.length > 0 ) data.textures = textures; 8572 if ( images.length > 0 ) data.images = images; 8573 8574 } 8575 8576 return data; 8577 8578 } 8579 8580 clone() { 8581 8582 return new this.constructor().copy( this ); 8583 8584 } 8585 8586 copy( source ) { 8587 8588 this.name = source.name; 8589 8590 this.blending = source.blending; 8591 this.side = source.side; 8592 this.vertexColors = source.vertexColors; 8593 8594 this.opacity = source.opacity; 8595 this.transparent = source.transparent; 8596 8597 this.blendSrc = source.blendSrc; 8598 this.blendDst = source.blendDst; 8599 this.blendEquation = source.blendEquation; 8600 this.blendSrcAlpha = source.blendSrcAlpha; 8601 this.blendDstAlpha = source.blendDstAlpha; 8602 this.blendEquationAlpha = source.blendEquationAlpha; 8603 8604 this.depthFunc = source.depthFunc; 8605 this.depthTest = source.depthTest; 8606 this.depthWrite = source.depthWrite; 8607 8608 this.stencilWriteMask = source.stencilWriteMask; 8609 this.stencilFunc = source.stencilFunc; 8610 this.stencilRef = source.stencilRef; 8611 this.stencilFuncMask = source.stencilFuncMask; 8612 this.stencilFail = source.stencilFail; 8613 this.stencilZFail = source.stencilZFail; 8614 this.stencilZPass = source.stencilZPass; 8615 this.stencilWrite = source.stencilWrite; 8616 8617 const srcPlanes = source.clippingPlanes; 8618 let dstPlanes = null; 8619 8620 if ( srcPlanes !== null ) { 8621 8622 const n = srcPlanes.length; 8623 dstPlanes = new Array( n ); 8624 8625 for ( let i = 0; i !== n; ++ i ) { 8626 8627 dstPlanes[ i ] = srcPlanes[ i ].clone(); 8628 8629 } 8630 8631 } 8632 8633 this.clippingPlanes = dstPlanes; 8634 this.clipIntersection = source.clipIntersection; 8635 this.clipShadows = source.clipShadows; 8636 8637 this.shadowSide = source.shadowSide; 8638 8639 this.colorWrite = source.colorWrite; 8640 8641 this.precision = source.precision; 8642 8643 this.polygonOffset = source.polygonOffset; 8644 this.polygonOffsetFactor = source.polygonOffsetFactor; 8645 this.polygonOffsetUnits = source.polygonOffsetUnits; 8646 8647 this.dithering = source.dithering; 8648 8649 this.alphaTest = source.alphaTest; 8650 this.alphaToCoverage = source.alphaToCoverage; 8651 this.premultipliedAlpha = source.premultipliedAlpha; 8652 this.forceSinglePass = source.forceSinglePass; 8653 8654 this.visible = source.visible; 8655 8656 this.toneMapped = source.toneMapped; 8657 8658 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 8659 8660 return this; 8661 8662 } 8663 8664 dispose() { 8665 8666 this.dispatchEvent( { type: 'dispose' } ); 8667 8668 } 8669 8670 set needsUpdate( value ) { 8671 8672 if ( value === true ) this.version ++; 8673 8674 } 8675 8676} 8677 8678const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, 8679 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, 8680 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, 8681 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, 8682 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, 8683 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, 8684 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, 8685 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, 8686 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, 8687 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, 8688 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, 8689 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, 8690 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, 8691 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, 8692 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, 8693 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, 8694 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, 8695 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, 8696 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, 8697 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
8698 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, 8699 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, 8700 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, 8701 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; 8702 8703const _hslA = { h: 0, s: 0, l: 0 }; 8704const _hslB = { h: 0, s: 0, l: 0 }; 8705 8706function hue2rgb( p, q, t ) { 8707 8708 if ( t < 0 ) t += 1; 8709 if ( t > 1 ) t -= 1; 8710 if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; 8711 if ( t < 1 / 2 ) return q; 8712 if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); 8713 return p; 8714 8715} 8716 8717class Color { 8718 8719 constructor( r, g, b ) { 8720 8721 this.isColor = true; 8722 8723 this.r = 1; 8724 this.g = 1; 8725 this.b = 1; 8726 8727 if ( g === undefined && b === undefined ) { 8728 8729 // r is THREE.Color, hex or string 8730 return this.set( r ); 8731 8732 } 8733 8734 return this.setRGB( r, g, b ); 8735 8736 } 8737 8738 set( value ) { 8739 8740 if ( value && value.isColor ) { 8741 8742 this.copy( value ); 8743 8744 } else if ( typeof value === 'number' ) { 8745 8746 this.setHex( value ); 8747 8748 } else if ( typeof value === 'string' ) { 8749 8750 this.setStyle( value ); 8751 8752 } 8753 8754 return this; 8755 8756 } 8757 8758 setScalar( scalar ) { 8759 8760 this.r = scalar; 8761 this.g = scalar; 8762 this.b = scalar; 8763 8764 return this; 8765 8766 } 8767 8768 setHex( hex, colorSpace = SRGBColorSpace ) { 8769 8770 hex = Math.floor( hex ); 8771 8772 this.r = ( hex >> 16 & 255 ) / 255; 8773 this.g = ( hex >> 8 & 255 ) / 255; 8774 this.b = ( hex & 255 ) / 255; 8775 8776 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8777 8778 return this; 8779 8780 } 8781 8782 setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { 8783 8784 this.r = r; 8785 this.g = g; 8786 this.b = b; 8787 8788 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8789 8790 return this; 8791 8792 } 8793 8794 setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { 8795 8796 // h,s,l ranges are in 0.0 - 1.0 8797 h = euclideanModulo( h, 1 ); 8798 s = clamp( s, 0, 1 ); 8799 l = clamp( l, 0, 1 ); 8800 8801 if ( s === 0 ) { 8802 8803 this.r = this.g = this.b = l; 8804 8805 } else { 8806 8807 const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); 8808 const q = ( 2 * l ) - p; 8809 8810 this.r = hue2rgb( q, p, h + 1 / 3 ); 8811 this.g = hue2rgb( q, p, h ); 8812 this.b = hue2rgb( q, p, h - 1 / 3 ); 8813 8814 } 8815 8816 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8817 8818 return this; 8819 8820 } 8821 8822 setStyle( style, colorSpace = SRGBColorSpace ) { 8823 8824 function handleAlpha( string ) { 8825 8826 if ( string === undefined ) return; 8827 8828 if ( parseFloat( string ) < 1 ) { 8829 8830 console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); 8831 8832 } 8833 8834 } 8835 8836 8837 let m; 8838 8839 if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) { 8840 8841 // rgb / hsl 8842 8843 let color; 8844 const name = m[ 1 ]; 8845 const components = m[ 2 ]; 8846 8847 switch ( name ) { 8848 8849 case 'rgb': 8850 case 'rgba': 8851 8852 if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { 8853 8854 // rgb(255,0,0) rgba(255,0,0,0.5) 8855 this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255; 8856 this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255; 8857 this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255; 8858 8859 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8860 8861 handleAlpha( color[ 4 ] ); 8862 8863 return this; 8864 8865 } 8866 8867 if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { 8868 8869 // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) 8870 this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100; 8871 this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100; 8872 this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100; 8873 8874 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8875 8876 handleAlpha( color[ 4 ] ); 8877 8878 return this; 8879 8880 } 8881 8882 break; 8883 8884 case 'hsl': 8885 case 'hsla': 8886 8887 if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { 8888 8889 // hsl(120,50%,50%) hsla(120,50%,50%,0.5) 8890 const h = parseFloat( color[ 1 ] ) / 360; 8891 const s = parseFloat( color[ 2 ] ) / 100; 8892 const l = parseFloat( color[ 3 ] ) / 100; 8893 8894 handleAlpha( color[ 4 ] ); 8895 8896 return this.setHSL( h, s, l, colorSpace ); 8897 8898 } 8899 8900 break; 8901 8902 default: 8903 8904 console.warn( 'THREE.Color: Unknown color model ' + style ); 8905 8906 } 8907 8908 } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { 8909 8910 // hex color 8911 8912 const hex = m[ 1 ]; 8913 const size = hex.length; 8914 8915 if ( size === 3 ) { 8916 8917 // #ff0 8918 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255; 8919 this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255; 8920 this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255; 8921
vendor: 20,875 bytes, lines 8922-10186
8922 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8923 8924 return this; 8925 8926 } else if ( size === 6 ) { 8927 8928 // #ff0000 8929 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255; 8930 this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255; 8931 this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255; 8932 8933 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8934 8935 return this; 8936 8937 } else { 8938 8939 console.warn( 'THREE.Color: Invalid hex color ' + style ); 8940 8941 } 8942 8943 } else if ( style && style.length > 0 ) { 8944 8945 return this.setColorName( style, colorSpace ); 8946 8947 } 8948 8949 return this; 8950 8951 } 8952 8953 setColorName( style, colorSpace = SRGBColorSpace ) { 8954 8955 // color keywords 8956 const hex = _colorKeywords[ style.toLowerCase() ]; 8957 8958 if ( hex !== undefined ) { 8959 8960 // red 8961 this.setHex( hex, colorSpace ); 8962 8963 } else { 8964 8965 // unknown color 8966 console.warn( 'THREE.Color: Unknown color ' + style ); 8967 8968 } 8969 8970 return this; 8971 8972 } 8973 8974 clone() { 8975 8976 return new this.constructor( this.r, this.g, this.b ); 8977 8978 } 8979 8980 copy( color ) { 8981 8982 this.r = color.r; 8983 this.g = color.g; 8984 this.b = color.b; 8985 8986 return this; 8987 8988 } 8989 8990 copySRGBToLinear( color ) { 8991 8992 this.r = SRGBToLinear( color.r ); 8993 this.g = SRGBToLinear( color.g ); 8994 this.b = SRGBToLinear( color.b ); 8995 8996 return this; 8997 8998 } 8999 9000 copyLinearToSRGB( color ) { 9001 9002 this.r = LinearToSRGB( color.r ); 9003 this.g = LinearToSRGB( color.g ); 9004 this.b = LinearToSRGB( color.b ); 9005 9006 return this; 9007 9008 } 9009 9010 convertSRGBToLinear() { 9011 9012 this.copySRGBToLinear( this ); 9013 9014 return this; 9015 9016 } 9017 9018 convertLinearToSRGB() { 9019 9020 this.copyLinearToSRGB( this ); 9021 9022 return this; 9023 9024 } 9025 9026 getHex( colorSpace = SRGBColorSpace ) { 9027 9028 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 9029 9030 return clamp( _color.r * 255, 0, 255 ) << 16 ^ clamp( _color.g * 255, 0, 255 ) << 8 ^ clamp( _color.b * 255, 0, 255 ) << 0; 9031 9032 } 9033 9034 getHexString( colorSpace = SRGBColorSpace ) { 9035 9036 return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); 9037 9038 } 9039 9040 getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { 9041 9042 // h,s,l ranges are in 0.0 - 1.0 9043 9044 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 9045 9046 const r = _color.r, g = _color.g, b = _color.b; 9047 9048 const max = Math.max( r, g, b ); 9049 const min = Math.min( r, g, b ); 9050 9051 let hue, saturation; 9052 const lightness = ( min + max ) / 2.0; 9053 9054 if ( min === max ) { 9055 9056 hue = 0; 9057 saturation = 0; 9058 9059 } else { 9060 9061 const delta = max - min; 9062 9063 saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); 9064 9065 switch ( max ) { 9066 9067 case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; 9068 case g: hue = ( b - r ) / delta + 2; break; 9069 case b: hue = ( r - g ) / delta + 4; break; 9070 9071 } 9072 9073 hue /= 6; 9074 9075 } 9076 9077 target.h = hue; 9078 target.s = saturation; 9079 target.l = lightness; 9080 9081 return target; 9082 9083 } 9084 9085 getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { 9086 9087 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 9088 9089 target.r = _color.r; 9090 target.g = _color.g; 9091 target.b = _color.b; 9092 9093 return target; 9094 9095 } 9096 9097 getStyle( colorSpace = SRGBColorSpace ) { 9098 9099 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 9100 9101 const r = _color.r, g = _color.g, b = _color.b; 9102 9103 if ( colorSpace !== SRGBColorSpace ) { 9104 9105 // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). 9106 return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`; 9107 9108 } 9109 9110 return `rgb(${( r * 255 ) | 0},${( g * 255 ) | 0},${( b * 255 ) | 0})`; 9111 9112 } 9113 9114 offsetHSL( h, s, l ) { 9115 9116 this.getHSL( _hslA ); 9117 9118 _hslA.h += h; _hslA.s += s; _hslA.l += l; 9119 9120 this.setHSL( _hslA.h, _hslA.s, _hslA.l ); 9121 9122 return this; 9123 9124 } 9125 9126 add( color ) { 9127 9128 this.r += color.r; 9129 this.g += color.g; 9130 this.b += color.b; 9131 9132 return this; 9133 9134 } 9135 9136 addColors( color1, color2 ) { 9137 9138 this.r = color1.r + color2.r; 9139 this.g = color1.g + color2.g; 9140 this.b = color1.b + color2.b; 9141 9142 return this; 9143 9144 } 9145 9146 addScalar( s ) { 9147 9148 this.r += s; 9149 this.g += s; 9150 this.b += s; 9151 9152 return this; 9153 9154 } 9155 9156 sub( color ) { 9157 9158 this.r = Math.max( 0, this.r - color.r ); 9159 this.g = Math.max( 0, this.g - color.g ); 9160 this.b = Math.max( 0, this.b - color.b ); 9161 9162 return this; 9163 9164 } 9165 9166 multiply( color ) { 9167 9168 this.r *= color.r; 9169 this.g *= color.g; 9170 this.b *= color.b; 9171 9172 return this; 9173 9174 } 9175 9176 multiplyScalar( s ) { 9177 9178 this.r *= s; 9179 this.g *= s; 9180 this.b *= s; 9181 9182 return this; 9183 9184 } 9185 9186 lerp( color, alpha ) { 9187 9188 this.r += ( color.r - this.r ) * alpha; 9189 this.g += ( color.g - this.g ) * alpha; 9190 this.b += ( color.b - this.b ) * alpha; 9191 9192 return this; 9193 9194 } 9195 9196 lerpColors( color1, color2, alpha ) { 9197 9198 this.r = color1.r + ( color2.r - color1.r ) * alpha; 9199 this.g = color1.g + ( color2.g - color1.g ) * alpha; 9200 this.b = color1.b + ( color2.b - color1.b ) * alpha; 9201 9202 return this; 9203 9204 } 9205 9206 lerpHSL( color, alpha ) { 9207 9208 this.getHSL( _hslA ); 9209 color.getHSL( _hslB ); 9210 9211 const h = lerp( _hslA.h, _hslB.h, alpha ); 9212 const s = lerp( _hslA.s, _hslB.s, alpha ); 9213 const l = lerp( _hslA.l, _hslB.l, alpha ); 9214 9215 this.setHSL( h, s, l ); 9216 9217 return this; 9218 9219 } 9220 9221 equals( c ) { 9222 9223 return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); 9224 9225 } 9226 9227 fromArray( array, offset = 0 ) { 9228 9229 this.r = array[ offset ]; 9230 this.g = array[ offset + 1 ]; 9231 this.b = array[ offset + 2 ]; 9232 9233 return this; 9234 9235 } 9236 9237 toArray( array = [], offset = 0 ) { 9238 9239 array[ offset ] = this.r; 9240 array[ offset + 1 ] = this.g; 9241 array[ offset + 2 ] = this.b; 9242 9243 return array; 9244 9245 } 9246 9247 fromBufferAttribute( attribute, index ) { 9248 9249 this.r = attribute.getX( index ); 9250 this.g = attribute.getY( index ); 9251 this.b = attribute.getZ( index ); 9252 9253 return this; 9254 9255 } 9256 9257 toJSON() { 9258 9259 return this.getHex(); 9260 9261 } 9262 9263 *[ Symbol.iterator ]() { 9264 9265 yield this.r; 9266 yield this.g; 9267 yield this.b; 9268 9269 } 9270 9271} 9272 9273const _color = new Color(); 9274 9275Color.NAMES = _colorKeywords; 9276 9277class MeshBasicMaterial extends Material { 9278 9279 constructor( parameters ) { 9280 9281 super(); 9282 9283 this.isMeshBasicMaterial = true; 9284 9285 this.type = 'MeshBasicMaterial'; 9286 9287 this.color = new Color( 0xffffff ); // emissive 9288 9289 this.map = null; 9290 9291 this.lightMap = null; 9292 this.lightMapIntensity = 1.0; 9293 9294 this.aoMap = null; 9295 this.aoMapIntensity = 1.0; 9296 9297 this.specularMap = null; 9298 9299 this.alphaMap = null; 9300 9301 this.envMap = null; 9302 this.combine = MultiplyOperation; 9303 this.reflectivity = 1; 9304 this.refractionRatio = 0.98; 9305 9306 this.wireframe = false; 9307 this.wireframeLinewidth = 1; 9308 this.wireframeLinecap = 'round'; 9309 this.wireframeLinejoin = 'round'; 9310 9311 this.fog = true; 9312 9313 this.setValues( parameters ); 9314 9315 } 9316 9317 copy( source ) { 9318 9319 super.copy( source ); 9320 9321 this.color.copy( source.color ); 9322 9323 this.map = source.map; 9324 9325 this.lightMap = source.lightMap; 9326 this.lightMapIntensity = source.lightMapIntensity; 9327 9328 this.aoMap = source.aoMap; 9329 this.aoMapIntensity = source.aoMapIntensity; 9330 9331 this.specularMap = source.specularMap; 9332 9333 this.alphaMap = source.alphaMap; 9334 9335 this.envMap = source.envMap; 9336 this.combine = source.combine; 9337 this.reflectivity = source.reflectivity; 9338 this.refractionRatio = source.refractionRatio; 9339 9340 this.wireframe = source.wireframe; 9341 this.wireframeLinewidth = source.wireframeLinewidth; 9342 this.wireframeLinecap = source.wireframeLinecap; 9343 this.wireframeLinejoin = source.wireframeLinejoin; 9344 9345 this.fog = source.fog; 9346 9347 return this; 9348 9349 } 9350 9351} 9352 9353const _vector$9 = /*@__PURE__*/ new Vector3(); 9354const _vector2$1 = /*@__PURE__*/ new Vector2(); 9355 9356class BufferAttribute { 9357 9358 constructor( array, itemSize, normalized = false ) { 9359 9360 if ( Array.isArray( array ) ) { 9361 9362 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); 9363 9364 } 9365 9366 this.isBufferAttribute = true; 9367 9368 this.name = ''; 9369 9370 this.array = array; 9371 this.itemSize = itemSize; 9372 this.count = array !== undefined ? array.length / itemSize : 0; 9373 this.normalized = normalized; 9374 9375 this.usage = StaticDrawUsage; 9376 this.updateRange = { offset: 0, count: - 1 }; 9377 9378 this.version = 0; 9379 9380 } 9381 9382 onUploadCallback() {} 9383 9384 set needsUpdate( value ) { 9385 9386 if ( value === true ) this.version ++; 9387 9388 } 9389 9390 setUsage( value ) { 9391 9392 this.usage = value; 9393 9394 return this; 9395 9396 } 9397 9398 copy( source ) { 9399 9400 this.name = source.name; 9401 this.array = new source.array.constructor( source.array ); 9402 this.itemSize = source.itemSize; 9403 this.count = source.count; 9404 this.normalized = source.normalized; 9405 9406 this.usage = source.usage; 9407 9408 return this; 9409 9410 } 9411 9412 copyAt( index1, attribute, index2 ) { 9413 9414 index1 *= this.itemSize; 9415 index2 *= attribute.itemSize; 9416 9417 for ( let i = 0, l = this.itemSize; i < l; i ++ ) { 9418 9419 this.array[ index1 + i ] = attribute.array[ index2 + i ]; 9420 9421 } 9422 9423 return this; 9424 9425 } 9426 9427 copyArray( array ) { 9428 9429 this.array.set( array ); 9430 9431 return this; 9432 9433 } 9434 9435 applyMatrix3( m ) { 9436 9437 if ( this.itemSize === 2 ) { 9438 9439 for ( let i = 0, l = this.count; i < l; i ++ ) { 9440 9441 _vector2$1.fromBufferAttribute( this, i ); 9442 _vector2$1.applyMatrix3( m ); 9443 9444 this.setXY( i, _vector2$1.x, _vector2$1.y ); 9445 9446 } 9447 9448 } else if ( this.itemSize === 3 ) { 9449 9450 for ( let i = 0, l = this.count; i < l; i ++ ) { 9451 9452 _vector$9.fromBufferAttribute( this, i ); 9453 _vector$9.applyMatrix3( m ); 9454 9455 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 9456 9457 } 9458 9459 } 9460 9461 return this; 9462 9463 } 9464 9465 applyMatrix4( m ) { 9466 9467 for ( let i = 0, l = this.count; i < l; i ++ ) { 9468 9469 _vector$9.fromBufferAttribute( this, i ); 9470 9471 _vector$9.applyMatrix4( m ); 9472 9473 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 9474 9475 } 9476 9477 return this; 9478 9479 } 9480 9481 applyNormalMatrix( m ) { 9482 9483 for ( let i = 0, l = this.count; i < l; i ++ ) { 9484 9485 _vector$9.fromBufferAttribute( this, i ); 9486 9487 _vector$9.applyNormalMatrix( m ); 9488 9489 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 9490 9491 } 9492 9493 return this; 9494 9495 } 9496 9497 transformDirection( m ) { 9498 9499 for ( let i = 0, l = this.count; i < l; i ++ ) { 9500 9501 _vector$9.fromBufferAttribute( this, i ); 9502 9503 _vector$9.transformDirection( m ); 9504 9505 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 9506 9507 } 9508 9509 return this; 9510 9511 } 9512 9513 set( value, offset = 0 ) { 9514 9515 // Matching BufferAttribute constructor, do not normalize the array. 9516 this.array.set( value, offset ); 9517 9518 return this; 9519 9520 } 9521 9522 getX( index ) { 9523 9524 let x = this.array[ index * this.itemSize ]; 9525 9526 if ( this.normalized ) x = denormalize( x, this.array ); 9527 9528 return x; 9529 9530 } 9531 9532 setX( index, x ) { 9533 9534 if ( this.normalized ) x = normalize( x, this.array ); 9535 9536 this.array[ index * this.itemSize ] = x; 9537 9538 return this; 9539 9540 } 9541 9542 getY( index ) { 9543 9544 let y = this.array[ index * this.itemSize + 1 ]; 9545 9546 if ( this.normalized ) y = denormalize( y, this.array ); 9547 9548 return y; 9549 9550 } 9551 9552 setY( index, y ) { 9553 9554 if ( this.normalized ) y = normalize( y, this.array ); 9555 9556 this.array[ index * this.itemSize + 1 ] = y; 9557 9558 return this; 9559 9560 } 9561 9562 getZ( index ) { 9563 9564 let z = this.array[ index * this.itemSize + 2 ]; 9565 9566 if ( this.normalized ) z = denormalize( z, this.array ); 9567 9568 return z; 9569 9570 } 9571 9572 setZ( index, z ) { 9573 9574 if ( this.normalized ) z = normalize( z, this.array ); 9575 9576 this.array[ index * this.itemSize + 2 ] = z; 9577 9578 return this; 9579 9580 } 9581 9582 getW( index ) { 9583 9584 let w = this.array[ index * this.itemSize + 3 ]; 9585 9586 if ( this.normalized ) w = denormalize( w, this.array ); 9587 9588 return w; 9589 9590 } 9591 9592 setW( index, w ) { 9593 9594 if ( this.normalized ) w = normalize( w, this.array ); 9595 9596 this.array[ index * this.itemSize + 3 ] = w; 9597 9598 return this; 9599 9600 } 9601 9602 setXY( index, x, y ) { 9603 9604 index *= this.itemSize; 9605 9606 if ( this.normalized ) { 9607 9608 x = normalize( x, this.array ); 9609 y = normalize( y, this.array ); 9610 9611 } 9612 9613 this.array[ index + 0 ] = x; 9614 this.array[ index + 1 ] = y; 9615 9616 return this; 9617 9618 } 9619 9620 setXYZ( index, x, y, z ) { 9621 9622 index *= this.itemSize; 9623 9624 if ( this.normalized ) { 9625 9626 x = normalize( x, this.array ); 9627 y = normalize( y, this.array ); 9628 z = normalize( z, this.array ); 9629 9630 } 9631 9632 this.array[ index + 0 ] = x; 9633 this.array[ index + 1 ] = y; 9634 this.array[ index + 2 ] = z; 9635 9636 return this; 9637 9638 } 9639 9640 setXYZW( index, x, y, z, w ) { 9641 9642 index *= this.itemSize; 9643 9644 if ( this.normalized ) { 9645 9646 x = normalize( x, this.array ); 9647 y = normalize( y, this.array ); 9648 z = normalize( z, this.array ); 9649 w = normalize( w, this.array ); 9650 9651 } 9652 9653 this.array[ index + 0 ] = x; 9654 this.array[ index + 1 ] = y; 9655 this.array[ index + 2 ] = z; 9656 this.array[ index + 3 ] = w; 9657 9658 return this; 9659 9660 } 9661 9662 onUpload( callback ) { 9663 9664 this.onUploadCallback = callback; 9665 9666 return this; 9667 9668 } 9669 9670 clone() { 9671 9672 return new this.constructor( this.array, this.itemSize ).copy( this ); 9673 9674 } 9675 9676 toJSON() { 9677 9678 const data = { 9679 itemSize: this.itemSize, 9680 type: this.array.constructor.name, 9681 array: Array.from( this.array ), 9682 normalized: this.normalized 9683 }; 9684 9685 if ( this.name !== '' ) data.name = this.name; 9686 if ( this.usage !== StaticDrawUsage ) data.usage = this.usage; 9687 if ( this.updateRange.offset !== 0 || this.updateRange.count !== - 1 ) data.updateRange = this.updateRange; 9688 9689 return data; 9690 9691 } 9692 9693 // @deprecated 9694 9695 copyColorsArray() { 9696 9697 console.error( 'THREE.BufferAttribute: copyColorsArray() was removed in r144.' ); 9698 9699 } 9700 9701 copyVector2sArray() { 9702 9703 console.error( 'THREE.BufferAttribute: copyVector2sArray() was removed in r144.' ); 9704 9705 } 9706 9707 copyVector3sArray() { 9708 9709 console.error( 'THREE.BufferAttribute: copyVector3sArray() was removed in r144.' ); 9710 9711 } 9712 9713 copyVector4sArray() { 9714 9715 console.error( 'THREE.BufferAttribute: copyVector4sArray() was removed in r144.' ); 9716 9717 } 9718 9719} 9720 9721// 9722 9723class Int8BufferAttribute extends BufferAttribute { 9724 9725 constructor( array, itemSize, normalized ) { 9726 9727 super( new Int8Array( array ), itemSize, normalized ); 9728 9729 } 9730 9731} 9732 9733class Uint8BufferAttribute extends BufferAttribute { 9734 9735 constructor( array, itemSize, normalized ) { 9736 9737 super( new Uint8Array( array ), itemSize, normalized ); 9738 9739 } 9740 9741} 9742 9743class Uint8ClampedBufferAttribute extends BufferAttribute { 9744 9745 constructor( array, itemSize, normalized ) { 9746 9747 super( new Uint8ClampedArray( array ), itemSize, normalized ); 9748 9749 } 9750 9751} 9752 9753class Int16BufferAttribute extends BufferAttribute { 9754 9755 constructor( array, itemSize, normalized ) { 9756 9757 super( new Int16Array( array ), itemSize, normalized ); 9758 9759 } 9760 9761} 9762 9763class Uint16BufferAttribute extends BufferAttribute { 9764 9765 constructor( array, itemSize, normalized ) { 9766 9767 super( new Uint16Array( array ), itemSize, normalized ); 9768 9769 } 9770 9771} 9772 9773class Int32BufferAttribute extends BufferAttribute { 9774 9775 constructor( array, itemSize, normalized ) { 9776 9777 super( new Int32Array( array ), itemSize, normalized ); 9778 9779 } 9780 9781} 9782 9783class Uint32BufferAttribute extends BufferAttribute { 9784 9785 constructor( array, itemSize, normalized ) { 9786 9787 super( new Uint32Array( array ), itemSize, normalized ); 9788 9789 } 9790 9791} 9792 9793class Float16BufferAttribute extends BufferAttribute { 9794 9795 constructor( array, itemSize, normalized ) { 9796 9797 super( new Uint16Array( array ), itemSize, normalized ); 9798 9799 this.isFloat16BufferAttribute = true; 9800 9801 } 9802 9803} 9804 9805 9806class Float32BufferAttribute extends BufferAttribute { 9807 9808 constructor( array, itemSize, normalized ) { 9809 9810 super( new Float32Array( array ), itemSize, normalized ); 9811 9812 } 9813 9814} 9815 9816class Float64BufferAttribute extends BufferAttribute { 9817 9818 constructor( array, itemSize, normalized ) { 9819 9820 super( new Float64Array( array ), itemSize, normalized ); 9821 9822 } 9823 9824} 9825 9826let _id$1 = 0; 9827 9828const _m1 = /*@__PURE__*/ new Matrix4(); 9829const _obj = /*@__PURE__*/ new Object3D(); 9830const _offset = /*@__PURE__*/ new Vector3(); 9831const _box$1 = /*@__PURE__*/ new Box3(); 9832const _boxMorphTargets = /*@__PURE__*/ new Box3(); 9833const _vector$8 = /*@__PURE__*/ new Vector3(); 9834 9835class BufferGeometry extends EventDispatcher { 9836 9837 constructor() { 9838 9839 super(); 9840 9841 this.isBufferGeometry = true; 9842 9843 Object.defineProperty( this, 'id', { value: _id$1 ++ } ); 9844 9845 this.uuid = generateUUID(); 9846 9847 this.name = ''; 9848 this.type = 'BufferGeometry'; 9849 9850 this.index = null; 9851 this.attributes = {}; 9852 9853 this.morphAttributes = {}; 9854 this.morphTargetsRelative = false; 9855 9856 this.groups = []; 9857 9858 this.boundingBox = null; 9859 this.boundingSphere = null; 9860 9861 this.drawRange = { start: 0, count: Infinity }; 9862 9863 this.userData = {}; 9864 9865 } 9866 9867 getIndex() { 9868 9869 return this.index; 9870 9871 } 9872 9873 setIndex( index ) { 9874 9875 if ( Array.isArray( index ) ) { 9876 9877 this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); 9878 9879 } else { 9880 9881 this.index = index; 9882 9883 } 9884 9885 return this; 9886 9887 } 9888 9889 getAttribute( name ) { 9890 9891 return this.attributes[ name ]; 9892 9893 } 9894 9895 setAttribute( name, attribute ) { 9896 9897 this.attributes[ name ] = attribute; 9898 9899 return this; 9900 9901 } 9902 9903 deleteAttribute( name ) { 9904 9905 delete this.attributes[ name ]; 9906 9907 return this; 9908 9909 } 9910 9911 hasAttribute( name ) { 9912 9913 return this.attributes[ name ] !== undefined; 9914 9915 } 9916 9917 addGroup( start, count, materialIndex = 0 ) { 9918 9919 this.groups.push( { 9920 9921 start: start, 9922 count: count, 9923 materialIndex: materialIndex 9924 9925 } ); 9926 9927 } 9928 9929 clearGroups() { 9930 9931 this.groups = []; 9932 9933 } 9934 9935 setDrawRange( start, count ) { 9936 9937 this.drawRange.start = start; 9938 this.drawRange.count = count; 9939 9940 } 9941 9942 applyMatrix4( matrix ) { 9943 9944 const position = this.attributes.position; 9945 9946 if ( position !== undefined ) { 9947 9948 position.applyMatrix4( matrix ); 9949 9950 position.needsUpdate = true; 9951 9952 } 9953 9954 const normal = this.attributes.normal; 9955 9956 if ( normal !== undefined ) { 9957 9958 const normalMatrix = new Matrix3().getNormalMatrix( matrix ); 9959 9960 normal.applyNormalMatrix( normalMatrix ); 9961 9962 normal.needsUpdate = true; 9963 9964 } 9965 9966 const tangent = this.attributes.tangent; 9967 9968 if ( tangent !== undefined ) { 9969 9970 tangent.transformDirection( matrix ); 9971 9972 tangent.needsUpdate = true; 9973 9974 } 9975 9976 if ( this.boundingBox !== null ) { 9977 9978 this.computeBoundingBox(); 9979 9980 } 9981 9982 if ( this.boundingSphere !== null ) { 9983 9984 this.computeBoundingSphere(); 9985 9986 } 9987 9988 return this; 9989 9990 } 9991 9992 applyQuaternion( q ) { 9993 9994 _m1.makeRotationFromQuaternion( q ); 9995 9996 this.applyMatrix4( _m1 ); 9997 9998 return this; 9999 10000 } 10001 10002 rotateX( angle ) { 10003 10004 // rotate geometry around world x-axis 10005 10006 _m1.makeRotationX( angle ); 10007 10008 this.applyMatrix4( _m1 ); 10009 10010 return this; 10011 10012 } 10013 10014 rotateY( angle ) { 10015 10016 // rotate geometry around world y-axis 10017 10018 _m1.makeRotationY( angle ); 10019 10020 this.applyMatrix4( _m1 ); 10021 10022 return this; 10023 10024 } 10025 10026 rotateZ( angle ) { 10027 10028 // rotate geometry around world z-axis 10029 10030 _m1.makeRotationZ( angle ); 10031 10032 this.applyMatrix4( _m1 ); 10033 10034 return this; 10035 10036 } 10037 10038 translate( x, y, z ) { 10039 10040 // translate geometry 10041 10042 _m1.makeTranslation( x, y, z ); 10043 10044 this.applyMatrix4( _m1 ); 10045 10046 return this; 10047 10048 } 10049 10050 scale( x, y, z ) { 10051 10052 // scale geometry 10053 10054 _m1.makeScale( x, y, z ); 10055 10056 this.applyMatrix4( _m1 ); 10057 10058 return this; 10059 10060 } 10061 10062 lookAt( vector ) { 10063 10064 _obj.lookAt( vector ); 10065 10066 _obj.updateMatrix(); 10067 10068 this.applyMatrix4( _obj.matrix ); 10069 10070 return this; 10071 10072 } 10073 10074 center() { 10075 10076 this.computeBoundingBox(); 10077 10078 this.boundingBox.getCenter( _offset ).negate(); 10079 10080 this.translate( _offset.x, _offset.y, _offset.z ); 10081 10082 return this; 10083 10084 } 10085 10086 setFromPoints( points ) { 10087 10088 const position = []; 10089 10090 for ( let i = 0, l = points.length; i < l; i ++ ) { 10091 10092 const point = points[ i ]; 10093 position.push( point.x, point.y, point.z || 0 ); 10094 10095 } 10096 10097 this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); 10098 10099 return this; 10100 10101 } 10102 10103 computeBoundingBox() { 10104 10105 if ( this.boundingBox === null ) { 10106 10107 this.boundingBox = new Box3(); 10108 10109 } 10110 10111 const position = this.attributes.position; 10112 const morphAttributesPosition = this.morphAttributes.position; 10113 10114 if ( position && position.isGLBufferAttribute ) { 10115 10116 console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this ); 10117 10118 this.boundingBox.set( 10119 new Vector3( - Infinity, - Infinity, - Infinity ), 10120 new Vector3( + Infinity, + Infinity, + Infinity ) 10121 ); 10122 10123 return; 10124 10125 } 10126 10127 if ( position !== undefined ) { 10128 10129 this.boundingBox.setFromBufferAttribute( position ); 10130 10131 // process morph attributes if present 10132 10133 if ( morphAttributesPosition ) { 10134 10135 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { 10136 10137 const morphAttribute = morphAttributesPosition[ i ]; 10138 _box$1.setFromBufferAttribute( morphAttribute ); 10139 10140 if ( this.morphTargetsRelative ) { 10141 10142 _vector$8.addVectors( this.boundingBox.min, _box$1.min ); 10143 this.boundingBox.expandByPoint( _vector$8 ); 10144 10145 _vector$8.addVectors( this.boundingBox.max, _box$1.max ); 10146 this.boundingBox.expandByPoint( _vector$8 ); 10147 10148 } else { 10149 10150 this.boundingBox.expandByPoint( _box$1.min ); 10151 this.boundingBox.expandByPoint( _box$1.max ); 10152 10153 } 10154 10155 } 10156 10157 } 10158 10159 } else { 10160 10161 this.boundingBox.makeEmpty(); 10162 10163 } 10164 10165 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { 10166 10167 console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); 10168 10169 } 10170 10171 } 10172 10173 computeBoundingSphere() { 10174 10175 if ( this.boundingSphere === null ) { 10176 10177 this.boundingSphere = new Sphere(); 10178 10179 } 10180 10181 const position = this.attributes.position; 10182 const morphAttributesPosition = this.morphAttributes.position; 10183 10184 if ( position && position.isGLBufferAttribute ) { 10185 10186 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "fal
vendor: 5,873 bytes, lines 10186-10456
10186se".', this ); 10187 10188 this.boundingSphere.set( new Vector3(), Infinity ); 10189 10190 return; 10191 10192 } 10193 10194 if ( position ) { 10195 10196 // first, find the center of the bounding sphere 10197 10198 const center = this.boundingSphere.center; 10199 10200 _box$1.setFromBufferAttribute( position ); 10201 10202 // process morph attributes if present 10203 10204 if ( morphAttributesPosition ) { 10205 10206 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { 10207 10208 const morphAttribute = morphAttributesPosition[ i ]; 10209 _boxMorphTargets.setFromBufferAttribute( morphAttribute ); 10210 10211 if ( this.morphTargetsRelative ) { 10212 10213 _vector$8.addVectors( _box$1.min, _boxMorphTargets.min ); 10214 _box$1.expandByPoint( _vector$8 ); 10215 10216 _vector$8.addVectors( _box$1.max, _boxMorphTargets.max ); 10217 _box$1.expandByPoint( _vector$8 ); 10218 10219 } else { 10220 10221 _box$1.expandByPoint( _boxMorphTargets.min ); 10222 _box$1.expandByPoint( _boxMorphTargets.max ); 10223 10224 } 10225 10226 } 10227 10228 } 10229 10230 _box$1.getCenter( center ); 10231 10232 // second, try to find a boundingSphere with a radius smaller than the 10233 // boundingSphere of the boundingBox: sqrt(3) smaller in the best case 10234 10235 let maxRadiusSq = 0; 10236 10237 for ( let i = 0, il = position.count; i < il; i ++ ) { 10238 10239 _vector$8.fromBufferAttribute( position, i ); 10240 10241 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); 10242 10243 } 10244 10245 // process morph attributes if present 10246 10247 if ( morphAttributesPosition ) { 10248 10249 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { 10250 10251 const morphAttribute = morphAttributesPosition[ i ]; 10252 const morphTargetsRelative = this.morphTargetsRelative; 10253 10254 for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) { 10255 10256 _vector$8.fromBufferAttribute( morphAttribute, j ); 10257 10258 if ( morphTargetsRelative ) { 10259 10260 _offset.fromBufferAttribute( position, j ); 10261 _vector$8.add( _offset ); 10262 10263 } 10264 10265 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); 10266 10267 } 10268 10269 } 10270 10271 } 10272 10273 this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); 10274 10275 if ( isNaN( this.boundingSphere.radius ) ) { 10276 10277 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); 10278 10279 } 10280 10281 } 10282 10283 } 10284 10285 computeTangents() { 10286 10287 const index = this.index; 10288 const attributes = this.attributes; 10289 10290 // based on http://www.terathon.com/code/tangent.html 10291 // (per vertex tangents) 10292 10293 if ( index === null || 10294 attributes.position === undefined || 10295 attributes.normal === undefined || 10296 attributes.uv === undefined ) { 10297 10298 console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' ); 10299 return; 10300 10301 } 10302 10303 const indices = index.array; 10304 const positions = attributes.position.array; 10305 const normals = attributes.normal.array; 10306 const uvs = attributes.uv.array; 10307 10308 const nVertices = positions.length / 3; 10309 10310 if ( this.hasAttribute( 'tangent' ) === false ) { 10311 10312 this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) ); 10313 10314 } 10315 10316 const tangents = this.getAttribute( 'tangent' ).array; 10317 10318 const tan1 = [], tan2 = []; 10319 10320 for ( let i = 0; i < nVertices; i ++ ) { 10321 10322 tan1[ i ] = new Vector3(); 10323 tan2[ i ] = new Vector3(); 10324 10325 } 10326 10327 const vA = new Vector3(), 10328 vB = new Vector3(), 10329 vC = new Vector3(), 10330 10331 uvA = new Vector2(), 10332 uvB = new Vector2(), 10333 uvC = new Vector2(), 10334 10335 sdir = new Vector3(), 10336 tdir = new Vector3(); 10337 10338 function handleTriangle( a, b, c ) { 10339 10340 vA.fromArray( positions, a * 3 ); 10341 vB.fromArray( positions, b * 3 ); 10342 vC.fromArray( positions, c * 3 ); 10343 10344 uvA.fromArray( uvs, a * 2 ); 10345 uvB.fromArray( uvs, b * 2 ); 10346 uvC.fromArray( uvs, c * 2 ); 10347 10348 vB.sub( vA ); 10349 vC.sub( vA ); 10350 10351 uvB.sub( uvA ); 10352 uvC.sub( uvA ); 10353 10354 const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y ); 10355 10356 // silently ignore degenerate uv triangles having coincident or colinear vertices 10357 10358 if ( ! isFinite( r ) ) return; 10359 10360 sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r ); 10361 tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r ); 10362 10363 tan1[ a ].add( sdir ); 10364 tan1[ b ].add( sdir ); 10365 tan1[ c ].add( sdir ); 10366 10367 tan2[ a ].add( tdir ); 10368 tan2[ b ].add( tdir ); 10369 tan2[ c ].add( tdir ); 10370 10371 } 10372 10373 let groups = this.groups; 10374 10375 if ( groups.length === 0 ) { 10376 10377 groups = [ { 10378 start: 0, 10379 count: indices.length 10380 } ]; 10381 10382 } 10383 10384 for ( let i = 0, il = groups.length; i < il; ++ i ) { 10385 10386 const group = groups[ i ]; 10387 10388 const start = group.start; 10389 const count = group.count; 10390 10391 for ( let j = start, jl = start + count; j < jl; j += 3 ) { 10392 10393 handleTriangle( 10394 indices[ j + 0 ], 10395 indices[ j + 1 ], 10396 indices[ j + 2 ] 10397 ); 10398 10399 } 10400 10401 } 10402 10403 const tmp = new Vector3(), tmp2 = new Vector3(); 10404 const n = new Vector3(), n2 = new Vector3(); 10405 10406 function handleVertex( v ) { 10407 10408 n.fromArray( normals, v * 3 ); 10409 n2.copy( n ); 10410 10411 const t = tan1[ v ]; 10412 10413 // Gram-Schmidt orthogonalize 10414 10415 tmp.copy( t ); 10416 tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize(); 10417 10418 // Calculate handedness 10419 10420 tmp2.crossVectors( n2, t ); 10421 const test = tmp2.dot( tan2[ v ] ); 10422 const w = ( test < 0.0 ) ? - 1.0 : 1.0; 10423 10424 tangents[ v * 4 ] = tmp.x; 10425 tangents[ v * 4 + 1 ] = tmp.y; 10426 tangents[ v * 4 + 2 ] = tmp.z; 10427 tangents[ v * 4 + 3 ] = w; 10428 10429 } 10430 10431 for ( let i = 0, il = groups.length; i < il; ++ i ) { 10432 10433 const group = groups[ i ]; 10434 10435 const start = group.start; 10436 const count = group.count; 10437 10438 for ( let j = start, jl = start + count; j < jl; j += 3 ) { 10439 10440 handleVertex( indices[ j + 0 ] ); 10441 handleVertex( indices[ j + 1 ] ); 10442 handleVertex( indices[ j + 2 ] ); 10443 10444 } 10445 10446 } 10447 10448 } 10449 10450 computeVertexNormals() { 10451 10452 const index = this.index; 10453 const positionAttribute = this.getAttribute( 'position' ); 10454 10455 if ( positionAttribute !== undefined ) { 10456
vendor: 12,723 bytes, lines 10457-11085
10457 let normalAttribute = this.getAttribute( 'normal' ); 10458 10459 if ( normalAttribute === undefined ) { 10460 10461 normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 ); 10462 this.setAttribute( 'normal', normalAttribute ); 10463 10464 } else { 10465 10466 // reset existing normals to zero 10467 10468 for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) { 10469 10470 normalAttribute.setXYZ( i, 0, 0, 0 ); 10471 10472 } 10473 10474 } 10475 10476 const pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); 10477 const nA = new Vector3(), nB = new Vector3(), nC = new Vector3(); 10478 const cb = new Vector3(), ab = new Vector3(); 10479 10480 // indexed elements 10481 10482 if ( index ) { 10483 10484 for ( let i = 0, il = index.count; i < il; i += 3 ) { 10485 10486 const vA = index.getX( i + 0 ); 10487 const vB = index.getX( i + 1 ); 10488 const vC = index.getX( i + 2 ); 10489 10490 pA.fromBufferAttribute( positionAttribute, vA ); 10491 pB.fromBufferAttribute( positionAttribute, vB ); 10492 pC.fromBufferAttribute( positionAttribute, vC ); 10493 10494 cb.subVectors( pC, pB ); 10495 ab.subVectors( pA, pB ); 10496 cb.cross( ab ); 10497 10498 nA.fromBufferAttribute( normalAttribute, vA ); 10499 nB.fromBufferAttribute( normalAttribute, vB ); 10500 nC.fromBufferAttribute( normalAttribute, vC ); 10501 10502 nA.add( cb ); 10503 nB.add( cb ); 10504 nC.add( cb ); 10505 10506 normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z ); 10507 normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z ); 10508 normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z ); 10509 10510 } 10511 10512 } else { 10513 10514 // non-indexed elements (unconnected triangle soup) 10515 10516 for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) { 10517 10518 pA.fromBufferAttribute( positionAttribute, i + 0 ); 10519 pB.fromBufferAttribute( positionAttribute, i + 1 ); 10520 pC.fromBufferAttribute( positionAttribute, i + 2 ); 10521 10522 cb.subVectors( pC, pB ); 10523 ab.subVectors( pA, pB ); 10524 cb.cross( ab ); 10525 10526 normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z ); 10527 normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z ); 10528 normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z ); 10529 10530 } 10531 10532 } 10533 10534 this.normalizeNormals(); 10535 10536 normalAttribute.needsUpdate = true; 10537 10538 } 10539 10540 } 10541 10542 // @deprecated since r144 10543 10544 merge() { 10545 10546 console.error( 'THREE.BufferGeometry.merge() has been removed. Use THREE.BufferGeometryUtils.mergeBufferGeometries() instead.' ); 10547 return this; 10548 10549 } 10550 10551 normalizeNormals() { 10552 10553 const normals = this.attributes.normal; 10554 10555 for ( let i = 0, il = normals.count; i < il; i ++ ) { 10556 10557 _vector$8.fromBufferAttribute( normals, i ); 10558 10559 _vector$8.normalize(); 10560 10561 normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); 10562 10563 } 10564 10565 } 10566 10567 toNonIndexed() { 10568 10569 function convertBufferAttribute( attribute, indices ) { 10570 10571 const array = attribute.array; 10572 const itemSize = attribute.itemSize; 10573 const normalized = attribute.normalized; 10574 10575 const array2 = new array.constructor( indices.length * itemSize ); 10576 10577 let index = 0, index2 = 0; 10578 10579 for ( let i = 0, l = indices.length; i < l; i ++ ) { 10580 10581 if ( attribute.isInterleavedBufferAttribute ) { 10582 10583 index = indices[ i ] * attribute.data.stride + attribute.offset; 10584 10585 } else { 10586 10587 index = indices[ i ] * itemSize; 10588 10589 } 10590 10591 for ( let j = 0; j < itemSize; j ++ ) { 10592 10593 array2[ index2 ++ ] = array[ index ++ ]; 10594 10595 } 10596 10597 } 10598 10599 return new BufferAttribute( array2, itemSize, normalized ); 10600 10601 } 10602 10603 // 10604 10605 if ( this.index === null ) { 10606 10607 console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' ); 10608 return this; 10609 10610 } 10611 10612 const geometry2 = new BufferGeometry(); 10613 10614 const indices = this.index.array; 10615 const attributes = this.attributes; 10616 10617 // attributes 10618 10619 for ( const name in attributes ) { 10620 10621 const attribute = attributes[ name ]; 10622 10623 const newAttribute = convertBufferAttribute( attribute, indices ); 10624 10625 geometry2.setAttribute( name, newAttribute ); 10626 10627 } 10628 10629 // morph attributes 10630 10631 const morphAttributes = this.morphAttributes; 10632 10633 for ( const name in morphAttributes ) { 10634 10635 const morphArray = []; 10636 const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes 10637 10638 for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) { 10639 10640 const attribute = morphAttribute[ i ]; 10641 10642 const newAttribute = convertBufferAttribute( attribute, indices ); 10643 10644 morphArray.push( newAttribute ); 10645 10646 } 10647 10648 geometry2.morphAttributes[ name ] = morphArray; 10649 10650 } 10651 10652 geometry2.morphTargetsRelative = this.morphTargetsRelative; 10653 10654 // groups 10655 10656 const groups = this.groups; 10657 10658 for ( let i = 0, l = groups.length; i < l; i ++ ) { 10659 10660 const group = groups[ i ]; 10661 geometry2.addGroup( group.start, group.count, group.materialIndex ); 10662 10663 } 10664 10665 return geometry2; 10666 10667 } 10668 10669 toJSON() { 10670 10671 const data = { 10672 metadata: { 10673 version: 4.5, 10674 type: 'BufferGeometry', 10675 generator: 'BufferGeometry.toJSON' 10676 } 10677 }; 10678 10679 // standard BufferGeometry serialization 10680 10681 data.uuid = this.uuid; 10682 data.type = this.type; 10683 if ( this.name !== '' ) data.name = this.name; 10684 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; 10685 10686 if ( this.parameters !== undefined ) { 10687 10688 const parameters = this.parameters; 10689 10690 for ( const key in parameters ) { 10691 10692 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; 10693 10694 } 10695 10696 return data; 10697 10698 } 10699 10700 // for simplicity the code assumes attributes are not shared across geometries, see #15811 10701 10702 data.data = { attributes: {} }; 10703 10704 const index = this.index; 10705 10706 if ( index !== null ) { 10707 10708 data.data.index = { 10709 type: index.array.constructor.name, 10710 array: Array.prototype.slice.call( index.array ) 10711 }; 10712 10713 } 10714 10715 const attributes = this.attributes; 10716 10717 for ( const key in attributes ) { 10718 10719 const attribute = attributes[ key ]; 10720 10721 data.data.attributes[ key ] = attribute.toJSON( data.data ); 10722 10723 } 10724 10725 const morphAttributes = {}; 10726 let hasMorphAttributes = false; 10727 10728 for ( const key in this.morphAttributes ) { 10729 10730 const attributeArray = this.morphAttributes[ key ]; 10731 10732 const array = []; 10733 10734 for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { 10735 10736 const attribute = attributeArray[ i ]; 10737 10738 array.push( attribute.toJSON( data.data ) ); 10739 10740 } 10741 10742 if ( array.length > 0 ) { 10743 10744 morphAttributes[ key ] = array; 10745 10746 hasMorphAttributes = true; 10747 10748 } 10749 10750 } 10751 10752 if ( hasMorphAttributes ) { 10753 10754 data.data.morphAttributes = morphAttributes; 10755 data.data.morphTargetsRelative = this.morphTargetsRelative; 10756 10757 } 10758 10759 const groups = this.groups; 10760 10761 if ( groups.length > 0 ) { 10762 10763 data.data.groups = JSON.parse( JSON.stringify( groups ) ); 10764 10765 } 10766 10767 const boundingSphere = this.boundingSphere; 10768 10769 if ( boundingSphere !== null ) { 10770 10771 data.data.boundingSphere = { 10772 center: boundingSphere.center.toArray(), 10773 radius: boundingSphere.radius 10774 }; 10775 10776 } 10777 10778 return data; 10779 10780 } 10781 10782 clone() { 10783 10784 return new this.constructor().copy( this ); 10785 10786 } 10787 10788 copy( source ) { 10789 10790 // reset 10791 10792 this.index = null; 10793 this.attributes = {}; 10794 this.morphAttributes = {}; 10795 this.groups = []; 10796 this.boundingBox = null; 10797 this.boundingSphere = null; 10798 10799 // used for storing cloned, shared data 10800 10801 const data = {}; 10802 10803 // name 10804 10805 this.name = source.name; 10806 10807 // index 10808 10809 const index = source.index; 10810 10811 if ( index !== null ) { 10812 10813 this.setIndex( index.clone( data ) ); 10814 10815 } 10816 10817 // attributes 10818 10819 const attributes = source.attributes; 10820 10821 for ( const name in attributes ) { 10822 10823 const attribute = attributes[ name ]; 10824 this.setAttribute( name, attribute.clone( data ) ); 10825 10826 } 10827 10828 // morph attributes 10829 10830 const morphAttributes = source.morphAttributes; 10831 10832 for ( const name in morphAttributes ) { 10833 10834 const array = []; 10835 const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes 10836 10837 for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) { 10838 10839 array.push( morphAttribute[ i ].clone( data ) ); 10840 10841 } 10842 10843 this.morphAttributes[ name ] = array; 10844 10845 } 10846 10847 this.morphTargetsRelative = source.morphTargetsRelative; 10848 10849 // groups 10850 10851 const groups = source.groups; 10852 10853 for ( let i = 0, l = groups.length; i < l; i ++ ) { 10854 10855 const group = groups[ i ]; 10856 this.addGroup( group.start, group.count, group.materialIndex ); 10857 10858 } 10859 10860 // bounding box 10861 10862 const boundingBox = source.boundingBox; 10863 10864 if ( boundingBox !== null ) { 10865 10866 this.boundingBox = boundingBox.clone(); 10867 10868 } 10869 10870 // bounding sphere 10871 10872 const boundingSphere = source.boundingSphere; 10873 10874 if ( boundingSphere !== null ) { 10875 10876 this.boundingSphere = boundingSphere.clone(); 10877 10878 } 10879 10880 // draw range 10881 10882 this.drawRange.start = source.drawRange.start; 10883 this.drawRange.count = source.drawRange.count; 10884 10885 // user data 10886 10887 this.userData = source.userData; 10888 10889 return this; 10890 10891 } 10892 10893 dispose() { 10894 10895 this.dispatchEvent( { type: 'dispose' } ); 10896 10897 } 10898 10899} 10900 10901const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); 10902const _ray$2 = /*@__PURE__*/ new Ray(); 10903const _sphere$3 = /*@__PURE__*/ new Sphere(); 10904const _sphereHitAt = /*@__PURE__*/ new Vector3(); 10905 10906const _vA$1 = /*@__PURE__*/ new Vector3(); 10907const _vB$1 = /*@__PURE__*/ new Vector3(); 10908const _vC$1 = /*@__PURE__*/ new Vector3(); 10909 10910const _tempA = /*@__PURE__*/ new Vector3(); 10911const _morphA = /*@__PURE__*/ new Vector3(); 10912 10913const _uvA$1 = /*@__PURE__*/ new Vector2(); 10914const _uvB$1 = /*@__PURE__*/ new Vector2(); 10915const _uvC$1 = /*@__PURE__*/ new Vector2(); 10916 10917const _intersectionPoint = /*@__PURE__*/ new Vector3(); 10918const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); 10919 10920class Mesh extends Object3D { 10921 10922 constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) { 10923 10924 super(); 10925 10926 this.isMesh = true; 10927 10928 this.type = 'Mesh'; 10929 10930 this.geometry = geometry; 10931 this.material = material; 10932 10933 this.updateMorphTargets(); 10934 10935 } 10936 10937 copy( source, recursive ) { 10938 10939 super.copy( source, recursive ); 10940 10941 if ( source.morphTargetInfluences !== undefined ) { 10942 10943 this.morphTargetInfluences = source.morphTargetInfluences.slice(); 10944 10945 } 10946 10947 if ( source.morphTargetDictionary !== undefined ) { 10948 10949 this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); 10950 10951 } 10952 10953 this.material = source.material; 10954 this.geometry = source.geometry; 10955 10956 return this; 10957 10958 } 10959 10960 updateMorphTargets() { 10961 10962 const geometry = this.geometry; 10963 10964 const morphAttributes = geometry.morphAttributes; 10965 const keys = Object.keys( morphAttributes ); 10966 10967 if ( keys.length > 0 ) { 10968 10969 const morphAttribute = morphAttributes[ keys[ 0 ] ]; 10970 10971 if ( morphAttribute !== undefined ) { 10972 10973 this.morphTargetInfluences = []; 10974 this.morphTargetDictionary = {}; 10975 10976 for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 10977 10978 const name = morphAttribute[ m ].name || String( m ); 10979 10980 this.morphTargetInfluences.push( 0 ); 10981 this.morphTargetDictionary[ name ] = m; 10982 10983 } 10984 10985 } 10986 10987 } 10988 10989 } 10990 10991 getVertexPosition( index, target ) { 10992 10993 const geometry = this.geometry; 10994 const position = geometry.attributes.position; 10995 const morphPosition = geometry.morphAttributes.position; 10996 const morphTargetsRelative = geometry.morphTargetsRelative; 10997 10998 target.fromBufferAttribute( position, index ); 10999 11000 const morphInfluences = this.morphTargetInfluences; 11001 11002 if ( morphPosition && morphInfluences ) { 11003 11004 _morphA.set( 0, 0, 0 ); 11005 11006 for ( let i = 0, il = morphPosition.length; i < il; i ++ ) { 11007 11008 const influence = morphInfluences[ i ]; 11009 const morphAttribute = morphPosition[ i ]; 11010 11011 if ( influence === 0 ) continue; 11012 11013 _tempA.fromBufferAttribute( morphAttribute, index ); 11014 11015 if ( morphTargetsRelative ) { 11016 11017 _morphA.addScaledVector( _tempA, influence ); 11018 11019 } else { 11020 11021 _morphA.addScaledVector( _tempA.sub( target ), influence ); 11022 11023 } 11024 11025 } 11026 11027 target.add( _morphA ); 11028 11029 } 11030 11031 if ( this.isSkinnedMesh ) { 11032 11033 this.boneTransform( index, target ); 11034 11035 } 11036 11037 return target; 11038 11039 } 11040 11041 raycast( raycaster, intersects ) { 11042 11043 const geometry = this.geometry; 11044 const material = this.material; 11045 const matrixWorld = this.matrixWorld; 11046 11047 if ( material === undefined ) return; 11048 11049 // Checking boundingSphere distance to ray 11050 11051 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 11052 11053 _sphere$3.copy( geometry.boundingSphere ); 11054 _sphere$3.applyMatrix4( matrixWorld ); 11055 11056 _ray$2.copy( raycaster.ray ).recast( raycaster.near ); 11057 11058 if ( _sphere$3.containsPoint( _ray$2.origin ) === false ) { 11059 11060 if ( _ray$2.intersectSphere( _sphere$3, _sphereHitAt ) === null ) return; 11061 11062 if ( _ray$2.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return; 11063 11064 } 11065 11066 // 11067 11068 _inverseMatrix$2.copy( matrixWorld ).invert(); 11069 _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); 11070 11071 // Check boundingBox before continuing 11072 11073 if ( geometry.boundingBox !== null ) { 11074 11075 if ( _ray$2.intersectsBox( geometry.boundingBox ) === false ) return; 11076 11077 } 11078 11079 let intersection; 11080 11081 const index = geometry.index; 11082 const position = geometry.attributes.position; 11083 const uv = geometry.attributes.uv; 11084 const uv2 = geometry.attributes.uv2; 11085 const groups = geometry.groups;
vendor: 6,468 bytes, lines 11086-11338
11086 const drawRange = geometry.drawRange; 11087 11088 if ( index !== null ) { 11089 11090 // indexed buffer geometry 11091 11092 if ( Array.isArray( material ) ) { 11093 11094 for ( let i = 0, il = groups.length; i < il; i ++ ) { 11095 11096 const group = groups[ i ]; 11097 const groupMaterial = material[ group.materialIndex ]; 11098 11099 const start = Math.max( group.start, drawRange.start ); 11100 const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); 11101 11102 for ( let j = start, jl = end; j < jl; j += 3 ) { 11103 11104 const a = index.getX( j ); 11105 const b = index.getX( j + 1 ); 11106 const c = index.getX( j + 2 ); 11107 11108 intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray$2, uv, uv2, a, b, c ); 11109 11110 if ( intersection ) { 11111 11112 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics 11113 intersection.face.materialIndex = group.materialIndex; 11114 intersects.push( intersection ); 11115 11116 } 11117 11118 } 11119 11120 } 11121 11122 } else { 11123 11124 const start = Math.max( 0, drawRange.start ); 11125 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); 11126 11127 for ( let i = start, il = end; i < il; i += 3 ) { 11128 11129 const a = index.getX( i ); 11130 const b = index.getX( i + 1 ); 11131 const c = index.getX( i + 2 ); 11132 11133 intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray$2, uv, uv2, a, b, c ); 11134 11135 if ( intersection ) { 11136 11137 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics 11138 intersects.push( intersection ); 11139 11140 } 11141 11142 } 11143 11144 } 11145 11146 } else if ( position !== undefined ) { 11147 11148 // non-indexed buffer geometry 11149 11150 if ( Array.isArray( material ) ) { 11151 11152 for ( let i = 0, il = groups.length; i < il; i ++ ) { 11153 11154 const group = groups[ i ]; 11155 const groupMaterial = material[ group.materialIndex ]; 11156 11157 const start = Math.max( group.start, drawRange.start ); 11158 const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); 11159 11160 for ( let j = start, jl = end; j < jl; j += 3 ) { 11161 11162 const a = j; 11163 const b = j + 1; 11164 const c = j + 2; 11165 11166 intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray$2, uv, uv2, a, b, c ); 11167 11168 if ( intersection ) { 11169 11170 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics 11171 intersection.face.materialIndex = group.materialIndex; 11172 intersects.push( intersection ); 11173 11174 } 11175 11176 } 11177 11178 } 11179 11180 } else { 11181 11182 const start = Math.max( 0, drawRange.start ); 11183 const end = Math.min( position.count, ( drawRange.start + drawRange.count ) ); 11184 11185 for ( let i = start, il = end; i < il; i += 3 ) { 11186 11187 const a = i; 11188 const b = i + 1; 11189 const c = i + 2; 11190 11191 intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray$2, uv, uv2, a, b, c ); 11192 11193 if ( intersection ) { 11194 11195 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics 11196 intersects.push( intersection ); 11197 11198 } 11199 11200 } 11201 11202 } 11203 11204 } 11205 11206 } 11207 11208} 11209 11210function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) { 11211 11212 let intersect; 11213 11214 if ( material.side === BackSide ) { 11215 11216 intersect = ray.intersectTriangle( pC, pB, pA, true, point ); 11217 11218 } else { 11219 11220 intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point ); 11221 11222 } 11223 11224 if ( intersect === null ) return null; 11225 11226 _intersectionPointWorld.copy( point ); 11227 _intersectionPointWorld.applyMatrix4( object.matrixWorld ); 11228 11229 const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld ); 11230 11231 if ( distance < raycaster.near || distance > raycaster.far ) return null; 11232 11233 return { 11234 distance: distance, 11235 point: _intersectionPointWorld.clone(), 11236 object: object 11237 }; 11238 11239} 11240 11241function checkBufferGeometryIntersection( object, material, raycaster, ray, uv, uv2, a, b, c ) { 11242 11243 object.getVertexPosition( a, _vA$1 ); 11244 object.getVertexPosition( b, _vB$1 ); 11245 object.getVertexPosition( c, _vC$1 ); 11246 11247 const intersection = checkIntersection( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint ); 11248 11249 if ( intersection ) { 11250 11251 if ( uv ) { 11252 11253 _uvA$1.fromBufferAttribute( uv, a ); 11254 _uvB$1.fromBufferAttribute( uv, b ); 11255 _uvC$1.fromBufferAttribute( uv, c ); 11256 11257 intersection.uv = Triangle.getUV( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); 11258 11259 } 11260 11261 if ( uv2 ) { 11262 11263 _uvA$1.fromBufferAttribute( uv2, a ); 11264 _uvB$1.fromBufferAttribute( uv2, b ); 11265 _uvC$1.fromBufferAttribute( uv2, c ); 11266 11267 intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); 11268 11269 } 11270 11271 const face = { 11272 a: a, 11273 b: b, 11274 c: c, 11275 normal: new Vector3(), 11276 materialIndex: 0 11277 }; 11278 11279 Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal ); 11280 11281 intersection.face = face; 11282 11283 } 11284 11285 return intersection; 11286 11287} 11288 11289class BoxGeometry extends BufferGeometry { 11290 11291 constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) { 11292 11293 super(); 11294 11295 this.type = 'BoxGeometry'; 11296 11297 this.parameters = { 11298 width: width, 11299 height: height, 11300 depth: depth, 11301 widthSegments: widthSegments, 11302 heightSegments: heightSegments, 11303 depthSegments: depthSegments 11304 }; 11305 11306 const scope = this; 11307 11308 // segments 11309 11310 widthSegments = Math.floor( widthSegments ); 11311 heightSegments = Math.floor( heightSegments ); 11312 depthSegments = Math.floor( depthSegments ); 11313 11314 // buffers 11315 11316 const indices = []; 11317 const vertices = []; 11318 const normals = []; 11319 const uvs = []; 11320 11321 // helper variables 11322 11323 let numberOfVertices = 0; 11324 let groupStart = 0; 11325 11326 // build each side of the box geometry 11327 11328 buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px 11329 buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx 11330 buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py 11331 buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny 11332 buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz 11333 buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz 11334 11335 // build geometry 11336 11337 this.setIndex( indices ); 11338 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,573 bytes, lines 11339-11579
11339 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 11340 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 11341 11342 function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { 11343 11344 const segmentWidth = width / gridX; 11345 const segmentHeight = height / gridY; 11346 11347 const widthHalf = width / 2; 11348 const heightHalf = height / 2; 11349 const depthHalf = depth / 2; 11350 11351 const gridX1 = gridX + 1; 11352 const gridY1 = gridY + 1; 11353 11354 let vertexCounter = 0; 11355 let groupCount = 0; 11356 11357 const vector = new Vector3(); 11358 11359 // generate vertices, normals and uvs 11360 11361 for ( let iy = 0; iy < gridY1; iy ++ ) { 11362 11363 const y = iy * segmentHeight - heightHalf; 11364 11365 for ( let ix = 0; ix < gridX1; ix ++ ) { 11366 11367 const x = ix * segmentWidth - widthHalf; 11368 11369 // set values to correct vector component 11370 11371 vector[ u ] = x * udir; 11372 vector[ v ] = y * vdir; 11373 vector[ w ] = depthHalf; 11374 11375 // now apply vector to vertex buffer 11376 11377 vertices.push( vector.x, vector.y, vector.z ); 11378 11379 // set values to correct vector component 11380 11381 vector[ u ] = 0; 11382 vector[ v ] = 0; 11383 vector[ w ] = depth > 0 ? 1 : - 1; 11384 11385 // now apply vector to normal buffer 11386 11387 normals.push( vector.x, vector.y, vector.z ); 11388 11389 // uvs 11390 11391 uvs.push( ix / gridX ); 11392 uvs.push( 1 - ( iy / gridY ) ); 11393 11394 // counters 11395 11396 vertexCounter += 1; 11397 11398 } 11399 11400 } 11401 11402 // indices 11403 11404 // 1. you need three indices to draw a single face 11405 // 2. a single segment consists of two faces 11406 // 3. so we need to generate six (2*3) indices per segment 11407 11408 for ( let iy = 0; iy < gridY; iy ++ ) { 11409 11410 for ( let ix = 0; ix < gridX; ix ++ ) { 11411 11412 const a = numberOfVertices + ix + gridX1 * iy; 11413 const b = numberOfVertices + ix + gridX1 * ( iy + 1 ); 11414 const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); 11415 const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; 11416 11417 // faces 11418 11419 indices.push( a, b, d ); 11420 indices.push( b, c, d ); 11421 11422 // increase counter 11423 11424 groupCount += 6; 11425 11426 } 11427 11428 } 11429 11430 // add a group to the geometry. this will ensure multi material support 11431 11432 scope.addGroup( groupStart, groupCount, materialIndex ); 11433 11434 // calculate new start value for groups 11435 11436 groupStart += groupCount; 11437 11438 // update total number of vertices 11439 11440 numberOfVertices += vertexCounter; 11441 11442 } 11443 11444 } 11445 11446 copy( source ) { 11447 11448 super.copy( source ); 11449 11450 this.parameters = Object.assign( {}, source.parameters ); 11451 11452 return this; 11453 11454 } 11455 11456 static fromJSON( data ) { 11457 11458 return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); 11459 11460 } 11461 11462} 11463 11464/** 11465 * Uniform Utilities 11466 */ 11467 11468function cloneUniforms( src ) { 11469 11470 const dst = {}; 11471 11472 for ( const u in src ) { 11473 11474 dst[ u ] = {}; 11475 11476 for ( const p in src[ u ] ) { 11477 11478 const property = src[ u ][ p ]; 11479 11480 if ( property && ( property.isColor || 11481 property.isMatrix3 || property.isMatrix4 || 11482 property.isVector2 || property.isVector3 || property.isVector4 || 11483 property.isTexture || property.isQuaternion ) ) { 11484 11485 dst[ u ][ p ] = property.clone(); 11486 11487 } else if ( Array.isArray( property ) ) { 11488 11489 dst[ u ][ p ] = property.slice(); 11490 11491 } else { 11492 11493 dst[ u ][ p ] = property; 11494 11495 } 11496 11497 } 11498 11499 } 11500 11501 return dst; 11502 11503} 11504 11505function mergeUniforms( uniforms ) { 11506 11507 const merged = {}; 11508 11509 for ( let u = 0; u < uniforms.length; u ++ ) { 11510 11511 const tmp = cloneUniforms( uniforms[ u ] ); 11512 11513 for ( const p in tmp ) { 11514 11515 merged[ p ] = tmp[ p ]; 11516 11517 } 11518 11519 } 11520 11521 return merged; 11522 11523} 11524 11525function cloneUniformsGroups( src ) { 11526 11527 const dst = []; 11528 11529 for ( let u = 0; u < src.length; u ++ ) { 11530 11531 dst.push( src[ u ].clone() ); 11532 11533 } 11534 11535 return dst; 11536 11537} 11538 11539function getUnlitUniformColorSpace( renderer ) { 11540 11541 if ( renderer.getRenderTarget() === null ) { 11542 11543 // https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398 11544 return renderer.outputEncoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace; 11545 11546 } 11547 11548 return LinearSRGBColorSpace; 11549 11550} 11551 11552// Legacy 11553 11554const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms }; 11555 11556var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"; 11557 11558var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}"; 11559 11560class ShaderMaterial extends Material { 11561 11562 constructor( parameters ) { 11563 11564 super(); 11565 11566 this.isShaderMaterial = true; 11567 11568 this.type = 'ShaderMaterial'; 11569 11570 this.defines = {}; 11571 this.uniforms = {}; 11572 this.uniformsGroups = []; 11573 11574 this.vertexShader = default_vertex; 11575 this.fragmentShader = default_fragment; 11576 11577 this.linewidth = 1; 11578 11579 this.wireframe = false;
vendor: 4,992 bytes, lines 11580-11834
11580 this.wireframeLinewidth = 1; 11581 11582 this.fog = false; // set to use scene fog 11583 this.lights = false; // set to use scene lights 11584 this.clipping = false; // set to use user-defined clipping planes 11585 11586 this.extensions = { 11587 derivatives: false, // set to use derivatives 11588 fragDepth: false, // set to use fragment depth values 11589 drawBuffers: false, // set to use draw buffers 11590 shaderTextureLOD: false // set to use shader texture LOD 11591 }; 11592 11593 // When rendered geometry doesn't include these attributes but the material does, 11594 // use these default values in WebGL. This avoids errors when buffer data is missing. 11595 this.defaultAttributeValues = { 11596 'color': [ 1, 1, 1 ], 11597 'uv': [ 0, 0 ], 11598 'uv2': [ 0, 0 ] 11599 }; 11600 11601 this.index0AttributeName = undefined; 11602 this.uniformsNeedUpdate = false; 11603 11604 this.glslVersion = null; 11605 11606 if ( parameters !== undefined ) { 11607 11608 this.setValues( parameters ); 11609 11610 } 11611 11612 } 11613 11614 copy( source ) { 11615 11616 super.copy( source ); 11617 11618 this.fragmentShader = source.fragmentShader; 11619 this.vertexShader = source.vertexShader; 11620 11621 this.uniforms = cloneUniforms( source.uniforms ); 11622 this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups ); 11623 11624 this.defines = Object.assign( {}, source.defines ); 11625 11626 this.wireframe = source.wireframe; 11627 this.wireframeLinewidth = source.wireframeLinewidth; 11628 11629 this.fog = source.fog; 11630 this.lights = source.lights; 11631 this.clipping = source.clipping; 11632 11633 this.extensions = Object.assign( {}, source.extensions ); 11634 11635 this.glslVersion = source.glslVersion; 11636 11637 return this; 11638 11639 } 11640 11641 toJSON( meta ) { 11642 11643 const data = super.toJSON( meta ); 11644 11645 data.glslVersion = this.glslVersion; 11646 data.uniforms = {}; 11647 11648 for ( const name in this.uniforms ) { 11649 11650 const uniform = this.uniforms[ name ]; 11651 const value = uniform.value; 11652 11653 if ( value && value.isTexture ) { 11654 11655 data.uniforms[ name ] = { 11656 type: 't', 11657 value: value.toJSON( meta ).uuid 11658 }; 11659 11660 } else if ( value && value.isColor ) { 11661 11662 data.uniforms[ name ] = { 11663 type: 'c', 11664 value: value.getHex() 11665 }; 11666 11667 } else if ( value && value.isVector2 ) { 11668 11669 data.uniforms[ name ] = { 11670 type: 'v2', 11671 value: value.toArray() 11672 }; 11673 11674 } else if ( value && value.isVector3 ) { 11675 11676 data.uniforms[ name ] = { 11677 type: 'v3', 11678 value: value.toArray() 11679 }; 11680 11681 } else if ( value && value.isVector4 ) { 11682 11683 data.uniforms[ name ] = { 11684 type: 'v4', 11685 value: value.toArray() 11686 }; 11687 11688 } else if ( value && value.isMatrix3 ) { 11689 11690 data.uniforms[ name ] = { 11691 type: 'm3', 11692 value: value.toArray() 11693 }; 11694 11695 } else if ( value && value.isMatrix4 ) { 11696 11697 data.uniforms[ name ] = { 11698 type: 'm4', 11699 value: value.toArray() 11700 }; 11701 11702 } else { 11703 11704 data.uniforms[ name ] = { 11705 value: value 11706 }; 11707 11708 // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far 11709 11710 } 11711 11712 } 11713 11714 if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines; 11715 11716 data.vertexShader = this.vertexShader; 11717 data.fragmentShader = this.fragmentShader; 11718 11719 const extensions = {}; 11720 11721 for ( const key in this.extensions ) { 11722 11723 if ( this.extensions[ key ] === true ) extensions[ key ] = true; 11724 11725 } 11726 11727 if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions; 11728 11729 return data; 11730 11731 } 11732 11733} 11734 11735class Camera extends Object3D { 11736 11737 constructor() { 11738 11739 super(); 11740 11741 this.isCamera = true; 11742 11743 this.type = 'Camera'; 11744 11745 this.matrixWorldInverse = new Matrix4(); 11746 11747 this.projectionMatrix = new Matrix4(); 11748 this.projectionMatrixInverse = new Matrix4(); 11749 11750 } 11751 11752 copy( source, recursive ) { 11753 11754 super.copy( source, recursive ); 11755 11756 this.matrixWorldInverse.copy( source.matrixWorldInverse ); 11757 11758 this.projectionMatrix.copy( source.projectionMatrix ); 11759 this.projectionMatrixInverse.copy( source.projectionMatrixInverse ); 11760 11761 return this; 11762 11763 } 11764 11765 getWorldDirection( target ) { 11766 11767 this.updateWorldMatrix( true, false ); 11768 11769 const e = this.matrixWorld.elements; 11770 11771 return target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize(); 11772 11773 } 11774 11775 updateMatrixWorld( force ) { 11776 11777 super.updateMatrixWorld( force ); 11778 11779 this.matrixWorldInverse.copy( this.matrixWorld ).invert(); 11780 11781 } 11782 11783 updateWorldMatrix( updateParents, updateChildren ) { 11784 11785 super.updateWorldMatrix( updateParents, updateChildren ); 11786 11787 this.matrixWorldInverse.copy( this.matrixWorld ).invert(); 11788 11789 } 11790 11791 clone() { 11792 11793 return new this.constructor().copy( this ); 11794 11795 } 11796 11797} 11798 11799class PerspectiveCamera extends Camera { 11800 11801 constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) { 11802 11803 super(); 11804 11805 this.isPerspectiveCamera = true; 11806 11807 this.type = 'PerspectiveCamera'; 11808 11809 this.fov = fov; 11810 this.zoom = 1; 11811 11812 this.near = near; 11813 this.far = far; 11814 this.focus = 10; 11815 11816 this.aspect = aspect; 11817 this.view = null; 11818 11819 this.filmGauge = 35; // width of the film (default in millimeters) 11820 this.filmOffset = 0; // horizontal film offset (same unit as gauge) 11821 11822 this.updateProjectionMatrix(); 11823 11824 } 11825 11826 copy( source, recursive ) { 11827 11828 super.copy( source, recursive ); 11829 11830 this.fov = source.fov; 11831 this.zoom = source.zoom; 11832 11833 this.near = source.near; 11834 this.far = source.far;
vendor: 3,387 bytes, lines 11835-11980
11835 this.focus = source.focus; 11836 11837 this.aspect = source.aspect; 11838 this.view = source.view === null ? null : Object.assign( {}, source.view ); 11839 11840 this.filmGauge = source.filmGauge; 11841 this.filmOffset = source.filmOffset; 11842 11843 return this; 11844 11845 } 11846 11847 /** 11848 * Sets the FOV by focal length in respect to the current .filmGauge. 11849 * 11850 * The default film gauge is 35, so that the focal length can be specified for 11851 * a 35mm (full frame) camera. 11852 * 11853 * Values for focal length and film gauge must have the same unit. 11854 */ 11855 setFocalLength( focalLength ) { 11856 11857 /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */ 11858 const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; 11859 11860 this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope ); 11861 this.updateProjectionMatrix(); 11862 11863 } 11864 11865 /** 11866 * Calculates the focal length from the current .fov and .filmGauge. 11867 */ 11868 getFocalLength() { 11869 11870 const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov ); 11871 11872 return 0.5 * this.getFilmHeight() / vExtentSlope; 11873 11874 } 11875 11876 getEffectiveFOV() { 11877 11878 return RAD2DEG * 2 * Math.atan( 11879 Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom ); 11880 11881 } 11882 11883 getFilmWidth() { 11884 11885 // film not completely covered in portrait format (aspect < 1) 11886 return this.filmGauge * Math.min( this.aspect, 1 ); 11887 11888 } 11889 11890 getFilmHeight() { 11891 11892 // film not completely covered in landscape format (aspect > 1) 11893 return this.filmGauge / Math.max( this.aspect, 1 ); 11894 11895 } 11896 11897 /** 11898 * Sets an offset in a larger frustum. This is useful for multi-window or 11899 * multi-monitor/multi-machine setups. 11900 * 11901 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and 11902 * the monitors are in grid like this 11903 * 11904 * +---+---+---+ 11905 * | A | B | C | 11906 * +---+---+---+ 11907 * | D | E | F | 11908 * +---+---+---+ 11909 * 11910 * then for each monitor you would call it like this 11911 * 11912 * const w = 1920; 11913 * const h = 1080; 11914 * const fullWidth = w * 3; 11915 * const fullHeight = h * 2; 11916 * 11917 * --A-- 11918 * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); 11919 * --B-- 11920 * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); 11921 * --C-- 11922 * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); 11923 * --D-- 11924 * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); 11925 * --E-- 11926 * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); 11927 * --F-- 11928 * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); 11929 * 11930 * Note there is no reason monitors have to be the same size or in a grid. 11931 */ 11932 setViewOffset( fullWidth, fullHeight, x, y, width, height ) { 11933 11934 this.aspect = fullWidth / fullHeight; 11935 11936 if ( this.view === null ) { 11937 11938 this.view = { 11939 enabled: true, 11940 fullWidth: 1, 11941 fullHeight: 1, 11942 offsetX: 0, 11943 offsetY: 0, 11944 width: 1, 11945 height: 1 11946 }; 11947 11948 } 11949 11950 this.view.enabled = true; 11951 this.view.fullWidth = fullWidth; 11952 this.view.fullHeight = fullHeight; 11953 this.view.offsetX = x; 11954 this.view.offsetY = y; 11955 this.view.width = width; 11956 this.view.height = height; 11957 11958 this.updateProjectionMatrix(); 11959 11960 } 11961 11962 clearViewOffset() { 11963 11964 if ( this.view !== null ) { 11965 11966 this.view.enabled = false; 11967 11968 } 11969 11970 this.updateProjectionMatrix(); 11971 11972 } 11973 11974 updateProjectionMatrix() { 11975 11976 const near = this.near; 11977 let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom; 11978 let height = 2 * top; 11979 let width = this.aspect * height; 11980 let left = - 0.5 * width;
11981 const view = this.view; 11982 11983 if ( this.view !== null && this.view.enabled ) { 11984 11985 const fullWidth = view.fullWidth, 11986 fullHeight = view.fullHeight; 11987 11988 left += view.offsetX * width / fullWidth; 11989 top -= view.offsetY * height / fullHeight; 11990 width *= view.width / fullWidth; 11991 height *= view.height / fullHeight; 11992 11993 } 11994 11995 const skew = this.filmOffset; 11996 if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); 11997 11998 this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far ); 11999 12000 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); 12001 12002 } 12003 12004 toJSON( meta ) { 12005 12006 const data = super.toJSON( meta ); 12007 12008 data.object.fov = this.fov; 12009 data.object.zoom = this.zoom; 12010 12011 data.object.near = this.near; 12012 data.object.far = this.far; 12013 data.object.focus = this.focus; 12014 12015 data.object.aspect = this.aspect; 12016 12017 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); 12018 12019 data.object.filmGauge = this.filmGauge; 12020 data.object.filmOffset = this.filmOffset; 12021 12022 return data; 12023 12024 } 12025 12026} 12027 12028const fov = - 90; // negative fov is not an error 12029const aspect = 1; 12030 12031class CubeCamera extends Object3D { 12032 12033 constructor( near, far, renderTarget ) { 12034 12035 super(); 12036 12037 this.type = 'CubeCamera'; 12038 12039 this.renderTarget = renderTarget; 12040 12041 const cameraPX = new PerspectiveCamera( fov, aspect, near, far ); 12042 cameraPX.layers = this.layers; 12043 cameraPX.up.set( 0, 1, 0 ); 12044 cameraPX.lookAt( 1, 0, 0 ); 12045 this.add( cameraPX ); 12046 12047 const cameraNX = new PerspectiveCamera( fov, aspect, near, far ); 12048 cameraNX.layers = this.layers; 12049 cameraNX.up.set( 0, 1, 0 ); 12050 cameraNX.lookAt( - 1, 0, 0 ); 12051 this.add( cameraNX ); 12052 12053 const cameraPY = new PerspectiveCamera( fov, aspect, near, far ); 12054 cameraPY.layers = this.layers; 12055 cameraPY.up.set( 0, 0, - 1 ); 12056 cameraPY.lookAt( 0, 1, 0 ); 12057 this.add( cameraPY ); 12058 12059 const cameraNY = new PerspectiveCamera( fov, aspect, near, far ); 12060 cameraNY.layers = this.layers; 12061 cameraNY.up.set( 0, 0, 1 ); 12062 cameraNY.lookAt( 0, - 1, 0 ); 12063 this.add( cameraNY ); 12064 12065 const cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); 12066 cameraPZ.layers = this.layers; 12067 cameraPZ.up.set( 0, 1, 0 ); 12068 cameraPZ.lookAt( 0, 0, 1 ); 12069 this.add( cameraPZ ); 12070 12071 const cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); 12072 cameraNZ.layers = this.layers; 12073 cameraNZ.up.set( 0, 1, 0 ); 12074 cameraNZ.lookAt( 0, 0, - 1 ); 12075 this.add( cameraNZ ); 12076 12077 } 12078 12079 update( renderer, scene ) { 12080 12081 if ( this.parent === null ) this.updateMatrixWorld(); 12082 12083 const renderTarget = this.renderTarget; 12084 12085 const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children; 12086 12087 const currentRenderTarget = renderer.getRenderTarget(); 12088 12089 const currentToneMapping = renderer.toneMapping; 12090 const currentXrEnabled = renderer.xr.enabled; 12091 12092 renderer.toneMapping = NoToneMapping; 12093 renderer.xr.enabled = false; 12094 12095 const generateMipmaps = renderTarget.texture.generateMipmaps; 12096 12097 renderTarget.texture.generateMipmaps = false; 12098 12099 renderer.setRenderTarget( renderTarget, 0 ); 12100 renderer.render( scene, cameraPX ); 12101 12102 renderer.setRenderTarget( renderTarget, 1 ); 12103 renderer.render( scene, cameraNX ); 12104 12105 renderer.setRenderTarget( renderTarget, 2 ); 12106 renderer.render( scene, cameraPY ); 12107 12108 renderer.setRenderTarget( renderTarget, 3 ); 12109 renderer.render( scene, cameraNY ); 12110 12111 renderer.setRenderTarget( renderTarget, 4 ); 12112 renderer.render( scene, cameraPZ ); 12113 12114 renderTarget.texture.generateMipmaps = generateMipmaps; 12115 12116 renderer.setRenderTarget( renderTarget, 5 ); 12117 renderer.render( scene, cameraNZ ); 12118 12119 renderer.setRenderTarget( currentRenderTarget ); 12120 12121 renderer.toneMapping = currentToneMapping; 12122 renderer.xr.enabled = currentXrEnabled; 12123 12124 renderTarget.texture.needsPMREMUpdate = true; 12125 12126 } 12127 12128} 12129 12130class CubeTexture extends Texture { 12131 12132 constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { 12133 12134 images = images !== undefined ? images : []; 12135 mapping = mapping !== undefined ? mapping : CubeReflectionMapping; 12136 12137 super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); 12138 12139 this.isCubeTexture = true; 12140 12141 this.flipY = false;
vendor: 4,767 bytes, lines 12142-12361
12142 12143 } 12144 12145 get images() { 12146 12147 return this.image; 12148 12149 } 12150 12151 set images( value ) { 12152 12153 this.image = value; 12154 12155 } 12156 12157} 12158 12159class WebGLCubeRenderTarget extends WebGLRenderTarget { 12160 12161 constructor( size = 1, options = {} ) { 12162 12163 super( size, size, options ); 12164 12165 this.isWebGLCubeRenderTarget = true; 12166 12167 const image = { width: size, height: size, depth: 1 }; 12168 const images = [ image, image, image, image, image, image ]; 12169 12170 this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); 12171 12172 // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) 12173 // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, 12174 // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly. 12175 12176 // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped 12177 // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture 12178 // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures). 12179 12180 this.texture.isRenderTargetTexture = true; 12181 12182 this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; 12183 this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; 12184 12185 } 12186 12187 fromEquirectangularTexture( renderer, texture ) { 12188 12189 this.texture.type = texture.type; 12190 this.texture.encoding = texture.encoding; 12191 12192 this.texture.generateMipmaps = texture.generateMipmaps; 12193 this.texture.minFilter = texture.minFilter; 12194 this.texture.magFilter = texture.magFilter; 12195 12196 const shader = { 12197 12198 uniforms: { 12199 tEquirect: { value: null }, 12200 }, 12201 12202 vertexShader: /* glsl */` 12203 12204 varying vec3 vWorldDirection; 12205 12206 vec3 transformDirection( in vec3 dir, in mat4 matrix ) { 12207 12208 return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); 12209 12210 } 12211 12212 void main() { 12213 12214 vWorldDirection = transformDirection( position, modelMatrix ); 12215 12216 #include <begin_vertex> 12217 #include <project_vertex> 12218 12219 } 12220 `, 12221 12222 fragmentShader: /* glsl */` 12223 12224 uniform sampler2D tEquirect; 12225 12226 varying vec3 vWorldDirection; 12227 12228 #include <common> 12229 12230 void main() { 12231 12232 vec3 direction = normalize( vWorldDirection ); 12233 12234 vec2 sampleUV = equirectUv( direction ); 12235 12236 gl_FragColor = texture2D( tEquirect, sampleUV ); 12237 12238 } 12239 ` 12240 }; 12241 12242 const geometry = new BoxGeometry( 5, 5, 5 ); 12243 12244 const material = new ShaderMaterial( { 12245 12246 name: 'CubemapFromEquirect', 12247 12248 uniforms: cloneUniforms( shader.uniforms ), 12249 vertexShader: shader.vertexShader, 12250 fragmentShader: shader.fragmentShader, 12251 side: BackSide, 12252 blending: NoBlending 12253 12254 } ); 12255 12256 material.uniforms.tEquirect.value = texture; 12257 12258 const mesh = new Mesh( geometry, material ); 12259 12260 const currentMinFilter = texture.minFilter; 12261 12262 // Avoid blurred poles 12263 if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter; 12264 12265 const camera = new CubeCamera( 1, 10, this ); 12266 camera.update( renderer, mesh ); 12267 12268 texture.minFilter = currentMinFilter; 12269 12270 mesh.geometry.dispose(); 12271 mesh.material.dispose(); 12272 12273 return this; 12274 12275 } 12276 12277 clear( renderer, color, depth, stencil ) { 12278 12279 const currentRenderTarget = renderer.getRenderTarget(); 12280 12281 for ( let i = 0; i < 6; i ++ ) { 12282 12283 renderer.setRenderTarget( this, i ); 12284 12285 renderer.clear( color, depth, stencil ); 12286 12287 } 12288 12289 renderer.setRenderTarget( currentRenderTarget ); 12290 12291 } 12292 12293} 12294 12295const _vector1 = /*@__PURE__*/ new Vector3(); 12296const _vector2 = /*@__PURE__*/ new Vector3(); 12297const _normalMatrix = /*@__PURE__*/ new Matrix3(); 12298 12299class Plane { 12300 12301 constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) { 12302 12303 this.isPlane = true; 12304 12305 // normal is assumed to be normalized 12306 12307 this.normal = normal; 12308 this.constant = constant; 12309 12310 } 12311 12312 set( normal, constant ) { 12313 12314 this.normal.copy( normal ); 12315 this.constant = constant; 12316 12317 return this; 12318 12319 } 12320 12321 setComponents( x, y, z, w ) { 12322 12323 this.normal.set( x, y, z ); 12324 this.constant = w; 12325 12326 return this; 12327 12328 } 12329 12330 setFromNormalAndCoplanarPoint( normal, point ) { 12331 12332 this.normal.copy( normal ); 12333 this.constant = - point.dot( this.normal ); 12334 12335 return this; 12336 12337 } 12338 12339 setFromCoplanarPoints( a, b, c ) { 12340 12341 const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize(); 12342 12343 // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? 12344 12345 this.setFromNormalAndCoplanarPoint( normal, a ); 12346 12347 return this; 12348 12349 } 12350 12351 copy( plane ) { 12352 12353 this.normal.copy( plane.normal ); 12354 this.constant = plane.constant; 12355 12356 return this; 12357 12358 } 12359 12360 normalize() { 12361
vendor: 4,441 bytes, lines 12362-12571
12362 // Note: will lead to a divide by zero if the plane is invalid. 12363 12364 const inverseNormalLength = 1.0 / this.normal.length(); 12365 this.normal.multiplyScalar( inverseNormalLength ); 12366 this.constant *= inverseNormalLength; 12367 12368 return this; 12369 12370 } 12371 12372 negate() { 12373 12374 this.constant *= - 1; 12375 this.normal.negate(); 12376 12377 return this; 12378 12379 } 12380 12381 distanceToPoint( point ) { 12382 12383 return this.normal.dot( point ) + this.constant; 12384 12385 } 12386 12387 distanceToSphere( sphere ) { 12388 12389 return this.distanceToPoint( sphere.center ) - sphere.radius; 12390 12391 } 12392 12393 projectPoint( point, target ) { 12394 12395 return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) ); 12396 12397 } 12398 12399 intersectLine( line, target ) { 12400 12401 const direction = line.delta( _vector1 ); 12402 12403 const denominator = this.normal.dot( direction ); 12404 12405 if ( denominator === 0 ) { 12406 12407 // line is coplanar, return origin 12408 if ( this.distanceToPoint( line.start ) === 0 ) { 12409 12410 return target.copy( line.start ); 12411 12412 } 12413 12414 // Unsure if this is the correct method to handle this case. 12415 return null; 12416 12417 } 12418 12419 const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; 12420 12421 if ( t < 0 || t > 1 ) { 12422 12423 return null; 12424 12425 } 12426 12427 return target.copy( line.start ).addScaledVector( direction, t ); 12428 12429 } 12430 12431 intersectsLine( line ) { 12432 12433 // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. 12434 12435 const startSign = this.distanceToPoint( line.start ); 12436 const endSign = this.distanceToPoint( line.end ); 12437 12438 return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); 12439 12440 } 12441 12442 intersectsBox( box ) { 12443 12444 return box.intersectsPlane( this ); 12445 12446 } 12447 12448 intersectsSphere( sphere ) { 12449 12450 return sphere.intersectsPlane( this ); 12451 12452 } 12453 12454 coplanarPoint( target ) { 12455 12456 return target.copy( this.normal ).multiplyScalar( - this.constant ); 12457 12458 } 12459 12460 applyMatrix4( matrix, optionalNormalMatrix ) { 12461 12462 const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix ); 12463 12464 const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix ); 12465 12466 const normal = this.normal.applyMatrix3( normalMatrix ).normalize(); 12467 12468 this.constant = - referencePoint.dot( normal ); 12469 12470 return this; 12471 12472 } 12473 12474 translate( offset ) { 12475 12476 this.constant -= offset.dot( this.normal ); 12477 12478 return this; 12479 12480 } 12481 12482 equals( plane ) { 12483 12484 return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); 12485 12486 } 12487 12488 clone() { 12489 12490 return new this.constructor().copy( this ); 12491 12492 } 12493 12494} 12495 12496const _sphere$2 = /*@__PURE__*/ new Sphere(); 12497const _vector$7 = /*@__PURE__*/ new Vector3(); 12498 12499class Frustum { 12500 12501 constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) { 12502 12503 this.planes = [ p0, p1, p2, p3, p4, p5 ]; 12504 12505 } 12506 12507 set( p0, p1, p2, p3, p4, p5 ) { 12508 12509 const planes = this.planes; 12510 12511 planes[ 0 ].copy( p0 ); 12512 planes[ 1 ].copy( p1 ); 12513 planes[ 2 ].copy( p2 ); 12514 planes[ 3 ].copy( p3 ); 12515 planes[ 4 ].copy( p4 ); 12516 planes[ 5 ].copy( p5 ); 12517 12518 return this; 12519 12520 } 12521 12522 copy( frustum ) { 12523 12524 const planes = this.planes; 12525 12526 for ( let i = 0; i < 6; i ++ ) { 12527 12528 planes[ i ].copy( frustum.planes[ i ] ); 12529 12530 } 12531 12532 return this; 12533 12534 } 12535 12536 setFromProjectionMatrix( m ) { 12537 12538 const planes = this.planes; 12539 const me = m.elements; 12540 const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ]; 12541 const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ]; 12542 const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ]; 12543 const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ]; 12544 12545 planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize(); 12546 planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize(); 12547 planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize(); 12548 planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize(); 12549 planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize(); 12550 planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); 12551 12552 return this; 12553 12554 } 12555 12556 intersectsObject( object ) { 12557 12558 const geometry = object.geometry; 12559 12560 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 12561 12562 _sphere$2.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); 12563 12564 return this.intersectsSphere( _sphere$2 ); 12565 12566 } 12567 12568 intersectsSprite( sprite ) { 12569 12570 _sphere$2.center.set( 0, 0, 0 ); 12571 _sphere$2.radius = 0.7071067811865476;
vendor: 5,575 bytes, lines 12572-12914
12572 _sphere$2.applyMatrix4( sprite.matrixWorld ); 12573 12574 return this.intersectsSphere( _sphere$2 ); 12575 12576 } 12577 12578 intersectsSphere( sphere ) { 12579 12580 const planes = this.planes; 12581 const center = sphere.center; 12582 const negRadius = - sphere.radius; 12583 12584 for ( let i = 0; i < 6; i ++ ) { 12585 12586 const distance = planes[ i ].distanceToPoint( center ); 12587 12588 if ( distance < negRadius ) { 12589 12590 return false; 12591 12592 } 12593 12594 } 12595 12596 return true; 12597 12598 } 12599 12600 intersectsBox( box ) { 12601 12602 const planes = this.planes; 12603 12604 for ( let i = 0; i < 6; i ++ ) { 12605 12606 const plane = planes[ i ]; 12607 12608 // corner at max distance 12609 12610 _vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x; 12611 _vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y; 12612 _vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z; 12613 12614 if ( plane.distanceToPoint( _vector$7 ) < 0 ) { 12615 12616 return false; 12617 12618 } 12619 12620 } 12621 12622 return true; 12623 12624 } 12625 12626 containsPoint( point ) { 12627 12628 const planes = this.planes; 12629 12630 for ( let i = 0; i < 6; i ++ ) { 12631 12632 if ( planes[ i ].distanceToPoint( point ) < 0 ) { 12633 12634 return false; 12635 12636 } 12637 12638 } 12639 12640 return true; 12641 12642 } 12643 12644 clone() { 12645 12646 return new this.constructor().copy( this ); 12647 12648 } 12649 12650} 12651 12652function WebGLAnimation() { 12653 12654 let context = null; 12655 let isAnimating = false; 12656 let animationLoop = null; 12657 let requestId = null; 12658 12659 function onAnimationFrame( time, frame ) { 12660 12661 animationLoop( time, frame ); 12662 12663 requestId = context.requestAnimationFrame( onAnimationFrame ); 12664 12665 } 12666 12667 return { 12668 12669 start: function () { 12670 12671 if ( isAnimating === true ) return; 12672 if ( animationLoop === null ) return; 12673 12674 requestId = context.requestAnimationFrame( onAnimationFrame ); 12675 12676 isAnimating = true; 12677 12678 }, 12679 12680 stop: function () { 12681 12682 context.cancelAnimationFrame( requestId ); 12683 12684 isAnimating = false; 12685 12686 }, 12687 12688 setAnimationLoop: function ( callback ) { 12689 12690 animationLoop = callback; 12691 12692 }, 12693 12694 setContext: function ( value ) { 12695 12696 context = value; 12697 12698 } 12699 12700 }; 12701 12702} 12703 12704function WebGLAttributes( gl, capabilities ) { 12705 12706 const isWebGL2 = capabilities.isWebGL2; 12707 12708 const buffers = new WeakMap(); 12709 12710 function createBuffer( attribute, bufferType ) { 12711 12712 const array = attribute.array; 12713 const usage = attribute.usage; 12714 12715 const buffer = gl.createBuffer(); 12716 12717 gl.bindBuffer( bufferType, buffer ); 12718 gl.bufferData( bufferType, array, usage ); 12719 12720 attribute.onUploadCallback(); 12721 12722 let type; 12723 12724 if ( array instanceof Float32Array ) { 12725 12726 type = 5126; 12727 12728 } else if ( array instanceof Uint16Array ) { 12729 12730 if ( attribute.isFloat16BufferAttribute ) { 12731 12732 if ( isWebGL2 ) { 12733 12734 type = 5131; 12735 12736 } else { 12737 12738 throw new Error( 'THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.' ); 12739 12740 } 12741 12742 } else { 12743 12744 type = 5123; 12745 12746 } 12747 12748 } else if ( array instanceof Int16Array ) { 12749 12750 type = 5122; 12751 12752 } else if ( array instanceof Uint32Array ) { 12753 12754 type = 5125; 12755 12756 } else if ( array instanceof Int32Array ) { 12757 12758 type = 5124; 12759 12760 } else if ( array instanceof Int8Array ) { 12761 12762 type = 5120; 12763 12764 } else if ( array instanceof Uint8Array ) { 12765 12766 type = 5121; 12767 12768 } else if ( array instanceof Uint8ClampedArray ) { 12769 12770 type = 5121; 12771 12772 } else { 12773 12774 throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array ); 12775 12776 } 12777 12778 return { 12779 buffer: buffer, 12780 type: type, 12781 bytesPerElement: array.BYTES_PER_ELEMENT, 12782 version: attribute.version 12783 }; 12784 12785 } 12786 12787 function updateBuffer( buffer, attribute, bufferType ) { 12788 12789 const array = attribute.array; 12790 const updateRange = attribute.updateRange; 12791 12792 gl.bindBuffer( bufferType, buffer ); 12793 12794 if ( updateRange.count === - 1 ) { 12795 12796 // Not using update ranges 12797 12798 gl.bufferSubData( bufferType, 0, array ); 12799 12800 } else { 12801 12802 if ( isWebGL2 ) { 12803 12804 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, 12805 array, updateRange.offset, updateRange.count ); 12806 12807 } else { 12808 12809 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, 12810 array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) ); 12811 12812 } 12813 12814 updateRange.count = - 1; // reset range 12815 12816 } 12817 12818 attribute.onUploadCallback(); 12819 12820 } 12821 12822 // 12823 12824 function get( attribute ) { 12825 12826 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 12827 12828 return buffers.get( attribute ); 12829 12830 } 12831 12832 function remove( attribute ) { 12833 12834 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 12835 12836 const data = buffers.get( attribute ); 12837 12838 if ( data ) { 12839 12840 gl.deleteBuffer( data.buffer ); 12841 12842 buffers.delete( attribute ); 12843 12844 } 12845 12846 } 12847 12848 function update( attribute, bufferType ) { 12849 12850 if ( attribute.isGLBufferAttribute ) { 12851 12852 const cached = buffers.get( attribute ); 12853 12854 if ( ! cached || cached.version < attribute.version ) { 12855 12856 buffers.set( attribute, { 12857 buffer: attribute.buffer, 12858 type: attribute.type, 12859 bytesPerElement: attribute.elementSize, 12860 version: attribute.version 12861 } ); 12862 12863 } 12864 12865 return; 12866 12867 } 12868 12869 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 12870 12871 const data = buffers.get( attribute ); 12872 12873 if ( data === undefined ) { 12874 12875 buffers.set( attribute, createBuffer( attribute, bufferType ) ); 12876 12877 } else if ( data.version < attribute.version ) { 12878 12879 updateBuffer( data.buffer, attribute, bufferType ); 12880 12881 data.version = attribute.version; 12882 12883 } 12884 12885 } 12886 12887 return { 12888 12889 get: get, 12890 remove: remove, 12891 update: update 12892 12893 }; 12894 12895} 12896 12897class PlaneGeometry extends BufferGeometry { 12898 12899 constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) { 12900 12901 super(); 12902 12903 this.type = 'PlaneGeometry'; 12904 12905 this.parameters = { 12906 width: width, 12907 height: height, 12908 widthSegments: widthSegments, 12909 heightSegments: heightSegments 12910 }; 12911 12912 const width_half = width / 2; 12913 const height_half = height / 2; 12914
vendor: 4,135 bytes, lines 12915-13007
12915 const gridX = Math.floor( widthSegments ); 12916 const gridY = Math.floor( heightSegments ); 12917 12918 const gridX1 = gridX + 1; 12919 const gridY1 = gridY + 1; 12920 12921 const segment_width = width / gridX; 12922 const segment_height = height / gridY; 12923 12924 // 12925 12926 const indices = []; 12927 const vertices = []; 12928 const normals = []; 12929 const uvs = []; 12930 12931 for ( let iy = 0; iy < gridY1; iy ++ ) { 12932 12933 const y = iy * segment_height - height_half; 12934 12935 for ( let ix = 0; ix < gridX1; ix ++ ) { 12936 12937 const x = ix * segment_width - width_half; 12938 12939 vertices.push( x, - y, 0 ); 12940 12941 normals.push( 0, 0, 1 ); 12942 12943 uvs.push( ix / gridX ); 12944 uvs.push( 1 - ( iy / gridY ) ); 12945 12946 } 12947 12948 } 12949 12950 for ( let iy = 0; iy < gridY; iy ++ ) { 12951 12952 for ( let ix = 0; ix < gridX; ix ++ ) { 12953 12954 const a = ix + gridX1 * iy; 12955 const b = ix + gridX1 * ( iy + 1 ); 12956 const c = ( ix + 1 ) + gridX1 * ( iy + 1 ); 12957 const d = ( ix + 1 ) + gridX1 * iy; 12958 12959 indices.push( a, b, d ); 12960 indices.push( b, c, d ); 12961 12962 } 12963 12964 } 12965 12966 this.setIndex( indices ); 12967 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 12968 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 12969 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 12970 12971 } 12972 12973 copy( source ) { 12974 12975 super.copy( source ); 12976 12977 this.parameters = Object.assign( {}, source.parameters ); 12978 12979 return this; 12980 12981 } 12982 12983 static fromJSON( data ) { 12984 12985 return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments ); 12986 12987 } 12988 12989} 12990 12991var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif"; 12992 12993var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; 12994 12995var alphatest_fragment = "#ifdef USE_ALPHATEST\n\tif ( diffuseColor.a < alphaTest ) discard;\n#endif"; 12996 12997var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif"; 12998 12999var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif"; 13000 13001var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; 13002 13003var begin_vertex = "vec3 transformed = vec3( position );"; 13004 13005var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif"; 13006 13007var bsdfs = "vec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );
13007\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( V * D );\n}\n#ifdef USE_IRIDESCENCE\n\tvec3 BRDF_GGX_Iridescence( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float iridescence, const in vec3 iridescenceFresnel, const in float roughness ) {\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = mix( F_Schlick( f0, f90, dotVH ), iridescenceFresnel, iridescence );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x >
13007 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif"; 13008 13009var iridescence_fragment = "#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660, 0.0556434,\n\t\t-1.5371385, 1.8760108, -0.2040259,\n\t\t-0.4985314, 0.0415560, 1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\t return vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );
13009\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat R21 = R12;\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif"; 13010 13011var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos.xyz );\n\t\tvec3 vSigmaY = dFdy( surf_pos.xyz );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif"; 13012 13013var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif"; 13014 13015var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif"; 13016 13017var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif"; 13018 13019var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif"; 13020 13021var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif"; 13022 13023var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif"; 13024 13025var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif"; 13026 13027var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif"; 13028 13029var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 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 max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nfloat w0( float a ) {\n\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n}\nfloat w1( float a ) {\n\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n}\nfloat w2( float a ){\n return ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n}\nfloat w3( float a ) {\n\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n}\nfloat g0( float a ) {\n\treturn w0( a ) + w1( a );\n}\nfloat g1( float a ) {\n\treturn w2( a ) + w3( a );\n}\nfloat h0( float a ) {\n\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n}\nfloat h1( float a ) {\n return 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n}\nvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, vec2 fullSize, float lod ) {\n\tuv = uv * texelSize.zw + 0.5;\n\tvec2 iuv = floor( uv );\n vec2 fuv = fract( uv );\n float g0x = g0( fuv.x );\n float g1x = g1( fuv.x );\n float h0x = h0( fuv.x );\n float h1x = h1( fuv.x );\n float h0y = h0( fuv.y );\n float h1y = h1( fuv.y );\n vec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n vec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n vec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n vec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n \n vec2 lodFudge = pow( 1.95, lod ) / fullSize;\n\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t g1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n}\nvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\tvec2 fullSize = vec2( textureSize( sampler, 0 ) );\n\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), fullSize, floor( lod ) );\n\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), fullSize, ceil( lod ) );\n\treturn mix( fSample, cSample, fract( lod ) );\n}"; 13030 13031var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_v0 0.339\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_v1 0.276\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_v4 0.046\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_v5 0.016\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_v6 0.0038\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif"; 13032 13033var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif"; 13034 13035var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif"; 13036 13037var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + dis
13037placementBias );\n#endif"; 13038 13039var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; 13040 13041var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif"; 13042 13043var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );"; 13044 13045var encodings_pars_fragment = "vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}"; 13046 13047var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif"; 13048 13049var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif"; 13050 13051var envmap_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif"; 13052 13053var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif"; 13054 13055var envmap_vertex = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t}
13055 else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif"; 13056 13057var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif"; 13058 13059var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif"; 13060 13061var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif"; 13062 13063var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif"; 13064 13065var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}"; 13066 13067var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; 13068 13069var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; 13070 13071var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;"; 13072 13073var lights_lambert_pars_fragment = "varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert"; 13074 13075var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}
13075\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif"; 13076 13077var envmap_physical_pars_fragment = "#if defined( USE_ENVMAP )\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif"; 13078 13079var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; 13080 13081var lights_toon_pars_fragment = "varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon"; 13082 13083var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;"; 13084 13085var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot
13085( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong"; 13086 13087var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;
13087\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif"; 13088 13089var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGAp
13089prox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness );\n\t#else\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;
13089\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; 13090 13091var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_L
13091IGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif"; 13092 13093var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; 13094 13095var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif"; 13096 13097var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; 13098 13099var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif"; 13100 13101var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif"; 13102 13103var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif"; 13104 13105var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif"; 13106 13107var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif"; 13108 13109var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif"; 13110 13111var map_particle_pars_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; 13112 13113var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; 13114 13115var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; 13116 13117var morphcolor_vertex = "#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif"; 13118 13119var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif"; 13120 13121var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif"; 13122 13123var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif"; 13124 13125var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;"; 13126 13127var normal_fragment_maps = "#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );
13127\n\t#else\n\t\tnormal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; 13128 13129var normal_pars_fragment = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif"; 13130 13131var normal_pars_vertex = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif"; 13132 13133var normal_vertex = "#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif"; 13134 13135var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif"; 13136 13137var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif"; 13138 13139var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n\t#endif\n#endif"; 13140 13141var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif"; 13142 13143var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif"; 13144 13145var output_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; 13146 13147var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}"; 13148 13149var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif"; 13150 13151var project_vertex = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;"; 13152 13153var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif"; 13154 13155var dithering_pars_fragment = "#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif"; 13156 13157var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, v
vendor: 14,091 bytes, lines 13157-13171
13157Uv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; 13158 13159var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; 13160 13161var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif"; 13162 13163var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif"; 13164 13165var shadowmap_vertex = "#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif"; 13166 13167var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}"; 13168 13169var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif"; 13170 13171var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\t
13171uniform int boneTextureSize;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tfloat j = i * 4.0;\n\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\ty = dy * ( y + 0.5 );\n\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\treturn bone;\n\t}\n#endif"; 13172 13173var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif"; 13174 13175var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif"; 13176 13177var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; 13178 13179var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; 13180 13181var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif"; 13182 13183var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; 13184 13185var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmission.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );\n#endif"; 13186 13187var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif"; 13188 13189var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif"; 13190 13191var uv_pars_vertex = "#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif"; 13192 13193var uv_vertex = "#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif"; 13194 13195var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif"; 13196 13197var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif"; 13198 13199var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif"; 13200 13201var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_L
13201IGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif"; 13202 13203const vertex$h = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}"; 13204 13205const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}"; 13206 13207const vertex$g = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}"; 13208 13209const fragment$g = "#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}"; 13210 13211const vertex$f = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}"; 13212 13213const fragment$f = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}"; 13214 13215const vertex$e = "#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>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}"; 13216 13217const fragment$e = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <logdepthbuf_fragment>\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}"; 13218 13219const vertex$d = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}"; 13220 13221const fragment$d = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}"; 13222 13223const vertex$c = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}"; 13224 13225const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}"; 13226 13227const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}"; 13228 13229const fragment$b = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}"; 13230 13231const vertex$a = "#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinbase_vertex>\n\t\t#include <skinnormal_vertex>\n\t\t#include <defaultnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}"; 13232 13233const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"; 13234 13235const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}"; 13236 13237const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_lambert_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_lambert_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"; 13238 13239const vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <color_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\tvViewPosition = - mvPosition.xyz;\n}"; 13240 13241const fragment$8 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <normal_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;
13241\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"; 13242 13243const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; 13244 13245const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <normal_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; 13246 13247const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}"; 13248 13249const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"; 13250 13251const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}"; 13252 13253const fragment$5 =
vendor: 3,950 bytes, line 13253
13253"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <bsdfs>\n#include <iridescence_fragment>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_physical_pars_fragment>\n#include <transmission_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_pars_fragment>\n#include <iridescence_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <clearcoat_normal_fragment_begin>\n\t#include <clearcoat_normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include <transmission_fragment>\n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"
vendor: 13,906 bytes, lines 13253-13449
13253; 13254 13255const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}"; 13256 13257const fragment$4 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_toon_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_toon_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"; 13258 13259const vertex$3 = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n}"; 13260 13261const fragment$3 = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}"; 13262 13263const vertex$2 = "#include <common>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}"; 13264 13265const fragment$2 = "uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <logdepthbuf_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n\t#include <logdepthbuf_fragment>\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}"; 13266 13267const vertex$1 = "uniform float rotation;\nuniform vec2 center;\n#include <common>\n#include <uv_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}"; 13268 13269const fragment$1 = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}"; 13270 13271const ShaderChunk = { 13272 alphamap_fragment: alphamap_fragment, 13273 alphamap_pars_fragment: alphamap_pars_fragment, 13274 alphatest_fragment: alphatest_fragment, 13275 alphatest_pars_fragment: alphatest_pars_fragment, 13276 aomap_fragment: aomap_fragment, 13277 aomap_pars_fragment: aomap_pars_fragment, 13278 begin_vertex: begin_vertex, 13279 beginnormal_vertex: beginnormal_vertex, 13280 bsdfs: bsdfs, 13281 iridescence_fragment: iridescence_fragment, 13282 bumpmap_pars_fragment: bumpmap_pars_fragment, 13283 clipping_planes_fragment: clipping_planes_fragment, 13284 clipping_planes_pars_fragment: clipping_planes_pars_fragment, 13285 clipping_planes_pars_vertex: clipping_planes_pars_vertex, 13286 clipping_planes_vertex: clipping_planes_vertex, 13287 color_fragment: color_fragment, 13288 color_pars_fragment: color_pars_fragment, 13289 color_pars_vertex: color_pars_vertex, 13290 color_vertex: color_vertex, 13291 common: common, 13292 cube_uv_reflection_fragment: cube_uv_reflection_fragment, 13293 defaultnormal_vertex: defaultnormal_vertex, 13294 displacementmap_pars_vertex: displacementmap_pars_vertex, 13295 displacementmap_vertex: displacementmap_vertex, 13296 emissivemap_fragment: emissivemap_fragment, 13297 emissivemap_pars_fragment: emissivemap_pars_fragment, 13298 encodings_fragment: encodings_fragment, 13299 encodings_pars_fragment: encodings_pars_fragment, 13300 envmap_fragment: envmap_fragment, 13301 envmap_common_pars_fragment: envmap_common_pars_fragment, 13302 envmap_pars_fragment: envmap_pars_fragment, 13303 envmap_pars_vertex: envmap_pars_vertex, 13304 envmap_physical_pars_fragment: envmap_physical_pars_fragment, 13305 envmap_vertex: envmap_vertex, 13306 fog_vertex: fog_vertex, 13307 fog_pars_vertex: fog_pars_vertex, 13308 fog_fragment: fog_fragment, 13309 fog_pars_fragment: fog_pars_fragment, 13310 gradientmap_pars_fragment: gradientmap_pars_fragment, 13311 lightmap_fragment: lightmap_fragment, 13312 lightmap_pars_fragment: lightmap_pars_fragment, 13313 lights_lambert_fragment: lights_lambert_fragment, 13314 lights_lambert_pars_fragment: lights_lambert_pars_fragment, 13315 lights_pars_begin: lights_pars_begin, 13316 lights_toon_fragment: lights_toon_fragment, 13317 lights_toon_pars_fragment: lights_toon_pars_fragment, 13318 lights_phong_fragment: lights_phong_fragment, 13319 lights_phong_pars_fragment: lights_phong_pars_fragment, 13320 lights_physical_fragment: lights_physical_fragment, 13321 lights_physical_pars_fragment: lights_physical_pars_fragment, 13322 lights_fragment_begin: lights_fragment_begin, 13323 lights_fragment_maps: lights_fragment_maps, 13324 lights_fragment_end: lights_fragment_end, 13325 logdepthbuf_fragment: logdepthbuf_fragment, 13326 logdepthbuf_pars_fragment: logdepthbuf_pars_fragment, 13327 logdepthbuf_pars_vertex: logdepthbuf_pars_vertex, 13328 logdepthbuf_vertex: logdepthbuf_vertex, 13329 map_fragment: map_fragment, 13330 map_pars_fragment: map_pars_fragment, 13331 map_particle_fragment: map_particle_fragment, 13332 map_particle_pars_fragment: map_particle_pars_fragment, 13333 metalnessmap_fragment: metalnessmap_fragment, 13334 metalnessmap_pars_fragment: metalnessmap_pars_fragment, 13335 morphcolor_vertex: morphcolor_vertex, 13336 morphnormal_vertex: morphnormal_vertex, 13337 morphtarget_pars_vertex: morphtarget_pars_vertex, 13338 morphtarget_vertex: morphtarget_vertex, 13339 normal_fragment_begin: normal_fragment_begin, 13340 normal_fragment_maps: normal_fragment_maps, 13341 normal_pars_fragment: normal_pars_fragment, 13342 normal_pars_vertex: normal_pars_vertex, 13343 normal_vertex: normal_vertex, 13344 normalmap_pars_fragment: normalmap_pars_fragment, 13345 clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin, 13346 clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps, 13347 clearcoat_pars_fragment: clearcoat_pars_fragment, 13348 iridescence_pars_fragment: iridescence_pars_fragment, 13349 output_fragment: output_fragment, 13350 packing: packing, 13351 premultiplied_alpha_fragment: premultiplied_alpha_fragment, 13352 project_vertex: project_vertex, 13353 dithering_fragment: dithering_fragment, 13354 dithering_pars_fragment: dithering_pars_fragment, 13355 roughnessmap_fragment: roughnessmap_fragment, 13356 roughnessmap_pars_fragment: roughnessmap_pars_fragment, 13357 shadowmap_pars_fragment: shadowmap_pars_fragment, 13358 shadowmap_pars_vertex: shadowmap_pars_vertex, 13359 shadowmap_vertex: shadowmap_vertex, 13360 shadowmask_pars_fragment: shadowmask_pars_fragment, 13361 skinbase_vertex: skinbase_vertex, 13362 skinning_pars_vertex: skinning_pars_vertex, 13363 skinning_vertex: skinning_vertex, 13364 skinnormal_vertex: skinnormal_vertex, 13365 specularmap_fragment: specularmap_fragment, 13366 specularmap_pars_fragment: specularmap_pars_fragment, 13367 tonemapping_fragment: tonemapping_fragment, 13368 tonemapping_pars_fragment: tonemapping_pars_fragment, 13369 transmission_fragment: transmission_fragment, 13370 transmission_pars_fragment: transmission_pars_fragment, 13371 uv_pars_fragment: uv_pars_fragment, 13372 uv_pars_vertex: uv_pars_vertex, 13373 uv_vertex: uv_vertex, 13374 uv2_pars_fragment: uv2_pars_fragment, 13375 uv2_pars_vertex: uv2_pars_vertex, 13376 uv2_vertex: uv2_vertex, 13377 worldpos_vertex: worldpos_vertex, 13378 13379 background_vert: vertex$h, 13380 background_frag: fragment$h, 13381 backgroundCube_vert: vertex$g, 13382 backgroundCube_frag: fragment$g, 13383 cube_vert: vertex$f, 13384 cube_frag: fragment$f, 13385 depth_vert: vertex$e, 13386 depth_frag: fragment$e, 13387 distanceRGBA_vert: vertex$d, 13388 distanceRGBA_frag: fragment$d, 13389 equirect_vert: vertex$c, 13390 equirect_frag: fragment$c, 13391 linedashed_vert: vertex$b, 13392 linedashed_frag: fragment$b, 13393 meshbasic_vert: vertex$a, 13394 meshbasic_frag: fragment$a, 13395 meshlambert_vert: vertex$9, 13396 meshlambert_frag: fragment$9, 13397 meshmatcap_vert: vertex$8, 13398 meshmatcap_frag: fragment$8, 13399 meshnormal_vert: vertex$7, 13400 meshnormal_frag: fragment$7, 13401 meshphong_vert: vertex$6, 13402 meshphong_frag: fragment$6, 13403 meshphysical_vert: vertex$5, 13404 meshphysical_frag: fragment$5, 13405 meshtoon_vert: vertex$4, 13406 meshtoon_frag: fragment$4, 13407 points_vert: vertex$3, 13408 points_frag: fragment$3, 13409 shadow_vert: vertex$2, 13410 shadow_frag: fragment$2, 13411 sprite_vert: vertex$1, 13412 sprite_frag: fragment$1 13413}; 13414 13415/** 13416 * Uniforms library for shared webgl shaders 13417 */ 13418 13419const UniformsLib = { 13420 13421 common: { 13422 13423 diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, 13424 opacity: { value: 1.0 }, 13425 13426 map: { value: null }, 13427 uvTransform: { value: /*@__PURE__*/ new Matrix3() }, 13428 uv2Transform: { value: /*@__PURE__*/ new Matrix3() }, 13429 13430 alphaMap: { value: null }, 13431 alphaTest: { value: 0 } 13432 13433 }, 13434 13435 specularmap: { 13436 13437 specularMap: { value: null }, 13438 13439 }, 13440 13441 envmap: { 13442 13443 envMap: { value: null }, 13444 flipEnvMap: { value: - 1 }, 13445 reflectivity: { value: 1.0 }, // basic, lambert, phong 13446 ior: { value: 1.5 }, // physical 13447 refractionRatio: { value: 0.98 }, // basic, lambert, phong 13448 13449 },
vendor: 5,741 bytes, lines 13450-13755
13450 13451 aomap: { 13452 13453 aoMap: { value: null }, 13454 aoMapIntensity: { value: 1 } 13455 13456 }, 13457 13458 lightmap: { 13459 13460 lightMap: { value: null }, 13461 lightMapIntensity: { value: 1 } 13462 13463 }, 13464 13465 emissivemap: { 13466 13467 emissiveMap: { value: null } 13468 13469 }, 13470 13471 bumpmap: { 13472 13473 bumpMap: { value: null }, 13474 bumpScale: { value: 1 } 13475 13476 }, 13477 13478 normalmap: { 13479 13480 normalMap: { value: null }, 13481 normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) } 13482 13483 }, 13484 13485 displacementmap: { 13486 13487 displacementMap: { value: null }, 13488 displacementScale: { value: 1 }, 13489 displacementBias: { value: 0 } 13490 13491 }, 13492 13493 roughnessmap: { 13494 13495 roughnessMap: { value: null } 13496 13497 }, 13498 13499 metalnessmap: { 13500 13501 metalnessMap: { value: null } 13502 13503 }, 13504 13505 gradientmap: { 13506 13507 gradientMap: { value: null } 13508 13509 }, 13510 13511 fog: { 13512 13513 fogDensity: { value: 0.00025 }, 13514 fogNear: { value: 1 }, 13515 fogFar: { value: 2000 }, 13516 fogColor: { value: /*@__PURE__*/ new Color( 0xffffff ) } 13517 13518 }, 13519 13520 lights: { 13521 13522 ambientLightColor: { value: [] }, 13523 13524 lightProbe: { value: [] }, 13525 13526 directionalLights: { value: [], properties: { 13527 direction: {}, 13528 color: {} 13529 } }, 13530 13531 directionalLightShadows: { value: [], properties: { 13532 shadowBias: {}, 13533 shadowNormalBias: {}, 13534 shadowRadius: {}, 13535 shadowMapSize: {} 13536 } }, 13537 13538 directionalShadowMap: { value: [] }, 13539 directionalShadowMatrix: { value: [] }, 13540 13541 spotLights: { value: [], properties: { 13542 color: {}, 13543 position: {}, 13544 direction: {}, 13545 distance: {}, 13546 coneCos: {}, 13547 penumbraCos: {}, 13548 decay: {} 13549 } }, 13550 13551 spotLightShadows: { value: [], properties: { 13552 shadowBias: {}, 13553 shadowNormalBias: {}, 13554 shadowRadius: {}, 13555 shadowMapSize: {} 13556 } }, 13557 13558 spotLightMap: { value: [] }, 13559 spotShadowMap: { value: [] }, 13560 spotLightMatrix: { value: [] }, 13561 13562 pointLights: { value: [], properties: { 13563 color: {}, 13564 position: {}, 13565 decay: {}, 13566 distance: {} 13567 } }, 13568 13569 pointLightShadows: { value: [], properties: { 13570 shadowBias: {}, 13571 shadowNormalBias: {}, 13572 shadowRadius: {}, 13573 shadowMapSize: {}, 13574 shadowCameraNear: {}, 13575 shadowCameraFar: {} 13576 } }, 13577 13578 pointShadowMap: { value: [] }, 13579 pointShadowMatrix: { value: [] }, 13580 13581 hemisphereLights: { value: [], properties: { 13582 direction: {}, 13583 skyColor: {}, 13584 groundColor: {} 13585 } }, 13586 13587 // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src 13588 rectAreaLights: { value: [], properties: { 13589 color: {}, 13590 position: {}, 13591 width: {}, 13592 height: {} 13593 } }, 13594 13595 ltc_1: { value: null }, 13596 ltc_2: { value: null } 13597 13598 }, 13599 13600 points: { 13601 13602 diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, 13603 opacity: { value: 1.0 }, 13604 size: { value: 1.0 }, 13605 scale: { value: 1.0 }, 13606 map: { value: null }, 13607 alphaMap: { value: null }, 13608 alphaTest: { value: 0 }, 13609 uvTransform: { value: /*@__PURE__*/ new Matrix3() } 13610 13611 }, 13612 13613 sprite: { 13614 13615 diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, 13616 opacity: { value: 1.0 }, 13617 center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) }, 13618 rotation: { value: 0.0 }, 13619 map: { value: null }, 13620 alphaMap: { value: null }, 13621 alphaTest: { value: 0 }, 13622 uvTransform: { value: /*@__PURE__*/ new Matrix3() } 13623 13624 } 13625 13626}; 13627 13628const ShaderLib = { 13629 13630 basic: { 13631 13632 uniforms: /*@__PURE__*/ mergeUniforms( [ 13633 UniformsLib.common, 13634 UniformsLib.specularmap, 13635 UniformsLib.envmap, 13636 UniformsLib.aomap, 13637 UniformsLib.lightmap, 13638 UniformsLib.fog 13639 ] ), 13640 13641 vertexShader: ShaderChunk.meshbasic_vert, 13642 fragmentShader: ShaderChunk.meshbasic_frag 13643 13644 }, 13645 13646 lambert: { 13647 13648 uniforms: /*@__PURE__*/ mergeUniforms( [ 13649 UniformsLib.common, 13650 UniformsLib.specularmap, 13651 UniformsLib.envmap, 13652 UniformsLib.aomap, 13653 UniformsLib.lightmap, 13654 UniformsLib.emissivemap, 13655 UniformsLib.bumpmap, 13656 UniformsLib.normalmap, 13657 UniformsLib.displacementmap, 13658 UniformsLib.fog, 13659 UniformsLib.lights, 13660 { 13661 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) } 13662 } 13663 ] ), 13664 13665 vertexShader: ShaderChunk.meshlambert_vert, 13666 fragmentShader: ShaderChunk.meshlambert_frag 13667 13668 }, 13669 13670 phong: { 13671 13672 uniforms: /*@__PURE__*/ mergeUniforms( [ 13673 UniformsLib.common, 13674 UniformsLib.specularmap, 13675 UniformsLib.envmap, 13676 UniformsLib.aomap, 13677 UniformsLib.lightmap, 13678 UniformsLib.emissivemap, 13679 UniformsLib.bumpmap, 13680 UniformsLib.normalmap, 13681 UniformsLib.displacementmap, 13682 UniformsLib.fog, 13683 UniformsLib.lights, 13684 { 13685 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 13686 specular: { value: /*@__PURE__*/ new Color( 0x111111 ) }, 13687 shininess: { value: 30 } 13688 } 13689 ] ), 13690 13691 vertexShader: ShaderChunk.meshphong_vert, 13692 fragmentShader: ShaderChunk.meshphong_frag 13693 13694 }, 13695 13696 standard: { 13697 13698 uniforms: /*@__PURE__*/ mergeUniforms( [ 13699 UniformsLib.common, 13700 UniformsLib.envmap, 13701 UniformsLib.aomap, 13702 UniformsLib.lightmap, 13703 UniformsLib.emissivemap, 13704 UniformsLib.bumpmap, 13705 UniformsLib.normalmap, 13706 UniformsLib.displacementmap, 13707 UniformsLib.roughnessmap, 13708 UniformsLib.metalnessmap, 13709 UniformsLib.fog, 13710 UniformsLib.lights, 13711 { 13712 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 13713 roughness: { value: 1.0 }, 13714 metalness: { value: 0.0 }, 13715 envMapIntensity: { value: 1 } // temporary 13716 } 13717 ] ), 13718 13719 vertexShader: ShaderChunk.meshphysical_vert, 13720 fragmentShader: ShaderChunk.meshphysical_frag 13721 13722 }, 13723 13724 toon: { 13725 13726 uniforms: /*@__PURE__*/ mergeUniforms( [ 13727 UniformsLib.common, 13728 UniformsLib.aomap, 13729 UniformsLib.lightmap, 13730 UniformsLib.emissivemap, 13731 UniformsLib.bumpmap, 13732 UniformsLib.normalmap, 13733 UniformsLib.displacementmap, 13734 UniformsLib.gradientmap, 13735 UniformsLib.fog, 13736 UniformsLib.lights, 13737 { 13738 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) } 13739 } 13740 ] ), 13741 13742 vertexShader: ShaderChunk.meshtoon_vert, 13743 fragmentShader: ShaderChunk.meshtoon_frag 13744 13745 }, 13746 13747 matcap: { 13748 13749 uniforms: /*@__PURE__*/ mergeUniforms( [ 13750 UniformsLib.common, 13751 UniformsLib.bumpmap, 13752 UniformsLib.normalmap, 13753 UniformsLib.displacementmap, 13754 UniformsLib.fog, 13755 {
vendor: 4,333 bytes, lines 13756-13964
13756 matcap: { value: null } 13757 } 13758 ] ), 13759 13760 vertexShader: ShaderChunk.meshmatcap_vert, 13761 fragmentShader: ShaderChunk.meshmatcap_frag 13762 13763 }, 13764 13765 points: { 13766 13767 uniforms: /*@__PURE__*/ mergeUniforms( [ 13768 UniformsLib.points, 13769 UniformsLib.fog 13770 ] ), 13771 13772 vertexShader: ShaderChunk.points_vert, 13773 fragmentShader: ShaderChunk.points_frag 13774 13775 }, 13776 13777 dashed: { 13778 13779 uniforms: /*@__PURE__*/ mergeUniforms( [ 13780 UniformsLib.common, 13781 UniformsLib.fog, 13782 { 13783 scale: { value: 1 }, 13784 dashSize: { value: 1 }, 13785 totalSize: { value: 2 } 13786 } 13787 ] ), 13788 13789 vertexShader: ShaderChunk.linedashed_vert, 13790 fragmentShader: ShaderChunk.linedashed_frag 13791 13792 }, 13793 13794 depth: { 13795 13796 uniforms: /*@__PURE__*/ mergeUniforms( [ 13797 UniformsLib.common, 13798 UniformsLib.displacementmap 13799 ] ), 13800 13801 vertexShader: ShaderChunk.depth_vert, 13802 fragmentShader: ShaderChunk.depth_frag 13803 13804 }, 13805 13806 normal: { 13807 13808 uniforms: /*@__PURE__*/ mergeUniforms( [ 13809 UniformsLib.common, 13810 UniformsLib.bumpmap, 13811 UniformsLib.normalmap, 13812 UniformsLib.displacementmap, 13813 { 13814 opacity: { value: 1.0 } 13815 } 13816 ] ), 13817 13818 vertexShader: ShaderChunk.meshnormal_vert, 13819 fragmentShader: ShaderChunk.meshnormal_frag 13820 13821 }, 13822 13823 sprite: { 13824 13825 uniforms: /*@__PURE__*/ mergeUniforms( [ 13826 UniformsLib.sprite, 13827 UniformsLib.fog 13828 ] ), 13829 13830 vertexShader: ShaderChunk.sprite_vert, 13831 fragmentShader: ShaderChunk.sprite_frag 13832 13833 }, 13834 13835 background: { 13836 13837 uniforms: { 13838 uvTransform: { value: /*@__PURE__*/ new Matrix3() }, 13839 t2D: { value: null }, 13840 backgroundIntensity: { value: 1 } 13841 }, 13842 13843 vertexShader: ShaderChunk.background_vert, 13844 fragmentShader: ShaderChunk.background_frag 13845 13846 }, 13847 13848 backgroundCube: { 13849 13850 uniforms: { 13851 envMap: { value: null }, 13852 flipEnvMap: { value: - 1 }, 13853 backgroundBlurriness: { value: 0 }, 13854 backgroundIntensity: { value: 1 } 13855 }, 13856 13857 vertexShader: ShaderChunk.backgroundCube_vert, 13858 fragmentShader: ShaderChunk.backgroundCube_frag 13859 13860 }, 13861 13862 cube: { 13863 13864 uniforms: { 13865 tCube: { value: null }, 13866 tFlip: { value: - 1 }, 13867 opacity: { value: 1.0 } 13868 }, 13869 13870 vertexShader: ShaderChunk.cube_vert, 13871 fragmentShader: ShaderChunk.cube_frag 13872 13873 }, 13874 13875 equirect: { 13876 13877 uniforms: { 13878 tEquirect: { value: null }, 13879 }, 13880 13881 vertexShader: ShaderChunk.equirect_vert, 13882 fragmentShader: ShaderChunk.equirect_frag 13883 13884 }, 13885 13886 distanceRGBA: { 13887 13888 uniforms: /*@__PURE__*/ mergeUniforms( [ 13889 UniformsLib.common, 13890 UniformsLib.displacementmap, 13891 { 13892 referencePosition: { value: /*@__PURE__*/ new Vector3() }, 13893 nearDistance: { value: 1 }, 13894 farDistance: { value: 1000 } 13895 } 13896 ] ), 13897 13898 vertexShader: ShaderChunk.distanceRGBA_vert, 13899 fragmentShader: ShaderChunk.distanceRGBA_frag 13900 13901 }, 13902 13903 shadow: { 13904 13905 uniforms: /*@__PURE__*/ mergeUniforms( [ 13906 UniformsLib.lights, 13907 UniformsLib.fog, 13908 { 13909 color: { value: /*@__PURE__*/ new Color( 0x00000 ) }, 13910 opacity: { value: 1.0 } 13911 }, 13912 ] ), 13913 13914 vertexShader: ShaderChunk.shadow_vert, 13915 fragmentShader: ShaderChunk.shadow_frag 13916 13917 } 13918 13919}; 13920 13921ShaderLib.physical = { 13922 13923 uniforms: /*@__PURE__*/ mergeUniforms( [ 13924 ShaderLib.standard.uniforms, 13925 { 13926 clearcoat: { value: 0 }, 13927 clearcoatMap: { value: null }, 13928 clearcoatRoughness: { value: 0 }, 13929 clearcoatRoughnessMap: { value: null }, 13930 clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, 13931 clearcoatNormalMap: { value: null }, 13932 iridescence: { value: 0 }, 13933 iridescenceMap: { value: null }, 13934 iridescenceIOR: { value: 1.3 }, 13935 iridescenceThicknessMinimum: { value: 100 }, 13936 iridescenceThicknessMaximum: { value: 400 }, 13937 iridescenceThicknessMap: { value: null }, 13938 sheen: { value: 0 }, 13939 sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 13940 sheenColorMap: { value: null }, 13941 sheenRoughness: { value: 1 }, 13942 sheenRoughnessMap: { value: null }, 13943 transmission: { value: 0 }, 13944 transmissionMap: { value: null }, 13945 transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() }, 13946 transmissionSamplerMap: { value: null }, 13947 thickness: { value: 0 }, 13948 thicknessMap: { value: null }, 13949 attenuationDistance: { value: 0 }, 13950 attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 13951 specularIntensity: { value: 1 }, 13952 specularIntensityMap: { value: null }, 13953 specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) }, 13954 specularColorMap: { value: null }, 13955 } 13956 ] ), 13957 13958 vertexShader: ShaderChunk.meshphysical_vert, 13959 fragmentShader: ShaderChunk.meshphysical_frag 13960 13961}; 13962 13963const _rgb = { r: 0, b: 0, g: 0 }; 13964
vendor: 18,567 bytes, lines 13965-14790
13965function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) { 13966 13967 const clearColor = new Color( 0x000000 ); 13968 let clearAlpha = alpha === true ? 0 : 1; 13969 13970 let planeMesh; 13971 let boxMesh; 13972 13973 let currentBackground = null; 13974 let currentBackgroundVersion = 0; 13975 let currentTonemapping = null; 13976 13977 function render( renderList, scene ) { 13978 13979 let forceClear = false; 13980 let background = scene.isScene === true ? scene.background : null; 13981 13982 if ( background && background.isTexture ) { 13983 13984 const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background 13985 background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background ); 13986 13987 } 13988 13989 // Ignore background in AR 13990 // TODO: Reconsider this. 13991 13992 const xr = renderer.xr; 13993 const session = xr.getSession && xr.getSession(); 13994 13995 if ( session && session.environmentBlendMode === 'additive' ) { 13996 13997 background = null; 13998 13999 } 14000 14001 if ( background === null ) { 14002 14003 setClear( clearColor, clearAlpha ); 14004 14005 } else if ( background && background.isColor ) { 14006 14007 setClear( background, 1 ); 14008 forceClear = true; 14009 14010 } 14011 14012 if ( renderer.autoClear || forceClear ) { 14013 14014 renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); 14015 14016 } 14017 14018 if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) { 14019 14020 if ( boxMesh === undefined ) { 14021 14022 boxMesh = new Mesh( 14023 new BoxGeometry( 1, 1, 1 ), 14024 new ShaderMaterial( { 14025 name: 'BackgroundCubeMaterial', 14026 uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ), 14027 vertexShader: ShaderLib.backgroundCube.vertexShader, 14028 fragmentShader: ShaderLib.backgroundCube.fragmentShader, 14029 side: BackSide, 14030 depthTest: false, 14031 depthWrite: false, 14032 fog: false 14033 } ) 14034 ); 14035 14036 boxMesh.geometry.deleteAttribute( 'normal' ); 14037 boxMesh.geometry.deleteAttribute( 'uv' ); 14038 14039 boxMesh.onBeforeRender = function ( renderer, scene, camera ) { 14040 14041 this.matrixWorld.copyPosition( camera.matrixWorld ); 14042 14043 }; 14044 14045 // add "envMap" material property so the renderer can evaluate it like for built-in materials 14046 Object.defineProperty( boxMesh.material, 'envMap', { 14047 14048 get: function () { 14049 14050 return this.uniforms.envMap.value; 14051 14052 } 14053 14054 } ); 14055 14056 objects.update( boxMesh ); 14057 14058 } 14059 14060 boxMesh.material.uniforms.envMap.value = background; 14061 boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1; 14062 boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness; 14063 boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; 14064 boxMesh.material.toneMapped = ( background.encoding === sRGBEncoding ) ? false : true; 14065 14066 if ( currentBackground !== background || 14067 currentBackgroundVersion !== background.version || 14068 currentTonemapping !== renderer.toneMapping ) { 14069 14070 boxMesh.material.needsUpdate = true; 14071 14072 currentBackground = background; 14073 currentBackgroundVersion = background.version; 14074 currentTonemapping = renderer.toneMapping; 14075 14076 } 14077 14078 boxMesh.layers.enableAll(); 14079 14080 // push to the pre-sorted opaque render list 14081 renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null ); 14082 14083 } else if ( background && background.isTexture ) { 14084 14085 if ( planeMesh === undefined ) { 14086 14087 planeMesh = new Mesh( 14088 new PlaneGeometry( 2, 2 ), 14089 new ShaderMaterial( { 14090 name: 'BackgroundMaterial', 14091 uniforms: cloneUniforms( ShaderLib.background.uniforms ), 14092 vertexShader: ShaderLib.background.vertexShader, 14093 fragmentShader: ShaderLib.background.fragmentShader, 14094 side: FrontSide, 14095 depthTest: false, 14096 depthWrite: false, 14097 fog: false 14098 } ) 14099 ); 14100 14101 planeMesh.geometry.deleteAttribute( 'normal' ); 14102 14103 // add "map" material property so the renderer can evaluate it like for built-in materials 14104 Object.defineProperty( planeMesh.material, 'map', { 14105 14106 get: function () { 14107 14108 return this.uniforms.t2D.value; 14109 14110 } 14111 14112 } ); 14113 14114 objects.update( planeMesh ); 14115 14116 } 14117 14118 planeMesh.material.uniforms.t2D.value = background; 14119 planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; 14120 planeMesh.material.toneMapped = ( background.encoding === sRGBEncoding ) ? false : true; 14121 14122 if ( background.matrixAutoUpdate === true ) { 14123 14124 background.updateMatrix(); 14125 14126 } 14127 14128 planeMesh.material.uniforms.uvTransform.value.copy( background.matrix ); 14129 14130 if ( currentBackground !== background || 14131 currentBackgroundVersion !== background.version || 14132 currentTonemapping !== renderer.toneMapping ) { 14133 14134 planeMesh.material.needsUpdate = true; 14135 14136 currentBackground = background; 14137 currentBackgroundVersion = background.version; 14138 currentTonemapping = renderer.toneMapping; 14139 14140 } 14141 14142 planeMesh.layers.enableAll(); 14143 14144 // push to the pre-sorted opaque render list 14145 renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null ); 14146 14147 } 14148 14149 } 14150 14151 function setClear( color, alpha ) { 14152 14153 color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) ); 14154 14155 state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha ); 14156 14157 } 14158 14159 return { 14160 14161 getClearColor: function () { 14162 14163 return clearColor; 14164 14165 }, 14166 setClearColor: function ( color, alpha = 1 ) { 14167 14168 clearColor.set( color ); 14169 clearAlpha = alpha; 14170 setClear( clearColor, clearAlpha ); 14171 14172 }, 14173 getClearAlpha: function () { 14174 14175 return clearAlpha; 14176 14177 }, 14178 setClearAlpha: function ( alpha ) { 14179 14180 clearAlpha = alpha; 14181 setClear( clearColor, clearAlpha ); 14182 14183 }, 14184 render: render 14185 14186 }; 14187 14188} 14189 14190function WebGLBindingStates( gl, extensions, attributes, capabilities ) { 14191 14192 const maxVertexAttributes = gl.getParameter( 34921 ); 14193 14194 const extension = capabilities.isWebGL2 ? null : extensions.get( 'OES_vertex_array_object' ); 14195 const vaoAvailable = capabilities.isWebGL2 || extension !== null; 14196 14197 const bindingStates = {}; 14198 14199 const defaultState = createBindingState( null ); 14200 let currentState = defaultState; 14201 let forceUpdate = false; 14202 14203 function setup( object, material, program, geometry, index ) { 14204 14205 let updateBuffers = false; 14206 14207 if ( vaoAvailable ) { 14208 14209 const state = getBindingState( geometry, program, material ); 14210 14211 if ( currentState !== state ) { 14212 14213 currentState = state; 14214 bindVertexArrayObject( currentState.object ); 14215 14216 } 14217 14218 updateBuffers = needsUpdate( object, geometry, program, index ); 14219 14220 if ( updateBuffers ) saveCache( object, geometry, program, index ); 14221 14222 } else { 14223 14224 const wireframe = ( material.wireframe === true ); 14225 14226 if ( currentState.geometry !== geometry.id || 14227 currentState.program !== program.id || 14228 currentState.wireframe !== wireframe ) { 14229 14230 currentState.geometry = geometry.id; 14231 currentState.program = program.id; 14232 currentState.wireframe = wireframe; 14233 14234 updateBuffers = true; 14235 14236 } 14237 14238 } 14239 14240 if ( index !== null ) { 14241 14242 attributes.update( index, 34963 ); 14243 14244 } 14245 14246 if ( updateBuffers || forceUpdate ) { 14247 14248 forceUpdate = false; 14249 14250 setupVertexAttributes( object, material, program, geometry ); 14251 14252 if ( index !== null ) { 14253 14254 gl.bindBuffer( 34963, attributes.get( index ).buffer ); 14255 14256 } 14257 14258 } 14259 14260 } 14261 14262 function createVertexArrayObject() { 14263 14264 if ( capabilities.isWebGL2 ) return gl.createVertexArray(); 14265 14266 return extension.createVertexArrayOES(); 14267 14268 } 14269 14270 function bindVertexArrayObject( vao ) { 14271 14272 if ( capabilities.isWebGL2 ) return gl.bindVertexArray( vao ); 14273 14274 return extension.bindVertexArrayOES( vao ); 14275 14276 } 14277 14278 function deleteVertexArrayObject( vao ) { 14279 14280 if ( capabilities.isWebGL2 ) return gl.deleteVertexArray( vao ); 14281 14282 return extension.deleteVertexArrayOES( vao ); 14283 14284 } 14285 14286 function getBindingState( geometry, program, material ) { 14287 14288 const wireframe = ( material.wireframe === true ); 14289 14290 let programMap = bindingStates[ geometry.id ]; 14291 14292 if ( programMap === undefined ) { 14293 14294 programMap = {}; 14295 bindingStates[ geometry.id ] = programMap; 14296 14297 } 14298 14299 let stateMap = programMap[ program.id ]; 14300 14301 if ( stateMap === undefined ) { 14302 14303 stateMap = {}; 14304 programMap[ program.id ] = stateMap; 14305 14306 } 14307 14308 let state = stateMap[ wireframe ]; 14309 14310 if ( state === undefined ) { 14311 14312 state = createBindingState( createVertexArrayObject() ); 14313 stateMap[ wireframe ] = state; 14314 14315 } 14316 14317 return state; 14318 14319 } 14320 14321 function createBindingState( vao ) { 14322 14323 const newAttributes = []; 14324 const enabledAttributes = []; 14325 const attributeDivisors = []; 14326 14327 for ( let i = 0; i < maxVertexAttributes; i ++ ) { 14328 14329 newAttributes[ i ] = 0; 14330 enabledAttributes[ i ] = 0; 14331 attributeDivisors[ i ] = 0; 14332 14333 } 14334 14335 return { 14336 14337 // for backward compatibility on non-VAO support browser 14338 geometry: null, 14339 program: null, 14340 wireframe: false, 14341 14342 newAttributes: newAttributes, 14343 enabledAttributes: enabledAttributes, 14344 attributeDivisors: attributeDivisors, 14345 object: vao, 14346 attributes: {}, 14347 index: null 14348 14349 }; 14350 14351 } 14352 14353 function needsUpdate( object, geometry, program, index ) { 14354 14355 const cachedAttributes = currentState.attributes; 14356 const geometryAttributes = geometry.attributes; 14357 14358 let attributesNum = 0; 14359 14360 const programAttributes = program.getAttributes(); 14361 14362 for ( const name in programAttributes ) { 14363 14364 const programAttribute = programAttributes[ name ]; 14365 14366 if ( programAttribute.location >= 0 ) { 14367 14368 const cachedAttribute = cachedAttributes[ name ]; 14369 let geometryAttribute = geometryAttributes[ name ]; 14370 14371 if ( geometryAttribute === undefined ) { 14372 14373 if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; 14374 if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; 14375 14376 } 14377 14378 if ( cachedAttribute === undefined ) return true; 14379 14380 if ( cachedAttribute.attribute !== geometryAttribute ) return true; 14381 14382 if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data ) return true; 14383 14384 attributesNum ++; 14385 14386 } 14387 14388 } 14389 14390 if ( currentState.attributesNum !== attributesNum ) return true; 14391 14392 if ( currentState.index !== index ) return true; 14393 14394 return false; 14395 14396 } 14397 14398 function saveCache( object, geometry, program, index ) { 14399 14400 const cache = {}; 14401 const attributes = geometry.attributes; 14402 let attributesNum = 0; 14403 14404 const programAttributes = program.getAttributes(); 14405 14406 for ( const name in programAttributes ) { 14407 14408 const programAttribute = programAttributes[ name ]; 14409 14410 if ( programAttribute.location >= 0 ) { 14411 14412 let attribute = attributes[ name ]; 14413 14414 if ( attribute === undefined ) { 14415 14416 if ( name === 'instanceMatrix' && object.instanceMatrix ) attribute = object.instanceMatrix; 14417 if ( name === 'instanceColor' && object.instanceColor ) attribute = object.instanceColor; 14418 14419 } 14420 14421 const data = {}; 14422 data.attribute = attribute; 14423 14424 if ( attribute && attribute.data ) { 14425 14426 data.data = attribute.data; 14427 14428 } 14429 14430 cache[ name ] = data; 14431 14432 attributesNum ++; 14433 14434 } 14435 14436 } 14437 14438 currentState.attributes = cache; 14439 currentState.attributesNum = attributesNum; 14440 14441 currentState.index = index; 14442 14443 } 14444 14445 function initAttributes() { 14446 14447 const newAttributes = currentState.newAttributes; 14448 14449 for ( let i = 0, il = newAttributes.length; i < il; i ++ ) { 14450 14451 newAttributes[ i ] = 0; 14452 14453 } 14454 14455 } 14456 14457 function enableAttribute( attribute ) { 14458 14459 enableAttributeAndDivisor( attribute, 0 ); 14460 14461 } 14462 14463 function enableAttributeAndDivisor( attribute, meshPerAttribute ) { 14464 14465 const newAttributes = currentState.newAttributes; 14466 const enabledAttributes = currentState.enabledAttributes; 14467 const attributeDivisors = currentState.attributeDivisors; 14468 14469 newAttributes[ attribute ] = 1; 14470 14471 if ( enabledAttributes[ attribute ] === 0 ) { 14472 14473 gl.enableVertexAttribArray( attribute ); 14474 enabledAttributes[ attribute ] = 1; 14475 14476 } 14477 14478 if ( attributeDivisors[ attribute ] !== meshPerAttribute ) { 14479 14480 const extension = capabilities.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' ); 14481 14482 extension[ capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute ); 14483 attributeDivisors[ attribute ] = meshPerAttribute; 14484 14485 } 14486 14487 } 14488 14489 function disableUnusedAttributes() { 14490 14491 const newAttributes = currentState.newAttributes; 14492 const enabledAttributes = currentState.enabledAttributes; 14493 14494 for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) { 14495 14496 if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { 14497 14498 gl.disableVertexAttribArray( i ); 14499 enabledAttributes[ i ] = 0; 14500 14501 } 14502 14503 } 14504 14505 } 14506 14507 function vertexAttribPointer( index, size, type, normalized, stride, offset ) { 14508 14509 if ( capabilities.isWebGL2 === true && ( type === 5124 || type === 5125 ) ) { 14510 14511 gl.vertexAttribIPointer( index, size, type, stride, offset ); 14512 14513 } else { 14514 14515 gl.vertexAttribPointer( index, size, type, normalized, stride, offset ); 14516 14517 } 14518 14519 } 14520 14521 function setupVertexAttributes( object, material, program, geometry ) { 14522 14523 if ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) { 14524 14525 if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) return; 14526 14527 } 14528 14529 initAttributes(); 14530 14531 const geometryAttributes = geometry.attributes; 14532 14533 const programAttributes = program.getAttributes(); 14534 14535 const materialDefaultAttributeValues = material.defaultAttributeValues; 14536 14537 for ( const name in programAttributes ) { 14538 14539 const programAttribute = programAttributes[ name ]; 14540 14541 if ( programAttribute.location >= 0 ) { 14542 14543 let geometryAttribute = geometryAttributes[ name ]; 14544 14545 if ( geometryAttribute === undefined ) { 14546 14547 if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; 14548 if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; 14549 14550 } 14551 14552 if ( geometryAttribute !== undefined ) { 14553 14554 const normalized = geometryAttribute.normalized; 14555 const size = geometryAttribute.itemSize; 14556 14557 const attribute = attributes.get( geometryAttribute ); 14558 14559 // TODO Attribute may not be available on context restore 14560 14561 if ( attribute === undefined ) continue; 14562 14563 const buffer = attribute.buffer; 14564 const type = attribute.type; 14565 const bytesPerElement = attribute.bytesPerElement; 14566 14567 if ( geometryAttribute.isInterleavedBufferAttribute ) { 14568 14569 const data = geometryAttribute.data; 14570 const stride = data.stride; 14571 const offset = geometryAttribute.offset; 14572 14573 if ( data.isInstancedInterleavedBuffer ) { 14574 14575 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 14576 14577 enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute ); 14578 14579 } 14580 14581 if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { 14582 14583 geometry._maxInstanceCount = data.meshPerAttribute * data.count; 14584 14585 } 14586 14587 } else { 14588 14589 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 14590 14591 enableAttribute( programAttribute.location + i ); 14592 14593 } 14594 14595 } 14596 14597 gl.bindBuffer( 34962, buffer ); 14598 14599 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 14600 14601 vertexAttribPointer( 14602 programAttribute.location + i, 14603 size / programAttribute.locationSize, 14604 type, 14605 normalized, 14606 stride * bytesPerElement, 14607 ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement 14608 ); 14609 14610 } 14611 14612 } else { 14613 14614 if ( geometryAttribute.isInstancedBufferAttribute ) { 14615 14616 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 14617 14618 enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute ); 14619 14620 } 14621 14622 if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { 14623 14624 geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; 14625 14626 } 14627 14628 } else { 14629 14630 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 14631 14632 enableAttribute( programAttribute.location + i ); 14633 14634 } 14635 14636 } 14637 14638 gl.bindBuffer( 34962, buffer ); 14639 14640 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 14641 14642 vertexAttribPointer( 14643 programAttribute.location + i, 14644 size / programAttribute.locationSize, 14645 type, 14646 normalized, 14647 size * bytesPerElement, 14648 ( size / programAttribute.locationSize ) * i * bytesPerElement 14649 ); 14650 14651 } 14652 14653 } 14654 14655 } else if ( materialDefaultAttributeValues !== undefined ) { 14656 14657 const value = materialDefaultAttributeValues[ name ]; 14658 14659 if ( value !== undefined ) { 14660 14661 switch ( value.length ) { 14662 14663 case 2: 14664 gl.vertexAttrib2fv( programAttribute.location, value ); 14665 break; 14666 14667 case 3: 14668 gl.vertexAttrib3fv( programAttribute.location, value ); 14669 break; 14670 14671 case 4: 14672 gl.vertexAttrib4fv( programAttribute.location, value ); 14673 break; 14674 14675 default: 14676 gl.vertexAttrib1fv( programAttribute.location, value ); 14677 14678 } 14679 14680 } 14681 14682 } 14683 14684 } 14685 14686 } 14687 14688 disableUnusedAttributes(); 14689 14690 } 14691 14692 function dispose() { 14693 14694 reset(); 14695 14696 for ( const geometryId in bindingStates ) { 14697 14698 const programMap = bindingStates[ geometryId ]; 14699 14700 for ( const programId in programMap ) { 14701 14702 const stateMap = programMap[ programId ]; 14703 14704 for ( const wireframe in stateMap ) { 14705 14706 deleteVertexArrayObject( stateMap[ wireframe ].object ); 14707 14708 delete stateMap[ wireframe ]; 14709 14710 } 14711 14712 delete programMap[ programId ]; 14713 14714 } 14715 14716 delete bindingStates[ geometryId ]; 14717 14718 } 14719 14720 } 14721 14722 function releaseStatesOfGeometry( geometry ) { 14723 14724 if ( bindingStates[ geometry.id ] === undefined ) return; 14725 14726 const programMap = bindingStates[ geometry.id ]; 14727 14728 for ( const programId in programMap ) { 14729 14730 const stateMap = programMap[ programId ]; 14731 14732 for ( const wireframe in stateMap ) { 14733 14734 deleteVertexArrayObject( stateMap[ wireframe ].object ); 14735 14736 delete stateMap[ wireframe ]; 14737 14738 } 14739 14740 delete programMap[ programId ]; 14741 14742 } 14743 14744 delete bindingStates[ geometry.id ]; 14745 14746 } 14747 14748 function releaseStatesOfProgram( program ) { 14749 14750 for ( const geometryId in bindingStates ) { 14751 14752 const programMap = bindingStates[ geometryId ]; 14753 14754 if ( programMap[ program.id ] === undefined ) continue; 14755 14756 const stateMap = programMap[ program.id ]; 14757 14758 for ( const wireframe in stateMap ) { 14759 14760 deleteVertexArrayObject( stateMap[ wireframe ].object ); 14761 14762 delete stateMap[ wireframe ]; 14763 14764 } 14765 14766 delete programMap[ program.id ]; 14767 14768 } 14769 14770 } 14771 14772 function reset() { 14773 14774 resetDefaultState(); 14775 forceUpdate = true; 14776 14777 if ( currentState === defaultState ) return; 14778 14779 currentState = defaultState; 14780 bindVertexArrayObject( currentState.object ); 14781 14782 } 14783 14784 // for backward-compatibility 14785 14786 function resetDefaultState() { 14787 14788 defaultState.geometry = null; 14789 defaultState.program = null; 14790 defaultState.wireframe = false;
vendor: 3,700 bytes, lines 14791-14963
14791 14792 } 14793 14794 return { 14795 14796 setup: setup, 14797 reset: reset, 14798 resetDefaultState: resetDefaultState, 14799 dispose: dispose, 14800 releaseStatesOfGeometry: releaseStatesOfGeometry, 14801 releaseStatesOfProgram: releaseStatesOfProgram, 14802 14803 initAttributes: initAttributes, 14804 enableAttribute: enableAttribute, 14805 disableUnusedAttributes: disableUnusedAttributes 14806 14807 }; 14808 14809} 14810 14811function WebGLBufferRenderer( gl, extensions, info, capabilities ) { 14812 14813 const isWebGL2 = capabilities.isWebGL2; 14814 14815 let mode; 14816 14817 function setMode( value ) { 14818 14819 mode = value; 14820 14821 } 14822 14823 function render( start, count ) { 14824 14825 gl.drawArrays( mode, start, count ); 14826 14827 info.update( count, mode, 1 ); 14828 14829 } 14830 14831 function renderInstances( start, count, primcount ) { 14832 14833 if ( primcount === 0 ) return; 14834 14835 let extension, methodName; 14836 14837 if ( isWebGL2 ) { 14838 14839 extension = gl; 14840 methodName = 'drawArraysInstanced'; 14841 14842 } else { 14843 14844 extension = extensions.get( 'ANGLE_instanced_arrays' ); 14845 methodName = 'drawArraysInstancedANGLE'; 14846 14847 if ( extension === null ) { 14848 14849 console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); 14850 return; 14851 14852 } 14853 14854 } 14855 14856 extension[ methodName ]( mode, start, count, primcount ); 14857 14858 info.update( count, mode, primcount ); 14859 14860 } 14861 14862 // 14863 14864 this.setMode = setMode; 14865 this.render = render; 14866 this.renderInstances = renderInstances; 14867 14868} 14869 14870function WebGLCapabilities( gl, extensions, parameters ) { 14871 14872 let maxAnisotropy; 14873 14874 function getMaxAnisotropy() { 14875 14876 if ( maxAnisotropy !== undefined ) return maxAnisotropy; 14877 14878 if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { 14879 14880 const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); 14881 14882 maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); 14883 14884 } else { 14885 14886 maxAnisotropy = 0; 14887 14888 } 14889 14890 return maxAnisotropy; 14891 14892 } 14893 14894 function getMaxPrecision( precision ) { 14895 14896 if ( precision === 'highp' ) { 14897 14898 if ( gl.getShaderPrecisionFormat( 35633, 36338 ).precision > 0 && 14899 gl.getShaderPrecisionFormat( 35632, 36338 ).precision > 0 ) { 14900 14901 return 'highp'; 14902 14903 } 14904 14905 precision = 'mediump'; 14906 14907 } 14908 14909 if ( precision === 'mediump' ) { 14910 14911 if ( gl.getShaderPrecisionFormat( 35633, 36337 ).precision > 0 && 14912 gl.getShaderPrecisionFormat( 35632, 36337 ).precision > 0 ) { 14913 14914 return 'mediump'; 14915 14916 } 14917 14918 } 14919 14920 return 'lowp'; 14921 14922 } 14923 14924 const isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext; 14925 14926 let precision = parameters.precision !== undefined ? parameters.precision : 'highp'; 14927 const maxPrecision = getMaxPrecision( precision ); 14928 14929 if ( maxPrecision !== precision ) { 14930 14931 console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); 14932 precision = maxPrecision; 14933 14934 } 14935 14936 const drawBuffers = isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ); 14937 14938 const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; 14939 14940 const maxTextures = gl.getParameter( 34930 ); 14941 const maxVertexTextures = gl.getParameter( 35660 ); 14942 const maxTextureSize = gl.getParameter( 3379 ); 14943 const maxCubemapSize = gl.getParameter( 34076 ); 14944 14945 const maxAttributes = gl.getParameter( 34921 ); 14946 const maxVertexUniforms = gl.getParameter( 36347 ); 14947 const maxVaryings = gl.getParameter( 36348 ); 14948 const maxFragmentUniforms = gl.getParameter( 36349 ); 14949 14950 const vertexTextures = maxVertexTextures > 0; 14951 const floatFragmentTextures = isWebGL2 || extensions.has( 'OES_texture_float' ); 14952 const floatVertexTextures = vertexTextures && floatFragmentTextures; 14953 14954 const maxSamples = isWebGL2 ? gl.getParameter( 36183 ) : 0; 14955 14956 return { 14957 14958 isWebGL2: isWebGL2, 14959 14960 drawBuffers: drawBuffers, 14961 14962 getMaxAnisotropy: getMaxAnisotropy, 14963 getMaxPrecision: getMaxPrecision,
vendor: 1,709 bytes, lines 14964-15046
14964 14965 precision: precision, 14966 logarithmicDepthBuffer: logarithmicDepthBuffer, 14967 14968 maxTextures: maxTextures, 14969 maxVertexTextures: maxVertexTextures, 14970 maxTextureSize: maxTextureSize, 14971 maxCubemapSize: maxCubemapSize, 14972 14973 maxAttributes: maxAttributes, 14974 maxVertexUniforms: maxVertexUniforms, 14975 maxVaryings: maxVaryings, 14976 maxFragmentUniforms: maxFragmentUniforms, 14977 14978 vertexTextures: vertexTextures, 14979 floatFragmentTextures: floatFragmentTextures, 14980 floatVertexTextures: floatVertexTextures, 14981 14982 maxSamples: maxSamples 14983 14984 }; 14985 14986} 14987 14988function WebGLClipping( properties ) { 14989 14990 const scope = this; 14991 14992 let globalState = null, 14993 numGlobalPlanes = 0, 14994 localClippingEnabled = false, 14995 renderingShadows = false; 14996 14997 const plane = new Plane(), 14998 viewNormalMatrix = new Matrix3(), 14999 15000 uniform = { value: null, needsUpdate: false }; 15001 15002 this.uniform = uniform; 15003 this.numPlanes = 0; 15004 this.numIntersection = 0; 15005 15006 this.init = function ( planes, enableLocalClipping ) { 15007 15008 const enabled = 15009 planes.length !== 0 || 15010 enableLocalClipping || 15011 // enable state of previous frame - the clipping code has to 15012 // run another frame in order to reset the state: 15013 numGlobalPlanes !== 0 || 15014 localClippingEnabled; 15015 15016 localClippingEnabled = enableLocalClipping; 15017 15018 numGlobalPlanes = planes.length; 15019 15020 return enabled; 15021 15022 }; 15023 15024 this.beginShadows = function () { 15025 15026 renderingShadows = true; 15027 projectPlanes( null ); 15028 15029 }; 15030 15031 this.endShadows = function () { 15032 15033 renderingShadows = false; 15034 15035 }; 15036 15037 this.setGlobalState = function ( planes, camera ) { 15038 15039 globalState = projectPlanes( planes, camera, 0 ); 15040 15041 }; 15042 15043 this.setState = function ( material, camera, useCache ) { 15044 15045 const planes = material.clippingPlanes, 15046 clipIntersection = material.clipIntersection,
vendor: 22,947 bytes, lines 15047-16018
15047 clipShadows = material.clipShadows; 15048 15049 const materialProperties = properties.get( material ); 15050 15051 if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) { 15052 15053 // there's no local clipping 15054 15055 if ( renderingShadows ) { 15056 15057 // there's no global clipping 15058 15059 projectPlanes( null ); 15060 15061 } else { 15062 15063 resetGlobalState(); 15064 15065 } 15066 15067 } else { 15068 15069 const nGlobal = renderingShadows ? 0 : numGlobalPlanes, 15070 lGlobal = nGlobal * 4; 15071 15072 let dstArray = materialProperties.clippingState || null; 15073 15074 uniform.value = dstArray; // ensure unique state 15075 15076 dstArray = projectPlanes( planes, camera, lGlobal, useCache ); 15077 15078 for ( let i = 0; i !== lGlobal; ++ i ) { 15079 15080 dstArray[ i ] = globalState[ i ]; 15081 15082 } 15083 15084 materialProperties.clippingState = dstArray; 15085 this.numIntersection = clipIntersection ? this.numPlanes : 0; 15086 this.numPlanes += nGlobal; 15087 15088 } 15089 15090 15091 }; 15092 15093 function resetGlobalState() { 15094 15095 if ( uniform.value !== globalState ) { 15096 15097 uniform.value = globalState; 15098 uniform.needsUpdate = numGlobalPlanes > 0; 15099 15100 } 15101 15102 scope.numPlanes = numGlobalPlanes; 15103 scope.numIntersection = 0; 15104 15105 } 15106 15107 function projectPlanes( planes, camera, dstOffset, skipTransform ) { 15108 15109 const nPlanes = planes !== null ? planes.length : 0; 15110 let dstArray = null; 15111 15112 if ( nPlanes !== 0 ) { 15113 15114 dstArray = uniform.value; 15115 15116 if ( skipTransform !== true || dstArray === null ) { 15117 15118 const flatSize = dstOffset + nPlanes * 4, 15119 viewMatrix = camera.matrixWorldInverse; 15120 15121 viewNormalMatrix.getNormalMatrix( viewMatrix ); 15122 15123 if ( dstArray === null || dstArray.length < flatSize ) { 15124 15125 dstArray = new Float32Array( flatSize ); 15126 15127 } 15128 15129 for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) { 15130 15131 plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix ); 15132 15133 plane.normal.toArray( dstArray, i4 ); 15134 dstArray[ i4 + 3 ] = plane.constant; 15135 15136 } 15137 15138 } 15139 15140 uniform.value = dstArray; 15141 uniform.needsUpdate = true; 15142 15143 } 15144 15145 scope.numPlanes = nPlanes; 15146 scope.numIntersection = 0; 15147 15148 return dstArray; 15149 15150 } 15151 15152} 15153 15154function WebGLCubeMaps( renderer ) { 15155 15156 let cubemaps = new WeakMap(); 15157 15158 function mapTextureMapping( texture, mapping ) { 15159 15160 if ( mapping === EquirectangularReflectionMapping ) { 15161 15162 texture.mapping = CubeReflectionMapping; 15163 15164 } else if ( mapping === EquirectangularRefractionMapping ) { 15165 15166 texture.mapping = CubeRefractionMapping; 15167 15168 } 15169 15170 return texture; 15171 15172 } 15173 15174 function get( texture ) { 15175 15176 if ( texture && texture.isTexture && texture.isRenderTargetTexture === false ) { 15177 15178 const mapping = texture.mapping; 15179 15180 if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) { 15181 15182 if ( cubemaps.has( texture ) ) { 15183 15184 const cubemap = cubemaps.get( texture ).texture; 15185 return mapTextureMapping( cubemap, texture.mapping ); 15186 15187 } else { 15188 15189 const image = texture.image; 15190 15191 if ( image && image.height > 0 ) { 15192 15193 const renderTarget = new WebGLCubeRenderTarget( image.height / 2 ); 15194 renderTarget.fromEquirectangularTexture( renderer, texture ); 15195 cubemaps.set( texture, renderTarget ); 15196 15197 texture.addEventListener( 'dispose', onTextureDispose ); 15198 15199 return mapTextureMapping( renderTarget.texture, texture.mapping ); 15200 15201 } else { 15202 15203 // image not yet ready. try the conversion next frame 15204 15205 return null; 15206 15207 } 15208 15209 } 15210 15211 } 15212 15213 } 15214 15215 return texture; 15216 15217 } 15218 15219 function onTextureDispose( event ) { 15220 15221 const texture = event.target; 15222 15223 texture.removeEventListener( 'dispose', onTextureDispose ); 15224 15225 const cubemap = cubemaps.get( texture ); 15226 15227 if ( cubemap !== undefined ) { 15228 15229 cubemaps.delete( texture ); 15230 cubemap.dispose(); 15231 15232 } 15233 15234 } 15235 15236 function dispose() { 15237 15238 cubemaps = new WeakMap(); 15239 15240 } 15241 15242 return { 15243 get: get, 15244 dispose: dispose 15245 }; 15246 15247} 15248 15249class OrthographicCamera extends Camera { 15250 15251 constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) { 15252 15253 super(); 15254 15255 this.isOrthographicCamera = true; 15256 15257 this.type = 'OrthographicCamera'; 15258 15259 this.zoom = 1; 15260 this.view = null; 15261 15262 this.left = left; 15263 this.right = right; 15264 this.top = top; 15265 this.bottom = bottom; 15266 15267 this.near = near; 15268 this.far = far; 15269 15270 this.updateProjectionMatrix(); 15271 15272 } 15273 15274 copy( source, recursive ) { 15275 15276 super.copy( source, recursive ); 15277 15278 this.left = source.left; 15279 this.right = source.right; 15280 this.top = source.top; 15281 this.bottom = source.bottom; 15282 this.near = source.near; 15283 this.far = source.far; 15284 15285 this.zoom = source.zoom; 15286 this.view = source.view === null ? null : Object.assign( {}, source.view ); 15287 15288 return this; 15289 15290 } 15291 15292 setViewOffset( fullWidth, fullHeight, x, y, width, height ) { 15293 15294 if ( this.view === null ) { 15295 15296 this.view = { 15297 enabled: true, 15298 fullWidth: 1, 15299 fullHeight: 1, 15300 offsetX: 0, 15301 offsetY: 0, 15302 width: 1, 15303 height: 1 15304 }; 15305 15306 } 15307 15308 this.view.enabled = true; 15309 this.view.fullWidth = fullWidth; 15310 this.view.fullHeight = fullHeight; 15311 this.view.offsetX = x; 15312 this.view.offsetY = y; 15313 this.view.width = width; 15314 this.view.height = height; 15315 15316 this.updateProjectionMatrix(); 15317 15318 } 15319 15320 clearViewOffset() { 15321 15322 if ( this.view !== null ) { 15323 15324 this.view.enabled = false; 15325 15326 } 15327 15328 this.updateProjectionMatrix(); 15329 15330 } 15331 15332 updateProjectionMatrix() { 15333 15334 const dx = ( this.right - this.left ) / ( 2 * this.zoom ); 15335 const dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); 15336 const cx = ( this.right + this.left ) / 2; 15337 const cy = ( this.top + this.bottom ) / 2; 15338 15339 let left = cx - dx; 15340 let right = cx + dx; 15341 let top = cy + dy; 15342 let bottom = cy - dy; 15343 15344 if ( this.view !== null && this.view.enabled ) { 15345 15346 const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom; 15347 const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom; 15348 15349 left += scaleW * this.view.offsetX; 15350 right = left + scaleW * this.view.width; 15351 top -= scaleH * this.view.offsetY; 15352 bottom = top - scaleH * this.view.height; 15353 15354 } 15355 15356 this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far ); 15357 15358 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); 15359 15360 } 15361 15362 toJSON( meta ) { 15363 15364 const data = super.toJSON( meta ); 15365 15366 data.object.zoom = this.zoom; 15367 data.object.left = this.left; 15368 data.object.right = this.right; 15369 data.object.top = this.top; 15370 data.object.bottom = this.bottom; 15371 data.object.near = this.near; 15372 data.object.far = this.far; 15373 15374 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); 15375 15376 return data; 15377 15378 } 15379 15380} 15381 15382const LOD_MIN = 4; 15383 15384// The standard deviations (radians) associated with the extra mips. These are 15385// chosen to approximate a Trowbridge-Reitz distribution function times the 15386// geometric shadowing function. These sigma values squared must match the 15387// variance #defines in cube_uv_reflection_fragment.glsl.js. 15388const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ]; 15389 15390// The maximum length of the blur for loop. Smaller sigmas will use fewer 15391// samples and exit early, but not recompile the shader. 15392const MAX_SAMPLES = 20; 15393 15394const _flatCamera = /*@__PURE__*/ new OrthographicCamera(); 15395const _clearColor = /*@__PURE__*/ new Color(); 15396let _oldTarget = null; 15397 15398// Golden Ratio 15399const PHI = ( 1 + Math.sqrt( 5 ) ) / 2; 15400const INV_PHI = 1 / PHI; 15401 15402// Vertices of a dodecahedron (except the opposites, which represent the 15403// same axis), used as axis directions evenly spread on a sphere. 15404const _axisDirections = [ 15405 /*@__PURE__*/ new Vector3( 1, 1, 1 ), 15406 /*@__PURE__*/ new Vector3( - 1, 1, 1 ), 15407 /*@__PURE__*/ new Vector3( 1, 1, - 1 ), 15408 /*@__PURE__*/ new Vector3( - 1, 1, - 1 ), 15409 /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), 15410 /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), 15411 /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), 15412 /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), 15413 /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), 15414 /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ) ]; 15415 15416/** 15417 * This class generates a Prefiltered, Mipmapped Radiance Environment Map 15418 * (PMREM) from a cubeMap environment texture. This allows different levels of 15419 * blur to be quickly accessed based on material roughness. It is packed into a 15420 * special CubeUV format that allows us to perform custom interpolation so that 15421 * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap 15422 * chain, it only goes down to the LOD_MIN level (above), and then creates extra 15423 * even more filtered 'mips' at the same LOD_MIN resolution, associated with 15424 * higher roughness levels. In this way we maintain resolution to smoothly 15425 * interpolate diffuse lighting while limiting sampling computation. 15426 * 15427 * Paper: Fast, Accurate Image-Based Lighting 15428 * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view 15429*/ 15430 15431class PMREMGenerator { 15432 15433 constructor( renderer ) { 15434 15435 this._renderer = renderer; 15436 this._pingPongRenderTarget = null; 15437 15438 this._lodMax = 0; 15439 this._cubeSize = 0; 15440 this._lodPlanes = []; 15441 this._sizeLods = []; 15442 this._sigmas = []; 15443 15444 this._blurMaterial = null; 15445 this._cubemapMaterial = null; 15446 this._equirectMaterial = null; 15447 15448 this._compileMaterial( this._blurMaterial ); 15449 15450 } 15451 15452 /** 15453 * Generates a PMREM from a supplied Scene, which can be faster than using an 15454 * image if networking bandwidth is low. Optional sigma specifies a blur radius 15455 * in radians to be applied to the scene before PMREM generation. Optional near 15456 * and far planes ensure the scene is rendered in its entirety (the cubeCamera 15457 * is placed at the origin). 15458 */ 15459 fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { 15460 15461 _oldTarget = this._renderer.getRenderTarget(); 15462 15463 this._setSize( 256 ); 15464 15465 const cubeUVRenderTarget = this._allocateTargets(); 15466 cubeUVRenderTarget.depthBuffer = true; 15467 15468 this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); 15469 15470 if ( sigma > 0 ) { 15471 15472 this._blur( cubeUVRenderTarget, 0, 0, sigma ); 15473 15474 } 15475 15476 this._applyPMREM( cubeUVRenderTarget ); 15477 this._cleanup( cubeUVRenderTarget ); 15478 15479 return cubeUVRenderTarget; 15480 15481 } 15482 15483 /** 15484 * Generates a PMREM from an equirectangular texture, which can be either LDR 15485 * or HDR. The ideal input image size is 1k (1024 x 512), 15486 * as this matches best with the 256 x 256 cubemap output. 15487 */ 15488 fromEquirectangular( equirectangular, renderTarget = null ) { 15489 15490 return this._fromTexture( equirectangular, renderTarget ); 15491 15492 } 15493 15494 /** 15495 * Generates a PMREM from an cubemap texture, which can be either LDR 15496 * or HDR. The ideal input cube size is 256 x 256, 15497 * as this matches best with the 256 x 256 cubemap output. 15498 */ 15499 fromCubemap( cubemap, renderTarget = null ) { 15500 15501 return this._fromTexture( cubemap, renderTarget ); 15502 15503 } 15504 15505 /** 15506 * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during 15507 * your texture's network fetch for increased concurrency. 15508 */ 15509 compileCubemapShader() { 15510 15511 if ( this._cubemapMaterial === null ) { 15512 15513 this._cubemapMaterial = _getCubemapMaterial(); 15514 this._compileMaterial( this._cubemapMaterial ); 15515 15516 } 15517 15518 } 15519 15520 /** 15521 * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during 15522 * your texture's network fetch for increased concurrency. 15523 */ 15524 compileEquirectangularShader() { 15525 15526 if ( this._equirectMaterial === null ) { 15527 15528 this._equirectMaterial = _getEquirectMaterial(); 15529 this._compileMaterial( this._equirectMaterial ); 15530 15531 } 15532 15533 } 15534 15535 /** 15536 * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class, 15537 * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on 15538 * one of them will cause any others to also become unusable. 15539 */ 15540 dispose() { 15541 15542 this._dispose(); 15543 15544 if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose(); 15545 if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose(); 15546 15547 } 15548 15549 // private interface 15550 15551 _setSize( cubeSize ) { 15552 15553 this._lodMax = Math.floor( Math.log2( cubeSize ) ); 15554 this._cubeSize = Math.pow( 2, this._lodMax ); 15555 15556 } 15557 15558 _dispose() { 15559 15560 if ( this._blurMaterial !== null ) this._blurMaterial.dispose(); 15561 15562 if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose(); 15563 15564 for ( let i = 0; i < this._lodPlanes.length; i ++ ) { 15565 15566 this._lodPlanes[ i ].dispose(); 15567 15568 } 15569 15570 } 15571 15572 _cleanup( outputTarget ) { 15573 15574 this._renderer.setRenderTarget( _oldTarget ); 15575 outputTarget.scissorTest = false; 15576 _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height ); 15577 15578 } 15579 15580 _fromTexture( texture, renderTarget ) { 15581 15582 if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) { 15583 15584 this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) ); 15585 15586 } else { // Equirectangular 15587 15588 this._setSize( texture.image.width / 4 ); 15589 15590 } 15591 15592 _oldTarget = this._renderer.getRenderTarget(); 15593 15594 const cubeUVRenderTarget = renderTarget || this._allocateTargets(); 15595 this._textureToCubeUV( texture, cubeUVRenderTarget ); 15596 this._applyPMREM( cubeUVRenderTarget ); 15597 this._cleanup( cubeUVRenderTarget ); 15598 15599 return cubeUVRenderTarget; 15600 15601 } 15602 15603 _allocateTargets() { 15604 15605 const width = 3 * Math.max( this._cubeSize, 16 * 7 ); 15606 const height = 4 * this._cubeSize; 15607 15608 const params = { 15609 magFilter: LinearFilter, 15610 minFilter: LinearFilter, 15611 generateMipmaps: false, 15612 type: HalfFloatType, 15613 format: RGBAFormat, 15614 encoding: LinearEncoding, 15615 depthBuffer: false 15616 }; 15617 15618 const cubeUVRenderTarget = _createRenderTarget( width, height, params ); 15619 15620 if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) { 15621 15622 if ( this._pingPongRenderTarget !== null ) { 15623 15624 this._dispose(); 15625 15626 } 15627 15628 this._pingPongRenderTarget = _createRenderTarget( width, height, params ); 15629 15630 const { _lodMax } = this; 15631 ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) ); 15632 15633 this._blurMaterial = _getBlurShader( _lodMax, width, height ); 15634 15635 } 15636 15637 return cubeUVRenderTarget; 15638 15639 } 15640 15641 _compileMaterial( material ) { 15642 15643 const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material ); 15644 this._renderer.compile( tmpMesh, _flatCamera ); 15645 15646 } 15647 15648 _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) { 15649 15650 const fov = 90; 15651 const aspect = 1; 15652 const cubeCamera = new PerspectiveCamera( fov, aspect, near, far ); 15653 const upSign = [ 1, - 1, 1, 1, 1, 1 ]; 15654 const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ]; 15655 const renderer = this._renderer; 15656 15657 const originalAutoClear = renderer.autoClear; 15658 const toneMapping = renderer.toneMapping; 15659 renderer.getClearColor( _clearColor ); 15660 15661 renderer.toneMapping = NoToneMapping; 15662 renderer.autoClear = false; 15663 15664 const backgroundMaterial = new MeshBasicMaterial( { 15665 name: 'PMREM.Background', 15666 side: BackSide, 15667 depthWrite: false, 15668 depthTest: false, 15669 } ); 15670 15671 const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial ); 15672 15673 let useSolidColor = false; 15674 const background = scene.background; 15675 15676 if ( background ) { 15677 15678 if ( background.isColor ) { 15679 15680 backgroundMaterial.color.copy( background ); 15681 scene.background = null; 15682 useSolidColor = true; 15683 15684 } 15685 15686 } else { 15687 15688 backgroundMaterial.color.copy( _clearColor ); 15689 useSolidColor = true; 15690 15691 } 15692 15693 for ( let i = 0; i < 6; i ++ ) { 15694 15695 const col = i % 3; 15696 15697 if ( col === 0 ) { 15698 15699 cubeCamera.up.set( 0, upSign[ i ], 0 ); 15700 cubeCamera.lookAt( forwardSign[ i ], 0, 0 ); 15701 15702 } else if ( col === 1 ) { 15703 15704 cubeCamera.up.set( 0, 0, upSign[ i ] ); 15705 cubeCamera.lookAt( 0, forwardSign[ i ], 0 ); 15706 15707 } else { 15708 15709 cubeCamera.up.set( 0, upSign[ i ], 0 ); 15710 cubeCamera.lookAt( 0, 0, forwardSign[ i ] ); 15711 15712 } 15713 15714 const size = this._cubeSize; 15715 15716 _setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size ); 15717 15718 renderer.setRenderTarget( cubeUVRenderTarget ); 15719 15720 if ( useSolidColor ) { 15721 15722 renderer.render( backgroundBox, cubeCamera ); 15723 15724 } 15725 15726 renderer.render( scene, cubeCamera ); 15727 15728 } 15729 15730 backgroundBox.geometry.dispose(); 15731 backgroundBox.material.dispose(); 15732 15733 renderer.toneMapping = toneMapping; 15734 renderer.autoClear = originalAutoClear; 15735 scene.background = background; 15736 15737 } 15738 15739 _textureToCubeUV( texture, cubeUVRenderTarget ) { 15740 15741 const renderer = this._renderer; 15742 15743 const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ); 15744 15745 if ( isCubeTexture ) { 15746 15747 if ( this._cubemapMaterial === null ) { 15748 15749 this._cubemapMaterial = _getCubemapMaterial(); 15750 15751 } 15752 15753 this._cubemapMaterial.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? - 1 : 1; 15754 15755 } else { 15756 15757 if ( this._equirectMaterial === null ) { 15758 15759 this._equirectMaterial = _getEquirectMaterial(); 15760 15761 } 15762 15763 } 15764 15765 const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; 15766 const mesh = new Mesh( this._lodPlanes[ 0 ], material ); 15767 15768 const uniforms = material.uniforms; 15769 15770 uniforms[ 'envMap' ].value = texture; 15771 15772 const size = this._cubeSize; 15773 15774 _setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size ); 15775 15776 renderer.setRenderTarget( cubeUVRenderTarget ); 15777 renderer.render( mesh, _flatCamera ); 15778 15779 } 15780 15781 _applyPMREM( cubeUVRenderTarget ) { 15782 15783 const renderer = this._renderer; 15784 const autoClear = renderer.autoClear; 15785 renderer.autoClear = false; 15786 15787 for ( let i = 1; i < this._lodPlanes.length; i ++ ) { 15788 15789 const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); 15790 15791 const poleAxis = _axisDirections[ ( i - 1 ) % _axisDirections.length ]; 15792 15793 this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); 15794 15795 } 15796 15797 renderer.autoClear = autoClear; 15798 15799 } 15800 15801 /** 15802 * This is a two-pass Gaussian blur for a cubemap. Normally this is done 15803 * vertically and horizontally, but this breaks down on a cube. Here we apply 15804 * the blur latitudinally (around the poles), and then longitudinally (towards 15805 * the poles) to approximate the orthogonally-separable blur. It is least 15806 * accurate at the poles, but still does a decent job. 15807 */ 15808 _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) { 15809 15810 const pingPongRenderTarget = this._pingPongRenderTarget; 15811 15812 this._halfBlur( 15813 cubeUVRenderTarget, 15814 pingPongRenderTarget, 15815 lodIn, 15816 lodOut, 15817 sigma, 15818 'latitudinal', 15819 poleAxis ); 15820 15821 this._halfBlur( 15822 pingPongRenderTarget, 15823 cubeUVRenderTarget, 15824 lodOut, 15825 lodOut, 15826 sigma, 15827 'longitudinal', 15828 poleAxis ); 15829 15830 } 15831 15832 _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) { 15833 15834 const renderer = this._renderer; 15835 const blurMaterial = this._blurMaterial; 15836 15837 if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { 15838 15839 console.error( 15840 'blur direction must be either latitudinal or longitudinal!' ); 15841 15842 } 15843 15844 // Number of standard deviations at which to cut off the discrete approximation. 15845 const STANDARD_DEVIATIONS = 3; 15846 15847 const blurMesh = new Mesh( this._lodPlanes[ lodOut ], blurMaterial ); 15848 const blurUniforms = blurMaterial.uniforms; 15849 15850 const pixels = this._sizeLods[ lodIn ] - 1; 15851 const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 ); 15852 const sigmaPixels = sigmaRadians / radiansPerPixel; 15853 const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES; 15854 15855 if ( samples > MAX_SAMPLES ) { 15856 15857 console.warn( `sigmaRadians, ${ 15858 sigmaRadians}, is too large and will clip, as it requested ${ 15859 samples} samples when the maximum is set to ${MAX_SAMPLES}` ); 15860 15861 } 15862 15863 const weights = []; 15864 let sum = 0; 15865 15866 for ( let i = 0; i < MAX_SAMPLES; ++ i ) { 15867 15868 const x = i / sigmaPixels; 15869 const weight = Math.exp( - x * x / 2 ); 15870 weights.push( weight ); 15871 15872 if ( i === 0 ) { 15873 15874 sum += weight; 15875 15876 } else if ( i < samples ) { 15877 15878 sum += 2 * weight; 15879 15880 } 15881 15882 } 15883 15884 for ( let i = 0; i < weights.length; i ++ ) { 15885 15886 weights[ i ] = weights[ i ] / sum; 15887 15888 } 15889 15890 blurUniforms[ 'envMap' ].value = targetIn.texture; 15891 blurUniforms[ 'samples' ].value = samples; 15892 blurUniforms[ 'weights' ].value = weights; 15893 blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal'; 15894 15895 if ( poleAxis ) { 15896 15897 blurUniforms[ 'poleAxis' ].value = poleAxis; 15898 15899 } 15900 15901 const { _lodMax } = this; 15902 blurUniforms[ 'dTheta' ].value = radiansPerPixel; 15903 blurUniforms[ 'mipInt' ].value = _lodMax - lodIn; 15904 15905 const outputSize = this._sizeLods[ lodOut ]; 15906 const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); 15907 const y = 4 * ( this._cubeSize - outputSize ); 15908 15909 _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize ); 15910 renderer.setRenderTarget( targetOut ); 15911 renderer.render( blurMesh, _flatCamera ); 15912 15913 } 15914 15915} 15916 15917 15918 15919function _createPlanes( lodMax ) { 15920 15921 const lodPlanes = []; 15922 const sizeLods = []; 15923 const sigmas = []; 15924 15925 let lod = lodMax; 15926 15927 const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length; 15928 15929 for ( let i = 0; i < totalLods; i ++ ) { 15930 15931 const sizeLod = Math.pow( 2, lod ); 15932 sizeLods.push( sizeLod ); 15933 let sigma = 1.0 / sizeLod; 15934 15935 if ( i > lodMax - LOD_MIN ) { 15936 15937 sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ]; 15938 15939 } else if ( i === 0 ) { 15940 15941 sigma = 0; 15942 15943 } 15944 15945 sigmas.push( sigma ); 15946 15947 const texelSize = 1.0 / ( sizeLod - 2 ); 15948 const min = - texelSize; 15949 const max = 1 + texelSize; 15950 const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ]; 15951 15952 const cubeFaces = 6; 15953 const vertices = 6; 15954 const positionSize = 3; 15955 const uvSize = 2; 15956 const faceIndexSize = 1; 15957 15958 const position = new Float32Array( positionSize * vertices * cubeFaces ); 15959 const uv = new Float32Array( uvSize * vertices * cubeFaces ); 15960 const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces ); 15961 15962 for ( let face = 0; face < cubeFaces; face ++ ) { 15963 15964 const x = ( face % 3 ) * 2 / 3 - 1; 15965 const y = face > 2 ? 0 : - 1; 15966 const coordinates = [ 15967 x, y, 0, 15968 x + 2 / 3, y, 0, 15969 x + 2 / 3, y + 1, 0, 15970 x, y, 0, 15971 x + 2 / 3, y + 1, 0, 15972 x, y + 1, 0 15973 ]; 15974 position.set( coordinates, positionSize * vertices * face ); 15975 uv.set( uv1, uvSize * vertices * face ); 15976 const fill = [ face, face, face, face, face, face ]; 15977 faceIndex.set( fill, faceIndexSize * vertices * face ); 15978 15979 } 15980 15981 const planes = new BufferGeometry(); 15982 planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) ); 15983 planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) ); 15984 planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) ); 15985 lodPlanes.push( planes ); 15986 15987 if ( lod > LOD_MIN ) { 15988 15989 lod --; 15990 15991 } 15992 15993 } 15994 15995 return { lodPlanes, sizeLods, sigmas }; 15996 15997} 15998 15999function _createRenderTarget( width, height, params ) { 16000 16001 const cubeUVRenderTarget = new WebGLRenderTarget( width, height, params ); 16002 cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping; 16003 cubeUVRenderTarget.texture.name = 'PMREM.cubeUv'; 16004 cubeUVRenderTarget.scissorTest = true; 16005 return cubeUVRenderTarget; 16006 16007} 16008 16009function _setViewport( target, x, y, width, height ) { 16010 16011 target.viewport.set( x, y, width, height ); 16012 target.scissor.set( x, y, width, height ); 16013 16014} 16015 16016function _getBlurShader( lodMax, width, height ) { 16017 16018 const weights = new Float32Array( MAX_SAMPLES );
vendor: 4,417 bytes, lines 16019-16257
16019 const poleAxis = new Vector3( 0, 1, 0 ); 16020 const shaderMaterial = new ShaderMaterial( { 16021 16022 name: 'SphericalGaussianBlur', 16023 16024 defines: { 16025 'n': MAX_SAMPLES, 16026 'CUBEUV_TEXEL_WIDTH': 1.0 / width, 16027 'CUBEUV_TEXEL_HEIGHT': 1.0 / height, 16028 'CUBEUV_MAX_MIP': `${lodMax}.0`, 16029 }, 16030 16031 uniforms: { 16032 'envMap': { value: null }, 16033 'samples': { value: 1 }, 16034 'weights': { value: weights }, 16035 'latitudinal': { value: false }, 16036 'dTheta': { value: 0 }, 16037 'mipInt': { value: 0 }, 16038 'poleAxis': { value: poleAxis } 16039 }, 16040 16041 vertexShader: _getCommonVertexShader(), 16042 16043 fragmentShader: /* glsl */` 16044 16045 precision mediump float; 16046 precision mediump int; 16047 16048 varying vec3 vOutputDirection; 16049 16050 uniform sampler2D envMap; 16051 uniform int samples; 16052 uniform float weights[ n ]; 16053 uniform bool latitudinal; 16054 uniform float dTheta; 16055 uniform float mipInt; 16056 uniform vec3 poleAxis; 16057 16058 #define ENVMAP_TYPE_CUBE_UV 16059 #include <cube_uv_reflection_fragment> 16060 16061 vec3 getSample( float theta, vec3 axis ) { 16062 16063 float cosTheta = cos( theta ); 16064 // Rodrigues' axis-angle rotation 16065 vec3 sampleDirection = vOutputDirection * cosTheta 16066 + cross( axis, vOutputDirection ) * sin( theta ) 16067 + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta ); 16068 16069 return bilinearCubeUV( envMap, sampleDirection, mipInt ); 16070 16071 } 16072 16073 void main() { 16074 16075 vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection ); 16076 16077 if ( all( equal( axis, vec3( 0.0 ) ) ) ) { 16078 16079 axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x ); 16080 16081 } 16082 16083 axis = normalize( axis ); 16084 16085 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); 16086 gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis ); 16087 16088 for ( int i = 1; i < n; i++ ) { 16089 16090 if ( i >= samples ) { 16091 16092 break; 16093 16094 } 16095 16096 float theta = dTheta * float( i ); 16097 gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis ); 16098 gl_FragColor.rgb += weights[ i ] * getSample( theta, axis ); 16099 16100 } 16101 16102 } 16103 `, 16104 16105 blending: NoBlending, 16106 depthTest: false, 16107 depthWrite: false 16108 16109 } ); 16110 16111 return shaderMaterial; 16112 16113} 16114 16115function _getEquirectMaterial() { 16116 16117 return new ShaderMaterial( { 16118 16119 name: 'EquirectangularToCubeUV', 16120 16121 uniforms: { 16122 'envMap': { value: null } 16123 }, 16124 16125 vertexShader: _getCommonVertexShader(), 16126 16127 fragmentShader: /* glsl */` 16128 16129 precision mediump float; 16130 precision mediump int; 16131 16132 varying vec3 vOutputDirection; 16133 16134 uniform sampler2D envMap; 16135 16136 #include <common> 16137 16138 void main() { 16139 16140 vec3 outputDirection = normalize( vOutputDirection ); 16141 vec2 uv = equirectUv( outputDirection ); 16142 16143 gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); 16144 16145 } 16146 `, 16147 16148 blending: NoBlending, 16149 depthTest: false, 16150 depthWrite: false 16151 16152 } ); 16153 16154} 16155 16156function _getCubemapMaterial() { 16157 16158 return new ShaderMaterial( { 16159 16160 name: 'CubemapToCubeUV', 16161 16162 uniforms: { 16163 'envMap': { value: null }, 16164 'flipEnvMap': { value: - 1 } 16165 }, 16166 16167 vertexShader: _getCommonVertexShader(), 16168 16169 fragmentShader: /* glsl */` 16170 16171 precision mediump float; 16172 precision mediump int; 16173 16174 uniform float flipEnvMap; 16175 16176 varying vec3 vOutputDirection; 16177 16178 uniform samplerCube envMap; 16179 16180 void main() { 16181 16182 gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); 16183 16184 } 16185 `, 16186 16187 blending: NoBlending, 16188 depthTest: false, 16189 depthWrite: false 16190 16191 } ); 16192 16193} 16194 16195function _getCommonVertexShader() { 16196 16197 return /* glsl */` 16198 16199 precision mediump float; 16200 precision mediump int; 16201 16202 attribute float faceIndex; 16203 16204 varying vec3 vOutputDirection; 16205 16206 // RH coordinate system; PMREM face-indexing convention 16207 vec3 getDirection( vec2 uv, float face ) { 16208 16209 uv = 2.0 * uv - 1.0; 16210 16211 vec3 direction = vec3( uv, 1.0 ); 16212 16213 if ( face == 0.0 ) { 16214 16215 direction = direction.zyx; // ( 1, v, u ) pos x 16216 16217 } else if ( face == 1.0 ) { 16218 16219 direction = direction.xzy; 16220 direction.xz *= -1.0; // ( -u, 1, -v ) pos y 16221 16222 } else if ( face == 2.0 ) { 16223 16224 direction.x *= -1.0; // ( -u, v, 1 ) pos z 16225 16226 } else if ( face == 3.0 ) { 16227 16228 direction = direction.zyx; 16229 direction.xz *= -1.0; // ( -1, v, -u ) neg x 16230 16231 } else if ( face == 4.0 ) { 16232 16233 direction = direction.xzy; 16234 direction.xy *= -1.0; // ( -u, -1, v ) neg y 16235 16236 } else if ( face == 5.0 ) { 16237 16238 direction.z *= -1.0; // ( u, v, -1 ) neg z 16239 16240 } 16241 16242 return direction; 16243 16244 } 16245 16246 void main() { 16247 16248 vOutputDirection = getDirection( uv, faceIndex ); 16249 gl_Position = vec4( position, 1.0 ); 16250 16251 } 16252 `; 16253 16254} 16255 16256function WebGLCubeUVMaps( renderer ) { 16257
vendor: 4,214 bytes, lines 16258-16447
16258 let cubeUVmaps = new WeakMap(); 16259 16260 let pmremGenerator = null; 16261 16262 function get( texture ) { 16263 16264 if ( texture && texture.isTexture ) { 16265 16266 const mapping = texture.mapping; 16267 16268 const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ); 16269 const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); 16270 16271 // equirect/cube map to cubeUV conversion 16272 16273 if ( isEquirectMap || isCubeMap ) { 16274 16275 if ( texture.isRenderTargetTexture && texture.needsPMREMUpdate === true ) { 16276 16277 texture.needsPMREMUpdate = false; 16278 16279 let renderTarget = cubeUVmaps.get( texture ); 16280 16281 if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); 16282 16283 renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget ); 16284 cubeUVmaps.set( texture, renderTarget ); 16285 16286 return renderTarget.texture; 16287 16288 } else { 16289 16290 if ( cubeUVmaps.has( texture ) ) { 16291 16292 return cubeUVmaps.get( texture ).texture; 16293 16294 } else { 16295 16296 const image = texture.image; 16297 16298 if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) { 16299 16300 if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); 16301 16302 const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture ); 16303 cubeUVmaps.set( texture, renderTarget ); 16304 16305 texture.addEventListener( 'dispose', onTextureDispose ); 16306 16307 return renderTarget.texture; 16308 16309 } else { 16310 16311 // image not yet ready. try the conversion next frame 16312 16313 return null; 16314 16315 } 16316 16317 } 16318 16319 } 16320 16321 } 16322 16323 } 16324 16325 return texture; 16326 16327 } 16328 16329 function isCubeTextureComplete( image ) { 16330 16331 let count = 0; 16332 const length = 6; 16333 16334 for ( let i = 0; i < length; i ++ ) { 16335 16336 if ( image[ i ] !== undefined ) count ++; 16337 16338 } 16339 16340 return count === length; 16341 16342 16343 } 16344 16345 function onTextureDispose( event ) { 16346 16347 const texture = event.target; 16348 16349 texture.removeEventListener( 'dispose', onTextureDispose ); 16350 16351 const cubemapUV = cubeUVmaps.get( texture ); 16352 16353 if ( cubemapUV !== undefined ) { 16354 16355 cubeUVmaps.delete( texture ); 16356 cubemapUV.dispose(); 16357 16358 } 16359 16360 } 16361 16362 function dispose() { 16363 16364 cubeUVmaps = new WeakMap(); 16365 16366 if ( pmremGenerator !== null ) { 16367 16368 pmremGenerator.dispose(); 16369 pmremGenerator = null; 16370 16371 } 16372 16373 } 16374 16375 return { 16376 get: get, 16377 dispose: dispose 16378 }; 16379 16380} 16381 16382function WebGLExtensions( gl ) { 16383 16384 const extensions = {}; 16385 16386 function getExtension( name ) { 16387 16388 if ( extensions[ name ] !== undefined ) { 16389 16390 return extensions[ name ]; 16391 16392 } 16393 16394 let extension; 16395 16396 switch ( name ) { 16397 16398 case 'WEBGL_depth_texture': 16399 extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' ); 16400 break; 16401 16402 case 'EXT_texture_filter_anisotropic': 16403 extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' ); 16404 break; 16405 16406 case 'WEBGL_compressed_texture_s3tc': 16407 extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' ); 16408 break; 16409 16410 case 'WEBGL_compressed_texture_pvrtc': 16411 extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' ); 16412 break; 16413 16414 default: 16415 extension = gl.getExtension( name ); 16416 16417 } 16418 16419 extensions[ name ] = extension; 16420 16421 return extension; 16422 16423 } 16424 16425 return { 16426 16427 has: function ( name ) { 16428 16429 return getExtension( name ) !== null; 16430 16431 }, 16432 16433 init: function ( capabilities ) { 16434 16435 if ( capabilities.isWebGL2 ) { 16436 16437 getExtension( 'EXT_color_buffer_float' ); 16438 16439 } else { 16440 16441 getExtension( 'WEBGL_depth_texture' ); 16442 getExtension( 'OES_texture_float' ); 16443 getExtension( 'OES_texture_half_float' ); 16444 getExtension( 'OES_texture_half_float_linear' ); 16445 getExtension( 'OES_standard_derivatives' ); 16446 getExtension( 'OES_element_index_uint' ); 16447 getExtension( 'OES_vertex_array_object' );
vendor: 4,537 bytes, lines 16448-16707
16448 getExtension( 'ANGLE_instanced_arrays' ); 16449 16450 } 16451 16452 getExtension( 'OES_texture_float_linear' ); 16453 getExtension( 'EXT_color_buffer_half_float' ); 16454 getExtension( 'WEBGL_multisampled_render_to_texture' ); 16455 16456 }, 16457 16458 get: function ( name ) { 16459 16460 const extension = getExtension( name ); 16461 16462 if ( extension === null ) { 16463 16464 console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); 16465 16466 } 16467 16468 return extension; 16469 16470 } 16471 16472 }; 16473 16474} 16475 16476function WebGLGeometries( gl, attributes, info, bindingStates ) { 16477 16478 const geometries = {}; 16479 const wireframeAttributes = new WeakMap(); 16480 16481 function onGeometryDispose( event ) { 16482 16483 const geometry = event.target; 16484 16485 if ( geometry.index !== null ) { 16486 16487 attributes.remove( geometry.index ); 16488 16489 } 16490 16491 for ( const name in geometry.attributes ) { 16492 16493 attributes.remove( geometry.attributes[ name ] ); 16494 16495 } 16496 16497 geometry.removeEventListener( 'dispose', onGeometryDispose ); 16498 16499 delete geometries[ geometry.id ]; 16500 16501 const attribute = wireframeAttributes.get( geometry ); 16502 16503 if ( attribute ) { 16504 16505 attributes.remove( attribute ); 16506 wireframeAttributes.delete( geometry ); 16507 16508 } 16509 16510 bindingStates.releaseStatesOfGeometry( geometry ); 16511 16512 if ( geometry.isInstancedBufferGeometry === true ) { 16513 16514 delete geometry._maxInstanceCount; 16515 16516 } 16517 16518 // 16519 16520 info.memory.geometries --; 16521 16522 } 16523 16524 function get( object, geometry ) { 16525 16526 if ( geometries[ geometry.id ] === true ) return geometry; 16527 16528 geometry.addEventListener( 'dispose', onGeometryDispose ); 16529 16530 geometries[ geometry.id ] = true; 16531 16532 info.memory.geometries ++; 16533 16534 return geometry; 16535 16536 } 16537 16538 function update( geometry ) { 16539 16540 const geometryAttributes = geometry.attributes; 16541 16542 // Updating index buffer in VAO now. See WebGLBindingStates. 16543 16544 for ( const name in geometryAttributes ) { 16545 16546 attributes.update( geometryAttributes[ name ], 34962 ); 16547 16548 } 16549 16550 // morph targets 16551 16552 const morphAttributes = geometry.morphAttributes; 16553 16554 for ( const name in morphAttributes ) { 16555 16556 const array = morphAttributes[ name ]; 16557 16558 for ( let i = 0, l = array.length; i < l; i ++ ) { 16559 16560 attributes.update( array[ i ], 34962 ); 16561 16562 } 16563 16564 } 16565 16566 } 16567 16568 function updateWireframeAttribute( geometry ) { 16569 16570 const indices = []; 16571 16572 const geometryIndex = geometry.index; 16573 const geometryPosition = geometry.attributes.position; 16574 let version = 0; 16575 16576 if ( geometryIndex !== null ) { 16577 16578 const array = geometryIndex.array; 16579 version = geometryIndex.version; 16580 16581 for ( let i = 0, l = array.length; i < l; i += 3 ) { 16582 16583 const a = array[ i + 0 ]; 16584 const b = array[ i + 1 ]; 16585 const c = array[ i + 2 ]; 16586 16587 indices.push( a, b, b, c, c, a ); 16588 16589 } 16590 16591 } else { 16592 16593 const array = geometryPosition.array; 16594 version = geometryPosition.version; 16595 16596 for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { 16597 16598 const a = i + 0; 16599 const b = i + 1; 16600 const c = i + 2; 16601 16602 indices.push( a, b, b, c, c, a ); 16603 16604 } 16605 16606 } 16607 16608 const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); 16609 attribute.version = version; 16610 16611 // Updating index buffer in VAO now. See WebGLBindingStates 16612 16613 // 16614 16615 const previousAttribute = wireframeAttributes.get( geometry ); 16616 16617 if ( previousAttribute ) attributes.remove( previousAttribute ); 16618 16619 // 16620 16621 wireframeAttributes.set( geometry, attribute ); 16622 16623 } 16624 16625 function getWireframeAttribute( geometry ) { 16626 16627 const currentAttribute = wireframeAttributes.get( geometry ); 16628 16629 if ( currentAttribute ) { 16630 16631 const geometryIndex = geometry.index; 16632 16633 if ( geometryIndex !== null ) { 16634 16635 // if the attribute is obsolete, create a new one 16636 16637 if ( currentAttribute.version < geometryIndex.version ) { 16638 16639 updateWireframeAttribute( geometry ); 16640 16641 } 16642 16643 } 16644 16645 } else { 16646 16647 updateWireframeAttribute( geometry ); 16648 16649 } 16650 16651 return wireframeAttributes.get( geometry ); 16652 16653 } 16654 16655 return { 16656 16657 get: get, 16658 update: update, 16659 16660 getWireframeAttribute: getWireframeAttribute 16661 16662 }; 16663 16664} 16665 16666function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) { 16667 16668 const isWebGL2 = capabilities.isWebGL2; 16669 16670 let mode; 16671 16672 function setMode( value ) { 16673 16674 mode = value; 16675 16676 } 16677 16678 let type, bytesPerElement; 16679 16680 function setIndex( value ) { 16681 16682 type = value.type; 16683 bytesPerElement = value.bytesPerElement; 16684 16685 } 16686 16687 function render( start, count ) { 16688 16689 gl.drawElements( mode, count, type, start * bytesPerElement ); 16690 16691 info.update( count, mode, 1 ); 16692 16693 } 16694 16695 function renderInstances( start, count, primcount ) { 16696 16697 if ( primcount === 0 ) return; 16698 16699 let extension, methodName; 16700 16701 if ( isWebGL2 ) { 16702 16703 extension = gl; 16704 methodName = 'drawElementsInstanced'; 16705 16706 } else { 16707
vendor: 10,265 bytes, lines 16708-17161
16708 extension = extensions.get( 'ANGLE_instanced_arrays' ); 16709 methodName = 'drawElementsInstancedANGLE'; 16710 16711 if ( extension === null ) { 16712 16713 console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); 16714 return; 16715 16716 } 16717 16718 } 16719 16720 extension[ methodName ]( mode, count, type, start * bytesPerElement, primcount ); 16721 16722 info.update( count, mode, primcount ); 16723 16724 } 16725 16726 // 16727 16728 this.setMode = setMode; 16729 this.setIndex = setIndex; 16730 this.render = render; 16731 this.renderInstances = renderInstances; 16732 16733} 16734 16735function WebGLInfo( gl ) { 16736 16737 const memory = { 16738 geometries: 0, 16739 textures: 0 16740 }; 16741 16742 const render = { 16743 frame: 0, 16744 calls: 0, 16745 triangles: 0, 16746 points: 0, 16747 lines: 0 16748 }; 16749 16750 function update( count, mode, instanceCount ) { 16751 16752 render.calls ++; 16753 16754 switch ( mode ) { 16755 16756 case 4: 16757 render.triangles += instanceCount * ( count / 3 ); 16758 break; 16759 16760 case 1: 16761 render.lines += instanceCount * ( count / 2 ); 16762 break; 16763 16764 case 3: 16765 render.lines += instanceCount * ( count - 1 ); 16766 break; 16767 16768 case 2: 16769 render.lines += instanceCount * count; 16770 break; 16771 16772 case 0: 16773 render.points += instanceCount * count; 16774 break; 16775 16776 default: 16777 console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode ); 16778 break; 16779 16780 } 16781 16782 } 16783 16784 function reset() { 16785 16786 render.frame ++; 16787 render.calls = 0; 16788 render.triangles = 0; 16789 render.points = 0; 16790 render.lines = 0; 16791 16792 } 16793 16794 return { 16795 memory: memory, 16796 render: render, 16797 programs: null, 16798 autoReset: true, 16799 reset: reset, 16800 update: update 16801 }; 16802 16803} 16804 16805function numericalSort( a, b ) { 16806 16807 return a[ 0 ] - b[ 0 ]; 16808 16809} 16810 16811function absNumericalSort( a, b ) { 16812 16813 return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] ); 16814 16815} 16816 16817function WebGLMorphtargets( gl, capabilities, textures ) { 16818 16819 const influencesList = {}; 16820 const morphInfluences = new Float32Array( 8 ); 16821 const morphTextures = new WeakMap(); 16822 const morph = new Vector4(); 16823 16824 const workInfluences = []; 16825 16826 for ( let i = 0; i < 8; i ++ ) { 16827 16828 workInfluences[ i ] = [ i, 0 ]; 16829 16830 } 16831 16832 function update( object, geometry, program ) { 16833 16834 const objectInfluences = object.morphTargetInfluences; 16835 16836 if ( capabilities.isWebGL2 === true ) { 16837 16838 // instead of using attributes, the WebGL 2 code path encodes morph targets 16839 // into an array of data textures. Each layer represents a single morph target. 16840 16841 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; 16842 const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; 16843 16844 let entry = morphTextures.get( geometry ); 16845 16846 if ( entry === undefined || entry.count !== morphTargetsCount ) { 16847 16848 if ( entry !== undefined ) entry.texture.dispose(); 16849 16850 const hasMorphPosition = geometry.morphAttributes.position !== undefined; 16851 const hasMorphNormals = geometry.morphAttributes.normal !== undefined; 16852 const hasMorphColors = geometry.morphAttributes.color !== undefined; 16853 16854 const morphTargets = geometry.morphAttributes.position || []; 16855 const morphNormals = geometry.morphAttributes.normal || []; 16856 const morphColors = geometry.morphAttributes.color || []; 16857 16858 let vertexDataCount = 0; 16859 16860 if ( hasMorphPosition === true ) vertexDataCount = 1; 16861 if ( hasMorphNormals === true ) vertexDataCount = 2; 16862 if ( hasMorphColors === true ) vertexDataCount = 3; 16863 16864 let width = geometry.attributes.position.count * vertexDataCount; 16865 let height = 1; 16866 16867 if ( width > capabilities.maxTextureSize ) { 16868 16869 height = Math.ceil( width / capabilities.maxTextureSize ); 16870 width = capabilities.maxTextureSize; 16871 16872 } 16873 16874 const buffer = new Float32Array( width * height * 4 * morphTargetsCount ); 16875 16876 const texture = new DataArrayTexture( buffer, width, height, morphTargetsCount ); 16877 texture.type = FloatType; 16878 texture.needsUpdate = true; 16879 16880 // fill buffer 16881 16882 const vertexDataStride = vertexDataCount * 4; 16883 16884 for ( let i = 0; i < morphTargetsCount; i ++ ) { 16885 16886 const morphTarget = morphTargets[ i ]; 16887 const morphNormal = morphNormals[ i ]; 16888 const morphColor = morphColors[ i ]; 16889 16890 const offset = width * height * 4 * i; 16891 16892 for ( let j = 0; j < morphTarget.count; j ++ ) { 16893 16894 const stride = j * vertexDataStride; 16895 16896 if ( hasMorphPosition === true ) { 16897 16898 morph.fromBufferAttribute( morphTarget, j ); 16899 16900 buffer[ offset + stride + 0 ] = morph.x; 16901 buffer[ offset + stride + 1 ] = morph.y; 16902 buffer[ offset + stride + 2 ] = morph.z; 16903 buffer[ offset + stride + 3 ] = 0; 16904 16905 } 16906 16907 if ( hasMorphNormals === true ) { 16908 16909 morph.fromBufferAttribute( morphNormal, j ); 16910 16911 buffer[ offset + stride + 4 ] = morph.x; 16912 buffer[ offset + stride + 5 ] = morph.y; 16913 buffer[ offset + stride + 6 ] = morph.z; 16914 buffer[ offset + stride + 7 ] = 0; 16915 16916 } 16917 16918 if ( hasMorphColors === true ) { 16919 16920 morph.fromBufferAttribute( morphColor, j ); 16921 16922 buffer[ offset + stride + 8 ] = morph.x; 16923 buffer[ offset + stride + 9 ] = morph.y; 16924 buffer[ offset + stride + 10 ] = morph.z; 16925 buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? morph.w : 1; 16926 16927 } 16928 16929 } 16930 16931 } 16932 16933 entry = { 16934 count: morphTargetsCount, 16935 texture: texture, 16936 size: new Vector2( width, height ) 16937 }; 16938 16939 morphTextures.set( geometry, entry ); 16940 16941 function disposeTexture() { 16942 16943 texture.dispose(); 16944 16945 morphTextures.delete( geometry ); 16946 16947 geometry.removeEventListener( 'dispose', disposeTexture ); 16948 16949 } 16950 16951 geometry.addEventListener( 'dispose', disposeTexture ); 16952 16953 } 16954 16955 // 16956 16957 let morphInfluencesSum = 0; 16958 16959 for ( let i = 0; i < objectInfluences.length; i ++ ) { 16960 16961 morphInfluencesSum += objectInfluences[ i ]; 16962 16963 } 16964 16965 const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; 16966 16967 program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence ); 16968 program.getUniforms().setValue( gl, 'morphTargetInfluences', objectInfluences ); 16969 16970 program.getUniforms().setValue( gl, 'morphTargetsTexture', entry.texture, textures ); 16971 program.getUniforms().setValue( gl, 'morphTargetsTextureSize', entry.size ); 16972 16973 16974 } else { 16975 16976 // When object doesn't have morph target influences defined, we treat it as a 0-length array 16977 // This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences 16978 16979 const length = objectInfluences === undefined ? 0 : objectInfluences.length; 16980 16981 let influences = influencesList[ geometry.id ]; 16982 16983 if ( influences === undefined || influences.length !== length ) { 16984 16985 // initialise list 16986 16987 influences = []; 16988 16989 for ( let i = 0; i < length; i ++ ) { 16990 16991 influences[ i ] = [ i, 0 ]; 16992 16993 } 16994 16995 influencesList[ geometry.id ] = influences; 16996 16997 } 16998 16999 // Collect influences 17000 17001 for ( let i = 0; i < length; i ++ ) { 17002 17003 const influence = influences[ i ]; 17004 17005 influence[ 0 ] = i; 17006 influence[ 1 ] = objectInfluences[ i ]; 17007 17008 } 17009 17010 influences.sort( absNumericalSort ); 17011 17012 for ( let i = 0; i < 8; i ++ ) { 17013 17014 if ( i < length && influences[ i ][ 1 ] ) { 17015 17016 workInfluences[ i ][ 0 ] = influences[ i ][ 0 ]; 17017 workInfluences[ i ][ 1 ] = influences[ i ][ 1 ]; 17018 17019 } else { 17020 17021 workInfluences[ i ][ 0 ] = Number.MAX_SAFE_INTEGER; 17022 workInfluences[ i ][ 1 ] = 0; 17023 17024 } 17025 17026 } 17027 17028 workInfluences.sort( numericalSort ); 17029 17030 const morphTargets = geometry.morphAttributes.position; 17031 const morphNormals = geometry.morphAttributes.normal; 17032 17033 let morphInfluencesSum = 0; 17034 17035 for ( let i = 0; i < 8; i ++ ) { 17036 17037 const influence = workInfluences[ i ]; 17038 const index = influence[ 0 ]; 17039 const value = influence[ 1 ]; 17040 17041 if ( index !== Number.MAX_SAFE_INTEGER && value ) { 17042 17043 if ( morphTargets && geometry.getAttribute( 'morphTarget' + i ) !== morphTargets[ index ] ) { 17044 17045 geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] ); 17046 17047 } 17048 17049 if ( morphNormals && geometry.getAttribute( 'morphNormal' + i ) !== morphNormals[ index ] ) { 17050 17051 geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] ); 17052 17053 } 17054 17055 morphInfluences[ i ] = value; 17056 morphInfluencesSum += value; 17057 17058 } else { 17059 17060 if ( morphTargets && geometry.hasAttribute( 'morphTarget' + i ) === true ) { 17061 17062 geometry.deleteAttribute( 'morphTarget' + i ); 17063 17064 } 17065 17066 if ( morphNormals && geometry.hasAttribute( 'morphNormal' + i ) === true ) { 17067 17068 geometry.deleteAttribute( 'morphNormal' + i ); 17069 17070 } 17071 17072 morphInfluences[ i ] = 0; 17073 17074 } 17075 17076 } 17077 17078 // GLSL shader uses formula baseinfluence * base + sum(target * influence) 17079 // This allows us to switch between absolute morphs and relative morphs without changing shader code 17080 // When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence) 17081 const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; 17082 17083 program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence ); 17084 program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences ); 17085 17086 } 17087 17088 } 17089 17090 return { 17091 17092 update: update 17093 17094 }; 17095 17096} 17097 17098function WebGLObjects( gl, geometries, attributes, info ) { 17099 17100 let updateMap = new WeakMap(); 17101 17102 function update( object ) { 17103 17104 const frame = info.render.frame; 17105 17106 const geometry = object.geometry; 17107 const buffergeometry = geometries.get( object, geometry ); 17108 17109 // Update once per frame 17110 17111 if ( updateMap.get( buffergeometry ) !== frame ) { 17112 17113 geometries.update( buffergeometry ); 17114 17115 updateMap.set( buffergeometry, frame ); 17116 17117 } 17118 17119 if ( object.isInstancedMesh ) { 17120 17121 if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) { 17122 17123 object.addEventListener( 'dispose', onInstancedMeshDispose ); 17124 17125 } 17126 17127 attributes.update( object.instanceMatrix, 34962 ); 17128 17129 if ( object.instanceColor !== null ) { 17130 17131 attributes.update( object.instanceColor, 34962 ); 17132 17133 } 17134 17135 } 17136 17137 return buffergeometry; 17138 17139 } 17140 17141 function dispose() { 17142 17143 updateMap = new WeakMap(); 17144 17145 } 17146 17147 function onInstancedMeshDispose( event ) { 17148 17149 const instancedMesh = event.target; 17150 17151 instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose ); 17152 17153 attributes.remove( instancedMesh.instanceMatrix ); 17154 17155 if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor ); 17156 17157 } 17158 17159 return { 17160 17161 update: update,
17162 dispose: dispose 17163 17164 }; 17165 17166} 17167 17168/** 17169 * Uniforms of a program. 17170 * Those form a tree structure with a special top-level container for the root, 17171 * which you get by calling 'new WebGLUniforms( gl, program )'. 17172 * 17173 * 17174 * Properties of inner nodes including the top-level container: 17175 * 17176 * .seq - array of nested uniforms 17177 * .map - nested uniforms by name 17178 * 17179 * 17180 * Methods of all nodes except the top-level container: 17181 * 17182 * .setValue( gl, value, [textures] ) 17183 * 17184 * uploads a uniform value(s) 17185 * the 'textures' parameter is needed for sampler uniforms 17186 * 17187 * 17188 * Static methods of the top-level container (textures factorizations): 17189 * 17190 * .upload( gl, seq, values, textures ) 17191 * 17192 * sets uniforms in 'seq' to 'values[id].value' 17193 * 17194 * .seqWithValue( seq, values ) : filteredSeq 17195 * 17196 * filters 'seq' entries with corresponding entry in values 17197 * 17198 * 17199 * Methods of the top-level container (textures factorizations): 17200 * 17201 * .setValue( gl, name, value, textures ) 17202 * 17203 * sets uniform with name 'name' to 'value' 17204 * 17205 * .setOptional( gl, obj, prop ) 17206 * 17207 * like .set for an optional property of the object 17208 * 17209 */ 17210 17211const emptyTexture = /*@__PURE__*/ new Texture(); 17212const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture(); 17213const empty3dTexture = /*@__PURE__*/ new Data3DTexture(); 17214const emptyCubeTexture = /*@__PURE__*/ new CubeTexture(); 17215 17216// --- Utilities --- 17217
vendor: 14,818 bytes, lines 17218-18089
17218// Array Caches (provide typed arrays for temporary by size) 17219 17220const arrayCacheF32 = []; 17221const arrayCacheI32 = []; 17222 17223// Float32Array caches used for uploading Matrix uniforms 17224 17225const mat4array = new Float32Array( 16 ); 17226const mat3array = new Float32Array( 9 ); 17227const mat2array = new Float32Array( 4 ); 17228 17229// Flattening for arrays of vectors and matrices 17230 17231function flatten( array, nBlocks, blockSize ) { 17232 17233 const firstElem = array[ 0 ]; 17234 17235 if ( firstElem <= 0 || firstElem > 0 ) return array; 17236 // unoptimized: ! isNaN( firstElem ) 17237 // see http://jacksondunstan.com/articles/983 17238 17239 const n = nBlocks * blockSize; 17240 let r = arrayCacheF32[ n ]; 17241 17242 if ( r === undefined ) { 17243 17244 r = new Float32Array( n ); 17245 arrayCacheF32[ n ] = r; 17246 17247 } 17248 17249 if ( nBlocks !== 0 ) { 17250 17251 firstElem.toArray( r, 0 ); 17252 17253 for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) { 17254 17255 offset += blockSize; 17256 array[ i ].toArray( r, offset ); 17257 17258 } 17259 17260 } 17261 17262 return r; 17263 17264} 17265 17266function arraysEqual( a, b ) { 17267 17268 if ( a.length !== b.length ) return false; 17269 17270 for ( let i = 0, l = a.length; i < l; i ++ ) { 17271 17272 if ( a[ i ] !== b[ i ] ) return false; 17273 17274 } 17275 17276 return true; 17277 17278} 17279 17280function copyArray( a, b ) { 17281 17282 for ( let i = 0, l = b.length; i < l; i ++ ) { 17283 17284 a[ i ] = b[ i ]; 17285 17286 } 17287 17288} 17289 17290// Texture unit allocation 17291 17292function allocTexUnits( textures, n ) { 17293 17294 let r = arrayCacheI32[ n ]; 17295 17296 if ( r === undefined ) { 17297 17298 r = new Int32Array( n ); 17299 arrayCacheI32[ n ] = r; 17300 17301 } 17302 17303 for ( let i = 0; i !== n; ++ i ) { 17304 17305 r[ i ] = textures.allocateTextureUnit(); 17306 17307 } 17308 17309 return r; 17310 17311} 17312 17313// --- Setters --- 17314 17315// Note: Defining these methods externally, because they come in a bunch 17316// and this way their names minify. 17317 17318// Single scalar 17319 17320function setValueV1f( gl, v ) { 17321 17322 const cache = this.cache; 17323 17324 if ( cache[ 0 ] === v ) return; 17325 17326 gl.uniform1f( this.addr, v ); 17327 17328 cache[ 0 ] = v; 17329 17330} 17331 17332// Single float vector (from flat array or THREE.VectorN) 17333 17334function setValueV2f( gl, v ) { 17335 17336 const cache = this.cache; 17337 17338 if ( v.x !== undefined ) { 17339 17340 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 17341 17342 gl.uniform2f( this.addr, v.x, v.y ); 17343 17344 cache[ 0 ] = v.x; 17345 cache[ 1 ] = v.y; 17346 17347 } 17348 17349 } else { 17350 17351 if ( arraysEqual( cache, v ) ) return; 17352 17353 gl.uniform2fv( this.addr, v ); 17354 17355 copyArray( cache, v ); 17356 17357 } 17358 17359} 17360 17361function setValueV3f( gl, v ) { 17362 17363 const cache = this.cache; 17364 17365 if ( v.x !== undefined ) { 17366 17367 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 17368 17369 gl.uniform3f( this.addr, v.x, v.y, v.z ); 17370 17371 cache[ 0 ] = v.x; 17372 cache[ 1 ] = v.y; 17373 cache[ 2 ] = v.z; 17374 17375 } 17376 17377 } else if ( v.r !== undefined ) { 17378 17379 if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) { 17380 17381 gl.uniform3f( this.addr, v.r, v.g, v.b ); 17382 17383 cache[ 0 ] = v.r; 17384 cache[ 1 ] = v.g; 17385 cache[ 2 ] = v.b; 17386 17387 } 17388 17389 } else { 17390 17391 if ( arraysEqual( cache, v ) ) return; 17392 17393 gl.uniform3fv( this.addr, v ); 17394 17395 copyArray( cache, v ); 17396 17397 } 17398 17399} 17400 17401function setValueV4f( gl, v ) { 17402 17403 const cache = this.cache; 17404 17405 if ( v.x !== undefined ) { 17406 17407 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 17408 17409 gl.uniform4f( this.addr, v.x, v.y, v.z, v.w ); 17410 17411 cache[ 0 ] = v.x; 17412 cache[ 1 ] = v.y; 17413 cache[ 2 ] = v.z; 17414 cache[ 3 ] = v.w; 17415 17416 } 17417 17418 } else { 17419 17420 if ( arraysEqual( cache, v ) ) return; 17421 17422 gl.uniform4fv( this.addr, v ); 17423 17424 copyArray( cache, v ); 17425 17426 } 17427 17428} 17429 17430// Single matrix (from flat array or THREE.MatrixN) 17431 17432function setValueM2( gl, v ) { 17433 17434 const cache = this.cache; 17435 const elements = v.elements; 17436 17437 if ( elements === undefined ) { 17438 17439 if ( arraysEqual( cache, v ) ) return; 17440 17441 gl.uniformMatrix2fv( this.addr, false, v ); 17442 17443 copyArray( cache, v ); 17444 17445 } else { 17446 17447 if ( arraysEqual( cache, elements ) ) return; 17448 17449 mat2array.set( elements ); 17450 17451 gl.uniformMatrix2fv( this.addr, false, mat2array ); 17452 17453 copyArray( cache, elements ); 17454 17455 } 17456 17457} 17458 17459function setValueM3( gl, v ) { 17460 17461 const cache = this.cache; 17462 const elements = v.elements; 17463 17464 if ( elements === undefined ) { 17465 17466 if ( arraysEqual( cache, v ) ) return; 17467 17468 gl.uniformMatrix3fv( this.addr, false, v ); 17469 17470 copyArray( cache, v ); 17471 17472 } else { 17473 17474 if ( arraysEqual( cache, elements ) ) return; 17475 17476 mat3array.set( elements ); 17477 17478 gl.uniformMatrix3fv( this.addr, false, mat3array ); 17479 17480 copyArray( cache, elements ); 17481 17482 } 17483 17484} 17485 17486function setValueM4( gl, v ) { 17487 17488 const cache = this.cache; 17489 const elements = v.elements; 17490 17491 if ( elements === undefined ) { 17492 17493 if ( arraysEqual( cache, v ) ) return; 17494 17495 gl.uniformMatrix4fv( this.addr, false, v ); 17496 17497 copyArray( cache, v ); 17498 17499 } else { 17500 17501 if ( arraysEqual( cache, elements ) ) return; 17502 17503 mat4array.set( elements ); 17504 17505 gl.uniformMatrix4fv( this.addr, false, mat4array ); 17506 17507 copyArray( cache, elements ); 17508 17509 } 17510 17511} 17512 17513// Single integer / boolean 17514 17515function setValueV1i( gl, v ) { 17516 17517 const cache = this.cache; 17518 17519 if ( cache[ 0 ] === v ) return; 17520 17521 gl.uniform1i( this.addr, v ); 17522 17523 cache[ 0 ] = v; 17524 17525} 17526 17527// Single integer / boolean vector (from flat array or THREE.VectorN) 17528 17529function setValueV2i( gl, v ) { 17530 17531 const cache = this.cache; 17532 17533 if ( v.x !== undefined ) { 17534 17535 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 17536 17537 gl.uniform2i( this.addr, v.x, v.y ); 17538 17539 cache[ 0 ] = v.x; 17540 cache[ 1 ] = v.y; 17541 17542 } 17543 17544 } else { 17545 17546 if ( arraysEqual( cache, v ) ) return; 17547 17548 gl.uniform2iv( this.addr, v ); 17549 17550 copyArray( cache, v ); 17551 17552 } 17553 17554} 17555 17556function setValueV3i( gl, v ) { 17557 17558 const cache = this.cache; 17559 17560 if ( v.x !== undefined ) { 17561 17562 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 17563 17564 gl.uniform3i( this.addr, v.x, v.y, v.z ); 17565 17566 cache[ 0 ] = v.x; 17567 cache[ 1 ] = v.y; 17568 cache[ 2 ] = v.z; 17569 17570 } 17571 17572 } else { 17573 17574 if ( arraysEqual( cache, v ) ) return; 17575 17576 gl.uniform3iv( this.addr, v ); 17577 17578 copyArray( cache, v ); 17579 17580 } 17581 17582} 17583 17584function setValueV4i( gl, v ) { 17585 17586 const cache = this.cache; 17587 17588 if ( v.x !== undefined ) { 17589 17590 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 17591 17592 gl.uniform4i( this.addr, v.x, v.y, v.z, v.w ); 17593 17594 cache[ 0 ] = v.x; 17595 cache[ 1 ] = v.y; 17596 cache[ 2 ] = v.z; 17597 cache[ 3 ] = v.w; 17598 17599 } 17600 17601 } else { 17602 17603 if ( arraysEqual( cache, v ) ) return; 17604 17605 gl.uniform4iv( this.addr, v ); 17606 17607 copyArray( cache, v ); 17608 17609 } 17610 17611} 17612 17613// Single unsigned integer 17614 17615function setValueV1ui( gl, v ) { 17616 17617 const cache = this.cache; 17618 17619 if ( cache[ 0 ] === v ) return; 17620 17621 gl.uniform1ui( this.addr, v ); 17622 17623 cache[ 0 ] = v; 17624 17625} 17626 17627// Single unsigned integer vector (from flat array or THREE.VectorN) 17628 17629function setValueV2ui( gl, v ) { 17630 17631 const cache = this.cache; 17632 17633 if ( v.x !== undefined ) { 17634 17635 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 17636 17637 gl.uniform2ui( this.addr, v.x, v.y ); 17638 17639 cache[ 0 ] = v.x; 17640 cache[ 1 ] = v.y; 17641 17642 } 17643 17644 } else { 17645 17646 if ( arraysEqual( cache, v ) ) return; 17647 17648 gl.uniform2uiv( this.addr, v ); 17649 17650 copyArray( cache, v ); 17651 17652 } 17653 17654} 17655 17656function setValueV3ui( gl, v ) { 17657 17658 const cache = this.cache; 17659 17660 if ( v.x !== undefined ) { 17661 17662 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 17663 17664 gl.uniform3ui( this.addr, v.x, v.y, v.z ); 17665 17666 cache[ 0 ] = v.x; 17667 cache[ 1 ] = v.y; 17668 cache[ 2 ] = v.z; 17669 17670 } 17671 17672 } else { 17673 17674 if ( arraysEqual( cache, v ) ) return; 17675 17676 gl.uniform3uiv( this.addr, v ); 17677 17678 copyArray( cache, v ); 17679 17680 } 17681 17682} 17683 17684function setValueV4ui( gl, v ) { 17685 17686 const cache = this.cache; 17687 17688 if ( v.x !== undefined ) { 17689 17690 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 17691 17692 gl.uniform4ui( this.addr, v.x, v.y, v.z, v.w ); 17693 17694 cache[ 0 ] = v.x; 17695 cache[ 1 ] = v.y; 17696 cache[ 2 ] = v.z; 17697 cache[ 3 ] = v.w; 17698 17699 } 17700 17701 } else { 17702 17703 if ( arraysEqual( cache, v ) ) return; 17704 17705 gl.uniform4uiv( this.addr, v ); 17706 17707 copyArray( cache, v ); 17708 17709 } 17710 17711} 17712 17713 17714// Single texture (2D / Cube) 17715 17716function setValueT1( gl, v, textures ) { 17717 17718 const cache = this.cache; 17719 const unit = textures.allocateTextureUnit(); 17720 17721 if ( cache[ 0 ] !== unit ) { 17722 17723 gl.uniform1i( this.addr, unit ); 17724 cache[ 0 ] = unit; 17725 17726 } 17727 17728 textures.setTexture2D( v || emptyTexture, unit ); 17729 17730} 17731 17732function setValueT3D1( gl, v, textures ) { 17733 17734 const cache = this.cache; 17735 const unit = textures.allocateTextureUnit(); 17736 17737 if ( cache[ 0 ] !== unit ) { 17738 17739 gl.uniform1i( this.addr, unit ); 17740 cache[ 0 ] = unit; 17741 17742 } 17743 17744 textures.setTexture3D( v || empty3dTexture, unit ); 17745 17746} 17747 17748function setValueT6( gl, v, textures ) { 17749 17750 const cache = this.cache; 17751 const unit = textures.allocateTextureUnit(); 17752 17753 if ( cache[ 0 ] !== unit ) { 17754 17755 gl.uniform1i( this.addr, unit ); 17756 cache[ 0 ] = unit; 17757 17758 } 17759 17760 textures.setTextureCube( v || emptyCubeTexture, unit ); 17761 17762} 17763 17764function setValueT2DArray1( gl, v, textures ) { 17765 17766 const cache = this.cache; 17767 const unit = textures.allocateTextureUnit(); 17768 17769 if ( cache[ 0 ] !== unit ) { 17770 17771 gl.uniform1i( this.addr, unit ); 17772 cache[ 0 ] = unit; 17773 17774 } 17775 17776 textures.setTexture2DArray( v || emptyArrayTexture, unit ); 17777 17778} 17779 17780// Helper to pick the right setter for the singular case 17781 17782function getSingularSetter( type ) { 17783 17784 switch ( type ) { 17785 17786 case 0x1406: return setValueV1f; // FLOAT 17787 case 0x8b50: return setValueV2f; // _VEC2 17788 case 0x8b51: return setValueV3f; // _VEC3 17789 case 0x8b52: return setValueV4f; // _VEC4 17790 17791 case 0x8b5a: return setValueM2; // _MAT2 17792 case 0x8b5b: return setValueM3; // _MAT3 17793 case 0x8b5c: return setValueM4; // _MAT4 17794 17795 case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL 17796 case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2 17797 case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3 17798 case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4 17799 17800 case 0x1405: return setValueV1ui; // UINT 17801 case 0x8dc6: return setValueV2ui; // _VEC2 17802 case 0x8dc7: return setValueV3ui; // _VEC3 17803 case 0x8dc8: return setValueV4ui; // _VEC4 17804 17805 case 0x8b5e: // SAMPLER_2D 17806 case 0x8d66: // SAMPLER_EXTERNAL_OES 17807 case 0x8dca: // INT_SAMPLER_2D 17808 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D 17809 case 0x8b62: // SAMPLER_2D_SHADOW 17810 return setValueT1; 17811 17812 case 0x8b5f: // SAMPLER_3D 17813 case 0x8dcb: // INT_SAMPLER_3D 17814 case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D 17815 return setValueT3D1; 17816 17817 case 0x8b60: // SAMPLER_CUBE 17818 case 0x8dcc: // INT_SAMPLER_CUBE 17819 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE 17820 case 0x8dc5: // SAMPLER_CUBE_SHADOW 17821 return setValueT6; 17822 17823 case 0x8dc1: // SAMPLER_2D_ARRAY 17824 case 0x8dcf: // INT_SAMPLER_2D_ARRAY 17825 case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY 17826 case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW 17827 return setValueT2DArray1; 17828 17829 } 17830 17831} 17832 17833 17834// Array of scalars 17835 17836function setValueV1fArray( gl, v ) { 17837 17838 gl.uniform1fv( this.addr, v ); 17839 17840} 17841 17842// Array of vectors (from flat array or array of THREE.VectorN) 17843 17844function setValueV2fArray( gl, v ) { 17845 17846 const data = flatten( v, this.size, 2 ); 17847 17848 gl.uniform2fv( this.addr, data ); 17849 17850} 17851 17852function setValueV3fArray( gl, v ) { 17853 17854 const data = flatten( v, this.size, 3 ); 17855 17856 gl.uniform3fv( this.addr, data ); 17857 17858} 17859 17860function setValueV4fArray( gl, v ) { 17861 17862 const data = flatten( v, this.size, 4 ); 17863 17864 gl.uniform4fv( this.addr, data ); 17865 17866} 17867 17868// Array of matrices (from flat array or array of THREE.MatrixN) 17869 17870function setValueM2Array( gl, v ) { 17871 17872 const data = flatten( v, this.size, 4 ); 17873 17874 gl.uniformMatrix2fv( this.addr, false, data ); 17875 17876} 17877 17878function setValueM3Array( gl, v ) { 17879 17880 const data = flatten( v, this.size, 9 ); 17881 17882 gl.uniformMatrix3fv( this.addr, false, data ); 17883 17884} 17885 17886function setValueM4Array( gl, v ) { 17887 17888 const data = flatten( v, this.size, 16 ); 17889 17890 gl.uniformMatrix4fv( this.addr, false, data ); 17891 17892} 17893 17894// Array of integer / boolean 17895 17896function setValueV1iArray( gl, v ) { 17897 17898 gl.uniform1iv( this.addr, v ); 17899 17900} 17901 17902// Array of integer / boolean vectors (from flat array) 17903 17904function setValueV2iArray( gl, v ) { 17905 17906 gl.uniform2iv( this.addr, v ); 17907 17908} 17909 17910function setValueV3iArray( gl, v ) { 17911 17912 gl.uniform3iv( this.addr, v ); 17913 17914} 17915 17916function setValueV4iArray( gl, v ) { 17917 17918 gl.uniform4iv( this.addr, v ); 17919 17920} 17921 17922// Array of unsigned integer 17923 17924function setValueV1uiArray( gl, v ) { 17925 17926 gl.uniform1uiv( this.addr, v ); 17927 17928} 17929 17930// Array of unsigned integer vectors (from flat array) 17931 17932function setValueV2uiArray( gl, v ) { 17933 17934 gl.uniform2uiv( this.addr, v ); 17935 17936} 17937 17938function setValueV3uiArray( gl, v ) { 17939 17940 gl.uniform3uiv( this.addr, v ); 17941 17942} 17943 17944function setValueV4uiArray( gl, v ) { 17945 17946 gl.uniform4uiv( this.addr, v ); 17947 17948} 17949 17950 17951// Array of textures (2D / 3D / Cube / 2DArray) 17952 17953function setValueT1Array( gl, v, textures ) { 17954 17955 const cache = this.cache; 17956 17957 const n = v.length; 17958 17959 const units = allocTexUnits( textures, n ); 17960 17961 if ( ! arraysEqual( cache, units ) ) { 17962 17963 gl.uniform1iv( this.addr, units ); 17964 17965 copyArray( cache, units ); 17966 17967 } 17968 17969 for ( let i = 0; i !== n; ++ i ) { 17970 17971 textures.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); 17972 17973 } 17974 17975} 17976 17977function setValueT3DArray( gl, v, textures ) { 17978 17979 const cache = this.cache; 17980 17981 const n = v.length; 17982 17983 const units = allocTexUnits( textures, n ); 17984 17985 if ( ! arraysEqual( cache, units ) ) { 17986 17987 gl.uniform1iv( this.addr, units ); 17988 17989 copyArray( cache, units ); 17990 17991 } 17992 17993 for ( let i = 0; i !== n; ++ i ) { 17994 17995 textures.setTexture3D( v[ i ] || empty3dTexture, units[ i ] ); 17996 17997 } 17998 17999} 18000 18001function setValueT6Array( gl, v, textures ) { 18002 18003 const cache = this.cache; 18004 18005 const n = v.length; 18006 18007 const units = allocTexUnits( textures, n ); 18008 18009 if ( ! arraysEqual( cache, units ) ) { 18010 18011 gl.uniform1iv( this.addr, units ); 18012 18013 copyArray( cache, units ); 18014 18015 } 18016 18017 for ( let i = 0; i !== n; ++ i ) { 18018 18019 textures.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] ); 18020 18021 } 18022 18023} 18024 18025function setValueT2DArrayArray( gl, v, textures ) { 18026 18027 const cache = this.cache; 18028 18029 const n = v.length; 18030 18031 const units = allocTexUnits( textures, n ); 18032 18033 if ( ! arraysEqual( cache, units ) ) { 18034 18035 gl.uniform1iv( this.addr, units ); 18036 18037 copyArray( cache, units ); 18038 18039 } 18040 18041 for ( let i = 0; i !== n; ++ i ) { 18042 18043 textures.setTexture2DArray( v[ i ] || emptyArrayTexture, units[ i ] ); 18044 18045 } 18046 18047} 18048 18049 18050// Helper to pick the right setter for a pure (bottom-level) array 18051 18052function getPureArraySetter( type ) { 18053 18054 switch ( type ) { 18055 18056 case 0x1406: return setValueV1fArray; // FLOAT 18057 case 0x8b50: return setValueV2fArray; // _VEC2 18058 case 0x8b51: return setValueV3fArray; // _VEC3 18059 case 0x8b52: return setValueV4fArray; // _VEC4 18060 18061 case 0x8b5a: return setValueM2Array; // _MAT2 18062 case 0x8b5b: return setValueM3Array; // _MAT3 18063 case 0x8b5c: return setValueM4Array; // _MAT4 18064 18065 case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL 18066 case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2 18067 case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3 18068 case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4 18069 18070 case 0x1405: return setValueV1uiArray; // UINT 18071 case 0x8dc6: return setValueV2uiArray; // _VEC2 18072 case 0x8dc7: return setValueV3uiArray; // _VEC3 18073 case 0x8dc8: return setValueV4uiArray; // _VEC4 18074 18075 case 0x8b5e: // SAMPLER_2D 18076 case 0x8d66: // SAMPLER_EXTERNAL_OES 18077 case 0x8dca: // INT_SAMPLER_2D 18078 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D 18079 case 0x8b62: // SAMPLER_2D_SHADOW 18080 return setValueT1Array; 18081 18082 case 0x8b5f: // SAMPLER_3D 18083 case 0x8dcb: // INT_SAMPLER_3D 18084 case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D 18085 return setValueT3DArray; 18086 18087 case 0x8b60: // SAMPLER_CUBE 18088 case 0x8dcc: // INT_SAMPLER_CUBE 18089 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
vendor: 26,694 bytes, lines 18090-19085
18090 case 0x8dc5: // SAMPLER_CUBE_SHADOW 18091 return setValueT6Array; 18092 18093 case 0x8dc1: // SAMPLER_2D_ARRAY 18094 case 0x8dcf: // INT_SAMPLER_2D_ARRAY 18095 case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY 18096 case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW 18097 return setValueT2DArrayArray; 18098 18099 } 18100 18101} 18102 18103// --- Uniform Classes --- 18104 18105class SingleUniform { 18106 18107 constructor( id, activeInfo, addr ) { 18108 18109 this.id = id; 18110 this.addr = addr; 18111 this.cache = []; 18112 this.setValue = getSingularSetter( activeInfo.type ); 18113 18114 // this.path = activeInfo.name; // DEBUG 18115 18116 } 18117 18118} 18119 18120class PureArrayUniform { 18121 18122 constructor( id, activeInfo, addr ) { 18123 18124 this.id = id; 18125 this.addr = addr; 18126 this.cache = []; 18127 this.size = activeInfo.size; 18128 this.setValue = getPureArraySetter( activeInfo.type ); 18129 18130 // this.path = activeInfo.name; // DEBUG 18131 18132 } 18133 18134} 18135 18136class StructuredUniform { 18137 18138 constructor( id ) { 18139 18140 this.id = id; 18141 18142 this.seq = []; 18143 this.map = {}; 18144 18145 } 18146 18147 setValue( gl, value, textures ) { 18148 18149 const seq = this.seq; 18150 18151 for ( let i = 0, n = seq.length; i !== n; ++ i ) { 18152 18153 const u = seq[ i ]; 18154 u.setValue( gl, value[ u.id ], textures ); 18155 18156 } 18157 18158 } 18159 18160} 18161 18162// --- Top-level --- 18163 18164// Parser - builds up the property tree from the path strings 18165 18166const RePathPart = /(\w+)(\])?(\[|\.)?/g; 18167 18168// extracts 18169// - the identifier (member name or array index) 18170// - followed by an optional right bracket (found when array index) 18171// - followed by an optional left bracket or dot (type of subscript) 18172// 18173// Note: These portions can be read in a non-overlapping fashion and 18174// allow straightforward parsing of the hierarchy that WebGL encodes 18175// in the uniform names. 18176 18177function addUniform( container, uniformObject ) { 18178 18179 container.seq.push( uniformObject ); 18180 container.map[ uniformObject.id ] = uniformObject; 18181 18182} 18183 18184function parseUniform( activeInfo, addr, container ) { 18185 18186 const path = activeInfo.name, 18187 pathLength = path.length; 18188 18189 // reset RegExp object, because of the early exit of a previous run 18190 RePathPart.lastIndex = 0; 18191 18192 while ( true ) { 18193 18194 const match = RePathPart.exec( path ), 18195 matchEnd = RePathPart.lastIndex; 18196 18197 let id = match[ 1 ]; 18198 const idIsIndex = match[ 2 ] === ']', 18199 subscript = match[ 3 ]; 18200 18201 if ( idIsIndex ) id = id | 0; // convert to integer 18202 18203 if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) { 18204 18205 // bare name or "pure" bottom-level array "[0]" suffix 18206 18207 addUniform( container, subscript === undefined ? 18208 new SingleUniform( id, activeInfo, addr ) : 18209 new PureArrayUniform( id, activeInfo, addr ) ); 18210 18211 break; 18212 18213 } else { 18214 18215 // step into inner node / create it in case it doesn't exist 18216 18217 const map = container.map; 18218 let next = map[ id ]; 18219 18220 if ( next === undefined ) { 18221 18222 next = new StructuredUniform( id ); 18223 addUniform( container, next ); 18224 18225 } 18226 18227 container = next; 18228 18229 } 18230 18231 } 18232 18233} 18234 18235// Root Container 18236 18237class WebGLUniforms { 18238 18239 constructor( gl, program ) { 18240 18241 this.seq = []; 18242 this.map = {}; 18243 18244 const n = gl.getProgramParameter( program, 35718 ); 18245 18246 for ( let i = 0; i < n; ++ i ) { 18247 18248 const info = gl.getActiveUniform( program, i ), 18249 addr = gl.getUniformLocation( program, info.name ); 18250 18251 parseUniform( info, addr, this ); 18252 18253 } 18254 18255 } 18256 18257 setValue( gl, name, value, textures ) { 18258 18259 const u = this.map[ name ]; 18260 18261 if ( u !== undefined ) u.setValue( gl, value, textures ); 18262 18263 } 18264 18265 setOptional( gl, object, name ) { 18266 18267 const v = object[ name ]; 18268 18269 if ( v !== undefined ) this.setValue( gl, name, v ); 18270 18271 } 18272 18273 static upload( gl, seq, values, textures ) { 18274 18275 for ( let i = 0, n = seq.length; i !== n; ++ i ) { 18276 18277 const u = seq[ i ], 18278 v = values[ u.id ]; 18279 18280 if ( v.needsUpdate !== false ) { 18281 18282 // note: always updating when .needsUpdate is undefined 18283 u.setValue( gl, v.value, textures ); 18284 18285 } 18286 18287 } 18288 18289 } 18290 18291 static seqWithValue( seq, values ) { 18292 18293 const r = []; 18294 18295 for ( let i = 0, n = seq.length; i !== n; ++ i ) { 18296 18297 const u = seq[ i ]; 18298 if ( u.id in values ) r.push( u ); 18299 18300 } 18301 18302 return r; 18303 18304 } 18305 18306} 18307 18308function WebGLShader( gl, type, string ) { 18309 18310 const shader = gl.createShader( type ); 18311 18312 gl.shaderSource( shader, string ); 18313 gl.compileShader( shader ); 18314 18315 return shader; 18316 18317} 18318 18319let programIdCount = 0; 18320 18321function handleSource( string, errorLine ) { 18322 18323 const lines = string.split( '\n' ); 18324 const lines2 = []; 18325 18326 const from = Math.max( errorLine - 6, 0 ); 18327 const to = Math.min( errorLine + 6, lines.length ); 18328 18329 for ( let i = from; i < to; i ++ ) { 18330 18331 const line = i + 1; 18332 lines2.push( `${line === errorLine ? '>' : ' '} ${line}: ${lines[ i ]}` ); 18333 18334 } 18335 18336 return lines2.join( '\n' ); 18337 18338} 18339 18340function getEncodingComponents( encoding ) { 18341 18342 switch ( encoding ) { 18343 18344 case LinearEncoding: 18345 return [ 'Linear', '( value )' ]; 18346 case sRGBEncoding: 18347 return [ 'sRGB', '( value )' ]; 18348 default: 18349 console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding ); 18350 return [ 'Linear', '( value )' ]; 18351 18352 } 18353 18354} 18355 18356function getShaderErrors( gl, shader, type ) { 18357 18358 const status = gl.getShaderParameter( shader, 35713 ); 18359 const errors = gl.getShaderInfoLog( shader ).trim(); 18360 18361 if ( status && errors === '' ) return ''; 18362 18363 const errorMatches = /ERROR: 0:(\d+)/.exec( errors ); 18364 if ( errorMatches ) { 18365 18366 // --enable-privileged-webgl-extension 18367 // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); 18368 18369 const errorLine = parseInt( errorMatches[ 1 ] ); 18370 return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine ); 18371 18372 } else { 18373 18374 return errors; 18375 18376 } 18377 18378} 18379 18380function getTexelEncodingFunction( functionName, encoding ) { 18381 18382 const components = getEncodingComponents( encoding ); 18383 return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }'; 18384 18385} 18386 18387function getToneMappingFunction( functionName, toneMapping ) { 18388 18389 let toneMappingName; 18390 18391 switch ( toneMapping ) { 18392 18393 case LinearToneMapping: 18394 toneMappingName = 'Linear'; 18395 break; 18396 18397 case ReinhardToneMapping: 18398 toneMappingName = 'Reinhard'; 18399 break; 18400 18401 case CineonToneMapping: 18402 toneMappingName = 'OptimizedCineon'; 18403 break; 18404 18405 case ACESFilmicToneMapping: 18406 toneMappingName = 'ACESFilmic'; 18407 break; 18408 18409 case CustomToneMapping: 18410 toneMappingName = 'Custom'; 18411 break; 18412 18413 default: 18414 console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping ); 18415 toneMappingName = 'Linear'; 18416 18417 } 18418 18419 return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }'; 18420 18421} 18422 18423function generateExtensions( parameters ) { 18424 18425 const chunks = [ 18426 ( parameters.extensionDerivatives || !! parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '', 18427 ( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '', 18428 ( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '', 18429 ( parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : '' 18430 ]; 18431 18432 return chunks.filter( filterEmptyLine ).join( '\n' ); 18433 18434} 18435 18436function generateDefines( defines ) { 18437 18438 const chunks = []; 18439 18440 for ( const name in defines ) { 18441 18442 const value = defines[ name ]; 18443 18444 if ( value === false ) continue; 18445 18446 chunks.push( '#define ' + name + ' ' + value ); 18447 18448 } 18449 18450 return chunks.join( '\n' ); 18451 18452} 18453 18454function fetchAttributeLocations( gl, program ) { 18455 18456 const attributes = {}; 18457 18458 const n = gl.getProgramParameter( program, 35721 ); 18459 18460 for ( let i = 0; i < n; i ++ ) { 18461 18462 const info = gl.getActiveAttrib( program, i ); 18463 const name = info.name; 18464 18465 let locationSize = 1; 18466 if ( info.type === 35674 ) locationSize = 2; 18467 if ( info.type === 35675 ) locationSize = 3; 18468 if ( info.type === 35676 ) locationSize = 4; 18469 18470 // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); 18471 18472 attributes[ name ] = { 18473 type: info.type, 18474 location: gl.getAttribLocation( program, name ), 18475 locationSize: locationSize 18476 }; 18477 18478 } 18479 18480 return attributes; 18481 18482} 18483 18484function filterEmptyLine( string ) { 18485 18486 return string !== ''; 18487 18488} 18489 18490function replaceLightNums( string, parameters ) { 18491 18492 const numSpotLightCoords = parameters.numSpotLightShadows + parameters.numSpotLightMaps - parameters.numSpotLightShadowsWithMaps; 18493 18494 return string 18495 .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights ) 18496 .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights ) 18497 .replace( /NUM_SPOT_LIGHT_MAPS/g, parameters.numSpotLightMaps ) 18498 .replace( /NUM_SPOT_LIGHT_COORDS/g, numSpotLightCoords ) 18499 .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights ) 18500 .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights ) 18501 .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights ) 18502 .replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows ) 18503 .replace( /NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g, parameters.numSpotLightShadowsWithMaps ) 18504 .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows ) 18505 .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows ); 18506 18507} 18508 18509function replaceClippingPlaneNums( string, parameters ) { 18510 18511 return string 18512 .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes ) 18513 .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) ); 18514 18515} 18516 18517// Resolve Includes 18518 18519const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm; 18520 18521function resolveIncludes( string ) { 18522 18523 return string.replace( includePattern, includeReplacer ); 18524 18525} 18526 18527function includeReplacer( match, include ) { 18528 18529 const string = ShaderChunk[ include ]; 18530 18531 if ( string === undefined ) { 18532 18533 throw new Error( 'Can not resolve #include <' + include + '>' ); 18534 18535 } 18536 18537 return resolveIncludes( string ); 18538 18539} 18540 18541// Unroll Loops 18542 18543const unrollLoopPattern = /#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g; 18544 18545function unrollLoops( string ) { 18546 18547 return string.replace( unrollLoopPattern, loopReplacer ); 18548 18549} 18550 18551function loopReplacer( match, start, end, snippet ) { 18552 18553 let string = ''; 18554 18555 for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) { 18556 18557 string += snippet 18558 .replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' ) 18559 .replace( /UNROLLED_LOOP_INDEX/g, i ); 18560 18561 } 18562 18563 return string; 18564 18565} 18566 18567// 18568 18569function generatePrecision( parameters ) { 18570 18571 let precisionstring = 'precision ' + parameters.precision + ' float;\nprecision ' + parameters.precision + ' int;'; 18572 18573 if ( parameters.precision === 'highp' ) { 18574 18575 precisionstring += '\n#define HIGH_PRECISION'; 18576 18577 } else if ( parameters.precision === 'mediump' ) { 18578 18579 precisionstring += '\n#define MEDIUM_PRECISION'; 18580 18581 } else if ( parameters.precision === 'lowp' ) { 18582 18583 precisionstring += '\n#define LOW_PRECISION'; 18584 18585 } 18586 18587 return precisionstring; 18588 18589} 18590 18591function generateShadowMapTypeDefine( parameters ) { 18592 18593 let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; 18594 18595 if ( parameters.shadowMapType === PCFShadowMap ) { 18596 18597 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; 18598 18599 } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { 18600 18601 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; 18602 18603 } else if ( parameters.shadowMapType === VSMShadowMap ) { 18604 18605 shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM'; 18606 18607 } 18608 18609 return shadowMapTypeDefine; 18610 18611} 18612 18613function generateEnvMapTypeDefine( parameters ) { 18614 18615 let envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; 18616 18617 if ( parameters.envMap ) { 18618 18619 switch ( parameters.envMapMode ) { 18620 18621 case CubeReflectionMapping: 18622 case CubeRefractionMapping: 18623 envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; 18624 break; 18625 18626 case CubeUVReflectionMapping: 18627 envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; 18628 break; 18629 18630 } 18631 18632 } 18633 18634 return envMapTypeDefine; 18635 18636} 18637 18638function generateEnvMapModeDefine( parameters ) { 18639 18640 let envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; 18641 18642 if ( parameters.envMap ) { 18643 18644 switch ( parameters.envMapMode ) { 18645 18646 case CubeRefractionMapping: 18647 18648 envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; 18649 break; 18650 18651 } 18652 18653 } 18654 18655 return envMapModeDefine; 18656 18657} 18658 18659function generateEnvMapBlendingDefine( parameters ) { 18660 18661 let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE'; 18662 18663 if ( parameters.envMap ) { 18664 18665 switch ( parameters.combine ) { 18666 18667 case MultiplyOperation: 18668 envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; 18669 break; 18670 18671 case MixOperation: 18672 envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; 18673 break; 18674 18675 case AddOperation: 18676 envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; 18677 break; 18678 18679 } 18680 18681 } 18682 18683 return envMapBlendingDefine; 18684 18685} 18686 18687function generateCubeUVSize( parameters ) { 18688 18689 const imageHeight = parameters.envMapCubeUVHeight; 18690 18691 if ( imageHeight === null ) return null; 18692 18693 const maxMip = Math.log2( imageHeight ) - 2; 18694 18695 const texelHeight = 1.0 / imageHeight; 18696 18697 const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) ); 18698 18699 return { texelWidth, texelHeight, maxMip }; 18700 18701} 18702 18703function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { 18704 18705 // TODO Send this event to Three.js DevTools 18706 // console.log( 'WebGLProgram', cacheKey ); 18707 18708 const gl = renderer.getContext(); 18709 18710 const defines = parameters.defines; 18711 18712 let vertexShader = parameters.vertexShader; 18713 let fragmentShader = parameters.fragmentShader; 18714 18715 const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters ); 18716 const envMapTypeDefine = generateEnvMapTypeDefine( parameters ); 18717 const envMapModeDefine = generateEnvMapModeDefine( parameters ); 18718 const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters ); 18719 const envMapCubeUVSize = generateCubeUVSize( parameters ); 18720 18721 const customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters ); 18722 18723 const customDefines = generateDefines( defines ); 18724 18725 const program = gl.createProgram(); 18726 18727 let prefixVertex, prefixFragment; 18728 let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : ''; 18729 18730 if ( parameters.isRawShaderMaterial ) { 18731 18732 prefixVertex = [ 18733 18734 customDefines 18735 18736 ].filter( filterEmptyLine ).join( '\n' ); 18737 18738 if ( prefixVertex.length > 0 ) { 18739 18740 prefixVertex += '\n'; 18741 18742 } 18743 18744 prefixFragment = [ 18745 18746 customExtensions, 18747 customDefines 18748 18749 ].filter( filterEmptyLine ).join( '\n' ); 18750 18751 if ( prefixFragment.length > 0 ) { 18752 18753 prefixFragment += '\n'; 18754 18755 } 18756 18757 } else { 18758 18759 prefixVertex = [ 18760 18761 generatePrecision( parameters ), 18762 18763 '#define SHADER_NAME ' + parameters.shaderName, 18764 18765 customDefines, 18766 18767 parameters.instancing ? '#define USE_INSTANCING' : '', 18768 parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', 18769 18770 parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', 18771 18772 ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', 18773 ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', 18774 18775 parameters.map ? '#define USE_MAP' : '', 18776 parameters.envMap ? '#define USE_ENVMAP' : '', 18777 parameters.envMap ? '#define ' + envMapModeDefine : '', 18778 parameters.lightMap ? '#define USE_LIGHTMAP' : '', 18779 parameters.aoMap ? '#define USE_AOMAP' : '', 18780 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', 18781 parameters.bumpMap ? '#define USE_BUMPMAP' : '', 18782 parameters.normalMap ? '#define USE_NORMALMAP' : '', 18783 ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '', 18784 ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '', 18785 18786 parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', 18787 parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', 18788 parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', 18789 18790 parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', 18791 parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', 18792 18793 parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', 18794 18795 parameters.specularMap ? '#define USE_SPECULARMAP' : '', 18796 parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', 18797 parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', 18798 18799 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', 18800 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', 18801 parameters.alphaMap ? '#define USE_ALPHAMAP' : '', 18802 18803 parameters.transmission ? '#define USE_TRANSMISSION' : '', 18804 parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', 18805 parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', 18806 18807 parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', 18808 parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', 18809 18810 parameters.vertexTangents ? '#define USE_TANGENT' : '', 18811 parameters.vertexColors ? '#define USE_COLOR' : '', 18812 parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', 18813 parameters.vertexUvs ? '#define USE_UV' : '', 18814 parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', 18815 18816 parameters.flatShading ? '#define FLAT_SHADED' : '', 18817 18818 parameters.skinning ? '#define USE_SKINNING' : '', 18819 18820 parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', 18821 parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', 18822 ( parameters.morphColors && parameters.isWebGL2 ) ? '#define USE_MORPHCOLORS' : '', 18823 ( parameters.morphTargetsCount > 0 && parameters.isWebGL2 ) ? '#define MORPHTARGETS_TEXTURE' : '', 18824 ( parameters.morphTargetsCount > 0 && parameters.isWebGL2 ) ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '', 18825 ( parameters.morphTargetsCount > 0 && parameters.isWebGL2 ) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '', 18826 parameters.doubleSided ? '#define DOUBLE_SIDED' : '', 18827 parameters.flipSided ? '#define FLIP_SIDED' : '', 18828 18829 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', 18830 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', 18831 18832 parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', 18833 18834 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', 18835 ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '', 18836 18837 'uniform mat4 modelMatrix;', 18838 'uniform mat4 modelViewMatrix;', 18839 'uniform mat4 projectionMatrix;', 18840 'uniform mat4 viewMatrix;', 18841 'uniform mat3 normalMatrix;', 18842 'uniform vec3 cameraPosition;', 18843 'uniform bool isOrthographic;', 18844 18845 '#ifdef USE_INSTANCING', 18846 18847 ' attribute mat4 instanceMatrix;', 18848 18849 '#endif', 18850 18851 '#ifdef USE_INSTANCING_COLOR', 18852 18853 ' attribute vec3 instanceColor;', 18854 18855 '#endif', 18856 18857 'attribute vec3 position;', 18858 'attribute vec3 normal;', 18859 'attribute vec2 uv;', 18860 18861 '#ifdef USE_TANGENT', 18862 18863 ' attribute vec4 tangent;', 18864 18865 '#endif', 18866 18867 '#if defined( USE_COLOR_ALPHA )', 18868 18869 ' attribute vec4 color;', 18870 18871 '#elif defined( USE_COLOR )', 18872 18873 ' attribute vec3 color;', 18874 18875 '#endif', 18876 18877 '#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )', 18878 18879 ' attribute vec3 morphTarget0;', 18880 ' attribute vec3 morphTarget1;', 18881 ' attribute vec3 morphTarget2;', 18882 ' attribute vec3 morphTarget3;', 18883 18884 ' #ifdef USE_MORPHNORMALS', 18885 18886 ' attribute vec3 morphNormal0;', 18887 ' attribute vec3 morphNormal1;', 18888 ' attribute vec3 morphNormal2;', 18889 ' attribute vec3 morphNormal3;', 18890 18891 ' #else', 18892 18893 ' attribute vec3 morphTarget4;', 18894 ' attribute vec3 morphTarget5;', 18895 ' attribute vec3 morphTarget6;', 18896 ' attribute vec3 morphTarget7;', 18897 18898 ' #endif', 18899 18900 '#endif', 18901 18902 '#ifdef USE_SKINNING', 18903 18904 ' attribute vec4 skinIndex;', 18905 ' attribute vec4 skinWeight;', 18906 18907 '#endif', 18908 18909 '\n' 18910 18911 ].filter( filterEmptyLine ).join( '\n' ); 18912 18913 prefixFragment = [ 18914 18915 customExtensions, 18916 18917 generatePrecision( parameters ), 18918 18919 '#define SHADER_NAME ' + parameters.shaderName, 18920 18921 customDefines, 18922 18923 ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', 18924 ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', 18925 18926 parameters.map ? '#define USE_MAP' : '', 18927 parameters.matcap ? '#define USE_MATCAP' : '', 18928 parameters.envMap ? '#define USE_ENVMAP' : '', 18929 parameters.envMap ? '#define ' + envMapTypeDefine : '', 18930 parameters.envMap ? '#define ' + envMapModeDefine : '', 18931 parameters.envMap ? '#define ' + envMapBlendingDefine : '', 18932 envMapCubeUVSize ? '#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth : '', 18933 envMapCubeUVSize ? '#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight : '', 18934 envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '', 18935 parameters.lightMap ? '#define USE_LIGHTMAP' : '', 18936 parameters.aoMap ? '#define USE_AOMAP' : '', 18937 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', 18938 parameters.bumpMap ? '#define USE_BUMPMAP' : '', 18939 parameters.normalMap ? '#define USE_NORMALMAP' : '', 18940 ( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '', 18941 ( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '', 18942 18943 parameters.clearcoat ? '#define USE_CLEARCOAT' : '', 18944 parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', 18945 parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', 18946 parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', 18947 18948 parameters.iridescence ? '#define USE_IRIDESCENCE' : '', 18949 parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', 18950 parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', 18951 18952 parameters.specularMap ? '#define USE_SPECULARMAP' : '', 18953 parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '', 18954 parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '', 18955 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', 18956 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', 18957 18958 parameters.alphaMap ? '#define USE_ALPHAMAP' : '', 18959 parameters.alphaTest ? '#define USE_ALPHATEST' : '', 18960 18961 parameters.sheen ? '#define USE_SHEEN' : '', 18962 parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '', 18963 parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '', 18964 18965 parameters.transmission ? '#define USE_TRANSMISSION' : '', 18966 parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', 18967 parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', 18968 18969 parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', 18970 18971 parameters.vertexTangents ? '#define USE_TANGENT' : '', 18972 parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', 18973 parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', 18974 parameters.vertexUvs ? '#define USE_UV' : '', 18975 parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '', 18976 18977 parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', 18978 18979 parameters.flatShading ? '#define FLAT_SHADED' : '', 18980 18981 parameters.doubleSided ? '#define DOUBLE_SIDED' : '', 18982 parameters.flipSided ? '#define FLIP_SIDED' : '', 18983 18984 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', 18985 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', 18986 18987 parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', 18988 18989 parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', 18990 18991 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', 18992 ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '', 18993 18994 'uniform mat4 viewMatrix;', 18995 'uniform vec3 cameraPosition;', 18996 'uniform bool isOrthographic;', 18997 18998 ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '', 18999 ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below 19000 ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '', 19001 19002 parameters.dithering ? '#define DITHERING' : '', 19003 parameters.opaque ? '#define OPAQUE' : '', 19004 19005 ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below 19006 getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ), 19007 19008 parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', 19009 19010 '\n' 19011 19012 ].filter( filterEmptyLine ).join( '\n' ); 19013 19014 } 19015 19016 vertexShader = resolveIncludes( vertexShader ); 19017 vertexShader = replaceLightNums( vertexShader, parameters ); 19018 vertexShader = replaceClippingPlaneNums( vertexShader, parameters ); 19019 19020 fragmentShader = resolveIncludes( fragmentShader ); 19021 fragmentShader = replaceLightNums( fragmentShader, parameters ); 19022 fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters ); 19023 19024 vertexShader = unrollLoops( vertexShader ); 19025 fragmentShader = unrollLoops( fragmentShader ); 19026 19027 if ( parameters.isWebGL2 && parameters.isRawShaderMaterial !== true ) { 19028 19029 // GLSL 3.0 conversion for built-in materials and ShaderMaterial 19030 19031 versionString = '#version 300 es\n'; 19032 19033 prefixVertex = [ 19034 'precision mediump sampler2DArray;', 19035 '#define attribute in', 19036 '#define varying out', 19037 '#define texture2D texture' 19038 ].join( '\n' ) + '\n' + prefixVertex; 19039 19040 prefixFragment = [ 19041 '#define varying in', 19042 ( parameters.glslVersion === GLSL3 ) ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;', 19043 ( parameters.glslVersion === GLSL3 ) ? '' : '#define gl_FragColor pc_fragColor', 19044 '#define gl_FragDepthEXT gl_FragDepth', 19045 '#define texture2D texture', 19046 '#define textureCube texture', 19047 '#define texture2DProj textureProj', 19048 '#define texture2DLodEXT textureLod', 19049 '#define texture2DProjLodEXT textureProjLod', 19050 '#define textureCubeLodEXT textureLod', 19051 '#define texture2DGradEXT textureGrad', 19052 '#define texture2DProjGradEXT textureProjGrad', 19053 '#define textureCubeGradEXT textureGrad' 19054 ].join( '\n' ) + '\n' + prefixFragment; 19055 19056 } 19057 19058 const vertexGlsl = versionString + prefixVertex + vertexShader; 19059 const fragmentGlsl = versionString + prefixFragment + fragmentShader; 19060 19061 // console.log( '*VERTEX*', vertexGlsl ); 19062 // console.log( '*FRAGMENT*', fragmentGlsl ); 19063 19064 const glVertexShader = WebGLShader( gl, 35633, vertexGlsl ); 19065 const glFragmentShader = WebGLShader( gl, 35632, fragmentGlsl ); 19066 19067 gl.attachShader( program, glVertexShader ); 19068 gl.attachShader( program, glFragmentShader ); 19069 19070 // Force a particular attribute to index 0. 19071 19072 if ( parameters.index0AttributeName !== undefined ) { 19073 19074 gl.bindAttribLocation( program, 0, parameters.index0AttributeName ); 19075 19076 } else if ( parameters.morphTargets === true ) { 19077 19078 // programs with morphTargets displace position out of attribute 0 19079 gl.bindAttribLocation( program, 0, 'position' ); 19080 19081 } 19082 19083 gl.linkProgram( program ); 19084 19085 // check for link errors
19086 if ( renderer.debug.checkShaderErrors ) { 19087 19088 const programLog = gl.getProgramInfoLog( program ).trim(); 19089 const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim(); 19090 const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim(); 19091 19092 let runnable = true; 19093 let haveDiagnostics = true; 19094 19095 if ( gl.getProgramParameter( program, 35714 ) === false ) { 19096 19097 runnable = false; 19098 19099 const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); 19100 const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); 19101 19102 console.error( 19103 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + 19104 'VALIDATE_STATUS ' + gl.getProgramParameter( program, 35715 ) + '\n\n' + 19105 'Program Info Log: ' + programLog + '\n' + 19106 vertexErrors + '\n' + 19107 fragmentErrors 19108 ); 19109 19110 } else if ( programLog !== '' ) { 19111 19112 console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog ); 19113 19114 } else if ( vertexLog === '' || fragmentLog === '' ) { 19115 19116 haveDiagnostics = false; 19117 19118 } 19119 19120 if ( haveDiagnostics ) { 19121 19122 this.diagnostics = { 19123 19124 runnable: runnable, 19125 19126 programLog: programLog, 19127 19128 vertexShader: { 19129 19130 log: vertexLog, 19131 prefix: prefixVertex 19132 19133 }, 19134 19135 fragmentShader: { 19136 19137 log: fragmentLog, 19138 prefix: prefixFragment 19139 19140 } 19141 19142 }; 19143 19144 } 19145 19146 } 19147 19148 // Clean up 19149 19150 // Crashes in iOS9 and iOS10. #18402 19151 // gl.detachShader( program, glVertexShader ); 19152 // gl.detachShader( program, glFragmentShader ); 19153 19154 gl.deleteShader( glVertexShader ); 19155 gl.deleteShader( glFragmentShader ); 19156 19157 // set up caching for uniform locations 19158 19159 let cachedUniforms; 19160 19161 this.getUniforms = function () { 19162 19163 if ( cachedUniforms === undefined ) { 19164 19165 cachedUniforms = new WebGLUniforms( gl, program ); 19166 19167 } 19168 19169 return cachedUniforms; 19170 19171 }; 19172 19173 // set up caching for attribute locations 19174 19175 let cachedAttributes; 19176 19177 this.getAttributes = function () { 19178 19179 if ( cachedAttributes === undefined ) { 19180 19181 cachedAttributes = fetchAttributeLocations( gl, program ); 19182 19183 } 19184 19185 return cachedAttributes; 19186 19187 }; 19188 19189 // free resource 19190 19191 this.destroy = function () { 19192 19193 bindingStates.releaseStatesOfProgram( this ); 19194 19195 gl.deleteProgram( program ); 19196 this.program = undefined; 19197 19198 }; 19199 19200 // 19201 19202 this.name = parameters.shaderName; 19203 this.id = programIdCount ++; 19204 this.cacheKey = cacheKey; 19205 this.usedTimes = 1; 19206 this.program = program; 19207 this.vertexShader = glVertexShader; 19208 this.fragmentShader = glFragmentShader; 19209 19210 return this; 19211 19212} 19213 19214let _id = 0; 19215 19216class WebGLShaderCache { 19217 19218 constructor() { 19219 19220 this.shaderCache = new Map(); 19221 this.materialCache = new Map(); 19222 19223 } 19224 19225 update( material ) { 19226 19227 const vertexShader = material.vertexShader; 19228 const fragmentShader = material.fragmentShader; 19229 19230 const vertexShaderStage = this._getShaderStage( vertexShader ); 19231 const fragmentShaderStage = this._getShaderStage( fragmentShader ); 19232 19233 const materialShaders = this._getShaderCacheForMaterial( material ); 19234 19235 if ( materialShaders.has( vertexShaderStage ) === false ) { 19236 19237 materialShaders.add( vertexShaderStage ); 19238 vertexShaderStage.usedTimes ++; 19239 19240 } 19241 19242 if ( materialShaders.has( fragmentShaderStage ) === false ) { 19243 19244 materialShaders.add( fragmentShaderStage ); 19245 fragmentShaderStage.usedTimes ++; 19246 19247 } 19248 19249 return this; 19250 19251 } 19252 19253 remove( material ) { 19254 19255 const materialShaders = this.materialCache.get( material ); 19256 19257 for ( const shaderStage of materialShaders ) { 19258 19259 shaderStage.usedTimes --; 19260 19261 if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage.code ); 19262 19263 } 19264 19265 this.materialCache.delete( material ); 19266 19267 return this; 19268 19269 } 19270 19271 getVertexShaderID( material ) { 19272 19273 return this._getShaderStage( material.vertexShader ).id; 19274 19275 } 19276 19277 getFragmentShaderID( material ) { 19278 19279 return this._getShaderStage( material.fragmentShader ).id; 19280 19281 } 19282 19283 dispose() { 19284 19285 this.shaderCache.clear(); 19286 this.materialCache.clear(); 19287 19288 } 19289 19290 _getShaderCacheForMaterial( material ) { 19291 19292 const cache = this.materialCache; 19293 let set = cache.get( material ); 19294 19295 if ( set === undefined ) { 19296 19297 set = new Set(); 19298 cache.set( material, set ); 19299 19300 } 19301 19302 return set; 19303 19304 } 19305 19306 _getShaderStage( code ) { 19307 19308 const cache = this.shaderCache;
19309 let stage = cache.get( code ); 19310 19311 if ( stage === undefined ) { 19312 19313 stage = new WebGLShaderStage( code ); 19314 cache.set( code, stage ); 19315 19316 } 19317 19318 return stage; 19319 19320 } 19321 19322} 19323 19324class WebGLShaderStage { 19325 19326 constructor( code ) { 19327 19328 this.id = _id ++; 19329 19330 this.code = code; 19331 this.usedTimes = 0; 19332 19333 } 19334 19335} 19336 19337function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) { 19338 19339 const _programLayers = new Layers(); 19340 const _customShaders = new WebGLShaderCache(); 19341 const programs = []; 19342 19343 const isWebGL2 = capabilities.isWebGL2; 19344 const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; 19345 const vertexTextures = capabilities.vertexTextures; 19346 let precision = capabilities.precision; 19347 19348 const shaderIDs = { 19349 MeshDepthMaterial: 'depth', 19350 MeshDistanceMaterial: 'distanceRGBA', 19351 MeshNormalMaterial: 'normal', 19352 MeshBasicMaterial: 'basic', 19353 MeshLambertMaterial: 'lambert', 19354 MeshPhongMaterial: 'phong', 19355 MeshToonMaterial: 'toon', 19356 MeshStandardMaterial: 'physical', 19357 MeshPhysicalMaterial: 'physical', 19358 MeshMatcapMaterial: 'matcap', 19359 LineBasicMaterial: 'basic', 19360 LineDashedMaterial: 'dashed', 19361 PointsMaterial: 'points', 19362 ShadowMaterial: 'shadow', 19363 SpriteMaterial: 'sprite' 19364 }; 19365 19366 function getParameters( material, lights, shadows, scene, object ) { 19367 19368 const fog = scene.fog; 19369 const geometry = object.geometry; 19370 const environment = material.isMeshStandardMaterial ? scene.environment : null; 19371 19372 const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); 19373 const envMapCubeUVHeight = ( !! envMap ) && ( envMap.mapping === CubeUVReflectionMapping ) ? envMap.image.height : null; 19374 19375 const shaderID = shaderIDs[ material.type ]; 19376 19377 // heuristics to create shader parameters according to lights in the scene 19378 // (not to blow over maxLights budget) 19379 19380 if ( material.precision !== null ) { 19381 19382 precision = capabilities.getMaxPrecision( material.precision ); 19383 19384 if ( precision !== material.precision ) { 19385 19386 console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); 19387 19388 } 19389 19390 } 19391 19392 // 19393 19394 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; 19395 const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; 19396 19397 let morphTextureStride = 0; 19398 19399 if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 1; 19400 if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 2; 19401 if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 3; 19402 19403 // 19404 19405 let vertexShader, fragmentShader; 19406 let customVertexShaderID, customFragmentShaderID; 19407 19408 if ( shaderID ) { 19409 19410 const shader = ShaderLib[ shaderID ]; 19411 19412 vertexShader = shader.vertexShader; 19413 fragmentShader = shader.fragmentShader; 19414 19415 } else { 19416 19417 vertexShader = material.vertexShader; 19418 fragmentShader = material.fragmentShader; 19419 19420 _customShaders.update( material ); 19421 19422 customVertexShaderID = _customShaders.getVertexShaderID( material ); 19423 customFragmentShaderID = _customShaders.getFragmentShaderID( material ); 19424 19425 } 19426 19427 const currentRenderTarget = renderer.getRenderTarget(); 19428 19429 const useAlphaTest = material.alphaTest > 0; 19430 const useClearcoat = material.clearcoat > 0; 19431 const useIridescence = material.iridescence > 0; 19432 19433 const parameters = { 19434 19435 isWebGL2: isWebGL2, 19436 19437 shaderID: shaderID, 19438 shaderName: material.type, 19439 19440 vertexShader: vertexShader, 19441 fragmentShader: fragmentShader, 19442 defines: material.defines, 19443 19444 customVertexShaderID: customVertexShaderID, 19445 customFragmentShaderID: customFragmentShaderID, 19446 19447 isRawShaderMaterial: material.isRawShaderMaterial === true, 19448 glslVersion: material.glslVersion, 19449 19450 precision: precision, 19451 19452 instancing: object.isInstancedMesh === true, 19453 instancingColor: object.isInstancedMesh === true && object.instanceColor !== null, 19454 19455 supportsVertexTextures: vertexTextures, 19456 outputEncoding: ( currentRenderTarget === null ) ? renderer.outputEncoding : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding ), 19457 map: !! material.map, 19458 matcap: !! material.matcap, 19459 envMap: !! envMap, 19460 envMapMode: envMap && envMap.mapping, 19461 envMapCubeUVHeight: envMapCubeUVHeight, 19462 lightMap: !! material.lightMap, 19463 aoMap: !! material.aoMap, 19464 emissiveMap: !! material.emissiveMap, 19465 bumpMap: !! material.bumpMap, 19466 normalMap: !! material.normalMap, 19467 objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap, 19468 tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap, 19469 19470 decodeVideoTexture: !! material.map && ( material.map.isVideoTexture === true ) && ( material.map.encoding === sRGBEncoding ), 19471 19472 clearcoat: useClearcoat, 19473 clearcoatMap: useClearcoat && !! material.clearcoatMap, 19474 clearcoatRoughnessMap: useClearcoat && !! material.clearcoatRoughnessMap, 19475 clearcoatNormalMap: useClearcoat && !! material.clearcoatNormalMap, 19476 19477 iridescence: useIridescence, 19478 iridescenceMap: useIridescence && !! material.iridescenceMap, 19479 iridescenceThicknessMap: useIridescence && !! material.iridescenceThicknessMap, 19480 19481 displacementMap: !! material.displacementMap, 19482 roughnessMap: !! material.roughnessMap, 19483 metalnessMap: !! material.metalnessMap, 19484 specularMap: !! material.specularMap, 19485 specularIntensityMap: !! material.specularIntensityMap, 19486 specularColorMap: !! material.specularColorMap, 19487 19488 opaque: material.transparent === false && material.blending === NormalBlending, 19489 19490 alphaMap: !! material.alphaMap, 19491 alphaTest: useAlphaTest, 19492 19493 gradientMap: !! material.gradientMap, 19494 19495 sheen: material.sheen > 0, 19496 sheenColorMap: !! material.sheenColorMap, 19497 sheenRoughnessMap: !! material.sheenRoughnessMap, 19498 19499 transmission: material.transmission > 0, 19500 transmissionMap: !! material.transmissionMap, 19501 thicknessMap: !! material.thicknessMap, 19502 19503 combine: material.combine, 19504 19505 vertexTangents: ( !! material.normalMap && !! geometry.attributes.tangent ), 19506 vertexColors: material.vertexColors, 19507 vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4, 19508 vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.iridescenceMap || !! material.iridescenceThicknessMap || !! material.displacementMap || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || !! material.sheenColorMap || !! material.sheenRoughnessMap, 19509 uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.iridescenceMap || !! material.iridescenceThicknessMap || material.transmission > 0 || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || material.sheen > 0 || !! material.sheenColorMap || !! material.sheenRoughnessMap ) && !! material.displacementMap, 19510 19511 fog: !! fog, 19512 useFog: material.fog === true, 19513 fogExp2: ( fog && fog.isFogExp2 ), 19514 19515 flatShading: !! material.flatShading, 19516 19517 sizeAttenuation: material.sizeAttenuation, 19518 logarithmicDepthBuffer: logarithmicDepthBuffer, 19519 19520 skinning: object.isSkinnedMesh === true, 19521 19522 morphTargets: geometry.morphAttributes.position !== undefined, 19523 morphNormals: geometry.morphAttributes.normal !== undefined, 19524 morphColors: geometry.morphAttributes.color !== undefined, 19525 morphTargetsCount: morphTargetsCount, 19526 morphTextureStride: morphTextureStride, 19527 19528 numDirLights: lights.directional.length, 19529 numPointLights: lights.point.length, 19530 numSpotLights: lights.spot.length, 19531 numSpotLightMaps: lights.spotLightMap.length, 19532 numRectAreaLights: lights.rectArea.length, 19533 numHemiLights: lights.hemi.length, 19534 19535 numDirLightShadows: lights.directionalShadowMap.length, 19536 numPointLightShadows: lights.pointShadowMap.length, 19537 numSpotLightShadows: lights.spotShadowMap.length, 19538 numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps, 19539 19540 numClippingPlanes: clipping.numPlanes, 19541 numClipIntersection: clipping.numIntersection, 19542 19543 dithering: material.dithering, 19544 19545 shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0, 19546 shadowMapType: renderer.shadowMap.type, 19547 19548 toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping, 19549 useLegacyLights: renderer.useLegacyLights, 19550 19551 premultipliedAlpha: material.premultipliedAlpha, 19552 19553 doubleSided: material.side === DoubleSide, 19554 flipSided: material.side === BackSide, 19555 19556 useDepthPacking: !! material.depthPacking, 19557 depthPacking: material.depthPacking || 0, 19558 19559 index0AttributeName: material.index0AttributeName, 19560 19561 extensionDerivatives: material.extensions && material.extensions.derivatives, 19562 extensionFragDepth: material.extensions && material.extensions.fragDepth, 19563 extensionDrawBuffers: material.extensions && material.extensions.drawBuffers, 19564 extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD, 19565 19566 rendererExtensionFragDepth: isWebGL2 || extensions.has( 'EXT_frag_depth' ), 19567 rendererExtensionDrawBuffers: isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ), 19568 rendererExtensionShaderTextureLod: isWebGL2 || extensions.has( 'EXT_shader_texture_lod' ), 19569 19570 customProgramCacheKey: material.customProgramCacheKey() 19571 19572 }; 19573 19574 return parameters; 19575 19576 } 19577 19578 function getProgramCacheKey( parameters ) { 19579 19580 const array = []; 19581 19582 if ( parameters.shaderID ) { 19583 19584 array.push( parameters.shaderID ); 19585 19586 } else { 19587 19588 array.push( parameters.customVertexShaderID ); 19589 array.push( parameters.customFragmentShaderID ); 19590 19591 } 19592 19593 if ( parameters.defines !== undefined ) { 19594 19595 for ( const name in parameters.defines ) { 19596 19597 array.push( name ); 19598 array.push( parameters.defines[ name ] ); 19599 19600 } 19601 19602 } 19603 19604 if ( parameters.isRawShaderMaterial === false ) { 19605 19606 getProgramCacheKeyParameters( array, parameters ); 19607 getProgramCacheKeyBooleans( array, parameters ); 19608 array.push( renderer.outputEncoding ); 19609 19610 } 19611 19612 array.push( parameters.customProgramCacheKey ); 19613 19614 return array.join(); 19615 19616 } 19617 19618 function getProgramCacheKeyParameters( array, parameters ) { 19619 19620 array.push( parameters.precision ); 19621 array.push( parameters.outputEncoding ); 19622 array.push( parameters.envMapMode ); 19623 array.push( parameters.envMapCubeUVHeight ); 19624 array.push( parameters.combine ); 19625 array.push( parameters.vertexUvs ); 19626 array.push( parameters.fogExp2 ); 19627 array.push( parameters.sizeAttenuation ); 19628 array.push( parameters.morphTargetsCount ); 19629 array.push( parameters.morphAttributeCount ); 19630 array.push( parameters.numDirLights ); 19631 array.push( parameters.numPointLights ); 19632 array.push( parameters.numSpotLights ); 19633 array.push( parameters.numSpotLightMaps ); 19634 array.push( parameters.numHemiLights ); 19635 array.push( parameters.numRectAreaLights ); 19636 array.push( parameters.numDirLightShadows ); 19637 array.push( parameters.numPointLightShadows ); 19638 array.push( parameters.numSpotLightShadows ); 19639 array.push( parameters.numSpotLightShadowsWithMaps ); 19640 array.push( parameters.shadowMapType ); 19641 array.push( parameters.toneMapping ); 19642 array.push( parameters.numClippingPlanes ); 19643 array.push( parameters.numClipIntersection ); 19644 array.push( parameters.depthPacking ); 19645 19646 } 19647 19648 function getProgramCacheKeyBooleans( array, parameters ) { 19649 19650 _programLayers.disableAll(); 19651 19652 if ( parameters.isWebGL2 ) 19653 _programLayers.enable( 0 ); 19654 if ( parameters.supportsVertexTextures ) 19655 _programLayers.enable( 1 ); 19656 if ( parameters.instancing ) 19657 _programLayers.enable( 2 ); 19658 if ( parameters.instancingColor ) 19659 _programLayers.enable( 3 ); 19660 if ( parameters.map ) 19661 _programLayers.enable( 4 );
vendor: 5,121 bytes, lines 19662-19864
19662 if ( parameters.matcap ) 19663 _programLayers.enable( 5 ); 19664 if ( parameters.envMap ) 19665 _programLayers.enable( 6 ); 19666 if ( parameters.lightMap ) 19667 _programLayers.enable( 7 ); 19668 if ( parameters.aoMap ) 19669 _programLayers.enable( 8 ); 19670 if ( parameters.emissiveMap ) 19671 _programLayers.enable( 9 ); 19672 if ( parameters.bumpMap ) 19673 _programLayers.enable( 10 ); 19674 if ( parameters.normalMap ) 19675 _programLayers.enable( 11 ); 19676 if ( parameters.objectSpaceNormalMap ) 19677 _programLayers.enable( 12 ); 19678 if ( parameters.tangentSpaceNormalMap ) 19679 _programLayers.enable( 13 ); 19680 if ( parameters.clearcoat ) 19681 _programLayers.enable( 14 ); 19682 if ( parameters.clearcoatMap ) 19683 _programLayers.enable( 15 ); 19684 if ( parameters.clearcoatRoughnessMap ) 19685 _programLayers.enable( 16 ); 19686 if ( parameters.clearcoatNormalMap ) 19687 _programLayers.enable( 17 ); 19688 if ( parameters.iridescence ) 19689 _programLayers.enable( 18 ); 19690 if ( parameters.iridescenceMap ) 19691 _programLayers.enable( 19 ); 19692 if ( parameters.iridescenceThicknessMap ) 19693 _programLayers.enable( 20 ); 19694 if ( parameters.displacementMap ) 19695 _programLayers.enable( 21 ); 19696 if ( parameters.specularMap ) 19697 _programLayers.enable( 22 ); 19698 if ( parameters.roughnessMap ) 19699 _programLayers.enable( 23 ); 19700 if ( parameters.metalnessMap ) 19701 _programLayers.enable( 24 ); 19702 if ( parameters.gradientMap ) 19703 _programLayers.enable( 25 ); 19704 if ( parameters.alphaMap ) 19705 _programLayers.enable( 26 ); 19706 if ( parameters.alphaTest ) 19707 _programLayers.enable( 27 ); 19708 if ( parameters.vertexColors ) 19709 _programLayers.enable( 28 ); 19710 if ( parameters.vertexAlphas ) 19711 _programLayers.enable( 29 ); 19712 if ( parameters.vertexUvs ) 19713 _programLayers.enable( 30 ); 19714 if ( parameters.vertexTangents ) 19715 _programLayers.enable( 31 ); 19716 if ( parameters.uvsVertexOnly ) 19717 _programLayers.enable( 32 ); 19718 19719 array.push( _programLayers.mask ); 19720 _programLayers.disableAll(); 19721 19722 if ( parameters.fog ) 19723 _programLayers.enable( 0 ); 19724 if ( parameters.useFog ) 19725 _programLayers.enable( 1 ); 19726 if ( parameters.flatShading ) 19727 _programLayers.enable( 2 ); 19728 if ( parameters.logarithmicDepthBuffer ) 19729 _programLayers.enable( 3 ); 19730 if ( parameters.skinning ) 19731 _programLayers.enable( 4 ); 19732 if ( parameters.morphTargets ) 19733 _programLayers.enable( 5 ); 19734 if ( parameters.morphNormals ) 19735 _programLayers.enable( 6 ); 19736 if ( parameters.morphColors ) 19737 _programLayers.enable( 7 ); 19738 if ( parameters.premultipliedAlpha ) 19739 _programLayers.enable( 8 ); 19740 if ( parameters.shadowMapEnabled ) 19741 _programLayers.enable( 9 ); 19742 if ( parameters.useLegacyLights ) 19743 _programLayers.enable( 10 ); 19744 if ( parameters.doubleSided ) 19745 _programLayers.enable( 11 ); 19746 if ( parameters.flipSided ) 19747 _programLayers.enable( 12 ); 19748 if ( parameters.useDepthPacking ) 19749 _programLayers.enable( 13 ); 19750 if ( parameters.dithering ) 19751 _programLayers.enable( 14 ); 19752 if ( parameters.specularIntensityMap ) 19753 _programLayers.enable( 15 ); 19754 if ( parameters.specularColorMap ) 19755 _programLayers.enable( 16 ); 19756 if ( parameters.transmission ) 19757 _programLayers.enable( 17 ); 19758 if ( parameters.transmissionMap ) 19759 _programLayers.enable( 18 ); 19760 if ( parameters.thicknessMap ) 19761 _programLayers.enable( 19 ); 19762 if ( parameters.sheen ) 19763 _programLayers.enable( 20 ); 19764 if ( parameters.sheenColorMap ) 19765 _programLayers.enable( 21 ); 19766 if ( parameters.sheenRoughnessMap ) 19767 _programLayers.enable( 22 ); 19768 if ( parameters.decodeVideoTexture ) 19769 _programLayers.enable( 23 ); 19770 if ( parameters.opaque ) 19771 _programLayers.enable( 24 ); 19772 19773 array.push( _programLayers.mask ); 19774 19775 } 19776 19777 function getUniforms( material ) { 19778 19779 const shaderID = shaderIDs[ material.type ]; 19780 let uniforms; 19781 19782 if ( shaderID ) { 19783 19784 const shader = ShaderLib[ shaderID ]; 19785 uniforms = UniformsUtils.clone( shader.uniforms ); 19786 19787 } else { 19788 19789 uniforms = material.uniforms; 19790 19791 } 19792 19793 return uniforms; 19794 19795 } 19796 19797 function acquireProgram( parameters, cacheKey ) { 19798 19799 let program; 19800 19801 // Check if code has been already compiled 19802 for ( let p = 0, pl = programs.length; p < pl; p ++ ) { 19803 19804 const preexistingProgram = programs[ p ]; 19805 19806 if ( preexistingProgram.cacheKey === cacheKey ) { 19807 19808 program = preexistingProgram; 19809 ++ program.usedTimes; 19810 19811 break; 19812 19813 } 19814 19815 } 19816 19817 if ( program === undefined ) { 19818 19819 program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates ); 19820 programs.push( program ); 19821 19822 } 19823 19824 return program; 19825 19826 } 19827 19828 function releaseProgram( program ) { 19829 19830 if ( -- program.usedTimes === 0 ) { 19831 19832 // Remove from unordered set 19833 const i = programs.indexOf( program ); 19834 programs[ i ] = programs[ programs.length - 1 ]; 19835 programs.pop(); 19836 19837 // Free WebGL resources 19838 program.destroy(); 19839 19840 } 19841 19842 } 19843 19844 function releaseShaderCache( material ) { 19845 19846 _customShaders.remove( material ); 19847 19848 } 19849 19850 function dispose() { 19851 19852 _customShaders.dispose(); 19853 19854 } 19855 19856 return { 19857 getParameters: getParameters, 19858 getProgramCacheKey: getProgramCacheKey, 19859 getUniforms: getUniforms, 19860 acquireProgram: acquireProgram, 19861 releaseProgram: releaseProgram, 19862 releaseShaderCache: releaseShaderCache, 19863 // Exposed for resource monitoring & error feedback via renderer.info: 19864 programs: programs,
vendor: 4,538 bytes, lines 19865-20146
19865 dispose: dispose 19866 }; 19867 19868} 19869 19870function WebGLProperties() { 19871 19872 let properties = new WeakMap(); 19873 19874 function get( object ) { 19875 19876 let map = properties.get( object ); 19877 19878 if ( map === undefined ) { 19879 19880 map = {}; 19881 properties.set( object, map ); 19882 19883 } 19884 19885 return map; 19886 19887 } 19888 19889 function remove( object ) { 19890 19891 properties.delete( object ); 19892 19893 } 19894 19895 function update( object, key, value ) { 19896 19897 properties.get( object )[ key ] = value; 19898 19899 } 19900 19901 function dispose() { 19902 19903 properties = new WeakMap(); 19904 19905 } 19906 19907 return { 19908 get: get, 19909 remove: remove, 19910 update: update, 19911 dispose: dispose 19912 }; 19913 19914} 19915 19916function painterSortStable( a, b ) { 19917 19918 if ( a.groupOrder !== b.groupOrder ) { 19919 19920 return a.groupOrder - b.groupOrder; 19921 19922 } else if ( a.renderOrder !== b.renderOrder ) { 19923 19924 return a.renderOrder - b.renderOrder; 19925 19926 } else if ( a.material.id !== b.material.id ) { 19927 19928 return a.material.id - b.material.id; 19929 19930 } else if ( a.z !== b.z ) { 19931 19932 return a.z - b.z; 19933 19934 } else { 19935 19936 return a.id - b.id; 19937 19938 } 19939 19940} 19941 19942function reversePainterSortStable( a, b ) { 19943 19944 if ( a.groupOrder !== b.groupOrder ) { 19945 19946 return a.groupOrder - b.groupOrder; 19947 19948 } else if ( a.renderOrder !== b.renderOrder ) { 19949 19950 return a.renderOrder - b.renderOrder; 19951 19952 } else if ( a.z !== b.z ) { 19953 19954 return b.z - a.z; 19955 19956 } else { 19957 19958 return a.id - b.id; 19959 19960 } 19961 19962} 19963 19964 19965function WebGLRenderList() { 19966 19967 const renderItems = []; 19968 let renderItemsIndex = 0; 19969 19970 const opaque = []; 19971 const transmissive = []; 19972 const transparent = []; 19973 19974 function init() { 19975 19976 renderItemsIndex = 0; 19977 19978 opaque.length = 0; 19979 transmissive.length = 0; 19980 transparent.length = 0; 19981 19982 } 19983 19984 function getNextRenderItem( object, geometry, material, groupOrder, z, group ) { 19985 19986 let renderItem = renderItems[ renderItemsIndex ]; 19987 19988 if ( renderItem === undefined ) { 19989 19990 renderItem = { 19991 id: object.id, 19992 object: object, 19993 geometry: geometry, 19994 material: material, 19995 groupOrder: groupOrder, 19996 renderOrder: object.renderOrder, 19997 z: z, 19998 group: group 19999 }; 20000 20001 renderItems[ renderItemsIndex ] = renderItem; 20002 20003 } else { 20004 20005 renderItem.id = object.id; 20006 renderItem.object = object; 20007 renderItem.geometry = geometry; 20008 renderItem.material = material; 20009 renderItem.groupOrder = groupOrder; 20010 renderItem.renderOrder = object.renderOrder; 20011 renderItem.z = z; 20012 renderItem.group = group; 20013 20014 } 20015 20016 renderItemsIndex ++; 20017 20018 return renderItem; 20019 20020 } 20021 20022 function push( object, geometry, material, groupOrder, z, group ) { 20023 20024 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); 20025 20026 if ( material.transmission > 0.0 ) { 20027 20028 transmissive.push( renderItem ); 20029 20030 } else if ( material.transparent === true ) { 20031 20032 transparent.push( renderItem ); 20033 20034 } else { 20035 20036 opaque.push( renderItem ); 20037 20038 } 20039 20040 } 20041 20042 function unshift( object, geometry, material, groupOrder, z, group ) { 20043 20044 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); 20045 20046 if ( material.transmission > 0.0 ) { 20047 20048 transmissive.unshift( renderItem ); 20049 20050 } else if ( material.transparent === true ) { 20051 20052 transparent.unshift( renderItem ); 20053 20054 } else { 20055 20056 opaque.unshift( renderItem ); 20057 20058 } 20059 20060 } 20061 20062 function sort( customOpaqueSort, customTransparentSort ) { 20063 20064 if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable ); 20065 if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable ); 20066 if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable ); 20067 20068 } 20069 20070 function finish() { 20071 20072 // Clear references from inactive renderItems in the list 20073 20074 for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) { 20075 20076 const renderItem = renderItems[ i ]; 20077 20078 if ( renderItem.id === null ) break; 20079 20080 renderItem.id = null; 20081 renderItem.object = null; 20082 renderItem.geometry = null; 20083 renderItem.material = null; 20084 renderItem.group = null; 20085 20086 } 20087 20088 } 20089 20090 return { 20091 20092 opaque: opaque, 20093 transmissive: transmissive, 20094 transparent: transparent, 20095 20096 init: init, 20097 push: push, 20098 unshift: unshift, 20099 finish: finish, 20100 20101 sort: sort 20102 }; 20103 20104} 20105 20106function WebGLRenderLists() { 20107 20108 let lists = new WeakMap(); 20109 20110 function get( scene, renderCallDepth ) { 20111 20112 const listArray = lists.get( scene ); 20113 let list; 20114 20115 if ( listArray === undefined ) { 20116 20117 list = new WebGLRenderList(); 20118 lists.set( scene, [ list ] ); 20119 20120 } else { 20121 20122 if ( renderCallDepth >= listArray.length ) { 20123 20124 list = new WebGLRenderList(); 20125 listArray.push( list ); 20126 20127 } else { 20128 20129 list = listArray[ renderCallDepth ]; 20130 20131 } 20132 20133 } 20134 20135 return list; 20136 20137 } 20138 20139 function dispose() { 20140 20141 lists = new WeakMap(); 20142 20143 } 20144 20145 return { 20146 get: get,
vendor: 10,755 bytes, lines 20147-20614
20147 dispose: dispose 20148 }; 20149 20150} 20151 20152function UniformsCache() { 20153 20154 const lights = {}; 20155 20156 return { 20157 20158 get: function ( light ) { 20159 20160 if ( lights[ light.id ] !== undefined ) { 20161 20162 return lights[ light.id ]; 20163 20164 } 20165 20166 let uniforms; 20167 20168 switch ( light.type ) { 20169 20170 case 'DirectionalLight': 20171 uniforms = { 20172 direction: new Vector3(), 20173 color: new Color() 20174 }; 20175 break; 20176 20177 case 'SpotLight': 20178 uniforms = { 20179 position: new Vector3(), 20180 direction: new Vector3(), 20181 color: new Color(), 20182 distance: 0, 20183 coneCos: 0, 20184 penumbraCos: 0, 20185 decay: 0 20186 }; 20187 break; 20188 20189 case 'PointLight': 20190 uniforms = { 20191 position: new Vector3(), 20192 color: new Color(), 20193 distance: 0, 20194 decay: 0 20195 }; 20196 break; 20197 20198 case 'HemisphereLight': 20199 uniforms = { 20200 direction: new Vector3(), 20201 skyColor: new Color(), 20202 groundColor: new Color() 20203 }; 20204 break; 20205 20206 case 'RectAreaLight': 20207 uniforms = { 20208 color: new Color(), 20209 position: new Vector3(), 20210 halfWidth: new Vector3(), 20211 halfHeight: new Vector3() 20212 }; 20213 break; 20214 20215 } 20216 20217 lights[ light.id ] = uniforms; 20218 20219 return uniforms; 20220 20221 } 20222 20223 }; 20224 20225} 20226 20227function ShadowUniformsCache() { 20228 20229 const lights = {}; 20230 20231 return { 20232 20233 get: function ( light ) { 20234 20235 if ( lights[ light.id ] !== undefined ) { 20236 20237 return lights[ light.id ]; 20238 20239 } 20240 20241 let uniforms; 20242 20243 switch ( light.type ) { 20244 20245 case 'DirectionalLight': 20246 uniforms = { 20247 shadowBias: 0, 20248 shadowNormalBias: 0, 20249 shadowRadius: 1, 20250 shadowMapSize: new Vector2() 20251 }; 20252 break; 20253 20254 case 'SpotLight': 20255 uniforms = { 20256 shadowBias: 0, 20257 shadowNormalBias: 0, 20258 shadowRadius: 1, 20259 shadowMapSize: new Vector2() 20260 }; 20261 break; 20262 20263 case 'PointLight': 20264 uniforms = { 20265 shadowBias: 0, 20266 shadowNormalBias: 0, 20267 shadowRadius: 1, 20268 shadowMapSize: new Vector2(), 20269 shadowCameraNear: 1, 20270 shadowCameraFar: 1000 20271 }; 20272 break; 20273 20274 // TODO (abelnation): set RectAreaLight shadow uniforms 20275 20276 } 20277 20278 lights[ light.id ] = uniforms; 20279 20280 return uniforms; 20281 20282 } 20283 20284 }; 20285 20286} 20287 20288 20289 20290let nextVersion = 0; 20291 20292function shadowCastingAndTexturingLightsFirst( lightA, lightB ) { 20293 20294 return ( lightB.castShadow ? 2 : 0 ) - ( lightA.castShadow ? 2 : 0 ) + ( lightB.map ? 1 : 0 ) - ( lightA.map ? 1 : 0 ); 20295 20296} 20297 20298function WebGLLights( extensions, capabilities ) { 20299 20300 const cache = new UniformsCache(); 20301 20302 const shadowCache = ShadowUniformsCache(); 20303 20304 const state = { 20305 20306 version: 0, 20307 20308 hash: { 20309 directionalLength: - 1, 20310 pointLength: - 1, 20311 spotLength: - 1, 20312 rectAreaLength: - 1, 20313 hemiLength: - 1, 20314 20315 numDirectionalShadows: - 1, 20316 numPointShadows: - 1, 20317 numSpotShadows: - 1, 20318 numSpotMaps: - 1 20319 }, 20320 20321 ambient: [ 0, 0, 0 ], 20322 probe: [], 20323 directional: [], 20324 directionalShadow: [], 20325 directionalShadowMap: [], 20326 directionalShadowMatrix: [], 20327 spot: [], 20328 spotLightMap: [], 20329 spotShadow: [], 20330 spotShadowMap: [], 20331 spotLightMatrix: [], 20332 rectArea: [], 20333 rectAreaLTC1: null, 20334 rectAreaLTC2: null, 20335 point: [], 20336 pointShadow: [], 20337 pointShadowMap: [], 20338 pointShadowMatrix: [], 20339 hemi: [], 20340 numSpotLightShadowsWithMaps: 0 20341 20342 }; 20343 20344 for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() ); 20345 20346 const vector3 = new Vector3(); 20347 const matrix4 = new Matrix4(); 20348 const matrix42 = new Matrix4(); 20349 20350 function setup( lights, useLegacyLights ) { 20351 20352 let r = 0, g = 0, b = 0; 20353 20354 for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 ); 20355 20356 let directionalLength = 0; 20357 let pointLength = 0; 20358 let spotLength = 0; 20359 let rectAreaLength = 0; 20360 let hemiLength = 0; 20361 20362 let numDirectionalShadows = 0; 20363 let numPointShadows = 0; 20364 let numSpotShadows = 0; 20365 let numSpotMaps = 0; 20366 let numSpotShadowsWithMaps = 0; 20367 20368 // ordering : [shadow casting + map texturing, map texturing, shadow casting, none ] 20369 lights.sort( shadowCastingAndTexturingLightsFirst ); 20370 20371 // artist-friendly light intensity scaling factor 20372 const scaleFactor = ( useLegacyLights === true ) ? Math.PI : 1; 20373 20374 for ( let i = 0, l = lights.length; i < l; i ++ ) { 20375 20376 const light = lights[ i ]; 20377 20378 const color = light.color; 20379 const intensity = light.intensity; 20380 const distance = light.distance; 20381 20382 const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; 20383 20384 if ( light.isAmbientLight ) { 20385 20386 r += color.r * intensity * scaleFactor; 20387 g += color.g * intensity * scaleFactor; 20388 b += color.b * intensity * scaleFactor; 20389 20390 } else if ( light.isLightProbe ) { 20391 20392 for ( let j = 0; j < 9; j ++ ) { 20393 20394 state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity ); 20395 20396 } 20397 20398 } else if ( light.isDirectionalLight ) { 20399 20400 const uniforms = cache.get( light ); 20401 20402 uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor ); 20403 20404 if ( light.castShadow ) { 20405 20406 const shadow = light.shadow; 20407 20408 const shadowUniforms = shadowCache.get( light ); 20409 20410 shadowUniforms.shadowBias = shadow.bias; 20411 shadowUniforms.shadowNormalBias = shadow.normalBias; 20412 shadowUniforms.shadowRadius = shadow.radius; 20413 shadowUniforms.shadowMapSize = shadow.mapSize; 20414 20415 state.directionalShadow[ directionalLength ] = shadowUniforms; 20416 state.directionalShadowMap[ directionalLength ] = shadowMap; 20417 state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; 20418 20419 numDirectionalShadows ++; 20420 20421 } 20422 20423 state.directional[ directionalLength ] = uniforms; 20424 20425 directionalLength ++; 20426 20427 } else if ( light.isSpotLight ) { 20428 20429 const uniforms = cache.get( light ); 20430 20431 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 20432 20433 uniforms.color.copy( color ).multiplyScalar( intensity * scaleFactor ); 20434 uniforms.distance = distance; 20435 20436 uniforms.coneCos = Math.cos( light.angle ); 20437 uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); 20438 uniforms.decay = light.decay; 20439 20440 state.spot[ spotLength ] = uniforms; 20441 20442 const shadow = light.shadow; 20443 20444 if ( light.map ) { 20445 20446 state.spotLightMap[ numSpotMaps ] = light.map; 20447 numSpotMaps ++; 20448 20449 // make sure the lightMatrix is up to date 20450 // TODO : do it if required only 20451 shadow.updateMatrices( light ); 20452 20453 if ( light.castShadow ) numSpotShadowsWithMaps ++; 20454 20455 } 20456 20457 state.spotLightMatrix[ spotLength ] = shadow.matrix; 20458 20459 if ( light.castShadow ) { 20460 20461 const shadowUniforms = shadowCache.get( light ); 20462 20463 shadowUniforms.shadowBias = shadow.bias; 20464 shadowUniforms.shadowNormalBias = shadow.normalBias; 20465 shadowUniforms.shadowRadius = shadow.radius; 20466 shadowUniforms.shadowMapSize = shadow.mapSize; 20467 20468 state.spotShadow[ spotLength ] = shadowUniforms; 20469 state.spotShadowMap[ spotLength ] = shadowMap; 20470 20471 numSpotShadows ++; 20472 20473 } 20474 20475 spotLength ++; 20476 20477 } else if ( light.isRectAreaLight ) { 20478 20479 const uniforms = cache.get( light ); 20480 20481 uniforms.color.copy( color ).multiplyScalar( intensity ); 20482 20483 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); 20484 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); 20485 20486 state.rectArea[ rectAreaLength ] = uniforms; 20487 20488 rectAreaLength ++; 20489 20490 } else if ( light.isPointLight ) { 20491 20492 const uniforms = cache.get( light ); 20493 20494 uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor ); 20495 uniforms.distance = light.distance; 20496 uniforms.decay = light.decay; 20497 20498 if ( light.castShadow ) { 20499 20500 const shadow = light.shadow; 20501 20502 const shadowUniforms = shadowCache.get( light ); 20503 20504 shadowUniforms.shadowBias = shadow.bias; 20505 shadowUniforms.shadowNormalBias = shadow.normalBias; 20506 shadowUniforms.shadowRadius = shadow.radius; 20507 shadowUniforms.shadowMapSize = shadow.mapSize; 20508 shadowUniforms.shadowCameraNear = shadow.camera.near; 20509 shadowUniforms.shadowCameraFar = shadow.camera.far; 20510 20511 state.pointShadow[ pointLength ] = shadowUniforms; 20512 state.pointShadowMap[ pointLength ] = shadowMap; 20513 state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; 20514 20515 numPointShadows ++; 20516 20517 } 20518 20519 state.point[ pointLength ] = uniforms; 20520 20521 pointLength ++; 20522 20523 } else if ( light.isHemisphereLight ) { 20524 20525 const uniforms = cache.get( light ); 20526 20527 uniforms.skyColor.copy( light.color ).multiplyScalar( intensity * scaleFactor ); 20528 uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity * scaleFactor ); 20529 20530 state.hemi[ hemiLength ] = uniforms; 20531 20532 hemiLength ++; 20533 20534 } 20535 20536 } 20537 20538 if ( rectAreaLength > 0 ) { 20539 20540 if ( capabilities.isWebGL2 ) { 20541 20542 // WebGL 2 20543 20544 state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1; 20545 state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2; 20546 20547 } else { 20548 20549 // WebGL 1 20550 20551 if ( extensions.has( 'OES_texture_float_linear' ) === true ) { 20552 20553 state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1; 20554 state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2; 20555 20556 } else if ( extensions.has( 'OES_texture_half_float_linear' ) === true ) { 20557 20558 state.rectAreaLTC1 = UniformsLib.LTC_HALF_1; 20559 state.rectAreaLTC2 = UniformsLib.LTC_HALF_2; 20560 20561 } else { 20562 20563 console.error( 'THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.' ); 20564 20565 } 20566 20567 } 20568 20569 } 20570 20571 state.ambient[ 0 ] = r; 20572 state.ambient[ 1 ] = g; 20573 state.ambient[ 2 ] = b; 20574 20575 const hash = state.hash; 20576 20577 if ( hash.directionalLength !== directionalLength || 20578 hash.pointLength !== pointLength || 20579 hash.spotLength !== spotLength || 20580 hash.rectAreaLength !== rectAreaLength || 20581 hash.hemiLength !== hemiLength || 20582 hash.numDirectionalShadows !== numDirectionalShadows || 20583 hash.numPointShadows !== numPointShadows || 20584 hash.numSpotShadows !== numSpotShadows || 20585 hash.numSpotMaps !== numSpotMaps ) { 20586 20587 state.directional.length = directionalLength; 20588 state.spot.length = spotLength; 20589 state.rectArea.length = rectAreaLength; 20590 state.point.length = pointLength; 20591 state.hemi.length = hemiLength; 20592 20593 state.directionalShadow.length = numDirectionalShadows; 20594 state.directionalShadowMap.length = numDirectionalShadows; 20595 state.pointShadow.length = numPointShadows; 20596 state.pointShadowMap.length = numPointShadows; 20597 state.spotShadow.length = numSpotShadows; 20598 state.spotShadowMap.length = numSpotShadows; 20599 state.directionalShadowMatrix.length = numDirectionalShadows; 20600 state.pointShadowMatrix.length = numPointShadows; 20601 state.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps; 20602 state.spotLightMap.length = numSpotMaps; 20603 state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps; 20604 20605 hash.directionalLength = directionalLength; 20606 hash.pointLength = pointLength; 20607 hash.spotLength = spotLength; 20608 hash.rectAreaLength = rectAreaLength; 20609 hash.hemiLength = hemiLength; 20610 20611 hash.numDirectionalShadows = numDirectionalShadows; 20612 hash.numPointShadows = numPointShadows; 20613 hash.numSpotShadows = numSpotShadows; 20614 hash.numSpotMaps = numSpotMap
vendor: 5,016 bytes, lines 20614-20877
20614s; 20615 20616 state.version = nextVersion ++; 20617 20618 } 20619 20620 } 20621 20622 function setupView( lights, camera ) { 20623 20624 let directionalLength = 0; 20625 let pointLength = 0; 20626 let spotLength = 0; 20627 let rectAreaLength = 0; 20628 let hemiLength = 0; 20629 20630 const viewMatrix = camera.matrixWorldInverse; 20631 20632 for ( let i = 0, l = lights.length; i < l; i ++ ) { 20633 20634 const light = lights[ i ]; 20635 20636 if ( light.isDirectionalLight ) { 20637 20638 const uniforms = state.directional[ directionalLength ]; 20639 20640 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 20641 vector3.setFromMatrixPosition( light.target.matrixWorld ); 20642 uniforms.direction.sub( vector3 ); 20643 uniforms.direction.transformDirection( viewMatrix ); 20644 20645 directionalLength ++; 20646 20647 } else if ( light.isSpotLight ) { 20648 20649 const uniforms = state.spot[ spotLength ]; 20650 20651 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 20652 uniforms.position.applyMatrix4( viewMatrix ); 20653 20654 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 20655 vector3.setFromMatrixPosition( light.target.matrixWorld ); 20656 uniforms.direction.sub( vector3 ); 20657 uniforms.direction.transformDirection( viewMatrix ); 20658 20659 spotLength ++; 20660 20661 } else if ( light.isRectAreaLight ) { 20662 20663 const uniforms = state.rectArea[ rectAreaLength ]; 20664 20665 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 20666 uniforms.position.applyMatrix4( viewMatrix ); 20667 20668 // extract local rotation of light to derive width/height half vectors 20669 matrix42.identity(); 20670 matrix4.copy( light.matrixWorld ); 20671 matrix4.premultiply( viewMatrix ); 20672 matrix42.extractRotation( matrix4 ); 20673 20674 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); 20675 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); 20676 20677 uniforms.halfWidth.applyMatrix4( matrix42 ); 20678 uniforms.halfHeight.applyMatrix4( matrix42 ); 20679 20680 rectAreaLength ++; 20681 20682 } else if ( light.isPointLight ) { 20683 20684 const uniforms = state.point[ pointLength ]; 20685 20686 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 20687 uniforms.position.applyMatrix4( viewMatrix ); 20688 20689 pointLength ++; 20690 20691 } else if ( light.isHemisphereLight ) { 20692 20693 const uniforms = state.hemi[ hemiLength ]; 20694 20695 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 20696 uniforms.direction.transformDirection( viewMatrix ); 20697 20698 hemiLength ++; 20699 20700 } 20701 20702 } 20703 20704 } 20705 20706 return { 20707 setup: setup, 20708 setupView: setupView, 20709 state: state 20710 }; 20711 20712} 20713 20714function WebGLRenderState( extensions, capabilities ) { 20715 20716 const lights = new WebGLLights( extensions, capabilities ); 20717 20718 const lightsArray = []; 20719 const shadowsArray = []; 20720 20721 function init() { 20722 20723 lightsArray.length = 0; 20724 shadowsArray.length = 0; 20725 20726 } 20727 20728 function pushLight( light ) { 20729 20730 lightsArray.push( light ); 20731 20732 } 20733 20734 function pushShadow( shadowLight ) { 20735 20736 shadowsArray.push( shadowLight ); 20737 20738 } 20739 20740 function setupLights( useLegacyLights ) { 20741 20742 lights.setup( lightsArray, useLegacyLights ); 20743 20744 } 20745 20746 function setupLightsView( camera ) { 20747 20748 lights.setupView( lightsArray, camera ); 20749 20750 } 20751 20752 const state = { 20753 lightsArray: lightsArray, 20754 shadowsArray: shadowsArray, 20755 20756 lights: lights 20757 }; 20758 20759 return { 20760 init: init, 20761 state: state, 20762 setupLights: setupLights, 20763 setupLightsView: setupLightsView, 20764 20765 pushLight: pushLight, 20766 pushShadow: pushShadow 20767 }; 20768 20769} 20770 20771function WebGLRenderStates( extensions, capabilities ) { 20772 20773 let renderStates = new WeakMap(); 20774 20775 function get( scene, renderCallDepth = 0 ) { 20776 20777 const renderStateArray = renderStates.get( scene ); 20778 let renderState; 20779 20780 if ( renderStateArray === undefined ) { 20781 20782 renderState = new WebGLRenderState( extensions, capabilities ); 20783 renderStates.set( scene, [ renderState ] ); 20784 20785 } else { 20786 20787 if ( renderCallDepth >= renderStateArray.length ) { 20788 20789 renderState = new WebGLRenderState( extensions, capabilities ); 20790 renderStateArray.push( renderState ); 20791 20792 } else { 20793 20794 renderState = renderStateArray[ renderCallDepth ]; 20795 20796 } 20797 20798 } 20799 20800 return renderState; 20801 20802 } 20803 20804 function dispose() { 20805 20806 renderStates = new WeakMap(); 20807 20808 } 20809 20810 return { 20811 get: get, 20812 dispose: dispose 20813 }; 20814 20815} 20816 20817class MeshDepthMaterial extends Material { 20818 20819 constructor( parameters ) { 20820 20821 super(); 20822 20823 this.isMeshDepthMaterial = true; 20824 20825 this.type = 'MeshDepthMaterial'; 20826 20827 this.depthPacking = BasicDepthPacking; 20828 20829 this.map = null; 20830 20831 this.alphaMap = null; 20832 20833 this.displacementMap = null; 20834 this.displacementScale = 1; 20835 this.displacementBias = 0; 20836 20837 this.wireframe = false; 20838 this.wireframeLinewidth = 1; 20839 20840 this.setValues( parameters ); 20841 20842 } 20843 20844 copy( source ) { 20845 20846 super.copy( source ); 20847 20848 this.depthPacking = source.depthPacking; 20849 20850 this.map = source.map; 20851 20852 this.alphaMap = source.alphaMap; 20853 20854 this.displacementMap = source.displacementMap; 20855 this.displacementScale = source.displacementScale; 20856 this.displacementBias = source.displacementBias; 20857 20858 this.wireframe = source.wireframe; 20859 this.wireframeLinewidth = source.wireframeLinewidth; 20860 20861 return this; 20862 20863 } 20864 20865} 20866 20867class MeshDistanceMaterial extends Material { 20868 20869 constructor( parameters ) { 20870 20871 super(); 20872 20873 this.isMeshDistanceMaterial = true; 20874 20875 this.type = 'MeshDistanceMaterial'; 20876 20877 this.
vendor: 6,012 bytes, lines 20877-21083
20877referencePosition = new Vector3(); 20878 this.nearDistance = 1; 20879 this.farDistance = 1000; 20880 20881 this.map = null; 20882 20883 this.alphaMap = null; 20884 20885 this.displacementMap = null; 20886 this.displacementScale = 1; 20887 this.displacementBias = 0; 20888 20889 this.setValues( parameters ); 20890 20891 } 20892 20893 copy( source ) { 20894 20895 super.copy( source ); 20896 20897 this.referencePosition.copy( source.referencePosition ); 20898 this.nearDistance = source.nearDistance; 20899 this.farDistance = source.farDistance; 20900 20901 this.map = source.map; 20902 20903 this.alphaMap = source.alphaMap; 20904 20905 this.displacementMap = source.displacementMap; 20906 this.displacementScale = source.displacementScale; 20907 this.displacementBias = source.displacementBias; 20908 20909 return this; 20910 20911 } 20912 20913} 20914 20915const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}"; 20916 20917const fragment = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"; 20918 20919function WebGLShadowMap( _renderer, _objects, _capabilities ) { 20920 20921 let _frustum = new Frustum(); 20922 20923 const _shadowMapSize = new Vector2(), 20924 _viewportSize = new Vector2(), 20925 20926 _viewport = new Vector4(), 20927 20928 _depthMaterial = new MeshDepthMaterial( { depthPacking: RGBADepthPacking } ), 20929 _distanceMaterial = new MeshDistanceMaterial(), 20930 20931 _materialCache = {}, 20932 20933 _maxTextureSize = _capabilities.maxTextureSize; 20934 20935 const shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide }; 20936 20937 const shadowMaterialVertical = new ShaderMaterial( { 20938 defines: { 20939 VSM_SAMPLES: 8 20940 }, 20941 uniforms: { 20942 shadow_pass: { value: null }, 20943 resolution: { value: new Vector2() }, 20944 radius: { value: 4.0 } 20945 }, 20946 20947 vertexShader: vertex, 20948 fragmentShader: fragment 20949 20950 } ); 20951 20952 const shadowMaterialHorizontal = shadowMaterialVertical.clone(); 20953 shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1; 20954 20955 const fullScreenTri = new BufferGeometry(); 20956 fullScreenTri.setAttribute( 20957 'position', 20958 new BufferAttribute( 20959 new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ), 20960 3 20961 ) 20962 ); 20963 20964 const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical ); 20965 20966 const scope = this; 20967 20968 this.enabled = false; 20969 20970 this.autoUpdate = true; 20971 this.needsUpdate = false; 20972 20973 this.type = PCFShadowMap; 20974 20975 this.render = function ( lights, scene, camera ) { 20976 20977 if ( scope.enabled === false ) return; 20978 if ( scope.autoUpdate === false && scope.needsUpdate === false ) return; 20979 20980 if ( lights.length === 0 ) return; 20981 20982 const currentRenderTarget = _renderer.getRenderTarget(); 20983 const activeCubeFace = _renderer.getActiveCubeFace(); 20984 const activeMipmapLevel = _renderer.getActiveMipmapLevel(); 20985 20986 const _state = _renderer.state; 20987 20988 // Set GL state for depth map. 20989 _state.setBlending( NoBlending ); 20990 _state.buffers.color.setClear( 1, 1, 1, 1 ); 20991 _state.buffers.depth.setTest( true ); 20992 _state.setScissorTest( false ); 20993 20994 // render depth map 20995 20996 for ( let i = 0, il = lights.length; i < il; i ++ ) { 20997 20998 const light = lights[ i ]; 20999 const shadow = light.shadow; 21000 21001 if ( shadow === undefined ) { 21002 21003 console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); 21004 continue; 21005 21006 } 21007 21008 if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue; 21009 21010 _shadowMapSize.copy( shadow.mapSize ); 21011 21012 const shadowFrameExtents = shadow.getFrameExtents(); 21013 21014 _shadowMapSize.multiply( shadowFrameExtents ); 21015 21016 _viewportSize.copy( shadow.mapSize ); 21017 21018 if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) { 21019 21020 if ( _shadowMapSize.x > _maxTextureSize ) { 21021 21022 _viewportSize.x = Math.floor( _maxTextureSize / shadowFrameExtents.x ); 21023 _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x; 21024 shadow.mapSize.x = _viewportSize.x; 21025 21026 } 21027 21028 if ( _shadowMapSize.y > _maxTextureSize ) { 21029 21030 _viewportSize.y = Math.floor( _maxTextureSize / shadowFrameExtents.y ); 21031 _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y; 21032 shadow.mapSize.y = _viewportSize.y; 21033 21034 } 21035 21036 } 21037 21038 if ( shadow.map === null ) { 21039 21040 const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; 21041 21042 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); 21043 shadow.map.texture.name = light.name + '.shadowMap'; 21044 21045 shadow.camera.updateProjectionMatrix(); 21046 21047 } 21048 21049 _renderer.setRenderTarget( shadow.map ); 21050 _renderer.clear(); 21051 21052 const viewportCount = shadow.getViewportCount(); 21053 21054 for ( let vp = 0; vp < viewportCount; vp ++ ) { 21055 21056 const viewport = shadow.getViewport( vp ); 21057 21058 _viewport.set( 21059 _viewportSize.x * viewport.x, 21060 _viewportSize.y * viewport.y, 21061 _viewportSize.x * viewport.z, 21062 _viewportSize.y * viewport.w 21063 ); 21064 21065 _state.viewport( _viewport ); 21066 21067 shadow.updateMatrices( light, vp ); 21068 21069 _frustum = shadow.getFrustum(); 21070 21071 renderObject( scene, camera, shadow.camera, light, this.type ); 21072 21073 } 21074 21075 // do blur pass for VSM 21076 21077 if ( shadow.isPointLightShadow !== true && this.type === VSMShadowMap ) { 21078 21079 VSMPass( shadow, camera ); 21080 21081 } 21082 21083 shadow.needsUpdate = false;
vendor: 1,882 bytes, lines 21084-21146
21084 21085 } 21086 21087 scope.needsUpdate = false; 21088 21089 _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); 21090 21091 }; 21092 21093 function VSMPass( shadow, camera ) { 21094 21095 const geometry = _objects.update( fullScreenMesh ); 21096 21097 if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) { 21098 21099 shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples; 21100 shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples; 21101 21102 shadowMaterialVertical.needsUpdate = true; 21103 shadowMaterialHorizontal.needsUpdate = true; 21104 21105 } 21106 21107 if ( shadow.mapPass === null ) { 21108 21109 shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y ); 21110 21111 } 21112 21113 // vertical pass 21114 21115 shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture; 21116 shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize; 21117 shadowMaterialVertical.uniforms.radius.value = shadow.radius; 21118 _renderer.setRenderTarget( shadow.mapPass ); 21119 _renderer.clear(); 21120 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null ); 21121 21122 // horizontal pass 21123 21124 shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture; 21125 shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize; 21126 shadowMaterialHorizontal.uniforms.radius.value = shadow.radius; 21127 _renderer.setRenderTarget( shadow.map ); 21128 _renderer.clear(); 21129 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null ); 21130 21131 } 21132 21133 function getDepthMaterial( object, material, light, shadowCameraNear, shadowCameraFar, type ) { 21134 21135 let result = null; 21136 21137 const customMaterial = ( light.isPointLight === true ) ? object.customDistanceMaterial : object.customDepthMaterial; 21138 21139 if ( customMaterial !== undefined ) { 21140 21141 result = customMaterial; 21142 21143 } else { 21144 21145 result = ( light.isPointLight === true ) ? _distanceMaterial : _depthMaterial; 21146
vendor: 1,354 bytes, lines 21147-21197
21147 if ( ( _renderer.localClippingEnabled && material.clipShadows === true && Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) || 21148 ( material.displacementMap && material.displacementScale !== 0 ) || 21149 ( material.alphaMap && material.alphaTest > 0 ) || 21150 ( material.map && material.alphaTest > 0 ) ) { 21151 21152 // in this case we need a unique material instance reflecting the 21153 // appropriate state 21154 21155 const keyA = result.uuid, keyB = material.uuid; 21156 21157 let materialsForVariant = _materialCache[ keyA ]; 21158 21159 if ( materialsForVariant === undefined ) { 21160 21161 materialsForVariant = {}; 21162 _materialCache[ keyA ] = materialsForVariant; 21163 21164 } 21165 21166 let cachedMaterial = materialsForVariant[ keyB ]; 21167 21168 if ( cachedMaterial === undefined ) { 21169 21170 cachedMaterial = result.clone(); 21171 materialsForVariant[ keyB ] = cachedMaterial; 21172 21173 } 21174 21175 result = cachedMaterial; 21176 21177 } 21178 21179 } 21180 21181 result.visible = material.visible; 21182 result.wireframe = material.wireframe; 21183 21184 if ( type === VSMShadowMap ) { 21185 21186 result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side; 21187 21188 } else { 21189 21190 result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ]; 21191 21192 } 21193 21194 result.alphaMap = material.alphaMap; 21195 result.alphaTest = material.alphaTest; 21196 result.map = material.map; 21197
vendor: 9,683 bytes, lines 21198-21696
21198 result.clipShadows = material.clipShadows; 21199 result.clippingPlanes = material.clippingPlanes; 21200 result.clipIntersection = material.clipIntersection; 21201 21202 result.displacementMap = material.displacementMap; 21203 result.displacementScale = material.displacementScale; 21204 result.displacementBias = material.displacementBias; 21205 21206 result.wireframeLinewidth = material.wireframeLinewidth; 21207 result.linewidth = material.linewidth; 21208 21209 if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) { 21210 21211 result.referencePosition.setFromMatrixPosition( light.matrixWorld ); 21212 result.nearDistance = shadowCameraNear; 21213 result.farDistance = shadowCameraFar; 21214 21215 } 21216 21217 return result; 21218 21219 } 21220 21221 function renderObject( object, camera, shadowCamera, light, type ) { 21222 21223 if ( object.visible === false ) return; 21224 21225 const visible = object.layers.test( camera.layers ); 21226 21227 if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { 21228 21229 if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { 21230 21231 object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); 21232 21233 const geometry = _objects.update( object ); 21234 const material = object.material; 21235 21236 if ( Array.isArray( material ) ) { 21237 21238 const groups = geometry.groups; 21239 21240 for ( let k = 0, kl = groups.length; k < kl; k ++ ) { 21241 21242 const group = groups[ k ]; 21243 const groupMaterial = material[ group.materialIndex ]; 21244 21245 if ( groupMaterial && groupMaterial.visible ) { 21246 21247 const depthMaterial = getDepthMaterial( object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type ); 21248 21249 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); 21250 21251 } 21252 21253 } 21254 21255 } else if ( material.visible ) { 21256 21257 const depthMaterial = getDepthMaterial( object, material, light, shadowCamera.near, shadowCamera.far, type ); 21258 21259 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); 21260 21261 } 21262 21263 } 21264 21265 } 21266 21267 const children = object.children; 21268 21269 for ( let i = 0, l = children.length; i < l; i ++ ) { 21270 21271 renderObject( children[ i ], camera, shadowCamera, light, type ); 21272 21273 } 21274 21275 } 21276 21277} 21278 21279function WebGLState( gl, extensions, capabilities ) { 21280 21281 const isWebGL2 = capabilities.isWebGL2; 21282 21283 function ColorBuffer() { 21284 21285 let locked = false; 21286 21287 const color = new Vector4(); 21288 let currentColorMask = null; 21289 const currentColorClear = new Vector4( 0, 0, 0, 0 ); 21290 21291 return { 21292 21293 setMask: function ( colorMask ) { 21294 21295 if ( currentColorMask !== colorMask && ! locked ) { 21296 21297 gl.colorMask( colorMask, colorMask, colorMask, colorMask ); 21298 currentColorMask = colorMask; 21299 21300 } 21301 21302 }, 21303 21304 setLocked: function ( lock ) { 21305 21306 locked = lock; 21307 21308 }, 21309 21310 setClear: function ( r, g, b, a, premultipliedAlpha ) { 21311 21312 if ( premultipliedAlpha === true ) { 21313 21314 r *= a; g *= a; b *= a; 21315 21316 } 21317 21318 color.set( r, g, b, a ); 21319 21320 if ( currentColorClear.equals( color ) === false ) { 21321 21322 gl.clearColor( r, g, b, a ); 21323 currentColorClear.copy( color ); 21324 21325 } 21326 21327 }, 21328 21329 reset: function () { 21330 21331 locked = false; 21332 21333 currentColorMask = null; 21334 currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state 21335 21336 } 21337 21338 }; 21339 21340 } 21341 21342 function DepthBuffer() { 21343 21344 let locked = false; 21345 21346 let currentDepthMask = null; 21347 let currentDepthFunc = null; 21348 let currentDepthClear = null; 21349 21350 return { 21351 21352 setTest: function ( depthTest ) { 21353 21354 if ( depthTest ) { 21355 21356 enable( 2929 ); 21357 21358 } else { 21359 21360 disable( 2929 ); 21361 21362 } 21363 21364 }, 21365 21366 setMask: function ( depthMask ) { 21367 21368 if ( currentDepthMask !== depthMask && ! locked ) { 21369 21370 gl.depthMask( depthMask ); 21371 currentDepthMask = depthMask; 21372 21373 } 21374 21375 }, 21376 21377 setFunc: function ( depthFunc ) { 21378 21379 if ( currentDepthFunc !== depthFunc ) { 21380 21381 switch ( depthFunc ) { 21382 21383 case NeverDepth: 21384 21385 gl.depthFunc( 512 ); 21386 break; 21387 21388 case AlwaysDepth: 21389 21390 gl.depthFunc( 519 ); 21391 break; 21392 21393 case LessDepth: 21394 21395 gl.depthFunc( 513 ); 21396 break; 21397 21398 case LessEqualDepth: 21399 21400 gl.depthFunc( 515 ); 21401 break; 21402 21403 case EqualDepth: 21404 21405 gl.depthFunc( 514 ); 21406 break; 21407 21408 case GreaterEqualDepth: 21409 21410 gl.depthFunc( 518 ); 21411 break; 21412 21413 case GreaterDepth: 21414 21415 gl.depthFunc( 516 ); 21416 break; 21417 21418 case NotEqualDepth: 21419 21420 gl.depthFunc( 517 ); 21421 break; 21422 21423 default: 21424 21425 gl.depthFunc( 515 ); 21426 21427 } 21428 21429 currentDepthFunc = depthFunc; 21430 21431 } 21432 21433 }, 21434 21435 setLocked: function ( lock ) { 21436 21437 locked = lock; 21438 21439 }, 21440 21441 setClear: function ( depth ) { 21442 21443 if ( currentDepthClear !== depth ) { 21444 21445 gl.clearDepth( depth ); 21446 currentDepthClear = depth; 21447 21448 } 21449 21450 }, 21451 21452 reset: function () { 21453 21454 locked = false; 21455 21456 currentDepthMask = null; 21457 currentDepthFunc = null; 21458 currentDepthClear = null; 21459 21460 } 21461 21462 }; 21463 21464 } 21465 21466 function StencilBuffer() { 21467 21468 let locked = false; 21469 21470 let currentStencilMask = null; 21471 let currentStencilFunc = null; 21472 let currentStencilRef = null; 21473 let currentStencilFuncMask = null; 21474 let currentStencilFail = null; 21475 let currentStencilZFail = null; 21476 let currentStencilZPass = null; 21477 let currentStencilClear = null; 21478 21479 return { 21480 21481 setTest: function ( stencilTest ) { 21482 21483 if ( ! locked ) { 21484 21485 if ( stencilTest ) { 21486 21487 enable( 2960 ); 21488 21489 } else { 21490 21491 disable( 2960 ); 21492 21493 } 21494 21495 } 21496 21497 }, 21498 21499 setMask: function ( stencilMask ) { 21500 21501 if ( currentStencilMask !== stencilMask && ! locked ) { 21502 21503 gl.stencilMask( stencilMask ); 21504 currentStencilMask = stencilMask; 21505 21506 } 21507 21508 }, 21509 21510 setFunc: function ( stencilFunc, stencilRef, stencilMask ) { 21511 21512 if ( currentStencilFunc !== stencilFunc || 21513 currentStencilRef !== stencilRef || 21514 currentStencilFuncMask !== stencilMask ) { 21515 21516 gl.stencilFunc( stencilFunc, stencilRef, stencilMask ); 21517 21518 currentStencilFunc = stencilFunc; 21519 currentStencilRef = stencilRef; 21520 currentStencilFuncMask = stencilMask; 21521 21522 } 21523 21524 }, 21525 21526 setOp: function ( stencilFail, stencilZFail, stencilZPass ) { 21527 21528 if ( currentStencilFail !== stencilFail || 21529 currentStencilZFail !== stencilZFail || 21530 currentStencilZPass !== stencilZPass ) { 21531 21532 gl.stencilOp( stencilFail, stencilZFail, stencilZPass ); 21533 21534 currentStencilFail = stencilFail; 21535 currentStencilZFail = stencilZFail; 21536 currentStencilZPass = stencilZPass; 21537 21538 } 21539 21540 }, 21541 21542 setLocked: function ( lock ) { 21543 21544 locked = lock; 21545 21546 }, 21547 21548 setClear: function ( stencil ) { 21549 21550 if ( currentStencilClear !== stencil ) { 21551 21552 gl.clearStencil( stencil ); 21553 currentStencilClear = stencil; 21554 21555 } 21556 21557 }, 21558 21559 reset: function () { 21560 21561 locked = false; 21562 21563 currentStencilMask = null; 21564 currentStencilFunc = null; 21565 currentStencilRef = null; 21566 currentStencilFuncMask = null; 21567 currentStencilFail = null; 21568 currentStencilZFail = null; 21569 currentStencilZPass = null; 21570 currentStencilClear = null; 21571 21572 } 21573 21574 }; 21575 21576 } 21577 21578 // 21579 21580 const colorBuffer = new ColorBuffer(); 21581 const depthBuffer = new DepthBuffer(); 21582 const stencilBuffer = new StencilBuffer(); 21583 21584 const uboBindings = new WeakMap(); 21585 const uboProgramMap = new WeakMap(); 21586 21587 let enabledCapabilities = {}; 21588 21589 let currentBoundFramebuffers = {}; 21590 let currentDrawbuffers = new WeakMap(); 21591 let defaultDrawbuffers = []; 21592 21593 let currentProgram = null; 21594 21595 let currentBlendingEnabled = false; 21596 let currentBlending = null; 21597 let currentBlendEquation = null; 21598 let currentBlendSrc = null; 21599 let currentBlendDst = null; 21600 let currentBlendEquationAlpha = null; 21601 let currentBlendSrcAlpha = null; 21602 let currentBlendDstAlpha = null; 21603 let currentPremultipledAlpha = false; 21604 21605 let currentFlipSided = null; 21606 let currentCullFace = null; 21607 21608 let currentLineWidth = null; 21609 21610 let currentPolygonOffsetFactor = null; 21611 let currentPolygonOffsetUnits = null; 21612 21613 const maxTextures = gl.getParameter( 35661 ); 21614 21615 let lineWidthAvailable = false; 21616 let version = 0; 21617 const glVersion = gl.getParameter( 7938 ); 21618 21619 if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) { 21620 21621 version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] ); 21622 lineWidthAvailable = ( version >= 1.0 ); 21623 21624 } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) { 21625 21626 version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] ); 21627 lineWidthAvailable = ( version >= 2.0 ); 21628 21629 } 21630 21631 let currentTextureSlot = null; 21632 let currentBoundTextures = {}; 21633 21634 const scissorParam = gl.getParameter( 3088 ); 21635 const viewportParam = gl.getParameter( 2978 ); 21636 21637 const currentScissor = new Vector4().fromArray( scissorParam ); 21638 const currentViewport = new Vector4().fromArray( viewportParam ); 21639 21640 function createTexture( type, target, count ) { 21641 21642 const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. 21643 const texture = gl.createTexture(); 21644 21645 gl.bindTexture( type, texture ); 21646 gl.texParameteri( type, 10241, 9728 ); 21647 gl.texParameteri( type, 10240, 9728 ); 21648 21649 for ( let i = 0; i < count; i ++ ) { 21650 21651 gl.texImage2D( target + i, 0, 6408, 1, 1, 0, 6408, 5121, data ); 21652 21653 } 21654 21655 return texture; 21656 21657 } 21658 21659 const emptyTextures = {}; 21660 emptyTextures[ 3553 ] = createTexture( 3553, 3553, 1 ); 21661 emptyTextures[ 34067 ] = createTexture( 34067, 34069, 6 ); 21662 21663 // init 21664 21665 colorBuffer.setClear( 0, 0, 0, 1 ); 21666 depthBuffer.setClear( 1 ); 21667 stencilBuffer.setClear( 0 ); 21668 21669 enable( 2929 ); 21670 depthBuffer.setFunc( LessEqualDepth ); 21671 21672 setFlipSided( false ); 21673 setCullFace( CullFaceBack ); 21674 enable( 2884 ); 21675 21676 setBlending( NoBlending ); 21677 21678 // 21679 21680 function enable( id ) { 21681 21682 if ( enabledCapabilities[ id ] !== true ) { 21683 21684 gl.enable( id ); 21685 enabledCapabilities[ id ] = true; 21686 21687 } 21688 21689 } 21690 21691 function disable( id ) { 21692 21693 if ( enabledCapabilities[ id ] !== false ) { 21694 21695 gl.disable( id ); 21696 enabledCapabilities[ id ] = false;
21697 21698 } 21699 21700 } 21701 21702 function bindFramebuffer( target, framebuffer ) { 21703 21704 if ( currentBoundFramebuffers[ target ] !== framebuffer ) { 21705 21706 gl.bindFramebuffer( target, framebuffer ); 21707 21708 currentBoundFramebuffers[ target ] = framebuffer; 21709 21710 if ( isWebGL2 ) { 21711 21712 // 36009 is equivalent to 36160 21713 21714 if ( target === 36009 ) { 21715 21716 currentBoundFramebuffers[ 36160 ] = framebuffer; 21717 21718 } 21719 21720 if ( target === 36160 ) { 21721 21722 currentBoundFramebuffers[ 36009 ] = framebuffer; 21723 21724 } 21725 21726 } 21727 21728 return true; 21729 21730 } 21731 21732 return false; 21733 21734 } 21735 21736 function drawBuffers( renderTarget, framebuffer ) { 21737 21738 let drawBuffers = defaultDrawbuffers; 21739 21740 let needsUpdate = false; 21741 21742 if ( renderTarget ) { 21743 21744 drawBuffers = currentDrawbuffers.get( framebuffer ); 21745 21746 if ( drawBuffers === undefined ) { 21747 21748 drawBuffers = []; 21749 currentDrawbuffers.set( framebuffer, drawBuffers ); 21750 21751 } 21752 21753 if ( renderTarget.isWebGLMultipleRenderTargets ) { 21754 21755 const textures = renderTarget.texture; 21756 21757 if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== 36064 ) { 21758 21759 for ( let i = 0, il = textures.length; i < il; i ++ ) { 21760 21761 drawBuffers[ i ] = 36064 + i; 21762 21763 } 21764 21765 drawBuffers.length = textures.length; 21766 21767 needsUpdate = true; 21768 21769 } 21770 21771 } else { 21772 21773 if ( drawBuffers[ 0 ] !== 36064 ) { 21774 21775 drawBuffers[ 0 ] = 36064; 21776 21777 needsUpdate = true; 21778 21779 } 21780 21781 } 21782 21783 } else { 21784 21785 if ( drawBuffers[ 0 ] !== 1029 ) { 21786 21787 drawBuffers[ 0 ] = 1029; 21788 21789 needsUpdate = true; 21790 21791 } 21792 21793 } 21794 21795 if ( needsUpdate ) { 21796 21797 if ( capabilities.isWebGL2 ) { 21798 21799 gl.drawBuffers( drawBuffers ); 21800 21801 } else { 21802 21803 extensions.get( 'WEBGL_draw_buffers' ).drawBuffersWEBGL( drawBuffers ); 21804 21805 } 21806 21807 } 21808 21809 21810 } 21811 21812 function useProgram( program ) { 21813 21814 if ( currentProgram !== program ) { 21815 21816 gl.useProgram( program ); 21817 21818 currentProgram = program; 21819 21820 return true; 21821 21822 } 21823 21824 return false; 21825 21826 } 21827 21828 const equationToGL = { 21829 [ AddEquation ]: 32774, 21830 [ SubtractEquation ]: 32778, 21831 [ ReverseSubtractEquation ]: 32779 21832 }; 21833 21834 if ( isWebGL2 ) { 21835 21836 equationToGL[ MinEquation ] = 32775; 21837 equationToGL[ MaxEquation ] = 32776; 21838 21839 } else { 21840 21841 const extension = extensions.get( 'EXT_blend_minmax' ); 21842 21843 if ( extension !== null ) { 21844 21845 equationToGL[ MinEquation ] = extension.MIN_EXT; 21846 equationToGL[ MaxEquation ] = extension.MAX_EXT; 21847 21848 } 21849 21850 } 21851 21852 const factorToGL = { 21853 [ ZeroFactor ]: 0, 21854 [ OneFactor ]: 1, 21855 [ SrcColorFactor ]: 768, 21856 [ SrcAlphaFactor ]: 770, 21857 [ SrcAlphaSaturateFactor ]: 776, 21858 [ DstColorFactor ]: 774, 21859 [ DstAlphaFactor ]: 772, 21860 [ OneMinusSrcColorFactor ]: 769, 21861 [ OneMinusSrcAlphaFactor ]: 771, 21862 [ OneMinusDstColorFactor ]: 775, 21863 [ OneMinusDstAlphaFactor ]: 773 21864 }; 21865 21866 function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { 21867 21868 if ( blending === NoBlending ) { 21869 21870 if ( currentBlendingEnabled === true ) { 21871 21872 disable( 3042 ); 21873 currentBlendingEnabled = false; 21874 21875 } 21876 21877 return; 21878 21879 } 21880 21881 if ( currentBlendingEnabled === false ) { 21882 21883 enable( 3042 ); 21884 currentBlendingEnabled = true; 21885 21886 } 21887 21888 if ( blending !== CustomBlending ) { 21889 21890 if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { 21891 21892 if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) { 21893 21894 gl.blendEquation( 32774 ); 21895 21896 currentBlendEquation = AddEquation; 21897 currentBlendEquationAlpha = AddEquation; 21898 21899 } 21900 21901 if ( premultipliedAlpha ) { 21902 21903 switch ( blending ) { 21904 21905 case NormalBlending: 21906 gl.blendFuncSeparate( 1, 771, 1, 771 ); 21907 break; 21908 21909 case AdditiveBlending: 21910 gl.blendFunc( 1, 1 ); 21911 break; 21912 21913 case SubtractiveBlending: 21914 gl.blendFuncSeparate( 0, 769, 0, 1 ); 21915 break; 21916 21917 case MultiplyBlending: 21918 gl.blendFuncSeparate( 0, 768, 0, 770 ); 21919 break; 21920 21921 default: 21922 console.error( 'THREE.WebGLState: Invalid blending: ', blending ); 21923 break; 21924 21925 } 21926 21927 } else { 21928 21929 switch ( blending ) { 21930 21931 case NormalBlending: 21932 gl.blendFuncSeparate( 770, 771, 1, 771 ); 21933 break; 21934 21935 case AdditiveBlending: 21936 gl.blendFunc( 770, 1 ); 21937 break; 21938 21939 case SubtractiveBlending: 21940 gl.blendFuncSeparate( 0, 769, 0, 1 ); 21941 break; 21942 21943 case MultiplyBlending: 21944 gl.blendFunc( 0, 768 ); 21945 break; 21946 21947 default: 21948 console.error( 'THREE.WebGLState: Invalid blending: ', blending ); 21949 break; 21950 21951 } 21952 21953 } 21954 21955 currentBlendSrc = null; 21956 currentBlendDst = null; 21957 currentBlendSrcAlpha = null; 21958 currentBlendDstAlpha = null; 21959 21960 currentBlending = blending; 21961 currentPremultipledAlpha = premultipliedAlpha; 21962 21963 } 21964 21965 return; 21966 21967 } 21968 21969 // custom blending 21970 21971 blendEquationAlpha = blendEquationAlpha || blendEquation; 21972 blendSrcAlpha = blendSrcAlpha || blendSrc; 21973 blendDstAlpha = blendDstAlpha || blendDst; 21974 21975 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { 21976 21977 gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] ); 21978 21979 currentBlendEquation = blendEquation; 21980 currentBlendEquationAlpha = blendEquationAlpha; 21981 21982 } 21983 21984 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { 21985 21986 gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] ); 21987 21988 currentBlendSrc = blendSrc; 21989 currentBlendDst = blendDst; 21990 currentBlendSrcAlpha = blendSrcAlpha; 21991 currentBlendDstAlpha = blendDstAlpha; 21992 21993 } 21994 21995 currentBlending = blending; 21996 currentPremultipledAlpha = false;
21997 21998 } 21999 22000 function setMaterial( material, frontFaceCW ) { 22001 22002 material.side === DoubleSide 22003 ? disable( 2884 ) 22004 : enable( 2884 ); 22005 22006 let flipSided = ( material.side === BackSide ); 22007 if ( frontFaceCW ) flipSided = ! flipSided; 22008 22009 setFlipSided( flipSided ); 22010 22011 ( material.blending === NormalBlending && material.transparent === false ) 22012 ? setBlending( NoBlending ) 22013 : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ); 22014 22015 depthBuffer.setFunc( material.depthFunc ); 22016 depthBuffer.setTest( material.depthTest ); 22017 depthBuffer.setMask( material.depthWrite ); 22018 colorBuffer.setMask( material.colorWrite ); 22019 22020 const stencilWrite = material.stencilWrite; 22021 stencilBuffer.setTest( stencilWrite ); 22022 if ( stencilWrite ) { 22023 22024 stencilBuffer.setMask( material.stencilWriteMask ); 22025 stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask ); 22026 stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass ); 22027 22028 } 22029 22030 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); 22031 22032 material.alphaToCoverage === true 22033 ? enable( 32926 ) 22034 : disable( 32926 ); 22035 22036 } 22037 22038 // 22039 22040 function setFlipSided( flipSided ) { 22041 22042 if ( currentFlipSided !== flipSided ) { 22043 22044 if ( flipSided ) { 22045 22046 gl.frontFace( 2304 ); 22047 22048 } else { 22049 22050 gl.frontFace( 2305 ); 22051 22052 } 22053 22054 currentFlipSided = flipSided; 22055 22056 } 22057 22058 } 22059 22060 function setCullFace( cullFace ) { 22061 22062 if ( cullFace !== CullFaceNone ) { 22063 22064 enable( 2884 ); 22065 22066 if ( cullFace !== currentCullFace ) { 22067 22068 if ( cullFace === CullFaceBack ) { 22069 22070 gl.cullFace( 1029 ); 22071 22072 } else if ( cullFace === CullFaceFront ) { 22073 22074 gl.cullFace( 1028 ); 22075 22076 } else { 22077 22078 gl.cullFace( 1032 ); 22079 22080 } 22081 22082 } 22083 22084 } else { 22085 22086 disable( 2884 ); 22087 22088 } 22089 22090 currentCullFace = cullFace; 22091 22092 } 22093 22094 function setLineWidth( width ) { 22095 22096 if ( width !== currentLineWidth ) { 22097 22098 if ( lineWidthAvailable ) gl.lineWidth( width ); 22099 22100 currentLineWidth = width; 22101 22102 } 22103 22104 } 22105 22106 function setPolygonOffset( polygonOffset, factor, units ) { 22107 22108 if ( polygonOffset ) { 22109 22110 enable( 32823 ); 22111 22112 if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { 22113 22114 gl.polygonOffset( factor, units ); 22115 22116 currentPolygonOffsetFactor = factor; 22117 currentPolygonOffsetUnits = units; 22118 22119 } 22120 22121 } else { 22122 22123 disable( 32823 ); 22124 22125 } 22126 22127 } 22128 22129 function setScissorTest( scissorTest ) { 22130 22131 if ( scissorTest ) { 22132 22133 enable( 3089 ); 22134 22135 } else { 22136 22137 disable( 3089 ); 22138 22139 } 22140 22141 } 22142 22143 // texture 22144 22145 function activeTexture( webglSlot ) { 22146 22147 if ( webglSlot === undefined ) webglSlot = 33984 + maxTextures - 1; 22148 22149 if ( currentTextureSlot !== webglSlot ) { 22150 22151 gl.activeTexture( webglSlot ); 22152 currentTextureSlot = webglSlot; 22153 22154 } 22155 22156 } 22157 22158 function bindTexture( webglType, webglTexture, webglSlot ) { 22159 22160 if ( webglSlot === undefined ) { 22161 22162 if ( currentTextureSlot === null ) { 22163 22164 webglSlot = 33984 + maxTextures - 1; 22165 22166 } else { 22167 22168 webglSlot = currentTextureSlot; 22169 22170 } 22171 22172 } 22173 22174 let boundTexture = currentBoundTextures[ webglSlot ]; 22175 22176 if ( boundTexture === undefined ) { 22177 22178 boundTexture = { type: undefined, texture: undefined }; 22179 currentBoundTextures[ webglSlot ] = boundTexture; 22180 22181 } 22182 22183 if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { 22184 22185 if ( currentTextureSlot !== webglSlot ) { 22186 22187 gl.activeTexture( webglSlot ); 22188 currentTextureSlot = webglSlot; 22189 22190 } 22191 22192 gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] ); 22193 22194 boundTexture.type = webglType; 22195 boundTexture.texture = webglTexture; 22196 22197 } 22198 22199 } 22200 22201 function unbindTexture() { 22202 22203 const boundTexture = currentBoundTextures[ currentTextureSlot ]; 22204 22205 if ( boundTexture !== undefined && boundTexture.type !== undefined ) { 22206 22207 gl.bindTexture( boundTexture.type, null ); 22208 22209 boundTexture.type = undefined; 22210 boundTexture.texture = undefined; 22211 22212 } 22213 22214 } 22215 22216 function compressedTexImage2D() { 22217 22218 try { 22219 22220 gl.compressedTexImage2D.apply( gl, arguments ); 22221 22222 } catch ( error ) { 22223 22224 console.error( 'THREE.WebGLState:', error ); 22225 22226 } 22227 22228 } 22229 22230 function compressedTexImage3D() { 22231 22232 try { 22233 22234 gl.compressedTexImage3D.apply( gl, arguments ); 22235 22236 } catch ( error ) { 22237 22238 console.error( 'THREE.WebGLState:', error ); 22239 22240 } 22241 22242 } 22243 22244 function texSubImage2D() { 22245 22246 try { 22247 22248 gl.texSubImage2D.apply( gl, arguments ); 22249 22250 } catch ( error ) { 22251 22252 console.error( 'THREE.WebGLState:', error ); 22253 22254 } 22255 22256 } 22257 22258 function texSubImage3D() { 22259 22260 try { 22261 22262 gl.texSubImage3D.apply( gl, arguments ); 22263 22264 } catch ( error ) { 22265 22266 console.error( 'THREE.WebGLState:', error ); 22267 22268 } 22269 22270 } 22271 22272 function compressedTexSubImage2D() { 22273 22274 try { 22275 22276 gl.compressedTexSubImage2D.apply( gl, arguments ); 22277 22278 } catch ( error ) { 22279 22280 console.error( 'THREE.WebGLState:', error ); 22281 22282 } 22283 22284 } 22285 22286 function compressedTexSubImage3D() { 22287 22288 try { 22289 22290 gl.compressedTexSubImage3D.apply( gl, arguments ); 22291 22292 } catch ( error ) { 22293 22294 console.error( 'THREE.WebGLState:', error ); 22295 22296 } 22297 22298 } 22299 22300 function texStorage2D() { 22301 22302 try { 22303 22304 gl.texStorage2D.apply( gl, arguments ); 22305 22306 } catch ( error ) { 22307 22308 console.error( 'THREE.WebGLState:', error ); 22309 22310 } 22311 22312 } 22313 22314 function texStorage3D() { 22315 22316 try { 22317 22318 gl.texStorage3D.apply( gl, arguments ); 22319 22320 } catch ( error ) { 22321 22322 console.error( 'THREE.WebGLState:', error ); 22323 22324 } 22325 22326 } 22327 22328 function texImage2D() { 22329 22330 try { 22331 22332 gl.texImage2D.apply( gl, arguments ); 22333 22334 } catch ( error ) { 22335 22336 console.error( 'THREE.WebGLState:', error ); 22337 22338 } 22339 22340 } 22341 22342 function texImage3D() { 22343 22344 try { 22345 22346 gl.texImage3D.apply( gl, arguments ); 22347 22348 } catch ( error ) { 22349 22350 console.error( 'THREE.WebGLState:', error ); 22351 22352 } 22353 22354 } 22355 22356 // 22357 22358 function scissor( scissor ) { 22359 22360 if ( currentScissor.equals( scissor ) === false ) { 22361 22362 gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w ); 22363 currentScissor.copy( scissor ); 22364 22365 } 22366 22367 } 22368 22369 function viewport( viewport ) { 22370 22371 if ( currentViewport.equals( viewport ) === false ) { 22372 22373 gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w ); 22374 currentViewport.copy( viewport ); 22375 22376 } 22377 22378 } 22379 22380 function updateUBOMapping( uniformsGroup, program ) { 22381 22382 let mapping = uboProgramMap.get( program ); 22383 22384 if ( mapping === undefined ) { 22385 22386 mapping = new WeakMap(); 22387 22388 uboProgramMap.set( program, mapping ); 22389 22390 } 22391 22392 let blockIndex = mapping.get( uniformsGroup ); 22393 22394 if ( blockIndex === undefined ) { 22395 22396 blockIndex = gl.getUniformBlockIndex( program, uniformsGroup.name ); 22397 22398 mapping.set( uniformsGroup, blockIndex ); 22399 22400 } 22401 22402 } 22403 22404 function uniformBlockBinding( uniformsGroup, program ) { 22405 22406 const mapping = uboProgramMap.get( program ); 22407 const blockIndex = mapping.get( uniformsGroup ); 22408 22409 if ( uboBindings.get( program ) !== blockIndex ) { 22410 22411 // bind shader specific block index to global block point 22412 gl.uniformBlockBinding( program, blockIndex, uniformsGroup.__bindingPointIndex ); 22413 22414 uboBindings.set( program, blockIndex ); 22415 22416 } 22417 22418 } 22419 22420 // 22421 22422 function reset() { 22423 22424 // reset state 22425 22426 gl.disable( 3042 ); 22427 gl.disable( 2884 ); 22428 gl.disable( 2929 ); 22429 gl.disable( 32823 ); 22430 gl.disable( 3089 ); 22431 gl.disable( 2960 ); 22432 gl.disable( 32926 ); 22433 22434 gl.blendEquation( 32774 ); 22435 gl.blendFunc( 1, 0 ); 22436 gl.blendFuncSeparate( 1, 0, 1, 0 ); 22437 22438 gl.colorMask( true, true, true, true ); 22439 gl.clearColor( 0, 0, 0, 0 ); 22440 22441 gl.depthMask( true ); 22442 gl.depthFunc( 513 ); 22443 gl.clearDepth( 1 ); 22444 22445 gl.stencilMask( 0xffffffff ); 22446 gl.stencilFunc( 519, 0, 0xffffffff ); 22447 gl.stencilOp( 7680, 7680, 7680 ); 22448 gl.clearStencil( 0 ); 22449 22450 gl.cullFace( 1029 ); 22451 gl.frontFace( 2305 ); 22452 22453 gl.polygonOffset( 0, 0 ); 22454 22455 gl.activeTexture( 33984 ); 22456 22457 gl.bindFramebuffer( 36160, null ); 22458 22459 if ( isWebGL2 === true ) { 22460 22461 gl.bindFramebuffer( 36009, null ); 22462 gl.bindFramebuffer( 36008, null ); 22463 22464 } 22465 22466 gl.useProgram( null ); 22467 22468 gl.lineWidth( 1 ); 22469 22470 gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height ); 22471 gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height ); 22472 22473 // reset internals 22474 22475 enabledCapabilities = {}; 22476 22477 currentTextureSlot = null; 22478 currentBoundTextures = {}; 22479 22480 currentBoundFramebuffers = {};
vendor: 4,181 bytes, lines 22481-22636
22481 currentDrawbuffers = new WeakMap(); 22482 defaultDrawbuffers = []; 22483 22484 currentProgram = null; 22485 22486 currentBlendingEnabled = false; 22487 currentBlending = null; 22488 currentBlendEquation = null; 22489 currentBlendSrc = null; 22490 currentBlendDst = null; 22491 currentBlendEquationAlpha = null; 22492 currentBlendSrcAlpha = null; 22493 currentBlendDstAlpha = null; 22494 currentPremultipledAlpha = false; 22495 22496 currentFlipSided = null; 22497 currentCullFace = null; 22498 22499 currentLineWidth = null; 22500 22501 currentPolygonOffsetFactor = null; 22502 currentPolygonOffsetUnits = null; 22503 22504 currentScissor.set( 0, 0, gl.canvas.width, gl.canvas.height ); 22505 currentViewport.set( 0, 0, gl.canvas.width, gl.canvas.height ); 22506 22507 colorBuffer.reset(); 22508 depthBuffer.reset(); 22509 stencilBuffer.reset(); 22510 22511 } 22512 22513 return { 22514 22515 buffers: { 22516 color: colorBuffer, 22517 depth: depthBuffer, 22518 stencil: stencilBuffer 22519 }, 22520 22521 enable: enable, 22522 disable: disable, 22523 22524 bindFramebuffer: bindFramebuffer, 22525 drawBuffers: drawBuffers, 22526 22527 useProgram: useProgram, 22528 22529 setBlending: setBlending, 22530 setMaterial: setMaterial, 22531 22532 setFlipSided: setFlipSided, 22533 setCullFace: setCullFace, 22534 22535 setLineWidth: setLineWidth, 22536 setPolygonOffset: setPolygonOffset, 22537 22538 setScissorTest: setScissorTest, 22539 22540 activeTexture: activeTexture, 22541 bindTexture: bindTexture, 22542 unbindTexture: unbindTexture, 22543 compressedTexImage2D: compressedTexImage2D, 22544 compressedTexImage3D: compressedTexImage3D, 22545 texImage2D: texImage2D, 22546 texImage3D: texImage3D, 22547 22548 updateUBOMapping: updateUBOMapping, 22549 uniformBlockBinding: uniformBlockBinding, 22550 22551 texStorage2D: texStorage2D, 22552 texStorage3D: texStorage3D, 22553 texSubImage2D: texSubImage2D, 22554 texSubImage3D: texSubImage3D, 22555 compressedTexSubImage2D: compressedTexSubImage2D, 22556 compressedTexSubImage3D: compressedTexSubImage3D, 22557 22558 scissor: scissor, 22559 viewport: viewport, 22560 22561 reset: reset 22562 22563 }; 22564 22565} 22566 22567function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) { 22568 22569 const isWebGL2 = capabilities.isWebGL2; 22570 const maxTextures = capabilities.maxTextures; 22571 const maxCubemapSize = capabilities.maxCubemapSize; 22572 const maxTextureSize = capabilities.maxTextureSize; 22573 const maxSamples = capabilities.maxSamples; 22574 const multisampledRTTExt = extensions.has( 'WEBGL_multisampled_render_to_texture' ) ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : null; 22575 const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test( navigator.userAgent ); 22576 22577 const _videoTextures = new WeakMap(); 22578 let _canvas; 22579 22580 const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source 22581 22582 // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas, 22583 // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")! 22584 // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d). 22585 22586 let useOffscreenCanvas = false; 22587 22588 try { 22589 22590 useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' 22591 // eslint-disable-next-line compat/compat 22592 && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null; 22593 22594 } catch ( err ) { 22595 22596 // Ignore any errors 22597 22598 } 22599 22600 function createCanvas( width, height ) { 22601 22602 // Use OffscreenCanvas when available. Specially needed in web workers 22603 22604 return useOffscreenCanvas ? 22605 // eslint-disable-next-line compat/compat 22606 new OffscreenCanvas( width, height ) : createElementNS( 'canvas' ); 22607 22608 } 22609 22610 function resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) { 22611 22612 let scale = 1; 22613 22614 // handle case if texture exceeds max size 22615 22616 if ( image.width > maxSize || image.height > maxSize ) { 22617 22618 scale = maxSize / Math.max( image.width, image.height ); 22619 22620 } 22621 22622 // only perform resize if necessary 22623 22624 if ( scale < 1 || needsPowerOfTwo === true ) { 22625 22626 // only perform resize for certain image types 22627 22628 if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || 22629 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || 22630 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { 22631 22632 const floor = needsPowerOfTwo ? floorPowerOfTwo : Math.floor; 22633 22634 const width = floor( scale * image.width ); 22635 const height = floor( scale * image.height ); 22636
22637 if ( _canvas === undefined ) _canvas = createCanvas( width, height ); 22638 22639 // cube textures can't reuse the same canvas 22640 22641 const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas; 22642 22643 canvas.width = width; 22644 canvas.height = height; 22645 22646 const context = canvas.getContext( '2d' ); 22647 context.drawImage( image, 0, 0, width, height ); 22648 22649 console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' ); 22650 22651 return canvas; 22652 22653 } else { 22654 22655 if ( 'data' in image ) { 22656 22657 console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' ); 22658 22659 } 22660 22661 return image; 22662 22663 } 22664 22665 } 22666 22667 return image; 22668 22669 } 22670 22671 function isPowerOfTwo$1( image ) { 22672 22673 return isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ); 22674 22675 } 22676 22677 function textureNeedsPowerOfTwo( texture ) { 22678 22679 if ( isWebGL2 ) return false; 22680 22681 return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) || 22682 ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ); 22683 22684 } 22685 22686 function textureNeedsGenerateMipmaps( texture, supportsMips ) { 22687 22688 return texture.generateMipmaps && supportsMips && 22689 texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; 22690 22691 } 22692 22693 function generateMipmap( target ) { 22694 22695 _gl.generateMipmap( target ); 22696 22697 } 22698 22699 function getInternalFormat( internalFormatName, glFormat, glType, encoding, forceLinearEncoding = false ) { 22700 22701 if ( isWebGL2 === false ) return glFormat; 22702 22703 if ( internalFormatName !== null ) { 22704 22705 if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ]; 22706 22707 console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' ); 22708 22709 } 22710 22711 let internalFormat = glFormat; 22712 22713 if ( glFormat === 6403 ) { 22714 22715 if ( glType === 5126 ) internalFormat = 33326; 22716 if ( glType === 5131 ) internalFormat = 33325; 22717 if ( glType === 5121 ) internalFormat = 33321; 22718 22719 } 22720 22721 if ( glFormat === 33319 ) { 22722 22723 if ( glType === 5126 ) internalFormat = 33328; 22724 if ( glType === 5131 ) internalFormat = 33327; 22725 if ( glType === 5121 ) internalFormat = 33323; 22726 22727 } 22728 22729 if ( glFormat === 6408 ) { 22730 22731 if ( glType === 5126 ) internalFormat = 34836; 22732 if ( glType === 5131 ) internalFormat = 34842; 22733 if ( glType === 5121 ) internalFormat = ( encoding === sRGBEncoding && forceLinearEncoding === false ) ? 35907 : 32856; 22734 if ( glType === 32819 ) internalFormat = 32854; 22735 if ( glType === 32820 ) internalFormat = 32855; 22736 22737 } 22738 22739 if ( internalFormat === 33325 || internalFormat === 33326 || 22740 internalFormat === 33327 || internalFormat === 33328 || 22741 internalFormat === 34842 || internalFormat === 34836 ) { 22742 22743 extensions.get( 'EXT_color_buffer_float' ); 22744 22745 } 22746 22747 return internalFormat; 22748 22749 } 22750 22751 function getMipLevels( texture, image, supportsMips ) { 22752 22753 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) === true || ( texture.isFramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) ) { 22754 22755 return Math.log2( Math.max( image.width, image.height ) ) + 1; 22756 22757 } else if ( texture.mipmaps !== undefined && texture.mipmaps.length > 0 ) { 22758 22759 // user-defined mipmaps 22760 22761 return texture.mipmaps.length; 22762 22763 } else if ( texture.isCompressedTexture && Array.isArray( texture.image ) ) { 22764 22765 return image.mipmaps.length; 22766 22767 } else { 22768 22769 // texture without mipmaps (only base level) 22770 22771 return 1; 22772 22773 } 22774 22775 } 22776 22777 // Fallback filters for non-power-of-2 textures 22778 22779 function filterFallback( f ) { 22780 22781 if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) { 22782 22783 return 9728; 22784 22785 } 22786 22787 return 9729; 22788 22789 } 22790 22791 // 22792 22793 function onTextureDispose( event ) { 22794 22795 const texture = event.target; 22796 22797 texture.removeEventListener( 'dispose', onTextureDispose ); 22798 22799 deallocateTexture( texture ); 22800 22801 if ( texture.isVideoTexture ) { 22802 22803 _videoTextures.delete( texture ); 22804 22805 } 22806 22807 } 22808 22809 function onRenderTargetDispose( event ) { 22810 22811 const renderTarget = event.target; 22812 22813 renderTarget.removeEventListener( 'dispose', onRenderTargetDispose ); 22814 22815 deallocateRenderTarget( renderTarget ); 22816 22817 } 22818 22819 // 22820 22821 function deallocateTexture( texture ) { 22822 22823 const textureProperties = properties.get( texture ); 22824 22825 if ( textureProperties.__webglInit === undefined ) return; 22826 22827 // check if it's necessary to remove the WebGLTexture object 22828 22829 const source = texture.source; 22830 const webglTextures = _sources.get( source ); 22831 22832 if ( webglTextures ) { 22833 22834 const webglTexture = webglTextures[ textureProperties.__cacheKey ]; 22835 webglTexture.usedTimes --; 22836 22837 // the WebGLTexture object is not used anymore, remove it 22838 22839 if ( webglTexture.usedTimes === 0 ) { 22840 22841 deleteTexture( texture ); 22842 22843 } 22844 22845 // remove the weak map entry if no WebGLTexture uses the source anymore 22846 22847 if ( Object.keys( webglTextures ).length === 0 ) { 22848 22849 _sources.delete( source ); 22850 22851 } 22852 22853 } 22854 22855 properties.remove( texture ); 22856 22857 } 22858 22859 function deleteTexture( texture ) { 22860 22861 const textureProperties = properties.get( texture ); 22862 _gl.deleteTexture( textureProperties.__webglTexture ); 22863 22864 const source = texture.source; 22865 const webglTextures = _sources.get( source ); 22866 delete webglTextures[ textureProperties.__cacheKey ]; 22867 22868 info.memory.textures --; 22869 22870 } 22871 22872 function deallocateRenderTarget( renderTarget ) { 22873 22874 const texture = renderTarget.texture; 22875 22876 const renderTargetProperties = properties.get( renderTarget ); 22877 const textureProperties = properties.get( texture ); 22878 22879 if ( textureProperties.__webglTexture !== undefined ) { 22880 22881 _gl.deleteTexture( textureProperties.__webglTexture ); 22882 22883 info.memory.textures --; 22884 22885 } 22886 22887 if ( renderTarget.depthTexture ) { 22888 22889 renderTarget.depthTexture.dispose(); 22890 22891 } 22892
22893 if ( renderTarget.isWebGLCubeRenderTarget ) { 22894 22895 for ( let i = 0; i < 6; i ++ ) { 22896 22897 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] ); 22898 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); 22899 22900 } 22901 22902 } else { 22903 22904 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer ); 22905 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); 22906 if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer ); 22907 22908 if ( renderTargetProperties.__webglColorRenderbuffer ) { 22909 22910 for ( let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i ++ ) { 22911 22912 if ( renderTargetProperties.__webglColorRenderbuffer[ i ] ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer[ i ] ); 22913 22914 } 22915 22916 } 22917 22918 if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer ); 22919 22920 } 22921 22922 if ( renderTarget.isWebGLMultipleRenderTargets ) { 22923 22924 for ( let i = 0, il = texture.length; i < il; i ++ ) { 22925 22926 const attachmentProperties = properties.get( texture[ i ] ); 22927 22928 if ( attachmentProperties.__webglTexture ) { 22929 22930 _gl.deleteTexture( attachmentProperties.__webglTexture ); 22931 22932 info.memory.textures --; 22933 22934 } 22935 22936 properties.remove( texture[ i ] ); 22937 22938 } 22939 22940 } 22941 22942 properties.remove( texture ); 22943 properties.remove( renderTarget ); 22944 22945 } 22946 22947 // 22948 22949 let textureUnits = 0; 22950 22951 function resetTextureUnits() { 22952 22953 textureUnits = 0; 22954 22955 } 22956 22957 function allocateTextureUnit() { 22958 22959 const textureUnit = textureUnits; 22960 22961 if ( textureUnit >= maxTextures ) { 22962 22963 console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures ); 22964 22965 } 22966 22967 textureUnits += 1; 22968 22969 return textureUnit; 22970 22971 } 22972 22973 function getTextureCacheKey( texture ) { 22974 22975 const array = []; 22976 22977 array.push( texture.wrapS ); 22978 array.push( texture.wrapT ); 22979 array.push( texture.wrapR || 0 ); 22980 array.push( texture.magFilter ); 22981 array.push( texture.minFilter ); 22982 array.push( texture.anisotropy ); 22983 array.push( texture.internalFormat ); 22984 array.push( texture.format ); 22985 array.push( texture.type ); 22986 array.push( texture.generateMipmaps ); 22987 array.push( texture.premultiplyAlpha ); 22988 array.push( texture.flipY ); 22989 array.push( texture.unpackAlignment ); 22990 array.push( texture.encoding ); 22991 22992 return array.join(); 22993 22994 } 22995 22996 // 22997 22998 function setTexture2D( texture, slot ) { 22999 23000 const textureProperties = properties.get( texture ); 23001 23002 if ( texture.isVideoTexture ) updateVideoTexture( texture ); 23003 23004 if ( texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version ) { 23005 23006 const image = texture.image; 23007 23008 if ( image === null ) { 23009 23010 console.warn( 'THREE.WebGLRenderer: Texture marked for update but no image data found.' ); 23011 23012 } else if ( image.complete === false ) { 23013 23014 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' ); 23015 23016 } else { 23017 23018 uploadTexture( textureProperties, texture, slot ); 23019 return; 23020 23021 } 23022 23023 } 23024 23025 state.bindTexture( 3553, textureProperties.__webglTexture, 33984 + slot ); 23026 23027 } 23028 23029 function setTexture2DArray( texture, slot ) { 23030 23031 const textureProperties = properties.get( texture ); 23032 23033 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 23034 23035 uploadTexture( textureProperties, texture, slot ); 23036 return; 23037 23038 } 23039 23040 state.bindTexture( 35866, textureProperties.__webglTexture, 33984 + slot ); 23041 23042 } 23043 23044 function setTexture3D( texture, slot ) { 23045 23046 const textureProperties = properties.get( texture ); 23047 23048 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 23049 23050 uploadTexture( textureProperties, texture, slot ); 23051 return; 23052 23053 } 23054 23055 state.bindTexture( 32879, textureProperties.__webglTexture, 33984 + slot ); 23056 23057 } 23058 23059 function setTextureCube( texture, slot ) { 23060 23061 const textureProperties = properties.get( texture ); 23062 23063 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 23064 23065 uploadCubeTexture( textureProperties, texture, slot ); 23066 return; 23067 23068 } 23069 23070 state.bindTexture( 34067, textureProperties.__webglTexture, 33984 + slot ); 23071 23072 } 23073 23074 const wrappingToGL = { 23075 [ RepeatWrapping ]: 10497, 23076 [ ClampToEdgeWrapping ]: 33071, 23077 [ MirroredRepeatWrapping ]: 33648 23078 }; 23079 23080 const filterToGL = { 23081 [ NearestFilter ]: 9728, 23082 [ NearestMipmapNearestFilter ]: 9984, 23083 [ NearestMipmapLinearFilter ]: 9986, 23084 23085 [ LinearFilter ]: 9729, 23086 [ LinearMipmapNearestFilter ]: 9985, 23087 [ LinearMipmapLinearFilter ]: 9987 23088 }; 23089 23090 function setTextureParameters( textureType, texture, supportsMips ) { 23091 23092 if ( supportsMips ) { 23093 23094 _gl.texParameteri( textureType, 10242, wrappingToGL[ texture.wrapS ] ); 23095 _gl.texParameteri( textureType, 10243, wrappingToGL[ texture.wrapT ] ); 23096 23097 if ( textureType === 32879 || textureType === 35866 ) { 23098 23099 _gl.texParameteri( textureType, 32882, wrappingToGL[ texture.wrapR ] ); 23100 23101 } 23102 23103 _gl.texParameteri( textureType, 10240, filterToGL[ texture.magFilter ] ); 23104 _gl.texParameteri( textureType, 10241, filterToGL[ texture.minFilter ] ); 23105 23106 } else { 23107 23108 _gl.texParameteri( textureType, 10242, 33071 ); 23109 _gl.texParameteri( textureType, 10243, 33071 ); 23110 23111 if ( textureType === 32879 || textureType === 35866 ) { 23112 23113 _gl.texParameteri( textureType, 32882, 33071 ); 23114 23115 } 23116 23117 if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) { 23118 23119 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' ); 23120 23121 } 23122 23123 _gl.texParameteri( textureType, 10240, filterFallback( texture.magFilter ) ); 23124 _gl.texParameteri( textureType, 10241, filterFallback( texture.minFilter ) ); 23125 23126 if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) { 23127 23128 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' ); 23129 23130 } 23131 23132 } 23133 23134 if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { 23135 23136 const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); 23137 23138 if ( texture.magFilter === NearestFilter ) return; 23139 if ( texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter ) return; 23140 if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false ) return; // verify extension for WebGL 1 and WebGL 2 23141 if ( isWebGL2 === false && ( texture.type === HalfFloatType && extensions.has( 'OES_texture_half_float_linear' ) === false ) ) return; // verify extension for WebGL 1 only 23142 23143 if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) { 23144 23145 _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) ); 23146 properties.get( texture ).__currentAnisotropy = texture.anisotropy; 23147 23148 } 23149 23150 } 23151 23152 } 23153 23154 function initTexture( textureProperties, texture ) { 23155 23156 let forceUpload = false;
23157 23158 if ( textureProperties.__webglInit === undefined ) { 23159 23160 textureProperties.__webglInit = true; 23161 23162 texture.addEventListener( 'dispose', onTextureDispose ); 23163 23164 } 23165 23166 // create Source <-> WebGLTextures mapping if necessary 23167 23168 const source = texture.source; 23169 let webglTextures = _sources.get( source ); 23170 23171 if ( webglTextures === undefined ) { 23172 23173 webglTextures = {}; 23174 _sources.set( source, webglTextures ); 23175 23176 } 23177 23178 // check if there is already a WebGLTexture object for the given texture parameters 23179 23180 const textureCacheKey = getTextureCacheKey( texture ); 23181 23182 if ( textureCacheKey !== textureProperties.__cacheKey ) { 23183 23184 // if not, create a new instance of WebGLTexture 23185 23186 if ( webglTextures[ textureCacheKey ] === undefined ) { 23187 23188 // create new entry 23189 23190 webglTextures[ textureCacheKey ] = { 23191 texture: _gl.createTexture(), 23192 usedTimes: 0 23193 }; 23194 23195 info.memory.textures ++; 23196 23197 // when a new instance of WebGLTexture was created, a texture upload is required 23198 // even if the image contents are identical 23199 23200 forceUpload = true; 23201 23202 } 23203 23204 webglTextures[ textureCacheKey ].usedTimes ++; 23205 23206 // every time the texture cache key changes, it's necessary to check if an instance of 23207 // WebGLTexture can be deleted in order to avoid a memory leak. 23208 23209 const webglTexture = webglTextures[ textureProperties.__cacheKey ]; 23210 23211 if ( webglTexture !== undefined ) { 23212 23213 webglTextures[ textureProperties.__cacheKey ].usedTimes --; 23214 23215 if ( webglTexture.usedTimes === 0 ) { 23216 23217 deleteTexture( texture ); 23218 23219 } 23220 23221 } 23222 23223 // store references to cache key and WebGLTexture object 23224 23225 textureProperties.__cacheKey = textureCacheKey; 23226 textureProperties.__webglTexture = webglTextures[ textureCacheKey ].texture; 23227 23228 } 23229 23230 return forceUpload; 23231 23232 } 23233 23234 function uploadTexture( textureProperties, texture, slot ) { 23235 23236 let textureType = 3553; 23237 23238 if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = 35866; 23239 if ( texture.isData3DTexture ) textureType = 32879; 23240 23241 const forceUpload = initTexture( textureProperties, texture ); 23242 const source = texture.source; 23243 23244 state.bindTexture( textureType, textureProperties.__webglTexture, 33984 + slot ); 23245 23246 const sourceProperties = properties.get( source ); 23247 23248 if ( source.version !== sourceProperties.__version || forceUpload === true ) { 23249 23250 state.activeTexture( 33984 + slot ); 23251 23252 _gl.pixelStorei( 37440, texture.flipY ); 23253 _gl.pixelStorei( 37441, texture.premultiplyAlpha ); 23254 _gl.pixelStorei( 3317, texture.unpackAlignment ); 23255 _gl.pixelStorei( 37443, 0 ); 23256 23257 const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo$1( texture.image ) === false; 23258 let image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize ); 23259 image = verifyColorSpace( texture, image ); 23260 23261 const supportsMips = isPowerOfTwo$1( image ) || isWebGL2, 23262 glFormat = utils.convert( texture.format, texture.encoding ); 23263 23264 let glType = utils.convert( texture.type ), 23265 glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture ); 23266 23267 setTextureParameters( textureType, texture, supportsMips ); 23268 23269 let mipmap; 23270 const mipmaps = texture.mipmaps; 23271 23272 const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true ); 23273 const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); 23274 const levels = getMipLevels( texture, image, supportsMips ); 23275 23276 if ( texture.isDepthTexture ) { 23277 23278 // populate depth texture with dummy data 23279 23280 glInternalFormat = 6402; 23281 23282 if ( isWebGL2 ) { 23283 23284 if ( texture.type === FloatType ) { 23285 23286 glInternalFormat = 36012; 23287 23288 } else if ( texture.type === UnsignedIntType ) { 23289 23290 glInternalFormat = 33190; 23291 23292 } else if ( texture.type === UnsignedInt248Type ) { 23293 23294 glInternalFormat = 35056; 23295 23296 } else { 23297 23298 glInternalFormat = 33189; // WebGL2 requires sized internalformat for glTexImage2D 23299 23300 } 23301 23302 } else { 23303 23304 if ( texture.type === FloatType ) { 23305 23306 console.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' ); 23307 23308 } 23309 23310 } 23311 23312 // validation checks for WebGL 1 23313 23314 if ( texture.format === DepthFormat && glInternalFormat === 6402 ) { 23315 23316 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are 23317 // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT 23318 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) 23319 if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) { 23320 23321 console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' ); 23322 23323 texture.type = UnsignedIntType; 23324 glType = utils.convert( texture.type ); 23325 23326 } 23327 23328 } 23329 23330 if ( texture.format === DepthStencilFormat && glInternalFormat === 6402 ) { 23331 23332 // Depth stencil textures need the DEPTH_STENCIL internal format 23333 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) 23334 glInternalFormat = 34041; 23335 23336 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are 23337 // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL. 23338 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) 23339 if ( texture.type !== UnsignedInt248Type ) { 23340 23341 console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' ); 23342 23343 texture.type = UnsignedInt248Type; 23344 glType = utils.convert( texture.type ); 23345 23346 } 23347 23348 } 23349 23350 // 23351 23352 if ( allocateMemory ) { 23353 23354 if ( useTexStorage ) { 23355 23356 state.texStorage2D( 3553, 1, glInternalFormat, image.width, image.height ); 23357 23358 } else { 23359
23360 state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ); 23361 23362 } 23363 23364 } 23365 23366 } else if ( texture.isDataTexture ) { 23367 23368 // use manually created mipmaps if available 23369 // if there are no manual mipmaps 23370 // set 0 level mipmap and then use GL to generate other mipmap levels 23371 23372 if ( mipmaps.length > 0 && supportsMips ) { 23373 23374 if ( useTexStorage && allocateMemory ) { 23375 23376 state.texStorage2D( 3553, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); 23377 23378 } 23379 23380 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 23381 23382 mipmap = mipmaps[ i ]; 23383 23384 if ( useTexStorage ) { 23385 23386 state.texSubImage2D( 3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); 23387 23388 } else { 23389 23390 state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 23391 23392 } 23393 23394 } 23395 23396 texture.generateMipmaps = false; 23397 23398 } else { 23399 23400 if ( useTexStorage ) { 23401 23402 if ( allocateMemory ) { 23403 23404 state.texStorage2D( 3553, levels, glInternalFormat, image.width, image.height ); 23405 23406 } 23407 23408 state.texSubImage2D( 3553, 0, 0, 0, image.width, image.height, glFormat, glType, image.data ); 23409 23410 } else { 23411 23412 state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data ); 23413 23414 } 23415 23416 } 23417 23418 } else if ( texture.isCompressedTexture ) { 23419 23420 if ( texture.isCompressedArrayTexture ) { 23421 23422 if ( useTexStorage && allocateMemory ) { 23423 23424 state.texStorage3D( 35866, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth ); 23425 23426 } 23427 23428 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 23429 23430 mipmap = mipmaps[ i ]; 23431 23432 if ( texture.format !== RGBAFormat ) { 23433 23434 if ( glFormat !== null ) { 23435 23436 if ( useTexStorage ) { 23437 23438 state.compressedTexSubImage3D( 35866, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); 23439 23440 } else { 23441 23442 state.compressedTexImage3D( 35866, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 ); 23443 23444 } 23445 23446 } else { 23447 23448 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); 23449 23450 } 23451 23452 } else { 23453 23454 if ( useTexStorage ) { 23455 23456 state.texSubImage3D( 35866, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data ); 23457 23458 } else { 23459 23460 state.texImage3D( 35866, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data ); 23461 23462 } 23463 23464 } 23465 23466 } 23467 23468 } else { 23469 23470 if ( useTexStorage && allocateMemory ) { 23471 23472 state.texStorage2D( 3553, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); 23473 23474 } 23475 23476 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 23477 23478 mipmap = mipmaps[ i ]; 23479 23480 if ( texture.format !== RGBAFormat ) { 23481 23482 if ( glFormat !== null ) { 23483 23484 if ( useTexStorage ) { 23485 23486 state.compressedTexSubImage2D( 3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); 23487 23488 } else { 23489 23490 state.compressedTexImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); 23491 23492 } 23493 23494 } else { 23495 23496 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); 23497 23498 } 23499 23500 } else { 23501 23502 if ( useTexStorage ) { 23503 23504 state.texSubImage2D( 3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); 23505 23506 } else { 23507 23508 state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 23509 23510 } 23511 23512 } 23513 23514 } 23515 23516 } 23517 23518 } else if ( texture.isDataArrayTexture ) { 23519 23520 if ( useTexStorage ) { 23521 23522 if ( allocateMemory ) { 23523 23524 state.texStorage3D( 35866, levels, glInternalFormat, image.width, image.height, image.depth ); 23525 23526 } 23527 23528 state.texSubImage3D( 35866, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); 23529 23530 } else { 23531 23532 state.texImage3D( 35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); 23533 23534 } 23535 23536 } else if ( texture.isData3DTexture ) { 23537 23538 if ( useTexStorage ) { 23539 23540 if ( allocateMemory ) { 23541 23542 state.texStorage3D( 32879, levels, glInternalFormat, image.width, image.height, image.depth ); 23543 23544 } 23545 23546 state.texSubImage3D( 32879, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); 23547 23548 } else { 23549 23550 state.texImage3D( 32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); 23551 23552 } 23553 23554 }
23554 else if ( texture.isFramebufferTexture ) { 23555 23556 if ( allocateMemory ) { 23557 23558 if ( useTexStorage ) { 23559 23560 state.texStorage2D( 3553, levels, glInternalFormat, image.width, image.height ); 23561 23562 } else { 23563 23564 let width = image.width, height = image.height; 23565 23566 for ( let i = 0; i < levels; i ++ ) { 23567 23568 state.texImage2D( 3553, i, glInternalFormat, width, height, 0, glFormat, glType, null ); 23569 23570 width >>= 1; 23571 height >>= 1; 23572 23573 } 23574 23575 } 23576 23577 } 23578 23579 } else { 23580 23581 // regular Texture (image, video, canvas) 23582 23583 // use manually created mipmaps if available 23584 // if there are no manual mipmaps 23585 // set 0 level mipmap and then use GL to generate other mipmap levels 23586 23587 if ( mipmaps.length > 0 && supportsMips ) { 23588 23589 if ( useTexStorage && allocateMemory ) { 23590 23591 state.texStorage2D( 3553, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); 23592 23593 } 23594 23595 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 23596 23597 mipmap = mipmaps[ i ]; 23598 23599 if ( useTexStorage ) { 23600 23601 state.texSubImage2D( 3553, i, 0, 0, glFormat, glType, mipmap ); 23602 23603 } else { 23604 23605 state.texImage2D( 3553, i, glInternalFormat, glFormat, glType, mipmap ); 23606 23607 } 23608 23609 } 23610 23611 texture.generateMipmaps = false; 23612 23613 } else { 23614 23615 if ( useTexStorage ) { 23616 23617 if ( allocateMemory ) { 23618 23619 state.texStorage2D( 3553, levels, glInternalFormat, image.width, image.height ); 23620 23621 } 23622 23623 state.texSubImage2D( 3553, 0, 0, 0, glFormat, glType, image ); 23624 23625 } else { 23626 23627 state.texImage2D( 3553, 0, glInternalFormat, glFormat, glType, image ); 23628 23629 } 23630 23631 } 23632 23633 } 23634 23635 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { 23636 23637 generateMipmap( textureType ); 23638 23639 } 23640 23641 sourceProperties.__version = source.version; 23642 23643 if ( texture.onUpdate ) texture.onUpdate( texture ); 23644 23645 } 23646 23647 textureProperties.__version = texture.version; 23648 23649 } 23650 23651 function uploadCubeTexture( textureProperties, texture, slot ) { 23652 23653 if ( texture.image.length !== 6 ) return; 23654 23655 const forceUpload = initTexture( textureProperties, texture ); 23656 const source = texture.source; 23657 23658 state.bindTexture( 34067, textureProperties.__webglTexture, 33984 + slot ); 23659 23660 const sourceProperties = properties.get( source ); 23661 23662 if ( source.version !== sourceProperties.__version || forceUpload === true ) { 23663 23664 state.activeTexture( 33984 + slot ); 23665 23666 _gl.pixelStorei( 37440, texture.flipY ); 23667 _gl.pixelStorei( 37441, texture.premultiplyAlpha ); 23668 _gl.pixelStorei( 3317, texture.unpackAlignment ); 23669 _gl.pixelStorei( 37443, 0 ); 23670 23671 const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ); 23672 const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); 23673 23674 const cubeImage = []; 23675 23676 for ( let i = 0; i < 6; i ++ ) { 23677 23678 if ( ! isCompressed && ! isDataTexture ) { 23679 23680 cubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize ); 23681 23682 } else { 23683 23684 cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ]; 23685 23686 } 23687 23688 cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] ); 23689 23690 } 23691 23692 const image = cubeImage[ 0 ], 23693 supportsMips = isPowerOfTwo$1( image ) || isWebGL2, 23694 glFormat = utils.convert( texture.format, texture.encoding ), 23695 glType = utils.convert( texture.type ), 23696 glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); 23697 23698 const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true ); 23699 const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); 23700 let levels = getMipLevels( texture, image, supportsMips ); 23701 23702 setTextureParameters( 34067, texture, supportsMips ); 23703 23704 let mipmaps; 23705 23706 if ( isCompressed ) { 23707 23708 if ( useTexStorage && allocateMemory ) { 23709 23710 state.texStorage2D( 34067, levels, glInternalFormat, image.width, image.height ); 23711 23712 } 23713 23714 for ( let i = 0; i < 6; i ++ ) { 23715 23716 mipmaps = cubeImage[ i ].mipmaps; 23717 23718 for ( let j = 0; j < mipmaps.length; j ++ ) { 23719 23720 const mipmap = mipmaps[ j ]; 23721 23722 if ( texture.format !== RGBAFormat ) { 23723 23724 if ( glFormat !== null ) { 23725 23726 if ( useTexStorage ) { 23727 23728 state.compressedTexSubImage2D( 34069 + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); 23729 23730 } else { 23731 23732 state.compressedTexImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); 23733 23734 } 23735 23736 } else { 23737 23738 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); 23739 23740 } 23741 23742 } else { 23743 23744 if ( useTexStorage ) { 23745 23746 state.texSubImage2D( 34069 + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); 23747 23748 } else { 23749 23750 state.texImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 23751 23752 } 23753 23754 } 23755 23756 } 23757 23758 } 23759 23760 } else { 23761 23762 mipmaps = texture.mipmaps; 23763 23764 if ( useTexStorage && allocateMemory ) { 23765 23766 // TODO: Uniformly handle mipmap definitions 23767 // Normal textures and compressed cube textures define base level + mips with their mipmap array 23768 // Uncompressed cube textures use their mipmap array only for mips (no base level) 23769 23770 if ( mipmaps.length > 0 ) levels ++; 23771 23772 state.texStorage2D( 34067, levels, glInternalFormat, cubeImage[ 0 ].width, cubeImage[ 0 ].height ); 23773 23774 } 23775 23776 for ( let i = 0; i < 6; i ++ ) { 23777 23778 if ( isDataTexture ) { 23779 23780 if ( useTexStorage ) { 23781 23782 state.texSubImage2D( 34069 + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data ); 23783 23784 } else { 23785 23786 state.texImage2D( 34069 + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); 23787 23788 } 23789 23790 for ( let j = 0; j < mipmaps.length; j ++ ) { 23791 23792 const mipmap = mipmaps[ j ]; 23793 const mipmapImage = mipmap.image[ i ].image; 23794 23795 if ( useTexStorage ) { 23796 23797 state.texSubImage2D( 34069 + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data ); 23798 23799 } else { 23800 23801 state.texImage2D( 34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data ); 23802 23803 } 23804 23805 } 23806 23807 } else { 23808 23809 if ( useTexStorage ) { 23810 23811 state.texSubImage2D( 34069 + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] ); 23812 23813 } else { 23814 23815 state.texImage2D( 34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] ); 23816 23817 } 23818 23819 for ( let j = 0; j < mipmaps.length; j ++ ) { 23820 23821 const mipmap = mipmaps[ j ]; 23822 23823 if ( useTexStorage ) { 23824 23825 state.texSubImage2D( 34069 + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] ); 23826 23827 } else { 23828 23829 state.texImage2D( 34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] ); 23830 23831 } 23832 23833 } 23834 23835 } 23836 23837 } 23838 23839 } 23840 23841 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { 23842 23843 // We assume images for cube map have the same size. 23844 generateMipmap( 34067 ); 23845 23846 } 23847 23848 sourceProperties.__version = source.version; 23849 23850 if ( texture.onUpdate ) texture.onUpdate( texture ); 23851 23852 } 23853 23854 textureProperties.__version = texture.version; 23855 23856 } 23857 23858 // Render targets 23859
23860 // Setup storage for target texture and bind it to correct framebuffer 23861 function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget ) { 23862 23863 const glFormat = utils.convert( texture.format, texture.encoding ); 23864 const glType = utils.convert( texture.type ); 23865 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); 23866 const renderTargetProperties = properties.get( renderTarget ); 23867 23868 if ( ! renderTargetProperties.__hasExternalTextures ) { 23869 23870 if ( textureTarget === 32879 || textureTarget === 35866 ) { 23871 23872 state.texImage3D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null ); 23873 23874 } else { 23875 23876 state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null ); 23877 23878 } 23879 23880 } 23881 23882 state.bindFramebuffer( 36160, framebuffer ); 23883 23884 if ( useMultisampledRTT( renderTarget ) ) { 23885 23886 multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); 23887 23888 } else if ( textureTarget === 3553 || ( textureTarget >= 34069 && textureTarget <= 34074 ) ) { // see #24753 23889 23890 _gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( texture ).__webglTexture, 0 ); 23891 23892 } 23893 23894 state.bindFramebuffer( 36160, null ); 23895 23896 } 23897 23898 23899 // Setup storage for internal depth/stencil buffers and bind to correct framebuffer 23900 function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) { 23901 23902 _gl.bindRenderbuffer( 36161, renderbuffer ); 23903 23904 if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) { 23905 23906 let glInternalFormat = 33189; 23907 23908 if ( isMultisample || useMultisampledRTT( renderTarget ) ) { 23909 23910 const depthTexture = renderTarget.depthTexture; 23911 23912 if ( depthTexture && depthTexture.isDepthTexture ) { 23913 23914 if ( depthTexture.type === FloatType ) { 23915 23916 glInternalFormat = 36012; 23917 23918 } else if ( depthTexture.type === UnsignedIntType ) { 23919 23920 glInternalFormat = 33190; 23921 23922 } 23923 23924 } 23925 23926 const samples = getRenderTargetSamples( renderTarget ); 23927 23928 if ( useMultisampledRTT( renderTarget ) ) { 23929 23930 multisampledRTTExt.renderbufferStorageMultisampleEXT( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 23931 23932 } else { 23933 23934 _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 23935 23936 } 23937 23938 } else { 23939 23940 _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height ); 23941 23942 } 23943 23944 _gl.framebufferRenderbuffer( 36160, 36096, 36161, renderbuffer ); 23945 23946 } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) { 23947 23948 const samples = getRenderTargetSamples( renderTarget ); 23949 23950 if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { 23951 23952 _gl.renderbufferStorageMultisample( 36161, samples, 35056, renderTarget.width, renderTarget.height ); 23953 23954 } else if ( useMultisampledRTT( renderTarget ) ) { 23955 23956 multisampledRTTExt.renderbufferStorageMultisampleEXT( 36161, samples, 35056, renderTarget.width, renderTarget.height ); 23957 23958 } else { 23959 23960 _gl.renderbufferStorage( 36161, 34041, renderTarget.width, renderTarget.height ); 23961 23962 } 23963 23964 23965 _gl.framebufferRenderbuffer( 36160, 33306, 36161, renderbuffer ); 23966 23967 } else { 23968 23969 const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [ renderTarget.texture ]; 23970 23971 for ( let i = 0; i < textures.length; i ++ ) { 23972 23973 const texture = textures[ i ]; 23974 23975 const glFormat = utils.convert( texture.format, texture.encoding ); 23976 const glType = utils.convert( texture.type ); 23977 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); 23978 const samples = getRenderTargetSamples( renderTarget ); 23979 23980 if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { 23981 23982 _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 23983 23984 } else if ( useMultisampledRTT( renderTarget ) ) { 23985 23986 multisampledRTTExt.renderbufferStorageMultisampleEXT( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 23987 23988 } else { 23989 23990 _gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height ); 23991 23992 } 23993 23994 } 23995 23996 } 23997 23998 _gl.bindRenderbuffer( 36161, null ); 23999 24000 } 24001 24002 // Setup resources for a Depth Texture for a FBO (needs an extension) 24003 function setupDepthTexture( framebuffer, renderTarget ) { 24004
24005 const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget ); 24006 if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); 24007 24008 state.bindFramebuffer( 36160, framebuffer ); 24009 24010 if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { 24011 24012 throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); 24013 24014 } 24015 24016 // upload an empty depth texture with framebuffer size 24017 if ( ! properties.get( renderTarget.depthTexture ).__webglTexture || 24018 renderTarget.depthTexture.image.width !== renderTarget.width || 24019 renderTarget.depthTexture.image.height !== renderTarget.height ) { 24020 24021 renderTarget.depthTexture.image.width = renderTarget.width; 24022 renderTarget.depthTexture.image.height = renderTarget.height; 24023 renderTarget.depthTexture.needsUpdate = true; 24024 24025 } 24026 24027 setTexture2D( renderTarget.depthTexture, 0 ); 24028 24029 const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; 24030 const samples = getRenderTargetSamples( renderTarget ); 24031 24032 if ( renderTarget.depthTexture.format === DepthFormat ) { 24033 24034 if ( useMultisampledRTT( renderTarget ) ) { 24035 24036 multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, 36096, 3553, webglDepthTexture, 0, samples ); 24037 24038 } else { 24039 24040 _gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 ); 24041 24042 } 24043 24044 } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { 24045 24046 if ( useMultisampledRTT( renderTarget ) ) { 24047 24048 multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, 33306, 3553, webglDepthTexture, 0, samples ); 24049 24050 } else { 24051 24052 _gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 ); 24053 24054 } 24055 24056 } else { 24057 24058 throw new Error( 'Unknown depthTexture format' ); 24059 24060 } 24061 24062 } 24063 24064 // Setup GL resources for a non-texture depth buffer 24065 function setupDepthRenderbuffer( renderTarget ) { 24066 24067 const renderTargetProperties = properties.get( renderTarget ); 24068 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); 24069 24070 if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) { 24071 24072 if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); 24073 24074 setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); 24075 24076 } else { 24077 24078 if ( isCube ) { 24079 24080 renderTargetProperties.__webglDepthbuffer = []; 24081 24082 for ( let i = 0; i < 6; i ++ ) { 24083 24084 state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer[ i ] ); 24085 renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); 24086 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false ); 24087 24088 } 24089 24090 } else { 24091 24092 state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer ); 24093 renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); 24094 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false ); 24095 24096 } 24097 24098 } 24099 24100 state.bindFramebuffer( 36160, null ); 24101 24102 } 24103 24104 // rebind framebuffer with external textures 24105 function rebindTextures( renderTarget, colorTexture, depthTexture ) { 24106 24107 const renderTargetProperties = properties.get( renderTarget ); 24108 24109 if ( colorTexture !== undefined ) { 24110 24111 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, 36064, 3553 ); 24112 24113 } 24114 24115 if ( depthTexture !== undefined ) { 24116 24117 setupDepthRenderbuffer( renderTarget ); 24118 24119 } 24120 24121 } 24122 24123 // Set up GL resources for the render target 24124 function setupRenderTarget( renderTarget ) { 24125 24126 const texture = renderTarget.texture; 24127 24128 const renderTargetProperties = properties.get( renderTarget ); 24129 const textureProperties = properties.get( texture ); 24130 24131 renderTarget.addEventListener( 'dispose', onRenderTargetDispose ); 24132 24133 if ( renderTarget.isWebGLMultipleRenderTargets !== true ) { 24134 24135 if ( textureProperties.__webglTexture === undefined ) { 24136 24137 textureProperties.__webglTexture = _gl.createTexture(); 24138 24139 } 24140 24141 textureProperties.__version = texture.version; 24142 info.memory.textures ++; 24143 24144 } 24145 24146 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); 24147 const isMultipleRenderTargets = ( renderTarget.isWebGLMultipleRenderTargets === true ); 24148 const supportsMips = isPowerOfTwo$1( renderTarget ) || isWebGL2; 24149 24150 // Setup framebuffer 24151 24152 if ( isCube ) { 24153 24154 renderTargetProperties.__webglFramebuffer = []; 24155 24156 for ( let i = 0; i < 6; i ++ ) { 24157 24158 renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer(); 24159 24160 } 24161 24162 } else { 24163 24164 renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); 24165 24166 if ( isMultipleRenderTargets ) { 24167 24168 if ( capabilities.drawBuffers ) { 24169 24170 const textures = renderTarget.texture; 24171 24172 for ( let i = 0, il = textures.length; i < il; i ++ ) { 24173 24174 const attachmentProperties = properties.get( textures[ i ] ); 24175 24176 if ( attachmentProperties.__webglTexture === undefined ) { 24177 24178 attachmentProperties.__webglTexture = _gl.createTexture(); 24179 24180 info.memory.textures ++; 24181 24182 } 24183 24184 } 24185 24186 } else { 24187 24188 console.warn( 'THREE.WebGLRenderer: WebGLMultipleRenderTargets can only be used with WebGL2 or WEBGL_draw_buffers extension.' ); 24189 24190 } 24191 24192 } 24193 24194 if ( ( isWebGL2 && renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) { 24195 24196 const textures = isMultipleRenderTargets ? texture : [ texture ]; 24197 24198 renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
24199 renderTargetProperties.__webglColorRenderbuffer = []; 24200 24201 state.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer ); 24202 24203 for ( let i = 0; i < textures.length; i ++ ) { 24204 24205 const texture = textures[ i ]; 24206 renderTargetProperties.__webglColorRenderbuffer[ i ] = _gl.createRenderbuffer(); 24207 24208 _gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 24209 24210 const glFormat = utils.convert( texture.format, texture.encoding ); 24211 const glType = utils.convert( texture.type ); 24212 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, renderTarget.isXRRenderTarget === true ); 24213 const samples = getRenderTargetSamples( renderTarget ); 24214 _gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 24215 24216 _gl.framebufferRenderbuffer( 36160, 36064 + i, 36161, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 24217 24218 } 24219 24220 _gl.bindRenderbuffer( 36161, null ); 24221 24222 if ( renderTarget.depthBuffer ) { 24223 24224 renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer(); 24225 setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true ); 24226 24227 } 24228 24229 state.bindFramebuffer( 36160, null ); 24230 24231 } 24232 24233 } 24234 24235 // Setup color buffer 24236 24237 if ( isCube ) { 24238 24239 state.bindTexture( 34067, textureProperties.__webglTexture ); 24240 setTextureParameters( 34067, texture, supportsMips ); 24241 24242 for ( let i = 0; i < 6; i ++ ) { 24243 24244 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, 36064, 34069 + i ); 24245 24246 } 24247 24248 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { 24249 24250 generateMipmap( 34067 ); 24251 24252 } 24253 24254 state.unbindTexture(); 24255 24256 } else if ( isMultipleRenderTargets ) { 24257 24258 const textures = renderTarget.texture; 24259 24260 for ( let i = 0, il = textures.length; i < il; i ++ ) { 24261 24262 const attachment = textures[ i ]; 24263 const attachmentProperties = properties.get( attachment ); 24264 24265 state.bindTexture( 3553, attachmentProperties.__webglTexture ); 24266 setTextureParameters( 3553, attachment, supportsMips ); 24267 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, 36064 + i, 3553 ); 24268 24269 if ( textureNeedsGenerateMipmaps( attachment, supportsMips ) ) { 24270 24271 generateMipmap( 3553 ); 24272 24273 } 24274 24275 } 24276 24277 state.unbindTexture(); 24278 24279 } else { 24280 24281 let glTextureType = 3553; 24282 24283 if ( renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) { 24284 24285 if ( isWebGL2 ) { 24286 24287 glTextureType = renderTarget.isWebGL3DRenderTarget ? 32879 : 35866; 24288 24289 } else { 24290 24291 console.error( 'THREE.WebGLTextures: THREE.Data3DTexture and THREE.DataArrayTexture only supported with WebGL2.' ); 24292 24293 } 24294 24295 } 24296 24297 state.bindTexture( glTextureType, textureProperties.__webglTexture ); 24298 setTextureParameters( glTextureType, texture, supportsMips ); 24299 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, 36064, glTextureType ); 24300 24301 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { 24302 24303 generateMipmap( glTextureType ); 24304 24305 } 24306 24307 state.unbindTexture(); 24308 24309 } 24310 24311 // Setup depth and stencil buffers 24312 24313 if ( renderTarget.depthBuffer ) { 24314 24315 setupDepthRenderbuffer( renderTarget ); 24316 24317 } 24318 24319 } 24320 24321 function updateRenderTargetMipmap( renderTarget ) { 24322 24323 const supportsMips = isPowerOfTwo$1( renderTarget ) || isWebGL2; 24324 24325 const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [ renderTarget.texture ]; 24326 24327 for ( let i = 0, il = textures.length; i < il; i ++ ) { 24328 24329 const texture = textures[ i ]; 24330 24331 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { 24332 24333 const target = renderTarget.isWebGLCubeRenderTarget ? 34067 : 3553; 24334 const webglTexture = properties.get( texture ).__webglTexture; 24335 24336 state.bindTexture( target, webglTexture ); 24337 generateMipmap( target ); 24338 state.unbindTexture(); 24339 24340 } 24341 24342 } 24343 24344 } 24345 24346 function updateMultisampleRenderTarget( renderTarget ) { 24347 24348 if ( ( isWebGL2 && renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) { 24349 24350 const textures = renderTarget.isWebGLMultipleRenderTargets ? renderTarget.texture : [ renderTarget.texture ]; 24351 const width = renderTarget.width; 24352 const height = renderTarget.height; 24353 let mask = 16384;
24354 const invalidationArray = []; 24355 const depthStyle = renderTarget.stencilBuffer ? 33306 : 36096; 24356 const renderTargetProperties = properties.get( renderTarget ); 24357 const isMultipleRenderTargets = ( renderTarget.isWebGLMultipleRenderTargets === true ); 24358 24359 // If MRT we need to remove FBO attachments 24360 if ( isMultipleRenderTargets ) { 24361 24362 for ( let i = 0; i < textures.length; i ++ ) { 24363 24364 state.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer ); 24365 _gl.framebufferRenderbuffer( 36160, 36064 + i, 36161, null ); 24366 24367 state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer ); 24368 _gl.framebufferTexture2D( 36009, 36064 + i, 3553, null, 0 ); 24369 24370 } 24371 24372 } 24373 24374 state.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer ); 24375 state.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer ); 24376 24377 for ( let i = 0; i < textures.length; i ++ ) { 24378 24379 invalidationArray.push( 36064 + i ); 24380 24381 if ( renderTarget.depthBuffer ) { 24382 24383 invalidationArray.push( depthStyle ); 24384 24385 } 24386 24387 const ignoreDepthValues = ( renderTargetProperties.__ignoreDepthValues !== undefined ) ? renderTargetProperties.__ignoreDepthValues : false; 24388 24389 if ( ignoreDepthValues === false ) { 24390 24391 if ( renderTarget.depthBuffer ) mask |= 256; 24392 if ( renderTarget.stencilBuffer ) mask |= 1024; 24393 24394 } 24395 24396 if ( isMultipleRenderTargets ) { 24397 24398 _gl.framebufferRenderbuffer( 36008, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 24399 24400 } 24401 24402 if ( ignoreDepthValues === true ) { 24403 24404 _gl.invalidateFramebuffer( 36008, [ depthStyle ] ); 24405 _gl.invalidateFramebuffer( 36009, [ depthStyle ] ); 24406 24407 } 24408 24409 if ( isMultipleRenderTargets ) { 24410 24411 const webglTexture = properties.get( textures[ i ] ).__webglTexture; 24412 _gl.framebufferTexture2D( 36009, 36064, 3553, webglTexture, 0 ); 24413 24414 } 24415 24416 _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 ); 24417 24418 if ( supportsInvalidateFramebuffer ) { 24419 24420 _gl.invalidateFramebuffer( 36008, invalidationArray ); 24421 24422 } 24423 24424 24425 } 24426 24427 state.bindFramebuffer( 36008, null ); 24428 state.bindFramebuffer( 36009, null ); 24429 24430 // If MRT since pre-blit we removed the FBO we need to reconstruct the attachments 24431 if ( isMultipleRenderTargets ) { 24432 24433 for ( let i = 0; i < textures.length; i ++ ) { 24434 24435 state.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer ); 24436 _gl.framebufferRenderbuffer( 36160, 36064 + i, 36161, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 24437 24438 const webglTexture = properties.get( textures[ i ] ).__webglTexture; 24439 24440 state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer ); 24441 _gl.framebufferTexture2D( 36009, 36064 + i, 3553, webglTexture, 0 ); 24442 24443 } 24444 24445 } 24446 24447 state.bindFramebuffer( 36009, renderTargetProperties.__webglMultisampledFramebuffer ); 24448 24449 } 24450 24451 } 24452 24453 function getRenderTargetSamples( renderTarget ) { 24454 24455 return Math.min( maxSamples, renderTarget.samples ); 24456 24457 } 24458 24459 function useMultisampledRTT( renderTarget ) { 24460 24461 const renderTargetProperties = properties.get( renderTarget ); 24462 24463 return isWebGL2 && renderTarget.samples > 0 && extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true && renderTargetProperties.__useRenderToTexture !== false; 24464 24465 } 24466 24467 function updateVideoTexture( texture ) { 24468 24469 const frame = info.render.frame; 24470 24471 // Check the last frame we updated the VideoTexture 24472 24473 if ( _videoTextures.get( texture ) !== frame ) { 24474 24475 _videoTextures.set( texture, frame ); 24476 texture.update(); 24477 24478 } 24479 24480 } 24481 24482 function verifyColorSpace( texture, image ) { 24483 24484 const encoding = texture.encoding; 24485 const format = texture.format; 24486 const type = texture.type; 24487 24488 if ( texture.isCompressedTexture === true || texture.isVideoTexture === true || texture.format === _SRGBAFormat ) return image; 24489 24490 if ( encoding !== LinearEncoding ) { 24491 24492 // sRGB 24493 24494 if ( encoding === sRGBEncoding ) { 24495 24496 if ( isWebGL2 === false ) { 24497 24498 // in WebGL 1, try to use EXT_sRGB extension and unsized formats 24499 24500 if ( extensions.has( 'EXT_sRGB' ) === true && format === RGBAFormat ) { 24501 24502 texture.format = _SRGBAFormat; 24503 24504 // it's not possible to generate mips in WebGL 1 with this extension 24505 24506 texture.minFilter = LinearFilter; 24507 texture.generateMipmaps = false;
24508 24509 } else { 24510 24511 // slow fallback (CPU decode) 24512 24513 image = ImageUtils.sRGBToLinear( image ); 24514 24515 } 24516 24517 } else { 24518 24519 // in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format 24520 24521 if ( format !== RGBAFormat || type !== UnsignedByteType ) { 24522 24523 console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' ); 24524 24525 } 24526 24527 } 24528 24529 } else { 24530 24531 console.error( 'THREE.WebGLTextures: Unsupported texture encoding:', encoding ); 24532 24533 } 24534 24535 } 24536 24537 return image; 24538 24539 } 24540 24541 // 24542 24543 this.allocateTextureUnit = allocateTextureUnit; 24544 this.resetTextureUnits = resetTextureUnits; 24545 24546 this.setTexture2D = setTexture2D; 24547 this.setTexture2DArray = setTexture2DArray; 24548 this.setTexture3D = setTexture3D; 24549 this.setTextureCube = setTextureCube; 24550 this.rebindTextures = rebindTextures; 24551 this.setupRenderTarget = setupRenderTarget; 24552 this.updateRenderTargetMipmap = updateRenderTargetMipmap; 24553 this.updateMultisampleRenderTarget = updateMultisampleRenderTarget; 24554 this.setupDepthRenderbuffer = setupDepthRenderbuffer; 24555 this.setupFrameBufferTexture = setupFrameBufferTexture; 24556 this.useMultisampledRTT = useMultisampledRTT; 24557 24558} 24559 24560function WebGLUtils( gl, extensions, capabilities ) { 24561 24562 const isWebGL2 = capabilities.isWebGL2; 24563 24564 function convert( p, encoding = null ) { 24565 24566 let extension; 24567 24568 if ( p === UnsignedByteType ) return 5121; 24569 if ( p === UnsignedShort4444Type ) return 32819; 24570 if ( p === UnsignedShort5551Type ) return 32820; 24571 24572 if ( p === ByteType ) return 5120; 24573 if ( p === ShortType ) return 5122; 24574 if ( p === UnsignedShortType ) return 5123; 24575 if ( p === IntType ) return 5124; 24576 if ( p === UnsignedIntType ) return 5125; 24577 if ( p === FloatType ) return 5126; 24578 24579 if ( p === HalfFloatType ) { 24580 24581 if ( isWebGL2 ) return 5131; 24582 24583 extension = extensions.get( 'OES_texture_half_float' ); 24584 24585 if ( extension !== null ) { 24586 24587 return extension.HALF_FLOAT_OES; 24588 24589 } else { 24590 24591 return null; 24592 24593 } 24594 24595 } 24596 24597 if ( p === AlphaFormat ) return 6406; 24598 if ( p === RGBAFormat ) return 6408; 24599 if ( p === LuminanceFormat ) return 6409; 24600 if ( p === LuminanceAlphaFormat ) return 6410; 24601 if ( p === DepthFormat ) return 6402; 24602 if ( p === DepthStencilFormat ) return 34041; 24603 24604 // WebGL 1 sRGB fallback 24605 24606 if ( p === _SRGBAFormat ) { 24607 24608 extension = extensions.get( 'EXT_sRGB' ); 24609 24610 if ( extension !== null ) { 24611 24612 return extension.SRGB_ALPHA_EXT; 24613 24614 } else { 24615 24616 return null; 24617 24618 } 24619 24620 } 24621 24622 // WebGL2 formats. 24623 24624 if ( p === RedFormat ) return 6403; 24625 if ( p === RedIntegerFormat ) return 36244; 24626 if ( p === RGFormat ) return 33319; 24627 if ( p === RGIntegerFormat ) return 33320; 24628 if ( p === RGBAIntegerFormat ) return 36249; 24629 24630 // S3TC 24631 24632 if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { 24633 24634 if ( encoding === sRGBEncoding ) { 24635 24636 extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); 24637 24638 if ( extension !== null ) { 24639 24640 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT; 24641 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; 24642 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; 24643 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; 24644 24645 } else { 24646 24647 return null; 24648 24649 } 24650 24651 } else { 24652 24653 extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); 24654 24655 if ( extension !== null ) { 24656 24657 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; 24658 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; 24659 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; 24660 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; 24661 24662 } else { 24663 24664 return null; 24665 24666 } 24667 24668 } 24669 24670 } 24671 24672 // PVRTC 24673 24674 if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { 24675 24676 extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); 24677 24678 if ( extension !== null ) { 24679 24680 if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; 24681 if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; 24682 if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; 24683 if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; 24684 24685 } else { 24686 24687 return null; 24688 24689 } 24690 24691 } 24692 24693 // ETC1 24694 24695 if ( p === RGB_ETC1_Format ) { 24696 24697 extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); 24698 24699 if ( extension !== null ) { 24700 24701 return extension.COMPRESSED_RGB_ETC1_WEBGL; 24702 24703 } else { 24704 24705 return null; 24706 24707 } 24708 24709 } 24710 24711 // ETC2 24712 24713 if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { 24714 24715 extension = extensions.get( 'WEBGL_compressed_texture_etc' ); 24716 24717 if ( extension !== null ) { 24718 24719 if ( p === RGB_ETC2_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; 24720 if ( p === RGBA_ETC2_EAC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; 24721 24722 } else { 24723 24724 return null; 24725 24726 } 24727 24728 } 24729 24730 // ASTC 24731 24732 if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format || 24733 p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format || 24734 p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format || 24735 p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format || 24736 p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) { 24737 24738 extension = extensions.get( 'WEBGL_compressed_texture_astc' ); 24739 24740 if ( extension !== null ) { 24741 24742 if ( p === RGBA_ASTC_4x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; 24743 if ( p === RGBA_ASTC_5x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; 24744 if ( p === RGBA_ASTC_5x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; 24745 if ( p === RGBA_ASTC_6x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; 24746 if ( p === RGBA_ASTC_6x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; 24747 if ( p === RGBA_ASTC_8x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; 24748 if ( p === RGBA_ASTC_8x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; 24749 if ( p === RGBA_ASTC_8x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; 24750 if ( p === RGBA_ASTC_10x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; 24751 if ( p === RGBA_ASTC_10x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; 24752 if ( p === RGBA_ASTC_10x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; 24753 if ( p === RGBA_ASTC_10x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; 24754 if ( p === RGBA_ASTC_12x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; 24755 if ( p === RGBA_ASTC_12x12_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; 24756 24757 } else { 24758 24759 return null; 24760 24761 } 24762 24763 } 24764 24765 // BPTC 24766 24767 if ( p === RGBA_BPTC_Format ) { 24768 24769 extension = extensions.get( 'EXT_texture_compression_bptc' ); 24770 24771 if ( extension !== null ) { 24772 24773 if ( p === RGBA_BPTC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; 24774 24775 } else { 24776 24777 return null; 24778 24779 } 24780 24781 } 24782
vendor: 19,771 bytes, lines 24783-25684
24783 // RGTC 24784 24785 if ( p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format ) { 24786 24787 extension = extensions.get( 'EXT_texture_compression_rgtc' ); 24788 24789 if ( extension !== null ) { 24790 24791 if ( p === RGBA_BPTC_Format ) return extension.COMPRESSED_RED_RGTC1_EXT; 24792 if ( p === SIGNED_RED_RGTC1_Format ) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT; 24793 if ( p === RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT; 24794 if ( p === SIGNED_RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT; 24795 24796 } else { 24797 24798 return null; 24799 24800 } 24801 24802 } 24803 24804 // 24805 24806 if ( p === UnsignedInt248Type ) { 24807 24808 if ( isWebGL2 ) return 34042; 24809 24810 extension = extensions.get( 'WEBGL_depth_texture' ); 24811 24812 if ( extension !== null ) { 24813 24814 return extension.UNSIGNED_INT_24_8_WEBGL; 24815 24816 } else { 24817 24818 return null; 24819 24820 } 24821 24822 } 24823 24824 // if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats) 24825 24826 return ( gl[ p ] !== undefined ) ? gl[ p ] : null; 24827 24828 } 24829 24830 return { convert: convert }; 24831 24832} 24833 24834class ArrayCamera extends PerspectiveCamera { 24835 24836 constructor( array = [] ) { 24837 24838 super(); 24839 24840 this.isArrayCamera = true; 24841 24842 this.cameras = array; 24843 24844 } 24845 24846} 24847 24848class Group extends Object3D { 24849 24850 constructor() { 24851 24852 super(); 24853 24854 this.isGroup = true; 24855 24856 this.type = 'Group'; 24857 24858 } 24859 24860} 24861 24862const _moveEvent = { type: 'move' }; 24863 24864class WebXRController { 24865 24866 constructor() { 24867 24868 this._targetRay = null; 24869 this._grip = null; 24870 this._hand = null; 24871 24872 } 24873 24874 getHandSpace() { 24875 24876 if ( this._hand === null ) { 24877 24878 this._hand = new Group(); 24879 this._hand.matrixAutoUpdate = false; 24880 this._hand.visible = false; 24881 24882 this._hand.joints = {}; 24883 this._hand.inputState = { pinching: false }; 24884 24885 } 24886 24887 return this._hand; 24888 24889 } 24890 24891 getTargetRaySpace() { 24892 24893 if ( this._targetRay === null ) { 24894 24895 this._targetRay = new Group(); 24896 this._targetRay.matrixAutoUpdate = false; 24897 this._targetRay.visible = false; 24898 this._targetRay.hasLinearVelocity = false; 24899 this._targetRay.linearVelocity = new Vector3(); 24900 this._targetRay.hasAngularVelocity = false; 24901 this._targetRay.angularVelocity = new Vector3(); 24902 24903 } 24904 24905 return this._targetRay; 24906 24907 } 24908 24909 getGripSpace() { 24910 24911 if ( this._grip === null ) { 24912 24913 this._grip = new Group(); 24914 this._grip.matrixAutoUpdate = false; 24915 this._grip.visible = false; 24916 this._grip.hasLinearVelocity = false; 24917 this._grip.linearVelocity = new Vector3(); 24918 this._grip.hasAngularVelocity = false; 24919 this._grip.angularVelocity = new Vector3(); 24920 24921 } 24922 24923 return this._grip; 24924 24925 } 24926 24927 dispatchEvent( event ) { 24928 24929 if ( this._targetRay !== null ) { 24930 24931 this._targetRay.dispatchEvent( event ); 24932 24933 } 24934 24935 if ( this._grip !== null ) { 24936 24937 this._grip.dispatchEvent( event ); 24938 24939 } 24940 24941 if ( this._hand !== null ) { 24942 24943 this._hand.dispatchEvent( event ); 24944 24945 } 24946 24947 return this; 24948 24949 } 24950 24951 connect( inputSource ) { 24952 24953 if ( inputSource && inputSource.hand ) { 24954 24955 const hand = this._hand; 24956 24957 if ( hand ) { 24958 24959 for ( const inputjoint of inputSource.hand.values() ) { 24960 24961 // Initialize hand with joints when connected 24962 this._getHandJoint( hand, inputjoint ); 24963 24964 } 24965 24966 } 24967 24968 } 24969 24970 this.dispatchEvent( { type: 'connected', data: inputSource } ); 24971 24972 return this; 24973 24974 } 24975 24976 disconnect( inputSource ) { 24977 24978 this.dispatchEvent( { type: 'disconnected', data: inputSource } ); 24979 24980 if ( this._targetRay !== null ) { 24981 24982 this._targetRay.visible = false; 24983 24984 } 24985 24986 if ( this._grip !== null ) { 24987 24988 this._grip.visible = false; 24989 24990 } 24991 24992 if ( this._hand !== null ) { 24993 24994 this._hand.visible = false; 24995 24996 } 24997 24998 return this; 24999 25000 } 25001 25002 update( inputSource, frame, referenceSpace ) { 25003 25004 let inputPose = null; 25005 let gripPose = null; 25006 let handPose = null; 25007 25008 const targetRay = this._targetRay; 25009 const grip = this._grip; 25010 const hand = this._hand; 25011 25012 if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) { 25013 25014 if ( hand && inputSource.hand ) { 25015 25016 handPose = true; 25017 25018 for ( const inputjoint of inputSource.hand.values() ) { 25019 25020 // Update the joints groups with the XRJoint poses 25021 const jointPose = frame.getJointPose( inputjoint, referenceSpace ); 25022 25023 // The transform of this joint will be updated with the joint pose on each frame 25024 const joint = this._getHandJoint( hand, inputjoint ); 25025 25026 if ( jointPose !== null ) { 25027 25028 joint.matrix.fromArray( jointPose.transform.matrix ); 25029 joint.matrix.decompose( joint.position, joint.rotation, joint.scale ); 25030 joint.jointRadius = jointPose.radius; 25031 25032 } 25033 25034 joint.visible = jointPose !== null; 25035 25036 } 25037 25038 // Custom events 25039 25040 // Check pinchz 25041 const indexTip = hand.joints[ 'index-finger-tip' ]; 25042 const thumbTip = hand.joints[ 'thumb-tip' ]; 25043 const distance = indexTip.position.distanceTo( thumbTip.position ); 25044 25045 const distanceToPinch = 0.02; 25046 const threshold = 0.005; 25047 25048 if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) { 25049 25050 hand.inputState.pinching = false; 25051 this.dispatchEvent( { 25052 type: 'pinchend', 25053 handedness: inputSource.handedness, 25054 target: this 25055 } ); 25056 25057 } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) { 25058 25059 hand.inputState.pinching = true; 25060 this.dispatchEvent( { 25061 type: 'pinchstart', 25062 handedness: inputSource.handedness, 25063 target: this 25064 } ); 25065 25066 } 25067 25068 } else { 25069 25070 if ( grip !== null && inputSource.gripSpace ) { 25071 25072 gripPose = frame.getPose( inputSource.gripSpace, referenceSpace ); 25073 25074 if ( gripPose !== null ) { 25075 25076 grip.matrix.fromArray( gripPose.transform.matrix ); 25077 grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); 25078 25079 if ( gripPose.linearVelocity ) { 25080 25081 grip.hasLinearVelocity = true; 25082 grip.linearVelocity.copy( gripPose.linearVelocity ); 25083 25084 } else { 25085 25086 grip.hasLinearVelocity = false; 25087 25088 } 25089 25090 if ( gripPose.angularVelocity ) { 25091 25092 grip.hasAngularVelocity = true; 25093 grip.angularVelocity.copy( gripPose.angularVelocity ); 25094 25095 } else { 25096 25097 grip.hasAngularVelocity = false; 25098 25099 } 25100 25101 } 25102 25103 } 25104 25105 } 25106 25107 if ( targetRay !== null ) { 25108 25109 inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace ); 25110 25111 // Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it 25112 if ( inputPose === null && gripPose !== null ) { 25113 25114 inputPose = gripPose; 25115 25116 } 25117 25118 if ( inputPose !== null ) { 25119 25120 targetRay.matrix.fromArray( inputPose.transform.matrix ); 25121 targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); 25122 25123 if ( inputPose.linearVelocity ) { 25124 25125 targetRay.hasLinearVelocity = true; 25126 targetRay.linearVelocity.copy( inputPose.linearVelocity ); 25127 25128 } else { 25129 25130 targetRay.hasLinearVelocity = false; 25131 25132 } 25133 25134 if ( inputPose.angularVelocity ) { 25135 25136 targetRay.hasAngularVelocity = true; 25137 targetRay.angularVelocity.copy( inputPose.angularVelocity ); 25138 25139 } else { 25140 25141 targetRay.hasAngularVelocity = false; 25142 25143 } 25144 25145 this.dispatchEvent( _moveEvent ); 25146 25147 } 25148 25149 } 25150 25151 25152 } 25153 25154 if ( targetRay !== null ) { 25155 25156 targetRay.visible = ( inputPose !== null ); 25157 25158 } 25159 25160 if ( grip !== null ) { 25161 25162 grip.visible = ( gripPose !== null ); 25163 25164 } 25165 25166 if ( hand !== null ) { 25167 25168 hand.visible = ( handPose !== null ); 25169 25170 } 25171 25172 return this; 25173 25174 } 25175 25176 // private method 25177 25178 _getHandJoint( hand, inputjoint ) { 25179 25180 if ( hand.joints[ inputjoint.jointName ] === undefined ) { 25181 25182 const joint = new Group(); 25183 joint.matrixAutoUpdate = false; 25184 joint.visible = false; 25185 hand.joints[ inputjoint.jointName ] = joint; 25186 25187 hand.add( joint ); 25188 25189 } 25190 25191 return hand.joints[ inputjoint.jointName ]; 25192 25193 } 25194 25195} 25196 25197class DepthTexture extends Texture { 25198 25199 constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) { 25200 25201 format = format !== undefined ? format : DepthFormat; 25202 25203 if ( format !== DepthFormat && format !== DepthStencilFormat ) { 25204 25205 throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); 25206 25207 } 25208 25209 if ( type === undefined && format === DepthFormat ) type = UnsignedIntType; 25210 if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type; 25211 25212 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 25213 25214 this.isDepthTexture = true; 25215 25216 this.image = { width: width, height: height }; 25217 25218 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; 25219 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; 25220 25221 this.flipY = false; 25222 this.generateMipmaps = false; 25223 25224 } 25225 25226 25227} 25228 25229class WebXRManager extends EventDispatcher { 25230 25231 constructor( renderer, gl ) { 25232 25233 super(); 25234 25235 const scope = this; 25236 25237 let session = null; 25238 let framebufferScaleFactor = 1.0; 25239 25240 let referenceSpace = null; 25241 let referenceSpaceType = 'local-floor'; 25242 // Set default foveation to maximum. 25243 let foveation = 1.0; 25244 let customReferenceSpace = null; 25245 25246 let pose = null; 25247 let glBinding = null; 25248 let glProjLayer = null; 25249 let glBaseLayer = null; 25250 let xrFrame = null; 25251 const attributes = gl.getContextAttributes(); 25252 let initialRenderTarget = null; 25253 let newRenderTarget = null; 25254 25255 const controllers = []; 25256 const controllerInputSources = []; 25257 25258 const planes = new Set(); 25259 const planesLastChangedTimes = new Map(); 25260 25261 // 25262 25263 const cameraL = new PerspectiveCamera(); 25264 cameraL.layers.enable( 1 ); 25265 cameraL.viewport = new Vector4(); 25266 25267 const cameraR = new PerspectiveCamera(); 25268 cameraR.layers.enable( 2 ); 25269 cameraR.viewport = new Vector4(); 25270 25271 const cameras = [ cameraL, cameraR ]; 25272 25273 const cameraVR = new ArrayCamera(); 25274 cameraVR.layers.enable( 1 ); 25275 cameraVR.layers.enable( 2 ); 25276 25277 let _currentDepthNear = null; 25278 let _currentDepthFar = null; 25279 25280 // 25281 25282 this.cameraAutoUpdate = true; 25283 this.enabled = false; 25284 25285 this.isPresenting = false; 25286 25287 this.getController = function ( index ) { 25288 25289 let controller = controllers[ index ]; 25290 25291 if ( controller === undefined ) { 25292 25293 controller = new WebXRController(); 25294 controllers[ index ] = controller; 25295 25296 } 25297 25298 return controller.getTargetRaySpace(); 25299 25300 }; 25301 25302 this.getControllerGrip = function ( index ) { 25303 25304 let controller = controllers[ index ]; 25305 25306 if ( controller === undefined ) { 25307 25308 controller = new WebXRController(); 25309 controllers[ index ] = controller; 25310 25311 } 25312 25313 return controller.getGripSpace(); 25314 25315 }; 25316 25317 this.getHand = function ( index ) { 25318 25319 let controller = controllers[ index ]; 25320 25321 if ( controller === undefined ) { 25322 25323 controller = new WebXRController(); 25324 controllers[ index ] = controller; 25325 25326 } 25327 25328 return controller.getHandSpace(); 25329 25330 }; 25331 25332 // 25333 25334 function onSessionEvent( event ) { 25335 25336 const controllerIndex = controllerInputSources.indexOf( event.inputSource ); 25337 25338 if ( controllerIndex === - 1 ) { 25339 25340 return; 25341 25342 } 25343 25344 const controller = controllers[ controllerIndex ]; 25345 25346 if ( controller !== undefined ) { 25347 25348 controller.dispatchEvent( { type: event.type, data: event.inputSource } ); 25349 25350 } 25351 25352 } 25353 25354 function onSessionEnd() { 25355 25356 session.removeEventListener( 'select', onSessionEvent ); 25357 session.removeEventListener( 'selectstart', onSessionEvent ); 25358 session.removeEventListener( 'selectend', onSessionEvent ); 25359 session.removeEventListener( 'squeeze', onSessionEvent ); 25360 session.removeEventListener( 'squeezestart', onSessionEvent ); 25361 session.removeEventListener( 'squeezeend', onSessionEvent ); 25362 session.removeEventListener( 'end', onSessionEnd ); 25363 session.removeEventListener( 'inputsourceschange', onInputSourcesChange ); 25364 25365 for ( let i = 0; i < controllers.length; i ++ ) { 25366 25367 const inputSource = controllerInputSources[ i ]; 25368 25369 if ( inputSource === null ) continue; 25370 25371 controllerInputSources[ i ] = null; 25372 25373 controllers[ i ].disconnect( inputSource ); 25374 25375 } 25376 25377 _currentDepthNear = null; 25378 _currentDepthFar = null; 25379 25380 // restore framebuffer/rendering state 25381 25382 renderer.setRenderTarget( initialRenderTarget ); 25383 25384 glBaseLayer = null; 25385 glProjLayer = null; 25386 glBinding = null; 25387 session = null; 25388 newRenderTarget = null; 25389 25390 // 25391 25392 animation.stop(); 25393 25394 scope.isPresenting = false; 25395 25396 scope.dispatchEvent( { type: 'sessionend' } ); 25397 25398 } 25399 25400 this.setFramebufferScaleFactor = function ( value ) { 25401 25402 framebufferScaleFactor = value; 25403 25404 if ( scope.isPresenting === true ) { 25405 25406 console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' ); 25407 25408 } 25409 25410 }; 25411 25412 this.setReferenceSpaceType = function ( value ) { 25413 25414 referenceSpaceType = value; 25415 25416 if ( scope.isPresenting === true ) { 25417 25418 console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' ); 25419 25420 } 25421 25422 }; 25423 25424 this.getReferenceSpace = function () { 25425 25426 return customReferenceSpace || referenceSpace; 25427 25428 }; 25429 25430 this.setReferenceSpace = function ( space ) { 25431 25432 customReferenceSpace = space; 25433 25434 }; 25435 25436 this.getBaseLayer = function () { 25437 25438 return glProjLayer !== null ? glProjLayer : glBaseLayer; 25439 25440 }; 25441 25442 this.getBinding = function () { 25443 25444 return glBinding; 25445 25446 }; 25447 25448 this.getFrame = function () { 25449 25450 return xrFrame; 25451 25452 }; 25453 25454 this.getSession = function () { 25455 25456 return session; 25457 25458 }; 25459 25460 this.setSession = async function ( value ) { 25461 25462 session = value; 25463 25464 if ( session !== null ) { 25465 25466 initialRenderTarget = renderer.getRenderTarget(); 25467 25468 session.addEventListener( 'select', onSessionEvent ); 25469 session.addEventListener( 'selectstart', onSessionEvent ); 25470 session.addEventListener( 'selectend', onSessionEvent ); 25471 session.addEventListener( 'squeeze', onSessionEvent ); 25472 session.addEventListener( 'squeezestart', onSessionEvent ); 25473 session.addEventListener( 'squeezeend', onSessionEvent ); 25474 session.addEventListener( 'end', onSessionEnd ); 25475 session.addEventListener( 'inputsourceschange', onInputSourcesChange ); 25476 25477 if ( attributes.xrCompatible !== true ) { 25478 25479 await gl.makeXRCompatible(); 25480 25481 } 25482 25483 if ( ( session.renderState.layers === undefined ) || ( renderer.capabilities.isWebGL2 === false ) ) { 25484 25485 const layerInit = { 25486 antialias: ( session.renderState.layers === undefined ) ? attributes.antialias : true, 25487 alpha: attributes.alpha, 25488 depth: attributes.depth, 25489 stencil: attributes.stencil, 25490 framebufferScaleFactor: framebufferScaleFactor 25491 }; 25492 25493 glBaseLayer = new XRWebGLLayer( session, gl, layerInit ); 25494 25495 session.updateRenderState( { baseLayer: glBaseLayer } ); 25496 25497 newRenderTarget = new WebGLRenderTarget( 25498 glBaseLayer.framebufferWidth, 25499 glBaseLayer.framebufferHeight, 25500 { 25501 format: RGBAFormat, 25502 type: UnsignedByteType, 25503 encoding: renderer.outputEncoding, 25504 stencilBuffer: attributes.stencil 25505 } 25506 ); 25507 25508 } else { 25509 25510 let depthFormat = null; 25511 let depthType = null; 25512 let glDepthFormat = null; 25513 25514 if ( attributes.depth ) { 25515 25516 glDepthFormat = attributes.stencil ? 35056 : 33190; 25517 depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat; 25518 depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType; 25519 25520 } 25521 25522 const projectionlayerInit = { 25523 colorFormat: 32856, 25524 depthFormat: glDepthFormat, 25525 scaleFactor: framebufferScaleFactor 25526 }; 25527 25528 glBinding = new XRWebGLBinding( session, gl ); 25529 25530 glProjLayer = glBinding.createProjectionLayer( projectionlayerInit ); 25531 25532 session.updateRenderState( { layers: [ glProjLayer ] } ); 25533 25534 newRenderTarget = new WebGLRenderTarget( 25535 glProjLayer.textureWidth, 25536 glProjLayer.textureHeight, 25537 { 25538 format: RGBAFormat, 25539 type: UnsignedByteType, 25540 depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), 25541 stencilBuffer: attributes.stencil, 25542 encoding: renderer.outputEncoding, 25543 samples: attributes.antialias ? 4 : 0 25544 } ); 25545 25546 const renderTargetProperties = renderer.properties.get( newRenderTarget ); 25547 renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues; 25548 25549 } 25550 25551 newRenderTarget.isXRRenderTarget = true; // TODO Remove this when possible, see #23278 25552 25553 this.setFoveation( foveation ); 25554 25555 customReferenceSpace = null; 25556 referenceSpace = await session.requestReferenceSpace( referenceSpaceType ); 25557 25558 animation.setContext( session ); 25559 animation.start(); 25560 25561 scope.isPresenting = true; 25562 25563 scope.dispatchEvent( { type: 'sessionstart' } ); 25564 25565 } 25566 25567 }; 25568 25569 function onInputSourcesChange( event ) { 25570 25571 // Notify disconnected 25572 25573 for ( let i = 0; i < event.removed.length; i ++ ) { 25574 25575 const inputSource = event.removed[ i ]; 25576 const index = controllerInputSources.indexOf( inputSource ); 25577 25578 if ( index >= 0 ) { 25579 25580 controllerInputSources[ index ] = null; 25581 controllers[ index ].disconnect( inputSource ); 25582 25583 } 25584 25585 } 25586 25587 // Notify connected 25588 25589 for ( let i = 0; i < event.added.length; i ++ ) { 25590 25591 const inputSource = event.added[ i ]; 25592 25593 let controllerIndex = controllerInputSources.indexOf( inputSource ); 25594 25595 if ( controllerIndex === - 1 ) { 25596 25597 // Assign input source a controller that currently has no input source 25598 25599 for ( let i = 0; i < controllers.length; i ++ ) { 25600 25601 if ( i >= controllerInputSources.length ) { 25602 25603 controllerInputSources.push( inputSource ); 25604 controllerIndex = i; 25605 break; 25606 25607 } else if ( controllerInputSources[ i ] === null ) { 25608 25609 controllerInputSources[ i ] = inputSource; 25610 controllerIndex = i; 25611 break; 25612 25613 } 25614 25615 } 25616 25617 // If all controllers do currently receive input we ignore new ones 25618 25619 if ( controllerIndex === - 1 ) break; 25620 25621 } 25622 25623 const controller = controllers[ controllerIndex ]; 25624 25625 if ( controller ) { 25626 25627 controller.connect( inputSource ); 25628 25629 } 25630 25631 } 25632 25633 } 25634 25635 // 25636 25637 const cameraLPos = new Vector3(); 25638 const cameraRPos = new Vector3(); 25639 25640 /** 25641 * Assumes 2 cameras that are parallel and share an X-axis, and that 25642 * the cameras' projection and world matrices have already been set. 25643 * And that near and far planes are identical for both cameras. 25644 * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 25645 */ 25646 function setProjectionFromUnion( camera, cameraL, cameraR ) { 25647 25648 cameraLPos.setFromMatrixPosition( cameraL.matrixWorld ); 25649 cameraRPos.setFromMatrixPosition( cameraR.matrixWorld ); 25650 25651 const ipd = cameraLPos.distanceTo( cameraRPos ); 25652 25653 const projL = cameraL.projectionMatrix.elements; 25654 const projR = cameraR.projectionMatrix.elements; 25655 25656 // VR systems will have identical far and near planes, and 25657 // most likely identical top and bottom frustum extents. 25658 // Use the left camera for these values. 25659 const near = projL[ 14 ] / ( projL[ 10 ] - 1 ); 25660 const far = projL[ 14 ] / ( projL[ 10 ] + 1 ); 25661 const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ]; 25662 const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ]; 25663 25664 const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ]; 25665 const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ]; 25666 const left = near * leftFov; 25667 const right = near * rightFov; 25668 25669 // Calculate the new camera's position offset from the 25670 // left camera. xOffset should be roughly half `ipd`. 25671 const zOffset = ipd / ( - leftFov + rightFov ); 25672 const xOffset = zOffset * - leftFov; 25673 25674 // TODO: Better way to apply this offset? 25675 cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale ); 25676 camera.translateX( xOffset ); 25677 camera.translateZ( zOffset ); 25678 camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale ); 25679 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); 25680 25681 // Find the union of the frustum values of the cameras and scale 25682 // the values so that the near plane's position does not change in world space, 25683 // although must now be relative to the new union camera. 25684 const near2 = near + zOffset;
25685 const far2 = far + zOffset; 25686 const left2 = left - xOffset; 25687 const right2 = right + ( ipd - xOffset ); 25688 const top2 = topFov * far / far2 * near2; 25689 const bottom2 = bottomFov * far / far2 * near2; 25690 25691 camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); 25692 25693 } 25694 25695 function updateCamera( camera, parent ) { 25696 25697 if ( parent === null ) { 25698 25699 camera.matrixWorld.copy( camera.matrix ); 25700 25701 } else { 25702 25703 camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix ); 25704 25705 } 25706 25707 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); 25708 25709 } 25710 25711 this.updateCamera = function ( camera ) { 25712 25713 if ( session === null ) return; 25714 25715 cameraVR.near = cameraR.near = cameraL.near = camera.near; 25716 cameraVR.far = cameraR.far = cameraL.far = camera.far; 25717 25718 if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) { 25719 25720 // Note that the new renderState won't apply until the next frame. See #18320 25721 25722 session.updateRenderState( { 25723 depthNear: cameraVR.near, 25724 depthFar: cameraVR.far 25725 } ); 25726 25727 _currentDepthNear = cameraVR.near; 25728 _currentDepthFar = cameraVR.far; 25729 25730 } 25731 25732 const parent = camera.parent; 25733 const cameras = cameraVR.cameras; 25734 25735 updateCamera( cameraVR, parent ); 25736 25737 for ( let i = 0; i < cameras.length; i ++ ) { 25738 25739 updateCamera( cameras[ i ], parent ); 25740 25741 } 25742 25743 cameraVR.matrixWorld.decompose( cameraVR.position, cameraVR.quaternion, cameraVR.scale ); 25744 25745 // update user camera and its children 25746 25747 camera.matrix.copy( cameraVR.matrix ); 25748 camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); 25749 25750 const children = camera.children; 25751 25752 for ( let i = 0, l = children.length; i < l; i ++ ) { 25753 25754 children[ i ].updateMatrixWorld( true ); 25755 25756 } 25757 25758 // update projection matrix for proper view frustum culling 25759 25760 if ( cameras.length === 2 ) { 25761 25762 setProjectionFromUnion( cameraVR, cameraL, cameraR ); 25763 25764 } else { 25765 25766 // assume single camera setup (AR) 25767 25768 cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); 25769 25770 } 25771 25772 }; 25773 25774 this.getCamera = function () { 25775 25776 return cameraVR; 25777 25778 }; 25779 25780 this.getFoveation = function () { 25781 25782 if ( glProjLayer === null && glBaseLayer === null ) { 25783 25784 return undefined; 25785 25786 } 25787 25788 return foveation; 25789 25790 }; 25791 25792 this.setFoveation = function ( value ) { 25793 25794 // 0 = no foveation = full resolution 25795 // 1 = maximum foveation = the edges render at lower resolution 25796 25797 foveation = value; 25798 25799 if ( glProjLayer !== null ) { 25800 25801 glProjLayer.fixedFoveation = value; 25802 25803 } 25804 25805 if ( glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined ) { 25806 25807 glBaseLayer.fixedFoveation = value; 25808 25809 } 25810 25811 }; 25812 25813 this.getPlanes = function () { 25814 25815 return planes; 25816 25817 }; 25818 25819 // Animation Loop 25820 25821 let onAnimationFrameCallback = null; 25822 25823 function onAnimationFrame( time, frame ) { 25824 25825 pose = frame.getViewerPose( customReferenceSpace || referenceSpace ); 25826 xrFrame = frame; 25827 25828 if ( pose !== null ) { 25829 25830 const views = pose.views; 25831 25832 if ( glBaseLayer !== null ) { 25833 25834 renderer.setRenderTargetFramebuffer( newRenderTarget, glBaseLayer.framebuffer ); 25835 renderer.setRenderTarget( newRenderTarget ); 25836 25837 } 25838 25839 let cameraVRNeedsUpdate = false; 25840 25841 // check if it's necessary to rebuild cameraVR's camera list 25842 25843 if ( views.length !== cameraVR.cameras.length ) { 25844 25845 cameraVR.cameras.length = 0; 25846 cameraVRNeedsUpdate = true; 25847 25848 } 25849 25850 for ( let i = 0; i < views.length; i ++ ) { 25851 25852 const view = views[ i ]; 25853 25854 let viewport = null; 25855 25856 if ( glBaseLayer !== null ) { 25857 25858 viewport = glBaseLayer.getViewport( view ); 25859 25860 } else { 25861 25862 const glSubImage = glBinding.getViewSubImage( glProjLayer, view ); 25863 viewport = glSubImage.viewport; 25864 25865 // For side-by-side projection, we only produce a single texture for both eyes. 25866 if ( i === 0 ) { 25867 25868 renderer.setRenderTargetTextures( 25869 newRenderTarget, 25870 glSubImage.colorTexture, 25871 glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture ); 25872 25873 renderer.setRenderTarget( newRenderTarget ); 25874 25875 } 25876 25877 } 25878 25879 let camera = cameras[ i ]; 25880 25881 if ( camera === undefined ) { 25882 25883 camera = new PerspectiveCamera(); 25884 camera.layers.enable( i ); 25885 camera.viewport = new Vector4(); 25886 cameras[ i ] = camera; 25887 25888 } 25889 25890 camera.matrix.fromArray( view.transform.matrix ); 25891 camera.projectionMatrix.fromArray( view.projectionMatrix ); 25892 camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); 25893 25894 if ( i === 0 ) { 25895 25896 cameraVR.matrix.copy( camera.matrix ); 25897 25898 } 25899 25900 if ( cameraVRNeedsUpdate === true ) { 25901 25902 cameraVR.cameras.push( camera ); 25903 25904 } 25905 25906 } 25907 25908 } 25909 25910 // 25911 25912 for ( let i = 0; i < controllers.length; i ++ ) { 25913 25914 const inputSource = controllerInputSources[ i ]; 25915 const controller = controllers[ i ]; 25916 25917 if ( inputSource !== null && controller !== undefined ) { 25918 25919 controller.update( inputSource, frame, customReferenceSpace || referenceSpace ); 25920 25921 } 25922 25923 } 25924 25925 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame ); 25926 25927 if ( frame.detectedPlanes ) { 25928 25929 scope.dispatchEvent( { type: 'planesdetected', data: frame.detectedPlanes } ); 25930 25931 let planesToRemove = null; 25932 25933 for ( const plane of planes ) { 25934 25935 if ( ! frame.detectedPlanes.has( plane ) ) { 25936 25937 if ( planesToRemove === null ) { 25938 25939 planesToRemove = []; 25940 25941 } 25942 25943 planesToRemove.push( plane ); 25944 25945 } 25946 25947 } 25948 25949 if ( planesToRemove !== null ) { 25950 25951 for ( const plane of planesToRemove ) { 25952 25953 planes.delete( plane ); 25954 planesLastChangedTimes.delete( plane ); 25955 scope.dispatchEvent( { type: 'planeremoved', data: plane } ); 25956 25957 } 25958 25959 } 25960 25961 for ( const plane of frame.detectedPlanes ) { 25962
vendor: 16,384 bytes, lines 25963-26738
25963 if ( ! planes.has( plane ) ) { 25964 25965 planes.add( plane ); 25966 planesLastChangedTimes.set( plane, frame.lastChangedTime ); 25967 scope.dispatchEvent( { type: 'planeadded', data: plane } ); 25968 25969 } else { 25970 25971 const lastKnownTime = planesLastChangedTimes.get( plane ); 25972 25973 if ( plane.lastChangedTime > lastKnownTime ) { 25974 25975 planesLastChangedTimes.set( plane, plane.lastChangedTime ); 25976 scope.dispatchEvent( { type: 'planechanged', data: plane } ); 25977 25978 } 25979 25980 } 25981 25982 } 25983 25984 } 25985 25986 xrFrame = null; 25987 25988 } 25989 25990 const animation = new WebGLAnimation(); 25991 25992 animation.setAnimationLoop( onAnimationFrame ); 25993 25994 this.setAnimationLoop = function ( callback ) { 25995 25996 onAnimationFrameCallback = callback; 25997 25998 }; 25999 26000 this.dispose = function () {}; 26001 26002 } 26003 26004} 26005 26006function WebGLMaterials( renderer, properties ) { 26007 26008 function refreshFogUniforms( uniforms, fog ) { 26009 26010 fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) ); 26011 26012 if ( fog.isFog ) { 26013 26014 uniforms.fogNear.value = fog.near; 26015 uniforms.fogFar.value = fog.far; 26016 26017 } else if ( fog.isFogExp2 ) { 26018 26019 uniforms.fogDensity.value = fog.density; 26020 26021 } 26022 26023 } 26024 26025 function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) { 26026 26027 if ( material.isMeshBasicMaterial ) { 26028 26029 refreshUniformsCommon( uniforms, material ); 26030 26031 } else if ( material.isMeshLambertMaterial ) { 26032 26033 refreshUniformsCommon( uniforms, material ); 26034 26035 } else if ( material.isMeshToonMaterial ) { 26036 26037 refreshUniformsCommon( uniforms, material ); 26038 refreshUniformsToon( uniforms, material ); 26039 26040 } else if ( material.isMeshPhongMaterial ) { 26041 26042 refreshUniformsCommon( uniforms, material ); 26043 refreshUniformsPhong( uniforms, material ); 26044 26045 } else if ( material.isMeshStandardMaterial ) { 26046 26047 refreshUniformsCommon( uniforms, material ); 26048 refreshUniformsStandard( uniforms, material ); 26049 26050 if ( material.isMeshPhysicalMaterial ) { 26051 26052 refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ); 26053 26054 } 26055 26056 } else if ( material.isMeshMatcapMaterial ) { 26057 26058 refreshUniformsCommon( uniforms, material ); 26059 refreshUniformsMatcap( uniforms, material ); 26060 26061 } else if ( material.isMeshDepthMaterial ) { 26062 26063 refreshUniformsCommon( uniforms, material ); 26064 26065 } else if ( material.isMeshDistanceMaterial ) { 26066 26067 refreshUniformsCommon( uniforms, material ); 26068 refreshUniformsDistance( uniforms, material ); 26069 26070 } else if ( material.isMeshNormalMaterial ) { 26071 26072 refreshUniformsCommon( uniforms, material ); 26073 26074 } else if ( material.isLineBasicMaterial ) { 26075 26076 refreshUniformsLine( uniforms, material ); 26077 26078 if ( material.isLineDashedMaterial ) { 26079 26080 refreshUniformsDash( uniforms, material ); 26081 26082 } 26083 26084 } else if ( material.isPointsMaterial ) { 26085 26086 refreshUniformsPoints( uniforms, material, pixelRatio, height ); 26087 26088 } else if ( material.isSpriteMaterial ) { 26089 26090 refreshUniformsSprites( uniforms, material ); 26091 26092 } else if ( material.isShadowMaterial ) { 26093 26094 uniforms.color.value.copy( material.color ); 26095 uniforms.opacity.value = material.opacity; 26096 26097 } else if ( material.isShaderMaterial ) { 26098 26099 material.uniformsNeedUpdate = false; // #15581 26100 26101 } 26102 26103 } 26104 26105 function refreshUniformsCommon( uniforms, material ) { 26106 26107 uniforms.opacity.value = material.opacity; 26108 26109 if ( material.color ) { 26110 26111 uniforms.diffuse.value.copy( material.color ); 26112 26113 } 26114 26115 if ( material.emissive ) { 26116 26117 uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity ); 26118 26119 } 26120 26121 if ( material.map ) { 26122 26123 uniforms.map.value = material.map; 26124 26125 } 26126 26127 if ( material.alphaMap ) { 26128 26129 uniforms.alphaMap.value = material.alphaMap; 26130 26131 } 26132 26133 if ( material.bumpMap ) { 26134 26135 uniforms.bumpMap.value = material.bumpMap; 26136 uniforms.bumpScale.value = material.bumpScale; 26137 if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1; 26138 26139 } 26140 26141 if ( material.displacementMap ) { 26142 26143 uniforms.displacementMap.value = material.displacementMap; 26144 uniforms.displacementScale.value = material.displacementScale; 26145 uniforms.displacementBias.value = material.displacementBias; 26146 26147 } 26148 26149 if ( material.emissiveMap ) { 26150 26151 uniforms.emissiveMap.value = material.emissiveMap; 26152 26153 } 26154 26155 if ( material.normalMap ) { 26156 26157 uniforms.normalMap.value = material.normalMap; 26158 uniforms.normalScale.value.copy( material.normalScale ); 26159 if ( material.side === BackSide ) uniforms.normalScale.value.negate(); 26160 26161 } 26162 26163 if ( material.specularMap ) { 26164 26165 uniforms.specularMap.value = material.specularMap; 26166 26167 } 26168 26169 if ( material.alphaTest > 0 ) { 26170 26171 uniforms.alphaTest.value = material.alphaTest; 26172 26173 } 26174 26175 const envMap = properties.get( material ).envMap; 26176 26177 if ( envMap ) { 26178 26179 uniforms.envMap.value = envMap; 26180 26181 uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; 26182 26183 uniforms.reflectivity.value = material.reflectivity; 26184 uniforms.ior.value = material.ior; 26185 uniforms.refractionRatio.value = material.refractionRatio; 26186 26187 } 26188 26189 if ( material.lightMap ) { 26190 26191 uniforms.lightMap.value = material.lightMap; 26192 26193 // artist-friendly light intensity scaling factor 26194 const scaleFactor = ( renderer.useLegacyLights === true ) ? Math.PI : 1; 26195 26196 uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor; 26197 26198 } 26199 26200 if ( material.aoMap ) { 26201 26202 uniforms.aoMap.value = material.aoMap; 26203 uniforms.aoMapIntensity.value = material.aoMapIntensity; 26204 26205 } 26206 26207 // uv repeat and offset setting priorities 26208 // 1. color map 26209 // 2. specular map 26210 // 3. displacementMap map 26211 // 4. normal map 26212 // 5. bump map 26213 // 6. roughnessMap map 26214 // 7. metalnessMap map 26215 // 8. alphaMap map 26216 // 9. emissiveMap map 26217 // 10. clearcoat map 26218 // 11. clearcoat normal map 26219 // 12. clearcoat roughnessMap map 26220 // 13. iridescence map 26221 // 14. iridescence thickness map 26222 // 15. specular intensity map 26223 // 16. specular tint map 26224 // 17. transmission map 26225 // 18. thickness map 26226 26227 let uvScaleMap; 26228 26229 if ( material.map ) { 26230 26231 uvScaleMap = material.map; 26232 26233 } else if ( material.specularMap ) { 26234 26235 uvScaleMap = material.specularMap; 26236 26237 } else if ( material.displacementMap ) { 26238 26239 uvScaleMap = material.displacementMap; 26240 26241 } else if ( material.normalMap ) { 26242 26243 uvScaleMap = material.normalMap; 26244 26245 } else if ( material.bumpMap ) { 26246 26247 uvScaleMap = material.bumpMap; 26248 26249 } else if ( material.roughnessMap ) { 26250 26251 uvScaleMap = material.roughnessMap; 26252 26253 } else if ( material.metalnessMap ) { 26254 26255 uvScaleMap = material.metalnessMap; 26256 26257 } else if ( material.alphaMap ) { 26258 26259 uvScaleMap = material.alphaMap; 26260 26261 } else if ( material.emissiveMap ) { 26262 26263 uvScaleMap = material.emissiveMap; 26264 26265 } else if ( material.clearcoatMap ) { 26266 26267 uvScaleMap = material.clearcoatMap; 26268 26269 } else if ( material.clearcoatNormalMap ) { 26270 26271 uvScaleMap = material.clearcoatNormalMap; 26272 26273 } else if ( material.clearcoatRoughnessMap ) { 26274 26275 uvScaleMap = material.clearcoatRoughnessMap; 26276 26277 } else if ( material.iridescenceMap ) { 26278 26279 uvScaleMap = material.iridescenceMap; 26280 26281 } else if ( material.iridescenceThicknessMap ) { 26282 26283 uvScaleMap = material.iridescenceThicknessMap; 26284 26285 } else if ( material.specularIntensityMap ) { 26286 26287 uvScaleMap = material.specularIntensityMap; 26288 26289 } else if ( material.specularColorMap ) { 26290 26291 uvScaleMap = material.specularColorMap; 26292 26293 } else if ( material.transmissionMap ) { 26294 26295 uvScaleMap = material.transmissionMap; 26296 26297 } else if ( material.thicknessMap ) { 26298 26299 uvScaleMap = material.thicknessMap; 26300 26301 } else if ( material.sheenColorMap ) { 26302 26303 uvScaleMap = material.sheenColorMap; 26304 26305 } else if ( material.sheenRoughnessMap ) { 26306 26307 uvScaleMap = material.sheenRoughnessMap; 26308 26309 } 26310 26311 if ( uvScaleMap !== undefined ) { 26312 26313 // backwards compatibility 26314 if ( uvScaleMap.isWebGLRenderTarget ) { 26315 26316 uvScaleMap = uvScaleMap.texture; 26317 26318 } 26319 26320 if ( uvScaleMap.matrixAutoUpdate === true ) { 26321 26322 uvScaleMap.updateMatrix(); 26323 26324 } 26325 26326 uniforms.uvTransform.value.copy( uvScaleMap.matrix ); 26327 26328 } 26329 26330 // uv repeat and offset setting priorities for uv2 26331 // 1. ao map 26332 // 2. light map 26333 26334 let uv2ScaleMap; 26335 26336 if ( material.aoMap ) { 26337 26338 uv2ScaleMap = material.aoMap; 26339 26340 } else if ( material.lightMap ) { 26341 26342 uv2ScaleMap = material.lightMap; 26343 26344 } 26345 26346 if ( uv2ScaleMap !== undefined ) { 26347 26348 // backwards compatibility 26349 if ( uv2ScaleMap.isWebGLRenderTarget ) { 26350 26351 uv2ScaleMap = uv2ScaleMap.texture; 26352 26353 } 26354 26355 if ( uv2ScaleMap.matrixAutoUpdate === true ) { 26356 26357 uv2ScaleMap.updateMatrix(); 26358 26359 } 26360 26361 uniforms.uv2Transform.value.copy( uv2ScaleMap.matrix ); 26362 26363 } 26364 26365 } 26366 26367 function refreshUniformsLine( uniforms, material ) { 26368 26369 uniforms.diffuse.value.copy( material.color ); 26370 uniforms.opacity.value = material.opacity; 26371 26372 } 26373 26374 function refreshUniformsDash( uniforms, material ) { 26375 26376 uniforms.dashSize.value = material.dashSize; 26377 uniforms.totalSize.value = material.dashSize + material.gapSize; 26378 uniforms.scale.value = material.scale; 26379 26380 } 26381 26382 function refreshUniformsPoints( uniforms, material, pixelRatio, height ) { 26383 26384 uniforms.diffuse.value.copy( material.color ); 26385 uniforms.opacity.value = material.opacity; 26386 uniforms.size.value = material.size * pixelRatio; 26387 uniforms.scale.value = height * 0.5; 26388 26389 if ( material.map ) { 26390 26391 uniforms.map.value = material.map; 26392 26393 } 26394 26395 if ( material.alphaMap ) { 26396 26397 uniforms.alphaMap.value = material.alphaMap; 26398 26399 } 26400 26401 if ( material.alphaTest > 0 ) { 26402 26403 uniforms.alphaTest.value = material.alphaTest; 26404 26405 } 26406 26407 // uv repeat and offset setting priorities 26408 // 1. color map 26409 // 2. alpha map 26410 26411 let uvScaleMap; 26412 26413 if ( material.map ) { 26414 26415 uvScaleMap = material.map; 26416 26417 } else if ( material.alphaMap ) { 26418 26419 uvScaleMap = material.alphaMap; 26420 26421 } 26422 26423 if ( uvScaleMap !== undefined ) { 26424 26425 if ( uvScaleMap.matrixAutoUpdate === true ) { 26426 26427 uvScaleMap.updateMatrix(); 26428 26429 } 26430 26431 uniforms.uvTransform.value.copy( uvScaleMap.matrix ); 26432 26433 } 26434 26435 } 26436 26437 function refreshUniformsSprites( uniforms, material ) { 26438 26439 uniforms.diffuse.value.copy( material.color ); 26440 uniforms.opacity.value = material.opacity; 26441 uniforms.rotation.value = material.rotation; 26442 26443 if ( material.map ) { 26444 26445 uniforms.map.value = material.map; 26446 26447 } 26448 26449 if ( material.alphaMap ) { 26450 26451 uniforms.alphaMap.value = material.alphaMap; 26452 26453 } 26454 26455 if ( material.alphaTest > 0 ) { 26456 26457 uniforms.alphaTest.value = material.alphaTest; 26458 26459 } 26460 26461 // uv repeat and offset setting priorities 26462 // 1. color map 26463 // 2. alpha map 26464 26465 let uvScaleMap; 26466 26467 if ( material.map ) { 26468 26469 uvScaleMap = material.map; 26470 26471 } else if ( material.alphaMap ) { 26472 26473 uvScaleMap = material.alphaMap; 26474 26475 } 26476 26477 if ( uvScaleMap !== undefined ) { 26478 26479 if ( uvScaleMap.matrixAutoUpdate === true ) { 26480 26481 uvScaleMap.updateMatrix(); 26482 26483 } 26484 26485 uniforms.uvTransform.value.copy( uvScaleMap.matrix ); 26486 26487 } 26488 26489 } 26490 26491 function refreshUniformsPhong( uniforms, material ) { 26492 26493 uniforms.specular.value.copy( material.specular ); 26494 uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 ) 26495 26496 } 26497 26498 function refreshUniformsToon( uniforms, material ) { 26499 26500 if ( material.gradientMap ) { 26501 26502 uniforms.gradientMap.value = material.gradientMap; 26503 26504 } 26505 26506 } 26507 26508 function refreshUniformsStandard( uniforms, material ) { 26509 26510 uniforms.roughness.value = material.roughness; 26511 uniforms.metalness.value = material.metalness; 26512 26513 if ( material.roughnessMap ) { 26514 26515 uniforms.roughnessMap.value = material.roughnessMap; 26516 26517 } 26518 26519 if ( material.metalnessMap ) { 26520 26521 uniforms.metalnessMap.value = material.metalnessMap; 26522 26523 } 26524 26525 const envMap = properties.get( material ).envMap; 26526 26527 if ( envMap ) { 26528 26529 //uniforms.envMap.value = material.envMap; // part of uniforms common 26530 uniforms.envMapIntensity.value = material.envMapIntensity; 26531 26532 } 26533 26534 } 26535 26536 function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) { 26537 26538 uniforms.ior.value = material.ior; // also part of uniforms common 26539 26540 if ( material.sheen > 0 ) { 26541 26542 uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen ); 26543 26544 uniforms.sheenRoughness.value = material.sheenRoughness; 26545 26546 if ( material.sheenColorMap ) { 26547 26548 uniforms.sheenColorMap.value = material.sheenColorMap; 26549 26550 } 26551 26552 if ( material.sheenRoughnessMap ) { 26553 26554 uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; 26555 26556 } 26557 26558 } 26559 26560 if ( material.clearcoat > 0 ) { 26561 26562 uniforms.clearcoat.value = material.clearcoat; 26563 uniforms.clearcoatRoughness.value = material.clearcoatRoughness; 26564 26565 if ( material.clearcoatMap ) { 26566 26567 uniforms.clearcoatMap.value = material.clearcoatMap; 26568 26569 } 26570 26571 if ( material.clearcoatRoughnessMap ) { 26572 26573 uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; 26574 26575 } 26576 26577 if ( material.clearcoatNormalMap ) { 26578 26579 uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); 26580 uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; 26581 26582 if ( material.side === BackSide ) { 26583 26584 uniforms.clearcoatNormalScale.value.negate(); 26585 26586 } 26587 26588 } 26589 26590 } 26591 26592 if ( material.iridescence > 0 ) { 26593 26594 uniforms.iridescence.value = material.iridescence; 26595 uniforms.iridescenceIOR.value = material.iridescenceIOR; 26596 uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[ 0 ]; 26597 uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[ 1 ]; 26598 26599 if ( material.iridescenceMap ) { 26600 26601 uniforms.iridescenceMap.value = material.iridescenceMap; 26602 26603 } 26604 26605 if ( material.iridescenceThicknessMap ) { 26606 26607 uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; 26608 26609 } 26610 26611 } 26612 26613 if ( material.transmission > 0 ) { 26614 26615 uniforms.transmission.value = material.transmission; 26616 uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture; 26617 uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height ); 26618 26619 if ( material.transmissionMap ) { 26620 26621 uniforms.transmissionMap.value = material.transmissionMap; 26622 26623 } 26624 26625 uniforms.thickness.value = material.thickness; 26626 26627 if ( material.thicknessMap ) { 26628 26629 uniforms.thicknessMap.value = material.thicknessMap; 26630 26631 } 26632 26633 uniforms.attenuationDistance.value = material.attenuationDistance; 26634 uniforms.attenuationColor.value.copy( material.attenuationColor ); 26635 26636 } 26637 26638 uniforms.specularIntensity.value = material.specularIntensity; 26639 uniforms.specularColor.value.copy( material.specularColor ); 26640 26641 if ( material.specularIntensityMap ) { 26642 26643 uniforms.specularIntensityMap.value = material.specularIntensityMap; 26644 26645 } 26646 26647 if ( material.specularColorMap ) { 26648 26649 uniforms.specularColorMap.value = material.specularColorMap; 26650 26651 } 26652 26653 } 26654 26655 function refreshUniformsMatcap( uniforms, material ) { 26656 26657 if ( material.matcap ) { 26658 26659 uniforms.matcap.value = material.matcap; 26660 26661 } 26662 26663 } 26664 26665 function refreshUniformsDistance( uniforms, material ) { 26666 26667 uniforms.referencePosition.value.copy( material.referencePosition ); 26668 uniforms.nearDistance.value = material.nearDistance; 26669 uniforms.farDistance.value = material.farDistance; 26670 26671 } 26672 26673 return { 26674 refreshFogUniforms: refreshFogUniforms, 26675 refreshMaterialUniforms: refreshMaterialUniforms 26676 }; 26677 26678} 26679 26680function WebGLUniformsGroups( gl, info, capabilities, state ) { 26681 26682 let buffers = {}; 26683 let updateList = {}; 26684 let allocatedBindingPoints = []; 26685 26686 const maxBindingPoints = ( capabilities.isWebGL2 ) ? gl.getParameter( 35375 ) : 0; // binding points are global whereas block indices are per shader program 26687 26688 function bind( uniformsGroup, program ) { 26689 26690 const webglProgram = program.program; 26691 state.uniformBlockBinding( uniformsGroup, webglProgram ); 26692 26693 } 26694 26695 function update( uniformsGroup, program ) { 26696 26697 let buffer = buffers[ uniformsGroup.id ]; 26698 26699 if ( buffer === undefined ) { 26700 26701 prepareUniformsGroup( uniformsGroup ); 26702 26703 buffer = createBuffer( uniformsGroup ); 26704 buffers[ uniformsGroup.id ] = buffer; 26705 26706 uniformsGroup.addEventListener( 'dispose', onUniformsGroupsDispose ); 26707 26708 } 26709 26710 // ensure to update the binding points/block indices mapping for this program 26711 26712 const webglProgram = program.program; 26713 state.updateUBOMapping( uniformsGroup, webglProgram ); 26714 26715 // update UBO once per frame 26716 26717 const frame = info.render.frame; 26718 26719 if ( updateList[ uniformsGroup.id ] !== frame ) { 26720 26721 updateBufferData( uniformsGroup ); 26722 26723 updateList[ uniformsGroup.id ] = frame; 26724 26725 } 26726 26727 } 26728 26729 function createBuffer( uniformsGroup ) { 26730 26731 // the setup of an UBO is independent of a particular shader program but global 26732 26733 const bindingPointIndex = allocateBindingPointIndex(); 26734 uniformsGroup.__bindingPointIndex = bindingPointIndex; 26735 26736 const buffer = gl.createBuffer(); 26737 const size = uniformsGroup.__size; 26738 const usage = uniformsGroup
26738.usage; 26739 26740 gl.bindBuffer( 35345, buffer ); 26741 gl.bufferData( 35345, size, usage ); 26742 gl.bindBuffer( 35345, null ); 26743 gl.bindBufferBase( 35345, bindingPointIndex, buffer ); 26744 26745 return buffer; 26746 26747 } 26748 26749 function allocateBindingPointIndex() { 26750 26751 for ( let i = 0; i < maxBindingPoints; i ++ ) { 26752 26753 if ( allocatedBindingPoints.indexOf( i ) === - 1 ) { 26754 26755 allocatedBindingPoints.push( i ); 26756 return i; 26757 26758 } 26759 26760 } 26761 26762 console.error( 'THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' ); 26763 26764 return 0; 26765 26766 } 26767 26768 function updateBufferData( uniformsGroup ) { 26769 26770 const buffer = buffers[ uniformsGroup.id ]; 26771 const uniforms = uniformsGroup.uniforms; 26772 const cache = uniformsGroup.__cache; 26773 26774 gl.bindBuffer( 35345, buffer ); 26775 26776 for ( let i = 0, il = uniforms.length; i < il; i ++ ) { 26777 26778 const uniform = uniforms[ i ]; 26779 26780 // partly update the buffer if necessary 26781 26782 if ( hasUniformChanged( uniform, i, cache ) === true ) { 26783 26784 const offset = uniform.__offset; 26785 26786 const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; 26787 26788 let arrayOffset = 0; 26789 26790 for ( let i = 0; i < values.length; i ++ ) { 26791 26792 const value = values[ i ]; 26793 26794 const info = getUniformSize( value ); 26795 26796 if ( typeof value === 'number' ) { 26797 26798 uniform.__data[ 0 ] = value; 26799 gl.bufferSubData( 35345, offset + arrayOffset, uniform.__data ); 26800 26801 } else if ( value.isMatrix3 ) { 26802 26803 // manually converting 3x3 to 3x4 26804 26805 uniform.__data[ 0 ] = value.elements[ 0 ]; 26806 uniform.__data[ 1 ] = value.elements[ 1 ]; 26807 uniform.__data[ 2 ] = value.elements[ 2 ]; 26808 uniform.__data[ 3 ] = value.elements[ 0 ]; 26809 uniform.__data[ 4 ] = value.elements[ 3 ]; 26810 uniform.__data[ 5 ] = value.elements[ 4 ]; 26811 uniform.__data[ 6 ] = value.elements[ 5 ]; 26812 uniform.__data[ 7 ] = value.elements[ 0 ]; 26813 uniform.__data[ 8 ] = value.elements[ 6 ]; 26814 uniform.__data[ 9 ] = value.elements[ 7 ]; 26815 uniform.__data[ 10 ] = value.elements[ 8 ]; 26816 uniform.__data[ 11 ] = value.elements[ 0 ]; 26817 26818 } else { 26819 26820 value.toArray( uniform.__data, arrayOffset ); 26821 26822 arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT; 26823 26824 } 26825 26826 } 26827 26828 gl.bufferSubData( 35345, offset, uniform.__data ); 26829 26830 } 26831 26832 } 26833 26834 gl.bindBuffer( 35345, null ); 26835 26836 } 26837 26838 function hasUniformChanged( uniform, index, cache ) { 26839 26840 const value = uniform.value; 26841 26842 if ( cache[ index ] === undefined ) { 26843 26844 // cache entry does not exist so far 26845 26846 if ( typeof value === 'number' ) { 26847 26848 cache[ index ] = value; 26849 26850 } else { 26851 26852 const values = Array.isArray( value ) ? value : [ value ]; 26853 26854 const tempValues = []; 26855 26856 for ( let i = 0; i < values.length; i ++ ) { 26857 26858 tempValues.push( values[ i ].clone() ); 26859 26860 } 26861 26862 cache[ index ] = tempValues; 26863 26864 } 26865 26866 return true; 26867 26868 } else { 26869 26870 // compare current value with cached entry 26871 26872 if ( typeof value === 'number' ) { 26873 26874 if ( cache[ index ] !== value ) { 26875 26876 cache[ index ] = value; 26877 return true; 26878 26879 } 26880 26881 } else { 26882 26883 const cachedObjects = Array.isArray( cache[ index ] ) ? cache[ index ] : [ cache[ index ] ]; 26884 const values = Array.isArray( value ) ? value : [ value ]; 26885 26886 for ( let i = 0; i < cachedObjects.length; i ++ ) { 26887 26888 const cachedObject = cachedObjects[ i ]; 26889 26890 if ( cachedObject.equals( values[ i ] ) === false ) { 26891 26892 cachedObject.copy( values[ i ] ); 26893 return true; 26894 26895 } 26896 26897 } 26898 26899 } 26900 26901 } 26902 26903 return false; 26904 26905 } 26906 26907 function prepareUniformsGroup( uniformsGroup ) { 26908 26909 // determine total buffer size according to the STD140 layout 26910 // Hint: STD140 is the only supported layout in WebGL 2 26911 26912 const uniforms = uniformsGroup.uniforms; 26913 26914 let offset = 0; // global buffer offset in bytes 26915 const chunkSize = 16; // size of a chunk in bytes 26916 let chunkOffset = 0; // offset within a single chunk in bytes 26917 26918 for ( let i = 0, l = uniforms.length; i < l; i ++ ) { 26919 26920 const uniform = uniforms[ i ]; 26921 26922 const infos = { 26923 boundary: 0, // bytes 26924 storage: 0 // bytes 26925 }; 26926 26927 const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; 26928 26929 for ( let j = 0, jl = values.length; j < jl; j ++ ) { 26930 26931 const value = values[ j ]; 26932 26933 const info = getUniformSize( value ); 26934 26935 infos.boundary += info.boundary; 26936 infos.storage += info.storage; 26937 26938 } 26939 26940 // the following two properties will be used for partial buffer updates 26941 26942 uniform.__data = new Float32Array( infos.storage / Float32Array.BYTES_PER_ELEMENT ); 26943 uniform.__offset = offset; 26944 26945 // 26946 26947 if ( i > 0 ) { 26948 26949 chunkOffset = offset % chunkSize; 26950 26951 const remainingSizeInChunk = chunkSize - chunkOffset; 26952 26953 // check for chunk overflow 26954 26955 if ( chunkOffset !== 0 && ( remainingSizeInChunk - infos.boundary ) < 0 ) { 26956 26957 // add padding and adjust offset 26958 26959 offset += ( chunkSize - chunkOffset ); 26960 uniform.__offset = offset; 26961 26962 } 26963 26964 } 26965 26966 offset += infos.storage; 26967 26968 } 26969 26970 // ensure correct final padding 26971 26972 chunkOffset = offset % chunkSize; 26973 26974 if ( chunkOffset > 0 ) offset += ( chunkSize - chunkOffset ); 26975 26976 // 26977 26978 uniformsGroup.__size = offset; 26979 uniformsGroup.__cache = {}; 26980 26981 return this; 26982 26983 } 26984 26985 function getUniformSize( value ) { 26986 26987 const info = { 26988 boundary: 0, // bytes 26989 storage: 0 // bytes 26990 }; 26991 26992 // determine sizes according to STD140 26993 26994 if ( typeof value === 'number' ) { 26995 26996 // float/int 26997 26998 info.boundary = 4; 26999 info.storage = 4; 27000 27001 } else if ( value.isVector2 ) { 27002 27003 // vec2 27004 27005 info.boundary = 8; 27006 info.storage = 8; 27007 27008 } else if ( value.isVector3 || value.isColor ) { 27009 27010 // vec3 27011 27012 info.boundary = 16; 27013 info.storage = 12; // evil: vec3 must start on a 16-byte boundary but it only consumes 12 bytes 27014 27015 } else if ( value.isVector4 ) { 27016 27017 // vec4 27018 27019 info.boundary = 16; 27020 info.storage = 16; 27021 27022 } else if ( value.isMatrix3 ) { 27023 27024 // mat3 (in STD140 a 3x3 matrix is represented as 3x4) 27025 27026 info.boundary = 48; 27027 info.storage = 48; 27028 27029 } else if ( value.isMatrix4 ) { 27030 27031 // mat4 27032 27033 info.boundary = 64; 27034 info.storage = 64; 27035 27036 } else if ( value.isTexture ) { 27037 27038 console.warn( 'THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.' ); 27039 27040 } else { 27041 27042 console.warn( 'THREE.WebGLRenderer: Unsupported uniform value type.', value ); 27043 27044 } 27045 27046 return info; 27047 27048 } 27049 27050 function onUniformsGroupsDispose( event ) { 27051 27052 const uniformsGroup = event.target; 27053 27054 uniformsGroup.removeEventListener( 'dispose', onUniformsGroupsDispose ); 27055 27056 const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex ); 27057 allocatedBindingPoints.splice( index, 1 ); 27058 27059 gl.deleteBuffer( buffers[ uniformsGroup.id ] ); 27060 27061 delete buffers[ uniformsGroup.id ]; 27062 delete updateList[ uniformsGroup.id ]; 27063 27064 } 27065 27066 function dispose() { 27067 27068 for ( const id in buffers ) { 27069 27070 gl.deleteBuffer( buffers[ id ] ); 27071 27072 } 27073 27074 allocatedBindingPoints = []; 27075 buffers = {}; 27076 updateList = {}; 27077 27078 } 27079 27080 return { 27081 27082 bind: bind, 27083 update: update, 27084
27085 dispose: dispose 27086 27087 }; 27088 27089} 27090 27091function createCanvasElement() { 27092 27093 const canvas = createElementNS( 'canvas' ); 27094 canvas.style.display = 'block'; 27095 return canvas; 27096 27097} 27098 27099function WebGLRenderer( parameters = {} ) { 27100 27101 this.isWebGLRenderer = true; 27102 27103 const _canvas = parameters.canvas !== undefined ? parameters.canvas : createCanvasElement(), 27104 _context = parameters.context !== undefined ? parameters.context : null, 27105 27106 _depth = parameters.depth !== undefined ? parameters.depth : true, 27107 _stencil = parameters.stencil !== undefined ? parameters.stencil : true, 27108 _antialias = parameters.antialias !== undefined ? parameters.antialias : false, 27109 _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, 27110 _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false, 27111 _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default', 27112 _failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false; 27113 27114 let _alpha; 27115 27116 if ( _context !== null ) { 27117 27118 _alpha = _context.getContextAttributes().alpha; 27119 27120 } else { 27121 27122 _alpha = parameters.alpha !== undefined ? parameters.alpha : false; 27123 27124 } 27125 27126 let currentRenderList = null; 27127 let currentRenderState = null; 27128 27129 // render() can be called from within a callback triggered by another render. 27130 // We track this so that the nested render call gets its list and state isolated from the parent render call. 27131 27132 const renderListStack = []; 27133 const renderStateStack = []; 27134 27135 // public properties 27136 27137 this.domElement = _canvas; 27138 27139 // Debug configuration container 27140 this.debug = { 27141 27142 /** 27143 * Enables error checking and reporting when shader programs are being compiled 27144 * @type {boolean} 27145 */
vendor: 10,774 bytes, lines 27146-27661
27146 checkShaderErrors: true 27147 }; 27148 27149 // clearing 27150 27151 this.autoClear = true; 27152 this.autoClearColor = true; 27153 this.autoClearDepth = true; 27154 this.autoClearStencil = true; 27155 27156 // scene graph 27157 27158 this.sortObjects = true; 27159 27160 // user-defined clipping 27161 27162 this.clippingPlanes = []; 27163 this.localClippingEnabled = false; 27164 27165 // physically based shading 27166 27167 this.outputEncoding = LinearEncoding; 27168 27169 // physical lights 27170 27171 this.useLegacyLights = true; 27172 27173 // tone mapping 27174 27175 this.toneMapping = NoToneMapping; 27176 this.toneMappingExposure = 1.0; 27177 27178 // internal properties 27179 27180 const _this = this; 27181 27182 let _isContextLost = false; 27183 27184 // internal state cache 27185 27186 let _currentActiveCubeFace = 0; 27187 let _currentActiveMipmapLevel = 0; 27188 let _currentRenderTarget = null; 27189 let _currentMaterialId = - 1; 27190 27191 let _currentCamera = null; 27192 27193 const _currentViewport = new Vector4(); 27194 const _currentScissor = new Vector4(); 27195 let _currentScissorTest = null; 27196 27197 // 27198 27199 let _width = _canvas.width; 27200 let _height = _canvas.height; 27201 27202 let _pixelRatio = 1; 27203 let _opaqueSort = null; 27204 let _transparentSort = null; 27205 27206 const _viewport = new Vector4( 0, 0, _width, _height ); 27207 const _scissor = new Vector4( 0, 0, _width, _height ); 27208 let _scissorTest = false; 27209 27210 // frustum 27211 27212 const _frustum = new Frustum(); 27213 27214 // clipping 27215 27216 let _clippingEnabled = false; 27217 let _localClippingEnabled = false; 27218 27219 // transmission 27220 27221 let _transmissionRenderTarget = null; 27222 27223 // camera matrices cache 27224 27225 const _projScreenMatrix = new Matrix4(); 27226 27227 const _vector3 = new Vector3(); 27228 27229 const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; 27230 27231 function getTargetPixelRatio() { 27232 27233 return _currentRenderTarget === null ? _pixelRatio : 1; 27234 27235 } 27236 27237 // initialize 27238 27239 let _gl = _context; 27240 27241 function getContext( contextNames, contextAttributes ) { 27242 27243 for ( let i = 0; i < contextNames.length; i ++ ) { 27244 27245 const contextName = contextNames[ i ]; 27246 const context = _canvas.getContext( contextName, contextAttributes ); 27247 if ( context !== null ) return context; 27248 27249 } 27250 27251 return null; 27252 27253 } 27254 27255 try { 27256 27257 const contextAttributes = { 27258 alpha: true, 27259 depth: _depth, 27260 stencil: _stencil, 27261 antialias: _antialias, 27262 premultipliedAlpha: _premultipliedAlpha, 27263 preserveDrawingBuffer: _preserveDrawingBuffer, 27264 powerPreference: _powerPreference, 27265 failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat 27266 }; 27267 27268 // OffscreenCanvas does not have setAttribute, see #22811 27269 if ( 'setAttribute' in _canvas ) _canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); 27270 27271 // event listeners must be registered before WebGL context is created, see #12753 27272 _canvas.addEventListener( 'webglcontextlost', onContextLost, false ); 27273 _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); 27274 _canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); 27275 27276 if ( _gl === null ) { 27277 27278 const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ]; 27279 27280 if ( _this.isWebGL1Renderer === true ) { 27281 27282 contextNames.shift(); 27283 27284 } 27285 27286 _gl = getContext( contextNames, contextAttributes ); 27287 27288 if ( _gl === null ) { 27289 27290 if ( getContext( contextNames ) ) { 27291 27292 throw new Error( 'Error creating WebGL context with your selected attributes.' ); 27293 27294 } else { 27295 27296 throw new Error( 'Error creating WebGL context.' ); 27297 27298 } 27299 27300 } 27301 27302 } 27303 27304 // Some experimental-webgl implementations do not have getShaderPrecisionFormat 27305 27306 if ( _gl.getShaderPrecisionFormat === undefined ) { 27307 27308 _gl.getShaderPrecisionFormat = function () { 27309 27310 return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; 27311 27312 }; 27313 27314 } 27315 27316 } catch ( error ) { 27317 27318 console.error( 'THREE.WebGLRenderer: ' + error.message ); 27319 throw error; 27320 27321 } 27322 27323 let extensions, capabilities, state, info; 27324 let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; 27325 let programCache, materials, renderLists, renderStates, clipping, shadowMap; 27326 27327 let background, morphtargets, bufferRenderer, indexedBufferRenderer; 27328 27329 let utils, bindingStates, uniformsGroups; 27330 27331 function initGLContext() { 27332 27333 extensions = new WebGLExtensions( _gl ); 27334 27335 capabilities = new WebGLCapabilities( _gl, extensions, parameters ); 27336 27337 extensions.init( capabilities ); 27338 27339 utils = new WebGLUtils( _gl, extensions, capabilities ); 27340 27341 state = new WebGLState( _gl, extensions, capabilities ); 27342 27343 info = new WebGLInfo(); 27344 properties = new WebGLProperties(); 27345 textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); 27346 cubemaps = new WebGLCubeMaps( _this ); 27347 cubeuvmaps = new WebGLCubeUVMaps( _this ); 27348 attributes = new WebGLAttributes( _gl, capabilities ); 27349 bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities ); 27350 geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); 27351 objects = new WebGLObjects( _gl, geometries, attributes, info ); 27352 morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); 27353 clipping = new WebGLClipping( properties ); 27354 programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); 27355 materials = new WebGLMaterials( _this, properties ); 27356 renderLists = new WebGLRenderLists(); 27357 renderStates = new WebGLRenderStates( extensions, capabilities ); 27358 background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, _premultipliedAlpha ); 27359 shadowMap = new WebGLShadowMap( _this, objects, capabilities ); 27360 uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); 27361 27362 bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities ); 27363 indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities ); 27364 27365 info.programs = programCache.programs; 27366 27367 _this.capabilities = capabilities; 27368 _this.extensions = extensions; 27369 _this.properties = properties; 27370 _this.renderLists = renderLists; 27371 _this.shadowMap = shadowMap; 27372 _this.state = state; 27373 _this.info = info; 27374 27375 } 27376 27377 initGLContext(); 27378 27379 // xr 27380 27381 const xr = new WebXRManager( _this, _gl ); 27382 27383 this.xr = xr; 27384 27385 // API 27386 27387 this.getContext = function () { 27388 27389 return _gl; 27390 27391 }; 27392 27393 this.getContextAttributes = function () { 27394 27395 return _gl.getContextAttributes(); 27396 27397 }; 27398 27399 this.forceContextLoss = function () { 27400 27401 const extension = extensions.get( 'WEBGL_lose_context' ); 27402 if ( extension ) extension.loseContext(); 27403 27404 }; 27405 27406 this.forceContextRestore = function () { 27407 27408 const extension = extensions.get( 'WEBGL_lose_context' ); 27409 if ( extension ) extension.restoreContext(); 27410 27411 }; 27412 27413 this.getPixelRatio = function () { 27414 27415 return _pixelRatio; 27416 27417 }; 27418 27419 this.setPixelRatio = function ( value ) { 27420 27421 if ( value === undefined ) return; 27422 27423 _pixelRatio = value; 27424 27425 this.setSize( _width, _height, false ); 27426 27427 }; 27428 27429 this.getSize = function ( target ) { 27430 27431 return target.set( _width, _height ); 27432 27433 }; 27434 27435 this.setSize = function ( width, height, updateStyle = true ) { 27436 27437 if ( xr.isPresenting ) { 27438 27439 console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); 27440 return; 27441 27442 } 27443 27444 _width = width; 27445 _height = height; 27446 27447 _canvas.width = Math.floor( width * _pixelRatio ); 27448 _canvas.height = Math.floor( height * _pixelRatio ); 27449 27450 if ( updateStyle === true ) { 27451 27452 _canvas.style.width = width + 'px'; 27453 _canvas.style.height = height + 'px'; 27454 27455 } 27456 27457 this.setViewport( 0, 0, width, height ); 27458 27459 }; 27460 27461 this.getDrawingBufferSize = function ( target ) { 27462 27463 return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); 27464 27465 }; 27466 27467 this.setDrawingBufferSize = function ( width, height, pixelRatio ) { 27468 27469 _width = width; 27470 _height = height; 27471 27472 _pixelRatio = pixelRatio; 27473 27474 _canvas.width = Math.floor( width * pixelRatio ); 27475 _canvas.height = Math.floor( height * pixelRatio ); 27476 27477 this.setViewport( 0, 0, width, height ); 27478 27479 }; 27480 27481 this.getCurrentViewport = function ( target ) { 27482 27483 return target.copy( _currentViewport ); 27484 27485 }; 27486 27487 this.getViewport = function ( target ) { 27488 27489 return target.copy( _viewport ); 27490 27491 }; 27492 27493 this.setViewport = function ( x, y, width, height ) { 27494 27495 if ( x.isVector4 ) { 27496 27497 _viewport.set( x.x, x.y, x.z, x.w ); 27498 27499 } else { 27500 27501 _viewport.set( x, y, width, height ); 27502 27503 } 27504 27505 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() ); 27506 27507 }; 27508 27509 this.getScissor = function ( target ) { 27510 27511 return target.copy( _scissor ); 27512 27513 }; 27514 27515 this.setScissor = function ( x, y, width, height ) { 27516 27517 if ( x.isVector4 ) { 27518 27519 _scissor.set( x.x, x.y, x.z, x.w ); 27520 27521 } else { 27522 27523 _scissor.set( x, y, width, height ); 27524 27525 } 27526 27527 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() ); 27528 27529 }; 27530 27531 this.getScissorTest = function () { 27532 27533 return _scissorTest; 27534 27535 }; 27536 27537 this.setScissorTest = function ( boolean ) { 27538 27539 state.setScissorTest( _scissorTest = boolean ); 27540 27541 }; 27542 27543 this.setOpaqueSort = function ( method ) { 27544 27545 _opaqueSort = method; 27546 27547 }; 27548 27549 this.setTransparentSort = function ( method ) { 27550 27551 _transparentSort = method; 27552 27553 }; 27554 27555 // Clearing 27556 27557 this.getClearColor = function ( target ) { 27558 27559 return target.copy( background.getClearColor() ); 27560 27561 }; 27562 27563 this.setClearColor = function () { 27564 27565 background.setClearColor.apply( background, arguments ); 27566 27567 }; 27568 27569 this.getClearAlpha = function () { 27570 27571 return background.getClearAlpha(); 27572 27573 }; 27574 27575 this.setClearAlpha = function () { 27576 27577 background.setClearAlpha.apply( background, arguments ); 27578 27579 }; 27580 27581 this.clear = function ( color = true, depth = true, stencil = true ) { 27582 27583 let bits = 0; 27584 27585 if ( color ) bits |= 16384; 27586 if ( depth ) bits |= 256; 27587 if ( stencil ) bits |= 1024; 27588 27589 _gl.clear( bits ); 27590 27591 }; 27592 27593 this.clearColor = function () { 27594 27595 this.clear( true, false, false ); 27596 27597 }; 27598 27599 this.clearDepth = function () { 27600 27601 this.clear( false, true, false ); 27602 27603 }; 27604 27605 this.clearStencil = function () { 27606 27607 this.clear( false, false, true ); 27608 27609 }; 27610 27611 // 27612 27613 this.dispose = function () { 27614 27615 _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); 27616 _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); 27617 _canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); 27618 27619 renderLists.dispose(); 27620 renderStates.dispose(); 27621 properties.dispose(); 27622 cubemaps.dispose(); 27623 cubeuvmaps.dispose(); 27624 objects.dispose(); 27625 bindingStates.dispose(); 27626 uniformsGroups.dispose(); 27627 programCache.dispose(); 27628 27629 xr.dispose(); 27630 27631 xr.removeEventListener( 'sessionstart', onXRSessionStart ); 27632 xr.removeEventListener( 'sessionend', onXRSessionEnd ); 27633 27634 if ( _transmissionRenderTarget ) { 27635 27636 _transmissionRenderTarget.dispose(); 27637 _transmissionRenderTarget = null; 27638 27639 } 27640 27641 animation.stop(); 27642 27643 }; 27644 27645 // Events 27646 27647 function onContextLost( event ) { 27648 27649 event.preventDefault(); 27650 27651 console.log( 'THREE.WebGLRenderer: Context Lost.' ); 27652 27653 _isContextLost = true; 27654 27655 } 27656 27657 function onContextRestore( /* event */ ) { 27658 27659 console.log( 'THREE.WebGLRenderer: Context Restored.' ); 27660 27661 _isContextLost = false;
vendor: 4,782 bytes, lines 27662-27891
27662 27663 const infoAutoReset = info.autoReset; 27664 const shadowMapEnabled = shadowMap.enabled; 27665 const shadowMapAutoUpdate = shadowMap.autoUpdate; 27666 const shadowMapNeedsUpdate = shadowMap.needsUpdate; 27667 const shadowMapType = shadowMap.type; 27668 27669 initGLContext(); 27670 27671 info.autoReset = infoAutoReset; 27672 shadowMap.enabled = shadowMapEnabled; 27673 shadowMap.autoUpdate = shadowMapAutoUpdate; 27674 shadowMap.needsUpdate = shadowMapNeedsUpdate; 27675 shadowMap.type = shadowMapType; 27676 27677 } 27678 27679 function onContextCreationError( event ) { 27680 27681 console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); 27682 27683 } 27684 27685 function onMaterialDispose( event ) { 27686 27687 const material = event.target; 27688 27689 material.removeEventListener( 'dispose', onMaterialDispose ); 27690 27691 deallocateMaterial( material ); 27692 27693 } 27694 27695 // Buffer deallocation 27696 27697 function deallocateMaterial( material ) { 27698 27699 releaseMaterialProgramReferences( material ); 27700 27701 properties.remove( material ); 27702 27703 } 27704 27705 27706 function releaseMaterialProgramReferences( material ) { 27707 27708 const programs = properties.get( material ).programs; 27709 27710 if ( programs !== undefined ) { 27711 27712 programs.forEach( function ( program ) { 27713 27714 programCache.releaseProgram( program ); 27715 27716 } ); 27717 27718 if ( material.isShaderMaterial ) { 27719 27720 programCache.releaseShaderCache( material ); 27721 27722 } 27723 27724 } 27725 27726 } 27727 27728 // Buffer rendering 27729 27730 this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { 27731 27732 if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) 27733 27734 const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); 27735 27736 const program = setProgram( camera, scene, geometry, material, object ); 27737 27738 state.setMaterial( material, frontFaceCW ); 27739 27740 // 27741 27742 let index = geometry.index; 27743 let rangeFactor = 1; 27744 27745 if ( material.wireframe === true ) { 27746 27747 index = geometries.getWireframeAttribute( geometry ); 27748 rangeFactor = 2; 27749 27750 } 27751 27752 // 27753 27754 const drawRange = geometry.drawRange; 27755 const position = geometry.attributes.position; 27756 27757 let drawStart = drawRange.start * rangeFactor; 27758 let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; 27759 27760 if ( group !== null ) { 27761 27762 drawStart = Math.max( drawStart, group.start * rangeFactor ); 27763 drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); 27764 27765 } 27766 27767 if ( index !== null ) { 27768 27769 drawStart = Math.max( drawStart, 0 ); 27770 drawEnd = Math.min( drawEnd, index.count ); 27771 27772 } else if ( position !== undefined && position !== null ) { 27773 27774 drawStart = Math.max( drawStart, 0 ); 27775 drawEnd = Math.min( drawEnd, position.count ); 27776 27777 } 27778 27779 const drawCount = drawEnd - drawStart; 27780 27781 if ( drawCount < 0 || drawCount === Infinity ) return; 27782 27783 // 27784 27785 bindingStates.setup( object, material, program, geometry, index ); 27786 27787 let attribute; 27788 let renderer = bufferRenderer; 27789 27790 if ( index !== null ) { 27791 27792 attribute = attributes.get( index ); 27793 27794 renderer = indexedBufferRenderer; 27795 renderer.setIndex( attribute ); 27796 27797 } 27798 27799 // 27800 27801 if ( object.isMesh ) { 27802 27803 if ( material.wireframe === true ) { 27804 27805 state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); 27806 renderer.setMode( 1 ); 27807 27808 } else { 27809 27810 renderer.setMode( 4 ); 27811 27812 } 27813 27814 } else if ( object.isLine ) { 27815 27816 let lineWidth = material.linewidth; 27817 27818 if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material 27819 27820 state.setLineWidth( lineWidth * getTargetPixelRatio() ); 27821 27822 if ( object.isLineSegments ) { 27823 27824 renderer.setMode( 1 ); 27825 27826 } else if ( object.isLineLoop ) { 27827 27828 renderer.setMode( 2 ); 27829 27830 } else { 27831 27832 renderer.setMode( 3 ); 27833 27834 } 27835 27836 } else if ( object.isPoints ) { 27837 27838 renderer.setMode( 0 ); 27839 27840 } else if ( object.isSprite ) { 27841 27842 renderer.setMode( 4 ); 27843 27844 } 27845 27846 if ( object.isInstancedMesh ) { 27847 27848 renderer.renderInstances( drawStart, drawCount, object.count ); 27849 27850 } else if ( geometry.isInstancedBufferGeometry ) { 27851 27852 const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; 27853 const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); 27854 27855 renderer.renderInstances( drawStart, drawCount, instanceCount ); 27856 27857 } else { 27858 27859 renderer.render( drawStart, drawCount ); 27860 27861 } 27862 27863 }; 27864 27865 // Compile 27866 27867 this.compile = function ( scene, camera ) { 27868 27869 function prepare( material, scene, object ) { 27870 27871 if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { 27872 27873 material.side = BackSide; 27874 material.needsUpdate = true; 27875 getProgram( material, scene, object ); 27876 27877 material.side = FrontSide; 27878 material.needsUpdate = true; 27879 getProgram( material, scene, object ); 27880 27881 material.side = DoubleSide; 27882 27883 } else { 27884 27885 getProgram( material, scene, object ); 27886 27887 } 27888 27889 } 27890 27891 currentRenderState = renderStates.get( scene );
vendor: 20,613 bytes, lines 27892-28663
27892 currentRenderState.init(); 27893 27894 renderStateStack.push( currentRenderState ); 27895 27896 scene.traverseVisible( function ( object ) { 27897 27898 if ( object.isLight && object.layers.test( camera.layers ) ) { 27899 27900 currentRenderState.pushLight( object ); 27901 27902 if ( object.castShadow ) { 27903 27904 currentRenderState.pushShadow( object ); 27905 27906 } 27907 27908 } 27909 27910 } ); 27911 27912 currentRenderState.setupLights( _this.useLegacyLights ); 27913 27914 scene.traverse( function ( object ) { 27915 27916 const material = object.material; 27917 27918 if ( material ) { 27919 27920 if ( Array.isArray( material ) ) { 27921 27922 for ( let i = 0; i < material.length; i ++ ) { 27923 27924 const material2 = material[ i ]; 27925 27926 prepare( material2, scene, object ); 27927 27928 } 27929 27930 } else { 27931 27932 prepare( material, scene, object ); 27933 27934 } 27935 27936 } 27937 27938 } ); 27939 27940 renderStateStack.pop(); 27941 currentRenderState = null; 27942 27943 }; 27944 27945 // Animation Loop 27946 27947 let onAnimationFrameCallback = null; 27948 27949 function onAnimationFrame( time ) { 27950 27951 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); 27952 27953 } 27954 27955 function onXRSessionStart() { 27956 27957 animation.stop(); 27958 27959 } 27960 27961 function onXRSessionEnd() { 27962 27963 animation.start(); 27964 27965 } 27966 27967 const animation = new WebGLAnimation(); 27968 animation.setAnimationLoop( onAnimationFrame ); 27969 27970 if ( typeof self !== 'undefined' ) animation.setContext( self ); 27971 27972 this.setAnimationLoop = function ( callback ) { 27973 27974 onAnimationFrameCallback = callback; 27975 xr.setAnimationLoop( callback ); 27976 27977 ( callback === null ) ? animation.stop() : animation.start(); 27978 27979 }; 27980 27981 xr.addEventListener( 'sessionstart', onXRSessionStart ); 27982 xr.addEventListener( 'sessionend', onXRSessionEnd ); 27983 27984 // Rendering 27985 27986 this.render = function ( scene, camera ) { 27987 27988 if ( camera !== undefined && camera.isCamera !== true ) { 27989 27990 console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); 27991 return; 27992 27993 } 27994 27995 if ( _isContextLost === true ) return; 27996 27997 // update scene graph 27998 27999 if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); 28000 28001 // update camera matrices and frustum 28002 28003 if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); 28004 28005 if ( xr.enabled === true && xr.isPresenting === true ) { 28006 28007 if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); 28008 28009 camera = xr.getCamera(); // use XR camera for rendering 28010 28011 } 28012 28013 // 28014 if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); 28015 28016 currentRenderState = renderStates.get( scene, renderStateStack.length ); 28017 currentRenderState.init(); 28018 28019 renderStateStack.push( currentRenderState ); 28020 28021 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); 28022 _frustum.setFromProjectionMatrix( _projScreenMatrix ); 28023 28024 _localClippingEnabled = this.localClippingEnabled; 28025 _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); 28026 28027 currentRenderList = renderLists.get( scene, renderListStack.length ); 28028 currentRenderList.init(); 28029 28030 renderListStack.push( currentRenderList ); 28031 28032 projectObject( scene, camera, 0, _this.sortObjects ); 28033 28034 currentRenderList.finish(); 28035 28036 if ( _this.sortObjects === true ) { 28037 28038 currentRenderList.sort( _opaqueSort, _transparentSort ); 28039 28040 } 28041 28042 // 28043 28044 if ( _clippingEnabled === true ) clipping.beginShadows(); 28045 28046 const shadowsArray = currentRenderState.state.shadowsArray; 28047 28048 shadowMap.render( shadowsArray, scene, camera ); 28049 28050 if ( _clippingEnabled === true ) clipping.endShadows(); 28051 28052 // 28053 28054 if ( this.info.autoReset === true ) this.info.reset(); 28055 28056 // 28057 28058 background.render( currentRenderList, scene ); 28059 28060 // render scene 28061 28062 currentRenderState.setupLights( _this.useLegacyLights ); 28063 28064 if ( camera.isArrayCamera ) { 28065 28066 const cameras = camera.cameras; 28067 28068 for ( let i = 0, l = cameras.length; i < l; i ++ ) { 28069 28070 const camera2 = cameras[ i ]; 28071 28072 renderScene( currentRenderList, scene, camera2, camera2.viewport ); 28073 28074 } 28075 28076 } else { 28077 28078 renderScene( currentRenderList, scene, camera ); 28079 28080 } 28081 28082 // 28083 28084 if ( _currentRenderTarget !== null ) { 28085 28086 // resolve multisample renderbuffers to a single-sample texture if necessary 28087 28088 textures.updateMultisampleRenderTarget( _currentRenderTarget ); 28089 28090 // Generate mipmap if we're using any kind of mipmap filtering 28091 28092 textures.updateRenderTargetMipmap( _currentRenderTarget ); 28093 28094 } 28095 28096 // 28097 28098 if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); 28099 28100 // _gl.finish(); 28101 28102 bindingStates.resetDefaultState(); 28103 _currentMaterialId = - 1; 28104 _currentCamera = null; 28105 28106 renderStateStack.pop(); 28107 28108 if ( renderStateStack.length > 0 ) { 28109 28110 currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; 28111 28112 } else { 28113 28114 currentRenderState = null; 28115 28116 } 28117 28118 renderListStack.pop(); 28119 28120 if ( renderListStack.length > 0 ) { 28121 28122 currentRenderList = renderListStack[ renderListStack.length - 1 ]; 28123 28124 } else { 28125 28126 currentRenderList = null; 28127 28128 } 28129 28130 }; 28131 28132 function projectObject( object, camera, groupOrder, sortObjects ) { 28133 28134 if ( object.visible === false ) return; 28135 28136 const visible = object.layers.test( camera.layers ); 28137 28138 if ( visible ) { 28139 28140 if ( object.isGroup ) { 28141 28142 groupOrder = object.renderOrder; 28143 28144 } else if ( object.isLOD ) { 28145 28146 if ( object.autoUpdate === true ) object.update( camera ); 28147 28148 } else if ( object.isLight ) { 28149 28150 currentRenderState.pushLight( object ); 28151 28152 if ( object.castShadow ) { 28153 28154 currentRenderState.pushShadow( object ); 28155 28156 } 28157 28158 } else if ( object.isSprite ) { 28159 28160 if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { 28161 28162 if ( sortObjects ) { 28163 28164 _vector3.setFromMatrixPosition( object.matrixWorld ) 28165 .applyMatrix4( _projScreenMatrix ); 28166 28167 } 28168 28169 const geometry = objects.update( object ); 28170 const material = object.material; 28171 28172 if ( material.visible ) { 28173 28174 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); 28175 28176 } 28177 28178 } 28179 28180 } else if ( object.isMesh || object.isLine || object.isPoints ) { 28181 28182 if ( object.isSkinnedMesh ) { 28183 28184 // update skeleton only once in a frame 28185 28186 if ( object.skeleton.frame !== info.render.frame ) { 28187 28188 object.skeleton.update(); 28189 object.skeleton.frame = info.render.frame; 28190 28191 } 28192 28193 } 28194 28195 if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { 28196 28197 if ( sortObjects ) { 28198 28199 _vector3.setFromMatrixPosition( object.matrixWorld ) 28200 .applyMatrix4( _projScreenMatrix ); 28201 28202 } 28203 28204 const geometry = objects.update( object ); 28205 const material = object.material; 28206 28207 if ( Array.isArray( material ) ) { 28208 28209 const groups = geometry.groups; 28210 28211 for ( let i = 0, l = groups.length; i < l; i ++ ) { 28212 28213 const group = groups[ i ]; 28214 const groupMaterial = material[ group.materialIndex ]; 28215 28216 if ( groupMaterial && groupMaterial.visible ) { 28217 28218 currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); 28219 28220 } 28221 28222 } 28223 28224 } else if ( material.visible ) { 28225 28226 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); 28227 28228 } 28229 28230 } 28231 28232 } 28233 28234 } 28235 28236 const children = object.children; 28237 28238 for ( let i = 0, l = children.length; i < l; i ++ ) { 28239 28240 projectObject( children[ i ], camera, groupOrder, sortObjects ); 28241 28242 } 28243 28244 } 28245 28246 function renderScene( currentRenderList, scene, camera, viewport ) { 28247 28248 const opaqueObjects = currentRenderList.opaque; 28249 const transmissiveObjects = currentRenderList.transmissive; 28250 const transparentObjects = currentRenderList.transparent; 28251 28252 currentRenderState.setupLightsView( camera ); 28253 28254 if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); 28255 28256 if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, scene, camera ); 28257 28258 if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); 28259 28260 if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); 28261 if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); 28262 if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); 28263 28264 // Ensure depth buffer writing is enabled so it can be cleared on next render 28265 28266 state.buffers.depth.setTest( true ); 28267 state.buffers.depth.setMask( true ); 28268 state.buffers.color.setMask( true ); 28269 28270 state.setPolygonOffset( false ); 28271 28272 } 28273 28274 function renderTransmissionPass( opaqueObjects, scene, camera ) { 28275 28276 const isWebGL2 = capabilities.isWebGL2; 28277 28278 if ( _transmissionRenderTarget === null ) { 28279 28280 _transmissionRenderTarget = new WebGLRenderTarget( 1024, 1024, { 28281 generateMipmaps: true, 28282 type: extensions.has( 'EXT_color_buffer_half_float' ) ? HalfFloatType : UnsignedByteType, 28283 minFilter: LinearMipmapLinearFilter, 28284 samples: ( isWebGL2 && _antialias === true ) ? 4 : 0 28285 } ); 28286 28287 } 28288 28289 // 28290 28291 const currentRenderTarget = _this.getRenderTarget(); 28292 _this.setRenderTarget( _transmissionRenderTarget ); 28293 _this.clear(); 28294 28295 // Turn off the features which can affect the frag color for opaque objects pass. 28296 // Otherwise they are applied twice in opaque objects pass and transmission objects pass. 28297 const currentToneMapping = _this.toneMapping; 28298 _this.toneMapping = NoToneMapping; 28299 28300 renderObjects( opaqueObjects, scene, camera ); 28301 28302 _this.toneMapping = currentToneMapping; 28303 28304 textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); 28305 textures.updateRenderTargetMipmap( _transmissionRenderTarget ); 28306 28307 _this.setRenderTarget( currentRenderTarget ); 28308 28309 } 28310 28311 function renderObjects( renderList, scene, camera ) { 28312 28313 const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; 28314 28315 for ( let i = 0, l = renderList.length; i < l; i ++ ) { 28316 28317 const renderItem = renderList[ i ]; 28318 28319 const object = renderItem.object; 28320 const geometry = renderItem.geometry; 28321 const material = overrideMaterial === null ? renderItem.material : overrideMaterial; 28322 const group = renderItem.group; 28323 28324 if ( object.layers.test( camera.layers ) ) { 28325 28326 renderObject( object, scene, camera, geometry, material, group ); 28327 28328 } 28329 28330 } 28331 28332 } 28333 28334 function renderObject( object, scene, camera, geometry, material, group ) { 28335 28336 object.onBeforeRender( _this, scene, camera, geometry, material, group ); 28337 28338 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); 28339 object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); 28340 28341 material.onBeforeRender( _this, scene, camera, geometry, object, group ); 28342 28343 if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { 28344 28345 material.side = BackSide; 28346 material.needsUpdate = true; 28347 _this.renderBufferDirect( camera, scene, geometry, material, object, group ); 28348 28349 material.side = FrontSide; 28350 material.needsUpdate = true; 28351 _this.renderBufferDirect( camera, scene, geometry, material, object, group ); 28352 28353 material.side = DoubleSide; 28354 28355 } else { 28356 28357 _this.renderBufferDirect( camera, scene, geometry, material, object, group ); 28358 28359 } 28360 28361 object.onAfterRender( _this, scene, camera, geometry, material, group ); 28362 28363 } 28364 28365 function getProgram( material, scene, object ) { 28366 28367 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... 28368 28369 const materialProperties = properties.get( material ); 28370 28371 const lights = currentRenderState.state.lights; 28372 const shadowsArray = currentRenderState.state.shadowsArray; 28373 28374 const lightsStateVersion = lights.state.version; 28375 28376 const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); 28377 const programCacheKey = programCache.getProgramCacheKey( parameters ); 28378 28379 let programs = materialProperties.programs; 28380 28381 // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change 28382 28383 materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; 28384 materialProperties.fog = scene.fog; 28385 materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); 28386 28387 if ( programs === undefined ) { 28388 28389 // new material 28390 28391 material.addEventListener( 'dispose', onMaterialDispose ); 28392 28393 programs = new Map(); 28394 materialProperties.programs = programs; 28395 28396 } 28397 28398 let program = programs.get( programCacheKey ); 28399 28400 if ( program !== undefined ) { 28401 28402 // early out if program and light state is identical 28403 28404 if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { 28405 28406 updateCommonMaterialProperties( material, parameters ); 28407 28408 return program; 28409 28410 } 28411 28412 } else { 28413 28414 parameters.uniforms = programCache.getUniforms( material ); 28415 28416 material.onBuild( object, parameters, _this ); 28417 28418 material.onBeforeCompile( parameters, _this ); 28419 28420 program = programCache.acquireProgram( parameters, programCacheKey ); 28421 programs.set( programCacheKey, program ); 28422 28423 materialProperties.uniforms = parameters.uniforms; 28424 28425 } 28426 28427 const uniforms = materialProperties.uniforms; 28428 28429 if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { 28430 28431 uniforms.clippingPlanes = clipping.uniform; 28432 28433 } 28434 28435 updateCommonMaterialProperties( material, parameters ); 28436 28437 // store the light setup it was created for 28438 28439 materialProperties.needsLights = materialNeedsLights( material ); 28440 materialProperties.lightsStateVersion = lightsStateVersion; 28441 28442 if ( materialProperties.needsLights ) { 28443 28444 // wire up the material to this renderer's lighting state 28445 28446 uniforms.ambientLightColor.value = lights.state.ambient; 28447 uniforms.lightProbe.value = lights.state.probe; 28448 uniforms.directionalLights.value = lights.state.directional; 28449 uniforms.directionalLightShadows.value = lights.state.directionalShadow; 28450 uniforms.spotLights.value = lights.state.spot; 28451 uniforms.spotLightShadows.value = lights.state.spotShadow; 28452 uniforms.rectAreaLights.value = lights.state.rectArea; 28453 uniforms.ltc_1.value = lights.state.rectAreaLTC1; 28454 uniforms.ltc_2.value = lights.state.rectAreaLTC2; 28455 uniforms.pointLights.value = lights.state.point; 28456 uniforms.pointLightShadows.value = lights.state.pointShadow; 28457 uniforms.hemisphereLights.value = lights.state.hemi; 28458 28459 uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; 28460 uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; 28461 uniforms.spotShadowMap.value = lights.state.spotShadowMap; 28462 uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; 28463 uniforms.spotLightMap.value = lights.state.spotLightMap; 28464 uniforms.pointShadowMap.value = lights.state.pointShadowMap; 28465 uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; 28466 // TODO (abelnation): add area lights shadow info to uniforms 28467 28468 } 28469 28470 const progUniforms = program.getUniforms(); 28471 const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); 28472 28473 materialProperties.currentProgram = program; 28474 materialProperties.uniformsList = uniformsList; 28475 28476 return program; 28477 28478 } 28479 28480 function updateCommonMaterialProperties( material, parameters ) { 28481 28482 const materialProperties = properties.get( material ); 28483 28484 materialProperties.outputEncoding = parameters.outputEncoding; 28485 materialProperties.instancing = parameters.instancing; 28486 materialProperties.skinning = parameters.skinning; 28487 materialProperties.morphTargets = parameters.morphTargets; 28488 materialProperties.morphNormals = parameters.morphNormals; 28489 materialProperties.morphColors = parameters.morphColors; 28490 materialProperties.morphTargetsCount = parameters.morphTargetsCount; 28491 materialProperties.numClippingPlanes = parameters.numClippingPlanes; 28492 materialProperties.numIntersection = parameters.numClipIntersection; 28493 materialProperties.vertexAlphas = parameters.vertexAlphas; 28494 materialProperties.vertexTangents = parameters.vertexTangents; 28495 materialProperties.toneMapping = parameters.toneMapping; 28496 28497 } 28498 28499 function setProgram( camera, scene, geometry, material, object ) { 28500 28501 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... 28502 28503 textures.resetTextureUnits(); 28504 28505 const fog = scene.fog; 28506 const environment = material.isMeshStandardMaterial ? scene.environment : null; 28507 const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.encoding : LinearEncoding ); 28508 const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); 28509 const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; 28510 const vertexTangents = !! material.normalMap && !! geometry.attributes.tangent; 28511 const morphTargets = !! geometry.morphAttributes.position; 28512 const morphNormals = !! geometry.morphAttributes.normal; 28513 const morphColors = !! geometry.morphAttributes.color; 28514 const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping; 28515 28516 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; 28517 const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; 28518 28519 const materialProperties = properties.get( material ); 28520 const lights = currentRenderState.state.lights; 28521 28522 if ( _clippingEnabled === true ) { 28523 28524 if ( _localClippingEnabled === true || camera !== _currentCamera ) { 28525 28526 const useCache = 28527 camera === _currentCamera && 28528 material.id === _currentMaterialId; 28529 28530 // we might want to call this function with some ClippingGroup 28531 // object instead of the material, once it becomes feasible 28532 // (#8465, #8379) 28533 clipping.setState( material, camera, useCache ); 28534 28535 } 28536 28537 } 28538 28539 // 28540 28541 let needsProgramChange = false; 28542 28543 if ( material.version === materialProperties.__version ) { 28544 28545 if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { 28546 28547 needsProgramChange = true; 28548 28549 } else if ( materialProperties.outputEncoding !== encoding ) { 28550 28551 needsProgramChange = true; 28552 28553 } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { 28554 28555 needsProgramChange = true; 28556 28557 } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { 28558 28559 needsProgramChange = true; 28560 28561 } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { 28562 28563 needsProgramChange = true; 28564 28565 } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { 28566 28567 needsProgramChange = true; 28568 28569 } else if ( materialProperties.envMap !== envMap ) { 28570 28571 needsProgramChange = true; 28572 28573 } else if ( material.fog === true && materialProperties.fog !== fog ) { 28574 28575 needsProgramChange = true; 28576 28577 } else if ( materialProperties.numClippingPlanes !== undefined && 28578 ( materialProperties.numClippingPlanes !== clipping.numPlanes || 28579 materialProperties.numIntersection !== clipping.numIntersection ) ) { 28580 28581 needsProgramChange = true; 28582 28583 } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { 28584 28585 needsProgramChange = true; 28586 28587 } else if ( materialProperties.vertexTangents !== vertexTangents ) { 28588 28589 needsProgramChange = true; 28590 28591 } else if ( materialProperties.morphTargets !== morphTargets ) { 28592 28593 needsProgramChange = true; 28594 28595 } else if ( materialProperties.morphNormals !== morphNormals ) { 28596 28597 needsProgramChange = true; 28598 28599 } else if ( materialProperties.morphColors !== morphColors ) { 28600 28601 needsProgramChange = true; 28602 28603 } else if ( materialProperties.toneMapping !== toneMapping ) { 28604 28605 needsProgramChange = true; 28606 28607 } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) { 28608 28609 needsProgramChange = true; 28610 28611 } 28612 28613 } else { 28614 28615 needsProgramChange = true; 28616 materialProperties.__version = material.version; 28617 28618 } 28619 28620 // 28621 28622 let program = materialProperties.currentProgram; 28623 28624 if ( needsProgramChange === true ) { 28625 28626 program = getProgram( material, scene, object ); 28627 28628 } 28629 28630 let refreshProgram = false; 28631 let refreshMaterial = false; 28632 let refreshLights = false; 28633 28634 const p_uniforms = program.getUniforms(), 28635 m_uniforms = materialProperties.uniforms; 28636 28637 if ( state.useProgram( program.program ) ) { 28638 28639 refreshProgram = true; 28640 refreshMaterial = true; 28641 refreshLights = true; 28642 28643 } 28644 28645 if ( material.id !== _currentMaterialId ) { 28646 28647 _currentMaterialId = material.id; 28648 28649 refreshMaterial = true; 28650 28651 } 28652 28653 if ( refreshProgram || _currentCamera !== camera ) { 28654 28655 p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); 28656 28657 if ( capabilities.logarithmicDepthBuffer ) { 28658 28659 p_uniforms.setValue( _gl, 'logDepthBufFC', 28660 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); 28661 28662 } 28663
28664 if ( _currentCamera !== camera ) { 28665 28666 _currentCamera = camera; 28667 28668 // lighting uniforms depend on the camera so enforce an update 28669 // now, in case this material supports lights - or later, when 28670 // the next material that does gets activated: 28671 28672 refreshMaterial = true; // set to true on material change 28673 refreshLights = true; // remains set until update done 28674 28675 } 28676 28677 // load material specific uniforms 28678 // (shader material also gets them for the sake of genericity) 28679 28680 if ( material.isShaderMaterial || 28681 material.isMeshPhongMaterial || 28682 material.isMeshToonMaterial || 28683 material.isMeshStandardMaterial || 28684 material.envMap ) { 28685 28686 const uCamPos = p_uniforms.map.cameraPosition; 28687 28688 if ( uCamPos !== undefined ) { 28689 28690 uCamPos.setValue( _gl, 28691 _vector3.setFromMatrixPosition( camera.matrixWorld ) ); 28692 28693 } 28694 28695 } 28696 28697 if ( material.isMeshPhongMaterial || 28698 material.isMeshToonMaterial || 28699 material.isMeshLambertMaterial || 28700 material.isMeshBasicMaterial || 28701 material.isMeshStandardMaterial || 28702 material.isShaderMaterial ) { 28703 28704 p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); 28705 28706 } 28707 28708 if ( material.isMeshPhongMaterial || 28709 material.isMeshToonMaterial || 28710 material.isMeshLambertMaterial || 28711 material.isMeshBasicMaterial || 28712 material.isMeshStandardMaterial || 28713 material.isShaderMaterial || 28714 material.isShadowMaterial || 28715 object.isSkinnedMesh ) { 28716 28717 p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); 28718 28719 } 28720 28721 } 28722 28723 // skinning and morph target uniforms must be set even if material didn't change 28724 // auto-setting of texture unit for bone and morph texture must go before other textures 28725 // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures 28726 28727 if ( object.isSkinnedMesh ) { 28728 28729 p_uniforms.setOptional( _gl, object, 'bindMatrix' ); 28730 p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); 28731 28732 const skeleton = object.skeleton; 28733 28734 if ( skeleton ) { 28735 28736 if ( capabilities.floatVertexTextures ) { 28737 28738 if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); 28739 28740 p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); 28741 p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); 28742 28743 } else { 28744 28745 console.warn( 'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' ); 28746 28747 } 28748 28749 } 28750 28751 } 28752 28753 const morphAttributes = geometry.morphAttributes; 28754 28755 if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined && capabilities.isWebGL2 === true ) ) { 28756 28757 morphtargets.update( object, geometry, program ); 28758 28759 } 28760 28761 if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { 28762 28763 materialProperties.receiveShadow = object.receiveShadow; 28764 p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); 28765 28766 } 28767 28768 // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 28769 28770 if ( material.isMeshGouraudMaterial && material.envMap !== null ) { 28771 28772 m_uniforms.envMap.value = envMap; 28773 28774 m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; 28775 28776 } 28777 28778 if ( refreshMaterial ) { 28779 28780 p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); 28781 28782 if ( materialProperties.needsLights ) { 28783 28784 // the current material requires lighting info 28785 28786 // note: all lighting uniforms are always set correctly 28787 // they simply reference the renderer's state for their 28788 // values 28789 // 28790 // use the current material's .needsUpdate flags to set 28791 // the GL state when required 28792 28793 markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); 28794 28795 } 28796 28797 // refresh uniforms common to several materials 28798 28799 if ( fog && material.fog === true ) { 28800 28801 materials.refreshFogUniforms( m_uniforms, fog ); 28802 28803 } 28804 28805 materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget ); 28806 28807 WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); 28808 28809 } 28810 28811 if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { 28812 28813 WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures ); 28814 material.uniformsNeedUpdate = false;
vendor: 4,663 bytes, lines 28815-28981
28815 28816 } 28817 28818 if ( material.isSpriteMaterial ) { 28819 28820 p_uniforms.setValue( _gl, 'center', object.center ); 28821 28822 } 28823 28824 // common matrices 28825 28826 p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); 28827 p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); 28828 p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); 28829 28830 // UBOs 28831 28832 if ( material.isShaderMaterial || material.isRawShaderMaterial ) { 28833 28834 const groups = material.uniformsGroups; 28835 28836 for ( let i = 0, l = groups.length; i < l; i ++ ) { 28837 28838 if ( capabilities.isWebGL2 ) { 28839 28840 const group = groups[ i ]; 28841 28842 uniformsGroups.update( group, program ); 28843 uniformsGroups.bind( group, program ); 28844 28845 } else { 28846 28847 console.warn( 'THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.' ); 28848 28849 } 28850 28851 } 28852 28853 } 28854 28855 return program; 28856 28857 } 28858 28859 // If uniforms are marked as clean, they don't need to be loaded to the GPU. 28860 28861 function markUniformsLightsNeedsUpdate( uniforms, value ) { 28862 28863 uniforms.ambientLightColor.needsUpdate = value; 28864 uniforms.lightProbe.needsUpdate = value; 28865 28866 uniforms.directionalLights.needsUpdate = value; 28867 uniforms.directionalLightShadows.needsUpdate = value; 28868 uniforms.pointLights.needsUpdate = value; 28869 uniforms.pointLightShadows.needsUpdate = value; 28870 uniforms.spotLights.needsUpdate = value; 28871 uniforms.spotLightShadows.needsUpdate = value; 28872 uniforms.rectAreaLights.needsUpdate = value; 28873 uniforms.hemisphereLights.needsUpdate = value; 28874 28875 } 28876 28877 function materialNeedsLights( material ) { 28878 28879 return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || 28880 material.isMeshStandardMaterial || material.isShadowMaterial || 28881 ( material.isShaderMaterial && material.lights === true ); 28882 28883 } 28884 28885 this.getActiveCubeFace = function () { 28886 28887 return _currentActiveCubeFace; 28888 28889 }; 28890 28891 this.getActiveMipmapLevel = function () { 28892 28893 return _currentActiveMipmapLevel; 28894 28895 }; 28896 28897 this.getRenderTarget = function () { 28898 28899 return _currentRenderTarget; 28900 28901 }; 28902 28903 this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { 28904 28905 properties.get( renderTarget.texture ).__webglTexture = colorTexture; 28906 properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; 28907 28908 const renderTargetProperties = properties.get( renderTarget ); 28909 renderTargetProperties.__hasExternalTextures = true; 28910 28911 if ( renderTargetProperties.__hasExternalTextures ) { 28912 28913 renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; 28914 28915 if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { 28916 28917 // The multisample_render_to_texture extension doesn't work properly if there 28918 // are midframe flushes and an external depth buffer. Disable use of the extension. 28919 if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { 28920 28921 console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); 28922 renderTargetProperties.__useRenderToTexture = false; 28923 28924 } 28925 28926 } 28927 28928 } 28929 28930 }; 28931 28932 this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { 28933 28934 const renderTargetProperties = properties.get( renderTarget ); 28935 renderTargetProperties.__webglFramebuffer = defaultFramebuffer; 28936 renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; 28937 28938 }; 28939 28940 this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { 28941 28942 _currentRenderTarget = renderTarget; 28943 _currentActiveCubeFace = activeCubeFace; 28944 _currentActiveMipmapLevel = activeMipmapLevel; 28945 28946 let useDefaultFramebuffer = true; 28947 let framebuffer = null; 28948 let isCube = false; 28949 let isRenderTarget3D = false; 28950 28951 if ( renderTarget ) { 28952 28953 const renderTargetProperties = properties.get( renderTarget ); 28954 28955 if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { 28956 28957 // We need to make sure to rebind the framebuffer. 28958 state.bindFramebuffer( 36160, null ); 28959 useDefaultFramebuffer = false; 28960 28961 } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { 28962 28963 textures.setupRenderTarget( renderTarget ); 28964 28965 } else if ( renderTargetProperties.__hasExternalTextures ) { 28966 28967 // Color and depth texture must be rebound in order for the swapchain to update. 28968 textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); 28969 28970 } 28971 28972 const texture = renderTarget.texture; 28973 28974 if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { 28975 28976 isRenderTarget3D = true; 28977 28978 } 28979 28980 const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; 28981
28982 if ( renderTarget.isWebGLCubeRenderTarget ) { 28983 28984 framebuffer = __webglFramebuffer[ activeCubeFace ]; 28985 isCube = true; 28986 28987 } else if ( ( capabilities.isWebGL2 && renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { 28988 28989 framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; 28990 28991 } else { 28992 28993 framebuffer = __webglFramebuffer; 28994 28995 } 28996 28997 _currentViewport.copy( renderTarget.viewport ); 28998 _currentScissor.copy( renderTarget.scissor ); 28999 _currentScissorTest = renderTarget.scissorTest; 29000 29001 } else { 29002 29003 _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); 29004 _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); 29005 _currentScissorTest = _scissorTest; 29006 29007 } 29008 29009 const framebufferBound = state.bindFramebuffer( 36160, framebuffer ); 29010 29011 if ( framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer ) { 29012 29013 state.drawBuffers( renderTarget, framebuffer ); 29014 29015 } 29016 29017 state.viewport( _currentViewport ); 29018 state.scissor( _currentScissor ); 29019 state.setScissorTest( _currentScissorTest ); 29020 29021 if ( isCube ) { 29022 29023 const textureProperties = properties.get( renderTarget.texture ); 29024 _gl.framebufferTexture2D( 36160, 36064, 34069 + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel ); 29025 29026 } else if ( isRenderTarget3D ) { 29027 29028 const textureProperties = properties.get( renderTarget.texture ); 29029 const layer = activeCubeFace || 0; 29030 _gl.framebufferTextureLayer( 36160, 36064, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); 29031 29032 } 29033 29034 _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings 29035 29036 }; 29037 29038 this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { 29039 29040 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { 29041 29042 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); 29043 return; 29044 29045 } 29046 29047 let framebuffer = properties.get( renderTarget ).__webglFramebuffer; 29048 29049 if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { 29050 29051 framebuffer = framebuffer[ activeCubeFaceIndex ]; 29052 29053 } 29054 29055 if ( framebuffer ) { 29056 29057 state.bindFramebuffer( 36160, framebuffer ); 29058 29059 try { 29060 29061 const texture = renderTarget.texture; 29062 const textureFormat = texture.format; 29063 const textureType = texture.type; 29064 29065 if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( 35739 ) ) { 29066 29067 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); 29068 return; 29069 29070 } 29071 29072 const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) ); 29073 29074 if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // Edge and Chrome Mac < 52 (#9513) 29075 ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox 29076 ! halfFloatSupportedByExt ) { 29077 29078 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); 29079 return; 29080 29081 } 29082 29083 // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) 29084 29085 if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { 29086 29087 _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); 29088 29089 } 29090 29091 } finally { 29092 29093 // restore framebuffer of current render target if necessary 29094 29095 const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; 29096 state.bindFramebuffer( 36160, framebuffer ); 29097 29098 } 29099 29100 } 29101 29102 }; 29103 29104 this.copyFramebufferToTexture = function ( position, texture, level = 0 ) { 29105 29106 const levelScale = Math.pow( 2, - level ); 29107 const width = Math.floor( texture.image.width * levelScale ); 29108 const height = Math.floor( texture.image.height * levelScale ); 29109 29110 textures.setTexture2D( texture, 0 ); 29111 29112 _gl.copyTexSubImage2D( 3553, level, 0, 0, position.x, position.y, width, height ); 29113 29114 state.unbindTexture(); 29115 29116 }; 29117 29118 this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) { 29119 29120 const width = srcTexture.image.width;
29121 const height = srcTexture.image.height; 29122 const glFormat = utils.convert( dstTexture.format ); 29123 const glType = utils.convert( dstTexture.type ); 29124 29125 textures.setTexture2D( dstTexture, 0 ); 29126 29127 // As another texture upload may have changed pixelStorei 29128 // parameters, make sure they are correct for the dstTexture 29129 _gl.pixelStorei( 37440, dstTexture.flipY ); 29130 _gl.pixelStorei( 37441, dstTexture.premultiplyAlpha ); 29131 _gl.pixelStorei( 3317, dstTexture.unpackAlignment ); 29132 29133 if ( srcTexture.isDataTexture ) { 29134 29135 _gl.texSubImage2D( 3553, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data ); 29136 29137 } else { 29138 29139 if ( srcTexture.isCompressedTexture ) { 29140 29141 _gl.compressedTexSubImage2D( 3553, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data ); 29142 29143 } else { 29144 29145 _gl.texSubImage2D( 3553, level, position.x, position.y, glFormat, glType, srcTexture.image ); 29146 29147 } 29148 29149 } 29150 29151 // Generate mipmaps only when copying level 0 29152 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( 3553 ); 29153 29154 state.unbindTexture(); 29155 29156 }; 29157 29158 this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) { 29159 29160 if ( _this.isWebGL1Renderer ) { 29161 29162 console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' ); 29163 return; 29164 29165 } 29166 29167 const width = sourceBox.max.x - sourceBox.min.x + 1; 29168 const height = sourceBox.max.y - sourceBox.min.y + 1; 29169 const depth = sourceBox.max.z - sourceBox.min.z + 1; 29170 const glFormat = utils.convert( dstTexture.format ); 29171 const glType = utils.convert( dstTexture.type ); 29172 let glTarget; 29173 29174 if ( dstTexture.isData3DTexture ) { 29175 29176 textures.setTexture3D( dstTexture, 0 ); 29177 glTarget = 32879; 29178 29179 } else if ( dstTexture.isDataArrayTexture ) { 29180 29181 textures.setTexture2DArray( dstTexture, 0 ); 29182 glTarget = 35866; 29183 29184 } else { 29185 29186 console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); 29187 return; 29188 29189 } 29190 29191 _gl.pixelStorei( 37440, dstTexture.flipY ); 29192 _gl.pixelStorei( 37441, dstTexture.premultiplyAlpha ); 29193 _gl.pixelStorei( 3317, dstTexture.unpackAlignment ); 29194 29195 const unpackRowLen = _gl.getParameter( 3314 ); 29196 const unpackImageHeight = _gl.getParameter( 32878 ); 29197 const unpackSkipPixels = _gl.getParameter( 3316 ); 29198 const unpackSkipRows = _gl.getParameter( 3315 ); 29199 const unpackSkipImages = _gl.getParameter( 32877 ); 29200 29201 const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ 0 ] : srcTexture.image; 29202 29203 _gl.pixelStorei( 3314, image.width ); 29204 _gl.pixelStorei( 32878, image.height ); 29205 _gl.pixelStorei( 3316, sourceBox.min.x ); 29206 _gl.pixelStorei( 3315, sourceBox.min.y ); 29207 _gl.pixelStorei( 32877, sourceBox.min.z ); 29208 29209 if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { 29210 29211 _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data ); 29212 29213 } else { 29214 29215 if ( srcTexture.isCompressedArrayTexture ) { 29216 29217 console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' ); 29218 _gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data ); 29219 29220 } else { 29221 29222 _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image ); 29223 29224 } 29225 29226 } 29227 29228 _gl.pixelStorei( 3314, unpackRowLen ); 29229 _gl.pixelStorei( 32878, unpackImageHeight ); 29230 _gl.pixelStorei( 3316, unpackSkipPixels ); 29231 _gl.pixelStorei( 3315, unpackSkipRows ); 29232 _gl.pixelStorei( 32877, unpackSkipImages ); 29233 29234 // Generate mipmaps only when copying level 0 29235 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); 29236 29237 state.unbindTexture(); 29238 29239 }; 29240 29241 this.initTexture = function ( texture ) { 29242 29243 if ( texture.isCubeTexture ) { 29244 29245 textures.setTextureCube( texture, 0 ); 29246 29247 } else if ( texture.isData3DTexture ) { 29248 29249 textures.setTexture3D( texture, 0 ); 29250 29251 } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { 29252 29253 textures.setTexture2DArray( texture, 0 ); 29254 29255 } else { 29256 29257 textures.setTexture2D( texture, 0 ); 29258 29259 } 29260 29261 state.unbindTexture(); 29262 29263 }; 29264 29265 this.resetState = function () { 29266 29267 _currentActiveCubeFace = 0; 29268 _currentActiveMipmapLevel = 0; 29269 _currentRenderTarget = null; 29270 29271 state.reset(); 29272 bindingStates.reset(); 29273 29274 }; 29275 29276 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { 29277 29278 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); 29279 29280 } 29281 29282} 29283 29284Object.defineProperties( WebGLRenderer.prototype, { 29285 29286 // @deprecated since r150 29287 29288 physicallyCorrectLights: { 29289 29290 get: function () { 29291 29292 console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' ); 29293 return ! this.useLegacyLights; 29294 29295 }, 29296 29297 set: function ( value ) { 29298 29299 console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' ); 29300 this.useLegacyLights = ! value; 29301 29302 } 29303 29304 } 29305 29306} ); 29307 29308class WebGL1Renderer extends WebGLRenderer {} 29309 29310WebGL1Renderer.prototype.isWebGL1Renderer = true; 29311 29312class FogExp2 {
vendor: 10,928 bytes, lines 29313-29960
29313 29314 constructor( color, density = 0.00025 ) { 29315 29316 this.isFogExp2 = true; 29317 29318 this.name = ''; 29319 29320 this.color = new Color( color ); 29321 this.density = density; 29322 29323 } 29324 29325 clone() { 29326 29327 return new FogExp2( this.color, this.density ); 29328 29329 } 29330 29331 toJSON( /* meta */ ) { 29332 29333 return { 29334 type: 'FogExp2', 29335 color: this.color.getHex(), 29336 density: this.density 29337 }; 29338 29339 } 29340 29341} 29342 29343class Fog { 29344 29345 constructor( color, near = 1, far = 1000 ) { 29346 29347 this.isFog = true; 29348 29349 this.name = ''; 29350 29351 this.color = new Color( color ); 29352 29353 this.near = near; 29354 this.far = far; 29355 29356 } 29357 29358 clone() { 29359 29360 return new Fog( this.color, this.near, this.far ); 29361 29362 } 29363 29364 toJSON( /* meta */ ) { 29365 29366 return { 29367 type: 'Fog', 29368 color: this.color.getHex(), 29369 near: this.near, 29370 far: this.far 29371 }; 29372 29373 } 29374 29375} 29376 29377class Scene extends Object3D { 29378 29379 constructor() { 29380 29381 super(); 29382 29383 this.isScene = true; 29384 29385 this.type = 'Scene'; 29386 29387 this.background = null; 29388 this.environment = null; 29389 this.fog = null; 29390 29391 this.backgroundBlurriness = 0; 29392 this.backgroundIntensity = 1; 29393 29394 this.overrideMaterial = null; 29395 29396 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { 29397 29398 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); 29399 29400 } 29401 29402 } 29403 29404 copy( source, recursive ) { 29405 29406 super.copy( source, recursive ); 29407 29408 if ( source.background !== null ) this.background = source.background.clone(); 29409 if ( source.environment !== null ) this.environment = source.environment.clone(); 29410 if ( source.fog !== null ) this.fog = source.fog.clone(); 29411 29412 this.backgroundBlurriness = source.backgroundBlurriness; 29413 this.backgroundIntensity = source.backgroundIntensity; 29414 29415 if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone(); 29416 29417 this.matrixAutoUpdate = source.matrixAutoUpdate; 29418 29419 return this; 29420 29421 } 29422 29423 toJSON( meta ) { 29424 29425 const data = super.toJSON( meta ); 29426 29427 if ( this.fog !== null ) data.object.fog = this.fog.toJSON(); 29428 if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness; 29429 if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity; 29430 29431 return data; 29432 29433 } 29434 29435 // @deprecated 29436 29437 get autoUpdate() { 29438 29439 console.warn( 'THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144.' ); 29440 return this.matrixWorldAutoUpdate; 29441 29442 } 29443 29444 set autoUpdate( value ) { 29445 29446 console.warn( 'THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144.' ); 29447 this.matrixWorldAutoUpdate = value; 29448 29449 } 29450 29451} 29452 29453class InterleavedBuffer { 29454 29455 constructor( array, stride ) { 29456 29457 this.isInterleavedBuffer = true; 29458 29459 this.array = array; 29460 this.stride = stride; 29461 this.count = array !== undefined ? array.length / stride : 0; 29462 29463 this.usage = StaticDrawUsage; 29464 this.updateRange = { offset: 0, count: - 1 }; 29465 29466 this.version = 0; 29467 29468 this.uuid = generateUUID(); 29469 29470 } 29471 29472 onUploadCallback() {} 29473 29474 set needsUpdate( value ) { 29475 29476 if ( value === true ) this.version ++; 29477 29478 } 29479 29480 setUsage( value ) { 29481 29482 this.usage = value; 29483 29484 return this; 29485 29486 } 29487 29488 copy( source ) { 29489 29490 this.array = new source.array.constructor( source.array ); 29491 this.count = source.count; 29492 this.stride = source.stride; 29493 this.usage = source.usage; 29494 29495 return this; 29496 29497 } 29498 29499 copyAt( index1, attribute, index2 ) { 29500 29501 index1 *= this.stride; 29502 index2 *= attribute.stride; 29503 29504 for ( let i = 0, l = this.stride; i < l; i ++ ) { 29505 29506 this.array[ index1 + i ] = attribute.array[ index2 + i ]; 29507 29508 } 29509 29510 return this; 29511 29512 } 29513 29514 set( value, offset = 0 ) { 29515 29516 this.array.set( value, offset ); 29517 29518 return this; 29519 29520 } 29521 29522 clone( data ) { 29523 29524 if ( data.arrayBuffers === undefined ) { 29525 29526 data.arrayBuffers = {}; 29527 29528 } 29529 29530 if ( this.array.buffer._uuid === undefined ) { 29531 29532 this.array.buffer._uuid = generateUUID(); 29533 29534 } 29535 29536 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { 29537 29538 data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer; 29539 29540 } 29541 29542 const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] ); 29543 29544 const ib = new this.constructor( array, this.stride ); 29545 ib.setUsage( this.usage ); 29546 29547 return ib; 29548 29549 } 29550 29551 onUpload( callback ) { 29552 29553 this.onUploadCallback = callback; 29554 29555 return this; 29556 29557 } 29558 29559 toJSON( data ) { 29560 29561 if ( data.arrayBuffers === undefined ) { 29562 29563 data.arrayBuffers = {}; 29564 29565 } 29566 29567 // generate UUID for array buffer if necessary 29568 29569 if ( this.array.buffer._uuid === undefined ) { 29570 29571 this.array.buffer._uuid = generateUUID(); 29572 29573 } 29574 29575 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { 29576 29577 data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) ); 29578 29579 } 29580 29581 // 29582 29583 return { 29584 uuid: this.uuid, 29585 buffer: this.array.buffer._uuid, 29586 type: this.array.constructor.name, 29587 stride: this.stride 29588 }; 29589 29590 } 29591 29592} 29593 29594const _vector$6 = /*@__PURE__*/ new Vector3(); 29595 29596class InterleavedBufferAttribute { 29597 29598 constructor( interleavedBuffer, itemSize, offset, normalized = false ) { 29599 29600 this.isInterleavedBufferAttribute = true; 29601 29602 this.name = ''; 29603 29604 this.data = interleavedBuffer; 29605 this.itemSize = itemSize; 29606 this.offset = offset; 29607 29608 this.normalized = normalized; 29609 29610 } 29611 29612 get count() { 29613 29614 return this.data.count; 29615 29616 } 29617 29618 get array() { 29619 29620 return this.data.array; 29621 29622 } 29623 29624 set needsUpdate( value ) { 29625 29626 this.data.needsUpdate = value; 29627 29628 } 29629 29630 applyMatrix4( m ) { 29631 29632 for ( let i = 0, l = this.data.count; i < l; i ++ ) { 29633 29634 _vector$6.fromBufferAttribute( this, i ); 29635 29636 _vector$6.applyMatrix4( m ); 29637 29638 this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); 29639 29640 } 29641 29642 return this; 29643 29644 } 29645 29646 applyNormalMatrix( m ) { 29647 29648 for ( let i = 0, l = this.count; i < l; i ++ ) { 29649 29650 _vector$6.fromBufferAttribute( this, i ); 29651 29652 _vector$6.applyNormalMatrix( m ); 29653 29654 this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); 29655 29656 } 29657 29658 return this; 29659 29660 } 29661 29662 transformDirection( m ) { 29663 29664 for ( let i = 0, l = this.count; i < l; i ++ ) { 29665 29666 _vector$6.fromBufferAttribute( this, i ); 29667 29668 _vector$6.transformDirection( m ); 29669 29670 this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); 29671 29672 } 29673 29674 return this; 29675 29676 } 29677 29678 setX( index, x ) { 29679 29680 if ( this.normalized ) x = normalize( x, this.array ); 29681 29682 this.data.array[ index * this.data.stride + this.offset ] = x; 29683 29684 return this; 29685 29686 } 29687 29688 setY( index, y ) { 29689 29690 if ( this.normalized ) y = normalize( y, this.array ); 29691 29692 this.data.array[ index * this.data.stride + this.offset + 1 ] = y; 29693 29694 return this; 29695 29696 } 29697 29698 setZ( index, z ) { 29699 29700 if ( this.normalized ) z = normalize( z, this.array ); 29701 29702 this.data.array[ index * this.data.stride + this.offset + 2 ] = z; 29703 29704 return this; 29705 29706 } 29707 29708 setW( index, w ) { 29709 29710 if ( this.normalized ) w = normalize( w, this.array ); 29711 29712 this.data.array[ index * this.data.stride + this.offset + 3 ] = w; 29713 29714 return this; 29715 29716 } 29717 29718 getX( index ) { 29719 29720 let x = this.data.array[ index * this.data.stride + this.offset ]; 29721 29722 if ( this.normalized ) x = denormalize( x, this.array ); 29723 29724 return x; 29725 29726 } 29727 29728 getY( index ) { 29729 29730 let y = this.data.array[ index * this.data.stride + this.offset + 1 ]; 29731 29732 if ( this.normalized ) y = denormalize( y, this.array ); 29733 29734 return y; 29735 29736 } 29737 29738 getZ( index ) { 29739 29740 let z = this.data.array[ index * this.data.stride + this.offset + 2 ]; 29741 29742 if ( this.normalized ) z = denormalize( z, this.array ); 29743 29744 return z; 29745 29746 } 29747 29748 getW( index ) { 29749 29750 let w = this.data.array[ index * this.data.stride + this.offset + 3 ]; 29751 29752 if ( this.normalized ) w = denormalize( w, this.array ); 29753 29754 return w; 29755 29756 } 29757 29758 setXY( index, x, y ) { 29759 29760 index = index * this.data.stride + this.offset; 29761 29762 if ( this.normalized ) { 29763 29764 x = normalize( x, this.array ); 29765 y = normalize( y, this.array ); 29766 29767 } 29768 29769 this.data.array[ index + 0 ] = x; 29770 this.data.array[ index + 1 ] = y; 29771 29772 return this; 29773 29774 } 29775 29776 setXYZ( index, x, y, z ) { 29777 29778 index = index * this.data.stride + this.offset; 29779 29780 if ( this.normalized ) { 29781 29782 x = normalize( x, this.array ); 29783 y = normalize( y, this.array ); 29784 z = normalize( z, this.array ); 29785 29786 } 29787 29788 this.data.array[ index + 0 ] = x; 29789 this.data.array[ index + 1 ] = y; 29790 this.data.array[ index + 2 ] = z; 29791 29792 return this; 29793 29794 } 29795 29796 setXYZW( index, x, y, z, w ) { 29797 29798 index = index * this.data.stride + this.offset; 29799 29800 if ( this.normalized ) { 29801 29802 x = normalize( x, this.array ); 29803 y = normalize( y, this.array ); 29804 z = normalize( z, this.array ); 29805 w = normalize( w, this.array ); 29806 29807 } 29808 29809 this.data.array[ index + 0 ] = x; 29810 this.data.array[ index + 1 ] = y; 29811 this.data.array[ index + 2 ] = z; 29812 this.data.array[ index + 3 ] = w; 29813 29814 return this; 29815 29816 } 29817 29818 clone( data ) { 29819 29820 if ( data === undefined ) { 29821 29822 console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' ); 29823 29824 const array = []; 29825 29826 for ( let i = 0; i < this.count; i ++ ) { 29827 29828 const index = i * this.data.stride + this.offset; 29829 29830 for ( let j = 0; j < this.itemSize; j ++ ) { 29831 29832 array.push( this.data.array[ index + j ] ); 29833 29834 } 29835 29836 } 29837 29838 return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized ); 29839 29840 } else { 29841 29842 if ( data.interleavedBuffers === undefined ) { 29843 29844 data.interleavedBuffers = {}; 29845 29846 } 29847 29848 if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { 29849 29850 data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data ); 29851 29852 } 29853 29854 return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized ); 29855 29856 } 29857 29858 } 29859 29860 toJSON( data ) { 29861 29862 if ( data === undefined ) { 29863 29864 console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' ); 29865 29866 const array = []; 29867 29868 for ( let i = 0; i < this.count; i ++ ) { 29869 29870 const index = i * this.data.stride + this.offset; 29871 29872 for ( let j = 0; j < this.itemSize; j ++ ) { 29873 29874 array.push( this.data.array[ index + j ] ); 29875 29876 } 29877 29878 } 29879 29880 // de-interleave data and save it as an ordinary buffer attribute for now 29881 29882 return { 29883 itemSize: this.itemSize, 29884 type: this.array.constructor.name, 29885 array: array, 29886 normalized: this.normalized 29887 }; 29888 29889 } else { 29890 29891 // save as true interleaved attribute 29892 29893 if ( data.interleavedBuffers === undefined ) { 29894 29895 data.interleavedBuffers = {}; 29896 29897 } 29898 29899 if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { 29900 29901 data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data ); 29902 29903 } 29904 29905 return { 29906 isInterleavedBufferAttribute: true, 29907 itemSize: this.itemSize, 29908 data: this.data.uuid, 29909 offset: this.offset, 29910 normalized: this.normalized 29911 }; 29912 29913 } 29914 29915 } 29916 29917} 29918 29919class SpriteMaterial extends Material { 29920 29921 constructor( parameters ) { 29922 29923 super(); 29924 29925 this.isSpriteMaterial = true; 29926 29927 this.type = 'SpriteMaterial'; 29928 29929 this.color = new Color( 0xffffff ); 29930 29931 this.map = null; 29932 29933 this.alphaMap = null; 29934 29935 this.rotation = 0; 29936 29937 this.sizeAttenuation = true; 29938 29939 this.transparent = true; 29940 29941 this.fog = true; 29942 29943 this.setValues( parameters ); 29944 29945 } 29946 29947 copy( source ) { 29948 29949 super.copy( source ); 29950 29951 this.color.copy( source.color ); 29952 29953 this.map = source.map; 29954 29955 this.alphaMap = source.alphaMap; 29956 29957 this.rotation = source.rotation; 29958 29959 this.sizeAttenuation = source.sizeAttenuation; 29960
vendor: 6,754 bytes, lines 29961-30297
29961 this.fog = source.fog; 29962 29963 return this; 29964 29965 } 29966 29967} 29968 29969let _geometry; 29970 29971const _intersectPoint = /*@__PURE__*/ new Vector3(); 29972const _worldScale = /*@__PURE__*/ new Vector3(); 29973const _mvPosition = /*@__PURE__*/ new Vector3(); 29974 29975const _alignedPosition = /*@__PURE__*/ new Vector2(); 29976const _rotatedPosition = /*@__PURE__*/ new Vector2(); 29977const _viewWorldMatrix = /*@__PURE__*/ new Matrix4(); 29978 29979const _vA = /*@__PURE__*/ new Vector3(); 29980const _vB = /*@__PURE__*/ new Vector3(); 29981const _vC = /*@__PURE__*/ new Vector3(); 29982 29983const _uvA = /*@__PURE__*/ new Vector2(); 29984const _uvB = /*@__PURE__*/ new Vector2(); 29985const _uvC = /*@__PURE__*/ new Vector2(); 29986 29987class Sprite extends Object3D { 29988 29989 constructor( material ) { 29990 29991 super(); 29992 29993 this.isSprite = true; 29994 29995 this.type = 'Sprite'; 29996 29997 if ( _geometry === undefined ) { 29998 29999 _geometry = new BufferGeometry(); 30000 30001 const float32Array = new Float32Array( [ 30002 - 0.5, - 0.5, 0, 0, 0, 30003 0.5, - 0.5, 0, 1, 0, 30004 0.5, 0.5, 0, 1, 1, 30005 - 0.5, 0.5, 0, 0, 1 30006 ] ); 30007 30008 const interleavedBuffer = new InterleavedBuffer( float32Array, 5 ); 30009 30010 _geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] ); 30011 _geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) ); 30012 _geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) ); 30013 30014 } 30015 30016 this.geometry = _geometry; 30017 this.material = ( material !== undefined ) ? material : new SpriteMaterial(); 30018 30019 this.center = new Vector2( 0.5, 0.5 ); 30020 30021 } 30022 30023 raycast( raycaster, intersects ) { 30024 30025 if ( raycaster.camera === null ) { 30026 30027 console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' ); 30028 30029 } 30030 30031 _worldScale.setFromMatrixScale( this.matrixWorld ); 30032 30033 _viewWorldMatrix.copy( raycaster.camera.matrixWorld ); 30034 this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld ); 30035 30036 _mvPosition.setFromMatrixPosition( this.modelViewMatrix ); 30037 30038 if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) { 30039 30040 _worldScale.multiplyScalar( - _mvPosition.z ); 30041 30042 } 30043 30044 const rotation = this.material.rotation; 30045 let sin, cos; 30046 30047 if ( rotation !== 0 ) { 30048 30049 cos = Math.cos( rotation ); 30050 sin = Math.sin( rotation ); 30051 30052 } 30053 30054 const center = this.center; 30055 30056 transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 30057 transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 30058 transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 30059 30060 _uvA.set( 0, 0 ); 30061 _uvB.set( 1, 0 ); 30062 _uvC.set( 1, 1 ); 30063 30064 // check first triangle 30065 let intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC, false, _intersectPoint ); 30066 30067 if ( intersect === null ) { 30068 30069 // check second triangle 30070 transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 30071 _uvB.set( 0, 1 ); 30072 30073 intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB, false, _intersectPoint ); 30074 if ( intersect === null ) { 30075 30076 return; 30077 30078 } 30079 30080 } 30081 30082 const distance = raycaster.ray.origin.distanceTo( _intersectPoint ); 30083 30084 if ( distance < raycaster.near || distance > raycaster.far ) return; 30085 30086 intersects.push( { 30087 30088 distance: distance, 30089 point: _intersectPoint.clone(), 30090 uv: Triangle.getUV( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), 30091 face: null, 30092 object: this 30093 30094 } ); 30095 30096 } 30097 30098 copy( source, recursive ) { 30099 30100 super.copy( source, recursive ); 30101 30102 if ( source.center !== undefined ) this.center.copy( source.center ); 30103 30104 this.material = source.material; 30105 30106 return this; 30107 30108 } 30109 30110} 30111 30112function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) { 30113 30114 // compute position in camera space 30115 _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale ); 30116 30117 // to check if rotation is not zero 30118 if ( sin !== undefined ) { 30119 30120 _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y ); 30121 _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y ); 30122 30123 } else { 30124 30125 _rotatedPosition.copy( _alignedPosition ); 30126 30127 } 30128 30129 30130 vertexPosition.copy( mvPosition ); 30131 vertexPosition.x += _rotatedPosition.x; 30132 vertexPosition.y += _rotatedPosition.y; 30133 30134 // transform to world space 30135 vertexPosition.applyMatrix4( _viewWorldMatrix ); 30136 30137} 30138 30139const _v1$2 = /*@__PURE__*/ new Vector3(); 30140const _v2$1 = /*@__PURE__*/ new Vector3(); 30141 30142class LOD extends Object3D { 30143 30144 constructor() { 30145 30146 super(); 30147 30148 this._currentLevel = 0; 30149 30150 this.type = 'LOD'; 30151 30152 Object.defineProperties( this, { 30153 levels: { 30154 enumerable: true, 30155 value: [] 30156 }, 30157 isLOD: { 30158 value: true, 30159 } 30160 } ); 30161 30162 this.autoUpdate = true; 30163 30164 } 30165 30166 copy( source ) { 30167 30168 super.copy( source, false ); 30169 30170 const levels = source.levels; 30171 30172 for ( let i = 0, l = levels.length; i < l; i ++ ) { 30173 30174 const level = levels[ i ]; 30175 30176 this.addLevel( level.object.clone(), level.distance, level.hysteresis ); 30177 30178 } 30179 30180 this.autoUpdate = source.autoUpdate; 30181 30182 return this; 30183 30184 } 30185 30186 addLevel( object, distance = 0, hysteresis = 0 ) { 30187 30188 distance = Math.abs( distance ); 30189 30190 const levels = this.levels; 30191 30192 let l; 30193 30194 for ( l = 0; l < levels.length; l ++ ) { 30195 30196 if ( distance < levels[ l ].distance ) { 30197 30198 break; 30199 30200 } 30201 30202 } 30203 30204 levels.splice( l, 0, { distance: distance, hysteresis: hysteresis, object: object } ); 30205 30206 this.add( object ); 30207 30208 return this; 30209 30210 } 30211 30212 getCurrentLevel() { 30213 30214 return this._currentLevel; 30215 30216 } 30217 30218 30219 30220 getObjectForDistance( distance ) { 30221 30222 const levels = this.levels; 30223 30224 if ( levels.length > 0 ) { 30225 30226 let i, l; 30227 30228 for ( i = 1, l = levels.length; i < l; i ++ ) { 30229 30230 let levelDistance = levels[ i ].distance; 30231 30232 if ( levels[ i ].object.visible ) { 30233 30234 levelDistance -= levelDistance * levels[ i ].hysteresis; 30235 30236 } 30237 30238 if ( distance < levelDistance ) { 30239 30240 break; 30241 30242 } 30243 30244 } 30245 30246 return levels[ i - 1 ].object; 30247 30248 } 30249 30250 return null; 30251 30252 } 30253 30254 raycast( raycaster, intersects ) { 30255 30256 const levels = this.levels; 30257 30258 if ( levels.length > 0 ) { 30259 30260 _v1$2.setFromMatrixPosition( this.matrixWorld ); 30261 30262 const distance = raycaster.ray.origin.distanceTo( _v1$2 ); 30263 30264 this.getObjectForDistance( distance ).raycast( raycaster, intersects ); 30265 30266 } 30267 30268 } 30269 30270 update( camera ) { 30271 30272 const levels = this.levels; 30273 30274 if ( levels.length > 1 ) { 30275 30276 _v1$2.setFromMatrixPosition( camera.matrixWorld ); 30277 _v2$1.setFromMatrixPosition( this.matrixWorld ); 30278 30279 const distance = _v1$2.distanceTo( _v2$1 ) / camera.zoom; 30280 30281 levels[ 0 ].object.visible = true; 30282 30283 let i, l; 30284 30285 for ( i = 1, l = levels.length; i < l; i ++ ) { 30286 30287 let levelDistance = levels[ i ].distance; 30288 30289 if ( levels[ i ].object.visible ) { 30290 30291 levelDistance -= levelDistance * levels[ i ].hysteresis; 30292 30293 } 30294 30295 if ( distance >= levelDistance ) { 30296 30297 levels[ i - 1 ].object.visible = false;
vendor: 2,147 bytes, lines 30298-30429
30298 levels[ i ].object.visible = true; 30299 30300 } else { 30301 30302 break; 30303 30304 } 30305 30306 } 30307 30308 this._currentLevel = i - 1; 30309 30310 for ( ; i < l; i ++ ) { 30311 30312 levels[ i ].object.visible = false; 30313 30314 } 30315 30316 } 30317 30318 } 30319 30320 toJSON( meta ) { 30321 30322 const data = super.toJSON( meta ); 30323 30324 if ( this.autoUpdate === false ) data.object.autoUpdate = false; 30325 30326 data.object.levels = []; 30327 30328 const levels = this.levels; 30329 30330 for ( let i = 0, l = levels.length; i < l; i ++ ) { 30331 30332 const level = levels[ i ]; 30333 30334 data.object.levels.push( { 30335 object: level.object.uuid, 30336 distance: level.distance, 30337 hysteresis: level.hysteresis 30338 } ); 30339 30340 } 30341 30342 return data; 30343 30344 } 30345 30346} 30347 30348const _basePosition = /*@__PURE__*/ new Vector3(); 30349 30350const _skinIndex = /*@__PURE__*/ new Vector4(); 30351const _skinWeight = /*@__PURE__*/ new Vector4(); 30352 30353const _vector$5 = /*@__PURE__*/ new Vector3(); 30354const _matrix = /*@__PURE__*/ new Matrix4(); 30355 30356class SkinnedMesh extends Mesh { 30357 30358 constructor( geometry, material ) { 30359 30360 super( geometry, material ); 30361 30362 this.isSkinnedMesh = true; 30363 30364 this.type = 'SkinnedMesh'; 30365 30366 this.bindMode = 'attached'; 30367 this.bindMatrix = new Matrix4(); 30368 this.bindMatrixInverse = new Matrix4(); 30369 30370 } 30371 30372 copy( source, recursive ) { 30373 30374 super.copy( source, recursive ); 30375 30376 this.bindMode = source.bindMode; 30377 this.bindMatrix.copy( source.bindMatrix ); 30378 this.bindMatrixInverse.copy( source.bindMatrixInverse ); 30379 30380 this.skeleton = source.skeleton; 30381 30382 return this; 30383 30384 } 30385 30386 bind( skeleton, bindMatrix ) { 30387 30388 this.skeleton = skeleton; 30389 30390 if ( bindMatrix === undefined ) { 30391 30392 this.updateMatrixWorld( true ); 30393 30394 this.skeleton.calculateInverses(); 30395 30396 bindMatrix = this.matrixWorld; 30397 30398 } 30399 30400 this.bindMatrix.copy( bindMatrix ); 30401 this.bindMatrixInverse.copy( bindMatrix ).invert(); 30402 30403 } 30404 30405 pose() { 30406 30407 this.skeleton.pose(); 30408 30409 } 30410 30411 normalizeSkinWeights() { 30412 30413 const vector = new Vector4(); 30414 30415 const skinWeight = this.geometry.attributes.skinWeight; 30416 30417 for ( let i = 0, l = skinWeight.count; i < l; i ++ ) { 30418 30419 vector.fromBufferAttribute( skinWeight, i ); 30420 30421 const scale = 1.0 / vector.manhattanLength(); 30422 30423 if ( scale !== Infinity ) { 30424 30425 vector.multiplyScalar( scale ); 30426 30427 } else { 30428 30429 vector.set( 1, 0, 0, 0 );
vendor: 17,414 bytes, lines 30429-31311
30429 // do something reasonable 30430 30431 } 30432 30433 skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w ); 30434 30435 } 30436 30437 } 30438 30439 updateMatrixWorld( force ) { 30440 30441 super.updateMatrixWorld( force ); 30442 30443 if ( this.bindMode === 'attached' ) { 30444 30445 this.bindMatrixInverse.copy( this.matrixWorld ).invert(); 30446 30447 } else if ( this.bindMode === 'detached' ) { 30448 30449 this.bindMatrixInverse.copy( this.bindMatrix ).invert(); 30450 30451 } else { 30452 30453 console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); 30454 30455 } 30456 30457 } 30458 30459 boneTransform( index, target ) { 30460 30461 const skeleton = this.skeleton; 30462 const geometry = this.geometry; 30463 30464 _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); 30465 _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); 30466 30467 _basePosition.copy( target ).applyMatrix4( this.bindMatrix ); 30468 30469 target.set( 0, 0, 0 ); 30470 30471 for ( let i = 0; i < 4; i ++ ) { 30472 30473 const weight = _skinWeight.getComponent( i ); 30474 30475 if ( weight !== 0 ) { 30476 30477 const boneIndex = _skinIndex.getComponent( i ); 30478 30479 _matrix.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); 30480 30481 target.addScaledVector( _vector$5.copy( _basePosition ).applyMatrix4( _matrix ), weight ); 30482 30483 } 30484 30485 } 30486 30487 return target.applyMatrix4( this.bindMatrixInverse ); 30488 30489 } 30490 30491} 30492 30493class Bone extends Object3D { 30494 30495 constructor() { 30496 30497 super(); 30498 30499 this.isBone = true; 30500 30501 this.type = 'Bone'; 30502 30503 } 30504 30505} 30506 30507class DataTexture extends Texture { 30508 30509 constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, encoding ) { 30510 30511 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); 30512 30513 this.isDataTexture = true; 30514 30515 this.image = { data: data, width: width, height: height }; 30516 30517 this.generateMipmaps = false; 30518 this.flipY = false; 30519 this.unpackAlignment = 1; 30520 30521 } 30522 30523} 30524 30525const _offsetMatrix = /*@__PURE__*/ new Matrix4(); 30526const _identityMatrix = /*@__PURE__*/ new Matrix4(); 30527 30528class Skeleton { 30529 30530 constructor( bones = [], boneInverses = [] ) { 30531 30532 this.uuid = generateUUID(); 30533 30534 this.bones = bones.slice( 0 ); 30535 this.boneInverses = boneInverses; 30536 this.boneMatrices = null; 30537 30538 this.boneTexture = null; 30539 this.boneTextureSize = 0; 30540 30541 this.frame = - 1; 30542 30543 this.init(); 30544 30545 } 30546 30547 init() { 30548 30549 const bones = this.bones; 30550 const boneInverses = this.boneInverses; 30551 30552 this.boneMatrices = new Float32Array( bones.length * 16 ); 30553 30554 // calculate inverse bone matrices if necessary 30555 30556 if ( boneInverses.length === 0 ) { 30557 30558 this.calculateInverses(); 30559 30560 } else { 30561 30562 // handle special case 30563 30564 if ( bones.length !== boneInverses.length ) { 30565 30566 console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' ); 30567 30568 this.boneInverses = []; 30569 30570 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 30571 30572 this.boneInverses.push( new Matrix4() ); 30573 30574 } 30575 30576 } 30577 30578 } 30579 30580 } 30581 30582 calculateInverses() { 30583 30584 this.boneInverses.length = 0; 30585 30586 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 30587 30588 const inverse = new Matrix4(); 30589 30590 if ( this.bones[ i ] ) { 30591 30592 inverse.copy( this.bones[ i ].matrixWorld ).invert(); 30593 30594 } 30595 30596 this.boneInverses.push( inverse ); 30597 30598 } 30599 30600 } 30601 30602 pose() { 30603 30604 // recover the bind-time world matrices 30605 30606 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 30607 30608 const bone = this.bones[ i ]; 30609 30610 if ( bone ) { 30611 30612 bone.matrixWorld.copy( this.boneInverses[ i ] ).invert(); 30613 30614 } 30615 30616 } 30617 30618 // compute the local matrices, positions, rotations and scales 30619 30620 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 30621 30622 const bone = this.bones[ i ]; 30623 30624 if ( bone ) { 30625 30626 if ( bone.parent && bone.parent.isBone ) { 30627 30628 bone.matrix.copy( bone.parent.matrixWorld ).invert(); 30629 bone.matrix.multiply( bone.matrixWorld ); 30630 30631 } else { 30632 30633 bone.matrix.copy( bone.matrixWorld ); 30634 30635 } 30636 30637 bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); 30638 30639 } 30640 30641 } 30642 30643 } 30644 30645 update() { 30646 30647 const bones = this.bones; 30648 const boneInverses = this.boneInverses; 30649 const boneMatrices = this.boneMatrices; 30650 const boneTexture = this.boneTexture; 30651 30652 // flatten bone matrices to array 30653 30654 for ( let i = 0, il = bones.length; i < il; i ++ ) { 30655 30656 // compute the offset between the current and the original transform 30657 30658 const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix; 30659 30660 _offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); 30661 _offsetMatrix.toArray( boneMatrices, i * 16 ); 30662 30663 } 30664 30665 if ( boneTexture !== null ) { 30666 30667 boneTexture.needsUpdate = true; 30668 30669 } 30670 30671 } 30672 30673 clone() { 30674 30675 return new Skeleton( this.bones, this.boneInverses ); 30676 30677 } 30678 30679 computeBoneTexture() { 30680 30681 // layout (1 matrix = 4 pixels) 30682 // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) 30683 // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) 30684 // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) 30685 // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) 30686 // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) 30687 30688 let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix 30689 size = ceilPowerOfTwo( size ); 30690 size = Math.max( size, 4 ); 30691 30692 const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel 30693 boneMatrices.set( this.boneMatrices ); // copy current values 30694 30695 const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); 30696 boneTexture.needsUpdate = true; 30697 30698 this.boneMatrices = boneMatrices; 30699 this.boneTexture = boneTexture; 30700 this.boneTextureSize = size; 30701 30702 return this; 30703 30704 } 30705 30706 getBoneByName( name ) { 30707 30708 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 30709 30710 const bone = this.bones[ i ]; 30711 30712 if ( bone.name === name ) { 30713 30714 return bone; 30715 30716 } 30717 30718 } 30719 30720 return undefined; 30721 30722 } 30723 30724 dispose( ) { 30725 30726 if ( this.boneTexture !== null ) { 30727 30728 this.boneTexture.dispose(); 30729 30730 this.boneTexture = null; 30731 30732 } 30733 30734 } 30735 30736 fromJSON( json, bones ) { 30737 30738 this.uuid = json.uuid; 30739 30740 for ( let i = 0, l = json.bones.length; i < l; i ++ ) { 30741 30742 const uuid = json.bones[ i ]; 30743 let bone = bones[ uuid ]; 30744 30745 if ( bone === undefined ) { 30746 30747 console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid ); 30748 bone = new Bone(); 30749 30750 } 30751 30752 this.bones.push( bone ); 30753 this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) ); 30754 30755 } 30756 30757 this.init(); 30758 30759 return this; 30760 30761 } 30762 30763 toJSON() { 30764 30765 const data = { 30766 metadata: { 30767 version: 4.5, 30768 type: 'Skeleton', 30769 generator: 'Skeleton.toJSON' 30770 }, 30771 bones: [], 30772 boneInverses: [] 30773 }; 30774 30775 data.uuid = this.uuid; 30776 30777 const bones = this.bones; 30778 const boneInverses = this.boneInverses; 30779 30780 for ( let i = 0, l = bones.length; i < l; i ++ ) { 30781 30782 const bone = bones[ i ]; 30783 data.bones.push( bone.uuid ); 30784 30785 const boneInverse = boneInverses[ i ]; 30786 data.boneInverses.push( boneInverse.toArray() ); 30787 30788 } 30789 30790 return data; 30791 30792 } 30793 30794} 30795 30796class InstancedBufferAttribute extends BufferAttribute { 30797 30798 constructor( array, itemSize, normalized, meshPerAttribute = 1 ) { 30799 30800 super( array, itemSize, normalized ); 30801 30802 this.isInstancedBufferAttribute = true; 30803 30804 this.meshPerAttribute = meshPerAttribute; 30805 30806 } 30807 30808 copy( source ) { 30809 30810 super.copy( source ); 30811 30812 this.meshPerAttribute = source.meshPerAttribute; 30813 30814 return this; 30815 30816 } 30817 30818 toJSON() { 30819 30820 const data = super.toJSON(); 30821 30822 data.meshPerAttribute = this.meshPerAttribute; 30823 30824 data.isInstancedBufferAttribute = true; 30825 30826 return data; 30827 30828 } 30829 30830} 30831 30832const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4(); 30833const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4(); 30834 30835const _instanceIntersects = []; 30836 30837const _identity = /*@__PURE__*/ new Matrix4(); 30838const _mesh = /*@__PURE__*/ new Mesh(); 30839 30840class InstancedMesh extends Mesh { 30841 30842 constructor( geometry, material, count ) { 30843 30844 super( geometry, material ); 30845 30846 this.isInstancedMesh = true; 30847 30848 this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 ); 30849 this.instanceColor = null; 30850 30851 this.count = count; 30852 30853 this.frustumCulled = false; 30854 30855 for ( let i = 0; i < count; i ++ ) { 30856 30857 this.setMatrixAt( i, _identity ); 30858 30859 } 30860 30861 } 30862 30863 copy( source, recursive ) { 30864 30865 super.copy( source, recursive ); 30866 30867 this.instanceMatrix.copy( source.instanceMatrix ); 30868 30869 if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone(); 30870 30871 this.count = source.count; 30872 30873 return this; 30874 30875 } 30876 30877 getColorAt( index, color ) { 30878 30879 color.fromArray( this.instanceColor.array, index * 3 ); 30880 30881 } 30882 30883 getMatrixAt( index, matrix ) { 30884 30885 matrix.fromArray( this.instanceMatrix.array, index * 16 ); 30886 30887 } 30888 30889 raycast( raycaster, intersects ) { 30890 30891 const matrixWorld = this.matrixWorld; 30892 const raycastTimes = this.count; 30893 30894 _mesh.geometry = this.geometry; 30895 _mesh.material = this.material; 30896 30897 if ( _mesh.material === undefined ) return; 30898 30899 for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) { 30900 30901 // calculate the world matrix for each instance 30902 30903 this.getMatrixAt( instanceId, _instanceLocalMatrix ); 30904 30905 _instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix ); 30906 30907 // the mesh represents this single instance 30908 30909 _mesh.matrixWorld = _instanceWorldMatrix; 30910 30911 _mesh.raycast( raycaster, _instanceIntersects ); 30912 30913 // process the result of raycast 30914 30915 for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) { 30916 30917 const intersect = _instanceIntersects[ i ]; 30918 intersect.instanceId = instanceId; 30919 intersect.object = this; 30920 intersects.push( intersect ); 30921 30922 } 30923 30924 _instanceIntersects.length = 0; 30925 30926 } 30927 30928 } 30929 30930 setColorAt( index, color ) { 30931 30932 if ( this.instanceColor === null ) { 30933 30934 this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ), 3 ); 30935 30936 } 30937 30938 color.toArray( this.instanceColor.array, index * 3 ); 30939 30940 } 30941 30942 setMatrixAt( index, matrix ) { 30943 30944 matrix.toArray( this.instanceMatrix.array, index * 16 ); 30945 30946 } 30947 30948 updateMorphTargets() { 30949 30950 } 30951 30952 dispose() { 30953 30954 this.dispatchEvent( { type: 'dispose' } ); 30955 30956 } 30957 30958} 30959 30960class LineBasicMaterial extends Material { 30961 30962 constructor( parameters ) { 30963 30964 super(); 30965 30966 this.isLineBasicMaterial = true; 30967 30968 this.type = 'LineBasicMaterial'; 30969 30970 this.color = new Color( 0xffffff ); 30971 30972 this.linewidth = 1; 30973 this.linecap = 'round'; 30974 this.linejoin = 'round'; 30975 30976 this.fog = true; 30977 30978 this.setValues( parameters ); 30979 30980 } 30981 30982 30983 copy( source ) { 30984 30985 super.copy( source ); 30986 30987 this.color.copy( source.color ); 30988 30989 this.linewidth = source.linewidth; 30990 this.linecap = source.linecap; 30991 this.linejoin = source.linejoin; 30992 30993 this.fog = source.fog; 30994 30995 return this; 30996 30997 } 30998 30999} 31000 31001const _start$1 = /*@__PURE__*/ new Vector3(); 31002const _end$1 = /*@__PURE__*/ new Vector3(); 31003const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4(); 31004const _ray$1 = /*@__PURE__*/ new Ray(); 31005const _sphere$1 = /*@__PURE__*/ new Sphere(); 31006 31007class Line extends Object3D { 31008 31009 constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) { 31010 31011 super(); 31012 31013 this.isLine = true; 31014 31015 this.type = 'Line'; 31016 31017 this.geometry = geometry; 31018 this.material = material; 31019 31020 this.updateMorphTargets(); 31021 31022 } 31023 31024 copy( source, recursive ) { 31025 31026 super.copy( source, recursive ); 31027 31028 this.material = source.material; 31029 this.geometry = source.geometry; 31030 31031 return this; 31032 31033 } 31034 31035 computeLineDistances() { 31036 31037 const geometry = this.geometry; 31038 31039 // we assume non-indexed geometry 31040 31041 if ( geometry.index === null ) { 31042 31043 const positionAttribute = geometry.attributes.position; 31044 const lineDistances = [ 0 ]; 31045 31046 for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) { 31047 31048 _start$1.fromBufferAttribute( positionAttribute, i - 1 ); 31049 _end$1.fromBufferAttribute( positionAttribute, i ); 31050 31051 lineDistances[ i ] = lineDistances[ i - 1 ]; 31052 lineDistances[ i ] += _start$1.distanceTo( _end$1 ); 31053 31054 } 31055 31056 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); 31057 31058 } else { 31059 31060 console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); 31061 31062 } 31063 31064 return this; 31065 31066 } 31067 31068 raycast( raycaster, intersects ) { 31069 31070 const geometry = this.geometry; 31071 const matrixWorld = this.matrixWorld; 31072 const threshold = raycaster.params.Line.threshold; 31073 const drawRange = geometry.drawRange; 31074 31075 // Checking boundingSphere distance to ray 31076 31077 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 31078 31079 _sphere$1.copy( geometry.boundingSphere ); 31080 _sphere$1.applyMatrix4( matrixWorld ); 31081 _sphere$1.radius += threshold; 31082 31083 if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return; 31084 31085 // 31086 31087 _inverseMatrix$1.copy( matrixWorld ).invert(); 31088 _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 ); 31089 31090 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); 31091 const localThresholdSq = localThreshold * localThreshold; 31092 31093 const vStart = new Vector3(); 31094 const vEnd = new Vector3(); 31095 const interSegment = new Vector3(); 31096 const interRay = new Vector3(); 31097 const step = this.isLineSegments ? 2 : 1; 31098 31099 const index = geometry.index; 31100 const attributes = geometry.attributes; 31101 const positionAttribute = attributes.position; 31102 31103 if ( index !== null ) { 31104 31105 const start = Math.max( 0, drawRange.start ); 31106 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); 31107 31108 for ( let i = start, l = end - 1; i < l; i += step ) { 31109 31110 const a = index.getX( i ); 31111 const b = index.getX( i + 1 ); 31112 31113 vStart.fromBufferAttribute( positionAttribute, a ); 31114 vEnd.fromBufferAttribute( positionAttribute, b ); 31115 31116 const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); 31117 31118 if ( distSq > localThresholdSq ) continue; 31119 31120 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation 31121 31122 const distance = raycaster.ray.origin.distanceTo( interRay ); 31123 31124 if ( distance < raycaster.near || distance > raycaster.far ) continue; 31125 31126 intersects.push( { 31127 31128 distance: distance, 31129 // What do we want? intersection point on the ray or on the segment?? 31130 // point: raycaster.ray.at( distance ), 31131 point: interSegment.clone().applyMatrix4( this.matrixWorld ), 31132 index: i, 31133 face: null, 31134 faceIndex: null, 31135 object: this 31136 31137 } ); 31138 31139 } 31140 31141 } else { 31142 31143 const start = Math.max( 0, drawRange.start ); 31144 const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); 31145 31146 for ( let i = start, l = end - 1; i < l; i += step ) { 31147 31148 vStart.fromBufferAttribute( positionAttribute, i ); 31149 vEnd.fromBufferAttribute( positionAttribute, i + 1 ); 31150 31151 const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); 31152 31153 if ( distSq > localThresholdSq ) continue; 31154 31155 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation 31156 31157 const distance = raycaster.ray.origin.distanceTo( interRay ); 31158 31159 if ( distance < raycaster.near || distance > raycaster.far ) continue; 31160 31161 intersects.push( { 31162 31163 distance: distance, 31164 // What do we want? intersection point on the ray or on the segment?? 31165 // point: raycaster.ray.at( distance ), 31166 point: interSegment.clone().applyMatrix4( this.matrixWorld ), 31167 index: i, 31168 face: null, 31169 faceIndex: null, 31170 object: this 31171 31172 } ); 31173 31174 } 31175 31176 } 31177 31178 } 31179 31180 updateMorphTargets() { 31181 31182 const geometry = this.geometry; 31183 31184 const morphAttributes = geometry.morphAttributes; 31185 const keys = Object.keys( morphAttributes ); 31186 31187 if ( keys.length > 0 ) { 31188 31189 const morphAttribute = morphAttributes[ keys[ 0 ] ]; 31190 31191 if ( morphAttribute !== undefined ) { 31192 31193 this.morphTargetInfluences = []; 31194 this.morphTargetDictionary = {}; 31195 31196 for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 31197 31198 const name = morphAttribute[ m ].name || String( m ); 31199 31200 this.morphTargetInfluences.push( 0 ); 31201 this.morphTargetDictionary[ name ] = m; 31202 31203 } 31204 31205 } 31206 31207 } 31208 31209 } 31210 31211} 31212 31213const _start = /*@__PURE__*/ new Vector3(); 31214const _end = /*@__PURE__*/ new Vector3(); 31215 31216class LineSegments extends Line { 31217 31218 constructor( geometry, material ) { 31219 31220 super( geometry, material ); 31221 31222 this.isLineSegments = true; 31223 31224 this.type = 'LineSegments'; 31225 31226 } 31227 31228 computeLineDistances() { 31229 31230 const geometry = this.geometry; 31231 31232 // we assume non-indexed geometry 31233 31234 if ( geometry.index === null ) { 31235 31236 const positionAttribute = geometry.attributes.position; 31237 const lineDistances = []; 31238 31239 for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) { 31240 31241 _start.fromBufferAttribute( positionAttribute, i ); 31242 _end.fromBufferAttribute( positionAttribute, i + 1 ); 31243 31244 lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ]; 31245 lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end ); 31246 31247 } 31248 31249 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); 31250 31251 } else { 31252 31253 console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); 31254 31255 } 31256 31257 return this; 31258 31259 } 31260 31261} 31262 31263class LineLoop extends Line { 31264 31265 constructor( geometry, material ) { 31266 31267 super( geometry, material ); 31268 31269 this.isLineLoop = true; 31270 31271 this.type = 'LineLoop'; 31272 31273 } 31274 31275} 31276 31277class PointsMaterial extends Material { 31278 31279 constructor( parameters ) { 31280 31281 super(); 31282 31283 this.isPointsMaterial = true; 31284 31285 this.type = 'PointsMaterial'; 31286 31287 this.color = new Color( 0xffffff ); 31288 31289 this.map = null; 31290 31291 this.alphaMap = null; 31292 31293 this.size = 1; 31294 this.sizeAttenuation = true; 31295 31296 this.fog = true; 31297 31298 this.setValues( parameters ); 31299 31300 } 31301 31302 copy( source ) { 31303 31304 super.copy( source ); 31305 31306 this.color.copy( source.color ); 31307 31308 this.map = source.map; 31309 31310 this.alphaMap = source.alphaMap; 31311
vendor: 4,136 bytes, lines 31312-31491
31312 this.size = source.size; 31313 this.sizeAttenuation = source.sizeAttenuation; 31314 31315 this.fog = source.fog; 31316 31317 return this; 31318 31319 } 31320 31321} 31322 31323const _inverseMatrix = /*@__PURE__*/ new Matrix4(); 31324const _ray = /*@__PURE__*/ new Ray(); 31325const _sphere = /*@__PURE__*/ new Sphere(); 31326const _position$2 = /*@__PURE__*/ new Vector3(); 31327 31328class Points extends Object3D { 31329 31330 constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) { 31331 31332 super(); 31333 31334 this.isPoints = true; 31335 31336 this.type = 'Points'; 31337 31338 this.geometry = geometry; 31339 this.material = material; 31340 31341 this.updateMorphTargets(); 31342 31343 } 31344 31345 copy( source, recursive ) { 31346 31347 super.copy( source, recursive ); 31348 31349 this.material = source.material; 31350 this.geometry = source.geometry; 31351 31352 return this; 31353 31354 } 31355 31356 raycast( raycaster, intersects ) { 31357 31358 const geometry = this.geometry; 31359 const matrixWorld = this.matrixWorld; 31360 const threshold = raycaster.params.Points.threshold; 31361 const drawRange = geometry.drawRange; 31362 31363 // Checking boundingSphere distance to ray 31364 31365 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 31366 31367 _sphere.copy( geometry.boundingSphere ); 31368 _sphere.applyMatrix4( matrixWorld ); 31369 _sphere.radius += threshold; 31370 31371 if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return; 31372 31373 // 31374 31375 _inverseMatrix.copy( matrixWorld ).invert(); 31376 _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix ); 31377 31378 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); 31379 const localThresholdSq = localThreshold * localThreshold; 31380 31381 const index = geometry.index; 31382 const attributes = geometry.attributes; 31383 const positionAttribute = attributes.position; 31384 31385 if ( index !== null ) { 31386 31387 const start = Math.max( 0, drawRange.start ); 31388 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); 31389 31390 for ( let i = start, il = end; i < il; i ++ ) { 31391 31392 const a = index.getX( i ); 31393 31394 _position$2.fromBufferAttribute( positionAttribute, a ); 31395 31396 testPoint( _position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this ); 31397 31398 } 31399 31400 } else { 31401 31402 const start = Math.max( 0, drawRange.start ); 31403 const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); 31404 31405 for ( let i = start, l = end; i < l; i ++ ) { 31406 31407 _position$2.fromBufferAttribute( positionAttribute, i ); 31408 31409 testPoint( _position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this ); 31410 31411 } 31412 31413 } 31414 31415 } 31416 31417 updateMorphTargets() { 31418 31419 const geometry = this.geometry; 31420 31421 const morphAttributes = geometry.morphAttributes; 31422 const keys = Object.keys( morphAttributes ); 31423 31424 if ( keys.length > 0 ) { 31425 31426 const morphAttribute = morphAttributes[ keys[ 0 ] ]; 31427 31428 if ( morphAttribute !== undefined ) { 31429 31430 this.morphTargetInfluences = []; 31431 this.morphTargetDictionary = {}; 31432 31433 for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 31434 31435 const name = morphAttribute[ m ].name || String( m ); 31436 31437 this.morphTargetInfluences.push( 0 ); 31438 this.morphTargetDictionary[ name ] = m; 31439 31440 } 31441 31442 } 31443 31444 } 31445 31446 } 31447 31448} 31449 31450function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) { 31451 31452 const rayPointDistanceSq = _ray.distanceSqToPoint( point ); 31453 31454 if ( rayPointDistanceSq < localThresholdSq ) { 31455 31456 const intersectPoint = new Vector3(); 31457 31458 _ray.closestPointToPoint( point, intersectPoint ); 31459 intersectPoint.applyMatrix4( matrixWorld ); 31460 31461 const distance = raycaster.ray.origin.distanceTo( intersectPoint ); 31462 31463 if ( distance < raycaster.near || distance > raycaster.far ) return; 31464 31465 intersects.push( { 31466 31467 distance: distance, 31468 distanceToRay: Math.sqrt( rayPointDistanceSq ), 31469 point: intersectPoint, 31470 index: index, 31471 face: null, 31472 object: object 31473 31474 } ); 31475 31476 } 31477 31478} 31479 31480class VideoTexture extends Texture { 31481 31482 constructor( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { 31483 31484 super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 31485 31486 this.isVideoTexture = true; 31487 31488 this.minFilter = minFilter !== undefined ? minFilter : LinearFilter; 31489 this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; 31490 31491 this.generateMipmaps = false;
31492 31493 const scope = this; 31494 31495 function updateVideo() { 31496 31497 scope.needsUpdate = true; 31498 video.requestVideoFrameCallback( updateVideo ); 31499 31500 } 31501 31502 if ( 'requestVideoFrameCallback' in video ) { 31503 31504 video.requestVideoFrameCallback( updateVideo ); 31505 31506 } 31507 31508 } 31509 31510 clone() { 31511 31512 return new this.constructor( this.image ).copy( this ); 31513 31514 } 31515 31516 update() { 31517 31518 const video = this.image; 31519 const hasVideoFrameCallback = 'requestVideoFrameCallback' in video; 31520 31521 if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) { 31522 31523 this.needsUpdate = true; 31524 31525 } 31526 31527 } 31528 31529} 31530 31531class FramebufferTexture extends Texture { 31532 31533 constructor( width, height, format ) { 31534 31535 super( { width, height } ); 31536 31537 this.isFramebufferTexture = true; 31538 31539 this.format = format; 31540 31541 this.magFilter = NearestFilter; 31542 this.minFilter = NearestFilter; 31543 31544 this.generateMipmaps = false; 31545 31546 this.needsUpdate = true; 31547 31548 } 31549 31550} 31551 31552class CompressedTexture extends Texture { 31553 31554 constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { 31555 31556 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); 31557 31558 this.isCompressedTexture = true; 31559 31560 this.image = { width: width, height: height }; 31561 this.mipmaps = mipmaps; 31562 31563 // no flipping for cube textures 31564 // (also flipping doesn't work for compressed textures ) 31565 31566 this.flipY = false; 31567 31568 // can't generate mipmaps for compressed textures 31569 // mips must be embedded in DDS files 31570 31571 this.generateMipmaps = false; 31572 31573 } 31574 31575} 31576 31577class CompressedArrayTexture extends CompressedTexture { 31578 31579 constructor( mipmaps, width, height, depth, format, type ) { 31580 31581 super( mipmaps, width, height, format, type ); 31582 31583 this.isCompressedArrayTexture = true; 31584 this.image.depth = depth; 31585 this.wrapR = ClampToEdgeWrapping; 31586 31587 } 31588 31589} 31590 31591class CanvasTexture extends Texture { 31592 31593 constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { 31594 31595 super( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 31596 31597 this.isCanvasTexture = true; 31598 31599 this.needsUpdate = true; 31600 31601 } 31602 31603} 31604 31605/** 31606 * Extensible curve object. 31607 * 31608 * Some common of curve methods: 31609 * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget ) 31610 * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget ) 31611 * .getPoints(), .getSpacedPoints() 31612 * .getLength() 31613 * .updateArcLengths() 31614 * 31615 * This following curves inherit from THREE.Curve: 31616 * 31617 * -- 2D curves -- 31618 * THREE.ArcCurve 31619 * THREE.CubicBezierCurve 31620 * THREE.EllipseCurve 31621 * THREE.LineCurve 31622 * THREE.QuadraticBezierCurve 31623 * THREE.SplineCurve 31624 * 31625 * -- 3D curves -- 31626 * THREE.CatmullRomCurve3 31627 * THREE.CubicBezierCurve3 31628 * THREE.LineCurve3 31629 * THREE.QuadraticBezierCurve3 31630 * 31631 * A series of curves can be represented as a THREE.CurvePath. 31632 * 31633 **/ 31634 31635class Curve { 31636 31637 constructor() { 31638 31639 this.type = 'Curve'; 31640 31641 this.arcLengthDivisions = 200; 31642 31643 } 31644 31645 // Virtual base class method to overwrite and implement in subclasses 31646 // - t [0 .. 1] 31647 31648 getPoint( /* t, optionalTarget */ ) { 31649 31650 console.warn( 'THREE.Curve: .getPoint() not implemented.' ); 31651 return null; 31652 31653 } 31654 31655 // Get point at relative position in curve according to arc length 31656 // - u [0 .. 1] 31657 31658 getPointAt( u, optionalTarget ) { 31659 31660 const t = this.getUtoTmapping( u ); 31661 return this.getPoint( t, optionalTarget ); 31662 31663 } 31664 31665 // Get sequence of points using getPoint( t ) 31666 31667 getPoints( divisions = 5 ) { 31668 31669 const points = []; 31670 31671 for ( let d = 0; d <= divisions; d ++ ) { 31672 31673 points.push( this.getPoint( d / divisions ) ); 31674 31675 } 31676 31677 return points; 31678 31679 } 31680 31681 // Get sequence of points using getPointAt( u ) 31682 31683 getSpacedPoints( divisions = 5 ) { 31684 31685 const points = []; 31686 31687 for ( let d = 0; d <= divisions; d ++ ) { 31688 31689 points.push( this.getPointAt( d / divisions ) ); 31690 31691 } 31692 31693 return points; 31694 31695 } 31696 31697 // Get total curve arc length 31698 31699 getLength() { 31700 31701 const lengths = this.getLengths(); 31702 return lengths[ lengths.length - 1 ]; 31703 31704 } 31705 31706 // Get list of cumulative segment lengths 31707 31708 getLengths( divisions = this.arcLengthDivisions ) { 31709 31710 if ( this.cacheArcLengths && 31711 ( this.cacheArcLengths.length === divisions + 1 ) && 31712 ! this.needsUpdate ) { 31713 31714 return this.cacheArcLengths; 31715 31716 } 31717 31718 this.needsUpdate = false;
vendor: 7,518 bytes, lines 31719-32110
31719 31720 const cache = []; 31721 let current, last = this.getPoint( 0 ); 31722 let sum = 0; 31723 31724 cache.push( 0 ); 31725 31726 for ( let p = 1; p <= divisions; p ++ ) { 31727 31728 current = this.getPoint( p / divisions ); 31729 sum += current.distanceTo( last ); 31730 cache.push( sum ); 31731 last = current; 31732 31733 } 31734 31735 this.cacheArcLengths = cache; 31736 31737 return cache; // { sums: cache, sum: sum }; Sum is in the last element. 31738 31739 } 31740 31741 updateArcLengths() { 31742 31743 this.needsUpdate = true; 31744 this.getLengths(); 31745 31746 } 31747 31748 // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant 31749 31750 getUtoTmapping( u, distance ) { 31751 31752 const arcLengths = this.getLengths(); 31753 31754 let i = 0; 31755 const il = arcLengths.length; 31756 31757 let targetArcLength; // The targeted u distance value to get 31758 31759 if ( distance ) { 31760 31761 targetArcLength = distance; 31762 31763 } else { 31764 31765 targetArcLength = u * arcLengths[ il - 1 ]; 31766 31767 } 31768 31769 // binary search for the index with largest value smaller than target u distance 31770 31771 let low = 0, high = il - 1, comparison; 31772 31773 while ( low <= high ) { 31774 31775 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 31776 31777 comparison = arcLengths[ i ] - targetArcLength; 31778 31779 if ( comparison < 0 ) { 31780 31781 low = i + 1; 31782 31783 } else if ( comparison > 0 ) { 31784 31785 high = i - 1; 31786 31787 } else { 31788 31789 high = i; 31790 break; 31791 31792 // DONE 31793 31794 } 31795 31796 } 31797 31798 i = high; 31799 31800 if ( arcLengths[ i ] === targetArcLength ) { 31801 31802 return i / ( il - 1 ); 31803 31804 } 31805 31806 // we could get finer grain at lengths, or use simple interpolation between two points 31807 31808 const lengthBefore = arcLengths[ i ]; 31809 const lengthAfter = arcLengths[ i + 1 ]; 31810 31811 const segmentLength = lengthAfter - lengthBefore; 31812 31813 // determine where we are between the 'before' and 'after' points 31814 31815 const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; 31816 31817 // add that fractional amount to t 31818 31819 const t = ( i + segmentFraction ) / ( il - 1 ); 31820 31821 return t; 31822 31823 } 31824 31825 // Returns a unit vector tangent at t 31826 // In case any sub curve does not implement its tangent derivation, 31827 // 2 points a small delta apart will be used to find its gradient 31828 // which seems to give a reasonable approximation 31829 31830 getTangent( t, optionalTarget ) { 31831 31832 const delta = 0.0001; 31833 let t1 = t - delta; 31834 let t2 = t + delta; 31835 31836 // Capping in case of danger 31837 31838 if ( t1 < 0 ) t1 = 0; 31839 if ( t2 > 1 ) t2 = 1; 31840 31841 const pt1 = this.getPoint( t1 ); 31842 const pt2 = this.getPoint( t2 ); 31843 31844 const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() ); 31845 31846 tangent.copy( pt2 ).sub( pt1 ).normalize(); 31847 31848 return tangent; 31849 31850 } 31851 31852 getTangentAt( u, optionalTarget ) { 31853 31854 const t = this.getUtoTmapping( u ); 31855 return this.getTangent( t, optionalTarget ); 31856 31857 } 31858 31859 computeFrenetFrames( segments, closed ) { 31860 31861 // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf 31862 31863 const normal = new Vector3(); 31864 31865 const tangents = []; 31866 const normals = []; 31867 const binormals = []; 31868 31869 const vec = new Vector3(); 31870 const mat = new Matrix4(); 31871 31872 // compute the tangent vectors for each segment on the curve 31873 31874 for ( let i = 0; i <= segments; i ++ ) { 31875 31876 const u = i / segments; 31877 31878 tangents[ i ] = this.getTangentAt( u, new Vector3() ); 31879 31880 } 31881 31882 // select an initial normal vector perpendicular to the first tangent vector, 31883 // and in the direction of the minimum tangent xyz component 31884 31885 normals[ 0 ] = new Vector3(); 31886 binormals[ 0 ] = new Vector3(); 31887 let min = Number.MAX_VALUE; 31888 const tx = Math.abs( tangents[ 0 ].x ); 31889 const ty = Math.abs( tangents[ 0 ].y ); 31890 const tz = Math.abs( tangents[ 0 ].z ); 31891 31892 if ( tx <= min ) { 31893 31894 min = tx; 31895 normal.set( 1, 0, 0 ); 31896 31897 } 31898 31899 if ( ty <= min ) { 31900 31901 min = ty; 31902 normal.set( 0, 1, 0 ); 31903 31904 } 31905 31906 if ( tz <= min ) { 31907 31908 normal.set( 0, 0, 1 ); 31909 31910 } 31911 31912 vec.crossVectors( tangents[ 0 ], normal ).normalize(); 31913 31914 normals[ 0 ].crossVectors( tangents[ 0 ], vec ); 31915 binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ); 31916 31917 31918 // compute the slowly-varying normal and binormal vectors for each segment on the curve 31919 31920 for ( let i = 1; i <= segments; i ++ ) { 31921 31922 normals[ i ] = normals[ i - 1 ].clone(); 31923 31924 binormals[ i ] = binormals[ i - 1 ].clone(); 31925 31926 vec.crossVectors( tangents[ i - 1 ], tangents[ i ] ); 31927 31928 if ( vec.length() > Number.EPSILON ) { 31929 31930 vec.normalize(); 31931 31932 const theta = Math.acos( clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors 31933 31934 normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) ); 31935 31936 } 31937 31938 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); 31939 31940 } 31941 31942 // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same 31943 31944 if ( closed === true ) { 31945 31946 let theta = Math.acos( clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) ); 31947 theta /= segments; 31948 31949 if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) { 31950 31951 theta = - theta; 31952 31953 } 31954 31955 for ( let i = 1; i <= segments; i ++ ) { 31956 31957 // twist a little... 31958 normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) ); 31959 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); 31960 31961 } 31962 31963 } 31964 31965 return { 31966 tangents: tangents, 31967 normals: normals, 31968 binormals: binormals 31969 }; 31970 31971 } 31972 31973 clone() { 31974 31975 return new this.constructor().copy( this ); 31976 31977 } 31978 31979 copy( source ) { 31980 31981 this.arcLengthDivisions = source.arcLengthDivisions; 31982 31983 return this; 31984 31985 } 31986 31987 toJSON() { 31988 31989 const data = { 31990 metadata: { 31991 version: 4.5, 31992 type: 'Curve', 31993 generator: 'Curve.toJSON' 31994 } 31995 }; 31996 31997 data.arcLengthDivisions = this.arcLengthDivisions; 31998 data.type = this.type; 31999 32000 return data; 32001 32002 } 32003 32004 fromJSON( json ) { 32005 32006 this.arcLengthDivisions = json.arcLengthDivisions; 32007 32008 return this; 32009 32010 } 32011 32012} 32013 32014class EllipseCurve extends Curve { 32015 32016 constructor( aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0 ) { 32017 32018 super(); 32019 32020 this.isEllipseCurve = true; 32021 32022 this.type = 'EllipseCurve'; 32023 32024 this.aX = aX; 32025 this.aY = aY; 32026 32027 this.xRadius = xRadius; 32028 this.yRadius = yRadius; 32029 32030 this.aStartAngle = aStartAngle; 32031 this.aEndAngle = aEndAngle; 32032 32033 this.aClockwise = aClockwise; 32034 32035 this.aRotation = aRotation; 32036 32037 } 32038 32039 getPoint( t, optionalTarget ) { 32040 32041 const point = optionalTarget || new Vector2(); 32042 32043 const twoPi = Math.PI * 2; 32044 let deltaAngle = this.aEndAngle - this.aStartAngle; 32045 const samePoints = Math.abs( deltaAngle ) < Number.EPSILON; 32046 32047 // ensures that deltaAngle is 0 .. 2 PI 32048 while ( deltaAngle < 0 ) deltaAngle += twoPi; 32049 while ( deltaAngle > twoPi ) deltaAngle -= twoPi; 32050 32051 if ( deltaAngle < Number.EPSILON ) { 32052 32053 if ( samePoints ) { 32054 32055 deltaAngle = 0; 32056 32057 } else { 32058 32059 deltaAngle = twoPi; 32060 32061 } 32062 32063 } 32064 32065 if ( this.aClockwise === true && ! samePoints ) { 32066 32067 if ( deltaAngle === twoPi ) { 32068 32069 deltaAngle = - twoPi; 32070 32071 } else { 32072 32073 deltaAngle = deltaAngle - twoPi; 32074 32075 } 32076 32077 } 32078 32079 const angle = this.aStartAngle + t * deltaAngle; 32080 let x = this.aX + this.xRadius * Math.cos( angle ); 32081 let y = this.aY + this.yRadius * Math.sin( angle ); 32082 32083 if ( this.aRotation !== 0 ) { 32084 32085 const cos = Math.cos( this.aRotation ); 32086 const sin = Math.sin( this.aRotation ); 32087 32088 const tx = x - this.aX; 32089 const ty = y - this.aY; 32090 32091 // Rotate the point about the center of the ellipse. 32092 x = tx * cos - ty * sin + this.aX; 32093 y = tx * sin + ty * cos + this.aY; 32094 32095 } 32096 32097 return point.set( x, y ); 32098 32099 } 32100 32101 copy( source ) { 32102 32103 super.copy( source ); 32104 32105 this.aX = source.aX; 32106 this.aY = source.aY; 32107 32108 this.xRadius = source.xRadius; 32109 this.yRadius = source.yRadius; 32110
vendor: 29,506 bytes, lines 32111-33786
32111 this.aStartAngle = source.aStartAngle; 32112 this.aEndAngle = source.aEndAngle; 32113 32114 this.aClockwise = source.aClockwise; 32115 32116 this.aRotation = source.aRotation; 32117 32118 return this; 32119 32120 } 32121 32122 toJSON() { 32123 32124 const data = super.toJSON(); 32125 32126 data.aX = this.aX; 32127 data.aY = this.aY; 32128 32129 data.xRadius = this.xRadius; 32130 data.yRadius = this.yRadius; 32131 32132 data.aStartAngle = this.aStartAngle; 32133 data.aEndAngle = this.aEndAngle; 32134 32135 data.aClockwise = this.aClockwise; 32136 32137 data.aRotation = this.aRotation; 32138 32139 return data; 32140 32141 } 32142 32143 fromJSON( json ) { 32144 32145 super.fromJSON( json ); 32146 32147 this.aX = json.aX; 32148 this.aY = json.aY; 32149 32150 this.xRadius = json.xRadius; 32151 this.yRadius = json.yRadius; 32152 32153 this.aStartAngle = json.aStartAngle; 32154 this.aEndAngle = json.aEndAngle; 32155 32156 this.aClockwise = json.aClockwise; 32157 32158 this.aRotation = json.aRotation; 32159 32160 return this; 32161 32162 } 32163 32164} 32165 32166class ArcCurve extends EllipseCurve { 32167 32168 constructor( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 32169 32170 super( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); 32171 32172 this.isArcCurve = true; 32173 32174 this.type = 'ArcCurve'; 32175 32176 } 32177 32178} 32179 32180/** 32181 * Centripetal CatmullRom Curve - which is useful for avoiding 32182 * cusps and self-intersections in non-uniform catmull rom curves. 32183 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf 32184 * 32185 * curve.type accepts centripetal(default), chordal and catmullrom 32186 * curve.tension is used for catmullrom which defaults to 0.5 32187 */ 32188 32189 32190/* 32191Based on an optimized c++ solution in 32192 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/ 32193 - http://ideone.com/NoEbVM 32194 32195This CubicPoly class could be used for reusing some variables and calculations, 32196but for three.js curve use, it could be possible inlined and flatten into a single function call 32197which can be placed in CurveUtils. 32198*/ 32199 32200function CubicPoly() { 32201 32202 let c0 = 0, c1 = 0, c2 = 0, c3 = 0; 32203 32204 /* 32205 * Compute coefficients for a cubic polynomial 32206 * p(s) = c0 + c1*s + c2*s^2 + c3*s^3 32207 * such that 32208 * p(0) = x0, p(1) = x1 32209 * and 32210 * p'(0) = t0, p'(1) = t1. 32211 */ 32212 function init( x0, x1, t0, t1 ) { 32213 32214 c0 = x0; 32215 c1 = t0; 32216 c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1; 32217 c3 = 2 * x0 - 2 * x1 + t0 + t1; 32218 32219 } 32220 32221 return { 32222 32223 initCatmullRom: function ( x0, x1, x2, x3, tension ) { 32224 32225 init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) ); 32226 32227 }, 32228 32229 initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) { 32230 32231 // compute tangents when parameterized in [t1,t2] 32232 let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1; 32233 let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2; 32234 32235 // rescale tangents for parametrization in [0,1] 32236 t1 *= dt1; 32237 t2 *= dt1; 32238 32239 init( x1, x2, t1, t2 ); 32240 32241 }, 32242 32243 calc: function ( t ) { 32244 32245 const t2 = t * t; 32246 const t3 = t2 * t; 32247 return c0 + c1 * t + c2 * t2 + c3 * t3; 32248 32249 } 32250 32251 }; 32252 32253} 32254 32255// 32256 32257const tmp = /*@__PURE__*/ new Vector3(); 32258const px = /*@__PURE__*/ new CubicPoly(); 32259const py = /*@__PURE__*/ new CubicPoly(); 32260const pz = /*@__PURE__*/ new CubicPoly(); 32261 32262class CatmullRomCurve3 extends Curve { 32263 32264 constructor( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) { 32265 32266 super(); 32267 32268 this.isCatmullRomCurve3 = true; 32269 32270 this.type = 'CatmullRomCurve3'; 32271 32272 this.points = points; 32273 this.closed = closed; 32274 this.curveType = curveType; 32275 this.tension = tension; 32276 32277 } 32278 32279 getPoint( t, optionalTarget = new Vector3() ) { 32280 32281 const point = optionalTarget; 32282 32283 const points = this.points; 32284 const l = points.length; 32285 32286 const p = ( l - ( this.closed ? 0 : 1 ) ) * t; 32287 let intPoint = Math.floor( p ); 32288 let weight = p - intPoint; 32289 32290 if ( this.closed ) { 32291 32292 intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l; 32293 32294 } else if ( weight === 0 && intPoint === l - 1 ) { 32295 32296 intPoint = l - 2; 32297 weight = 1; 32298 32299 } 32300 32301 let p0, p3; // 4 points (p1 & p2 defined below) 32302 32303 if ( this.closed || intPoint > 0 ) { 32304 32305 p0 = points[ ( intPoint - 1 ) % l ]; 32306 32307 } else { 32308 32309 // extrapolate first point 32310 tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] ); 32311 p0 = tmp; 32312 32313 } 32314 32315 const p1 = points[ intPoint % l ]; 32316 const p2 = points[ ( intPoint + 1 ) % l ]; 32317 32318 if ( this.closed || intPoint + 2 < l ) { 32319 32320 p3 = points[ ( intPoint + 2 ) % l ]; 32321 32322 } else { 32323 32324 // extrapolate last point 32325 tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] ); 32326 p3 = tmp; 32327 32328 } 32329 32330 if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) { 32331 32332 // init Centripetal / Chordal Catmull-Rom 32333 const pow = this.curveType === 'chordal' ? 0.5 : 0.25; 32334 let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow ); 32335 let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow ); 32336 let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow ); 32337 32338 // safety check for repeated points 32339 if ( dt1 < 1e-4 ) dt1 = 1.0; 32340 if ( dt0 < 1e-4 ) dt0 = dt1; 32341 if ( dt2 < 1e-4 ) dt2 = dt1; 32342 32343 px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 ); 32344 py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 ); 32345 pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 ); 32346 32347 } else if ( this.curveType === 'catmullrom' ) { 32348 32349 px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension ); 32350 py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension ); 32351 pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension ); 32352 32353 } 32354 32355 point.set( 32356 px.calc( weight ), 32357 py.calc( weight ), 32358 pz.calc( weight ) 32359 ); 32360 32361 return point; 32362 32363 } 32364 32365 copy( source ) { 32366 32367 super.copy( source ); 32368 32369 this.points = []; 32370 32371 for ( let i = 0, l = source.points.length; i < l; i ++ ) { 32372 32373 const point = source.points[ i ]; 32374 32375 this.points.push( point.clone() ); 32376 32377 } 32378 32379 this.closed = source.closed; 32380 this.curveType = source.curveType; 32381 this.tension = source.tension; 32382 32383 return this; 32384 32385 } 32386 32387 toJSON() { 32388 32389 const data = super.toJSON(); 32390 32391 data.points = []; 32392 32393 for ( let i = 0, l = this.points.length; i < l; i ++ ) { 32394 32395 const point = this.points[ i ]; 32396 data.points.push( point.toArray() ); 32397 32398 } 32399 32400 data.closed = this.closed; 32401 data.curveType = this.curveType; 32402 data.tension = this.tension; 32403 32404 return data; 32405 32406 } 32407 32408 fromJSON( json ) { 32409 32410 super.fromJSON( json ); 32411 32412 this.points = []; 32413 32414 for ( let i = 0, l = json.points.length; i < l; i ++ ) { 32415 32416 const point = json.points[ i ]; 32417 this.points.push( new Vector3().fromArray( point ) ); 32418 32419 } 32420 32421 this.closed = json.closed; 32422 this.curveType = json.curveType; 32423 this.tension = json.tension; 32424 32425 return this; 32426 32427 } 32428 32429} 32430 32431/** 32432 * Bezier Curves formulas obtained from 32433 * https://en.wikipedia.org/wiki/B%C3%A9zier_curve 32434 */ 32435 32436function CatmullRom( t, p0, p1, p2, p3 ) { 32437 32438 const v0 = ( p2 - p0 ) * 0.5; 32439 const v1 = ( p3 - p1 ) * 0.5; 32440 const t2 = t * t; 32441 const t3 = t * t2; 32442 return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1; 32443 32444} 32445 32446// 32447 32448function QuadraticBezierP0( t, p ) { 32449 32450 const k = 1 - t; 32451 return k * k * p; 32452 32453} 32454 32455function QuadraticBezierP1( t, p ) { 32456 32457 return 2 * ( 1 - t ) * t * p; 32458 32459} 32460 32461function QuadraticBezierP2( t, p ) { 32462 32463 return t * t * p; 32464 32465} 32466 32467function QuadraticBezier( t, p0, p1, p2 ) { 32468 32469 return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) + 32470 QuadraticBezierP2( t, p2 ); 32471 32472} 32473 32474// 32475 32476function CubicBezierP0( t, p ) { 32477 32478 const k = 1 - t; 32479 return k * k * k * p; 32480 32481} 32482 32483function CubicBezierP1( t, p ) { 32484 32485 const k = 1 - t; 32486 return 3 * k * k * t * p; 32487 32488} 32489 32490function CubicBezierP2( t, p ) { 32491 32492 return 3 * ( 1 - t ) * t * t * p; 32493 32494} 32495 32496function CubicBezierP3( t, p ) { 32497 32498 return t * t * t * p; 32499 32500} 32501 32502function CubicBezier( t, p0, p1, p2, p3 ) { 32503 32504 return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) + 32505 CubicBezierP3( t, p3 ); 32506 32507} 32508 32509class CubicBezierCurve extends Curve { 32510 32511 constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) { 32512 32513 super(); 32514 32515 this.isCubicBezierCurve = true; 32516 32517 this.type = 'CubicBezierCurve'; 32518 32519 this.v0 = v0; 32520 this.v1 = v1; 32521 this.v2 = v2; 32522 this.v3 = v3; 32523 32524 } 32525 32526 getPoint( t, optionalTarget = new Vector2() ) { 32527 32528 const point = optionalTarget; 32529 32530 const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; 32531 32532 point.set( 32533 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), 32534 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ) 32535 ); 32536 32537 return point; 32538 32539 } 32540 32541 copy( source ) { 32542 32543 super.copy( source ); 32544 32545 this.v0.copy( source.v0 ); 32546 this.v1.copy( source.v1 ); 32547 this.v2.copy( source.v2 ); 32548 this.v3.copy( source.v3 ); 32549 32550 return this; 32551 32552 } 32553 32554 toJSON() { 32555 32556 const data = super.toJSON(); 32557 32558 data.v0 = this.v0.toArray(); 32559 data.v1 = this.v1.toArray(); 32560 data.v2 = this.v2.toArray(); 32561 data.v3 = this.v3.toArray(); 32562 32563 return data; 32564 32565 } 32566 32567 fromJSON( json ) { 32568 32569 super.fromJSON( json ); 32570 32571 this.v0.fromArray( json.v0 ); 32572 this.v1.fromArray( json.v1 ); 32573 this.v2.fromArray( json.v2 ); 32574 this.v3.fromArray( json.v3 ); 32575 32576 return this; 32577 32578 } 32579 32580} 32581 32582class CubicBezierCurve3 extends Curve { 32583 32584 constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) { 32585 32586 super(); 32587 32588 this.isCubicBezierCurve3 = true; 32589 32590 this.type = 'CubicBezierCurve3'; 32591 32592 this.v0 = v0; 32593 this.v1 = v1; 32594 this.v2 = v2; 32595 this.v3 = v3; 32596 32597 } 32598 32599 getPoint( t, optionalTarget = new Vector3() ) { 32600 32601 const point = optionalTarget; 32602 32603 const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; 32604 32605 point.set( 32606 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), 32607 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ), 32608 CubicBezier( t, v0.z, v1.z, v2.z, v3.z ) 32609 ); 32610 32611 return point; 32612 32613 } 32614 32615 copy( source ) { 32616 32617 super.copy( source ); 32618 32619 this.v0.copy( source.v0 ); 32620 this.v1.copy( source.v1 ); 32621 this.v2.copy( source.v2 ); 32622 this.v3.copy( source.v3 ); 32623 32624 return this; 32625 32626 } 32627 32628 toJSON() { 32629 32630 const data = super.toJSON(); 32631 32632 data.v0 = this.v0.toArray(); 32633 data.v1 = this.v1.toArray(); 32634 data.v2 = this.v2.toArray(); 32635 data.v3 = this.v3.toArray(); 32636 32637 return data; 32638 32639 } 32640 32641 fromJSON( json ) { 32642 32643 super.fromJSON( json ); 32644 32645 this.v0.fromArray( json.v0 ); 32646 this.v1.fromArray( json.v1 ); 32647 this.v2.fromArray( json.v2 ); 32648 this.v3.fromArray( json.v3 ); 32649 32650 return this; 32651 32652 } 32653 32654} 32655 32656class LineCurve extends Curve { 32657 32658 constructor( v1 = new Vector2(), v2 = new Vector2() ) { 32659 32660 super(); 32661 32662 this.isLineCurve = true; 32663 32664 this.type = 'LineCurve'; 32665 32666 this.v1 = v1; 32667 this.v2 = v2; 32668 32669 } 32670 32671 getPoint( t, optionalTarget = new Vector2() ) { 32672 32673 const point = optionalTarget; 32674 32675 if ( t === 1 ) { 32676 32677 point.copy( this.v2 ); 32678 32679 } else { 32680 32681 point.copy( this.v2 ).sub( this.v1 ); 32682 point.multiplyScalar( t ).add( this.v1 ); 32683 32684 } 32685 32686 return point; 32687 32688 } 32689 32690 // Line curve is linear, so we can overwrite default getPointAt 32691 getPointAt( u, optionalTarget ) { 32692 32693 return this.getPoint( u, optionalTarget ); 32694 32695 } 32696 32697 getTangent( t, optionalTarget = new Vector2() ) { 32698 32699 return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); 32700 32701 } 32702 32703 getTangentAt( u, optionalTarget ) { 32704 32705 return this.getTangent( u, optionalTarget ); 32706 32707 } 32708 32709 copy( source ) { 32710 32711 super.copy( source ); 32712 32713 this.v1.copy( source.v1 ); 32714 this.v2.copy( source.v2 ); 32715 32716 return this; 32717 32718 } 32719 32720 toJSON() { 32721 32722 const data = super.toJSON(); 32723 32724 data.v1 = this.v1.toArray(); 32725 data.v2 = this.v2.toArray(); 32726 32727 return data; 32728 32729 } 32730 32731 fromJSON( json ) { 32732 32733 super.fromJSON( json ); 32734 32735 this.v1.fromArray( json.v1 ); 32736 this.v2.fromArray( json.v2 ); 32737 32738 return this; 32739 32740 } 32741 32742} 32743 32744class LineCurve3 extends Curve { 32745 32746 constructor( v1 = new Vector3(), v2 = new Vector3() ) { 32747 32748 super(); 32749 32750 this.isLineCurve3 = true; 32751 32752 this.type = 'LineCurve3'; 32753 32754 this.v1 = v1; 32755 this.v2 = v2; 32756 32757 } 32758 getPoint( t, optionalTarget = new Vector3() ) { 32759 32760 const point = optionalTarget; 32761 32762 if ( t === 1 ) { 32763 32764 point.copy( this.v2 ); 32765 32766 } else { 32767 32768 point.copy( this.v2 ).sub( this.v1 ); 32769 point.multiplyScalar( t ).add( this.v1 ); 32770 32771 } 32772 32773 return point; 32774 32775 } 32776 // Line curve is linear, so we can overwrite default getPointAt 32777 getPointAt( u, optionalTarget ) { 32778 32779 return this.getPoint( u, optionalTarget ); 32780 32781 } 32782 32783 getTangent( t, optionalTarget = new Vector3() ) { 32784 32785 return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); 32786 32787 } 32788 32789 getTangentAt( u, optionalTarget ) { 32790 32791 return this.getTangent( u, optionalTarget ); 32792 32793 } 32794 32795 copy( source ) { 32796 32797 super.copy( source ); 32798 32799 this.v1.copy( source.v1 ); 32800 this.v2.copy( source.v2 ); 32801 32802 return this; 32803 32804 } 32805 toJSON() { 32806 32807 const data = super.toJSON(); 32808 32809 data.v1 = this.v1.toArray(); 32810 data.v2 = this.v2.toArray(); 32811 32812 return data; 32813 32814 } 32815 fromJSON( json ) { 32816 32817 super.fromJSON( json ); 32818 32819 this.v1.fromArray( json.v1 ); 32820 this.v2.fromArray( json.v2 ); 32821 32822 return this; 32823 32824 } 32825 32826} 32827 32828class QuadraticBezierCurve extends Curve { 32829 32830 constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) { 32831 32832 super(); 32833 32834 this.isQuadraticBezierCurve = true; 32835 32836 this.type = 'QuadraticBezierCurve'; 32837 32838 this.v0 = v0; 32839 this.v1 = v1; 32840 this.v2 = v2; 32841 32842 } 32843 32844 getPoint( t, optionalTarget = new Vector2() ) { 32845 32846 const point = optionalTarget; 32847 32848 const v0 = this.v0, v1 = this.v1, v2 = this.v2; 32849 32850 point.set( 32851 QuadraticBezier( t, v0.x, v1.x, v2.x ), 32852 QuadraticBezier( t, v0.y, v1.y, v2.y ) 32853 ); 32854 32855 return point; 32856 32857 } 32858 32859 copy( source ) { 32860 32861 super.copy( source ); 32862 32863 this.v0.copy( source.v0 ); 32864 this.v1.copy( source.v1 ); 32865 this.v2.copy( source.v2 ); 32866 32867 return this; 32868 32869 } 32870 32871 toJSON() { 32872 32873 const data = super.toJSON(); 32874 32875 data.v0 = this.v0.toArray(); 32876 data.v1 = this.v1.toArray(); 32877 data.v2 = this.v2.toArray(); 32878 32879 return data; 32880 32881 } 32882 32883 fromJSON( json ) { 32884 32885 super.fromJSON( json ); 32886 32887 this.v0.fromArray( json.v0 ); 32888 this.v1.fromArray( json.v1 ); 32889 this.v2.fromArray( json.v2 ); 32890 32891 return this; 32892 32893 } 32894 32895} 32896 32897class QuadraticBezierCurve3 extends Curve { 32898 32899 constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) { 32900 32901 super(); 32902 32903 this.isQuadraticBezierCurve3 = true; 32904 32905 this.type = 'QuadraticBezierCurve3'; 32906 32907 this.v0 = v0; 32908 this.v1 = v1; 32909 this.v2 = v2; 32910 32911 } 32912 32913 getPoint( t, optionalTarget = new Vector3() ) { 32914 32915 const point = optionalTarget; 32916 32917 const v0 = this.v0, v1 = this.v1, v2 = this.v2; 32918 32919 point.set( 32920 QuadraticBezier( t, v0.x, v1.x, v2.x ), 32921 QuadraticBezier( t, v0.y, v1.y, v2.y ), 32922 QuadraticBezier( t, v0.z, v1.z, v2.z ) 32923 ); 32924 32925 return point; 32926 32927 } 32928 32929 copy( source ) { 32930 32931 super.copy( source ); 32932 32933 this.v0.copy( source.v0 ); 32934 this.v1.copy( source.v1 ); 32935 this.v2.copy( source.v2 ); 32936 32937 return this; 32938 32939 } 32940 32941 toJSON() { 32942 32943 const data = super.toJSON(); 32944 32945 data.v0 = this.v0.toArray(); 32946 data.v1 = this.v1.toArray(); 32947 data.v2 = this.v2.toArray(); 32948 32949 return data; 32950 32951 } 32952 32953 fromJSON( json ) { 32954 32955 super.fromJSON( json ); 32956 32957 this.v0.fromArray( json.v0 ); 32958 this.v1.fromArray( json.v1 ); 32959 this.v2.fromArray( json.v2 ); 32960 32961 return this; 32962 32963 } 32964 32965} 32966 32967class SplineCurve extends Curve { 32968 32969 constructor( points = [] ) { 32970 32971 super(); 32972 32973 this.isSplineCurve = true; 32974 32975 this.type = 'SplineCurve'; 32976 32977 this.points = points; 32978 32979 } 32980 32981 getPoint( t, optionalTarget = new Vector2() ) { 32982 32983 const point = optionalTarget; 32984 32985 const points = this.points; 32986 const p = ( points.length - 1 ) * t; 32987 32988 const intPoint = Math.floor( p ); 32989 const weight = p - intPoint; 32990 32991 const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ]; 32992 const p1 = points[ intPoint ]; 32993 const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ]; 32994 const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ]; 32995 32996 point.set( 32997 CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ), 32998 CatmullRom( weight, p0.y, p1.y, p2.y, p3.y ) 32999 ); 33000 33001 return point; 33002 33003 } 33004 33005 copy( source ) { 33006 33007 super.copy( source ); 33008 33009 this.points = []; 33010 33011 for ( let i = 0, l = source.points.length; i < l; i ++ ) { 33012 33013 const point = source.points[ i ]; 33014 33015 this.points.push( point.clone() ); 33016 33017 } 33018 33019 return this; 33020 33021 } 33022 33023 toJSON() { 33024 33025 const data = super.toJSON(); 33026 33027 data.points = []; 33028 33029 for ( let i = 0, l = this.points.length; i < l; i ++ ) { 33030 33031 const point = this.points[ i ]; 33032 data.points.push( point.toArray() ); 33033 33034 } 33035 33036 return data; 33037 33038 } 33039 33040 fromJSON( json ) { 33041 33042 super.fromJSON( json ); 33043 33044 this.points = []; 33045 33046 for ( let i = 0, l = json.points.length; i < l; i ++ ) { 33047 33048 const point = json.points[ i ]; 33049 this.points.push( new Vector2().fromArray( point ) ); 33050 33051 } 33052 33053 return this; 33054 33055 } 33056 33057} 33058 33059var Curves = /*#__PURE__*/Object.freeze({ 33060 __proto__: null, 33061 ArcCurve: ArcCurve, 33062 CatmullRomCurve3: CatmullRomCurve3, 33063 CubicBezierCurve: CubicBezierCurve, 33064 CubicBezierCurve3: CubicBezierCurve3, 33065 EllipseCurve: EllipseCurve, 33066 LineCurve: LineCurve, 33067 LineCurve3: LineCurve3, 33068 QuadraticBezierCurve: QuadraticBezierCurve, 33069 QuadraticBezierCurve3: QuadraticBezierCurve3, 33070 SplineCurve: SplineCurve 33071}); 33072 33073/************************************************************** 33074 * Curved Path - a curve path is simply a array of connected 33075 * curves, but retains the api of a curve 33076 **************************************************************/ 33077 33078class CurvePath extends Curve { 33079 33080 constructor() { 33081 33082 super(); 33083 33084 this.type = 'CurvePath'; 33085 33086 this.curves = []; 33087 this.autoClose = false; // Automatically closes the path 33088 33089 } 33090 33091 add( curve ) { 33092 33093 this.curves.push( curve ); 33094 33095 } 33096 33097 closePath() { 33098 33099 // Add a line curve if start and end of lines are not connected 33100 const startPoint = this.curves[ 0 ].getPoint( 0 ); 33101 const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 ); 33102 33103 if ( ! startPoint.equals( endPoint ) ) { 33104 33105 this.curves.push( new LineCurve( endPoint, startPoint ) ); 33106 33107 } 33108 33109 } 33110 33111 // To get accurate point with reference to 33112 // entire path distance at time t, 33113 // following has to be done: 33114 33115 // 1. Length of each sub path have to be known 33116 // 2. Locate and identify type of curve 33117 // 3. Get t for the curve 33118 // 4. Return curve.getPointAt(t') 33119 33120 getPoint( t, optionalTarget ) { 33121 33122 const d = t * this.getLength(); 33123 const curveLengths = this.getCurveLengths(); 33124 let i = 0; 33125 33126 // To think about boundaries points. 33127 33128 while ( i < curveLengths.length ) { 33129 33130 if ( curveLengths[ i ] >= d ) { 33131 33132 const diff = curveLengths[ i ] - d; 33133 const curve = this.curves[ i ]; 33134 33135 const segmentLength = curve.getLength(); 33136 const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength; 33137 33138 return curve.getPointAt( u, optionalTarget ); 33139 33140 } 33141 33142 i ++; 33143 33144 } 33145 33146 return null; 33147 33148 // loop where sum != 0, sum > d , sum+1 <d 33149 33150 } 33151 33152 // We cannot use the default THREE.Curve getPoint() with getLength() because in 33153 // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath 33154 // getPoint() depends on getLength 33155 33156 getLength() { 33157 33158 const lens = this.getCurveLengths(); 33159 return lens[ lens.length - 1 ]; 33160 33161 } 33162 33163 // cacheLengths must be recalculated. 33164 updateArcLengths() { 33165 33166 this.needsUpdate = true; 33167 this.cacheLengths = null; 33168 this.getCurveLengths(); 33169 33170 } 33171 33172 // Compute lengths and cache them 33173 // We cannot overwrite getLengths() because UtoT mapping uses it. 33174 33175 getCurveLengths() { 33176 33177 // We use cache values if curves and cache array are same length 33178 33179 if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) { 33180 33181 return this.cacheLengths; 33182 33183 } 33184 33185 // Get length of sub-curve 33186 // Push sums into cached array 33187 33188 const lengths = []; 33189 let sums = 0; 33190 33191 for ( let i = 0, l = this.curves.length; i < l; i ++ ) { 33192 33193 sums += this.curves[ i ].getLength(); 33194 lengths.push( sums ); 33195 33196 } 33197 33198 this.cacheLengths = lengths; 33199 33200 return lengths; 33201 33202 } 33203 33204 getSpacedPoints( divisions = 40 ) { 33205 33206 const points = []; 33207 33208 for ( let i = 0; i <= divisions; i ++ ) { 33209 33210 points.push( this.getPoint( i / divisions ) ); 33211 33212 } 33213 33214 if ( this.autoClose ) { 33215 33216 points.push( points[ 0 ] ); 33217 33218 } 33219 33220 return points; 33221 33222 } 33223 33224 getPoints( divisions = 12 ) { 33225 33226 const points = []; 33227 let last; 33228 33229 for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) { 33230 33231 const curve = curves[ i ]; 33232 const resolution = curve.isEllipseCurve ? divisions * 2 33233 : ( curve.isLineCurve || curve.isLineCurve3 ) ? 1 33234 : curve.isSplineCurve ? divisions * curve.points.length 33235 : divisions; 33236 33237 const pts = curve.getPoints( resolution ); 33238 33239 for ( let j = 0; j < pts.length; j ++ ) { 33240 33241 const point = pts[ j ]; 33242 33243 if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates 33244 33245 points.push( point ); 33246 last = point; 33247 33248 } 33249 33250 } 33251 33252 if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) { 33253 33254 points.push( points[ 0 ] ); 33255 33256 } 33257 33258 return points; 33259 33260 } 33261 33262 copy( source ) { 33263 33264 super.copy( source ); 33265 33266 this.curves = []; 33267 33268 for ( let i = 0, l = source.curves.length; i < l; i ++ ) { 33269 33270 const curve = source.curves[ i ]; 33271 33272 this.curves.push( curve.clone() ); 33273 33274 } 33275 33276 this.autoClose = source.autoClose; 33277 33278 return this; 33279 33280 } 33281 33282 toJSON() { 33283 33284 const data = super.toJSON(); 33285 33286 data.autoClose = this.autoClose; 33287 data.curves = []; 33288 33289 for ( let i = 0, l = this.curves.length; i < l; i ++ ) { 33290 33291 const curve = this.curves[ i ]; 33292 data.curves.push( curve.toJSON() ); 33293 33294 } 33295 33296 return data; 33297 33298 } 33299 33300 fromJSON( json ) { 33301 33302 super.fromJSON( json ); 33303 33304 this.autoClose = json.autoClose; 33305 this.curves = []; 33306 33307 for ( let i = 0, l = json.curves.length; i < l; i ++ ) { 33308 33309 const curve = json.curves[ i ]; 33310 this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) ); 33311 33312 } 33313 33314 return this; 33315 33316 } 33317 33318} 33319 33320class Path extends CurvePath { 33321 33322 constructor( points ) { 33323 33324 super(); 33325 33326 this.type = 'Path'; 33327 33328 this.currentPoint = new Vector2(); 33329 33330 if ( points ) { 33331 33332 this.setFromPoints( points ); 33333 33334 } 33335 33336 } 33337 33338 setFromPoints( points ) { 33339 33340 this.moveTo( points[ 0 ].x, points[ 0 ].y ); 33341 33342 for ( let i = 1, l = points.length; i < l; i ++ ) { 33343 33344 this.lineTo( points[ i ].x, points[ i ].y ); 33345 33346 } 33347 33348 return this; 33349 33350 } 33351 33352 moveTo( x, y ) { 33353 33354 this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying? 33355 33356 return this; 33357 33358 } 33359 33360 lineTo( x, y ) { 33361 33362 const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) ); 33363 this.curves.push( curve ); 33364 33365 this.currentPoint.set( x, y ); 33366 33367 return this; 33368 33369 } 33370 33371 quadraticCurveTo( aCPx, aCPy, aX, aY ) { 33372 33373 const curve = new QuadraticBezierCurve( 33374 this.currentPoint.clone(), 33375 new Vector2( aCPx, aCPy ), 33376 new Vector2( aX, aY ) 33377 ); 33378 33379 this.curves.push( curve ); 33380 33381 this.currentPoint.set( aX, aY ); 33382 33383 return this; 33384 33385 } 33386 33387 bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { 33388 33389 const curve = new CubicBezierCurve( 33390 this.currentPoint.clone(), 33391 new Vector2( aCP1x, aCP1y ), 33392 new Vector2( aCP2x, aCP2y ), 33393 new Vector2( aX, aY ) 33394 ); 33395 33396 this.curves.push( curve ); 33397 33398 this.currentPoint.set( aX, aY ); 33399 33400 return this; 33401 33402 } 33403 33404 splineThru( pts /*Array of Vector*/ ) { 33405 33406 const npts = [ this.currentPoint.clone() ].concat( pts ); 33407 33408 const curve = new SplineCurve( npts ); 33409 this.curves.push( curve ); 33410 33411 this.currentPoint.copy( pts[ pts.length - 1 ] ); 33412 33413 return this; 33414 33415 } 33416 33417 arc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 33418 33419 const x0 = this.currentPoint.x; 33420 const y0 = this.currentPoint.y; 33421 33422 this.absarc( aX + x0, aY + y0, aRadius, 33423 aStartAngle, aEndAngle, aClockwise ); 33424 33425 return this; 33426 33427 } 33428 33429 absarc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 33430 33431 this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); 33432 33433 return this; 33434 33435 } 33436 33437 ellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { 33438 33439 const x0 = this.currentPoint.x; 33440 const y0 = this.currentPoint.y; 33441 33442 this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); 33443 33444 return this; 33445 33446 } 33447 33448 absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { 33449 33450 const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); 33451 33452 if ( this.curves.length > 0 ) { 33453 33454 // if a previous curve is present, attempt to join 33455 const firstPoint = curve.getPoint( 0 ); 33456 33457 if ( ! firstPoint.equals( this.currentPoint ) ) { 33458 33459 this.lineTo( firstPoint.x, firstPoint.y ); 33460 33461 } 33462 33463 } 33464 33465 this.curves.push( curve ); 33466 33467 const lastPoint = curve.getPoint( 1 ); 33468 this.currentPoint.copy( lastPoint ); 33469 33470 return this; 33471 33472 } 33473 33474 copy( source ) { 33475 33476 super.copy( source ); 33477 33478 this.currentPoint.copy( source.currentPoint ); 33479 33480 return this; 33481 33482 } 33483 33484 toJSON() { 33485 33486 const data = super.toJSON(); 33487 33488 data.currentPoint = this.currentPoint.toArray(); 33489 33490 return data; 33491 33492 } 33493 33494 fromJSON( json ) { 33495 33496 super.fromJSON( json ); 33497 33498 this.currentPoint.fromArray( json.currentPoint ); 33499 33500 return this; 33501 33502 } 33503 33504} 33505 33506class LatheGeometry extends BufferGeometry { 33507 33508 constructor( points = [ new Vector2( 0, - 0.5 ), new Vector2( 0.5, 0 ), new Vector2( 0, 0.5 ) ], segments = 12, phiStart = 0, phiLength = Math.PI * 2 ) { 33509 33510 super(); 33511 33512 this.type = 'LatheGeometry'; 33513 33514 this.parameters = { 33515 points: points, 33516 segments: segments, 33517 phiStart: phiStart, 33518 phiLength: phiLength 33519 }; 33520 33521 segments = Math.floor( segments ); 33522 33523 // clamp phiLength so it's in range of [ 0, 2PI ] 33524 33525 phiLength = clamp( phiLength, 0, Math.PI * 2 ); 33526 33527 // buffers 33528 33529 const indices = []; 33530 const vertices = []; 33531 const uvs = []; 33532 const initNormals = []; 33533 const normals = []; 33534 33535 // helper variables 33536 33537 const inverseSegments = 1.0 / segments; 33538 const vertex = new Vector3(); 33539 const uv = new Vector2(); 33540 const normal = new Vector3(); 33541 const curNormal = new Vector3(); 33542 const prevNormal = new Vector3(); 33543 let dx = 0; 33544 let dy = 0; 33545 33546 // pre-compute normals for initial "meridian" 33547 33548 for ( let j = 0; j <= ( points.length - 1 ); j ++ ) { 33549 33550 switch ( j ) { 33551 33552 case 0: // special handling for 1st vertex on path 33553 33554 dx = points[ j + 1 ].x - points[ j ].x; 33555 dy = points[ j + 1 ].y - points[ j ].y; 33556 33557 normal.x = dy * 1.0; 33558 normal.y = - dx; 33559 normal.z = dy * 0.0; 33560 33561 prevNormal.copy( normal ); 33562 33563 normal.normalize(); 33564 33565 initNormals.push( normal.x, normal.y, normal.z ); 33566 33567 break; 33568 33569 case ( points.length - 1 ): // special handling for last Vertex on path 33570 33571 initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z ); 33572 33573 break; 33574 33575 default: // default handling for all vertices in between 33576 33577 dx = points[ j + 1 ].x - points[ j ].x; 33578 dy = points[ j + 1 ].y - points[ j ].y; 33579 33580 normal.x = dy * 1.0; 33581 normal.y = - dx; 33582 normal.z = dy * 0.0; 33583 33584 curNormal.copy( normal ); 33585 33586 normal.x += prevNormal.x; 33587 normal.y += prevNormal.y; 33588 normal.z += prevNormal.z; 33589 33590 normal.normalize(); 33591 33592 initNormals.push( normal.x, normal.y, normal.z ); 33593 33594 prevNormal.copy( curNormal ); 33595 33596 } 33597 33598 } 33599 33600 // generate vertices, uvs and normals 33601 33602 for ( let i = 0; i <= segments; i ++ ) { 33603 33604 const phi = phiStart + i * inverseSegments * phiLength; 33605 33606 const sin = Math.sin( phi ); 33607 const cos = Math.cos( phi ); 33608 33609 for ( let j = 0; j <= ( points.length - 1 ); j ++ ) { 33610 33611 // vertex 33612 33613 vertex.x = points[ j ].x * sin; 33614 vertex.y = points[ j ].y; 33615 vertex.z = points[ j ].x * cos; 33616 33617 vertices.push( vertex.x, vertex.y, vertex.z ); 33618 33619 // uv 33620 33621 uv.x = i / segments; 33622 uv.y = j / ( points.length - 1 ); 33623 33624 uvs.push( uv.x, uv.y ); 33625 33626 // normal 33627 33628 const x = initNormals[ 3 * j + 0 ] * sin; 33629 const y = initNormals[ 3 * j + 1 ]; 33630 const z = initNormals[ 3 * j + 0 ] * cos; 33631 33632 normals.push( x, y, z ); 33633 33634 } 33635 33636 } 33637 33638 // indices 33639 33640 for ( let i = 0; i < segments; i ++ ) { 33641 33642 for ( let j = 0; j < ( points.length - 1 ); j ++ ) { 33643 33644 const base = j + i * points.length; 33645 33646 const a = base; 33647 const b = base + points.length; 33648 const c = base + points.length + 1; 33649 const d = base + 1; 33650 33651 // faces 33652 33653 indices.push( a, b, d ); 33654 indices.push( c, d, b ); 33655 33656 } 33657 33658 } 33659 33660 // build geometry 33661 33662 this.setIndex( indices ); 33663 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 33664 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 33665 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 33666 33667 } 33668 33669 copy( source ) { 33670 33671 super.copy( source ); 33672 33673 this.parameters = Object.assign( {}, source.parameters ); 33674 33675 return this; 33676 33677 } 33678 33679 static fromJSON( data ) { 33680 33681 return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength ); 33682 33683 } 33684 33685} 33686 33687class CapsuleGeometry extends LatheGeometry { 33688 33689 constructor( radius = 1, length = 1, capSegments = 4, radialSegments = 8 ) { 33690 33691 const path = new Path(); 33692 path.absarc( 0, - length / 2, radius, Math.PI * 1.5, 0 ); 33693 path.absarc( 0, length / 2, radius, 0, Math.PI * 0.5 ); 33694 33695 super( path.getPoints( capSegments ), radialSegments ); 33696 33697 this.type = 'CapsuleGeometry'; 33698 33699 this.parameters = { 33700 radius: radius, 33701 height: length, 33702 capSegments: capSegments, 33703 radialSegments: radialSegments, 33704 }; 33705 33706 } 33707 33708 static fromJSON( data ) { 33709 33710 return new CapsuleGeometry( data.radius, data.length, data.capSegments, data.radialSegments ); 33711 33712 } 33713 33714} 33715 33716class CircleGeometry extends BufferGeometry { 33717 33718 constructor( radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2 ) { 33719 33720 super(); 33721 33722 this.type = 'CircleGeometry'; 33723 33724 this.parameters = { 33725 radius: radius, 33726 segments: segments, 33727 thetaStart: thetaStart, 33728 thetaLength: thetaLength 33729 }; 33730 33731 segments = Math.max( 3, segments ); 33732 33733 // buffers 33734 33735 const indices = []; 33736 const vertices = []; 33737 const normals = []; 33738 const uvs = []; 33739 33740 // helper variables 33741 33742 const vertex = new Vector3(); 33743 const uv = new Vector2(); 33744 33745 // center point 33746 33747 vertices.push( 0, 0, 0 ); 33748 normals.push( 0, 0, 1 ); 33749 uvs.push( 0.5, 0.5 ); 33750 33751 for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) { 33752 33753 const segment = thetaStart + s / segments * thetaLength; 33754 33755 // vertex 33756 33757 vertex.x = radius * Math.cos( segment ); 33758 vertex.y = radius * Math.sin( segment ); 33759 33760 vertices.push( vertex.x, vertex.y, vertex.z ); 33761 33762 // normal 33763 33764 normals.push( 0, 0, 1 ); 33765 33766 // uvs 33767 33768 uv.x = ( vertices[ i ] / radius + 1 ) / 2; 33769 uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2; 33770 33771 uvs.push( uv.x, uv.y ); 33772 33773 } 33774 33775 // indices 33776 33777 for ( let i = 1; i <= segments; i ++ ) { 33778 33779 indices.push( i, i + 1, 0 ); 33780 33781 } 33782 33783 // build geometry 33784 33785 this.setIndex( indices ); 33786 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,756 bytes, lines 33787-34012
33787 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 33788 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 33789 33790 } 33791 33792 copy( source ) { 33793 33794 super.copy( source ); 33795 33796 this.parameters = Object.assign( {}, source.parameters ); 33797 33798 return this; 33799 33800 } 33801 33802 static fromJSON( data ) { 33803 33804 return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength ); 33805 33806 } 33807 33808} 33809 33810class CylinderGeometry extends BufferGeometry { 33811 33812 constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { 33813 33814 super(); 33815 33816 this.type = 'CylinderGeometry'; 33817 33818 this.parameters = { 33819 radiusTop: radiusTop, 33820 radiusBottom: radiusBottom, 33821 height: height, 33822 radialSegments: radialSegments, 33823 heightSegments: heightSegments, 33824 openEnded: openEnded, 33825 thetaStart: thetaStart, 33826 thetaLength: thetaLength 33827 }; 33828 33829 const scope = this; 33830 33831 radialSegments = Math.floor( radialSegments ); 33832 heightSegments = Math.floor( heightSegments ); 33833 33834 // buffers 33835 33836 const indices = []; 33837 const vertices = []; 33838 const normals = []; 33839 const uvs = []; 33840 33841 // helper variables 33842 33843 let index = 0; 33844 const indexArray = []; 33845 const halfHeight = height / 2; 33846 let groupStart = 0; 33847 33848 // generate geometry 33849 33850 generateTorso(); 33851 33852 if ( openEnded === false ) { 33853 33854 if ( radiusTop > 0 ) generateCap( true ); 33855 if ( radiusBottom > 0 ) generateCap( false ); 33856 33857 } 33858 33859 // build geometry 33860 33861 this.setIndex( indices ); 33862 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 33863 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 33864 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 33865 33866 function generateTorso() { 33867 33868 const normal = new Vector3(); 33869 const vertex = new Vector3(); 33870 33871 let groupCount = 0; 33872 33873 // this will be used to calculate the normal 33874 const slope = ( radiusBottom - radiusTop ) / height; 33875 33876 // generate vertices, normals and uvs 33877 33878 for ( let y = 0; y <= heightSegments; y ++ ) { 33879 33880 const indexRow = []; 33881 33882 const v = y / heightSegments; 33883 33884 // calculate the radius of the current row 33885 33886 const radius = v * ( radiusBottom - radiusTop ) + radiusTop; 33887 33888 for ( let x = 0; x <= radialSegments; x ++ ) { 33889 33890 const u = x / radialSegments; 33891 33892 const theta = u * thetaLength + thetaStart; 33893 33894 const sinTheta = Math.sin( theta ); 33895 const cosTheta = Math.cos( theta ); 33896 33897 // vertex 33898 33899 vertex.x = radius * sinTheta; 33900 vertex.y = - v * height + halfHeight; 33901 vertex.z = radius * cosTheta; 33902 vertices.push( vertex.x, vertex.y, vertex.z ); 33903 33904 // normal 33905 33906 normal.set( sinTheta, slope, cosTheta ).normalize(); 33907 normals.push( normal.x, normal.y, normal.z ); 33908 33909 // uv 33910 33911 uvs.push( u, 1 - v ); 33912 33913 // save index of vertex in respective row 33914 33915 indexRow.push( index ++ ); 33916 33917 } 33918 33919 // now save vertices of the row in our index array 33920 33921 indexArray.push( indexRow ); 33922 33923 } 33924 33925 // generate indices 33926 33927 for ( let x = 0; x < radialSegments; x ++ ) { 33928 33929 for ( let y = 0; y < heightSegments; y ++ ) { 33930 33931 // we use the index array to access the correct indices 33932 33933 const a = indexArray[ y ][ x ]; 33934 const b = indexArray[ y + 1 ][ x ]; 33935 const c = indexArray[ y + 1 ][ x + 1 ]; 33936 const d = indexArray[ y ][ x + 1 ]; 33937 33938 // faces 33939 33940 indices.push( a, b, d ); 33941 indices.push( b, c, d ); 33942 33943 // update group counter 33944 33945 groupCount += 6; 33946 33947 } 33948 33949 } 33950 33951 // add a group to the geometry. this will ensure multi material support 33952 33953 scope.addGroup( groupStart, groupCount, 0 ); 33954 33955 // calculate new start value for groups 33956 33957 groupStart += groupCount; 33958 33959 } 33960 33961 function generateCap( top ) { 33962 33963 // save the index of the first center vertex 33964 const centerIndexStart = index; 33965 33966 const uv = new Vector2(); 33967 const vertex = new Vector3(); 33968 33969 let groupCount = 0; 33970 33971 const radius = ( top === true ) ? radiusTop : radiusBottom; 33972 const sign = ( top === true ) ? 1 : - 1; 33973 33974 // first we generate the center vertex data of the cap. 33975 // because the geometry needs one set of uvs per face, 33976 // we must generate a center vertex per face/segment 33977 33978 for ( let x = 1; x <= radialSegments; x ++ ) { 33979 33980 // vertex 33981 33982 vertices.push( 0, halfHeight * sign, 0 ); 33983 33984 // normal 33985 33986 normals.push( 0, sign, 0 ); 33987 33988 // uv 33989 33990 uvs.push( 0.5, 0.5 ); 33991 33992 // increase index 33993 33994 index ++; 33995 33996 } 33997 33998 // save the index of the last center vertex 33999 const centerIndexEnd = index; 34000 34001 // now we generate the surrounding vertices, normals and uvs 34002 34003 for ( let x = 0; x <= radialSegments; x ++ ) { 34004 34005 const u = x / radialSegments; 34006 const theta = u * thetaLength + thetaStart; 34007 34008 const cosTheta = Math.cos( theta ); 34009 const sinTheta = Math.sin( theta ); 34010 34011 // vertex 34012
vendor: 16,069 bytes, lines 34013-34791
34013 vertex.x = radius * sinTheta; 34014 vertex.y = halfHeight * sign; 34015 vertex.z = radius * cosTheta; 34016 vertices.push( vertex.x, vertex.y, vertex.z ); 34017 34018 // normal 34019 34020 normals.push( 0, sign, 0 ); 34021 34022 // uv 34023 34024 uv.x = ( cosTheta * 0.5 ) + 0.5; 34025 uv.y = ( sinTheta * 0.5 * sign ) + 0.5; 34026 uvs.push( uv.x, uv.y ); 34027 34028 // increase index 34029 34030 index ++; 34031 34032 } 34033 34034 // generate indices 34035 34036 for ( let x = 0; x < radialSegments; x ++ ) { 34037 34038 const c = centerIndexStart + x; 34039 const i = centerIndexEnd + x; 34040 34041 if ( top === true ) { 34042 34043 // face top 34044 34045 indices.push( i, i + 1, c ); 34046 34047 } else { 34048 34049 // face bottom 34050 34051 indices.push( i + 1, i, c ); 34052 34053 } 34054 34055 groupCount += 3; 34056 34057 } 34058 34059 // add a group to the geometry. this will ensure multi material support 34060 34061 scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); 34062 34063 // calculate new start value for groups 34064 34065 groupStart += groupCount; 34066 34067 } 34068 34069 } 34070 34071 copy( source ) { 34072 34073 super.copy( source ); 34074 34075 this.parameters = Object.assign( {}, source.parameters ); 34076 34077 return this; 34078 34079 } 34080 34081 static fromJSON( data ) { 34082 34083 return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); 34084 34085 } 34086 34087} 34088 34089class ConeGeometry extends CylinderGeometry { 34090 34091 constructor( radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { 34092 34093 super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); 34094 34095 this.type = 'ConeGeometry'; 34096 34097 this.parameters = { 34098 radius: radius, 34099 height: height, 34100 radialSegments: radialSegments, 34101 heightSegments: heightSegments, 34102 openEnded: openEnded, 34103 thetaStart: thetaStart, 34104 thetaLength: thetaLength 34105 }; 34106 34107 } 34108 34109 static fromJSON( data ) { 34110 34111 return new ConeGeometry( data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); 34112 34113 } 34114 34115} 34116 34117class PolyhedronGeometry extends BufferGeometry { 34118 34119 constructor( vertices = [], indices = [], radius = 1, detail = 0 ) { 34120 34121 super(); 34122 34123 this.type = 'PolyhedronGeometry'; 34124 34125 this.parameters = { 34126 vertices: vertices, 34127 indices: indices, 34128 radius: radius, 34129 detail: detail 34130 }; 34131 34132 // default buffer data 34133 34134 const vertexBuffer = []; 34135 const uvBuffer = []; 34136 34137 // the subdivision creates the vertex buffer data 34138 34139 subdivide( detail ); 34140 34141 // all vertices should lie on a conceptual sphere with a given radius 34142 34143 applyRadius( radius ); 34144 34145 // finally, create the uv data 34146 34147 generateUVs(); 34148 34149 // build non-indexed geometry 34150 34151 this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) ); 34152 this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) ); 34153 this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) ); 34154 34155 if ( detail === 0 ) { 34156 34157 this.computeVertexNormals(); // flat normals 34158 34159 } else { 34160 34161 this.normalizeNormals(); // smooth normals 34162 34163 } 34164 34165 // helper functions 34166 34167 function subdivide( detail ) { 34168 34169 const a = new Vector3(); 34170 const b = new Vector3(); 34171 const c = new Vector3(); 34172 34173 // iterate over all faces and apply a subdivision with the given detail value 34174 34175 for ( let i = 0; i < indices.length; i += 3 ) { 34176 34177 // get the vertices of the face 34178 34179 getVertexByIndex( indices[ i + 0 ], a ); 34180 getVertexByIndex( indices[ i + 1 ], b ); 34181 getVertexByIndex( indices[ i + 2 ], c ); 34182 34183 // perform subdivision 34184 34185 subdivideFace( a, b, c, detail ); 34186 34187 } 34188 34189 } 34190 34191 function subdivideFace( a, b, c, detail ) { 34192 34193 const cols = detail + 1; 34194 34195 // we use this multidimensional array as a data structure for creating the subdivision 34196 34197 const v = []; 34198 34199 // construct all of the vertices for this subdivision 34200 34201 for ( let i = 0; i <= cols; i ++ ) { 34202 34203 v[ i ] = []; 34204 34205 const aj = a.clone().lerp( c, i / cols ); 34206 const bj = b.clone().lerp( c, i / cols ); 34207 34208 const rows = cols - i; 34209 34210 for ( let j = 0; j <= rows; j ++ ) { 34211 34212 if ( j === 0 && i === cols ) { 34213 34214 v[ i ][ j ] = aj; 34215 34216 } else { 34217 34218 v[ i ][ j ] = aj.clone().lerp( bj, j / rows ); 34219 34220 } 34221 34222 } 34223 34224 } 34225 34226 // construct all of the faces 34227 34228 for ( let i = 0; i < cols; i ++ ) { 34229 34230 for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) { 34231 34232 const k = Math.floor( j / 2 ); 34233 34234 if ( j % 2 === 0 ) { 34235 34236 pushVertex( v[ i ][ k + 1 ] ); 34237 pushVertex( v[ i + 1 ][ k ] ); 34238 pushVertex( v[ i ][ k ] ); 34239 34240 } else { 34241 34242 pushVertex( v[ i ][ k + 1 ] ); 34243 pushVertex( v[ i + 1 ][ k + 1 ] ); 34244 pushVertex( v[ i + 1 ][ k ] ); 34245 34246 } 34247 34248 } 34249 34250 } 34251 34252 } 34253 34254 function applyRadius( radius ) { 34255 34256 const vertex = new Vector3(); 34257 34258 // iterate over the entire buffer and apply the radius to each vertex 34259 34260 for ( let i = 0; i < vertexBuffer.length; i += 3 ) { 34261 34262 vertex.x = vertexBuffer[ i + 0 ]; 34263 vertex.y = vertexBuffer[ i + 1 ]; 34264 vertex.z = vertexBuffer[ i + 2 ]; 34265 34266 vertex.normalize().multiplyScalar( radius ); 34267 34268 vertexBuffer[ i + 0 ] = vertex.x; 34269 vertexBuffer[ i + 1 ] = vertex.y; 34270 vertexBuffer[ i + 2 ] = vertex.z; 34271 34272 } 34273 34274 } 34275 34276 function generateUVs() { 34277 34278 const vertex = new Vector3(); 34279 34280 for ( let i = 0; i < vertexBuffer.length; i += 3 ) { 34281 34282 vertex.x = vertexBuffer[ i + 0 ]; 34283 vertex.y = vertexBuffer[ i + 1 ]; 34284 vertex.z = vertexBuffer[ i + 2 ]; 34285 34286 const u = azimuth( vertex ) / 2 / Math.PI + 0.5; 34287 const v = inclination( vertex ) / Math.PI + 0.5; 34288 uvBuffer.push( u, 1 - v ); 34289 34290 } 34291 34292 correctUVs(); 34293 34294 correctSeam(); 34295 34296 } 34297 34298 function correctSeam() { 34299 34300 // handle case when face straddles the seam, see #3269 34301 34302 for ( let i = 0; i < uvBuffer.length; i += 6 ) { 34303 34304 // uv data of a single face 34305 34306 const x0 = uvBuffer[ i + 0 ]; 34307 const x1 = uvBuffer[ i + 2 ]; 34308 const x2 = uvBuffer[ i + 4 ]; 34309 34310 const max = Math.max( x0, x1, x2 ); 34311 const min = Math.min( x0, x1, x2 ); 34312 34313 // 0.9 is somewhat arbitrary 34314 34315 if ( max > 0.9 && min < 0.1 ) { 34316 34317 if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1; 34318 if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1; 34319 if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1; 34320 34321 } 34322 34323 } 34324 34325 } 34326 34327 function pushVertex( vertex ) { 34328 34329 vertexBuffer.push( vertex.x, vertex.y, vertex.z ); 34330 34331 } 34332 34333 function getVertexByIndex( index, vertex ) { 34334 34335 const stride = index * 3; 34336 34337 vertex.x = vertices[ stride + 0 ]; 34338 vertex.y = vertices[ stride + 1 ]; 34339 vertex.z = vertices[ stride + 2 ]; 34340 34341 } 34342 34343 function correctUVs() { 34344 34345 const a = new Vector3(); 34346 const b = new Vector3(); 34347 const c = new Vector3(); 34348 34349 const centroid = new Vector3(); 34350 34351 const uvA = new Vector2(); 34352 const uvB = new Vector2(); 34353 const uvC = new Vector2(); 34354 34355 for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) { 34356 34357 a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] ); 34358 b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] ); 34359 c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] ); 34360 34361 uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] ); 34362 uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] ); 34363 uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] ); 34364 34365 centroid.copy( a ).add( b ).add( c ).divideScalar( 3 ); 34366 34367 const azi = azimuth( centroid ); 34368 34369 correctUV( uvA, j + 0, a, azi ); 34370 correctUV( uvB, j + 2, b, azi ); 34371 correctUV( uvC, j + 4, c, azi ); 34372 34373 } 34374 34375 } 34376 34377 function correctUV( uv, stride, vector, azimuth ) { 34378 34379 if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) { 34380 34381 uvBuffer[ stride ] = uv.x - 1; 34382 34383 } 34384 34385 if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) { 34386 34387 uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5; 34388 34389 } 34390 34391 } 34392 34393 // Angle around the Y axis, counter-clockwise when looking from above. 34394 34395 function azimuth( vector ) { 34396 34397 return Math.atan2( vector.z, - vector.x ); 34398 34399 } 34400 34401 34402 // Angle above the XZ plane. 34403 34404 function inclination( vector ) { 34405 34406 return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) ); 34407 34408 } 34409 34410 } 34411 34412 copy( source ) { 34413 34414 super.copy( source ); 34415 34416 this.parameters = Object.assign( {}, source.parameters ); 34417 34418 return this; 34419 34420 } 34421 34422 static fromJSON( data ) { 34423 34424 return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details ); 34425 34426 } 34427 34428} 34429 34430class DodecahedronGeometry extends PolyhedronGeometry { 34431 34432 constructor( radius = 1, detail = 0 ) { 34433 34434 const t = ( 1 + Math.sqrt( 5 ) ) / 2; 34435 const r = 1 / t; 34436 34437 const vertices = [ 34438 34439 // (±1, ±1, ±1) 34440 - 1, - 1, - 1, - 1, - 1, 1, 34441 - 1, 1, - 1, - 1, 1, 1, 34442 1, - 1, - 1, 1, - 1, 1, 34443 1, 1, - 1, 1, 1, 1, 34444 34445 // (0, ±1/Ï, ±Ï) 34446 0, - r, - t, 0, - r, t, 34447 0, r, - t, 0, r, t, 34448 34449 // (±1/Ï, ±Ï, 0) 34450 - r, - t, 0, - r, t, 0, 34451 r, - t, 0, r, t, 0, 34452 34453 // (±Ï, 0, ±1/Ï) 34454 - t, 0, - r, t, 0, - r, 34455 - t, 0, r, t, 0, r 34456 ]; 34457 34458 const indices = [ 34459 3, 11, 7, 3, 7, 15, 3, 15, 13, 34460 7, 19, 17, 7, 17, 6, 7, 6, 15, 34461 17, 4, 8, 17, 8, 10, 17, 10, 6, 34462 8, 0, 16, 8, 16, 2, 8, 2, 10, 34463 0, 12, 1, 0, 1, 18, 0, 18, 16, 34464 6, 10, 2, 6, 2, 13, 6, 13, 15, 34465 2, 16, 18, 2, 18, 3, 2, 3, 13, 34466 18, 1, 9, 18, 9, 11, 18, 11, 3, 34467 4, 14, 12, 4, 12, 0, 4, 0, 8, 34468 11, 9, 5, 11, 5, 19, 11, 19, 7, 34469 19, 5, 14, 19, 14, 4, 19, 4, 17, 34470 1, 12, 14, 1, 14, 5, 1, 5, 9 34471 ]; 34472 34473 super( vertices, indices, radius, detail ); 34474 34475 this.type = 'DodecahedronGeometry'; 34476 34477 this.parameters = { 34478 radius: radius, 34479 detail: detail 34480 }; 34481 34482 } 34483 34484 static fromJSON( data ) { 34485 34486 return new DodecahedronGeometry( data.radius, data.detail ); 34487 34488 } 34489 34490} 34491 34492const _v0 = /*@__PURE__*/ new Vector3(); 34493const _v1$1 = /*@__PURE__*/ new Vector3(); 34494const _normal = /*@__PURE__*/ new Vector3(); 34495const _triangle = /*@__PURE__*/ new Triangle(); 34496 34497class EdgesGeometry extends BufferGeometry { 34498 34499 constructor( geometry = null, thresholdAngle = 1 ) { 34500 34501 super(); 34502 34503 this.type = 'EdgesGeometry'; 34504 34505 this.parameters = { 34506 geometry: geometry, 34507 thresholdAngle: thresholdAngle 34508 }; 34509 34510 if ( geometry !== null ) { 34511 34512 const precisionPoints = 4; 34513 const precision = Math.pow( 10, precisionPoints ); 34514 const thresholdDot = Math.cos( DEG2RAD * thresholdAngle ); 34515 34516 const indexAttr = geometry.getIndex(); 34517 const positionAttr = geometry.getAttribute( 'position' ); 34518 const indexCount = indexAttr ? indexAttr.count : positionAttr.count; 34519 34520 const indexArr = [ 0, 0, 0 ]; 34521 const vertKeys = [ 'a', 'b', 'c' ]; 34522 const hashes = new Array( 3 ); 34523 34524 const edgeData = {}; 34525 const vertices = []; 34526 for ( let i = 0; i < indexCount; i += 3 ) { 34527 34528 if ( indexAttr ) { 34529 34530 indexArr[ 0 ] = indexAttr.getX( i ); 34531 indexArr[ 1 ] = indexAttr.getX( i + 1 ); 34532 indexArr[ 2 ] = indexAttr.getX( i + 2 ); 34533 34534 } else { 34535 34536 indexArr[ 0 ] = i; 34537 indexArr[ 1 ] = i + 1; 34538 indexArr[ 2 ] = i + 2; 34539 34540 } 34541 34542 const { a, b, c } = _triangle; 34543 a.fromBufferAttribute( positionAttr, indexArr[ 0 ] ); 34544 b.fromBufferAttribute( positionAttr, indexArr[ 1 ] ); 34545 c.fromBufferAttribute( positionAttr, indexArr[ 2 ] ); 34546 _triangle.getNormal( _normal ); 34547 34548 // create hashes for the edge from the vertices 34549 hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`; 34550 hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`; 34551 hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`; 34552 34553 // skip degenerate triangles 34554 if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) { 34555 34556 continue; 34557 34558 } 34559 34560 // iterate over every edge 34561 for ( let j = 0; j < 3; j ++ ) { 34562 34563 // get the first and next vertex making up the edge 34564 const jNext = ( j + 1 ) % 3; 34565 const vecHash0 = hashes[ j ]; 34566 const vecHash1 = hashes[ jNext ]; 34567 const v0 = _triangle[ vertKeys[ j ] ]; 34568 const v1 = _triangle[ vertKeys[ jNext ] ]; 34569 34570 const hash = `${ vecHash0 }_${ vecHash1 }`; 34571 const reverseHash = `${ vecHash1 }_${ vecHash0 }`; 34572 34573 if ( reverseHash in edgeData && edgeData[ reverseHash ] ) { 34574 34575 // if we found a sibling edge add it into the vertex array if 34576 // it meets the angle threshold and delete the edge from the map. 34577 if ( _normal.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) { 34578 34579 vertices.push( v0.x, v0.y, v0.z ); 34580 vertices.push( v1.x, v1.y, v1.z ); 34581 34582 } 34583 34584 edgeData[ reverseHash ] = null; 34585 34586 } else if ( ! ( hash in edgeData ) ) { 34587 34588 // if we've already got an edge here then skip adding a new one 34589 edgeData[ hash ] = { 34590 34591 index0: indexArr[ j ], 34592 index1: indexArr[ jNext ], 34593 normal: _normal.clone(), 34594 34595 }; 34596 34597 } 34598 34599 } 34600 34601 } 34602 34603 // iterate over all remaining, unmatched edges and add them to the vertex array 34604 for ( const key in edgeData ) { 34605 34606 if ( edgeData[ key ] ) { 34607 34608 const { index0, index1 } = edgeData[ key ]; 34609 _v0.fromBufferAttribute( positionAttr, index0 ); 34610 _v1$1.fromBufferAttribute( positionAttr, index1 ); 34611 34612 vertices.push( _v0.x, _v0.y, _v0.z ); 34613 vertices.push( _v1$1.x, _v1$1.y, _v1$1.z ); 34614 34615 } 34616 34617 } 34618 34619 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 34620 34621 } 34622 34623 } 34624 34625 copy( source ) { 34626 34627 super.copy( source ); 34628 34629 this.parameters = Object.assign( {}, source.parameters ); 34630 34631 return this; 34632 34633 } 34634 34635} 34636 34637class Shape extends Path { 34638 34639 constructor( points ) { 34640 34641 super( points ); 34642 34643 this.uuid = generateUUID(); 34644 34645 this.type = 'Shape'; 34646 34647 this.holes = []; 34648 34649 } 34650 34651 getPointsHoles( divisions ) { 34652 34653 const holesPts = []; 34654 34655 for ( let i = 0, l = this.holes.length; i < l; i ++ ) { 34656 34657 holesPts[ i ] = this.holes[ i ].getPoints( divisions ); 34658 34659 } 34660 34661 return holesPts; 34662 34663 } 34664 34665 // get points of shape and holes (keypoints based on segments parameter) 34666 34667 extractPoints( divisions ) { 34668 34669 return { 34670 34671 shape: this.getPoints( divisions ), 34672 holes: this.getPointsHoles( divisions ) 34673 34674 }; 34675 34676 } 34677 34678 copy( source ) { 34679 34680 super.copy( source ); 34681 34682 this.holes = []; 34683 34684 for ( let i = 0, l = source.holes.length; i < l; i ++ ) { 34685 34686 const hole = source.holes[ i ]; 34687 34688 this.holes.push( hole.clone() ); 34689 34690 } 34691 34692 return this; 34693 34694 } 34695 34696 toJSON() { 34697 34698 const data = super.toJSON(); 34699 34700 data.uuid = this.uuid; 34701 data.holes = []; 34702 34703 for ( let i = 0, l = this.holes.length; i < l; i ++ ) { 34704 34705 const hole = this.holes[ i ]; 34706 data.holes.push( hole.toJSON() ); 34707 34708 } 34709 34710 return data; 34711 34712 } 34713 34714 fromJSON( json ) { 34715 34716 super.fromJSON( json ); 34717 34718 this.uuid = json.uuid; 34719 this.holes = []; 34720 34721 for ( let i = 0, l = json.holes.length; i < l; i ++ ) { 34722 34723 const hole = json.holes[ i ]; 34724 this.holes.push( new Path().fromJSON( hole ) ); 34725 34726 } 34727 34728 return this; 34729 34730 } 34731 34732} 34733 34734/** 34735 * Port from https://github.com/mapbox/earcut (v2.2.4) 34736 */ 34737 34738const Earcut = { 34739 34740 triangulate: function ( data, holeIndices, dim = 2 ) { 34741 34742 const hasHoles = holeIndices && holeIndices.length; 34743 const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length; 34744 let outerNode = linkedList( data, 0, outerLen, dim, true ); 34745 const triangles = []; 34746 34747 if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles; 34748 34749 let minX, minY, maxX, maxY, x, y, invSize; 34750 34751 if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim ); 34752 34753 // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox 34754 if ( data.length > 80 * dim ) { 34755 34756 minX = maxX = data[ 0 ]; 34757 minY = maxY = data[ 1 ]; 34758 34759 for ( let i = dim; i < outerLen; i += dim ) { 34760 34761 x = data[ i ]; 34762 y = data[ i + 1 ]; 34763 if ( x < minX ) minX = x; 34764 if ( y < minY ) minY = y; 34765 if ( x > maxX ) maxX = x; 34766 if ( y > maxY ) maxY = y; 34767 34768 } 34769 34770 // minX, minY and invSize are later used to transform coords into integers for z-order calculation 34771 invSize = Math.max( maxX - minX, maxY - minY ); 34772 invSize = invSize !== 0 ? 32767 / invSize : 0; 34773 34774 } 34775 34776 earcutLinked( outerNode, triangles, dim, minX, minY, invSize, 0 ); 34777 34778 return triangles; 34779 34780 } 34781 34782}; 34783 34784// create a circular doubly linked list from polygon points in the specified winding order 34785function linkedList( data, start, end, dim, clockwise ) { 34786 34787 let i, last; 34788 34789 if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) { 34790 34791 for ( i = start; i < end;
vendor: 10,405 bytes, lines 34791-35264
34791 i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); 34792 34793 } else { 34794 34795 for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); 34796 34797 } 34798 34799 if ( last && equals( last, last.next ) ) { 34800 34801 removeNode( last ); 34802 last = last.next; 34803 34804 } 34805 34806 return last; 34807 34808} 34809 34810// eliminate colinear or duplicate points 34811function filterPoints( start, end ) { 34812 34813 if ( ! start ) return start; 34814 if ( ! end ) end = start; 34815 34816 let p = start, 34817 again; 34818 do { 34819 34820 again = false; 34821 34822 if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) { 34823 34824 removeNode( p ); 34825 p = end = p.prev; 34826 if ( p === p.next ) break; 34827 again = true; 34828 34829 } else { 34830 34831 p = p.next; 34832 34833 } 34834 34835 } while ( again || p !== end ); 34836 34837 return end; 34838 34839} 34840 34841// main ear slicing loop which triangulates a polygon (given as a linked list) 34842function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) { 34843 34844 if ( ! ear ) return; 34845 34846 // interlink polygon nodes in z-order 34847 if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize ); 34848 34849 let stop = ear, 34850 prev, next; 34851 34852 // iterate through ears, slicing them one by one 34853 while ( ear.prev !== ear.next ) { 34854 34855 prev = ear.prev; 34856 next = ear.next; 34857 34858 if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) { 34859 34860 // cut off the triangle 34861 triangles.push( prev.i / dim | 0 ); 34862 triangles.push( ear.i / dim | 0 ); 34863 triangles.push( next.i / dim | 0 ); 34864 34865 removeNode( ear ); 34866 34867 // skipping the next vertex leads to less sliver triangles 34868 ear = next.next; 34869 stop = next.next; 34870 34871 continue; 34872 34873 } 34874 34875 ear = next; 34876 34877 // if we looped through the whole remaining polygon and can't find any more ears 34878 if ( ear === stop ) { 34879 34880 // try filtering points and slicing again 34881 if ( ! pass ) { 34882 34883 earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 ); 34884 34885 // if this didn't work, try curing all small self-intersections locally 34886 34887 } else if ( pass === 1 ) { 34888 34889 ear = cureLocalIntersections( filterPoints( ear ), triangles, dim ); 34890 earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 ); 34891 34892 // as a last resort, try splitting the remaining polygon into two 34893 34894 } else if ( pass === 2 ) { 34895 34896 splitEarcut( ear, triangles, dim, minX, minY, invSize ); 34897 34898 } 34899 34900 break; 34901 34902 } 34903 34904 } 34905 34906} 34907 34908// check whether a polygon node forms a valid ear with adjacent nodes 34909function isEar( ear ) { 34910 34911 const a = ear.prev, 34912 b = ear, 34913 c = ear.next; 34914 34915 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear 34916 34917 // now make sure we don't have other points inside the potential ear 34918 const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; 34919 34920 // triangle bbox; min & max are calculated like this for speed 34921 const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ), 34922 y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ), 34923 x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ), 34924 y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy ); 34925 34926 let p = c.next; 34927 while ( p !== a ) { 34928 34929 if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && 34930 pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && 34931 area( p.prev, p, p.next ) >= 0 ) return false; 34932 p = p.next; 34933 34934 } 34935 34936 return true; 34937 34938} 34939 34940function isEarHashed( ear, minX, minY, invSize ) { 34941 34942 const a = ear.prev, 34943 b = ear, 34944 c = ear.next; 34945 34946 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear 34947 34948 const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; 34949 34950 // triangle bbox; min & max are calculated like this for speed 34951 const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ), 34952 y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ), 34953 x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ), 34954 y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy ); 34955 34956 // z-order range for the current triangle bbox; 34957 const minZ = zOrder( x0, y0, minX, minY, invSize ), 34958 maxZ = zOrder( x1, y1, minX, minY, invSize ); 34959 34960 let p = ear.prevZ, 34961 n = ear.nextZ; 34962 34963 // look for points inside the triangle in both directions 34964 while ( p && p.z >= minZ && n && n.z <= maxZ ) { 34965 34966 if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && 34967 pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false; 34968 p = p.prevZ; 34969 34970 if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && 34971 pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false; 34972 n = n.nextZ; 34973 34974 } 34975 34976 // look for remaining points in decreasing z-order 34977 while ( p && p.z >= minZ ) { 34978 34979 if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && 34980 pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false; 34981 p = p.prevZ; 34982 34983 } 34984 34985 // look for remaining points in increasing z-order 34986 while ( n && n.z <= maxZ ) { 34987 34988 if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && 34989 pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false; 34990 n = n.nextZ; 34991 34992 } 34993 34994 return true; 34995 34996} 34997 34998// go through all polygon nodes and cure small local self-intersections 34999function cureLocalIntersections( start, triangles, dim ) { 35000 35001 let p = start; 35002 do { 35003 35004 const a = p.prev, 35005 b = p.next.next; 35006 35007 if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) { 35008 35009 triangles.push( a.i / dim | 0 ); 35010 triangles.push( p.i / dim | 0 ); 35011 triangles.push( b.i / dim | 0 ); 35012 35013 // remove two nodes involved 35014 removeNode( p ); 35015 removeNode( p.next ); 35016 35017 p = start = b; 35018 35019 } 35020 35021 p = p.next; 35022 35023 } while ( p !== start ); 35024 35025 return filterPoints( p ); 35026 35027} 35028 35029// try splitting polygon into two and triangulate them independently 35030function splitEarcut( start, triangles, dim, minX, minY, invSize ) { 35031 35032 // look for a valid diagonal that divides the polygon into two 35033 let a = start; 35034 do { 35035 35036 let b = a.next.next; 35037 while ( b !== a.prev ) { 35038 35039 if ( a.i !== b.i && isValidDiagonal( a, b ) ) { 35040 35041 // split the polygon in two by the diagonal 35042 let c = splitPolygon( a, b ); 35043 35044 // filter colinear points around the cuts 35045 a = filterPoints( a, a.next ); 35046 c = filterPoints( c, c.next ); 35047 35048 // run earcut on each half 35049 earcutLinked( a, triangles, dim, minX, minY, invSize, 0 ); 35050 earcutLinked( c, triangles, dim, minX, minY, invSize, 0 ); 35051 return; 35052 35053 } 35054 35055 b = b.next; 35056 35057 } 35058 35059 a = a.next; 35060 35061 } while ( a !== start ); 35062 35063} 35064 35065// link every hole into the outer loop, producing a single-ring polygon without holes 35066function eliminateHoles( data, holeIndices, outerNode, dim ) { 35067 35068 const queue = []; 35069 let i, len, start, end, list; 35070 35071 for ( i = 0, len = holeIndices.length; i < len; i ++ ) { 35072 35073 start = holeIndices[ i ] * dim; 35074 end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length; 35075 list = linkedList( data, start, end, dim, false ); 35076 if ( list === list.next ) list.steiner = true; 35077 queue.push( getLeftmost( list ) ); 35078 35079 } 35080 35081 queue.sort( compareX ); 35082 35083 // process holes from left to right 35084 for ( i = 0; i < queue.length; i ++ ) { 35085 35086 outerNode = eliminateHole( queue[ i ], outerNode ); 35087 35088 } 35089 35090 return outerNode; 35091 35092} 35093 35094function compareX( a, b ) { 35095 35096 return a.x - b.x; 35097 35098} 35099 35100// find a bridge between vertices that connects hole with an outer ring and link it 35101function eliminateHole( hole, outerNode ) { 35102 35103 const bridge = findHoleBridge( hole, outerNode ); 35104 if ( ! bridge ) { 35105 35106 return outerNode; 35107 35108 } 35109 35110 const bridgeReverse = splitPolygon( bridge, hole ); 35111 35112 // filter collinear points around the cuts 35113 filterPoints( bridgeReverse, bridgeReverse.next ); 35114 return filterPoints( bridge, bridge.next ); 35115 35116} 35117 35118// David Eberly's algorithm for finding a bridge between hole and outer polygon 35119function findHoleBridge( hole, outerNode ) { 35120 35121 let p = outerNode, 35122 qx = - Infinity, 35123 m; 35124 35125 const hx = hole.x, hy = hole.y; 35126 35127 // find a segment intersected by a ray from the hole's leftmost point to the left; 35128 // segment's endpoint with lesser x will be potential connection point 35129 do { 35130 35131 if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) { 35132 35133 const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y ); 35134 if ( x <= hx && x > qx ) { 35135 35136 qx = x; 35137 m = p.x < p.next.x ? p : p.next; 35138 if ( x === hx ) return m; // hole touches outer segment; pick leftmost endpoint 35139 35140 } 35141 35142 } 35143 35144 p = p.next; 35145 35146 } while ( p !== outerNode ); 35147 35148 if ( ! m ) return null; 35149 35150 // look for points inside the triangle of hole point, segment intersection and endpoint; 35151 // if there are no points found, we have a valid connection; 35152 // otherwise choose the point of the minimum angle with the ray as connection point 35153 35154 const stop = m, 35155 mx = m.x, 35156 my = m.y; 35157 let tanMin = Infinity, tan; 35158 35159 p = m; 35160 35161 do { 35162 35163 if ( hx >= p.x && p.x >= mx && hx !== p.x && 35164 pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) { 35165 35166 tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential 35167 35168 if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) { 35169 35170 m = p; 35171 tanMin = tan; 35172 35173 } 35174 35175 } 35176 35177 p = p.next; 35178 35179 } while ( p !== stop ); 35180 35181 return m; 35182 35183} 35184 35185// whether sector in vertex m contains sector in vertex p in the same coordinates 35186function sectorContainsSector( m, p ) { 35187 35188 return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0; 35189 35190} 35191 35192// interlink polygon nodes in z-order 35193function indexCurve( start, minX, minY, invSize ) { 35194 35195 let p = start; 35196 do { 35197 35198 if ( p.z === 0 ) p.z = zOrder( p.x, p.y, minX, minY, invSize ); 35199 p.prevZ = p.prev; 35200 p.nextZ = p.next; 35201 p = p.next; 35202 35203 } while ( p !== start ); 35204 35205 p.prevZ.nextZ = null; 35206 p.prevZ = null; 35207 35208 sortLinked( p ); 35209 35210} 35211 35212// Simon Tatham's linked list merge sort algorithm 35213// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html 35214function sortLinked( list ) { 35215 35216 let i, p, q, e, tail, numMerges, pSize, qSize, 35217 inSize = 1; 35218 35219 do { 35220 35221 p = list; 35222 list = null; 35223 tail = null; 35224 numMerges = 0; 35225 35226 while ( p ) { 35227 35228 numMerges ++; 35229 q = p; 35230 pSize = 0; 35231 for ( i = 0; i < inSize; i ++ ) { 35232 35233 pSize ++; 35234 q = q.nextZ; 35235 if ( ! q ) break; 35236 35237 } 35238 35239 qSize = inSize; 35240 35241 while ( pSize > 0 || ( qSize > 0 && q ) ) { 35242 35243 if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) { 35244 35245 e = p; 35246 p = p.nextZ; 35247 pSize --; 35248 35249 } else { 35250 35251 e = q; 35252 q = q.nextZ; 35253 qSize --; 35254 35255 } 35256 35257 if ( tail ) tail.nextZ = e; 35258 else list = e; 35259 35260 e.prevZ = tail; 35261 tail = e; 35262 35263 } 35264
vendor: 9,706 bytes, lines 35265-35691
35265 p = q; 35266 35267 } 35268 35269 tail.nextZ = null; 35270 inSize *= 2; 35271 35272 } while ( numMerges > 1 ); 35273 35274 return list; 35275 35276} 35277 35278// z-order of a point given coords and inverse of the longer side of data bbox 35279function zOrder( x, y, minX, minY, invSize ) { 35280 35281 // coords are transformed into non-negative 15-bit integer range 35282 x = ( x - minX ) * invSize | 0; 35283 y = ( y - minY ) * invSize | 0; 35284 35285 x = ( x | ( x << 8 ) ) & 0x00FF00FF; 35286 x = ( x | ( x << 4 ) ) & 0x0F0F0F0F; 35287 x = ( x | ( x << 2 ) ) & 0x33333333; 35288 x = ( x | ( x << 1 ) ) & 0x55555555; 35289 35290 y = ( y | ( y << 8 ) ) & 0x00FF00FF; 35291 y = ( y | ( y << 4 ) ) & 0x0F0F0F0F; 35292 y = ( y | ( y << 2 ) ) & 0x33333333; 35293 y = ( y | ( y << 1 ) ) & 0x55555555; 35294 35295 return x | ( y << 1 ); 35296 35297} 35298 35299// find the leftmost node of a polygon ring 35300function getLeftmost( start ) { 35301 35302 let p = start, 35303 leftmost = start; 35304 do { 35305 35306 if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p; 35307 p = p.next; 35308 35309 } while ( p !== start ); 35310 35311 return leftmost; 35312 35313} 35314 35315// check if a point lies within a convex triangle 35316function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) { 35317 35318 return ( cx - px ) * ( ay - py ) >= ( ax - px ) * ( cy - py ) && 35319 ( ax - px ) * ( by - py ) >= ( bx - px ) * ( ay - py ) && 35320 ( bx - px ) * ( cy - py ) >= ( cx - px ) * ( by - py ); 35321 35322} 35323 35324// check if a diagonal between two polygon nodes is valid (lies in polygon interior) 35325function isValidDiagonal( a, b ) { 35326 35327 return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges 35328 ( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible 35329 ( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors 35330 equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case 35331 35332} 35333 35334// signed area of a triangle 35335function area( p, q, r ) { 35336 35337 return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y ); 35338 35339} 35340 35341// check if two points are equal 35342function equals( p1, p2 ) { 35343 35344 return p1.x === p2.x && p1.y === p2.y; 35345 35346} 35347 35348// check if two segments intersect 35349function intersects( p1, q1, p2, q2 ) { 35350 35351 const o1 = sign( area( p1, q1, p2 ) ); 35352 const o2 = sign( area( p1, q1, q2 ) ); 35353 const o3 = sign( area( p2, q2, p1 ) ); 35354 const o4 = sign( area( p2, q2, q1 ) ); 35355 35356 if ( o1 !== o2 && o3 !== o4 ) return true; // general case 35357 35358 if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1 35359 if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1 35360 if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2 35361 if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2 35362 35363 return false; 35364 35365} 35366 35367// for collinear points p, q, r, check if point q lies on segment pr 35368function onSegment( p, q, r ) { 35369 35370 return q.x <= Math.max( p.x, r.x ) && q.x >= Math.min( p.x, r.x ) && q.y <= Math.max( p.y, r.y ) && q.y >= Math.min( p.y, r.y ); 35371 35372} 35373 35374function sign( num ) { 35375 35376 return num > 0 ? 1 : num < 0 ? - 1 : 0; 35377 35378} 35379 35380// check if a polygon diagonal intersects any polygon segments 35381function intersectsPolygon( a, b ) { 35382 35383 let p = a; 35384 do { 35385 35386 if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && 35387 intersects( p, p.next, a, b ) ) return true; 35388 p = p.next; 35389 35390 } while ( p !== a ); 35391 35392 return false; 35393 35394} 35395 35396// check if a polygon diagonal is locally inside the polygon 35397function locallyInside( a, b ) { 35398 35399 return area( a.prev, a, a.next ) < 0 ? 35400 area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 : 35401 area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0; 35402 35403} 35404 35405// check if the middle point of a polygon diagonal is inside the polygon 35406function middleInside( a, b ) { 35407 35408 let p = a, 35409 inside = false; 35410 const px = ( a.x + b.x ) / 2, 35411 py = ( a.y + b.y ) / 2; 35412 do { 35413 35414 if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y && 35415 ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) 35416 inside = ! inside; 35417 p = p.next; 35418 35419 } while ( p !== a ); 35420 35421 return inside; 35422 35423} 35424 35425// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; 35426// if one belongs to the outer ring and another to a hole, it merges it into a single ring 35427function splitPolygon( a, b ) { 35428 35429 const a2 = new Node( a.i, a.x, a.y ), 35430 b2 = new Node( b.i, b.x, b.y ), 35431 an = a.next, 35432 bp = b.prev; 35433 35434 a.next = b; 35435 b.prev = a; 35436 35437 a2.next = an; 35438 an.prev = a2; 35439 35440 b2.next = a2; 35441 a2.prev = b2; 35442 35443 bp.next = b2; 35444 b2.prev = bp; 35445 35446 return b2; 35447 35448} 35449 35450// create a node and optionally link it with previous one (in a circular doubly linked list) 35451function insertNode( i, x, y, last ) { 35452 35453 const p = new Node( i, x, y ); 35454 35455 if ( ! last ) { 35456 35457 p.prev = p; 35458 p.next = p; 35459 35460 } else { 35461 35462 p.next = last.next; 35463 p.prev = last; 35464 last.next.prev = p; 35465 last.next = p; 35466 35467 } 35468 35469 return p; 35470 35471} 35472 35473function removeNode( p ) { 35474 35475 p.next.prev = p.prev; 35476 p.prev.next = p.next; 35477 35478 if ( p.prevZ ) p.prevZ.nextZ = p.nextZ; 35479 if ( p.nextZ ) p.nextZ.prevZ = p.prevZ; 35480 35481} 35482 35483function Node( i, x, y ) { 35484 35485 // vertex index in coordinates array 35486 this.i = i; 35487 35488 // vertex coordinates 35489 this.x = x; 35490 this.y = y; 35491 35492 // previous and next vertex nodes in a polygon ring 35493 this.prev = null; 35494 this.next = null; 35495 35496 // z-order curve value 35497 this.z = 0; 35498 35499 // previous and next nodes in z-order 35500 this.prevZ = null; 35501 this.nextZ = null; 35502 35503 // indicates whether this is a steiner point 35504 this.steiner = false; 35505 35506} 35507 35508function signedArea( data, start, end, dim ) { 35509 35510 let sum = 0; 35511 for ( let i = start, j = end - dim; i < end; i += dim ) { 35512 35513 sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] ); 35514 j = i; 35515 35516 } 35517 35518 return sum; 35519 35520} 35521 35522class ShapeUtils { 35523 35524 // calculate area of the contour polygon 35525 35526 static area( contour ) { 35527 35528 const n = contour.length; 35529 let a = 0.0; 35530 35531 for ( let p = n - 1, q = 0; q < n; p = q ++ ) { 35532 35533 a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y; 35534 35535 } 35536 35537 return a * 0.5; 35538 35539 } 35540 35541 static isClockWise( pts ) { 35542 35543 return ShapeUtils.area( pts ) < 0; 35544 35545 } 35546 35547 static triangulateShape( contour, holes ) { 35548 35549 const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ] 35550 const holeIndices = []; // array of hole indices 35551 const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ] 35552 35553 removeDupEndPts( contour ); 35554 addContour( vertices, contour ); 35555 35556 // 35557 35558 let holeIndex = contour.length; 35559 35560 holes.forEach( removeDupEndPts ); 35561 35562 for ( let i = 0; i < holes.length; i ++ ) { 35563 35564 holeIndices.push( holeIndex ); 35565 holeIndex += holes[ i ].length; 35566 addContour( vertices, holes[ i ] ); 35567 35568 } 35569 35570 // 35571 35572 const triangles = Earcut.triangulate( vertices, holeIndices ); 35573 35574 // 35575 35576 for ( let i = 0; i < triangles.length; i += 3 ) { 35577 35578 faces.push( triangles.slice( i, i + 3 ) ); 35579 35580 } 35581 35582 return faces; 35583 35584 } 35585 35586} 35587 35588function removeDupEndPts( points ) { 35589 35590 const l = points.length; 35591 35592 if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) { 35593 35594 points.pop(); 35595 35596 } 35597 35598} 35599 35600function addContour( vertices, contour ) { 35601 35602 for ( let i = 0; i < contour.length; i ++ ) { 35603 35604 vertices.push( contour[ i ].x ); 35605 vertices.push( contour[ i ].y ); 35606 35607 } 35608 35609} 35610 35611/** 35612 * Creates extruded geometry from a path shape. 35613 * 35614 * parameters = { 35615 * 35616 * curveSegments: <int>, // number of points on the curves 35617 * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too 35618 * depth: <float>, // Depth to extrude the shape 35619 * 35620 * bevelEnabled: <bool>, // turn on bevel 35621 * bevelThickness: <float>, // how deep into the original shape bevel goes 35622 * bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel 35623 * bevelOffset: <float>, // how far from shape outline does bevel start 35624 * bevelSegments: <int>, // number of bevel layers 35625 * 35626 * extrudePath: <THREE.Curve> // curve to extrude shape along 35627 * 35628 * UVGenerator: <Object> // object that provides UV generator functions 35629 * 35630 * } 35631 */ 35632 35633class ExtrudeGeometry extends BufferGeometry { 35634 35635 constructor( shapes = new Shape( [ new Vector2( 0.5, 0.5 ), new Vector2( - 0.5, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), options = {} ) { 35636 35637 super(); 35638 35639 this.type = 'ExtrudeGeometry'; 35640 35641 this.parameters = { 35642 shapes: shapes, 35643 options: options 35644 }; 35645 35646 shapes = Array.isArray( shapes ) ? shapes : [ shapes ]; 35647 35648 const scope = this; 35649 35650 const verticesArray = []; 35651 const uvArray = []; 35652 35653 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 35654 35655 const shape = shapes[ i ]; 35656 addShape( shape ); 35657 35658 } 35659 35660 // build geometry 35661 35662 this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) ); 35663 this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) ); 35664 35665 this.computeVertexNormals(); 35666 35667 // functions 35668 35669 function addShape( shape ) { 35670 35671 const placeholder = []; 35672 35673 // options 35674 35675 const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12; 35676 const steps = options.steps !== undefined ? options.steps : 1; 35677 const depth = options.depth !== undefined ? options.depth : 1; 35678 35679 let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; 35680 let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2; 35681 let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1; 35682 let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0; 35683 let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3; 35684 35685 const extrudePath = options.extrudePath; 35686 35687 const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator; 35688 35689 // 35690 35691 let extrudePts, extrudeByPath = false;
vendor: 2,791 bytes, lines 35692-35805
35692 let splineTube, binormal, normal, position2; 35693 35694 if ( extrudePath ) { 35695 35696 extrudePts = extrudePath.getSpacedPoints( steps ); 35697 35698 extrudeByPath = true; 35699 bevelEnabled = false; // bevels not supported for path extrusion 35700 35701 // SETUP TNB variables 35702 35703 // TODO1 - have a .isClosed in spline? 35704 35705 splineTube = extrudePath.computeFrenetFrames( steps, false ); 35706 35707 // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length); 35708 35709 binormal = new Vector3(); 35710 normal = new Vector3(); 35711 position2 = new Vector3(); 35712 35713 } 35714 35715 // Safeguards if bevels are not enabled 35716 35717 if ( ! bevelEnabled ) { 35718 35719 bevelSegments = 0; 35720 bevelThickness = 0; 35721 bevelSize = 0; 35722 bevelOffset = 0; 35723 35724 } 35725 35726 // Variables initialization 35727 35728 const shapePoints = shape.extractPoints( curveSegments ); 35729 35730 let vertices = shapePoints.shape; 35731 const holes = shapePoints.holes; 35732 35733 const reverse = ! ShapeUtils.isClockWise( vertices ); 35734 35735 if ( reverse ) { 35736 35737 vertices = vertices.reverse(); 35738 35739 // Maybe we should also check if holes are in the opposite direction, just to be safe ... 35740 35741 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 35742 35743 const ahole = holes[ h ]; 35744 35745 if ( ShapeUtils.isClockWise( ahole ) ) { 35746 35747 holes[ h ] = ahole.reverse(); 35748 35749 } 35750 35751 } 35752 35753 } 35754 35755 35756 const faces = ShapeUtils.triangulateShape( vertices, holes ); 35757 35758 /* Vertices */ 35759 35760 const contour = vertices; // vertices has all points but contour has only points of circumference 35761 35762 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 35763 35764 const ahole = holes[ h ]; 35765 35766 vertices = vertices.concat( ahole ); 35767 35768 } 35769 35770 35771 function scalePt2( pt, vec, size ) { 35772 35773 if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' ); 35774 35775 return pt.clone().addScaledVector( vec, size ); 35776 35777 } 35778 35779 const vlen = vertices.length, flen = faces.length; 35780 35781 35782 // Find directions for point movement 35783 35784 35785 function getBevelVec( inPt, inPrev, inNext ) { 35786 35787 // computes for inPt the corresponding point inPt' on a new contour 35788 // shifted by 1 unit (length of normalized vector) to the left 35789 // if we walk along contour clockwise, this new contour is outside the old one 35790 // 35791 // inPt' is the intersection of the two lines parallel to the two 35792 // adjacent edges of inPt at a distance of 1 unit on the left side. 35793 35794 let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt 35795 35796 // good reading for geometry algorithms (here: line-line intersection) 35797 // http://geomalgorithms.com/a05-_intersect-1.html 35798 35799 const v_prev_x = inPt.x - inPrev.x, 35800 v_prev_y = inPt.y - inPrev.y; 35801 const v_next_x = inNext.x - inPt.x, 35802 v_next_y = inNext.y - inPt.y; 35803 35804 const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y ); 35805
vendor: 17,452 bytes, lines 35806-36657
35806 // check for collinear edges 35807 const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x ); 35808 35809 if ( Math.abs( collinear0 ) > Number.EPSILON ) { 35810 35811 // not collinear 35812 35813 // length of vectors for normalizing 35814 35815 const v_prev_len = Math.sqrt( v_prev_lensq ); 35816 const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y ); 35817 35818 // shift adjacent points by unit vectors to the left 35819 35820 const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len ); 35821 const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len ); 35822 35823 const ptNextShift_x = ( inNext.x - v_next_y / v_next_len ); 35824 const ptNextShift_y = ( inNext.y + v_next_x / v_next_len ); 35825 35826 // scaling factor for v_prev to intersection point 35827 35828 const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y - 35829 ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) / 35830 ( v_prev_x * v_next_y - v_prev_y * v_next_x ); 35831 35832 // vector from inPt to intersection point 35833 35834 v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x ); 35835 v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y ); 35836 35837 // Don't normalize!, otherwise sharp corners become ugly 35838 // but prevent crazy spikes 35839 const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y ); 35840 if ( v_trans_lensq <= 2 ) { 35841 35842 return new Vector2( v_trans_x, v_trans_y ); 35843 35844 } else { 35845 35846 shrink_by = Math.sqrt( v_trans_lensq / 2 ); 35847 35848 } 35849 35850 } else { 35851 35852 // handle special case of collinear edges 35853 35854 let direction_eq = false; // assumes: opposite 35855 35856 if ( v_prev_x > Number.EPSILON ) { 35857 35858 if ( v_next_x > Number.EPSILON ) { 35859 35860 direction_eq = true; 35861 35862 } 35863 35864 } else { 35865 35866 if ( v_prev_x < - Number.EPSILON ) { 35867 35868 if ( v_next_x < - Number.EPSILON ) { 35869 35870 direction_eq = true; 35871 35872 } 35873 35874 } else { 35875 35876 if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) { 35877 35878 direction_eq = true; 35879 35880 } 35881 35882 } 35883 35884 } 35885 35886 if ( direction_eq ) { 35887 35888 // console.log("Warning: lines are a straight sequence"); 35889 v_trans_x = - v_prev_y; 35890 v_trans_y = v_prev_x; 35891 shrink_by = Math.sqrt( v_prev_lensq ); 35892 35893 } else { 35894 35895 // console.log("Warning: lines are a straight spike"); 35896 v_trans_x = v_prev_x; 35897 v_trans_y = v_prev_y; 35898 shrink_by = Math.sqrt( v_prev_lensq / 2 ); 35899 35900 } 35901 35902 } 35903 35904 return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by ); 35905 35906 } 35907 35908 35909 const contourMovements = []; 35910 35911 for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { 35912 35913 if ( j === il ) j = 0; 35914 if ( k === il ) k = 0; 35915 35916 // (j)---(i)---(k) 35917 // console.log('i,j,k', i, j , k) 35918 35919 contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); 35920 35921 } 35922 35923 const holesMovements = []; 35924 let oneHoleMovements, verticesMovements = contourMovements.concat(); 35925 35926 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 35927 35928 const ahole = holes[ h ]; 35929 35930 oneHoleMovements = []; 35931 35932 for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { 35933 35934 if ( j === il ) j = 0; 35935 if ( k === il ) k = 0; 35936 35937 // (j)---(i)---(k) 35938 oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] ); 35939 35940 } 35941 35942 holesMovements.push( oneHoleMovements ); 35943 verticesMovements = verticesMovements.concat( oneHoleMovements ); 35944 35945 } 35946 35947 35948 // Loop bevelSegments, 1 for the front, 1 for the back 35949 35950 for ( let b = 0; b < bevelSegments; b ++ ) { 35951 35952 //for ( b = bevelSegments; b > 0; b -- ) { 35953 35954 const t = b / bevelSegments; 35955 const z = bevelThickness * Math.cos( t * Math.PI / 2 ); 35956 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset; 35957 35958 // contract shape 35959 35960 for ( let i = 0, il = contour.length; i < il; i ++ ) { 35961 35962 const vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); 35963 35964 v( vert.x, vert.y, - z ); 35965 35966 } 35967 35968 // expand holes 35969 35970 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 35971 35972 const ahole = holes[ h ]; 35973 oneHoleMovements = holesMovements[ h ]; 35974 35975 for ( let i = 0, il = ahole.length; i < il; i ++ ) { 35976 35977 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); 35978 35979 v( vert.x, vert.y, - z ); 35980 35981 } 35982 35983 } 35984 35985 } 35986 35987 const bs = bevelSize + bevelOffset; 35988 35989 // Back facing vertices 35990 35991 for ( let i = 0; i < vlen; i ++ ) { 35992 35993 const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; 35994 35995 if ( ! extrudeByPath ) { 35996 35997 v( vert.x, vert.y, 0 ); 35998 35999 } else { 36000 36001 // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x ); 36002 36003 normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x ); 36004 binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y ); 36005 36006 position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal ); 36007 36008 v( position2.x, position2.y, position2.z ); 36009 36010 } 36011 36012 } 36013 36014 // Add stepped vertices... 36015 // Including front facing vertices 36016 36017 for ( let s = 1; s <= steps; s ++ ) { 36018 36019 for ( let i = 0; i < vlen; i ++ ) { 36020 36021 const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; 36022 36023 if ( ! extrudeByPath ) { 36024 36025 v( vert.x, vert.y, depth / steps * s ); 36026 36027 } else { 36028 36029 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x ); 36030 36031 normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x ); 36032 binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y ); 36033 36034 position2.copy( extrudePts[ s ] ).add( normal ).add( binormal ); 36035 36036 v( position2.x, position2.y, position2.z ); 36037 36038 } 36039 36040 } 36041 36042 } 36043 36044 36045 // Add bevel segments planes 36046 36047 //for ( b = 1; b <= bevelSegments; b ++ ) { 36048 for ( let b = bevelSegments - 1; b >= 0; b -- ) { 36049 36050 const t = b / bevelSegments; 36051 const z = bevelThickness * Math.cos( t * Math.PI / 2 ); 36052 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset; 36053 36054 // contract shape 36055 36056 for ( let i = 0, il = contour.length; i < il; i ++ ) { 36057 36058 const vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); 36059 v( vert.x, vert.y, depth + z ); 36060 36061 } 36062 36063 // expand holes 36064 36065 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 36066 36067 const ahole = holes[ h ]; 36068 oneHoleMovements = holesMovements[ h ]; 36069 36070 for ( let i = 0, il = ahole.length; i < il; i ++ ) { 36071 36072 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); 36073 36074 if ( ! extrudeByPath ) { 36075 36076 v( vert.x, vert.y, depth + z ); 36077 36078 } else { 36079 36080 v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z ); 36081 36082 } 36083 36084 } 36085 36086 } 36087 36088 } 36089 36090 /* Faces */ 36091 36092 // Top and bottom faces 36093 36094 buildLidFaces(); 36095 36096 // Sides faces 36097 36098 buildSideFaces(); 36099 36100 36101 ///// Internal functions 36102 36103 function buildLidFaces() { 36104 36105 const start = verticesArray.length / 3; 36106 36107 if ( bevelEnabled ) { 36108 36109 let layer = 0; // steps + 1 36110 let offset = vlen * layer; 36111 36112 // Bottom faces 36113 36114 for ( let i = 0; i < flen; i ++ ) { 36115 36116 const face = faces[ i ]; 36117 f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset ); 36118 36119 } 36120 36121 layer = steps + bevelSegments * 2; 36122 offset = vlen * layer; 36123 36124 // Top faces 36125 36126 for ( let i = 0; i < flen; i ++ ) { 36127 36128 const face = faces[ i ]; 36129 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset ); 36130 36131 } 36132 36133 } else { 36134 36135 // Bottom faces 36136 36137 for ( let i = 0; i < flen; i ++ ) { 36138 36139 const face = faces[ i ]; 36140 f3( face[ 2 ], face[ 1 ], face[ 0 ] ); 36141 36142 } 36143 36144 // Top faces 36145 36146 for ( let i = 0; i < flen; i ++ ) { 36147 36148 const face = faces[ i ]; 36149 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps ); 36150 36151 } 36152 36153 } 36154 36155 scope.addGroup( start, verticesArray.length / 3 - start, 0 ); 36156 36157 } 36158 36159 // Create faces for the z-sides of the shape 36160 36161 function buildSideFaces() { 36162 36163 const start = verticesArray.length / 3; 36164 let layeroffset = 0; 36165 sidewalls( contour, layeroffset ); 36166 layeroffset += contour.length; 36167 36168 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 36169 36170 const ahole = holes[ h ]; 36171 sidewalls( ahole, layeroffset ); 36172 36173 //, true 36174 layeroffset += ahole.length; 36175 36176 } 36177 36178 36179 scope.addGroup( start, verticesArray.length / 3 - start, 1 ); 36180 36181 36182 } 36183 36184 function sidewalls( contour, layeroffset ) { 36185 36186 let i = contour.length; 36187 36188 while ( -- i >= 0 ) { 36189 36190 const j = i; 36191 let k = i - 1; 36192 if ( k < 0 ) k = contour.length - 1; 36193 36194 //console.log('b', i,j, i-1, k,vertices.length); 36195 36196 for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) { 36197 36198 const slen1 = vlen * s; 36199 const slen2 = vlen * ( s + 1 ); 36200 36201 const a = layeroffset + j + slen1, 36202 b = layeroffset + k + slen1, 36203 c = layeroffset + k + slen2, 36204 d = layeroffset + j + slen2; 36205 36206 f4( a, b, c, d ); 36207 36208 } 36209 36210 } 36211 36212 } 36213 36214 function v( x, y, z ) { 36215 36216 placeholder.push( x ); 36217 placeholder.push( y ); 36218 placeholder.push( z ); 36219 36220 } 36221 36222 36223 function f3( a, b, c ) { 36224 36225 addVertex( a ); 36226 addVertex( b ); 36227 addVertex( c ); 36228 36229 const nextIndex = verticesArray.length / 3; 36230 const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); 36231 36232 addUV( uvs[ 0 ] ); 36233 addUV( uvs[ 1 ] ); 36234 addUV( uvs[ 2 ] ); 36235 36236 } 36237 36238 function f4( a, b, c, d ) { 36239 36240 addVertex( a ); 36241 addVertex( b ); 36242 addVertex( d ); 36243 36244 addVertex( b ); 36245 addVertex( c ); 36246 addVertex( d ); 36247 36248 36249 const nextIndex = verticesArray.length / 3; 36250 const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); 36251 36252 addUV( uvs[ 0 ] ); 36253 addUV( uvs[ 1 ] ); 36254 addUV( uvs[ 3 ] ); 36255 36256 addUV( uvs[ 1 ] ); 36257 addUV( uvs[ 2 ] ); 36258 addUV( uvs[ 3 ] ); 36259 36260 } 36261 36262 function addVertex( index ) { 36263 36264 verticesArray.push( placeholder[ index * 3 + 0 ] ); 36265 verticesArray.push( placeholder[ index * 3 + 1 ] ); 36266 verticesArray.push( placeholder[ index * 3 + 2 ] ); 36267 36268 } 36269 36270 36271 function addUV( vector2 ) { 36272 36273 uvArray.push( vector2.x ); 36274 uvArray.push( vector2.y ); 36275 36276 } 36277 36278 } 36279 36280 } 36281 36282 copy( source ) { 36283 36284 super.copy( source ); 36285 36286 this.parameters = Object.assign( {}, source.parameters ); 36287 36288 return this; 36289 36290 } 36291 36292 toJSON() { 36293 36294 const data = super.toJSON(); 36295 36296 const shapes = this.parameters.shapes; 36297 const options = this.parameters.options; 36298 36299 return toJSON$1( shapes, options, data ); 36300 36301 } 36302 36303 static fromJSON( data, shapes ) { 36304 36305 const geometryShapes = []; 36306 36307 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) { 36308 36309 const shape = shapes[ data.shapes[ j ] ]; 36310 36311 geometryShapes.push( shape ); 36312 36313 } 36314 36315 const extrudePath = data.options.extrudePath; 36316 36317 if ( extrudePath !== undefined ) { 36318 36319 data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath ); 36320 36321 } 36322 36323 return new ExtrudeGeometry( geometryShapes, data.options ); 36324 36325 } 36326 36327} 36328 36329const WorldUVGenerator = { 36330 36331 generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) { 36332 36333 const a_x = vertices[ indexA * 3 ]; 36334 const a_y = vertices[ indexA * 3 + 1 ]; 36335 const b_x = vertices[ indexB * 3 ]; 36336 const b_y = vertices[ indexB * 3 + 1 ]; 36337 const c_x = vertices[ indexC * 3 ]; 36338 const c_y = vertices[ indexC * 3 + 1 ]; 36339 36340 return [ 36341 new Vector2( a_x, a_y ), 36342 new Vector2( b_x, b_y ), 36343 new Vector2( c_x, c_y ) 36344 ]; 36345 36346 }, 36347 36348 generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) { 36349 36350 const a_x = vertices[ indexA * 3 ]; 36351 const a_y = vertices[ indexA * 3 + 1 ]; 36352 const a_z = vertices[ indexA * 3 + 2 ]; 36353 const b_x = vertices[ indexB * 3 ]; 36354 const b_y = vertices[ indexB * 3 + 1 ]; 36355 const b_z = vertices[ indexB * 3 + 2 ]; 36356 const c_x = vertices[ indexC * 3 ]; 36357 const c_y = vertices[ indexC * 3 + 1 ]; 36358 const c_z = vertices[ indexC * 3 + 2 ]; 36359 const d_x = vertices[ indexD * 3 ]; 36360 const d_y = vertices[ indexD * 3 + 1 ]; 36361 const d_z = vertices[ indexD * 3 + 2 ]; 36362 36363 if ( Math.abs( a_y - b_y ) < Math.abs( a_x - b_x ) ) { 36364 36365 return [ 36366 new Vector2( a_x, 1 - a_z ), 36367 new Vector2( b_x, 1 - b_z ), 36368 new Vector2( c_x, 1 - c_z ), 36369 new Vector2( d_x, 1 - d_z ) 36370 ]; 36371 36372 } else { 36373 36374 return [ 36375 new Vector2( a_y, 1 - a_z ), 36376 new Vector2( b_y, 1 - b_z ), 36377 new Vector2( c_y, 1 - c_z ), 36378 new Vector2( d_y, 1 - d_z ) 36379 ]; 36380 36381 } 36382 36383 } 36384 36385}; 36386 36387function toJSON$1( shapes, options, data ) { 36388 36389 data.shapes = []; 36390 36391 if ( Array.isArray( shapes ) ) { 36392 36393 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 36394 36395 const shape = shapes[ i ]; 36396 36397 data.shapes.push( shape.uuid ); 36398 36399 } 36400 36401 } else { 36402 36403 data.shapes.push( shapes.uuid ); 36404 36405 } 36406 36407 data.options = Object.assign( {}, options ); 36408 36409 if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON(); 36410 36411 return data; 36412 36413} 36414 36415class IcosahedronGeometry extends PolyhedronGeometry { 36416 36417 constructor( radius = 1, detail = 0 ) { 36418 36419 const t = ( 1 + Math.sqrt( 5 ) ) / 2; 36420 36421 const vertices = [ 36422 - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0, 36423 0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 36424 t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1 36425 ]; 36426 36427 const indices = [ 36428 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 36429 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, 36430 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 36431 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1 36432 ]; 36433 36434 super( vertices, indices, radius, detail ); 36435 36436 this.type = 'IcosahedronGeometry'; 36437 36438 this.parameters = { 36439 radius: radius, 36440 detail: detail 36441 }; 36442 36443 } 36444 36445 static fromJSON( data ) { 36446 36447 return new IcosahedronGeometry( data.radius, data.detail ); 36448 36449 } 36450 36451} 36452 36453class OctahedronGeometry extends PolyhedronGeometry { 36454 36455 constructor( radius = 1, detail = 0 ) { 36456 36457 const vertices = [ 36458 1, 0, 0, - 1, 0, 0, 0, 1, 0, 36459 0, - 1, 0, 0, 0, 1, 0, 0, - 1 36460 ]; 36461 36462 const indices = [ 36463 0, 2, 4, 0, 4, 3, 0, 3, 5, 36464 0, 5, 2, 1, 2, 5, 1, 5, 3, 36465 1, 3, 4, 1, 4, 2 36466 ]; 36467 36468 super( vertices, indices, radius, detail ); 36469 36470 this.type = 'OctahedronGeometry'; 36471 36472 this.parameters = { 36473 radius: radius, 36474 detail: detail 36475 }; 36476 36477 } 36478 36479 static fromJSON( data ) { 36480 36481 return new OctahedronGeometry( data.radius, data.detail ); 36482 36483 } 36484 36485} 36486 36487class RingGeometry extends BufferGeometry { 36488 36489 constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) { 36490 36491 super(); 36492 36493 this.type = 'RingGeometry'; 36494 36495 this.parameters = { 36496 innerRadius: innerRadius, 36497 outerRadius: outerRadius, 36498 thetaSegments: thetaSegments, 36499 phiSegments: phiSegments, 36500 thetaStart: thetaStart, 36501 thetaLength: thetaLength 36502 }; 36503 36504 thetaSegments = Math.max( 3, thetaSegments ); 36505 phiSegments = Math.max( 1, phiSegments ); 36506 36507 // buffers 36508 36509 const indices = []; 36510 const vertices = []; 36511 const normals = []; 36512 const uvs = []; 36513 36514 // some helper variables 36515 36516 let radius = innerRadius; 36517 const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments ); 36518 const vertex = new Vector3(); 36519 const uv = new Vector2(); 36520 36521 // generate vertices, normals and uvs 36522 36523 for ( let j = 0; j <= phiSegments; j ++ ) { 36524 36525 for ( let i = 0; i <= thetaSegments; i ++ ) { 36526 36527 // values are generate from the inside of the ring to the outside 36528 36529 const segment = thetaStart + i / thetaSegments * thetaLength; 36530 36531 // vertex 36532 36533 vertex.x = radius * Math.cos( segment ); 36534 vertex.y = radius * Math.sin( segment ); 36535 36536 vertices.push( vertex.x, vertex.y, vertex.z ); 36537 36538 // normal 36539 36540 normals.push( 0, 0, 1 ); 36541 36542 // uv 36543 36544 uv.x = ( vertex.x / outerRadius + 1 ) / 2; 36545 uv.y = ( vertex.y / outerRadius + 1 ) / 2; 36546 36547 uvs.push( uv.x, uv.y ); 36548 36549 } 36550 36551 // increase the radius for next row of vertices 36552 36553 radius += radiusStep; 36554 36555 } 36556 36557 // indices 36558 36559 for ( let j = 0; j < phiSegments; j ++ ) { 36560 36561 const thetaSegmentLevel = j * ( thetaSegments + 1 ); 36562 36563 for ( let i = 0; i < thetaSegments; i ++ ) { 36564 36565 const segment = i + thetaSegmentLevel; 36566 36567 const a = segment; 36568 const b = segment + thetaSegments + 1; 36569 const c = segment + thetaSegments + 2; 36570 const d = segment + 1; 36571 36572 // faces 36573 36574 indices.push( a, b, d ); 36575 indices.push( b, c, d ); 36576 36577 } 36578 36579 } 36580 36581 // build geometry 36582 36583 this.setIndex( indices ); 36584 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 36585 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 36586 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 36587 36588 } 36589 36590 copy( source ) { 36591 36592 super.copy( source ); 36593 36594 this.parameters = Object.assign( {}, source.parameters ); 36595 36596 return this; 36597 36598 } 36599 36600 static fromJSON( data ) { 36601 36602 return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength ); 36603 36604 } 36605 36606} 36607 36608class ShapeGeometry extends BufferGeometry { 36609 36610 constructor( shapes = new Shape( [ new Vector2( 0, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), curveSegments = 12 ) { 36611 36612 super(); 36613 36614 this.type = 'ShapeGeometry'; 36615 36616 this.parameters = { 36617 shapes: shapes, 36618 curveSegments: curveSegments 36619 }; 36620 36621 // buffers 36622 36623 const indices = []; 36624 const vertices = []; 36625 const normals = []; 36626 const uvs = []; 36627 36628 // helper variables 36629 36630 let groupStart = 0; 36631 let groupCount = 0; 36632 36633 // allow single and array values for "shapes" parameter 36634 36635 if ( Array.isArray( shapes ) === false ) { 36636 36637 addShape( shapes ); 36638 36639 } else { 36640 36641 for ( let i = 0; i < shapes.length; i ++ ) { 36642 36643 addShape( shapes[ i ] ); 36644 36645 this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support 36646 36647 groupStart += groupCount; 36648 groupCount = 0; 36649 36650 } 36651 36652 } 36653 36654 // build geometry 36655 36656 this.setIndex( indices ); 36657 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,874 bytes, lines 36658-36904
36658 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 36659 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 36660 36661 36662 // helper functions 36663 36664 function addShape( shape ) { 36665 36666 const indexOffset = vertices.length / 3; 36667 const points = shape.extractPoints( curveSegments ); 36668 36669 let shapeVertices = points.shape; 36670 const shapeHoles = points.holes; 36671 36672 // check direction of vertices 36673 36674 if ( ShapeUtils.isClockWise( shapeVertices ) === false ) { 36675 36676 shapeVertices = shapeVertices.reverse(); 36677 36678 } 36679 36680 for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) { 36681 36682 const shapeHole = shapeHoles[ i ]; 36683 36684 if ( ShapeUtils.isClockWise( shapeHole ) === true ) { 36685 36686 shapeHoles[ i ] = shapeHole.reverse(); 36687 36688 } 36689 36690 } 36691 36692 const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles ); 36693 36694 // join vertices of inner and outer paths to a single array 36695 36696 for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) { 36697 36698 const shapeHole = shapeHoles[ i ]; 36699 shapeVertices = shapeVertices.concat( shapeHole ); 36700 36701 } 36702 36703 // vertices, normals, uvs 36704 36705 for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) { 36706 36707 const vertex = shapeVertices[ i ]; 36708 36709 vertices.push( vertex.x, vertex.y, 0 ); 36710 normals.push( 0, 0, 1 ); 36711 uvs.push( vertex.x, vertex.y ); // world uvs 36712 36713 } 36714 36715 // indices 36716 36717 for ( let i = 0, l = faces.length; i < l; i ++ ) { 36718 36719 const face = faces[ i ]; 36720 36721 const a = face[ 0 ] + indexOffset; 36722 const b = face[ 1 ] + indexOffset; 36723 const c = face[ 2 ] + indexOffset; 36724 36725 indices.push( a, b, c ); 36726 groupCount += 3; 36727 36728 } 36729 36730 } 36731 36732 } 36733 36734 copy( source ) { 36735 36736 super.copy( source ); 36737 36738 this.parameters = Object.assign( {}, source.parameters ); 36739 36740 return this; 36741 36742 } 36743 36744 toJSON() { 36745 36746 const data = super.toJSON(); 36747 36748 const shapes = this.parameters.shapes; 36749 36750 return toJSON( shapes, data ); 36751 36752 } 36753 36754 static fromJSON( data, shapes ) { 36755 36756 const geometryShapes = []; 36757 36758 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) { 36759 36760 const shape = shapes[ data.shapes[ j ] ]; 36761 36762 geometryShapes.push( shape ); 36763 36764 } 36765 36766 return new ShapeGeometry( geometryShapes, data.curveSegments ); 36767 36768 } 36769 36770} 36771 36772function toJSON( shapes, data ) { 36773 36774 data.shapes = []; 36775 36776 if ( Array.isArray( shapes ) ) { 36777 36778 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 36779 36780 const shape = shapes[ i ]; 36781 36782 data.shapes.push( shape.uuid ); 36783 36784 } 36785 36786 } else { 36787 36788 data.shapes.push( shapes.uuid ); 36789 36790 } 36791 36792 return data; 36793 36794} 36795 36796class SphereGeometry extends BufferGeometry { 36797 36798 constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) { 36799 36800 super(); 36801 36802 this.type = 'SphereGeometry'; 36803 36804 this.parameters = { 36805 radius: radius, 36806 widthSegments: widthSegments, 36807 heightSegments: heightSegments, 36808 phiStart: phiStart, 36809 phiLength: phiLength, 36810 thetaStart: thetaStart, 36811 thetaLength: thetaLength 36812 }; 36813 36814 widthSegments = Math.max( 3, Math.floor( widthSegments ) ); 36815 heightSegments = Math.max( 2, Math.floor( heightSegments ) ); 36816 36817 const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI ); 36818 36819 let index = 0; 36820 const grid = []; 36821 36822 const vertex = new Vector3(); 36823 const normal = new Vector3(); 36824 36825 // buffers 36826 36827 const indices = []; 36828 const vertices = []; 36829 const normals = []; 36830 const uvs = []; 36831 36832 // generate vertices, normals and uvs 36833 36834 for ( let iy = 0; iy <= heightSegments; iy ++ ) { 36835 36836 const verticesRow = []; 36837 36838 const v = iy / heightSegments; 36839 36840 // special case for the poles 36841 36842 let uOffset = 0; 36843 36844 if ( iy == 0 && thetaStart == 0 ) { 36845 36846 uOffset = 0.5 / widthSegments; 36847 36848 } else if ( iy == heightSegments && thetaEnd == Math.PI ) { 36849 36850 uOffset = - 0.5 / widthSegments; 36851 36852 } 36853 36854 for ( let ix = 0; ix <= widthSegments; ix ++ ) { 36855 36856 const u = ix / widthSegments; 36857 36858 // vertex 36859 36860 vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); 36861 vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); 36862 vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); 36863 36864 vertices.push( vertex.x, vertex.y, vertex.z ); 36865 36866 // normal 36867 36868 normal.copy( vertex ).normalize(); 36869 normals.push( normal.x, normal.y, normal.z ); 36870 36871 // uv 36872 36873 uvs.push( u + uOffset, 1 - v ); 36874 36875 verticesRow.push( index ++ ); 36876 36877 } 36878 36879 grid.push( verticesRow ); 36880 36881 } 36882 36883 // indices 36884 36885 for ( let iy = 0; iy < heightSegments; iy ++ ) { 36886 36887 for ( let ix = 0; ix < widthSegments; ix ++ ) { 36888 36889 const a = grid[ iy ][ ix + 1 ]; 36890 const b = grid[ iy ][ ix ]; 36891 const c = grid[ iy + 1 ][ ix ]; 36892 const d = grid[ iy + 1 ][ ix + 1 ]; 36893 36894 if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d ); 36895 if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d ); 36896 36897 } 36898 36899 } 36900 36901 // build geometry 36902 36903 this.setIndex( indices ); 36904 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 6,566 bytes, lines 36905-37197
36905 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 36906 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 36907 36908 } 36909 36910 copy( source ) { 36911 36912 super.copy( source ); 36913 36914 this.parameters = Object.assign( {}, source.parameters ); 36915 36916 return this; 36917 36918 } 36919 36920 static fromJSON( data ) { 36921 36922 return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); 36923 36924 } 36925 36926} 36927 36928class TetrahedronGeometry extends PolyhedronGeometry { 36929 36930 constructor( radius = 1, detail = 0 ) { 36931 36932 const vertices = [ 36933 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1 36934 ]; 36935 36936 const indices = [ 36937 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 36938 ]; 36939 36940 super( vertices, indices, radius, detail ); 36941 36942 this.type = 'TetrahedronGeometry'; 36943 36944 this.parameters = { 36945 radius: radius, 36946 detail: detail 36947 }; 36948 36949 } 36950 36951 static fromJSON( data ) { 36952 36953 return new TetrahedronGeometry( data.radius, data.detail ); 36954 36955 } 36956 36957} 36958 36959class TorusGeometry extends BufferGeometry { 36960 36961 constructor( radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2 ) { 36962 36963 super(); 36964 36965 this.type = 'TorusGeometry'; 36966 36967 this.parameters = { 36968 radius: radius, 36969 tube: tube, 36970 radialSegments: radialSegments, 36971 tubularSegments: tubularSegments, 36972 arc: arc 36973 }; 36974 36975 radialSegments = Math.floor( radialSegments ); 36976 tubularSegments = Math.floor( tubularSegments ); 36977 36978 // buffers 36979 36980 const indices = []; 36981 const vertices = []; 36982 const normals = []; 36983 const uvs = []; 36984 36985 // helper variables 36986 36987 const center = new Vector3(); 36988 const vertex = new Vector3(); 36989 const normal = new Vector3(); 36990 36991 // generate vertices, normals and uvs 36992 36993 for ( let j = 0; j <= radialSegments; j ++ ) { 36994 36995 for ( let i = 0; i <= tubularSegments; i ++ ) { 36996 36997 const u = i / tubularSegments * arc; 36998 const v = j / radialSegments * Math.PI * 2; 36999 37000 // vertex 37001 37002 vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u ); 37003 vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u ); 37004 vertex.z = tube * Math.sin( v ); 37005 37006 vertices.push( vertex.x, vertex.y, vertex.z ); 37007 37008 // normal 37009 37010 center.x = radius * Math.cos( u ); 37011 center.y = radius * Math.sin( u ); 37012 normal.subVectors( vertex, center ).normalize(); 37013 37014 normals.push( normal.x, normal.y, normal.z ); 37015 37016 // uv 37017 37018 uvs.push( i / tubularSegments ); 37019 uvs.push( j / radialSegments ); 37020 37021 } 37022 37023 } 37024 37025 // generate indices 37026 37027 for ( let j = 1; j <= radialSegments; j ++ ) { 37028 37029 for ( let i = 1; i <= tubularSegments; i ++ ) { 37030 37031 // indices 37032 37033 const a = ( tubularSegments + 1 ) * j + i - 1; 37034 const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1; 37035 const c = ( tubularSegments + 1 ) * ( j - 1 ) + i; 37036 const d = ( tubularSegments + 1 ) * j + i; 37037 37038 // faces 37039 37040 indices.push( a, b, d ); 37041 indices.push( b, c, d ); 37042 37043 } 37044 37045 } 37046 37047 // build geometry 37048 37049 this.setIndex( indices ); 37050 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 37051 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 37052 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 37053 37054 } 37055 37056 copy( source ) { 37057 37058 super.copy( source ); 37059 37060 this.parameters = Object.assign( {}, source.parameters ); 37061 37062 return this; 37063 37064 } 37065 37066 static fromJSON( data ) { 37067 37068 return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc ); 37069 37070 } 37071 37072} 37073 37074class TorusKnotGeometry extends BufferGeometry { 37075 37076 constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) { 37077 37078 super(); 37079 37080 this.type = 'TorusKnotGeometry'; 37081 37082 this.parameters = { 37083 radius: radius, 37084 tube: tube, 37085 tubularSegments: tubularSegments, 37086 radialSegments: radialSegments, 37087 p: p, 37088 q: q 37089 }; 37090 37091 tubularSegments = Math.floor( tubularSegments ); 37092 radialSegments = Math.floor( radialSegments ); 37093 37094 // buffers 37095 37096 const indices = []; 37097 const vertices = []; 37098 const normals = []; 37099 const uvs = []; 37100 37101 // helper variables 37102 37103 const vertex = new Vector3(); 37104 const normal = new Vector3(); 37105 37106 const P1 = new Vector3(); 37107 const P2 = new Vector3(); 37108 37109 const B = new Vector3(); 37110 const T = new Vector3(); 37111 const N = new Vector3(); 37112 37113 // generate vertices, normals and uvs 37114 37115 for ( let i = 0; i <= tubularSegments; ++ i ) { 37116 37117 // the radian "u" is used to calculate the position on the torus curve of the current tubular segment 37118 37119 const u = i / tubularSegments * p * Math.PI * 2; 37120 37121 // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead. 37122 // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions 37123 37124 calculatePositionOnCurve( u, p, q, radius, P1 ); 37125 calculatePositionOnCurve( u + 0.01, p, q, radius, P2 ); 37126 37127 // calculate orthonormal basis 37128 37129 T.subVectors( P2, P1 ); 37130 N.addVectors( P2, P1 ); 37131 B.crossVectors( T, N ); 37132 N.crossVectors( B, T ); 37133 37134 // normalize B, N. T can be ignored, we don't use it 37135 37136 B.normalize(); 37137 N.normalize(); 37138 37139 for ( let j = 0; j <= radialSegments; ++ j ) { 37140 37141 // now calculate the vertices. they are nothing more than an extrusion of the torus curve. 37142 // because we extrude a shape in the xy-plane, there is no need to calculate a z-value. 37143 37144 const v = j / radialSegments * Math.PI * 2; 37145 const cx = - tube * Math.cos( v ); 37146 const cy = tube * Math.sin( v ); 37147 37148 // now calculate the final vertex position. 37149 // first we orient the extrusion with our basis vectors, then we add it to the current position on the curve 37150 37151 vertex.x = P1.x + ( cx * N.x + cy * B.x ); 37152 vertex.y = P1.y + ( cx * N.y + cy * B.y ); 37153 vertex.z = P1.z + ( cx * N.z + cy * B.z ); 37154 37155 vertices.push( vertex.x, vertex.y, vertex.z ); 37156 37157 // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal) 37158 37159 normal.subVectors( vertex, P1 ).normalize(); 37160 37161 normals.push( normal.x, normal.y, normal.z ); 37162 37163 // uv 37164 37165 uvs.push( i / tubularSegments ); 37166 uvs.push( j / radialSegments ); 37167 37168 } 37169 37170 } 37171 37172 // generate indices 37173 37174 for ( let j = 1; j <= tubularSegments; j ++ ) { 37175 37176 for ( let i = 1; i <= radialSegments; i ++ ) { 37177 37178 // indices 37179 37180 const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); 37181 const b = ( radialSegments + 1 ) * j + ( i - 1 ); 37182 const c = ( radialSegments + 1 ) * j + i; 37183 const d = ( radialSegments + 1 ) * ( j - 1 ) + i; 37184 37185 // faces 37186 37187 indices.push( a, b, d ); 37188 indices.push( b, c, d ); 37189 37190 } 37191 37192 } 37193 37194 // build geometry 37195 37196 this.setIndex( indices ); 37197 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 7,450 bytes, lines 37198-37556
37198 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 37199 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 37200 37201 // this function calculates the current position on the torus curve 37202 37203 function calculatePositionOnCurve( u, p, q, radius, position ) { 37204 37205 const cu = Math.cos( u ); 37206 const su = Math.sin( u ); 37207 const quOverP = q / p * u; 37208 const cs = Math.cos( quOverP ); 37209 37210 position.x = radius * ( 2 + cs ) * 0.5 * cu; 37211 position.y = radius * ( 2 + cs ) * su * 0.5; 37212 position.z = radius * Math.sin( quOverP ) * 0.5; 37213 37214 } 37215 37216 } 37217 37218 copy( source ) { 37219 37220 super.copy( source ); 37221 37222 this.parameters = Object.assign( {}, source.parameters ); 37223 37224 return this; 37225 37226 } 37227 37228 static fromJSON( data ) { 37229 37230 return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q ); 37231 37232 } 37233 37234} 37235 37236class TubeGeometry extends BufferGeometry { 37237 37238 constructor( path = new QuadraticBezierCurve3( new Vector3( - 1, - 1, 0 ), new Vector3( - 1, 1, 0 ), new Vector3( 1, 1, 0 ) ), tubularSegments = 64, radius = 1, radialSegments = 8, closed = false ) { 37239 37240 super(); 37241 37242 this.type = 'TubeGeometry'; 37243 37244 this.parameters = { 37245 path: path, 37246 tubularSegments: tubularSegments, 37247 radius: radius, 37248 radialSegments: radialSegments, 37249 closed: closed 37250 }; 37251 37252 const frames = path.computeFrenetFrames( tubularSegments, closed ); 37253 37254 // expose internals 37255 37256 this.tangents = frames.tangents; 37257 this.normals = frames.normals; 37258 this.binormals = frames.binormals; 37259 37260 // helper variables 37261 37262 const vertex = new Vector3(); 37263 const normal = new Vector3(); 37264 const uv = new Vector2(); 37265 let P = new Vector3(); 37266 37267 // buffer 37268 37269 const vertices = []; 37270 const normals = []; 37271 const uvs = []; 37272 const indices = []; 37273 37274 // create buffer data 37275 37276 generateBufferData(); 37277 37278 // build geometry 37279 37280 this.setIndex( indices ); 37281 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 37282 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 37283 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 37284 37285 // functions 37286 37287 function generateBufferData() { 37288 37289 for ( let i = 0; i < tubularSegments; i ++ ) { 37290 37291 generateSegment( i ); 37292 37293 } 37294 37295 // if the geometry is not closed, generate the last row of vertices and normals 37296 // at the regular position on the given path 37297 // 37298 // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ) 37299 37300 generateSegment( ( closed === false ) ? tubularSegments : 0 ); 37301 37302 // uvs are generated in a separate function. 37303 // this makes it easy compute correct values for closed geometries 37304 37305 generateUVs(); 37306 37307 // finally create faces 37308 37309 generateIndices(); 37310 37311 } 37312 37313 function generateSegment( i ) { 37314 37315 // we use getPointAt to sample evenly distributed points from the given path 37316 37317 P = path.getPointAt( i / tubularSegments, P ); 37318 37319 // retrieve corresponding normal and binormal 37320 37321 const N = frames.normals[ i ]; 37322 const B = frames.binormals[ i ]; 37323 37324 // generate normals and vertices for the current segment 37325 37326 for ( let j = 0; j <= radialSegments; j ++ ) { 37327 37328 const v = j / radialSegments * Math.PI * 2; 37329 37330 const sin = Math.sin( v ); 37331 const cos = - Math.cos( v ); 37332 37333 // normal 37334 37335 normal.x = ( cos * N.x + sin * B.x ); 37336 normal.y = ( cos * N.y + sin * B.y ); 37337 normal.z = ( cos * N.z + sin * B.z ); 37338 normal.normalize(); 37339 37340 normals.push( normal.x, normal.y, normal.z ); 37341 37342 // vertex 37343 37344 vertex.x = P.x + radius * normal.x; 37345 vertex.y = P.y + radius * normal.y; 37346 vertex.z = P.z + radius * normal.z; 37347 37348 vertices.push( vertex.x, vertex.y, vertex.z ); 37349 37350 } 37351 37352 } 37353 37354 function generateIndices() { 37355 37356 for ( let j = 1; j <= tubularSegments; j ++ ) { 37357 37358 for ( let i = 1; i <= radialSegments; i ++ ) { 37359 37360 const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); 37361 const b = ( radialSegments + 1 ) * j + ( i - 1 ); 37362 const c = ( radialSegments + 1 ) * j + i; 37363 const d = ( radialSegments + 1 ) * ( j - 1 ) + i; 37364 37365 // faces 37366 37367 indices.push( a, b, d ); 37368 indices.push( b, c, d ); 37369 37370 } 37371 37372 } 37373 37374 } 37375 37376 function generateUVs() { 37377 37378 for ( let i = 0; i <= tubularSegments; i ++ ) { 37379 37380 for ( let j = 0; j <= radialSegments; j ++ ) { 37381 37382 uv.x = i / tubularSegments; 37383 uv.y = j / radialSegments; 37384 37385 uvs.push( uv.x, uv.y ); 37386 37387 } 37388 37389 } 37390 37391 } 37392 37393 } 37394 37395 copy( source ) { 37396 37397 super.copy( source ); 37398 37399 this.parameters = Object.assign( {}, source.parameters ); 37400 37401 return this; 37402 37403 } 37404 37405 toJSON() { 37406 37407 const data = super.toJSON(); 37408 37409 data.path = this.parameters.path.toJSON(); 37410 37411 return data; 37412 37413 } 37414 37415 static fromJSON( data ) { 37416 37417 // This only works for built-in curves (e.g. CatmullRomCurve3). 37418 // User defined curves or instances of CurvePath will not be deserialized. 37419 return new TubeGeometry( 37420 new Curves[ data.path.type ]().fromJSON( data.path ), 37421 data.tubularSegments, 37422 data.radius, 37423 data.radialSegments, 37424 data.closed 37425 ); 37426 37427 } 37428 37429} 37430 37431class WireframeGeometry extends BufferGeometry { 37432 37433 constructor( geometry = null ) { 37434 37435 super(); 37436 37437 this.type = 'WireframeGeometry'; 37438 37439 this.parameters = { 37440 geometry: geometry 37441 }; 37442 37443 if ( geometry !== null ) { 37444 37445 // buffer 37446 37447 const vertices = []; 37448 const edges = new Set(); 37449 37450 // helper variables 37451 37452 const start = new Vector3(); 37453 const end = new Vector3(); 37454 37455 if ( geometry.index !== null ) { 37456 37457 // indexed BufferGeometry 37458 37459 const position = geometry.attributes.position; 37460 const indices = geometry.index; 37461 let groups = geometry.groups; 37462 37463 if ( groups.length === 0 ) { 37464 37465 groups = [ { start: 0, count: indices.count, materialIndex: 0 } ]; 37466 37467 } 37468 37469 // create a data structure that contains all edges without duplicates 37470 37471 for ( let o = 0, ol = groups.length; o < ol; ++ o ) { 37472 37473 const group = groups[ o ]; 37474 37475 const groupStart = group.start; 37476 const groupCount = group.count; 37477 37478 for ( let i = groupStart, l = ( groupStart + groupCount ); i < l; i += 3 ) { 37479 37480 for ( let j = 0; j < 3; j ++ ) { 37481 37482 const index1 = indices.getX( i + j ); 37483 const index2 = indices.getX( i + ( j + 1 ) % 3 ); 37484 37485 start.fromBufferAttribute( position, index1 ); 37486 end.fromBufferAttribute( position, index2 ); 37487 37488 if ( isUniqueEdge( start, end, edges ) === true ) { 37489 37490 vertices.push( start.x, start.y, start.z ); 37491 vertices.push( end.x, end.y, end.z ); 37492 37493 } 37494 37495 } 37496 37497 } 37498 37499 } 37500 37501 } else { 37502 37503 // non-indexed BufferGeometry 37504 37505 const position = geometry.attributes.position; 37506 37507 for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) { 37508 37509 for ( let j = 0; j < 3; j ++ ) { 37510 37511 // three edges per triangle, an edge is represented as (index1, index2) 37512 // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0) 37513 37514 const index1 = 3 * i + j; 37515 const index2 = 3 * i + ( ( j + 1 ) % 3 ); 37516 37517 start.fromBufferAttribute( position, index1 ); 37518 end.fromBufferAttribute( position, index2 ); 37519 37520 if ( isUniqueEdge( start, end, edges ) === true ) { 37521 37522 vertices.push( start.x, start.y, start.z ); 37523 vertices.push( end.x, end.y, end.z ); 37524 37525 } 37526 37527 } 37528 37529 } 37530 37531 } 37532 37533 // build geometry 37534 37535 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 37536 37537 } 37538 37539 } 37540 37541 copy( source ) { 37542 37543 super.copy( source ); 37544 37545 this.parameters = Object.assign( {}, source.parameters ); 37546 37547 return this; 37548 37549 } 37550 37551} 37552 37553function isUniqueEdge( start, end, edges ) { 37554 37555 const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`; 37556 const hash2 = `${end.x}
37556,${end.y},${end.z}-${start.x},${start.y},${start.z}`; // coincident edge 37557 37558 if ( edges.has( hash1 ) === true || edges.has( hash2 ) === true ) { 37559 37560 return false; 37561 37562 } else { 37563 37564 edges.add( hash1 ); 37565 edges.add( hash2 ); 37566 return true; 37567 37568 } 37569 37570} 37571 37572var Geometries = /*#__PURE__*/Object.freeze({ 37573 __proto__: null, 37574 BoxGeometry: BoxGeometry, 37575 CapsuleGeometry: CapsuleGeometry, 37576 CircleGeometry: CircleGeometry, 37577 ConeGeometry: ConeGeometry, 37578 CylinderGeometry: CylinderGeometry, 37579 DodecahedronGeometry: DodecahedronGeometry, 37580 EdgesGeometry: EdgesGeometry, 37581 ExtrudeGeometry: ExtrudeGeometry, 37582 IcosahedronGeometry: IcosahedronGeometry, 37583 LatheGeometry: LatheGeometry, 37584 OctahedronGeometry: OctahedronGeometry, 37585 PlaneGeometry: PlaneGeometry, 37586 PolyhedronGeometry: PolyhedronGeometry, 37587 RingGeometry: RingGeometry, 37588 ShapeGeometry: ShapeGeometry, 37589 SphereGeometry: SphereGeometry, 37590 TetrahedronGeometry: TetrahedronGeometry, 37591 TorusGeometry: TorusGeometry, 37592 TorusKnotGeometry: TorusKnotGeometry, 37593 TubeGeometry: TubeGeometry, 37594 WireframeGeometry: WireframeGeometry 37595}); 37596 37597class ShadowMaterial extends Material { 37598 37599 constructor( parameters ) { 37600 37601 super(); 37602 37603 this.isShadowMaterial = true; 37604 37605 this.type = 'ShadowMaterial'; 37606 37607 this.color = new Color( 0x000000 ); 37608 this.transparent = true; 37609 37610 this.fog = true; 37611 37612 this.setValues( parameters ); 37613 37614 } 37615 37616 copy( source ) { 37617 37618 super.copy( source ); 37619 37620 this.color.copy( source.color ); 37621 37622 this.fog = source.fog; 37623 37624 return this; 37625 37626 } 37627 37628} 37629 37630class RawShaderMaterial extends ShaderMaterial { 37631 37632 constructor( parameters ) { 37633 37634 super( parameters ); 37635 37636 this.isRawShaderMaterial = true; 37637 37638 this.type = 'RawShaderMaterial'; 37639 37640 } 37641 37642} 37643 37644class MeshStandardMaterial extends Material { 37645 37646 constructor( parameters ) { 37647 37648 super(); 37649 37650 this.isMeshStandardMaterial = true; 37651 37652 this.defines = { 'STANDARD': '' }; 37653 37654 this.type = 'MeshStandardMaterial'; 37655 37656 this.color = new Color( 0xffffff ); // diffuse 37657 this.roughness = 1.0; 37658 this.metalness = 0.0; 37659 37660 this.map = null; 37661 37662 this.lightMap = null; 37663 this.lightMapIntensity = 1.0; 37664 37665 this.aoMap = null; 37666 this.aoMapIntensity = 1.0; 37667 37668 this.emissive = new Color( 0x000000 ); 37669 this.emissiveIntensity = 1.0; 37670 this.emissiveMap = null; 37671 37672 this.bumpMap = null; 37673 this.bumpScale = 1; 37674 37675 this.normalMap = null; 37676 this.normalMapType = TangentSpaceNormalMap; 37677 this.normalScale = new Vector2( 1, 1 ); 37678 37679 this.displacementMap = null; 37680 this.displacementScale = 1; 37681 this.displacementBias = 0; 37682 37683 this.roughnessMap = null; 37684 37685 this.metalnessMap = null; 37686 37687 this.alphaMap = null; 37688 37689 this.envMap = null; 37690 this.envMapIntensity = 1.0; 37691 37692 this.wireframe = false; 37693 this.wireframeLinewidth = 1; 37694 this.wireframeLinecap = 'round'; 37695 this.wireframeLinejoin = 'round'; 37696 37697 this.flatShading = false; 37698 37699 this.fog = true; 37700 37701 this.setValues( parameters ); 37702 37703 } 37704 37705 copy( source ) { 37706 37707 super.copy( source ); 37708 37709 this.defines = { 'STANDARD': '' }; 37710 37711 this.color.copy( source.color ); 37712 this.roughness = source.roughness; 37713 this.metalness = source.metalness; 37714 37715 this.map = source.map; 37716 37717 this.lightMap = source.lightMap; 37718 this.lightMapIntensity = source.lightMapIntensity; 37719 37720 this.aoMap = source.aoMap; 37721 this.aoMapIntensity = source.aoMapIntensity; 37722 37723 this.emissive.copy( source.emissive ); 37724 this.emissiveMap = source.emissiveMap; 37725 this.emissiveIntensity = source.emissiveIntensity; 37726 37727 this.bumpMap = source.bumpMap; 37728 this.bumpScale = source.bumpScale; 37729 37730 this.normalMap = source.normalMap; 37731 this.normalMapType = source.normalMapType; 37732 this.normalScale.copy( source.normalScale ); 37733 37734 this.displacementMap = source.displacementMap; 37735 this.displacementScale = source.displacementScale; 37736 this.displacementBias = source.displacementBias; 37737 37738 this.roughnessMap = source.roughnessMap; 37739 37740 this.metalnessMap = source.metalnessMap; 37741 37742 this.alphaMap = source.alphaMap; 37743 37744 this.envMap = source.envMap; 37745 this.envMapIntensity = source.envMapIntensity; 37746 37747 this.wireframe = source.wireframe; 37748 this.wireframeLinewidth = source.wireframeLinewidth; 37749 this.wireframeLinecap = source.wireframeLinecap; 37750 this.wireframeLinejoin = source.wireframeLinejoin; 37751 37752 this.flatShading = source.flatShading; 37753 37754 this.fog = source.fog; 37755 37756 return this; 37757 37758 } 37759 37760} 37761 37762class MeshPhysicalMaterial extends MeshStandardMaterial { 37763 37764 constructor( parameters ) { 37765 37766 super(); 37767 37768 this.isMeshPhysicalMaterial = true; 37769 37770 this.defines = { 37771 37772 'STANDARD': '', 37773 'PHYSICAL': '' 37774 37775 }; 37776 37777 this.type = 'MeshPhysicalMaterial'; 37778 37779 this.clearcoatMap = null; 37780 this.clearcoatRoughness = 0.0; 37781 this.clearcoatRoughnessMap = null; 37782 this.clearcoatNormalScale = new Vector2( 1, 1 ); 37783 this.clearcoatNormalMap = null; 37784 37785 this.ior = 1.5; 37786 37787 Object.defineProperty( this, 'reflectivity', { 37788 get: function () { 37789 37790 return ( clamp( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) ); 37791 37792 },
vendor: 8,621 bytes, lines 37793-38211
37793 set: function ( reflectivity ) { 37794 37795 this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity ); 37796 37797 } 37798 } ); 37799 37800 this.iridescenceMap = null; 37801 this.iridescenceIOR = 1.3; 37802 this.iridescenceThicknessRange = [ 100, 400 ]; 37803 this.iridescenceThicknessMap = null; 37804 37805 this.sheenColor = new Color( 0x000000 ); 37806 this.sheenColorMap = null; 37807 this.sheenRoughness = 1.0; 37808 this.sheenRoughnessMap = null; 37809 37810 this.transmissionMap = null; 37811 37812 this.thickness = 0; 37813 this.thicknessMap = null; 37814 this.attenuationDistance = Infinity; 37815 this.attenuationColor = new Color( 1, 1, 1 ); 37816 37817 this.specularIntensity = 1.0; 37818 this.specularIntensityMap = null; 37819 this.specularColor = new Color( 1, 1, 1 ); 37820 this.specularColorMap = null; 37821 37822 this._sheen = 0.0; 37823 this._clearcoat = 0; 37824 this._iridescence = 0; 37825 this._transmission = 0; 37826 37827 this.setValues( parameters ); 37828 37829 } 37830 37831 get sheen() { 37832 37833 return this._sheen; 37834 37835 } 37836 37837 set sheen( value ) { 37838 37839 if ( this._sheen > 0 !== value > 0 ) { 37840 37841 this.version ++; 37842 37843 } 37844 37845 this._sheen = value; 37846 37847 } 37848 37849 get clearcoat() { 37850 37851 return this._clearcoat; 37852 37853 } 37854 37855 set clearcoat( value ) { 37856 37857 if ( this._clearcoat > 0 !== value > 0 ) { 37858 37859 this.version ++; 37860 37861 } 37862 37863 this._clearcoat = value; 37864 37865 } 37866 37867 get iridescence() { 37868 37869 return this._iridescence; 37870 37871 } 37872 37873 set iridescence( value ) { 37874 37875 if ( this._iridescence > 0 !== value > 0 ) { 37876 37877 this.version ++; 37878 37879 } 37880 37881 this._iridescence = value; 37882 37883 } 37884 37885 get transmission() { 37886 37887 return this._transmission; 37888 37889 } 37890 37891 set transmission( value ) { 37892 37893 if ( this._transmission > 0 !== value > 0 ) { 37894 37895 this.version ++; 37896 37897 } 37898 37899 this._transmission = value; 37900 37901 } 37902 37903 copy( source ) { 37904 37905 super.copy( source ); 37906 37907 this.defines = { 37908 37909 'STANDARD': '', 37910 'PHYSICAL': '' 37911 37912 }; 37913 37914 this.clearcoat = source.clearcoat; 37915 this.clearcoatMap = source.clearcoatMap; 37916 this.clearcoatRoughness = source.clearcoatRoughness; 37917 this.clearcoatRoughnessMap = source.clearcoatRoughnessMap; 37918 this.clearcoatNormalMap = source.clearcoatNormalMap; 37919 this.clearcoatNormalScale.copy( source.clearcoatNormalScale ); 37920 37921 this.ior = source.ior; 37922 37923 this.iridescence = source.iridescence; 37924 this.iridescenceMap = source.iridescenceMap; 37925 this.iridescenceIOR = source.iridescenceIOR; 37926 this.iridescenceThicknessRange = [ ...source.iridescenceThicknessRange ]; 37927 this.iridescenceThicknessMap = source.iridescenceThicknessMap; 37928 37929 this.sheen = source.sheen; 37930 this.sheenColor.copy( source.sheenColor ); 37931 this.sheenColorMap = source.sheenColorMap; 37932 this.sheenRoughness = source.sheenRoughness; 37933 this.sheenRoughnessMap = source.sheenRoughnessMap; 37934 37935 this.transmission = source.transmission; 37936 this.transmissionMap = source.transmissionMap; 37937 37938 this.thickness = source.thickness; 37939 this.thicknessMap = source.thicknessMap; 37940 this.attenuationDistance = source.attenuationDistance; 37941 this.attenuationColor.copy( source.attenuationColor ); 37942 37943 this.specularIntensity = source.specularIntensity; 37944 this.specularIntensityMap = source.specularIntensityMap; 37945 this.specularColor.copy( source.specularColor ); 37946 this.specularColorMap = source.specularColorMap; 37947 37948 return this; 37949 37950 } 37951 37952} 37953 37954class MeshPhongMaterial extends Material { 37955 37956 constructor( parameters ) { 37957 37958 super(); 37959 37960 this.isMeshPhongMaterial = true; 37961 37962 this.type = 'MeshPhongMaterial'; 37963 37964 this.color = new Color( 0xffffff ); // diffuse 37965 this.specular = new Color( 0x111111 ); 37966 this.shininess = 30; 37967 37968 this.map = null; 37969 37970 this.lightMap = null; 37971 this.lightMapIntensity = 1.0; 37972 37973 this.aoMap = null; 37974 this.aoMapIntensity = 1.0; 37975 37976 this.emissive = new Color( 0x000000 ); 37977 this.emissiveIntensity = 1.0; 37978 this.emissiveMap = null; 37979 37980 this.bumpMap = null; 37981 this.bumpScale = 1; 37982 37983 this.normalMap = null; 37984 this.normalMapType = TangentSpaceNormalMap; 37985 this.normalScale = new Vector2( 1, 1 ); 37986 37987 this.displacementMap = null; 37988 this.displacementScale = 1; 37989 this.displacementBias = 0; 37990 37991 this.specularMap = null; 37992 37993 this.alphaMap = null; 37994 37995 this.envMap = null; 37996 this.combine = MultiplyOperation; 37997 this.reflectivity = 1; 37998 this.refractionRatio = 0.98; 37999 38000 this.wireframe = false; 38001 this.wireframeLinewidth = 1; 38002 this.wireframeLinecap = 'round'; 38003 this.wireframeLinejoin = 'round'; 38004 38005 this.flatShading = false; 38006 38007 this.fog = true; 38008 38009 this.setValues( parameters ); 38010 38011 } 38012 38013 copy( source ) { 38014 38015 super.copy( source ); 38016 38017 this.color.copy( source.color ); 38018 this.specular.copy( source.specular ); 38019 this.shininess = source.shininess; 38020 38021 this.map = source.map; 38022 38023 this.lightMap = source.lightMap; 38024 this.lightMapIntensity = source.lightMapIntensity; 38025 38026 this.aoMap = source.aoMap; 38027 this.aoMapIntensity = source.aoMapIntensity; 38028 38029 this.emissive.copy( source.emissive ); 38030 this.emissiveMap = source.emissiveMap; 38031 this.emissiveIntensity = source.emissiveIntensity; 38032 38033 this.bumpMap = source.bumpMap; 38034 this.bumpScale = source.bumpScale; 38035 38036 this.normalMap = source.normalMap; 38037 this.normalMapType = source.normalMapType; 38038 this.normalScale.copy( source.normalScale ); 38039 38040 this.displacementMap = source.displacementMap; 38041 this.displacementScale = source.displacementScale; 38042 this.displacementBias = source.displacementBias; 38043 38044 this.specularMap = source.specularMap; 38045 38046 this.alphaMap = source.alphaMap; 38047 38048 this.envMap = source.envMap; 38049 this.combine = source.combine; 38050 this.reflectivity = source.reflectivity; 38051 this.refractionRatio = source.refractionRatio; 38052 38053 this.wireframe = source.wireframe; 38054 this.wireframeLinewidth = source.wireframeLinewidth; 38055 this.wireframeLinecap = source.wireframeLinecap; 38056 this.wireframeLinejoin = source.wireframeLinejoin; 38057 38058 this.flatShading = source.flatShading; 38059 38060 this.fog = source.fog; 38061 38062 return this; 38063 38064 } 38065 38066} 38067 38068class MeshToonMaterial extends Material { 38069 38070 constructor( parameters ) { 38071 38072 super(); 38073 38074 this.isMeshToonMaterial = true; 38075 38076 this.defines = { 'TOON': '' }; 38077 38078 this.type = 'MeshToonMaterial'; 38079 38080 this.color = new Color( 0xffffff ); 38081 38082 this.map = null; 38083 this.gradientMap = null; 38084 38085 this.lightMap = null; 38086 this.lightMapIntensity = 1.0; 38087 38088 this.aoMap = null; 38089 this.aoMapIntensity = 1.0; 38090 38091 this.emissive = new Color( 0x000000 ); 38092 this.emissiveIntensity = 1.0; 38093 this.emissiveMap = null; 38094 38095 this.bumpMap = null; 38096 this.bumpScale = 1; 38097 38098 this.normalMap = null; 38099 this.normalMapType = TangentSpaceNormalMap; 38100 this.normalScale = new Vector2( 1, 1 ); 38101 38102 this.displacementMap = null; 38103 this.displacementScale = 1; 38104 this.displacementBias = 0; 38105 38106 this.alphaMap = null; 38107 38108 this.wireframe = false; 38109 this.wireframeLinewidth = 1; 38110 this.wireframeLinecap = 'round'; 38111 this.wireframeLinejoin = 'round'; 38112 38113 this.fog = true; 38114 38115 this.setValues( parameters ); 38116 38117 } 38118 38119 copy( source ) { 38120 38121 super.copy( source ); 38122 38123 this.color.copy( source.color ); 38124 38125 this.map = source.map; 38126 this.gradientMap = source.gradientMap; 38127 38128 this.lightMap = source.lightMap; 38129 this.lightMapIntensity = source.lightMapIntensity; 38130 38131 this.aoMap = source.aoMap; 38132 this.aoMapIntensity = source.aoMapIntensity; 38133 38134 this.emissive.copy( source.emissive ); 38135 this.emissiveMap = source.emissiveMap; 38136 this.emissiveIntensity = source.emissiveIntensity; 38137 38138 this.bumpMap = source.bumpMap; 38139 this.bumpScale = source.bumpScale; 38140 38141 this.normalMap = source.normalMap; 38142 this.normalMapType = source.normalMapType; 38143 this.normalScale.copy( source.normalScale ); 38144 38145 this.displacementMap = source.displacementMap; 38146 this.displacementScale = source.displacementScale; 38147 this.displacementBias = source.displacementBias; 38148 38149 this.alphaMap = source.alphaMap; 38150 38151 this.wireframe = source.wireframe; 38152 this.wireframeLinewidth = source.wireframeLinewidth; 38153 this.wireframeLinecap = source.wireframeLinecap; 38154 this.wireframeLinejoin = source.wireframeLinejoin; 38155 38156 this.fog = source.fog; 38157 38158 return this; 38159 38160 } 38161 38162} 38163 38164class MeshNormalMaterial extends Material { 38165 38166 constructor( parameters ) { 38167 38168 super(); 38169 38170 this.isMeshNormalMaterial = true; 38171 38172 this.type = 'MeshNormalMaterial'; 38173 38174 this.bumpMap = null; 38175 this.bumpScale = 1; 38176 38177 this.normalMap = null; 38178 this.normalMapType = TangentSpaceNormalMap; 38179 this.normalScale = new Vector2( 1, 1 ); 38180 38181 this.displacementMap = null; 38182 this.displacementScale = 1; 38183 this.displacementBias = 0; 38184 38185 this.wireframe = false; 38186 this.wireframeLinewidth = 1; 38187 38188 this.flatShading = false; 38189 38190 this.setValues( parameters ); 38191 38192 } 38193 38194 copy( source ) { 38195 38196 super.copy( source ); 38197 38198 this.bumpMap = source.bumpMap; 38199 this.bumpScale = source.bumpScale; 38200 38201 this.normalMap = source.normalMap; 38202 this.normalMapType = source.normalMapType; 38203 this.normalScale.copy( source.normalScale ); 38204 38205 this.displacementMap = source.displacementMap; 38206 this.displacementScale = source.displacementScale; 38207 this.displacementBias = source.displacementBias; 38208 38209 this.wireframe = source.wireframe; 38210 this.wireframeLinewidth = source.wireframeLinewidth; 38211
38212 this.flatShading = source.flatShading; 38213 38214 return this; 38215 38216 } 38217 38218} 38219 38220class MeshLambertMaterial extends Material { 38221 38222 constructor( parameters ) { 38223 38224 super(); 38225 38226 this.isMeshLambertMaterial = true; 38227 38228 this.type = 'MeshLambertMaterial'; 38229 38230 this.color = new Color( 0xffffff ); // diffuse 38231 38232 this.map = null; 38233 38234 this.lightMap = null; 38235 this.lightMapIntensity = 1.0; 38236 38237 this.aoMap = null; 38238 this.aoMapIntensity = 1.0; 38239 38240 this.emissive = new Color( 0x000000 ); 38241 this.emissiveIntensity = 1.0; 38242 this.emissiveMap = null; 38243 38244 this.bumpMap = null; 38245 this.bumpScale = 1; 38246 38247 this.normalMap = null; 38248 this.normalMapType = TangentSpaceNormalMap; 38249 this.normalScale = new Vector2( 1, 1 ); 38250 38251 this.displacementMap = null; 38252 this.displacementScale = 1; 38253 this.displacementBias = 0; 38254 38255 this.specularMap = null; 38256 38257 this.alphaMap = null; 38258 38259 this.envMap = null; 38260 this.combine = MultiplyOperation; 38261 this.reflectivity = 1; 38262 this.refractionRatio = 0.98; 38263 38264 this.wireframe = false; 38265 this.wireframeLinewidth = 1; 38266 this.wireframeLinecap = 'round'; 38267 this.wireframeLinejoin = 'round'; 38268 38269 this.flatShading = false; 38270 38271 this.fog = true; 38272 38273 this.setValues( parameters ); 38274 38275 } 38276 38277 copy( source ) { 38278 38279 super.copy( source ); 38280 38281 this.color.copy( source.color ); 38282 38283 this.map = source.map; 38284 38285 this.lightMap = source.lightMap; 38286 this.lightMapIntensity = source.lightMapIntensity; 38287 38288 this.aoMap = source.aoMap; 38289 this.aoMapIntensity = source.aoMapIntensity; 38290 38291 this.emissive.copy( source.emissive ); 38292 this.emissiveMap = source.emissiveMap; 38293 this.emissiveIntensity = source.emissiveIntensity; 38294 38295 this.bumpMap = source.bumpMap; 38296 this.bumpScale = source.bumpScale; 38297 38298 this.normalMap = source.normalMap; 38299 this.normalMapType = source.normalMapType; 38300 this.normalScale.copy( source.normalScale ); 38301 38302 this.displacementMap = source.displacementMap; 38303 this.displacementScale = source.displacementScale; 38304 this.displacementBias = source.displacementBias; 38305 38306 this.specularMap = source.specularMap; 38307 38308 this.alphaMap = source.alphaMap; 38309 38310 this.envMap = source.envMap; 38311 this.combine = source.combine; 38312 this.reflectivity = source.reflectivity; 38313 this.refractionRatio = source.refractionRatio; 38314 38315 this.wireframe = source.wireframe; 38316 this.wireframeLinewidth = source.wireframeLinewidth; 38317 this.wireframeLinecap = source.wireframeLinecap; 38318 this.wireframeLinejoin = source.wireframeLinejoin; 38319 38320 this.flatShading = source.flatShading; 38321 38322 this.fog = source.fog; 38323 38324 return this; 38325 38326 } 38327 38328} 38329 38330class MeshMatcapMaterial extends Material { 38331 38332 constructor( parameters ) { 38333 38334 super(); 38335 38336 this.isMeshMatcapMaterial = true; 38337 38338 this.defines = { 'MATCAP': '' }; 38339 38340 this.type = 'MeshMatcapMaterial'; 38341 38342 this.color = new Color( 0xffffff ); // diffuse 38343 38344 this.matcap = null; 38345 38346 this.map = null; 38347 38348 this.bumpMap = null; 38349 this.bumpScale = 1; 38350 38351 this.normalMap = null; 38352 this.normalMapType = TangentSpaceNormalMap; 38353 this.normalScale = new Vector2( 1, 1 ); 38354 38355 this.displacementMap = null; 38356 this.displacementScale = 1; 38357 this.displacementBias = 0; 38358 38359 this.alphaMap = null; 38360 38361 this.flatShading = false; 38362 38363 this.fog = true; 38364 38365 this.setValues( parameters ); 38366 38367 } 38368 38369 38370 copy( source ) { 38371 38372 super.copy( source ); 38373 38374 this.defines = { 'MATCAP': '' }; 38375 38376 this.color.copy( source.color ); 38377 38378 this.matcap = source.matcap; 38379 38380 this.map = source.map; 38381 38382 this.bumpMap = source.bumpMap; 38383 this.bumpScale = source.bumpScale; 38384 38385 this.normalMap = source.normalMap; 38386 this.normalMapType = source.normalMapType; 38387 this.normalScale.copy( source.normalScale ); 38388 38389 this.displacementMap = source.displacementMap; 38390 this.displacementScale = source.displacementScale; 38391 this.displacementBias = source.displacementBias; 38392 38393 this.alphaMap = source.alphaMap; 38394 38395 this.flatShading = source.flatShading; 38396 38397 this.fog = source.fog; 38398 38399 return this; 38400 38401 } 38402 38403} 38404 38405class LineDashedMaterial extends LineBasicMaterial { 38406 38407 constructor( parameters ) { 38408 38409 super(); 38410 38411 this.isLineDashedMaterial = true; 38412 38413 this.type = 'LineDashedMaterial'; 38414 38415 this.scale = 1; 38416 this.dashSize = 3; 38417 this.gapSize = 1; 38418 38419 this.setValues( parameters ); 38420 38421 } 38422 38423 copy( source ) { 38424 38425 super.copy( source ); 38426 38427 this.scale = source.scale; 38428 this.dashSize = source.dashSize; 38429 this.gapSize = source.gapSize; 38430 38431 return this; 38432 38433 } 38434 38435} 38436 38437// same as Array.prototype.slice, but also works on typed arrays 38438function arraySlice( array, from, to ) { 38439 38440 if ( isTypedArray( array ) ) { 38441 38442 // in ios9 array.subarray(from, undefined) will return empty array 38443 // but array.subarray(from) or array.subarray(from, len) is correct 38444 return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) ); 38445 38446 } 38447 38448 return array.slice( from, to ); 38449 38450} 38451 38452// converts an array to a specific type 38453function convertArray( array, type, forceClone ) { 38454 38455 if ( ! array || // let 'undefined' and 'null' pass
vendor: 15,766 bytes, lines 38456-39243
38456 ! forceClone && array.constructor === type ) return array; 38457 38458 if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { 38459 38460 return new type( array ); // create typed array 38461 38462 } 38463 38464 return Array.prototype.slice.call( array ); // create Array 38465 38466} 38467 38468function isTypedArray( object ) { 38469 38470 return ArrayBuffer.isView( object ) && 38471 ! ( object instanceof DataView ); 38472 38473} 38474 38475// returns an array by which times and values can be sorted 38476function getKeyframeOrder( times ) { 38477 38478 function compareTime( i, j ) { 38479 38480 return times[ i ] - times[ j ]; 38481 38482 } 38483 38484 const n = times.length; 38485 const result = new Array( n ); 38486 for ( let i = 0; i !== n; ++ i ) result[ i ] = i; 38487 38488 result.sort( compareTime ); 38489 38490 return result; 38491 38492} 38493 38494// uses the array previously returned by 'getKeyframeOrder' to sort data 38495function sortedArray( values, stride, order ) { 38496 38497 const nValues = values.length; 38498 const result = new values.constructor( nValues ); 38499 38500 for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { 38501 38502 const srcOffset = order[ i ] * stride; 38503 38504 for ( let j = 0; j !== stride; ++ j ) { 38505 38506 result[ dstOffset ++ ] = values[ srcOffset + j ]; 38507 38508 } 38509 38510 } 38511 38512 return result; 38513 38514} 38515 38516// function for parsing AOS keyframe formats 38517function flattenJSON( jsonKeys, times, values, valuePropertyName ) { 38518 38519 let i = 1, key = jsonKeys[ 0 ]; 38520 38521 while ( key !== undefined && key[ valuePropertyName ] === undefined ) { 38522 38523 key = jsonKeys[ i ++ ]; 38524 38525 } 38526 38527 if ( key === undefined ) return; // no data 38528 38529 let value = key[ valuePropertyName ]; 38530 if ( value === undefined ) return; // no data 38531 38532 if ( Array.isArray( value ) ) { 38533 38534 do { 38535 38536 value = key[ valuePropertyName ]; 38537 38538 if ( value !== undefined ) { 38539 38540 times.push( key.time ); 38541 values.push.apply( values, value ); // push all elements 38542 38543 } 38544 38545 key = jsonKeys[ i ++ ]; 38546 38547 } while ( key !== undefined ); 38548 38549 } else if ( value.toArray !== undefined ) { 38550 38551 // ...assume THREE.Math-ish 38552 38553 do { 38554 38555 value = key[ valuePropertyName ]; 38556 38557 if ( value !== undefined ) { 38558 38559 times.push( key.time ); 38560 value.toArray( values, values.length ); 38561 38562 } 38563 38564 key = jsonKeys[ i ++ ]; 38565 38566 } while ( key !== undefined ); 38567 38568 } else { 38569 38570 // otherwise push as-is 38571 38572 do { 38573 38574 value = key[ valuePropertyName ]; 38575 38576 if ( value !== undefined ) { 38577 38578 times.push( key.time ); 38579 values.push( value ); 38580 38581 } 38582 38583 key = jsonKeys[ i ++ ]; 38584 38585 } while ( key !== undefined ); 38586 38587 } 38588 38589} 38590 38591function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) { 38592 38593 const clip = sourceClip.clone(); 38594 38595 clip.name = name; 38596 38597 const tracks = []; 38598 38599 for ( let i = 0; i < clip.tracks.length; ++ i ) { 38600 38601 const track = clip.tracks[ i ]; 38602 const valueSize = track.getValueSize(); 38603 38604 const times = []; 38605 const values = []; 38606 38607 for ( let j = 0; j < track.times.length; ++ j ) { 38608 38609 const frame = track.times[ j ] * fps; 38610 38611 if ( frame < startFrame || frame >= endFrame ) continue; 38612 38613 times.push( track.times[ j ] ); 38614 38615 for ( let k = 0; k < valueSize; ++ k ) { 38616 38617 values.push( track.values[ j * valueSize + k ] ); 38618 38619 } 38620 38621 } 38622 38623 if ( times.length === 0 ) continue; 38624 38625 track.times = convertArray( times, track.times.constructor ); 38626 track.values = convertArray( values, track.values.constructor ); 38627 38628 tracks.push( track ); 38629 38630 } 38631 38632 clip.tracks = tracks; 38633 38634 // find minimum .times value across all tracks in the trimmed clip 38635 38636 let minStartTime = Infinity; 38637 38638 for ( let i = 0; i < clip.tracks.length; ++ i ) { 38639 38640 if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) { 38641 38642 minStartTime = clip.tracks[ i ].times[ 0 ]; 38643 38644 } 38645 38646 } 38647 38648 // shift all tracks such that clip begins at t=0 38649 38650 for ( let i = 0; i < clip.tracks.length; ++ i ) { 38651 38652 clip.tracks[ i ].shift( - 1 * minStartTime ); 38653 38654 } 38655 38656 clip.resetDuration(); 38657 38658 return clip; 38659 38660} 38661 38662function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) { 38663 38664 if ( fps <= 0 ) fps = 30; 38665 38666 const numTracks = referenceClip.tracks.length; 38667 const referenceTime = referenceFrame / fps; 38668 38669 // Make each track's values relative to the values at the reference frame 38670 for ( let i = 0; i < numTracks; ++ i ) { 38671 38672 const referenceTrack = referenceClip.tracks[ i ]; 38673 const referenceTrackType = referenceTrack.ValueTypeName; 38674 38675 // Skip this track if it's non-numeric 38676 if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue; 38677 38678 // Find the track in the target clip whose name and type matches the reference track 38679 const targetTrack = targetClip.tracks.find( function ( track ) { 38680 38681 return track.name === referenceTrack.name 38682 && track.ValueTypeName === referenceTrackType; 38683 38684 } ); 38685 38686 if ( targetTrack === undefined ) continue; 38687 38688 let referenceOffset = 0; 38689 const referenceValueSize = referenceTrack.getValueSize(); 38690 38691 if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { 38692 38693 referenceOffset = referenceValueSize / 3; 38694 38695 } 38696 38697 let targetOffset = 0; 38698 const targetValueSize = targetTrack.getValueSize(); 38699 38700 if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { 38701 38702 targetOffset = targetValueSize / 3; 38703 38704 } 38705 38706 const lastIndex = referenceTrack.times.length - 1; 38707 let referenceValue; 38708 38709 // Find the value to subtract out of the track 38710 if ( referenceTime <= referenceTrack.times[ 0 ] ) { 38711 38712 // Reference frame is earlier than the first keyframe, so just use the first keyframe 38713 const startIndex = referenceOffset; 38714 const endIndex = referenceValueSize - referenceOffset; 38715 referenceValue = arraySlice( referenceTrack.values, startIndex, endIndex ); 38716 38717 } else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) { 38718 38719 // Reference frame is after the last keyframe, so just use the last keyframe 38720 const startIndex = lastIndex * referenceValueSize + referenceOffset; 38721 const endIndex = startIndex + referenceValueSize - referenceOffset; 38722 referenceValue = arraySlice( referenceTrack.values, startIndex, endIndex ); 38723 38724 } else { 38725 38726 // Interpolate to the reference value 38727 const interpolant = referenceTrack.createInterpolant(); 38728 const startIndex = referenceOffset; 38729 const endIndex = referenceValueSize - referenceOffset; 38730 interpolant.evaluate( referenceTime ); 38731 referenceValue = arraySlice( interpolant.resultBuffer, startIndex, endIndex ); 38732 38733 } 38734 38735 // Conjugate the quaternion 38736 if ( referenceTrackType === 'quaternion' ) { 38737 38738 const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate(); 38739 referenceQuat.toArray( referenceValue ); 38740 38741 } 38742 38743 // Subtract the reference value from all of the track values 38744 38745 const numTimes = targetTrack.times.length; 38746 for ( let j = 0; j < numTimes; ++ j ) { 38747 38748 const valueStart = j * targetValueSize + targetOffset; 38749 38750 if ( referenceTrackType === 'quaternion' ) { 38751 38752 // Multiply the conjugate for quaternion track types 38753 Quaternion.multiplyQuaternionsFlat( 38754 targetTrack.values, 38755 valueStart, 38756 referenceValue, 38757 0, 38758 targetTrack.values, 38759 valueStart 38760 ); 38761 38762 } else { 38763 38764 const valueEnd = targetValueSize - targetOffset * 2; 38765 38766 // Subtract each value for all other numeric track types 38767 for ( let k = 0; k < valueEnd; ++ k ) { 38768 38769 targetTrack.values[ valueStart + k ] -= referenceValue[ k ]; 38770 38771 } 38772 38773 } 38774 38775 } 38776 38777 } 38778 38779 targetClip.blendMode = AdditiveAnimationBlendMode; 38780 38781 return targetClip; 38782 38783} 38784 38785const AnimationUtils = { 38786 arraySlice: arraySlice, 38787 convertArray: convertArray, 38788 isTypedArray: isTypedArray, 38789 getKeyframeOrder: getKeyframeOrder, 38790 sortedArray: sortedArray, 38791 flattenJSON: flattenJSON, 38792 subclip: subclip, 38793 makeClipAdditive: makeClipAdditive 38794}; 38795 38796/** 38797 * Abstract base class of interpolants over parametric samples. 38798 * 38799 * The parameter domain is one dimensional, typically the time or a path 38800 * along a curve defined by the data. 38801 * 38802 * The sample values can have any dimensionality and derived classes may 38803 * apply special interpretations to the data. 38804 * 38805 * This class provides the interval seek in a Template Method, deferring 38806 * the actual interpolation to derived classes. 38807 * 38808 * Time complexity is O(1) for linear access crossing at most two points 38809 * and O(log N) for random access, where N is the number of positions. 38810 * 38811 * References: 38812 * 38813 * http://www.oodesign.com/template-method-pattern.html 38814 * 38815 */ 38816 38817class Interpolant { 38818 38819 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 38820 38821 this.parameterPositions = parameterPositions; 38822 this._cachedIndex = 0; 38823 38824 this.resultBuffer = resultBuffer !== undefined ? 38825 resultBuffer : new sampleValues.constructor( sampleSize ); 38826 this.sampleValues = sampleValues; 38827 this.valueSize = sampleSize; 38828 38829 this.settings = null; 38830 this.DefaultSettings_ = {}; 38831 38832 } 38833 38834 evaluate( t ) { 38835 38836 const pp = this.parameterPositions; 38837 let i1 = this._cachedIndex, 38838 t1 = pp[ i1 ], 38839 t0 = pp[ i1 - 1 ]; 38840 38841 validate_interval: { 38842 38843 seek: { 38844 38845 let right; 38846 38847 linear_scan: { 38848 38849 //- See http://jsperf.com/comparison-to-undefined/3 38850 //- slower code: 38851 //- 38852 //- if ( t >= t1 || t1 === undefined ) { 38853 forward_scan: if ( ! ( t < t1 ) ) { 38854 38855 for ( let giveUpAt = i1 + 2; ; ) { 38856 38857 if ( t1 === undefined ) { 38858 38859 if ( t < t0 ) break forward_scan; 38860 38861 // after end 38862 38863 i1 = pp.length; 38864 this._cachedIndex = i1; 38865 return this.copySampleValue_( i1 - 1 ); 38866 38867 } 38868 38869 if ( i1 === giveUpAt ) break; // this loop 38870 38871 t0 = t1; 38872 t1 = pp[ ++ i1 ]; 38873 38874 if ( t < t1 ) { 38875 38876 // we have arrived at the sought interval 38877 break seek; 38878 38879 } 38880 38881 } 38882 38883 // prepare binary search on the right side of the index 38884 right = pp.length; 38885 break linear_scan; 38886 38887 } 38888 38889 //- slower code: 38890 //- if ( t < t0 || t0 === undefined ) { 38891 if ( ! ( t >= t0 ) ) { 38892 38893 // looping? 38894 38895 const t1global = pp[ 1 ]; 38896 38897 if ( t < t1global ) { 38898 38899 i1 = 2; // + 1, using the scan for the details 38900 t0 = t1global; 38901 38902 } 38903 38904 // linear reverse scan 38905 38906 for ( let giveUpAt = i1 - 2; ; ) { 38907 38908 if ( t0 === undefined ) { 38909 38910 // before start 38911 38912 this._cachedIndex = 0; 38913 return this.copySampleValue_( 0 ); 38914 38915 } 38916 38917 if ( i1 === giveUpAt ) break; // this loop 38918 38919 t1 = t0; 38920 t0 = pp[ -- i1 - 1 ]; 38921 38922 if ( t >= t0 ) { 38923 38924 // we have arrived at the sought interval 38925 break seek; 38926 38927 } 38928 38929 } 38930 38931 // prepare binary search on the left side of the index 38932 right = i1; 38933 i1 = 0; 38934 break linear_scan; 38935 38936 } 38937 38938 // the interval is valid 38939 38940 break validate_interval; 38941 38942 } // linear scan 38943 38944 // binary search 38945 38946 while ( i1 < right ) { 38947 38948 const mid = ( i1 + right ) >>> 1; 38949 38950 if ( t < pp[ mid ] ) { 38951 38952 right = mid; 38953 38954 } else { 38955 38956 i1 = mid + 1; 38957 38958 } 38959 38960 } 38961 38962 t1 = pp[ i1 ]; 38963 t0 = pp[ i1 - 1 ]; 38964 38965 // check boundary cases, again 38966 38967 if ( t0 === undefined ) { 38968 38969 this._cachedIndex = 0; 38970 return this.copySampleValue_( 0 ); 38971 38972 } 38973 38974 if ( t1 === undefined ) { 38975 38976 i1 = pp.length; 38977 this._cachedIndex = i1; 38978 return this.copySampleValue_( i1 - 1 ); 38979 38980 } 38981 38982 } // seek 38983 38984 this._cachedIndex = i1; 38985 38986 this.intervalChanged_( i1, t0, t1 ); 38987 38988 } // validate_interval 38989 38990 return this.interpolate_( i1, t0, t, t1 ); 38991 38992 } 38993 38994 getSettings_() { 38995 38996 return this.settings || this.DefaultSettings_; 38997 38998 } 38999 39000 copySampleValue_( index ) { 39001 39002 // copies a sample value to the result buffer 39003 39004 const result = this.resultBuffer, 39005 values = this.sampleValues, 39006 stride = this.valueSize, 39007 offset = index * stride; 39008 39009 for ( let i = 0; i !== stride; ++ i ) { 39010 39011 result[ i ] = values[ offset + i ]; 39012 39013 } 39014 39015 return result; 39016 39017 } 39018 39019 // Template methods for derived classes: 39020 39021 interpolate_( /* i1, t0, t, t1 */ ) { 39022 39023 throw new Error( 'call to abstract method' ); 39024 // implementations shall return this.resultBuffer 39025 39026 } 39027 39028 intervalChanged_( /* i1, t0, t1 */ ) { 39029 39030 // empty 39031 39032 } 39033 39034} 39035 39036/** 39037 * Fast and simple cubic spline interpolant. 39038 * 39039 * It was derived from a Hermitian construction setting the first derivative 39040 * at each sample position to the linear slope between neighboring positions 39041 * over their parameter interval. 39042 */ 39043 39044class CubicInterpolant extends Interpolant { 39045 39046 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 39047 39048 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 39049 39050 this._weightPrev = - 0; 39051 this._offsetPrev = - 0; 39052 this._weightNext = - 0; 39053 this._offsetNext = - 0; 39054 39055 this.DefaultSettings_ = { 39056 39057 endingStart: ZeroCurvatureEnding, 39058 endingEnd: ZeroCurvatureEnding 39059 39060 }; 39061 39062 } 39063 39064 intervalChanged_( i1, t0, t1 ) { 39065 39066 const pp = this.parameterPositions; 39067 let iPrev = i1 - 2, 39068 iNext = i1 + 1, 39069 39070 tPrev = pp[ iPrev ], 39071 tNext = pp[ iNext ]; 39072 39073 if ( tPrev === undefined ) { 39074 39075 switch ( this.getSettings_().endingStart ) { 39076 39077 case ZeroSlopeEnding: 39078 39079 // f'(t0) = 0 39080 iPrev = i1; 39081 tPrev = 2 * t0 - t1; 39082 39083 break; 39084 39085 case WrapAroundEnding: 39086 39087 // use the other end of the curve 39088 iPrev = pp.length - 2; 39089 tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; 39090 39091 break; 39092 39093 default: // ZeroCurvatureEnding 39094 39095 // f''(t0) = 0 a.k.a. Natural Spline 39096 iPrev = i1; 39097 tPrev = t1; 39098 39099 } 39100 39101 } 39102 39103 if ( tNext === undefined ) { 39104 39105 switch ( this.getSettings_().endingEnd ) { 39106 39107 case ZeroSlopeEnding: 39108 39109 // f'(tN) = 0 39110 iNext = i1; 39111 tNext = 2 * t1 - t0; 39112 39113 break; 39114 39115 case WrapAroundEnding: 39116 39117 // use the other end of the curve 39118 iNext = 1; 39119 tNext = t1 + pp[ 1 ] - pp[ 0 ]; 39120 39121 break; 39122 39123 default: // ZeroCurvatureEnding 39124 39125 // f''(tN) = 0, a.k.a. Natural Spline 39126 iNext = i1 - 1; 39127 tNext = t0; 39128 39129 } 39130 39131 } 39132 39133 const halfDt = ( t1 - t0 ) * 0.5, 39134 stride = this.valueSize; 39135 39136 this._weightPrev = halfDt / ( t0 - tPrev ); 39137 this._weightNext = halfDt / ( tNext - t1 ); 39138 this._offsetPrev = iPrev * stride; 39139 this._offsetNext = iNext * stride; 39140 39141 } 39142 39143 interpolate_( i1, t0, t, t1 ) { 39144 39145 const result = this.resultBuffer, 39146 values = this.sampleValues, 39147 stride = this.valueSize, 39148 39149 o1 = i1 * stride, o0 = o1 - stride, 39150 oP = this._offsetPrev, oN = this._offsetNext, 39151 wP = this._weightPrev, wN = this._weightNext, 39152 39153 p = ( t - t0 ) / ( t1 - t0 ), 39154 pp = p * p, 39155 ppp = pp * p; 39156 39157 // evaluate polynomials 39158 39159 const sP = - wP * ppp + 2 * wP * pp - wP * p; 39160 const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1; 39161 const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p; 39162 const sN = wN * ppp - wN * pp; 39163 39164 // combine data linearly 39165 39166 for ( let i = 0; i !== stride; ++ i ) { 39167 39168 result[ i ] = 39169 sP * values[ oP + i ] + 39170 s0 * values[ o0 + i ] + 39171 s1 * values[ o1 + i ] + 39172 sN * values[ oN + i ]; 39173 39174 } 39175 39176 return result; 39177 39178 } 39179 39180} 39181 39182class LinearInterpolant extends Interpolant { 39183 39184 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 39185 39186 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 39187 39188 } 39189 39190 interpolate_( i1, t0, t, t1 ) { 39191 39192 const result = this.resultBuffer, 39193 values = this.sampleValues, 39194 stride = this.valueSize, 39195 39196 offset1 = i1 * stride, 39197 offset0 = offset1 - stride, 39198 39199 weight1 = ( t - t0 ) / ( t1 - t0 ), 39200 weight0 = 1 - weight1; 39201 39202 for ( let i = 0; i !== stride; ++ i ) { 39203 39204 result[ i ] = 39205 values[ offset0 + i ] * weight0 + 39206 values[ offset1 + i ] * weight1; 39207 39208 } 39209 39210 return result; 39211 39212 } 39213 39214} 39215 39216/** 39217 * 39218 * Interpolant that evaluates to the sample value at the position preceding 39219 * the parameter. 39220 */ 39221 39222class DiscreteInterpolant extends Interpolant { 39223 39224 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 39225 39226 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 39227 39228 } 39229 39230 interpolate_( i1 /*, t0, t, t1 */ ) { 39231 39232 return this.copySampleValue_( i1 - 1 ); 39233 39234 } 39235 39236} 39237 39238class KeyframeTrack { 39239 39240 constructor( name, times, values, interpolation ) { 39241 39242 if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); 39243 if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + n
vendor: 4,615 bytes, lines 39243-39487
39243ame ); 39244 39245 this.name = name; 39246 39247 this.times = convertArray( times, this.TimeBufferType ); 39248 this.values = convertArray( values, this.ValueBufferType ); 39249 39250 this.setInterpolation( interpolation || this.DefaultInterpolation ); 39251 39252 } 39253 39254 // Serialization (in static context, because of constructor invocation 39255 // and automatic invocation of .toJSON): 39256 39257 static toJSON( track ) { 39258 39259 const trackType = track.constructor; 39260 39261 let json; 39262 39263 // derived classes can define a static toJSON method 39264 if ( trackType.toJSON !== this.toJSON ) { 39265 39266 json = trackType.toJSON( track ); 39267 39268 } else { 39269 39270 // by default, we assume the data can be serialized as-is 39271 json = { 39272 39273 'name': track.name, 39274 'times': convertArray( track.times, Array ), 39275 'values': convertArray( track.values, Array ) 39276 39277 }; 39278 39279 const interpolation = track.getInterpolation(); 39280 39281 if ( interpolation !== track.DefaultInterpolation ) { 39282 39283 json.interpolation = interpolation; 39284 39285 } 39286 39287 } 39288 39289 json.type = track.ValueTypeName; // mandatory 39290 39291 return json; 39292 39293 } 39294 39295 InterpolantFactoryMethodDiscrete( result ) { 39296 39297 return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); 39298 39299 } 39300 39301 InterpolantFactoryMethodLinear( result ) { 39302 39303 return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); 39304 39305 } 39306 39307 InterpolantFactoryMethodSmooth( result ) { 39308 39309 return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); 39310 39311 } 39312 39313 setInterpolation( interpolation ) { 39314 39315 let factoryMethod; 39316 39317 switch ( interpolation ) { 39318 39319 case InterpolateDiscrete: 39320 39321 factoryMethod = this.InterpolantFactoryMethodDiscrete; 39322 39323 break; 39324 39325 case InterpolateLinear: 39326 39327 factoryMethod = this.InterpolantFactoryMethodLinear; 39328 39329 break; 39330 39331 case InterpolateSmooth: 39332 39333 factoryMethod = this.InterpolantFactoryMethodSmooth; 39334 39335 break; 39336 39337 } 39338 39339 if ( factoryMethod === undefined ) { 39340 39341 const message = 'unsupported interpolation for ' + 39342 this.ValueTypeName + ' keyframe track named ' + this.name; 39343 39344 if ( this.createInterpolant === undefined ) { 39345 39346 // fall back to default, unless the default itself is messed up 39347 if ( interpolation !== this.DefaultInterpolation ) { 39348 39349 this.setInterpolation( this.DefaultInterpolation ); 39350 39351 } else { 39352 39353 throw new Error( message ); // fatal, in this case 39354 39355 } 39356 39357 } 39358 39359 console.warn( 'THREE.KeyframeTrack:', message ); 39360 return this; 39361 39362 } 39363 39364 this.createInterpolant = factoryMethod; 39365 39366 return this; 39367 39368 } 39369 39370 getInterpolation() { 39371 39372 switch ( this.createInterpolant ) { 39373 39374 case this.InterpolantFactoryMethodDiscrete: 39375 39376 return InterpolateDiscrete; 39377 39378 case this.InterpolantFactoryMethodLinear: 39379 39380 return InterpolateLinear; 39381 39382 case this.InterpolantFactoryMethodSmooth: 39383 39384 return InterpolateSmooth; 39385 39386 } 39387 39388 } 39389 39390 getValueSize() { 39391 39392 return this.values.length / this.times.length; 39393 39394 } 39395 39396 // move all keyframes either forwards or backwards in time 39397 shift( timeOffset ) { 39398 39399 if ( timeOffset !== 0.0 ) { 39400 39401 const times = this.times; 39402 39403 for ( let i = 0, n = times.length; i !== n; ++ i ) { 39404 39405 times[ i ] += timeOffset; 39406 39407 } 39408 39409 } 39410 39411 return this; 39412 39413 } 39414 39415 // scale all keyframe times by a factor (useful for frame <-> seconds conversions) 39416 scale( timeScale ) { 39417 39418 if ( timeScale !== 1.0 ) { 39419 39420 const times = this.times; 39421 39422 for ( let i = 0, n = times.length; i !== n; ++ i ) { 39423 39424 times[ i ] *= timeScale; 39425 39426 } 39427 39428 } 39429 39430 return this; 39431 39432 } 39433 39434 // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. 39435 // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values 39436 trim( startTime, endTime ) { 39437 39438 const times = this.times, 39439 nKeys = times.length; 39440 39441 let from = 0, 39442 to = nKeys - 1; 39443 39444 while ( from !== nKeys && times[ from ] < startTime ) { 39445 39446 ++ from; 39447 39448 } 39449 39450 while ( to !== - 1 && times[ to ] > endTime ) { 39451 39452 -- to; 39453 39454 } 39455 39456 ++ to; // inclusive -> exclusive bound 39457 39458 if ( from !== 0 || to !== nKeys ) { 39459 39460 // empty tracks are forbidden, so keep at least one keyframe 39461 if ( from >= to ) { 39462 39463 to = Math.max( to, 1 ); 39464 from = to - 1; 39465 39466 } 39467 39468 const stride = this.getValueSize(); 39469 this.times = arraySlice( times, from, to ); 39470 this.values = arraySlice( this.values, from * stride, to * stride ); 39471 39472 } 39473 39474 return this; 39475 39476 } 39477 39478 // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable 39479 validate() { 39480 39481 let valid = true; 39482 39483 const valueSize = this.getValueSize(); 39484 if ( valueSize - Math.floor( valueSize ) !== 0 ) { 39485 39486 console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); 39487 valid = false;
39488 39489 } 39490 39491 const times = this.times, 39492 values = this.values, 39493 39494 nKeys = times.length; 39495 39496 if ( nKeys === 0 ) { 39497 39498 console.error( 'THREE.KeyframeTrack: Track is empty.', this ); 39499 valid = false; 39500 39501 } 39502 39503 let prevTime = null; 39504 39505 for ( let i = 0; i !== nKeys; i ++ ) { 39506 39507 const currTime = times[ i ]; 39508 39509 if ( typeof currTime === 'number' && isNaN( currTime ) ) { 39510 39511 console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); 39512 valid = false; 39513 break; 39514 39515 } 39516 39517 if ( prevTime !== null && prevTime > currTime ) { 39518 39519 console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); 39520 valid = false; 39521 break; 39522 39523 } 39524 39525 prevTime = currTime; 39526 39527 } 39528 39529 if ( values !== undefined ) { 39530 39531 if ( isTypedArray( values ) ) { 39532 39533 for ( let i = 0, n = values.length; i !== n; ++ i ) { 39534 39535 const value = values[ i ]; 39536 39537 if ( isNaN( value ) ) { 39538 39539 console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); 39540 valid = false; 39541 break; 39542 39543 } 39544 39545 } 39546 39547 } 39548 39549 } 39550 39551 return valid; 39552 39553 } 39554 39555 // removes equivalent sequential keys as common in morph target sequences 39556 // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) 39557 optimize() { 39558 39559 // times or values may be shared with other tracks, so overwriting is unsafe 39560 const times = arraySlice( this.times ), 39561 values = arraySlice( this.values ), 39562 stride = this.getValueSize(), 39563 39564 smoothInterpolation = this.getInterpolation() === InterpolateSmooth, 39565 39566 lastIndex = times.length - 1; 39567 39568 let writeIndex = 1; 39569 39570 for ( let i = 1; i < lastIndex; ++ i ) { 39571 39572 let keep = false; 39573 39574 const time = times[ i ]; 39575 const timeNext = times[ i + 1 ]; 39576 39577 // remove adjacent keyframes scheduled at the same time 39578 39579 if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) { 39580 39581 if ( ! smoothInterpolation ) { 39582 39583 // remove unnecessary keyframes same as their neighbors 39584 39585 const offset = i * stride, 39586 offsetP = offset - stride, 39587 offsetN = offset + stride; 39588 39589 for ( let j = 0; j !== stride; ++ j ) { 39590 39591 const value = values[ offset + j ]; 39592 39593 if ( value !== values[ offsetP + j ] || 39594 value !== values[ offsetN + j ] ) { 39595 39596 keep = true; 39597 break; 39598 39599 } 39600 39601 } 39602 39603 } else { 39604 39605 keep = true; 39606 39607 } 39608 39609 } 39610 39611 // in-place compaction 39612 39613 if ( keep ) { 39614 39615 if ( i !== writeIndex ) { 39616 39617 times[ writeIndex ] = times[ i ]; 39618 39619 const readOffset = i * stride, 39620 writeOffset = writeIndex * stride; 39621 39622 for ( let j = 0; j !== stride; ++ j ) { 39623 39624 values[ writeOffset + j ] = values[ readOffset + j ]; 39625 39626 } 39627 39628 } 39629 39630 ++ writeIndex; 39631 39632 } 39633 39634 } 39635 39636 // flush last keyframe (compaction looks ahead) 39637 39638 if ( lastIndex > 0 ) { 39639 39640 times[ writeIndex ] = times[ lastIndex ]; 39641 39642 for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { 39643 39644 values[ writeOffset + j ] = values[ readOffset + j ]; 39645 39646 } 39647 39648 ++ writeIndex; 39649 39650 } 39651 39652 if ( writeIndex !== times.length ) { 39653 39654 this.times = arraySlice( times, 0, writeIndex ); 39655 this.values = arraySlice( values, 0, writeIndex * stride ); 39656 39657 } else { 39658 39659 this.times = times; 39660 this.values = values; 39661 39662 } 39663 39664 return this; 39665 39666 } 39667 39668 clone() { 39669 39670 const times = arraySlice( this.times, 0 ); 39671 const values = arraySlice( this.values, 0 ); 39672 39673 const TypedKeyframeTrack = this.constructor; 39674 const track = new TypedKeyframeTrack( this.name, times, values ); 39675 39676 // Interpolant argument to constructor is not saved, so copy the factory method directly. 39677 track.createInterpolant = this.createInterpolant; 39678 39679 return track; 39680 39681 } 39682 39683} 39684 39685KeyframeTrack.prototype.TimeBufferType = Float32Array; 39686KeyframeTrack.prototype.ValueBufferType = Float32Array; 39687KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; 39688 39689/** 39690 * A Track of Boolean keyframe values. 39691 */ 39692class BooleanKeyframeTrack extends KeyframeTrack {} 39693 39694BooleanKeyframeTrack.prototype.ValueTypeName = 'bool'; 39695BooleanKeyframeTrack.prototype.ValueBufferType = Array; 39696BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; 39697BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; 39698BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; 39699 39700/** 39701 * A Track of keyframe values that represent color. 39702 */ 39703class ColorKeyframeTrack extends KeyframeTrack {} 39704 39705ColorKeyframeTrack.prototype.ValueTypeName = 'color'; 39706 39707/** 39708 * A Track of numeric keyframe values. 39709 */ 39710class NumberKeyframeTrack extends KeyframeTrack {} 39711 39712NumberKeyframeTrack.prototype.ValueTypeName = 'number'; 39713 39714/** 39715 * Spherical linear unit quaternion interpolant. 39716 */ 39717 39718class QuaternionLinearInterpolant extends Interpolant { 39719 39720 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 39721 39722 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 39723 39724 } 39725 39726 interpolate_( i1, t0, t, t1 ) { 39727 39728 const result = this.resultBuffer, 39729 values = this.sampleValues, 39730 stride = this.valueSize, 39731 39732 alpha = ( t - t0 ) / ( t1 - t0 ); 39733 39734 let offset = i1 * stride; 39735 39736 for ( let end = offset + stride; offset !== end; offset += 4 ) { 39737 39738 Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); 39739 39740 } 39741 39742 return result; 39743 39744 } 39745 39746} 39747 39748/** 39749 * A Track of quaternion keyframe values. 39750 */ 39751class QuaternionKeyframeTrack extends KeyframeTrack { 39752 39753 InterpolantFactoryMethodLinear( result ) { 39754 39755 return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); 39756 39757 } 39758 39759} 39760 39761QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion';
vendor: 12,201 bytes, lines 39762-40433
39762// ValueBufferType is inherited 39763QuaternionKeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; 39764QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; 39765 39766/** 39767 * A Track that interpolates Strings 39768 */ 39769class StringKeyframeTrack extends KeyframeTrack {} 39770 39771StringKeyframeTrack.prototype.ValueTypeName = 'string'; 39772StringKeyframeTrack.prototype.ValueBufferType = Array; 39773StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; 39774StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; 39775StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; 39776 39777/** 39778 * A Track of vectored keyframe values. 39779 */ 39780class VectorKeyframeTrack extends KeyframeTrack {} 39781 39782VectorKeyframeTrack.prototype.ValueTypeName = 'vector'; 39783 39784class AnimationClip { 39785 39786 constructor( name, duration = - 1, tracks, blendMode = NormalAnimationBlendMode ) { 39787 39788 this.name = name; 39789 this.tracks = tracks; 39790 this.duration = duration; 39791 this.blendMode = blendMode; 39792 39793 this.uuid = generateUUID(); 39794 39795 // this means it should figure out its duration by scanning the tracks 39796 if ( this.duration < 0 ) { 39797 39798 this.resetDuration(); 39799 39800 } 39801 39802 } 39803 39804 39805 static parse( json ) { 39806 39807 const tracks = [], 39808 jsonTracks = json.tracks, 39809 frameTime = 1.0 / ( json.fps || 1.0 ); 39810 39811 for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) { 39812 39813 tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) ); 39814 39815 } 39816 39817 const clip = new this( json.name, json.duration, tracks, json.blendMode ); 39818 clip.uuid = json.uuid; 39819 39820 return clip; 39821 39822 } 39823 39824 static toJSON( clip ) { 39825 39826 const tracks = [], 39827 clipTracks = clip.tracks; 39828 39829 const json = { 39830 39831 'name': clip.name, 39832 'duration': clip.duration, 39833 'tracks': tracks, 39834 'uuid': clip.uuid, 39835 'blendMode': clip.blendMode 39836 39837 }; 39838 39839 for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) { 39840 39841 tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); 39842 39843 } 39844 39845 return json; 39846 39847 } 39848 39849 static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) { 39850 39851 const numMorphTargets = morphTargetSequence.length; 39852 const tracks = []; 39853 39854 for ( let i = 0; i < numMorphTargets; i ++ ) { 39855 39856 let times = []; 39857 let values = []; 39858 39859 times.push( 39860 ( i + numMorphTargets - 1 ) % numMorphTargets, 39861 i, 39862 ( i + 1 ) % numMorphTargets ); 39863 39864 values.push( 0, 1, 0 ); 39865 39866 const order = getKeyframeOrder( times ); 39867 times = sortedArray( times, 1, order ); 39868 values = sortedArray( values, 1, order ); 39869 39870 // if there is a key at the first frame, duplicate it as the 39871 // last frame as well for perfect loop. 39872 if ( ! noLoop && times[ 0 ] === 0 ) { 39873 39874 times.push( numMorphTargets ); 39875 values.push( values[ 0 ] ); 39876 39877 } 39878 39879 tracks.push( 39880 new NumberKeyframeTrack( 39881 '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', 39882 times, values 39883 ).scale( 1.0 / fps ) ); 39884 39885 } 39886 39887 return new this( name, - 1, tracks ); 39888 39889 } 39890 39891 static findByName( objectOrClipArray, name ) { 39892 39893 let clipArray = objectOrClipArray; 39894 39895 if ( ! Array.isArray( objectOrClipArray ) ) { 39896 39897 const o = objectOrClipArray; 39898 clipArray = o.geometry && o.geometry.animations || o.animations; 39899 39900 } 39901 39902 for ( let i = 0; i < clipArray.length; i ++ ) { 39903 39904 if ( clipArray[ i ].name === name ) { 39905 39906 return clipArray[ i ]; 39907 39908 } 39909 39910 } 39911 39912 return null; 39913 39914 } 39915 39916 static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) { 39917 39918 const animationToMorphTargets = {}; 39919 39920 // tested with https://regex101.com/ on trick sequences 39921 // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 39922 const pattern = /^([\w-]*?)([\d]+)$/; 39923 39924 // sort morph target names into animation groups based 39925 // patterns like Walk_001, Walk_002, Run_001, Run_002 39926 for ( let i = 0, il = morphTargets.length; i < il; i ++ ) { 39927 39928 const morphTarget = morphTargets[ i ]; 39929 const parts = morphTarget.name.match( pattern ); 39930 39931 if ( parts && parts.length > 1 ) { 39932 39933 const name = parts[ 1 ]; 39934 39935 let animationMorphTargets = animationToMorphTargets[ name ]; 39936 39937 if ( ! animationMorphTargets ) { 39938 39939 animationToMorphTargets[ name ] = animationMorphTargets = []; 39940 39941 } 39942 39943 animationMorphTargets.push( morphTarget ); 39944 39945 } 39946 39947 } 39948 39949 const clips = []; 39950 39951 for ( const name in animationToMorphTargets ) { 39952 39953 clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); 39954 39955 } 39956 39957 return clips; 39958 39959 } 39960 39961 // parse the animation.hierarchy format 39962 static parseAnimation( animation, bones ) { 39963 39964 if ( ! animation ) { 39965 39966 console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); 39967 return null; 39968 39969 } 39970 39971 const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { 39972 39973 // only return track if there are actually keys. 39974 if ( animationKeys.length !== 0 ) { 39975 39976 const times = []; 39977 const values = []; 39978 39979 flattenJSON( animationKeys, times, values, propertyName ); 39980 39981 // empty keys are filtered out, so check again 39982 if ( times.length !== 0 ) { 39983 39984 destTracks.push( new trackType( trackName, times, values ) ); 39985 39986 } 39987 39988 } 39989 39990 }; 39991 39992 const tracks = []; 39993 39994 const clipName = animation.name || 'default'; 39995 const fps = animation.fps || 30; 39996 const blendMode = animation.blendMode; 39997 39998 // automatic length determination in AnimationClip. 39999 let duration = animation.length || - 1; 40000 40001 const hierarchyTracks = animation.hierarchy || []; 40002 40003 for ( let h = 0; h < hierarchyTracks.length; h ++ ) { 40004 40005 const animationKeys = hierarchyTracks[ h ].keys; 40006 40007 // skip empty tracks 40008 if ( ! animationKeys || animationKeys.length === 0 ) continue; 40009 40010 // process morph targets 40011 if ( animationKeys[ 0 ].morphTargets ) { 40012 40013 // figure out all morph targets used in this track 40014 const morphTargetNames = {}; 40015 40016 let k; 40017 40018 for ( k = 0; k < animationKeys.length; k ++ ) { 40019 40020 if ( animationKeys[ k ].morphTargets ) { 40021 40022 for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { 40023 40024 morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; 40025 40026 } 40027 40028 } 40029 40030 } 40031 40032 // create a track for each morph target with all zero 40033 // morphTargetInfluences except for the keys in which 40034 // the morphTarget is named. 40035 for ( const morphTargetName in morphTargetNames ) { 40036 40037 const times = []; 40038 const values = []; 40039 40040 for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { 40041 40042 const animationKey = animationKeys[ k ]; 40043 40044 times.push( animationKey.time ); 40045 values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); 40046 40047 } 40048 40049 tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); 40050 40051 } 40052 40053 duration = morphTargetNames.length * fps; 40054 40055 } else { 40056 40057 // ...assume skeletal animation 40058 40059 const boneName = '.bones[' + bones[ h ].name + ']'; 40060 40061 addNonemptyTrack( 40062 VectorKeyframeTrack, boneName + '.position', 40063 animationKeys, 'pos', tracks ); 40064 40065 addNonemptyTrack( 40066 QuaternionKeyframeTrack, boneName + '.quaternion', 40067 animationKeys, 'rot', tracks ); 40068 40069 addNonemptyTrack( 40070 VectorKeyframeTrack, boneName + '.scale', 40071 animationKeys, 'scl', tracks ); 40072 40073 } 40074 40075 } 40076 40077 if ( tracks.length === 0 ) { 40078 40079 return null; 40080 40081 } 40082 40083 const clip = new this( clipName, duration, tracks, blendMode ); 40084 40085 return clip; 40086 40087 } 40088 40089 resetDuration() { 40090 40091 const tracks = this.tracks; 40092 let duration = 0; 40093 40094 for ( let i = 0, n = tracks.length; i !== n; ++ i ) { 40095 40096 const track = this.tracks[ i ]; 40097 40098 duration = Math.max( duration, track.times[ track.times.length - 1 ] ); 40099 40100 } 40101 40102 this.duration = duration; 40103 40104 return this; 40105 40106 } 40107 40108 trim() { 40109 40110 for ( let i = 0; i < this.tracks.length; i ++ ) { 40111 40112 this.tracks[ i ].trim( 0, this.duration ); 40113 40114 } 40115 40116 return this; 40117 40118 } 40119 40120 validate() { 40121 40122 let valid = true; 40123 40124 for ( let i = 0; i < this.tracks.length; i ++ ) { 40125 40126 valid = valid && this.tracks[ i ].validate(); 40127 40128 } 40129 40130 return valid; 40131 40132 } 40133 40134 optimize() { 40135 40136 for ( let i = 0; i < this.tracks.length; i ++ ) { 40137 40138 this.tracks[ i ].optimize(); 40139 40140 } 40141 40142 return this; 40143 40144 } 40145 40146 clone() { 40147 40148 const tracks = []; 40149 40150 for ( let i = 0; i < this.tracks.length; i ++ ) { 40151 40152 tracks.push( this.tracks[ i ].clone() ); 40153 40154 } 40155 40156 return new this.constructor( this.name, this.duration, tracks, this.blendMode ); 40157 40158 } 40159 40160 toJSON() { 40161 40162 return this.constructor.toJSON( this ); 40163 40164 } 40165 40166} 40167 40168function getTrackTypeForValueTypeName( typeName ) { 40169 40170 switch ( typeName.toLowerCase() ) { 40171 40172 case 'scalar': 40173 case 'double': 40174 case 'float': 40175 case 'number': 40176 case 'integer': 40177 40178 return NumberKeyframeTrack; 40179 40180 case 'vector': 40181 case 'vector2': 40182 case 'vector3': 40183 case 'vector4': 40184 40185 return VectorKeyframeTrack; 40186 40187 case 'color': 40188 40189 return ColorKeyframeTrack; 40190 40191 case 'quaternion': 40192 40193 return QuaternionKeyframeTrack; 40194 40195 case 'bool': 40196 case 'boolean': 40197 40198 return BooleanKeyframeTrack; 40199 40200 case 'string': 40201 40202 return StringKeyframeTrack; 40203 40204 } 40205 40206 throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); 40207 40208} 40209 40210function parseKeyframeTrack( json ) { 40211 40212 if ( json.type === undefined ) { 40213 40214 throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); 40215 40216 } 40217 40218 const trackType = getTrackTypeForValueTypeName( json.type ); 40219 40220 if ( json.times === undefined ) { 40221 40222 const times = [], values = []; 40223 40224 flattenJSON( json.keys, times, values, 'value' ); 40225 40226 json.times = times; 40227 json.values = values; 40228 40229 } 40230 40231 // derived classes can define a static parse method 40232 if ( trackType.parse !== undefined ) { 40233 40234 return trackType.parse( json ); 40235 40236 } else { 40237 40238 // by default, we assume a constructor compatible with the base 40239 return new trackType( json.name, json.times, json.values, json.interpolation ); 40240 40241 } 40242 40243} 40244 40245const Cache = { 40246 40247 enabled: false, 40248 40249 files: {}, 40250 40251 add: function ( key, file ) { 40252 40253 if ( this.enabled === false ) return; 40254 40255 // console.log( 'THREE.Cache', 'Adding key:', key ); 40256 40257 this.files[ key ] = file; 40258 40259 }, 40260 40261 get: function ( key ) { 40262 40263 if ( this.enabled === false ) return; 40264 40265 // console.log( 'THREE.Cache', 'Checking key:', key ); 40266 40267 return this.files[ key ]; 40268 40269 }, 40270 40271 remove: function ( key ) { 40272 40273 delete this.files[ key ]; 40274 40275 }, 40276 40277 clear: function () { 40278 40279 this.files = {}; 40280 40281 } 40282 40283}; 40284 40285class LoadingManager { 40286 40287 constructor( onLoad, onProgress, onError ) { 40288 40289 const scope = this; 40290 40291 let isLoading = false; 40292 let itemsLoaded = 0; 40293 let itemsTotal = 0; 40294 let urlModifier = undefined; 40295 const handlers = []; 40296 40297 // Refer to #5689 for the reason why we don't set .onStart 40298 // in the constructor 40299 40300 this.onStart = undefined; 40301 this.onLoad = onLoad; 40302 this.onProgress = onProgress; 40303 this.onError = onError; 40304 40305 this.itemStart = function ( url ) { 40306 40307 itemsTotal ++; 40308 40309 if ( isLoading === false ) { 40310 40311 if ( scope.onStart !== undefined ) { 40312 40313 scope.onStart( url, itemsLoaded, itemsTotal ); 40314 40315 } 40316 40317 } 40318 40319 isLoading = true; 40320 40321 }; 40322 40323 this.itemEnd = function ( url ) { 40324 40325 itemsLoaded ++; 40326 40327 if ( scope.onProgress !== undefined ) { 40328 40329 scope.onProgress( url, itemsLoaded, itemsTotal ); 40330 40331 } 40332 40333 if ( itemsLoaded === itemsTotal ) { 40334 40335 isLoading = false; 40336 40337 if ( scope.onLoad !== undefined ) { 40338 40339 scope.onLoad(); 40340 40341 } 40342 40343 } 40344 40345 }; 40346 40347 this.itemError = function ( url ) { 40348 40349 if ( scope.onError !== undefined ) { 40350 40351 scope.onError( url ); 40352 40353 } 40354 40355 }; 40356 40357 this.resolveURL = function ( url ) { 40358 40359 if ( urlModifier ) { 40360 40361 return urlModifier( url ); 40362 40363 } 40364 40365 return url; 40366 40367 }; 40368 40369 this.setURLModifier = function ( transform ) { 40370 40371 urlModifier = transform; 40372 40373 return this; 40374 40375 }; 40376 40377 this.addHandler = function ( regex, loader ) { 40378 40379 handlers.push( regex, loader ); 40380 40381 return this; 40382 40383 }; 40384 40385 this.removeHandler = function ( regex ) { 40386 40387 const index = handlers.indexOf( regex ); 40388 40389 if ( index !== - 1 ) { 40390 40391 handlers.splice( index, 2 ); 40392 40393 } 40394 40395 return this; 40396 40397 }; 40398 40399 this.getHandler = function ( file ) { 40400 40401 for ( let i = 0, l = handlers.length; i < l; i += 2 ) { 40402 40403 const regex = handlers[ i ]; 40404 const loader = handlers[ i + 1 ]; 40405 40406 if ( regex.global ) regex.lastIndex = 0; // see #17920 40407 40408 if ( regex.test( file ) ) { 40409 40410 return loader; 40411 40412 } 40413 40414 } 40415 40416 return null; 40417 40418 }; 40419 40420 } 40421 40422} 40423 40424const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager(); 40425 40426class Loader { 40427 40428 constructor( manager ) { 40429 40430 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 40431 40432 this.crossOrigin = 'anonymous'; 40433 this.withCredentials = false;
vendor: 12,657 bytes, lines 40434-41139
40434 this.path = ''; 40435 this.resourcePath = ''; 40436 this.requestHeader = {}; 40437 40438 } 40439 40440 load( /* url, onLoad, onProgress, onError */ ) {} 40441 40442 loadAsync( url, onProgress ) { 40443 40444 const scope = this; 40445 40446 return new Promise( function ( resolve, reject ) { 40447 40448 scope.load( url, resolve, onProgress, reject ); 40449 40450 } ); 40451 40452 } 40453 40454 parse( /* data */ ) {} 40455 40456 setCrossOrigin( crossOrigin ) { 40457 40458 this.crossOrigin = crossOrigin; 40459 return this; 40460 40461 } 40462 40463 setWithCredentials( value ) { 40464 40465 this.withCredentials = value; 40466 return this; 40467 40468 } 40469 40470 setPath( path ) { 40471 40472 this.path = path; 40473 return this; 40474 40475 } 40476 40477 setResourcePath( resourcePath ) { 40478 40479 this.resourcePath = resourcePath; 40480 return this; 40481 40482 } 40483 40484 setRequestHeader( requestHeader ) { 40485 40486 this.requestHeader = requestHeader; 40487 return this; 40488 40489 } 40490 40491} 40492 40493const loading = {}; 40494 40495class HttpError extends Error { 40496 40497 constructor( message, response ) { 40498 40499 super( message ); 40500 this.response = response; 40501 40502 } 40503 40504} 40505 40506class FileLoader extends Loader { 40507 40508 constructor( manager ) { 40509 40510 super( manager ); 40511 40512 } 40513 40514 load( url, onLoad, onProgress, onError ) { 40515 40516 if ( url === undefined ) url = ''; 40517 40518 if ( this.path !== undefined ) url = this.path + url; 40519 40520 url = this.manager.resolveURL( url ); 40521 40522 const cached = Cache.get( url ); 40523 40524 if ( cached !== undefined ) { 40525 40526 this.manager.itemStart( url ); 40527 40528 setTimeout( () => { 40529 40530 if ( onLoad ) onLoad( cached ); 40531 40532 this.manager.itemEnd( url ); 40533 40534 }, 0 ); 40535 40536 return cached; 40537 40538 } 40539 40540 // Check if request is duplicate 40541 40542 if ( loading[ url ] !== undefined ) { 40543 40544 loading[ url ].push( { 40545 40546 onLoad: onLoad, 40547 onProgress: onProgress, 40548 onError: onError 40549 40550 } ); 40551 40552 return; 40553 40554 } 40555 40556 // Initialise array for duplicate requests 40557 loading[ url ] = []; 40558 40559 loading[ url ].push( { 40560 onLoad: onLoad, 40561 onProgress: onProgress, 40562 onError: onError, 40563 } ); 40564 40565 // create request 40566 const req = new Request( url, { 40567 headers: new Headers( this.requestHeader ), 40568 credentials: this.withCredentials ? 'include' : 'same-origin', 40569 // An abort controller could be added within a future PR 40570 } ); 40571 40572 // record states ( avoid data race ) 40573 const mimeType = this.mimeType; 40574 const responseType = this.responseType; 40575 40576 // start the fetch 40577 fetch( req ) 40578 .then( response => { 40579 40580 if ( response.status === 200 || response.status === 0 ) { 40581 40582 // Some browsers return HTTP Status 0 when using non-http protocol 40583 // e.g. 'file://' or 'data://'. Handle as success. 40584 40585 if ( response.status === 0 ) { 40586 40587 console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); 40588 40589 } 40590 40591 // Workaround: Checking if response.body === undefined for Alipay browser #23548 40592 40593 if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) { 40594 40595 return response; 40596 40597 } 40598 40599 const callbacks = loading[ url ]; 40600 const reader = response.body.getReader(); 40601 40602 // Nginx needs X-File-Size check 40603 // https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content 40604 const contentLength = response.headers.get( 'Content-Length' ) || response.headers.get( 'X-File-Size' ); 40605 const total = contentLength ? parseInt( contentLength ) : 0; 40606 const lengthComputable = total !== 0; 40607 let loaded = 0; 40608 40609 // periodically read data into the new stream tracking while download progress 40610 const stream = new ReadableStream( { 40611 start( controller ) { 40612 40613 readData(); 40614 40615 function readData() { 40616 40617 reader.read().then( ( { done, value } ) => { 40618 40619 if ( done ) { 40620 40621 controller.close(); 40622 40623 } else { 40624 40625 loaded += value.byteLength; 40626 40627 const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } ); 40628 for ( let i = 0, il = callbacks.length; i < il; i ++ ) { 40629 40630 const callback = callbacks[ i ]; 40631 if ( callback.onProgress ) callback.onProgress( event ); 40632 40633 } 40634 40635 controller.enqueue( value ); 40636 readData(); 40637 40638 } 40639 40640 } ); 40641 40642 } 40643 40644 } 40645 40646 } ); 40647 40648 return new Response( stream ); 40649 40650 } else { 40651 40652 throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response ); 40653 40654 } 40655 40656 } ) 40657 .then( response => { 40658 40659 switch ( responseType ) { 40660 40661 case 'arraybuffer': 40662 40663 return response.arrayBuffer(); 40664 40665 case 'blob': 40666 40667 return response.blob(); 40668 40669 case 'document': 40670 40671 return response.text() 40672 .then( text => { 40673 40674 const parser = new DOMParser(); 40675 return parser.parseFromString( text, mimeType ); 40676 40677 } ); 40678 40679 case 'json': 40680 40681 return response.json(); 40682 40683 default: 40684 40685 if ( mimeType === undefined ) { 40686 40687 return response.text(); 40688 40689 } else { 40690 40691 // sniff encoding 40692 const re = /charset="?([^;"\s]*)"?/i; 40693 const exec = re.exec( mimeType ); 40694 const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined; 40695 const decoder = new TextDecoder( label ); 40696 return response.arrayBuffer().then( ab => decoder.decode( ab ) ); 40697 40698 } 40699 40700 } 40701 40702 } ) 40703 .then( data => { 40704 40705 // Add to cache only on HTTP success, so that we do not cache 40706 // error response bodies as proper responses to requests. 40707 Cache.add( url, data ); 40708 40709 const callbacks = loading[ url ]; 40710 delete loading[ url ]; 40711 40712 for ( let i = 0, il = callbacks.length; i < il; i ++ ) { 40713 40714 const callback = callbacks[ i ]; 40715 if ( callback.onLoad ) callback.onLoad( data ); 40716 40717 } 40718 40719 } ) 40720 .catch( err => { 40721 40722 // Abort errors and other errors are handled the same 40723 40724 const callbacks = loading[ url ]; 40725 40726 if ( callbacks === undefined ) { 40727 40728 // When onLoad was called and url was deleted in `loading` 40729 this.manager.itemError( url ); 40730 throw err; 40731 40732 } 40733 40734 delete loading[ url ]; 40735 40736 for ( let i = 0, il = callbacks.length; i < il; i ++ ) { 40737 40738 const callback = callbacks[ i ]; 40739 if ( callback.onError ) callback.onError( err ); 40740 40741 } 40742 40743 this.manager.itemError( url ); 40744 40745 } ) 40746 .finally( () => { 40747 40748 this.manager.itemEnd( url ); 40749 40750 } ); 40751 40752 this.manager.itemStart( url ); 40753 40754 } 40755 40756 setResponseType( value ) { 40757 40758 this.responseType = value; 40759 return this; 40760 40761 } 40762 40763 setMimeType( value ) { 40764 40765 this.mimeType = value; 40766 return this; 40767 40768 } 40769 40770} 40771 40772class AnimationLoader extends Loader { 40773 40774 constructor( manager ) { 40775 40776 super( manager ); 40777 40778 } 40779 40780 load( url, onLoad, onProgress, onError ) { 40781 40782 const scope = this; 40783 40784 const loader = new FileLoader( this.manager ); 40785 loader.setPath( this.path ); 40786 loader.setRequestHeader( this.requestHeader ); 40787 loader.setWithCredentials( this.withCredentials ); 40788 loader.load( url, function ( text ) { 40789 40790 try { 40791 40792 onLoad( scope.parse( JSON.parse( text ) ) ); 40793 40794 } catch ( e ) { 40795 40796 if ( onError ) { 40797 40798 onError( e ); 40799 40800 } else { 40801 40802 console.error( e ); 40803 40804 } 40805 40806 scope.manager.itemError( url ); 40807 40808 } 40809 40810 }, onProgress, onError ); 40811 40812 } 40813 40814 parse( json ) { 40815 40816 const animations = []; 40817 40818 for ( let i = 0; i < json.length; i ++ ) { 40819 40820 const clip = AnimationClip.parse( json[ i ] ); 40821 40822 animations.push( clip ); 40823 40824 } 40825 40826 return animations; 40827 40828 } 40829 40830} 40831 40832/** 40833 * Abstract Base class to block based textures loader (dds, pvr, ...) 40834 * 40835 * Sub classes have to implement the parse() method which will be used in load(). 40836 */ 40837 40838class CompressedTextureLoader extends Loader { 40839 40840 constructor( manager ) { 40841 40842 super( manager ); 40843 40844 } 40845 40846 load( url, onLoad, onProgress, onError ) { 40847 40848 const scope = this; 40849 40850 const images = []; 40851 40852 const texture = new CompressedTexture(); 40853 40854 const loader = new FileLoader( this.manager ); 40855 loader.setPath( this.path ); 40856 loader.setResponseType( 'arraybuffer' ); 40857 loader.setRequestHeader( this.requestHeader ); 40858 loader.setWithCredentials( scope.withCredentials ); 40859 40860 let loaded = 0; 40861 40862 function loadTexture( i ) { 40863 40864 loader.load( url[ i ], function ( buffer ) { 40865 40866 const texDatas = scope.parse( buffer, true ); 40867 40868 images[ i ] = { 40869 width: texDatas.width, 40870 height: texDatas.height, 40871 format: texDatas.format, 40872 mipmaps: texDatas.mipmaps 40873 }; 40874 40875 loaded += 1; 40876 40877 if ( loaded === 6 ) { 40878 40879 if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter; 40880 40881 texture.image = images; 40882 texture.format = texDatas.format; 40883 texture.needsUpdate = true; 40884 40885 if ( onLoad ) onLoad( texture ); 40886 40887 } 40888 40889 }, onProgress, onError ); 40890 40891 } 40892 40893 if ( Array.isArray( url ) ) { 40894 40895 for ( let i = 0, il = url.length; i < il; ++ i ) { 40896 40897 loadTexture( i ); 40898 40899 } 40900 40901 } else { 40902 40903 // compressed cubemap texture stored in a single DDS file 40904 40905 loader.load( url, function ( buffer ) { 40906 40907 const texDatas = scope.parse( buffer, true ); 40908 40909 if ( texDatas.isCubemap ) { 40910 40911 const faces = texDatas.mipmaps.length / texDatas.mipmapCount; 40912 40913 for ( let f = 0; f < faces; f ++ ) { 40914 40915 images[ f ] = { mipmaps: [] }; 40916 40917 for ( let i = 0; i < texDatas.mipmapCount; i ++ ) { 40918 40919 images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] ); 40920 images[ f ].format = texDatas.format; 40921 images[ f ].width = texDatas.width; 40922 images[ f ].height = texDatas.height; 40923 40924 } 40925 40926 } 40927 40928 texture.image = images; 40929 40930 } else { 40931 40932 texture.image.width = texDatas.width; 40933 texture.image.height = texDatas.height; 40934 texture.mipmaps = texDatas.mipmaps; 40935 40936 } 40937 40938 if ( texDatas.mipmapCount === 1 ) { 40939 40940 texture.minFilter = LinearFilter; 40941 40942 } 40943 40944 texture.format = texDatas.format; 40945 texture.needsUpdate = true; 40946 40947 if ( onLoad ) onLoad( texture ); 40948 40949 }, onProgress, onError ); 40950 40951 } 40952 40953 return texture; 40954 40955 } 40956 40957} 40958 40959class ImageLoader extends Loader { 40960 40961 constructor( manager ) { 40962 40963 super( manager ); 40964 40965 } 40966 40967 load( url, onLoad, onProgress, onError ) { 40968 40969 if ( this.path !== undefined ) url = this.path + url; 40970 40971 url = this.manager.resolveURL( url ); 40972 40973 const scope = this; 40974 40975 const cached = Cache.get( url ); 40976 40977 if ( cached !== undefined ) { 40978 40979 scope.manager.itemStart( url ); 40980 40981 setTimeout( function () { 40982 40983 if ( onLoad ) onLoad( cached ); 40984 40985 scope.manager.itemEnd( url ); 40986 40987 }, 0 ); 40988 40989 return cached; 40990 40991 } 40992 40993 const image = createElementNS( 'img' ); 40994 40995 function onImageLoad() { 40996 40997 removeEventListeners(); 40998 40999 Cache.add( url, this ); 41000 41001 if ( onLoad ) onLoad( this ); 41002 41003 scope.manager.itemEnd( url ); 41004 41005 } 41006 41007 function onImageError( event ) { 41008 41009 removeEventListeners(); 41010 41011 if ( onError ) onError( event ); 41012 41013 scope.manager.itemError( url ); 41014 scope.manager.itemEnd( url ); 41015 41016 } 41017 41018 function removeEventListeners() { 41019 41020 image.removeEventListener( 'load', onImageLoad, false ); 41021 image.removeEventListener( 'error', onImageError, false ); 41022 41023 } 41024 41025 image.addEventListener( 'load', onImageLoad, false ); 41026 image.addEventListener( 'error', onImageError, false ); 41027 41028 if ( url.slice( 0, 5 ) !== 'data:' ) { 41029 41030 if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; 41031 41032 } 41033 41034 scope.manager.itemStart( url ); 41035 41036 image.src = url; 41037 41038 return image; 41039 41040 } 41041 41042} 41043 41044class CubeTextureLoader extends Loader { 41045 41046 constructor( manager ) { 41047 41048 super( manager ); 41049 41050 } 41051 41052 load( urls, onLoad, onProgress, onError ) { 41053 41054 const texture = new CubeTexture(); 41055 41056 const loader = new ImageLoader( this.manager ); 41057 loader.setCrossOrigin( this.crossOrigin ); 41058 loader.setPath( this.path ); 41059 41060 let loaded = 0; 41061 41062 function loadTexture( i ) { 41063 41064 loader.load( urls[ i ], function ( image ) { 41065 41066 texture.images[ i ] = image; 41067 41068 loaded ++; 41069 41070 if ( loaded === 6 ) { 41071 41072 texture.needsUpdate = true; 41073 41074 if ( onLoad ) onLoad( texture ); 41075 41076 } 41077 41078 }, undefined, onError ); 41079 41080 } 41081 41082 for ( let i = 0; i < urls.length; ++ i ) { 41083 41084 loadTexture( i ); 41085 41086 } 41087 41088 return texture; 41089 41090 } 41091 41092} 41093 41094/** 41095 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) 41096 * 41097 * Sub classes have to implement the parse() method which will be used in load(). 41098 */ 41099 41100class DataTextureLoader extends Loader { 41101 41102 constructor( manager ) { 41103 41104 super( manager ); 41105 41106 } 41107 41108 load( url, onLoad, onProgress, onError ) { 41109 41110 const scope = this; 41111 41112 const texture = new DataTexture(); 41113 41114 const loader = new FileLoader( this.manager ); 41115 loader.setResponseType( 'arraybuffer' ); 41116 loader.setRequestHeader( this.requestHeader ); 41117 loader.setPath( this.path ); 41118 loader.setWithCredentials( scope.withCredentials ); 41119 loader.load( url, function ( buffer ) { 41120 41121 const texData = scope.parse( buffer ); 41122 41123 if ( ! texData ) return; 41124 41125 if ( texData.image !== undefined ) { 41126 41127 texture.image = texData.image; 41128 41129 } else if ( texData.data !== undefined ) { 41130 41131 texture.image.width = texData.width; 41132 texture.image.height = texData.height; 41133 texture.image.data = texData.data; 41134 41135 } 41136 41137 texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping; 41138 texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping; 41139
vendor: 4,947 bytes, lines 41140-41426
41140 texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter; 41141 texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter; 41142 41143 texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; 41144 41145 if ( texData.encoding !== undefined ) { 41146 41147 texture.encoding = texData.encoding; 41148 41149 } 41150 41151 if ( texData.flipY !== undefined ) { 41152 41153 texture.flipY = texData.flipY; 41154 41155 } 41156 41157 if ( texData.format !== undefined ) { 41158 41159 texture.format = texData.format; 41160 41161 } 41162 41163 if ( texData.type !== undefined ) { 41164 41165 texture.type = texData.type; 41166 41167 } 41168 41169 if ( texData.mipmaps !== undefined ) { 41170 41171 texture.mipmaps = texData.mipmaps; 41172 texture.minFilter = LinearMipmapLinearFilter; // presumably... 41173 41174 } 41175 41176 if ( texData.mipmapCount === 1 ) { 41177 41178 texture.minFilter = LinearFilter; 41179 41180 } 41181 41182 if ( texData.generateMipmaps !== undefined ) { 41183 41184 texture.generateMipmaps = texData.generateMipmaps; 41185 41186 } 41187 41188 texture.needsUpdate = true; 41189 41190 if ( onLoad ) onLoad( texture, texData ); 41191 41192 }, onProgress, onError ); 41193 41194 41195 return texture; 41196 41197 } 41198 41199} 41200 41201class TextureLoader extends Loader { 41202 41203 constructor( manager ) { 41204 41205 super( manager ); 41206 41207 } 41208 41209 load( url, onLoad, onProgress, onError ) { 41210 41211 const texture = new Texture(); 41212 41213 const loader = new ImageLoader( this.manager ); 41214 loader.setCrossOrigin( this.crossOrigin ); 41215 loader.setPath( this.path ); 41216 41217 loader.load( url, function ( image ) { 41218 41219 texture.image = image; 41220 texture.needsUpdate = true; 41221 41222 if ( onLoad !== undefined ) { 41223 41224 onLoad( texture ); 41225 41226 } 41227 41228 }, onProgress, onError ); 41229 41230 return texture; 41231 41232 } 41233 41234} 41235 41236class Light extends Object3D { 41237 41238 constructor( color, intensity = 1 ) { 41239 41240 super(); 41241 41242 this.isLight = true; 41243 41244 this.type = 'Light'; 41245 41246 this.color = new Color( color ); 41247 this.intensity = intensity; 41248 41249 } 41250 41251 dispose() { 41252 41253 // Empty here in base class; some subclasses override. 41254 41255 } 41256 41257 copy( source, recursive ) { 41258 41259 super.copy( source, recursive ); 41260 41261 this.color.copy( source.color ); 41262 this.intensity = source.intensity; 41263 41264 return this; 41265 41266 } 41267 41268 toJSON( meta ) { 41269 41270 const data = super.toJSON( meta ); 41271 41272 data.object.color = this.color.getHex(); 41273 data.object.intensity = this.intensity; 41274 41275 if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); 41276 41277 if ( this.distance !== undefined ) data.object.distance = this.distance; 41278 if ( this.angle !== undefined ) data.object.angle = this.angle; 41279 if ( this.decay !== undefined ) data.object.decay = this.decay; 41280 if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; 41281 41282 if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); 41283 41284 return data; 41285 41286 } 41287 41288} 41289 41290class HemisphereLight extends Light { 41291 41292 constructor( skyColor, groundColor, intensity ) { 41293 41294 super( skyColor, intensity ); 41295 41296 this.isHemisphereLight = true; 41297 41298 this.type = 'HemisphereLight'; 41299 41300 this.position.copy( Object3D.DEFAULT_UP ); 41301 this.updateMatrix(); 41302 41303 this.groundColor = new Color( groundColor ); 41304 41305 } 41306 41307 copy( source, recursive ) { 41308 41309 super.copy( source, recursive ); 41310 41311 this.groundColor.copy( source.groundColor ); 41312 41313 return this; 41314 41315 } 41316 41317} 41318 41319const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4(); 41320const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3(); 41321const _lookTarget$1 = /*@__PURE__*/ new Vector3(); 41322 41323class LightShadow { 41324 41325 constructor( camera ) { 41326 41327 this.camera = camera; 41328 41329 this.bias = 0; 41330 this.normalBias = 0; 41331 this.radius = 1; 41332 this.blurSamples = 8; 41333 41334 this.mapSize = new Vector2( 512, 512 ); 41335 41336 this.map = null; 41337 this.mapPass = null; 41338 this.matrix = new Matrix4(); 41339 41340 this.autoUpdate = true; 41341 this.needsUpdate = false; 41342 41343 this._frustum = new Frustum(); 41344 this._frameExtents = new Vector2( 1, 1 ); 41345 41346 this._viewportCount = 1; 41347 41348 this._viewports = [ 41349 41350 new Vector4( 0, 0, 1, 1 ) 41351 41352 ]; 41353 41354 } 41355 41356 getViewportCount() { 41357 41358 return this._viewportCount; 41359 41360 } 41361 41362 getFrustum() { 41363 41364 return this._frustum; 41365 41366 } 41367 41368 updateMatrices( light ) { 41369 41370 const shadowCamera = this.camera; 41371 const shadowMatrix = this.matrix; 41372 41373 _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld ); 41374 shadowCamera.position.copy( _lightPositionWorld$1 ); 41375 41376 _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld ); 41377 shadowCamera.lookAt( _lookTarget$1 ); 41378 shadowCamera.updateMatrixWorld(); 41379 41380 _projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); 41381 this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 ); 41382 41383 shadowMatrix.set( 41384 0.5, 0.0, 0.0, 0.5, 41385 0.0, 0.5, 0.0, 0.5, 41386 0.0, 0.0, 0.5, 0.5, 41387 0.0, 0.0, 0.0, 1.0 41388 ); 41389 41390 shadowMatrix.multiply( _projScreenMatrix$1 ); 41391 41392 } 41393 41394 getViewport( viewportIndex ) { 41395 41396 return this._viewports[ viewportIndex ]; 41397 41398 } 41399 41400 getFrameExtents() { 41401 41402 return this._frameExtents; 41403 41404 } 41405 41406 dispose() { 41407 41408 if ( this.map ) { 41409 41410 this.map.dispose(); 41411 41412 } 41413 41414 if ( this.mapPass ) { 41415 41416 this.mapPass.dispose(); 41417 41418 } 41419 41420 } 41421 41422 copy( source ) { 41423 41424 this.camera = source.camera.clone(); 41425 41426 this.bias = source.bias;
vendor: 5,709 bytes, lines 41427-41714
41427 this.radius = source.radius; 41428 41429 this.mapSize.copy( source.mapSize ); 41430 41431 return this; 41432 41433 } 41434 41435 clone() { 41436 41437 return new this.constructor().copy( this ); 41438 41439 } 41440 41441 toJSON() { 41442 41443 const object = {}; 41444 41445 if ( this.bias !== 0 ) object.bias = this.bias; 41446 if ( this.normalBias !== 0 ) object.normalBias = this.normalBias; 41447 if ( this.radius !== 1 ) object.radius = this.radius; 41448 if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray(); 41449 41450 object.camera = this.camera.toJSON( false ).object; 41451 delete object.camera.matrix; 41452 41453 return object; 41454 41455 } 41456 41457} 41458 41459class SpotLightShadow extends LightShadow { 41460 41461 constructor() { 41462 41463 super( new PerspectiveCamera( 50, 1, 0.5, 500 ) ); 41464 41465 this.isSpotLightShadow = true; 41466 41467 this.focus = 1; 41468 41469 } 41470 41471 updateMatrices( light ) { 41472 41473 const camera = this.camera; 41474 41475 const fov = RAD2DEG * 2 * light.angle * this.focus; 41476 const aspect = this.mapSize.width / this.mapSize.height; 41477 const far = light.distance || camera.far; 41478 41479 if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { 41480 41481 camera.fov = fov; 41482 camera.aspect = aspect; 41483 camera.far = far; 41484 camera.updateProjectionMatrix(); 41485 41486 } 41487 41488 super.updateMatrices( light ); 41489 41490 } 41491 41492 copy( source ) { 41493 41494 super.copy( source ); 41495 41496 this.focus = source.focus; 41497 41498 return this; 41499 41500 } 41501 41502} 41503 41504class SpotLight extends Light { 41505 41506 constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) { 41507 41508 super( color, intensity ); 41509 41510 this.isSpotLight = true; 41511 41512 this.type = 'SpotLight'; 41513 41514 this.position.copy( Object3D.DEFAULT_UP ); 41515 this.updateMatrix(); 41516 41517 this.target = new Object3D(); 41518 41519 this.distance = distance; 41520 this.angle = angle; 41521 this.penumbra = penumbra; 41522 this.decay = decay; 41523 41524 this.map = null; 41525 41526 this.shadow = new SpotLightShadow(); 41527 41528 } 41529 41530 get power() { 41531 41532 // compute the light's luminous power (in lumens) from its intensity (in candela) 41533 // by convention for a spotlight, luminous power (lm) = Ï * luminous intensity (cd) 41534 return this.intensity * Math.PI; 41535 41536 } 41537 41538 set power( power ) { 41539 41540 // set the light's intensity (in candela) from the desired luminous power (in lumens) 41541 this.intensity = power / Math.PI; 41542 41543 } 41544 41545 dispose() { 41546 41547 this.shadow.dispose(); 41548 41549 } 41550 41551 copy( source, recursive ) { 41552 41553 super.copy( source, recursive ); 41554 41555 this.distance = source.distance; 41556 this.angle = source.angle; 41557 this.penumbra = source.penumbra; 41558 this.decay = source.decay; 41559 41560 this.target = source.target.clone(); 41561 41562 this.shadow = source.shadow.clone(); 41563 41564 return this; 41565 41566 } 41567 41568} 41569 41570const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); 41571const _lightPositionWorld = /*@__PURE__*/ new Vector3(); 41572const _lookTarget = /*@__PURE__*/ new Vector3(); 41573 41574class PointLightShadow extends LightShadow { 41575 41576 constructor() { 41577 41578 super( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); 41579 41580 this.isPointLightShadow = true; 41581 41582 this._frameExtents = new Vector2( 4, 2 ); 41583 41584 this._viewportCount = 6; 41585 41586 this._viewports = [ 41587 // These viewports map a cube-map onto a 2D texture with the 41588 // following orientation: 41589 // 41590 // xzXZ 41591 // y Y 41592 // 41593 // X - Positive x direction 41594 // x - Negative x direction 41595 // Y - Positive y direction 41596 // y - Negative y direction 41597 // Z - Positive z direction 41598 // z - Negative z direction 41599 41600 // positive X 41601 new Vector4( 2, 1, 1, 1 ), 41602 // negative X 41603 new Vector4( 0, 1, 1, 1 ), 41604 // positive Z 41605 new Vector4( 3, 1, 1, 1 ), 41606 // negative Z 41607 new Vector4( 1, 1, 1, 1 ), 41608 // positive Y 41609 new Vector4( 3, 0, 1, 1 ), 41610 // negative Y 41611 new Vector4( 1, 0, 1, 1 ) 41612 ]; 41613 41614 this._cubeDirections = [ 41615 new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), 41616 new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) 41617 ]; 41618 41619 this._cubeUps = [ 41620 new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), 41621 new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) 41622 ]; 41623 41624 } 41625 41626 updateMatrices( light, viewportIndex = 0 ) { 41627 41628 const camera = this.camera; 41629 const shadowMatrix = this.matrix; 41630 41631 const far = light.distance || camera.far; 41632 41633 if ( far !== camera.far ) { 41634 41635 camera.far = far; 41636 camera.updateProjectionMatrix(); 41637 41638 } 41639 41640 _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); 41641 camera.position.copy( _lightPositionWorld ); 41642 41643 _lookTarget.copy( camera.position ); 41644 _lookTarget.add( this._cubeDirections[ viewportIndex ] ); 41645 camera.up.copy( this._cubeUps[ viewportIndex ] ); 41646 camera.lookAt( _lookTarget ); 41647 camera.updateMatrixWorld(); 41648 41649 shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); 41650 41651 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); 41652 this._frustum.setFromProjectionMatrix( _projScreenMatrix ); 41653 41654 } 41655 41656} 41657 41658class PointLight extends Light { 41659 41660 constructor( color, intensity, distance = 0, decay = 2 ) { 41661 41662 super( color, intensity ); 41663 41664 this.isPointLight = true; 41665 41666 this.type = 'PointLight'; 41667 41668 this.distance = distance; 41669 this.decay = decay; 41670 41671 this.shadow = new PointLightShadow(); 41672 41673 } 41674 41675 get power() { 41676 41677 // compute the light's luminous power (in lumens) from its intensity (in candela) 41678 // for an isotropic light source, luminous power (lm) = 4 Ï luminous intensity (cd) 41679 return this.intensity * 4 * Math.PI; 41680 41681 } 41682 41683 set power( power ) { 41684 41685 // set the light's intensity (in candela) from the desired luminous power (in lumens) 41686 this.intensity = power / ( 4 * Math.PI ); 41687 41688 } 41689 41690 dispose() { 41691 41692 this.shadow.dispose(); 41693 41694 } 41695 41696 copy( source, recursive ) { 41697 41698 super.copy( source, recursive ); 41699 41700 this.distance = source.distance; 41701 this.decay = source.decay; 41702 41703 this.shadow = source.shadow.clone(); 41704 41705 return this; 41706 41707 } 41708 41709} 41710 41711class DirectionalLightShadow extends LightShadow { 41712 41713 constructor() { 41714
vendor: 4,273 bytes, lines 41715-41936
41715 super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); 41716 41717 this.isDirectionalLightShadow = true; 41718 41719 } 41720 41721} 41722 41723class DirectionalLight extends Light { 41724 41725 constructor( color, intensity ) { 41726 41727 super( color, intensity ); 41728 41729 this.isDirectionalLight = true; 41730 41731 this.type = 'DirectionalLight'; 41732 41733 this.position.copy( Object3D.DEFAULT_UP ); 41734 this.updateMatrix(); 41735 41736 this.target = new Object3D(); 41737 41738 this.shadow = new DirectionalLightShadow(); 41739 41740 } 41741 41742 dispose() { 41743 41744 this.shadow.dispose(); 41745 41746 } 41747 41748 copy( source ) { 41749 41750 super.copy( source ); 41751 41752 this.target = source.target.clone(); 41753 this.shadow = source.shadow.clone(); 41754 41755 return this; 41756 41757 } 41758 41759} 41760 41761class AmbientLight extends Light { 41762 41763 constructor( color, intensity ) { 41764 41765 super( color, intensity ); 41766 41767 this.isAmbientLight = true; 41768 41769 this.type = 'AmbientLight'; 41770 41771 } 41772 41773} 41774 41775class RectAreaLight extends Light { 41776 41777 constructor( color, intensity, width = 10, height = 10 ) { 41778 41779 super( color, intensity ); 41780 41781 this.isRectAreaLight = true; 41782 41783 this.type = 'RectAreaLight'; 41784 41785 this.width = width; 41786 this.height = height; 41787 41788 } 41789 41790 get power() { 41791 41792 // compute the light's luminous power (in lumens) from its intensity (in nits) 41793 return this.intensity * this.width * this.height * Math.PI; 41794 41795 } 41796 41797 set power( power ) { 41798 41799 // set the light's intensity (in nits) from the desired luminous power (in lumens) 41800 this.intensity = power / ( this.width * this.height * Math.PI ); 41801 41802 } 41803 41804 copy( source ) { 41805 41806 super.copy( source ); 41807 41808 this.width = source.width; 41809 this.height = source.height; 41810 41811 return this; 41812 41813 } 41814 41815 toJSON( meta ) { 41816 41817 const data = super.toJSON( meta ); 41818 41819 data.object.width = this.width; 41820 data.object.height = this.height; 41821 41822 return data; 41823 41824 } 41825 41826} 41827 41828/** 41829 * Primary reference: 41830 * https://graphics.stanford.edu/papers/envmap/envmap.pdf 41831 * 41832 * Secondary reference: 41833 * https://www.ppsloan.org/publications/StupidSH36.pdf 41834 */ 41835 41836// 3-band SH defined by 9 coefficients 41837 41838class SphericalHarmonics3 { 41839 41840 constructor() { 41841 41842 this.isSphericalHarmonics3 = true; 41843 41844 this.coefficients = []; 41845 41846 for ( let i = 0; i < 9; i ++ ) { 41847 41848 this.coefficients.push( new Vector3() ); 41849 41850 } 41851 41852 } 41853 41854 set( coefficients ) { 41855 41856 for ( let i = 0; i < 9; i ++ ) { 41857 41858 this.coefficients[ i ].copy( coefficients[ i ] ); 41859 41860 } 41861 41862 return this; 41863 41864 } 41865 41866 zero() { 41867 41868 for ( let i = 0; i < 9; i ++ ) { 41869 41870 this.coefficients[ i ].set( 0, 0, 0 ); 41871 41872 } 41873 41874 return this; 41875 41876 } 41877 41878 // get the radiance in the direction of the normal 41879 // target is a Vector3 41880 getAt( normal, target ) { 41881 41882 // normal is assumed to be unit length 41883 41884 const x = normal.x, y = normal.y, z = normal.z; 41885 41886 const coeff = this.coefficients; 41887 41888 // band 0 41889 target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 ); 41890 41891 // band 1 41892 target.addScaledVector( coeff[ 1 ], 0.488603 * y ); 41893 target.addScaledVector( coeff[ 2 ], 0.488603 * z ); 41894 target.addScaledVector( coeff[ 3 ], 0.488603 * x ); 41895 41896 // band 2 41897 target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) ); 41898 target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) ); 41899 target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) ); 41900 target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) ); 41901 target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) ); 41902 41903 return target; 41904 41905 } 41906 41907 // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal 41908 // target is a Vector3 41909 // https://graphics.stanford.edu/papers/envmap/envmap.pdf 41910 getIrradianceAt( normal, target ) { 41911 41912 // normal is assumed to be unit length 41913 41914 const x = normal.x, y = normal.y, z = normal.z; 41915 41916 const coeff = this.coefficients; 41917 41918 // band 0 41919 target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // Ï * 0.282095 41920 41921 // band 1 41922 target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * Ï / 3 ) * 0.488603 41923 target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z ); 41924 target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x ); 41925 41926 // band 2 41927 target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( Ï / 4 ) * 1.092548 41928 target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z ); 41929 target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( Ï / 4 ) * 0.315392 * 3 41930 target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z ); 41931 target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( Ï / 4 ) * 0.546274 41932 41933 return target; 41934 41935 } 41936
vendor: 38,021 bytes, lines 41937-43558
41937 add( sh ) { 41938 41939 for ( let i = 0; i < 9; i ++ ) { 41940 41941 this.coefficients[ i ].add( sh.coefficients[ i ] ); 41942 41943 } 41944 41945 return this; 41946 41947 } 41948 41949 addScaledSH( sh, s ) { 41950 41951 for ( let i = 0; i < 9; i ++ ) { 41952 41953 this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s ); 41954 41955 } 41956 41957 return this; 41958 41959 } 41960 41961 scale( s ) { 41962 41963 for ( let i = 0; i < 9; i ++ ) { 41964 41965 this.coefficients[ i ].multiplyScalar( s ); 41966 41967 } 41968 41969 return this; 41970 41971 } 41972 41973 lerp( sh, alpha ) { 41974 41975 for ( let i = 0; i < 9; i ++ ) { 41976 41977 this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha ); 41978 41979 } 41980 41981 return this; 41982 41983 } 41984 41985 equals( sh ) { 41986 41987 for ( let i = 0; i < 9; i ++ ) { 41988 41989 if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) { 41990 41991 return false; 41992 41993 } 41994 41995 } 41996 41997 return true; 41998 41999 } 42000 42001 copy( sh ) { 42002 42003 return this.set( sh.coefficients ); 42004 42005 } 42006 42007 clone() { 42008 42009 return new this.constructor().copy( this ); 42010 42011 } 42012 42013 fromArray( array, offset = 0 ) { 42014 42015 const coefficients = this.coefficients; 42016 42017 for ( let i = 0; i < 9; i ++ ) { 42018 42019 coefficients[ i ].fromArray( array, offset + ( i * 3 ) ); 42020 42021 } 42022 42023 return this; 42024 42025 } 42026 42027 toArray( array = [], offset = 0 ) { 42028 42029 const coefficients = this.coefficients; 42030 42031 for ( let i = 0; i < 9; i ++ ) { 42032 42033 coefficients[ i ].toArray( array, offset + ( i * 3 ) ); 42034 42035 } 42036 42037 return array; 42038 42039 } 42040 42041 // evaluate the basis functions 42042 // shBasis is an Array[ 9 ] 42043 static getBasisAt( normal, shBasis ) { 42044 42045 // normal is assumed to be unit length 42046 42047 const x = normal.x, y = normal.y, z = normal.z; 42048 42049 // band 0 42050 shBasis[ 0 ] = 0.282095; 42051 42052 // band 1 42053 shBasis[ 1 ] = 0.488603 * y; 42054 shBasis[ 2 ] = 0.488603 * z; 42055 shBasis[ 3 ] = 0.488603 * x; 42056 42057 // band 2 42058 shBasis[ 4 ] = 1.092548 * x * y; 42059 shBasis[ 5 ] = 1.092548 * y * z; 42060 shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 ); 42061 shBasis[ 7 ] = 1.092548 * x * z; 42062 shBasis[ 8 ] = 0.546274 * ( x * x - y * y ); 42063 42064 } 42065 42066} 42067 42068class LightProbe extends Light { 42069 42070 constructor( sh = new SphericalHarmonics3(), intensity = 1 ) { 42071 42072 super( undefined, intensity ); 42073 42074 this.isLightProbe = true; 42075 42076 this.sh = sh; 42077 42078 } 42079 42080 copy( source ) { 42081 42082 super.copy( source ); 42083 42084 this.sh.copy( source.sh ); 42085 42086 return this; 42087 42088 } 42089 42090 fromJSON( json ) { 42091 42092 this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON(); 42093 this.sh.fromArray( json.sh ); 42094 42095 return this; 42096 42097 } 42098 42099 toJSON( meta ) { 42100 42101 const data = super.toJSON( meta ); 42102 42103 data.object.sh = this.sh.toArray(); 42104 42105 return data; 42106 42107 } 42108 42109} 42110 42111class MaterialLoader extends Loader { 42112 42113 constructor( manager ) { 42114 42115 super( manager ); 42116 this.textures = {}; 42117 42118 } 42119 42120 load( url, onLoad, onProgress, onError ) { 42121 42122 const scope = this; 42123 42124 const loader = new FileLoader( scope.manager ); 42125 loader.setPath( scope.path ); 42126 loader.setRequestHeader( scope.requestHeader ); 42127 loader.setWithCredentials( scope.withCredentials ); 42128 loader.load( url, function ( text ) { 42129 42130 try { 42131 42132 onLoad( scope.parse( JSON.parse( text ) ) ); 42133 42134 } catch ( e ) { 42135 42136 if ( onError ) { 42137 42138 onError( e ); 42139 42140 } else { 42141 42142 console.error( e ); 42143 42144 } 42145 42146 scope.manager.itemError( url ); 42147 42148 } 42149 42150 }, onProgress, onError ); 42151 42152 } 42153 42154 parse( json ) { 42155 42156 const textures = this.textures; 42157 42158 function getTexture( name ) { 42159 42160 if ( textures[ name ] === undefined ) { 42161 42162 console.warn( 'THREE.MaterialLoader: Undefined texture', name ); 42163 42164 } 42165 42166 return textures[ name ]; 42167 42168 } 42169 42170 const material = MaterialLoader.createMaterialFromType( json.type ); 42171 42172 if ( json.uuid !== undefined ) material.uuid = json.uuid; 42173 if ( json.name !== undefined ) material.name = json.name; 42174 if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color ); 42175 if ( json.roughness !== undefined ) material.roughness = json.roughness; 42176 if ( json.metalness !== undefined ) material.metalness = json.metalness; 42177 if ( json.sheen !== undefined ) material.sheen = json.sheen; 42178 if ( json.sheenColor !== undefined ) material.sheenColor = new Color().setHex( json.sheenColor ); 42179 if ( json.sheenRoughness !== undefined ) material.sheenRoughness = json.sheenRoughness; 42180 if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive ); 42181 if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular ); 42182 if ( json.specularIntensity !== undefined ) material.specularIntensity = json.specularIntensity; 42183 if ( json.specularColor !== undefined && material.specularColor !== undefined ) material.specularColor.setHex( json.specularColor ); 42184 if ( json.shininess !== undefined ) material.shininess = json.shininess; 42185 if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat; 42186 if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness; 42187 if ( json.iridescence !== undefined ) material.iridescence = json.iridescence; 42188 if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR; 42189 if ( json.iridescenceThicknessRange !== undefined ) material.iridescenceThicknessRange = json.iridescenceThicknessRange; 42190 if ( json.transmission !== undefined ) material.transmission = json.transmission; 42191 if ( json.thickness !== undefined ) material.thickness = json.thickness; 42192 if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance; 42193 if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor ); 42194 if ( json.fog !== undefined ) material.fog = json.fog; 42195 if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; 42196 if ( json.blending !== undefined ) material.blending = json.blending; 42197 if ( json.combine !== undefined ) material.combine = json.combine; 42198 if ( json.side !== undefined ) material.side = json.side; 42199 if ( json.shadowSide !== undefined ) material.shadowSide = json.shadowSide; 42200 if ( json.opacity !== undefined ) material.opacity = json.opacity; 42201 if ( json.transparent !== undefined ) material.transparent = json.transparent; 42202 if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest; 42203 if ( json.depthTest !== undefined ) material.depthTest = json.depthTest; 42204 if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite; 42205 if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite; 42206 42207 if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite; 42208 if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask; 42209 if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc; 42210 if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef; 42211 if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask; 42212 if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail; 42213 if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail; 42214 if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass; 42215 42216 if ( json.wireframe !== undefined ) material.wireframe = json.wireframe; 42217 if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth; 42218 if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap; 42219 if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin; 42220 42221 if ( json.rotation !== undefined ) material.rotation = json.rotation; 42222 42223 if ( json.linewidth !== 1 ) material.linewidth = json.linewidth; 42224 if ( json.dashSize !== undefined ) material.dashSize = json.dashSize; 42225 if ( json.gapSize !== undefined ) material.gapSize = json.gapSize; 42226 if ( json.scale !== undefined ) material.scale = json.scale; 42227 42228 if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset; 42229 if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor; 42230 if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits; 42231 42232 if ( json.dithering !== undefined ) material.dithering = json.dithering; 42233 42234 if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage; 42235 if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha; 42236 if ( json.forceSinglePass !== undefined ) material.forceSinglePass = json.forceSinglePass; 42237 42238 if ( json.visible !== undefined ) material.visible = json.visible; 42239 42240 if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped; 42241 42242 if ( json.userData !== undefined ) material.userData = json.userData; 42243 42244 if ( json.vertexColors !== undefined ) { 42245 42246 if ( typeof json.vertexColors === 'number' ) { 42247 42248 material.vertexColors = ( json.vertexColors > 0 ) ? true : false; 42249 42250 } else { 42251 42252 material.vertexColors = json.vertexColors; 42253 42254 } 42255 42256 } 42257 42258 // Shader Material 42259 42260 if ( json.uniforms !== undefined ) { 42261 42262 for ( const name in json.uniforms ) { 42263 42264 const uniform = json.uniforms[ name ]; 42265 42266 material.uniforms[ name ] = {}; 42267 42268 switch ( uniform.type ) { 42269 42270 case 't': 42271 material.uniforms[ name ].value = getTexture( uniform.value ); 42272 break; 42273 42274 case 'c': 42275 material.uniforms[ name ].value = new Color().setHex( uniform.value ); 42276 break; 42277 42278 case 'v2': 42279 material.uniforms[ name ].value = new Vector2().fromArray( uniform.value ); 42280 break; 42281 42282 case 'v3': 42283 material.uniforms[ name ].value = new Vector3().fromArray( uniform.value ); 42284 break; 42285 42286 case 'v4': 42287 material.uniforms[ name ].value = new Vector4().fromArray( uniform.value ); 42288 break; 42289 42290 case 'm3': 42291 material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value ); 42292 break; 42293 42294 case 'm4': 42295 material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value ); 42296 break; 42297 42298 default: 42299 material.uniforms[ name ].value = uniform.value; 42300 42301 } 42302 42303 } 42304 42305 } 42306 42307 if ( json.defines !== undefined ) material.defines = json.defines; 42308 if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader; 42309 if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; 42310 if ( json.glslVersion !== undefined ) material.glslVersion = json.glslVersion; 42311 42312 if ( json.extensions !== undefined ) { 42313 42314 for ( const key in json.extensions ) { 42315 42316 material.extensions[ key ] = json.extensions[ key ]; 42317 42318 } 42319 42320 } 42321 42322 // for PointsMaterial 42323 42324 if ( json.size !== undefined ) material.size = json.size; 42325 if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation; 42326 42327 // maps 42328 42329 if ( json.map !== undefined ) material.map = getTexture( json.map ); 42330 if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap ); 42331 42332 if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap ); 42333 42334 if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap ); 42335 if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale; 42336 42337 if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap ); 42338 if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType; 42339 if ( json.normalScale !== undefined ) { 42340 42341 let normalScale = json.normalScale; 42342 42343 if ( Array.isArray( normalScale ) === false ) { 42344 42345 // Blender exporter used to export a scalar. See #7459 42346 42347 normalScale = [ normalScale, normalScale ]; 42348 42349 } 42350 42351 material.normalScale = new Vector2().fromArray( normalScale ); 42352 42353 } 42354 42355 if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap ); 42356 if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale; 42357 if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias; 42358 42359 if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap ); 42360 if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap ); 42361 42362 if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap ); 42363 if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity; 42364 42365 if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap ); 42366 if ( json.specularIntensityMap !== undefined ) material.specularIntensityMap = getTexture( json.specularIntensityMap ); 42367 if ( json.specularColorMap !== undefined ) material.specularColorMap = getTexture( json.specularColorMap ); 42368 42369 if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap ); 42370 if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity; 42371 42372 if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity; 42373 if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio; 42374 42375 if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap ); 42376 if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity; 42377 42378 if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap ); 42379 if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity; 42380 42381 if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap ); 42382 42383 if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap ); 42384 if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap ); 42385 if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap ); 42386 if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale ); 42387 42388 if ( json.iridescenceMap !== undefined ) material.iridescenceMap = getTexture( json.iridescenceMap ); 42389 if ( json.iridescenceThicknessMap !== undefined ) material.iridescenceThicknessMap = getTexture( json.iridescenceThicknessMap ); 42390 42391 if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap ); 42392 if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap ); 42393 42394 if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap ); 42395 if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap ); 42396 42397 return material; 42398 42399 } 42400 42401 setTextures( value ) { 42402 42403 this.textures = value; 42404 return this; 42405 42406 } 42407 42408 static createMaterialFromType( type ) { 42409 42410 const materialLib = { 42411 ShadowMaterial, 42412 SpriteMaterial, 42413 RawShaderMaterial, 42414 ShaderMaterial, 42415 PointsMaterial, 42416 MeshPhysicalMaterial, 42417 MeshStandardMaterial, 42418 MeshPhongMaterial, 42419 MeshToonMaterial, 42420 MeshNormalMaterial, 42421 MeshLambertMaterial, 42422 MeshDepthMaterial, 42423 MeshDistanceMaterial, 42424 MeshBasicMaterial, 42425 MeshMatcapMaterial, 42426 LineDashedMaterial, 42427 LineBasicMaterial, 42428 Material 42429 }; 42430 42431 return new materialLib[ type ](); 42432 42433 } 42434 42435} 42436 42437class LoaderUtils { 42438 42439 static decodeText( array ) { 42440 42441 if ( typeof TextDecoder !== 'undefined' ) { 42442 42443 return new TextDecoder().decode( array ); 42444 42445 } 42446 42447 // Avoid the String.fromCharCode.apply(null, array) shortcut, which 42448 // throws a "maximum call stack size exceeded" error for large arrays. 42449 42450 let s = ''; 42451 42452 for ( let i = 0, il = array.length; i < il; i ++ ) { 42453 42454 // Implicitly assumes little-endian. 42455 s += String.fromCharCode( array[ i ] ); 42456 42457 } 42458 42459 try { 42460 42461 // merges multi-byte utf-8 characters. 42462 42463 return decodeURIComponent( escape( s ) ); 42464 42465 } catch ( e ) { // see #16358 42466 42467 return s; 42468 42469 } 42470 42471 } 42472 42473 static extractUrlBase( url ) { 42474 42475 const index = url.lastIndexOf( '/' ); 42476 42477 if ( index === - 1 ) return './'; 42478 42479 return url.slice( 0, index + 1 ); 42480 42481 } 42482 42483 static resolveURL( url, path ) { 42484 42485 // Invalid URL 42486 if ( typeof url !== 'string' || url === '' ) return ''; 42487 42488 // Host Relative URL 42489 if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) { 42490 42491 path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' ); 42492 42493 } 42494 42495 // Absolute URL http://,https://,// 42496 if ( /^(https?:)?\/\//i.test( url ) ) return url; 42497 42498 // Data URI 42499 if ( /^data:.*,.*$/i.test( url ) ) return url; 42500 42501 // Blob URL 42502 if ( /^blob:.*$/i.test( url ) ) return url; 42503 42504 // Relative URL 42505 return path + url; 42506 42507 } 42508 42509} 42510 42511class InstancedBufferGeometry extends BufferGeometry { 42512 42513 constructor() { 42514 42515 super(); 42516 42517 this.isInstancedBufferGeometry = true; 42518 42519 this.type = 'InstancedBufferGeometry'; 42520 this.instanceCount = Infinity; 42521 42522 } 42523 42524 copy( source ) { 42525 42526 super.copy( source ); 42527 42528 this.instanceCount = source.instanceCount; 42529 42530 return this; 42531 42532 } 42533 42534 toJSON() { 42535 42536 const data = super.toJSON(); 42537 42538 data.instanceCount = this.instanceCount; 42539 42540 data.isInstancedBufferGeometry = true; 42541 42542 return data; 42543 42544 } 42545 42546} 42547 42548class BufferGeometryLoader extends Loader { 42549 42550 constructor( manager ) { 42551 42552 super( manager ); 42553 42554 } 42555 42556 load( url, onLoad, onProgress, onError ) { 42557 42558 const scope = this; 42559 42560 const loader = new FileLoader( scope.manager ); 42561 loader.setPath( scope.path ); 42562 loader.setRequestHeader( scope.requestHeader ); 42563 loader.setWithCredentials( scope.withCredentials ); 42564 loader.load( url, function ( text ) { 42565 42566 try { 42567 42568 onLoad( scope.parse( JSON.parse( text ) ) ); 42569 42570 } catch ( e ) { 42571 42572 if ( onError ) { 42573 42574 onError( e ); 42575 42576 } else { 42577 42578 console.error( e ); 42579 42580 } 42581 42582 scope.manager.itemError( url ); 42583 42584 } 42585 42586 }, onProgress, onError ); 42587 42588 } 42589 42590 parse( json ) { 42591 42592 const interleavedBufferMap = {}; 42593 const arrayBufferMap = {}; 42594 42595 function getInterleavedBuffer( json, uuid ) { 42596 42597 if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ]; 42598 42599 const interleavedBuffers = json.interleavedBuffers; 42600 const interleavedBuffer = interleavedBuffers[ uuid ]; 42601 42602 const buffer = getArrayBuffer( json, interleavedBuffer.buffer ); 42603 42604 const array = getTypedArray( interleavedBuffer.type, buffer ); 42605 const ib = new InterleavedBuffer( array, interleavedBuffer.stride ); 42606 ib.uuid = interleavedBuffer.uuid; 42607 42608 interleavedBufferMap[ uuid ] = ib; 42609 42610 return ib; 42611 42612 } 42613 42614 function getArrayBuffer( json, uuid ) { 42615 42616 if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ]; 42617 42618 const arrayBuffers = json.arrayBuffers; 42619 const arrayBuffer = arrayBuffers[ uuid ]; 42620 42621 const ab = new Uint32Array( arrayBuffer ).buffer; 42622 42623 arrayBufferMap[ uuid ] = ab; 42624 42625 return ab; 42626 42627 } 42628 42629 const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry(); 42630 42631 const index = json.data.index; 42632 42633 if ( index !== undefined ) { 42634 42635 const typedArray = getTypedArray( index.type, index.array ); 42636 geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); 42637 42638 } 42639 42640 const attributes = json.data.attributes; 42641 42642 for ( const key in attributes ) { 42643 42644 const attribute = attributes[ key ]; 42645 let bufferAttribute; 42646 42647 if ( attribute.isInterleavedBufferAttribute ) { 42648 42649 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); 42650 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); 42651 42652 } else { 42653 42654 const typedArray = getTypedArray( attribute.type, attribute.array ); 42655 const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute; 42656 bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized ); 42657 42658 } 42659 42660 if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; 42661 if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage ); 42662 42663 if ( attribute.updateRange !== undefined ) { 42664 42665 bufferAttribute.updateRange.offset = attribute.updateRange.offset; 42666 bufferAttribute.updateRange.count = attribute.updateRange.count; 42667 42668 } 42669 42670 geometry.setAttribute( key, bufferAttribute ); 42671 42672 } 42673 42674 const morphAttributes = json.data.morphAttributes; 42675 42676 if ( morphAttributes ) { 42677 42678 for ( const key in morphAttributes ) { 42679 42680 const attributeArray = morphAttributes[ key ]; 42681 42682 const array = []; 42683 42684 for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { 42685 42686 const attribute = attributeArray[ i ]; 42687 let bufferAttribute; 42688 42689 if ( attribute.isInterleavedBufferAttribute ) { 42690 42691 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); 42692 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); 42693 42694 } else { 42695 42696 const typedArray = getTypedArray( attribute.type, attribute.array ); 42697 bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ); 42698 42699 } 42700 42701 if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; 42702 array.push( bufferAttribute ); 42703 42704 } 42705 42706 geometry.morphAttributes[ key ] = array; 42707 42708 } 42709 42710 } 42711 42712 const morphTargetsRelative = json.data.morphTargetsRelative; 42713 42714 if ( morphTargetsRelative ) { 42715 42716 geometry.morphTargetsRelative = true; 42717 42718 } 42719 42720 const groups = json.data.groups || json.data.drawcalls || json.data.offsets; 42721 42722 if ( groups !== undefined ) { 42723 42724 for ( let i = 0, n = groups.length; i !== n; ++ i ) { 42725 42726 const group = groups[ i ]; 42727 42728 geometry.addGroup( group.start, group.count, group.materialIndex ); 42729 42730 } 42731 42732 } 42733 42734 const boundingSphere = json.data.boundingSphere; 42735 42736 if ( boundingSphere !== undefined ) { 42737 42738 const center = new Vector3(); 42739 42740 if ( boundingSphere.center !== undefined ) { 42741 42742 center.fromArray( boundingSphere.center ); 42743 42744 } 42745 42746 geometry.boundingSphere = new Sphere( center, boundingSphere.radius ); 42747 42748 } 42749 42750 if ( json.name ) geometry.name = json.name; 42751 if ( json.userData ) geometry.userData = json.userData; 42752 42753 return geometry; 42754 42755 } 42756 42757} 42758 42759class ObjectLoader extends Loader { 42760 42761 constructor( manager ) { 42762 42763 super( manager ); 42764 42765 } 42766 42767 load( url, onLoad, onProgress, onError ) { 42768 42769 const scope = this; 42770 42771 const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; 42772 this.resourcePath = this.resourcePath || path; 42773 42774 const loader = new FileLoader( this.manager ); 42775 loader.setPath( this.path ); 42776 loader.setRequestHeader( this.requestHeader ); 42777 loader.setWithCredentials( this.withCredentials ); 42778 loader.load( url, function ( text ) { 42779 42780 let json = null; 42781 42782 try { 42783 42784 json = JSON.parse( text ); 42785 42786 } catch ( error ) { 42787 42788 if ( onError !== undefined ) onError( error ); 42789 42790 console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); 42791 42792 return; 42793 42794 } 42795 42796 const metadata = json.metadata; 42797 42798 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { 42799 42800 if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) ); 42801 42802 console.error( 'THREE.ObjectLoader: Can\'t load ' + url ); 42803 return; 42804 42805 } 42806 42807 scope.parse( json, onLoad ); 42808 42809 }, onProgress, onError ); 42810 42811 } 42812 42813 async loadAsync( url, onProgress ) { 42814 42815 const scope = this; 42816 42817 const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; 42818 this.resourcePath = this.resourcePath || path; 42819 42820 const loader = new FileLoader( this.manager ); 42821 loader.setPath( this.path ); 42822 loader.setRequestHeader( this.requestHeader ); 42823 loader.setWithCredentials( this.withCredentials ); 42824 42825 const text = await loader.loadAsync( url, onProgress ); 42826 42827 const json = JSON.parse( text ); 42828 42829 const metadata = json.metadata; 42830 42831 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { 42832 42833 throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url ); 42834 42835 } 42836 42837 return await scope.parseAsync( json ); 42838 42839 } 42840 42841 parse( json, onLoad ) { 42842 42843 const animations = this.parseAnimations( json.animations ); 42844 const shapes = this.parseShapes( json.shapes ); 42845 const geometries = this.parseGeometries( json.geometries, shapes ); 42846 42847 const images = this.parseImages( json.images, function () { 42848 42849 if ( onLoad !== undefined ) onLoad( object ); 42850 42851 } ); 42852 42853 const textures = this.parseTextures( json.textures, images ); 42854 const materials = this.parseMaterials( json.materials, textures ); 42855 42856 const object = this.parseObject( json.object, geometries, materials, textures, animations ); 42857 const skeletons = this.parseSkeletons( json.skeletons, object ); 42858 42859 this.bindSkeletons( object, skeletons ); 42860 42861 // 42862 42863 if ( onLoad !== undefined ) { 42864 42865 let hasImages = false; 42866 42867 for ( const uuid in images ) { 42868 42869 if ( images[ uuid ].data instanceof HTMLImageElement ) { 42870 42871 hasImages = true; 42872 break; 42873 42874 } 42875 42876 } 42877 42878 if ( hasImages === false ) onLoad( object ); 42879 42880 } 42881 42882 return object; 42883 42884 } 42885 42886 async parseAsync( json ) { 42887 42888 const animations = this.parseAnimations( json.animations ); 42889 const shapes = this.parseShapes( json.shapes ); 42890 const geometries = this.parseGeometries( json.geometries, shapes ); 42891 42892 const images = await this.parseImagesAsync( json.images ); 42893 42894 const textures = this.parseTextures( json.textures, images ); 42895 const materials = this.parseMaterials( json.materials, textures ); 42896 42897 const object = this.parseObject( json.object, geometries, materials, textures, animations ); 42898 const skeletons = this.parseSkeletons( json.skeletons, object ); 42899 42900 this.bindSkeletons( object, skeletons ); 42901 42902 return object; 42903 42904 } 42905 42906 parseShapes( json ) { 42907 42908 const shapes = {}; 42909 42910 if ( json !== undefined ) { 42911 42912 for ( let i = 0, l = json.length; i < l; i ++ ) { 42913 42914 const shape = new Shape().fromJSON( json[ i ] ); 42915 42916 shapes[ shape.uuid ] = shape; 42917 42918 } 42919 42920 } 42921 42922 return shapes; 42923 42924 } 42925 42926 parseSkeletons( json, object ) { 42927 42928 const skeletons = {}; 42929 const bones = {}; 42930 42931 // generate bone lookup table 42932 42933 object.traverse( function ( child ) { 42934 42935 if ( child.isBone ) bones[ child.uuid ] = child; 42936 42937 } ); 42938 42939 // create skeletons 42940 42941 if ( json !== undefined ) { 42942 42943 for ( let i = 0, l = json.length; i < l; i ++ ) { 42944 42945 const skeleton = new Skeleton().fromJSON( json[ i ], bones ); 42946 42947 skeletons[ skeleton.uuid ] = skeleton; 42948 42949 } 42950 42951 } 42952 42953 return skeletons; 42954 42955 } 42956 42957 parseGeometries( json, shapes ) { 42958 42959 const geometries = {}; 42960 42961 if ( json !== undefined ) { 42962 42963 const bufferGeometryLoader = new BufferGeometryLoader(); 42964 42965 for ( let i = 0, l = json.length; i < l; i ++ ) { 42966 42967 let geometry; 42968 const data = json[ i ]; 42969 42970 switch ( data.type ) { 42971 42972 case 'BufferGeometry': 42973 case 'InstancedBufferGeometry': 42974 42975 geometry = bufferGeometryLoader.parse( data ); 42976 break; 42977 42978 default: 42979 42980 if ( data.type in Geometries ) { 42981 42982 geometry = Geometries[ data.type ].fromJSON( data, shapes ); 42983 42984 } else { 42985 42986 console.warn( `THREE.ObjectLoader: Unsupported geometry type "${ data.type }"` ); 42987 42988 } 42989 42990 } 42991 42992 geometry.uuid = data.uuid; 42993 42994 if ( data.name !== undefined ) geometry.name = data.name; 42995 if ( data.userData !== undefined ) geometry.userData = data.userData; 42996 42997 geometries[ data.uuid ] = geometry; 42998 42999 } 43000 43001 } 43002 43003 return geometries; 43004 43005 } 43006 43007 parseMaterials( json, textures ) { 43008 43009 const cache = {}; // MultiMaterial 43010 const materials = {}; 43011 43012 if ( json !== undefined ) { 43013 43014 const loader = new MaterialLoader(); 43015 loader.setTextures( textures ); 43016 43017 for ( let i = 0, l = json.length; i < l; i ++ ) { 43018 43019 const data = json[ i ]; 43020 43021 if ( cache[ data.uuid ] === undefined ) { 43022 43023 cache[ data.uuid ] = loader.parse( data ); 43024 43025 } 43026 43027 materials[ data.uuid ] = cache[ data.uuid ]; 43028 43029 } 43030 43031 } 43032 43033 return materials; 43034 43035 } 43036 43037 parseAnimations( json ) { 43038 43039 const animations = {}; 43040 43041 if ( json !== undefined ) { 43042 43043 for ( let i = 0; i < json.length; i ++ ) { 43044 43045 const data = json[ i ]; 43046 43047 const clip = AnimationClip.parse( data ); 43048 43049 animations[ clip.uuid ] = clip; 43050 43051 } 43052 43053 } 43054 43055 return animations; 43056 43057 } 43058 43059 parseImages( json, onLoad ) { 43060 43061 const scope = this; 43062 const images = {}; 43063 43064 let loader; 43065 43066 function loadImage( url ) { 43067 43068 scope.manager.itemStart( url ); 43069 43070 return loader.load( url, function () { 43071 43072 scope.manager.itemEnd( url ); 43073 43074 }, undefined, function () { 43075 43076 scope.manager.itemError( url ); 43077 scope.manager.itemEnd( url ); 43078 43079 } ); 43080 43081 } 43082 43083 function deserializeImage( image ) { 43084 43085 if ( typeof image === 'string' ) { 43086 43087 const url = image; 43088 43089 const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; 43090 43091 return loadImage( path ); 43092 43093 } else { 43094 43095 if ( image.data ) { 43096 43097 return { 43098 data: getTypedArray( image.type, image.data ), 43099 width: image.width, 43100 height: image.height 43101 }; 43102 43103 } else { 43104 43105 return null; 43106 43107 } 43108 43109 } 43110 43111 } 43112 43113 if ( json !== undefined && json.length > 0 ) { 43114 43115 const manager = new LoadingManager( onLoad ); 43116 43117 loader = new ImageLoader( manager ); 43118 loader.setCrossOrigin( this.crossOrigin ); 43119 43120 for ( let i = 0, il = json.length; i < il; i ++ ) { 43121 43122 const image = json[ i ]; 43123 const url = image.url; 43124 43125 if ( Array.isArray( url ) ) { 43126 43127 // load array of images e.g CubeTexture 43128 43129 const imageArray = []; 43130 43131 for ( let j = 0, jl = url.length; j < jl; j ++ ) { 43132 43133 const currentUrl = url[ j ]; 43134 43135 const deserializedImage = deserializeImage( currentUrl ); 43136 43137 if ( deserializedImage !== null ) { 43138 43139 if ( deserializedImage instanceof HTMLImageElement ) { 43140 43141 imageArray.push( deserializedImage ); 43142 43143 } else { 43144 43145 // special case: handle array of data textures for cube textures 43146 43147 imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); 43148 43149 } 43150 43151 } 43152 43153 } 43154 43155 images[ image.uuid ] = new Source( imageArray ); 43156 43157 } else { 43158 43159 // load single image 43160 43161 const deserializedImage = deserializeImage( image.url ); 43162 images[ image.uuid ] = new Source( deserializedImage ); 43163 43164 43165 } 43166 43167 } 43168 43169 } 43170 43171 return images; 43172 43173 } 43174 43175 async parseImagesAsync( json ) { 43176 43177 const scope = this; 43178 const images = {}; 43179 43180 let loader; 43181 43182 async function deserializeImage( image ) { 43183 43184 if ( typeof image === 'string' ) { 43185 43186 const url = image; 43187 43188 const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; 43189 43190 return await loader.loadAsync( path ); 43191 43192 } else { 43193 43194 if ( image.data ) { 43195 43196 return { 43197 data: getTypedArray( image.type, image.data ), 43198 width: image.width, 43199 height: image.height 43200 }; 43201 43202 } else { 43203 43204 return null; 43205 43206 } 43207 43208 } 43209 43210 } 43211 43212 if ( json !== undefined && json.length > 0 ) { 43213 43214 loader = new ImageLoader( this.manager ); 43215 loader.setCrossOrigin( this.crossOrigin ); 43216 43217 for ( let i = 0, il = json.length; i < il; i ++ ) { 43218 43219 const image = json[ i ]; 43220 const url = image.url; 43221 43222 if ( Array.isArray( url ) ) { 43223 43224 // load array of images e.g CubeTexture 43225 43226 const imageArray = []; 43227 43228 for ( let j = 0, jl = url.length; j < jl; j ++ ) { 43229 43230 const currentUrl = url[ j ]; 43231 43232 const deserializedImage = await deserializeImage( currentUrl ); 43233 43234 if ( deserializedImage !== null ) { 43235 43236 if ( deserializedImage instanceof HTMLImageElement ) { 43237 43238 imageArray.push( deserializedImage ); 43239 43240 } else { 43241 43242 // special case: handle array of data textures for cube textures 43243 43244 imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); 43245 43246 } 43247 43248 } 43249 43250 } 43251 43252 images[ image.uuid ] = new Source( imageArray ); 43253 43254 } else { 43255 43256 // load single image 43257 43258 const deserializedImage = await deserializeImage( image.url ); 43259 images[ image.uuid ] = new Source( deserializedImage ); 43260 43261 } 43262 43263 } 43264 43265 } 43266 43267 return images; 43268 43269 } 43270 43271 parseTextures( json, images ) { 43272 43273 function parseConstant( value, type ) { 43274 43275 if ( typeof value === 'number' ) return value; 43276 43277 console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); 43278 43279 return type[ value ]; 43280 43281 } 43282 43283 const textures = {}; 43284 43285 if ( json !== undefined ) { 43286 43287 for ( let i = 0, l = json.length; i < l; i ++ ) { 43288 43289 const data = json[ i ]; 43290 43291 if ( data.image === undefined ) { 43292 43293 console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); 43294 43295 } 43296 43297 if ( images[ data.image ] === undefined ) { 43298 43299 console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); 43300 43301 } 43302 43303 const source = images[ data.image ]; 43304 const image = source.data; 43305 43306 let texture; 43307 43308 if ( Array.isArray( image ) ) { 43309 43310 texture = new CubeTexture(); 43311 43312 if ( image.length === 6 ) texture.needsUpdate = true; 43313 43314 } else { 43315 43316 if ( image && image.data ) { 43317 43318 texture = new DataTexture(); 43319 43320 } else { 43321 43322 texture = new Texture(); 43323 43324 } 43325 43326 if ( image ) texture.needsUpdate = true; // textures can have undefined image data 43327 43328 } 43329 43330 texture.source = source; 43331 43332 texture.uuid = data.uuid; 43333 43334 if ( data.name !== undefined ) texture.name = data.name; 43335 43336 if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); 43337 43338 if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); 43339 if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); 43340 if ( data.center !== undefined ) texture.center.fromArray( data.center ); 43341 if ( data.rotation !== undefined ) texture.rotation = data.rotation; 43342 43343 if ( data.wrap !== undefined ) { 43344 43345 texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); 43346 texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); 43347 43348 } 43349 43350 if ( data.format !== undefined ) texture.format = data.format; 43351 if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat; 43352 if ( data.type !== undefined ) texture.type = data.type; 43353 if ( data.encoding !== undefined ) texture.encoding = data.encoding; 43354 43355 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); 43356 if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); 43357 if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy; 43358 43359 if ( data.flipY !== undefined ) texture.flipY = data.flipY; 43360 43361 if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps; 43362 if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha; 43363 if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment; 43364 43365 if ( data.userData !== undefined ) texture.userData = data.userData; 43366 43367 textures[ data.uuid ] = texture; 43368 43369 } 43370 43371 } 43372 43373 return textures; 43374 43375 } 43376 43377 parseObject( data, geometries, materials, textures, animations ) { 43378 43379 let object; 43380 43381 function getGeometry( name ) { 43382 43383 if ( geometries[ name ] === undefined ) { 43384 43385 console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); 43386 43387 } 43388 43389 return geometries[ name ]; 43390 43391 } 43392 43393 function getMaterial( name ) { 43394 43395 if ( name === undefined ) return undefined; 43396 43397 if ( Array.isArray( name ) ) { 43398 43399 const array = []; 43400 43401 for ( let i = 0, l = name.length; i < l; i ++ ) { 43402 43403 const uuid = name[ i ]; 43404 43405 if ( materials[ uuid ] === undefined ) { 43406 43407 console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); 43408 43409 } 43410 43411 array.push( materials[ uuid ] ); 43412 43413 } 43414 43415 return array; 43416 43417 } 43418 43419 if ( materials[ name ] === undefined ) { 43420 43421 console.warn( 'THREE.ObjectLoader: Undefined material', name ); 43422 43423 } 43424 43425 return materials[ name ]; 43426 43427 } 43428 43429 function getTexture( uuid ) { 43430 43431 if ( textures[ uuid ] === undefined ) { 43432 43433 console.warn( 'THREE.ObjectLoader: Undefined texture', uuid ); 43434 43435 } 43436 43437 return textures[ uuid ]; 43438 43439 } 43440 43441 let geometry, material; 43442 43443 switch ( data.type ) { 43444 43445 case 'Scene': 43446 43447 object = new Scene(); 43448 43449 if ( data.background !== undefined ) { 43450 43451 if ( Number.isInteger( data.background ) ) { 43452 43453 object.background = new Color( data.background ); 43454 43455 } else { 43456 43457 object.background = getTexture( data.background ); 43458 43459 } 43460 43461 } 43462 43463 if ( data.environment !== undefined ) { 43464 43465 object.environment = getTexture( data.environment ); 43466 43467 } 43468 43469 if ( data.fog !== undefined ) { 43470 43471 if ( data.fog.type === 'Fog' ) { 43472 43473 object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); 43474 43475 } else if ( data.fog.type === 'FogExp2' ) { 43476 43477 object.fog = new FogExp2( data.fog.color, data.fog.density ); 43478 43479 } 43480 43481 } 43482 43483 if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness; 43484 if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity; 43485 43486 break; 43487 43488 case 'PerspectiveCamera': 43489 43490 object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); 43491 43492 if ( data.focus !== undefined ) object.focus = data.focus; 43493 if ( data.zoom !== undefined ) object.zoom = data.zoom; 43494 if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge; 43495 if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset; 43496 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); 43497 43498 break; 43499 43500 case 'OrthographicCamera': 43501 43502 object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); 43503 43504 if ( data.zoom !== undefined ) object.zoom = data.zoom; 43505 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); 43506 43507 break; 43508 43509 case 'AmbientLight': 43510 43511 object = new AmbientLight( data.color, data.intensity ); 43512 43513 break; 43514 43515 case 'DirectionalLight': 43516 43517 object = new DirectionalLight( data.color, data.intensity ); 43518 43519 break; 43520 43521 case 'PointLight': 43522 43523 object = new PointLight( data.color, data.intensity, data.distance, data.decay ); 43524 43525 break; 43526 43527 case 'RectAreaLight': 43528 43529 object = new RectAreaLight( data.color, data.intensity, data.width, data.height ); 43530 43531 break; 43532 43533 case 'SpotLight': 43534 43535 object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay ); 43536 43537 break; 43538 43539 case 'HemisphereLight': 43540 43541 object = new HemisphereLight( data.color, data.groundColor, data.intensity ); 43542 43543 break; 43544 43545 case 'LightProbe': 43546 43547 object = new LightProbe().fromJSON( data ); 43548 43549 break; 43550 43551 case 'SkinnedMesh': 43552 43553 geometry = getGeometry( data.geometry ); 43554 material = getMaterial( data.material ); 43555 43556 object = new SkinnedMesh( geometry, material ); 43557 43558 if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
vendor: 8,329 bytes, lines 43559-43930
43559 if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix ); 43560 if ( data.skeleton !== undefined ) object.skeleton = data.skeleton; 43561 43562 break; 43563 43564 case 'Mesh': 43565 43566 geometry = getGeometry( data.geometry ); 43567 material = getMaterial( data.material ); 43568 43569 object = new Mesh( geometry, material ); 43570 43571 break; 43572 43573 case 'InstancedMesh': 43574 43575 geometry = getGeometry( data.geometry ); 43576 material = getMaterial( data.material ); 43577 const count = data.count; 43578 const instanceMatrix = data.instanceMatrix; 43579 const instanceColor = data.instanceColor; 43580 43581 object = new InstancedMesh( geometry, material, count ); 43582 object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 ); 43583 if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize ); 43584 43585 break; 43586 43587 case 'LOD': 43588 43589 object = new LOD(); 43590 43591 break; 43592 43593 case 'Line': 43594 43595 object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) ); 43596 43597 break; 43598 43599 case 'LineLoop': 43600 43601 object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); 43602 43603 break; 43604 43605 case 'LineSegments': 43606 43607 object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); 43608 43609 break; 43610 43611 case 'PointCloud': 43612 case 'Points': 43613 43614 object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) ); 43615 43616 break; 43617 43618 case 'Sprite': 43619 43620 object = new Sprite( getMaterial( data.material ) ); 43621 43622 break; 43623 43624 case 'Group': 43625 43626 object = new Group(); 43627 43628 break; 43629 43630 case 'Bone': 43631 43632 object = new Bone(); 43633 43634 break; 43635 43636 default: 43637 43638 object = new Object3D(); 43639 43640 } 43641 43642 object.uuid = data.uuid; 43643 43644 if ( data.name !== undefined ) object.name = data.name; 43645 43646 if ( data.matrix !== undefined ) { 43647 43648 object.matrix.fromArray( data.matrix ); 43649 43650 if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate; 43651 if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale ); 43652 43653 } else { 43654 43655 if ( data.position !== undefined ) object.position.fromArray( data.position ); 43656 if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation ); 43657 if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion ); 43658 if ( data.scale !== undefined ) object.scale.fromArray( data.scale ); 43659 43660 } 43661 43662 if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; 43663 if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; 43664 43665 if ( data.shadow ) { 43666 43667 if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias; 43668 if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias; 43669 if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius; 43670 if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize ); 43671 if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera ); 43672 43673 } 43674 43675 if ( data.visible !== undefined ) object.visible = data.visible; 43676 if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled; 43677 if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder; 43678 if ( data.userData !== undefined ) object.userData = data.userData; 43679 if ( data.layers !== undefined ) object.layers.mask = data.layers; 43680 43681 if ( data.children !== undefined ) { 43682 43683 const children = data.children; 43684 43685 for ( let i = 0; i < children.length; i ++ ) { 43686 43687 object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) ); 43688 43689 } 43690 43691 } 43692 43693 if ( data.animations !== undefined ) { 43694 43695 const objectAnimations = data.animations; 43696 43697 for ( let i = 0; i < objectAnimations.length; i ++ ) { 43698 43699 const uuid = objectAnimations[ i ]; 43700 43701 object.animations.push( animations[ uuid ] ); 43702 43703 } 43704 43705 } 43706 43707 if ( data.type === 'LOD' ) { 43708 43709 if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate; 43710 43711 const levels = data.levels; 43712 43713 for ( let l = 0; l < levels.length; l ++ ) { 43714 43715 const level = levels[ l ]; 43716 const child = object.getObjectByProperty( 'uuid', level.object ); 43717 43718 if ( child !== undefined ) { 43719 43720 object.addLevel( child, level.distance, level.hysteresis ); 43721 43722 } 43723 43724 } 43725 43726 } 43727 43728 return object; 43729 43730 } 43731 43732 bindSkeletons( object, skeletons ) { 43733 43734 if ( Object.keys( skeletons ).length === 0 ) return; 43735 43736 object.traverse( function ( child ) { 43737 43738 if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) { 43739 43740 const skeleton = skeletons[ child.skeleton ]; 43741 43742 if ( skeleton === undefined ) { 43743 43744 console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton ); 43745 43746 } else { 43747 43748 child.bind( skeleton, child.bindMatrix ); 43749 43750 } 43751 43752 } 43753 43754 } ); 43755 43756 } 43757 43758} 43759 43760const TEXTURE_MAPPING = { 43761 UVMapping: UVMapping, 43762 CubeReflectionMapping: CubeReflectionMapping, 43763 CubeRefractionMapping: CubeRefractionMapping, 43764 EquirectangularReflectionMapping: EquirectangularReflectionMapping, 43765 EquirectangularRefractionMapping: EquirectangularRefractionMapping, 43766 CubeUVReflectionMapping: CubeUVReflectionMapping 43767}; 43768 43769const TEXTURE_WRAPPING = { 43770 RepeatWrapping: RepeatWrapping, 43771 ClampToEdgeWrapping: ClampToEdgeWrapping, 43772 MirroredRepeatWrapping: MirroredRepeatWrapping 43773}; 43774 43775const TEXTURE_FILTER = { 43776 NearestFilter: NearestFilter, 43777 NearestMipmapNearestFilter: NearestMipmapNearestFilter, 43778 NearestMipmapLinearFilter: NearestMipmapLinearFilter, 43779 LinearFilter: LinearFilter, 43780 LinearMipmapNearestFilter: LinearMipmapNearestFilter, 43781 LinearMipmapLinearFilter: LinearMipmapLinearFilter 43782}; 43783 43784class ImageBitmapLoader extends Loader { 43785 43786 constructor( manager ) { 43787 43788 super( manager ); 43789 43790 this.isImageBitmapLoader = true; 43791 43792 if ( typeof createImageBitmap === 'undefined' ) { 43793 43794 console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' ); 43795 43796 } 43797 43798 if ( typeof fetch === 'undefined' ) { 43799 43800 console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' ); 43801 43802 } 43803 43804 this.options = { premultiplyAlpha: 'none' }; 43805 43806 } 43807 43808 setOptions( options ) { 43809 43810 this.options = options; 43811 43812 return this; 43813 43814 } 43815 43816 load( url, onLoad, onProgress, onError ) { 43817 43818 if ( url === undefined ) url = ''; 43819 43820 if ( this.path !== undefined ) url = this.path + url; 43821 43822 url = this.manager.resolveURL( url ); 43823 43824 const scope = this; 43825 43826 const cached = Cache.get( url ); 43827 43828 if ( cached !== undefined ) { 43829 43830 scope.manager.itemStart( url ); 43831 43832 setTimeout( function () { 43833 43834 if ( onLoad ) onLoad( cached ); 43835 43836 scope.manager.itemEnd( url ); 43837 43838 }, 0 ); 43839 43840 return cached; 43841 43842 } 43843 43844 const fetchOptions = {}; 43845 fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include'; 43846 fetchOptions.headers = this.requestHeader; 43847 43848 fetch( url, fetchOptions ).then( function ( res ) { 43849 43850 return res.blob(); 43851 43852 } ).then( function ( blob ) { 43853 43854 return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) ); 43855 43856 } ).then( function ( imageBitmap ) { 43857 43858 Cache.add( url, imageBitmap ); 43859 43860 if ( onLoad ) onLoad( imageBitmap ); 43861 43862 scope.manager.itemEnd( url ); 43863 43864 } ).catch( function ( e ) { 43865 43866 if ( onError ) onError( e ); 43867 43868 scope.manager.itemError( url ); 43869 scope.manager.itemEnd( url ); 43870 43871 } ); 43872 43873 scope.manager.itemStart( url ); 43874 43875 } 43876 43877} 43878 43879let _context; 43880 43881class AudioContext { 43882 43883 static getContext() { 43884 43885 if ( _context === undefined ) { 43886 43887 _context = new ( window.AudioContext || window.webkitAudioContext )(); 43888 43889 } 43890 43891 return _context; 43892 43893 } 43894 43895 static setContext( value ) { 43896 43897 _context = value; 43898 43899 } 43900 43901} 43902 43903class AudioLoader extends Loader { 43904 43905 constructor( manager ) { 43906 43907 super( manager ); 43908 43909 } 43910 43911 load( url, onLoad, onProgress, onError ) { 43912 43913 const scope = this; 43914 43915 const loader = new FileLoader( this.manager ); 43916 loader.setResponseType( 'arraybuffer' ); 43917 loader.setPath( this.path ); 43918 loader.setRequestHeader( this.requestHeader ); 43919 loader.setWithCredentials( this.withCredentials ); 43920 loader.load( url, function ( buffer ) { 43921 43922 try { 43923 43924 // Create a copy of the buffer. The `decodeAudioData` method 43925 // detaches the buffer when complete, preventing reuse. 43926 const bufferCopy = buffer.slice( 0 ); 43927 43928 const context = AudioContext.getContext(); 43929 context.decodeAudioData( bufferCopy, function ( audioBuffer ) { 43930
43931 onLoad( audioBuffer ); 43932 43933 } ); 43934 43935 } catch ( e ) { 43936 43937 if ( onError ) { 43938 43939 onError( e ); 43940 43941 } else { 43942 43943 console.error( e ); 43944 43945 } 43946 43947 scope.manager.itemError( url ); 43948 43949 } 43950 43951 }, onProgress, onError ); 43952 43953 } 43954 43955} 43956 43957class HemisphereLightProbe extends LightProbe { 43958 43959 constructor( skyColor, groundColor, intensity = 1 ) { 43960 43961 super( undefined, intensity ); 43962 43963 this.isHemisphereLightProbe = true; 43964 43965 const color1 = new Color().set( skyColor ); 43966 const color2 = new Color().set( groundColor ); 43967 43968 const sky = new Vector3( color1.r, color1.g, color1.b ); 43969 const ground = new Vector3( color2.r, color2.g, color2.b ); 43970 43971 // without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI ); 43972 const c0 = Math.sqrt( Math.PI ); 43973 const c1 = c0 * Math.sqrt( 0.75 ); 43974 43975 this.sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 ); 43976 this.sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 ); 43977 43978 } 43979 43980} 43981 43982class AmbientLightProbe extends LightProbe { 43983 43984 constructor( color, intensity = 1 ) { 43985 43986 super( undefined, intensity ); 43987 43988 this.isAmbientLightProbe = true; 43989 43990 const color1 = new Color().set( color ); 43991 43992 // without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI ); 43993 this.sh.coefficients[ 0 ].set( color1.r, color1.g, color1.b ).multiplyScalar( 2 * Math.sqrt( Math.PI ) ); 43994 43995 } 43996 43997} 43998 43999const _eyeRight = /*@__PURE__*/ new Matrix4(); 44000const _eyeLeft = /*@__PURE__*/ new Matrix4(); 44001const _projectionMatrix = /*@__PURE__*/ new Matrix4(); 44002 44003class StereoCamera { 44004 44005 constructor() { 44006 44007 this.type = 'StereoCamera'; 44008 44009 this.aspect = 1; 44010 44011 this.eyeSep = 0.064; 44012 44013 this.cameraL = new PerspectiveCamera(); 44014 this.cameraL.layers.enable( 1 ); 44015 this.cameraL.matrixAutoUpdate = false; 44016 44017 this.cameraR = new PerspectiveCamera(); 44018 this.cameraR.layers.enable( 2 ); 44019 this.cameraR.matrixAutoUpdate = false; 44020 44021 this._cache = { 44022 focus: null, 44023 fov: null, 44024 aspect: null, 44025 near: null, 44026 far: null, 44027 zoom: null, 44028 eyeSep: null 44029 }; 44030 44031 } 44032 44033 update( camera ) { 44034 44035 const cache = this._cache; 44036 44037 const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov || 44038 cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near || 44039 cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep; 44040 44041 if ( needsUpdate ) { 44042 44043 cache.focus = camera.focus; 44044 cache.fov = camera.fov; 44045 cache.aspect = camera.aspect * this.aspect; 44046 cache.near = camera.near; 44047 cache.far = camera.far; 44048 cache.zoom = camera.zoom; 44049 cache.eyeSep = this.eyeSep; 44050 44051 // Off-axis stereoscopic effect based on 44052 // http://paulbourke.net/stereographics/stereorender/ 44053 44054 _projectionMatrix.copy( camera.projectionMatrix ); 44055 const eyeSepHalf = cache.eyeSep / 2; 44056 const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus; 44057 const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom; 44058 let xmin, xmax; 44059 44060 // translate xOffset 44061 44062 _eyeLeft.elements[ 12 ] = - eyeSepHalf; 44063 _eyeRight.elements[ 12 ] = eyeSepHalf; 44064 44065 // for left eye 44066 44067 xmin = - ymax * cache.aspect + eyeSepOnProjection; 44068 xmax = ymax * cache.aspect + eyeSepOnProjection; 44069 44070 _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); 44071 _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); 44072 44073 this.cameraL.projectionMatrix.copy( _projectionMatrix ); 44074 44075 // for right eye 44076 44077 xmin = - ymax * cache.aspect - eyeSepOnProjection; 44078 xmax = ymax * cache.aspect - eyeSepOnProjection; 44079 44080 _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); 44081 _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); 44082 44083 this.cameraR.projectionMatrix.copy( _projectionMatrix ); 44084 44085 } 44086 44087 this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft ); 44088 this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight ); 44089 44090 } 44091 44092} 44093 44094class Clock { 44095 44096 constructor( autoStart = true ) { 44097 44098 this.autoStart = autoStart; 44099 44100 this.startTime = 0; 44101 this.oldTime = 0; 44102 this.elapsedTime = 0; 44103 44104 this.running = false; 44105 44106 } 44107 44108 start() { 44109 44110 this.startTime = now(); 44111 44112 this.oldTime = this.startTime; 44113 this.elapsedTime = 0; 44114 this.running = true; 44115 44116 } 44117 44118 stop() { 44119 44120 this.getElapsedTime(); 44121 this.running = false;
vendor: 4,123 bytes, lines 44122-44353
44122 this.autoStart = false; 44123 44124 } 44125 44126 getElapsedTime() { 44127 44128 this.getDelta(); 44129 return this.elapsedTime; 44130 44131 } 44132 44133 getDelta() { 44134 44135 let diff = 0; 44136 44137 if ( this.autoStart && ! this.running ) { 44138 44139 this.start(); 44140 return 0; 44141 44142 } 44143 44144 if ( this.running ) { 44145 44146 const newTime = now(); 44147 44148 diff = ( newTime - this.oldTime ) / 1000; 44149 this.oldTime = newTime; 44150 44151 this.elapsedTime += diff; 44152 44153 } 44154 44155 return diff; 44156 44157 } 44158 44159} 44160 44161function now() { 44162 44163 return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732 44164 44165} 44166 44167const _position$1 = /*@__PURE__*/ new Vector3(); 44168const _quaternion$1 = /*@__PURE__*/ new Quaternion(); 44169const _scale$1 = /*@__PURE__*/ new Vector3(); 44170const _orientation$1 = /*@__PURE__*/ new Vector3(); 44171 44172class AudioListener extends Object3D { 44173 44174 constructor() { 44175 44176 super(); 44177 44178 this.type = 'AudioListener'; 44179 44180 this.context = AudioContext.getContext(); 44181 44182 this.gain = this.context.createGain(); 44183 this.gain.connect( this.context.destination ); 44184 44185 this.filter = null; 44186 44187 this.timeDelta = 0; 44188 44189 // private 44190 44191 this._clock = new Clock(); 44192 44193 } 44194 44195 getInput() { 44196 44197 return this.gain; 44198 44199 } 44200 44201 removeFilter() { 44202 44203 if ( this.filter !== null ) { 44204 44205 this.gain.disconnect( this.filter ); 44206 this.filter.disconnect( this.context.destination ); 44207 this.gain.connect( this.context.destination ); 44208 this.filter = null; 44209 44210 } 44211 44212 return this; 44213 44214 } 44215 44216 getFilter() { 44217 44218 return this.filter; 44219 44220 } 44221 44222 setFilter( value ) { 44223 44224 if ( this.filter !== null ) { 44225 44226 this.gain.disconnect( this.filter ); 44227 this.filter.disconnect( this.context.destination ); 44228 44229 } else { 44230 44231 this.gain.disconnect( this.context.destination ); 44232 44233 } 44234 44235 this.filter = value; 44236 this.gain.connect( this.filter ); 44237 this.filter.connect( this.context.destination ); 44238 44239 return this; 44240 44241 } 44242 44243 getMasterVolume() { 44244 44245 return this.gain.gain.value; 44246 44247 } 44248 44249 setMasterVolume( value ) { 44250 44251 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); 44252 44253 return this; 44254 44255 } 44256 44257 updateMatrixWorld( force ) { 44258 44259 super.updateMatrixWorld( force ); 44260 44261 const listener = this.context.listener; 44262 const up = this.up; 44263 44264 this.timeDelta = this._clock.getDelta(); 44265 44266 this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 ); 44267 44268 _orientation$1.set( 0, 0, - 1 ).applyQuaternion( _quaternion$1 ); 44269 44270 if ( listener.positionX ) { 44271 44272 // code path for Chrome (see #14393) 44273 44274 const endTime = this.context.currentTime + this.timeDelta; 44275 44276 listener.positionX.linearRampToValueAtTime( _position$1.x, endTime ); 44277 listener.positionY.linearRampToValueAtTime( _position$1.y, endTime ); 44278 listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime ); 44279 listener.forwardX.linearRampToValueAtTime( _orientation$1.x, endTime ); 44280 listener.forwardY.linearRampToValueAtTime( _orientation$1.y, endTime ); 44281 listener.forwardZ.linearRampToValueAtTime( _orientation$1.z, endTime ); 44282 listener.upX.linearRampToValueAtTime( up.x, endTime ); 44283 listener.upY.linearRampToValueAtTime( up.y, endTime ); 44284 listener.upZ.linearRampToValueAtTime( up.z, endTime ); 44285 44286 } else { 44287 44288 listener.setPosition( _position$1.x, _position$1.y, _position$1.z ); 44289 listener.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z ); 44290 44291 } 44292 44293 } 44294 44295} 44296 44297class Audio extends Object3D { 44298 44299 constructor( listener ) { 44300 44301 super(); 44302 44303 this.type = 'Audio'; 44304 44305 this.listener = listener; 44306 this.context = listener.context; 44307 44308 this.gain = this.context.createGain(); 44309 this.gain.connect( listener.getInput() ); 44310 44311 this.autoplay = false; 44312 44313 this.buffer = null; 44314 this.detune = 0; 44315 this.loop = false; 44316 this.loopStart = 0; 44317 this.loopEnd = 0; 44318 this.offset = 0; 44319 this.duration = undefined; 44320 this.playbackRate = 1; 44321 this.isPlaying = false; 44322 this.hasPlaybackControl = true; 44323 this.source = null; 44324 this.sourceType = 'empty'; 44325 44326 this._startedAt = 0; 44327 this._progress = 0; 44328 this._connected = false; 44329 44330 this.filters = []; 44331 44332 } 44333 44334 getOutput() { 44335 44336 return this.gain; 44337 44338 } 44339 44340 setNodeSource( audioNode ) { 44341 44342 this.hasPlaybackControl = false; 44343 this.sourceType = 'audioNode'; 44344 this.source = audioNode; 44345 this.connect(); 44346 44347 return this; 44348 44349 } 44350 44351 setMediaElementSource( mediaElement ) { 44352 44353 this.hasPlaybackControl = false;
vendor: 4,234 bytes, lines 44354-44620
44354 this.sourceType = 'mediaNode'; 44355 this.source = this.context.createMediaElementSource( mediaElement ); 44356 this.connect(); 44357 44358 return this; 44359 44360 } 44361 44362 setMediaStreamSource( mediaStream ) { 44363 44364 this.hasPlaybackControl = false; 44365 this.sourceType = 'mediaStreamNode'; 44366 this.source = this.context.createMediaStreamSource( mediaStream ); 44367 this.connect(); 44368 44369 return this; 44370 44371 } 44372 44373 setBuffer( audioBuffer ) { 44374 44375 this.buffer = audioBuffer; 44376 this.sourceType = 'buffer'; 44377 44378 if ( this.autoplay ) this.play(); 44379 44380 return this; 44381 44382 } 44383 44384 play( delay = 0 ) { 44385 44386 if ( this.isPlaying === true ) { 44387 44388 console.warn( 'THREE.Audio: Audio is already playing.' ); 44389 return; 44390 44391 } 44392 44393 if ( this.hasPlaybackControl === false ) { 44394 44395 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 44396 return; 44397 44398 } 44399 44400 this._startedAt = this.context.currentTime + delay; 44401 44402 const source = this.context.createBufferSource(); 44403 source.buffer = this.buffer; 44404 source.loop = this.loop; 44405 source.loopStart = this.loopStart; 44406 source.loopEnd = this.loopEnd; 44407 source.onended = this.onEnded.bind( this ); 44408 source.start( this._startedAt, this._progress + this.offset, this.duration ); 44409 44410 this.isPlaying = true; 44411 44412 this.source = source; 44413 44414 this.setDetune( this.detune ); 44415 this.setPlaybackRate( this.playbackRate ); 44416 44417 return this.connect(); 44418 44419 } 44420 44421 pause() { 44422 44423 if ( this.hasPlaybackControl === false ) { 44424 44425 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 44426 return; 44427 44428 } 44429 44430 if ( this.isPlaying === true ) { 44431 44432 // update current progress 44433 44434 this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate; 44435 44436 if ( this.loop === true ) { 44437 44438 // ensure _progress does not exceed duration with looped audios 44439 44440 this._progress = this._progress % ( this.duration || this.buffer.duration ); 44441 44442 } 44443 44444 this.source.stop(); 44445 this.source.onended = null; 44446 44447 this.isPlaying = false; 44448 44449 } 44450 44451 return this; 44452 44453 } 44454 44455 stop() { 44456 44457 if ( this.hasPlaybackControl === false ) { 44458 44459 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 44460 return; 44461 44462 } 44463 44464 this._progress = 0; 44465 44466 if ( this.source !== null ) { 44467 44468 this.source.stop(); 44469 this.source.onended = null; 44470 44471 } 44472 44473 this.isPlaying = false; 44474 44475 return this; 44476 44477 } 44478 44479 connect() { 44480 44481 if ( this.filters.length > 0 ) { 44482 44483 this.source.connect( this.filters[ 0 ] ); 44484 44485 for ( let i = 1, l = this.filters.length; i < l; i ++ ) { 44486 44487 this.filters[ i - 1 ].connect( this.filters[ i ] ); 44488 44489 } 44490 44491 this.filters[ this.filters.length - 1 ].connect( this.getOutput() ); 44492 44493 } else { 44494 44495 this.source.connect( this.getOutput() ); 44496 44497 } 44498 44499 this._connected = true; 44500 44501 return this; 44502 44503 } 44504 44505 disconnect() { 44506 44507 if ( this.filters.length > 0 ) { 44508 44509 this.source.disconnect( this.filters[ 0 ] ); 44510 44511 for ( let i = 1, l = this.filters.length; i < l; i ++ ) { 44512 44513 this.filters[ i - 1 ].disconnect( this.filters[ i ] ); 44514 44515 } 44516 44517 this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() ); 44518 44519 } else { 44520 44521 this.source.disconnect( this.getOutput() ); 44522 44523 } 44524 44525 this._connected = false; 44526 44527 return this; 44528 44529 } 44530 44531 getFilters() { 44532 44533 return this.filters; 44534 44535 } 44536 44537 setFilters( value ) { 44538 44539 if ( ! value ) value = []; 44540 44541 if ( this._connected === true ) { 44542 44543 this.disconnect(); 44544 this.filters = value.slice(); 44545 this.connect(); 44546 44547 } else { 44548 44549 this.filters = value.slice(); 44550 44551 } 44552 44553 return this; 44554 44555 } 44556 44557 setDetune( value ) { 44558 44559 this.detune = value; 44560 44561 if ( this.source.detune === undefined ) return; // only set detune when available 44562 44563 if ( this.isPlaying === true ) { 44564 44565 this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 ); 44566 44567 } 44568 44569 return this; 44570 44571 } 44572 44573 getDetune() { 44574 44575 return this.detune; 44576 44577 } 44578 44579 getFilter() { 44580 44581 return this.getFilters()[ 0 ]; 44582 44583 } 44584 44585 setFilter( filter ) { 44586 44587 return this.setFilters( filter ? [ filter ] : [] ); 44588 44589 } 44590 44591 setPlaybackRate( value ) { 44592 44593 if ( this.hasPlaybackControl === false ) { 44594 44595 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 44596 return; 44597 44598 } 44599 44600 this.playbackRate = value; 44601 44602 if ( this.isPlaying === true ) { 44603 44604 this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 ); 44605 44606 } 44607 44608 return this; 44609 44610 } 44611 44612 getPlaybackRate() { 44613 44614 return this.playbackRate; 44615 44616 } 44617 44618 onEnded() { 44619 44620 this.isPlaying = false;
vendor: 4,367 bytes, lines 44621-44885
44621 44622 } 44623 44624 getLoop() { 44625 44626 if ( this.hasPlaybackControl === false ) { 44627 44628 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 44629 return false; 44630 44631 } 44632 44633 return this.loop; 44634 44635 } 44636 44637 setLoop( value ) { 44638 44639 if ( this.hasPlaybackControl === false ) { 44640 44641 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 44642 return; 44643 44644 } 44645 44646 this.loop = value; 44647 44648 if ( this.isPlaying === true ) { 44649 44650 this.source.loop = this.loop; 44651 44652 } 44653 44654 return this; 44655 44656 } 44657 44658 setLoopStart( value ) { 44659 44660 this.loopStart = value; 44661 44662 return this; 44663 44664 } 44665 44666 setLoopEnd( value ) { 44667 44668 this.loopEnd = value; 44669 44670 return this; 44671 44672 } 44673 44674 getVolume() { 44675 44676 return this.gain.gain.value; 44677 44678 } 44679 44680 setVolume( value ) { 44681 44682 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); 44683 44684 return this; 44685 44686 } 44687 44688} 44689 44690const _position = /*@__PURE__*/ new Vector3(); 44691const _quaternion = /*@__PURE__*/ new Quaternion(); 44692const _scale = /*@__PURE__*/ new Vector3(); 44693const _orientation = /*@__PURE__*/ new Vector3(); 44694 44695class PositionalAudio extends Audio { 44696 44697 constructor( listener ) { 44698 44699 super( listener ); 44700 44701 this.panner = this.context.createPanner(); 44702 this.panner.panningModel = 'HRTF'; 44703 this.panner.connect( this.gain ); 44704 44705 } 44706 44707 disconnect() { 44708 44709 super.disconnect(); 44710 44711 this.panner.disconnect( this.gain ); 44712 44713 } 44714 44715 getOutput() { 44716 44717 return this.panner; 44718 44719 } 44720 44721 getRefDistance() { 44722 44723 return this.panner.refDistance; 44724 44725 } 44726 44727 setRefDistance( value ) { 44728 44729 this.panner.refDistance = value; 44730 44731 return this; 44732 44733 } 44734 44735 getRolloffFactor() { 44736 44737 return this.panner.rolloffFactor; 44738 44739 } 44740 44741 setRolloffFactor( value ) { 44742 44743 this.panner.rolloffFactor = value; 44744 44745 return this; 44746 44747 } 44748 44749 getDistanceModel() { 44750 44751 return this.panner.distanceModel; 44752 44753 } 44754 44755 setDistanceModel( value ) { 44756 44757 this.panner.distanceModel = value; 44758 44759 return this; 44760 44761 } 44762 44763 getMaxDistance() { 44764 44765 return this.panner.maxDistance; 44766 44767 } 44768 44769 setMaxDistance( value ) { 44770 44771 this.panner.maxDistance = value; 44772 44773 return this; 44774 44775 } 44776 44777 setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) { 44778 44779 this.panner.coneInnerAngle = coneInnerAngle; 44780 this.panner.coneOuterAngle = coneOuterAngle; 44781 this.panner.coneOuterGain = coneOuterGain; 44782 44783 return this; 44784 44785 } 44786 44787 updateMatrixWorld( force ) { 44788 44789 super.updateMatrixWorld( force ); 44790 44791 if ( this.hasPlaybackControl === true && this.isPlaying === false ) return; 44792 44793 this.matrixWorld.decompose( _position, _quaternion, _scale ); 44794 44795 _orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion ); 44796 44797 const panner = this.panner; 44798 44799 if ( panner.positionX ) { 44800 44801 // code path for Chrome and Firefox (see #14393) 44802 44803 const endTime = this.context.currentTime + this.listener.timeDelta; 44804 44805 panner.positionX.linearRampToValueAtTime( _position.x, endTime ); 44806 panner.positionY.linearRampToValueAtTime( _position.y, endTime ); 44807 panner.positionZ.linearRampToValueAtTime( _position.z, endTime ); 44808 panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime ); 44809 panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime ); 44810 panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime ); 44811 44812 } else { 44813 44814 panner.setPosition( _position.x, _position.y, _position.z ); 44815 panner.setOrientation( _orientation.x, _orientation.y, _orientation.z ); 44816 44817 } 44818 44819 } 44820 44821} 44822 44823class AudioAnalyser { 44824 44825 constructor( audio, fftSize = 2048 ) { 44826 44827 this.analyser = audio.context.createAnalyser(); 44828 this.analyser.fftSize = fftSize; 44829 44830 this.data = new Uint8Array( this.analyser.frequencyBinCount ); 44831 44832 audio.getOutput().connect( this.analyser ); 44833 44834 } 44835 44836 44837 getFrequencyData() { 44838 44839 this.analyser.getByteFrequencyData( this.data ); 44840 44841 return this.data; 44842 44843 } 44844 44845 getAverageFrequency() { 44846 44847 let value = 0; 44848 const data = this.getFrequencyData(); 44849 44850 for ( let i = 0; i < data.length; i ++ ) { 44851 44852 value += data[ i ]; 44853 44854 } 44855 44856 return value / data.length; 44857 44858 } 44859 44860} 44861 44862class PropertyMixer { 44863 44864 constructor( binding, typeName, valueSize ) { 44865 44866 this.binding = binding; 44867 this.valueSize = valueSize; 44868 44869 let mixFunction, 44870 mixFunctionAdditive, 44871 setIdentity; 44872 44873 // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ] 44874 // 44875 // interpolators can use .buffer as their .result 44876 // the data then goes to 'incoming' 44877 // 44878 // 'accu0' and 'accu1' are used frame-interleaved for 44879 // the cumulative result and are compared to detect 44880 // changes 44881 // 44882 // 'orig' stores the original state of the property 44883 // 44884 // 'add' is used for additive cumulative results 44885 //
vendor: 13,778 bytes, lines 44886-45516
44886 // 'work' is optional and is only present for quaternion types. It is used 44887 // to store intermediate quaternion multiplication results 44888 44889 switch ( typeName ) { 44890 44891 case 'quaternion': 44892 mixFunction = this._slerp; 44893 mixFunctionAdditive = this._slerpAdditive; 44894 setIdentity = this._setAdditiveIdentityQuaternion; 44895 44896 this.buffer = new Float64Array( valueSize * 6 ); 44897 this._workIndex = 5; 44898 break; 44899 44900 case 'string': 44901 case 'bool': 44902 mixFunction = this._select; 44903 44904 // Use the regular mix function and for additive on these types, 44905 // additive is not relevant for non-numeric types 44906 mixFunctionAdditive = this._select; 44907 44908 setIdentity = this._setAdditiveIdentityOther; 44909 44910 this.buffer = new Array( valueSize * 5 ); 44911 break; 44912 44913 default: 44914 mixFunction = this._lerp; 44915 mixFunctionAdditive = this._lerpAdditive; 44916 setIdentity = this._setAdditiveIdentityNumeric; 44917 44918 this.buffer = new Float64Array( valueSize * 5 ); 44919 44920 } 44921 44922 this._mixBufferRegion = mixFunction; 44923 this._mixBufferRegionAdditive = mixFunctionAdditive; 44924 this._setIdentity = setIdentity; 44925 this._origIndex = 3; 44926 this._addIndex = 4; 44927 44928 this.cumulativeWeight = 0; 44929 this.cumulativeWeightAdditive = 0; 44930 44931 this.useCount = 0; 44932 this.referenceCount = 0; 44933 44934 } 44935 44936 // accumulate data in the 'incoming' region into 'accu<i>' 44937 accumulate( accuIndex, weight ) { 44938 44939 // note: happily accumulating nothing when weight = 0, the caller knows 44940 // the weight and shouldn't have made the call in the first place 44941 44942 const buffer = this.buffer, 44943 stride = this.valueSize, 44944 offset = accuIndex * stride + stride; 44945 44946 let currentWeight = this.cumulativeWeight; 44947 44948 if ( currentWeight === 0 ) { 44949 44950 // accuN := incoming * weight 44951 44952 for ( let i = 0; i !== stride; ++ i ) { 44953 44954 buffer[ offset + i ] = buffer[ i ]; 44955 44956 } 44957 44958 currentWeight = weight; 44959 44960 } else { 44961 44962 // accuN := accuN + incoming * weight 44963 44964 currentWeight += weight; 44965 const mix = weight / currentWeight; 44966 this._mixBufferRegion( buffer, offset, 0, mix, stride ); 44967 44968 } 44969 44970 this.cumulativeWeight = currentWeight; 44971 44972 } 44973 44974 // accumulate data in the 'incoming' region into 'add' 44975 accumulateAdditive( weight ) { 44976 44977 const buffer = this.buffer, 44978 stride = this.valueSize, 44979 offset = stride * this._addIndex; 44980 44981 if ( this.cumulativeWeightAdditive === 0 ) { 44982 44983 // add = identity 44984 44985 this._setIdentity(); 44986 44987 } 44988 44989 // add := add + incoming * weight 44990 44991 this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride ); 44992 this.cumulativeWeightAdditive += weight; 44993 44994 } 44995 44996 // apply the state of 'accu<i>' to the binding when accus differ 44997 apply( accuIndex ) { 44998 44999 const stride = this.valueSize, 45000 buffer = this.buffer, 45001 offset = accuIndex * stride + stride, 45002 45003 weight = this.cumulativeWeight, 45004 weightAdditive = this.cumulativeWeightAdditive, 45005 45006 binding = this.binding; 45007 45008 this.cumulativeWeight = 0; 45009 this.cumulativeWeightAdditive = 0; 45010 45011 if ( weight < 1 ) { 45012 45013 // accuN := accuN + original * ( 1 - cumulativeWeight ) 45014 45015 const originalValueOffset = stride * this._origIndex; 45016 45017 this._mixBufferRegion( 45018 buffer, offset, originalValueOffset, 1 - weight, stride ); 45019 45020 } 45021 45022 if ( weightAdditive > 0 ) { 45023 45024 // accuN := accuN + additive accuN 45025 45026 this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride ); 45027 45028 } 45029 45030 for ( let i = stride, e = stride + stride; i !== e; ++ i ) { 45031 45032 if ( buffer[ i ] !== buffer[ i + stride ] ) { 45033 45034 // value has changed -> update scene graph 45035 45036 binding.setValue( buffer, offset ); 45037 break; 45038 45039 } 45040 45041 } 45042 45043 } 45044 45045 // remember the state of the bound property and copy it to both accus 45046 saveOriginalState() { 45047 45048 const binding = this.binding; 45049 45050 const buffer = this.buffer, 45051 stride = this.valueSize, 45052 45053 originalValueOffset = stride * this._origIndex; 45054 45055 binding.getValue( buffer, originalValueOffset ); 45056 45057 // accu[0..1] := orig -- initially detect changes against the original 45058 for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) { 45059 45060 buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ]; 45061 45062 } 45063 45064 // Add to identity for additive 45065 this._setIdentity(); 45066 45067 this.cumulativeWeight = 0; 45068 this.cumulativeWeightAdditive = 0; 45069 45070 } 45071 45072 // apply the state previously taken via 'saveOriginalState' to the binding 45073 restoreOriginalState() { 45074 45075 const originalValueOffset = this.valueSize * 3; 45076 this.binding.setValue( this.buffer, originalValueOffset ); 45077 45078 } 45079 45080 _setAdditiveIdentityNumeric() { 45081 45082 const startIndex = this._addIndex * this.valueSize; 45083 const endIndex = startIndex + this.valueSize; 45084 45085 for ( let i = startIndex; i < endIndex; i ++ ) { 45086 45087 this.buffer[ i ] = 0; 45088 45089 } 45090 45091 } 45092 45093 _setAdditiveIdentityQuaternion() { 45094 45095 this._setAdditiveIdentityNumeric(); 45096 this.buffer[ this._addIndex * this.valueSize + 3 ] = 1; 45097 45098 } 45099 45100 _setAdditiveIdentityOther() { 45101 45102 const startIndex = this._origIndex * this.valueSize; 45103 const targetIndex = this._addIndex * this.valueSize; 45104 45105 for ( let i = 0; i < this.valueSize; i ++ ) { 45106 45107 this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ]; 45108 45109 } 45110 45111 } 45112 45113 45114 // mix functions 45115 45116 _select( buffer, dstOffset, srcOffset, t, stride ) { 45117 45118 if ( t >= 0.5 ) { 45119 45120 for ( let i = 0; i !== stride; ++ i ) { 45121 45122 buffer[ dstOffset + i ] = buffer[ srcOffset + i ]; 45123 45124 } 45125 45126 } 45127 45128 } 45129 45130 _slerp( buffer, dstOffset, srcOffset, t ) { 45131 45132 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t ); 45133 45134 } 45135 45136 _slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { 45137 45138 const workOffset = this._workIndex * stride; 45139 45140 // Store result in intermediate buffer offset 45141 Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset ); 45142 45143 // Slerp to the intermediate result 45144 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t ); 45145 45146 } 45147 45148 _lerp( buffer, dstOffset, srcOffset, t, stride ) { 45149 45150 const s = 1 - t; 45151 45152 for ( let i = 0; i !== stride; ++ i ) { 45153 45154 const j = dstOffset + i; 45155 45156 buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t; 45157 45158 } 45159 45160 } 45161 45162 _lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { 45163 45164 for ( let i = 0; i !== stride; ++ i ) { 45165 45166 const j = dstOffset + i; 45167 45168 buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t; 45169 45170 } 45171 45172 } 45173 45174} 45175 45176// Characters [].:/ are reserved for track binding syntax. 45177const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/'; 45178const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' ); 45179 45180// Attempts to allow node names from any language. ES5's `\w` regexp matches 45181// only latin characters, and the unicode \p{L} is not yet supported. So 45182// instead, we exclude reserved characters and match everything else. 45183const _wordChar = '[^' + _RESERVED_CHARS_RE + ']'; 45184const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']'; 45185 45186// Parent directories, delimited by '/' or ':'. Currently unused, but must 45187// be matched to parse the rest of the track name. 45188const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar ); 45189 45190// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'. 45191const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot ); 45192 45193// Object on target node, and accessor. May not contain reserved 45194// characters. Accessor may contain any character except closing bracket. 45195const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar ); 45196 45197// Property and accessor. May not contain reserved characters. Accessor may 45198// contain any non-bracket characters. 45199const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar ); 45200 45201const _trackRe = new RegExp( '' 45202 + '^' 45203 + _directoryRe 45204 + _nodeRe 45205 + _objectRe 45206 + _propertyRe 45207 + '$' 45208); 45209 45210const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ]; 45211 45212class Composite { 45213 45214 constructor( targetGroup, path, optionalParsedPath ) { 45215 45216 const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); 45217 45218 this._targetGroup = targetGroup; 45219 this._bindings = targetGroup.subscribe_( path, parsedPath ); 45220 45221 } 45222 45223 getValue( array, offset ) { 45224 45225 this.bind(); // bind all binding 45226 45227 const firstValidIndex = this._targetGroup.nCachedObjects_, 45228 binding = this._bindings[ firstValidIndex ]; 45229 45230 // and only call .getValue on the first 45231 if ( binding !== undefined ) binding.getValue( array, offset ); 45232 45233 } 45234 45235 setValue( array, offset ) { 45236 45237 const bindings = this._bindings; 45238 45239 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { 45240 45241 bindings[ i ].setValue( array, offset ); 45242 45243 } 45244 45245 } 45246 45247 bind() { 45248 45249 const bindings = this._bindings; 45250 45251 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { 45252 45253 bindings[ i ].bind(); 45254 45255 } 45256 45257 } 45258 45259 unbind() { 45260 45261 const bindings = this._bindings; 45262 45263 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { 45264 45265 bindings[ i ].unbind(); 45266 45267 } 45268 45269 } 45270 45271} 45272 45273// Note: This class uses a State pattern on a per-method basis: 45274// 'bind' sets 'this.getValue' / 'setValue' and shadows the 45275// prototype version of these methods with one that represents 45276// the bound state. When the property is not found, the methods 45277// become no-ops. 45278class PropertyBinding { 45279 45280 constructor( rootNode, path, parsedPath ) { 45281 45282 this.path = path; 45283 this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); 45284 45285 this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ); 45286 45287 this.rootNode = rootNode; 45288 45289 // initial state of these methods that calls 'bind' 45290 this.getValue = this._getValue_unbound; 45291 this.setValue = this._setValue_unbound; 45292 45293 } 45294 45295 45296 static create( root, path, parsedPath ) { 45297 45298 if ( ! ( root && root.isAnimationObjectGroup ) ) { 45299 45300 return new PropertyBinding( root, path, parsedPath ); 45301 45302 } else { 45303 45304 return new PropertyBinding.Composite( root, path, parsedPath ); 45305 45306 } 45307 45308 } 45309 45310 /** 45311 * Replaces spaces with underscores and removes unsupported characters from 45312 * node names, to ensure compatibility with parseTrackName(). 45313 * 45314 * @param {string} name Node name to be sanitized. 45315 * @return {string} 45316 */ 45317 static sanitizeNodeName( name ) { 45318 45319 return name.replace( /\s/g, '_' ).replace( _reservedRe, '' ); 45320 45321 } 45322 45323 static parseTrackName( trackName ) { 45324 45325 const matches = _trackRe.exec( trackName ); 45326 45327 if ( matches === null ) { 45328 45329 throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName ); 45330 45331 } 45332 45333 const results = { 45334 // directoryName: matches[ 1 ], // (tschw) currently unused 45335 nodeName: matches[ 2 ], 45336 objectName: matches[ 3 ], 45337 objectIndex: matches[ 4 ], 45338 propertyName: matches[ 5 ], // required 45339 propertyIndex: matches[ 6 ] 45340 }; 45341 45342 const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' ); 45343 45344 if ( lastDot !== undefined && lastDot !== - 1 ) { 45345 45346 const objectName = results.nodeName.substring( lastDot + 1 ); 45347 45348 // Object names must be checked against an allowlist. Otherwise, there 45349 // is no way to parse 'foo.bar.baz': 'baz' must be a property, but 45350 // 'bar' could be the objectName, or part of a nodeName (which can 45351 // include '.' characters). 45352 if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) { 45353 45354 results.nodeName = results.nodeName.substring( 0, lastDot ); 45355 results.objectName = objectName; 45356 45357 } 45358 45359 } 45360 45361 if ( results.propertyName === null || results.propertyName.length === 0 ) { 45362 45363 throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName ); 45364 45365 } 45366 45367 return results; 45368 45369 } 45370 45371 static findNode( root, nodeName ) { 45372 45373 if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { 45374 45375 return root; 45376 45377 } 45378 45379 // search into skeleton bones. 45380 if ( root.skeleton ) { 45381 45382 const bone = root.skeleton.getBoneByName( nodeName ); 45383 45384 if ( bone !== undefined ) { 45385 45386 return bone; 45387 45388 } 45389 45390 } 45391 45392 // search into node subtree. 45393 if ( root.children ) { 45394 45395 const searchNodeSubtree = function ( children ) { 45396 45397 for ( let i = 0; i < children.length; i ++ ) { 45398 45399 const childNode = children[ i ]; 45400 45401 if ( childNode.name === nodeName || childNode.uuid === nodeName ) { 45402 45403 return childNode; 45404 45405 } 45406 45407 const result = searchNodeSubtree( childNode.children ); 45408 45409 if ( result ) return result; 45410 45411 } 45412 45413 return null; 45414 45415 }; 45416 45417 const subTreeNode = searchNodeSubtree( root.children ); 45418 45419 if ( subTreeNode ) { 45420 45421 return subTreeNode; 45422 45423 } 45424 45425 } 45426 45427 return null; 45428 45429 } 45430 45431 // these are used to "bind" a nonexistent property 45432 _getValue_unavailable() {} 45433 _setValue_unavailable() {} 45434 45435 // Getters 45436 45437 _getValue_direct( buffer, offset ) { 45438 45439 buffer[ offset ] = this.targetObject[ this.propertyName ]; 45440 45441 } 45442 45443 _getValue_array( buffer, offset ) { 45444 45445 const source = this.resolvedProperty; 45446 45447 for ( let i = 0, n = source.length; i !== n; ++ i ) { 45448 45449 buffer[ offset ++ ] = source[ i ]; 45450 45451 } 45452 45453 } 45454 45455 _getValue_arrayElement( buffer, offset ) { 45456 45457 buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; 45458 45459 } 45460 45461 _getValue_toArray( buffer, offset ) { 45462 45463 this.resolvedProperty.toArray( buffer, offset ); 45464 45465 } 45466 45467 // Direct 45468 45469 _setValue_direct( buffer, offset ) { 45470 45471 this.targetObject[ this.propertyName ] = buffer[ offset ]; 45472 45473 } 45474 45475 _setValue_direct_setNeedsUpdate( buffer, offset ) { 45476 45477 this.targetObject[ this.propertyName ] = buffer[ offset ]; 45478 this.targetObject.needsUpdate = true; 45479 45480 } 45481 45482 _setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { 45483 45484 this.targetObject[ this.propertyName ] = buffer[ offset ]; 45485 this.targetObject.matrixWorldNeedsUpdate = true; 45486 45487 } 45488 45489 // EntireArray 45490 45491 _setValue_array( buffer, offset ) { 45492 45493 const dest = this.resolvedProperty; 45494 45495 for ( let i = 0, n = dest.length; i !== n; ++ i ) { 45496 45497 dest[ i ] = buffer[ offset ++ ]; 45498 45499 } 45500 45501 } 45502 45503 _setValue_array_setNeedsUpdate( buffer, offset ) { 45504 45505 const dest = this.resolvedProperty; 45506 45507 for ( let i = 0, n = dest.length; i !== n; ++ i ) { 45508 45509 dest[ i ] = buffer[ offset ++ ]; 45510 45511 } 45512 45513 this.targetObject.needsUpdate = true; 45514 45515 } 45516
vendor: 8,208 bytes, lines 45517-45872
45517 _setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { 45518 45519 const dest = this.resolvedProperty; 45520 45521 for ( let i = 0, n = dest.length; i !== n; ++ i ) { 45522 45523 dest[ i ] = buffer[ offset ++ ]; 45524 45525 } 45526 45527 this.targetObject.matrixWorldNeedsUpdate = true; 45528 45529 } 45530 45531 // ArrayElement 45532 45533 _setValue_arrayElement( buffer, offset ) { 45534 45535 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 45536 45537 } 45538 45539 _setValue_arrayElement_setNeedsUpdate( buffer, offset ) { 45540 45541 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 45542 this.targetObject.needsUpdate = true; 45543 45544 } 45545 45546 _setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { 45547 45548 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 45549 this.targetObject.matrixWorldNeedsUpdate = true; 45550 45551 } 45552 45553 // HasToFromArray 45554 45555 _setValue_fromArray( buffer, offset ) { 45556 45557 this.resolvedProperty.fromArray( buffer, offset ); 45558 45559 } 45560 45561 _setValue_fromArray_setNeedsUpdate( buffer, offset ) { 45562 45563 this.resolvedProperty.fromArray( buffer, offset ); 45564 this.targetObject.needsUpdate = true; 45565 45566 } 45567 45568 _setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { 45569 45570 this.resolvedProperty.fromArray( buffer, offset ); 45571 this.targetObject.matrixWorldNeedsUpdate = true; 45572 45573 } 45574 45575 _getValue_unbound( targetArray, offset ) { 45576 45577 this.bind(); 45578 this.getValue( targetArray, offset ); 45579 45580 } 45581 45582 _setValue_unbound( sourceArray, offset ) { 45583 45584 this.bind(); 45585 this.setValue( sourceArray, offset ); 45586 45587 } 45588 45589 // create getter / setter pair for a property in the scene graph 45590 bind() { 45591 45592 let targetObject = this.node; 45593 const parsedPath = this.parsedPath; 45594 45595 const objectName = parsedPath.objectName; 45596 const propertyName = parsedPath.propertyName; 45597 let propertyIndex = parsedPath.propertyIndex; 45598 45599 if ( ! targetObject ) { 45600 45601 targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ); 45602 45603 this.node = targetObject; 45604 45605 } 45606 45607 // set fail state so we can just 'return' on error 45608 this.getValue = this._getValue_unavailable; 45609 this.setValue = this._setValue_unavailable; 45610 45611 // ensure there is a value node 45612 if ( ! targetObject ) { 45613 45614 console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' ); 45615 return; 45616 45617 } 45618 45619 if ( objectName ) { 45620 45621 let objectIndex = parsedPath.objectIndex; 45622 45623 // special cases were we need to reach deeper into the hierarchy to get the face materials.... 45624 switch ( objectName ) { 45625 45626 case 'materials': 45627 45628 if ( ! targetObject.material ) { 45629 45630 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); 45631 return; 45632 45633 } 45634 45635 if ( ! targetObject.material.materials ) { 45636 45637 console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this ); 45638 return; 45639 45640 } 45641 45642 targetObject = targetObject.material.materials; 45643 45644 break; 45645 45646 case 'bones': 45647 45648 if ( ! targetObject.skeleton ) { 45649 45650 console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this ); 45651 return; 45652 45653 } 45654 45655 // potential future optimization: skip this if propertyIndex is already an integer 45656 // and convert the integer string to a true integer. 45657 45658 targetObject = targetObject.skeleton.bones; 45659 45660 // support resolving morphTarget names into indices. 45661 for ( let i = 0; i < targetObject.length; i ++ ) { 45662 45663 if ( targetObject[ i ].name === objectIndex ) { 45664 45665 objectIndex = i; 45666 break; 45667 45668 } 45669 45670 } 45671 45672 break; 45673 45674 case 'map': 45675 45676 if ( 'map' in targetObject ) { 45677 45678 targetObject = targetObject.map; 45679 break; 45680 45681 } 45682 45683 if ( ! targetObject.material ) { 45684 45685 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); 45686 return; 45687 45688 } 45689 45690 if ( ! targetObject.material.map ) { 45691 45692 console.error( 'THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.', this ); 45693 return; 45694 45695 } 45696 45697 targetObject = targetObject.material.map; 45698 break; 45699 45700 default: 45701 45702 if ( targetObject[ objectName ] === undefined ) { 45703 45704 console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this ); 45705 return; 45706 45707 } 45708 45709 targetObject = targetObject[ objectName ]; 45710 45711 } 45712 45713 45714 if ( objectIndex !== undefined ) { 45715 45716 if ( targetObject[ objectIndex ] === undefined ) { 45717 45718 console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject ); 45719 return; 45720 45721 } 45722 45723 targetObject = targetObject[ objectIndex ]; 45724 45725 } 45726 45727 } 45728 45729 // resolve property 45730 const nodeProperty = targetObject[ propertyName ]; 45731 45732 if ( nodeProperty === undefined ) { 45733 45734 const nodeName = parsedPath.nodeName; 45735 45736 console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName + 45737 '.' + propertyName + ' but it wasn\'t found.', targetObject ); 45738 return; 45739 45740 } 45741 45742 // determine versioning scheme 45743 let versioning = this.Versioning.None; 45744 45745 this.targetObject = targetObject; 45746 45747 if ( targetObject.needsUpdate !== undefined ) { // material 45748 45749 versioning = this.Versioning.NeedsUpdate; 45750 45751 } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform 45752 45753 versioning = this.Versioning.MatrixWorldNeedsUpdate; 45754 45755 } 45756 45757 // determine how the property gets bound 45758 let bindingType = this.BindingType.Direct; 45759 45760 if ( propertyIndex !== undefined ) { 45761 45762 // access a sub element of the property array (only primitives are supported right now) 45763 45764 if ( propertyName === 'morphTargetInfluences' ) { 45765 45766 // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer. 45767 45768 // support resolving morphTarget names into indices. 45769 if ( ! targetObject.geometry ) { 45770 45771 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this ); 45772 return; 45773 45774 } 45775 45776 if ( ! targetObject.geometry.morphAttributes ) { 45777 45778 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this ); 45779 return; 45780 45781 } 45782 45783 if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) { 45784 45785 propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ]; 45786 45787 } 45788 45789 } 45790 45791 bindingType = this.BindingType.ArrayElement; 45792 45793 this.resolvedProperty = nodeProperty; 45794 this.propertyIndex = propertyIndex; 45795 45796 } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) { 45797 45798 // must use copy for Object3D.Euler/Quaternion 45799 45800 bindingType = this.BindingType.HasFromToArray; 45801 45802 this.resolvedProperty = nodeProperty; 45803 45804 } else if ( Array.isArray( nodeProperty ) ) { 45805 45806 bindingType = this.BindingType.EntireArray; 45807 45808 this.resolvedProperty = nodeProperty; 45809 45810 } else { 45811 45812 this.propertyName = propertyName; 45813 45814 } 45815 45816 // select getter / setter 45817 this.getValue = this.GetterByBindingType[ bindingType ]; 45818 this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; 45819 45820 } 45821 45822 unbind() { 45823 45824 this.node = null; 45825 45826 // back to the prototype version of getValue / setValue 45827 // note: avoiding to mutate the shape of 'this' via 'delete' 45828 this.getValue = this._getValue_unbound; 45829 this.setValue = this._setValue_unbound; 45830 45831 } 45832 45833} 45834 45835PropertyBinding.Composite = Composite; 45836 45837PropertyBinding.prototype.BindingType = { 45838 Direct: 0, 45839 EntireArray: 1, 45840 ArrayElement: 2, 45841 HasFromToArray: 3 45842}; 45843 45844PropertyBinding.prototype.Versioning = { 45845 None: 0, 45846 NeedsUpdate: 1, 45847 MatrixWorldNeedsUpdate: 2 45848}; 45849 45850PropertyBinding.prototype.GetterByBindingType = [ 45851 45852 PropertyBinding.prototype._getValue_direct, 45853 PropertyBinding.prototype._getValue_array, 45854 PropertyBinding.prototype._getValue_arrayElement, 45855 PropertyBinding.prototype._getValue_toArray, 45856 45857]; 45858 45859PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [ 45860 45861 [ 45862 // Direct 45863 PropertyBinding.prototype._setValue_direct, 45864 PropertyBinding.prototype._setValue_direct_setNeedsUpdate, 45865 PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate, 45866 45867 ], [ 45868 45869 // EntireArray 45870 45871 PropertyBinding.prototype._setValue_array, 45872 PropertyBinding.prototype._setValue_array_setNeedsUpdate,
vendor: 4,282 bytes, lines 45873-46053
45873 PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate, 45874 45875 ], [ 45876 45877 // ArrayElement 45878 PropertyBinding.prototype._setValue_arrayElement, 45879 PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate, 45880 PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate, 45881 45882 ], [ 45883 45884 // HasToFromArray 45885 PropertyBinding.prototype._setValue_fromArray, 45886 PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate, 45887 PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate, 45888 45889 ] 45890 45891]; 45892 45893/** 45894 * 45895 * A group of objects that receives a shared animation state. 45896 * 45897 * Usage: 45898 * 45899 * - Add objects you would otherwise pass as 'root' to the 45900 * constructor or the .clipAction method of AnimationMixer. 45901 * 45902 * - Instead pass this object as 'root'. 45903 * 45904 * - You can also add and remove objects later when the mixer 45905 * is running. 45906 * 45907 * Note: 45908 * 45909 * Objects of this class appear as one object to the mixer, 45910 * so cache control of the individual objects must be done 45911 * on the group. 45912 * 45913 * Limitation: 45914 * 45915 * - The animated properties must be compatible among the 45916 * all objects in the group. 45917 * 45918 * - A single property can either be controlled through a 45919 * target group or directly, but not both. 45920 */ 45921 45922class AnimationObjectGroup { 45923 45924 constructor() { 45925 45926 this.isAnimationObjectGroup = true; 45927 45928 this.uuid = generateUUID(); 45929 45930 // cached objects followed by the active ones 45931 this._objects = Array.prototype.slice.call( arguments ); 45932 45933 this.nCachedObjects_ = 0; // threshold 45934 // note: read by PropertyBinding.Composite 45935 45936 const indices = {}; 45937 this._indicesByUUID = indices; // for bookkeeping 45938 45939 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 45940 45941 indices[ arguments[ i ].uuid ] = i; 45942 45943 } 45944 45945 this._paths = []; // inside: string 45946 this._parsedPaths = []; // inside: { we don't care, here } 45947 this._bindings = []; // inside: Array< PropertyBinding > 45948 this._bindingsIndicesByPath = {}; // inside: indices in these arrays 45949 45950 const scope = this; 45951 45952 this.stats = { 45953 45954 objects: { 45955 get total() { 45956 45957 return scope._objects.length; 45958 45959 }, 45960 get inUse() { 45961 45962 return this.total - scope.nCachedObjects_; 45963 45964 } 45965 }, 45966 get bindingsPerObject() { 45967 45968 return scope._bindings.length; 45969 45970 } 45971 45972 }; 45973 45974 } 45975 45976 add() { 45977 45978 const objects = this._objects, 45979 indicesByUUID = this._indicesByUUID, 45980 paths = this._paths, 45981 parsedPaths = this._parsedPaths, 45982 bindings = this._bindings, 45983 nBindings = bindings.length; 45984 45985 let knownObject = undefined, 45986 nObjects = objects.length, 45987 nCachedObjects = this.nCachedObjects_; 45988 45989 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 45990 45991 const object = arguments[ i ], 45992 uuid = object.uuid; 45993 let index = indicesByUUID[ uuid ]; 45994 45995 if ( index === undefined ) { 45996 45997 // unknown object -> add it to the ACTIVE region 45998 45999 index = nObjects ++; 46000 indicesByUUID[ uuid ] = index; 46001 objects.push( object ); 46002 46003 // accounting is done, now do the same for all bindings 46004 46005 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 46006 46007 bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); 46008 46009 } 46010 46011 } else if ( index < nCachedObjects ) { 46012 46013 knownObject = objects[ index ]; 46014 46015 // move existing object to the ACTIVE region 46016 46017 const firstActiveIndex = -- nCachedObjects, 46018 lastCachedObject = objects[ firstActiveIndex ]; 46019 46020 indicesByUUID[ lastCachedObject.uuid ] = index; 46021 objects[ index ] = lastCachedObject; 46022 46023 indicesByUUID[ uuid ] = firstActiveIndex; 46024 objects[ firstActiveIndex ] = object; 46025 46026 // accounting is done, now do the same for all bindings 46027 46028 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 46029 46030 const bindingsForPath = bindings[ j ], 46031 lastCached = bindingsForPath[ firstActiveIndex ]; 46032 46033 let binding = bindingsForPath[ index ]; 46034 46035 bindingsForPath[ index ] = lastCached; 46036 46037 if ( binding === undefined ) { 46038 46039 // since we do not bother to create new bindings 46040 // for objects that are cached, the binding may 46041 // or may not exist 46042 46043 binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); 46044 46045 } 46046 46047 bindingsForPath[ firstActiveIndex ] = binding; 46048 46049 } 46050 46051 } else if ( objects[ index ] !== knownObject ) { 46052 46053 console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
vendor: 4,120 bytes, lines 46054-46220
46054 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); 46055 46056 } // else the object is already where we want it to be 46057 46058 } // for arguments 46059 46060 this.nCachedObjects_ = nCachedObjects; 46061 46062 } 46063 46064 remove() { 46065 46066 const objects = this._objects, 46067 indicesByUUID = this._indicesByUUID, 46068 bindings = this._bindings, 46069 nBindings = bindings.length; 46070 46071 let nCachedObjects = this.nCachedObjects_; 46072 46073 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 46074 46075 const object = arguments[ i ], 46076 uuid = object.uuid, 46077 index = indicesByUUID[ uuid ]; 46078 46079 if ( index !== undefined && index >= nCachedObjects ) { 46080 46081 // move existing object into the CACHED region 46082 46083 const lastCachedIndex = nCachedObjects ++, 46084 firstActiveObject = objects[ lastCachedIndex ]; 46085 46086 indicesByUUID[ firstActiveObject.uuid ] = index; 46087 objects[ index ] = firstActiveObject; 46088 46089 indicesByUUID[ uuid ] = lastCachedIndex; 46090 objects[ lastCachedIndex ] = object; 46091 46092 // accounting is done, now do the same for all bindings 46093 46094 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 46095 46096 const bindingsForPath = bindings[ j ], 46097 firstActive = bindingsForPath[ lastCachedIndex ], 46098 binding = bindingsForPath[ index ]; 46099 46100 bindingsForPath[ index ] = firstActive; 46101 bindingsForPath[ lastCachedIndex ] = binding; 46102 46103 } 46104 46105 } 46106 46107 } // for arguments 46108 46109 this.nCachedObjects_ = nCachedObjects; 46110 46111 } 46112 46113 // remove & forget 46114 uncache() { 46115 46116 const objects = this._objects, 46117 indicesByUUID = this._indicesByUUID, 46118 bindings = this._bindings, 46119 nBindings = bindings.length; 46120 46121 let nCachedObjects = this.nCachedObjects_, 46122 nObjects = objects.length; 46123 46124 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 46125 46126 const object = arguments[ i ], 46127 uuid = object.uuid, 46128 index = indicesByUUID[ uuid ]; 46129 46130 if ( index !== undefined ) { 46131 46132 delete indicesByUUID[ uuid ]; 46133 46134 if ( index < nCachedObjects ) { 46135 46136 // object is cached, shrink the CACHED region 46137 46138 const firstActiveIndex = -- nCachedObjects, 46139 lastCachedObject = objects[ firstActiveIndex ], 46140 lastIndex = -- nObjects, 46141 lastObject = objects[ lastIndex ]; 46142 46143 // last cached object takes this object's place 46144 indicesByUUID[ lastCachedObject.uuid ] = index; 46145 objects[ index ] = lastCachedObject; 46146 46147 // last object goes to the activated slot and pop 46148 indicesByUUID[ lastObject.uuid ] = firstActiveIndex; 46149 objects[ firstActiveIndex ] = lastObject; 46150 objects.pop(); 46151 46152 // accounting is done, now do the same for all bindings 46153 46154 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 46155 46156 const bindingsForPath = bindings[ j ], 46157 lastCached = bindingsForPath[ firstActiveIndex ], 46158 last = bindingsForPath[ lastIndex ]; 46159 46160 bindingsForPath[ index ] = lastCached; 46161 bindingsForPath[ firstActiveIndex ] = last; 46162 bindingsForPath.pop(); 46163 46164 } 46165 46166 } else { 46167 46168 // object is active, just swap with the last and pop 46169 46170 const lastIndex = -- nObjects, 46171 lastObject = objects[ lastIndex ]; 46172 46173 if ( lastIndex > 0 ) { 46174 46175 indicesByUUID[ lastObject.uuid ] = index; 46176 46177 } 46178 46179 objects[ index ] = lastObject; 46180 objects.pop(); 46181 46182 // accounting is done, now do the same for all bindings 46183 46184 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 46185 46186 const bindingsForPath = bindings[ j ]; 46187 46188 bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; 46189 bindingsForPath.pop(); 46190 46191 } 46192 46193 } // cached or active 46194 46195 } // if object is known 46196 46197 } // for arguments 46198 46199 this.nCachedObjects_ = nCachedObjects; 46200 46201 } 46202 46203 // Internal interface used by befriended PropertyBinding.Composite: 46204 46205 subscribe_( path, parsedPath ) { 46206 46207 // returns an array of bindings for the given path that is changed 46208 // according to the contained objects in the group 46209 46210 const indicesByPath = this._bindingsIndicesByPath; 46211 let index = indicesByPath[ path ]; 46212 const bindings = this._bindings; 46213 46214 if ( index !== undefined ) return bindings[ index ]; 46215 46216 const paths = this._paths, 46217 parsedPaths = this._parsedPaths, 46218 objects = this._objects, 46219 nObjects = objects.length, 46220 nCachedObjects = this.nCachedObjects_,
vendor: 7,613 bytes, lines 46221-46614
46221 bindingsForPath = new Array( nObjects ); 46222 46223 index = bindings.length; 46224 46225 indicesByPath[ path ] = index; 46226 46227 paths.push( path ); 46228 parsedPaths.push( parsedPath ); 46229 bindings.push( bindingsForPath ); 46230 46231 for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) { 46232 46233 const object = objects[ i ]; 46234 bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); 46235 46236 } 46237 46238 return bindingsForPath; 46239 46240 } 46241 46242 unsubscribe_( path ) { 46243 46244 // tells the group to forget about a property path and no longer 46245 // update the array previously obtained with 'subscribe_' 46246 46247 const indicesByPath = this._bindingsIndicesByPath, 46248 index = indicesByPath[ path ]; 46249 46250 if ( index !== undefined ) { 46251 46252 const paths = this._paths, 46253 parsedPaths = this._parsedPaths, 46254 bindings = this._bindings, 46255 lastBindingsIndex = bindings.length - 1, 46256 lastBindings = bindings[ lastBindingsIndex ], 46257 lastBindingsPath = path[ lastBindingsIndex ]; 46258 46259 indicesByPath[ lastBindingsPath ] = index; 46260 46261 bindings[ index ] = lastBindings; 46262 bindings.pop(); 46263 46264 parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; 46265 parsedPaths.pop(); 46266 46267 paths[ index ] = paths[ lastBindingsIndex ]; 46268 paths.pop(); 46269 46270 } 46271 46272 } 46273 46274} 46275 46276class AnimationAction { 46277 46278 constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) { 46279 46280 this._mixer = mixer; 46281 this._clip = clip; 46282 this._localRoot = localRoot; 46283 this.blendMode = blendMode; 46284 46285 const tracks = clip.tracks, 46286 nTracks = tracks.length, 46287 interpolants = new Array( nTracks ); 46288 46289 const interpolantSettings = { 46290 endingStart: ZeroCurvatureEnding, 46291 endingEnd: ZeroCurvatureEnding 46292 }; 46293 46294 for ( let i = 0; i !== nTracks; ++ i ) { 46295 46296 const interpolant = tracks[ i ].createInterpolant( null ); 46297 interpolants[ i ] = interpolant; 46298 interpolant.settings = interpolantSettings; 46299 46300 } 46301 46302 this._interpolantSettings = interpolantSettings; 46303 46304 this._interpolants = interpolants; // bound by the mixer 46305 46306 // inside: PropertyMixer (managed by the mixer) 46307 this._propertyBindings = new Array( nTracks ); 46308 46309 this._cacheIndex = null; // for the memory manager 46310 this._byClipCacheIndex = null; // for the memory manager 46311 46312 this._timeScaleInterpolant = null; 46313 this._weightInterpolant = null; 46314 46315 this.loop = LoopRepeat; 46316 this._loopCount = - 1; 46317 46318 // global mixer time when the action is to be started 46319 // it's set back to 'null' upon start of the action 46320 this._startTime = null; 46321 46322 // scaled local time of the action 46323 // gets clamped or wrapped to 0..clip.duration according to loop 46324 this.time = 0; 46325 46326 this.timeScale = 1; 46327 this._effectiveTimeScale = 1; 46328 46329 this.weight = 1; 46330 this._effectiveWeight = 1; 46331 46332 this.repetitions = Infinity; // no. of repetitions when looping 46333 46334 this.paused = false; // true -> zero effective time scale 46335 this.enabled = true; // false -> zero effective weight 46336 46337 this.clampWhenFinished = false;// keep feeding the last frame? 46338 46339 this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate 46340 this.zeroSlopeAtEnd = true;// clips for start, loop and end 46341 46342 } 46343 46344 // State & Scheduling 46345 46346 play() { 46347 46348 this._mixer._activateAction( this ); 46349 46350 return this; 46351 46352 } 46353 46354 stop() { 46355 46356 this._mixer._deactivateAction( this ); 46357 46358 return this.reset(); 46359 46360 } 46361 46362 reset() { 46363 46364 this.paused = false; 46365 this.enabled = true; 46366 46367 this.time = 0; // restart clip 46368 this._loopCount = - 1;// forget previous loops 46369 this._startTime = null;// forget scheduling 46370 46371 return this.stopFading().stopWarping(); 46372 46373 } 46374 46375 isRunning() { 46376 46377 return this.enabled && ! this.paused && this.timeScale !== 0 && 46378 this._startTime === null && this._mixer._isActiveAction( this ); 46379 46380 } 46381 46382 // return true when play has been called 46383 isScheduled() { 46384 46385 return this._mixer._isActiveAction( this ); 46386 46387 } 46388 46389 startAt( time ) { 46390 46391 this._startTime = time; 46392 46393 return this; 46394 46395 } 46396 46397 setLoop( mode, repetitions ) { 46398 46399 this.loop = mode; 46400 this.repetitions = repetitions; 46401 46402 return this; 46403 46404 } 46405 46406 // Weight 46407 46408 // set the weight stopping any scheduled fading 46409 // although .enabled = false yields an effective weight of zero, this 46410 // method does *not* change .enabled, because it would be confusing 46411 setEffectiveWeight( weight ) { 46412 46413 this.weight = weight; 46414 46415 // note: same logic as when updated at runtime 46416 this._effectiveWeight = this.enabled ? weight : 0; 46417 46418 return this.stopFading(); 46419 46420 } 46421 46422 // return the weight considering fading and .enabled 46423 getEffectiveWeight() { 46424 46425 return this._effectiveWeight; 46426 46427 } 46428 46429 fadeIn( duration ) { 46430 46431 return this._scheduleFading( duration, 0, 1 ); 46432 46433 } 46434 46435 fadeOut( duration ) { 46436 46437 return this._scheduleFading( duration, 1, 0 ); 46438 46439 } 46440 46441 crossFadeFrom( fadeOutAction, duration, warp ) { 46442 46443 fadeOutAction.fadeOut( duration ); 46444 this.fadeIn( duration ); 46445 46446 if ( warp ) { 46447 46448 const fadeInDuration = this._clip.duration, 46449 fadeOutDuration = fadeOutAction._clip.duration, 46450 46451 startEndRatio = fadeOutDuration / fadeInDuration, 46452 endStartRatio = fadeInDuration / fadeOutDuration; 46453 46454 fadeOutAction.warp( 1.0, startEndRatio, duration ); 46455 this.warp( endStartRatio, 1.0, duration ); 46456 46457 } 46458 46459 return this; 46460 46461 } 46462 46463 crossFadeTo( fadeInAction, duration, warp ) { 46464 46465 return fadeInAction.crossFadeFrom( this, duration, warp ); 46466 46467 } 46468 46469 stopFading() { 46470 46471 const weightInterpolant = this._weightInterpolant; 46472 46473 if ( weightInterpolant !== null ) { 46474 46475 this._weightInterpolant = null; 46476 this._mixer._takeBackControlInterpolant( weightInterpolant ); 46477 46478 } 46479 46480 return this; 46481 46482 } 46483 46484 // Time Scale Control 46485 46486 // set the time scale stopping any scheduled warping 46487 // although .paused = true yields an effective time scale of zero, this 46488 // method does *not* change .paused, because it would be confusing 46489 setEffectiveTimeScale( timeScale ) { 46490 46491 this.timeScale = timeScale; 46492 this._effectiveTimeScale = this.paused ? 0 : timeScale; 46493 46494 return this.stopWarping(); 46495 46496 } 46497 46498 // return the time scale considering warping and .paused 46499 getEffectiveTimeScale() { 46500 46501 return this._effectiveTimeScale; 46502 46503 } 46504 46505 setDuration( duration ) { 46506 46507 this.timeScale = this._clip.duration / duration; 46508 46509 return this.stopWarping(); 46510 46511 } 46512 46513 syncWith( action ) { 46514 46515 this.time = action.time; 46516 this.timeScale = action.timeScale; 46517 46518 return this.stopWarping(); 46519 46520 } 46521 46522 halt( duration ) { 46523 46524 return this.warp( this._effectiveTimeScale, 0, duration ); 46525 46526 } 46527 46528 warp( startTimeScale, endTimeScale, duration ) { 46529 46530 const mixer = this._mixer, 46531 now = mixer.time, 46532 timeScale = this.timeScale; 46533 46534 let interpolant = this._timeScaleInterpolant; 46535 46536 if ( interpolant === null ) { 46537 46538 interpolant = mixer._lendControlInterpolant(); 46539 this._timeScaleInterpolant = interpolant; 46540 46541 } 46542 46543 const times = interpolant.parameterPositions, 46544 values = interpolant.sampleValues; 46545 46546 times[ 0 ] = now; 46547 times[ 1 ] = now + duration; 46548 46549 values[ 0 ] = startTimeScale / timeScale; 46550 values[ 1 ] = endTimeScale / timeScale; 46551 46552 return this; 46553 46554 } 46555 46556 stopWarping() { 46557 46558 const timeScaleInterpolant = this._timeScaleInterpolant; 46559 46560 if ( timeScaleInterpolant !== null ) { 46561 46562 this._timeScaleInterpolant = null; 46563 this._mixer._takeBackControlInterpolant( timeScaleInterpolant ); 46564 46565 } 46566 46567 return this; 46568 46569 } 46570 46571 // Object Accessors 46572 46573 getMixer() { 46574 46575 return this._mixer; 46576 46577 } 46578 46579 getClip() { 46580 46581 return this._clip; 46582 46583 } 46584 46585 getRoot() { 46586 46587 return this._localRoot || this._mixer._root; 46588 46589 } 46590 46591 // Interna 46592 46593 _update( time, deltaTime, timeDirection, accuIndex ) { 46594 46595 // called by the mixer 46596 46597 if ( ! this.enabled ) { 46598 46599 // call ._updateWeight() to update ._effectiveWeight 46600 46601 this._updateWeight( time ); 46602 return; 46603 46604 } 46605 46606 const startTime = this._startTime; 46607 46608 if ( startTime !== null ) { 46609 46610 // check for scheduled start of action 46611 46612 const timeRunning = ( time - startTime ) * timeDirection; 46613 if ( timeRunning < 0 || timeDirection === 0 ) { 46614
vendor: 6,044 bytes, lines 46615-46973
46615 deltaTime = 0; 46616 46617 } else { 46618 46619 46620 this._startTime = null; // unschedule 46621 deltaTime = timeDirection * timeRunning; 46622 46623 } 46624 46625 } 46626 46627 // apply time scale and advance time 46628 46629 deltaTime *= this._updateTimeScale( time ); 46630 const clipTime = this._updateTime( deltaTime ); 46631 46632 // note: _updateTime may disable the action resulting in 46633 // an effective weight of 0 46634 46635 const weight = this._updateWeight( time ); 46636 46637 if ( weight > 0 ) { 46638 46639 const interpolants = this._interpolants; 46640 const propertyMixers = this._propertyBindings; 46641 46642 switch ( this.blendMode ) { 46643 46644 case AdditiveAnimationBlendMode: 46645 46646 for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { 46647 46648 interpolants[ j ].evaluate( clipTime ); 46649 propertyMixers[ j ].accumulateAdditive( weight ); 46650 46651 } 46652 46653 break; 46654 46655 case NormalAnimationBlendMode: 46656 default: 46657 46658 for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { 46659 46660 interpolants[ j ].evaluate( clipTime ); 46661 propertyMixers[ j ].accumulate( accuIndex, weight ); 46662 46663 } 46664 46665 } 46666 46667 } 46668 46669 } 46670 46671 _updateWeight( time ) { 46672 46673 let weight = 0; 46674 46675 if ( this.enabled ) { 46676 46677 weight = this.weight; 46678 const interpolant = this._weightInterpolant; 46679 46680 if ( interpolant !== null ) { 46681 46682 const interpolantValue = interpolant.evaluate( time )[ 0 ]; 46683 46684 weight *= interpolantValue; 46685 46686 if ( time > interpolant.parameterPositions[ 1 ] ) { 46687 46688 this.stopFading(); 46689 46690 if ( interpolantValue === 0 ) { 46691 46692 // faded out, disable 46693 this.enabled = false; 46694 46695 } 46696 46697 } 46698 46699 } 46700 46701 } 46702 46703 this._effectiveWeight = weight; 46704 return weight; 46705 46706 } 46707 46708 _updateTimeScale( time ) { 46709 46710 let timeScale = 0; 46711 46712 if ( ! this.paused ) { 46713 46714 timeScale = this.timeScale; 46715 46716 const interpolant = this._timeScaleInterpolant; 46717 46718 if ( interpolant !== null ) { 46719 46720 const interpolantValue = interpolant.evaluate( time )[ 0 ]; 46721 46722 timeScale *= interpolantValue; 46723 46724 if ( time > interpolant.parameterPositions[ 1 ] ) { 46725 46726 this.stopWarping(); 46727 46728 if ( timeScale === 0 ) { 46729 46730 // motion has halted, pause 46731 this.paused = true; 46732 46733 } else { 46734 46735 // warp done - apply final time scale 46736 this.timeScale = timeScale; 46737 46738 } 46739 46740 } 46741 46742 } 46743 46744 } 46745 46746 this._effectiveTimeScale = timeScale; 46747 return timeScale; 46748 46749 } 46750 46751 _updateTime( deltaTime ) { 46752 46753 const duration = this._clip.duration; 46754 const loop = this.loop; 46755 46756 let time = this.time + deltaTime; 46757 let loopCount = this._loopCount; 46758 46759 const pingPong = ( loop === LoopPingPong ); 46760 46761 if ( deltaTime === 0 ) { 46762 46763 if ( loopCount === - 1 ) return time; 46764 46765 return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time; 46766 46767 } 46768 46769 if ( loop === LoopOnce ) { 46770 46771 if ( loopCount === - 1 ) { 46772 46773 // just started 46774 46775 this._loopCount = 0; 46776 this._setEndings( true, true, false ); 46777 46778 } 46779 46780 handle_stop: { 46781 46782 if ( time >= duration ) { 46783 46784 time = duration; 46785 46786 } else if ( time < 0 ) { 46787 46788 time = 0; 46789 46790 } else { 46791 46792 this.time = time; 46793 46794 break handle_stop; 46795 46796 } 46797 46798 if ( this.clampWhenFinished ) this.paused = true; 46799 else this.enabled = false; 46800 46801 this.time = time; 46802 46803 this._mixer.dispatchEvent( { 46804 type: 'finished', action: this, 46805 direction: deltaTime < 0 ? - 1 : 1 46806 } ); 46807 46808 } 46809 46810 } else { // repetitive Repeat or PingPong 46811 46812 if ( loopCount === - 1 ) { 46813 46814 // just started 46815 46816 if ( deltaTime >= 0 ) { 46817 46818 loopCount = 0; 46819 46820 this._setEndings( true, this.repetitions === 0, pingPong ); 46821 46822 } else { 46823 46824 // when looping in reverse direction, the initial 46825 // transition through zero counts as a repetition, 46826 // so leave loopCount at -1 46827 46828 this._setEndings( this.repetitions === 0, true, pingPong ); 46829 46830 } 46831 46832 } 46833 46834 if ( time >= duration || time < 0 ) { 46835 46836 // wrap around 46837 46838 const loopDelta = Math.floor( time / duration ); // signed 46839 time -= duration * loopDelta; 46840 46841 loopCount += Math.abs( loopDelta ); 46842 46843 const pending = this.repetitions - loopCount; 46844 46845 if ( pending <= 0 ) { 46846 46847 // have to stop (switch state, clamp time, fire event) 46848 46849 if ( this.clampWhenFinished ) this.paused = true; 46850 else this.enabled = false; 46851 46852 time = deltaTime > 0 ? duration : 0; 46853 46854 this.time = time; 46855 46856 this._mixer.dispatchEvent( { 46857 type: 'finished', action: this, 46858 direction: deltaTime > 0 ? 1 : - 1 46859 } ); 46860 46861 } else { 46862 46863 // keep running 46864 46865 if ( pending === 1 ) { 46866 46867 // entering the last round 46868 46869 const atStart = deltaTime < 0; 46870 this._setEndings( atStart, ! atStart, pingPong ); 46871 46872 } else { 46873 46874 this._setEndings( false, false, pingPong ); 46875 46876 } 46877 46878 this._loopCount = loopCount; 46879 46880 this.time = time; 46881 46882 this._mixer.dispatchEvent( { 46883 type: 'loop', action: this, loopDelta: loopDelta 46884 } ); 46885 46886 } 46887 46888 } else { 46889 46890 this.time = time; 46891 46892 } 46893 46894 if ( pingPong && ( loopCount & 1 ) === 1 ) { 46895 46896 // invert time for the "pong round" 46897 46898 return duration - time; 46899 46900 } 46901 46902 } 46903 46904 return time; 46905 46906 } 46907 46908 _setEndings( atStart, atEnd, pingPong ) { 46909 46910 const settings = this._interpolantSettings; 46911 46912 if ( pingPong ) { 46913 46914 settings.endingStart = ZeroSlopeEnding; 46915 settings.endingEnd = ZeroSlopeEnding; 46916 46917 } else { 46918 46919 // assuming for LoopOnce atStart == atEnd == true 46920 46921 if ( atStart ) { 46922 46923 settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding; 46924 46925 } else { 46926 46927 settings.endingStart = WrapAroundEnding; 46928 46929 } 46930 46931 if ( atEnd ) { 46932 46933 settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding; 46934 46935 } else { 46936 46937 settings.endingEnd = WrapAroundEnding; 46938 46939 } 46940 46941 } 46942 46943 } 46944 46945 _scheduleFading( duration, weightNow, weightThen ) { 46946 46947 const mixer = this._mixer, now = mixer.time; 46948 let interpolant = this._weightInterpolant; 46949 46950 if ( interpolant === null ) { 46951 46952 interpolant = mixer._lendControlInterpolant(); 46953 this._weightInterpolant = interpolant; 46954 46955 } 46956 46957 const times = interpolant.parameterPositions, 46958 values = interpolant.sampleValues; 46959 46960 times[ 0 ] = now; 46961 values[ 0 ] = weightNow; 46962 times[ 1 ] = now + duration; 46963 values[ 1 ] = weightThen; 46964 46965 return this; 46966 46967 } 46968 46969} 46970 46971const _controlInterpolantsResultBuffer = new Float32Array( 1 ); 46972 46973
vendor: 13,381 bytes, lines 46974-47614
46974class AnimationMixer extends EventDispatcher { 46975 46976 constructor( root ) { 46977 46978 super(); 46979 46980 this._root = root; 46981 this._initMemoryManager(); 46982 this._accuIndex = 0; 46983 this.time = 0; 46984 this.timeScale = 1.0; 46985 46986 } 46987 46988 _bindAction( action, prototypeAction ) { 46989 46990 const root = action._localRoot || this._root, 46991 tracks = action._clip.tracks, 46992 nTracks = tracks.length, 46993 bindings = action._propertyBindings, 46994 interpolants = action._interpolants, 46995 rootUuid = root.uuid, 46996 bindingsByRoot = this._bindingsByRootAndName; 46997 46998 let bindingsByName = bindingsByRoot[ rootUuid ]; 46999 47000 if ( bindingsByName === undefined ) { 47001 47002 bindingsByName = {}; 47003 bindingsByRoot[ rootUuid ] = bindingsByName; 47004 47005 } 47006 47007 for ( let i = 0; i !== nTracks; ++ i ) { 47008 47009 const track = tracks[ i ], 47010 trackName = track.name; 47011 47012 let binding = bindingsByName[ trackName ]; 47013 47014 if ( binding !== undefined ) { 47015 47016 ++ binding.referenceCount; 47017 bindings[ i ] = binding; 47018 47019 } else { 47020 47021 binding = bindings[ i ]; 47022 47023 if ( binding !== undefined ) { 47024 47025 // existing binding, make sure the cache knows 47026 47027 if ( binding._cacheIndex === null ) { 47028 47029 ++ binding.referenceCount; 47030 this._addInactiveBinding( binding, rootUuid, trackName ); 47031 47032 } 47033 47034 continue; 47035 47036 } 47037 47038 const path = prototypeAction && prototypeAction. 47039 _propertyBindings[ i ].binding.parsedPath; 47040 47041 binding = new PropertyMixer( 47042 PropertyBinding.create( root, trackName, path ), 47043 track.ValueTypeName, track.getValueSize() ); 47044 47045 ++ binding.referenceCount; 47046 this._addInactiveBinding( binding, rootUuid, trackName ); 47047 47048 bindings[ i ] = binding; 47049 47050 } 47051 47052 interpolants[ i ].resultBuffer = binding.buffer; 47053 47054 } 47055 47056 } 47057 47058 _activateAction( action ) { 47059 47060 if ( ! this._isActiveAction( action ) ) { 47061 47062 if ( action._cacheIndex === null ) { 47063 47064 // this action has been forgotten by the cache, but the user 47065 // appears to be still using it -> rebind 47066 47067 const rootUuid = ( action._localRoot || this._root ).uuid, 47068 clipUuid = action._clip.uuid, 47069 actionsForClip = this._actionsByClip[ clipUuid ]; 47070 47071 this._bindAction( action, 47072 actionsForClip && actionsForClip.knownActions[ 0 ] ); 47073 47074 this._addInactiveAction( action, clipUuid, rootUuid ); 47075 47076 } 47077 47078 const bindings = action._propertyBindings; 47079 47080 // increment reference counts / sort out state 47081 for ( let i = 0, n = bindings.length; i !== n; ++ i ) { 47082 47083 const binding = bindings[ i ]; 47084 47085 if ( binding.useCount ++ === 0 ) { 47086 47087 this._lendBinding( binding ); 47088 binding.saveOriginalState(); 47089 47090 } 47091 47092 } 47093 47094 this._lendAction( action ); 47095 47096 } 47097 47098 } 47099 47100 _deactivateAction( action ) { 47101 47102 if ( this._isActiveAction( action ) ) { 47103 47104 const bindings = action._propertyBindings; 47105 47106 // decrement reference counts / sort out state 47107 for ( let i = 0, n = bindings.length; i !== n; ++ i ) { 47108 47109 const binding = bindings[ i ]; 47110 47111 if ( -- binding.useCount === 0 ) { 47112 47113 binding.restoreOriginalState(); 47114 this._takeBackBinding( binding ); 47115 47116 } 47117 47118 } 47119 47120 this._takeBackAction( action ); 47121 47122 } 47123 47124 } 47125 47126 // Memory manager 47127 47128 _initMemoryManager() { 47129 47130 this._actions = []; // 'nActiveActions' followed by inactive ones 47131 this._nActiveActions = 0; 47132 47133 this._actionsByClip = {}; 47134 // inside: 47135 // { 47136 // knownActions: Array< AnimationAction > - used as prototypes 47137 // actionByRoot: AnimationAction - lookup 47138 // } 47139 47140 47141 this._bindings = []; // 'nActiveBindings' followed by inactive ones 47142 this._nActiveBindings = 0; 47143 47144 this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer > 47145 47146 47147 this._controlInterpolants = []; // same game as above 47148 this._nActiveControlInterpolants = 0; 47149 47150 const scope = this; 47151 47152 this.stats = { 47153 47154 actions: { 47155 get total() { 47156 47157 return scope._actions.length; 47158 47159 }, 47160 get inUse() { 47161 47162 return scope._nActiveActions; 47163 47164 } 47165 }, 47166 bindings: { 47167 get total() { 47168 47169 return scope._bindings.length; 47170 47171 }, 47172 get inUse() { 47173 47174 return scope._nActiveBindings; 47175 47176 } 47177 }, 47178 controlInterpolants: { 47179 get total() { 47180 47181 return scope._controlInterpolants.length; 47182 47183 }, 47184 get inUse() { 47185 47186 return scope._nActiveControlInterpolants; 47187 47188 } 47189 } 47190 47191 }; 47192 47193 } 47194 47195 // Memory management for AnimationAction objects 47196 47197 _isActiveAction( action ) { 47198 47199 const index = action._cacheIndex; 47200 return index !== null && index < this._nActiveActions; 47201 47202 } 47203 47204 _addInactiveAction( action, clipUuid, rootUuid ) { 47205 47206 const actions = this._actions, 47207 actionsByClip = this._actionsByClip; 47208 47209 let actionsForClip = actionsByClip[ clipUuid ]; 47210 47211 if ( actionsForClip === undefined ) { 47212 47213 actionsForClip = { 47214 47215 knownActions: [ action ], 47216 actionByRoot: {} 47217 47218 }; 47219 47220 action._byClipCacheIndex = 0; 47221 47222 actionsByClip[ clipUuid ] = actionsForClip; 47223 47224 } else { 47225 47226 const knownActions = actionsForClip.knownActions; 47227 47228 action._byClipCacheIndex = knownActions.length; 47229 knownActions.push( action ); 47230 47231 } 47232 47233 action._cacheIndex = actions.length; 47234 actions.push( action ); 47235 47236 actionsForClip.actionByRoot[ rootUuid ] = action; 47237 47238 } 47239 47240 _removeInactiveAction( action ) { 47241 47242 const actions = this._actions, 47243 lastInactiveAction = actions[ actions.length - 1 ], 47244 cacheIndex = action._cacheIndex; 47245 47246 lastInactiveAction._cacheIndex = cacheIndex; 47247 actions[ cacheIndex ] = lastInactiveAction; 47248 actions.pop(); 47249 47250 action._cacheIndex = null; 47251 47252 47253 const clipUuid = action._clip.uuid, 47254 actionsByClip = this._actionsByClip, 47255 actionsForClip = actionsByClip[ clipUuid ], 47256 knownActionsForClip = actionsForClip.knownActions, 47257 47258 lastKnownAction = 47259 knownActionsForClip[ knownActionsForClip.length - 1 ], 47260 47261 byClipCacheIndex = action._byClipCacheIndex; 47262 47263 lastKnownAction._byClipCacheIndex = byClipCacheIndex; 47264 knownActionsForClip[ byClipCacheIndex ] = lastKnownAction; 47265 knownActionsForClip.pop(); 47266 47267 action._byClipCacheIndex = null; 47268 47269 47270 const actionByRoot = actionsForClip.actionByRoot, 47271 rootUuid = ( action._localRoot || this._root ).uuid; 47272 47273 delete actionByRoot[ rootUuid ]; 47274 47275 if ( knownActionsForClip.length === 0 ) { 47276 47277 delete actionsByClip[ clipUuid ]; 47278 47279 } 47280 47281 this._removeInactiveBindingsForAction( action ); 47282 47283 } 47284 47285 _removeInactiveBindingsForAction( action ) { 47286 47287 const bindings = action._propertyBindings; 47288 47289 for ( let i = 0, n = bindings.length; i !== n; ++ i ) { 47290 47291 const binding = bindings[ i ]; 47292 47293 if ( -- binding.referenceCount === 0 ) { 47294 47295 this._removeInactiveBinding( binding ); 47296 47297 } 47298 47299 } 47300 47301 } 47302 47303 _lendAction( action ) { 47304 47305 // [ active actions | inactive actions ] 47306 // [ active actions >| inactive actions ] 47307 // s a 47308 // <-swap-> 47309 // a s 47310 47311 const actions = this._actions, 47312 prevIndex = action._cacheIndex, 47313 47314 lastActiveIndex = this._nActiveActions ++, 47315 47316 firstInactiveAction = actions[ lastActiveIndex ]; 47317 47318 action._cacheIndex = lastActiveIndex; 47319 actions[ lastActiveIndex ] = action; 47320 47321 firstInactiveAction._cacheIndex = prevIndex; 47322 actions[ prevIndex ] = firstInactiveAction; 47323 47324 } 47325 47326 _takeBackAction( action ) { 47327 47328 // [ active actions | inactive actions ] 47329 // [ active actions |< inactive actions ] 47330 // a s 47331 // <-swap-> 47332 // s a 47333 47334 const actions = this._actions, 47335 prevIndex = action._cacheIndex, 47336 47337 firstInactiveIndex = -- this._nActiveActions, 47338 47339 lastActiveAction = actions[ firstInactiveIndex ]; 47340 47341 action._cacheIndex = firstInactiveIndex; 47342 actions[ firstInactiveIndex ] = action; 47343 47344 lastActiveAction._cacheIndex = prevIndex; 47345 actions[ prevIndex ] = lastActiveAction; 47346 47347 } 47348 47349 // Memory management for PropertyMixer objects 47350 47351 _addInactiveBinding( binding, rootUuid, trackName ) { 47352 47353 const bindingsByRoot = this._bindingsByRootAndName, 47354 bindings = this._bindings; 47355 47356 let bindingByName = bindingsByRoot[ rootUuid ]; 47357 47358 if ( bindingByName === undefined ) { 47359 47360 bindingByName = {}; 47361 bindingsByRoot[ rootUuid ] = bindingByName; 47362 47363 } 47364 47365 bindingByName[ trackName ] = binding; 47366 47367 binding._cacheIndex = bindings.length; 47368 bindings.push( binding ); 47369 47370 } 47371 47372 _removeInactiveBinding( binding ) { 47373 47374 const bindings = this._bindings, 47375 propBinding = binding.binding, 47376 rootUuid = propBinding.rootNode.uuid, 47377 trackName = propBinding.path, 47378 bindingsByRoot = this._bindingsByRootAndName, 47379 bindingByName = bindingsByRoot[ rootUuid ], 47380 47381 lastInactiveBinding = bindings[ bindings.length - 1 ], 47382 cacheIndex = binding._cacheIndex; 47383 47384 lastInactiveBinding._cacheIndex = cacheIndex; 47385 bindings[ cacheIndex ] = lastInactiveBinding; 47386 bindings.pop(); 47387 47388 delete bindingByName[ trackName ]; 47389 47390 if ( Object.keys( bindingByName ).length === 0 ) { 47391 47392 delete bindingsByRoot[ rootUuid ]; 47393 47394 } 47395 47396 } 47397 47398 _lendBinding( binding ) { 47399 47400 const bindings = this._bindings, 47401 prevIndex = binding._cacheIndex, 47402 47403 lastActiveIndex = this._nActiveBindings ++, 47404 47405 firstInactiveBinding = bindings[ lastActiveIndex ]; 47406 47407 binding._cacheIndex = lastActiveIndex; 47408 bindings[ lastActiveIndex ] = binding; 47409 47410 firstInactiveBinding._cacheIndex = prevIndex; 47411 bindings[ prevIndex ] = firstInactiveBinding; 47412 47413 } 47414 47415 _takeBackBinding( binding ) { 47416 47417 const bindings = this._bindings, 47418 prevIndex = binding._cacheIndex, 47419 47420 firstInactiveIndex = -- this._nActiveBindings, 47421 47422 lastActiveBinding = bindings[ firstInactiveIndex ]; 47423 47424 binding._cacheIndex = firstInactiveIndex; 47425 bindings[ firstInactiveIndex ] = binding; 47426 47427 lastActiveBinding._cacheIndex = prevIndex; 47428 bindings[ prevIndex ] = lastActiveBinding; 47429 47430 } 47431 47432 47433 // Memory management of Interpolants for weight and time scale 47434 47435 _lendControlInterpolant() { 47436 47437 const interpolants = this._controlInterpolants, 47438 lastActiveIndex = this._nActiveControlInterpolants ++; 47439 47440 let interpolant = interpolants[ lastActiveIndex ]; 47441 47442 if ( interpolant === undefined ) { 47443 47444 interpolant = new LinearInterpolant( 47445 new Float32Array( 2 ), new Float32Array( 2 ), 47446 1, _controlInterpolantsResultBuffer ); 47447 47448 interpolant.__cacheIndex = lastActiveIndex; 47449 interpolants[ lastActiveIndex ] = interpolant; 47450 47451 } 47452 47453 return interpolant; 47454 47455 } 47456 47457 _takeBackControlInterpolant( interpolant ) { 47458 47459 const interpolants = this._controlInterpolants, 47460 prevIndex = interpolant.__cacheIndex, 47461 47462 firstInactiveIndex = -- this._nActiveControlInterpolants, 47463 47464 lastActiveInterpolant = interpolants[ firstInactiveIndex ]; 47465 47466 interpolant.__cacheIndex = firstInactiveIndex; 47467 interpolants[ firstInactiveIndex ] = interpolant; 47468 47469 lastActiveInterpolant.__cacheIndex = prevIndex; 47470 interpolants[ prevIndex ] = lastActiveInterpolant; 47471 47472 } 47473 47474 // return an action for a clip optionally using a custom root target 47475 // object (this method allocates a lot of dynamic memory in case a 47476 // previously unknown clip/root combination is specified) 47477 clipAction( clip, optionalRoot, blendMode ) { 47478 47479 const root = optionalRoot || this._root, 47480 rootUuid = root.uuid; 47481 47482 let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip; 47483 47484 const clipUuid = clipObject !== null ? clipObject.uuid : clip; 47485 47486 const actionsForClip = this._actionsByClip[ clipUuid ]; 47487 let prototypeAction = null; 47488 47489 if ( blendMode === undefined ) { 47490 47491 if ( clipObject !== null ) { 47492 47493 blendMode = clipObject.blendMode; 47494 47495 } else { 47496 47497 blendMode = NormalAnimationBlendMode; 47498 47499 } 47500 47501 } 47502 47503 if ( actionsForClip !== undefined ) { 47504 47505 const existingAction = actionsForClip.actionByRoot[ rootUuid ]; 47506 47507 if ( existingAction !== undefined && existingAction.blendMode === blendMode ) { 47508 47509 return existingAction; 47510 47511 } 47512 47513 // we know the clip, so we don't have to parse all 47514 // the bindings again but can just copy 47515 prototypeAction = actionsForClip.knownActions[ 0 ]; 47516 47517 // also, take the clip from the prototype action 47518 if ( clipObject === null ) 47519 clipObject = prototypeAction._clip; 47520 47521 } 47522 47523 // clip must be known when specified via string 47524 if ( clipObject === null ) return null; 47525 47526 // allocate all resources required to run it 47527 const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode ); 47528 47529 this._bindAction( newAction, prototypeAction ); 47530 47531 // and make the action known to the memory manager 47532 this._addInactiveAction( newAction, clipUuid, rootUuid ); 47533 47534 return newAction; 47535 47536 } 47537 47538 // get an existing action 47539 existingAction( clip, optionalRoot ) { 47540 47541 const root = optionalRoot || this._root, 47542 rootUuid = root.uuid, 47543 47544 clipObject = typeof clip === 'string' ? 47545 AnimationClip.findByName( root, clip ) : clip, 47546 47547 clipUuid = clipObject ? clipObject.uuid : clip, 47548 47549 actionsForClip = this._actionsByClip[ clipUuid ]; 47550 47551 if ( actionsForClip !== undefined ) { 47552 47553 return actionsForClip.actionByRoot[ rootUuid ] || null; 47554 47555 } 47556 47557 return null; 47558 47559 } 47560 47561 // deactivates all previously scheduled actions 47562 stopAllAction() { 47563 47564 const actions = this._actions, 47565 nActions = this._nActiveActions; 47566 47567 for ( let i = nActions - 1; i >= 0; -- i ) { 47568 47569 actions[ i ].stop(); 47570 47571 } 47572 47573 return this; 47574 47575 } 47576 47577 // advance the time and update apply the animation 47578 update( deltaTime ) { 47579 47580 deltaTime *= this.timeScale; 47581 47582 const actions = this._actions, 47583 nActions = this._nActiveActions, 47584 47585 time = this.time += deltaTime, 47586 timeDirection = Math.sign( deltaTime ), 47587 47588 accuIndex = this._accuIndex ^= 1; 47589 47590 // run active actions 47591 47592 for ( let i = 0; i !== nActions; ++ i ) { 47593 47594 const action = actions[ i ]; 47595 47596 action._update( time, deltaTime, timeDirection, accuIndex ); 47597 47598 } 47599 47600 // update scene graph 47601 47602 const bindings = this._bindings, 47603 nBindings = this._nActiveBindings; 47604 47605 for ( let i = 0; i !== nBindings; ++ i ) { 47606 47607 bindings[ i ].apply( accuIndex ); 47608 47609 } 47610 47611 return this; 47612 47613 } 47614
vendor: 2,762 bytes, lines 47615-47748
47615 // Allows you to seek to a specific time in an animation. 47616 setTime( timeInSeconds ) { 47617 47618 this.time = 0; // Zero out time attribute for AnimationMixer object; 47619 for ( let i = 0; i < this._actions.length; i ++ ) { 47620 47621 this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects. 47622 47623 } 47624 47625 return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object. 47626 47627 } 47628 47629 // return this mixer's root target object 47630 getRoot() { 47631 47632 return this._root; 47633 47634 } 47635 47636 // free all resources specific to a particular clip 47637 uncacheClip( clip ) { 47638 47639 const actions = this._actions, 47640 clipUuid = clip.uuid, 47641 actionsByClip = this._actionsByClip, 47642 actionsForClip = actionsByClip[ clipUuid ]; 47643 47644 if ( actionsForClip !== undefined ) { 47645 47646 // note: just calling _removeInactiveAction would mess up the 47647 // iteration state and also require updating the state we can 47648 // just throw away 47649 47650 const actionsToRemove = actionsForClip.knownActions; 47651 47652 for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) { 47653 47654 const action = actionsToRemove[ i ]; 47655 47656 this._deactivateAction( action ); 47657 47658 const cacheIndex = action._cacheIndex, 47659 lastInactiveAction = actions[ actions.length - 1 ]; 47660 47661 action._cacheIndex = null; 47662 action._byClipCacheIndex = null; 47663 47664 lastInactiveAction._cacheIndex = cacheIndex; 47665 actions[ cacheIndex ] = lastInactiveAction; 47666 actions.pop(); 47667 47668 this._removeInactiveBindingsForAction( action ); 47669 47670 } 47671 47672 delete actionsByClip[ clipUuid ]; 47673 47674 } 47675 47676 } 47677 47678 // free all resources specific to a particular root target object 47679 uncacheRoot( root ) { 47680 47681 const rootUuid = root.uuid, 47682 actionsByClip = this._actionsByClip; 47683 47684 for ( const clipUuid in actionsByClip ) { 47685 47686 const actionByRoot = actionsByClip[ clipUuid ].actionByRoot, 47687 action = actionByRoot[ rootUuid ]; 47688 47689 if ( action !== undefined ) { 47690 47691 this._deactivateAction( action ); 47692 this._removeInactiveAction( action ); 47693 47694 } 47695 47696 } 47697 47698 const bindingsByRoot = this._bindingsByRootAndName, 47699 bindingByName = bindingsByRoot[ rootUuid ]; 47700 47701 if ( bindingByName !== undefined ) { 47702 47703 for ( const trackName in bindingByName ) { 47704 47705 const binding = bindingByName[ trackName ]; 47706 binding.restoreOriginalState(); 47707 this._removeInactiveBinding( binding ); 47708 47709 } 47710 47711 } 47712 47713 } 47714 47715 // remove a targeted clip from the cache 47716 uncacheAction( clip, optionalRoot ) { 47717 47718 const action = this.existingAction( clip, optionalRoot ); 47719 47720 if ( action !== null ) { 47721 47722 this._deactivateAction( action ); 47723 this._removeInactiveAction( action ); 47724 47725 } 47726 47727 } 47728 47729} 47730 47731class Uniform { 47732 47733 constructor( value ) { 47734 47735 this.value = value; 47736 47737 } 47738 47739 clone() { 47740 47741 return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() ); 47742 47743 } 47744 47745} 47746 47747let id = 0; 47748
vendor: 4,765 bytes, lines 47749-48053
47749class UniformsGroup extends EventDispatcher { 47750 47751 constructor() { 47752 47753 super(); 47754 47755 this.isUniformsGroup = true; 47756 47757 Object.defineProperty( this, 'id', { value: id ++ } ); 47758 47759 this.name = ''; 47760 47761 this.usage = StaticDrawUsage; 47762 this.uniforms = []; 47763 47764 } 47765 47766 add( uniform ) { 47767 47768 this.uniforms.push( uniform ); 47769 47770 return this; 47771 47772 } 47773 47774 remove( uniform ) { 47775 47776 const index = this.uniforms.indexOf( uniform ); 47777 47778 if ( index !== - 1 ) this.uniforms.splice( index, 1 ); 47779 47780 return this; 47781 47782 } 47783 47784 setName( name ) { 47785 47786 this.name = name; 47787 47788 return this; 47789 47790 } 47791 47792 setUsage( value ) { 47793 47794 this.usage = value; 47795 47796 return this; 47797 47798 } 47799 47800 dispose() { 47801 47802 this.dispatchEvent( { type: 'dispose' } ); 47803 47804 return this; 47805 47806 } 47807 47808 copy( source ) { 47809 47810 this.name = source.name; 47811 this.usage = source.usage; 47812 47813 const uniformsSource = source.uniforms; 47814 47815 this.uniforms.length = 0; 47816 47817 for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) { 47818 47819 this.uniforms.push( uniformsSource[ i ].clone() ); 47820 47821 } 47822 47823 return this; 47824 47825 } 47826 47827 clone() { 47828 47829 return new this.constructor().copy( this ); 47830 47831 } 47832 47833} 47834 47835class InstancedInterleavedBuffer extends InterleavedBuffer { 47836 47837 constructor( array, stride, meshPerAttribute = 1 ) { 47838 47839 super( array, stride ); 47840 47841 this.isInstancedInterleavedBuffer = true; 47842 47843 this.meshPerAttribute = meshPerAttribute; 47844 47845 } 47846 47847 copy( source ) { 47848 47849 super.copy( source ); 47850 47851 this.meshPerAttribute = source.meshPerAttribute; 47852 47853 return this; 47854 47855 } 47856 47857 clone( data ) { 47858 47859 const ib = super.clone( data ); 47860 47861 ib.meshPerAttribute = this.meshPerAttribute; 47862 47863 return ib; 47864 47865 } 47866 47867 toJSON( data ) { 47868 47869 const json = super.toJSON( data ); 47870 47871 json.isInstancedInterleavedBuffer = true; 47872 json.meshPerAttribute = this.meshPerAttribute; 47873 47874 return json; 47875 47876 } 47877 47878} 47879 47880class GLBufferAttribute { 47881 47882 constructor( buffer, type, itemSize, elementSize, count ) { 47883 47884 this.isGLBufferAttribute = true; 47885 47886 this.name = ''; 47887 47888 this.buffer = buffer; 47889 this.type = type; 47890 this.itemSize = itemSize; 47891 this.elementSize = elementSize; 47892 this.count = count; 47893 47894 this.version = 0; 47895 47896 } 47897 47898 set needsUpdate( value ) { 47899 47900 if ( value === true ) this.version ++; 47901 47902 } 47903 47904 setBuffer( buffer ) { 47905 47906 this.buffer = buffer; 47907 47908 return this; 47909 47910 } 47911 47912 setType( type, elementSize ) { 47913 47914 this.type = type; 47915 this.elementSize = elementSize; 47916 47917 return this; 47918 47919 } 47920 47921 setItemSize( itemSize ) { 47922 47923 this.itemSize = itemSize; 47924 47925 return this; 47926 47927 } 47928 47929 setCount( count ) { 47930 47931 this.count = count; 47932 47933 return this; 47934 47935 } 47936 47937} 47938 47939class Raycaster { 47940 47941 constructor( origin, direction, near = 0, far = Infinity ) { 47942 47943 this.ray = new Ray( origin, direction ); 47944 // direction is assumed to be normalized (for accurate distance calculations) 47945 47946 this.near = near; 47947 this.far = far; 47948 this.camera = null; 47949 this.layers = new Layers(); 47950 47951 this.params = { 47952 Mesh: {}, 47953 Line: { threshold: 1 }, 47954 LOD: {}, 47955 Points: { threshold: 1 }, 47956 Sprite: {} 47957 }; 47958 47959 } 47960 47961 set( origin, direction ) { 47962 47963 // direction is assumed to be normalized (for accurate distance calculations) 47964 47965 this.ray.set( origin, direction ); 47966 47967 } 47968 47969 setFromCamera( coords, camera ) { 47970 47971 if ( camera.isPerspectiveCamera ) { 47972 47973 this.ray.origin.setFromMatrixPosition( camera.matrixWorld ); 47974 this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize(); 47975 this.camera = camera; 47976 47977 } else if ( camera.isOrthographicCamera ) { 47978 47979 this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera 47980 this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); 47981 this.camera = camera; 47982 47983 } else { 47984 47985 console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type ); 47986 47987 } 47988 47989 } 47990 47991 intersectObject( object, recursive = true, intersects = [] ) { 47992 47993 intersectObject( object, this, intersects, recursive ); 47994 47995 intersects.sort( ascSort ); 47996 47997 return intersects; 47998 47999 } 48000 48001 intersectObjects( objects, recursive = true, intersects = [] ) { 48002 48003 for ( let i = 0, l = objects.length; i < l; i ++ ) { 48004 48005 intersectObject( objects[ i ], this, intersects, recursive ); 48006 48007 } 48008 48009 intersects.sort( ascSort ); 48010 48011 return intersects; 48012 48013 } 48014 48015} 48016 48017function ascSort( a, b ) { 48018 48019 return a.distance - b.distance; 48020 48021} 48022 48023function intersectObject( object, raycaster, intersects, recursive ) { 48024 48025 if ( object.layers.test( raycaster.layers ) ) { 48026 48027 object.raycast( raycaster, intersects ); 48028 48029 } 48030 48031 if ( recursive === true ) { 48032 48033 const children = object.children; 48034 48035 for ( let i = 0, l = children.length; i < l; i ++ ) { 48036 48037 intersectObject( children[ i ], raycaster, intersects, true ); 48038 48039 } 48040 48041 } 48042 48043} 48044 48045/** 48046 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system 48047 * 48048 * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up. 48049 * The azimuthal angle (theta) is measured from the positive z-axis. 48050 */ 48051 48052class Spherical { 48053
vendor: 20,801 bytes, lines 48054-49189
48054 constructor( radius = 1, phi = 0, theta = 0 ) { 48055 48056 this.radius = radius; 48057 this.phi = phi; // polar angle 48058 this.theta = theta; // azimuthal angle 48059 48060 return this; 48061 48062 } 48063 48064 set( radius, phi, theta ) { 48065 48066 this.radius = radius; 48067 this.phi = phi; 48068 this.theta = theta; 48069 48070 return this; 48071 48072 } 48073 48074 copy( other ) { 48075 48076 this.radius = other.radius; 48077 this.phi = other.phi; 48078 this.theta = other.theta; 48079 48080 return this; 48081 48082 } 48083 48084 // restrict phi to be between EPS and PI-EPS 48085 makeSafe() { 48086 48087 const EPS = 0.000001; 48088 this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) ); 48089 48090 return this; 48091 48092 } 48093 48094 setFromVector3( v ) { 48095 48096 return this.setFromCartesianCoords( v.x, v.y, v.z ); 48097 48098 } 48099 48100 setFromCartesianCoords( x, y, z ) { 48101 48102 this.radius = Math.sqrt( x * x + y * y + z * z ); 48103 48104 if ( this.radius === 0 ) { 48105 48106 this.theta = 0; 48107 this.phi = 0; 48108 48109 } else { 48110 48111 this.theta = Math.atan2( x, z ); 48112 this.phi = Math.acos( clamp( y / this.radius, - 1, 1 ) ); 48113 48114 } 48115 48116 return this; 48117 48118 } 48119 48120 clone() { 48121 48122 return new this.constructor().copy( this ); 48123 48124 } 48125 48126} 48127 48128/** 48129 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system 48130 */ 48131 48132class Cylindrical { 48133 48134 constructor( radius = 1, theta = 0, y = 0 ) { 48135 48136 this.radius = radius; // distance from the origin to a point in the x-z plane 48137 this.theta = theta; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis 48138 this.y = y; // height above the x-z plane 48139 48140 return this; 48141 48142 } 48143 48144 set( radius, theta, y ) { 48145 48146 this.radius = radius; 48147 this.theta = theta; 48148 this.y = y; 48149 48150 return this; 48151 48152 } 48153 48154 copy( other ) { 48155 48156 this.radius = other.radius; 48157 this.theta = other.theta; 48158 this.y = other.y; 48159 48160 return this; 48161 48162 } 48163 48164 setFromVector3( v ) { 48165 48166 return this.setFromCartesianCoords( v.x, v.y, v.z ); 48167 48168 } 48169 48170 setFromCartesianCoords( x, y, z ) { 48171 48172 this.radius = Math.sqrt( x * x + z * z ); 48173 this.theta = Math.atan2( x, z ); 48174 this.y = y; 48175 48176 return this; 48177 48178 } 48179 48180 clone() { 48181 48182 return new this.constructor().copy( this ); 48183 48184 } 48185 48186} 48187 48188const _vector$4 = /*@__PURE__*/ new Vector2(); 48189 48190class Box2 { 48191 48192 constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) { 48193 48194 this.isBox2 = true; 48195 48196 this.min = min; 48197 this.max = max; 48198 48199 } 48200 48201 set( min, max ) { 48202 48203 this.min.copy( min ); 48204 this.max.copy( max ); 48205 48206 return this; 48207 48208 } 48209 48210 setFromPoints( points ) { 48211 48212 this.makeEmpty(); 48213 48214 for ( let i = 0, il = points.length; i < il; i ++ ) { 48215 48216 this.expandByPoint( points[ i ] ); 48217 48218 } 48219 48220 return this; 48221 48222 } 48223 48224 setFromCenterAndSize( center, size ) { 48225 48226 const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 ); 48227 this.min.copy( center ).sub( halfSize ); 48228 this.max.copy( center ).add( halfSize ); 48229 48230 return this; 48231 48232 } 48233 48234 clone() { 48235 48236 return new this.constructor().copy( this ); 48237 48238 } 48239 48240 copy( box ) { 48241 48242 this.min.copy( box.min ); 48243 this.max.copy( box.max ); 48244 48245 return this; 48246 48247 } 48248 48249 makeEmpty() { 48250 48251 this.min.x = this.min.y = + Infinity; 48252 this.max.x = this.max.y = - Infinity; 48253 48254 return this; 48255 48256 } 48257 48258 isEmpty() { 48259 48260 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes 48261 48262 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); 48263 48264 } 48265 48266 getCenter( target ) { 48267 48268 return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); 48269 48270 } 48271 48272 getSize( target ) { 48273 48274 return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min ); 48275 48276 } 48277 48278 expandByPoint( point ) { 48279 48280 this.min.min( point ); 48281 this.max.max( point ); 48282 48283 return this; 48284 48285 } 48286 48287 expandByVector( vector ) { 48288 48289 this.min.sub( vector ); 48290 this.max.add( vector ); 48291 48292 return this; 48293 48294 } 48295 48296 expandByScalar( scalar ) { 48297 48298 this.min.addScalar( - scalar ); 48299 this.max.addScalar( scalar ); 48300 48301 return this; 48302 48303 } 48304 48305 containsPoint( point ) { 48306 48307 return point.x < this.min.x || point.x > this.max.x || 48308 point.y < this.min.y || point.y > this.max.y ? false : true; 48309 48310 } 48311 48312 containsBox( box ) { 48313 48314 return this.min.x <= box.min.x && box.max.x <= this.max.x && 48315 this.min.y <= box.min.y && box.max.y <= this.max.y; 48316 48317 } 48318 48319 getParameter( point, target ) { 48320 48321 // This can potentially have a divide by zero if the box 48322 // has a size dimension of 0. 48323 48324 return target.set( 48325 ( point.x - this.min.x ) / ( this.max.x - this.min.x ), 48326 ( point.y - this.min.y ) / ( this.max.y - this.min.y ) 48327 ); 48328 48329 } 48330 48331 intersectsBox( box ) { 48332 48333 // using 4 splitting planes to rule out intersections 48334 48335 return box.max.x < this.min.x || box.min.x > this.max.x || 48336 box.max.y < this.min.y || box.min.y > this.max.y ? false : true; 48337 48338 } 48339 48340 clampPoint( point, target ) { 48341 48342 return target.copy( point ).clamp( this.min, this.max ); 48343 48344 } 48345 48346 distanceToPoint( point ) { 48347 48348 return this.clampPoint( point, _vector$4 ).distanceTo( point ); 48349 48350 } 48351 48352 intersect( box ) { 48353 48354 this.min.max( box.min ); 48355 this.max.min( box.max ); 48356 48357 if ( this.isEmpty() ) this.makeEmpty(); 48358 48359 return this; 48360 48361 } 48362 48363 union( box ) { 48364 48365 this.min.min( box.min ); 48366 this.max.max( box.max ); 48367 48368 return this; 48369 48370 } 48371 48372 translate( offset ) { 48373 48374 this.min.add( offset ); 48375 this.max.add( offset ); 48376 48377 return this; 48378 48379 } 48380 48381 equals( box ) { 48382 48383 return box.min.equals( this.min ) && box.max.equals( this.max ); 48384 48385 } 48386 48387} 48388 48389const _startP = /*@__PURE__*/ new Vector3(); 48390const _startEnd = /*@__PURE__*/ new Vector3(); 48391 48392class Line3 { 48393 48394 constructor( start = new Vector3(), end = new Vector3() ) { 48395 48396 this.start = start; 48397 this.end = end; 48398 48399 } 48400 48401 set( start, end ) { 48402 48403 this.start.copy( start ); 48404 this.end.copy( end ); 48405 48406 return this; 48407 48408 } 48409 48410 copy( line ) { 48411 48412 this.start.copy( line.start ); 48413 this.end.copy( line.end ); 48414 48415 return this; 48416 48417 } 48418 48419 getCenter( target ) { 48420 48421 return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); 48422 48423 } 48424 48425 delta( target ) { 48426 48427 return target.subVectors( this.end, this.start ); 48428 48429 } 48430 48431 distanceSq() { 48432 48433 return this.start.distanceToSquared( this.end ); 48434 48435 } 48436 48437 distance() { 48438 48439 return this.start.distanceTo( this.end ); 48440 48441 } 48442 48443 at( t, target ) { 48444 48445 return this.delta( target ).multiplyScalar( t ).add( this.start ); 48446 48447 } 48448 48449 closestPointToPointParameter( point, clampToLine ) { 48450 48451 _startP.subVectors( point, this.start ); 48452 _startEnd.subVectors( this.end, this.start ); 48453 48454 const startEnd2 = _startEnd.dot( _startEnd ); 48455 const startEnd_startP = _startEnd.dot( _startP ); 48456 48457 let t = startEnd_startP / startEnd2; 48458 48459 if ( clampToLine ) { 48460 48461 t = clamp( t, 0, 1 ); 48462 48463 } 48464 48465 return t; 48466 48467 } 48468 48469 closestPointToPoint( point, clampToLine, target ) { 48470 48471 const t = this.closestPointToPointParameter( point, clampToLine ); 48472 48473 return this.delta( target ).multiplyScalar( t ).add( this.start ); 48474 48475 } 48476 48477 applyMatrix4( matrix ) { 48478 48479 this.start.applyMatrix4( matrix ); 48480 this.end.applyMatrix4( matrix ); 48481 48482 return this; 48483 48484 } 48485 48486 equals( line ) { 48487 48488 return line.start.equals( this.start ) && line.end.equals( this.end ); 48489 48490 } 48491 48492 clone() { 48493 48494 return new this.constructor().copy( this ); 48495 48496 } 48497 48498} 48499 48500const _vector$3 = /*@__PURE__*/ new Vector3(); 48501 48502class SpotLightHelper extends Object3D { 48503 48504 constructor( light, color ) { 48505 48506 super(); 48507 48508 this.light = light; 48509 48510 this.matrix = light.matrixWorld; 48511 this.matrixAutoUpdate = false; 48512 48513 this.color = color; 48514 48515 this.type = 'SpotLightHelper'; 48516 48517 const geometry = new BufferGeometry(); 48518 48519 const positions = [ 48520 0, 0, 0, 0, 0, 1, 48521 0, 0, 0, 1, 0, 1, 48522 0, 0, 0, - 1, 0, 1, 48523 0, 0, 0, 0, 1, 1, 48524 0, 0, 0, 0, - 1, 1 48525 ]; 48526 48527 for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) { 48528 48529 const p1 = ( i / l ) * Math.PI * 2; 48530 const p2 = ( j / l ) * Math.PI * 2; 48531 48532 positions.push( 48533 Math.cos( p1 ), Math.sin( p1 ), 1, 48534 Math.cos( p2 ), Math.sin( p2 ), 1 48535 ); 48536 48537 } 48538 48539 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 48540 48541 const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); 48542 48543 this.cone = new LineSegments( geometry, material ); 48544 this.add( this.cone ); 48545 48546 this.update(); 48547 48548 } 48549 48550 dispose() { 48551 48552 this.cone.geometry.dispose(); 48553 this.cone.material.dispose(); 48554 48555 } 48556 48557 update() { 48558 48559 this.light.updateWorldMatrix( true, false ); 48560 this.light.target.updateWorldMatrix( true, false ); 48561 48562 const coneLength = this.light.distance ? this.light.distance : 1000; 48563 const coneWidth = coneLength * Math.tan( this.light.angle ); 48564 48565 this.cone.scale.set( coneWidth, coneWidth, coneLength ); 48566 48567 _vector$3.setFromMatrixPosition( this.light.target.matrixWorld ); 48568 48569 this.cone.lookAt( _vector$3 ); 48570 48571 if ( this.color !== undefined ) { 48572 48573 this.cone.material.color.set( this.color ); 48574 48575 } else { 48576 48577 this.cone.material.color.copy( this.light.color ); 48578 48579 } 48580 48581 } 48582 48583} 48584 48585const _vector$2 = /*@__PURE__*/ new Vector3(); 48586const _boneMatrix = /*@__PURE__*/ new Matrix4(); 48587const _matrixWorldInv = /*@__PURE__*/ new Matrix4(); 48588 48589 48590class SkeletonHelper extends LineSegments { 48591 48592 constructor( object ) { 48593 48594 const bones = getBoneList( object ); 48595 48596 const geometry = new BufferGeometry(); 48597 48598 const vertices = []; 48599 const colors = []; 48600 48601 const color1 = new Color( 0, 0, 1 ); 48602 const color2 = new Color( 0, 1, 0 ); 48603 48604 for ( let i = 0; i < bones.length; i ++ ) { 48605 48606 const bone = bones[ i ]; 48607 48608 if ( bone.parent && bone.parent.isBone ) { 48609 48610 vertices.push( 0, 0, 0 ); 48611 vertices.push( 0, 0, 0 ); 48612 colors.push( color1.r, color1.g, color1.b ); 48613 colors.push( color2.r, color2.g, color2.b ); 48614 48615 } 48616 48617 } 48618 48619 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 48620 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 48621 48622 const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } ); 48623 48624 super( geometry, material ); 48625 48626 this.isSkeletonHelper = true; 48627 48628 this.type = 'SkeletonHelper'; 48629 48630 this.root = object; 48631 this.bones = bones; 48632 48633 this.matrix = object.matrixWorld; 48634 this.matrixAutoUpdate = false; 48635 48636 } 48637 48638 updateMatrixWorld( force ) { 48639 48640 const bones = this.bones; 48641 48642 const geometry = this.geometry; 48643 const position = geometry.getAttribute( 'position' ); 48644 48645 _matrixWorldInv.copy( this.root.matrixWorld ).invert(); 48646 48647 for ( let i = 0, j = 0; i < bones.length; i ++ ) { 48648 48649 const bone = bones[ i ]; 48650 48651 if ( bone.parent && bone.parent.isBone ) { 48652 48653 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld ); 48654 _vector$2.setFromMatrixPosition( _boneMatrix ); 48655 position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z ); 48656 48657 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld ); 48658 _vector$2.setFromMatrixPosition( _boneMatrix ); 48659 position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z ); 48660 48661 j += 2; 48662 48663 } 48664 48665 } 48666 48667 geometry.getAttribute( 'position' ).needsUpdate = true; 48668 48669 super.updateMatrixWorld( force ); 48670 48671 } 48672 48673 dispose() { 48674 48675 this.geometry.dispose(); 48676 this.material.dispose(); 48677 48678 } 48679 48680} 48681 48682 48683function getBoneList( object ) { 48684 48685 const boneList = []; 48686 48687 if ( object.isBone === true ) { 48688 48689 boneList.push( object ); 48690 48691 } 48692 48693 for ( let i = 0; i < object.children.length; i ++ ) { 48694 48695 boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); 48696 48697 } 48698 48699 return boneList; 48700 48701} 48702 48703class PointLightHelper extends Mesh { 48704 48705 constructor( light, sphereSize, color ) { 48706 48707 const geometry = new SphereGeometry( sphereSize, 4, 2 ); 48708 const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); 48709 48710 super( geometry, material ); 48711 48712 this.light = light; 48713 48714 this.color = color; 48715 48716 this.type = 'PointLightHelper'; 48717 48718 this.matrix = this.light.matrixWorld; 48719 this.matrixAutoUpdate = false; 48720 48721 this.update(); 48722 48723 48724 /* 48725 // TODO: delete this comment? 48726 const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); 48727 const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); 48728 48729 this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); 48730 this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); 48731 48732 const d = light.distance; 48733 48734 if ( d === 0.0 ) { 48735 48736 this.lightDistance.visible = false; 48737 48738 } else { 48739 48740 this.lightDistance.scale.set( d, d, d ); 48741 48742 } 48743 48744 this.add( this.lightDistance ); 48745 */ 48746 48747 } 48748 48749 dispose() { 48750 48751 this.geometry.dispose(); 48752 this.material.dispose(); 48753 48754 } 48755 48756 update() { 48757 48758 this.light.updateWorldMatrix( true, false ); 48759 48760 if ( this.color !== undefined ) { 48761 48762 this.material.color.set( this.color ); 48763 48764 } else { 48765 48766 this.material.color.copy( this.light.color ); 48767 48768 } 48769 48770 /* 48771 const d = this.light.distance; 48772 48773 if ( d === 0.0 ) { 48774 48775 this.lightDistance.visible = false; 48776 48777 } else { 48778 48779 this.lightDistance.visible = true; 48780 this.lightDistance.scale.set( d, d, d ); 48781 48782 } 48783 */ 48784 48785 } 48786 48787} 48788 48789const _vector$1 = /*@__PURE__*/ new Vector3(); 48790const _color1 = /*@__PURE__*/ new Color(); 48791const _color2 = /*@__PURE__*/ new Color(); 48792 48793class HemisphereLightHelper extends Object3D { 48794 48795 constructor( light, size, color ) { 48796 48797 super(); 48798 48799 this.light = light; 48800 48801 this.matrix = light.matrixWorld; 48802 this.matrixAutoUpdate = false; 48803 48804 this.color = color; 48805 48806 this.type = 'HemisphereLightHelper'; 48807 48808 const geometry = new OctahedronGeometry( size ); 48809 geometry.rotateY( Math.PI * 0.5 ); 48810 48811 this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); 48812 if ( this.color === undefined ) this.material.vertexColors = true; 48813 48814 const position = geometry.getAttribute( 'position' ); 48815 const colors = new Float32Array( position.count * 3 ); 48816 48817 geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) ); 48818 48819 this.add( new Mesh( geometry, this.material ) ); 48820 48821 this.update(); 48822 48823 } 48824 48825 dispose() { 48826 48827 this.children[ 0 ].geometry.dispose(); 48828 this.children[ 0 ].material.dispose(); 48829 48830 } 48831 48832 update() { 48833 48834 const mesh = this.children[ 0 ]; 48835 48836 if ( this.color !== undefined ) { 48837 48838 this.material.color.set( this.color ); 48839 48840 } else { 48841 48842 const colors = mesh.geometry.getAttribute( 'color' ); 48843 48844 _color1.copy( this.light.color ); 48845 _color2.copy( this.light.groundColor ); 48846 48847 for ( let i = 0, l = colors.count; i < l; i ++ ) { 48848 48849 const color = ( i < ( l / 2 ) ) ? _color1 : _color2; 48850 48851 colors.setXYZ( i, color.r, color.g, color.b ); 48852 48853 } 48854 48855 colors.needsUpdate = true; 48856 48857 } 48858 48859 this.light.updateWorldMatrix( true, false ); 48860 48861 mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() ); 48862 48863 } 48864 48865} 48866 48867class GridHelper extends LineSegments { 48868 48869 constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) { 48870 48871 color1 = new Color( color1 ); 48872 color2 = new Color( color2 ); 48873 48874 const center = divisions / 2; 48875 const step = size / divisions; 48876 const halfSize = size / 2; 48877 48878 const vertices = [], colors = []; 48879 48880 for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) { 48881 48882 vertices.push( - halfSize, 0, k, halfSize, 0, k ); 48883 vertices.push( k, 0, - halfSize, k, 0, halfSize ); 48884 48885 const color = i === center ? color1 : color2; 48886 48887 color.toArray( colors, j ); j += 3; 48888 color.toArray( colors, j ); j += 3; 48889 color.toArray( colors, j ); j += 3; 48890 color.toArray( colors, j ); j += 3; 48891 48892 } 48893 48894 const geometry = new BufferGeometry(); 48895 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 48896 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 48897 48898 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); 48899 48900 super( geometry, material ); 48901 48902 this.type = 'GridHelper'; 48903 48904 } 48905 48906 dispose() { 48907 48908 this.geometry.dispose(); 48909 this.material.dispose(); 48910 48911 } 48912 48913} 48914 48915class PolarGridHelper extends LineSegments { 48916 48917 constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) { 48918 48919 color1 = new Color( color1 ); 48920 color2 = new Color( color2 ); 48921 48922 const vertices = []; 48923 const colors = []; 48924 48925 // create the sectors 48926 48927 if ( sectors > 1 ) { 48928 48929 for ( let i = 0; i < sectors; i ++ ) { 48930 48931 const v = ( i / sectors ) * ( Math.PI * 2 ); 48932 48933 const x = Math.sin( v ) * radius; 48934 const z = Math.cos( v ) * radius; 48935 48936 vertices.push( 0, 0, 0 ); 48937 vertices.push( x, 0, z ); 48938 48939 const color = ( i & 1 ) ? color1 : color2; 48940 48941 colors.push( color.r, color.g, color.b ); 48942 colors.push( color.r, color.g, color.b ); 48943 48944 } 48945 48946 } 48947 48948 // create the rings 48949 48950 for ( let i = 0; i < rings; i ++ ) { 48951 48952 const color = ( i & 1 ) ? color1 : color2; 48953 48954 const r = radius - ( radius / rings * i ); 48955 48956 for ( let j = 0; j < divisions; j ++ ) { 48957 48958 // first vertex 48959 48960 let v = ( j / divisions ) * ( Math.PI * 2 ); 48961 48962 let x = Math.sin( v ) * r; 48963 let z = Math.cos( v ) * r; 48964 48965 vertices.push( x, 0, z ); 48966 colors.push( color.r, color.g, color.b ); 48967 48968 // second vertex 48969 48970 v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 ); 48971 48972 x = Math.sin( v ) * r; 48973 z = Math.cos( v ) * r; 48974 48975 vertices.push( x, 0, z ); 48976 colors.push( color.r, color.g, color.b ); 48977 48978 } 48979 48980 } 48981 48982 const geometry = new BufferGeometry(); 48983 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 48984 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 48985 48986 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); 48987 48988 super( geometry, material ); 48989 48990 this.type = 'PolarGridHelper'; 48991 48992 } 48993 48994 dispose() { 48995 48996 this.geometry.dispose(); 48997 this.material.dispose(); 48998 48999 } 49000 49001} 49002 49003const _v1 = /*@__PURE__*/ new Vector3(); 49004const _v2 = /*@__PURE__*/ new Vector3(); 49005const _v3 = /*@__PURE__*/ new Vector3(); 49006 49007class DirectionalLightHelper extends Object3D { 49008 49009 constructor( light, size, color ) { 49010 49011 super(); 49012 49013 this.light = light; 49014 49015 this.matrix = light.matrixWorld; 49016 this.matrixAutoUpdate = false; 49017 49018 this.color = color; 49019 49020 this.type = 'DirectionalLightHelper'; 49021 49022 if ( size === undefined ) size = 1; 49023 49024 let geometry = new BufferGeometry(); 49025 geometry.setAttribute( 'position', new Float32BufferAttribute( [ 49026 - size, size, 0, 49027 size, size, 0, 49028 size, - size, 0, 49029 - size, - size, 0, 49030 - size, size, 0 49031 ], 3 ) ); 49032 49033 const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); 49034 49035 this.lightPlane = new Line( geometry, material ); 49036 this.add( this.lightPlane ); 49037 49038 geometry = new BufferGeometry(); 49039 geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); 49040 49041 this.targetLine = new Line( geometry, material ); 49042 this.add( this.targetLine ); 49043 49044 this.update(); 49045 49046 } 49047 49048 dispose() { 49049 49050 this.lightPlane.geometry.dispose(); 49051 this.lightPlane.material.dispose(); 49052 this.targetLine.geometry.dispose(); 49053 this.targetLine.material.dispose(); 49054 49055 } 49056 49057 update() { 49058 49059 this.light.updateWorldMatrix( true, false ); 49060 this.light.target.updateWorldMatrix( true, false ); 49061 49062 _v1.setFromMatrixPosition( this.light.matrixWorld ); 49063 _v2.setFromMatrixPosition( this.light.target.matrixWorld ); 49064 _v3.subVectors( _v2, _v1 ); 49065 49066 this.lightPlane.lookAt( _v2 ); 49067 49068 if ( this.color !== undefined ) { 49069 49070 this.lightPlane.material.color.set( this.color ); 49071 this.targetLine.material.color.set( this.color ); 49072 49073 } else { 49074 49075 this.lightPlane.material.color.copy( this.light.color ); 49076 this.targetLine.material.color.copy( this.light.color ); 49077 49078 } 49079 49080 this.targetLine.lookAt( _v2 ); 49081 this.targetLine.scale.z = _v3.length(); 49082 49083 } 49084 49085} 49086 49087const _vector = /*@__PURE__*/ new Vector3(); 49088const _camera = /*@__PURE__*/ new Camera(); 49089 49090/** 49091 * - shows frustum, line of sight and up of the camera 49092 * - suitable for fast updates 49093 * - based on frustum visualization in lightgl.js shadowmap example 49094 * https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html 49095 */ 49096 49097class CameraHelper extends LineSegments { 49098 49099 constructor( camera ) { 49100 49101 const geometry = new BufferGeometry(); 49102 const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } ); 49103 49104 const vertices = []; 49105 const colors = []; 49106 49107 const pointMap = {}; 49108 49109 // near 49110 49111 addLine( 'n1', 'n2' ); 49112 addLine( 'n2', 'n4' ); 49113 addLine( 'n4', 'n3' ); 49114 addLine( 'n3', 'n1' ); 49115 49116 // far 49117 49118 addLine( 'f1', 'f2' ); 49119 addLine( 'f2', 'f4' ); 49120 addLine( 'f4', 'f3' ); 49121 addLine( 'f3', 'f1' ); 49122 49123 // sides 49124 49125 addLine( 'n1', 'f1' ); 49126 addLine( 'n2', 'f2' ); 49127 addLine( 'n3', 'f3' ); 49128 addLine( 'n4', 'f4' ); 49129 49130 // cone 49131 49132 addLine( 'p', 'n1' ); 49133 addLine( 'p', 'n2' ); 49134 addLine( 'p', 'n3' ); 49135 addLine( 'p', 'n4' ); 49136 49137 // up 49138 49139 addLine( 'u1', 'u2' ); 49140 addLine( 'u2', 'u3' ); 49141 addLine( 'u3', 'u1' ); 49142 49143 // target 49144 49145 addLine( 'c', 't' ); 49146 addLine( 'p', 'c' ); 49147 49148 // cross 49149 49150 addLine( 'cn1', 'cn2' ); 49151 addLine( 'cn3', 'cn4' ); 49152 49153 addLine( 'cf1', 'cf2' ); 49154 addLine( 'cf3', 'cf4' ); 49155 49156 function addLine( a, b ) { 49157 49158 addPoint( a ); 49159 addPoint( b ); 49160 49161 } 49162 49163 function addPoint( id ) { 49164 49165 vertices.push( 0, 0, 0 ); 49166 colors.push( 0, 0, 0 ); 49167 49168 if ( pointMap[ id ] === undefined ) { 49169 49170 pointMap[ id ] = []; 49171 49172 } 49173 49174 pointMap[ id ].push( ( vertices.length / 3 ) - 1 ); 49175 49176 } 49177 49178 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 49179 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 49180 49181 super( geometry, material ); 49182 49183 this.type = 'CameraHelper'; 49184 49185 this.camera = camera; 49186 if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix(); 49187 49188 this.matrix = camera.matrixWorld; 49189 this.matrixAutoUpdate = false;
49190 49191 this.pointMap = pointMap; 49192 49193 this.update(); 49194 49195 // colors 49196 49197 const colorFrustum = new Color( 0xffaa00 ); 49198 const colorCone = new Color( 0xff0000 ); 49199 const colorUp = new Color( 0x00aaff ); 49200 const colorTarget = new Color( 0xffffff ); 49201 const colorCross = new Color( 0x333333 ); 49202 49203 this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross ); 49204 49205 } 49206 49207 setColors( frustum, cone, up, target, cross ) { 49208 49209 const geometry = this.geometry; 49210 49211 const colorAttribute = geometry.getAttribute( 'color' ); 49212 49213 // near 49214 49215 colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2 49216 colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4 49217 colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3 49218 colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1 49219 49220 // far 49221 49222 colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2 49223 colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4 49224 colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3 49225 colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1 49226 49227 // sides 49228 49229 colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1 49230 colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2 49231 colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3 49232 colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4 49233 49234 // cone 49235 49236 colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1 49237 colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2 49238 colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3 49239 colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4 49240 49241 // up 49242 49243 colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2 49244 colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3 49245 colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1 49246 49247 // target 49248 49249 colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t 49250 colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c 49251 49252 // cross 49253 49254 colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2 49255 colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4 49256 49257 colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2 49258 colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4 49259 49260 colorAttribute.needsUpdate = true; 49261 49262 } 49263 49264 update() { 49265 49266 const geometry = this.geometry; 49267 const pointMap = this.pointMap; 49268 49269 const w = 1, h = 1; 49270 49271 // we need just camera projection matrix inverse 49272 // world matrix must be identity 49273 49274 _camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse ); 49275 49276 // center / target 49277 49278 setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 ); 49279 setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 ); 49280 49281 // near 49282 49283 setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 ); 49284 setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 ); 49285 setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 ); 49286 setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 ); 49287 49288 // far 49289 49290 setPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 ); 49291 setPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 ); 49292 setPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 ); 49293 setPoint( 'f4', pointMap, geometry, _camera, w, h, 1 ); 49294 49295 // up 49296 49297 setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 ); 49298 setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 ); 49299 setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 ); 49300 49301 // cross 49302 49303 setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 ); 49304 setPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 ); 49305 setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 ); 49306 setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 ); 49307 49308 setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 ); 49309 setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 ); 49310 setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 ); 49311 setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 ); 49312 49313 geometry.getAttribute( 'position' ).needsUpdate = true; 49314 49315 } 49316 49317 dispose() { 49318 49319 this.geometry.dispose(); 49320 this.material.dispose(); 49321 49322 } 49323 49324} 49325 49326 49327function setPoint( point, pointMap, geometry, camera, x, y, z ) { 49328 49329 _vector.set( x, y, z ).unproject( camera ); 49330 49331 const points = pointMap[ point ]; 49332 49333 if ( points !== undefined ) { 49334 49335 const position = geometry.getAttribute( 'position' ); 49336 49337 for ( let i = 0, l = points.length; i < l; i ++ ) { 49338 49339 position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z ); 49340 49341 } 49342 49343 } 49344 49345} 49346 49347const _box = /*@__PURE__*/ new Box3(); 49348 49349class BoxHelper extends LineSegments { 49350 49351 constructor( object, color = 0xffff00 ) { 49352 49353 const 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 ] ); 49354 const positions = new Float32Array( 8 * 3 ); 49355 49356 const geometry = new BufferGeometry(); 49357 geometry.setIndex( new BufferAttribute( indices, 1 ) ); 49358 geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) ); 49359 49360 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 49361 49362 this.object = object; 49363 this.type = 'BoxHelper'; 49364 49365 this.matrixAutoUpdate = false;
vendor: 4,705 bytes, lines 49366-49582
49366 49367 this.update(); 49368 49369 } 49370 49371 update( object ) { 49372 49373 if ( object !== undefined ) { 49374 49375 console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' ); 49376 49377 } 49378 49379 if ( this.object !== undefined ) { 49380 49381 _box.setFromObject( this.object ); 49382 49383 } 49384 49385 if ( _box.isEmpty() ) return; 49386 49387 const min = _box.min; 49388 const max = _box.max; 49389 49390 /* 49391 5____4 49392 1/___0/| 49393 | 6__|_7 49394 2/___3/ 49395 49396 0: max.x, max.y, max.z 49397 1: min.x, max.y, max.z 49398 2: min.x, min.y, max.z 49399 3: max.x, min.y, max.z 49400 4: max.x, max.y, min.z 49401 5: min.x, max.y, min.z 49402 6: min.x, min.y, min.z 49403 7: max.x, min.y, min.z 49404 */ 49405 49406 const position = this.geometry.attributes.position; 49407 const array = position.array; 49408 49409 array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z; 49410 array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z; 49411 array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z; 49412 array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z; 49413 array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z; 49414 array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z; 49415 array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z; 49416 array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z; 49417 49418 position.needsUpdate = true; 49419 49420 this.geometry.computeBoundingSphere(); 49421 49422 } 49423 49424 setFromObject( object ) { 49425 49426 this.object = object; 49427 this.update(); 49428 49429 return this; 49430 49431 } 49432 49433 copy( source, recursive ) { 49434 49435 super.copy( source, recursive ); 49436 49437 this.object = source.object; 49438 49439 return this; 49440 49441 } 49442 49443 dispose() { 49444 49445 this.geometry.dispose(); 49446 this.material.dispose(); 49447 49448 } 49449 49450} 49451 49452class Box3Helper extends LineSegments { 49453 49454 constructor( box, color = 0xffff00 ) { 49455 49456 const 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 ] ); 49457 49458 const positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ]; 49459 49460 const geometry = new BufferGeometry(); 49461 49462 geometry.setIndex( new BufferAttribute( indices, 1 ) ); 49463 49464 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 49465 49466 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 49467 49468 this.box = box; 49469 49470 this.type = 'Box3Helper'; 49471 49472 this.geometry.computeBoundingSphere(); 49473 49474 } 49475 49476 updateMatrixWorld( force ) { 49477 49478 const box = this.box; 49479 49480 if ( box.isEmpty() ) return; 49481 49482 box.getCenter( this.position ); 49483 49484 box.getSize( this.scale ); 49485 49486 this.scale.multiplyScalar( 0.5 ); 49487 49488 super.updateMatrixWorld( force ); 49489 49490 } 49491 49492 dispose() { 49493 49494 this.geometry.dispose(); 49495 this.material.dispose(); 49496 49497 } 49498 49499} 49500 49501class PlaneHelper extends Line { 49502 49503 constructor( plane, size = 1, hex = 0xffff00 ) { 49504 49505 const color = hex; 49506 49507 const positions = [ 1, - 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, - 1, 0, 1, 1, 0 ]; 49508 49509 const geometry = new BufferGeometry(); 49510 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 49511 geometry.computeBoundingSphere(); 49512 49513 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 49514 49515 this.type = 'PlaneHelper'; 49516 49517 this.plane = plane; 49518 49519 this.size = size; 49520 49521 const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ]; 49522 49523 const geometry2 = new BufferGeometry(); 49524 geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); 49525 geometry2.computeBoundingSphere(); 49526 49527 this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) ); 49528 49529 } 49530 49531 updateMatrixWorld( force ) { 49532 49533 this.position.set( 0, 0, 0 ); 49534 49535 this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 ); 49536 49537 this.lookAt( this.plane.normal ); 49538 49539 this.translateZ( - this.plane.constant ); 49540 49541 super.updateMatrixWorld( force ); 49542 49543 } 49544 49545 dispose() { 49546 49547 this.geometry.dispose(); 49548 this.material.dispose(); 49549 this.children[ 0 ].geometry.dispose(); 49550 this.children[ 0 ].material.dispose(); 49551 49552 } 49553 49554} 49555 49556const _axis = /*@__PURE__*/ new Vector3(); 49557let _lineGeometry, _coneGeometry; 49558 49559class ArrowHelper extends Object3D { 49560 49561 // dir is assumed to be normalized 49562 49563 constructor( dir = new Vector3( 0, 0, 1 ), origin = new Vector3( 0, 0, 0 ), length = 1, color = 0xffff00, headLength = length * 0.2, headWidth = headLength * 0.2 ) { 49564 49565 super(); 49566 49567 this.type = 'ArrowHelper'; 49568 49569 if ( _lineGeometry === undefined ) { 49570 49571 _lineGeometry = new BufferGeometry(); 49572 _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); 49573 49574 _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 ); 49575 _coneGeometry.translate( 0, - 0.5, 0 ); 49576 49577 } 49578 49579 this.position.copy( origin ); 49580 49581 this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 49582 this.line.matrixAutoUpdate = false;
vendor: 3,957 bytes, lines 49583-49802
49583 this.add( this.line ); 49584 49585 this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) ); 49586 this.cone.matrixAutoUpdate = false; 49587 this.add( this.cone ); 49588 49589 this.setDirection( dir ); 49590 this.setLength( length, headLength, headWidth ); 49591 49592 } 49593 49594 setDirection( dir ) { 49595 49596 // dir is assumed to be normalized 49597 49598 if ( dir.y > 0.99999 ) { 49599 49600 this.quaternion.set( 0, 0, 0, 1 ); 49601 49602 } else if ( dir.y < - 0.99999 ) { 49603 49604 this.quaternion.set( 1, 0, 0, 0 ); 49605 49606 } else { 49607 49608 _axis.set( dir.z, 0, - dir.x ).normalize(); 49609 49610 const radians = Math.acos( dir.y ); 49611 49612 this.quaternion.setFromAxisAngle( _axis, radians ); 49613 49614 } 49615 49616 } 49617 49618 setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) { 49619 49620 this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458 49621 this.line.updateMatrix(); 49622 49623 this.cone.scale.set( headWidth, headLength, headWidth ); 49624 this.cone.position.y = length; 49625 this.cone.updateMatrix(); 49626 49627 } 49628 49629 setColor( color ) { 49630 49631 this.line.material.color.set( color ); 49632 this.cone.material.color.set( color ); 49633 49634 } 49635 49636 copy( source ) { 49637 49638 super.copy( source, false ); 49639 49640 this.line.copy( source.line ); 49641 this.cone.copy( source.cone ); 49642 49643 return this; 49644 49645 } 49646 49647 dispose() { 49648 49649 this.line.geometry.dispose(); 49650 this.line.material.dispose(); 49651 this.cone.geometry.dispose(); 49652 this.cone.material.dispose(); 49653 49654 } 49655 49656} 49657 49658class AxesHelper extends LineSegments { 49659 49660 constructor( size = 1 ) { 49661 49662 const vertices = [ 49663 0, 0, 0, size, 0, 0, 49664 0, 0, 0, 0, size, 0, 49665 0, 0, 0, 0, 0, size 49666 ]; 49667 49668 const colors = [ 49669 1, 0, 0, 1, 0.6, 0, 49670 0, 1, 0, 0.6, 1, 0, 49671 0, 0, 1, 0, 0.6, 1 49672 ]; 49673 49674 const geometry = new BufferGeometry(); 49675 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 49676 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 49677 49678 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); 49679 49680 super( geometry, material ); 49681 49682 this.type = 'AxesHelper'; 49683 49684 } 49685 49686 setColors( xAxisColor, yAxisColor, zAxisColor ) { 49687 49688 const color = new Color(); 49689 const array = this.geometry.attributes.color.array; 49690 49691 color.set( xAxisColor ); 49692 color.toArray( array, 0 ); 49693 color.toArray( array, 3 ); 49694 49695 color.set( yAxisColor ); 49696 color.toArray( array, 6 ); 49697 color.toArray( array, 9 ); 49698 49699 color.set( zAxisColor ); 49700 color.toArray( array, 12 ); 49701 color.toArray( array, 15 ); 49702 49703 this.geometry.attributes.color.needsUpdate = true; 49704 49705 return this; 49706 49707 } 49708 49709 dispose() { 49710 49711 this.geometry.dispose(); 49712 this.material.dispose(); 49713 49714 } 49715 49716} 49717 49718class ShapePath { 49719 49720 constructor() { 49721 49722 this.type = 'ShapePath'; 49723 49724 this.color = new Color(); 49725 49726 this.subPaths = []; 49727 this.currentPath = null; 49728 49729 } 49730 49731 moveTo( x, y ) { 49732 49733 this.currentPath = new Path(); 49734 this.subPaths.push( this.currentPath ); 49735 this.currentPath.moveTo( x, y ); 49736 49737 return this; 49738 49739 } 49740 49741 lineTo( x, y ) { 49742 49743 this.currentPath.lineTo( x, y ); 49744 49745 return this; 49746 49747 } 49748 49749 quadraticCurveTo( aCPx, aCPy, aX, aY ) { 49750 49751 this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY ); 49752 49753 return this; 49754 49755 } 49756 49757 bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { 49758 49759 this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ); 49760 49761 return this; 49762 49763 } 49764 49765 splineThru( pts ) { 49766 49767 this.currentPath.splineThru( pts ); 49768 49769 return this; 49770 49771 } 49772 49773 toShapes( isCCW ) { 49774 49775 function toShapesNoHoles( inSubpaths ) { 49776 49777 const shapes = []; 49778 49779 for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) { 49780 49781 const tmpPath = inSubpaths[ i ]; 49782 49783 const tmpShape = new Shape(); 49784 tmpShape.curves = tmpPath.curves; 49785 49786 shapes.push( tmpShape ); 49787 49788 } 49789 49790 return shapes; 49791 49792 } 49793 49794 function isPointInsidePolygon( inPt, inPolygon ) { 49795 49796 const polyLen = inPolygon.length; 49797 49798 // inPt on polygon contour => immediate success or 49799 // toggling of inside/outside at every single! intersection point of an edge 49800 // with the horizontal line through inPt, left of inPt 49801 // not counting lowerY endpoints of edges and whole edges on that line 49802 let inside = false;
49803 for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { 49804 49805 let edgeLowPt = inPolygon[ p ]; 49806 let edgeHighPt = inPolygon[ q ]; 49807 49808 let edgeDx = edgeHighPt.x - edgeLowPt.x; 49809 let edgeDy = edgeHighPt.y - edgeLowPt.y; 49810 49811 if ( Math.abs( edgeDy ) > Number.EPSILON ) { 49812 49813 // not parallel 49814 if ( edgeDy < 0 ) { 49815 49816 edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx; 49817 edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy; 49818 49819 } 49820 49821 if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue; 49822 49823 if ( inPt.y === edgeLowPt.y ) { 49824 49825 if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ? 49826 // continue; // no intersection or edgeLowPt => doesn't count !!! 49827 49828 } else { 49829 49830 const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y ); 49831 if ( perpEdge === 0 ) return true; // inPt is on contour ? 49832 if ( perpEdge < 0 ) continue; 49833 inside = ! inside; // true intersection left of inPt 49834 49835 } 49836 49837 } else { 49838 49839 // parallel or collinear 49840 if ( inPt.y !== edgeLowPt.y ) continue; // parallel 49841 // edge lies on the same horizontal line as inPt 49842 if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || 49843 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour ! 49844 // continue; 49845 49846 } 49847 49848 } 49849 49850 return inside; 49851 49852 } 49853 49854 const isClockWise = ShapeUtils.isClockWise; 49855 49856 const subPaths = this.subPaths; 49857 if ( subPaths.length === 0 ) return []; 49858 49859 let solid, tmpPath, tmpShape; 49860 const shapes = []; 49861 49862 if ( subPaths.length === 1 ) { 49863 49864 tmpPath = subPaths[ 0 ]; 49865 tmpShape = new Shape(); 49866 tmpShape.curves = tmpPath.curves; 49867 shapes.push( tmpShape ); 49868 return shapes; 49869 49870 } 49871 49872 let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); 49873 holesFirst = isCCW ? ! holesFirst : holesFirst; 49874 49875 // console.log("Holes first", holesFirst); 49876 49877 const betterShapeHoles = []; 49878 const newShapes = []; 49879 let newShapeHoles = []; 49880 let mainIdx = 0; 49881 let tmpPoints; 49882 49883 newShapes[ mainIdx ] = undefined; 49884 newShapeHoles[ mainIdx ] = []; 49885 49886 for ( let i = 0, l = subPaths.length; i < l; i ++ ) { 49887 49888 tmpPath = subPaths[ i ]; 49889 tmpPoints = tmpPath.getPoints(); 49890 solid = isClockWise( tmpPoints ); 49891 solid = isCCW ? ! solid : solid; 49892 49893 if ( solid ) { 49894 49895 if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++; 49896 49897 newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints }; 49898 newShapes[ mainIdx ].s.curves = tmpPath.curves; 49899 49900 if ( holesFirst ) mainIdx ++; 49901 newShapeHoles[ mainIdx ] = []; 49902 49903 //console.log('cw', i); 49904 49905 } else { 49906 49907 newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); 49908 49909 //console.log('ccw', i); 49910 49911 } 49912 49913 } 49914 49915 // only Holes? -> probably all Shapes with wrong orientation 49916 if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths ); 49917 49918 49919 if ( newShapes.length > 1 ) { 49920 49921 let ambiguous = false; 49922 let toChange = 0; 49923 49924 for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { 49925 49926 betterShapeHoles[ sIdx ] = []; 49927 49928 } 49929 49930 for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { 49931 49932 const sho = newShapeHoles[ sIdx ]; 49933 49934 for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) { 49935 49936 const ho = sho[ hIdx ]; 49937 let hole_unassigned = true; 49938 49939 for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) { 49940 49941 if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) { 49942 49943 if ( sIdx !== s2Idx ) toChange ++; 49944 49945 if ( hole_unassigned ) { 49946 49947 hole_unassigned = false; 49948 betterShapeHoles[ s2Idx ].push( ho ); 49949 49950 } else { 49951 49952 ambiguous = true; 49953 49954 } 49955 49956 } 49957 49958 } 49959 49960 if ( hole_unassigned ) { 49961 49962 betterShapeHoles[ sIdx ].push( ho ); 49963 49964 } 49965 49966 } 49967 49968 } 49969 49970 if ( toChange > 0 && ambiguous === false ) { 49971 49972 newShapeHoles = betterShapeHoles; 49973 49974 } 49975 49976 } 49977 49978 let tmpHoles; 49979 49980 for ( let i = 0, il = newShapes.length; i < il; i ++ ) { 49981 49982 tmpShape = newShapes[ i ].s; 49983 shapes.push( tmpShape ); 49984 tmpHoles = newShapeHoles[ i ]; 49985 49986 for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) { 49987 49988 tmpShape.holes.push( tmpHoles[ j ].h ); 49989 49990 } 49991 49992 } 49993 49994 //console.log("shape", shapes); 49995 49996 return shapes; 49997 49998 } 49999 50000} 50001 50002// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf 50003 50004const _tables = /*@__PURE__*/ _generateTables(); 50005 50006function _generateTables() { 50007 50008 // float32 to float16 helpers 50009 50010 const buffer = new ArrayBuffer( 4 ); 50011 const floatView = new Float32Array( buffer ); 50012 const uint32View = new Uint32Array( buffer ); 50013 50014 const baseTable = new Uint32Array( 512 ); 50015 const shiftTable = new Uint32Array( 512 ); 50016 50017 for ( let i = 0; i < 256; ++ i ) { 50018 50019 const e = i - 127; 50020 50021 // very small number (0, -0) 50022 50023 if ( e < - 27 ) { 50024 50025 baseTable[ i ] = 0x0000; 50026 baseTable[ i | 0x100 ] = 0x8000; 50027 shiftTable[ i ] = 24; 50028 shiftTable[ i | 0x100 ] = 24; 50029 50030 // small number (denorm) 50031 50032 } else if ( e < - 14 ) { 50033 50034 baseTable[ i ] = 0x0400 >> ( - e - 14 ); 50035 baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000; 50036 shiftTable[ i ] = - e - 1; 50037 shiftTable[ i | 0x100 ] = - e - 1; 50038 50039 // normal number 50040 50041 } else if ( e <= 15 ) { 50042 50043 baseTable[ i ] = ( e + 15 ) << 10; 50044 baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000; 50045 shiftTable[ i ] = 13; 50046 shiftTable[ i | 0x100 ] = 13; 50047 50048 // large number (Infinity, -Infinity) 50049 50050 } else if ( e < 128 ) { 50051 50052 baseTable[ i ] = 0x7c00; 50053 baseTable[ i | 0x100 ] = 0xfc00; 50054 shiftTable[ i ] = 24; 50055 shiftTable[ i | 0x100 ] = 24; 50056 50057 // stay (NaN, Infinity, -Infinity) 50058 50059 } else { 50060 50061 baseTable[ i ] = 0x7c00; 50062 baseTable[ i | 0x100 ] = 0xfc00; 50063 shiftTable[ i ] = 13; 50064 shiftTable[ i | 0x100 ] = 13; 50065 50066 } 50067 50068 } 50069 50070 // float16 to float32 helpers 50071 50072 const mantissaTable = new Uint32Array( 2048 ); 50073 const exponentTable = new Uint32Array( 64 ); 50074 const offsetTable = new Uint32Array( 64 ); 50075 50076 for ( let i = 1; i < 1024; ++ i ) { 50077 50078 let m = i << 13; // zero pad mantissa bits 50079 let e = 0; // zero exponent 50080 50081 // normalized 50082 while ( ( m & 0x00800000 ) === 0 ) { 50083 50084 m <<= 1; 50085 e -= 0x00800000; // decrement exponent 50086 50087 } 50088 50089 m &= ~ 0x00800000; // clear leading 1 bit 50090 e += 0x38800000; // adjust bias 50091 50092 mantissaTable[ i ] = m | e; 50093 50094 } 50095 50096 for ( let i = 1024; i < 2048; ++ i ) { 50097 50098 mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 ); 50099 50100 } 50101 50102 for ( let i = 1; i < 31; ++ i ) { 50103 50104 exponentTable[ i ] = i << 23; 50105 50106 } 50107 50108 exponentTable[ 31 ] = 0x47800000; 50109 exponentTable[ 32 ] = 0x80000000; 50110 50111 for ( let i = 33; i < 63; ++ i ) { 50112 50113 exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 ); 50114 50115 } 50116 50117 exponentTable[ 63 ] = 0xc7800000; 50118 50119 for ( let i = 1; i < 64; ++ i ) { 50120 50121 if ( i !== 32 ) { 50122 50123 offsetTable[ i ] = 1024; 50124 50125 } 50126 50127 } 50128 50129 return { 50130 floatView: floatView, 50131 uint32View: uint32View, 50132 baseTable: baseTable, 50133 shiftTable: shiftTable, 50134 mantissaTable: mantissaTable, 50135 exponentTable: exponentTable, 50136 offsetTable: offsetTable 50137 }; 50138 50139} 50140 50141// float32 to float16 50142 50143function toHalfFloat( val ) { 50144 50145 if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' ); 50146 50147 val = clamp( val, - 65504, 65504 ); 50148 50149 _tables.floatView[ 0 ] = val; 50150 const f = _tables.uint32View[ 0 ]; 50151 const e = ( f >> 23 ) & 0x1ff; 50152 return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] ); 50153 50154} 50155 50156// float16 to float32 50157 50158function fromHalfFloat( val ) { 50159 50160 const m = val >> 10; 50161 _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ]; 50162 return _tables.floatView[ 0 ]; 50163 50164} 50165 50166const DataUtils = { 50167 toHalfFloat: toHalfFloat, 50168 fromHalfFloat: fromHalfFloat, 50169}; 50170 50171// r144 50172 50173class BoxBufferGeometry extends BoxGeometry { 50174 50175 constructor( width, height, depth, widthSegments, heightSegments, depthSegments ) { 50176 50177 console.warn( 'THREE.BoxBufferGeometry has been renamed to THREE.BoxGeometry.' ); 50178 super( width, height, depth, widthSegments, heightSegments, depthSegments ); 50179 50180 50181 } 50182 50183} 50184 50185// r144 50186 50187class CapsuleBufferGeometry extends CapsuleGeometry { 50188
50189 constructor( radius, length, capSegments, radialSegments ) { 50190 50191 console.warn( 'THREE.CapsuleBufferGeometry has been renamed to THREE.CapsuleGeometry.' ); 50192 super( radius, length, capSegments, radialSegments ); 50193 50194 } 50195 50196} 50197 50198// r144 50199 50200class CircleBufferGeometry extends CircleGeometry { 50201 50202 constructor( radius, segments, thetaStart, thetaLength ) { 50203 50204 console.warn( 'THREE.CircleBufferGeometry has been renamed to THREE.CircleGeometry.' ); 50205 super( radius, segments, thetaStart, thetaLength ); 50206 50207 } 50208 50209} 50210 50211// r144 50212 50213class ConeBufferGeometry extends ConeGeometry { 50214 50215 constructor( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { 50216 50217 console.warn( 'THREE.ConeBufferGeometry has been renamed to THREE.ConeGeometry.' ); 50218 super( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); 50219 50220 } 50221 50222} 50223 50224// r144 50225 50226class CylinderBufferGeometry extends CylinderGeometry { 50227 50228 constructor( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { 50229 50230 console.warn( 'THREE.CylinderBufferGeometry has been renamed to THREE.CylinderGeometry.' ); 50231 super( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); 50232 50233 } 50234 50235} 50236 50237// r144 50238 50239class DodecahedronBufferGeometry extends DodecahedronGeometry { 50240 50241 constructor( radius, detail ) { 50242 50243 console.warn( 'THREE.DodecahedronBufferGeometry has been renamed to THREE.DodecahedronGeometry.' ); 50244 super( radius, detail ); 50245 50246 } 50247 50248} 50249 50250// r144 50251 50252class ExtrudeBufferGeometry extends ExtrudeGeometry { 50253 50254 constructor( shapes, options ) { 50255 50256 console.warn( 'THREE.ExtrudeBufferGeometry has been renamed to THREE.ExtrudeGeometry.' ); 50257 super( shapes, options ); 50258 50259 } 50260 50261} 50262 50263// r144 50264 50265class IcosahedronBufferGeometry extends IcosahedronGeometry { 50266 50267 constructor( radius, detail ) { 50268 50269 console.warn( 'THREE.IcosahedronBufferGeometry has been renamed to THREE.IcosahedronGeometry.' ); 50270 super( radius, detail ); 50271 50272 } 50273 50274} 50275 50276// r144 50277 50278class LatheBufferGeometry extends LatheGeometry { 50279 50280 constructor( points, segments, phiStart, phiLength ) { 50281 50282 console.warn( 'THREE.LatheBufferGeometry has been renamed to THREE.LatheGeometry.' ); 50283 super( points, segments, phiStart, phiLength ); 50284 50285 } 50286 50287} 50288 50289// r144 50290 50291class OctahedronBufferGeometry extends OctahedronGeometry { 50292 50293 constructor( radius, detail ) { 50294 50295 console.warn( 'THREE.OctahedronBufferGeometry has been renamed to THREE.OctahedronGeometry.' ); 50296 super( radius, detail ); 50297 50298 } 50299 50300} 50301 50302// r144 50303 50304class PlaneBufferGeometry extends PlaneGeometry { 50305 50306 constructor( width, height, widthSegments, heightSegments ) { 50307 50308 console.warn( 'THREE.PlaneBufferGeometry has been renamed to THREE.PlaneGeometry.' ); 50309 super( width, height, widthSegments, heightSegments ); 50310 50311 } 50312 50313} 50314 50315// r144 50316 50317class PolyhedronBufferGeometry extends PolyhedronGeometry { 50318 50319 constructor( vertices, indices, radius, detail ) { 50320 50321 console.warn( 'THREE.PolyhedronBufferGeometry has been renamed to THREE.PolyhedronGeometry.' ); 50322 super( vertices, indices, radius, detail ); 50323 50324 } 50325 50326} 50327 50328// r144 50329 50330class RingBufferGeometry extends RingGeometry { 50331 50332 constructor( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { 50333 50334 console.warn( 'THREE.RingBufferGeometry has been renamed to THREE.RingGeometry.' ); 50335 super( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ); 50336 50337 } 50338 50339} 50340 50341// r144 50342 50343class ShapeBufferGeometry extends ShapeGeometry { 50344 50345 constructor( shapes, curveSegments ) { 50346 50347 console.warn( 'THREE.ShapeBufferGeometry has been renamed to THREE.ShapeGeometry.' ); 50348 super( shapes, curveSegments ); 50349 50350 } 50351 50352} 50353 50354// r144 50355 50356class SphereBufferGeometry extends SphereGeometry { 50357 50358 constructor( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { 50359 50360 console.warn( 'THREE.SphereBufferGeometry has been renamed to THREE.SphereGeometry.' ); 50361 super( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ); 50362 50363 } 50364 50365} 50366 50367// r144 50368 50369class TetrahedronBufferGeometry extends TetrahedronGeometry { 50370 50371 constructor( radius, detail ) { 50372 50373 console.warn( 'THREE.TetrahedronBufferGeometry has been renamed to THREE.TetrahedronGeometry.' ); 50374 super( radius, detail ); 50375 50376 } 50377 50378} 50379 50380// r144 50381 50382class TorusBufferGeometry extends TorusGeometry { 50383
50384 constructor( radius, tube, radialSegments, tubularSegments, arc ) { 50385 50386 console.warn( 'THREE.TorusBufferGeometry has been renamed to THREE.TorusGeometry.' ); 50387 super( radius, tube, radialSegments, tubularSegments, arc ); 50388 50389 } 50390 50391} 50392 50393// r144 50394 50395class TorusKnotBufferGeometry extends TorusKnotGeometry { 50396 50397 constructor( radius, tube, tubularSegments, radialSegments, p, q ) { 50398 50399 console.warn( 'THREE.TorusKnotBufferGeometry has been renamed to THREE.TorusKnotGeometry.' ); 50400 super( radius, tube, tubularSegments, radialSegments, p, q ); 50401 50402 } 50403 50404} 50405 50406// r144 50407 50408class TubeBufferGeometry extends TubeGeometry { 50409 50410 constructor( path, tubularSegments, radius, radialSegments, closed ) { 50411 50412 console.warn( 'THREE.TubeBufferGeometry has been renamed to THREE.TubeGeometry.' ); 50413 super( path, tubularSegments, radius, radialSegments, closed ); 50414 50415 } 50416 50417} 50418 50419if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { 50420 50421 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: { 50422 revision: REVISION, 50423 } } ) ); 50424 50425} 50426 50427if ( typeof window !== 'undefined' ) { 50428 50429 if ( window.__THREE__ ) { 50430 50431 console.warn( 'WARNING: Multiple instances of Three.js being imported.' ); 50432 50433 } else { 50434 50435 window.__THREE__ = REVISION; 50436 50437 } 50438 50439} 50440 50441export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AlphaFormat, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightProbe, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BackSide, BasicDepthPacking, BasicShadowMap, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxBufferGeometry, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasTexture, CapsuleBufferGeometry, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleBufferGeometry, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, ColorManagement, CompressedArrayTexture, CompressedTexture, CompressedTextureLoader, ConeBufferGeometry, ConeGeometry, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderBufferGeometry, CylinderGeometry, Cylindrical, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DisplayP3ColorSpace, DodecahedronBufferGeometry, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeBufferGeometry, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, Float64BufferAttribute, FloatType, Fog, FogExp2, FramebufferTexture, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GreaterDepth, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightProbe, IcosahedronBufferGeometry, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheBufferGeometry, LatheGeometry, Layers, LessDepth, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearEncoding, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, MOUSE, Material, MaterialLoader, MathUtils, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronBufferGeometry, OctahedronGeometry, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, Orthogra
50441phicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, Path, PerspectiveCamera, Plane, PlaneBufferGeometry, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronBufferGeometry, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingBufferGeometry, RingGeometry, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, Scene, ShaderChunk, ShaderLib, ShaderMaterial, ShadowMaterial, Shape, ShapeBufferGeometry, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereBufferGeometry, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronBufferGeometry, TetrahedronGeometry, Texture, TextureLoader, TorusBufferGeometry, TorusGeometry, TorusKnotBufferGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeBufferGeometry, TubeGeometry, TwoPassDoubleSide, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoTexture, WebGL1Renderer, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLRenderTarget, WebGLRenderer, WebGLUtils, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, _SRGBAFormat, sRGBEncoding };
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.