1/** 2 * @license 3 * Copyright 2010-2023 Three.js Authors 4 * SPDX-License-Identifier: MIT 5 */ 6const REVISION = '163'; 7 8const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; 9const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; 10const CullFaceNone = 0; 11const CullFaceBack = 1; 12const CullFaceFront = 2; 13const CullFaceFrontBack = 3; 14const BasicShadowMap = 0; 15const PCFShadowMap = 1; 16const PCFSoftShadowMap = 2; 17const VSMShadowMap = 3; 18const FrontSide = 0; 19const BackSide = 1; 20const DoubleSide = 2; 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 ConstantColorFactor = 211; 44const OneMinusConstantColorFactor = 212; 45const ConstantAlphaFactor = 213; 46const OneMinusConstantAlphaFactor = 214; 47const NeverDepth = 0; 48const AlwaysDepth = 1; 49const LessDepth = 2; 50const LessEqualDepth = 3; 51const EqualDepth = 4; 52const GreaterEqualDepth = 5; 53const GreaterDepth = 6; 54const NotEqualDepth = 7; 55const MultiplyOperation = 0; 56const MixOperation = 1; 57const AddOperation = 2; 58const NoToneMapping = 0; 59const LinearToneMapping = 1; 60const ReinhardToneMapping = 2; 61const CineonToneMapping = 3; 62const ACESFilmicToneMapping = 4; 63const CustomToneMapping = 5; 64const AgXToneMapping = 6; 65const NeutralToneMapping = 7; 66const AttachedBindMode = 'attached'; 67const DetachedBindMode = 'detached'; 68 69const UVMapping = 300; 70const CubeReflectionMapping = 301; 71const CubeRefractionMapping = 302; 72const EquirectangularReflectionMapping = 303; 73const EquirectangularRefractionMapping = 304; 74const CubeUVReflectionMapping = 306; 75const RepeatWrapping = 1000; 76const ClampToEdgeWrapping = 1001; 77const MirroredRepeatWrapping = 1002; 78const NearestFilter = 1003; 79const NearestMipmapNearestFilter = 1004; 80const NearestMipMapNearestFilter = 1004; 81const NearestMipmapLinearFilter = 1005; 82const NearestMipMapLinearFilter = 1005; 83const LinearFilter = 1006; 84const LinearMipmapNearestFilter = 1007; 85const LinearMipMapNearestFilter = 1007; 86const LinearMipmapLinearFilter = 1008; 87const LinearMipMapLinearFilter = 1008; 88const UnsignedByteType = 1009; 89const ByteType = 1010; 90const ShortType = 1011; 91const UnsignedShortType = 1012; 92const IntType = 1013; 93const UnsignedIntType = 1014; 94const FloatType = 1015; 95const HalfFloatType = 1016; 96const UnsignedShort4444Type = 1017; 97const UnsignedShort5551Type = 1018; 98const UnsignedInt248Type = 1020; 99const UnsignedInt5999Type = 35902; 100const AlphaFormat = 1021; 101const RGBFormat = 1022; 102const RGBAFormat = 1023; 103const LuminanceFormat = 1024; 104const LuminanceAlphaFormat = 1025; 105const DepthFormat = 1026; 106const DepthStencilFormat = 1027; 107const RedFormat = 1028; 108const RedIntegerFormat = 1029; 109const RGFormat = 1030; 110const RGIntegerFormat = 1031; 111const RGBAIntegerFormat = 1033; 112 113const RGB_S3TC_DXT1_Format = 33776; 114const RGBA_S3TC_DXT1_Format = 33777; 115const RGBA_S3TC_DXT3_Format = 33778; 116const RGBA_S3TC_DXT5_Format = 33779; 117const RGB_PVRTC_4BPPV1_Format = 35840; 118const RGB_PVRTC_2BPPV1_Format = 35841; 119const RGBA_PVRTC_4BPPV1_Format = 35842; 120const RGBA_PVRTC_2BPPV1_Format = 35843; 121const RGB_ETC1_Format = 36196; 122const RGB_ETC2_Format = 37492; 123const RGBA_ETC2_EAC_Format = 37496; 124const RGBA_ASTC_4x4_Format = 37808; 125const RGBA_ASTC_5x4_Format = 37809; 126const RGBA_ASTC_5x5_Format = 37810; 127const RGBA_ASTC_6x5_Format = 37811; 128const RGBA_ASTC_6x6_Format = 37812; 129const RGBA_ASTC_8x5_Format = 37813; 130const RGBA_ASTC_8x6_Format = 37814; 131const RGBA_ASTC_8x8_Format = 37815; 132const RGBA_ASTC_10x5_Format = 37816; 133const RGBA_ASTC_10x6_Format = 37817; 134const RGBA_ASTC_10x8_Format = 37818; 135const RGBA_ASTC_10x10_Format = 37819; 136const RGBA_ASTC_12x10_Format = 37820; 137const RGBA_ASTC_12x12_Format = 37821; 138const RGBA_BPTC_Format = 36492; 139const RGB_BPTC_SIGNED_Format = 36494; 140const RGB_BPTC_UNSIGNED_Format = 36495; 141const RED_RGTC1_Format = 36283;
vendor: 8,145 bytes, lines 142-430
142const SIGNED_RED_RGTC1_Format = 36284; 143const RED_GREEN_RGTC2_Format = 36285; 144const SIGNED_RED_GREEN_RGTC2_Format = 36286; 145const LoopOnce = 2200; 146const LoopRepeat = 2201; 147const LoopPingPong = 2202; 148const InterpolateDiscrete = 2300; 149const InterpolateLinear = 2301; 150const InterpolateSmooth = 2302; 151const ZeroCurvatureEnding = 2400; 152const ZeroSlopeEnding = 2401; 153const WrapAroundEnding = 2402; 154const NormalAnimationBlendMode = 2500; 155const AdditiveAnimationBlendMode = 2501; 156const TrianglesDrawMode = 0; 157const TriangleStripDrawMode = 1; 158const TriangleFanDrawMode = 2; 159const BasicDepthPacking = 3200; 160const RGBADepthPacking = 3201; 161const TangentSpaceNormalMap = 0; 162const ObjectSpaceNormalMap = 1; 163 164// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available. 165const NoColorSpace = ''; 166const SRGBColorSpace = 'srgb'; 167const LinearSRGBColorSpace = 'srgb-linear'; 168const DisplayP3ColorSpace = 'display-p3'; 169const LinearDisplayP3ColorSpace = 'display-p3-linear'; 170 171const LinearTransfer = 'linear'; 172const SRGBTransfer = 'srgb'; 173 174const Rec709Primaries = 'rec709'; 175const P3Primaries = 'p3'; 176 177const ZeroStencilOp = 0; 178const KeepStencilOp = 7680; 179const ReplaceStencilOp = 7681; 180const IncrementStencilOp = 7682; 181const DecrementStencilOp = 7683; 182const IncrementWrapStencilOp = 34055; 183const DecrementWrapStencilOp = 34056; 184const InvertStencilOp = 5386; 185 186const NeverStencilFunc = 512; 187const LessStencilFunc = 513; 188const EqualStencilFunc = 514; 189const LessEqualStencilFunc = 515; 190const GreaterStencilFunc = 516; 191const NotEqualStencilFunc = 517; 192const GreaterEqualStencilFunc = 518; 193const AlwaysStencilFunc = 519; 194 195const NeverCompare = 512; 196const LessCompare = 513; 197const EqualCompare = 514; 198const LessEqualCompare = 515; 199const GreaterCompare = 516; 200const NotEqualCompare = 517; 201const GreaterEqualCompare = 518; 202const AlwaysCompare = 519; 203 204const StaticDrawUsage = 35044; 205const DynamicDrawUsage = 35048; 206const StreamDrawUsage = 35040; 207const StaticReadUsage = 35045; 208const DynamicReadUsage = 35049; 209const StreamReadUsage = 35041; 210const StaticCopyUsage = 35046; 211const DynamicCopyUsage = 35050; 212const StreamCopyUsage = 35042; 213 214const GLSL1 = '100'; 215const GLSL3 = '300 es'; 216 217const WebGLCoordinateSystem = 2000; 218const WebGPUCoordinateSystem = 2001; 219 220/** 221 * https://github.com/mrdoob/eventdispatcher.js/ 222 */ 223 224class EventDispatcher { 225 226 addEventListener( type, listener ) { 227 228 if ( this._listeners === undefined ) this._listeners = {}; 229 230 const listeners = this._listeners; 231 232 if ( listeners[ type ] === undefined ) { 233 234 listeners[ type ] = []; 235 236 } 237 238 if ( listeners[ type ].indexOf( listener ) === - 1 ) { 239 240 listeners[ type ].push( listener ); 241 242 } 243 244 } 245 246 hasEventListener( type, listener ) { 247 248 if ( this._listeners === undefined ) return false; 249 250 const listeners = this._listeners; 251 252 return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1; 253 254 } 255 256 removeEventListener( type, listener ) { 257 258 if ( this._listeners === undefined ) return; 259 260 const listeners = this._listeners; 261 const listenerArray = listeners[ type ]; 262 263 if ( listenerArray !== undefined ) { 264 265 const index = listenerArray.indexOf( listener ); 266 267 if ( index !== - 1 ) { 268 269 listenerArray.splice( index, 1 ); 270 271 } 272 273 } 274 275 } 276 277 dispatchEvent( event ) { 278 279 if ( this._listeners === undefined ) return; 280 281 const listeners = this._listeners; 282 const listenerArray = listeners[ event.type ]; 283 284 if ( listenerArray !== undefined ) { 285 286 event.target = this; 287 288 // Make a copy, in case listeners are removed while iterating. 289 const array = listenerArray.slice( 0 ); 290 291 for ( let i = 0, l = array.length; i < l; i ++ ) { 292 293 array[ i ].call( this, event ); 294 295 } 296 297 event.target = null; 298 299 } 300 301 } 302 303} 304 305const _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' ]; 306 307let _seed = 1234567; 308 309 310const DEG2RAD = Math.PI / 180; 311const RAD2DEG = 180 / Math.PI; 312 313// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 314function generateUUID() { 315 316 const d0 = Math.random() * 0xffffffff | 0; 317 const d1 = Math.random() * 0xffffffff | 0; 318 const d2 = Math.random() * 0xffffffff | 0; 319 const d3 = Math.random() * 0xffffffff | 0; 320 const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' + 321 _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' + 322 _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] + 323 _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ]; 324 325 // .toLowerCase() here flattens concatenated strings to save heap memory space. 326 return uuid.toLowerCase(); 327 328} 329 330function clamp( value, min, max ) { 331 332 return Math.max( min, Math.min( max, value ) ); 333 334} 335 336// compute euclidean modulo of m % n 337// https://en.wikipedia.org/wiki/Modulo_operation 338function euclideanModulo( n, m ) { 339 340 return ( ( n % m ) + m ) % m; 341 342} 343 344// Linear mapping from range <a1, a2> to range <b1, b2> 345function mapLinear( x, a1, a2, b1, b2 ) { 346 347 return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); 348 349} 350 351// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/ 352function inverseLerp( x, y, value ) { 353 354 if ( x !== y ) { 355 356 return ( value - x ) / ( y - x ); 357 358 } else { 359 360 return 0; 361 362 } 363 364} 365 366// https://en.wikipedia.org/wiki/Linear_interpolation 367function lerp( x, y, t ) { 368 369 return ( 1 - t ) * x + t * y; 370 371} 372 373// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ 374function damp( x, y, lambda, dt ) { 375 376 return lerp( x, y, 1 - Math.exp( - lambda * dt ) ); 377 378} 379 380// https://www.desmos.com/calculator/vcsjnyz7x4 381function pingpong( x, length = 1 ) { 382 383 return length - Math.abs( euclideanModulo( x, length * 2 ) - length ); 384 385} 386 387// http://en.wikipedia.org/wiki/Smoothstep 388function smoothstep( x, min, max ) { 389 390 if ( x <= min ) return 0; 391 if ( x >= max ) return 1; 392 393 x = ( x - min ) / ( max - min ); 394 395 return x * x * ( 3 - 2 * x ); 396 397} 398 399function smootherstep( x, min, max ) { 400 401 if ( x <= min ) return 0; 402 if ( x >= max ) return 1; 403 404 x = ( x - min ) / ( max - min ); 405 406 return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); 407 408} 409 410// Random integer from <low, high> interval 411function randInt( low, high ) { 412 413 return low + Math.floor( Math.random() * ( high - low + 1 ) ); 414 415} 416 417// Random float from <low, high> interval 418function randFloat( low, high ) { 419 420 return low + Math.random() * ( high - low ); 421 422} 423 424// Random float from <-range/2, range/2> interval 425function randFloatSpread( range ) { 426 427 return range * ( 0.5 - Math.random() ); 428 429} 430
vendor: 7,916 bytes, lines 431-1006
431// Deterministic pseudo-random float in the interval [ 0, 1 ] 432function seededRandom( s ) { 433 434 if ( s !== undefined ) _seed = s; 435 436 // Mulberry32 generator 437 438 let t = _seed += 0x6D2B79F5; 439 440 t = Math.imul( t ^ t >>> 15, t | 1 ); 441 442 t ^= t + Math.imul( t ^ t >>> 7, t | 61 ); 443 444 return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296; 445 446} 447 448function degToRad( degrees ) { 449 450 return degrees * DEG2RAD; 451 452} 453 454function radToDeg( radians ) { 455 456 return radians * RAD2DEG; 457 458} 459 460function isPowerOfTwo( value ) { 461 462 return ( value & ( value - 1 ) ) === 0 && value !== 0; 463 464} 465 466function ceilPowerOfTwo( value ) { 467 468 return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); 469 470} 471 472function floorPowerOfTwo( value ) { 473 474 return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); 475 476} 477 478function setQuaternionFromProperEuler( q, a, b, c, order ) { 479 480 // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles 481 482 // rotations are applied to the axes in the order specified by 'order' 483 // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c' 484 // angles are in radians 485 486 const cos = Math.cos; 487 const sin = Math.sin; 488 489 const c2 = cos( b / 2 ); 490 const s2 = sin( b / 2 ); 491 492 const c13 = cos( ( a + c ) / 2 ); 493 const s13 = sin( ( a + c ) / 2 ); 494 495 const c1_3 = cos( ( a - c ) / 2 ); 496 const s1_3 = sin( ( a - c ) / 2 ); 497 498 const c3_1 = cos( ( c - a ) / 2 ); 499 const s3_1 = sin( ( c - a ) / 2 ); 500 501 switch ( order ) { 502 503 case 'XYX': 504 q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 ); 505 break; 506 507 case 'YZY': 508 q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 ); 509 break; 510 511 case 'ZXZ': 512 q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 ); 513 break; 514 515 case 'XZX': 516 q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 ); 517 break; 518 519 case 'YXY': 520 q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 ); 521 break; 522 523 case 'ZYZ': 524 q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 ); 525 break; 526 527 default: 528 console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order ); 529 530 } 531 532} 533 534function denormalize( value, array ) { 535 536 switch ( array.constructor ) { 537 538 case Float32Array: 539 540 return value; 541 542 case Uint32Array: 543 544 return value / 4294967295.0; 545 546 case Uint16Array: 547 548 return value / 65535.0; 549 550 case Uint8Array: 551 552 return value / 255.0; 553 554 case Int32Array: 555 556 return Math.max( value / 2147483647.0, - 1.0 ); 557 558 case Int16Array: 559 560 return Math.max( value / 32767.0, - 1.0 ); 561 562 case Int8Array: 563 564 return Math.max( value / 127.0, - 1.0 ); 565 566 default: 567 568 throw new Error( 'Invalid component type.' ); 569 570 } 571 572} 573 574function normalize( value, array ) { 575 576 switch ( array.constructor ) { 577 578 case Float32Array: 579 580 return value; 581 582 case Uint32Array: 583 584 return Math.round( value * 4294967295.0 ); 585 586 case Uint16Array: 587 588 return Math.round( value * 65535.0 ); 589 590 case Uint8Array: 591 592 return Math.round( value * 255.0 ); 593 594 case Int32Array: 595 596 return Math.round( value * 2147483647.0 ); 597 598 case Int16Array: 599 600 return Math.round( value * 32767.0 ); 601 602 case Int8Array: 603 604 return Math.round( value * 127.0 ); 605 606 default: 607 608 throw new Error( 'Invalid component type.' ); 609 610 } 611 612} 613 614const MathUtils = { 615 DEG2RAD: DEG2RAD, 616 RAD2DEG: RAD2DEG, 617 generateUUID: generateUUID, 618 clamp: clamp, 619 euclideanModulo: euclideanModulo, 620 mapLinear: mapLinear, 621 inverseLerp: inverseLerp, 622 lerp: lerp, 623 damp: damp, 624 pingpong: pingpong, 625 smoothstep: smoothstep, 626 smootherstep: smootherstep, 627 randInt: randInt, 628 randFloat: randFloat, 629 randFloatSpread: randFloatSpread, 630 seededRandom: seededRandom, 631 degToRad: degToRad, 632 radToDeg: radToDeg, 633 isPowerOfTwo: isPowerOfTwo, 634 ceilPowerOfTwo: ceilPowerOfTwo, 635 floorPowerOfTwo: floorPowerOfTwo, 636 setQuaternionFromProperEuler: setQuaternionFromProperEuler, 637 normalize: normalize, 638 denormalize: denormalize 639}; 640 641class Vector2 { 642 643 constructor( x = 0, y = 0 ) { 644 645 Vector2.prototype.isVector2 = true; 646 647 this.x = x; 648 this.y = y; 649 650 } 651 652 get width() { 653 654 return this.x; 655 656 } 657 658 set width( value ) { 659 660 this.x = value; 661 662 } 663 664 get height() { 665 666 return this.y; 667 668 } 669 670 set height( value ) { 671 672 this.y = value; 673 674 } 675 676 set( x, y ) { 677 678 this.x = x; 679 this.y = y; 680 681 return this; 682 683 } 684 685 setScalar( scalar ) { 686 687 this.x = scalar; 688 this.y = scalar; 689 690 return this; 691 692 } 693 694 setX( x ) { 695 696 this.x = x; 697 698 return this; 699 700 } 701 702 setY( y ) { 703 704 this.y = y; 705 706 return this; 707 708 } 709 710 setComponent( index, value ) { 711 712 switch ( index ) { 713 714 case 0: this.x = value; break; 715 case 1: this.y = value; break; 716 default: throw new Error( 'index is out of range: ' + index ); 717 718 } 719 720 return this; 721 722 } 723 724 getComponent( index ) { 725 726 switch ( index ) { 727 728 case 0: return this.x; 729 case 1: return this.y; 730 default: throw new Error( 'index is out of range: ' + index ); 731 732 } 733 734 } 735 736 clone() { 737 738 return new this.constructor( this.x, this.y ); 739 740 } 741 742 copy( v ) { 743 744 this.x = v.x; 745 this.y = v.y; 746 747 return this; 748 749 } 750 751 add( v ) { 752 753 this.x += v.x; 754 this.y += v.y; 755 756 return this; 757 758 } 759 760 addScalar( s ) { 761 762 this.x += s; 763 this.y += s; 764 765 return this; 766 767 } 768 769 addVectors( a, b ) { 770 771 this.x = a.x + b.x; 772 this.y = a.y + b.y; 773 774 return this; 775 776 } 777 778 addScaledVector( v, s ) { 779 780 this.x += v.x * s; 781 this.y += v.y * s; 782 783 return this; 784 785 } 786 787 sub( v ) { 788 789 this.x -= v.x; 790 this.y -= v.y; 791 792 return this; 793 794 } 795 796 subScalar( s ) { 797 798 this.x -= s; 799 this.y -= s; 800 801 return this; 802 803 } 804 805 subVectors( a, b ) { 806 807 this.x = a.x - b.x; 808 this.y = a.y - b.y; 809 810 return this; 811 812 } 813 814 multiply( v ) { 815 816 this.x *= v.x; 817 this.y *= v.y; 818 819 return this; 820 821 } 822 823 multiplyScalar( scalar ) { 824 825 this.x *= scalar; 826 this.y *= scalar; 827 828 return this; 829 830 } 831 832 divide( v ) { 833 834 this.x /= v.x; 835 this.y /= v.y; 836 837 return this; 838 839 } 840 841 divideScalar( scalar ) { 842 843 return this.multiplyScalar( 1 / scalar ); 844 845 } 846 847 applyMatrix3( m ) { 848 849 const x = this.x, y = this.y; 850 const e = m.elements; 851 852 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ]; 853 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ]; 854 855 return this; 856 857 } 858 859 min( v ) { 860 861 this.x = Math.min( this.x, v.x ); 862 this.y = Math.min( this.y, v.y ); 863 864 return this; 865 866 } 867 868 max( v ) { 869 870 this.x = Math.max( this.x, v.x ); 871 this.y = Math.max( this.y, v.y ); 872 873 return this; 874 875 } 876 877 clamp( min, max ) { 878 879 // assumes min < max, componentwise 880 881 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 882 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 883 884 return this; 885 886 } 887 888 clampScalar( minVal, maxVal ) { 889 890 this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); 891 this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); 892 893 return this; 894 895 } 896 897 clampLength( min, max ) { 898 899 const length = this.length(); 900 901 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 902 903 } 904 905 floor() { 906 907 this.x = Math.floor( this.x ); 908 this.y = Math.floor( this.y ); 909 910 return this; 911 912 } 913 914 ceil() { 915 916 this.x = Math.ceil( this.x ); 917 this.y = Math.ceil( this.y ); 918 919 return this; 920 921 } 922 923 round() { 924 925 this.x = Math.round( this.x ); 926 this.y = Math.round( this.y ); 927 928 return this; 929 930 } 931 932 roundToZero() { 933 934 this.x = Math.trunc( this.x ); 935 this.y = Math.trunc( this.y ); 936 937 return this; 938 939 } 940 941 negate() { 942 943 this.x = - this.x; 944 this.y = - this.y; 945 946 return this; 947 948 } 949 950 dot( v ) { 951 952 return this.x * v.x + this.y * v.y; 953 954 } 955 956 cross( v ) { 957 958 return this.x * v.y - this.y * v.x; 959 960 } 961 962 lengthSq() { 963 964 return this.x * this.x + this.y * this.y; 965 966 } 967 968 length() { 969 970 return Math.sqrt( this.x * this.x + this.y * this.y ); 971 972 } 973 974 manhattanLength() { 975 976 return Math.abs( this.x ) + Math.abs( this.y ); 977 978 } 979 980 normalize() { 981 982 return this.divideScalar( this.length() || 1 ); 983 984 } 985 986 angle() { 987 988 // computes the angle in radians with respect to the positive x-axis 989 990 const angle = Math.atan2( - this.y, - this.x ) + Math.PI; 991 992 return angle; 993 994 } 995 996 angleTo( v ) { 997 998 const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); 999 1000 if ( denominator === 0 ) return Math.PI / 2; 1001 1002 const theta = this.dot( v ) / denominator; 1003 1004 // clamp, to handle numerical problems 1005 1006 return Math.acos( clamp( theta, -
vendor: 7,768 bytes, lines 1006-1518
10061, 1 ) ); 1007 1008 } 1009 1010 distanceTo( v ) { 1011 1012 return Math.sqrt( this.distanceToSquared( v ) ); 1013 1014 } 1015 1016 distanceToSquared( v ) { 1017 1018 const dx = this.x - v.x, dy = this.y - v.y; 1019 return dx * dx + dy * dy; 1020 1021 } 1022 1023 manhattanDistanceTo( v ) { 1024 1025 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ); 1026 1027 } 1028 1029 setLength( length ) { 1030 1031 return this.normalize().multiplyScalar( length ); 1032 1033 } 1034 1035 lerp( v, alpha ) { 1036 1037 this.x += ( v.x - this.x ) * alpha; 1038 this.y += ( v.y - this.y ) * alpha; 1039 1040 return this; 1041 1042 } 1043 1044 lerpVectors( v1, v2, alpha ) { 1045 1046 this.x = v1.x + ( v2.x - v1.x ) * alpha; 1047 this.y = v1.y + ( v2.y - v1.y ) * alpha; 1048 1049 return this; 1050 1051 } 1052 1053 equals( v ) { 1054 1055 return ( ( v.x === this.x ) && ( v.y === this.y ) ); 1056 1057 } 1058 1059 fromArray( array, offset = 0 ) { 1060 1061 this.x = array[ offset ]; 1062 this.y = array[ offset + 1 ]; 1063 1064 return this; 1065 1066 } 1067 1068 toArray( array = [], offset = 0 ) { 1069 1070 array[ offset ] = this.x; 1071 array[ offset + 1 ] = this.y; 1072 1073 return array; 1074 1075 } 1076 1077 fromBufferAttribute( attribute, index ) { 1078 1079 this.x = attribute.getX( index ); 1080 this.y = attribute.getY( index ); 1081 1082 return this; 1083 1084 } 1085 1086 rotateAround( center, angle ) { 1087 1088 const c = Math.cos( angle ), s = Math.sin( angle ); 1089 1090 const x = this.x - center.x; 1091 const y = this.y - center.y; 1092 1093 this.x = x * c - y * s + center.x; 1094 this.y = x * s + y * c + center.y; 1095 1096 return this; 1097 1098 } 1099 1100 random() { 1101 1102 this.x = Math.random(); 1103 this.y = Math.random(); 1104 1105 return this; 1106 1107 } 1108 1109 *[ Symbol.iterator ]() { 1110 1111 yield this.x; 1112 yield this.y; 1113 1114 } 1115 1116} 1117 1118class Matrix3 { 1119 1120 constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { 1121 1122 Matrix3.prototype.isMatrix3 = true; 1123 1124 this.elements = [ 1125 1126 1, 0, 0, 1127 0, 1, 0, 1128 0, 0, 1 1129 1130 ]; 1131 1132 if ( n11 !== undefined ) { 1133 1134 this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ); 1135 1136 } 1137 1138 } 1139 1140 set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { 1141 1142 const te = this.elements; 1143 1144 te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31; 1145 te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32; 1146 te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33; 1147 1148 return this; 1149 1150 } 1151 1152 identity() { 1153 1154 this.set( 1155 1156 1, 0, 0, 1157 0, 1, 0, 1158 0, 0, 1 1159 1160 ); 1161 1162 return this; 1163 1164 } 1165 1166 copy( m ) { 1167 1168 const te = this.elements; 1169 const me = m.elements; 1170 1171 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; 1172 te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; 1173 te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ]; 1174 1175 return this; 1176 1177 } 1178 1179 extractBasis( xAxis, yAxis, zAxis ) { 1180 1181 xAxis.setFromMatrix3Column( this, 0 ); 1182 yAxis.setFromMatrix3Column( this, 1 ); 1183 zAxis.setFromMatrix3Column( this, 2 ); 1184 1185 return this; 1186 1187 } 1188 1189 setFromMatrix4( m ) { 1190 1191 const me = m.elements; 1192 1193 this.set( 1194 1195 me[ 0 ], me[ 4 ], me[ 8 ], 1196 me[ 1 ], me[ 5 ], me[ 9 ], 1197 me[ 2 ], me[ 6 ], me[ 10 ] 1198 1199 ); 1200 1201 return this; 1202 1203 } 1204 1205 multiply( m ) { 1206 1207 return this.multiplyMatrices( this, m ); 1208 1209 } 1210 1211 premultiply( m ) { 1212 1213 return this.multiplyMatrices( m, this ); 1214 1215 } 1216 1217 multiplyMatrices( a, b ) { 1218 1219 const ae = a.elements; 1220 const be = b.elements; 1221 const te = this.elements; 1222 1223 const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ]; 1224 const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ]; 1225 const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ]; 1226 1227 const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ]; 1228 const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ]; 1229 const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ]; 1230 1231 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; 1232 te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; 1233 te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; 1234 1235 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; 1236 te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; 1237 te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; 1238 1239 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31; 1240 te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32; 1241 te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33; 1242 1243 return this; 1244 1245 } 1246 1247 multiplyScalar( s ) { 1248 1249 const te = this.elements; 1250 1251 te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s; 1252 te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s; 1253 te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s; 1254 1255 return this; 1256 1257 } 1258 1259 determinant() { 1260 1261 const te = this.elements; 1262 1263 const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], 1264 d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], 1265 g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; 1266 1267 return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; 1268 1269 } 1270 1271 invert() { 1272 1273 const te = this.elements, 1274 1275 n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], 1276 n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ], 1277 n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ], 1278 1279 t11 = n33 * n22 - n32 * n23, 1280 t12 = n32 * n13 - n33 * n12, 1281 t13 = n23 * n12 - n22 * n13, 1282 1283 det = n11 * t11 + n21 * t12 + n31 * t13; 1284 1285 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); 1286 1287 const detInv = 1 / det; 1288 1289 te[ 0 ] = t11 * detInv; 1290 te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; 1291 te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; 1292 1293 te[ 3 ] = t12 * detInv; 1294 te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; 1295 te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; 1296 1297 te[ 6 ] = t13 * detInv; 1298 te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; 1299 te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; 1300 1301 return this; 1302 1303 } 1304 1305 transpose() { 1306 1307 let tmp; 1308 const m = this.elements; 1309 1310 tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp; 1311 tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp; 1312 tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp; 1313 1314 return this; 1315 1316 } 1317 1318 getNormalMatrix( matrix4 ) { 1319 1320 return this.setFromMatrix4( matrix4 ).invert().transpose(); 1321 1322 } 1323 1324 transposeIntoArray( r ) { 1325 1326 const m = this.elements; 1327 1328 r[ 0 ] = m[ 0 ]; 1329 r[ 1 ] = m[ 3 ]; 1330 r[ 2 ] = m[ 6 ]; 1331 r[ 3 ] = m[ 1 ]; 1332 r[ 4 ] = m[ 4 ]; 1333 r[ 5 ] = m[ 7 ]; 1334 r[ 6 ] = m[ 2 ]; 1335 r[ 7 ] = m[ 5 ]; 1336 r[ 8 ] = m[ 8 ]; 1337 1338 return this; 1339 1340 } 1341 1342 setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) { 1343 1344 const c = Math.cos( rotation ); 1345 const s = Math.sin( rotation ); 1346 1347 this.set( 1348 sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, 1349 - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, 1350 0, 0, 1 1351 ); 1352 1353 return this; 1354 1355 } 1356 1357 // 1358 1359 scale( sx, sy ) { 1360 1361 this.premultiply( _m3.makeScale( sx, sy ) ); 1362 1363 return this; 1364 1365 } 1366 1367 rotate( theta ) { 1368 1369 this.premultiply( _m3.makeRotation( - theta ) ); 1370 1371 return this; 1372 1373 } 1374 1375 translate( tx, ty ) { 1376 1377 this.premultiply( _m3.makeTranslation( tx, ty ) ); 1378 1379 return this; 1380 1381 } 1382 1383 // for 2D Transforms 1384 1385 makeTranslation( x, y ) { 1386 1387 if ( x.isVector2 ) { 1388 1389 this.set( 1390 1391 1, 0, x.x, 1392 0, 1, x.y, 1393 0, 0, 1 1394 1395 ); 1396 1397 } else { 1398 1399 this.set( 1400 1401 1, 0, x, 1402 0, 1, y, 1403 0, 0, 1 1404 1405 ); 1406 1407 } 1408 1409 return this; 1410 1411 } 1412 1413 makeRotation( theta ) { 1414 1415 // counterclockwise 1416 1417 const c = Math.cos( theta ); 1418 const s = Math.sin( theta ); 1419 1420 this.set( 1421 1422 c, - s, 0, 1423 s, c, 0, 1424 0, 0, 1 1425 1426 ); 1427 1428 return this; 1429 1430 } 1431 1432 makeScale( x, y ) { 1433 1434 this.set( 1435 1436 x, 0, 0, 1437 0, y, 0, 1438 0, 0, 1 1439 1440 ); 1441 1442 return this; 1443 1444 } 1445 1446 // 1447 1448 equals( matrix ) { 1449 1450 const te = this.elements; 1451 const me = matrix.elements; 1452 1453 for ( let i = 0; i < 9; i ++ ) { 1454 1455 if ( te[ i ] !== me[ i ] ) return false; 1456 1457 } 1458 1459 return true; 1460 1461 } 1462 1463 fromArray( array, offset = 0 ) { 1464 1465 for ( let i = 0; i < 9; i ++ ) { 1466 1467 this.elements[ i ] = array[ i + offset ]; 1468 1469 } 1470 1471 return this; 1472 1473 } 1474 1475 toArray( array = [], offset = 0 ) { 1476 1477 const te = this.elements; 1478 1479 array[ offset ] = te[ 0 ]; 1480 array[ offset + 1 ] = te[ 1 ]; 1481 array[ offset + 2 ] = te[ 2 ]; 1482 1483 array[ offset + 3 ] = te[ 3 ]; 1484 array[ offset + 4 ] = te[ 4 ]; 1485 array[ offset + 5 ] = te[ 5 ]; 1486 1487 array[ offset + 6 ] = te[ 6 ]; 1488 array[ offset + 7 ] = te[ 7 ]; 1489 array[ offset + 8 ] = te[ 8 ]; 1490 1491 return array; 1492 1493 } 1494 1495 clone() { 1496 1497 return new this.constructor().fromArray( this.elements ); 1498 1499 } 1500 1501} 1502 1503const _m3 = /*@__PURE__*/ new Matrix3(); 1504 1505function arrayNeedsUint32( array ) { 1506 1507 // assumes larger values usually on last 1508 1509 for ( let i = array.length - 1; i >= 0; -- i ) { 1510 1511 if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 1512 1513 } 1514 1515 return false; 1516 1517} 1518
vendor: 13,026 bytes, lines 1519-2158
1519const TYPED_ARRAYS = { 1520 Int8Array: Int8Array, 1521 Uint8Array: Uint8Array, 1522 Uint8ClampedArray: Uint8ClampedArray, 1523 Int16Array: Int16Array, 1524 Uint16Array: Uint16Array, 1525 Int32Array: Int32Array, 1526 Uint32Array: Uint32Array, 1527 Float32Array: Float32Array, 1528 Float64Array: Float64Array 1529}; 1530 1531function getTypedArray( type, buffer ) { 1532 1533 return new TYPED_ARRAYS[ type ]( buffer ); 1534 1535} 1536 1537function createElementNS( name ) { 1538 1539 return document.createElementNS( 'http://www.w3.org/1999/xhtml', name ); 1540 1541} 1542 1543function createCanvasElement() { 1544 1545 const canvas = createElementNS( 'canvas' ); 1546 canvas.style.display = 'block'; 1547 return canvas; 1548 1549} 1550 1551const _cache = {}; 1552 1553function warnOnce( message ) { 1554 1555 if ( message in _cache ) return; 1556 1557 _cache[ message ] = true; 1558 1559 console.warn( message ); 1560 1561} 1562 1563/** 1564 * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping 1565 * or clipping. Based on W3C specifications for sRGB and Display P3, 1566 * and ICC specifications for the D50 connection space. Values in/out 1567 * are _linear_ sRGB and _linear_ Display P3. 1568 * 1569 * Note that both sRGB and Display P3 use the sRGB transfer functions. 1570 * 1571 * Reference: 1572 * - http://www.russellcottrell.com/photo/matrixCalculator.htm 1573 */ 1574 1575const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().set( 1576 0.8224621, 0.177538, 0.0, 1577 0.0331941, 0.9668058, 0.0, 1578 0.0170827, 0.0723974, 0.9105199, 1579); 1580 1581const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().set( 1582 1.2249401, - 0.2249404, 0.0, 1583 - 0.0420569, 1.0420571, 0.0, 1584 - 0.0196376, - 0.0786361, 1.0982735 1585); 1586 1587/** 1588 * Defines supported color spaces by transfer function and primaries, 1589 * and provides conversions to/from the Linear-sRGB reference space. 1590 */ 1591const COLOR_SPACES = { 1592 [ LinearSRGBColorSpace ]: { 1593 transfer: LinearTransfer, 1594 primaries: Rec709Primaries, 1595 toReference: ( color ) => color, 1596 fromReference: ( color ) => color, 1597 }, 1598 [ SRGBColorSpace ]: { 1599 transfer: SRGBTransfer, 1600 primaries: Rec709Primaries, 1601 toReference: ( color ) => color.convertSRGBToLinear(), 1602 fromReference: ( color ) => color.convertLinearToSRGB(), 1603 }, 1604 [ LinearDisplayP3ColorSpace ]: { 1605 transfer: LinearTransfer, 1606 primaries: P3Primaries, 1607 toReference: ( color ) => color.applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), 1608 fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ), 1609 }, 1610 [ DisplayP3ColorSpace ]: { 1611 transfer: SRGBTransfer, 1612 primaries: P3Primaries, 1613 toReference: ( color ) => color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), 1614 fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(), 1615 }, 1616}; 1617 1618const SUPPORTED_WORKING_COLOR_SPACES = new Set( [ LinearSRGBColorSpace, LinearDisplayP3ColorSpace ] ); 1619 1620const ColorManagement = { 1621 1622 enabled: true, 1623 1624 _workingColorSpace: LinearSRGBColorSpace, 1625 1626 get workingColorSpace() { 1627 1628 return this._workingColorSpace; 1629 1630 }, 1631 1632 set workingColorSpace( colorSpace ) { 1633 1634 if ( ! SUPPORTED_WORKING_COLOR_SPACES.has( colorSpace ) ) { 1635 1636 throw new Error( `Unsupported working color space, "${ colorSpace }".` ); 1637 1638 } 1639 1640 this._workingColorSpace = colorSpace; 1641 1642 }, 1643 1644 convert: function ( color, sourceColorSpace, targetColorSpace ) { 1645 1646 if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { 1647 1648 return color; 1649 1650 } 1651 1652 const sourceToReference = COLOR_SPACES[ sourceColorSpace ].toReference; 1653 const targetFromReference = COLOR_SPACES[ targetColorSpace ].fromReference; 1654 1655 return targetFromReference( sourceToReference( color ) ); 1656 1657 }, 1658 1659 fromWorkingColorSpace: function ( color, targetColorSpace ) { 1660 1661 return this.convert( color, this._workingColorSpace, targetColorSpace ); 1662 1663 }, 1664 1665 toWorkingColorSpace: function ( color, sourceColorSpace ) { 1666 1667 return this.convert( color, sourceColorSpace, this._workingColorSpace ); 1668 1669 }, 1670 1671 getPrimaries: function ( colorSpace ) { 1672 1673 return COLOR_SPACES[ colorSpace ].primaries; 1674 1675 }, 1676 1677 getTransfer: function ( colorSpace ) { 1678 1679 if ( colorSpace === NoColorSpace ) return LinearTransfer; 1680 1681 return COLOR_SPACES[ colorSpace ].transfer; 1682 1683 }, 1684 1685}; 1686 1687 1688function SRGBToLinear( c ) { 1689 1690 return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 ); 1691 1692} 1693 1694function LinearToSRGB( c ) { 1695 1696 return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055; 1697 1698} 1699 1700let _canvas; 1701 1702class ImageUtils { 1703 1704 static getDataURL( image ) { 1705 1706 if ( /^data:/i.test( image.src ) ) { 1707 1708 return image.src; 1709 1710 } 1711 1712 if ( typeof HTMLCanvasElement === 'undefined' ) { 1713 1714 return image.src; 1715 1716 } 1717 1718 let canvas; 1719 1720 if ( image instanceof HTMLCanvasElement ) { 1721 1722 canvas = image; 1723 1724 } else { 1725 1726 if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); 1727 1728 _canvas.width = image.width; 1729 _canvas.height = image.height; 1730 1731 const context = _canvas.getContext( '2d' ); 1732 1733 if ( image instanceof ImageData ) { 1734 1735 context.putImageData( image, 0, 0 ); 1736 1737 } else { 1738 1739 context.drawImage( image, 0, 0, image.width, image.height ); 1740 1741 } 1742 1743 canvas = _canvas; 1744 1745 } 1746 1747 if ( canvas.width > 2048 || canvas.height > 2048 ) { 1748 1749 console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); 1750 1751 return canvas.toDataURL( 'image/jpeg', 0.6 ); 1752 1753 } else { 1754 1755 return canvas.toDataURL( 'image/png' ); 1756 1757 } 1758 1759 } 1760 1761 static sRGBToLinear( image ) { 1762 1763 if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || 1764 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || 1765 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { 1766 1767 const canvas = createElementNS( 'canvas' ); 1768 1769 canvas.width = image.width; 1770 canvas.height = image.height; 1771 1772 const context = canvas.getContext( '2d' ); 1773 context.drawImage( image, 0, 0, image.width, image.height ); 1774 1775 const imageData = context.getImageData( 0, 0, image.width, image.height ); 1776 const data = imageData.data; 1777 1778 for ( let i = 0; i < data.length; i ++ ) { 1779 1780 data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; 1781 1782 } 1783 1784 context.putImageData( imageData, 0, 0 ); 1785 1786 return canvas; 1787 1788 } else if ( image.data ) { 1789 1790 const data = image.data.slice( 0 ); 1791 1792 for ( let i = 0; i < data.length; i ++ ) { 1793 1794 if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { 1795 1796 data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); 1797 1798 } else { 1799 1800 // assuming float 1801 1802 data[ i ] = SRGBToLinear( data[ i ] ); 1803 1804 } 1805 1806 } 1807 1808 return { 1809 data: data, 1810 width: image.width, 1811 height: image.height 1812 }; 1813 1814 } else { 1815 1816 console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); 1817 return image; 1818 1819 } 1820 1821 } 1822 1823} 1824 1825let _sourceId = 0; 1826 1827class Source { 1828 1829 constructor( data = null ) { 1830 1831 this.isSource = true; 1832 1833 Object.defineProperty( this, 'id', { value: _sourceId ++ } ); 1834 1835 this.uuid = generateUUID(); 1836 1837 this.data = data; 1838 this.dataReady = true; 1839 1840 this.version = 0; 1841 1842 } 1843 1844 set needsUpdate( value ) { 1845 1846 if ( value === true ) this.version ++; 1847 1848 } 1849 1850 toJSON( meta ) { 1851 1852 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 1853 1854 if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { 1855 1856 return meta.images[ this.uuid ]; 1857 1858 } 1859 1860 const output = { 1861 uuid: this.uuid, 1862 url: '' 1863 }; 1864 1865 const data = this.data; 1866 1867 if ( data !== null ) { 1868 1869 let url; 1870 1871 if ( Array.isArray( data ) ) { 1872 1873 // cube texture 1874 1875 url = []; 1876 1877 for ( let i = 0, l = data.length; i < l; i ++ ) { 1878 1879 if ( data[ i ].isDataTexture ) { 1880 1881 url.push( serializeImage( data[ i ].image ) ); 1882 1883 } else { 1884 1885 url.push( serializeImage( data[ i ] ) ); 1886 1887 } 1888 1889 } 1890 1891 } else { 1892 1893 // texture 1894 1895 url = serializeImage( data ); 1896 1897 } 1898 1899 output.url = url; 1900 1901 } 1902 1903 if ( ! isRootObject ) { 1904 1905 meta.images[ this.uuid ] = output; 1906 1907 } 1908 1909 return output; 1910 1911 } 1912 1913} 1914 1915function serializeImage( image ) { 1916 1917 if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || 1918 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || 1919 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { 1920 1921 // default images 1922 1923 return ImageUtils.getDataURL( image ); 1924 1925 } else { 1926 1927 if ( image.data ) { 1928 1929 // images of DataTexture 1930 1931 return { 1932 data: Array.from( image.data ), 1933 width: image.width, 1934 height: image.height, 1935 type: image.data.constructor.name 1936 }; 1937 1938 } else { 1939 1940 console.warn( 'THREE.Texture: Unable to serialize Texture.' ); 1941 return {}; 1942 1943 } 1944 1945 } 1946 1947} 1948 1949let _textureId = 0; 1950 1951class Texture extends EventDispatcher { 1952 1953 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, colorSpace = NoColorSpace ) { 1954 1955 super(); 1956 1957 this.isTexture = true; 1958 1959 Object.defineProperty( this, 'id', { value: _textureId ++ } ); 1960 1961 this.uuid = generateUUID(); 1962 1963 this.name = ''; 1964 1965 this.source = new Source( image ); 1966 this.mipmaps = []; 1967 1968 this.mapping = mapping; 1969 this.channel = 0; 1970 1971 this.wrapS = wrapS; 1972 this.wrapT = wrapT; 1973 1974 this.magFilter = magFilter; 1975 this.minFilter = minFilter; 1976 1977 this.anisotropy = anisotropy; 1978 1979 this.format = format; 1980 this.internalFormat = null; 1981 this.type = type; 1982 1983 this.offset = new Vector2( 0, 0 ); 1984 this.repeat = new Vector2( 1, 1 ); 1985 this.center = new Vector2( 0, 0 ); 1986 this.rotation = 0; 1987 1988 this.matrixAutoUpdate = true; 1989 this.matrix = new Matrix3(); 1990 1991 this.generateMipmaps = true; 1992 this.premultiplyAlpha = false; 1993 this.flipY = true; 1994 this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) 1995 1996 this.colorSpace = colorSpace; 1997 1998 this.userData = {}; 1999 2000 this.version = 0; 2001 this.onUpdate = null; 2002 2003 this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not 2004 this.pmremVersion = 0; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) 2005 2006 } 2007 2008 get image() { 2009 2010 return this.source.data; 2011 2012 } 2013 2014 set image( value = null ) { 2015 2016 this.source.data = value; 2017 2018 } 2019 2020 updateMatrix() { 2021 2022 this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); 2023 2024 } 2025 2026 clone() { 2027 2028 return new this.constructor().copy( this ); 2029 2030 } 2031 2032 copy( source ) { 2033 2034 this.name = source.name; 2035 2036 this.source = source.source; 2037 this.mipmaps = source.mipmaps.slice( 0 ); 2038 2039 this.mapping = source.mapping; 2040 this.channel = source.channel; 2041 2042 this.wrapS = source.wrapS; 2043 this.wrapT = source.wrapT; 2044 2045 this.magFilter = source.magFilter; 2046 this.minFilter = source.minFilter; 2047 2048 this.anisotropy = source.anisotropy; 2049 2050 this.format = source.format; 2051 this.internalFormat = source.internalFormat; 2052 this.type = source.type; 2053 2054 this.offset.copy( source.offset ); 2055 this.repeat.copy( source.repeat ); 2056 this.center.copy( source.center ); 2057 this.rotation = source.rotation; 2058 2059 this.matrixAutoUpdate = source.matrixAutoUpdate; 2060 this.matrix.copy( source.matrix ); 2061 2062 this.generateMipmaps = source.generateMipmaps; 2063 this.premultiplyAlpha = source.premultiplyAlpha; 2064 this.flipY = source.flipY; 2065 this.unpackAlignment = source.unpackAlignment; 2066 this.colorSpace = source.colorSpace; 2067 2068 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 2069 2070 this.needsUpdate = true; 2071 2072 return this; 2073 2074 } 2075 2076 toJSON( meta ) { 2077 2078 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 2079 2080 if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { 2081 2082 return meta.textures[ this.uuid ]; 2083 2084 } 2085 2086 const output = { 2087 2088 metadata: { 2089 version: 4.6, 2090 type: 'Texture', 2091 generator: 'Texture.toJSON' 2092 }, 2093 2094 uuid: this.uuid, 2095 name: this.name, 2096 2097 image: this.source.toJSON( meta ).uuid, 2098 2099 mapping: this.mapping, 2100 channel: this.channel, 2101 2102 repeat: [ this.repeat.x, this.repeat.y ], 2103 offset: [ this.offset.x, this.offset.y ], 2104 center: [ this.center.x, this.center.y ], 2105 rotation: this.rotation, 2106 2107 wrap: [ this.wrapS, this.wrapT ], 2108 2109 format: this.format, 2110 internalFormat: this.internalFormat, 2111 type: this.type, 2112 colorSpace: this.colorSpace, 2113 2114 minFilter: this.minFilter, 2115 magFilter: this.magFilter, 2116 anisotropy: this.anisotropy, 2117 2118 flipY: this.flipY, 2119 2120 generateMipmaps: this.generateMipmaps, 2121 premultiplyAlpha: this.premultiplyAlpha, 2122 unpackAlignment: this.unpackAlignment 2123 2124 }; 2125 2126 if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; 2127 2128 if ( ! isRootObject ) { 2129 2130 meta.textures[ this.uuid ] = output; 2131 2132 } 2133 2134 return output; 2135 2136 } 2137 2138 dispose() { 2139 2140 this.dispatchEvent( { type: 'dispose' } ); 2141 2142 } 2143 2144 transformUv( uv ) { 2145 2146 if ( this.mapping !== UVMapping ) return uv; 2147 2148 uv.applyMatrix3( this.matrix ); 2149 2150 if ( uv.x < 0 || uv.x > 1 ) { 2151 2152 switch ( this.wrapS ) { 2153 2154 case RepeatWrapping: 2155 2156 uv.x = uv.x - Math.floor( uv.x ); 2157 break; 2158
vendor: 995 bytes, lines 2159-2239
2159 case ClampToEdgeWrapping: 2160 2161 uv.x = uv.x < 0 ? 0 : 1; 2162 break; 2163 2164 case MirroredRepeatWrapping: 2165 2166 if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { 2167 2168 uv.x = Math.ceil( uv.x ) - uv.x; 2169 2170 } else { 2171 2172 uv.x = uv.x - Math.floor( uv.x ); 2173 2174 } 2175 2176 break; 2177 2178 } 2179 2180 } 2181 2182 if ( uv.y < 0 || uv.y > 1 ) { 2183 2184 switch ( this.wrapT ) { 2185 2186 case RepeatWrapping: 2187 2188 uv.y = uv.y - Math.floor( uv.y ); 2189 break; 2190 2191 case ClampToEdgeWrapping: 2192 2193 uv.y = uv.y < 0 ? 0 : 1; 2194 break; 2195 2196 case MirroredRepeatWrapping: 2197 2198 if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { 2199 2200 uv.y = Math.ceil( uv.y ) - uv.y; 2201 2202 } else { 2203 2204 uv.y = uv.y - Math.floor( uv.y ); 2205 2206 } 2207 2208 break; 2209 2210 } 2211 2212 } 2213 2214 if ( this.flipY ) { 2215 2216 uv.y = 1 - uv.y; 2217 2218 } 2219 2220 return uv; 2221 2222 } 2223 2224 set needsUpdate( value ) { 2225 2226 if ( value === true ) { 2227 2228 this.version ++; 2229 this.source.needsUpdate = true; 2230 2231 } 2232 2233 } 2234 2235 set needsPMREMUpdate( value ) { 2236 2237 if ( value === true ) { 2238 2239 this.pmremVersion ++
vendor: 13,852 bytes, lines 2239-3076
2239; 2240 2241 } 2242 2243 } 2244 2245} 2246 2247Texture.DEFAULT_IMAGE = null; 2248Texture.DEFAULT_MAPPING = UVMapping; 2249Texture.DEFAULT_ANISOTROPY = 1; 2250 2251class Vector4 { 2252 2253 constructor( x = 0, y = 0, z = 0, w = 1 ) { 2254 2255 Vector4.prototype.isVector4 = true; 2256 2257 this.x = x; 2258 this.y = y; 2259 this.z = z; 2260 this.w = w; 2261 2262 } 2263 2264 get width() { 2265 2266 return this.z; 2267 2268 } 2269 2270 set width( value ) { 2271 2272 this.z = value; 2273 2274 } 2275 2276 get height() { 2277 2278 return this.w; 2279 2280 } 2281 2282 set height( value ) { 2283 2284 this.w = value; 2285 2286 } 2287 2288 set( x, y, z, w ) { 2289 2290 this.x = x; 2291 this.y = y; 2292 this.z = z; 2293 this.w = w; 2294 2295 return this; 2296 2297 } 2298 2299 setScalar( scalar ) { 2300 2301 this.x = scalar; 2302 this.y = scalar; 2303 this.z = scalar; 2304 this.w = scalar; 2305 2306 return this; 2307 2308 } 2309 2310 setX( x ) { 2311 2312 this.x = x; 2313 2314 return this; 2315 2316 } 2317 2318 setY( y ) { 2319 2320 this.y = y; 2321 2322 return this; 2323 2324 } 2325 2326 setZ( z ) { 2327 2328 this.z = z; 2329 2330 return this; 2331 2332 } 2333 2334 setW( w ) { 2335 2336 this.w = w; 2337 2338 return this; 2339 2340 } 2341 2342 setComponent( index, value ) { 2343 2344 switch ( index ) { 2345 2346 case 0: this.x = value; break; 2347 case 1: this.y = value; break; 2348 case 2: this.z = value; break; 2349 case 3: this.w = value; break; 2350 default: throw new Error( 'index is out of range: ' + index ); 2351 2352 } 2353 2354 return this; 2355 2356 } 2357 2358 getComponent( index ) { 2359 2360 switch ( index ) { 2361 2362 case 0: return this.x; 2363 case 1: return this.y; 2364 case 2: return this.z; 2365 case 3: return this.w; 2366 default: throw new Error( 'index is out of range: ' + index ); 2367 2368 } 2369 2370 } 2371 2372 clone() { 2373 2374 return new this.constructor( this.x, this.y, this.z, this.w ); 2375 2376 } 2377 2378 copy( v ) { 2379 2380 this.x = v.x; 2381 this.y = v.y; 2382 this.z = v.z; 2383 this.w = ( v.w !== undefined ) ? v.w : 1; 2384 2385 return this; 2386 2387 } 2388 2389 add( v ) { 2390 2391 this.x += v.x; 2392 this.y += v.y; 2393 this.z += v.z; 2394 this.w += v.w; 2395 2396 return this; 2397 2398 } 2399 2400 addScalar( s ) { 2401 2402 this.x += s; 2403 this.y += s; 2404 this.z += s; 2405 this.w += s; 2406 2407 return this; 2408 2409 } 2410 2411 addVectors( a, b ) { 2412 2413 this.x = a.x + b.x; 2414 this.y = a.y + b.y; 2415 this.z = a.z + b.z; 2416 this.w = a.w + b.w; 2417 2418 return this; 2419 2420 } 2421 2422 addScaledVector( v, s ) { 2423 2424 this.x += v.x * s; 2425 this.y += v.y * s; 2426 this.z += v.z * s; 2427 this.w += v.w * s; 2428 2429 return this; 2430 2431 } 2432 2433 sub( v ) { 2434 2435 this.x -= v.x; 2436 this.y -= v.y; 2437 this.z -= v.z; 2438 this.w -= v.w; 2439 2440 return this; 2441 2442 } 2443 2444 subScalar( s ) { 2445 2446 this.x -= s; 2447 this.y -= s; 2448 this.z -= s; 2449 this.w -= s; 2450 2451 return this; 2452 2453 } 2454 2455 subVectors( a, b ) { 2456 2457 this.x = a.x - b.x; 2458 this.y = a.y - b.y; 2459 this.z = a.z - b.z; 2460 this.w = a.w - b.w; 2461 2462 return this; 2463 2464 } 2465 2466 multiply( v ) { 2467 2468 this.x *= v.x; 2469 this.y *= v.y; 2470 this.z *= v.z; 2471 this.w *= v.w; 2472 2473 return this; 2474 2475 } 2476 2477 multiplyScalar( scalar ) { 2478 2479 this.x *= scalar; 2480 this.y *= scalar; 2481 this.z *= scalar; 2482 this.w *= scalar; 2483 2484 return this; 2485 2486 } 2487 2488 applyMatrix4( m ) { 2489 2490 const x = this.x, y = this.y, z = this.z, w = this.w; 2491 const e = m.elements; 2492 2493 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; 2494 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; 2495 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; 2496 this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; 2497 2498 return this; 2499 2500 } 2501 2502 divideScalar( scalar ) { 2503 2504 return this.multiplyScalar( 1 / scalar ); 2505 2506 } 2507 2508 setAxisAngleFromQuaternion( q ) { 2509 2510 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm 2511 2512 // q is assumed to be normalized 2513 2514 this.w = 2 * Math.acos( q.w ); 2515 2516 const s = Math.sqrt( 1 - q.w * q.w ); 2517 2518 if ( s < 0.0001 ) { 2519 2520 this.x = 1; 2521 this.y = 0; 2522 this.z = 0; 2523 2524 } else { 2525 2526 this.x = q.x / s; 2527 this.y = q.y / s; 2528 this.z = q.z / s; 2529 2530 } 2531 2532 return this; 2533 2534 } 2535 2536 setAxisAngleFromRotationMatrix( m ) { 2537 2538 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm 2539 2540 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 2541 2542 let angle, x, y, z; // variables for result 2543 const epsilon = 0.01, // margin to allow for rounding errors 2544 epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees 2545 2546 te = m.elements, 2547 2548 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], 2549 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], 2550 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; 2551 2552 if ( ( Math.abs( m12 - m21 ) < epsilon ) && 2553 ( Math.abs( m13 - m31 ) < epsilon ) && 2554 ( Math.abs( m23 - m32 ) < epsilon ) ) { 2555 2556 // singularity found 2557 // first check for identity matrix which must have +1 for all terms 2558 // in leading diagonal and zero in other terms 2559 2560 if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && 2561 ( Math.abs( m13 + m31 ) < epsilon2 ) && 2562 ( Math.abs( m23 + m32 ) < epsilon2 ) && 2563 ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { 2564 2565 // this singularity is identity matrix so angle = 0 2566 2567 this.set( 1, 0, 0, 0 ); 2568 2569 return this; // zero angle, arbitrary axis 2570 2571 } 2572 2573 // otherwise this singularity is angle = 180 2574 2575 angle = Math.PI; 2576 2577 const xx = ( m11 + 1 ) / 2; 2578 const yy = ( m22 + 1 ) / 2; 2579 const zz = ( m33 + 1 ) / 2; 2580 const xy = ( m12 + m21 ) / 4; 2581 const xz = ( m13 + m31 ) / 4; 2582 const yz = ( m23 + m32 ) / 4; 2583 2584 if ( ( xx > yy ) && ( xx > zz ) ) { 2585 2586 // m11 is the largest diagonal term 2587 2588 if ( xx < epsilon ) { 2589 2590 x = 0; 2591 y = 0.707106781; 2592 z = 0.707106781; 2593 2594 } else { 2595 2596 x = Math.sqrt( xx ); 2597 y = xy / x; 2598 z = xz / x; 2599 2600 } 2601 2602 } else if ( yy > zz ) { 2603 2604 // m22 is the largest diagonal term 2605 2606 if ( yy < epsilon ) { 2607 2608 x = 0.707106781; 2609 y = 0; 2610 z = 0.707106781; 2611 2612 } else { 2613 2614 y = Math.sqrt( yy ); 2615 x = xy / y; 2616 z = yz / y; 2617 2618 } 2619 2620 } else { 2621 2622 // m33 is the largest diagonal term so base result on this 2623 2624 if ( zz < epsilon ) { 2625 2626 x = 0.707106781; 2627 y = 0.707106781; 2628 z = 0; 2629 2630 } else { 2631 2632 z = Math.sqrt( zz ); 2633 x = xz / z; 2634 y = yz / z; 2635 2636 } 2637 2638 } 2639 2640 this.set( x, y, z, angle ); 2641 2642 return this; // return 180 deg rotation 2643 2644 } 2645 2646 // as we have reached here there are no singularities so we can handle normally 2647 2648 let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + 2649 ( m13 - m31 ) * ( m13 - m31 ) + 2650 ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize 2651 2652 if ( Math.abs( s ) < 0.001 ) s = 1; 2653 2654 // prevent divide by zero, should not happen if matrix is orthogonal and should be 2655 // caught by singularity test above, but I've left it in just in case 2656 2657 this.x = ( m32 - m23 ) / s; 2658 this.y = ( m13 - m31 ) / s; 2659 this.z = ( m21 - m12 ) / s; 2660 this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); 2661 2662 return this; 2663 2664 } 2665 2666 min( v ) { 2667 2668 this.x = Math.min( this.x, v.x ); 2669 this.y = Math.min( this.y, v.y ); 2670 this.z = Math.min( this.z, v.z ); 2671 this.w = Math.min( this.w, v.w ); 2672 2673 return this; 2674 2675 } 2676 2677 max( v ) { 2678 2679 this.x = Math.max( this.x, v.x ); 2680 this.y = Math.max( this.y, v.y ); 2681 this.z = Math.max( this.z, v.z ); 2682 this.w = Math.max( this.w, v.w ); 2683 2684 return this; 2685 2686 } 2687 2688 clamp( min, max ) { 2689 2690 // assumes min < max, componentwise 2691 2692 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 2693 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 2694 this.z = Math.max( min.z, Math.min( max.z, this.z ) ); 2695 this.w = Math.max( min.w, Math.min( max.w, this.w ) ); 2696 2697 return this; 2698 2699 } 2700 2701 clampScalar( minVal, maxVal ) { 2702 2703 this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); 2704 this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); 2705 this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); 2706 this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); 2707 2708 return this; 2709 2710 } 2711 2712 clampLength( min, max ) { 2713 2714 const length = this.length(); 2715 2716 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 2717 2718 } 2719 2720 floor() { 2721 2722 this.x = Math.floor( this.x ); 2723 this.y = Math.floor( this.y ); 2724 this.z = Math.floor( this.z ); 2725 this.w = Math.floor( this.w ); 2726 2727 return this; 2728 2729 } 2730 2731 ceil() { 2732 2733 this.x = Math.ceil( this.x ); 2734 this.y = Math.ceil( this.y ); 2735 this.z = Math.ceil( this.z ); 2736 this.w = Math.ceil( this.w ); 2737 2738 return this; 2739 2740 } 2741 2742 round() { 2743 2744 this.x = Math.round( this.x ); 2745 this.y = Math.round( this.y ); 2746 this.z = Math.round( this.z ); 2747 this.w = Math.round( this.w ); 2748 2749 return this; 2750 2751 } 2752 2753 roundToZero() { 2754 2755 this.x = Math.trunc( this.x ); 2756 this.y = Math.trunc( this.y ); 2757 this.z = Math.trunc( this.z ); 2758 this.w = Math.trunc( this.w ); 2759 2760 return this; 2761 2762 } 2763 2764 negate() { 2765 2766 this.x = - this.x; 2767 this.y = - this.y; 2768 this.z = - this.z; 2769 this.w = - this.w; 2770 2771 return this; 2772 2773 } 2774 2775 dot( v ) { 2776 2777 return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; 2778 2779 } 2780 2781 lengthSq() { 2782 2783 return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; 2784 2785 } 2786 2787 length() { 2788 2789 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); 2790 2791 } 2792 2793 manhattanLength() { 2794 2795 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); 2796 2797 } 2798 2799 normalize() { 2800 2801 return this.divideScalar( this.length() || 1 ); 2802 2803 } 2804 2805 setLength( length ) { 2806 2807 return this.normalize().multiplyScalar( length ); 2808 2809 } 2810 2811 lerp( v, alpha ) { 2812 2813 this.x += ( v.x - this.x ) * alpha; 2814 this.y += ( v.y - this.y ) * alpha; 2815 this.z += ( v.z - this.z ) * alpha; 2816 this.w += ( v.w - this.w ) * alpha; 2817 2818 return this; 2819 2820 } 2821 2822 lerpVectors( v1, v2, alpha ) { 2823 2824 this.x = v1.x + ( v2.x - v1.x ) * alpha; 2825 this.y = v1.y + ( v2.y - v1.y ) * alpha; 2826 this.z = v1.z + ( v2.z - v1.z ) * alpha; 2827 this.w = v1.w + ( v2.w - v1.w ) * alpha; 2828 2829 return this; 2830 2831 } 2832 2833 equals( v ) { 2834 2835 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); 2836 2837 } 2838 2839 fromArray( array, offset = 0 ) { 2840 2841 this.x = array[ offset ]; 2842 this.y = array[ offset + 1 ]; 2843 this.z = array[ offset + 2 ]; 2844 this.w = array[ offset + 3 ]; 2845 2846 return this; 2847 2848 } 2849 2850 toArray( array = [], offset = 0 ) { 2851 2852 array[ offset ] = this.x; 2853 array[ offset + 1 ] = this.y; 2854 array[ offset + 2 ] = this.z; 2855 array[ offset + 3 ] = this.w; 2856 2857 return array; 2858 2859 } 2860 2861 fromBufferAttribute( attribute, index ) { 2862 2863 this.x = attribute.getX( index ); 2864 this.y = attribute.getY( index ); 2865 this.z = attribute.getZ( index ); 2866 this.w = attribute.getW( index ); 2867 2868 return this; 2869 2870 } 2871 2872 random() { 2873 2874 this.x = Math.random(); 2875 this.y = Math.random(); 2876 this.z = Math.random(); 2877 this.w = Math.random(); 2878 2879 return this; 2880 2881 } 2882 2883 *[ Symbol.iterator ]() { 2884 2885 yield this.x; 2886 yield this.y; 2887 yield this.z; 2888 yield this.w; 2889 2890 } 2891 2892} 2893 2894/* 2895 In options, we can specify: 2896 * Texture parameters for an auto-generated target texture 2897 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers 2898*/ 2899class RenderTarget extends EventDispatcher { 2900 2901 constructor( width = 1, height = 1, options = {} ) { 2902 2903 super(); 2904 2905 this.isRenderTarget = true; 2906 2907 this.width = width; 2908 this.height = height; 2909 this.depth = 1; 2910 2911 this.scissor = new Vector4( 0, 0, width, height ); 2912 this.scissorTest = false; 2913 2914 this.viewport = new Vector4( 0, 0, width, height ); 2915 2916 const image = { width: width, height: height, depth: 1 }; 2917 2918 options = Object.assign( { 2919 generateMipmaps: false, 2920 internalFormat: null, 2921 minFilter: LinearFilter, 2922 depthBuffer: true, 2923 stencilBuffer: false, 2924 depthTexture: null, 2925 samples: 0, 2926 count: 1 2927 }, options ); 2928 2929 const texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); 2930 2931 texture.flipY = false; 2932 texture.generateMipmaps = options.generateMipmaps; 2933 texture.internalFormat = options.internalFormat; 2934 2935 this.textures = []; 2936 2937 const count = options.count; 2938 for ( let i = 0; i < count; i ++ ) { 2939 2940 this.textures[ i ] = texture.clone(); 2941 this.textures[ i ].isRenderTargetTexture = true; 2942 2943 } 2944 2945 this.depthBuffer = options.depthBuffer; 2946 this.stencilBuffer = options.stencilBuffer; 2947 2948 this.depthTexture = options.depthTexture; 2949 2950 this.samples = options.samples; 2951 2952 } 2953 2954 get texture() { 2955 2956 return this.textures[ 0 ]; 2957 2958 } 2959 2960 set texture( value ) { 2961 2962 this.textures[ 0 ] = value; 2963 2964 } 2965 2966 setSize( width, height, depth = 1 ) { 2967 2968 if ( this.width !== width || this.height !== height || this.depth !== depth ) { 2969 2970 this.width = width; 2971 this.height = height; 2972 this.depth = depth; 2973 2974 for ( let i = 0, il = this.textures.length; i < il; i ++ ) { 2975 2976 this.textures[ i ].image.width = width; 2977 this.textures[ i ].image.height = height; 2978 this.textures[ i ].image.depth = depth; 2979 2980 } 2981 2982 this.dispose(); 2983 2984 } 2985 2986 this.viewport.set( 0, 0, width, height ); 2987 this.scissor.set( 0, 0, width, height ); 2988 2989 } 2990 2991 clone() { 2992 2993 return new this.constructor().copy( this ); 2994 2995 } 2996 2997 copy( source ) { 2998 2999 this.width = source.width; 3000 this.height = source.height; 3001 this.depth = source.depth; 3002 3003 this.scissor.copy( source.scissor ); 3004 this.scissorTest = source.scissorTest; 3005 3006 this.viewport.copy( source.viewport ); 3007 3008 this.textures.length = 0; 3009 3010 for ( let i = 0, il = source.textures.length; i < il; i ++ ) { 3011 3012 this.textures[ i ] = source.textures[ i ].clone(); 3013 this.textures[ i ].isRenderTargetTexture = true; 3014 3015 } 3016 3017 // ensure image object is not shared, see #20328 3018 3019 const image = Object.assign( {}, source.texture.image ); 3020 this.texture.source = new Source( image ); 3021 3022 this.depthBuffer = source.depthBuffer; 3023 this.stencilBuffer = source.stencilBuffer; 3024 3025 if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); 3026 3027 this.samples = source.samples; 3028 3029 return this; 3030 3031 } 3032 3033 dispose() { 3034 3035 this.dispatchEvent( { type: 'dispose' } ); 3036 3037 } 3038 3039} 3040 3041class WebGLRenderTarget extends RenderTarget { 3042 3043 constructor( width = 1, height = 1, options = {} ) { 3044 3045 super( width, height, options ); 3046 3047 this.isWebGLRenderTarget = true; 3048 3049 } 3050 3051} 3052 3053class DataArrayTexture extends Texture { 3054 3055 constructor( data = null, width = 1, height = 1, depth = 1 ) { 3056 3057 super( null ); 3058 3059 this.isDataArrayTexture = true; 3060 3061 this.image = { data, width, height, depth }; 3062 3063 this.magFilter = NearestFilter; 3064 this.minFilter = NearestFilter; 3065 3066 this.wrapR = ClampToEdgeWrapping; 3067 3068 this.generateMipmaps = false; 3069 this.flipY = false; 3070 this.unpackAlignment = 1; 3071 3072 } 3073 3074} 3075 3076class
vendor: 21,754 bytes, lines 3076-4355
3076WebGLArrayRenderTarget extends WebGLRenderTarget { 3077 3078 constructor( width = 1, height = 1, depth = 1, options = {} ) { 3079 3080 super( width, height, options ); 3081 3082 this.isWebGLArrayRenderTarget = true; 3083 3084 this.depth = depth; 3085 3086 this.texture = new DataArrayTexture( null, width, height, depth ); 3087 3088 this.texture.isRenderTargetTexture = true; 3089 3090 } 3091 3092} 3093 3094class Data3DTexture extends Texture { 3095 3096 constructor( data = null, width = 1, height = 1, depth = 1 ) { 3097 3098 // We're going to add .setXXX() methods for setting properties later. 3099 // Users can still set in DataTexture3D directly. 3100 // 3101 // const texture = new THREE.DataTexture3D( data, width, height, depth ); 3102 // texture.anisotropy = 16; 3103 // 3104 // See #14839 3105 3106 super( null ); 3107 3108 this.isData3DTexture = true; 3109 3110 this.image = { data, width, height, depth }; 3111 3112 this.magFilter = NearestFilter; 3113 this.minFilter = NearestFilter; 3114 3115 this.wrapR = ClampToEdgeWrapping; 3116 3117 this.generateMipmaps = false; 3118 this.flipY = false; 3119 this.unpackAlignment = 1; 3120 3121 } 3122 3123} 3124 3125class WebGL3DRenderTarget extends WebGLRenderTarget { 3126 3127 constructor( width = 1, height = 1, depth = 1, options = {} ) { 3128 3129 super( width, height, options ); 3130 3131 this.isWebGL3DRenderTarget = true; 3132 3133 this.depth = depth; 3134 3135 this.texture = new Data3DTexture( null, width, height, depth ); 3136 3137 this.texture.isRenderTargetTexture = true; 3138 3139 } 3140 3141} 3142 3143class Quaternion { 3144 3145 constructor( x = 0, y = 0, z = 0, w = 1 ) { 3146 3147 this.isQuaternion = true; 3148 3149 this._x = x; 3150 this._y = y; 3151 this._z = z; 3152 this._w = w; 3153 3154 } 3155 3156 static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { 3157 3158 // fuzz-free, array-based Quaternion SLERP operation 3159 3160 let x0 = src0[ srcOffset0 + 0 ], 3161 y0 = src0[ srcOffset0 + 1 ], 3162 z0 = src0[ srcOffset0 + 2 ], 3163 w0 = src0[ srcOffset0 + 3 ]; 3164 3165 const x1 = src1[ srcOffset1 + 0 ], 3166 y1 = src1[ srcOffset1 + 1 ], 3167 z1 = src1[ srcOffset1 + 2 ], 3168 w1 = src1[ srcOffset1 + 3 ]; 3169 3170 if ( t === 0 ) { 3171 3172 dst[ dstOffset + 0 ] = x0; 3173 dst[ dstOffset + 1 ] = y0; 3174 dst[ dstOffset + 2 ] = z0; 3175 dst[ dstOffset + 3 ] = w0; 3176 return; 3177 3178 } 3179 3180 if ( t === 1 ) { 3181 3182 dst[ dstOffset + 0 ] = x1; 3183 dst[ dstOffset + 1 ] = y1; 3184 dst[ dstOffset + 2 ] = z1; 3185 dst[ dstOffset + 3 ] = w1; 3186 return; 3187 3188 } 3189 3190 if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { 3191 3192 let s = 1 - t; 3193 const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, 3194 dir = ( cos >= 0 ? 1 : - 1 ), 3195 sqrSin = 1 - cos * cos; 3196 3197 // Skip the Slerp for tiny steps to avoid numeric problems: 3198 if ( sqrSin > Number.EPSILON ) { 3199 3200 const sin = Math.sqrt( sqrSin ), 3201 len = Math.atan2( sin, cos * dir ); 3202 3203 s = Math.sin( s * len ) / sin; 3204 t = Math.sin( t * len ) / sin; 3205 3206 } 3207 3208 const tDir = t * dir; 3209 3210 x0 = x0 * s + x1 * tDir; 3211 y0 = y0 * s + y1 * tDir; 3212 z0 = z0 * s + z1 * tDir; 3213 w0 = w0 * s + w1 * tDir; 3214 3215 // Normalize in case we just did a lerp: 3216 if ( s === 1 - t ) { 3217 3218 const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); 3219 3220 x0 *= f; 3221 y0 *= f; 3222 z0 *= f; 3223 w0 *= f; 3224 3225 } 3226 3227 } 3228 3229 dst[ dstOffset ] = x0; 3230 dst[ dstOffset + 1 ] = y0; 3231 dst[ dstOffset + 2 ] = z0; 3232 dst[ dstOffset + 3 ] = w0; 3233 3234 } 3235 3236 static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { 3237 3238 const x0 = src0[ srcOffset0 ]; 3239 const y0 = src0[ srcOffset0 + 1 ]; 3240 const z0 = src0[ srcOffset0 + 2 ]; 3241 const w0 = src0[ srcOffset0 + 3 ]; 3242 3243 const x1 = src1[ srcOffset1 ]; 3244 const y1 = src1[ srcOffset1 + 1 ]; 3245 const z1 = src1[ srcOffset1 + 2 ]; 3246 const w1 = src1[ srcOffset1 + 3 ]; 3247 3248 dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; 3249 dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; 3250 dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; 3251 dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; 3252 3253 return dst; 3254 3255 } 3256 3257 get x() { 3258 3259 return this._x; 3260 3261 } 3262 3263 set x( value ) { 3264 3265 this._x = value; 3266 this._onChangeCallback(); 3267 3268 } 3269 3270 get y() { 3271 3272 return this._y; 3273 3274 } 3275 3276 set y( value ) { 3277 3278 this._y = value; 3279 this._onChangeCallback(); 3280 3281 } 3282 3283 get z() { 3284 3285 return this._z; 3286 3287 } 3288 3289 set z( value ) { 3290 3291 this._z = value; 3292 this._onChangeCallback(); 3293 3294 } 3295 3296 get w() { 3297 3298 return this._w; 3299 3300 } 3301 3302 set w( value ) { 3303 3304 this._w = value; 3305 this._onChangeCallback(); 3306 3307 } 3308 3309 set( x, y, z, w ) { 3310 3311 this._x = x; 3312 this._y = y; 3313 this._z = z; 3314 this._w = w; 3315 3316 this._onChangeCallback(); 3317 3318 return this; 3319 3320 } 3321 3322 clone() { 3323 3324 return new this.constructor( this._x, this._y, this._z, this._w ); 3325 3326 } 3327 3328 copy( quaternion ) { 3329 3330 this._x = quaternion.x; 3331 this._y = quaternion.y; 3332 this._z = quaternion.z; 3333 this._w = quaternion.w; 3334 3335 this._onChangeCallback(); 3336 3337 return this; 3338 3339 } 3340 3341 setFromEuler( euler, update = true ) { 3342 3343 const x = euler._x, y = euler._y, z = euler._z, order = euler._order; 3344 3345 // http://www.mathworks.com/matlabcentral/fileexchange/ 3346 // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ 3347 // content/SpinCalc.m 3348 3349 const cos = Math.cos; 3350 const sin = Math.sin; 3351 3352 const c1 = cos( x / 2 ); 3353 const c2 = cos( y / 2 ); 3354 const c3 = cos( z / 2 ); 3355 3356 const s1 = sin( x / 2 ); 3357 const s2 = sin( y / 2 ); 3358 const s3 = sin( z / 2 ); 3359 3360 switch ( order ) { 3361 3362 case 'XYZ': 3363 this._x = s1 * c2 * c3 + c1 * s2 * s3; 3364 this._y = c1 * s2 * c3 - s1 * c2 * s3; 3365 this._z = c1 * c2 * s3 + s1 * s2 * c3; 3366 this._w = c1 * c2 * c3 - s1 * s2 * s3; 3367 break; 3368 3369 case 'YXZ': 3370 this._x = s1 * c2 * c3 + c1 * s2 * s3; 3371 this._y = c1 * s2 * c3 - s1 * c2 * s3; 3372 this._z = c1 * c2 * s3 - s1 * s2 * c3; 3373 this._w = c1 * c2 * c3 + s1 * s2 * s3; 3374 break; 3375 3376 case 'ZXY': 3377 this._x = s1 * c2 * c3 - c1 * s2 * s3; 3378 this._y = c1 * s2 * c3 + s1 * c2 * s3; 3379 this._z = c1 * c2 * s3 + s1 * s2 * c3; 3380 this._w = c1 * c2 * c3 - s1 * s2 * s3; 3381 break; 3382 3383 case 'ZYX': 3384 this._x = s1 * c2 * c3 - c1 * s2 * s3; 3385 this._y = c1 * s2 * c3 + s1 * c2 * s3; 3386 this._z = c1 * c2 * s3 - s1 * s2 * c3; 3387 this._w = c1 * c2 * c3 + s1 * s2 * s3; 3388 break; 3389 3390 case 'YZX': 3391 this._x = s1 * c2 * c3 + c1 * s2 * s3; 3392 this._y = c1 * s2 * c3 + s1 * c2 * s3; 3393 this._z = c1 * c2 * s3 - s1 * s2 * c3; 3394 this._w = c1 * c2 * c3 - s1 * s2 * s3; 3395 break; 3396 3397 case 'XZY': 3398 this._x = s1 * c2 * c3 - c1 * s2 * s3; 3399 this._y = c1 * s2 * c3 - s1 * c2 * s3; 3400 this._z = c1 * c2 * s3 + s1 * s2 * c3; 3401 this._w = c1 * c2 * c3 + s1 * s2 * s3; 3402 break; 3403 3404 default: 3405 console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); 3406 3407 } 3408 3409 if ( update === true ) this._onChangeCallback(); 3410 3411 return this; 3412 3413 } 3414 3415 setFromAxisAngle( axis, angle ) { 3416 3417 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm 3418 3419 // assumes axis is normalized 3420 3421 const halfAngle = angle / 2, s = Math.sin( halfAngle ); 3422 3423 this._x = axis.x * s; 3424 this._y = axis.y * s; 3425 this._z = axis.z * s; 3426 this._w = Math.cos( halfAngle ); 3427 3428 this._onChangeCallback(); 3429 3430 return this; 3431 3432 } 3433 3434 setFromRotationMatrix( m ) { 3435 3436 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm 3437 3438 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 3439 3440 const te = m.elements, 3441 3442 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], 3443 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], 3444 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], 3445 3446 trace = m11 + m22 + m33; 3447 3448 if ( trace > 0 ) { 3449 3450 const s = 0.5 / Math.sqrt( trace + 1.0 ); 3451 3452 this._w = 0.25 / s; 3453 this._x = ( m32 - m23 ) * s; 3454 this._y = ( m13 - m31 ) * s; 3455 this._z = ( m21 - m12 ) * s; 3456 3457 } else if ( m11 > m22 && m11 > m33 ) { 3458 3459 const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); 3460 3461 this._w = ( m32 - m23 ) / s; 3462 this._x = 0.25 * s; 3463 this._y = ( m12 + m21 ) / s; 3464 this._z = ( m13 + m31 ) / s; 3465 3466 } else if ( m22 > m33 ) { 3467 3468 const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); 3469 3470 this._w = ( m13 - m31 ) / s; 3471 this._x = ( m12 + m21 ) / s; 3472 this._y = 0.25 * s; 3473 this._z = ( m23 + m32 ) / s; 3474 3475 } else { 3476 3477 const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); 3478 3479 this._w = ( m21 - m12 ) / s; 3480 this._x = ( m13 + m31 ) / s; 3481 this._y = ( m23 + m32 ) / s; 3482 this._z = 0.25 * s; 3483 3484 } 3485 3486 this._onChangeCallback(); 3487 3488 return this; 3489 3490 } 3491 3492 setFromUnitVectors( vFrom, vTo ) { 3493 3494 // assumes direction vectors vFrom and vTo are normalized 3495 3496 let r = vFrom.dot( vTo ) + 1; 3497 3498 if ( r < Number.EPSILON ) { 3499 3500 // vFrom and vTo point in opposite directions 3501 3502 r = 0; 3503 3504 if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { 3505 3506 this._x = - vFrom.y; 3507 this._y = vFrom.x; 3508 this._z = 0; 3509 this._w = r; 3510 3511 } else { 3512 3513 this._x = 0; 3514 this._y = - vFrom.z; 3515 this._z = vFrom.y; 3516 this._w = r; 3517 3518 } 3519 3520 } else { 3521 3522 // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 3523 3524 this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; 3525 this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; 3526 this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; 3527 this._w = r; 3528 3529 } 3530 3531 return this.normalize(); 3532 3533 } 3534 3535 angleTo( q ) { 3536 3537 return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); 3538 3539 } 3540 3541 rotateTowards( q, step ) { 3542 3543 const angle = this.angleTo( q ); 3544 3545 if ( angle === 0 ) return this; 3546 3547 const t = Math.min( 1, step / angle ); 3548 3549 this.slerp( q, t ); 3550 3551 return this; 3552 3553 } 3554 3555 identity() { 3556 3557 return this.set( 0, 0, 0, 1 ); 3558 3559 } 3560 3561 invert() { 3562 3563 // quaternion is assumed to have unit length 3564 3565 return this.conjugate(); 3566 3567 } 3568 3569 conjugate() { 3570 3571 this._x *= - 1; 3572 this._y *= - 1; 3573 this._z *= - 1; 3574 3575 this._onChangeCallback(); 3576 3577 return this; 3578 3579 } 3580 3581 dot( v ) { 3582 3583 return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; 3584 3585 } 3586 3587 lengthSq() { 3588 3589 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; 3590 3591 } 3592 3593 length() { 3594 3595 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); 3596 3597 } 3598 3599 normalize() { 3600 3601 let l = this.length(); 3602 3603 if ( l === 0 ) { 3604 3605 this._x = 0; 3606 this._y = 0; 3607 this._z = 0; 3608 this._w = 1; 3609 3610 } else { 3611 3612 l = 1 / l; 3613 3614 this._x = this._x * l; 3615 this._y = this._y * l; 3616 this._z = this._z * l; 3617 this._w = this._w * l; 3618 3619 } 3620 3621 this._onChangeCallback(); 3622 3623 return this; 3624 3625 } 3626 3627 multiply( q ) { 3628 3629 return this.multiplyQuaternions( this, q ); 3630 3631 } 3632 3633 premultiply( q ) { 3634 3635 return this.multiplyQuaternions( q, this ); 3636 3637 } 3638 3639 multiplyQuaternions( a, b ) { 3640 3641 // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm 3642 3643 const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; 3644 const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; 3645 3646 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; 3647 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; 3648 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; 3649 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; 3650 3651 this._onChangeCallback(); 3652 3653 return this; 3654 3655 } 3656 3657 slerp( qb, t ) { 3658 3659 if ( t === 0 ) return this; 3660 if ( t === 1 ) return this.copy( qb ); 3661 3662 const x = this._x, y = this._y, z = this._z, w = this._w; 3663 3664 // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ 3665 3666 let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; 3667 3668 if ( cosHalfTheta < 0 ) { 3669 3670 this._w = - qb._w; 3671 this._x = - qb._x; 3672 this._y = - qb._y; 3673 this._z = - qb._z; 3674 3675 cosHalfTheta = - cosHalfTheta; 3676 3677 } else { 3678 3679 this.copy( qb ); 3680 3681 } 3682 3683 if ( cosHalfTheta >= 1.0 ) { 3684 3685 this._w = w; 3686 this._x = x; 3687 this._y = y; 3688 this._z = z; 3689 3690 return this; 3691 3692 } 3693 3694 const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; 3695 3696 if ( sqrSinHalfTheta <= Number.EPSILON ) { 3697 3698 const s = 1 - t; 3699 this._w = s * w + t * this._w; 3700 this._x = s * x + t * this._x; 3701 this._y = s * y + t * this._y; 3702 this._z = s * z + t * this._z; 3703 3704 this.normalize(); // normalize calls _onChangeCallback() 3705 3706 return this; 3707 3708 } 3709 3710 const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); 3711 const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); 3712 const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, 3713 ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; 3714 3715 this._w = ( w * ratioA + this._w * ratioB ); 3716 this._x = ( x * ratioA + this._x * ratioB ); 3717 this._y = ( y * ratioA + this._y * ratioB ); 3718 this._z = ( z * ratioA + this._z * ratioB ); 3719 3720 this._onChangeCallback(); 3721 3722 return this; 3723 3724 } 3725 3726 slerpQuaternions( qa, qb, t ) { 3727 3728 return this.copy( qa ).slerp( qb, t ); 3729 3730 } 3731 3732 random() { 3733 3734 // sets this quaternion to a uniform random unit quaternnion 3735 3736 // Ken Shoemake 3737 // Uniform random rotations 3738 // D. Kirk, editor, Graphics Gems III, pages 124-132. Academic Press, New York, 1992. 3739 3740 const theta1 = 2 * Math.PI * Math.random(); 3741 const theta2 = 2 * Math.PI * Math.random(); 3742 3743 const x0 = Math.random(); 3744 const r1 = Math.sqrt( 1 - x0 ); 3745 const r2 = Math.sqrt( x0 ); 3746 3747 return this.set( 3748 r1 * Math.sin( theta1 ), 3749 r1 * Math.cos( theta1 ), 3750 r2 * Math.sin( theta2 ), 3751 r2 * Math.cos( theta2 ), 3752 ); 3753 3754 } 3755 3756 equals( quaternion ) { 3757 3758 return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); 3759 3760 } 3761 3762 fromArray( array, offset = 0 ) { 3763 3764 this._x = array[ offset ]; 3765 this._y = array[ offset + 1 ]; 3766 this._z = array[ offset + 2 ]; 3767 this._w = array[ offset + 3 ]; 3768 3769 this._onChangeCallback(); 3770 3771 return this; 3772 3773 } 3774 3775 toArray( array = [], offset = 0 ) { 3776 3777 array[ offset ] = this._x; 3778 array[ offset + 1 ] = this._y; 3779 array[ offset + 2 ] = this._z; 3780 array[ offset + 3 ] = this._w; 3781 3782 return array; 3783 3784 } 3785 3786 fromBufferAttribute( attribute, index ) { 3787 3788 this._x = attribute.getX( index ); 3789 this._y = attribute.getY( index ); 3790 this._z = attribute.getZ( index ); 3791 this._w = attribute.getW( index ); 3792 3793 this._onChangeCallback(); 3794 3795 return this; 3796 3797 } 3798 3799 toJSON() { 3800 3801 return this.toArray(); 3802 3803 } 3804 3805 _onChange( callback ) { 3806 3807 this._onChangeCallback = callback; 3808 3809 return this; 3810 3811 } 3812 3813 _onChangeCallback() {} 3814 3815 *[ Symbol.iterator ]() { 3816 3817 yield this._x; 3818 yield this._y; 3819 yield this._z; 3820 yield this._w; 3821 3822 } 3823 3824} 3825 3826class Vector3 { 3827 3828 constructor( x = 0, y = 0, z = 0 ) { 3829 3830 Vector3.prototype.isVector3 = true; 3831 3832 this.x = x; 3833 this.y = y; 3834 this.z = z; 3835 3836 } 3837 3838 set( x, y, z ) { 3839 3840 if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) 3841 3842 this.x = x; 3843 this.y = y; 3844 this.z = z; 3845 3846 return this; 3847 3848 } 3849 3850 setScalar( scalar ) { 3851 3852 this.x = scalar; 3853 this.y = scalar; 3854 this.z = scalar; 3855 3856 return this; 3857 3858 } 3859 3860 setX( x ) { 3861 3862 this.x = x; 3863 3864 return this; 3865 3866 } 3867 3868 setY( y ) { 3869 3870 this.y = y; 3871 3872 return this; 3873 3874 } 3875 3876 setZ( z ) { 3877 3878 this.z = z; 3879 3880 return this; 3881 3882 } 3883 3884 setComponent( index, value ) { 3885 3886 switch ( index ) { 3887 3888 case 0: this.x = value; break; 3889 case 1: this.y = value; break; 3890 case 2: this.z = value; break; 3891 default: throw new Error( 'index is out of range: ' + index ); 3892 3893 } 3894 3895 return this; 3896 3897 } 3898 3899 getComponent( index ) { 3900 3901 switch ( index ) { 3902 3903 case 0: return this.x; 3904 case 1: return this.y; 3905 case 2: return this.z; 3906 default: throw new Error( 'index is out of range: ' + index ); 3907 3908 } 3909 3910 } 3911 3912 clone() { 3913 3914 return new this.constructor( this.x, this.y, this.z ); 3915 3916 } 3917 3918 copy( v ) { 3919 3920 this.x = v.x; 3921 this.y = v.y; 3922 this.z = v.z; 3923 3924 return this; 3925 3926 } 3927 3928 add( v ) { 3929 3930 this.x += v.x; 3931 this.y += v.y; 3932 this.z += v.z; 3933 3934 return this; 3935 3936 } 3937 3938 addScalar( s ) { 3939 3940 this.x += s; 3941 this.y += s; 3942 this.z += s; 3943 3944 return this; 3945 3946 } 3947 3948 addVectors( a, b ) { 3949 3950 this.x = a.x + b.x; 3951 this.y = a.y + b.y; 3952 this.z = a.z + b.z; 3953 3954 return this; 3955 3956 } 3957 3958 addScaledVector( v, s ) { 3959 3960 this.x += v.x * s; 3961 this.y += v.y * s; 3962 this.z += v.z * s; 3963 3964 return this; 3965 3966 } 3967 3968 sub( v ) { 3969 3970 this.x -= v.x; 3971 this.y -= v.y; 3972 this.z -= v.z; 3973 3974 return this; 3975 3976 } 3977 3978 subScalar( s ) { 3979 3980 this.x -= s; 3981 this.y -= s; 3982 this.z -= s; 3983 3984 return this; 3985 3986 } 3987 3988 subVectors( a, b ) { 3989 3990 this.x = a.x - b.x; 3991 this.y = a.y - b.y; 3992 this.z = a.z - b.z; 3993 3994 return this; 3995 3996 } 3997 3998 multiply( v ) { 3999 4000 this.x *= v.x; 4001 this.y *= v.y; 4002 this.z *= v.z; 4003 4004 return this; 4005 4006 } 4007 4008 multiplyScalar( scalar ) { 4009 4010 this.x *= scalar; 4011 this.y *= scalar; 4012 this.z *= scalar; 4013 4014 return this; 4015 4016 } 4017 4018 multiplyVectors( a, b ) { 4019 4020 this.x = a.x * b.x; 4021 this.y = a.y * b.y; 4022 this.z = a.z * b.z; 4023 4024 return this; 4025 4026 } 4027 4028 applyEuler( euler ) { 4029 4030 return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); 4031 4032 } 4033 4034 applyAxisAngle( axis, angle ) { 4035 4036 return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); 4037 4038 } 4039 4040 applyMatrix3( m ) { 4041 4042 const x = this.x, y = this.y, z = this.z; 4043 const e = m.elements; 4044 4045 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; 4046 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; 4047 this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; 4048 4049 return this; 4050 4051 } 4052 4053 applyNormalMatrix( m ) { 4054 4055 return this.applyMatrix3( m ).normalize(); 4056 4057 } 4058 4059 applyMatrix4( m ) { 4060 4061 const x = this.x, y = this.y, z = this.z; 4062 const e = m.elements; 4063 4064 const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); 4065 4066 this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; 4067 this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; 4068 this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; 4069 4070 return this; 4071 4072 } 4073 4074 applyQuaternion( q ) { 4075 4076 // quaternion q is assumed to have unit length 4077 4078 const vx = this.x, vy = this.y, vz = this.z; 4079 const qx = q.x, qy = q.y, qz = q.z, qw = q.w; 4080 4081 // t = 2 * cross( q.xyz, v ); 4082 const tx = 2 * ( qy * vz - qz * vy ); 4083 const ty = 2 * ( qz * vx - qx * vz ); 4084 const tz = 2 * ( qx * vy - qy * vx ); 4085 4086 // v + q.w * t + cross( q.xyz, t ); 4087 this.x = vx + qw * tx + qy * tz - qz * ty; 4088 this.y = vy + qw * ty + qz * tx - qx * tz; 4089 this.z = vz + qw * tz + qx * ty - qy * tx; 4090 4091 return this; 4092 4093 } 4094 4095 project( camera ) { 4096 4097 return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); 4098 4099 } 4100 4101 unproject( camera ) { 4102 4103 return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); 4104 4105 } 4106 4107 transformDirection( m ) { 4108 4109 // input: THREE.Matrix4 affine matrix 4110 // vector interpreted as a direction 4111 4112 const x = this.x, y = this.y, z = this.z; 4113 const e = m.elements; 4114 4115 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; 4116 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; 4117 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; 4118 4119 return this.normalize(); 4120 4121 } 4122 4123 divide( v ) { 4124 4125 this.x /= v.x; 4126 this.y /= v.y; 4127 this.z /= v.z; 4128 4129 return this; 4130 4131 } 4132 4133 divideScalar( scalar ) { 4134 4135 return this.multiplyScalar( 1 / scalar ); 4136 4137 } 4138 4139 min( v ) { 4140 4141 this.x = Math.min( this.x, v.x ); 4142 this.y = Math.min( this.y, v.y ); 4143 this.z = Math.min( this.z, v.z ); 4144 4145 return this; 4146 4147 } 4148 4149 max( v ) { 4150 4151 this.x = Math.max( this.x, v.x ); 4152 this.y = Math.max( this.y, v.y ); 4153 this.z = Math.max( this.z, v.z ); 4154 4155 return this; 4156 4157 } 4158 4159 clamp( min, max ) { 4160 4161 // assumes min < max, componentwise 4162 4163 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 4164 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 4165 this.z = Math.max( min.z, Math.min( max.z, this.z ) ); 4166 4167 return this; 4168 4169 } 4170 4171 clampScalar( minVal, maxVal ) { 4172 4173 this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); 4174 this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); 4175 this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); 4176 4177 return this; 4178 4179 } 4180 4181 clampLength( min, max ) { 4182 4183 const length = this.length(); 4184 4185 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 4186 4187 } 4188 4189 floor() { 4190 4191 this.x = Math.floor( this.x ); 4192 this.y = Math.floor( this.y ); 4193 this.z = Math.floor( this.z ); 4194 4195 return this; 4196 4197 } 4198 4199 ceil() { 4200 4201 this.x = Math.ceil( this.x ); 4202 this.y = Math.ceil( this.y ); 4203 this.z = Math.ceil( this.z ); 4204 4205 return this; 4206 4207 } 4208 4209 round() { 4210 4211 this.x = Math.round( this.x ); 4212 this.y = Math.round( this.y ); 4213 this.z = Math.round( this.z ); 4214 4215 return this; 4216 4217 } 4218 4219 roundToZero() { 4220 4221 this.x = Math.trunc( this.x ); 4222 this.y = Math.trunc( this.y ); 4223 this.z = Math.trunc( this.z ); 4224 4225 return this; 4226 4227 } 4228 4229 negate() { 4230 4231 this.x = - this.x; 4232 this.y = - this.y; 4233 this.z = - this.z; 4234 4235 return this; 4236 4237 } 4238 4239 dot( v ) { 4240 4241 return this.x * v.x + this.y * v.y + this.z * v.z; 4242 4243 } 4244 4245 // TODO lengthSquared? 4246 4247 lengthSq() { 4248 4249 return this.x * this.x + this.y * this.y + this.z * this.z; 4250 4251 } 4252 4253 length() { 4254 4255 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); 4256 4257 } 4258 4259 manhattanLength() { 4260 4261 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); 4262 4263 } 4264 4265 normalize() { 4266 4267 return this.divideScalar( this.length() || 1 ); 4268 4269 } 4270 4271 setLength( length ) { 4272 4273 return this.normalize().multiplyScalar( length ); 4274 4275 } 4276 4277 lerp( v, alpha ) { 4278 4279 this.x += ( v.x - this.x ) * alpha; 4280 this.y += ( v.y - this.y ) * alpha; 4281 this.z += ( v.z - this.z ) * alpha; 4282 4283 return this; 4284 4285 } 4286 4287 lerpVectors( v1, v2, alpha ) { 4288 4289 this.x = v1.x + ( v2.x - v1.x ) * alpha; 4290 this.y = v1.y + ( v2.y - v1.y ) * alpha; 4291 this.z = v1.z + ( v2.z - v1.z ) * alpha; 4292 4293 return this; 4294 4295 } 4296 4297 cross( v ) { 4298 4299 return this.crossVectors( this, v ); 4300 4301 } 4302 4303 crossVectors( a, b ) { 4304 4305 const ax = a.x, ay = a.y, az = a.z; 4306 const bx = b.x, by = b.y, bz = b.z; 4307 4308 this.x = ay * bz - az * by; 4309 this.y = az * bx - ax * bz; 4310 this.z = ax * by - ay * bx; 4311 4312 return this; 4313 4314 } 4315 4316 projectOnVector( v ) { 4317 4318 const denominator = v.lengthSq(); 4319 4320 if ( denominator === 0 ) return this.set( 0, 0, 0 ); 4321 4322 const scalar = v.dot( this ) / denominator; 4323 4324 return this.copy( v ).multiplyScalar( scalar ); 4325 4326 } 4327 4328 projectOnPlane( planeNormal ) { 4329 4330 _vector$c.copy( this ).projectOnVector( planeNormal ); 4331 4332 return this.sub( _vector$c ); 4333 4334 } 4335 4336 reflect( normal ) { 4337 4338 // reflect incident vector off plane orthogonal to normal 4339 // normal is assumed to have unit length 4340 4341 return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); 4342 4343 } 4344 4345 angleTo( v ) { 4346 4347 const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); 4348 4349 if ( denominator === 0 ) return Math.PI / 2; 4350 4351 const theta = this.dot( v ) / denominator; 4352 4353 // clamp, to handle numerical problems 4354 4355 return Math.acos( clamp( theta, -
vendor: 14,574 bytes, lines 4355-5083
43551, 1 ) ); 4356 4357 } 4358 4359 distanceTo( v ) { 4360 4361 return Math.sqrt( this.distanceToSquared( v ) ); 4362 4363 } 4364 4365 distanceToSquared( v ) { 4366 4367 const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; 4368 4369 return dx * dx + dy * dy + dz * dz; 4370 4371 } 4372 4373 manhattanDistanceTo( v ) { 4374 4375 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); 4376 4377 } 4378 4379 setFromSpherical( s ) { 4380 4381 return this.setFromSphericalCoords( s.radius, s.phi, s.theta ); 4382 4383 } 4384 4385 setFromSphericalCoords( radius, phi, theta ) { 4386 4387 const sinPhiRadius = Math.sin( phi ) * radius; 4388 4389 this.x = sinPhiRadius * Math.sin( theta ); 4390 this.y = Math.cos( phi ) * radius; 4391 this.z = sinPhiRadius * Math.cos( theta ); 4392 4393 return this; 4394 4395 } 4396 4397 setFromCylindrical( c ) { 4398 4399 return this.setFromCylindricalCoords( c.radius, c.theta, c.y ); 4400 4401 } 4402 4403 setFromCylindricalCoords( radius, theta, y ) { 4404 4405 this.x = radius * Math.sin( theta ); 4406 this.y = y; 4407 this.z = radius * Math.cos( theta ); 4408 4409 return this; 4410 4411 } 4412 4413 setFromMatrixPosition( m ) { 4414 4415 const e = m.elements; 4416 4417 this.x = e[ 12 ]; 4418 this.y = e[ 13 ]; 4419 this.z = e[ 14 ]; 4420 4421 return this; 4422 4423 } 4424 4425 setFromMatrixScale( m ) { 4426 4427 const sx = this.setFromMatrixColumn( m, 0 ).length(); 4428 const sy = this.setFromMatrixColumn( m, 1 ).length(); 4429 const sz = this.setFromMatrixColumn( m, 2 ).length(); 4430 4431 this.x = sx; 4432 this.y = sy; 4433 this.z = sz; 4434 4435 return this; 4436 4437 } 4438 4439 setFromMatrixColumn( m, index ) { 4440 4441 return this.fromArray( m.elements, index * 4 ); 4442 4443 } 4444 4445 setFromMatrix3Column( m, index ) { 4446 4447 return this.fromArray( m.elements, index * 3 ); 4448 4449 } 4450 4451 setFromEuler( e ) { 4452 4453 this.x = e._x; 4454 this.y = e._y; 4455 this.z = e._z; 4456 4457 return this; 4458 4459 } 4460 4461 setFromColor( c ) { 4462 4463 this.x = c.r; 4464 this.y = c.g; 4465 this.z = c.b; 4466 4467 return this; 4468 4469 } 4470 4471 equals( v ) { 4472 4473 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); 4474 4475 } 4476 4477 fromArray( array, offset = 0 ) { 4478 4479 this.x = array[ offset ]; 4480 this.y = array[ offset + 1 ]; 4481 this.z = array[ offset + 2 ]; 4482 4483 return this; 4484 4485 } 4486 4487 toArray( array = [], offset = 0 ) { 4488 4489 array[ offset ] = this.x; 4490 array[ offset + 1 ] = this.y; 4491 array[ offset + 2 ] = this.z; 4492 4493 return array; 4494 4495 } 4496 4497 fromBufferAttribute( attribute, index ) { 4498 4499 this.x = attribute.getX( index ); 4500 this.y = attribute.getY( index ); 4501 this.z = attribute.getZ( index ); 4502 4503 return this; 4504 4505 } 4506 4507 random() { 4508 4509 this.x = Math.random(); 4510 this.y = Math.random(); 4511 this.z = Math.random(); 4512 4513 return this; 4514 4515 } 4516 4517 randomDirection() { 4518 4519 // https://mathworld.wolfram.com/SpherePointPicking.html 4520 4521 const theta = Math.random() * Math.PI * 2; 4522 const u = Math.random() * 2 - 1; 4523 const c = Math.sqrt( 1 - u * u ); 4524 4525 this.x = c * Math.cos( theta ); 4526 this.y = u; 4527 this.z = c * Math.sin( theta ); 4528 4529 return this; 4530 4531 } 4532 4533 *[ Symbol.iterator ]() { 4534 4535 yield this.x; 4536 yield this.y; 4537 yield this.z; 4538 4539 } 4540 4541} 4542 4543const _vector$c = /*@__PURE__*/ new Vector3(); 4544const _quaternion$4 = /*@__PURE__*/ new Quaternion(); 4545 4546class Box3 { 4547 4548 constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) { 4549 4550 this.isBox3 = true; 4551 4552 this.min = min; 4553 this.max = max; 4554 4555 } 4556 4557 set( min, max ) { 4558 4559 this.min.copy( min ); 4560 this.max.copy( max ); 4561 4562 return this; 4563 4564 } 4565 4566 setFromArray( array ) { 4567 4568 this.makeEmpty(); 4569 4570 for ( let i = 0, il = array.length; i < il; i += 3 ) { 4571 4572 this.expandByPoint( _vector$b.fromArray( array, i ) ); 4573 4574 } 4575 4576 return this; 4577 4578 } 4579 4580 setFromBufferAttribute( attribute ) { 4581 4582 this.makeEmpty(); 4583 4584 for ( let i = 0, il = attribute.count; i < il; i ++ ) { 4585 4586 this.expandByPoint( _vector$b.fromBufferAttribute( attribute, i ) ); 4587 4588 } 4589 4590 return this; 4591 4592 } 4593 4594 setFromPoints( points ) { 4595 4596 this.makeEmpty(); 4597 4598 for ( let i = 0, il = points.length; i < il; i ++ ) { 4599 4600 this.expandByPoint( points[ i ] ); 4601 4602 } 4603 4604 return this; 4605 4606 } 4607 4608 setFromCenterAndSize( center, size ) { 4609 4610 const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); 4611 4612 this.min.copy( center ).sub( halfSize ); 4613 this.max.copy( center ).add( halfSize ); 4614 4615 return this; 4616 4617 } 4618 4619 setFromObject( object, precise = false ) { 4620 4621 this.makeEmpty(); 4622 4623 return this.expandByObject( object, precise ); 4624 4625 } 4626 4627 clone() { 4628 4629 return new this.constructor().copy( this ); 4630 4631 } 4632 4633 copy( box ) { 4634 4635 this.min.copy( box.min ); 4636 this.max.copy( box.max ); 4637 4638 return this; 4639 4640 } 4641 4642 makeEmpty() { 4643 4644 this.min.x = this.min.y = this.min.z = + Infinity; 4645 this.max.x = this.max.y = this.max.z = - Infinity; 4646 4647 return this; 4648 4649 } 4650 4651 isEmpty() { 4652 4653 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes 4654 4655 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); 4656 4657 } 4658 4659 getCenter( target ) { 4660 4661 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); 4662 4663 } 4664 4665 getSize( target ) { 4666 4667 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min ); 4668 4669 } 4670 4671 expandByPoint( point ) { 4672 4673 this.min.min( point ); 4674 this.max.max( point ); 4675 4676 return this; 4677 4678 } 4679 4680 expandByVector( vector ) { 4681 4682 this.min.sub( vector ); 4683 this.max.add( vector ); 4684 4685 return this; 4686 4687 } 4688 4689 expandByScalar( scalar ) { 4690 4691 this.min.addScalar( - scalar ); 4692 this.max.addScalar( scalar ); 4693 4694 return this; 4695 4696 } 4697 4698 expandByObject( object, precise = false ) { 4699 4700 // Computes the world-axis-aligned bounding box of an object (including its children), 4701 // accounting for both the object's, and children's, world transforms 4702 4703 object.updateWorldMatrix( false, false ); 4704 4705 const geometry = object.geometry; 4706 4707 if ( geometry !== undefined ) { 4708 4709 const positionAttribute = geometry.getAttribute( 'position' ); 4710 4711 // precise AABB computation based on vertex data requires at least a position attribute. 4712 // instancing isn't supported so far and uses the normal (conservative) code path. 4713 4714 if ( precise === true && positionAttribute !== undefined && object.isInstancedMesh !== true ) { 4715 4716 for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) { 4717 4718 if ( object.isMesh === true ) { 4719 4720 object.getVertexPosition( i, _vector$b ); 4721 4722 } else { 4723 4724 _vector$b.fromBufferAttribute( positionAttribute, i ); 4725 4726 } 4727 4728 _vector$b.applyMatrix4( object.matrixWorld ); 4729 this.expandByPoint( _vector$b ); 4730 4731 } 4732 4733 } else { 4734 4735 if ( object.boundingBox !== undefined ) { 4736 4737 // object-level bounding box 4738 4739 if ( object.boundingBox === null ) { 4740 4741 object.computeBoundingBox(); 4742 4743 } 4744 4745 _box$4.copy( object.boundingBox ); 4746 4747 4748 } else { 4749 4750 // geometry-level bounding box 4751 4752 if ( geometry.boundingBox === null ) { 4753 4754 geometry.computeBoundingBox(); 4755 4756 } 4757 4758 _box$4.copy( geometry.boundingBox ); 4759 4760 } 4761 4762 _box$4.applyMatrix4( object.matrixWorld ); 4763 4764 this.union( _box$4 ); 4765 4766 } 4767 4768 } 4769 4770 const children = object.children; 4771 4772 for ( let i = 0, l = children.length; i < l; i ++ ) { 4773 4774 this.expandByObject( children[ i ], precise ); 4775 4776 } 4777 4778 return this; 4779 4780 } 4781 4782 containsPoint( point ) { 4783 4784 return point.x < this.min.x || point.x > this.max.x || 4785 point.y < this.min.y || point.y > this.max.y || 4786 point.z < this.min.z || point.z > this.max.z ? false : true; 4787 4788 } 4789 4790 containsBox( box ) { 4791 4792 return this.min.x <= box.min.x && box.max.x <= this.max.x && 4793 this.min.y <= box.min.y && box.max.y <= this.max.y && 4794 this.min.z <= box.min.z && box.max.z <= this.max.z; 4795 4796 } 4797 4798 getParameter( point, target ) { 4799 4800 // This can potentially have a divide by zero if the box 4801 // has a size dimension of 0. 4802 4803 return target.set( 4804 ( point.x - this.min.x ) / ( this.max.x - this.min.x ), 4805 ( point.y - this.min.y ) / ( this.max.y - this.min.y ), 4806 ( point.z - this.min.z ) / ( this.max.z - this.min.z ) 4807 ); 4808 4809 } 4810 4811 intersectsBox( box ) { 4812 4813 // using 6 splitting planes to rule out intersections. 4814 return box.max.x < this.min.x || box.min.x > this.max.x || 4815 box.max.y < this.min.y || box.min.y > this.max.y || 4816 box.max.z < this.min.z || box.min.z > this.max.z ? false : true; 4817 4818 } 4819 4820 intersectsSphere( sphere ) { 4821 4822 // Find the point on the AABB closest to the sphere center. 4823 this.clampPoint( sphere.center, _vector$b ); 4824 4825 // If that point is inside the sphere, the AABB and sphere intersect. 4826 return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); 4827 4828 } 4829 4830 intersectsPlane( plane ) { 4831 4832 // We compute the minimum and maximum dot product values. If those values 4833 // are on the same side (back or front) of the plane, then there is no intersection. 4834 4835 let min, max; 4836 4837 if ( plane.normal.x > 0 ) { 4838 4839 min = plane.normal.x * this.min.x; 4840 max = plane.normal.x * this.max.x; 4841 4842 } else { 4843 4844 min = plane.normal.x * this.max.x; 4845 max = plane.normal.x * this.min.x; 4846 4847 } 4848 4849 if ( plane.normal.y > 0 ) { 4850 4851 min += plane.normal.y * this.min.y; 4852 max += plane.normal.y * this.max.y; 4853 4854 } else { 4855 4856 min += plane.normal.y * this.max.y; 4857 max += plane.normal.y * this.min.y; 4858 4859 } 4860 4861 if ( plane.normal.z > 0 ) { 4862 4863 min += plane.normal.z * this.min.z; 4864 max += plane.normal.z * this.max.z; 4865 4866 } else { 4867 4868 min += plane.normal.z * this.max.z; 4869 max += plane.normal.z * this.min.z; 4870 4871 } 4872 4873 return ( min <= - plane.constant && max >= - plane.constant ); 4874 4875 } 4876 4877 intersectsTriangle( triangle ) { 4878 4879 if ( this.isEmpty() ) { 4880 4881 return false; 4882 4883 } 4884 4885 // compute box center and extents 4886 this.getCenter( _center ); 4887 _extents.subVectors( this.max, _center ); 4888 4889 // translate triangle to aabb origin 4890 _v0$2.subVectors( triangle.a, _center ); 4891 _v1$7.subVectors( triangle.b, _center ); 4892 _v2$4.subVectors( triangle.c, _center ); 4893 4894 // compute edge vectors for triangle 4895 _f0.subVectors( _v1$7, _v0$2 ); 4896 _f1.subVectors( _v2$4, _v1$7 ); 4897 _f2.subVectors( _v0$2, _v2$4 ); 4898 4899 // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb 4900 // 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 4901 // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned) 4902 let axes = [ 4903 0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y, 4904 _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x, 4905 - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0 4906 ]; 4907 if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) { 4908 4909 return false; 4910 4911 } 4912 4913 // test 3 face normals from the aabb 4914 axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; 4915 if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) { 4916 4917 return false; 4918 4919 } 4920 4921 // finally testing the face normal of the triangle 4922 // use already existing triangle edge vectors here 4923 _triangleNormal.crossVectors( _f0, _f1 ); 4924 axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ]; 4925 4926 return satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ); 4927 4928 } 4929 4930 clampPoint( point, target ) { 4931 4932 return target.copy( point ).clamp( this.min, this.max ); 4933 4934 } 4935 4936 distanceToPoint( point ) { 4937 4938 return this.clampPoint( point, _vector$b ).distanceTo( point ); 4939 4940 } 4941 4942 getBoundingSphere( target ) { 4943 4944 if ( this.isEmpty() ) { 4945 4946 target.makeEmpty(); 4947 4948 } else { 4949 4950 this.getCenter( target.center ); 4951 4952 target.radius = this.getSize( _vector$b ).length() * 0.5; 4953 4954 } 4955 4956 return target; 4957 4958 } 4959 4960 intersect( box ) { 4961 4962 this.min.max( box.min ); 4963 this.max.min( box.max ); 4964 4965 // 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. 4966 if ( this.isEmpty() ) this.makeEmpty(); 4967 4968 return this; 4969 4970 } 4971 4972 union( box ) { 4973 4974 this.min.min( box.min ); 4975 this.max.max( box.max ); 4976 4977 return this; 4978 4979 } 4980 4981 applyMatrix4( matrix ) { 4982 4983 // transform of empty box is an empty box. 4984 if ( this.isEmpty() ) return this; 4985 4986 // NOTE: I am using a binary pattern to specify all 2^3 combinations below 4987 _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 4988 _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 4989 _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 4990 _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 4991 _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 4992 _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 4993 _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 4994 _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 4995 4996 this.setFromPoints( _points ); 4997 4998 return this; 4999 5000 } 5001 5002 translate( offset ) { 5003 5004 this.min.add( offset ); 5005 this.max.add( offset ); 5006 5007 return this; 5008 5009 } 5010 5011 equals( box ) { 5012 5013 return box.min.equals( this.min ) && box.max.equals( this.max ); 5014 5015 } 5016 5017} 5018 5019const _points = [ 5020 /*@__PURE__*/ new Vector3(), 5021 /*@__PURE__*/ new Vector3(), 5022 /*@__PURE__*/ new Vector3(), 5023 /*@__PURE__*/ new Vector3(), 5024 /*@__PURE__*/ new Vector3(), 5025 /*@__PURE__*/ new Vector3(), 5026 /*@__PURE__*/ new Vector3(), 5027 /*@__PURE__*/ new Vector3() 5028]; 5029 5030const _vector$b = /*@__PURE__*/ new Vector3(); 5031 5032const _box$4 = /*@__PURE__*/ new Box3(); 5033 5034// triangle centered vertices 5035 5036const _v0$2 = /*@__PURE__*/ new Vector3(); 5037const _v1$7 = /*@__PURE__*/ new Vector3(); 5038const _v2$4 = /*@__PURE__*/ new Vector3(); 5039 5040// triangle edge vectors 5041 5042const _f0 = /*@__PURE__*/ new Vector3(); 5043const _f1 = /*@__PURE__*/ new Vector3(); 5044const _f2 = /*@__PURE__*/ new Vector3(); 5045 5046const _center = /*@__PURE__*/ new Vector3(); 5047const _extents = /*@__PURE__*/ new Vector3(); 5048const _triangleNormal = /*@__PURE__*/ new Vector3(); 5049const _testAxis = /*@__PURE__*/ new Vector3(); 5050 5051function satForAxes( axes, v0, v1, v2, extents ) { 5052 5053 for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) { 5054 5055 _testAxis.fromArray( axes, i ); 5056 // project the aabb onto the separating axis 5057 const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z ); 5058 // project all 3 vertices of the triangle onto the separating axis 5059 const p0 = v0.dot( _testAxis ); 5060 const p1 = v1.dot( _testAxis ); 5061 const p2 = v2.dot( _testAxis ); 5062 // actual test, basically see if either of the most extreme of the triangle points intersects r 5063 if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) { 5064 5065 // points of the projected triangle are outside the projected half-length of the aabb 5066 // the axis is separating and we can exit 5067 return false; 5068 5069 } 5070 5071 } 5072 5073 return true; 5074 5075} 5076 5077const _box$3 = /*@__PURE__*/ new Box3(); 5078const _v1$6 = /*@__PURE__*/ new Vector3(); 5079const _v2$3 = /*@__PURE__*/ new Vector3(); 5080 5081class Sphere { 5082 5083 constructor( center = new Vector3(), radius = -
vendor: 3,824 bytes, lines 5083-5329
5083 1 ) { 5084 5085 this.isSphere = true; 5086 5087 this.center = center; 5088 this.radius = radius; 5089 5090 } 5091 5092 set( center, radius ) { 5093 5094 this.center.copy( center ); 5095 this.radius = radius; 5096 5097 return this; 5098 5099 } 5100 5101 setFromPoints( points, optionalCenter ) { 5102 5103 const center = this.center; 5104 5105 if ( optionalCenter !== undefined ) { 5106 5107 center.copy( optionalCenter ); 5108 5109 } else { 5110 5111 _box$3.setFromPoints( points ).getCenter( center ); 5112 5113 } 5114 5115 let maxRadiusSq = 0; 5116 5117 for ( let i = 0, il = points.length; i < il; i ++ ) { 5118 5119 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); 5120 5121 } 5122 5123 this.radius = Math.sqrt( maxRadiusSq ); 5124 5125 return this; 5126 5127 } 5128 5129 copy( sphere ) { 5130 5131 this.center.copy( sphere.center ); 5132 this.radius = sphere.radius; 5133 5134 return this; 5135 5136 } 5137 5138 isEmpty() { 5139 5140 return ( this.radius < 0 ); 5141 5142 } 5143 5144 makeEmpty() { 5145 5146 this.center.set( 0, 0, 0 ); 5147 this.radius = - 1; 5148 5149 return this; 5150 5151 } 5152 5153 containsPoint( point ) { 5154 5155 return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); 5156 5157 } 5158 5159 distanceToPoint( point ) { 5160 5161 return ( point.distanceTo( this.center ) - this.radius ); 5162 5163 } 5164 5165 intersectsSphere( sphere ) { 5166 5167 const radiusSum = this.radius + sphere.radius; 5168 5169 return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); 5170 5171 } 5172 5173 intersectsBox( box ) { 5174 5175 return box.intersectsSphere( this ); 5176 5177 } 5178 5179 intersectsPlane( plane ) { 5180 5181 return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; 5182 5183 } 5184 5185 clampPoint( point, target ) { 5186 5187 const deltaLengthSq = this.center.distanceToSquared( point ); 5188 5189 target.copy( point ); 5190 5191 if ( deltaLengthSq > ( this.radius * this.radius ) ) { 5192 5193 target.sub( this.center ).normalize(); 5194 target.multiplyScalar( this.radius ).add( this.center ); 5195 5196 } 5197 5198 return target; 5199 5200 } 5201 5202 getBoundingBox( target ) { 5203 5204 if ( this.isEmpty() ) { 5205 5206 // Empty sphere produces empty bounding box 5207 target.makeEmpty(); 5208 return target; 5209 5210 } 5211 5212 target.set( this.center, this.center ); 5213 target.expandByScalar( this.radius ); 5214 5215 return target; 5216 5217 } 5218 5219 applyMatrix4( matrix ) { 5220 5221 this.center.applyMatrix4( matrix ); 5222 this.radius = this.radius * matrix.getMaxScaleOnAxis(); 5223 5224 return this; 5225 5226 } 5227 5228 translate( offset ) { 5229 5230 this.center.add( offset ); 5231 5232 return this; 5233 5234 } 5235 5236 expandByPoint( point ) { 5237 5238 if ( this.isEmpty() ) { 5239 5240 this.center.copy( point ); 5241 5242 this.radius = 0; 5243 5244 return this; 5245 5246 } 5247 5248 _v1$6.subVectors( point, this.center ); 5249 5250 const lengthSq = _v1$6.lengthSq(); 5251 5252 if ( lengthSq > ( this.radius * this.radius ) ) { 5253 5254 // calculate the minimal sphere 5255 5256 const length = Math.sqrt( lengthSq ); 5257 5258 const delta = ( length - this.radius ) * 0.5; 5259 5260 this.center.addScaledVector( _v1$6, delta / length ); 5261 5262 this.radius += delta; 5263 5264 } 5265 5266 return this; 5267 5268 } 5269 5270 union( sphere ) { 5271 5272 if ( sphere.isEmpty() ) { 5273 5274 return this; 5275 5276 } 5277 5278 if ( this.isEmpty() ) { 5279 5280 this.copy( sphere ); 5281 5282 return this; 5283 5284 } 5285 5286 if ( this.center.equals( sphere.center ) === true ) { 5287 5288 this.radius = Math.max( this.radius, sphere.radius ); 5289 5290 } else { 5291 5292 _v2$3.subVectors( sphere.center, this.center ).setLength( sphere.radius ); 5293 5294 this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) ); 5295 5296 this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) ); 5297 5298 } 5299 5300 return this; 5301 5302 } 5303 5304 equals( sphere ) { 5305 5306 return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); 5307 5308 } 5309 5310 clone() { 5311 5312 return new this.constructor().copy( this ); 5313 5314 } 5315 5316} 5317 5318const _vector$a = /*@__PURE__*/ new Vector3(); 5319const _segCenter = /*@__PURE__*/ new Vector3(); 5320const _segDir = /*@__PURE__*/ new Vector3(); 5321const _diff = /*@__PURE__*/ new Vector3(); 5322 5323const _edge1 = /*@__PURE__*/ new Vector3(); 5324const _edge2 = /*@__PURE__*/ new Vector3(); 5325const _normal$1 = /*@__PURE__*/ new Vector3(); 5326 5327class Ray { 5328 5329 constructor( origin = new Vector3(), direction = new Vector3( 0, 0, -
vendor: 8,510 bytes, lines 5329-5735
53291 ) ) { 5330 5331 this.origin = origin; 5332 this.direction = direction; 5333 5334 } 5335 5336 set( origin, direction ) { 5337 5338 this.origin.copy( origin ); 5339 this.direction.copy( direction ); 5340 5341 return this; 5342 5343 } 5344 5345 copy( ray ) { 5346 5347 this.origin.copy( ray.origin ); 5348 this.direction.copy( ray.direction ); 5349 5350 return this; 5351 5352 } 5353 5354 at( t, target ) { 5355 5356 return target.copy( this.origin ).addScaledVector( this.direction, t ); 5357 5358 } 5359 5360 lookAt( v ) { 5361 5362 this.direction.copy( v ).sub( this.origin ).normalize(); 5363 5364 return this; 5365 5366 } 5367 5368 recast( t ) { 5369 5370 this.origin.copy( this.at( t, _vector$a ) ); 5371 5372 return this; 5373 5374 } 5375 5376 closestPointToPoint( point, target ) { 5377 5378 target.subVectors( point, this.origin ); 5379 5380 const directionDistance = target.dot( this.direction ); 5381 5382 if ( directionDistance < 0 ) { 5383 5384 return target.copy( this.origin ); 5385 5386 } 5387 5388 return target.copy( this.origin ).addScaledVector( this.direction, directionDistance ); 5389 5390 } 5391 5392 distanceToPoint( point ) { 5393 5394 return Math.sqrt( this.distanceSqToPoint( point ) ); 5395 5396 } 5397 5398 distanceSqToPoint( point ) { 5399 5400 const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); 5401 5402 // point behind the ray 5403 5404 if ( directionDistance < 0 ) { 5405 5406 return this.origin.distanceToSquared( point ); 5407 5408 } 5409 5410 _vector$a.copy( this.origin ).addScaledVector( this.direction, directionDistance ); 5411 5412 return _vector$a.distanceToSquared( point ); 5413 5414 } 5415 5416 distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { 5417 5418 // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h 5419 // It returns the min distance between the ray and the segment 5420 // defined by v0 and v1 5421 // It can also set two optional targets : 5422 // - The closest point on the ray 5423 // - The closest point on the segment 5424 5425 _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); 5426 _segDir.copy( v1 ).sub( v0 ).normalize(); 5427 _diff.copy( this.origin ).sub( _segCenter ); 5428 5429 const segExtent = v0.distanceTo( v1 ) * 0.5; 5430 const a01 = - this.direction.dot( _segDir ); 5431 const b0 = _diff.dot( this.direction ); 5432 const b1 = - _diff.dot( _segDir ); 5433 const c = _diff.lengthSq(); 5434 const det = Math.abs( 1 - a01 * a01 ); 5435 let s0, s1, sqrDist, extDet; 5436 5437 if ( det > 0 ) { 5438 5439 // The ray and segment are not parallel. 5440 5441 s0 = a01 * b1 - b0; 5442 s1 = a01 * b0 - b1; 5443 extDet = segExtent * det; 5444 5445 if ( s0 >= 0 ) { 5446 5447 if ( s1 >= - extDet ) { 5448 5449 if ( s1 <= extDet ) { 5450 5451 // region 0 5452 // Minimum at interior points of ray and segment. 5453 5454 const invDet = 1 / det; 5455 s0 *= invDet; 5456 s1 *= invDet; 5457 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; 5458 5459 } else { 5460 5461 // region 1 5462 5463 s1 = segExtent; 5464 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 5465 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5466 5467 } 5468 5469 } else { 5470 5471 // region 5 5472 5473 s1 = - segExtent; 5474 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 5475 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5476 5477 } 5478 5479 } else { 5480 5481 if ( s1 <= - extDet ) { 5482 5483 // region 4 5484 5485 s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) ); 5486 s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); 5487 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5488 5489 } else if ( s1 <= extDet ) { 5490 5491 // region 3 5492 5493 s0 = 0; 5494 s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); 5495 sqrDist = s1 * ( s1 + 2 * b1 ) + c; 5496 5497 } else { 5498 5499 // region 2 5500 5501 s0 = Math.max( 0, - ( a01 * segExtent + b0 ) ); 5502 s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); 5503 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5504 5505 } 5506 5507 } 5508 5509 } else { 5510 5511 // Ray and segment are parallel. 5512 5513 s1 = ( a01 > 0 ) ? - segExtent : segExtent; 5514 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 5515 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5516 5517 } 5518 5519 if ( optionalPointOnRay ) { 5520 5521 optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 ); 5522 5523 } 5524 5525 if ( optionalPointOnSegment ) { 5526 5527 optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 ); 5528 5529 } 5530 5531 return sqrDist; 5532 5533 } 5534 5535 intersectSphere( sphere, target ) { 5536 5537 _vector$a.subVectors( sphere.center, this.origin ); 5538 const tca = _vector$a.dot( this.direction ); 5539 const d2 = _vector$a.dot( _vector$a ) - tca * tca; 5540 const radius2 = sphere.radius * sphere.radius; 5541 5542 if ( d2 > radius2 ) return null; 5543 5544 const thc = Math.sqrt( radius2 - d2 ); 5545 5546 // t0 = first intersect point - entrance on front of sphere 5547 const t0 = tca - thc; 5548 5549 // t1 = second intersect point - exit point on back of sphere 5550 const t1 = tca + thc; 5551 5552 // test to see if t1 is behind the ray - if so, return null 5553 if ( t1 < 0 ) return null; 5554 5555 // test to see if t0 is behind the ray: 5556 // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, 5557 // in order to always return an intersect point that is in front of the ray. 5558 if ( t0 < 0 ) return this.at( t1, target ); 5559 5560 // else t0 is in front of the ray, so return the first collision point scaled by t0 5561 return this.at( t0, target ); 5562 5563 } 5564 5565 intersectsSphere( sphere ) { 5566 5567 return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius ); 5568 5569 } 5570 5571 distanceToPlane( plane ) { 5572 5573 const denominator = plane.normal.dot( this.direction ); 5574 5575 if ( denominator === 0 ) { 5576 5577 // line is coplanar, return origin 5578 if ( plane.distanceToPoint( this.origin ) === 0 ) { 5579 5580 return 0; 5581 5582 } 5583 5584 // Null is preferable to undefined since undefined means.... it is undefined 5585 5586 return null; 5587 5588 } 5589 5590 const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; 5591 5592 // Return if the ray never intersects the plane 5593 5594 return t >= 0 ? t : null; 5595 5596 } 5597 5598 intersectPlane( plane, target ) { 5599 5600 const t = this.distanceToPlane( plane ); 5601 5602 if ( t === null ) { 5603 5604 return null; 5605 5606 } 5607 5608 return this.at( t, target ); 5609 5610 } 5611 5612 intersectsPlane( plane ) { 5613 5614 // check if the ray lies on the plane first 5615 5616 const distToPoint = plane.distanceToPoint( this.origin ); 5617 5618 if ( distToPoint === 0 ) { 5619 5620 return true; 5621 5622 } 5623 5624 const denominator = plane.normal.dot( this.direction ); 5625 5626 if ( denominator * distToPoint < 0 ) { 5627 5628 return true; 5629 5630 } 5631 5632 // ray origin is behind the plane (and is pointing behind it) 5633 5634 return false; 5635 5636 } 5637 5638 intersectBox( box, target ) { 5639 5640 let tmin, tmax, tymin, tymax, tzmin, tzmax; 5641 5642 const invdirx = 1 / this.direction.x, 5643 invdiry = 1 / this.direction.y, 5644 invdirz = 1 / this.direction.z; 5645 5646 const origin = this.origin; 5647 5648 if ( invdirx >= 0 ) { 5649 5650 tmin = ( box.min.x - origin.x ) * invdirx; 5651 tmax = ( box.max.x - origin.x ) * invdirx; 5652 5653 } else { 5654 5655 tmin = ( box.max.x - origin.x ) * invdirx; 5656 tmax = ( box.min.x - origin.x ) * invdirx; 5657 5658 } 5659 5660 if ( invdiry >= 0 ) { 5661 5662 tymin = ( box.min.y - origin.y ) * invdiry; 5663 tymax = ( box.max.y - origin.y ) * invdiry; 5664 5665 } else { 5666 5667 tymin = ( box.max.y - origin.y ) * invdiry; 5668 tymax = ( box.min.y - origin.y ) * invdiry; 5669 5670 } 5671 5672 if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; 5673 5674 if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin; 5675 5676 if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax; 5677 5678 if ( invdirz >= 0 ) { 5679 5680 tzmin = ( box.min.z - origin.z ) * invdirz; 5681 tzmax = ( box.max.z - origin.z ) * invdirz; 5682 5683 } else { 5684 5685 tzmin = ( box.max.z - origin.z ) * invdirz; 5686 tzmax = ( box.min.z - origin.z ) * invdirz; 5687 5688 } 5689 5690 if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; 5691 5692 if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; 5693 5694 if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; 5695 5696 //return point closest to the ray (positive side) 5697 5698 if ( tmax < 0 ) return null; 5699 5700 return this.at( tmin >= 0 ? tmin : tmax, target ); 5701 5702 } 5703 5704 intersectsBox( box ) { 5705 5706 return this.intersectBox( box, _vector$a ) !== null; 5707 5708 } 5709 5710 intersectTriangle( a, b, c, backfaceCulling, target ) { 5711 5712 // Compute the offset origin, edges, and normal. 5713 5714 // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h 5715 5716 _edge1.subVectors( b, a ); 5717 _edge2.subVectors( c, a ); 5718 _normal$1.crossVectors( _edge1, _edge2 ); 5719 5720 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, 5721 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by 5722 // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) 5723 // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) 5724 // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) 5725 let DdN = this.direction.dot( _normal$1 ); 5726 let sign; 5727 5728 if ( DdN > 0 ) { 5729 5730 if ( backfaceCulling ) return null; 5731 sign = 1; 5732 5733 } else if ( DdN < 0 ) { 5734 5735 sign = -
5735
vendor: 17,907 bytes, lines 5735-6595
57351; 5736 DdN = - DdN; 5737 5738 } else { 5739 5740 return null; 5741 5742 } 5743 5744 _diff.subVectors( this.origin, a ); 5745 const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) ); 5746 5747 // b1 < 0, no intersection 5748 if ( DdQxE2 < 0 ) { 5749 5750 return null; 5751 5752 } 5753 5754 const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) ); 5755 5756 // b2 < 0, no intersection 5757 if ( DdE1xQ < 0 ) { 5758 5759 return null; 5760 5761 } 5762 5763 // b1+b2 > 1, no intersection 5764 if ( DdQxE2 + DdE1xQ > DdN ) { 5765 5766 return null; 5767 5768 } 5769 5770 // Line intersects triangle, check if ray does. 5771 const QdN = - sign * _diff.dot( _normal$1 ); 5772 5773 // t < 0, no intersection 5774 if ( QdN < 0 ) { 5775 5776 return null; 5777 5778 } 5779 5780 // Ray intersects triangle. 5781 return this.at( QdN / DdN, target ); 5782 5783 } 5784 5785 applyMatrix4( matrix4 ) { 5786 5787 this.origin.applyMatrix4( matrix4 ); 5788 this.direction.transformDirection( matrix4 ); 5789 5790 return this; 5791 5792 } 5793 5794 equals( ray ) { 5795 5796 return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); 5797 5798 } 5799 5800 clone() { 5801 5802 return new this.constructor().copy( this ); 5803 5804 } 5805 5806} 5807 5808class Matrix4 { 5809 5810 constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { 5811 5812 Matrix4.prototype.isMatrix4 = true; 5813 5814 this.elements = [ 5815 5816 1, 0, 0, 0, 5817 0, 1, 0, 0, 5818 0, 0, 1, 0, 5819 0, 0, 0, 1 5820 5821 ]; 5822 5823 if ( n11 !== undefined ) { 5824 5825 this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ); 5826 5827 } 5828 5829 } 5830 5831 set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { 5832 5833 const te = this.elements; 5834 5835 te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14; 5836 te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24; 5837 te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34; 5838 te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44; 5839 5840 return this; 5841 5842 } 5843 5844 identity() { 5845 5846 this.set( 5847 5848 1, 0, 0, 0, 5849 0, 1, 0, 0, 5850 0, 0, 1, 0, 5851 0, 0, 0, 1 5852 5853 ); 5854 5855 return this; 5856 5857 } 5858 5859 clone() { 5860 5861 return new Matrix4().fromArray( this.elements ); 5862 5863 } 5864 5865 copy( m ) { 5866 5867 const te = this.elements; 5868 const me = m.elements; 5869 5870 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ]; 5871 te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; 5872 te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ]; 5873 te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ]; 5874 5875 return this; 5876 5877 } 5878 5879 copyPosition( m ) { 5880 5881 const te = this.elements, me = m.elements; 5882 5883 te[ 12 ] = me[ 12 ]; 5884 te[ 13 ] = me[ 13 ]; 5885 te[ 14 ] = me[ 14 ]; 5886 5887 return this; 5888 5889 } 5890 5891 setFromMatrix3( m ) { 5892 5893 const me = m.elements; 5894 5895 this.set( 5896 5897 me[ 0 ], me[ 3 ], me[ 6 ], 0, 5898 me[ 1 ], me[ 4 ], me[ 7 ], 0, 5899 me[ 2 ], me[ 5 ], me[ 8 ], 0, 5900 0, 0, 0, 1 5901 5902 ); 5903 5904 return this; 5905 5906 } 5907 5908 extractBasis( xAxis, yAxis, zAxis ) { 5909 5910 xAxis.setFromMatrixColumn( this, 0 ); 5911 yAxis.setFromMatrixColumn( this, 1 ); 5912 zAxis.setFromMatrixColumn( this, 2 ); 5913 5914 return this; 5915 5916 } 5917 5918 makeBasis( xAxis, yAxis, zAxis ) { 5919 5920 this.set( 5921 xAxis.x, yAxis.x, zAxis.x, 0, 5922 xAxis.y, yAxis.y, zAxis.y, 0, 5923 xAxis.z, yAxis.z, zAxis.z, 0, 5924 0, 0, 0, 1 5925 ); 5926 5927 return this; 5928 5929 } 5930 5931 extractRotation( m ) { 5932 5933 // this method does not support reflection matrices 5934 5935 const te = this.elements; 5936 const me = m.elements; 5937 5938 const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length(); 5939 const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length(); 5940 const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length(); 5941 5942 te[ 0 ] = me[ 0 ] * scaleX; 5943 te[ 1 ] = me[ 1 ] * scaleX; 5944 te[ 2 ] = me[ 2 ] * scaleX; 5945 te[ 3 ] = 0; 5946 5947 te[ 4 ] = me[ 4 ] * scaleY; 5948 te[ 5 ] = me[ 5 ] * scaleY; 5949 te[ 6 ] = me[ 6 ] * scaleY; 5950 te[ 7 ] = 0; 5951 5952 te[ 8 ] = me[ 8 ] * scaleZ; 5953 te[ 9 ] = me[ 9 ] * scaleZ; 5954 te[ 10 ] = me[ 10 ] * scaleZ; 5955 te[ 11 ] = 0; 5956 5957 te[ 12 ] = 0; 5958 te[ 13 ] = 0; 5959 te[ 14 ] = 0; 5960 te[ 15 ] = 1; 5961 5962 return this; 5963 5964 } 5965 5966 makeRotationFromEuler( euler ) { 5967 5968 const te = this.elements; 5969 5970 const x = euler.x, y = euler.y, z = euler.z; 5971 const a = Math.cos( x ), b = Math.sin( x ); 5972 const c = Math.cos( y ), d = Math.sin( y ); 5973 const e = Math.cos( z ), f = Math.sin( z ); 5974 5975 if ( euler.order === 'XYZ' ) { 5976 5977 const ae = a * e, af = a * f, be = b * e, bf = b * f; 5978 5979 te[ 0 ] = c * e; 5980 te[ 4 ] = - c * f; 5981 te[ 8 ] = d; 5982 5983 te[ 1 ] = af + be * d; 5984 te[ 5 ] = ae - bf * d; 5985 te[ 9 ] = - b * c; 5986 5987 te[ 2 ] = bf - ae * d; 5988 te[ 6 ] = be + af * d; 5989 te[ 10 ] = a * c; 5990 5991 } else if ( euler.order === 'YXZ' ) { 5992 5993 const ce = c * e, cf = c * f, de = d * e, df = d * f; 5994 5995 te[ 0 ] = ce + df * b; 5996 te[ 4 ] = de * b - cf; 5997 te[ 8 ] = a * d; 5998 5999 te[ 1 ] = a * f; 6000 te[ 5 ] = a * e; 6001 te[ 9 ] = - b; 6002 6003 te[ 2 ] = cf * b - de; 6004 te[ 6 ] = df + ce * b; 6005 te[ 10 ] = a * c; 6006 6007 } else if ( euler.order === 'ZXY' ) { 6008 6009 const ce = c * e, cf = c * f, de = d * e, df = d * f; 6010 6011 te[ 0 ] = ce - df * b; 6012 te[ 4 ] = - a * f; 6013 te[ 8 ] = de + cf * b; 6014 6015 te[ 1 ] = cf + de * b; 6016 te[ 5 ] = a * e; 6017 te[ 9 ] = df - ce * b; 6018 6019 te[ 2 ] = - a * d; 6020 te[ 6 ] = b; 6021 te[ 10 ] = a * c; 6022 6023 } else if ( euler.order === 'ZYX' ) { 6024 6025 const ae = a * e, af = a * f, be = b * e, bf = b * f; 6026 6027 te[ 0 ] = c * e; 6028 te[ 4 ] = be * d - af; 6029 te[ 8 ] = ae * d + bf; 6030 6031 te[ 1 ] = c * f; 6032 te[ 5 ] = bf * d + ae; 6033 te[ 9 ] = af * d - be; 6034 6035 te[ 2 ] = - d; 6036 te[ 6 ] = b * c; 6037 te[ 10 ] = a * c; 6038 6039 } else if ( euler.order === 'YZX' ) { 6040 6041 const ac = a * c, ad = a * d, bc = b * c, bd = b * d; 6042 6043 te[ 0 ] = c * e; 6044 te[ 4 ] = bd - ac * f; 6045 te[ 8 ] = bc * f + ad; 6046 6047 te[ 1 ] = f; 6048 te[ 5 ] = a * e; 6049 te[ 9 ] = - b * e; 6050 6051 te[ 2 ] = - d * e; 6052 te[ 6 ] = ad * f + bc; 6053 te[ 10 ] = ac - bd * f; 6054 6055 } else if ( euler.order === 'XZY' ) { 6056 6057 const ac = a * c, ad = a * d, bc = b * c, bd = b * d; 6058 6059 te[ 0 ] = c * e; 6060 te[ 4 ] = - f; 6061 te[ 8 ] = d * e; 6062 6063 te[ 1 ] = ac * f + bd; 6064 te[ 5 ] = a * e; 6065 te[ 9 ] = ad * f - bc; 6066 6067 te[ 2 ] = bc * f - ad; 6068 te[ 6 ] = b * e; 6069 te[ 10 ] = bd * f + ac; 6070 6071 } 6072 6073 // bottom row 6074 te[ 3 ] = 0; 6075 te[ 7 ] = 0; 6076 te[ 11 ] = 0; 6077 6078 // last column 6079 te[ 12 ] = 0; 6080 te[ 13 ] = 0; 6081 te[ 14 ] = 0; 6082 te[ 15 ] = 1; 6083 6084 return this; 6085 6086 } 6087 6088 makeRotationFromQuaternion( q ) { 6089 6090 return this.compose( _zero, q, _one ); 6091 6092 } 6093 6094 lookAt( eye, target, up ) { 6095 6096 const te = this.elements; 6097 6098 _z.subVectors( eye, target ); 6099 6100 if ( _z.lengthSq() === 0 ) { 6101 6102 // eye and target are in the same position 6103 6104 _z.z = 1; 6105 6106 } 6107 6108 _z.normalize(); 6109 _x.crossVectors( up, _z ); 6110 6111 if ( _x.lengthSq() === 0 ) { 6112 6113 // up and z are parallel 6114 6115 if ( Math.abs( up.z ) === 1 ) { 6116 6117 _z.x += 0.0001; 6118 6119 } else { 6120 6121 _z.z += 0.0001; 6122 6123 } 6124 6125 _z.normalize(); 6126 _x.crossVectors( up, _z ); 6127 6128 } 6129 6130 _x.normalize(); 6131 _y.crossVectors( _z, _x ); 6132 6133 te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x; 6134 te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y; 6135 te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z; 6136 6137 return this; 6138 6139 } 6140 6141 multiply( m ) { 6142 6143 return this.multiplyMatrices( this, m ); 6144 6145 } 6146 6147 premultiply( m ) { 6148 6149 return this.multiplyMatrices( m, this ); 6150 6151 } 6152 6153 multiplyMatrices( a, b ) { 6154 6155 const ae = a.elements; 6156 const be = b.elements; 6157 const te = this.elements; 6158 6159 const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ]; 6160 const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ]; 6161 const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ]; 6162 const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ]; 6163 6164 const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ]; 6165 const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ]; 6166 const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ]; 6167 const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ]; 6168 6169 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; 6170 te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; 6171 te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; 6172 te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; 6173 6174 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; 6175 te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; 6176 te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; 6177 te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; 6178 6179 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; 6180 te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; 6181 te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; 6182 te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; 6183 6184 te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; 6185 te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; 6186 te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; 6187 te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; 6188 6189 return this; 6190 6191 } 6192 6193 multiplyScalar( s ) { 6194 6195 const te = this.elements; 6196 6197 te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s; 6198 te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s; 6199 te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s; 6200 te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s; 6201 6202 return this; 6203 6204 } 6205 6206 determinant() { 6207 6208 const te = this.elements; 6209 6210 const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ]; 6211 const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ]; 6212 const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ]; 6213 const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ]; 6214 6215 //TODO: make this more efficient 6216 //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) 6217 6218 return ( 6219 n41 * ( 6220 + n14 * n23 * n32 6221 - n13 * n24 * n32 6222 - n14 * n22 * n33 6223 + n12 * n24 * n33 6224 + n13 * n22 * n34 6225 - n12 * n23 * n34 6226 ) + 6227 n42 * ( 6228 + n11 * n23 * n34 6229 - n11 * n24 * n33 6230 + n14 * n21 * n33 6231 - n13 * n21 * n34 6232 + n13 * n24 * n31 6233 - n14 * n23 * n31 6234 ) + 6235 n43 * ( 6236 + n11 * n24 * n32 6237 - n11 * n22 * n34 6238 - n14 * n21 * n32 6239 + n12 * n21 * n34 6240 + n14 * n22 * n31 6241 - n12 * n24 * n31 6242 ) + 6243 n44 * ( 6244 - n13 * n22 * n31 6245 - n11 * n23 * n32 6246 + n11 * n22 * n33 6247 + n13 * n21 * n32 6248 - n12 * n21 * n33 6249 + n12 * n23 * n31 6250 ) 6251 6252 ); 6253 6254 } 6255 6256 transpose() { 6257 6258 const te = this.elements; 6259 let tmp; 6260 6261 tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp; 6262 tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp; 6263 tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp; 6264 6265 tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp; 6266 tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp; 6267 tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp; 6268 6269 return this; 6270 6271 } 6272 6273 setPosition( x, y, z ) { 6274 6275 const te = this.elements; 6276 6277 if ( x.isVector3 ) { 6278 6279 te[ 12 ] = x.x; 6280 te[ 13 ] = x.y; 6281 te[ 14 ] = x.z; 6282 6283 } else { 6284 6285 te[ 12 ] = x; 6286 te[ 13 ] = y; 6287 te[ 14 ] = z; 6288 6289 } 6290 6291 return this; 6292 6293 } 6294 6295 invert() { 6296 6297 // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm 6298 const te = this.elements, 6299 6300 n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ], 6301 n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ], 6302 n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ], 6303 n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ], 6304 6305 t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44, 6306 t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44, 6307 t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44, 6308 t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34; 6309 6310 const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; 6311 6312 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); 6313 6314 const detInv = 1 / det; 6315 6316 te[ 0 ] = t11 * detInv; 6317 te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv; 6318 te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv; 6319 te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv; 6320 6321 te[ 4 ] = t12 * detInv; 6322 te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv; 6323 te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv; 6324 te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv; 6325 6326 te[ 8 ] = t13 * detInv; 6327 te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv; 6328 te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv; 6329 te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv; 6330 6331 te[ 12 ] = t14 * detInv; 6332 te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv; 6333 te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv; 6334 te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv; 6335 6336 return this; 6337 6338 } 6339 6340 scale( v ) { 6341 6342 const te = this.elements; 6343 const x = v.x, y = v.y, z = v.z; 6344 6345 te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; 6346 te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; 6347 te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; 6348 te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; 6349 6350 return this; 6351 6352 } 6353 6354 getMaxScaleOnAxis() { 6355 6356 const te = this.elements; 6357 6358 const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ]; 6359 const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ]; 6360 const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ]; 6361 6362 return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); 6363 6364 } 6365 6366 makeTranslation( x, y, z ) { 6367 6368 if ( x.isVector3 ) { 6369 6370 this.set( 6371 6372 1, 0, 0, x.x, 6373 0, 1, 0, x.y, 6374 0, 0, 1, x.z, 6375 0, 0, 0, 1 6376 6377 ); 6378 6379 } else { 6380 6381 this.set( 6382 6383 1, 0, 0, x, 6384 0, 1, 0, y, 6385 0, 0, 1, z, 6386 0, 0, 0, 1 6387 6388 ); 6389 6390 } 6391 6392 return this; 6393 6394 } 6395 6396 makeRotationX( theta ) { 6397 6398 const c = Math.cos( theta ), s = Math.sin( theta ); 6399 6400 this.set( 6401 6402 1, 0, 0, 0, 6403 0, c, - s, 0, 6404 0, s, c, 0, 6405 0, 0, 0, 1 6406 6407 ); 6408 6409 return this; 6410 6411 } 6412 6413 makeRotationY( theta ) { 6414 6415 const c = Math.cos( theta ), s = Math.sin( theta ); 6416 6417 this.set( 6418 6419 c, 0, s, 0, 6420 0, 1, 0, 0, 6421 - s, 0, c, 0, 6422 0, 0, 0, 1 6423 6424 ); 6425 6426 return this; 6427 6428 } 6429 6430 makeRotationZ( theta ) { 6431 6432 const c = Math.cos( theta ), s = Math.sin( theta ); 6433 6434 this.set( 6435 6436 c, - s, 0, 0, 6437 s, c, 0, 0, 6438 0, 0, 1, 0, 6439 0, 0, 0, 1 6440 6441 ); 6442 6443 return this; 6444 6445 } 6446 6447 makeRotationAxis( axis, angle ) { 6448 6449 // Based on http://www.gamedev.net/reference/articles/article1199.asp 6450 6451 const c = Math.cos( angle ); 6452 const s = Math.sin( angle ); 6453 const t = 1 - c; 6454 const x = axis.x, y = axis.y, z = axis.z; 6455 const tx = t * x, ty = t * y; 6456 6457 this.set( 6458 6459 tx * x + c, tx * y - s * z, tx * z + s * y, 0, 6460 tx * y + s * z, ty * y + c, ty * z - s * x, 0, 6461 tx * z - s * y, ty * z + s * x, t * z * z + c, 0, 6462 0, 0, 0, 1 6463 6464 ); 6465 6466 return this; 6467 6468 } 6469 6470 makeScale( x, y, z ) { 6471 6472 this.set( 6473 6474 x, 0, 0, 0, 6475 0, y, 0, 0, 6476 0, 0, z, 0, 6477 0, 0, 0, 1 6478 6479 ); 6480 6481 return this; 6482 6483 } 6484 6485 makeShear( xy, xz, yx, yz, zx, zy ) { 6486 6487 this.set( 6488 6489 1, yx, zx, 0, 6490 xy, 1, zy, 0, 6491 xz, yz, 1, 0, 6492 0, 0, 0, 1 6493 6494 ); 6495 6496 return this; 6497 6498 } 6499 6500 compose( position, quaternion, scale ) { 6501 6502 const te = this.elements; 6503 6504 const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w; 6505 const x2 = x + x, y2 = y + y, z2 = z + z; 6506 const xx = x * x2, xy = x * y2, xz = x * z2; 6507 const yy = y * y2, yz = y * z2, zz = z * z2; 6508 const wx = w * x2, wy = w * y2, wz = w * z2; 6509 6510 const sx = scale.x, sy = scale.y, sz = scale.z; 6511 6512 te[ 0 ] = ( 1 - ( yy + zz ) ) * sx; 6513 te[ 1 ] = ( xy + wz ) * sx; 6514 te[ 2 ] = ( xz - wy ) * sx; 6515 te[ 3 ] = 0; 6516 6517 te[ 4 ] = ( xy - wz ) * sy; 6518 te[ 5 ] = ( 1 - ( xx + zz ) ) * sy; 6519 te[ 6 ] = ( yz + wx ) * sy; 6520 te[ 7 ] = 0; 6521 6522 te[ 8 ] = ( xz + wy ) * sz; 6523 te[ 9 ] = ( yz - wx ) * sz; 6524 te[ 10 ] = ( 1 - ( xx + yy ) ) * sz; 6525 te[ 11 ] = 0; 6526 6527 te[ 12 ] = position.x; 6528 te[ 13 ] = position.y; 6529 te[ 14 ] = position.z; 6530 te[ 15 ] = 1; 6531 6532 return this; 6533 6534 } 6535 6536 decompose( position, quaternion, scale ) { 6537 6538 const te = this.elements; 6539 6540 let sx = _v1$5.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); 6541 const sy = _v1$5.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); 6542 const sz = _v1$5.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); 6543 6544 // if determine is negative, we need to invert one scale 6545 const det = this.determinant(); 6546 if ( det < 0 ) sx = - sx; 6547 6548 position.x = te[ 12 ]; 6549 position.y = te[ 13 ]; 6550 position.z = te[ 14 ]; 6551 6552 // scale the rotation part 6553 _m1$4.copy( this ); 6554 6555 const invSX = 1 / sx; 6556 const invSY = 1 / sy; 6557 const invSZ = 1 / sz; 6558 6559 _m1$4.elements[ 0 ] *= invSX; 6560 _m1$4.elements[ 1 ] *= invSX; 6561 _m1$4.elements[ 2 ] *= invSX; 6562 6563 _m1$4.elements[ 4 ] *= invSY; 6564 _m1$4.elements[ 5 ] *= invSY; 6565 _m1$4.elements[ 6 ] *= invSY; 6566 6567 _m1$4.elements[ 8 ] *= invSZ; 6568 _m1$4.elements[ 9 ] *= invSZ; 6569 _m1$4.elements[ 10 ] *= invSZ; 6570 6571 quaternion.setFromRotationMatrix( _m1$4 ); 6572 6573 scale.x = sx; 6574 scale.y = sy; 6575 scale.z = sz; 6576 6577 return this; 6578 6579 } 6580 6581 makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { 6582 6583 const te = this.elements; 6584 const x = 2 * near / ( right - left ); 6585 const y = 2 * near / ( top - bottom ); 6586 6587 const a = ( right + left ) / ( right - left ); 6588 const b = ( top + bottom ) / ( top - bottom ); 6589 6590 let c, d; 6591 6592 if ( coordinateSystem === WebGLCoordinateSystem ) { 6593 6594 c = - ( far + near ) / ( far - near ); 6595 d = ( -
vendor: 8,642 bytes, lines 6595-7107
6595 2 * far * near ) / ( far - near ); 6596 6597 } else if ( coordinateSystem === WebGPUCoordinateSystem ) { 6598 6599 c = - far / ( far - near ); 6600 d = ( - far * near ) / ( far - near ); 6601 6602 } else { 6603 6604 throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem ); 6605 6606 } 6607 6608 te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; 6609 te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; 6610 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; 6611 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; 6612 6613 return this; 6614 6615 } 6616 6617 makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { 6618 6619 const te = this.elements; 6620 const w = 1.0 / ( right - left ); 6621 const h = 1.0 / ( top - bottom ); 6622 const p = 1.0 / ( far - near ); 6623 6624 const x = ( right + left ) * w; 6625 const y = ( top + bottom ) * h; 6626 6627 let z, zInv; 6628 6629 if ( coordinateSystem === WebGLCoordinateSystem ) { 6630 6631 z = ( far + near ) * p; 6632 zInv = - 2 * p; 6633 6634 } else if ( coordinateSystem === WebGPUCoordinateSystem ) { 6635 6636 z = near * p; 6637 zInv = - 1 * p; 6638 6639 } else { 6640 6641 throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem ); 6642 6643 } 6644 6645 te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; 6646 te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; 6647 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = zInv; te[ 14 ] = - z; 6648 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; 6649 6650 return this; 6651 6652 } 6653 6654 equals( matrix ) { 6655 6656 const te = this.elements; 6657 const me = matrix.elements; 6658 6659 for ( let i = 0; i < 16; i ++ ) { 6660 6661 if ( te[ i ] !== me[ i ] ) return false; 6662 6663 } 6664 6665 return true; 6666 6667 } 6668 6669 fromArray( array, offset = 0 ) { 6670 6671 for ( let i = 0; i < 16; i ++ ) { 6672 6673 this.elements[ i ] = array[ i + offset ]; 6674 6675 } 6676 6677 return this; 6678 6679 } 6680 6681 toArray( array = [], offset = 0 ) { 6682 6683 const te = this.elements; 6684 6685 array[ offset ] = te[ 0 ]; 6686 array[ offset + 1 ] = te[ 1 ]; 6687 array[ offset + 2 ] = te[ 2 ]; 6688 array[ offset + 3 ] = te[ 3 ]; 6689 6690 array[ offset + 4 ] = te[ 4 ]; 6691 array[ offset + 5 ] = te[ 5 ]; 6692 array[ offset + 6 ] = te[ 6 ]; 6693 array[ offset + 7 ] = te[ 7 ]; 6694 6695 array[ offset + 8 ] = te[ 8 ]; 6696 array[ offset + 9 ] = te[ 9 ]; 6697 array[ offset + 10 ] = te[ 10 ]; 6698 array[ offset + 11 ] = te[ 11 ]; 6699 6700 array[ offset + 12 ] = te[ 12 ]; 6701 array[ offset + 13 ] = te[ 13 ]; 6702 array[ offset + 14 ] = te[ 14 ]; 6703 array[ offset + 15 ] = te[ 15 ]; 6704 6705 return array; 6706 6707 } 6708 6709} 6710 6711const _v1$5 = /*@__PURE__*/ new Vector3(); 6712const _m1$4 = /*@__PURE__*/ new Matrix4(); 6713const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 ); 6714const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 ); 6715const _x = /*@__PURE__*/ new Vector3(); 6716const _y = /*@__PURE__*/ new Vector3(); 6717const _z = /*@__PURE__*/ new Vector3(); 6718 6719const _matrix$2 = /*@__PURE__*/ new Matrix4(); 6720const _quaternion$3 = /*@__PURE__*/ new Quaternion(); 6721 6722class Euler { 6723 6724 constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) { 6725 6726 this.isEuler = true; 6727 6728 this._x = x; 6729 this._y = y; 6730 this._z = z; 6731 this._order = order; 6732 6733 } 6734 6735 get x() { 6736 6737 return this._x; 6738 6739 } 6740 6741 set x( value ) { 6742 6743 this._x = value; 6744 this._onChangeCallback(); 6745 6746 } 6747 6748 get y() { 6749 6750 return this._y; 6751 6752 } 6753 6754 set y( value ) { 6755 6756 this._y = value; 6757 this._onChangeCallback(); 6758 6759 } 6760 6761 get z() { 6762 6763 return this._z; 6764 6765 } 6766 6767 set z( value ) { 6768 6769 this._z = value; 6770 this._onChangeCallback(); 6771 6772 } 6773 6774 get order() { 6775 6776 return this._order; 6777 6778 } 6779 6780 set order( value ) { 6781 6782 this._order = value; 6783 this._onChangeCallback(); 6784 6785 } 6786 6787 set( x, y, z, order = this._order ) { 6788 6789 this._x = x; 6790 this._y = y; 6791 this._z = z; 6792 this._order = order; 6793 6794 this._onChangeCallback(); 6795 6796 return this; 6797 6798 } 6799 6800 clone() { 6801 6802 return new this.constructor( this._x, this._y, this._z, this._order ); 6803 6804 } 6805 6806 copy( euler ) { 6807 6808 this._x = euler._x; 6809 this._y = euler._y; 6810 this._z = euler._z; 6811 this._order = euler._order; 6812 6813 this._onChangeCallback(); 6814 6815 return this; 6816 6817 } 6818 6819 setFromRotationMatrix( m, order = this._order, update = true ) { 6820 6821 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 6822 6823 const te = m.elements; 6824 const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ]; 6825 const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ]; 6826 const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; 6827 6828 switch ( order ) { 6829 6830 case 'XYZ': 6831 6832 this._y = Math.asin( clamp( m13, - 1, 1 ) ); 6833 6834 if ( Math.abs( m13 ) < 0.9999999 ) { 6835 6836 this._x = Math.atan2( - m23, m33 ); 6837 this._z = Math.atan2( - m12, m11 ); 6838 6839 } else { 6840 6841 this._x = Math.atan2( m32, m22 ); 6842 this._z = 0; 6843 6844 } 6845 6846 break; 6847 6848 case 'YXZ': 6849 6850 this._x = Math.asin( - clamp( m23, - 1, 1 ) ); 6851 6852 if ( Math.abs( m23 ) < 0.9999999 ) { 6853 6854 this._y = Math.atan2( m13, m33 ); 6855 this._z = Math.atan2( m21, m22 ); 6856 6857 } else { 6858 6859 this._y = Math.atan2( - m31, m11 ); 6860 this._z = 0; 6861 6862 } 6863 6864 break; 6865 6866 case 'ZXY': 6867 6868 this._x = Math.asin( clamp( m32, - 1, 1 ) ); 6869 6870 if ( Math.abs( m32 ) < 0.9999999 ) { 6871 6872 this._y = Math.atan2( - m31, m33 ); 6873 this._z = Math.atan2( - m12, m22 ); 6874 6875 } else { 6876 6877 this._y = 0; 6878 this._z = Math.atan2( m21, m11 ); 6879 6880 } 6881 6882 break; 6883 6884 case 'ZYX': 6885 6886 this._y = Math.asin( - clamp( m31, - 1, 1 ) ); 6887 6888 if ( Math.abs( m31 ) < 0.9999999 ) { 6889 6890 this._x = Math.atan2( m32, m33 ); 6891 this._z = Math.atan2( m21, m11 ); 6892 6893 } else { 6894 6895 this._x = 0; 6896 this._z = Math.atan2( - m12, m22 ); 6897 6898 } 6899 6900 break; 6901 6902 case 'YZX': 6903 6904 this._z = Math.asin( clamp( m21, - 1, 1 ) ); 6905 6906 if ( Math.abs( m21 ) < 0.9999999 ) { 6907 6908 this._x = Math.atan2( - m23, m22 ); 6909 this._y = Math.atan2( - m31, m11 ); 6910 6911 } else { 6912 6913 this._x = 0; 6914 this._y = Math.atan2( m13, m33 ); 6915 6916 } 6917 6918 break; 6919 6920 case 'XZY': 6921 6922 this._z = Math.asin( - clamp( m12, - 1, 1 ) ); 6923 6924 if ( Math.abs( m12 ) < 0.9999999 ) { 6925 6926 this._x = Math.atan2( m32, m22 ); 6927 this._y = Math.atan2( m13, m11 ); 6928 6929 } else { 6930 6931 this._x = Math.atan2( - m23, m33 ); 6932 this._y = 0; 6933 6934 } 6935 6936 break; 6937 6938 default: 6939 6940 console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order ); 6941 6942 } 6943 6944 this._order = order; 6945 6946 if ( update === true ) this._onChangeCallback(); 6947 6948 return this; 6949 6950 } 6951 6952 setFromQuaternion( q, order, update ) { 6953 6954 _matrix$2.makeRotationFromQuaternion( q ); 6955 6956 return this.setFromRotationMatrix( _matrix$2, order, update ); 6957 6958 } 6959 6960 setFromVector3( v, order = this._order ) { 6961 6962 return this.set( v.x, v.y, v.z, order ); 6963 6964 } 6965 6966 reorder( newOrder ) { 6967 6968 // WARNING: this discards revolution information -bhouston 6969 6970 _quaternion$3.setFromEuler( this ); 6971 6972 return this.setFromQuaternion( _quaternion$3, newOrder ); 6973 6974 } 6975 6976 equals( euler ) { 6977 6978 return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); 6979 6980 } 6981 6982 fromArray( array ) { 6983 6984 this._x = array[ 0 ]; 6985 this._y = array[ 1 ]; 6986 this._z = array[ 2 ]; 6987 if ( array[ 3 ] !== undefined ) this._order = array[ 3 ]; 6988 6989 this._onChangeCallback(); 6990 6991 return this; 6992 6993 } 6994 6995 toArray( array = [], offset = 0 ) { 6996 6997 array[ offset ] = this._x; 6998 array[ offset + 1 ] = this._y; 6999 array[ offset + 2 ] = this._z; 7000 array[ offset + 3 ] = this._order; 7001 7002 return array; 7003 7004 } 7005 7006 _onChange( callback ) { 7007 7008 this._onChangeCallback = callback; 7009 7010 return this; 7011 7012 } 7013 7014 _onChangeCallback() {} 7015 7016 *[ Symbol.iterator ]() { 7017 7018 yield this._x; 7019 yield this._y; 7020 yield this._z; 7021 yield this._order; 7022 7023 } 7024 7025} 7026 7027Euler.DEFAULT_ORDER = 'XYZ'; 7028 7029class Layers { 7030 7031 constructor() { 7032 7033 this.mask = 1 | 0; 7034 7035 } 7036 7037 set( channel ) { 7038 7039 this.mask = ( 1 << channel | 0 ) >>> 0; 7040 7041 } 7042 7043 enable( channel ) { 7044 7045 this.mask |= 1 << channel | 0; 7046 7047 } 7048 7049 enableAll() { 7050 7051 this.mask = 0xffffffff | 0; 7052 7053 } 7054 7055 toggle( channel ) { 7056 7057 this.mask ^= 1 << channel | 0; 7058 7059 } 7060 7061 disable( channel ) { 7062 7063 this.mask &= ~ ( 1 << channel | 0 ); 7064 7065 } 7066 7067 disableAll() { 7068 7069 this.mask = 0; 7070 7071 } 7072 7073 test( layers ) { 7074 7075 return ( this.mask & layers.mask ) !== 0; 7076 7077 } 7078 7079 isEnabled( channel ) { 7080 7081 return ( this.mask & ( 1 << channel | 0 ) ) !== 0; 7082 7083 } 7084 7085} 7086 7087let _object3DId = 0; 7088 7089const _v1$4 = /*@__PURE__*/ new Vector3(); 7090const _q1 = /*@__PURE__*/ new Quaternion(); 7091const _m1$3 = /*@__PURE__*/ new Matrix4(); 7092const _target = /*@__PURE__*/ new Vector3(); 7093 7094const _position$3 = /*@__PURE__*/ new Vector3(); 7095const _scale$2 = /*@__PURE__*/ new Vector3(); 7096const _quaternion$2 = /*@__PURE__*/ new Quaternion(); 7097 7098const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 ); 7099const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 ); 7100const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 ); 7101 7102const _addedEvent = { type: 'added' }; 7103const _removedEvent = { type: 'removed' }; 7104 7105const _childaddedEvent = { type: 'childadded', child: null }; 7106const _childremovedEvent = { type: 'childremoved', child: null }; 7107
vendor: 7,170 bytes, lines 7108-7516
7108class Object3D extends EventDispatcher { 7109 7110 constructor() { 7111 7112 super(); 7113 7114 this.isObject3D = true; 7115 7116 Object.defineProperty( this, 'id', { value: _object3DId ++ } ); 7117 7118 this.uuid = generateUUID(); 7119 7120 this.name = ''; 7121 this.type = 'Object3D'; 7122 7123 this.parent = null; 7124 this.children = []; 7125 7126 this.up = Object3D.DEFAULT_UP.clone(); 7127 7128 const position = new Vector3(); 7129 const rotation = new Euler(); 7130 const quaternion = new Quaternion(); 7131 const scale = new Vector3( 1, 1, 1 ); 7132 7133 function onRotationChange() { 7134 7135 quaternion.setFromEuler( rotation, false ); 7136 7137 } 7138 7139 function onQuaternionChange() { 7140 7141 rotation.setFromQuaternion( quaternion, undefined, false ); 7142 7143 } 7144 7145 rotation._onChange( onRotationChange ); 7146 quaternion._onChange( onQuaternionChange ); 7147 7148 Object.defineProperties( this, { 7149 position: { 7150 configurable: true, 7151 enumerable: true, 7152 value: position 7153 }, 7154 rotation: { 7155 configurable: true, 7156 enumerable: true, 7157 value: rotation 7158 }, 7159 quaternion: { 7160 configurable: true, 7161 enumerable: true, 7162 value: quaternion 7163 }, 7164 scale: { 7165 configurable: true, 7166 enumerable: true, 7167 value: scale 7168 }, 7169 modelViewMatrix: { 7170 value: new Matrix4() 7171 }, 7172 normalMatrix: { 7173 value: new Matrix3() 7174 } 7175 } ); 7176 7177 this.matrix = new Matrix4(); 7178 this.matrixWorld = new Matrix4(); 7179 7180 this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE; 7181 7182 this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer 7183 this.matrixWorldNeedsUpdate = false; 7184 7185 this.layers = new Layers(); 7186 this.visible = true; 7187 7188 this.castShadow = false; 7189 this.receiveShadow = false; 7190 7191 this.frustumCulled = true; 7192 this.renderOrder = 0; 7193 7194 this.animations = []; 7195 7196 this.userData = {}; 7197 7198 } 7199 7200 onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} 7201 7202 onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} 7203 7204 onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {} 7205 7206 onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {} 7207 7208 applyMatrix4( matrix ) { 7209 7210 if ( this.matrixAutoUpdate ) this.updateMatrix(); 7211 7212 this.matrix.premultiply( matrix ); 7213 7214 this.matrix.decompose( this.position, this.quaternion, this.scale ); 7215 7216 } 7217 7218 applyQuaternion( q ) { 7219 7220 this.quaternion.premultiply( q ); 7221 7222 return this; 7223 7224 } 7225 7226 setRotationFromAxisAngle( axis, angle ) { 7227 7228 // assumes axis is normalized 7229 7230 this.quaternion.setFromAxisAngle( axis, angle ); 7231 7232 } 7233 7234 setRotationFromEuler( euler ) { 7235 7236 this.quaternion.setFromEuler( euler, true ); 7237 7238 } 7239 7240 setRotationFromMatrix( m ) { 7241 7242 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 7243 7244 this.quaternion.setFromRotationMatrix( m ); 7245 7246 } 7247 7248 setRotationFromQuaternion( q ) { 7249 7250 // assumes q is normalized 7251 7252 this.quaternion.copy( q ); 7253 7254 } 7255 7256 rotateOnAxis( axis, angle ) { 7257 7258 // rotate object on axis in object space 7259 // axis is assumed to be normalized 7260 7261 _q1.setFromAxisAngle( axis, angle ); 7262 7263 this.quaternion.multiply( _q1 ); 7264 7265 return this; 7266 7267 } 7268 7269 rotateOnWorldAxis( axis, angle ) { 7270 7271 // rotate object on axis in world space 7272 // axis is assumed to be normalized 7273 // method assumes no rotated parent 7274 7275 _q1.setFromAxisAngle( axis, angle ); 7276 7277 this.quaternion.premultiply( _q1 ); 7278 7279 return this; 7280 7281 } 7282 7283 rotateX( angle ) { 7284 7285 return this.rotateOnAxis( _xAxis, angle ); 7286 7287 } 7288 7289 rotateY( angle ) { 7290 7291 return this.rotateOnAxis( _yAxis, angle ); 7292 7293 } 7294 7295 rotateZ( angle ) { 7296 7297 return this.rotateOnAxis( _zAxis, angle ); 7298 7299 } 7300 7301 translateOnAxis( axis, distance ) { 7302 7303 // translate object by distance along axis in object space 7304 // axis is assumed to be normalized 7305 7306 _v1$4.copy( axis ).applyQuaternion( this.quaternion ); 7307 7308 this.position.add( _v1$4.multiplyScalar( distance ) ); 7309 7310 return this; 7311 7312 } 7313 7314 translateX( distance ) { 7315 7316 return this.translateOnAxis( _xAxis, distance ); 7317 7318 } 7319 7320 translateY( distance ) { 7321 7322 return this.translateOnAxis( _yAxis, distance ); 7323 7324 } 7325 7326 translateZ( distance ) { 7327 7328 return this.translateOnAxis( _zAxis, distance ); 7329 7330 } 7331 7332 localToWorld( vector ) { 7333 7334 this.updateWorldMatrix( true, false ); 7335 7336 return vector.applyMatrix4( this.matrixWorld ); 7337 7338 } 7339 7340 worldToLocal( vector ) { 7341 7342 this.updateWorldMatrix( true, false ); 7343 7344 return vector.applyMatrix4( _m1$3.copy( this.matrixWorld ).invert() ); 7345 7346 } 7347 7348 lookAt( x, y, z ) { 7349 7350 // This method does not support objects having non-uniformly-scaled parent(s) 7351 7352 if ( x.isVector3 ) { 7353 7354 _target.copy( x ); 7355 7356 } else { 7357 7358 _target.set( x, y, z ); 7359 7360 } 7361 7362 const parent = this.parent; 7363 7364 this.updateWorldMatrix( true, false ); 7365 7366 _position$3.setFromMatrixPosition( this.matrixWorld ); 7367 7368 if ( this.isCamera || this.isLight ) { 7369 7370 _m1$3.lookAt( _position$3, _target, this.up ); 7371 7372 } else { 7373 7374 _m1$3.lookAt( _target, _position$3, this.up ); 7375 7376 } 7377 7378 this.quaternion.setFromRotationMatrix( _m1$3 ); 7379 7380 if ( parent ) { 7381 7382 _m1$3.extractRotation( parent.matrixWorld ); 7383 _q1.setFromRotationMatrix( _m1$3 ); 7384 this.quaternion.premultiply( _q1.invert() ); 7385 7386 } 7387 7388 } 7389 7390 add( object ) { 7391 7392 if ( arguments.length > 1 ) { 7393 7394 for ( let i = 0; i < arguments.length; i ++ ) { 7395 7396 this.add( arguments[ i ] ); 7397 7398 } 7399 7400 return this; 7401 7402 } 7403 7404 if ( object === this ) { 7405 7406 console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object ); 7407 return this; 7408 7409 } 7410 7411 if ( object && object.isObject3D ) { 7412 7413 object.removeFromParent(); 7414 object.parent = this; 7415 this.children.push( object ); 7416 7417 object.dispatchEvent( _addedEvent ); 7418 7419 _childaddedEvent.child = object; 7420 this.dispatchEvent( _childaddedEvent ); 7421 _childaddedEvent.child = null; 7422 7423 } else { 7424 7425 console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object ); 7426 7427 } 7428 7429 return this; 7430 7431 } 7432 7433 remove( object ) { 7434 7435 if ( arguments.length > 1 ) { 7436 7437 for ( let i = 0; i < arguments.length; i ++ ) { 7438 7439 this.remove( arguments[ i ] ); 7440 7441 } 7442 7443 return this; 7444 7445 } 7446 7447 const index = this.children.indexOf( object ); 7448 7449 if ( index !== - 1 ) { 7450 7451 object.parent = null; 7452 this.children.splice( index, 1 ); 7453 7454 object.dispatchEvent( _removedEvent ); 7455 7456 _childremovedEvent.child = object; 7457 this.dispatchEvent( _childremovedEvent ); 7458 _childremovedEvent.child = null; 7459 7460 } 7461 7462 return this; 7463 7464 } 7465 7466 removeFromParent() { 7467 7468 const parent = this.parent; 7469 7470 if ( parent !== null ) { 7471 7472 parent.remove( this ); 7473 7474 } 7475 7476 return this; 7477 7478 } 7479 7480 clear() { 7481 7482 return this.remove( ... this.children ); 7483 7484 } 7485 7486 attach( object ) { 7487 7488 // adds object as a child of this, while maintaining the object's world transform 7489 7490 // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s) 7491 7492 this.updateWorldMatrix( true, false ); 7493 7494 _m1$3.copy( this.matrixWorld ).invert(); 7495 7496 if ( object.parent !== null ) { 7497 7498 object.parent.updateWorldMatrix( true, false ); 7499 7500 _m1$3.multiply( object.parent.matrixWorld ); 7501 7502 } 7503 7504 object.applyMatrix4( _m1$3 ); 7505 7506 object.removeFromParent(); 7507 object.parent = this; 7508 this.children.push( object ); 7509 7510 object.updateWorldMatrix( false, true ); 7511 7512 object.dispatchEvent( _addedEvent ); 7513 7514 _childaddedEvent.child = object; 7515 this.dispatchEvent( _childaddedEvent ); 7516 _childaddedEvent.child = null
vendor: 23,035 bytes, lines 7516-8532
7516; 7517 7518 return this; 7519 7520 } 7521 7522 getObjectById( id ) { 7523 7524 return this.getObjectByProperty( 'id', id ); 7525 7526 } 7527 7528 getObjectByName( name ) { 7529 7530 return this.getObjectByProperty( 'name', name ); 7531 7532 } 7533 7534 getObjectByProperty( name, value ) { 7535 7536 if ( this[ name ] === value ) return this; 7537 7538 for ( let i = 0, l = this.children.length; i < l; i ++ ) { 7539 7540 const child = this.children[ i ]; 7541 const object = child.getObjectByProperty( name, value ); 7542 7543 if ( object !== undefined ) { 7544 7545 return object; 7546 7547 } 7548 7549 } 7550 7551 return undefined; 7552 7553 } 7554 7555 getObjectsByProperty( name, value, result = [] ) { 7556 7557 if ( this[ name ] === value ) result.push( this ); 7558 7559 const children = this.children; 7560 7561 for ( let i = 0, l = children.length; i < l; i ++ ) { 7562 7563 children[ i ].getObjectsByProperty( name, value, result ); 7564 7565 } 7566 7567 return result; 7568 7569 } 7570 7571 getWorldPosition( target ) { 7572 7573 this.updateWorldMatrix( true, false ); 7574 7575 return target.setFromMatrixPosition( this.matrixWorld ); 7576 7577 } 7578 7579 getWorldQuaternion( target ) { 7580 7581 this.updateWorldMatrix( true, false ); 7582 7583 this.matrixWorld.decompose( _position$3, target, _scale$2 ); 7584 7585 return target; 7586 7587 } 7588 7589 getWorldScale( target ) { 7590 7591 this.updateWorldMatrix( true, false ); 7592 7593 this.matrixWorld.decompose( _position$3, _quaternion$2, target ); 7594 7595 return target; 7596 7597 } 7598 7599 getWorldDirection( target ) { 7600 7601 this.updateWorldMatrix( true, false ); 7602 7603 const e = this.matrixWorld.elements; 7604 7605 return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize(); 7606 7607 } 7608 7609 raycast( /* raycaster, intersects */ ) {} 7610 7611 traverse( callback ) { 7612 7613 callback( this ); 7614 7615 const children = this.children; 7616 7617 for ( let i = 0, l = children.length; i < l; i ++ ) { 7618 7619 children[ i ].traverse( callback ); 7620 7621 } 7622 7623 } 7624 7625 traverseVisible( callback ) { 7626 7627 if ( this.visible === false ) return; 7628 7629 callback( this ); 7630 7631 const children = this.children; 7632 7633 for ( let i = 0, l = children.length; i < l; i ++ ) { 7634 7635 children[ i ].traverseVisible( callback ); 7636 7637 } 7638 7639 } 7640 7641 traverseAncestors( callback ) { 7642 7643 const parent = this.parent; 7644 7645 if ( parent !== null ) { 7646 7647 callback( parent ); 7648 7649 parent.traverseAncestors( callback ); 7650 7651 } 7652 7653 } 7654 7655 updateMatrix() { 7656 7657 this.matrix.compose( this.position, this.quaternion, this.scale ); 7658 7659 this.matrixWorldNeedsUpdate = true; 7660 7661 } 7662 7663 updateMatrixWorld( force ) { 7664 7665 if ( this.matrixAutoUpdate ) this.updateMatrix(); 7666 7667 if ( this.matrixWorldNeedsUpdate || force ) { 7668 7669 if ( this.parent === null ) { 7670 7671 this.matrixWorld.copy( this.matrix ); 7672 7673 } else { 7674 7675 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); 7676 7677 } 7678 7679 this.matrixWorldNeedsUpdate = false; 7680 7681 force = true; 7682 7683 } 7684 7685 // update children 7686 7687 const children = this.children; 7688 7689 for ( let i = 0, l = children.length; i < l; i ++ ) { 7690 7691 const child = children[ i ]; 7692 7693 if ( child.matrixWorldAutoUpdate === true || force === true ) { 7694 7695 child.updateMatrixWorld( force ); 7696 7697 } 7698 7699 } 7700 7701 } 7702 7703 updateWorldMatrix( updateParents, updateChildren ) { 7704 7705 const parent = this.parent; 7706 7707 if ( updateParents === true && parent !== null && parent.matrixWorldAutoUpdate === true ) { 7708 7709 parent.updateWorldMatrix( true, false ); 7710 7711 } 7712 7713 if ( this.matrixAutoUpdate ) this.updateMatrix(); 7714 7715 if ( this.parent === null ) { 7716 7717 this.matrixWorld.copy( this.matrix ); 7718 7719 } else { 7720 7721 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); 7722 7723 } 7724 7725 // update children 7726 7727 if ( updateChildren === true ) { 7728 7729 const children = this.children; 7730 7731 for ( let i = 0, l = children.length; i < l; i ++ ) { 7732 7733 const child = children[ i ]; 7734 7735 if ( child.matrixWorldAutoUpdate === true ) { 7736 7737 child.updateWorldMatrix( false, true ); 7738 7739 } 7740 7741 } 7742 7743 } 7744 7745 } 7746 7747 toJSON( meta ) { 7748 7749 // meta is a string when called from JSON.stringify 7750 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 7751 7752 const output = {}; 7753 7754 // meta is a hash used to collect geometries, materials. 7755 // not providing it implies that this is the root object 7756 // being serialized. 7757 if ( isRootObject ) { 7758 7759 // initialize meta obj 7760 meta = { 7761 geometries: {}, 7762 materials: {}, 7763 textures: {}, 7764 images: {}, 7765 shapes: {}, 7766 skeletons: {}, 7767 animations: {}, 7768 nodes: {} 7769 }; 7770 7771 output.metadata = { 7772 version: 4.6, 7773 type: 'Object', 7774 generator: 'Object3D.toJSON' 7775 }; 7776 7777 } 7778 7779 // standard Object3D serialization 7780 7781 const object = {}; 7782 7783 object.uuid = this.uuid; 7784 object.type = this.type; 7785 7786 if ( this.name !== '' ) object.name = this.name; 7787 if ( this.castShadow === true ) object.castShadow = true; 7788 if ( this.receiveShadow === true ) object.receiveShadow = true; 7789 if ( this.visible === false ) object.visible = false; 7790 if ( this.frustumCulled === false ) object.frustumCulled = false; 7791 if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder; 7792 if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData; 7793 7794 object.layers = this.layers.mask; 7795 object.matrix = this.matrix.toArray(); 7796 object.up = this.up.toArray(); 7797 7798 if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; 7799 7800 // object specific properties 7801 7802 if ( this.isInstancedMesh ) { 7803 7804 object.type = 'InstancedMesh'; 7805 object.count = this.count; 7806 object.instanceMatrix = this.instanceMatrix.toJSON(); 7807 if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON(); 7808 7809 } 7810 7811 if ( this.isBatchedMesh ) { 7812 7813 object.type = 'BatchedMesh'; 7814 object.perObjectFrustumCulled = this.perObjectFrustumCulled; 7815 object.sortObjects = this.sortObjects; 7816 7817 object.drawRanges = this._drawRanges; 7818 object.reservedRanges = this._reservedRanges; 7819 7820 object.visibility = this._visibility; 7821 object.active = this._active; 7822 object.bounds = this._bounds.map( bound => ( { 7823 boxInitialized: bound.boxInitialized, 7824 boxMin: bound.box.min.toArray(), 7825 boxMax: bound.box.max.toArray(), 7826 7827 sphereInitialized: bound.sphereInitialized, 7828 sphereRadius: bound.sphere.radius, 7829 sphereCenter: bound.sphere.center.toArray() 7830 } ) ); 7831 7832 object.maxGeometryCount = this._maxGeometryCount; 7833 object.maxVertexCount = this._maxVertexCount; 7834 object.maxIndexCount = this._maxIndexCount; 7835 7836 object.geometryInitialized = this._geometryInitialized; 7837 object.geometryCount = this._geometryCount; 7838 7839 object.matricesTexture = this._matricesTexture.toJSON( meta ); 7840 7841 if ( this.boundingSphere !== null ) { 7842 7843 object.boundingSphere = { 7844 center: object.boundingSphere.center.toArray(), 7845 radius: object.boundingSphere.radius 7846 }; 7847 7848 } 7849 7850 if ( this.boundingBox !== null ) { 7851 7852 object.boundingBox = { 7853 min: object.boundingBox.min.toArray(), 7854 max: object.boundingBox.max.toArray() 7855 }; 7856 7857 } 7858 7859 } 7860 7861 // 7862 7863 function serialize( library, element ) { 7864 7865 if ( library[ element.uuid ] === undefined ) { 7866 7867 library[ element.uuid ] = element.toJSON( meta ); 7868 7869 } 7870 7871 return element.uuid; 7872 7873 } 7874 7875 if ( this.isScene ) { 7876 7877 if ( this.background ) { 7878 7879 if ( this.background.isColor ) { 7880 7881 object.background = this.background.toJSON(); 7882 7883 } else if ( this.background.isTexture ) { 7884 7885 object.background = this.background.toJSON( meta ).uuid; 7886 7887 } 7888 7889 } 7890 7891 if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) { 7892 7893 object.environment = this.environment.toJSON( meta ).uuid; 7894 7895 } 7896 7897 } else if ( this.isMesh || this.isLine || this.isPoints ) { 7898 7899 object.geometry = serialize( meta.geometries, this.geometry ); 7900 7901 const parameters = this.geometry.parameters; 7902 7903 if ( parameters !== undefined && parameters.shapes !== undefined ) { 7904 7905 const shapes = parameters.shapes; 7906 7907 if ( Array.isArray( shapes ) ) { 7908 7909 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 7910 7911 const shape = shapes[ i ]; 7912 7913 serialize( meta.shapes, shape ); 7914 7915 } 7916 7917 } else { 7918 7919 serialize( meta.shapes, shapes ); 7920 7921 } 7922 7923 } 7924 7925 } 7926 7927 if ( this.isSkinnedMesh ) { 7928 7929 object.bindMode = this.bindMode; 7930 object.bindMatrix = this.bindMatrix.toArray(); 7931 7932 if ( this.skeleton !== undefined ) { 7933 7934 serialize( meta.skeletons, this.skeleton ); 7935 7936 object.skeleton = this.skeleton.uuid; 7937 7938 } 7939 7940 } 7941 7942 if ( this.material !== undefined ) { 7943 7944 if ( Array.isArray( this.material ) ) { 7945 7946 const uuids = []; 7947 7948 for ( let i = 0, l = this.material.length; i < l; i ++ ) { 7949 7950 uuids.push( serialize( meta.materials, this.material[ i ] ) ); 7951 7952 } 7953 7954 object.material = uuids; 7955 7956 } else { 7957 7958 object.material = serialize( meta.materials, this.material ); 7959 7960 } 7961 7962 } 7963 7964 // 7965 7966 if ( this.children.length > 0 ) { 7967 7968 object.children = []; 7969 7970 for ( let i = 0; i < this.children.length; i ++ ) { 7971 7972 object.children.push( this.children[ i ].toJSON( meta ).object ); 7973 7974 } 7975 7976 } 7977 7978 // 7979 7980 if ( this.animations.length > 0 ) { 7981 7982 object.animations = []; 7983 7984 for ( let i = 0; i < this.animations.length; i ++ ) { 7985 7986 const animation = this.animations[ i ]; 7987 7988 object.animations.push( serialize( meta.animations, animation ) ); 7989 7990 } 7991 7992 } 7993 7994 if ( isRootObject ) { 7995 7996 const geometries = extractFromCache( meta.geometries ); 7997 const materials = extractFromCache( meta.materials ); 7998 const textures = extractFromCache( meta.textures ); 7999 const images = extractFromCache( meta.images ); 8000 const shapes = extractFromCache( meta.shapes ); 8001 const skeletons = extractFromCache( meta.skeletons ); 8002 const animations = extractFromCache( meta.animations ); 8003 const nodes = extractFromCache( meta.nodes ); 8004 8005 if ( geometries.length > 0 ) output.geometries = geometries; 8006 if ( materials.length > 0 ) output.materials = materials; 8007 if ( textures.length > 0 ) output.textures = textures; 8008 if ( images.length > 0 ) output.images = images; 8009 if ( shapes.length > 0 ) output.shapes = shapes; 8010 if ( skeletons.length > 0 ) output.skeletons = skeletons; 8011 if ( animations.length > 0 ) output.animations = animations; 8012 if ( nodes.length > 0 ) output.nodes = nodes; 8013 8014 } 8015 8016 output.object = object; 8017 8018 return output; 8019 8020 // extract data from the cache hash 8021 // remove metadata on each item 8022 // and return as array 8023 function extractFromCache( cache ) { 8024 8025 const values = []; 8026 for ( const key in cache ) { 8027 8028 const data = cache[ key ]; 8029 delete data.metadata; 8030 values.push( data ); 8031 8032 } 8033 8034 return values; 8035 8036 } 8037 8038 } 8039 8040 clone( recursive ) { 8041 8042 return new this.constructor().copy( this, recursive ); 8043 8044 } 8045 8046 copy( source, recursive = true ) { 8047 8048 this.name = source.name; 8049 8050 this.up.copy( source.up ); 8051 8052 this.position.copy( source.position ); 8053 this.rotation.order = source.rotation.order; 8054 this.quaternion.copy( source.quaternion ); 8055 this.scale.copy( source.scale ); 8056 8057 this.matrix.copy( source.matrix ); 8058 this.matrixWorld.copy( source.matrixWorld ); 8059 8060 this.matrixAutoUpdate = source.matrixAutoUpdate; 8061 8062 this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate; 8063 this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; 8064 8065 this.layers.mask = source.layers.mask; 8066 this.visible = source.visible; 8067 8068 this.castShadow = source.castShadow; 8069 this.receiveShadow = source.receiveShadow; 8070 8071 this.frustumCulled = source.frustumCulled; 8072 this.renderOrder = source.renderOrder; 8073 8074 this.animations = source.animations.slice(); 8075 8076 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 8077 8078 if ( recursive === true ) { 8079 8080 for ( let i = 0; i < source.children.length; i ++ ) { 8081 8082 const child = source.children[ i ]; 8083 this.add( child.clone() ); 8084 8085 } 8086 8087 } 8088 8089 return this; 8090 8091 } 8092 8093} 8094 8095Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 ); 8096Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true; 8097Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true; 8098 8099const _v0$1 = /*@__PURE__*/ new Vector3(); 8100const _v1$3 = /*@__PURE__*/ new Vector3(); 8101const _v2$2 = /*@__PURE__*/ new Vector3(); 8102const _v3$2 = /*@__PURE__*/ new Vector3(); 8103 8104const _vab = /*@__PURE__*/ new Vector3(); 8105const _vac = /*@__PURE__*/ new Vector3(); 8106const _vbc = /*@__PURE__*/ new Vector3(); 8107const _vap = /*@__PURE__*/ new Vector3(); 8108const _vbp = /*@__PURE__*/ new Vector3(); 8109const _vcp = /*@__PURE__*/ new Vector3(); 8110 8111class Triangle { 8112 8113 constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { 8114 8115 this.a = a; 8116 this.b = b; 8117 this.c = c; 8118 8119 } 8120 8121 static getNormal( a, b, c, target ) { 8122 8123 target.subVectors( c, b ); 8124 _v0$1.subVectors( a, b ); 8125 target.cross( _v0$1 ); 8126 8127 const targetLengthSq = target.lengthSq(); 8128 if ( targetLengthSq > 0 ) { 8129 8130 return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) ); 8131 8132 } 8133 8134 return target.set( 0, 0, 0 ); 8135 8136 } 8137 8138 // static/instance method to calculate barycentric coordinates 8139 // based on: http://www.blackpawn.com/texts/pointinpoly/default.html 8140 static getBarycoord( point, a, b, c, target ) { 8141 8142 _v0$1.subVectors( c, a ); 8143 _v1$3.subVectors( b, a ); 8144 _v2$2.subVectors( point, a ); 8145 8146 const dot00 = _v0$1.dot( _v0$1 ); 8147 const dot01 = _v0$1.dot( _v1$3 ); 8148 const dot02 = _v0$1.dot( _v2$2 ); 8149 const dot11 = _v1$3.dot( _v1$3 ); 8150 const dot12 = _v1$3.dot( _v2$2 ); 8151 8152 const denom = ( dot00 * dot11 - dot01 * dot01 ); 8153 8154 // collinear or singular triangle 8155 if ( denom === 0 ) { 8156 8157 target.set( 0, 0, 0 ); 8158 return null; 8159 8160 } 8161 8162 const invDenom = 1 / denom; 8163 const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; 8164 const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; 8165 8166 // barycentric coordinates must always sum to 1 8167 return target.set( 1 - u - v, v, u ); 8168 8169 } 8170 8171 static containsPoint( point, a, b, c ) { 8172 8173 // if the triangle is degenerate then we can't contain a point 8174 if ( this.getBarycoord( point, a, b, c, _v3$2 ) === null ) { 8175 8176 return false; 8177 8178 } 8179 8180 return ( _v3$2.x >= 0 ) && ( _v3$2.y >= 0 ) && ( ( _v3$2.x + _v3$2.y ) <= 1 ); 8181 8182 } 8183 8184 static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) { 8185 8186 if ( this.getBarycoord( point, p1, p2, p3, _v3$2 ) === null ) { 8187 8188 target.x = 0; 8189 target.y = 0; 8190 if ( 'z' in target ) target.z = 0; 8191 if ( 'w' in target ) target.w = 0; 8192 return null; 8193 8194 } 8195 8196 target.setScalar( 0 ); 8197 target.addScaledVector( v1, _v3$2.x ); 8198 target.addScaledVector( v2, _v3$2.y ); 8199 target.addScaledVector( v3, _v3$2.z ); 8200 8201 return target; 8202 8203 } 8204 8205 static isFrontFacing( a, b, c, direction ) { 8206 8207 _v0$1.subVectors( c, b ); 8208 _v1$3.subVectors( a, b ); 8209 8210 // strictly front facing 8211 return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false; 8212 8213 } 8214 8215 set( a, b, c ) { 8216 8217 this.a.copy( a ); 8218 this.b.copy( b ); 8219 this.c.copy( c ); 8220 8221 return this; 8222 8223 } 8224 8225 setFromPointsAndIndices( points, i0, i1, i2 ) { 8226 8227 this.a.copy( points[ i0 ] ); 8228 this.b.copy( points[ i1 ] ); 8229 this.c.copy( points[ i2 ] ); 8230 8231 return this; 8232 8233 } 8234 8235 setFromAttributeAndIndices( attribute, i0, i1, i2 ) { 8236 8237 this.a.fromBufferAttribute( attribute, i0 ); 8238 this.b.fromBufferAttribute( attribute, i1 ); 8239 this.c.fromBufferAttribute( attribute, i2 ); 8240 8241 return this; 8242 8243 } 8244 8245 clone() { 8246 8247 return new this.constructor().copy( this ); 8248 8249 } 8250 8251 copy( triangle ) { 8252 8253 this.a.copy( triangle.a ); 8254 this.b.copy( triangle.b ); 8255 this.c.copy( triangle.c ); 8256 8257 return this; 8258 8259 } 8260 8261 getArea() { 8262 8263 _v0$1.subVectors( this.c, this.b ); 8264 _v1$3.subVectors( this.a, this.b ); 8265 8266 return _v0$1.cross( _v1$3 ).length() * 0.5; 8267 8268 } 8269 8270 getMidpoint( target ) { 8271 8272 return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); 8273 8274 } 8275 8276 getNormal( target ) { 8277 8278 return Triangle.getNormal( this.a, this.b, this.c, target ); 8279 8280 } 8281 8282 getPlane( target ) { 8283 8284 return target.setFromCoplanarPoints( this.a, this.b, this.c ); 8285 8286 } 8287 8288 getBarycoord( point, target ) { 8289 8290 return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); 8291 8292 } 8293 8294 getInterpolation( point, v1, v2, v3, target ) { 8295 8296 return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target ); 8297 8298 } 8299 8300 containsPoint( point ) { 8301 8302 return Triangle.containsPoint( point, this.a, this.b, this.c ); 8303 8304 } 8305 8306 isFrontFacing( direction ) { 8307 8308 return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); 8309 8310 } 8311 8312 intersectsBox( box ) { 8313 8314 return box.intersectsTriangle( this ); 8315 8316 } 8317 8318 closestPointToPoint( p, target ) { 8319 8320 const a = this.a, b = this.b, c = this.c; 8321 let v, w; 8322 8323 // algorithm thanks to Real-Time Collision Detection by Christer Ericson, 8324 // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., 8325 // under the accompanying license; see chapter 5.1.5 for detailed explanation. 8326 // basically, we're distinguishing which of the voronoi regions of the triangle 8327 // the point lies in with the minimum amount of redundant computation. 8328 8329 _vab.subVectors( b, a ); 8330 _vac.subVectors( c, a ); 8331 _vap.subVectors( p, a ); 8332 const d1 = _vab.dot( _vap ); 8333 const d2 = _vac.dot( _vap ); 8334 if ( d1 <= 0 && d2 <= 0 ) { 8335 8336 // vertex region of A; barycentric coords (1, 0, 0) 8337 return target.copy( a ); 8338 8339 } 8340 8341 _vbp.subVectors( p, b ); 8342 const d3 = _vab.dot( _vbp ); 8343 const d4 = _vac.dot( _vbp ); 8344 if ( d3 >= 0 && d4 <= d3 ) { 8345 8346 // vertex region of B; barycentric coords (0, 1, 0) 8347 return target.copy( b ); 8348 8349 } 8350 8351 const vc = d1 * d4 - d3 * d2; 8352 if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { 8353 8354 v = d1 / ( d1 - d3 ); 8355 // edge region of AB; barycentric coords (1-v, v, 0) 8356 return target.copy( a ).addScaledVector( _vab, v ); 8357 8358 } 8359 8360 _vcp.subVectors( p, c ); 8361 const d5 = _vab.dot( _vcp ); 8362 const d6 = _vac.dot( _vcp ); 8363 if ( d6 >= 0 && d5 <= d6 ) { 8364 8365 // vertex region of C; barycentric coords (0, 0, 1) 8366 return target.copy( c ); 8367 8368 } 8369 8370 const vb = d5 * d2 - d1 * d6; 8371 if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { 8372 8373 w = d2 / ( d2 - d6 ); 8374 // edge region of AC; barycentric coords (1-w, 0, w) 8375 return target.copy( a ).addScaledVector( _vac, w ); 8376 8377 } 8378 8379 const va = d3 * d6 - d5 * d4; 8380 if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { 8381 8382 _vbc.subVectors( c, b ); 8383 w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); 8384 // edge region of BC; barycentric coords (0, 1-w, w) 8385 return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC 8386 8387 } 8388 8389 // face region 8390 const denom = 1 / ( va + vb + vc ); 8391 // u = va * denom 8392 v = vb * denom; 8393 w = vc * denom; 8394 8395 return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); 8396 8397 } 8398 8399 equals( triangle ) { 8400 8401 return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); 8402 8403 } 8404 8405} 8406 8407const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, 8408 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, 8409 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, 8410 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, 8411 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, 8412 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, 8413 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, 8414 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, 8415 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, 8416 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, 8417 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, 8418 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, 8419 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, 8420 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, 8421 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, 8422 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, 8423 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, 8424 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, 8425 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, 8426 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, 8427 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, 8428 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, 8429 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, 8430 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; 8431 8432const _hslA = { h: 0, s: 0, l: 0 }; 8433const _hslB = { h: 0, s: 0, l: 0 }; 8434 8435function hue2rgb( p, q, t ) { 8436 8437 if ( t < 0 ) t += 1; 8438 if ( t > 1 ) t -= 1; 8439 if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; 8440 if ( t < 1 / 2 ) return q; 8441 if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); 8442 return p; 8443 8444} 8445 8446class Color { 8447 8448 constructor( r, g, b ) { 8449 8450 this.isColor = true; 8451 8452 this.r = 1; 8453 this.g = 1; 8454 this.b = 1; 8455 8456 return this.set( r, g, b ); 8457 8458 } 8459 8460 set( r, g, b ) { 8461 8462 if ( g === undefined && b === undefined ) { 8463 8464 // r is THREE.Color, hex or string 8465 8466 const value = r; 8467 8468 if ( value && value.isColor ) { 8469 8470 this.copy( value ); 8471 8472 } else if ( typeof value === 'number' ) { 8473 8474 this.setHex( value ); 8475 8476 } else if ( typeof value === 'string' ) { 8477 8478 this.setStyle( value ); 8479 8480 } 8481 8482 } else { 8483 8484 this.setRGB( r, g, b ); 8485 8486 } 8487 8488 return this; 8489 8490 } 8491 8492 setScalar( scalar ) { 8493 8494 this.r = scalar; 8495 this.g = scalar; 8496 this.b = scalar; 8497 8498 return this; 8499 8500 } 8501 8502 setHex( hex, colorSpace = SRGBColorSpace ) { 8503 8504 hex = Math.floor( hex ); 8505 8506 this.r = ( hex >> 16 & 255 ) / 255; 8507 this.g = ( hex >> 8 & 255 ) / 255; 8508 this.b = ( hex & 255 ) / 255; 8509 8510 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8511 8512 return this; 8513 8514 } 8515 8516 setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { 8517 8518 this.r = r; 8519 this.g = g; 8520 this.b = b; 8521 8522 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8523 8524 return this; 8525 8526 } 8527 8528 setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { 8529 8530 // h,s,l ranges are in 0.0 - 1.0 8531 h = euclideanModulo( h, 1 ); 8532 s = clamp
vendor: 4,270 bytes, lines 8532-8765
8532( s, 0, 1 ); 8533 l = clamp( l, 0, 1 ); 8534 8535 if ( s === 0 ) { 8536 8537 this.r = this.g = this.b = l; 8538 8539 } else { 8540 8541 const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); 8542 const q = ( 2 * l ) - p; 8543 8544 this.r = hue2rgb( q, p, h + 1 / 3 ); 8545 this.g = hue2rgb( q, p, h ); 8546 this.b = hue2rgb( q, p, h - 1 / 3 ); 8547 8548 } 8549 8550 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8551 8552 return this; 8553 8554 } 8555 8556 setStyle( style, colorSpace = SRGBColorSpace ) { 8557 8558 function handleAlpha( string ) { 8559 8560 if ( string === undefined ) return; 8561 8562 if ( parseFloat( string ) < 1 ) { 8563 8564 console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); 8565 8566 } 8567 8568 } 8569 8570 8571 let m; 8572 8573 if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) { 8574 8575 // rgb / hsl 8576 8577 let color; 8578 const name = m[ 1 ]; 8579 const components = m[ 2 ]; 8580 8581 switch ( name ) { 8582 8583 case 'rgb': 8584 case 'rgba': 8585 8586 if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { 8587 8588 // rgb(255,0,0) rgba(255,0,0,0.5) 8589 8590 handleAlpha( color[ 4 ] ); 8591 8592 return this.setRGB( 8593 Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255, 8594 Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255, 8595 Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255, 8596 colorSpace 8597 ); 8598 8599 } 8600 8601 if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { 8602 8603 // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) 8604 8605 handleAlpha( color[ 4 ] ); 8606 8607 return this.setRGB( 8608 Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100, 8609 Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100, 8610 Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100, 8611 colorSpace 8612 ); 8613 8614 } 8615 8616 break; 8617 8618 case 'hsl': 8619 case 'hsla': 8620 8621 if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { 8622 8623 // hsl(120,50%,50%) hsla(120,50%,50%,0.5) 8624 8625 handleAlpha( color[ 4 ] ); 8626 8627 return this.setHSL( 8628 parseFloat( color[ 1 ] ) / 360, 8629 parseFloat( color[ 2 ] ) / 100, 8630 parseFloat( color[ 3 ] ) / 100, 8631 colorSpace 8632 ); 8633 8634 } 8635 8636 break; 8637 8638 default: 8639 8640 console.warn( 'THREE.Color: Unknown color model ' + style ); 8641 8642 } 8643 8644 } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { 8645 8646 // hex color 8647 8648 const hex = m[ 1 ]; 8649 const size = hex.length; 8650 8651 if ( size === 3 ) { 8652 8653 // #ff0 8654 return this.setRGB( 8655 parseInt( hex.charAt( 0 ), 16 ) / 15, 8656 parseInt( hex.charAt( 1 ), 16 ) / 15, 8657 parseInt( hex.charAt( 2 ), 16 ) / 15, 8658 colorSpace 8659 ); 8660 8661 } else if ( size === 6 ) { 8662 8663 // #ff0000 8664 return this.setHex( parseInt( hex, 16 ), colorSpace ); 8665 8666 } else { 8667 8668 console.warn( 'THREE.Color: Invalid hex color ' + style ); 8669 8670 } 8671 8672 } else if ( style && style.length > 0 ) { 8673 8674 return this.setColorName( style, colorSpace ); 8675 8676 } 8677 8678 return this; 8679 8680 } 8681 8682 setColorName( style, colorSpace = SRGBColorSpace ) { 8683 8684 // color keywords 8685 const hex = _colorKeywords[ style.toLowerCase() ]; 8686 8687 if ( hex !== undefined ) { 8688 8689 // red 8690 this.setHex( hex, colorSpace ); 8691 8692 } else { 8693 8694 // unknown color 8695 console.warn( 'THREE.Color: Unknown color ' + style ); 8696 8697 } 8698 8699 return this; 8700 8701 } 8702 8703 clone() { 8704 8705 return new this.constructor( this.r, this.g, this.b ); 8706 8707 } 8708 8709 copy( color ) { 8710 8711 this.r = color.r; 8712 this.g = color.g; 8713 this.b = color.b; 8714 8715 return this; 8716 8717 } 8718 8719 copySRGBToLinear( color ) { 8720 8721 this.r = SRGBToLinear( color.r ); 8722 this.g = SRGBToLinear( color.g ); 8723 this.b = SRGBToLinear( color.b ); 8724 8725 return this; 8726 8727 } 8728 8729 copyLinearToSRGB( color ) { 8730 8731 this.r = LinearToSRGB( color.r ); 8732 this.g = LinearToSRGB( color.g ); 8733 this.b = LinearToSRGB( color.b ); 8734 8735 return this; 8736 8737 } 8738 8739 convertSRGBToLinear() { 8740 8741 this.copySRGBToLinear( this ); 8742 8743 return this; 8744 8745 } 8746 8747 convertLinearToSRGB() { 8748 8749 this.copyLinearToSRGB( this ); 8750 8751 return this; 8752 8753 } 8754 8755 getHex( colorSpace = SRGBColorSpace ) { 8756 8757 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 8758 8759 return Math.round( clamp( _color.r * 255, 0, 255 ) ) * 65536 + Math.round( clamp( _color.g * 255, 0, 255 ) ) * 256 + Math.round( clamp( _color.b * 255, 0, 255 ) ); 8760 8761 } 8762 8763 getHexString( colorSpace = SRGBColorSpace ) { 8764 8765 return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( -
vendor: 21,438 bytes, lines 8765-9619
87656 ); 8766 8767 } 8768 8769 getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { 8770 8771 // h,s,l ranges are in 0.0 - 1.0 8772 8773 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 8774 8775 const r = _color.r, g = _color.g, b = _color.b; 8776 8777 const max = Math.max( r, g, b ); 8778 const min = Math.min( r, g, b ); 8779 8780 let hue, saturation; 8781 const lightness = ( min + max ) / 2.0; 8782 8783 if ( min === max ) { 8784 8785 hue = 0; 8786 saturation = 0; 8787 8788 } else { 8789 8790 const delta = max - min; 8791 8792 saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); 8793 8794 switch ( max ) { 8795 8796 case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; 8797 case g: hue = ( b - r ) / delta + 2; break; 8798 case b: hue = ( r - g ) / delta + 4; break; 8799 8800 } 8801 8802 hue /= 6; 8803 8804 } 8805 8806 target.h = hue; 8807 target.s = saturation; 8808 target.l = lightness; 8809 8810 return target; 8811 8812 } 8813 8814 getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { 8815 8816 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 8817 8818 target.r = _color.r; 8819 target.g = _color.g; 8820 target.b = _color.b; 8821 8822 return target; 8823 8824 } 8825 8826 getStyle( colorSpace = SRGBColorSpace ) { 8827 8828 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 8829 8830 const r = _color.r, g = _color.g, b = _color.b; 8831 8832 if ( colorSpace !== SRGBColorSpace ) { 8833 8834 // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). 8835 return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`; 8836 8837 } 8838 8839 return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`; 8840 8841 } 8842 8843 offsetHSL( h, s, l ) { 8844 8845 this.getHSL( _hslA ); 8846 8847 return this.setHSL( _hslA.h + h, _hslA.s + s, _hslA.l + l ); 8848 8849 } 8850 8851 add( color ) { 8852 8853 this.r += color.r; 8854 this.g += color.g; 8855 this.b += color.b; 8856 8857 return this; 8858 8859 } 8860 8861 addColors( color1, color2 ) { 8862 8863 this.r = color1.r + color2.r; 8864 this.g = color1.g + color2.g; 8865 this.b = color1.b + color2.b; 8866 8867 return this; 8868 8869 } 8870 8871 addScalar( s ) { 8872 8873 this.r += s; 8874 this.g += s; 8875 this.b += s; 8876 8877 return this; 8878 8879 } 8880 8881 sub( color ) { 8882 8883 this.r = Math.max( 0, this.r - color.r ); 8884 this.g = Math.max( 0, this.g - color.g ); 8885 this.b = Math.max( 0, this.b - color.b ); 8886 8887 return this; 8888 8889 } 8890 8891 multiply( color ) { 8892 8893 this.r *= color.r; 8894 this.g *= color.g; 8895 this.b *= color.b; 8896 8897 return this; 8898 8899 } 8900 8901 multiplyScalar( s ) { 8902 8903 this.r *= s; 8904 this.g *= s; 8905 this.b *= s; 8906 8907 return this; 8908 8909 } 8910 8911 lerp( color, alpha ) { 8912 8913 this.r += ( color.r - this.r ) * alpha; 8914 this.g += ( color.g - this.g ) * alpha; 8915 this.b += ( color.b - this.b ) * alpha; 8916 8917 return this; 8918 8919 } 8920 8921 lerpColors( color1, color2, alpha ) { 8922 8923 this.r = color1.r + ( color2.r - color1.r ) * alpha; 8924 this.g = color1.g + ( color2.g - color1.g ) * alpha; 8925 this.b = color1.b + ( color2.b - color1.b ) * alpha; 8926 8927 return this; 8928 8929 } 8930 8931 lerpHSL( color, alpha ) { 8932 8933 this.getHSL( _hslA ); 8934 color.getHSL( _hslB ); 8935 8936 const h = lerp( _hslA.h, _hslB.h, alpha ); 8937 const s = lerp( _hslA.s, _hslB.s, alpha ); 8938 const l = lerp( _hslA.l, _hslB.l, alpha ); 8939 8940 this.setHSL( h, s, l ); 8941 8942 return this; 8943 8944 } 8945 8946 setFromVector3( v ) { 8947 8948 this.r = v.x; 8949 this.g = v.y; 8950 this.b = v.z; 8951 8952 return this; 8953 8954 } 8955 8956 applyMatrix3( m ) { 8957 8958 const r = this.r, g = this.g, b = this.b; 8959 const e = m.elements; 8960 8961 this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b; 8962 this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b; 8963 this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b; 8964 8965 return this; 8966 8967 } 8968 8969 equals( c ) { 8970 8971 return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); 8972 8973 } 8974 8975 fromArray( array, offset = 0 ) { 8976 8977 this.r = array[ offset ]; 8978 this.g = array[ offset + 1 ]; 8979 this.b = array[ offset + 2 ]; 8980 8981 return this; 8982 8983 } 8984 8985 toArray( array = [], offset = 0 ) { 8986 8987 array[ offset ] = this.r; 8988 array[ offset + 1 ] = this.g; 8989 array[ offset + 2 ] = this.b; 8990 8991 return array; 8992 8993 } 8994 8995 fromBufferAttribute( attribute, index ) { 8996 8997 this.r = attribute.getX( index ); 8998 this.g = attribute.getY( index ); 8999 this.b = attribute.getZ( index ); 9000 9001 return this; 9002 9003 } 9004 9005 toJSON() { 9006 9007 return this.getHex(); 9008 9009 } 9010 9011 *[ Symbol.iterator ]() { 9012 9013 yield this.r; 9014 yield this.g; 9015 yield this.b; 9016 9017 } 9018 9019} 9020 9021const _color = /*@__PURE__*/ new Color(); 9022 9023Color.NAMES = _colorKeywords; 9024 9025let _materialId = 0; 9026 9027class Material extends EventDispatcher { 9028 9029 constructor() { 9030 9031 super(); 9032 9033 this.isMaterial = true; 9034 9035 Object.defineProperty( this, 'id', { value: _materialId ++ } ); 9036 9037 this.uuid = generateUUID(); 9038 9039 this.name = ''; 9040 this.type = 'Material'; 9041 9042 this.blending = NormalBlending; 9043 this.side = FrontSide; 9044 this.vertexColors = false; 9045 9046 this.opacity = 1; 9047 this.transparent = false; 9048 this.alphaHash = false; 9049 9050 this.blendSrc = SrcAlphaFactor; 9051 this.blendDst = OneMinusSrcAlphaFactor; 9052 this.blendEquation = AddEquation; 9053 this.blendSrcAlpha = null; 9054 this.blendDstAlpha = null; 9055 this.blendEquationAlpha = null; 9056 this.blendColor = new Color( 0, 0, 0 ); 9057 this.blendAlpha = 0; 9058 9059 this.depthFunc = LessEqualDepth; 9060 this.depthTest = true; 9061 this.depthWrite = true; 9062 9063 this.stencilWriteMask = 0xff; 9064 this.stencilFunc = AlwaysStencilFunc; 9065 this.stencilRef = 0; 9066 this.stencilFuncMask = 0xff; 9067 this.stencilFail = KeepStencilOp; 9068 this.stencilZFail = KeepStencilOp; 9069 this.stencilZPass = KeepStencilOp; 9070 this.stencilWrite = false; 9071 9072 this.clippingPlanes = null; 9073 this.clipIntersection = false; 9074 this.clipShadows = false; 9075 9076 this.shadowSide = null; 9077 9078 this.colorWrite = true; 9079 9080 this.precision = null; // override the renderer's default precision for this material 9081 9082 this.polygonOffset = false; 9083 this.polygonOffsetFactor = 0; 9084 this.polygonOffsetUnits = 0; 9085 9086 this.dithering = false; 9087 9088 this.alphaToCoverage = false; 9089 this.premultipliedAlpha = false; 9090 this.forceSinglePass = false; 9091 9092 this.visible = true; 9093 9094 this.toneMapped = true; 9095 9096 this.userData = {}; 9097 9098 this.version = 0; 9099 9100 this._alphaTest = 0; 9101 9102 } 9103 9104 get alphaTest() { 9105 9106 return this._alphaTest; 9107 9108 } 9109 9110 set alphaTest( value ) { 9111 9112 if ( this._alphaTest > 0 !== value > 0 ) { 9113 9114 this.version ++; 9115 9116 } 9117 9118 this._alphaTest = value; 9119 9120 } 9121 9122 onBuild( /* shaderobject, renderer */ ) {} 9123 9124 onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} 9125 9126 onBeforeCompile( /* shaderobject, renderer */ ) {} 9127 9128 customProgramCacheKey() { 9129 9130 return this.onBeforeCompile.toString(); 9131 9132 } 9133 9134 setValues( values ) { 9135 9136 if ( values === undefined ) return; 9137 9138 for ( const key in values ) { 9139 9140 const newValue = values[ key ]; 9141 9142 if ( newValue === undefined ) { 9143 9144 console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` ); 9145 continue; 9146 9147 } 9148 9149 const currentValue = this[ key ]; 9150 9151 if ( currentValue === undefined ) { 9152 9153 console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` ); 9154 continue; 9155 9156 } 9157 9158 if ( currentValue && currentValue.isColor ) { 9159 9160 currentValue.set( newValue ); 9161 9162 } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { 9163 9164 currentValue.copy( newValue ); 9165 9166 } else { 9167 9168 this[ key ] = newValue; 9169 9170 } 9171 9172 } 9173 9174 } 9175 9176 toJSON( meta ) { 9177 9178 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 9179 9180 if ( isRootObject ) { 9181 9182 meta = { 9183 textures: {}, 9184 images: {} 9185 }; 9186 9187 } 9188 9189 const data = { 9190 metadata: { 9191 version: 4.6, 9192 type: 'Material', 9193 generator: 'Material.toJSON' 9194 } 9195 }; 9196 9197 // standard Material serialization 9198 data.uuid = this.uuid; 9199 data.type = this.type; 9200 9201 if ( this.name !== '' ) data.name = this.name; 9202 9203 if ( this.color && this.color.isColor ) data.color = this.color.getHex(); 9204 9205 if ( this.roughness !== undefined ) data.roughness = this.roughness; 9206 if ( this.metalness !== undefined ) data.metalness = this.metalness; 9207 9208 if ( this.sheen !== undefined ) data.sheen = this.sheen; 9209 if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); 9210 if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; 9211 if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); 9212 if ( this.emissiveIntensity !== undefined && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; 9213 9214 if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); 9215 if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; 9216 if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); 9217 if ( this.shininess !== undefined ) data.shininess = this.shininess; 9218 if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; 9219 if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; 9220 9221 if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { 9222 9223 data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; 9224 9225 } 9226 9227 if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { 9228 9229 data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; 9230 9231 } 9232 9233 if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { 9234 9235 data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; 9236 data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); 9237 9238 } 9239 9240 if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; 9241 if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; 9242 if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; 9243 9244 if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { 9245 9246 data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; 9247 9248 } 9249 9250 if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { 9251 9252 data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; 9253 9254 } 9255 9256 if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy; 9257 if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation; 9258 9259 if ( this.anisotropyMap && this.anisotropyMap.isTexture ) { 9260 9261 data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid; 9262 9263 } 9264 9265 if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; 9266 if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; 9267 if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; 9268 9269 if ( this.lightMap && this.lightMap.isTexture ) { 9270 9271 data.lightMap = this.lightMap.toJSON( meta ).uuid; 9272 data.lightMapIntensity = this.lightMapIntensity; 9273 9274 } 9275 9276 if ( this.aoMap && this.aoMap.isTexture ) { 9277 9278 data.aoMap = this.aoMap.toJSON( meta ).uuid; 9279 data.aoMapIntensity = this.aoMapIntensity; 9280 9281 } 9282 9283 if ( this.bumpMap && this.bumpMap.isTexture ) { 9284 9285 data.bumpMap = this.bumpMap.toJSON( meta ).uuid; 9286 data.bumpScale = this.bumpScale; 9287 9288 } 9289 9290 if ( this.normalMap && this.normalMap.isTexture ) { 9291 9292 data.normalMap = this.normalMap.toJSON( meta ).uuid; 9293 data.normalMapType = this.normalMapType; 9294 data.normalScale = this.normalScale.toArray(); 9295 9296 } 9297 9298 if ( this.displacementMap && this.displacementMap.isTexture ) { 9299 9300 data.displacementMap = this.displacementMap.toJSON( meta ).uuid; 9301 data.displacementScale = this.displacementScale; 9302 data.displacementBias = this.displacementBias; 9303 9304 } 9305 9306 if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; 9307 if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; 9308 9309 if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; 9310 if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; 9311 if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; 9312 if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; 9313 9314 if ( this.envMap && this.envMap.isTexture ) { 9315 9316 data.envMap = this.envMap.toJSON( meta ).uuid; 9317 9318 if ( this.combine !== undefined ) data.combine = this.combine; 9319 9320 } 9321 9322 if ( this.envMapRotation !== undefined ) data.envMapRotation = this.envMapRotation.toArray(); 9323 if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; 9324 if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; 9325 if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; 9326 9327 if ( this.gradientMap && this.gradientMap.isTexture ) { 9328 9329 data.gradientMap = this.gradientMap.toJSON( meta ).uuid; 9330 9331 } 9332 9333 if ( this.transmission !== undefined ) data.transmission = this.transmission; 9334 if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; 9335 if ( this.thickness !== undefined ) data.thickness = this.thickness; 9336 if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; 9337 if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; 9338 if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); 9339 9340 if ( this.size !== undefined ) data.size = this.size; 9341 if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; 9342 if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; 9343 9344 if ( this.blending !== NormalBlending ) data.blending = this.blending; 9345 if ( this.side !== FrontSide ) data.side = this.side; 9346 if ( this.vertexColors === true ) data.vertexColors = true; 9347 9348 if ( this.opacity < 1 ) data.opacity = this.opacity; 9349 if ( this.transparent === true ) data.transparent = true; 9350 9351 if ( this.blendSrc !== SrcAlphaFactor ) data.blendSrc = this.blendSrc; 9352 if ( this.blendDst !== OneMinusSrcAlphaFactor ) data.blendDst = this.blendDst; 9353 if ( this.blendEquation !== AddEquation ) data.blendEquation = this.blendEquation; 9354 if ( this.blendSrcAlpha !== null ) data.blendSrcAlpha = this.blendSrcAlpha; 9355 if ( this.blendDstAlpha !== null ) data.blendDstAlpha = this.blendDstAlpha; 9356 if ( this.blendEquationAlpha !== null ) data.blendEquationAlpha = this.blendEquationAlpha; 9357 if ( this.blendColor && this.blendColor.isColor ) data.blendColor = this.blendColor.getHex(); 9358 if ( this.blendAlpha !== 0 ) data.blendAlpha = this.blendAlpha; 9359 9360 if ( this.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc; 9361 if ( this.depthTest === false ) data.depthTest = this.depthTest; 9362 if ( this.depthWrite === false ) data.depthWrite = this.depthWrite; 9363 if ( this.colorWrite === false ) data.colorWrite = this.colorWrite; 9364 9365 if ( this.stencilWriteMask !== 0xff ) data.stencilWriteMask = this.stencilWriteMask; 9366 if ( this.stencilFunc !== AlwaysStencilFunc ) data.stencilFunc = this.stencilFunc; 9367 if ( this.stencilRef !== 0 ) data.stencilRef = this.stencilRef; 9368 if ( this.stencilFuncMask !== 0xff ) data.stencilFuncMask = this.stencilFuncMask; 9369 if ( this.stencilFail !== KeepStencilOp ) data.stencilFail = this.stencilFail; 9370 if ( this.stencilZFail !== KeepStencilOp ) data.stencilZFail = this.stencilZFail; 9371 if ( this.stencilZPass !== KeepStencilOp ) data.stencilZPass = this.stencilZPass; 9372 if ( this.stencilWrite === true ) data.stencilWrite = this.stencilWrite; 9373 9374 // rotation (SpriteMaterial) 9375 if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; 9376 9377 if ( this.polygonOffset === true ) data.polygonOffset = true; 9378 if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; 9379 if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; 9380 9381 if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; 9382 if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; 9383 if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; 9384 if ( this.scale !== undefined ) data.scale = this.scale; 9385 9386 if ( this.dithering === true ) data.dithering = true; 9387 9388 if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; 9389 if ( this.alphaHash === true ) data.alphaHash = true; 9390 if ( this.alphaToCoverage === true ) data.alphaToCoverage = true; 9391 if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = true; 9392 if ( this.forceSinglePass === true ) data.forceSinglePass = true; 9393 9394 if ( this.wireframe === true ) data.wireframe = true; 9395 if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; 9396 if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; 9397 if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; 9398 9399 if ( this.flatShading === true ) data.flatShading = true; 9400 9401 if ( this.visible === false ) data.visible = false; 9402 9403 if ( this.toneMapped === false ) data.toneMapped = false; 9404 9405 if ( this.fog === false ) data.fog = false; 9406 9407 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; 9408 9409 // TODO: Copied from Object3D.toJSON 9410 9411 function extractFromCache( cache ) { 9412 9413 const values = []; 9414 9415 for ( const key in cache ) { 9416 9417 const data = cache[ key ]; 9418 delete data.metadata; 9419 values.push( data ); 9420 9421 } 9422 9423 return values; 9424 9425 } 9426 9427 if ( isRootObject ) { 9428 9429 const textures = extractFromCache( meta.textures ); 9430 const images = extractFromCache( meta.images ); 9431 9432 if ( textures.length > 0 ) data.textures = textures; 9433 if ( images.length > 0 ) data.images = images; 9434 9435 } 9436 9437 return data; 9438 9439 } 9440 9441 clone() { 9442 9443 return new this.constructor().copy( this ); 9444 9445 } 9446 9447 copy( source ) { 9448 9449 this.name = source.name; 9450 9451 this.blending = source.blending; 9452 this.side = source.side; 9453 this.vertexColors = source.vertexColors; 9454 9455 this.opacity = source.opacity; 9456 this.transparent = source.transparent; 9457 9458 this.blendSrc = source.blendSrc; 9459 this.blendDst = source.blendDst; 9460 this.blendEquation = source.blendEquation; 9461 this.blendSrcAlpha = source.blendSrcAlpha; 9462 this.blendDstAlpha = source.blendDstAlpha; 9463 this.blendEquationAlpha = source.blendEquationAlpha; 9464 this.blendColor.copy( source.blendColor ); 9465 this.blendAlpha = source.blendAlpha; 9466 9467 this.depthFunc = source.depthFunc; 9468 this.depthTest = source.depthTest; 9469 this.depthWrite = source.depthWrite; 9470 9471 this.stencilWriteMask = source.stencilWriteMask; 9472 this.stencilFunc = source.stencilFunc; 9473 this.stencilRef = source.stencilRef; 9474 this.stencilFuncMask = source.stencilFuncMask; 9475 this.stencilFail = source.stencilFail; 9476 this.stencilZFail = source.stencilZFail; 9477 this.stencilZPass = source.stencilZPass; 9478 this.stencilWrite = source.stencilWrite; 9479 9480 const srcPlanes = source.clippingPlanes; 9481 let dstPlanes = null; 9482 9483 if ( srcPlanes !== null ) { 9484 9485 const n = srcPlanes.length; 9486 dstPlanes = new Array( n ); 9487 9488 for ( let i = 0; i !== n; ++ i ) { 9489 9490 dstPlanes[ i ] = srcPlanes[ i ].clone(); 9491 9492 } 9493 9494 } 9495 9496 this.clippingPlanes = dstPlanes; 9497 this.clipIntersection = source.clipIntersection; 9498 this.clipShadows = source.clipShadows; 9499 9500 this.shadowSide = source.shadowSide; 9501 9502 this.colorWrite = source.colorWrite; 9503 9504 this.precision = source.precision; 9505 9506 this.polygonOffset = source.polygonOffset; 9507 this.polygonOffsetFactor = source.polygonOffsetFactor; 9508 this.polygonOffsetUnits = source.polygonOffsetUnits; 9509 9510 this.dithering = source.dithering; 9511 9512 this.alphaTest = source.alphaTest; 9513 this.alphaHash = source.alphaHash; 9514 this.alphaToCoverage = source.alphaToCoverage; 9515 this.premultipliedAlpha = source.premultipliedAlpha; 9516 this.forceSinglePass = source.forceSinglePass; 9517 9518 this.visible = source.visible; 9519 9520 this.toneMapped = source.toneMapped; 9521 9522 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 9523 9524 return this; 9525 9526 } 9527 9528 dispose() { 9529 9530 this.dispatchEvent( { type: 'dispose' } ); 9531 9532 } 9533 9534 set needsUpdate( value ) { 9535 9536 if ( value === true ) this.version ++; 9537 9538 } 9539 9540} 9541 9542class MeshBasicMaterial extends Material { 9543 9544 constructor( parameters ) { 9545 9546 super(); 9547 9548 this.isMeshBasicMaterial = true; 9549 9550 this.type = 'MeshBasicMaterial'; 9551 9552 this.color = new Color( 0xffffff ); // emissive 9553 9554 this.map = null; 9555 9556 this.lightMap = null; 9557 this.lightMapIntensity = 1.0; 9558 9559 this.aoMap = null; 9560 this.aoMapIntensity = 1.0; 9561 9562 this.specularMap = null; 9563 9564 this.alphaMap = null; 9565 9566 this.envMap = null; 9567 this.envMapRotation = new Euler(); 9568 this.combine = MultiplyOperation; 9569 this.reflectivity = 1; 9570 this.refractionRatio = 0.98; 9571 9572 this.wireframe = false; 9573 this.wireframeLinewidth = 1; 9574 this.wireframeLinecap = 'round'; 9575 this.wireframeLinejoin = 'round'; 9576 9577 this.fog = true; 9578 9579 this.setValues( parameters ); 9580 9581 } 9582 9583 copy( source ) { 9584 9585 super.copy( source ); 9586 9587 this.color.copy( source.color ); 9588 9589 this.map = source.map; 9590 9591 this.lightMap = source.lightMap; 9592 this.lightMapIntensity = source.lightMapIntensity; 9593 9594 this.aoMap = source.aoMap; 9595 this.aoMapIntensity = source.aoMapIntensity; 9596 9597 this.specularMap = source.specularMap; 9598 9599 this.alphaMap = source.alphaMap; 9600 9601 this.envMap = source.envMap; 9602 this.envMapRotation.copy( source.envMapRotation ); 9603 this.combine = source.combine; 9604 this.reflectivity = source.reflectivity; 9605 this.refractionRatio = source.refractionRatio; 9606 9607 this.wireframe = source.wireframe; 9608 this.wireframeLinewidth = source.wireframeLinewidth; 9609 this.wireframeLinecap = source.wireframeLinecap; 9610 this.wireframeLinejoin = source.wireframeLinejoin; 9611 9612 this.fog = source.fog; 9613 9614 return this; 9615 9616 } 9617 9618} 9619
vendor: 4,666 bytes, lines 9620-9858
9620// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf 9621 9622const _tables = /*@__PURE__*/ _generateTables(); 9623 9624function _generateTables() { 9625 9626 // float32 to float16 helpers 9627 9628 const buffer = new ArrayBuffer( 4 ); 9629 const floatView = new Float32Array( buffer ); 9630 const uint32View = new Uint32Array( buffer ); 9631 9632 const baseTable = new Uint32Array( 512 ); 9633 const shiftTable = new Uint32Array( 512 ); 9634 9635 for ( let i = 0; i < 256; ++ i ) { 9636 9637 const e = i - 127; 9638 9639 // very small number (0, -0) 9640 9641 if ( e < - 27 ) { 9642 9643 baseTable[ i ] = 0x0000; 9644 baseTable[ i | 0x100 ] = 0x8000; 9645 shiftTable[ i ] = 24; 9646 shiftTable[ i | 0x100 ] = 24; 9647 9648 // small number (denorm) 9649 9650 } else if ( e < - 14 ) { 9651 9652 baseTable[ i ] = 0x0400 >> ( - e - 14 ); 9653 baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000; 9654 shiftTable[ i ] = - e - 1; 9655 shiftTable[ i | 0x100 ] = - e - 1; 9656 9657 // normal number 9658 9659 } else if ( e <= 15 ) { 9660 9661 baseTable[ i ] = ( e + 15 ) << 10; 9662 baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000; 9663 shiftTable[ i ] = 13; 9664 shiftTable[ i | 0x100 ] = 13; 9665 9666 // large number (Infinity, -Infinity) 9667 9668 } else if ( e < 128 ) { 9669 9670 baseTable[ i ] = 0x7c00; 9671 baseTable[ i | 0x100 ] = 0xfc00; 9672 shiftTable[ i ] = 24; 9673 shiftTable[ i | 0x100 ] = 24; 9674 9675 // stay (NaN, Infinity, -Infinity) 9676 9677 } else { 9678 9679 baseTable[ i ] = 0x7c00; 9680 baseTable[ i | 0x100 ] = 0xfc00; 9681 shiftTable[ i ] = 13; 9682 shiftTable[ i | 0x100 ] = 13; 9683 9684 } 9685 9686 } 9687 9688 // float16 to float32 helpers 9689 9690 const mantissaTable = new Uint32Array( 2048 ); 9691 const exponentTable = new Uint32Array( 64 ); 9692 const offsetTable = new Uint32Array( 64 ); 9693 9694 for ( let i = 1; i < 1024; ++ i ) { 9695 9696 let m = i << 13; // zero pad mantissa bits 9697 let e = 0; // zero exponent 9698 9699 // normalized 9700 while ( ( m & 0x00800000 ) === 0 ) { 9701 9702 m <<= 1; 9703 e -= 0x00800000; // decrement exponent 9704 9705 } 9706 9707 m &= ~ 0x00800000; // clear leading 1 bit 9708 e += 0x38800000; // adjust bias 9709 9710 mantissaTable[ i ] = m | e; 9711 9712 } 9713 9714 for ( let i = 1024; i < 2048; ++ i ) { 9715 9716 mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 ); 9717 9718 } 9719 9720 for ( let i = 1; i < 31; ++ i ) { 9721 9722 exponentTable[ i ] = i << 23; 9723 9724 } 9725 9726 exponentTable[ 31 ] = 0x47800000; 9727 exponentTable[ 32 ] = 0x80000000; 9728 9729 for ( let i = 33; i < 63; ++ i ) { 9730 9731 exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 ); 9732 9733 } 9734 9735 exponentTable[ 63 ] = 0xc7800000; 9736 9737 for ( let i = 1; i < 64; ++ i ) { 9738 9739 if ( i !== 32 ) { 9740 9741 offsetTable[ i ] = 1024; 9742 9743 } 9744 9745 } 9746 9747 return { 9748 floatView: floatView, 9749 uint32View: uint32View, 9750 baseTable: baseTable, 9751 shiftTable: shiftTable, 9752 mantissaTable: mantissaTable, 9753 exponentTable: exponentTable, 9754 offsetTable: offsetTable 9755 }; 9756 9757} 9758 9759// float32 to float16 9760 9761function toHalfFloat( val ) { 9762 9763 if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' ); 9764 9765 val = clamp( val, - 65504, 65504 ); 9766 9767 _tables.floatView[ 0 ] = val; 9768 const f = _tables.uint32View[ 0 ]; 9769 const e = ( f >> 23 ) & 0x1ff; 9770 return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] ); 9771 9772} 9773 9774// float16 to float32 9775 9776function fromHalfFloat( val ) { 9777 9778 const m = val >> 10; 9779 _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ]; 9780 return _tables.floatView[ 0 ]; 9781 9782} 9783 9784const DataUtils = { 9785 toHalfFloat: toHalfFloat, 9786 fromHalfFloat: fromHalfFloat, 9787}; 9788 9789const _vector$9 = /*@__PURE__*/ new Vector3(); 9790const _vector2$1 = /*@__PURE__*/ new Vector2(); 9791 9792class BufferAttribute { 9793 9794 constructor( array, itemSize, normalized = false ) { 9795 9796 if ( Array.isArray( array ) ) { 9797 9798 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); 9799 9800 } 9801 9802 this.isBufferAttribute = true; 9803 9804 this.name = ''; 9805 9806 this.array = array; 9807 this.itemSize = itemSize; 9808 this.count = array !== undefined ? array.length / itemSize : 0; 9809 this.normalized = normalized; 9810 9811 this.usage = StaticDrawUsage; 9812 this._updateRange = { offset: 0, count: - 1 }; 9813 this.updateRanges = []; 9814 this.gpuType = FloatType; 9815 9816 this.version = 0; 9817 9818 } 9819 9820 onUploadCallback() {} 9821 9822 set needsUpdate( value ) { 9823 9824 if ( value === true ) this.version ++; 9825 9826 } 9827 9828 get updateRange() { 9829 9830 warnOnce( 'THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 9831 return this._updateRange; 9832 9833 } 9834 9835 setUsage( value ) { 9836 9837 this.usage = value; 9838 9839 return this; 9840 9841 } 9842 9843 addUpdateRange( start, count ) { 9844 9845 this.updateRanges.push( { start, count } ); 9846 9847 } 9848 9849 clearUpdateRanges() { 9850 9851 this.updateRanges.length = 0; 9852 9853 } 9854 9855 copy( source ) { 9856 9857 this.name = source.name; 9858 this.array = new source.array.constructor( source.array );
vendor: 8,607 bytes, lines 9859-10390
9859 this.itemSize = source.itemSize; 9860 this.count = source.count; 9861 this.normalized = source.normalized; 9862 9863 this.usage = source.usage; 9864 this.gpuType = source.gpuType; 9865 9866 return this; 9867 9868 } 9869 9870 copyAt( index1, attribute, index2 ) { 9871 9872 index1 *= this.itemSize; 9873 index2 *= attribute.itemSize; 9874 9875 for ( let i = 0, l = this.itemSize; i < l; i ++ ) { 9876 9877 this.array[ index1 + i ] = attribute.array[ index2 + i ]; 9878 9879 } 9880 9881 return this; 9882 9883 } 9884 9885 copyArray( array ) { 9886 9887 this.array.set( array ); 9888 9889 return this; 9890 9891 } 9892 9893 applyMatrix3( m ) { 9894 9895 if ( this.itemSize === 2 ) { 9896 9897 for ( let i = 0, l = this.count; i < l; i ++ ) { 9898 9899 _vector2$1.fromBufferAttribute( this, i ); 9900 _vector2$1.applyMatrix3( m ); 9901 9902 this.setXY( i, _vector2$1.x, _vector2$1.y ); 9903 9904 } 9905 9906 } else if ( this.itemSize === 3 ) { 9907 9908 for ( let i = 0, l = this.count; i < l; i ++ ) { 9909 9910 _vector$9.fromBufferAttribute( this, i ); 9911 _vector$9.applyMatrix3( m ); 9912 9913 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 9914 9915 } 9916 9917 } 9918 9919 return this; 9920 9921 } 9922 9923 applyMatrix4( m ) { 9924 9925 for ( let i = 0, l = this.count; i < l; i ++ ) { 9926 9927 _vector$9.fromBufferAttribute( this, i ); 9928 9929 _vector$9.applyMatrix4( m ); 9930 9931 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 9932 9933 } 9934 9935 return this; 9936 9937 } 9938 9939 applyNormalMatrix( m ) { 9940 9941 for ( let i = 0, l = this.count; i < l; i ++ ) { 9942 9943 _vector$9.fromBufferAttribute( this, i ); 9944 9945 _vector$9.applyNormalMatrix( m ); 9946 9947 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 9948 9949 } 9950 9951 return this; 9952 9953 } 9954 9955 transformDirection( m ) { 9956 9957 for ( let i = 0, l = this.count; i < l; i ++ ) { 9958 9959 _vector$9.fromBufferAttribute( this, i ); 9960 9961 _vector$9.transformDirection( m ); 9962 9963 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 9964 9965 } 9966 9967 return this; 9968 9969 } 9970 9971 set( value, offset = 0 ) { 9972 9973 // Matching BufferAttribute constructor, do not normalize the array. 9974 this.array.set( value, offset ); 9975 9976 return this; 9977 9978 } 9979 9980 getComponent( index, component ) { 9981 9982 let value = this.array[ index * this.itemSize + component ]; 9983 9984 if ( this.normalized ) value = denormalize( value, this.array ); 9985 9986 return value; 9987 9988 } 9989 9990 setComponent( index, component, value ) { 9991 9992 if ( this.normalized ) value = normalize( value, this.array ); 9993 9994 this.array[ index * this.itemSize + component ] = value; 9995 9996 return this; 9997 9998 } 9999 10000 getX( index ) { 10001 10002 let x = this.array[ index * this.itemSize ]; 10003 10004 if ( this.normalized ) x = denormalize( x, this.array ); 10005 10006 return x; 10007 10008 } 10009 10010 setX( index, x ) { 10011 10012 if ( this.normalized ) x = normalize( x, this.array ); 10013 10014 this.array[ index * this.itemSize ] = x; 10015 10016 return this; 10017 10018 } 10019 10020 getY( index ) { 10021 10022 let y = this.array[ index * this.itemSize + 1 ]; 10023 10024 if ( this.normalized ) y = denormalize( y, this.array ); 10025 10026 return y; 10027 10028 } 10029 10030 setY( index, y ) { 10031 10032 if ( this.normalized ) y = normalize( y, this.array ); 10033 10034 this.array[ index * this.itemSize + 1 ] = y; 10035 10036 return this; 10037 10038 } 10039 10040 getZ( index ) { 10041 10042 let z = this.array[ index * this.itemSize + 2 ]; 10043 10044 if ( this.normalized ) z = denormalize( z, this.array ); 10045 10046 return z; 10047 10048 } 10049 10050 setZ( index, z ) { 10051 10052 if ( this.normalized ) z = normalize( z, this.array ); 10053 10054 this.array[ index * this.itemSize + 2 ] = z; 10055 10056 return this; 10057 10058 } 10059 10060 getW( index ) { 10061 10062 let w = this.array[ index * this.itemSize + 3 ]; 10063 10064 if ( this.normalized ) w = denormalize( w, this.array ); 10065 10066 return w; 10067 10068 } 10069 10070 setW( index, w ) { 10071 10072 if ( this.normalized ) w = normalize( w, this.array ); 10073 10074 this.array[ index * this.itemSize + 3 ] = w; 10075 10076 return this; 10077 10078 } 10079 10080 setXY( index, x, y ) { 10081 10082 index *= this.itemSize; 10083 10084 if ( this.normalized ) { 10085 10086 x = normalize( x, this.array ); 10087 y = normalize( y, this.array ); 10088 10089 } 10090 10091 this.array[ index + 0 ] = x; 10092 this.array[ index + 1 ] = y; 10093 10094 return this; 10095 10096 } 10097 10098 setXYZ( index, x, y, z ) { 10099 10100 index *= this.itemSize; 10101 10102 if ( this.normalized ) { 10103 10104 x = normalize( x, this.array ); 10105 y = normalize( y, this.array ); 10106 z = normalize( z, this.array ); 10107 10108 } 10109 10110 this.array[ index + 0 ] = x; 10111 this.array[ index + 1 ] = y; 10112 this.array[ index + 2 ] = z; 10113 10114 return this; 10115 10116 } 10117 10118 setXYZW( index, x, y, z, w ) { 10119 10120 index *= this.itemSize; 10121 10122 if ( this.normalized ) { 10123 10124 x = normalize( x, this.array ); 10125 y = normalize( y, this.array ); 10126 z = normalize( z, this.array ); 10127 w = normalize( w, this.array ); 10128 10129 } 10130 10131 this.array[ index + 0 ] = x; 10132 this.array[ index + 1 ] = y; 10133 this.array[ index + 2 ] = z; 10134 this.array[ index + 3 ] = w; 10135 10136 return this; 10137 10138 } 10139 10140 onUpload( callback ) { 10141 10142 this.onUploadCallback = callback; 10143 10144 return this; 10145 10146 } 10147 10148 clone() { 10149 10150 return new this.constructor( this.array, this.itemSize ).copy( this ); 10151 10152 } 10153 10154 toJSON() { 10155 10156 const data = { 10157 itemSize: this.itemSize, 10158 type: this.array.constructor.name, 10159 array: Array.from( this.array ), 10160 normalized: this.normalized 10161 }; 10162 10163 if ( this.name !== '' ) data.name = this.name; 10164 if ( this.usage !== StaticDrawUsage ) data.usage = this.usage; 10165 10166 return data; 10167 10168 } 10169 10170} 10171 10172// 10173 10174class Int8BufferAttribute extends BufferAttribute { 10175 10176 constructor( array, itemSize, normalized ) { 10177 10178 super( new Int8Array( array ), itemSize, normalized ); 10179 10180 } 10181 10182} 10183 10184class Uint8BufferAttribute extends BufferAttribute { 10185 10186 constructor( array, itemSize, normalized ) { 10187 10188 super( new Uint8Array( array ), itemSize, normalized ); 10189 10190 } 10191 10192} 10193 10194class Uint8ClampedBufferAttribute extends BufferAttribute { 10195 10196 constructor( array, itemSize, normalized ) { 10197 10198 super( new Uint8ClampedArray( array ), itemSize, normalized ); 10199 10200 } 10201 10202} 10203 10204class Int16BufferAttribute extends BufferAttribute { 10205 10206 constructor( array, itemSize, normalized ) { 10207 10208 super( new Int16Array( array ), itemSize, normalized ); 10209 10210 } 10211 10212} 10213 10214class Uint16BufferAttribute extends BufferAttribute { 10215 10216 constructor( array, itemSize, normalized ) { 10217 10218 super( new Uint16Array( array ), itemSize, normalized ); 10219 10220 } 10221 10222} 10223 10224class Int32BufferAttribute extends BufferAttribute { 10225 10226 constructor( array, itemSize, normalized ) { 10227 10228 super( new Int32Array( array ), itemSize, normalized ); 10229 10230 } 10231 10232} 10233 10234class Uint32BufferAttribute extends BufferAttribute { 10235 10236 constructor( array, itemSize, normalized ) { 10237 10238 super( new Uint32Array( array ), itemSize, normalized ); 10239 10240 } 10241 10242} 10243 10244class Float16BufferAttribute extends BufferAttribute { 10245 10246 constructor( array, itemSize, normalized ) { 10247 10248 super( new Uint16Array( array ), itemSize, normalized ); 10249 10250 this.isFloat16BufferAttribute = true; 10251 10252 } 10253 10254 getX( index ) { 10255 10256 let x = fromHalfFloat( this.array[ index * this.itemSize ] ); 10257 10258 if ( this.normalized ) x = denormalize( x, this.array ); 10259 10260 return x; 10261 10262 } 10263 10264 setX( index, x ) { 10265 10266 if ( this.normalized ) x = normalize( x, this.array ); 10267 10268 this.array[ index * this.itemSize ] = toHalfFloat( x ); 10269 10270 return this; 10271 10272 } 10273 10274 getY( index ) { 10275 10276 let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] ); 10277 10278 if ( this.normalized ) y = denormalize( y, this.array ); 10279 10280 return y; 10281 10282 } 10283 10284 setY( index, y ) { 10285 10286 if ( this.normalized ) y = normalize( y, this.array ); 10287 10288 this.array[ index * this.itemSize + 1 ] = toHalfFloat( y ); 10289 10290 return this; 10291 10292 } 10293 10294 getZ( index ) { 10295 10296 let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] ); 10297 10298 if ( this.normalized ) z = denormalize( z, this.array ); 10299 10300 return z; 10301 10302 } 10303 10304 setZ( index, z ) { 10305 10306 if ( this.normalized ) z = normalize( z, this.array ); 10307 10308 this.array[ index * this.itemSize + 2 ] = toHalfFloat( z ); 10309 10310 return this; 10311 10312 } 10313 10314 getW( index ) { 10315 10316 let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] ); 10317 10318 if ( this.normalized ) w = denormalize( w, this.array ); 10319 10320 return w; 10321 10322 } 10323 10324 setW( index, w ) { 10325 10326 if ( this.normalized ) w = normalize( w, this.array ); 10327 10328 this.array[ index * this.itemSize + 3 ] = toHalfFloat( w ); 10329 10330 return this; 10331 10332 } 10333 10334 setXY( index, x, y ) { 10335 10336 index *= this.itemSize; 10337 10338 if ( this.normalized ) { 10339 10340 x = normalize( x, this.array ); 10341 y = normalize( y, this.array ); 10342 10343 } 10344 10345 this.array[ index + 0 ] = toHalfFloat( x ); 10346 this.array[ index + 1 ] = toHalfFloat( y ); 10347 10348 return this; 10349 10350 } 10351 10352 setXYZ( index, x, y, z ) { 10353 10354 index *= this.itemSize; 10355 10356 if ( this.normalized ) { 10357 10358 x = normalize( x, this.array ); 10359 y = normalize( y, this.array ); 10360 z = normalize( z, this.array ); 10361 10362 } 10363 10364 this.array[ index + 0 ] = toHalfFloat( x ); 10365 this.array[ index + 1 ] = toHalfFloat( y ); 10366 this.array[ index + 2 ] = toHalfFloat( z ); 10367 10368 return this; 10369 10370 } 10371 10372 setXYZW( index, x, y, z, w ) { 10373 10374 index *= this.itemSize; 10375 10376 if ( this.normalized ) { 10377 10378 x = normalize( x, this.array ); 10379 y = normalize( y, this.array ); 10380 z = normalize( z, this.array ); 10381 w = normalize( w, this.array ); 10382 10383 } 10384 10385 this.array[ index + 0 ] = toHalfFloat( x ); 10386 this.array[ index + 1 ] = toHalfFloat( y ); 10387 this.array[ index + 2 ] = toHalfFloat( z ); 10388 this.array[ index + 3 ] = toHalfFloat( w ); 10389 10390 return this
vendor: 11,366 bytes, lines 10390-11000
10390; 10391 10392 } 10393 10394} 10395 10396 10397class Float32BufferAttribute extends BufferAttribute { 10398 10399 constructor( array, itemSize, normalized ) { 10400 10401 super( new Float32Array( array ), itemSize, normalized ); 10402 10403 } 10404 10405} 10406 10407let _id$2 = 0; 10408 10409const _m1$2 = /*@__PURE__*/ new Matrix4(); 10410const _obj = /*@__PURE__*/ new Object3D(); 10411const _offset = /*@__PURE__*/ new Vector3(); 10412const _box$2 = /*@__PURE__*/ new Box3(); 10413const _boxMorphTargets = /*@__PURE__*/ new Box3(); 10414const _vector$8 = /*@__PURE__*/ new Vector3(); 10415 10416class BufferGeometry extends EventDispatcher { 10417 10418 constructor() { 10419 10420 super(); 10421 10422 this.isBufferGeometry = true; 10423 10424 Object.defineProperty( this, 'id', { value: _id$2 ++ } ); 10425 10426 this.uuid = generateUUID(); 10427 10428 this.name = ''; 10429 this.type = 'BufferGeometry'; 10430 10431 this.index = null; 10432 this.attributes = {}; 10433 10434 this.morphAttributes = {}; 10435 this.morphTargetsRelative = false; 10436 10437 this.groups = []; 10438 10439 this.boundingBox = null; 10440 this.boundingSphere = null; 10441 10442 this.drawRange = { start: 0, count: Infinity }; 10443 10444 this.userData = {}; 10445 10446 } 10447 10448 getIndex() { 10449 10450 return this.index; 10451 10452 } 10453 10454 setIndex( index ) { 10455 10456 if ( Array.isArray( index ) ) { 10457 10458 this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); 10459 10460 } else { 10461 10462 this.index = index; 10463 10464 } 10465 10466 return this; 10467 10468 } 10469 10470 getAttribute( name ) { 10471 10472 return this.attributes[ name ]; 10473 10474 } 10475 10476 setAttribute( name, attribute ) { 10477 10478 this.attributes[ name ] = attribute; 10479 10480 return this; 10481 10482 } 10483 10484 deleteAttribute( name ) { 10485 10486 delete this.attributes[ name ]; 10487 10488 return this; 10489 10490 } 10491 10492 hasAttribute( name ) { 10493 10494 return this.attributes[ name ] !== undefined; 10495 10496 } 10497 10498 addGroup( start, count, materialIndex = 0 ) { 10499 10500 this.groups.push( { 10501 10502 start: start, 10503 count: count, 10504 materialIndex: materialIndex 10505 10506 } ); 10507 10508 } 10509 10510 clearGroups() { 10511 10512 this.groups = []; 10513 10514 } 10515 10516 setDrawRange( start, count ) { 10517 10518 this.drawRange.start = start; 10519 this.drawRange.count = count; 10520 10521 } 10522 10523 applyMatrix4( matrix ) { 10524 10525 const position = this.attributes.position; 10526 10527 if ( position !== undefined ) { 10528 10529 position.applyMatrix4( matrix ); 10530 10531 position.needsUpdate = true; 10532 10533 } 10534 10535 const normal = this.attributes.normal; 10536 10537 if ( normal !== undefined ) { 10538 10539 const normalMatrix = new Matrix3().getNormalMatrix( matrix ); 10540 10541 normal.applyNormalMatrix( normalMatrix ); 10542 10543 normal.needsUpdate = true; 10544 10545 } 10546 10547 const tangent = this.attributes.tangent; 10548 10549 if ( tangent !== undefined ) { 10550 10551 tangent.transformDirection( matrix ); 10552 10553 tangent.needsUpdate = true; 10554 10555 } 10556 10557 if ( this.boundingBox !== null ) { 10558 10559 this.computeBoundingBox(); 10560 10561 } 10562 10563 if ( this.boundingSphere !== null ) { 10564 10565 this.computeBoundingSphere(); 10566 10567 } 10568 10569 return this; 10570 10571 } 10572 10573 applyQuaternion( q ) { 10574 10575 _m1$2.makeRotationFromQuaternion( q ); 10576 10577 this.applyMatrix4( _m1$2 ); 10578 10579 return this; 10580 10581 } 10582 10583 rotateX( angle ) { 10584 10585 // rotate geometry around world x-axis 10586 10587 _m1$2.makeRotationX( angle ); 10588 10589 this.applyMatrix4( _m1$2 ); 10590 10591 return this; 10592 10593 } 10594 10595 rotateY( angle ) { 10596 10597 // rotate geometry around world y-axis 10598 10599 _m1$2.makeRotationY( angle ); 10600 10601 this.applyMatrix4( _m1$2 ); 10602 10603 return this; 10604 10605 } 10606 10607 rotateZ( angle ) { 10608 10609 // rotate geometry around world z-axis 10610 10611 _m1$2.makeRotationZ( angle ); 10612 10613 this.applyMatrix4( _m1$2 ); 10614 10615 return this; 10616 10617 } 10618 10619 translate( x, y, z ) { 10620 10621 // translate geometry 10622 10623 _m1$2.makeTranslation( x, y, z ); 10624 10625 this.applyMatrix4( _m1$2 ); 10626 10627 return this; 10628 10629 } 10630 10631 scale( x, y, z ) { 10632 10633 // scale geometry 10634 10635 _m1$2.makeScale( x, y, z ); 10636 10637 this.applyMatrix4( _m1$2 ); 10638 10639 return this; 10640 10641 } 10642 10643 lookAt( vector ) { 10644 10645 _obj.lookAt( vector ); 10646 10647 _obj.updateMatrix(); 10648 10649 this.applyMatrix4( _obj.matrix ); 10650 10651 return this; 10652 10653 } 10654 10655 center() { 10656 10657 this.computeBoundingBox(); 10658 10659 this.boundingBox.getCenter( _offset ).negate(); 10660 10661 this.translate( _offset.x, _offset.y, _offset.z ); 10662 10663 return this; 10664 10665 } 10666 10667 setFromPoints( points ) { 10668 10669 const position = []; 10670 10671 for ( let i = 0, l = points.length; i < l; i ++ ) { 10672 10673 const point = points[ i ]; 10674 position.push( point.x, point.y, point.z || 0 ); 10675 10676 } 10677 10678 this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); 10679 10680 return this; 10681 10682 } 10683 10684 computeBoundingBox() { 10685 10686 if ( this.boundingBox === null ) { 10687 10688 this.boundingBox = new Box3(); 10689 10690 } 10691 10692 const position = this.attributes.position; 10693 const morphAttributesPosition = this.morphAttributes.position; 10694 10695 if ( position && position.isGLBufferAttribute ) { 10696 10697 console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.', this ); 10698 10699 this.boundingBox.set( 10700 new Vector3( - Infinity, - Infinity, - Infinity ), 10701 new Vector3( + Infinity, + Infinity, + Infinity ) 10702 ); 10703 10704 return; 10705 10706 } 10707 10708 if ( position !== undefined ) { 10709 10710 this.boundingBox.setFromBufferAttribute( position ); 10711 10712 // process morph attributes if present 10713 10714 if ( morphAttributesPosition ) { 10715 10716 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { 10717 10718 const morphAttribute = morphAttributesPosition[ i ]; 10719 _box$2.setFromBufferAttribute( morphAttribute ); 10720 10721 if ( this.morphTargetsRelative ) { 10722 10723 _vector$8.addVectors( this.boundingBox.min, _box$2.min ); 10724 this.boundingBox.expandByPoint( _vector$8 ); 10725 10726 _vector$8.addVectors( this.boundingBox.max, _box$2.max ); 10727 this.boundingBox.expandByPoint( _vector$8 ); 10728 10729 } else { 10730 10731 this.boundingBox.expandByPoint( _box$2.min ); 10732 this.boundingBox.expandByPoint( _box$2.max ); 10733 10734 } 10735 10736 } 10737 10738 } 10739 10740 } else { 10741 10742 this.boundingBox.makeEmpty(); 10743 10744 } 10745 10746 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { 10747 10748 console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); 10749 10750 } 10751 10752 } 10753 10754 computeBoundingSphere() { 10755 10756 if ( this.boundingSphere === null ) { 10757 10758 this.boundingSphere = new Sphere(); 10759 10760 } 10761 10762 const position = this.attributes.position; 10763 const morphAttributesPosition = this.morphAttributes.position; 10764 10765 if ( position && position.isGLBufferAttribute ) { 10766 10767 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere.', this ); 10768 10769 this.boundingSphere.set( new Vector3(), Infinity ); 10770 10771 return; 10772 10773 } 10774 10775 if ( position ) { 10776 10777 // first, find the center of the bounding sphere 10778 10779 const center = this.boundingSphere.center; 10780 10781 _box$2.setFromBufferAttribute( position ); 10782 10783 // process morph attributes if present 10784 10785 if ( morphAttributesPosition ) { 10786 10787 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { 10788 10789 const morphAttribute = morphAttributesPosition[ i ]; 10790 _boxMorphTargets.setFromBufferAttribute( morphAttribute ); 10791 10792 if ( this.morphTargetsRelative ) { 10793 10794 _vector$8.addVectors( _box$2.min, _boxMorphTargets.min ); 10795 _box$2.expandByPoint( _vector$8 ); 10796 10797 _vector$8.addVectors( _box$2.max, _boxMorphTargets.max ); 10798 _box$2.expandByPoint( _vector$8 ); 10799 10800 } else { 10801 10802 _box$2.expandByPoint( _boxMorphTargets.min ); 10803 _box$2.expandByPoint( _boxMorphTargets.max ); 10804 10805 } 10806 10807 } 10808 10809 } 10810 10811 _box$2.getCenter( center ); 10812 10813 // second, try to find a boundingSphere with a radius smaller than the 10814 // boundingSphere of the boundingBox: sqrt(3) smaller in the best case 10815 10816 let maxRadiusSq = 0; 10817 10818 for ( let i = 0, il = position.count; i < il; i ++ ) { 10819 10820 _vector$8.fromBufferAttribute( position, i ); 10821 10822 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); 10823 10824 } 10825 10826 // process morph attributes if present 10827 10828 if ( morphAttributesPosition ) { 10829 10830 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { 10831 10832 const morphAttribute = morphAttributesPosition[ i ]; 10833 const morphTargetsRelative = this.morphTargetsRelative; 10834 10835 for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) { 10836 10837 _vector$8.fromBufferAttribute( morphAttribute, j ); 10838 10839 if ( morphTargetsRelative ) { 10840 10841 _offset.fromBufferAttribute( position, j ); 10842 _vector$8.add( _offset ); 10843 10844 } 10845 10846 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); 10847 10848 } 10849 10850 } 10851 10852 } 10853 10854 this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); 10855 10856 if ( isNaN( this.boundingSphere.radius ) ) { 10857 10858 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); 10859 10860 } 10861 10862 } 10863 10864 } 10865 10866 computeTangents() { 10867 10868 const index = this.index; 10869 const attributes = this.attributes; 10870 10871 // based on http://www.terathon.com/code/tangent.html 10872 // (per vertex tangents) 10873 10874 if ( index === null || 10875 attributes.position === undefined || 10876 attributes.normal === undefined || 10877 attributes.uv === undefined ) { 10878 10879 console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' ); 10880 return; 10881 10882 } 10883 10884 const positionAttribute = attributes.position; 10885 const normalAttribute = attributes.normal; 10886 const uvAttribute = attributes.uv; 10887 10888 if ( this.hasAttribute( 'tangent' ) === false ) { 10889 10890 this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * positionAttribute.count ), 4 ) ); 10891 10892 } 10893 10894 const tangentAttribute = this.getAttribute( 'tangent' ); 10895 10896 const tan1 = [], tan2 = []; 10897 10898 for ( let i = 0; i < positionAttribute.count; i ++ ) { 10899 10900 tan1[ i ] = new Vector3(); 10901 tan2[ i ] = new Vector3(); 10902 10903 } 10904 10905 const vA = new Vector3(), 10906 vB = new Vector3(), 10907 vC = new Vector3(), 10908 10909 uvA = new Vector2(), 10910 uvB = new Vector2(), 10911 uvC = new Vector2(), 10912 10913 sdir = new Vector3(), 10914 tdir = new Vector3(); 10915 10916 function handleTriangle( a, b, c ) { 10917 10918 vA.fromBufferAttribute( positionAttribute, a ); 10919 vB.fromBufferAttribute( positionAttribute, b ); 10920 vC.fromBufferAttribute( positionAttribute, c ); 10921 10922 uvA.fromBufferAttribute( uvAttribute, a ); 10923 uvB.fromBufferAttribute( uvAttribute, b ); 10924 uvC.fromBufferAttribute( uvAttribute, c ); 10925 10926 vB.sub( vA ); 10927 vC.sub( vA ); 10928 10929 uvB.sub( uvA ); 10930 uvC.sub( uvA ); 10931 10932 const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y ); 10933 10934 // silently ignore degenerate uv triangles having coincident or colinear vertices 10935 10936 if ( ! isFinite( r ) ) return; 10937 10938 sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r ); 10939 tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r ); 10940 10941 tan1[ a ].add( sdir ); 10942 tan1[ b ].add( sdir ); 10943 tan1[ c ].add( sdir ); 10944 10945 tan2[ a ].add( tdir ); 10946 tan2[ b ].add( tdir ); 10947 tan2[ c ].add( tdir ); 10948 10949 } 10950 10951 let groups = this.groups; 10952 10953 if ( groups.length === 0 ) { 10954 10955 groups = [ { 10956 start: 0, 10957 count: index.count 10958 } ]; 10959 10960 } 10961 10962 for ( let i = 0, il = groups.length; i < il; ++ i ) { 10963 10964 const group = groups[ i ]; 10965 10966 const start = group.start; 10967 const count = group.count; 10968 10969 for ( let j = start, jl = start + count; j < jl; j += 3 ) { 10970 10971 handleTriangle( 10972 index.getX( j + 0 ), 10973 index.getX( j + 1 ), 10974 index.getX( j + 2 ) 10975 ); 10976 10977 } 10978 10979 } 10980 10981 const tmp = new Vector3(), tmp2 = new Vector3(); 10982 const n = new Vector3(), n2 = new Vector3(); 10983 10984 function handleVertex( v ) { 10985 10986 n.fromBufferAttribute( normalAttribute, v ); 10987 n2.copy( n ); 10988 10989 const t = tan1[ v ]; 10990 10991 // Gram-Schmidt orthogonalize 10992 10993 tmp.copy( t ); 10994 tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize(); 10995 10996 // Calculate handedness 10997 10998 tmp2.crossVectors( n2, t ); 10999 const test = tmp2.dot( tan2[ v ] ); 11000 const w = ( test < 0.0 ) ? -
11000 1.0
vendor: 18,822 bytes, lines 11000-11859
11000 : 1.0; 11001 11002 tangentAttribute.setXYZW( v, tmp.x, tmp.y, tmp.z, w ); 11003 11004 } 11005 11006 for ( let i = 0, il = groups.length; i < il; ++ i ) { 11007 11008 const group = groups[ i ]; 11009 11010 const start = group.start; 11011 const count = group.count; 11012 11013 for ( let j = start, jl = start + count; j < jl; j += 3 ) { 11014 11015 handleVertex( index.getX( j + 0 ) ); 11016 handleVertex( index.getX( j + 1 ) ); 11017 handleVertex( index.getX( j + 2 ) ); 11018 11019 } 11020 11021 } 11022 11023 } 11024 11025 computeVertexNormals() { 11026 11027 const index = this.index; 11028 const positionAttribute = this.getAttribute( 'position' ); 11029 11030 if ( positionAttribute !== undefined ) { 11031 11032 let normalAttribute = this.getAttribute( 'normal' ); 11033 11034 if ( normalAttribute === undefined ) { 11035 11036 normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 ); 11037 this.setAttribute( 'normal', normalAttribute ); 11038 11039 } else { 11040 11041 // reset existing normals to zero 11042 11043 for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) { 11044 11045 normalAttribute.setXYZ( i, 0, 0, 0 ); 11046 11047 } 11048 11049 } 11050 11051 const pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); 11052 const nA = new Vector3(), nB = new Vector3(), nC = new Vector3(); 11053 const cb = new Vector3(), ab = new Vector3(); 11054 11055 // indexed elements 11056 11057 if ( index ) { 11058 11059 for ( let i = 0, il = index.count; i < il; i += 3 ) { 11060 11061 const vA = index.getX( i + 0 ); 11062 const vB = index.getX( i + 1 ); 11063 const vC = index.getX( i + 2 ); 11064 11065 pA.fromBufferAttribute( positionAttribute, vA ); 11066 pB.fromBufferAttribute( positionAttribute, vB ); 11067 pC.fromBufferAttribute( positionAttribute, vC ); 11068 11069 cb.subVectors( pC, pB ); 11070 ab.subVectors( pA, pB ); 11071 cb.cross( ab ); 11072 11073 nA.fromBufferAttribute( normalAttribute, vA ); 11074 nB.fromBufferAttribute( normalAttribute, vB ); 11075 nC.fromBufferAttribute( normalAttribute, vC ); 11076 11077 nA.add( cb ); 11078 nB.add( cb ); 11079 nC.add( cb ); 11080 11081 normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z ); 11082 normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z ); 11083 normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z ); 11084 11085 } 11086 11087 } else { 11088 11089 // non-indexed elements (unconnected triangle soup) 11090 11091 for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) { 11092 11093 pA.fromBufferAttribute( positionAttribute, i + 0 ); 11094 pB.fromBufferAttribute( positionAttribute, i + 1 ); 11095 pC.fromBufferAttribute( positionAttribute, i + 2 ); 11096 11097 cb.subVectors( pC, pB ); 11098 ab.subVectors( pA, pB ); 11099 cb.cross( ab ); 11100 11101 normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z ); 11102 normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z ); 11103 normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z ); 11104 11105 } 11106 11107 } 11108 11109 this.normalizeNormals(); 11110 11111 normalAttribute.needsUpdate = true; 11112 11113 } 11114 11115 } 11116 11117 normalizeNormals() { 11118 11119 const normals = this.attributes.normal; 11120 11121 for ( let i = 0, il = normals.count; i < il; i ++ ) { 11122 11123 _vector$8.fromBufferAttribute( normals, i ); 11124 11125 _vector$8.normalize(); 11126 11127 normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); 11128 11129 } 11130 11131 } 11132 11133 toNonIndexed() { 11134 11135 function convertBufferAttribute( attribute, indices ) { 11136 11137 const array = attribute.array; 11138 const itemSize = attribute.itemSize; 11139 const normalized = attribute.normalized; 11140 11141 const array2 = new array.constructor( indices.length * itemSize ); 11142 11143 let index = 0, index2 = 0; 11144 11145 for ( let i = 0, l = indices.length; i < l; i ++ ) { 11146 11147 if ( attribute.isInterleavedBufferAttribute ) { 11148 11149 index = indices[ i ] * attribute.data.stride + attribute.offset; 11150 11151 } else { 11152 11153 index = indices[ i ] * itemSize; 11154 11155 } 11156 11157 for ( let j = 0; j < itemSize; j ++ ) { 11158 11159 array2[ index2 ++ ] = array[ index ++ ]; 11160 11161 } 11162 11163 } 11164 11165 return new BufferAttribute( array2, itemSize, normalized ); 11166 11167 } 11168 11169 // 11170 11171 if ( this.index === null ) { 11172 11173 console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' ); 11174 return this; 11175 11176 } 11177 11178 const geometry2 = new BufferGeometry(); 11179 11180 const indices = this.index.array; 11181 const attributes = this.attributes; 11182 11183 // attributes 11184 11185 for ( const name in attributes ) { 11186 11187 const attribute = attributes[ name ]; 11188 11189 const newAttribute = convertBufferAttribute( attribute, indices ); 11190 11191 geometry2.setAttribute( name, newAttribute ); 11192 11193 } 11194 11195 // morph attributes 11196 11197 const morphAttributes = this.morphAttributes; 11198 11199 for ( const name in morphAttributes ) { 11200 11201 const morphArray = []; 11202 const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes 11203 11204 for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) { 11205 11206 const attribute = morphAttribute[ i ]; 11207 11208 const newAttribute = convertBufferAttribute( attribute, indices ); 11209 11210 morphArray.push( newAttribute ); 11211 11212 } 11213 11214 geometry2.morphAttributes[ name ] = morphArray; 11215 11216 } 11217 11218 geometry2.morphTargetsRelative = this.morphTargetsRelative; 11219 11220 // groups 11221 11222 const groups = this.groups; 11223 11224 for ( let i = 0, l = groups.length; i < l; i ++ ) { 11225 11226 const group = groups[ i ]; 11227 geometry2.addGroup( group.start, group.count, group.materialIndex ); 11228 11229 } 11230 11231 return geometry2; 11232 11233 } 11234 11235 toJSON() { 11236 11237 const data = { 11238 metadata: { 11239 version: 4.6, 11240 type: 'BufferGeometry', 11241 generator: 'BufferGeometry.toJSON' 11242 } 11243 }; 11244 11245 // standard BufferGeometry serialization 11246 11247 data.uuid = this.uuid; 11248 data.type = this.type; 11249 if ( this.name !== '' ) data.name = this.name; 11250 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; 11251 11252 if ( this.parameters !== undefined ) { 11253 11254 const parameters = this.parameters; 11255 11256 for ( const key in parameters ) { 11257 11258 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; 11259 11260 } 11261 11262 return data; 11263 11264 } 11265 11266 // for simplicity the code assumes attributes are not shared across geometries, see #15811 11267 11268 data.data = { attributes: {} }; 11269 11270 const index = this.index; 11271 11272 if ( index !== null ) { 11273 11274 data.data.index = { 11275 type: index.array.constructor.name, 11276 array: Array.prototype.slice.call( index.array ) 11277 }; 11278 11279 } 11280 11281 const attributes = this.attributes; 11282 11283 for ( const key in attributes ) { 11284 11285 const attribute = attributes[ key ]; 11286 11287 data.data.attributes[ key ] = attribute.toJSON( data.data ); 11288 11289 } 11290 11291 const morphAttributes = {}; 11292 let hasMorphAttributes = false; 11293 11294 for ( const key in this.morphAttributes ) { 11295 11296 const attributeArray = this.morphAttributes[ key ]; 11297 11298 const array = []; 11299 11300 for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { 11301 11302 const attribute = attributeArray[ i ]; 11303 11304 array.push( attribute.toJSON( data.data ) ); 11305 11306 } 11307 11308 if ( array.length > 0 ) { 11309 11310 morphAttributes[ key ] = array; 11311 11312 hasMorphAttributes = true; 11313 11314 } 11315 11316 } 11317 11318 if ( hasMorphAttributes ) { 11319 11320 data.data.morphAttributes = morphAttributes; 11321 data.data.morphTargetsRelative = this.morphTargetsRelative; 11322 11323 } 11324 11325 const groups = this.groups; 11326 11327 if ( groups.length > 0 ) { 11328 11329 data.data.groups = JSON.parse( JSON.stringify( groups ) ); 11330 11331 } 11332 11333 const boundingSphere = this.boundingSphere; 11334 11335 if ( boundingSphere !== null ) { 11336 11337 data.data.boundingSphere = { 11338 center: boundingSphere.center.toArray(), 11339 radius: boundingSphere.radius 11340 }; 11341 11342 } 11343 11344 return data; 11345 11346 } 11347 11348 clone() { 11349 11350 return new this.constructor().copy( this ); 11351 11352 } 11353 11354 copy( source ) { 11355 11356 // reset 11357 11358 this.index = null; 11359 this.attributes = {}; 11360 this.morphAttributes = {}; 11361 this.groups = []; 11362 this.boundingBox = null; 11363 this.boundingSphere = null; 11364 11365 // used for storing cloned, shared data 11366 11367 const data = {}; 11368 11369 // name 11370 11371 this.name = source.name; 11372 11373 // index 11374 11375 const index = source.index; 11376 11377 if ( index !== null ) { 11378 11379 this.setIndex( index.clone( data ) ); 11380 11381 } 11382 11383 // attributes 11384 11385 const attributes = source.attributes; 11386 11387 for ( const name in attributes ) { 11388 11389 const attribute = attributes[ name ]; 11390 this.setAttribute( name, attribute.clone( data ) ); 11391 11392 } 11393 11394 // morph attributes 11395 11396 const morphAttributes = source.morphAttributes; 11397 11398 for ( const name in morphAttributes ) { 11399 11400 const array = []; 11401 const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes 11402 11403 for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) { 11404 11405 array.push( morphAttribute[ i ].clone( data ) ); 11406 11407 } 11408 11409 this.morphAttributes[ name ] = array; 11410 11411 } 11412 11413 this.morphTargetsRelative = source.morphTargetsRelative; 11414 11415 // groups 11416 11417 const groups = source.groups; 11418 11419 for ( let i = 0, l = groups.length; i < l; i ++ ) { 11420 11421 const group = groups[ i ]; 11422 this.addGroup( group.start, group.count, group.materialIndex ); 11423 11424 } 11425 11426 // bounding box 11427 11428 const boundingBox = source.boundingBox; 11429 11430 if ( boundingBox !== null ) { 11431 11432 this.boundingBox = boundingBox.clone(); 11433 11434 } 11435 11436 // bounding sphere 11437 11438 const boundingSphere = source.boundingSphere; 11439 11440 if ( boundingSphere !== null ) { 11441 11442 this.boundingSphere = boundingSphere.clone(); 11443 11444 } 11445 11446 // draw range 11447 11448 this.drawRange.start = source.drawRange.start; 11449 this.drawRange.count = source.drawRange.count; 11450 11451 // user data 11452 11453 this.userData = source.userData; 11454 11455 return this; 11456 11457 } 11458 11459 dispose() { 11460 11461 this.dispatchEvent( { type: 'dispose' } ); 11462 11463 } 11464 11465} 11466 11467const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4(); 11468const _ray$3 = /*@__PURE__*/ new Ray(); 11469const _sphere$6 = /*@__PURE__*/ new Sphere(); 11470const _sphereHitAt = /*@__PURE__*/ new Vector3(); 11471 11472const _vA$1 = /*@__PURE__*/ new Vector3(); 11473const _vB$1 = /*@__PURE__*/ new Vector3(); 11474const _vC$1 = /*@__PURE__*/ new Vector3(); 11475 11476const _tempA = /*@__PURE__*/ new Vector3(); 11477const _morphA = /*@__PURE__*/ new Vector3(); 11478 11479const _uvA$1 = /*@__PURE__*/ new Vector2(); 11480const _uvB$1 = /*@__PURE__*/ new Vector2(); 11481const _uvC$1 = /*@__PURE__*/ new Vector2(); 11482 11483const _normalA = /*@__PURE__*/ new Vector3(); 11484const _normalB = /*@__PURE__*/ new Vector3(); 11485const _normalC = /*@__PURE__*/ new Vector3(); 11486 11487const _intersectionPoint = /*@__PURE__*/ new Vector3(); 11488const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); 11489 11490class Mesh extends Object3D { 11491 11492 constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) { 11493 11494 super(); 11495 11496 this.isMesh = true; 11497 11498 this.type = 'Mesh'; 11499 11500 this.geometry = geometry; 11501 this.material = material; 11502 11503 this.updateMorphTargets(); 11504 11505 } 11506 11507 copy( source, recursive ) { 11508 11509 super.copy( source, recursive ); 11510 11511 if ( source.morphTargetInfluences !== undefined ) { 11512 11513 this.morphTargetInfluences = source.morphTargetInfluences.slice(); 11514 11515 } 11516 11517 if ( source.morphTargetDictionary !== undefined ) { 11518 11519 this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); 11520 11521 } 11522 11523 this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; 11524 this.geometry = source.geometry; 11525 11526 return this; 11527 11528 } 11529 11530 updateMorphTargets() { 11531 11532 const geometry = this.geometry; 11533 11534 const morphAttributes = geometry.morphAttributes; 11535 const keys = Object.keys( morphAttributes ); 11536 11537 if ( keys.length > 0 ) { 11538 11539 const morphAttribute = morphAttributes[ keys[ 0 ] ]; 11540 11541 if ( morphAttribute !== undefined ) { 11542 11543 this.morphTargetInfluences = []; 11544 this.morphTargetDictionary = {}; 11545 11546 for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 11547 11548 const name = morphAttribute[ m ].name || String( m ); 11549 11550 this.morphTargetInfluences.push( 0 ); 11551 this.morphTargetDictionary[ name ] = m; 11552 11553 } 11554 11555 } 11556 11557 } 11558 11559 } 11560 11561 getVertexPosition( index, target ) { 11562 11563 const geometry = this.geometry; 11564 const position = geometry.attributes.position; 11565 const morphPosition = geometry.morphAttributes.position; 11566 const morphTargetsRelative = geometry.morphTargetsRelative; 11567 11568 target.fromBufferAttribute( position, index ); 11569 11570 const morphInfluences = this.morphTargetInfluences; 11571 11572 if ( morphPosition && morphInfluences ) { 11573 11574 _morphA.set( 0, 0, 0 ); 11575 11576 for ( let i = 0, il = morphPosition.length; i < il; i ++ ) { 11577 11578 const influence = morphInfluences[ i ]; 11579 const morphAttribute = morphPosition[ i ]; 11580 11581 if ( influence === 0 ) continue; 11582 11583 _tempA.fromBufferAttribute( morphAttribute, index ); 11584 11585 if ( morphTargetsRelative ) { 11586 11587 _morphA.addScaledVector( _tempA, influence ); 11588 11589 } else { 11590 11591 _morphA.addScaledVector( _tempA.sub( target ), influence ); 11592 11593 } 11594 11595 } 11596 11597 target.add( _morphA ); 11598 11599 } 11600 11601 return target; 11602 11603 } 11604 11605 raycast( raycaster, intersects ) { 11606 11607 const geometry = this.geometry; 11608 const material = this.material; 11609 const matrixWorld = this.matrixWorld; 11610 11611 if ( material === undefined ) return; 11612 11613 // test with bounding sphere in world space 11614 11615 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 11616 11617 _sphere$6.copy( geometry.boundingSphere ); 11618 _sphere$6.applyMatrix4( matrixWorld ); 11619 11620 // check distance from ray origin to bounding sphere 11621 11622 _ray$3.copy( raycaster.ray ).recast( raycaster.near ); 11623 11624 if ( _sphere$6.containsPoint( _ray$3.origin ) === false ) { 11625 11626 if ( _ray$3.intersectSphere( _sphere$6, _sphereHitAt ) === null ) return; 11627 11628 if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return; 11629 11630 } 11631 11632 // convert ray to local space of mesh 11633 11634 _inverseMatrix$3.copy( matrixWorld ).invert(); 11635 _ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 ); 11636 11637 // test with bounding box in local space 11638 11639 if ( geometry.boundingBox !== null ) { 11640 11641 if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return; 11642 11643 } 11644 11645 // test for intersections with geometry 11646 11647 this._computeIntersections( raycaster, intersects, _ray$3 ); 11648 11649 } 11650 11651 _computeIntersections( raycaster, intersects, rayLocalSpace ) { 11652 11653 let intersection; 11654 11655 const geometry = this.geometry; 11656 const material = this.material; 11657 11658 const index = geometry.index; 11659 const position = geometry.attributes.position; 11660 const uv = geometry.attributes.uv; 11661 const uv1 = geometry.attributes.uv1; 11662 const normal = geometry.attributes.normal; 11663 const groups = geometry.groups; 11664 const drawRange = geometry.drawRange; 11665 11666 if ( index !== null ) { 11667 11668 // indexed buffer geometry 11669 11670 if ( Array.isArray( material ) ) { 11671 11672 for ( let i = 0, il = groups.length; i < il; i ++ ) { 11673 11674 const group = groups[ i ]; 11675 const groupMaterial = material[ group.materialIndex ]; 11676 11677 const start = Math.max( group.start, drawRange.start ); 11678 const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); 11679 11680 for ( let j = start, jl = end; j < jl; j += 3 ) { 11681 11682 const a = index.getX( j ); 11683 const b = index.getX( j + 1 ); 11684 const c = index.getX( j + 2 ); 11685 11686 intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); 11687 11688 if ( intersection ) { 11689 11690 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics 11691 intersection.face.materialIndex = group.materialIndex; 11692 intersects.push( intersection ); 11693 11694 } 11695 11696 } 11697 11698 } 11699 11700 } else { 11701 11702 const start = Math.max( 0, drawRange.start ); 11703 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); 11704 11705 for ( let i = start, il = end; i < il; i += 3 ) { 11706 11707 const a = index.getX( i ); 11708 const b = index.getX( i + 1 ); 11709 const c = index.getX( i + 2 ); 11710 11711 intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); 11712 11713 if ( intersection ) { 11714 11715 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics 11716 intersects.push( intersection ); 11717 11718 } 11719 11720 } 11721 11722 } 11723 11724 } else if ( position !== undefined ) { 11725 11726 // non-indexed buffer geometry 11727 11728 if ( Array.isArray( material ) ) { 11729 11730 for ( let i = 0, il = groups.length; i < il; i ++ ) { 11731 11732 const group = groups[ i ]; 11733 const groupMaterial = material[ group.materialIndex ]; 11734 11735 const start = Math.max( group.start, drawRange.start ); 11736 const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); 11737 11738 for ( let j = start, jl = end; j < jl; j += 3 ) { 11739 11740 const a = j; 11741 const b = j + 1; 11742 const c = j + 2; 11743 11744 intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); 11745 11746 if ( intersection ) { 11747 11748 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics 11749 intersection.face.materialIndex = group.materialIndex; 11750 intersects.push( intersection ); 11751 11752 } 11753 11754 } 11755 11756 } 11757 11758 } else { 11759 11760 const start = Math.max( 0, drawRange.start ); 11761 const end = Math.min( position.count, ( drawRange.start + drawRange.count ) ); 11762 11763 for ( let i = start, il = end; i < il; i += 3 ) { 11764 11765 const a = i; 11766 const b = i + 1; 11767 const c = i + 2; 11768 11769 intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); 11770 11771 if ( intersection ) { 11772 11773 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics 11774 intersects.push( intersection ); 11775 11776 } 11777 11778 } 11779 11780 } 11781 11782 } 11783 11784 } 11785 11786} 11787 11788function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) { 11789 11790 let intersect; 11791 11792 if ( material.side === BackSide ) { 11793 11794 intersect = ray.intersectTriangle( pC, pB, pA, true, point ); 11795 11796 } else { 11797 11798 intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point ); 11799 11800 } 11801 11802 if ( intersect === null ) return null; 11803 11804 _intersectionPointWorld.copy( point ); 11805 _intersectionPointWorld.applyMatrix4( object.matrixWorld ); 11806 11807 const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld ); 11808 11809 if ( distance < raycaster.near || distance > raycaster.far ) return null; 11810 11811 return { 11812 distance: distance, 11813 point: _intersectionPointWorld.clone(), 11814 object: object 11815 }; 11816 11817} 11818 11819function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) { 11820 11821 object.getVertexPosition( a, _vA$1 ); 11822 object.getVertexPosition( b, _vB$1 ); 11823 object.getVertexPosition( c, _vC$1 ); 11824 11825 const intersection = checkIntersection( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint ); 11826 11827 if ( intersection ) { 11828 11829 if ( uv ) { 11830 11831 _uvA$1.fromBufferAttribute( uv, a ); 11832 _uvB$1.fromBufferAttribute( uv, b ); 11833 _uvC$1.fromBufferAttribute( uv, c ); 11834 11835 intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); 11836 11837 } 11838 11839 if ( uv1 ) { 11840 11841 _uvA$1.fromBufferAttribute( uv1, a ); 11842 _uvB$1.fromBufferAttribute( uv1, b ); 11843 _uvC$1.fromBufferAttribute( uv1, c ); 11844 11845 intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); 11846 11847 } 11848 11849 if ( normal ) { 11850 11851 _normalA.fromBufferAttribute( normal, a ); 11852 _normalB.fromBufferAttribute( normal, b ); 11853 _normalC.fromBufferAttribute( normal, c ); 11854 11855 intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() ); 11856 11857 if ( intersection.normal.dot( ray.direction ) > 0 ) { 11858 11859 intersection.normal.multiplyScalar( -
vendor: 6,710 bytes, lines 11859-12191
11859 1 ); 11860 11861 } 11862 11863 } 11864 11865 const face = { 11866 a: a, 11867 b: b, 11868 c: c, 11869 normal: new Vector3(), 11870 materialIndex: 0 11871 }; 11872 11873 Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal ); 11874 11875 intersection.face = face; 11876 11877 } 11878 11879 return intersection; 11880 11881} 11882 11883class BoxGeometry extends BufferGeometry { 11884 11885 constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) { 11886 11887 super(); 11888 11889 this.type = 'BoxGeometry'; 11890 11891 this.parameters = { 11892 width: width, 11893 height: height, 11894 depth: depth, 11895 widthSegments: widthSegments, 11896 heightSegments: heightSegments, 11897 depthSegments: depthSegments 11898 }; 11899 11900 const scope = this; 11901 11902 // segments 11903 11904 widthSegments = Math.floor( widthSegments ); 11905 heightSegments = Math.floor( heightSegments ); 11906 depthSegments = Math.floor( depthSegments ); 11907 11908 // buffers 11909 11910 const indices = []; 11911 const vertices = []; 11912 const normals = []; 11913 const uvs = []; 11914 11915 // helper variables 11916 11917 let numberOfVertices = 0; 11918 let groupStart = 0; 11919 11920 // build each side of the box geometry 11921 11922 buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px 11923 buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx 11924 buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py 11925 buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny 11926 buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz 11927 buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz 11928 11929 // build geometry 11930 11931 this.setIndex( indices ); 11932 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 11933 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 11934 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 11935 11936 function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { 11937 11938 const segmentWidth = width / gridX; 11939 const segmentHeight = height / gridY; 11940 11941 const widthHalf = width / 2; 11942 const heightHalf = height / 2; 11943 const depthHalf = depth / 2; 11944 11945 const gridX1 = gridX + 1; 11946 const gridY1 = gridY + 1; 11947 11948 let vertexCounter = 0; 11949 let groupCount = 0; 11950 11951 const vector = new Vector3(); 11952 11953 // generate vertices, normals and uvs 11954 11955 for ( let iy = 0; iy < gridY1; iy ++ ) { 11956 11957 const y = iy * segmentHeight - heightHalf; 11958 11959 for ( let ix = 0; ix < gridX1; ix ++ ) { 11960 11961 const x = ix * segmentWidth - widthHalf; 11962 11963 // set values to correct vector component 11964 11965 vector[ u ] = x * udir; 11966 vector[ v ] = y * vdir; 11967 vector[ w ] = depthHalf; 11968 11969 // now apply vector to vertex buffer 11970 11971 vertices.push( vector.x, vector.y, vector.z ); 11972 11973 // set values to correct vector component 11974 11975 vector[ u ] = 0; 11976 vector[ v ] = 0; 11977 vector[ w ] = depth > 0 ? 1 : - 1; 11978 11979 // now apply vector to normal buffer 11980 11981 normals.push( vector.x, vector.y, vector.z ); 11982 11983 // uvs 11984 11985 uvs.push( ix / gridX ); 11986 uvs.push( 1 - ( iy / gridY ) ); 11987 11988 // counters 11989 11990 vertexCounter += 1; 11991 11992 } 11993 11994 } 11995 11996 // indices 11997 11998 // 1. you need three indices to draw a single face 11999 // 2. a single segment consists of two faces 12000 // 3. so we need to generate six (2*3) indices per segment 12001 12002 for ( let iy = 0; iy < gridY; iy ++ ) { 12003 12004 for ( let ix = 0; ix < gridX; ix ++ ) { 12005 12006 const a = numberOfVertices + ix + gridX1 * iy; 12007 const b = numberOfVertices + ix + gridX1 * ( iy + 1 ); 12008 const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); 12009 const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; 12010 12011 // faces 12012 12013 indices.push( a, b, d ); 12014 indices.push( b, c, d ); 12015 12016 // increase counter 12017 12018 groupCount += 6; 12019 12020 } 12021 12022 } 12023 12024 // add a group to the geometry. this will ensure multi material support 12025 12026 scope.addGroup( groupStart, groupCount, materialIndex ); 12027 12028 // calculate new start value for groups 12029 12030 groupStart += groupCount; 12031 12032 // update total number of vertices 12033 12034 numberOfVertices += vertexCounter; 12035 12036 } 12037 12038 } 12039 12040 copy( source ) { 12041 12042 super.copy( source ); 12043 12044 this.parameters = Object.assign( {}, source.parameters ); 12045 12046 return this; 12047 12048 } 12049 12050 static fromJSON( data ) { 12051 12052 return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); 12053 12054 } 12055 12056} 12057 12058/** 12059 * Uniform Utilities 12060 */ 12061 12062function cloneUniforms( src ) { 12063 12064 const dst = {}; 12065 12066 for ( const u in src ) { 12067 12068 dst[ u ] = {}; 12069 12070 for ( const p in src[ u ] ) { 12071 12072 const property = src[ u ][ p ]; 12073 12074 if ( property && ( property.isColor || 12075 property.isMatrix3 || property.isMatrix4 || 12076 property.isVector2 || property.isVector3 || property.isVector4 || 12077 property.isTexture || property.isQuaternion ) ) { 12078 12079 if ( property.isRenderTargetTexture ) { 12080 12081 console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); 12082 dst[ u ][ p ] = null; 12083 12084 } else { 12085 12086 dst[ u ][ p ] = property.clone(); 12087 12088 } 12089 12090 } else if ( Array.isArray( property ) ) { 12091 12092 dst[ u ][ p ] = property.slice(); 12093 12094 } else { 12095 12096 dst[ u ][ p ] = property; 12097 12098 } 12099 12100 } 12101 12102 } 12103 12104 return dst; 12105 12106} 12107 12108function mergeUniforms( uniforms ) { 12109 12110 const merged = {}; 12111 12112 for ( let u = 0; u < uniforms.length; u ++ ) { 12113 12114 const tmp = cloneUniforms( uniforms[ u ] ); 12115 12116 for ( const p in tmp ) { 12117 12118 merged[ p ] = tmp[ p ]; 12119 12120 } 12121 12122 } 12123 12124 return merged; 12125 12126} 12127 12128function cloneUniformsGroups( src ) { 12129 12130 const dst = []; 12131 12132 for ( let u = 0; u < src.length; u ++ ) { 12133 12134 dst.push( src[ u ].clone() ); 12135 12136 } 12137 12138 return dst; 12139 12140} 12141 12142function getUnlitUniformColorSpace( renderer ) { 12143 12144 const currentRenderTarget = renderer.getRenderTarget(); 12145 12146 if ( currentRenderTarget === null ) { 12147 12148 // https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398 12149 return renderer.outputColorSpace; 12150 12151 } 12152 12153 // https://github.com/mrdoob/three.js/issues/27868 12154 if ( currentRenderTarget.isXRRenderTarget === true ) { 12155 12156 return currentRenderTarget.texture.colorSpace; 12157 12158 } 12159 12160 return ColorManagement.workingColorSpace; 12161 12162} 12163 12164// Legacy 12165 12166const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms }; 12167 12168var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"; 12169 12170var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}"; 12171 12172class ShaderMaterial extends Material { 12173 12174 constructor( parameters ) { 12175 12176 super(); 12177 12178 this.isShaderMaterial = true; 12179 12180 this.type = 'ShaderMaterial'; 12181 12182 this.defines = {}; 12183 this.uniforms = {}; 12184 this.uniformsGroups = []; 12185 12186 this.vertexShader = default_vertex; 12187 this.fragmentShader = default_fragment; 12188 12189 this.linewidth = 1; 12190 12191 this.wireframe = false;
vendor: 5,162 bytes, lines 12192-12454
12192 this.wireframeLinewidth = 1; 12193 12194 this.fog = false; // set to use scene fog 12195 this.lights = false; // set to use scene lights 12196 this.clipping = false; // set to use user-defined clipping planes 12197 12198 this.forceSinglePass = true; 12199 12200 this.extensions = { 12201 clipCullDistance: false, // set to use vertex shader clipping 12202 multiDraw: false // set to use vertex shader multi_draw / enable gl_DrawID 12203 }; 12204 12205 // When rendered geometry doesn't include these attributes but the material does, 12206 // use these default values in WebGL. This avoids errors when buffer data is missing. 12207 this.defaultAttributeValues = { 12208 'color': [ 1, 1, 1 ], 12209 'uv': [ 0, 0 ], 12210 'uv1': [ 0, 0 ] 12211 }; 12212 12213 this.index0AttributeName = undefined; 12214 this.uniformsNeedUpdate = false; 12215 12216 this.glslVersion = null; 12217 12218 if ( parameters !== undefined ) { 12219 12220 this.setValues( parameters ); 12221 12222 } 12223 12224 } 12225 12226 copy( source ) { 12227 12228 super.copy( source ); 12229 12230 this.fragmentShader = source.fragmentShader; 12231 this.vertexShader = source.vertexShader; 12232 12233 this.uniforms = cloneUniforms( source.uniforms ); 12234 this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups ); 12235 12236 this.defines = Object.assign( {}, source.defines ); 12237 12238 this.wireframe = source.wireframe; 12239 this.wireframeLinewidth = source.wireframeLinewidth; 12240 12241 this.fog = source.fog; 12242 this.lights = source.lights; 12243 this.clipping = source.clipping; 12244 12245 this.extensions = Object.assign( {}, source.extensions ); 12246 12247 this.glslVersion = source.glslVersion; 12248 12249 return this; 12250 12251 } 12252 12253 toJSON( meta ) { 12254 12255 const data = super.toJSON( meta ); 12256 12257 data.glslVersion = this.glslVersion; 12258 data.uniforms = {}; 12259 12260 for ( const name in this.uniforms ) { 12261 12262 const uniform = this.uniforms[ name ]; 12263 const value = uniform.value; 12264 12265 if ( value && value.isTexture ) { 12266 12267 data.uniforms[ name ] = { 12268 type: 't', 12269 value: value.toJSON( meta ).uuid 12270 }; 12271 12272 } else if ( value && value.isColor ) { 12273 12274 data.uniforms[ name ] = { 12275 type: 'c', 12276 value: value.getHex() 12277 }; 12278 12279 } else if ( value && value.isVector2 ) { 12280 12281 data.uniforms[ name ] = { 12282 type: 'v2', 12283 value: value.toArray() 12284 }; 12285 12286 } else if ( value && value.isVector3 ) { 12287 12288 data.uniforms[ name ] = { 12289 type: 'v3', 12290 value: value.toArray() 12291 }; 12292 12293 } else if ( value && value.isVector4 ) { 12294 12295 data.uniforms[ name ] = { 12296 type: 'v4', 12297 value: value.toArray() 12298 }; 12299 12300 } else if ( value && value.isMatrix3 ) { 12301 12302 data.uniforms[ name ] = { 12303 type: 'm3', 12304 value: value.toArray() 12305 }; 12306 12307 } else if ( value && value.isMatrix4 ) { 12308 12309 data.uniforms[ name ] = { 12310 type: 'm4', 12311 value: value.toArray() 12312 }; 12313 12314 } else { 12315 12316 data.uniforms[ name ] = { 12317 value: value 12318 }; 12319 12320 // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far 12321 12322 } 12323 12324 } 12325 12326 if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines; 12327 12328 data.vertexShader = this.vertexShader; 12329 data.fragmentShader = this.fragmentShader; 12330 12331 data.lights = this.lights; 12332 data.clipping = this.clipping; 12333 12334 const extensions = {}; 12335 12336 for ( const key in this.extensions ) { 12337 12338 if ( this.extensions[ key ] === true ) extensions[ key ] = true; 12339 12340 } 12341 12342 if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions; 12343 12344 return data; 12345 12346 } 12347 12348} 12349 12350class Camera extends Object3D { 12351 12352 constructor() { 12353 12354 super(); 12355 12356 this.isCamera = true; 12357 12358 this.type = 'Camera'; 12359 12360 this.matrixWorldInverse = new Matrix4(); 12361 12362 this.projectionMatrix = new Matrix4(); 12363 this.projectionMatrixInverse = new Matrix4(); 12364 12365 this.coordinateSystem = WebGLCoordinateSystem; 12366 12367 } 12368 12369 copy( source, recursive ) { 12370 12371 super.copy( source, recursive ); 12372 12373 this.matrixWorldInverse.copy( source.matrixWorldInverse ); 12374 12375 this.projectionMatrix.copy( source.projectionMatrix ); 12376 this.projectionMatrixInverse.copy( source.projectionMatrixInverse ); 12377 12378 this.coordinateSystem = source.coordinateSystem; 12379 12380 return this; 12381 12382 } 12383 12384 getWorldDirection( target ) { 12385 12386 return super.getWorldDirection( target ).negate(); 12387 12388 } 12389 12390 updateMatrixWorld( force ) { 12391 12392 super.updateMatrixWorld( force ); 12393 12394 this.matrixWorldInverse.copy( this.matrixWorld ).invert(); 12395 12396 } 12397 12398 updateWorldMatrix( updateParents, updateChildren ) { 12399 12400 super.updateWorldMatrix( updateParents, updateChildren ); 12401 12402 this.matrixWorldInverse.copy( this.matrixWorld ).invert(); 12403 12404 } 12405 12406 clone() { 12407 12408 return new this.constructor().copy( this ); 12409 12410 } 12411 12412} 12413 12414const _v3$1 = /*@__PURE__*/ new Vector3(); 12415const _minTarget = /*@__PURE__*/ new Vector2(); 12416const _maxTarget = /*@__PURE__*/ new Vector2(); 12417 12418 12419class PerspectiveCamera extends Camera { 12420 12421 constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) { 12422 12423 super(); 12424 12425 this.isPerspectiveCamera = true; 12426 12427 this.type = 'PerspectiveCamera'; 12428 12429 this.fov = fov; 12430 this.zoom = 1; 12431 12432 this.near = near; 12433 this.far = far; 12434 this.focus = 10; 12435 12436 this.aspect = aspect; 12437 this.view = null; 12438 12439 this.filmGauge = 35; // width of the film (default in millimeters) 12440 this.filmOffset = 0; // horizontal film offset (same unit as gauge) 12441 12442 this.updateProjectionMatrix(); 12443 12444 } 12445 12446 copy( source, recursive ) { 12447 12448 super.copy( source, recursive ); 12449 12450 this.fov = source.fov; 12451 this.zoom = source.zoom; 12452 12453 this.near = source.near; 12454 this.far = source.far;
vendor: 4,346 bytes, lines 12455-12628
12455 this.focus = source.focus; 12456 12457 this.aspect = source.aspect; 12458 this.view = source.view === null ? null : Object.assign( {}, source.view ); 12459 12460 this.filmGauge = source.filmGauge; 12461 this.filmOffset = source.filmOffset; 12462 12463 return this; 12464 12465 } 12466 12467 /** 12468 * Sets the FOV by focal length in respect to the current .filmGauge. 12469 * 12470 * The default film gauge is 35, so that the focal length can be specified for 12471 * a 35mm (full frame) camera. 12472 * 12473 * Values for focal length and film gauge must have the same unit. 12474 */ 12475 setFocalLength( focalLength ) { 12476 12477 /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */ 12478 const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; 12479 12480 this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope ); 12481 this.updateProjectionMatrix(); 12482 12483 } 12484 12485 /** 12486 * Calculates the focal length from the current .fov and .filmGauge. 12487 */ 12488 getFocalLength() { 12489 12490 const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov ); 12491 12492 return 0.5 * this.getFilmHeight() / vExtentSlope; 12493 12494 } 12495 12496 getEffectiveFOV() { 12497 12498 return RAD2DEG * 2 * Math.atan( 12499 Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom ); 12500 12501 } 12502 12503 getFilmWidth() { 12504 12505 // film not completely covered in portrait format (aspect < 1) 12506 return this.filmGauge * Math.min( this.aspect, 1 ); 12507 12508 } 12509 12510 getFilmHeight() { 12511 12512 // film not completely covered in landscape format (aspect > 1) 12513 return this.filmGauge / Math.max( this.aspect, 1 ); 12514 12515 } 12516 12517 /** 12518 * Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction. 12519 * Sets minTarget and maxTarget to the coordinates of the lower-left and upper-right corners of the view rectangle. 12520 */ 12521 getViewBounds( distance, minTarget, maxTarget ) { 12522 12523 _v3$1.set( - 1, - 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse ); 12524 12525 minTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z ); 12526 12527 _v3$1.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse ); 12528 12529 maxTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z ); 12530 12531 } 12532 12533 /** 12534 * Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction. 12535 * Copies the result into the target Vector2, where x is width and y is height. 12536 */ 12537 getViewSize( distance, target ) { 12538 12539 this.getViewBounds( distance, _minTarget, _maxTarget ); 12540 12541 return target.subVectors( _maxTarget, _minTarget ); 12542 12543 } 12544 12545 /** 12546 * Sets an offset in a larger frustum. This is useful for multi-window or 12547 * multi-monitor/multi-machine setups. 12548 * 12549 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and 12550 * the monitors are in grid like this 12551 * 12552 * +---+---+---+ 12553 * | A | B | C | 12554 * +---+---+---+ 12555 * | D | E | F | 12556 * +---+---+---+ 12557 * 12558 * then for each monitor you would call it like this 12559 * 12560 * const w = 1920; 12561 * const h = 1080; 12562 * const fullWidth = w * 3; 12563 * const fullHeight = h * 2; 12564 * 12565 * --A-- 12566 * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); 12567 * --B-- 12568 * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); 12569 * --C-- 12570 * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); 12571 * --D-- 12572 * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); 12573 * --E-- 12574 * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); 12575 * --F-- 12576 * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); 12577 * 12578 * Note there is no reason monitors have to be the same size or in a grid. 12579 */ 12580 setViewOffset( fullWidth, fullHeight, x, y, width, height ) { 12581 12582 this.aspect = fullWidth / fullHeight; 12583 12584 if ( this.view === null ) { 12585 12586 this.view = { 12587 enabled: true, 12588 fullWidth: 1, 12589 fullHeight: 1, 12590 offsetX: 0, 12591 offsetY: 0, 12592 width: 1, 12593 height: 1 12594 }; 12595 12596 } 12597 12598 this.view.enabled = true; 12599 this.view.fullWidth = fullWidth; 12600 this.view.fullHeight = fullHeight; 12601 this.view.offsetX = x; 12602 this.view.offsetY = y; 12603 this.view.width = width; 12604 this.view.height = height; 12605 12606 this.updateProjectionMatrix(); 12607 12608 } 12609 12610 clearViewOffset() { 12611 12612 if ( this.view !== null ) { 12613 12614 this.view.enabled = false; 12615 12616 } 12617 12618 this.updateProjectionMatrix(); 12619 12620 } 12621 12622 updateProjectionMatrix() { 12623 12624 const near = this.near; 12625 let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom; 12626 let height = 2 * top; 12627 let width = this.aspect * height; 12628 let left = - 0.5 * width;
vendor: 3,266 bytes, lines 12629-12765
12629 const view = this.view; 12630 12631 if ( this.view !== null && this.view.enabled ) { 12632 12633 const fullWidth = view.fullWidth, 12634 fullHeight = view.fullHeight; 12635 12636 left += view.offsetX * width / fullWidth; 12637 top -= view.offsetY * height / fullHeight; 12638 width *= view.width / fullWidth; 12639 height *= view.height / fullHeight; 12640 12641 } 12642 12643 const skew = this.filmOffset; 12644 if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); 12645 12646 this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem ); 12647 12648 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); 12649 12650 } 12651 12652 toJSON( meta ) { 12653 12654 const data = super.toJSON( meta ); 12655 12656 data.object.fov = this.fov; 12657 data.object.zoom = this.zoom; 12658 12659 data.object.near = this.near; 12660 data.object.far = this.far; 12661 data.object.focus = this.focus; 12662 12663 data.object.aspect = this.aspect; 12664 12665 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); 12666 12667 data.object.filmGauge = this.filmGauge; 12668 data.object.filmOffset = this.filmOffset; 12669 12670 return data; 12671 12672 } 12673 12674} 12675 12676const fov = - 90; // negative fov is not an error 12677const aspect = 1; 12678 12679class CubeCamera extends Object3D { 12680 12681 constructor( near, far, renderTarget ) { 12682 12683 super(); 12684 12685 this.type = 'CubeCamera'; 12686 12687 this.renderTarget = renderTarget; 12688 this.coordinateSystem = null; 12689 this.activeMipmapLevel = 0; 12690 12691 const cameraPX = new PerspectiveCamera( fov, aspect, near, far ); 12692 cameraPX.layers = this.layers; 12693 this.add( cameraPX ); 12694 12695 const cameraNX = new PerspectiveCamera( fov, aspect, near, far ); 12696 cameraNX.layers = this.layers; 12697 this.add( cameraNX ); 12698 12699 const cameraPY = new PerspectiveCamera( fov, aspect, near, far ); 12700 cameraPY.layers = this.layers; 12701 this.add( cameraPY ); 12702 12703 const cameraNY = new PerspectiveCamera( fov, aspect, near, far ); 12704 cameraNY.layers = this.layers; 12705 this.add( cameraNY ); 12706 12707 const cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); 12708 cameraPZ.layers = this.layers; 12709 this.add( cameraPZ ); 12710 12711 const cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); 12712 cameraNZ.layers = this.layers; 12713 this.add( cameraNZ ); 12714 12715 } 12716 12717 updateCoordinateSystem() { 12718 12719 const coordinateSystem = this.coordinateSystem; 12720 12721 const cameras = this.children.concat(); 12722 12723 const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras; 12724 12725 for ( const camera of cameras ) this.remove( camera ); 12726 12727 if ( coordinateSystem === WebGLCoordinateSystem ) { 12728 12729 cameraPX.up.set( 0, 1, 0 ); 12730 cameraPX.lookAt( 1, 0, 0 ); 12731 12732 cameraNX.up.set( 0, 1, 0 ); 12733 cameraNX.lookAt( - 1, 0, 0 ); 12734 12735 cameraPY.up.set( 0, 0, - 1 ); 12736 cameraPY.lookAt( 0, 1, 0 ); 12737 12738 cameraNY.up.set( 0, 0, 1 ); 12739 cameraNY.lookAt( 0, - 1, 0 ); 12740 12741 cameraPZ.up.set( 0, 1, 0 ); 12742 cameraPZ.lookAt( 0, 0, 1 ); 12743 12744 cameraNZ.up.set( 0, 1, 0 ); 12745 cameraNZ.lookAt( 0, 0, - 1 ); 12746 12747 } else if ( coordinateSystem === WebGPUCoordinateSystem ) { 12748 12749 cameraPX.up.set( 0, - 1, 0 ); 12750 cameraPX.lookAt( - 1, 0, 0 ); 12751 12752 cameraNX.up.set( 0, - 1, 0 ); 12753 cameraNX.lookAt( 1, 0, 0 ); 12754 12755 cameraPY.up.set( 0, 0, 1 ); 12756 cameraPY.lookAt( 0, 1, 0 ); 12757 12758 cameraNY.up.set( 0, 0, - 1 ); 12759 cameraNY.lookAt( 0, - 1, 0 ); 12760 12761 cameraPZ.up.set( 0, - 1, 0 ); 12762 cameraPZ.lookAt( 0, 0, 1 ); 12763 12764 cameraNZ.up.set( 0, - 1, 0 ); 12765 cameraNZ.lookAt( 0, 0, -
vendor: 7,494 bytes, lines 12765-13088
127651 ); 12766 12767 } else { 12768 12769 throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem ); 12770 12771 } 12772 12773 for ( const camera of cameras ) { 12774 12775 this.add( camera ); 12776 12777 camera.updateMatrixWorld(); 12778 12779 } 12780 12781 } 12782 12783 update( renderer, scene ) { 12784 12785 if ( this.parent === null ) this.updateMatrixWorld(); 12786 12787 const { renderTarget, activeMipmapLevel } = this; 12788 12789 if ( this.coordinateSystem !== renderer.coordinateSystem ) { 12790 12791 this.coordinateSystem = renderer.coordinateSystem; 12792 12793 this.updateCoordinateSystem(); 12794 12795 } 12796 12797 const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children; 12798 12799 const currentRenderTarget = renderer.getRenderTarget(); 12800 const currentActiveCubeFace = renderer.getActiveCubeFace(); 12801 const currentActiveMipmapLevel = renderer.getActiveMipmapLevel(); 12802 12803 const currentXrEnabled = renderer.xr.enabled; 12804 12805 renderer.xr.enabled = false; 12806 12807 const generateMipmaps = renderTarget.texture.generateMipmaps; 12808 12809 renderTarget.texture.generateMipmaps = false; 12810 12811 renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel ); 12812 renderer.render( scene, cameraPX ); 12813 12814 renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel ); 12815 renderer.render( scene, cameraNX ); 12816 12817 renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel ); 12818 renderer.render( scene, cameraPY ); 12819 12820 renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel ); 12821 renderer.render( scene, cameraNY ); 12822 12823 renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel ); 12824 renderer.render( scene, cameraPZ ); 12825 12826 // mipmaps are generated during the last call of render() 12827 // at this point, all sides of the cube render target are defined 12828 12829 renderTarget.texture.generateMipmaps = generateMipmaps; 12830 12831 renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel ); 12832 renderer.render( scene, cameraNZ ); 12833 12834 renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel ); 12835 12836 renderer.xr.enabled = currentXrEnabled; 12837 12838 renderTarget.texture.needsPMREMUpdate = true; 12839 12840 } 12841 12842} 12843 12844class CubeTexture extends Texture { 12845 12846 constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { 12847 12848 images = images !== undefined ? images : []; 12849 mapping = mapping !== undefined ? mapping : CubeReflectionMapping; 12850 12851 super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); 12852 12853 this.isCubeTexture = true; 12854 12855 this.flipY = false; 12856 12857 } 12858 12859 get images() { 12860 12861 return this.image; 12862 12863 } 12864 12865 set images( value ) { 12866 12867 this.image = value; 12868 12869 } 12870 12871} 12872 12873class WebGLCubeRenderTarget extends WebGLRenderTarget { 12874 12875 constructor( size = 1, options = {} ) { 12876 12877 super( size, size, options ); 12878 12879 this.isWebGLCubeRenderTarget = true; 12880 12881 const image = { width: size, height: size, depth: 1 }; 12882 const images = [ image, image, image, image, image, image ]; 12883 12884 this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); 12885 12886 // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) 12887 // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, 12888 // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly. 12889 12890 // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped 12891 // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture 12892 // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures). 12893 12894 this.texture.isRenderTargetTexture = true; 12895 12896 this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; 12897 this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; 12898 12899 } 12900 12901 fromEquirectangularTexture( renderer, texture ) { 12902 12903 this.texture.type = texture.type; 12904 this.texture.colorSpace = texture.colorSpace; 12905 12906 this.texture.generateMipmaps = texture.generateMipmaps; 12907 this.texture.minFilter = texture.minFilter; 12908 this.texture.magFilter = texture.magFilter; 12909 12910 const shader = { 12911 12912 uniforms: { 12913 tEquirect: { value: null }, 12914 }, 12915 12916 vertexShader: /* glsl */` 12917 12918 varying vec3 vWorldDirection; 12919 12920 vec3 transformDirection( in vec3 dir, in mat4 matrix ) { 12921 12922 return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); 12923 12924 } 12925 12926 void main() { 12927 12928 vWorldDirection = transformDirection( position, modelMatrix ); 12929 12930 #include <begin_vertex> 12931 #include <project_vertex> 12932 12933 } 12934 `, 12935 12936 fragmentShader: /* glsl */` 12937 12938 uniform sampler2D tEquirect; 12939 12940 varying vec3 vWorldDirection; 12941 12942 #include <common> 12943 12944 void main() { 12945 12946 vec3 direction = normalize( vWorldDirection ); 12947 12948 vec2 sampleUV = equirectUv( direction ); 12949 12950 gl_FragColor = texture2D( tEquirect, sampleUV ); 12951 12952 } 12953 ` 12954 }; 12955 12956 const geometry = new BoxGeometry( 5, 5, 5 ); 12957 12958 const material = new ShaderMaterial( { 12959 12960 name: 'CubemapFromEquirect', 12961 12962 uniforms: cloneUniforms( shader.uniforms ), 12963 vertexShader: shader.vertexShader, 12964 fragmentShader: shader.fragmentShader, 12965 side: BackSide, 12966 blending: NoBlending 12967 12968 } ); 12969 12970 material.uniforms.tEquirect.value = texture; 12971 12972 const mesh = new Mesh( geometry, material ); 12973 12974 const currentMinFilter = texture.minFilter; 12975 12976 // Avoid blurred poles 12977 if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter; 12978 12979 const camera = new CubeCamera( 1, 10, this ); 12980 camera.update( renderer, mesh ); 12981 12982 texture.minFilter = currentMinFilter; 12983 12984 mesh.geometry.dispose(); 12985 mesh.material.dispose(); 12986 12987 return this; 12988 12989 } 12990 12991 clear( renderer, color, depth, stencil ) { 12992 12993 const currentRenderTarget = renderer.getRenderTarget(); 12994 12995 for ( let i = 0; i < 6; i ++ ) { 12996 12997 renderer.setRenderTarget( this, i ); 12998 12999 renderer.clear( color, depth, stencil ); 13000 13001 } 13002 13003 renderer.setRenderTarget( currentRenderTarget ); 13004 13005 } 13006 13007} 13008 13009const _vector1 = /*@__PURE__*/ new Vector3(); 13010const _vector2 = /*@__PURE__*/ new Vector3(); 13011const _normalMatrix = /*@__PURE__*/ new Matrix3(); 13012 13013class Plane { 13014 13015 constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) { 13016 13017 this.isPlane = true; 13018 13019 // normal is assumed to be normalized 13020 13021 this.normal = normal; 13022 this.constant = constant; 13023 13024 } 13025 13026 set( normal, constant ) { 13027 13028 this.normal.copy( normal ); 13029 this.constant = constant; 13030 13031 return this; 13032 13033 } 13034 13035 setComponents( x, y, z, w ) { 13036 13037 this.normal.set( x, y, z ); 13038 this.constant = w; 13039 13040 return this; 13041 13042 } 13043 13044 setFromNormalAndCoplanarPoint( normal, point ) { 13045 13046 this.normal.copy( normal ); 13047 this.constant = - point.dot( this.normal ); 13048 13049 return this; 13050 13051 } 13052 13053 setFromCoplanarPoints( a, b, c ) { 13054 13055 const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize(); 13056 13057 // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? 13058 13059 this.setFromNormalAndCoplanarPoint( normal, a ); 13060 13061 return this; 13062 13063 } 13064 13065 copy( plane ) { 13066 13067 this.normal.copy( plane.normal ); 13068 this.constant = plane.constant; 13069 13070 return this; 13071 13072 } 13073 13074 normalize() { 13075 13076 // Note: will lead to a divide by zero if the plane is invalid. 13077 13078 const inverseNormalLength = 1.0 / this.normal.length(); 13079 this.normal.multiplyScalar( inverseNormalLength ); 13080 this.constant *= inverseNormalLength; 13081 13082 return this; 13083 13084 } 13085 13086 negate() { 13087 13088 this.constant *= -
vendor: 8,824 bytes, lines 13088-13552
13088 1; 13089 this.normal.negate(); 13090 13091 return this; 13092 13093 } 13094 13095 distanceToPoint( point ) { 13096 13097 return this.normal.dot( point ) + this.constant; 13098 13099 } 13100 13101 distanceToSphere( sphere ) { 13102 13103 return this.distanceToPoint( sphere.center ) - sphere.radius; 13104 13105 } 13106 13107 projectPoint( point, target ) { 13108 13109 return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) ); 13110 13111 } 13112 13113 intersectLine( line, target ) { 13114 13115 const direction = line.delta( _vector1 ); 13116 13117 const denominator = this.normal.dot( direction ); 13118 13119 if ( denominator === 0 ) { 13120 13121 // line is coplanar, return origin 13122 if ( this.distanceToPoint( line.start ) === 0 ) { 13123 13124 return target.copy( line.start ); 13125 13126 } 13127 13128 // Unsure if this is the correct method to handle this case. 13129 return null; 13130 13131 } 13132 13133 const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; 13134 13135 if ( t < 0 || t > 1 ) { 13136 13137 return null; 13138 13139 } 13140 13141 return target.copy( line.start ).addScaledVector( direction, t ); 13142 13143 } 13144 13145 intersectsLine( line ) { 13146 13147 // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. 13148 13149 const startSign = this.distanceToPoint( line.start ); 13150 const endSign = this.distanceToPoint( line.end ); 13151 13152 return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); 13153 13154 } 13155 13156 intersectsBox( box ) { 13157 13158 return box.intersectsPlane( this ); 13159 13160 } 13161 13162 intersectsSphere( sphere ) { 13163 13164 return sphere.intersectsPlane( this ); 13165 13166 } 13167 13168 coplanarPoint( target ) { 13169 13170 return target.copy( this.normal ).multiplyScalar( - this.constant ); 13171 13172 } 13173 13174 applyMatrix4( matrix, optionalNormalMatrix ) { 13175 13176 const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix ); 13177 13178 const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix ); 13179 13180 const normal = this.normal.applyMatrix3( normalMatrix ).normalize(); 13181 13182 this.constant = - referencePoint.dot( normal ); 13183 13184 return this; 13185 13186 } 13187 13188 translate( offset ) { 13189 13190 this.constant -= offset.dot( this.normal ); 13191 13192 return this; 13193 13194 } 13195 13196 equals( plane ) { 13197 13198 return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); 13199 13200 } 13201 13202 clone() { 13203 13204 return new this.constructor().copy( this ); 13205 13206 } 13207 13208} 13209 13210const _sphere$5 = /*@__PURE__*/ new Sphere(); 13211const _vector$7 = /*@__PURE__*/ new Vector3(); 13212 13213class Frustum { 13214 13215 constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) { 13216 13217 this.planes = [ p0, p1, p2, p3, p4, p5 ]; 13218 13219 } 13220 13221 set( p0, p1, p2, p3, p4, p5 ) { 13222 13223 const planes = this.planes; 13224 13225 planes[ 0 ].copy( p0 ); 13226 planes[ 1 ].copy( p1 ); 13227 planes[ 2 ].copy( p2 ); 13228 planes[ 3 ].copy( p3 ); 13229 planes[ 4 ].copy( p4 ); 13230 planes[ 5 ].copy( p5 ); 13231 13232 return this; 13233 13234 } 13235 13236 copy( frustum ) { 13237 13238 const planes = this.planes; 13239 13240 for ( let i = 0; i < 6; i ++ ) { 13241 13242 planes[ i ].copy( frustum.planes[ i ] ); 13243 13244 } 13245 13246 return this; 13247 13248 } 13249 13250 setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem ) { 13251 13252 const planes = this.planes; 13253 const me = m.elements; 13254 const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ]; 13255 const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ]; 13256 const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ]; 13257 const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ]; 13258 13259 planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize(); 13260 planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize(); 13261 planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize(); 13262 planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize(); 13263 planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize(); 13264 13265 if ( coordinateSystem === WebGLCoordinateSystem ) { 13266 13267 planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); 13268 13269 } else if ( coordinateSystem === WebGPUCoordinateSystem ) { 13270 13271 planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize(); 13272 13273 } else { 13274 13275 throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem ); 13276 13277 } 13278 13279 return this; 13280 13281 } 13282 13283 intersectsObject( object ) { 13284 13285 if ( object.boundingSphere !== undefined ) { 13286 13287 if ( object.boundingSphere === null ) object.computeBoundingSphere(); 13288 13289 _sphere$5.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld ); 13290 13291 } else { 13292 13293 const geometry = object.geometry; 13294 13295 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 13296 13297 _sphere$5.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); 13298 13299 } 13300 13301 return this.intersectsSphere( _sphere$5 ); 13302 13303 } 13304 13305 intersectsSprite( sprite ) { 13306 13307 _sphere$5.center.set( 0, 0, 0 ); 13308 _sphere$5.radius = 0.7071067811865476; 13309 _sphere$5.applyMatrix4( sprite.matrixWorld ); 13310 13311 return this.intersectsSphere( _sphere$5 ); 13312 13313 } 13314 13315 intersectsSphere( sphere ) { 13316 13317 const planes = this.planes; 13318 const center = sphere.center; 13319 const negRadius = - sphere.radius; 13320 13321 for ( let i = 0; i < 6; i ++ ) { 13322 13323 const distance = planes[ i ].distanceToPoint( center ); 13324 13325 if ( distance < negRadius ) { 13326 13327 return false; 13328 13329 } 13330 13331 } 13332 13333 return true; 13334 13335 } 13336 13337 intersectsBox( box ) { 13338 13339 const planes = this.planes; 13340 13341 for ( let i = 0; i < 6; i ++ ) { 13342 13343 const plane = planes[ i ]; 13344 13345 // corner at max distance 13346 13347 _vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x; 13348 _vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y; 13349 _vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z; 13350 13351 if ( plane.distanceToPoint( _vector$7 ) < 0 ) { 13352 13353 return false; 13354 13355 } 13356 13357 } 13358 13359 return true; 13360 13361 } 13362 13363 containsPoint( point ) { 13364 13365 const planes = this.planes; 13366 13367 for ( let i = 0; i < 6; i ++ ) { 13368 13369 if ( planes[ i ].distanceToPoint( point ) < 0 ) { 13370 13371 return false; 13372 13373 } 13374 13375 } 13376 13377 return true; 13378 13379 } 13380 13381 clone() { 13382 13383 return new this.constructor().copy( this ); 13384 13385 } 13386 13387} 13388 13389function WebGLAnimation() { 13390 13391 let context = null; 13392 let isAnimating = false; 13393 let animationLoop = null; 13394 let requestId = null; 13395 13396 function onAnimationFrame( time, frame ) { 13397 13398 animationLoop( time, frame ); 13399 13400 requestId = context.requestAnimationFrame( onAnimationFrame ); 13401 13402 } 13403 13404 return { 13405 13406 start: function () { 13407 13408 if ( isAnimating === true ) return; 13409 if ( animationLoop === null ) return; 13410 13411 requestId = context.requestAnimationFrame( onAnimationFrame ); 13412 13413 isAnimating = true; 13414 13415 }, 13416 13417 stop: function () { 13418 13419 context.cancelAnimationFrame( requestId ); 13420 13421 isAnimating = false; 13422 13423 }, 13424 13425 setAnimationLoop: function ( callback ) { 13426 13427 animationLoop = callback; 13428 13429 }, 13430 13431 setContext: function ( value ) { 13432 13433 context = value; 13434 13435 } 13436 13437 }; 13438 13439} 13440 13441function WebGLAttributes( gl ) { 13442 13443 const buffers = new WeakMap(); 13444 13445 function createBuffer( attribute, bufferType ) { 13446 13447 const array = attribute.array; 13448 const usage = attribute.usage; 13449 const size = array.byteLength; 13450 13451 const buffer = gl.createBuffer(); 13452 13453 gl.bindBuffer( bufferType, buffer ); 13454 gl.bufferData( bufferType, array, usage ); 13455 13456 attribute.onUploadCallback(); 13457 13458 let type; 13459 13460 if ( array instanceof Float32Array ) { 13461 13462 type = gl.FLOAT; 13463 13464 } else if ( array instanceof Uint16Array ) { 13465 13466 if ( attribute.isFloat16BufferAttribute ) { 13467 13468 type = gl.HALF_FLOAT; 13469 13470 } else { 13471 13472 type = gl.UNSIGNED_SHORT; 13473 13474 } 13475 13476 } else if ( array instanceof Int16Array ) { 13477 13478 type = gl.SHORT; 13479 13480 } else if ( array instanceof Uint32Array ) { 13481 13482 type = gl.UNSIGNED_INT; 13483 13484 } else if ( array instanceof Int32Array ) { 13485 13486 type = gl.INT; 13487 13488 } else if ( array instanceof Int8Array ) { 13489 13490 type = gl.BYTE; 13491 13492 } else if ( array instanceof Uint8Array ) { 13493 13494 type = gl.UNSIGNED_BYTE; 13495 13496 } else if ( array instanceof Uint8ClampedArray ) { 13497 13498 type = gl.UNSIGNED_BYTE; 13499 13500 } else { 13501 13502 throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array ); 13503 13504 } 13505 13506 return { 13507 buffer: buffer, 13508 type: type, 13509 bytesPerElement: array.BYTES_PER_ELEMENT, 13510 version: attribute.version, 13511 size: size 13512 }; 13513 13514 } 13515 13516 function updateBuffer( buffer, attribute, bufferType ) { 13517 13518 const array = attribute.array; 13519 const updateRange = attribute._updateRange; // @deprecated, r159 13520 const updateRanges = attribute.updateRanges; 13521 13522 gl.bindBuffer( bufferType, buffer ); 13523 13524 if ( updateRange.count === - 1 && updateRanges.length === 0 ) { 13525 13526 // Not using update ranges 13527 gl.bufferSubData( bufferType, 0, array ); 13528 13529 } 13530 13531 if ( updateRanges.length !== 0 ) { 13532 13533 for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { 13534 13535 const range = updateRanges[ i ]; 13536 13537 gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, 13538 array, range.start, range.count ); 13539 13540 } 13541 13542 attribute.clearUpdateRanges(); 13543 13544 } 13545 13546 // @deprecated, r159 13547 if ( updateRange.count !== - 1 ) { 13548 13549 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, 13550 array, updateRange.offset, updateRange.count ); 13551 13552 updateRange.count = -
vendor: 65,372 bytes, lines 13552-13849
135521; // reset range 13553 13554 } 13555 13556 attribute.onUploadCallback(); 13557 13558 } 13559 13560 // 13561 13562 function get( attribute ) { 13563 13564 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 13565 13566 return buffers.get( attribute ); 13567 13568 } 13569 13570 function remove( attribute ) { 13571 13572 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 13573 13574 const data = buffers.get( attribute ); 13575 13576 if ( data ) { 13577 13578 gl.deleteBuffer( data.buffer ); 13579 13580 buffers.delete( attribute ); 13581 13582 } 13583 13584 } 13585 13586 function update( attribute, bufferType ) { 13587 13588 if ( attribute.isGLBufferAttribute ) { 13589 13590 const cached = buffers.get( attribute ); 13591 13592 if ( ! cached || cached.version < attribute.version ) { 13593 13594 buffers.set( attribute, { 13595 buffer: attribute.buffer, 13596 type: attribute.type, 13597 bytesPerElement: attribute.elementSize, 13598 version: attribute.version 13599 } ); 13600 13601 } 13602 13603 return; 13604 13605 } 13606 13607 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 13608 13609 const data = buffers.get( attribute ); 13610 13611 if ( data === undefined ) { 13612 13613 buffers.set( attribute, createBuffer( attribute, bufferType ) ); 13614 13615 } else if ( data.version < attribute.version ) { 13616 13617 if ( data.size !== attribute.array.byteLength ) { 13618 13619 throw new Error( 'THREE.WebGLAttributes: The size of the buffer attribute\'s array buffer does not match the original size. Resizing buffer attributes is not supported.' ); 13620 13621 } 13622 13623 updateBuffer( data.buffer, attribute, bufferType ); 13624 13625 data.version = attribute.version; 13626 13627 } 13628 13629 } 13630 13631 return { 13632 13633 get: get, 13634 remove: remove, 13635 update: update 13636 13637 }; 13638 13639} 13640 13641class PlaneGeometry extends BufferGeometry { 13642 13643 constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) { 13644 13645 super(); 13646 13647 this.type = 'PlaneGeometry'; 13648 13649 this.parameters = { 13650 width: width, 13651 height: height, 13652 widthSegments: widthSegments, 13653 heightSegments: heightSegments 13654 }; 13655 13656 const width_half = width / 2; 13657 const height_half = height / 2; 13658 13659 const gridX = Math.floor( widthSegments ); 13660 const gridY = Math.floor( heightSegments ); 13661 13662 const gridX1 = gridX + 1; 13663 const gridY1 = gridY + 1; 13664 13665 const segment_width = width / gridX; 13666 const segment_height = height / gridY; 13667 13668 // 13669 13670 const indices = []; 13671 const vertices = []; 13672 const normals = []; 13673 const uvs = []; 13674 13675 for ( let iy = 0; iy < gridY1; iy ++ ) { 13676 13677 const y = iy * segment_height - height_half; 13678 13679 for ( let ix = 0; ix < gridX1; ix ++ ) { 13680 13681 const x = ix * segment_width - width_half; 13682 13683 vertices.push( x, - y, 0 ); 13684 13685 normals.push( 0, 0, 1 ); 13686 13687 uvs.push( ix / gridX ); 13688 uvs.push( 1 - ( iy / gridY ) ); 13689 13690 } 13691 13692 } 13693 13694 for ( let iy = 0; iy < gridY; iy ++ ) { 13695 13696 for ( let ix = 0; ix < gridX; ix ++ ) { 13697 13698 const a = ix + gridX1 * iy; 13699 const b = ix + gridX1 * ( iy + 1 ); 13700 const c = ( ix + 1 ) + gridX1 * ( iy + 1 ); 13701 const d = ( ix + 1 ) + gridX1 * iy; 13702 13703 indices.push( a, b, d ); 13704 indices.push( b, c, d ); 13705 13706 } 13707 13708 } 13709 13710 this.setIndex( indices ); 13711 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 13712 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 13713 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 13714 13715 } 13716 13717 copy( source ) { 13718 13719 super.copy( source ); 13720 13721 this.parameters = Object.assign( {}, source.parameters ); 13722 13723 return this; 13724 13725 } 13726 13727 static fromJSON( data ) { 13728 13729 return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments ); 13730 13731 } 13732 13733} 13734 13735var alphahash_fragment = "#ifdef USE_ALPHAHASH\n\tif ( diffuseColor.a < getAlphaHashThreshold( vPosition ) ) discard;\n#endif"; 13736 13737var alphahash_pars_fragment = "#ifdef USE_ALPHAHASH\n\tconst float ALPHA_HASH_SCALE = 0.05;\n\tfloat hash2D( vec2 value ) {\n\t\treturn fract( 1.0e4 * sin( 17.0 * value.x + 0.1 * value.y ) * ( 0.1 + abs( sin( 13.0 * value.y + value.x ) ) ) );\n\t}\n\tfloat hash3D( vec3 value ) {\n\t\treturn hash2D( vec2( hash2D( value.xy ), value.z ) );\n\t}\n\tfloat getAlphaHashThreshold( vec3 position ) {\n\t\tfloat maxDeriv = max(\n\t\t\tlength( dFdx( position.xyz ) ),\n\t\t\tlength( dFdy( position.xyz ) )\n\t\t);\n\t\tfloat pixScale = 1.0 / ( ALPHA_HASH_SCALE * maxDeriv );\n\t\tvec2 pixScales = vec2(\n\t\t\texp2( floor( log2( pixScale ) ) ),\n\t\t\texp2( ceil( log2( pixScale ) ) )\n\t\t);\n\t\tvec2 alpha = vec2(\n\t\t\thash3D( floor( pixScales.x * position.xyz ) ),\n\t\t\thash3D( floor( pixScales.y * position.xyz ) )\n\t\t);\n\t\tfloat lerpFactor = fract( log2( pixScale ) );\n\t\tfloat x = ( 1.0 - lerpFactor ) * alpha.x + lerpFactor * alpha.y;\n\t\tfloat a = min( lerpFactor, 1.0 - lerpFactor );\n\t\tvec3 cases = vec3(\n\t\t\tx * x / ( 2.0 * a * ( 1.0 - a ) ),\n\t\t\t( x - 0.5 * a ) / ( 1.0 - a ),\n\t\t\t1.0 - ( ( 1.0 - x ) * ( 1.0 - x ) / ( 2.0 * a * ( 1.0 - a ) ) )\n\t\t);\n\t\tfloat threshold = ( x < ( 1.0 - a ) )\n\t\t\t? ( ( x < a ) ? cases.x : cases.y )\n\t\t\t: cases.z;\n\t\treturn clamp( threshold , 1.0e-6, 1.0 );\n\t}\n#endif"; 13738 13739var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif"; 13740 13741var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; 13742 13743var alphatest_fragment = "#ifdef USE_ALPHATEST\n\t#ifdef ALPHA_TO_COVERAGE\n\tdiffuseColor.a = smoothstep( alphaTest, alphaTest + fwidth( diffuseColor.a ), diffuseColor.a );\n\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\tif ( diffuseColor.a < alphaTest ) discard;\n\t#endif\n#endif"; 13744 13745var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif"; 13746 13747var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_CLEARCOAT ) \n\t\tclearcoatSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_SHEEN ) \n\t\tsheenSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometryNormal, geometryViewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif"; 13748 13749var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; 13750 13751var batching_pars_vertex = "#ifdef USE_BATCHING\n\tattribute float batchId;\n\tuniform highp sampler2D batchingTexture;\n\tmat4 getBatchingMatrix( const in float i ) {\n\t\tint size = textureSize( batchingTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( batchingTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( batchingTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( batchingTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( batchingTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif"; 13752 13753var batching_vertex = "#ifdef USE_BATCHING\n\tmat4 batchingMatrix = getBatchingMatrix( batchId );\n#endif"; 13754 13755var begin_vertex = "vec3 transformed = vec3( position );\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif"; 13756 13757var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif"; 13758 13759var bsdfs = "float 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} // validated"; 13760 13761var 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\treturn vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\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"; 13762 13763var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vBumpMapUv );\n\t\tvec2 dSTdy = dFdy( vBumpMapUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vBumpMapUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vBumpMapUv + 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 = normalize( dFdx( surf_pos.xyz ) );\n\t\tvec3 vSigmaY = normalize( 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"; 13764 13765var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#ifdef ALPHA_TO_COVERAGE\n\t\tfloat distanceToPlane, distanceGradient;\n\t\tfloat clipOpacity = 1.0;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\tclipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\tif ( clipOpacity == 0.0 ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tfloat unionClipOpacity = 1.0;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\t\tunionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tclipOpacity *= 1.0 - unionClipOpacity;\n\t\t#endif\n\t\tdiffuseColor.a *= clipOpacity;\n\t\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tbool clipped = true;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tif ( clipped ) discard;\n\t\t#endif\n\t#endif\n#endif"; 13766 13767var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif"; 13768 13769var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif"; 13770 13771var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif"; 13772 13773var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif"; 13774 13775var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif"; 13776 13777var 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"; 13778 13779var 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"; 13780 13781var 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};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\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}\nvec3 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} // validated"; 13782 13783var 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_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\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"; 13784 13785var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif"; 13786 13787var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif"; 13788 13789var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif"; 13790 13791var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; 13792 13793var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif"; 13794 13795var colorspace_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );"; 13796 13797var colorspace_pars_fragment = "\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn sRGBTransferOETF( value );\n}"; 13798 13799var 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, envMapRotation * 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"; 13800 13801var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\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"; 13802 13803var 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"; 13804 13805var 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"; 13806 13807var 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} 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"; 13808 13809var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif"; 13810 13811var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif"; 13812 13813var 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"; 13814 13815var 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"; 13816 13817var 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}"; 13818 13819var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; 13820 13821var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; 13822 13823var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;"; 13824 13825var 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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"; 13826 13827var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\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, 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 vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\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}\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 vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\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"; 13828 13829var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * 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#ifdef 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, envMapRotation * 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\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif"; 13830 13831var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; 13832 13833var lights_toon_pars_fragment = "varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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"; 13834 13835var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;"; 13836 13837var 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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"; 13838 13839var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\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 USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\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;\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, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).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, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).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_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif"; 13840 13841var 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\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\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}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\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 = F_Schlick( f0, f90, dotVH );\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\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\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 dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\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\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 = DFGApprox( 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, 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}"; 13842 13843var lights_fragment_begin = "\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\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, geometryPosition, 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, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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, geometryPosition, 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_LIGHT_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, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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, 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, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\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 ], geometryNormal );\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"; 13844 13845var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\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( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif"; 13846 13847var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif"; 13848 13849var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF )
13849\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; 13850 13851var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif"; 13852 13853var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif"; 13854 13855var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );
vendor: 20,217 bytes, lines 13855-13915
13855\n#endif"; 13856 13857var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\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\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif"; 13858 13859var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif"; 13860 13861var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\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"; 13862 13863var map_particle_pars_fragment = "#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; 13864 13865var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; 13866 13867var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; 13868 13869var morphinstance_vertex = "#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[MORPHTARGETS_COUNT];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif"; 13870 13871var 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"; 13872 13873var 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"; 13874 13875var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t#endif\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\t#ifndef USE_INSTANCING_MORPH\n\t\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\t#endif\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"; 13876 13877var 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"; 13878 13879var 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 *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;"; 13880 13881var normal_fragment_maps = "#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).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( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif"; 13882 13883var 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"; 13884 13885var 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"; 13886 13887var 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"; 13888 13889var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.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 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif"; 13890 13891var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif"; 13892 13893var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif"; 13894 13895var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif"; 13896 13897var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif"; 13898 13899var opaque_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );"; 13900 13901var 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 depth, const in float near, const in float far ) {\n\treturn depth * ( 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 depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}"; 13902 13903var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif"; 13904 13905var project_vertex = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;"; 13906 13907var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif"; 13908 13909var 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"; 13910 13911var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; 13912 13913var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; 13914 13915var 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\t
13915float shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn shadow;
vendor: 10,186 bytes, lines 13915-13937
13915\n\t}\n#endif"; 13916 13917var 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"; 13918 13919var 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"; 13920 13921var 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}"; 13922 13923var 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"; 13924 13925var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif"; 13926 13927var 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"; 13928 13929var 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"; 13930 13931var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; 13932 13933var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; 13934 13935var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif"; 13936 13937var 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 saturate( 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}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tfloat startCompression = 0.8 - 0.04;\n\tfloat desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min(color.r, min(color.g, color.b));\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max(color.r, max(color.g, color.b));\n\tif (peak < startCompression) return color;\n\tfloat d = 1. - startCompression;\n\tfloat newPeak = 1. - d * d / (peak + d - startCompression);\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / (desaturation * (peak - newPeak) + 1.);\n\treturn mix(color,
13937newPeak * vec3(1, 1, 1), g);\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; 13938 13939var 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, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = 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, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif"; 13940 13941var 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\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\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 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\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 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );
vendor: 6,253 bytes, lines 13941-13947
13941\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif"; 13942 13943var uv_pars_fragment = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; 13944 13945var uv_pars_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif"; 13946 13947var uv_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;
vendor: 43,618 bytes, lines 13947-14197
13947\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif"; 13948 13949var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif"; 13950 13951const 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}"; 13952 13953const 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 <colorspace_fragment>\n}"; 13954 13955const 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}"; 13956 13957const 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;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * 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 <colorspace_fragment>\n}"; 13958 13959const 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}"; 13960 13961const 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 <colorspace_fragment>\n}"; 13962 13963const vertex$e = "#include <common>\n#include <batching_pars_vertex>\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 <batching_vertex>\n\t#include <skinbase_vertex>\n\t#include <morphinstance_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}"; 13964 13965const 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 <alphahash_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <clipping_planes_fragment>\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 <alphahash_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}"; 13966 13967const vertex$d = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <batching_pars_vertex>\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 <batching_vertex>\n\t#include <skinbase_vertex>\n\t#include <morphinstance_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}"; 13968 13969const 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 <alphahash_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <clipping_planes_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}"; 13970 13971const 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}"; 13972 13973const 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 <colorspace_fragment>\n}"; 13974 13975const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <uv_pars_vertex>\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 <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphinstance_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}"; 13976 13977const 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 <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}"; 13978 13979const vertex$a = "#include <common>\n#include <batching_pars_vertex>\n#include <uv_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 <color_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_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}"; 13980 13981const 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 <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\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 <alphahash_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, vLightMapUv );\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 <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"; 13982 13983const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_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 <color_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_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}"; 13984 13985const 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 <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\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 <alphahash_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 <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"; 13986 13987const vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\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 <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_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}"; 13988 13989const 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 <alphahash_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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\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 <alphahash_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#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 <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"; 13990 13991const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include <common>\n#include <batching_pars_vertex>\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 <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphinstance_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( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}"; 13992 13993const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\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\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\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 ), diffuseColor.a );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; 13994 13995const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_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 <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphinstance_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}"; 13996 13997const 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 <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\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 <alphahash_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 <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"; 13998 13999const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_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 <color_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_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}"; 14000 14001const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_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 USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\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_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\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 <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\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 <alphahash_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 + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"; 14002 14003const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_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 <color_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_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}"; 14004 14005const 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 <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\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 <alphahash_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 <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"; 14006 14007const 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>\n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include <color_vertex>\n\t#include <morphinstance_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}"; 14008 14009const 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 <alphahash_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}"; 14010 14011const vertex$2 = "#include <common>\n#include <batching_pars_vertex>\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 <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphinstance_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}"; 14012 14013const 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 <colorspace_fragment>\n\t#include <fog_fragment>\n}"; 14014 14015const 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}"; 14016 14017const 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 <alphahash_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n}"; 14018 14019const ShaderChunk = { 14020 alphahash_fragment: alphahash_fragment, 14021 alphahash_pars_fragment: alphahash_pars_fragment, 14022 alphamap_fragment: alphamap_fragment, 14023 alphamap_pars_fragment: alphamap_pars_fragment, 14024 alphatest_fragment: alphatest_fragment, 14025 alphatest_pars_fragment: alphatest_pars_fragment, 14026 aomap_fragment: aomap_fragment, 14027 aomap_pars_fragment: aomap_pars_fragment, 14028 batching_pars_vertex: batching_pars_vertex, 14029 batching_vertex: batching_vertex, 14030 begin_vertex: begin_vertex, 14031 beginnormal_vertex: beginnormal_vertex, 14032 bsdfs: bsdfs, 14033 iridescence_fragment: iridescence_fragment, 14034 bumpmap_pars_fragment: bumpmap_pars_fragment, 14035 clipping_planes_fragment: clipping_planes_fragment, 14036 clipping_planes_pars_fragment: clipping_planes_pars_fragment, 14037 clipping_planes_pars_vertex: clipping_planes_pars_vertex, 14038 clipping_planes_vertex: clipping_planes_vertex, 14039 color_fragment: color_fragment, 14040 color_pars_fragment: color_pars_fragment, 14041 color_pars_vertex: color_pars_vertex, 14042 color_vertex: color_vertex, 14043 common: common, 14044 cube_uv_reflection_fragment: cube_uv_reflection_fragment, 14045 defaultnormal_vertex: defaultnormal_vertex, 14046 displacementmap_pars_vertex: displacementmap_pars_vertex, 14047 displacementmap_vertex: displacementmap_vertex, 14048 emissivemap_fragment: emissivemap_fragment, 14049 emissivemap_pars_fragment: emissivemap_pars_fragment, 14050 colorspace_fragment: colorspace_fragment, 14051 colorspace_pars_fragment: colorspace_pars_fragment, 14052 envmap_fragment: envmap_fragment, 14053 envmap_common_pars_fragment: envmap_common_pars_fragment, 14054 envmap_pars_fragment: envmap_pars_fragment, 14055 envmap_pars_vertex: envmap_pars_vertex, 14056 envmap_physical_pars_fragment: envmap_physical_pars_fragment, 14057 envmap_vertex: envmap_vertex, 14058 fog_vertex: fog_vertex, 14059 fog_pars_vertex: fog_pars_vertex, 14060 fog_fragment: fog_fragment, 14061 fog_pars_fragment: fog_pars_fragment, 14062 gradientmap_pars_fragment: gradientmap_pars_fragment, 14063 lightmap_fragment: lightmap_fragment, 14064 lightmap_pars_fragment: lightmap_pars_fragment, 14065 lights_lambert_fragment: lights_lambert_fragment, 14066 lights_lambert_pars_fragment: lights_lambert_pars_fragment, 14067 lights_pars_begin: lights_pars_begin, 14068 lights_toon_fragment: lights_toon_fragment, 14069 lights_toon_pars_fragment: lights_toon_pars_fragment, 14070 lights_phong_fragment: lights_phong_fragment, 14071 lights_phong_pars_fragment: lights_phong_pars_fragment, 14072 lights_physical_fragment: lights_physical_fragment, 14073 lights_physical_pars_fragment: lights_physical_pars_fragment, 14074 lights_fragment_begin: lights_fragment_begin, 14075 lights_fragment_maps: lights_fragment_maps, 14076 lights_fragment_end: lights_fragment_end, 14077 logdepthbuf_fragment: logdepthbuf_fragment, 14078 logdepthbuf_pars_fragment: logdepthbuf_pars_fragment, 14079 logdepthbuf_pars_vertex: logdepthbuf_pars_vertex, 14080 logdepthbuf_vertex: logdepthbuf_vertex, 14081 map_fragment: map_fragment, 14082 map_pars_fragment: map_pars_fragment, 14083 map_particle_fragment: map_particle_fragment, 14084 map_particle_pars_fragment: map_particle_pars_fragment, 14085 metalnessmap_fragment: metalnessmap_fragment, 14086 metalnessmap_pars_fragment: metalnessmap_pars_fragment, 14087 morphinstance_vertex: morphinstance_vertex, 14088 morphcolor_vertex: morphcolor_vertex, 14089 morphnormal_vertex: morphnormal_vertex, 14090 morphtarget_pars_vertex: morphtarget_pars_vertex, 14091 morphtarget_vertex: morphtarget_vertex, 14092 normal_fragment_begin: normal_fragment_begin, 14093 normal_fragment_maps: normal_fragment_maps, 14094 normal_pars_fragment: normal_pars_fragment, 14095 normal_pars_vertex: normal_pars_vertex, 14096 normal_vertex: normal_vertex, 14097 normalmap_pars_fragment: normalmap_pars_fragment, 14098 clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin, 14099 clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps, 14100 clearcoat_pars_fragment: clearcoat_pars_fragment, 14101 iridescence_pars_fragment: iridescence_pars_fragment, 14102 opaque_fragment: opaque_fragment, 14103 packing: packing, 14104 premultiplied_alpha_fragment: premultiplied_alpha_fragment, 14105 project_vertex: project_vertex, 14106 dithering_fragment: dithering_fragment, 14107 dithering_pars_fragment: dithering_pars_fragment, 14108 roughnessmap_fragment: roughnessmap_fragment, 14109 roughnessmap_pars_fragment: roughnessmap_pars_fragment, 14110 shadowmap_pars_fragment: shadowmap_pars_fragment, 14111 shadowmap_pars_vertex: shadowmap_pars_vertex, 14112 shadowmap_vertex: shadowmap_vertex, 14113 shadowmask_pars_fragment: shadowmask_pars_fragment, 14114 skinbase_vertex: skinbase_vertex, 14115 skinning_pars_vertex: skinning_pars_vertex, 14116 skinning_vertex: skinning_vertex, 14117 skinnormal_vertex: skinnormal_vertex, 14118 specularmap_fragment: specularmap_fragment, 14119 specularmap_pars_fragment: specularmap_pars_fragment, 14120 tonemapping_fragment: tonemapping_fragment, 14121 tonemapping_pars_fragment: tonemapping_pars_fragment, 14122 transmission_fragment: transmission_fragment, 14123 transmission_pars_fragment: transmission_pars_fragment, 14124 uv_pars_fragment: uv_pars_fragment, 14125 uv_pars_vertex: uv_pars_vertex, 14126 uv_vertex: uv_vertex, 14127 worldpos_vertex: worldpos_vertex, 14128 14129 background_vert: vertex$h, 14130 background_frag: fragment$h, 14131 backgroundCube_vert: vertex$g, 14132 backgroundCube_frag: fragment$g, 14133 cube_vert: vertex$f, 14134 cube_frag: fragment$f, 14135 depth_vert: vertex$e, 14136 depth_frag: fragment$e, 14137 distanceRGBA_vert: vertex$d, 14138 distanceRGBA_frag: fragment$d, 14139 equirect_vert: vertex$c, 14140 equirect_frag: fragment$c, 14141 linedashed_vert: vertex$b, 14142 linedashed_frag: fragment$b, 14143 meshbasic_vert: vertex$a, 14144 meshbasic_frag: fragment$a, 14145 meshlambert_vert: vertex$9, 14146 meshlambert_frag: fragment$9, 14147 meshmatcap_vert: vertex$8, 14148 meshmatcap_frag: fragment$8, 14149 meshnormal_vert: vertex$7, 14150 meshnormal_frag: fragment$7, 14151 meshphong_vert: vertex$6, 14152 meshphong_frag: fragment$6, 14153 meshphysical_vert: vertex$5, 14154 meshphysical_frag: fragment$5, 14155 meshtoon_vert: vertex$4, 14156 meshtoon_frag: fragment$4, 14157 points_vert: vertex$3, 14158 points_frag: fragment$3, 14159 shadow_vert: vertex$2, 14160 shadow_frag: fragment$2, 14161 sprite_vert: vertex$1, 14162 sprite_frag: fragment$1 14163}; 14164 14165/** 14166 * Uniforms library for shared webgl shaders 14167 */ 14168 14169const UniformsLib = { 14170 14171 common: { 14172 14173 diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, 14174 opacity: { value: 1.0 }, 14175 14176 map: { value: null }, 14177 mapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14178 14179 alphaMap: { value: null }, 14180 alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14181 14182 alphaTest: { value: 0 } 14183 14184 }, 14185 14186 specularmap: { 14187 14188 specularMap: { value: null }, 14189 specularMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14190 14191 }, 14192 14193 envmap: { 14194 14195 envMap: { value: null }, 14196 envMapRotation: { value: /*@__PURE__*/ new Matrix3() }, 14197 flipEnvMap: { value: -
14197 1 }, 14198 reflectivity: { value: 1.0 }, // basic, lambert, phong 14199 ior: { value: 1.5 }, // physical 14200 refractionRatio: { value: 0.98 }, // basic, lambert, phong 14201 14202 },
vendor: 6,354 bytes, lines 14203-14518
14203 14204 aomap: { 14205 14206 aoMap: { value: null }, 14207 aoMapIntensity: { value: 1 }, 14208 aoMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14209 14210 }, 14211 14212 lightmap: { 14213 14214 lightMap: { value: null }, 14215 lightMapIntensity: { value: 1 }, 14216 lightMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14217 14218 }, 14219 14220 bumpmap: { 14221 14222 bumpMap: { value: null }, 14223 bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14224 bumpScale: { value: 1 } 14225 14226 }, 14227 14228 normalmap: { 14229 14230 normalMap: { value: null }, 14231 normalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14232 normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) } 14233 14234 }, 14235 14236 displacementmap: { 14237 14238 displacementMap: { value: null }, 14239 displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14240 displacementScale: { value: 1 }, 14241 displacementBias: { value: 0 } 14242 14243 }, 14244 14245 emissivemap: { 14246 14247 emissiveMap: { value: null }, 14248 emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14249 14250 }, 14251 14252 metalnessmap: { 14253 14254 metalnessMap: { value: null }, 14255 metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14256 14257 }, 14258 14259 roughnessmap: { 14260 14261 roughnessMap: { value: null }, 14262 roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14263 14264 }, 14265 14266 gradientmap: { 14267 14268 gradientMap: { value: null } 14269 14270 }, 14271 14272 fog: { 14273 14274 fogDensity: { value: 0.00025 }, 14275 fogNear: { value: 1 }, 14276 fogFar: { value: 2000 }, 14277 fogColor: { value: /*@__PURE__*/ new Color( 0xffffff ) } 14278 14279 }, 14280 14281 lights: { 14282 14283 ambientLightColor: { value: [] }, 14284 14285 lightProbe: { value: [] }, 14286 14287 directionalLights: { value: [], properties: { 14288 direction: {}, 14289 color: {} 14290 } }, 14291 14292 directionalLightShadows: { value: [], properties: { 14293 shadowBias: {}, 14294 shadowNormalBias: {}, 14295 shadowRadius: {}, 14296 shadowMapSize: {} 14297 } }, 14298 14299 directionalShadowMap: { value: [] }, 14300 directionalShadowMatrix: { value: [] }, 14301 14302 spotLights: { value: [], properties: { 14303 color: {}, 14304 position: {}, 14305 direction: {}, 14306 distance: {}, 14307 coneCos: {}, 14308 penumbraCos: {}, 14309 decay: {} 14310 } }, 14311 14312 spotLightShadows: { value: [], properties: { 14313 shadowBias: {}, 14314 shadowNormalBias: {}, 14315 shadowRadius: {}, 14316 shadowMapSize: {} 14317 } }, 14318 14319 spotLightMap: { value: [] }, 14320 spotShadowMap: { value: [] }, 14321 spotLightMatrix: { value: [] }, 14322 14323 pointLights: { value: [], properties: { 14324 color: {}, 14325 position: {}, 14326 decay: {}, 14327 distance: {} 14328 } }, 14329 14330 pointLightShadows: { value: [], properties: { 14331 shadowBias: {}, 14332 shadowNormalBias: {}, 14333 shadowRadius: {}, 14334 shadowMapSize: {}, 14335 shadowCameraNear: {}, 14336 shadowCameraFar: {} 14337 } }, 14338 14339 pointShadowMap: { value: [] }, 14340 pointShadowMatrix: { value: [] }, 14341 14342 hemisphereLights: { value: [], properties: { 14343 direction: {}, 14344 skyColor: {}, 14345 groundColor: {} 14346 } }, 14347 14348 // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src 14349 rectAreaLights: { value: [], properties: { 14350 color: {}, 14351 position: {}, 14352 width: {}, 14353 height: {} 14354 } }, 14355 14356 ltc_1: { value: null }, 14357 ltc_2: { value: null } 14358 14359 }, 14360 14361 points: { 14362 14363 diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, 14364 opacity: { value: 1.0 }, 14365 size: { value: 1.0 }, 14366 scale: { value: 1.0 }, 14367 map: { value: null }, 14368 alphaMap: { value: null }, 14369 alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14370 alphaTest: { value: 0 }, 14371 uvTransform: { value: /*@__PURE__*/ new Matrix3() } 14372 14373 }, 14374 14375 sprite: { 14376 14377 diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, 14378 opacity: { value: 1.0 }, 14379 center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) }, 14380 rotation: { value: 0.0 }, 14381 map: { value: null }, 14382 mapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14383 alphaMap: { value: null }, 14384 alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14385 alphaTest: { value: 0 } 14386 14387 } 14388 14389}; 14390 14391const ShaderLib = { 14392 14393 basic: { 14394 14395 uniforms: /*@__PURE__*/ mergeUniforms( [ 14396 UniformsLib.common, 14397 UniformsLib.specularmap, 14398 UniformsLib.envmap, 14399 UniformsLib.aomap, 14400 UniformsLib.lightmap, 14401 UniformsLib.fog 14402 ] ), 14403 14404 vertexShader: ShaderChunk.meshbasic_vert, 14405 fragmentShader: ShaderChunk.meshbasic_frag 14406 14407 }, 14408 14409 lambert: { 14410 14411 uniforms: /*@__PURE__*/ mergeUniforms( [ 14412 UniformsLib.common, 14413 UniformsLib.specularmap, 14414 UniformsLib.envmap, 14415 UniformsLib.aomap, 14416 UniformsLib.lightmap, 14417 UniformsLib.emissivemap, 14418 UniformsLib.bumpmap, 14419 UniformsLib.normalmap, 14420 UniformsLib.displacementmap, 14421 UniformsLib.fog, 14422 UniformsLib.lights, 14423 { 14424 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) } 14425 } 14426 ] ), 14427 14428 vertexShader: ShaderChunk.meshlambert_vert, 14429 fragmentShader: ShaderChunk.meshlambert_frag 14430 14431 }, 14432 14433 phong: { 14434 14435 uniforms: /*@__PURE__*/ mergeUniforms( [ 14436 UniformsLib.common, 14437 UniformsLib.specularmap, 14438 UniformsLib.envmap, 14439 UniformsLib.aomap, 14440 UniformsLib.lightmap, 14441 UniformsLib.emissivemap, 14442 UniformsLib.bumpmap, 14443 UniformsLib.normalmap, 14444 UniformsLib.displacementmap, 14445 UniformsLib.fog, 14446 UniformsLib.lights, 14447 { 14448 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 14449 specular: { value: /*@__PURE__*/ new Color( 0x111111 ) }, 14450 shininess: { value: 30 } 14451 } 14452 ] ), 14453 14454 vertexShader: ShaderChunk.meshphong_vert, 14455 fragmentShader: ShaderChunk.meshphong_frag 14456 14457 }, 14458 14459 standard: { 14460 14461 uniforms: /*@__PURE__*/ mergeUniforms( [ 14462 UniformsLib.common, 14463 UniformsLib.envmap, 14464 UniformsLib.aomap, 14465 UniformsLib.lightmap, 14466 UniformsLib.emissivemap, 14467 UniformsLib.bumpmap, 14468 UniformsLib.normalmap, 14469 UniformsLib.displacementmap, 14470 UniformsLib.roughnessmap, 14471 UniformsLib.metalnessmap, 14472 UniformsLib.fog, 14473 UniformsLib.lights, 14474 { 14475 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 14476 roughness: { value: 1.0 }, 14477 metalness: { value: 0.0 }, 14478 envMapIntensity: { value: 1 } 14479 } 14480 ] ), 14481 14482 vertexShader: ShaderChunk.meshphysical_vert, 14483 fragmentShader: ShaderChunk.meshphysical_frag 14484 14485 }, 14486 14487 toon: { 14488 14489 uniforms: /*@__PURE__*/ mergeUniforms( [ 14490 UniformsLib.common, 14491 UniformsLib.aomap, 14492 UniformsLib.lightmap, 14493 UniformsLib.emissivemap, 14494 UniformsLib.bumpmap, 14495 UniformsLib.normalmap, 14496 UniformsLib.displacementmap, 14497 UniformsLib.gradientmap, 14498 UniformsLib.fog, 14499 UniformsLib.lights, 14500 { 14501 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) } 14502 } 14503 ] ), 14504 14505 vertexShader: ShaderChunk.meshtoon_vert, 14506 fragmentShader: ShaderChunk.meshtoon_frag 14507 14508 }, 14509 14510 matcap: { 14511 14512 uniforms: /*@__PURE__*/ mergeUniforms( [ 14513 UniformsLib.common, 14514 UniformsLib.bumpmap, 14515 UniformsLib.normalmap, 14516 UniformsLib.displacementmap, 14517 UniformsLib.fog, 14518 {
vendor: 5,418 bytes, lines 14519-14744
14519 matcap: { value: null } 14520 } 14521 ] ), 14522 14523 vertexShader: ShaderChunk.meshmatcap_vert, 14524 fragmentShader: ShaderChunk.meshmatcap_frag 14525 14526 }, 14527 14528 points: { 14529 14530 uniforms: /*@__PURE__*/ mergeUniforms( [ 14531 UniformsLib.points, 14532 UniformsLib.fog 14533 ] ), 14534 14535 vertexShader: ShaderChunk.points_vert, 14536 fragmentShader: ShaderChunk.points_frag 14537 14538 }, 14539 14540 dashed: { 14541 14542 uniforms: /*@__PURE__*/ mergeUniforms( [ 14543 UniformsLib.common, 14544 UniformsLib.fog, 14545 { 14546 scale: { value: 1 }, 14547 dashSize: { value: 1 }, 14548 totalSize: { value: 2 } 14549 } 14550 ] ), 14551 14552 vertexShader: ShaderChunk.linedashed_vert, 14553 fragmentShader: ShaderChunk.linedashed_frag 14554 14555 }, 14556 14557 depth: { 14558 14559 uniforms: /*@__PURE__*/ mergeUniforms( [ 14560 UniformsLib.common, 14561 UniformsLib.displacementmap 14562 ] ), 14563 14564 vertexShader: ShaderChunk.depth_vert, 14565 fragmentShader: ShaderChunk.depth_frag 14566 14567 }, 14568 14569 normal: { 14570 14571 uniforms: /*@__PURE__*/ mergeUniforms( [ 14572 UniformsLib.common, 14573 UniformsLib.bumpmap, 14574 UniformsLib.normalmap, 14575 UniformsLib.displacementmap, 14576 { 14577 opacity: { value: 1.0 } 14578 } 14579 ] ), 14580 14581 vertexShader: ShaderChunk.meshnormal_vert, 14582 fragmentShader: ShaderChunk.meshnormal_frag 14583 14584 }, 14585 14586 sprite: { 14587 14588 uniforms: /*@__PURE__*/ mergeUniforms( [ 14589 UniformsLib.sprite, 14590 UniformsLib.fog 14591 ] ), 14592 14593 vertexShader: ShaderChunk.sprite_vert, 14594 fragmentShader: ShaderChunk.sprite_frag 14595 14596 }, 14597 14598 background: { 14599 14600 uniforms: { 14601 uvTransform: { value: /*@__PURE__*/ new Matrix3() }, 14602 t2D: { value: null }, 14603 backgroundIntensity: { value: 1 } 14604 }, 14605 14606 vertexShader: ShaderChunk.background_vert, 14607 fragmentShader: ShaderChunk.background_frag 14608 14609 }, 14610 14611 backgroundCube: { 14612 14613 uniforms: { 14614 envMap: { value: null }, 14615 flipEnvMap: { value: - 1 }, 14616 backgroundBlurriness: { value: 0 }, 14617 backgroundIntensity: { value: 1 }, 14618 backgroundRotation: { value: /*@__PURE__*/ new Matrix3() } 14619 }, 14620 14621 vertexShader: ShaderChunk.backgroundCube_vert, 14622 fragmentShader: ShaderChunk.backgroundCube_frag 14623 14624 }, 14625 14626 cube: { 14627 14628 uniforms: { 14629 tCube: { value: null }, 14630 tFlip: { value: - 1 }, 14631 opacity: { value: 1.0 } 14632 }, 14633 14634 vertexShader: ShaderChunk.cube_vert, 14635 fragmentShader: ShaderChunk.cube_frag 14636 14637 }, 14638 14639 equirect: { 14640 14641 uniforms: { 14642 tEquirect: { value: null }, 14643 }, 14644 14645 vertexShader: ShaderChunk.equirect_vert, 14646 fragmentShader: ShaderChunk.equirect_frag 14647 14648 }, 14649 14650 distanceRGBA: { 14651 14652 uniforms: /*@__PURE__*/ mergeUniforms( [ 14653 UniformsLib.common, 14654 UniformsLib.displacementmap, 14655 { 14656 referencePosition: { value: /*@__PURE__*/ new Vector3() }, 14657 nearDistance: { value: 1 }, 14658 farDistance: { value: 1000 } 14659 } 14660 ] ), 14661 14662 vertexShader: ShaderChunk.distanceRGBA_vert, 14663 fragmentShader: ShaderChunk.distanceRGBA_frag 14664 14665 }, 14666 14667 shadow: { 14668 14669 uniforms: /*@__PURE__*/ mergeUniforms( [ 14670 UniformsLib.lights, 14671 UniformsLib.fog, 14672 { 14673 color: { value: /*@__PURE__*/ new Color( 0x00000 ) }, 14674 opacity: { value: 1.0 } 14675 }, 14676 ] ), 14677 14678 vertexShader: ShaderChunk.shadow_vert, 14679 fragmentShader: ShaderChunk.shadow_frag 14680 14681 } 14682 14683}; 14684 14685ShaderLib.physical = { 14686 14687 uniforms: /*@__PURE__*/ mergeUniforms( [ 14688 ShaderLib.standard.uniforms, 14689 { 14690 clearcoat: { value: 0 }, 14691 clearcoatMap: { value: null }, 14692 clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14693 clearcoatNormalMap: { value: null }, 14694 clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14695 clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, 14696 clearcoatRoughness: { value: 0 }, 14697 clearcoatRoughnessMap: { value: null }, 14698 clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14699 iridescence: { value: 0 }, 14700 iridescenceMap: { value: null }, 14701 iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14702 iridescenceIOR: { value: 1.3 }, 14703 iridescenceThicknessMinimum: { value: 100 }, 14704 iridescenceThicknessMaximum: { value: 400 }, 14705 iridescenceThicknessMap: { value: null }, 14706 iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14707 sheen: { value: 0 }, 14708 sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 14709 sheenColorMap: { value: null }, 14710 sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14711 sheenRoughness: { value: 1 }, 14712 sheenRoughnessMap: { value: null }, 14713 sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14714 transmission: { value: 0 }, 14715 transmissionMap: { value: null }, 14716 transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14717 transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() }, 14718 transmissionSamplerMap: { value: null }, 14719 thickness: { value: 0 }, 14720 thicknessMap: { value: null }, 14721 thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14722 attenuationDistance: { value: 0 }, 14723 attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 14724 specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) }, 14725 specularColorMap: { value: null }, 14726 specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14727 specularIntensity: { value: 1 }, 14728 specularIntensityMap: { value: null }, 14729 specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14730 anisotropyVector: { value: /*@__PURE__*/ new Vector2() }, 14731 anisotropyMap: { value: null }, 14732 anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14733 } 14734 ] ), 14735 14736 vertexShader: ShaderChunk.meshphysical_vert, 14737 fragmentShader: ShaderChunk.meshphysical_frag 14738 14739}; 14740 14741const _rgb = { r: 0, b: 0, g: 0 }; 14742const _e1$1 = /*@__PURE__*/ new Euler(); 14743const _m1$1 = /*@__PURE__*/ new Matrix4(); 14744
vendor: 4,335 bytes, lines 14745-14894
14745function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) { 14746 14747 const clearColor = new Color( 0x000000 ); 14748 let clearAlpha = alpha === true ? 0 : 1; 14749 14750 let planeMesh; 14751 let boxMesh; 14752 14753 let currentBackground = null; 14754 let currentBackgroundVersion = 0; 14755 let currentTonemapping = null; 14756 14757 function render( renderList, scene ) { 14758 14759 let forceClear = false; 14760 let background = scene.isScene === true ? scene.background : null; 14761 14762 if ( background && background.isTexture ) { 14763 14764 const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background 14765 background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background ); 14766 14767 } 14768 14769 if ( background === null ) { 14770 14771 setClear( clearColor, clearAlpha ); 14772 14773 } else if ( background && background.isColor ) { 14774 14775 setClear( background, 1 ); 14776 forceClear = true; 14777 14778 } 14779 14780 const environmentBlendMode = renderer.xr.getEnvironmentBlendMode(); 14781 14782 if ( environmentBlendMode === 'additive' ) { 14783 14784 state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha ); 14785 14786 } else if ( environmentBlendMode === 'alpha-blend' ) { 14787 14788 state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha ); 14789 14790 } 14791 14792 if ( renderer.autoClear || forceClear ) { 14793 14794 renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); 14795 14796 } 14797 14798 if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) { 14799 14800 if ( boxMesh === undefined ) { 14801 14802 boxMesh = new Mesh( 14803 new BoxGeometry( 1, 1, 1 ), 14804 new ShaderMaterial( { 14805 name: 'BackgroundCubeMaterial', 14806 uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ), 14807 vertexShader: ShaderLib.backgroundCube.vertexShader, 14808 fragmentShader: ShaderLib.backgroundCube.fragmentShader, 14809 side: BackSide, 14810 depthTest: false, 14811 depthWrite: false, 14812 fog: false 14813 } ) 14814 ); 14815 14816 boxMesh.geometry.deleteAttribute( 'normal' ); 14817 boxMesh.geometry.deleteAttribute( 'uv' ); 14818 14819 boxMesh.onBeforeRender = function ( renderer, scene, camera ) { 14820 14821 this.matrixWorld.copyPosition( camera.matrixWorld ); 14822 14823 }; 14824 14825 // add "envMap" material property so the renderer can evaluate it like for built-in materials 14826 Object.defineProperty( boxMesh.material, 'envMap', { 14827 14828 get: function () { 14829 14830 return this.uniforms.envMap.value; 14831 14832 } 14833 14834 } ); 14835 14836 objects.update( boxMesh ); 14837 14838 } 14839 14840 _e1$1.copy( scene.backgroundRotation ); 14841 14842 // accommodate left-handed frame 14843 _e1$1.x *= - 1; _e1$1.y *= - 1; _e1$1.z *= - 1; 14844 14845 if ( background.isCubeTexture && background.isRenderTargetTexture === false ) { 14846 14847 // environment maps which are not cube render targets or PMREMs follow a different convention 14848 _e1$1.y *= - 1; 14849 _e1$1.z *= - 1; 14850 14851 } 14852 14853 boxMesh.material.uniforms.envMap.value = background; 14854 boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1; 14855 boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness; 14856 boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; 14857 boxMesh.material.uniforms.backgroundRotation.value.setFromMatrix4( _m1$1.makeRotationFromEuler( _e1$1 ) ); 14858 boxMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer; 14859 14860 if ( currentBackground !== background || 14861 currentBackgroundVersion !== background.version || 14862 currentTonemapping !== renderer.toneMapping ) { 14863 14864 boxMesh.material.needsUpdate = true; 14865 14866 currentBackground = background; 14867 currentBackgroundVersion = background.version; 14868 currentTonemapping = renderer.toneMapping; 14869 14870 } 14871 14872 boxMesh.layers.enableAll(); 14873 14874 // push to the pre-sorted opaque render list 14875 renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null ); 14876 14877 } else if ( background && background.isTexture ) { 14878 14879 if ( planeMesh === undefined ) { 14880 14881 planeMesh = new Mesh( 14882 new PlaneGeometry( 2, 2 ), 14883 new ShaderMaterial( { 14884 name: 'BackgroundMaterial', 14885 uniforms: cloneUniforms( ShaderLib.background.uniforms ), 14886 vertexShader: ShaderLib.background.vertexShader, 14887 fragmentShader: ShaderLib.background.fragmentShader, 14888 side: FrontSide, 14889 depthTest: false, 14890 depthWrite: false, 14891 fog: false 14892 } ) 14893 ); 14894
vendor: 13,870 bytes, lines 14895-15553
14895 planeMesh.geometry.deleteAttribute( 'normal' ); 14896 14897 // add "map" material property so the renderer can evaluate it like for built-in materials 14898 Object.defineProperty( planeMesh.material, 'map', { 14899 14900 get: function () { 14901 14902 return this.uniforms.t2D.value; 14903 14904 } 14905 14906 } ); 14907 14908 objects.update( planeMesh ); 14909 14910 } 14911 14912 planeMesh.material.uniforms.t2D.value = background; 14913 planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; 14914 planeMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer; 14915 14916 if ( background.matrixAutoUpdate === true ) { 14917 14918 background.updateMatrix(); 14919 14920 } 14921 14922 planeMesh.material.uniforms.uvTransform.value.copy( background.matrix ); 14923 14924 if ( currentBackground !== background || 14925 currentBackgroundVersion !== background.version || 14926 currentTonemapping !== renderer.toneMapping ) { 14927 14928 planeMesh.material.needsUpdate = true; 14929 14930 currentBackground = background; 14931 currentBackgroundVersion = background.version; 14932 currentTonemapping = renderer.toneMapping; 14933 14934 } 14935 14936 planeMesh.layers.enableAll(); 14937 14938 // push to the pre-sorted opaque render list 14939 renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null ); 14940 14941 } 14942 14943 } 14944 14945 function setClear( color, alpha ) { 14946 14947 color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) ); 14948 14949 state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha ); 14950 14951 } 14952 14953 return { 14954 14955 getClearColor: function () { 14956 14957 return clearColor; 14958 14959 }, 14960 setClearColor: function ( color, alpha = 1 ) { 14961 14962 clearColor.set( color ); 14963 clearAlpha = alpha; 14964 setClear( clearColor, clearAlpha ); 14965 14966 }, 14967 getClearAlpha: function () { 14968 14969 return clearAlpha; 14970 14971 }, 14972 setClearAlpha: function ( alpha ) { 14973 14974 clearAlpha = alpha; 14975 setClear( clearColor, clearAlpha ); 14976 14977 }, 14978 render: render 14979 14980 }; 14981 14982} 14983 14984function WebGLBindingStates( gl, attributes ) { 14985 14986 const maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); 14987 14988 const bindingStates = {}; 14989 14990 const defaultState = createBindingState( null ); 14991 let currentState = defaultState; 14992 let forceUpdate = false; 14993 14994 function setup( object, material, program, geometry, index ) { 14995 14996 let updateBuffers = false; 14997 14998 const state = getBindingState( geometry, program, material ); 14999 15000 if ( currentState !== state ) { 15001 15002 currentState = state; 15003 bindVertexArrayObject( currentState.object ); 15004 15005 } 15006 15007 updateBuffers = needsUpdate( object, geometry, program, index ); 15008 15009 if ( updateBuffers ) saveCache( object, geometry, program, index ); 15010 15011 if ( index !== null ) { 15012 15013 attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); 15014 15015 } 15016 15017 if ( updateBuffers || forceUpdate ) { 15018 15019 forceUpdate = false; 15020 15021 setupVertexAttributes( object, material, program, geometry ); 15022 15023 if ( index !== null ) { 15024 15025 gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer ); 15026 15027 } 15028 15029 } 15030 15031 } 15032 15033 function createVertexArrayObject() { 15034 15035 return gl.createVertexArray(); 15036 15037 } 15038 15039 function bindVertexArrayObject( vao ) { 15040 15041 return gl.bindVertexArray( vao ); 15042 15043 } 15044 15045 function deleteVertexArrayObject( vao ) { 15046 15047 return gl.deleteVertexArray( vao ); 15048 15049 } 15050 15051 function getBindingState( geometry, program, material ) { 15052 15053 const wireframe = ( material.wireframe === true ); 15054 15055 let programMap = bindingStates[ geometry.id ]; 15056 15057 if ( programMap === undefined ) { 15058 15059 programMap = {}; 15060 bindingStates[ geometry.id ] = programMap; 15061 15062 } 15063 15064 let stateMap = programMap[ program.id ]; 15065 15066 if ( stateMap === undefined ) { 15067 15068 stateMap = {}; 15069 programMap[ program.id ] = stateMap; 15070 15071 } 15072 15073 let state = stateMap[ wireframe ]; 15074 15075 if ( state === undefined ) { 15076 15077 state = createBindingState( createVertexArrayObject() ); 15078 stateMap[ wireframe ] = state; 15079 15080 } 15081 15082 return state; 15083 15084 } 15085 15086 function createBindingState( vao ) { 15087 15088 const newAttributes = []; 15089 const enabledAttributes = []; 15090 const attributeDivisors = []; 15091 15092 for ( let i = 0; i < maxVertexAttributes; i ++ ) { 15093 15094 newAttributes[ i ] = 0; 15095 enabledAttributes[ i ] = 0; 15096 attributeDivisors[ i ] = 0; 15097 15098 } 15099 15100 return { 15101 15102 // for backward compatibility on non-VAO support browser 15103 geometry: null, 15104 program: null, 15105 wireframe: false, 15106 15107 newAttributes: newAttributes, 15108 enabledAttributes: enabledAttributes, 15109 attributeDivisors: attributeDivisors, 15110 object: vao, 15111 attributes: {}, 15112 index: null 15113 15114 }; 15115 15116 } 15117 15118 function needsUpdate( object, geometry, program, index ) { 15119 15120 const cachedAttributes = currentState.attributes; 15121 const geometryAttributes = geometry.attributes; 15122 15123 let attributesNum = 0; 15124 15125 const programAttributes = program.getAttributes(); 15126 15127 for ( const name in programAttributes ) { 15128 15129 const programAttribute = programAttributes[ name ]; 15130 15131 if ( programAttribute.location >= 0 ) { 15132 15133 const cachedAttribute = cachedAttributes[ name ]; 15134 let geometryAttribute = geometryAttributes[ name ]; 15135 15136 if ( geometryAttribute === undefined ) { 15137 15138 if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; 15139 if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; 15140 15141 } 15142 15143 if ( cachedAttribute === undefined ) return true; 15144 15145 if ( cachedAttribute.attribute !== geometryAttribute ) return true; 15146 15147 if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data ) return true; 15148 15149 attributesNum ++; 15150 15151 } 15152 15153 } 15154 15155 if ( currentState.attributesNum !== attributesNum ) return true; 15156 15157 if ( currentState.index !== index ) return true; 15158 15159 return false; 15160 15161 } 15162 15163 function saveCache( object, geometry, program, index ) { 15164 15165 const cache = {}; 15166 const attributes = geometry.attributes; 15167 let attributesNum = 0; 15168 15169 const programAttributes = program.getAttributes(); 15170 15171 for ( const name in programAttributes ) { 15172 15173 const programAttribute = programAttributes[ name ]; 15174 15175 if ( programAttribute.location >= 0 ) { 15176 15177 let attribute = attributes[ name ]; 15178 15179 if ( attribute === undefined ) { 15180 15181 if ( name === 'instanceMatrix' && object.instanceMatrix ) attribute = object.instanceMatrix; 15182 if ( name === 'instanceColor' && object.instanceColor ) attribute = object.instanceColor; 15183 15184 } 15185 15186 const data = {}; 15187 data.attribute = attribute; 15188 15189 if ( attribute && attribute.data ) { 15190 15191 data.data = attribute.data; 15192 15193 } 15194 15195 cache[ name ] = data; 15196 15197 attributesNum ++; 15198 15199 } 15200 15201 } 15202 15203 currentState.attributes = cache; 15204 currentState.attributesNum = attributesNum; 15205 15206 currentState.index = index; 15207 15208 } 15209 15210 function initAttributes() { 15211 15212 const newAttributes = currentState.newAttributes; 15213 15214 for ( let i = 0, il = newAttributes.length; i < il; i ++ ) { 15215 15216 newAttributes[ i ] = 0; 15217 15218 } 15219 15220 } 15221 15222 function enableAttribute( attribute ) { 15223 15224 enableAttributeAndDivisor( attribute, 0 ); 15225 15226 } 15227 15228 function enableAttributeAndDivisor( attribute, meshPerAttribute ) { 15229 15230 const newAttributes = currentState.newAttributes; 15231 const enabledAttributes = currentState.enabledAttributes; 15232 const attributeDivisors = currentState.attributeDivisors; 15233 15234 newAttributes[ attribute ] = 1; 15235 15236 if ( enabledAttributes[ attribute ] === 0 ) { 15237 15238 gl.enableVertexAttribArray( attribute ); 15239 enabledAttributes[ attribute ] = 1; 15240 15241 } 15242 15243 if ( attributeDivisors[ attribute ] !== meshPerAttribute ) { 15244 15245 gl.vertexAttribDivisor( attribute, meshPerAttribute ); 15246 attributeDivisors[ attribute ] = meshPerAttribute; 15247 15248 } 15249 15250 } 15251 15252 function disableUnusedAttributes() { 15253 15254 const newAttributes = currentState.newAttributes; 15255 const enabledAttributes = currentState.enabledAttributes; 15256 15257 for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) { 15258 15259 if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { 15260 15261 gl.disableVertexAttribArray( i ); 15262 enabledAttributes[ i ] = 0; 15263 15264 } 15265 15266 } 15267 15268 } 15269 15270 function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) { 15271 15272 if ( integer === true ) { 15273 15274 gl.vertexAttribIPointer( index, size, type, stride, offset ); 15275 15276 } else { 15277 15278 gl.vertexAttribPointer( index, size, type, normalized, stride, offset ); 15279 15280 } 15281 15282 } 15283 15284 function setupVertexAttributes( object, material, program, geometry ) { 15285 15286 initAttributes(); 15287 15288 const geometryAttributes = geometry.attributes; 15289 15290 const programAttributes = program.getAttributes(); 15291 15292 const materialDefaultAttributeValues = material.defaultAttributeValues; 15293 15294 for ( const name in programAttributes ) { 15295 15296 const programAttribute = programAttributes[ name ]; 15297 15298 if ( programAttribute.location >= 0 ) { 15299 15300 let geometryAttribute = geometryAttributes[ name ]; 15301 15302 if ( geometryAttribute === undefined ) { 15303 15304 if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; 15305 if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; 15306 15307 } 15308 15309 if ( geometryAttribute !== undefined ) { 15310 15311 const normalized = geometryAttribute.normalized; 15312 const size = geometryAttribute.itemSize; 15313 15314 const attribute = attributes.get( geometryAttribute ); 15315 15316 // TODO Attribute may not be available on context restore 15317 15318 if ( attribute === undefined ) continue; 15319 15320 const buffer = attribute.buffer; 15321 const type = attribute.type; 15322 const bytesPerElement = attribute.bytesPerElement; 15323 15324 // check for integer attributes 15325 15326 const integer = ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType ); 15327 15328 if ( geometryAttribute.isInterleavedBufferAttribute ) { 15329 15330 const data = geometryAttribute.data; 15331 const stride = data.stride; 15332 const offset = geometryAttribute.offset; 15333 15334 if ( data.isInstancedInterleavedBuffer ) { 15335 15336 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15337 15338 enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute ); 15339 15340 } 15341 15342 if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { 15343 15344 geometry._maxInstanceCount = data.meshPerAttribute * data.count; 15345 15346 } 15347 15348 } else { 15349 15350 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15351 15352 enableAttribute( programAttribute.location + i ); 15353 15354 } 15355 15356 } 15357 15358 gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); 15359 15360 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15361 15362 vertexAttribPointer( 15363 programAttribute.location + i, 15364 size / programAttribute.locationSize, 15365 type, 15366 normalized, 15367 stride * bytesPerElement, 15368 ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement, 15369 integer 15370 ); 15371 15372 } 15373 15374 } else { 15375 15376 if ( geometryAttribute.isInstancedBufferAttribute ) { 15377 15378 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15379 15380 enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute ); 15381 15382 } 15383 15384 if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { 15385 15386 geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; 15387 15388 } 15389 15390 } else { 15391 15392 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15393 15394 enableAttribute( programAttribute.location + i ); 15395 15396 } 15397 15398 } 15399 15400 gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); 15401 15402 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15403 15404 vertexAttribPointer( 15405 programAttribute.location + i, 15406 size / programAttribute.locationSize, 15407 type, 15408 normalized, 15409 size * bytesPerElement, 15410 ( size / programAttribute.locationSize ) * i * bytesPerElement, 15411 integer 15412 ); 15413 15414 } 15415 15416 } 15417 15418 } else if ( materialDefaultAttributeValues !== undefined ) { 15419 15420 const value = materialDefaultAttributeValues[ name ]; 15421 15422 if ( value !== undefined ) { 15423 15424 switch ( value.length ) { 15425 15426 case 2: 15427 gl.vertexAttrib2fv( programAttribute.location, value ); 15428 break; 15429 15430 case 3: 15431 gl.vertexAttrib3fv( programAttribute.location, value ); 15432 break; 15433 15434 case 4: 15435 gl.vertexAttrib4fv( programAttribute.location, value ); 15436 break; 15437 15438 default: 15439 gl.vertexAttrib1fv( programAttribute.location, value ); 15440 15441 } 15442 15443 } 15444 15445 } 15446 15447 } 15448 15449 } 15450 15451 disableUnusedAttributes(); 15452 15453 } 15454 15455 function dispose() { 15456 15457 reset(); 15458 15459 for ( const geometryId in bindingStates ) { 15460 15461 const programMap = bindingStates[ geometryId ]; 15462 15463 for ( const programId in programMap ) { 15464 15465 const stateMap = programMap[ programId ]; 15466 15467 for ( const wireframe in stateMap ) { 15468 15469 deleteVertexArrayObject( stateMap[ wireframe ].object ); 15470 15471 delete stateMap[ wireframe ]; 15472 15473 } 15474 15475 delete programMap[ programId ]; 15476 15477 } 15478 15479 delete bindingStates[ geometryId ]; 15480 15481 } 15482 15483 } 15484 15485 function releaseStatesOfGeometry( geometry ) { 15486 15487 if ( bindingStates[ geometry.id ] === undefined ) return; 15488 15489 const programMap = bindingStates[ geometry.id ]; 15490 15491 for ( const programId in programMap ) { 15492 15493 const stateMap = programMap[ programId ]; 15494 15495 for ( const wireframe in stateMap ) { 15496 15497 deleteVertexArrayObject( stateMap[ wireframe ].object ); 15498 15499 delete stateMap[ wireframe ]; 15500 15501 } 15502 15503 delete programMap[ programId ]; 15504 15505 } 15506 15507 delete bindingStates[ geometry.id ]; 15508 15509 } 15510 15511 function releaseStatesOfProgram( program ) { 15512 15513 for ( const geometryId in bindingStates ) { 15514 15515 const programMap = bindingStates[ geometryId ]; 15516 15517 if ( programMap[ program.id ] === undefined ) continue; 15518 15519 const stateMap = programMap[ program.id ]; 15520 15521 for ( const wireframe in stateMap ) { 15522 15523 deleteVertexArrayObject( stateMap[ wireframe ].object ); 15524 15525 delete stateMap[ wireframe ]; 15526 15527 } 15528 15529 delete programMap[ program.id ]; 15530 15531 } 15532 15533 } 15534 15535 function reset() { 15536 15537 resetDefaultState(); 15538 forceUpdate = true; 15539 15540 if ( currentState === defaultState ) return; 15541 15542 currentState = defaultState; 15543 bindVertexArrayObject( currentState.object ); 15544 15545 } 15546 15547 // for backward-compatibility 15548 15549 function resetDefaultState() { 15550 15551 defaultState.geometry = null; 15552 defaultState.program = null; 15553 defaultState.wireframe = false;
vendor: 3,707 bytes, lines 15554-15727
15554 15555 } 15556 15557 return { 15558 15559 setup: setup, 15560 reset: reset, 15561 resetDefaultState: resetDefaultState, 15562 dispose: dispose, 15563 releaseStatesOfGeometry: releaseStatesOfGeometry, 15564 releaseStatesOfProgram: releaseStatesOfProgram, 15565 15566 initAttributes: initAttributes, 15567 enableAttribute: enableAttribute, 15568 disableUnusedAttributes: disableUnusedAttributes 15569 15570 }; 15571 15572} 15573 15574function WebGLBufferRenderer( gl, extensions, info ) { 15575 15576 let mode; 15577 15578 function setMode( value ) { 15579 15580 mode = value; 15581 15582 } 15583 15584 function render( start, count ) { 15585 15586 gl.drawArrays( mode, start, count ); 15587 15588 info.update( count, mode, 1 ); 15589 15590 } 15591 15592 function renderInstances( start, count, primcount ) { 15593 15594 if ( primcount === 0 ) return; 15595 15596 gl.drawArraysInstanced( mode, start, count, primcount ); 15597 15598 info.update( count, mode, primcount ); 15599 15600 } 15601 15602 function renderMultiDraw( starts, counts, drawCount ) { 15603 15604 if ( drawCount === 0 ) return; 15605 15606 const extension = extensions.get( 'WEBGL_multi_draw' ); 15607 15608 if ( extension === null ) { 15609 15610 for ( let i = 0; i < drawCount; i ++ ) { 15611 15612 this.render( starts[ i ], counts[ i ] ); 15613 15614 } 15615 15616 } else { 15617 15618 extension.multiDrawArraysWEBGL( mode, starts, 0, counts, 0, drawCount ); 15619 15620 let elementCount = 0; 15621 for ( let i = 0; i < drawCount; i ++ ) { 15622 15623 elementCount += counts[ i ]; 15624 15625 } 15626 15627 info.update( elementCount, mode, 1 ); 15628 15629 } 15630 15631 } 15632 15633 // 15634 15635 this.setMode = setMode; 15636 this.render = render; 15637 this.renderInstances = renderInstances; 15638 this.renderMultiDraw = renderMultiDraw; 15639 15640} 15641 15642function WebGLCapabilities( gl, extensions, parameters ) { 15643 15644 let maxAnisotropy; 15645 15646 function getMaxAnisotropy() { 15647 15648 if ( maxAnisotropy !== undefined ) return maxAnisotropy; 15649 15650 if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { 15651 15652 const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); 15653 15654 maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); 15655 15656 } else { 15657 15658 maxAnisotropy = 0; 15659 15660 } 15661 15662 return maxAnisotropy; 15663 15664 } 15665 15666 function getMaxPrecision( precision ) { 15667 15668 if ( precision === 'highp' ) { 15669 15670 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 && 15671 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) { 15672 15673 return 'highp'; 15674 15675 } 15676 15677 precision = 'mediump'; 15678 15679 } 15680 15681 if ( precision === 'mediump' ) { 15682 15683 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 && 15684 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) { 15685 15686 return 'mediump'; 15687 15688 } 15689 15690 } 15691 15692 return 'lowp'; 15693 15694 } 15695 15696 let precision = parameters.precision !== undefined ? parameters.precision : 'highp'; 15697 const maxPrecision = getMaxPrecision( precision ); 15698 15699 if ( maxPrecision !== precision ) { 15700 15701 console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); 15702 precision = maxPrecision; 15703 15704 } 15705 15706 const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; 15707 15708 const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); 15709 const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); 15710 const maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE ); 15711 const maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE ); 15712 15713 const maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); 15714 const maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS ); 15715 const maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS ); 15716 const maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS ); 15717 15718 const vertexTextures = maxVertexTextures > 0; 15719 15720 const maxSamples = gl.getParameter( gl.MAX_SAMPLES ); 15721 15722 return { 15723 15724 isWebGL2: true, // keeping this for backwards compatibility 15725 15726 getMaxAnisotropy: getMaxAnisotropy, 15727 getMaxPrecision: getMaxPrecision,
vendor: 1,617 bytes, lines 15728-15808
15728 15729 precision: precision, 15730 logarithmicDepthBuffer: logarithmicDepthBuffer, 15731 15732 maxTextures: maxTextures, 15733 maxVertexTextures: maxVertexTextures, 15734 maxTextureSize: maxTextureSize, 15735 maxCubemapSize: maxCubemapSize, 15736 15737 maxAttributes: maxAttributes, 15738 maxVertexUniforms: maxVertexUniforms, 15739 maxVaryings: maxVaryings, 15740 maxFragmentUniforms: maxFragmentUniforms, 15741 15742 vertexTextures: vertexTextures, 15743 15744 maxSamples: maxSamples 15745 15746 }; 15747 15748} 15749 15750function WebGLClipping( properties ) { 15751 15752 const scope = this; 15753 15754 let globalState = null, 15755 numGlobalPlanes = 0, 15756 localClippingEnabled = false, 15757 renderingShadows = false; 15758 15759 const plane = new Plane(), 15760 viewNormalMatrix = new Matrix3(), 15761 15762 uniform = { value: null, needsUpdate: false }; 15763 15764 this.uniform = uniform; 15765 this.numPlanes = 0; 15766 this.numIntersection = 0; 15767 15768 this.init = function ( planes, enableLocalClipping ) { 15769 15770 const enabled = 15771 planes.length !== 0 || 15772 enableLocalClipping || 15773 // enable state of previous frame - the clipping code has to 15774 // run another frame in order to reset the state: 15775 numGlobalPlanes !== 0 || 15776 localClippingEnabled; 15777 15778 localClippingEnabled = enableLocalClipping; 15779 15780 numGlobalPlanes = planes.length; 15781 15782 return enabled; 15783 15784 }; 15785 15786 this.beginShadows = function () { 15787 15788 renderingShadows = true; 15789 projectPlanes( null ); 15790 15791 }; 15792 15793 this.endShadows = function () { 15794 15795 renderingShadows = false; 15796 15797 }; 15798 15799 this.setGlobalState = function ( planes, camera ) { 15800 15801 globalState = projectPlanes( planes, camera, 0 ); 15802 15803 }; 15804 15805 this.setState = function ( material, camera, useCache ) { 15806 15807 const planes = material.clippingPlanes, 15808 clipIntersection = material.clipIntersection,
vendor: 9,736 bytes, lines 15809-16231
15809 clipShadows = material.clipShadows; 15810 15811 const materialProperties = properties.get( material ); 15812 15813 if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) { 15814 15815 // there's no local clipping 15816 15817 if ( renderingShadows ) { 15818 15819 // there's no global clipping 15820 15821 projectPlanes( null ); 15822 15823 } else { 15824 15825 resetGlobalState(); 15826 15827 } 15828 15829 } else { 15830 15831 const nGlobal = renderingShadows ? 0 : numGlobalPlanes, 15832 lGlobal = nGlobal * 4; 15833 15834 let dstArray = materialProperties.clippingState || null; 15835 15836 uniform.value = dstArray; // ensure unique state 15837 15838 dstArray = projectPlanes( planes, camera, lGlobal, useCache ); 15839 15840 for ( let i = 0; i !== lGlobal; ++ i ) { 15841 15842 dstArray[ i ] = globalState[ i ]; 15843 15844 } 15845 15846 materialProperties.clippingState = dstArray; 15847 this.numIntersection = clipIntersection ? this.numPlanes : 0; 15848 this.numPlanes += nGlobal; 15849 15850 } 15851 15852 15853 }; 15854 15855 function resetGlobalState() { 15856 15857 if ( uniform.value !== globalState ) { 15858 15859 uniform.value = globalState; 15860 uniform.needsUpdate = numGlobalPlanes > 0; 15861 15862 } 15863 15864 scope.numPlanes = numGlobalPlanes; 15865 scope.numIntersection = 0; 15866 15867 } 15868 15869 function projectPlanes( planes, camera, dstOffset, skipTransform ) { 15870 15871 const nPlanes = planes !== null ? planes.length : 0; 15872 let dstArray = null; 15873 15874 if ( nPlanes !== 0 ) { 15875 15876 dstArray = uniform.value; 15877 15878 if ( skipTransform !== true || dstArray === null ) { 15879 15880 const flatSize = dstOffset + nPlanes * 4, 15881 viewMatrix = camera.matrixWorldInverse; 15882 15883 viewNormalMatrix.getNormalMatrix( viewMatrix ); 15884 15885 if ( dstArray === null || dstArray.length < flatSize ) { 15886 15887 dstArray = new Float32Array( flatSize ); 15888 15889 } 15890 15891 for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) { 15892 15893 plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix ); 15894 15895 plane.normal.toArray( dstArray, i4 ); 15896 dstArray[ i4 + 3 ] = plane.constant; 15897 15898 } 15899 15900 } 15901 15902 uniform.value = dstArray; 15903 uniform.needsUpdate = true; 15904 15905 } 15906 15907 scope.numPlanes = nPlanes; 15908 scope.numIntersection = 0; 15909 15910 return dstArray; 15911 15912 } 15913 15914} 15915 15916function WebGLCubeMaps( renderer ) { 15917 15918 let cubemaps = new WeakMap(); 15919 15920 function mapTextureMapping( texture, mapping ) { 15921 15922 if ( mapping === EquirectangularReflectionMapping ) { 15923 15924 texture.mapping = CubeReflectionMapping; 15925 15926 } else if ( mapping === EquirectangularRefractionMapping ) { 15927 15928 texture.mapping = CubeRefractionMapping; 15929 15930 } 15931 15932 return texture; 15933 15934 } 15935 15936 function get( texture ) { 15937 15938 if ( texture && texture.isTexture ) { 15939 15940 const mapping = texture.mapping; 15941 15942 if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) { 15943 15944 if ( cubemaps.has( texture ) ) { 15945 15946 const cubemap = cubemaps.get( texture ).texture; 15947 return mapTextureMapping( cubemap, texture.mapping ); 15948 15949 } else { 15950 15951 const image = texture.image; 15952 15953 if ( image && image.height > 0 ) { 15954 15955 const renderTarget = new WebGLCubeRenderTarget( image.height ); 15956 renderTarget.fromEquirectangularTexture( renderer, texture ); 15957 cubemaps.set( texture, renderTarget ); 15958 15959 texture.addEventListener( 'dispose', onTextureDispose ); 15960 15961 return mapTextureMapping( renderTarget.texture, texture.mapping ); 15962 15963 } else { 15964 15965 // image not yet ready. try the conversion next frame 15966 15967 return null; 15968 15969 } 15970 15971 } 15972 15973 } 15974 15975 } 15976 15977 return texture; 15978 15979 } 15980 15981 function onTextureDispose( event ) { 15982 15983 const texture = event.target; 15984 15985 texture.removeEventListener( 'dispose', onTextureDispose ); 15986 15987 const cubemap = cubemaps.get( texture ); 15988 15989 if ( cubemap !== undefined ) { 15990 15991 cubemaps.delete( texture ); 15992 cubemap.dispose(); 15993 15994 } 15995 15996 } 15997 15998 function dispose() { 15999 16000 cubemaps = new WeakMap(); 16001 16002 } 16003 16004 return { 16005 get: get, 16006 dispose: dispose 16007 }; 16008 16009} 16010 16011class OrthographicCamera extends Camera { 16012 16013 constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) { 16014 16015 super(); 16016 16017 this.isOrthographicCamera = true; 16018 16019 this.type = 'OrthographicCamera'; 16020 16021 this.zoom = 1; 16022 this.view = null; 16023 16024 this.left = left; 16025 this.right = right; 16026 this.top = top; 16027 this.bottom = bottom; 16028 16029 this.near = near; 16030 this.far = far; 16031 16032 this.updateProjectionMatrix(); 16033 16034 } 16035 16036 copy( source, recursive ) { 16037 16038 super.copy( source, recursive ); 16039 16040 this.left = source.left; 16041 this.right = source.right; 16042 this.top = source.top; 16043 this.bottom = source.bottom; 16044 this.near = source.near; 16045 this.far = source.far; 16046 16047 this.zoom = source.zoom; 16048 this.view = source.view === null ? null : Object.assign( {}, source.view ); 16049 16050 return this; 16051 16052 } 16053 16054 setViewOffset( fullWidth, fullHeight, x, y, width, height ) { 16055 16056 if ( this.view === null ) { 16057 16058 this.view = { 16059 enabled: true, 16060 fullWidth: 1, 16061 fullHeight: 1, 16062 offsetX: 0, 16063 offsetY: 0, 16064 width: 1, 16065 height: 1 16066 }; 16067 16068 } 16069 16070 this.view.enabled = true; 16071 this.view.fullWidth = fullWidth; 16072 this.view.fullHeight = fullHeight; 16073 this.view.offsetX = x; 16074 this.view.offsetY = y; 16075 this.view.width = width; 16076 this.view.height = height; 16077 16078 this.updateProjectionMatrix(); 16079 16080 } 16081 16082 clearViewOffset() { 16083 16084 if ( this.view !== null ) { 16085 16086 this.view.enabled = false; 16087 16088 } 16089 16090 this.updateProjectionMatrix(); 16091 16092 } 16093 16094 updateProjectionMatrix() { 16095 16096 const dx = ( this.right - this.left ) / ( 2 * this.zoom ); 16097 const dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); 16098 const cx = ( this.right + this.left ) / 2; 16099 const cy = ( this.top + this.bottom ) / 2; 16100 16101 let left = cx - dx; 16102 let right = cx + dx; 16103 let top = cy + dy; 16104 let bottom = cy - dy; 16105 16106 if ( this.view !== null && this.view.enabled ) { 16107 16108 const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom; 16109 const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom; 16110 16111 left += scaleW * this.view.offsetX; 16112 right = left + scaleW * this.view.width; 16113 top -= scaleH * this.view.offsetY; 16114 bottom = top - scaleH * this.view.height; 16115 16116 } 16117 16118 this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem ); 16119 16120 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); 16121 16122 } 16123 16124 toJSON( meta ) { 16125 16126 const data = super.toJSON( meta ); 16127 16128 data.object.zoom = this.zoom; 16129 data.object.left = this.left; 16130 data.object.right = this.right; 16131 data.object.top = this.top; 16132 data.object.bottom = this.bottom; 16133 data.object.near = this.near; 16134 data.object.far = this.far; 16135 16136 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); 16137 16138 return data; 16139 16140 } 16141 16142} 16143 16144const LOD_MIN = 4; 16145 16146// The standard deviations (radians) associated with the extra mips. These are 16147// chosen to approximate a Trowbridge-Reitz distribution function times the 16148// geometric shadowing function. These sigma values squared must match the 16149// variance #defines in cube_uv_reflection_fragment.glsl.js. 16150const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ]; 16151 16152// The maximum length of the blur for loop. Smaller sigmas will use fewer 16153// samples and exit early, but not recompile the shader. 16154const MAX_SAMPLES = 20; 16155 16156const _flatCamera = /*@__PURE__*/ new OrthographicCamera(); 16157const _clearColor = /*@__PURE__*/ new Color(); 16158let _oldTarget = null; 16159let _oldActiveCubeFace = 0; 16160let _oldActiveMipmapLevel = 0; 16161let _oldXrEnabled = false; 16162 16163// Golden Ratio 16164const PHI = ( 1 + Math.sqrt( 5 ) ) / 2; 16165const INV_PHI = 1 / PHI; 16166 16167// Vertices of a dodecahedron (except the opposites, which represent the 16168// same axis), used as axis directions evenly spread on a sphere. 16169const _axisDirections = [ 16170 /*@__PURE__*/ new Vector3( 1, 1, 1 ), 16171 /*@__PURE__*/ new Vector3( - 1, 1, 1 ), 16172 /*@__PURE__*/ new Vector3( 1, 1, - 1 ), 16173 /*@__PURE__*/ new Vector3( - 1, 1, - 1 ), 16174 /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), 16175 /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), 16176 /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), 16177 /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), 16178 /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), 16179 /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ) ]; 16180 16181/** 16182 * This class generates a Prefiltered, Mipmapped Radiance Environment Map 16183 * (PMREM) from a cubeMap environment texture. This allows different levels of 16184 * blur to be quickly accessed based on material roughness. It is packed into a 16185 * special CubeUV format that allows us to perform custom interpolation so that 16186 * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap 16187 * chain, it only goes down to the LOD_MIN level (above), and then creates extra 16188 * even more filtered 'mips' at the same LOD_MIN resolution, associated with 16189 * higher roughness levels. In this way we maintain resolution to smoothly 16190 * interpolate diffuse lighting while limiting sampling computation. 16191 * 16192 * Paper: Fast, Accurate Image-Based Lighting 16193 * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view 16194*/ 16195 16196class PMREMGenerator { 16197 16198 constructor( renderer ) { 16199 16200 this._renderer = renderer; 16201 this._pingPongRenderTarget = null; 16202 16203 this._lodMax = 0; 16204 this._cubeSize = 0; 16205 this._lodPlanes = []; 16206 this._sizeLods = []; 16207 this._sigmas = []; 16208 16209 this._blurMaterial = null; 16210 this._cubemapMaterial = null; 16211 this._equirectMaterial = null; 16212 16213 this._compileMaterial( this._blurMaterial ); 16214 16215 } 16216 16217 /** 16218 * Generates a PMREM from a supplied Scene, which can be faster than using an 16219 * image if networking bandwidth is low. Optional sigma specifies a blur radius 16220 * in radians to be applied to the scene before PMREM generation. Optional near 16221 * and far planes ensure the scene is rendered in its entirety (the cubeCamera 16222 * is placed at the origin). 16223 */ 16224 fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { 16225 16226 _oldTarget = this._renderer.getRenderTarget(); 16227 _oldActiveCubeFace = this._renderer.getActiveCubeFace(); 16228 _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); 16229 _oldXrEnabled = this._renderer.xr.enabled; 16230 16231 this._renderer.xr.enabled = false;
vendor: 5,454 bytes, lines 16232-16441
16232 16233 this._setSize( 256 ); 16234 16235 const cubeUVRenderTarget = this._allocateTargets(); 16236 cubeUVRenderTarget.depthBuffer = true; 16237 16238 this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); 16239 16240 if ( sigma > 0 ) { 16241 16242 this._blur( cubeUVRenderTarget, 0, 0, sigma ); 16243 16244 } 16245 16246 this._applyPMREM( cubeUVRenderTarget ); 16247 this._cleanup( cubeUVRenderTarget ); 16248 16249 return cubeUVRenderTarget; 16250 16251 } 16252 16253 /** 16254 * Generates a PMREM from an equirectangular texture, which can be either LDR 16255 * or HDR. The ideal input image size is 1k (1024 x 512), 16256 * as this matches best with the 256 x 256 cubemap output. 16257 * The smallest supported equirectangular image size is 64 x 32. 16258 */ 16259 fromEquirectangular( equirectangular, renderTarget = null ) { 16260 16261 return this._fromTexture( equirectangular, renderTarget ); 16262 16263 } 16264 16265 /** 16266 * Generates a PMREM from an cubemap texture, which can be either LDR 16267 * or HDR. The ideal input cube size is 256 x 256, 16268 * as this matches best with the 256 x 256 cubemap output. 16269 * The smallest supported cube size is 16 x 16. 16270 */ 16271 fromCubemap( cubemap, renderTarget = null ) { 16272 16273 return this._fromTexture( cubemap, renderTarget ); 16274 16275 } 16276 16277 /** 16278 * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during 16279 * your texture's network fetch for increased concurrency. 16280 */ 16281 compileCubemapShader() { 16282 16283 if ( this._cubemapMaterial === null ) { 16284 16285 this._cubemapMaterial = _getCubemapMaterial(); 16286 this._compileMaterial( this._cubemapMaterial ); 16287 16288 } 16289 16290 } 16291 16292 /** 16293 * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during 16294 * your texture's network fetch for increased concurrency. 16295 */ 16296 compileEquirectangularShader() { 16297 16298 if ( this._equirectMaterial === null ) { 16299 16300 this._equirectMaterial = _getEquirectMaterial(); 16301 this._compileMaterial( this._equirectMaterial ); 16302 16303 } 16304 16305 } 16306 16307 /** 16308 * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class, 16309 * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on 16310 * one of them will cause any others to also become unusable. 16311 */ 16312 dispose() { 16313 16314 this._dispose(); 16315 16316 if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose(); 16317 if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose(); 16318 16319 } 16320 16321 // private interface 16322 16323 _setSize( cubeSize ) { 16324 16325 this._lodMax = Math.floor( Math.log2( cubeSize ) ); 16326 this._cubeSize = Math.pow( 2, this._lodMax ); 16327 16328 } 16329 16330 _dispose() { 16331 16332 if ( this._blurMaterial !== null ) this._blurMaterial.dispose(); 16333 16334 if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose(); 16335 16336 for ( let i = 0; i < this._lodPlanes.length; i ++ ) { 16337 16338 this._lodPlanes[ i ].dispose(); 16339 16340 } 16341 16342 } 16343 16344 _cleanup( outputTarget ) { 16345 16346 this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel ); 16347 this._renderer.xr.enabled = _oldXrEnabled; 16348 16349 outputTarget.scissorTest = false; 16350 _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height ); 16351 16352 } 16353 16354 _fromTexture( texture, renderTarget ) { 16355 16356 if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) { 16357 16358 this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) ); 16359 16360 } else { // Equirectangular 16361 16362 this._setSize( texture.image.width / 4 ); 16363 16364 } 16365 16366 _oldTarget = this._renderer.getRenderTarget(); 16367 _oldActiveCubeFace = this._renderer.getActiveCubeFace(); 16368 _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); 16369 _oldXrEnabled = this._renderer.xr.enabled; 16370 16371 this._renderer.xr.enabled = false; 16372 16373 const cubeUVRenderTarget = renderTarget || this._allocateTargets(); 16374 this._textureToCubeUV( texture, cubeUVRenderTarget ); 16375 this._applyPMREM( cubeUVRenderTarget ); 16376 this._cleanup( cubeUVRenderTarget ); 16377 16378 return cubeUVRenderTarget; 16379 16380 } 16381 16382 _allocateTargets() { 16383 16384 const width = 3 * Math.max( this._cubeSize, 16 * 7 ); 16385 const height = 4 * this._cubeSize; 16386 16387 const params = { 16388 magFilter: LinearFilter, 16389 minFilter: LinearFilter, 16390 generateMipmaps: false, 16391 type: HalfFloatType, 16392 format: RGBAFormat, 16393 colorSpace: LinearSRGBColorSpace, 16394 depthBuffer: false 16395 }; 16396 16397 const cubeUVRenderTarget = _createRenderTarget( width, height, params ); 16398 16399 if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) { 16400 16401 if ( this._pingPongRenderTarget !== null ) { 16402 16403 this._dispose(); 16404 16405 } 16406 16407 this._pingPongRenderTarget = _createRenderTarget( width, height, params ); 16408 16409 const { _lodMax } = this; 16410 ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) ); 16411 16412 this._blurMaterial = _getBlurShader( _lodMax, width, height ); 16413 16414 } 16415 16416 return cubeUVRenderTarget; 16417 16418 } 16419 16420 _compileMaterial( material ) { 16421 16422 const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material ); 16423 this._renderer.compile( tmpMesh, _flatCamera ); 16424 16425 } 16426 16427 _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) { 16428 16429 const fov = 90; 16430 const aspect = 1; 16431 const cubeCamera = new PerspectiveCamera( fov, aspect, near, far ); 16432 const upSign = [ 1, - 1, 1, 1, 1, 1 ]; 16433 const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ]; 16434 const renderer = this._renderer; 16435 16436 const originalAutoClear = renderer.autoClear; 16437 const toneMapping = renderer.toneMapping; 16438 renderer.getClearColor( _clearColor ); 16439 16440 renderer.toneMapping = NoToneMapping; 16441 renderer.autoClear = false;
vendor: 8,445 bytes, lines 16442-16797
16442 16443 const backgroundMaterial = new MeshBasicMaterial( { 16444 name: 'PMREM.Background', 16445 side: BackSide, 16446 depthWrite: false, 16447 depthTest: false, 16448 } ); 16449 16450 const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial ); 16451 16452 let useSolidColor = false; 16453 const background = scene.background; 16454 16455 if ( background ) { 16456 16457 if ( background.isColor ) { 16458 16459 backgroundMaterial.color.copy( background ); 16460 scene.background = null; 16461 useSolidColor = true; 16462 16463 } 16464 16465 } else { 16466 16467 backgroundMaterial.color.copy( _clearColor ); 16468 useSolidColor = true; 16469 16470 } 16471 16472 for ( let i = 0; i < 6; i ++ ) { 16473 16474 const col = i % 3; 16475 16476 if ( col === 0 ) { 16477 16478 cubeCamera.up.set( 0, upSign[ i ], 0 ); 16479 cubeCamera.lookAt( forwardSign[ i ], 0, 0 ); 16480 16481 } else if ( col === 1 ) { 16482 16483 cubeCamera.up.set( 0, 0, upSign[ i ] ); 16484 cubeCamera.lookAt( 0, forwardSign[ i ], 0 ); 16485 16486 } else { 16487 16488 cubeCamera.up.set( 0, upSign[ i ], 0 ); 16489 cubeCamera.lookAt( 0, 0, forwardSign[ i ] ); 16490 16491 } 16492 16493 const size = this._cubeSize; 16494 16495 _setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size ); 16496 16497 renderer.setRenderTarget( cubeUVRenderTarget ); 16498 16499 if ( useSolidColor ) { 16500 16501 renderer.render( backgroundBox, cubeCamera ); 16502 16503 } 16504 16505 renderer.render( scene, cubeCamera ); 16506 16507 } 16508 16509 backgroundBox.geometry.dispose(); 16510 backgroundBox.material.dispose(); 16511 16512 renderer.toneMapping = toneMapping; 16513 renderer.autoClear = originalAutoClear; 16514 scene.background = background; 16515 16516 } 16517 16518 _textureToCubeUV( texture, cubeUVRenderTarget ) { 16519 16520 const renderer = this._renderer; 16521 16522 const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ); 16523 16524 if ( isCubeTexture ) { 16525 16526 if ( this._cubemapMaterial === null ) { 16527 16528 this._cubemapMaterial = _getCubemapMaterial(); 16529 16530 } 16531 16532 this._cubemapMaterial.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? - 1 : 1; 16533 16534 } else { 16535 16536 if ( this._equirectMaterial === null ) { 16537 16538 this._equirectMaterial = _getEquirectMaterial(); 16539 16540 } 16541 16542 } 16543 16544 const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; 16545 const mesh = new Mesh( this._lodPlanes[ 0 ], material ); 16546 16547 const uniforms = material.uniforms; 16548 16549 uniforms[ 'envMap' ].value = texture; 16550 16551 const size = this._cubeSize; 16552 16553 _setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size ); 16554 16555 renderer.setRenderTarget( cubeUVRenderTarget ); 16556 renderer.render( mesh, _flatCamera ); 16557 16558 } 16559 16560 _applyPMREM( cubeUVRenderTarget ) { 16561 16562 const renderer = this._renderer; 16563 const autoClear = renderer.autoClear; 16564 renderer.autoClear = false; 16565 16566 for ( let i = 1; i < this._lodPlanes.length; i ++ ) { 16567 16568 const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); 16569 16570 const poleAxis = _axisDirections[ ( i - 1 ) % _axisDirections.length ]; 16571 16572 this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); 16573 16574 } 16575 16576 renderer.autoClear = autoClear; 16577 16578 } 16579 16580 /** 16581 * This is a two-pass Gaussian blur for a cubemap. Normally this is done 16582 * vertically and horizontally, but this breaks down on a cube. Here we apply 16583 * the blur latitudinally (around the poles), and then longitudinally (towards 16584 * the poles) to approximate the orthogonally-separable blur. It is least 16585 * accurate at the poles, but still does a decent job. 16586 */ 16587 _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) { 16588 16589 const pingPongRenderTarget = this._pingPongRenderTarget; 16590 16591 this._halfBlur( 16592 cubeUVRenderTarget, 16593 pingPongRenderTarget, 16594 lodIn, 16595 lodOut, 16596 sigma, 16597 'latitudinal', 16598 poleAxis ); 16599 16600 this._halfBlur( 16601 pingPongRenderTarget, 16602 cubeUVRenderTarget, 16603 lodOut, 16604 lodOut, 16605 sigma, 16606 'longitudinal', 16607 poleAxis ); 16608 16609 } 16610 16611 _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) { 16612 16613 const renderer = this._renderer; 16614 const blurMaterial = this._blurMaterial; 16615 16616 if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { 16617 16618 console.error( 16619 'blur direction must be either latitudinal or longitudinal!' ); 16620 16621 } 16622 16623 // Number of standard deviations at which to cut off the discrete approximation. 16624 const STANDARD_DEVIATIONS = 3; 16625 16626 const blurMesh = new Mesh( this._lodPlanes[ lodOut ], blurMaterial ); 16627 const blurUniforms = blurMaterial.uniforms; 16628 16629 const pixels = this._sizeLods[ lodIn ] - 1; 16630 const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 ); 16631 const sigmaPixels = sigmaRadians / radiansPerPixel; 16632 const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES; 16633 16634 if ( samples > MAX_SAMPLES ) { 16635 16636 console.warn( `sigmaRadians, ${ 16637 sigmaRadians}, is too large and will clip, as it requested ${ 16638 samples} samples when the maximum is set to ${MAX_SAMPLES}` ); 16639 16640 } 16641 16642 const weights = []; 16643 let sum = 0; 16644 16645 for ( let i = 0; i < MAX_SAMPLES; ++ i ) { 16646 16647 const x = i / sigmaPixels; 16648 const weight = Math.exp( - x * x / 2 ); 16649 weights.push( weight ); 16650 16651 if ( i === 0 ) { 16652 16653 sum += weight; 16654 16655 } else if ( i < samples ) { 16656 16657 sum += 2 * weight; 16658 16659 } 16660 16661 } 16662 16663 for ( let i = 0; i < weights.length; i ++ ) { 16664 16665 weights[ i ] = weights[ i ] / sum; 16666 16667 } 16668 16669 blurUniforms[ 'envMap' ].value = targetIn.texture; 16670 blurUniforms[ 'samples' ].value = samples; 16671 blurUniforms[ 'weights' ].value = weights; 16672 blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal'; 16673 16674 if ( poleAxis ) { 16675 16676 blurUniforms[ 'poleAxis' ].value = poleAxis; 16677 16678 } 16679 16680 const { _lodMax } = this; 16681 blurUniforms[ 'dTheta' ].value = radiansPerPixel; 16682 blurUniforms[ 'mipInt' ].value = _lodMax - lodIn; 16683 16684 const outputSize = this._sizeLods[ lodOut ]; 16685 const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); 16686 const y = 4 * ( this._cubeSize - outputSize ); 16687 16688 _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize ); 16689 renderer.setRenderTarget( targetOut ); 16690 renderer.render( blurMesh, _flatCamera ); 16691 16692 } 16693 16694} 16695 16696 16697 16698function _createPlanes( lodMax ) { 16699 16700 const lodPlanes = []; 16701 const sizeLods = []; 16702 const sigmas = []; 16703 16704 let lod = lodMax; 16705 16706 const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length; 16707 16708 for ( let i = 0; i < totalLods; i ++ ) { 16709 16710 const sizeLod = Math.pow( 2, lod ); 16711 sizeLods.push( sizeLod ); 16712 let sigma = 1.0 / sizeLod; 16713 16714 if ( i > lodMax - LOD_MIN ) { 16715 16716 sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ]; 16717 16718 } else if ( i === 0 ) { 16719 16720 sigma = 0; 16721 16722 } 16723 16724 sigmas.push( sigma ); 16725 16726 const texelSize = 1.0 / ( sizeLod - 2 ); 16727 const min = - texelSize; 16728 const max = 1 + texelSize; 16729 const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ]; 16730 16731 const cubeFaces = 6; 16732 const vertices = 6; 16733 const positionSize = 3; 16734 const uvSize = 2; 16735 const faceIndexSize = 1; 16736 16737 const position = new Float32Array( positionSize * vertices * cubeFaces ); 16738 const uv = new Float32Array( uvSize * vertices * cubeFaces ); 16739 const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces ); 16740 16741 for ( let face = 0; face < cubeFaces; face ++ ) { 16742 16743 const x = ( face % 3 ) * 2 / 3 - 1; 16744 const y = face > 2 ? 0 : - 1; 16745 const coordinates = [ 16746 x, y, 0, 16747 x + 2 / 3, y, 0, 16748 x + 2 / 3, y + 1, 0, 16749 x, y, 0, 16750 x + 2 / 3, y + 1, 0, 16751 x, y + 1, 0 16752 ]; 16753 position.set( coordinates, positionSize * vertices * face ); 16754 uv.set( uv1, uvSize * vertices * face ); 16755 const fill = [ face, face, face, face, face, face ]; 16756 faceIndex.set( fill, faceIndexSize * vertices * face ); 16757 16758 } 16759 16760 const planes = new BufferGeometry(); 16761 planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) ); 16762 planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) ); 16763 planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) ); 16764 lodPlanes.push( planes ); 16765 16766 if ( lod > LOD_MIN ) { 16767 16768 lod --; 16769 16770 } 16771 16772 } 16773 16774 return { lodPlanes, sizeLods, sigmas }; 16775 16776} 16777 16778function _createRenderTarget( width, height, params ) { 16779 16780 const cubeUVRenderTarget = new WebGLRenderTarget( width, height, params ); 16781 cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping; 16782 cubeUVRenderTarget.texture.name = 'PMREM.cubeUv'; 16783 cubeUVRenderTarget.scissorTest = true; 16784 return cubeUVRenderTarget; 16785 16786} 16787 16788function _setViewport( target, x, y, width, height ) { 16789 16790 target.viewport.set( x, y, width, height ); 16791 target.scissor.set( x, y, width, height ); 16792 16793} 16794 16795function _getBlurShader( lodMax, width, height ) { 16796 16797 const weights = new Float32Array( MAX_SAMPLES );
vendor: 4,417 bytes, lines 16798-17036
16798 const poleAxis = new Vector3( 0, 1, 0 ); 16799 const shaderMaterial = new ShaderMaterial( { 16800 16801 name: 'SphericalGaussianBlur', 16802 16803 defines: { 16804 'n': MAX_SAMPLES, 16805 'CUBEUV_TEXEL_WIDTH': 1.0 / width, 16806 'CUBEUV_TEXEL_HEIGHT': 1.0 / height, 16807 'CUBEUV_MAX_MIP': `${lodMax}.0`, 16808 }, 16809 16810 uniforms: { 16811 'envMap': { value: null }, 16812 'samples': { value: 1 }, 16813 'weights': { value: weights }, 16814 'latitudinal': { value: false }, 16815 'dTheta': { value: 0 }, 16816 'mipInt': { value: 0 }, 16817 'poleAxis': { value: poleAxis } 16818 }, 16819 16820 vertexShader: _getCommonVertexShader(), 16821 16822 fragmentShader: /* glsl */` 16823 16824 precision mediump float; 16825 precision mediump int; 16826 16827 varying vec3 vOutputDirection; 16828 16829 uniform sampler2D envMap; 16830 uniform int samples; 16831 uniform float weights[ n ]; 16832 uniform bool latitudinal; 16833 uniform float dTheta; 16834 uniform float mipInt; 16835 uniform vec3 poleAxis; 16836 16837 #define ENVMAP_TYPE_CUBE_UV 16838 #include <cube_uv_reflection_fragment> 16839 16840 vec3 getSample( float theta, vec3 axis ) { 16841 16842 float cosTheta = cos( theta ); 16843 // Rodrigues' axis-angle rotation 16844 vec3 sampleDirection = vOutputDirection * cosTheta 16845 + cross( axis, vOutputDirection ) * sin( theta ) 16846 + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta ); 16847 16848 return bilinearCubeUV( envMap, sampleDirection, mipInt ); 16849 16850 } 16851 16852 void main() { 16853 16854 vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection ); 16855 16856 if ( all( equal( axis, vec3( 0.0 ) ) ) ) { 16857 16858 axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x ); 16859 16860 } 16861 16862 axis = normalize( axis ); 16863 16864 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); 16865 gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis ); 16866 16867 for ( int i = 1; i < n; i++ ) { 16868 16869 if ( i >= samples ) { 16870 16871 break; 16872 16873 } 16874 16875 float theta = dTheta * float( i ); 16876 gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis ); 16877 gl_FragColor.rgb += weights[ i ] * getSample( theta, axis ); 16878 16879 } 16880 16881 } 16882 `, 16883 16884 blending: NoBlending, 16885 depthTest: false, 16886 depthWrite: false 16887 16888 } ); 16889 16890 return shaderMaterial; 16891 16892} 16893 16894function _getEquirectMaterial() { 16895 16896 return new ShaderMaterial( { 16897 16898 name: 'EquirectangularToCubeUV', 16899 16900 uniforms: { 16901 'envMap': { value: null } 16902 }, 16903 16904 vertexShader: _getCommonVertexShader(), 16905 16906 fragmentShader: /* glsl */` 16907 16908 precision mediump float; 16909 precision mediump int; 16910 16911 varying vec3 vOutputDirection; 16912 16913 uniform sampler2D envMap; 16914 16915 #include <common> 16916 16917 void main() { 16918 16919 vec3 outputDirection = normalize( vOutputDirection ); 16920 vec2 uv = equirectUv( outputDirection ); 16921 16922 gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); 16923 16924 } 16925 `, 16926 16927 blending: NoBlending, 16928 depthTest: false, 16929 depthWrite: false 16930 16931 } ); 16932 16933} 16934 16935function _getCubemapMaterial() { 16936 16937 return new ShaderMaterial( { 16938 16939 name: 'CubemapToCubeUV', 16940 16941 uniforms: { 16942 'envMap': { value: null }, 16943 'flipEnvMap': { value: - 1 } 16944 }, 16945 16946 vertexShader: _getCommonVertexShader(), 16947 16948 fragmentShader: /* glsl */` 16949 16950 precision mediump float; 16951 precision mediump int; 16952 16953 uniform float flipEnvMap; 16954 16955 varying vec3 vOutputDirection; 16956 16957 uniform samplerCube envMap; 16958 16959 void main() { 16960 16961 gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); 16962 16963 } 16964 `, 16965 16966 blending: NoBlending, 16967 depthTest: false, 16968 depthWrite: false 16969 16970 } ); 16971 16972} 16973 16974function _getCommonVertexShader() { 16975 16976 return /* glsl */` 16977 16978 precision mediump float; 16979 precision mediump int; 16980 16981 attribute float faceIndex; 16982 16983 varying vec3 vOutputDirection; 16984 16985 // RH coordinate system; PMREM face-indexing convention 16986 vec3 getDirection( vec2 uv, float face ) { 16987 16988 uv = 2.0 * uv - 1.0; 16989 16990 vec3 direction = vec3( uv, 1.0 ); 16991 16992 if ( face == 0.0 ) { 16993 16994 direction = direction.zyx; // ( 1, v, u ) pos x 16995 16996 } else if ( face == 1.0 ) { 16997 16998 direction = direction.xzy; 16999 direction.xz *= -1.0; // ( -u, 1, -v ) pos y 17000 17001 } else if ( face == 2.0 ) { 17002 17003 direction.x *= -1.0; // ( -u, v, 1 ) pos z 17004 17005 } else if ( face == 3.0 ) { 17006 17007 direction = direction.zyx; 17008 direction.xz *= -1.0; // ( -1, v, -u ) neg x 17009 17010 } else if ( face == 4.0 ) { 17011 17012 direction = direction.xzy; 17013 direction.xy *= -1.0; // ( -u, -1, v ) neg y 17014 17015 } else if ( face == 5.0 ) { 17016 17017 direction.z *= -1.0; // ( u, v, -1 ) neg z 17018 17019 } 17020 17021 return direction; 17022 17023 } 17024 17025 void main() { 17026 17027 vOutputDirection = getDirection( uv, faceIndex ); 17028 gl_Position = vec4( position, 1.0 ); 17029 17030 } 17031 `; 17032 17033} 17034 17035function WebGLCubeUVMaps( renderer ) { 17036
vendor: 12,094 bytes, lines 17037-17637
17037 let cubeUVmaps = new WeakMap(); 17038 17039 let pmremGenerator = null; 17040 17041 function get( texture ) { 17042 17043 if ( texture && texture.isTexture ) { 17044 17045 const mapping = texture.mapping; 17046 17047 const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ); 17048 const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); 17049 17050 // equirect/cube map to cubeUV conversion 17051 17052 if ( isEquirectMap || isCubeMap ) { 17053 17054 let renderTarget = cubeUVmaps.get( texture ); 17055 17056 const currentPMREMVersion = renderTarget !== undefined ? renderTarget.texture.pmremVersion : 0; 17057 17058 if ( texture.isRenderTargetTexture && texture.pmremVersion !== currentPMREMVersion ) { 17059 17060 if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); 17061 17062 renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget ); 17063 renderTarget.texture.pmremVersion = texture.pmremVersion; 17064 17065 cubeUVmaps.set( texture, renderTarget ); 17066 17067 return renderTarget.texture; 17068 17069 } else { 17070 17071 if ( renderTarget !== undefined ) { 17072 17073 return renderTarget.texture; 17074 17075 } else { 17076 17077 const image = texture.image; 17078 17079 if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) { 17080 17081 if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); 17082 17083 renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture ); 17084 renderTarget.texture.pmremVersion = texture.pmremVersion; 17085 17086 cubeUVmaps.set( texture, renderTarget ); 17087 17088 texture.addEventListener( 'dispose', onTextureDispose ); 17089 17090 return renderTarget.texture; 17091 17092 } else { 17093 17094 // image not yet ready. try the conversion next frame 17095 17096 return null; 17097 17098 } 17099 17100 } 17101 17102 } 17103 17104 } 17105 17106 } 17107 17108 return texture; 17109 17110 } 17111 17112 function isCubeTextureComplete( image ) { 17113 17114 let count = 0; 17115 const length = 6; 17116 17117 for ( let i = 0; i < length; i ++ ) { 17118 17119 if ( image[ i ] !== undefined ) count ++; 17120 17121 } 17122 17123 return count === length; 17124 17125 17126 } 17127 17128 function onTextureDispose( event ) { 17129 17130 const texture = event.target; 17131 17132 texture.removeEventListener( 'dispose', onTextureDispose ); 17133 17134 const cubemapUV = cubeUVmaps.get( texture ); 17135 17136 if ( cubemapUV !== undefined ) { 17137 17138 cubeUVmaps.delete( texture ); 17139 cubemapUV.dispose(); 17140 17141 } 17142 17143 } 17144 17145 function dispose() { 17146 17147 cubeUVmaps = new WeakMap(); 17148 17149 if ( pmremGenerator !== null ) { 17150 17151 pmremGenerator.dispose(); 17152 pmremGenerator = null; 17153 17154 } 17155 17156 } 17157 17158 return { 17159 get: get, 17160 dispose: dispose 17161 }; 17162 17163} 17164 17165function WebGLExtensions( gl ) { 17166 17167 const extensions = {}; 17168 17169 function getExtension( name ) { 17170 17171 if ( extensions[ name ] !== undefined ) { 17172 17173 return extensions[ name ]; 17174 17175 } 17176 17177 let extension; 17178 17179 switch ( name ) { 17180 17181 case 'WEBGL_depth_texture': 17182 extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' ); 17183 break; 17184 17185 case 'EXT_texture_filter_anisotropic': 17186 extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' ); 17187 break; 17188 17189 case 'WEBGL_compressed_texture_s3tc': 17190 extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' ); 17191 break; 17192 17193 case 'WEBGL_compressed_texture_pvrtc': 17194 extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' ); 17195 break; 17196 17197 default: 17198 extension = gl.getExtension( name ); 17199 17200 } 17201 17202 extensions[ name ] = extension; 17203 17204 return extension; 17205 17206 } 17207 17208 return { 17209 17210 has: function ( name ) { 17211 17212 return getExtension( name ) !== null; 17213 17214 }, 17215 17216 init: function () { 17217 17218 getExtension( 'EXT_color_buffer_float' ); 17219 getExtension( 'WEBGL_clip_cull_distance' ); 17220 getExtension( 'OES_texture_float_linear' ); 17221 getExtension( 'EXT_color_buffer_half_float' ); 17222 getExtension( 'WEBGL_multisampled_render_to_texture' ); 17223 getExtension( 'WEBGL_render_shared_exponent' ); 17224 17225 }, 17226 17227 get: function ( name ) { 17228 17229 const extension = getExtension( name ); 17230 17231 if ( extension === null ) { 17232 17233 console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); 17234 17235 } 17236 17237 return extension; 17238 17239 } 17240 17241 }; 17242 17243} 17244 17245function WebGLGeometries( gl, attributes, info, bindingStates ) { 17246 17247 const geometries = {}; 17248 const wireframeAttributes = new WeakMap(); 17249 17250 function onGeometryDispose( event ) { 17251 17252 const geometry = event.target; 17253 17254 if ( geometry.index !== null ) { 17255 17256 attributes.remove( geometry.index ); 17257 17258 } 17259 17260 for ( const name in geometry.attributes ) { 17261 17262 attributes.remove( geometry.attributes[ name ] ); 17263 17264 } 17265 17266 for ( const name in geometry.morphAttributes ) { 17267 17268 const array = geometry.morphAttributes[ name ]; 17269 17270 for ( let i = 0, l = array.length; i < l; i ++ ) { 17271 17272 attributes.remove( array[ i ] ); 17273 17274 } 17275 17276 } 17277 17278 geometry.removeEventListener( 'dispose', onGeometryDispose ); 17279 17280 delete geometries[ geometry.id ]; 17281 17282 const attribute = wireframeAttributes.get( geometry ); 17283 17284 if ( attribute ) { 17285 17286 attributes.remove( attribute ); 17287 wireframeAttributes.delete( geometry ); 17288 17289 } 17290 17291 bindingStates.releaseStatesOfGeometry( geometry ); 17292 17293 if ( geometry.isInstancedBufferGeometry === true ) { 17294 17295 delete geometry._maxInstanceCount; 17296 17297 } 17298 17299 // 17300 17301 info.memory.geometries --; 17302 17303 } 17304 17305 function get( object, geometry ) { 17306 17307 if ( geometries[ geometry.id ] === true ) return geometry; 17308 17309 geometry.addEventListener( 'dispose', onGeometryDispose ); 17310 17311 geometries[ geometry.id ] = true; 17312 17313 info.memory.geometries ++; 17314 17315 return geometry; 17316 17317 } 17318 17319 function update( geometry ) { 17320 17321 const geometryAttributes = geometry.attributes; 17322 17323 // Updating index buffer in VAO now. See WebGLBindingStates. 17324 17325 for ( const name in geometryAttributes ) { 17326 17327 attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER ); 17328 17329 } 17330 17331 // morph targets 17332 17333 const morphAttributes = geometry.morphAttributes; 17334 17335 for ( const name in morphAttributes ) { 17336 17337 const array = morphAttributes[ name ]; 17338 17339 for ( let i = 0, l = array.length; i < l; i ++ ) { 17340 17341 attributes.update( array[ i ], gl.ARRAY_BUFFER ); 17342 17343 } 17344 17345 } 17346 17347 } 17348 17349 function updateWireframeAttribute( geometry ) { 17350 17351 const indices = []; 17352 17353 const geometryIndex = geometry.index; 17354 const geometryPosition = geometry.attributes.position; 17355 let version = 0; 17356 17357 if ( geometryIndex !== null ) { 17358 17359 const array = geometryIndex.array; 17360 version = geometryIndex.version; 17361 17362 for ( let i = 0, l = array.length; i < l; i += 3 ) { 17363 17364 const a = array[ i + 0 ]; 17365 const b = array[ i + 1 ]; 17366 const c = array[ i + 2 ]; 17367 17368 indices.push( a, b, b, c, c, a ); 17369 17370 } 17371 17372 } else if ( geometryPosition !== undefined ) { 17373 17374 const array = geometryPosition.array; 17375 version = geometryPosition.version; 17376 17377 for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { 17378 17379 const a = i + 0; 17380 const b = i + 1; 17381 const c = i + 2; 17382 17383 indices.push( a, b, b, c, c, a ); 17384 17385 } 17386 17387 } else { 17388 17389 return; 17390 17391 } 17392 17393 const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); 17394 attribute.version = version; 17395 17396 // Updating index buffer in VAO now. See WebGLBindingStates 17397 17398 // 17399 17400 const previousAttribute = wireframeAttributes.get( geometry ); 17401 17402 if ( previousAttribute ) attributes.remove( previousAttribute ); 17403 17404 // 17405 17406 wireframeAttributes.set( geometry, attribute ); 17407 17408 } 17409 17410 function getWireframeAttribute( geometry ) { 17411 17412 const currentAttribute = wireframeAttributes.get( geometry ); 17413 17414 if ( currentAttribute ) { 17415 17416 const geometryIndex = geometry.index; 17417 17418 if ( geometryIndex !== null ) { 17419 17420 // if the attribute is obsolete, create a new one 17421 17422 if ( currentAttribute.version < geometryIndex.version ) { 17423 17424 updateWireframeAttribute( geometry ); 17425 17426 } 17427 17428 } 17429 17430 } else { 17431 17432 updateWireframeAttribute( geometry ); 17433 17434 } 17435 17436 return wireframeAttributes.get( geometry ); 17437 17438 } 17439 17440 return { 17441 17442 get: get, 17443 update: update, 17444 17445 getWireframeAttribute: getWireframeAttribute 17446 17447 }; 17448 17449} 17450 17451function WebGLIndexedBufferRenderer( gl, extensions, info ) { 17452 17453 let mode; 17454 17455 function setMode( value ) { 17456 17457 mode = value; 17458 17459 } 17460 17461 let type, bytesPerElement; 17462 17463 function setIndex( value ) { 17464 17465 type = value.type; 17466 bytesPerElement = value.bytesPerElement; 17467 17468 } 17469 17470 function render( start, count ) { 17471 17472 gl.drawElements( mode, count, type, start * bytesPerElement ); 17473 17474 info.update( count, mode, 1 ); 17475 17476 } 17477 17478 function renderInstances( start, count, primcount ) { 17479 17480 if ( primcount === 0 ) return; 17481 17482 gl.drawElementsInstanced( mode, count, type, start * bytesPerElement, primcount ); 17483 17484 info.update( count, mode, primcount ); 17485 17486 } 17487 17488 function renderMultiDraw( starts, counts, drawCount ) { 17489 17490 if ( drawCount === 0 ) return; 17491 17492 const extension = extensions.get( 'WEBGL_multi_draw' ); 17493 17494 if ( extension === null ) { 17495 17496 for ( let i = 0; i < drawCount; i ++ ) { 17497 17498 this.render( starts[ i ] / bytesPerElement, counts[ i ] ); 17499 17500 } 17501 17502 } else { 17503 17504 extension.multiDrawElementsWEBGL( mode, counts, 0, type, starts, 0, drawCount ); 17505 17506 let elementCount = 0; 17507 for ( let i = 0; i < drawCount; i ++ ) { 17508 17509 elementCount += counts[ i ]; 17510 17511 } 17512 17513 info.update( elementCount, mode, 1 ); 17514 17515 } 17516 17517 } 17518 17519 // 17520 17521 this.setMode = setMode; 17522 this.setIndex = setIndex; 17523 this.render = render; 17524 this.renderInstances = renderInstances; 17525 this.renderMultiDraw = renderMultiDraw; 17526 17527} 17528 17529function WebGLInfo( gl ) { 17530 17531 const memory = { 17532 geometries: 0, 17533 textures: 0 17534 }; 17535 17536 const render = { 17537 frame: 0, 17538 calls: 0, 17539 triangles: 0, 17540 points: 0, 17541 lines: 0 17542 }; 17543 17544 function update( count, mode, instanceCount ) { 17545 17546 render.calls ++; 17547 17548 switch ( mode ) { 17549 17550 case gl.TRIANGLES: 17551 render.triangles += instanceCount * ( count / 3 ); 17552 break; 17553 17554 case gl.LINES: 17555 render.lines += instanceCount * ( count / 2 ); 17556 break; 17557 17558 case gl.LINE_STRIP: 17559 render.lines += instanceCount * ( count - 1 ); 17560 break; 17561 17562 case gl.LINE_LOOP: 17563 render.lines += instanceCount * count; 17564 break; 17565 17566 case gl.POINTS: 17567 render.points += instanceCount * count; 17568 break; 17569 17570 default: 17571 console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode ); 17572 break; 17573 17574 } 17575 17576 } 17577 17578 function reset() { 17579 17580 render.calls = 0; 17581 render.triangles = 0; 17582 render.points = 0; 17583 render.lines = 0; 17584 17585 } 17586 17587 return { 17588 memory: memory, 17589 render: render, 17590 programs: null, 17591 autoReset: true, 17592 reset: reset, 17593 update: update 17594 }; 17595 17596} 17597 17598function WebGLMorphtargets( gl, capabilities, textures ) { 17599 17600 const morphTextures = new WeakMap(); 17601 const morph = new Vector4(); 17602 17603 function update( object, geometry, program ) { 17604 17605 const objectInfluences = object.morphTargetInfluences; 17606 17607 // instead of using attributes, the WebGL 2 code path encodes morph targets 17608 // into an array of data textures. Each layer represents a single morph target. 17609 17610 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; 17611 const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; 17612 17613 let entry = morphTextures.get( geometry ); 17614 17615 if ( entry === undefined || entry.count !== morphTargetsCount ) { 17616 17617 if ( entry !== undefined ) entry.texture.dispose(); 17618 17619 const hasMorphPosition = geometry.morphAttributes.position !== undefined; 17620 const hasMorphNormals = geometry.morphAttributes.normal !== undefined; 17621 const hasMorphColors = geometry.morphAttributes.color !== undefined; 17622 17623 const morphTargets = geometry.morphAttributes.position || []; 17624 const morphNormals = geometry.morphAttributes.normal || []; 17625 const morphColors = geometry.morphAttributes.color || []; 17626 17627 let vertexDataCount = 0; 17628 17629 if ( hasMorphPosition === true ) vertexDataCount = 1; 17630 if ( hasMorphNormals === true ) vertexDataCount = 2; 17631 if ( hasMorphColors === true ) vertexDataCount = 3; 17632 17633 let width = geometry.attributes.position.count * vertexDataCount; 17634 let height = 1; 17635 17636 if ( width > capabilities.maxTextureSize ) { 17637
vendor: 2,781 bytes, lines 17638-17748
17638 height = Math.ceil( width / capabilities.maxTextureSize ); 17639 width = capabilities.maxTextureSize; 17640 17641 } 17642 17643 const buffer = new Float32Array( width * height * 4 * morphTargetsCount ); 17644 17645 const texture = new DataArrayTexture( buffer, width, height, morphTargetsCount ); 17646 texture.type = FloatType; 17647 texture.needsUpdate = true; 17648 17649 // fill buffer 17650 17651 const vertexDataStride = vertexDataCount * 4; 17652 17653 for ( let i = 0; i < morphTargetsCount; i ++ ) { 17654 17655 const morphTarget = morphTargets[ i ]; 17656 const morphNormal = morphNormals[ i ]; 17657 const morphColor = morphColors[ i ]; 17658 17659 const offset = width * height * 4 * i; 17660 17661 for ( let j = 0; j < morphTarget.count; j ++ ) { 17662 17663 const stride = j * vertexDataStride; 17664 17665 if ( hasMorphPosition === true ) { 17666 17667 morph.fromBufferAttribute( morphTarget, j ); 17668 17669 buffer[ offset + stride + 0 ] = morph.x; 17670 buffer[ offset + stride + 1 ] = morph.y; 17671 buffer[ offset + stride + 2 ] = morph.z; 17672 buffer[ offset + stride + 3 ] = 0; 17673 17674 } 17675 17676 if ( hasMorphNormals === true ) { 17677 17678 morph.fromBufferAttribute( morphNormal, j ); 17679 17680 buffer[ offset + stride + 4 ] = morph.x; 17681 buffer[ offset + stride + 5 ] = morph.y; 17682 buffer[ offset + stride + 6 ] = morph.z; 17683 buffer[ offset + stride + 7 ] = 0; 17684 17685 } 17686 17687 if ( hasMorphColors === true ) { 17688 17689 morph.fromBufferAttribute( morphColor, j ); 17690 17691 buffer[ offset + stride + 8 ] = morph.x; 17692 buffer[ offset + stride + 9 ] = morph.y; 17693 buffer[ offset + stride + 10 ] = morph.z; 17694 buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? morph.w : 1; 17695 17696 } 17697 17698 } 17699 17700 } 17701 17702 entry = { 17703 count: morphTargetsCount, 17704 texture: texture, 17705 size: new Vector2( width, height ) 17706 }; 17707 17708 morphTextures.set( geometry, entry ); 17709 17710 function disposeTexture() { 17711 17712 texture.dispose(); 17713 17714 morphTextures.delete( geometry ); 17715 17716 geometry.removeEventListener( 'dispose', disposeTexture ); 17717 17718 } 17719 17720 geometry.addEventListener( 'dispose', disposeTexture ); 17721 17722 } 17723 17724 // 17725 if ( object.isInstancedMesh === true && object.morphTexture !== null ) { 17726 17727 program.getUniforms().setValue( gl, 'morphTexture', object.morphTexture, textures ); 17728 17729 } else { 17730 17731 let morphInfluencesSum = 0; 17732 17733 for ( let i = 0; i < objectInfluences.length; i ++ ) { 17734 17735 morphInfluencesSum += objectInfluences[ i ]; 17736 17737 } 17738 17739 const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; 17740 17741 17742 program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence ); 17743 program.getUniforms().setValue( gl, 'morphTargetInfluences', objectInfluences ); 17744 17745 } 17746 17747 program.getUniforms().setValue( gl, 'morphTargetsTexture', entry.texture, textures ); 17748 program.getUniforms().setValue( gl, 'morphTargetsTextureSize', entry.size );
vendor: 26,597 bytes, lines 17748-19202
17748 17749 17750 } 17751 17752 return { 17753 17754 update: update 17755 17756 }; 17757 17758} 17759 17760function WebGLObjects( gl, geometries, attributes, info ) { 17761 17762 let updateMap = new WeakMap(); 17763 17764 function update( object ) { 17765 17766 const frame = info.render.frame; 17767 17768 const geometry = object.geometry; 17769 const buffergeometry = geometries.get( object, geometry ); 17770 17771 // Update once per frame 17772 17773 if ( updateMap.get( buffergeometry ) !== frame ) { 17774 17775 geometries.update( buffergeometry ); 17776 17777 updateMap.set( buffergeometry, frame ); 17778 17779 } 17780 17781 if ( object.isInstancedMesh ) { 17782 17783 if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) { 17784 17785 object.addEventListener( 'dispose', onInstancedMeshDispose ); 17786 17787 } 17788 17789 if ( updateMap.get( object ) !== frame ) { 17790 17791 attributes.update( object.instanceMatrix, gl.ARRAY_BUFFER ); 17792 17793 if ( object.instanceColor !== null ) { 17794 17795 attributes.update( object.instanceColor, gl.ARRAY_BUFFER ); 17796 17797 } 17798 17799 updateMap.set( object, frame ); 17800 17801 } 17802 17803 } 17804 17805 if ( object.isSkinnedMesh ) { 17806 17807 const skeleton = object.skeleton; 17808 17809 if ( updateMap.get( skeleton ) !== frame ) { 17810 17811 skeleton.update(); 17812 17813 updateMap.set( skeleton, frame ); 17814 17815 } 17816 17817 } 17818 17819 return buffergeometry; 17820 17821 } 17822 17823 function dispose() { 17824 17825 updateMap = new WeakMap(); 17826 17827 } 17828 17829 function onInstancedMeshDispose( event ) { 17830 17831 const instancedMesh = event.target; 17832 17833 instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose ); 17834 17835 attributes.remove( instancedMesh.instanceMatrix ); 17836 17837 if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor ); 17838 17839 } 17840 17841 return { 17842 17843 update: update, 17844 dispose: dispose 17845 17846 }; 17847 17848} 17849 17850class DepthTexture extends Texture { 17851 17852 constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) { 17853 17854 format = format !== undefined ? format : DepthFormat; 17855 17856 if ( format !== DepthFormat && format !== DepthStencilFormat ) { 17857 17858 throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); 17859 17860 } 17861 17862 if ( type === undefined && format === DepthFormat ) type = UnsignedIntType; 17863 if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type; 17864 17865 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 17866 17867 this.isDepthTexture = true; 17868 17869 this.image = { width: width, height: height }; 17870 17871 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; 17872 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; 17873 17874 this.flipY = false; 17875 this.generateMipmaps = false; 17876 17877 this.compareFunction = null; 17878 17879 } 17880 17881 17882 copy( source ) { 17883 17884 super.copy( source ); 17885 17886 this.compareFunction = source.compareFunction; 17887 17888 return this; 17889 17890 } 17891 17892 toJSON( meta ) { 17893 17894 const data = super.toJSON( meta ); 17895 17896 if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction; 17897 17898 return data; 17899 17900 } 17901 17902} 17903 17904/** 17905 * Uniforms of a program. 17906 * Those form a tree structure with a special top-level container for the root, 17907 * which you get by calling 'new WebGLUniforms( gl, program )'. 17908 * 17909 * 17910 * Properties of inner nodes including the top-level container: 17911 * 17912 * .seq - array of nested uniforms 17913 * .map - nested uniforms by name 17914 * 17915 * 17916 * Methods of all nodes except the top-level container: 17917 * 17918 * .setValue( gl, value, [textures] ) 17919 * 17920 * uploads a uniform value(s) 17921 * the 'textures' parameter is needed for sampler uniforms 17922 * 17923 * 17924 * Static methods of the top-level container (textures factorizations): 17925 * 17926 * .upload( gl, seq, values, textures ) 17927 * 17928 * sets uniforms in 'seq' to 'values[id].value' 17929 * 17930 * .seqWithValue( seq, values ) : filteredSeq 17931 * 17932 * filters 'seq' entries with corresponding entry in values 17933 * 17934 * 17935 * Methods of the top-level container (textures factorizations): 17936 * 17937 * .setValue( gl, name, value, textures ) 17938 * 17939 * sets uniform with name 'name' to 'value' 17940 * 17941 * .setOptional( gl, obj, prop ) 17942 * 17943 * like .set for an optional property of the object 17944 * 17945 */ 17946 17947 17948const emptyTexture = /*@__PURE__*/ new Texture(); 17949 17950const emptyShadowTexture = /*@__PURE__*/ new DepthTexture( 1, 1 ); 17951emptyShadowTexture.compareFunction = LessEqualCompare; 17952 17953const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture(); 17954const empty3dTexture = /*@__PURE__*/ new Data3DTexture(); 17955const emptyCubeTexture = /*@__PURE__*/ new CubeTexture(); 17956 17957// --- Utilities --- 17958 17959// Array Caches (provide typed arrays for temporary by size) 17960 17961const arrayCacheF32 = []; 17962const arrayCacheI32 = []; 17963 17964// Float32Array caches used for uploading Matrix uniforms 17965 17966const mat4array = new Float32Array( 16 ); 17967const mat3array = new Float32Array( 9 ); 17968const mat2array = new Float32Array( 4 ); 17969 17970// Flattening for arrays of vectors and matrices 17971 17972function flatten( array, nBlocks, blockSize ) { 17973 17974 const firstElem = array[ 0 ]; 17975 17976 if ( firstElem <= 0 || firstElem > 0 ) return array; 17977 // unoptimized: ! isNaN( firstElem ) 17978 // see http://jacksondunstan.com/articles/983 17979 17980 const n = nBlocks * blockSize; 17981 let r = arrayCacheF32[ n ]; 17982 17983 if ( r === undefined ) { 17984 17985 r = new Float32Array( n ); 17986 arrayCacheF32[ n ] = r; 17987 17988 } 17989 17990 if ( nBlocks !== 0 ) { 17991 17992 firstElem.toArray( r, 0 ); 17993 17994 for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) { 17995 17996 offset += blockSize; 17997 array[ i ].toArray( r, offset ); 17998 17999 } 18000 18001 } 18002 18003 return r; 18004 18005} 18006 18007function arraysEqual( a, b ) { 18008 18009 if ( a.length !== b.length ) return false; 18010 18011 for ( let i = 0, l = a.length; i < l; i ++ ) { 18012 18013 if ( a[ i ] !== b[ i ] ) return false; 18014 18015 } 18016 18017 return true; 18018 18019} 18020 18021function copyArray( a, b ) { 18022 18023 for ( let i = 0, l = b.length; i < l; i ++ ) { 18024 18025 a[ i ] = b[ i ]; 18026 18027 } 18028 18029} 18030 18031// Texture unit allocation 18032 18033function allocTexUnits( textures, n ) { 18034 18035 let r = arrayCacheI32[ n ]; 18036 18037 if ( r === undefined ) { 18038 18039 r = new Int32Array( n ); 18040 arrayCacheI32[ n ] = r; 18041 18042 } 18043 18044 for ( let i = 0; i !== n; ++ i ) { 18045 18046 r[ i ] = textures.allocateTextureUnit(); 18047 18048 } 18049 18050 return r; 18051 18052} 18053 18054// --- Setters --- 18055 18056// Note: Defining these methods externally, because they come in a bunch 18057// and this way their names minify. 18058 18059// Single scalar 18060 18061function setValueV1f( gl, v ) { 18062 18063 const cache = this.cache; 18064 18065 if ( cache[ 0 ] === v ) return; 18066 18067 gl.uniform1f( this.addr, v ); 18068 18069 cache[ 0 ] = v; 18070 18071} 18072 18073// Single float vector (from flat array or THREE.VectorN) 18074 18075function setValueV2f( gl, v ) { 18076 18077 const cache = this.cache; 18078 18079 if ( v.x !== undefined ) { 18080 18081 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 18082 18083 gl.uniform2f( this.addr, v.x, v.y ); 18084 18085 cache[ 0 ] = v.x; 18086 cache[ 1 ] = v.y; 18087 18088 } 18089 18090 } else { 18091 18092 if ( arraysEqual( cache, v ) ) return; 18093 18094 gl.uniform2fv( this.addr, v ); 18095 18096 copyArray( cache, v ); 18097 18098 } 18099 18100} 18101 18102function setValueV3f( gl, v ) { 18103 18104 const cache = this.cache; 18105 18106 if ( v.x !== undefined ) { 18107 18108 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 18109 18110 gl.uniform3f( this.addr, v.x, v.y, v.z ); 18111 18112 cache[ 0 ] = v.x; 18113 cache[ 1 ] = v.y; 18114 cache[ 2 ] = v.z; 18115 18116 } 18117 18118 } else if ( v.r !== undefined ) { 18119 18120 if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) { 18121 18122 gl.uniform3f( this.addr, v.r, v.g, v.b ); 18123 18124 cache[ 0 ] = v.r; 18125 cache[ 1 ] = v.g; 18126 cache[ 2 ] = v.b; 18127 18128 } 18129 18130 } else { 18131 18132 if ( arraysEqual( cache, v ) ) return; 18133 18134 gl.uniform3fv( this.addr, v ); 18135 18136 copyArray( cache, v ); 18137 18138 } 18139 18140} 18141 18142function setValueV4f( gl, v ) { 18143 18144 const cache = this.cache; 18145 18146 if ( v.x !== undefined ) { 18147 18148 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 18149 18150 gl.uniform4f( this.addr, v.x, v.y, v.z, v.w ); 18151 18152 cache[ 0 ] = v.x; 18153 cache[ 1 ] = v.y; 18154 cache[ 2 ] = v.z; 18155 cache[ 3 ] = v.w; 18156 18157 } 18158 18159 } else { 18160 18161 if ( arraysEqual( cache, v ) ) return; 18162 18163 gl.uniform4fv( this.addr, v ); 18164 18165 copyArray( cache, v ); 18166 18167 } 18168 18169} 18170 18171// Single matrix (from flat array or THREE.MatrixN) 18172 18173function setValueM2( gl, v ) { 18174 18175 const cache = this.cache; 18176 const elements = v.elements; 18177 18178 if ( elements === undefined ) { 18179 18180 if ( arraysEqual( cache, v ) ) return; 18181 18182 gl.uniformMatrix2fv( this.addr, false, v ); 18183 18184 copyArray( cache, v ); 18185 18186 } else { 18187 18188 if ( arraysEqual( cache, elements ) ) return; 18189 18190 mat2array.set( elements ); 18191 18192 gl.uniformMatrix2fv( this.addr, false, mat2array ); 18193 18194 copyArray( cache, elements ); 18195 18196 } 18197 18198} 18199 18200function setValueM3( gl, v ) { 18201 18202 const cache = this.cache; 18203 const elements = v.elements; 18204 18205 if ( elements === undefined ) { 18206 18207 if ( arraysEqual( cache, v ) ) return; 18208 18209 gl.uniformMatrix3fv( this.addr, false, v ); 18210 18211 copyArray( cache, v ); 18212 18213 } else { 18214 18215 if ( arraysEqual( cache, elements ) ) return; 18216 18217 mat3array.set( elements ); 18218 18219 gl.uniformMatrix3fv( this.addr, false, mat3array ); 18220 18221 copyArray( cache, elements ); 18222 18223 } 18224 18225} 18226 18227function setValueM4( gl, v ) { 18228 18229 const cache = this.cache; 18230 const elements = v.elements; 18231 18232 if ( elements === undefined ) { 18233 18234 if ( arraysEqual( cache, v ) ) return; 18235 18236 gl.uniformMatrix4fv( this.addr, false, v ); 18237 18238 copyArray( cache, v ); 18239 18240 } else { 18241 18242 if ( arraysEqual( cache, elements ) ) return; 18243 18244 mat4array.set( elements ); 18245 18246 gl.uniformMatrix4fv( this.addr, false, mat4array ); 18247 18248 copyArray( cache, elements ); 18249 18250 } 18251 18252} 18253 18254// Single integer / boolean 18255 18256function setValueV1i( gl, v ) { 18257 18258 const cache = this.cache; 18259 18260 if ( cache[ 0 ] === v ) return; 18261 18262 gl.uniform1i( this.addr, v ); 18263 18264 cache[ 0 ] = v; 18265 18266} 18267 18268// Single integer / boolean vector (from flat array or THREE.VectorN) 18269 18270function setValueV2i( gl, v ) { 18271 18272 const cache = this.cache; 18273 18274 if ( v.x !== undefined ) { 18275 18276 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 18277 18278 gl.uniform2i( this.addr, v.x, v.y ); 18279 18280 cache[ 0 ] = v.x; 18281 cache[ 1 ] = v.y; 18282 18283 } 18284 18285 } else { 18286 18287 if ( arraysEqual( cache, v ) ) return; 18288 18289 gl.uniform2iv( this.addr, v ); 18290 18291 copyArray( cache, v ); 18292 18293 } 18294 18295} 18296 18297function setValueV3i( gl, v ) { 18298 18299 const cache = this.cache; 18300 18301 if ( v.x !== undefined ) { 18302 18303 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 18304 18305 gl.uniform3i( this.addr, v.x, v.y, v.z ); 18306 18307 cache[ 0 ] = v.x; 18308 cache[ 1 ] = v.y; 18309 cache[ 2 ] = v.z; 18310 18311 } 18312 18313 } else { 18314 18315 if ( arraysEqual( cache, v ) ) return; 18316 18317 gl.uniform3iv( this.addr, v ); 18318 18319 copyArray( cache, v ); 18320 18321 } 18322 18323} 18324 18325function setValueV4i( gl, v ) { 18326 18327 const cache = this.cache; 18328 18329 if ( v.x !== undefined ) { 18330 18331 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 18332 18333 gl.uniform4i( this.addr, v.x, v.y, v.z, v.w ); 18334 18335 cache[ 0 ] = v.x; 18336 cache[ 1 ] = v.y; 18337 cache[ 2 ] = v.z; 18338 cache[ 3 ] = v.w; 18339 18340 } 18341 18342 } else { 18343 18344 if ( arraysEqual( cache, v ) ) return; 18345 18346 gl.uniform4iv( this.addr, v ); 18347 18348 copyArray( cache, v ); 18349 18350 } 18351 18352} 18353 18354// Single unsigned integer 18355 18356function setValueV1ui( gl, v ) { 18357 18358 const cache = this.cache; 18359 18360 if ( cache[ 0 ] === v ) return; 18361 18362 gl.uniform1ui( this.addr, v ); 18363 18364 cache[ 0 ] = v; 18365 18366} 18367 18368// Single unsigned integer vector (from flat array or THREE.VectorN) 18369 18370function setValueV2ui( gl, v ) { 18371 18372 const cache = this.cache; 18373 18374 if ( v.x !== undefined ) { 18375 18376 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 18377 18378 gl.uniform2ui( this.addr, v.x, v.y ); 18379 18380 cache[ 0 ] = v.x; 18381 cache[ 1 ] = v.y; 18382 18383 } 18384 18385 } else { 18386 18387 if ( arraysEqual( cache, v ) ) return; 18388 18389 gl.uniform2uiv( this.addr, v ); 18390 18391 copyArray( cache, v ); 18392 18393 } 18394 18395} 18396 18397function setValueV3ui( gl, v ) { 18398 18399 const cache = this.cache; 18400 18401 if ( v.x !== undefined ) { 18402 18403 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 18404 18405 gl.uniform3ui( this.addr, v.x, v.y, v.z ); 18406 18407 cache[ 0 ] = v.x; 18408 cache[ 1 ] = v.y; 18409 cache[ 2 ] = v.z; 18410 18411 } 18412 18413 } else { 18414 18415 if ( arraysEqual( cache, v ) ) return; 18416 18417 gl.uniform3uiv( this.addr, v ); 18418 18419 copyArray( cache, v ); 18420 18421 } 18422 18423} 18424 18425function setValueV4ui( gl, v ) { 18426 18427 const cache = this.cache; 18428 18429 if ( v.x !== undefined ) { 18430 18431 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 18432 18433 gl.uniform4ui( this.addr, v.x, v.y, v.z, v.w ); 18434 18435 cache[ 0 ] = v.x; 18436 cache[ 1 ] = v.y; 18437 cache[ 2 ] = v.z; 18438 cache[ 3 ] = v.w; 18439 18440 } 18441 18442 } else { 18443 18444 if ( arraysEqual( cache, v ) ) return; 18445 18446 gl.uniform4uiv( this.addr, v ); 18447 18448 copyArray( cache, v ); 18449 18450 } 18451 18452} 18453 18454 18455// Single texture (2D / Cube) 18456 18457function setValueT1( gl, v, textures ) { 18458 18459 const cache = this.cache; 18460 const unit = textures.allocateTextureUnit(); 18461 18462 if ( cache[ 0 ] !== unit ) { 18463 18464 gl.uniform1i( this.addr, unit ); 18465 cache[ 0 ] = unit; 18466 18467 } 18468 18469 const emptyTexture2D = ( this.type === gl.SAMPLER_2D_SHADOW ) ? emptyShadowTexture : emptyTexture; 18470 18471 textures.setTexture2D( v || emptyTexture2D, unit ); 18472 18473} 18474 18475function setValueT3D1( gl, v, textures ) { 18476 18477 const cache = this.cache; 18478 const unit = textures.allocateTextureUnit(); 18479 18480 if ( cache[ 0 ] !== unit ) { 18481 18482 gl.uniform1i( this.addr, unit ); 18483 cache[ 0 ] = unit; 18484 18485 } 18486 18487 textures.setTexture3D( v || empty3dTexture, unit ); 18488 18489} 18490 18491function setValueT6( gl, v, textures ) { 18492 18493 const cache = this.cache; 18494 const unit = textures.allocateTextureUnit(); 18495 18496 if ( cache[ 0 ] !== unit ) { 18497 18498 gl.uniform1i( this.addr, unit ); 18499 cache[ 0 ] = unit; 18500 18501 } 18502 18503 textures.setTextureCube( v || emptyCubeTexture, unit ); 18504 18505} 18506 18507function setValueT2DArray1( gl, v, textures ) { 18508 18509 const cache = this.cache; 18510 const unit = textures.allocateTextureUnit(); 18511 18512 if ( cache[ 0 ] !== unit ) { 18513 18514 gl.uniform1i( this.addr, unit ); 18515 cache[ 0 ] = unit; 18516 18517 } 18518 18519 textures.setTexture2DArray( v || emptyArrayTexture, unit ); 18520 18521} 18522 18523// Helper to pick the right setter for the singular case 18524 18525function getSingularSetter( type ) { 18526 18527 switch ( type ) { 18528 18529 case 0x1406: return setValueV1f; // FLOAT 18530 case 0x8b50: return setValueV2f; // _VEC2 18531 case 0x8b51: return setValueV3f; // _VEC3 18532 case 0x8b52: return setValueV4f; // _VEC4 18533 18534 case 0x8b5a: return setValueM2; // _MAT2 18535 case 0x8b5b: return setValueM3; // _MAT3 18536 case 0x8b5c: return setValueM4; // _MAT4 18537 18538 case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL 18539 case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2 18540 case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3 18541 case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4 18542 18543 case 0x1405: return setValueV1ui; // UINT 18544 case 0x8dc6: return setValueV2ui; // _VEC2 18545 case 0x8dc7: return setValueV3ui; // _VEC3 18546 case 0x8dc8: return setValueV4ui; // _VEC4 18547 18548 case 0x8b5e: // SAMPLER_2D 18549 case 0x8d66: // SAMPLER_EXTERNAL_OES 18550 case 0x8dca: // INT_SAMPLER_2D 18551 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D 18552 case 0x8b62: // SAMPLER_2D_SHADOW 18553 return setValueT1; 18554 18555 case 0x8b5f: // SAMPLER_3D 18556 case 0x8dcb: // INT_SAMPLER_3D 18557 case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D 18558 return setValueT3D1; 18559 18560 case 0x8b60: // SAMPLER_CUBE 18561 case 0x8dcc: // INT_SAMPLER_CUBE 18562 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE 18563 case 0x8dc5: // SAMPLER_CUBE_SHADOW 18564 return setValueT6; 18565 18566 case 0x8dc1: // SAMPLER_2D_ARRAY 18567 case 0x8dcf: // INT_SAMPLER_2D_ARRAY 18568 case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY 18569 case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW 18570 return setValueT2DArray1; 18571 18572 } 18573 18574} 18575 18576 18577// Array of scalars 18578 18579function setValueV1fArray( gl, v ) { 18580 18581 gl.uniform1fv( this.addr, v ); 18582 18583} 18584 18585// Array of vectors (from flat array or array of THREE.VectorN) 18586 18587function setValueV2fArray( gl, v ) { 18588 18589 const data = flatten( v, this.size, 2 ); 18590 18591 gl.uniform2fv( this.addr, data ); 18592 18593} 18594 18595function setValueV3fArray( gl, v ) { 18596 18597 const data = flatten( v, this.size, 3 ); 18598 18599 gl.uniform3fv( this.addr, data ); 18600 18601} 18602 18603function setValueV4fArray( gl, v ) { 18604 18605 const data = flatten( v, this.size, 4 ); 18606 18607 gl.uniform4fv( this.addr, data ); 18608 18609} 18610 18611// Array of matrices (from flat array or array of THREE.MatrixN) 18612 18613function setValueM2Array( gl, v ) { 18614 18615 const data = flatten( v, this.size, 4 ); 18616 18617 gl.uniformMatrix2fv( this.addr, false, data ); 18618 18619} 18620 18621function setValueM3Array( gl, v ) { 18622 18623 const data = flatten( v, this.size, 9 ); 18624 18625 gl.uniformMatrix3fv( this.addr, false, data ); 18626 18627} 18628 18629function setValueM4Array( gl, v ) { 18630 18631 const data = flatten( v, this.size, 16 ); 18632 18633 gl.uniformMatrix4fv( this.addr, false, data ); 18634 18635} 18636 18637// Array of integer / boolean 18638 18639function setValueV1iArray( gl, v ) { 18640 18641 gl.uniform1iv( this.addr, v ); 18642 18643} 18644 18645// Array of integer / boolean vectors (from flat array) 18646 18647function setValueV2iArray( gl, v ) { 18648 18649 gl.uniform2iv( this.addr, v ); 18650 18651} 18652 18653function setValueV3iArray( gl, v ) { 18654 18655 gl.uniform3iv( this.addr, v ); 18656 18657} 18658 18659function setValueV4iArray( gl, v ) { 18660 18661 gl.uniform4iv( this.addr, v ); 18662 18663} 18664 18665// Array of unsigned integer 18666 18667function setValueV1uiArray( gl, v ) { 18668 18669 gl.uniform1uiv( this.addr, v ); 18670 18671} 18672 18673// Array of unsigned integer vectors (from flat array) 18674 18675function setValueV2uiArray( gl, v ) { 18676 18677 gl.uniform2uiv( this.addr, v ); 18678 18679} 18680 18681function setValueV3uiArray( gl, v ) { 18682 18683 gl.uniform3uiv( this.addr, v ); 18684 18685} 18686 18687function setValueV4uiArray( gl, v ) { 18688 18689 gl.uniform4uiv( this.addr, v ); 18690 18691} 18692 18693 18694// Array of textures (2D / 3D / Cube / 2DArray) 18695 18696function setValueT1Array( gl, v, textures ) { 18697 18698 const cache = this.cache; 18699 18700 const n = v.length; 18701 18702 const units = allocTexUnits( textures, n ); 18703 18704 if ( ! arraysEqual( cache, units ) ) { 18705 18706 gl.uniform1iv( this.addr, units ); 18707 18708 copyArray( cache, units ); 18709 18710 } 18711 18712 for ( let i = 0; i !== n; ++ i ) { 18713 18714 textures.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); 18715 18716 } 18717 18718} 18719 18720function setValueT3DArray( gl, v, textures ) { 18721 18722 const cache = this.cache; 18723 18724 const n = v.length; 18725 18726 const units = allocTexUnits( textures, n ); 18727 18728 if ( ! arraysEqual( cache, units ) ) { 18729 18730 gl.uniform1iv( this.addr, units ); 18731 18732 copyArray( cache, units ); 18733 18734 } 18735 18736 for ( let i = 0; i !== n; ++ i ) { 18737 18738 textures.setTexture3D( v[ i ] || empty3dTexture, units[ i ] ); 18739 18740 } 18741 18742} 18743 18744function setValueT6Array( gl, v, textures ) { 18745 18746 const cache = this.cache; 18747 18748 const n = v.length; 18749 18750 const units = allocTexUnits( textures, n ); 18751 18752 if ( ! arraysEqual( cache, units ) ) { 18753 18754 gl.uniform1iv( this.addr, units ); 18755 18756 copyArray( cache, units ); 18757 18758 } 18759 18760 for ( let i = 0; i !== n; ++ i ) { 18761 18762 textures.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] ); 18763 18764 } 18765 18766} 18767 18768function setValueT2DArrayArray( gl, v, textures ) { 18769 18770 const cache = this.cache; 18771 18772 const n = v.length; 18773 18774 const units = allocTexUnits( textures, n ); 18775 18776 if ( ! arraysEqual( cache, units ) ) { 18777 18778 gl.uniform1iv( this.addr, units ); 18779 18780 copyArray( cache, units ); 18781 18782 } 18783 18784 for ( let i = 0; i !== n; ++ i ) { 18785 18786 textures.setTexture2DArray( v[ i ] || emptyArrayTexture, units[ i ] ); 18787 18788 } 18789 18790} 18791 18792 18793// Helper to pick the right setter for a pure (bottom-level) array 18794 18795function getPureArraySetter( type ) { 18796 18797 switch ( type ) { 18798 18799 case 0x1406: return setValueV1fArray; // FLOAT 18800 case 0x8b50: return setValueV2fArray; // _VEC2 18801 case 0x8b51: return setValueV3fArray; // _VEC3 18802 case 0x8b52: return setValueV4fArray; // _VEC4 18803 18804 case 0x8b5a: return setValueM2Array; // _MAT2 18805 case 0x8b5b: return setValueM3Array; // _MAT3 18806 case 0x8b5c: return setValueM4Array; // _MAT4 18807 18808 case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL 18809 case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2 18810 case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3 18811 case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4 18812 18813 case 0x1405: return setValueV1uiArray; // UINT 18814 case 0x8dc6: return setValueV2uiArray; // _VEC2 18815 case 0x8dc7: return setValueV3uiArray; // _VEC3 18816 case 0x8dc8: return setValueV4uiArray; // _VEC4 18817 18818 case 0x8b5e: // SAMPLER_2D 18819 case 0x8d66: // SAMPLER_EXTERNAL_OES 18820 case 0x8dca: // INT_SAMPLER_2D 18821 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D 18822 case 0x8b62: // SAMPLER_2D_SHADOW 18823 return setValueT1Array; 18824 18825 case 0x8b5f: // SAMPLER_3D 18826 case 0x8dcb: // INT_SAMPLER_3D 18827 case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D 18828 return setValueT3DArray; 18829 18830 case 0x8b60: // SAMPLER_CUBE 18831 case 0x8dcc: // INT_SAMPLER_CUBE 18832 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE 18833 case 0x8dc5: // SAMPLER_CUBE_SHADOW 18834 return setValueT6Array; 18835 18836 case 0x8dc1: // SAMPLER_2D_ARRAY 18837 case 0x8dcf: // INT_SAMPLER_2D_ARRAY 18838 case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY 18839 case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW 18840 return setValueT2DArrayArray; 18841 18842 } 18843 18844} 18845 18846// --- Uniform Classes --- 18847 18848class SingleUniform { 18849 18850 constructor( id, activeInfo, addr ) { 18851 18852 this.id = id; 18853 this.addr = addr; 18854 this.cache = []; 18855 this.type = activeInfo.type; 18856 this.setValue = getSingularSetter( activeInfo.type ); 18857 18858 // this.path = activeInfo.name; // DEBUG 18859 18860 } 18861 18862} 18863 18864class PureArrayUniform { 18865 18866 constructor( id, activeInfo, addr ) { 18867 18868 this.id = id; 18869 this.addr = addr; 18870 this.cache = []; 18871 this.type = activeInfo.type; 18872 this.size = activeInfo.size; 18873 this.setValue = getPureArraySetter( activeInfo.type ); 18874 18875 // this.path = activeInfo.name; // DEBUG 18876 18877 } 18878 18879} 18880 18881class StructuredUniform { 18882 18883 constructor( id ) { 18884 18885 this.id = id; 18886 18887 this.seq = []; 18888 this.map = {}; 18889 18890 } 18891 18892 setValue( gl, value, textures ) { 18893 18894 const seq = this.seq; 18895 18896 for ( let i = 0, n = seq.length; i !== n; ++ i ) { 18897 18898 const u = seq[ i ]; 18899 u.setValue( gl, value[ u.id ], textures ); 18900 18901 } 18902 18903 } 18904 18905} 18906 18907// --- Top-level --- 18908 18909// Parser - builds up the property tree from the path strings 18910 18911const RePathPart = /(\w+)(\])?(\[|\.)?/g; 18912 18913// extracts 18914// - the identifier (member name or array index) 18915// - followed by an optional right bracket (found when array index) 18916// - followed by an optional left bracket or dot (type of subscript) 18917// 18918// Note: These portions can be read in a non-overlapping fashion and 18919// allow straightforward parsing of the hierarchy that WebGL encodes 18920// in the uniform names. 18921 18922function addUniform( container, uniformObject ) { 18923 18924 container.seq.push( uniformObject ); 18925 container.map[ uniformObject.id ] = uniformObject; 18926 18927} 18928 18929function parseUniform( activeInfo, addr, container ) { 18930 18931 const path = activeInfo.name, 18932 pathLength = path.length; 18933 18934 // reset RegExp object, because of the early exit of a previous run 18935 RePathPart.lastIndex = 0; 18936 18937 while ( true ) { 18938 18939 const match = RePathPart.exec( path ), 18940 matchEnd = RePathPart.lastIndex; 18941 18942 let id = match[ 1 ]; 18943 const idIsIndex = match[ 2 ] === ']', 18944 subscript = match[ 3 ]; 18945 18946 if ( idIsIndex ) id = id | 0; // convert to integer 18947 18948 if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) { 18949 18950 // bare name or "pure" bottom-level array "[0]" suffix 18951 18952 addUniform( container, subscript === undefined ? 18953 new SingleUniform( id, activeInfo, addr ) : 18954 new PureArrayUniform( id, activeInfo, addr ) ); 18955 18956 break; 18957 18958 } else { 18959 18960 // step into inner node / create it in case it doesn't exist 18961 18962 const map = container.map; 18963 let next = map[ id ]; 18964 18965 if ( next === undefined ) { 18966 18967 next = new StructuredUniform( id ); 18968 addUniform( container, next ); 18969 18970 } 18971 18972 container = next; 18973 18974 } 18975 18976 } 18977 18978} 18979 18980// Root Container 18981 18982class WebGLUniforms { 18983 18984 constructor( gl, program ) { 18985 18986 this.seq = []; 18987 this.map = {}; 18988 18989 const n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS ); 18990 18991 for ( let i = 0; i < n; ++ i ) { 18992 18993 const info = gl.getActiveUniform( program, i ), 18994 addr = gl.getUniformLocation( program, info.name ); 18995 18996 parseUniform( info, addr, this ); 18997 18998 } 18999 19000 } 19001 19002 setValue( gl, name, value, textures ) { 19003 19004 const u = this.map[ name ]; 19005 19006 if ( u !== undefined ) u.setValue( gl, value, textures ); 19007 19008 } 19009 19010 setOptional( gl, object, name ) { 19011 19012 const v = object[ name ]; 19013 19014 if ( v !== undefined ) this.setValue( gl, name, v ); 19015 19016 } 19017 19018 static upload( gl, seq, values, textures ) { 19019 19020 for ( let i = 0, n = seq.length; i !== n; ++ i ) { 19021 19022 const u = seq[ i ], 19023 v = values[ u.id ]; 19024 19025 if ( v.needsUpdate !== false ) { 19026 19027 // note: always updating when .needsUpdate is undefined 19028 u.setValue( gl, v.value, textures ); 19029 19030 } 19031 19032 } 19033 19034 } 19035 19036 static seqWithValue( seq, values ) { 19037 19038 const r = []; 19039 19040 for ( let i = 0, n = seq.length; i !== n; ++ i ) { 19041 19042 const u = seq[ i ]; 19043 if ( u.id in values ) r.push( u ); 19044 19045 } 19046 19047 return r; 19048 19049 } 19050 19051} 19052 19053function WebGLShader( gl, type, string ) { 19054 19055 const shader = gl.createShader( type ); 19056 19057 gl.shaderSource( shader, string ); 19058 gl.compileShader( shader ); 19059 19060 return shader; 19061 19062} 19063 19064// From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/ 19065const COMPLETION_STATUS_KHR = 0x91B1; 19066 19067let programIdCount = 0; 19068 19069function handleSource( string, errorLine ) { 19070 19071 const lines = string.split( '\n' ); 19072 const lines2 = []; 19073 19074 const from = Math.max( errorLine - 6, 0 ); 19075 const to = Math.min( errorLine + 6, lines.length ); 19076 19077 for ( let i = from; i < to; i ++ ) { 19078 19079 const line = i + 1; 19080 lines2.push( `${line === errorLine ? '>' : ' '} ${line}: ${lines[ i ]}` ); 19081 19082 } 19083 19084 return lines2.join( '\n' ); 19085 19086} 19087 19088function getEncodingComponents( colorSpace ) { 19089 19090 const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); 19091 const encodingPrimaries = ColorManagement.getPrimaries( colorSpace ); 19092 19093 let gamutMapping; 19094 19095 if ( workingPrimaries === encodingPrimaries ) { 19096 19097 gamutMapping = ''; 19098 19099 } else if ( workingPrimaries === P3Primaries && encodingPrimaries === Rec709Primaries ) { 19100 19101 gamutMapping = 'LinearDisplayP3ToLinearSRGB'; 19102 19103 } else if ( workingPrimaries === Rec709Primaries && encodingPrimaries === P3Primaries ) { 19104 19105 gamutMapping = 'LinearSRGBToLinearDisplayP3'; 19106 19107 } 19108 19109 switch ( colorSpace ) { 19110 19111 case LinearSRGBColorSpace: 19112 case LinearDisplayP3ColorSpace: 19113 return [ gamutMapping, 'LinearTransferOETF' ]; 19114 19115 case SRGBColorSpace: 19116 case DisplayP3ColorSpace: 19117 return [ gamutMapping, 'sRGBTransferOETF' ]; 19118 19119 default: 19120 console.warn( 'THREE.WebGLProgram: Unsupported color space:', colorSpace ); 19121 return [ gamutMapping, 'LinearTransferOETF' ]; 19122 19123 } 19124 19125} 19126 19127function getShaderErrors( gl, shader, type ) { 19128 19129 const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS ); 19130 const errors = gl.getShaderInfoLog( shader ).trim(); 19131 19132 if ( status && errors === '' ) return ''; 19133 19134 const errorMatches = /ERROR: 0:(\d+)/.exec( errors ); 19135 if ( errorMatches ) { 19136 19137 // --enable-privileged-webgl-extension 19138 // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); 19139 19140 const errorLine = parseInt( errorMatches[ 1 ] ); 19141 return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine ); 19142 19143 } else { 19144 19145 return errors; 19146 19147 } 19148 19149} 19150 19151function getTexelEncodingFunction( functionName, colorSpace ) { 19152 19153 const components = getEncodingComponents( colorSpace ); 19154 return `vec4 ${functionName}( vec4 value ) { return ${components[ 0 ]}( ${components[ 1 ]}( value ) ); }`; 19155 19156} 19157 19158function getToneMappingFunction( functionName, toneMapping ) { 19159 19160 let toneMappingName; 19161 19162 switch ( toneMapping ) { 19163 19164 case LinearToneMapping: 19165 toneMappingName = 'Linear'; 19166 break; 19167 19168 case ReinhardToneMapping: 19169 toneMappingName = 'Reinhard'; 19170 break; 19171 19172 case CineonToneMapping: 19173 toneMappingName = 'OptimizedCineon'; 19174 break; 19175 19176 case ACESFilmicToneMapping: 19177 toneMappingName = 'ACESFilmic'; 19178 break; 19179 19180 case AgXToneMapping: 19181 toneMappingName = 'AgX'; 19182 break; 19183 19184 case NeutralToneMapping: 19185 toneMappingName = 'Neutral'; 19186 break; 19187 19188 case CustomToneMapping: 19189 toneMappingName = 'Custom'; 19190 break; 19191 19192 default: 19193 console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping ); 19194 toneMappingName = 'Linear'; 19195 19196 } 19197 19198 return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }'; 19199 19200} 19201 19202function generate
19202VertexExtensions( parameters ) { 19203 19204 const chunks = [
vendor: 7,293 bytes, lines 19205-19516
19205 parameters.extensionClipCullDistance ? '#extension GL_ANGLE_clip_cull_distance : require' : '', 19206 parameters.extensionMultiDraw ? '#extension GL_ANGLE_multi_draw : require' : '', 19207 ]; 19208 19209 return chunks.filter( filterEmptyLine ).join( '\n' ); 19210 19211} 19212 19213function generateDefines( defines ) { 19214 19215 const chunks = []; 19216 19217 for ( const name in defines ) { 19218 19219 const value = defines[ name ]; 19220 19221 if ( value === false ) continue; 19222 19223 chunks.push( '#define ' + name + ' ' + value ); 19224 19225 } 19226 19227 return chunks.join( '\n' ); 19228 19229} 19230 19231function fetchAttributeLocations( gl, program ) { 19232 19233 const attributes = {}; 19234 19235 const n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES ); 19236 19237 for ( let i = 0; i < n; i ++ ) { 19238 19239 const info = gl.getActiveAttrib( program, i ); 19240 const name = info.name; 19241 19242 let locationSize = 1; 19243 if ( info.type === gl.FLOAT_MAT2 ) locationSize = 2; 19244 if ( info.type === gl.FLOAT_MAT3 ) locationSize = 3; 19245 if ( info.type === gl.FLOAT_MAT4 ) locationSize = 4; 19246 19247 // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); 19248 19249 attributes[ name ] = { 19250 type: info.type, 19251 location: gl.getAttribLocation( program, name ), 19252 locationSize: locationSize 19253 }; 19254 19255 } 19256 19257 return attributes; 19258 19259} 19260 19261function filterEmptyLine( string ) { 19262 19263 return string !== ''; 19264 19265} 19266 19267function replaceLightNums( string, parameters ) { 19268 19269 const numSpotLightCoords = parameters.numSpotLightShadows + parameters.numSpotLightMaps - parameters.numSpotLightShadowsWithMaps; 19270 19271 return string 19272 .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights ) 19273 .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights ) 19274 .replace( /NUM_SPOT_LIGHT_MAPS/g, parameters.numSpotLightMaps ) 19275 .replace( /NUM_SPOT_LIGHT_COORDS/g, numSpotLightCoords ) 19276 .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights ) 19277 .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights ) 19278 .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights ) 19279 .replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows ) 19280 .replace( /NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g, parameters.numSpotLightShadowsWithMaps ) 19281 .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows ) 19282 .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows ); 19283 19284} 19285 19286function replaceClippingPlaneNums( string, parameters ) { 19287 19288 return string 19289 .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes ) 19290 .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) ); 19291 19292} 19293 19294// Resolve Includes 19295 19296const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm; 19297 19298function resolveIncludes( string ) { 19299 19300 return string.replace( includePattern, includeReplacer ); 19301 19302} 19303 19304const shaderChunkMap = new Map( [ 19305 [ 'encodings_fragment', 'colorspace_fragment' ], // @deprecated, r154 19306 [ 'encodings_pars_fragment', 'colorspace_pars_fragment' ], // @deprecated, r154 19307 [ 'output_fragment', 'opaque_fragment' ], // @deprecated, r154 19308] ); 19309 19310function includeReplacer( match, include ) { 19311 19312 let string = ShaderChunk[ include ]; 19313 19314 if ( string === undefined ) { 19315 19316 const newInclude = shaderChunkMap.get( include ); 19317 19318 if ( newInclude !== undefined ) { 19319 19320 string = ShaderChunk[ newInclude ]; 19321 console.warn( 'THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude ); 19322 19323 } else { 19324 19325 throw new Error( 'Can not resolve #include <' + include + '>' ); 19326 19327 } 19328 19329 } 19330 19331 return resolveIncludes( string ); 19332 19333} 19334 19335// Unroll Loops 19336 19337const 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; 19338 19339function unrollLoops( string ) { 19340 19341 return string.replace( unrollLoopPattern, loopReplacer ); 19342 19343} 19344 19345function loopReplacer( match, start, end, snippet ) { 19346 19347 let string = ''; 19348 19349 for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) { 19350 19351 string += snippet 19352 .replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' ) 19353 .replace( /UNROLLED_LOOP_INDEX/g, i ); 19354 19355 } 19356 19357 return string; 19358 19359} 19360 19361// 19362 19363function generatePrecision( parameters ) { 19364 19365 let precisionstring = `precision ${parameters.precision} float; 19366 precision ${parameters.precision} int; 19367 precision ${parameters.precision} sampler2D; 19368 precision ${parameters.precision} samplerCube; 19369 precision ${parameters.precision} sampler3D; 19370 precision ${parameters.precision} sampler2DArray; 19371 precision ${parameters.precision} sampler2DShadow; 19372 precision ${parameters.precision} samplerCubeShadow; 19373 precision ${parameters.precision} sampler2DArrayShadow; 19374 precision ${parameters.precision} isampler2D; 19375 precision ${parameters.precision} isampler3D; 19376 precision ${parameters.precision} isamplerCube; 19377 precision ${parameters.precision} isampler2DArray; 19378 precision ${parameters.precision} usampler2D; 19379 precision ${parameters.precision} usampler3D; 19380 precision ${parameters.precision} usamplerCube; 19381 precision ${parameters.precision} usampler2DArray; 19382 `; 19383 19384 if ( parameters.precision === 'highp' ) { 19385 19386 precisionstring += '\n#define HIGH_PRECISION'; 19387 19388 } else if ( parameters.precision === 'mediump' ) { 19389 19390 precisionstring += '\n#define MEDIUM_PRECISION'; 19391 19392 } else if ( parameters.precision === 'lowp' ) { 19393 19394 precisionstring += '\n#define LOW_PRECISION'; 19395 19396 } 19397 19398 return precisionstring; 19399 19400} 19401 19402function generateShadowMapTypeDefine( parameters ) { 19403 19404 let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; 19405 19406 if ( parameters.shadowMapType === PCFShadowMap ) { 19407 19408 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; 19409 19410 } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { 19411 19412 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; 19413 19414 } else if ( parameters.shadowMapType === VSMShadowMap ) { 19415 19416 shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM'; 19417 19418 } 19419 19420 return shadowMapTypeDefine; 19421 19422} 19423 19424function generateEnvMapTypeDefine( parameters ) { 19425 19426 let envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; 19427 19428 if ( parameters.envMap ) { 19429 19430 switch ( parameters.envMapMode ) { 19431 19432 case CubeReflectionMapping: 19433 case CubeRefractionMapping: 19434 envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; 19435 break; 19436 19437 case CubeUVReflectionMapping: 19438 envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; 19439 break; 19440 19441 } 19442 19443 } 19444 19445 return envMapTypeDefine; 19446 19447} 19448 19449function generateEnvMapModeDefine( parameters ) { 19450 19451 let envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; 19452 19453 if ( parameters.envMap ) { 19454 19455 switch ( parameters.envMapMode ) { 19456 19457 case CubeRefractionMapping: 19458 19459 envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; 19460 break; 19461 19462 } 19463 19464 } 19465 19466 return envMapModeDefine; 19467 19468} 19469 19470function generateEnvMapBlendingDefine( parameters ) { 19471 19472 let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE'; 19473 19474 if ( parameters.envMap ) { 19475 19476 switch ( parameters.combine ) { 19477 19478 case MultiplyOperation: 19479 envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; 19480 break; 19481 19482 case MixOperation: 19483 envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; 19484 break; 19485 19486 case AddOperation: 19487 envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; 19488 break; 19489 19490 } 19491 19492 } 19493 19494 return envMapBlendingDefine; 19495 19496} 19497 19498function generateCubeUVSize( parameters ) { 19499 19500 const imageHeight = parameters.envMapCubeUVHeight; 19501 19502 if ( imageHeight === null ) return null; 19503 19504 const maxMip = Math.log2( imageHeight ) - 2; 19505 19506 const texelHeight = 1.0 / imageHeight; 19507 19508 const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) ); 19509 19510 return { texelWidth, texelHeight, maxMip }; 19511 19512} 19513 19514function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { 19515 19516 // TODO Send this event to Three.js DevTools
vendor: 15,382 bytes, lines 19517-19935
19517 // console.log( 'WebGLProgram', cacheKey ); 19518 19519 const gl = renderer.getContext(); 19520 19521 const defines = parameters.defines; 19522 19523 let vertexShader = parameters.vertexShader; 19524 let fragmentShader = parameters.fragmentShader; 19525 19526 const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters ); 19527 const envMapTypeDefine = generateEnvMapTypeDefine( parameters ); 19528 const envMapModeDefine = generateEnvMapModeDefine( parameters ); 19529 const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters ); 19530 const envMapCubeUVSize = generateCubeUVSize( parameters ); 19531 19532 const customVertexExtensions = generateVertexExtensions( parameters ); 19533 19534 const customDefines = generateDefines( defines ); 19535 19536 const program = gl.createProgram(); 19537 19538 let prefixVertex, prefixFragment; 19539 let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : ''; 19540 19541 if ( parameters.isRawShaderMaterial ) { 19542 19543 prefixVertex = [ 19544 19545 '#define SHADER_TYPE ' + parameters.shaderType, 19546 '#define SHADER_NAME ' + parameters.shaderName, 19547 19548 customDefines 19549 19550 ].filter( filterEmptyLine ).join( '\n' ); 19551 19552 if ( prefixVertex.length > 0 ) { 19553 19554 prefixVertex += '\n'; 19555 19556 } 19557 19558 prefixFragment = [ 19559 19560 '#define SHADER_TYPE ' + parameters.shaderType, 19561 '#define SHADER_NAME ' + parameters.shaderName, 19562 19563 customDefines 19564 19565 ].filter( filterEmptyLine ).join( '\n' ); 19566 19567 if ( prefixFragment.length > 0 ) { 19568 19569 prefixFragment += '\n'; 19570 19571 } 19572 19573 } else { 19574 19575 prefixVertex = [ 19576 19577 generatePrecision( parameters ), 19578 19579 '#define SHADER_TYPE ' + parameters.shaderType, 19580 '#define SHADER_NAME ' + parameters.shaderName, 19581 19582 customDefines, 19583 19584 parameters.extensionClipCullDistance ? '#define USE_CLIP_DISTANCE' : '', 19585 parameters.batching ? '#define USE_BATCHING' : '', 19586 parameters.instancing ? '#define USE_INSTANCING' : '', 19587 parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', 19588 parameters.instancingMorph ? '#define USE_INSTANCING_MORPH' : '', 19589 19590 parameters.useFog && parameters.fog ? '#define USE_FOG' : '', 19591 parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', 19592 19593 parameters.map ? '#define USE_MAP' : '', 19594 parameters.envMap ? '#define USE_ENVMAP' : '', 19595 parameters.envMap ? '#define ' + envMapModeDefine : '', 19596 parameters.lightMap ? '#define USE_LIGHTMAP' : '', 19597 parameters.aoMap ? '#define USE_AOMAP' : '', 19598 parameters.bumpMap ? '#define USE_BUMPMAP' : '', 19599 parameters.normalMap ? '#define USE_NORMALMAP' : '', 19600 parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', 19601 parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', 19602 parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '', 19603 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', 19604 19605 parameters.anisotropy ? '#define USE_ANISOTROPY' : '', 19606 parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', 19607 19608 parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', 19609 parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', 19610 parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', 19611 19612 parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', 19613 parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', 19614 19615 parameters.specularMap ? '#define USE_SPECULARMAP' : '', 19616 parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', 19617 parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', 19618 19619 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', 19620 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', 19621 parameters.alphaMap ? '#define USE_ALPHAMAP' : '', 19622 parameters.alphaHash ? '#define USE_ALPHAHASH' : '', 19623 19624 parameters.transmission ? '#define USE_TRANSMISSION' : '', 19625 parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', 19626 parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', 19627 19628 parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', 19629 parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', 19630 19631 // 19632 19633 parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '', 19634 parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '', 19635 parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '', 19636 parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '', 19637 parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '', 19638 parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '', 19639 parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '', 19640 parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '', 19641 19642 parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '', 19643 parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '', 19644 19645 parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '', 19646 19647 parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '', 19648 parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '', 19649 parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '', 19650 19651 parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '', 19652 parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '', 19653 19654 parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '', 19655 parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '', 19656 19657 parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '', 19658 parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '', 19659 parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '', 19660 19661 parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '', 19662 parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '', 19663 19664 // 19665 19666 parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', 19667 parameters.vertexColors ? '#define USE_COLOR' : '', 19668 parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', 19669 parameters.vertexUv1s ? '#define USE_UV1' : '', 19670 parameters.vertexUv2s ? '#define USE_UV2' : '', 19671 parameters.vertexUv3s ? '#define USE_UV3' : '', 19672 19673 parameters.pointsUvs ? '#define USE_POINTS_UV' : '', 19674 19675 parameters.flatShading ? '#define FLAT_SHADED' : '', 19676 19677 parameters.skinning ? '#define USE_SKINNING' : '', 19678 19679 parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', 19680 parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', 19681 ( parameters.morphColors ) ? '#define USE_MORPHCOLORS' : '', 19682 ( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_TEXTURE' : '', 19683 ( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '', 19684 ( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '', 19685 parameters.doubleSided ? '#define DOUBLE_SIDED' : '', 19686 parameters.flipSided ? '#define FLIP_SIDED' : '', 19687 19688 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', 19689 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', 19690 19691 parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', 19692 19693 parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', 19694 19695 parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', 19696 19697 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', 19698 19699 'uniform mat4 modelMatrix;', 19700 'uniform mat4 modelViewMatrix;', 19701 'uniform mat4 projectionMatrix;', 19702 'uniform mat4 viewMatrix;', 19703 'uniform mat3 normalMatrix;', 19704 'uniform vec3 cameraPosition;', 19705 'uniform bool isOrthographic;', 19706 19707 '#ifdef USE_INSTANCING', 19708 19709 ' attribute mat4 instanceMatrix;', 19710 19711 '#endif', 19712 19713 '#ifdef USE_INSTANCING_COLOR', 19714 19715 ' attribute vec3 instanceColor;', 19716 19717 '#endif', 19718 19719 '#ifdef USE_INSTANCING_MORPH', 19720 19721 ' uniform sampler2D morphTexture;', 19722 19723 '#endif', 19724 19725 'attribute vec3 position;', 19726 'attribute vec3 normal;', 19727 'attribute vec2 uv;', 19728 19729 '#ifdef USE_UV1', 19730 19731 ' attribute vec2 uv1;', 19732 19733 '#endif', 19734 19735 '#ifdef USE_UV2', 19736 19737 ' attribute vec2 uv2;', 19738 19739 '#endif', 19740 19741 '#ifdef USE_UV3', 19742 19743 ' attribute vec2 uv3;', 19744 19745 '#endif', 19746 19747 '#ifdef USE_TANGENT', 19748 19749 ' attribute vec4 tangent;', 19750 19751 '#endif', 19752 19753 '#if defined( USE_COLOR_ALPHA )', 19754 19755 ' attribute vec4 color;', 19756 19757 '#elif defined( USE_COLOR )', 19758 19759 ' attribute vec3 color;', 19760 19761 '#endif', 19762 19763 '#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )', 19764 19765 ' attribute vec3 morphTarget0;', 19766 ' attribute vec3 morphTarget1;', 19767 ' attribute vec3 morphTarget2;', 19768 ' attribute vec3 morphTarget3;', 19769 19770 ' #ifdef USE_MORPHNORMALS', 19771 19772 ' attribute vec3 morphNormal0;', 19773 ' attribute vec3 morphNormal1;', 19774 ' attribute vec3 morphNormal2;', 19775 ' attribute vec3 morphNormal3;', 19776 19777 ' #else', 19778 19779 ' attribute vec3 morphTarget4;', 19780 ' attribute vec3 morphTarget5;', 19781 ' attribute vec3 morphTarget6;', 19782 ' attribute vec3 morphTarget7;', 19783 19784 ' #endif', 19785 19786 '#endif', 19787 19788 '#ifdef USE_SKINNING', 19789 19790 ' attribute vec4 skinIndex;', 19791 ' attribute vec4 skinWeight;', 19792 19793 '#endif', 19794 19795 '\n' 19796 19797 ].filter( filterEmptyLine ).join( '\n' ); 19798 19799 prefixFragment = [ 19800 19801 generatePrecision( parameters ), 19802 19803 '#define SHADER_TYPE ' + parameters.shaderType, 19804 '#define SHADER_NAME ' + parameters.shaderName, 19805 19806 customDefines, 19807 19808 parameters.useFog && parameters.fog ? '#define USE_FOG' : '', 19809 parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', 19810 19811 parameters.alphaToCoverage ? '#define ALPHA_TO_COVERAGE' : '', 19812 parameters.map ? '#define USE_MAP' : '', 19813 parameters.matcap ? '#define USE_MATCAP' : '', 19814 parameters.envMap ? '#define USE_ENVMAP' : '', 19815 parameters.envMap ? '#define ' + envMapTypeDefine : '', 19816 parameters.envMap ? '#define ' + envMapModeDefine : '', 19817 parameters.envMap ? '#define ' + envMapBlendingDefine : '', 19818 envMapCubeUVSize ? '#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth : '', 19819 envMapCubeUVSize ? '#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight : '', 19820 envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '', 19821 parameters.lightMap ? '#define USE_LIGHTMAP' : '', 19822 parameters.aoMap ? '#define USE_AOMAP' : '', 19823 parameters.bumpMap ? '#define USE_BUMPMAP' : '', 19824 parameters.normalMap ? '#define USE_NORMALMAP' : '', 19825 parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', 19826 parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', 19827 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', 19828 19829 parameters.anisotropy ? '#define USE_ANISOTROPY' : '', 19830 parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', 19831 19832 parameters.clearcoat ? '#define USE_CLEARCOAT' : '', 19833 parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', 19834 parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', 19835 parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', 19836 19837 parameters.iridescence ? '#define USE_IRIDESCENCE' : '', 19838 parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', 19839 parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', 19840 19841 parameters.specularMap ? '#define USE_SPECULARMAP' : '', 19842 parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', 19843 parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', 19844 19845 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', 19846 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', 19847 19848 parameters.alphaMap ? '#define USE_ALPHAMAP' : '', 19849 parameters.alphaTest ? '#define USE_ALPHATEST' : '', 19850 parameters.alphaHash ? '#define USE_ALPHAHASH' : '', 19851 19852 parameters.sheen ? '#define USE_SHEEN' : '', 19853 parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', 19854 parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', 19855 19856 parameters.transmission ? '#define USE_TRANSMISSION' : '', 19857 parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', 19858 parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', 19859 19860 parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', 19861 parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', 19862 parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', 19863 parameters.vertexUv1s ? '#define USE_UV1' : '', 19864 parameters.vertexUv2s ? '#define USE_UV2' : '', 19865 parameters.vertexUv3s ? '#define USE_UV3' : '', 19866 19867 parameters.pointsUvs ? '#define USE_POINTS_UV' : '', 19868 19869 parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', 19870 19871 parameters.flatShading ? '#define FLAT_SHADED' : '', 19872 19873 parameters.doubleSided ? '#define DOUBLE_SIDED' : '', 19874 parameters.flipSided ? '#define FLIP_SIDED' : '', 19875 19876 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', 19877 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', 19878 19879 parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', 19880 19881 parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', 19882 19883 parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', 19884 19885 parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', 19886 19887 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', 19888 19889 'uniform mat4 viewMatrix;', 19890 'uniform vec3 cameraPosition;', 19891 'uniform bool isOrthographic;', 19892 19893 ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '', 19894 ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below 19895 ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '', 19896 19897 parameters.dithering ? '#define DITHERING' : '', 19898 parameters.opaque ? '#define OPAQUE' : '', 19899 19900 ShaderChunk[ 'colorspace_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below 19901 getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputColorSpace ), 19902 19903 parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', 19904 19905 '\n' 19906 19907 ].filter( filterEmptyLine ).join( '\n' ); 19908 19909 } 19910 19911 vertexShader = resolveIncludes( vertexShader ); 19912 vertexShader = replaceLightNums( vertexShader, parameters ); 19913 vertexShader = replaceClippingPlaneNums( vertexShader, parameters ); 19914 19915 fragmentShader = resolveIncludes( fragmentShader ); 19916 fragmentShader = replaceLightNums( fragmentShader, parameters ); 19917 fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters ); 19918 19919 vertexShader = unrollLoops( vertexShader ); 19920 fragmentShader = unrollLoops( fragmentShader ); 19921 19922 if ( parameters.isRawShaderMaterial !== true ) { 19923 19924 // GLSL 3.0 conversion for built-in materials and ShaderMaterial 19925 19926 versionString = '#version 300 es\n'; 19927 19928 prefixVertex = [ 19929 customVertexExtensions, 19930 '#define attribute in', 19931 '#define varying out', 19932 '#define texture2D texture' 19933 ].join( '\n' ) + '\n' + prefixVertex; 19934 19935 prefixFragment = [
vendor: 7,213 bytes, lines 19935-20278
19935 19936 '#define varying in', 19937 ( parameters.glslVersion === GLSL3 ) ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;', 19938 ( parameters.glslVersion === GLSL3 ) ? '' : '#define gl_FragColor pc_fragColor', 19939 '#define gl_FragDepthEXT gl_FragDepth', 19940 '#define texture2D texture', 19941 '#define textureCube texture', 19942 '#define texture2DProj textureProj', 19943 '#define texture2DLodEXT textureLod', 19944 '#define texture2DProjLodEXT textureProjLod', 19945 '#define textureCubeLodEXT textureLod', 19946 '#define texture2DGradEXT textureGrad', 19947 '#define texture2DProjGradEXT textureProjGrad', 19948 '#define textureCubeGradEXT textureGrad' 19949 ].join( '\n' ) + '\n' + prefixFragment; 19950 19951 } 19952 19953 const vertexGlsl = versionString + prefixVertex + vertexShader; 19954 const fragmentGlsl = versionString + prefixFragment + fragmentShader; 19955 19956 // console.log( '*VERTEX*', vertexGlsl ); 19957 // console.log( '*FRAGMENT*', fragmentGlsl ); 19958 19959 const glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); 19960 const glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); 19961 19962 gl.attachShader( program, glVertexShader ); 19963 gl.attachShader( program, glFragmentShader ); 19964 19965 // Force a particular attribute to index 0. 19966 19967 if ( parameters.index0AttributeName !== undefined ) { 19968 19969 gl.bindAttribLocation( program, 0, parameters.index0AttributeName ); 19970 19971 } else if ( parameters.morphTargets === true ) { 19972 19973 // programs with morphTargets displace position out of attribute 0 19974 gl.bindAttribLocation( program, 0, 'position' ); 19975 19976 } 19977 19978 gl.linkProgram( program ); 19979 19980 function onFirstUse( self ) { 19981 19982 // check for link errors 19983 if ( renderer.debug.checkShaderErrors ) { 19984 19985 const programLog = gl.getProgramInfoLog( program ).trim(); 19986 const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim(); 19987 const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim(); 19988 19989 let runnable = true; 19990 let haveDiagnostics = true; 19991 19992 if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { 19993 19994 runnable = false; 19995 19996 if ( typeof renderer.debug.onShaderError === 'function' ) { 19997 19998 renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader ); 19999 20000 } else { 20001 20002 // default error reporting 20003 20004 const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); 20005 const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); 20006 20007 console.error( 20008 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + 20009 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + 20010 'Material Name: ' + self.name + '\n' + 20011 'Material Type: ' + self.type + '\n\n' + 20012 'Program Info Log: ' + programLog + '\n' + 20013 vertexErrors + '\n' + 20014 fragmentErrors 20015 ); 20016 20017 } 20018 20019 } else if ( programLog !== '' ) { 20020 20021 console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog ); 20022 20023 } else if ( vertexLog === '' || fragmentLog === '' ) { 20024 20025 haveDiagnostics = false; 20026 20027 } 20028 20029 if ( haveDiagnostics ) { 20030 20031 self.diagnostics = { 20032 20033 runnable: runnable, 20034 20035 programLog: programLog, 20036 20037 vertexShader: { 20038 20039 log: vertexLog, 20040 prefix: prefixVertex 20041 20042 }, 20043 20044 fragmentShader: { 20045 20046 log: fragmentLog, 20047 prefix: prefixFragment 20048 20049 } 20050 20051 }; 20052 20053 } 20054 20055 } 20056 20057 // Clean up 20058 20059 // Crashes in iOS9 and iOS10. #18402 20060 // gl.detachShader( program, glVertexShader ); 20061 // gl.detachShader( program, glFragmentShader ); 20062 20063 gl.deleteShader( glVertexShader ); 20064 gl.deleteShader( glFragmentShader ); 20065 20066 cachedUniforms = new WebGLUniforms( gl, program ); 20067 cachedAttributes = fetchAttributeLocations( gl, program ); 20068 20069 } 20070 20071 // set up caching for uniform locations 20072 20073 let cachedUniforms; 20074 20075 this.getUniforms = function () { 20076 20077 if ( cachedUniforms === undefined ) { 20078 20079 // Populates cachedUniforms and cachedAttributes 20080 onFirstUse( this ); 20081 20082 } 20083 20084 return cachedUniforms; 20085 20086 }; 20087 20088 // set up caching for attribute locations 20089 20090 let cachedAttributes; 20091 20092 this.getAttributes = function () { 20093 20094 if ( cachedAttributes === undefined ) { 20095 20096 // Populates cachedAttributes and cachedUniforms 20097 onFirstUse( this ); 20098 20099 } 20100 20101 return cachedAttributes; 20102 20103 }; 20104 20105 // indicate when the program is ready to be used. if the KHR_parallel_shader_compile extension isn't supported, 20106 // flag the program as ready immediately. It may cause a stall when it's first used. 20107 20108 let programReady = ( parameters.rendererExtensionParallelShaderCompile === false ); 20109 20110 this.isReady = function () { 20111 20112 if ( programReady === false ) { 20113 20114 programReady = gl.getProgramParameter( program, COMPLETION_STATUS_KHR ); 20115 20116 } 20117 20118 return programReady; 20119 20120 }; 20121 20122 // free resource 20123 20124 this.destroy = function () { 20125 20126 bindingStates.releaseStatesOfProgram( this ); 20127 20128 gl.deleteProgram( program ); 20129 this.program = undefined; 20130 20131 }; 20132 20133 // 20134 20135 this.type = parameters.shaderType; 20136 this.name = parameters.shaderName; 20137 this.id = programIdCount ++; 20138 this.cacheKey = cacheKey; 20139 this.usedTimes = 1; 20140 this.program = program; 20141 this.vertexShader = glVertexShader; 20142 this.fragmentShader = glFragmentShader; 20143 20144 return this; 20145 20146} 20147 20148let _id$1 = 0; 20149 20150class WebGLShaderCache { 20151 20152 constructor() { 20153 20154 this.shaderCache = new Map(); 20155 this.materialCache = new Map(); 20156 20157 } 20158 20159 update( material ) { 20160 20161 const vertexShader = material.vertexShader; 20162 const fragmentShader = material.fragmentShader; 20163 20164 const vertexShaderStage = this._getShaderStage( vertexShader ); 20165 const fragmentShaderStage = this._getShaderStage( fragmentShader ); 20166 20167 const materialShaders = this._getShaderCacheForMaterial( material ); 20168 20169 if ( materialShaders.has( vertexShaderStage ) === false ) { 20170 20171 materialShaders.add( vertexShaderStage ); 20172 vertexShaderStage.usedTimes ++; 20173 20174 } 20175 20176 if ( materialShaders.has( fragmentShaderStage ) === false ) { 20177 20178 materialShaders.add( fragmentShaderStage ); 20179 fragmentShaderStage.usedTimes ++; 20180 20181 } 20182 20183 return this; 20184 20185 } 20186 20187 remove( material ) { 20188 20189 const materialShaders = this.materialCache.get( material ); 20190 20191 for ( const shaderStage of materialShaders ) { 20192 20193 shaderStage.usedTimes --; 20194 20195 if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage.code ); 20196 20197 } 20198 20199 this.materialCache.delete( material ); 20200 20201 return this; 20202 20203 } 20204 20205 getVertexShaderID( material ) { 20206 20207 return this._getShaderStage( material.vertexShader ).id; 20208 20209 } 20210 20211 getFragmentShaderID( material ) { 20212 20213 return this._getShaderStage( material.fragmentShader ).id; 20214 20215 } 20216 20217 dispose() { 20218 20219 this.shaderCache.clear(); 20220 this.materialCache.clear(); 20221 20222 } 20223 20224 _getShaderCacheForMaterial( material ) { 20225 20226 const cache = this.materialCache; 20227 let set = cache.get( material ); 20228 20229 if ( set === undefined ) { 20230 20231 set = new Set(); 20232 cache.set( material, set ); 20233 20234 } 20235 20236 return set; 20237 20238 } 20239 20240 _getShaderStage( code ) { 20241 20242 const cache = this.shaderCache; 20243 let stage = cache.get( code ); 20244 20245 if ( stage === undefined ) { 20246 20247 stage = new WebGLShaderStage( code ); 20248 cache.set( code, stage ); 20249 20250 } 20251 20252 return stage; 20253 20254 } 20255 20256} 20257 20258class WebGLShaderStage { 20259 20260 constructor( code ) { 20261 20262 this.id = _id$1 ++; 20263 20264 this.code = code; 20265 this.usedTimes = 0; 20266 20267 } 20268 20269} 20270 20271function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) { 20272 20273 const _programLayers = new Layers(); 20274 const _customShaders = new WebGLShaderCache(); 20275 const _activeChannels = new Set(); 20276 const programs = []; 20277 20278 const
vendor: 19,894 bytes, lines 20278-20908
20278logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; 20279 const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures; 20280 20281 let precision = capabilities.precision; 20282 20283 const shaderIDs = { 20284 MeshDepthMaterial: 'depth', 20285 MeshDistanceMaterial: 'distanceRGBA', 20286 MeshNormalMaterial: 'normal', 20287 MeshBasicMaterial: 'basic', 20288 MeshLambertMaterial: 'lambert', 20289 MeshPhongMaterial: 'phong', 20290 MeshToonMaterial: 'toon', 20291 MeshStandardMaterial: 'physical', 20292 MeshPhysicalMaterial: 'physical', 20293 MeshMatcapMaterial: 'matcap', 20294 LineBasicMaterial: 'basic', 20295 LineDashedMaterial: 'dashed', 20296 PointsMaterial: 'points', 20297 ShadowMaterial: 'shadow', 20298 SpriteMaterial: 'sprite' 20299 }; 20300 20301 function getChannel( value ) { 20302 20303 _activeChannels.add( value ); 20304 20305 if ( value === 0 ) return 'uv'; 20306 20307 return `uv${ value }`; 20308 20309 } 20310 20311 function getParameters( material, lights, shadows, scene, object ) { 20312 20313 const fog = scene.fog; 20314 const geometry = object.geometry; 20315 const environment = material.isMeshStandardMaterial ? scene.environment : null; 20316 20317 const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); 20318 const envMapCubeUVHeight = ( !! envMap ) && ( envMap.mapping === CubeUVReflectionMapping ) ? envMap.image.height : null; 20319 20320 const shaderID = shaderIDs[ material.type ]; 20321 20322 // heuristics to create shader parameters according to lights in the scene 20323 // (not to blow over maxLights budget) 20324 20325 if ( material.precision !== null ) { 20326 20327 precision = capabilities.getMaxPrecision( material.precision ); 20328 20329 if ( precision !== material.precision ) { 20330 20331 console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); 20332 20333 } 20334 20335 } 20336 20337 // 20338 20339 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; 20340 const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; 20341 20342 let morphTextureStride = 0; 20343 20344 if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 1; 20345 if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 2; 20346 if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 3; 20347 20348 // 20349 20350 let vertexShader, fragmentShader; 20351 let customVertexShaderID, customFragmentShaderID; 20352 20353 if ( shaderID ) { 20354 20355 const shader = ShaderLib[ shaderID ]; 20356 20357 vertexShader = shader.vertexShader; 20358 fragmentShader = shader.fragmentShader; 20359 20360 } else { 20361 20362 vertexShader = material.vertexShader; 20363 fragmentShader = material.fragmentShader; 20364 20365 _customShaders.update( material ); 20366 20367 customVertexShaderID = _customShaders.getVertexShaderID( material ); 20368 customFragmentShaderID = _customShaders.getFragmentShaderID( material ); 20369 20370 } 20371 20372 const currentRenderTarget = renderer.getRenderTarget(); 20373 20374 const IS_INSTANCEDMESH = object.isInstancedMesh === true; 20375 const IS_BATCHEDMESH = object.isBatchedMesh === true; 20376 20377 const HAS_MAP = !! material.map; 20378 const HAS_MATCAP = !! material.matcap; 20379 const HAS_ENVMAP = !! envMap; 20380 const HAS_AOMAP = !! material.aoMap; 20381 const HAS_LIGHTMAP = !! material.lightMap; 20382 const HAS_BUMPMAP = !! material.bumpMap; 20383 const HAS_NORMALMAP = !! material.normalMap; 20384 const HAS_DISPLACEMENTMAP = !! material.displacementMap; 20385 const HAS_EMISSIVEMAP = !! material.emissiveMap; 20386 20387 const HAS_METALNESSMAP = !! material.metalnessMap; 20388 const HAS_ROUGHNESSMAP = !! material.roughnessMap; 20389 20390 const HAS_ANISOTROPY = material.anisotropy > 0; 20391 const HAS_CLEARCOAT = material.clearcoat > 0; 20392 const HAS_IRIDESCENCE = material.iridescence > 0; 20393 const HAS_SHEEN = material.sheen > 0; 20394 const HAS_TRANSMISSION = material.transmission > 0; 20395 20396 const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap; 20397 20398 const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap; 20399 const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap; 20400 const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap; 20401 20402 const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap; 20403 const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap; 20404 20405 const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap; 20406 const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap; 20407 20408 const HAS_SPECULARMAP = !! material.specularMap; 20409 const HAS_SPECULAR_COLORMAP = !! material.specularColorMap; 20410 const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap; 20411 20412 const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap; 20413 const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap; 20414 20415 const HAS_GRADIENTMAP = !! material.gradientMap; 20416 20417 const HAS_ALPHAMAP = !! material.alphaMap; 20418 20419 const HAS_ALPHATEST = material.alphaTest > 0; 20420 20421 const HAS_ALPHAHASH = !! material.alphaHash; 20422 20423 const HAS_EXTENSIONS = !! material.extensions; 20424 20425 let toneMapping = NoToneMapping; 20426 20427 if ( material.toneMapped ) { 20428 20429 if ( currentRenderTarget === null || currentRenderTarget.isXRRenderTarget === true ) { 20430 20431 toneMapping = renderer.toneMapping; 20432 20433 } 20434 20435 } 20436 20437 const parameters = { 20438 20439 shaderID: shaderID, 20440 shaderType: material.type, 20441 shaderName: material.name, 20442 20443 vertexShader: vertexShader, 20444 fragmentShader: fragmentShader, 20445 defines: material.defines, 20446 20447 customVertexShaderID: customVertexShaderID, 20448 customFragmentShaderID: customFragmentShaderID, 20449 20450 isRawShaderMaterial: material.isRawShaderMaterial === true, 20451 glslVersion: material.glslVersion, 20452 20453 precision: precision, 20454 20455 batching: IS_BATCHEDMESH, 20456 instancing: IS_INSTANCEDMESH, 20457 instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, 20458 instancingMorph: IS_INSTANCEDMESH && object.morphTexture !== null, 20459 20460 supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES, 20461 outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ), 20462 alphaToCoverage: !! material.alphaToCoverage, 20463 20464 map: HAS_MAP, 20465 matcap: HAS_MATCAP, 20466 envMap: HAS_ENVMAP, 20467 envMapMode: HAS_ENVMAP && envMap.mapping, 20468 envMapCubeUVHeight: envMapCubeUVHeight, 20469 aoMap: HAS_AOMAP, 20470 lightMap: HAS_LIGHTMAP, 20471 bumpMap: HAS_BUMPMAP, 20472 normalMap: HAS_NORMALMAP, 20473 displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP, 20474 emissiveMap: HAS_EMISSIVEMAP, 20475 20476 normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap, 20477 normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap, 20478 20479 metalnessMap: HAS_METALNESSMAP, 20480 roughnessMap: HAS_ROUGHNESSMAP, 20481 20482 anisotropy: HAS_ANISOTROPY, 20483 anisotropyMap: HAS_ANISOTROPYMAP, 20484 20485 clearcoat: HAS_CLEARCOAT, 20486 clearcoatMap: HAS_CLEARCOATMAP, 20487 clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP, 20488 clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP, 20489 20490 iridescence: HAS_IRIDESCENCE, 20491 iridescenceMap: HAS_IRIDESCENCEMAP, 20492 iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP, 20493 20494 sheen: HAS_SHEEN, 20495 sheenColorMap: HAS_SHEEN_COLORMAP, 20496 sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP, 20497 20498 specularMap: HAS_SPECULARMAP, 20499 specularColorMap: HAS_SPECULAR_COLORMAP, 20500 specularIntensityMap: HAS_SPECULAR_INTENSITYMAP, 20501 20502 transmission: HAS_TRANSMISSION, 20503 transmissionMap: HAS_TRANSMISSIONMAP, 20504 thicknessMap: HAS_THICKNESSMAP, 20505 20506 gradientMap: HAS_GRADIENTMAP, 20507 20508 opaque: material.transparent === false && material.blending === NormalBlending && material.alphaToCoverage === false, 20509 20510 alphaMap: HAS_ALPHAMAP, 20511 alphaTest: HAS_ALPHATEST, 20512 alphaHash: HAS_ALPHAHASH, 20513 20514 combine: material.combine, 20515 20516 // 20517 20518 mapUv: HAS_MAP && getChannel( material.map.channel ), 20519 aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ), 20520 lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ), 20521 bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ), 20522 normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ), 20523 displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ), 20524 emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ), 20525 20526 metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ), 20527 roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ), 20528 20529 anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ), 20530 20531 clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ), 20532 clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ), 20533 clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ), 20534 20535 iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ), 20536 iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ), 20537 20538 sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ), 20539 sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ), 20540 20541 specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ), 20542 specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ), 20543 specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ), 20544 20545 transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ), 20546 thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ), 20547 20548 alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ), 20549 20550 // 20551 20552 vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ), 20553 vertexColors: material.vertexColors, 20554 vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4, 20555 20556 pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ), 20557 20558 fog: !! fog, 20559 useFog: material.fog === true, 20560 fogExp2: ( !! fog && fog.isFogExp2 ), 20561 20562 flatShading: material.flatShading === true, 20563 20564 sizeAttenuation: material.sizeAttenuation === true, 20565 logarithmicDepthBuffer: logarithmicDepthBuffer, 20566 20567 skinning: object.isSkinnedMesh === true, 20568 20569 morphTargets: geometry.morphAttributes.position !== undefined, 20570 morphNormals: geometry.morphAttributes.normal !== undefined, 20571 morphColors: geometry.morphAttributes.color !== undefined, 20572 morphTargetsCount: morphTargetsCount, 20573 morphTextureStride: morphTextureStride, 20574 20575 numDirLights: lights.directional.length, 20576 numPointLights: lights.point.length, 20577 numSpotLights: lights.spot.length, 20578 numSpotLightMaps: lights.spotLightMap.length, 20579 numRectAreaLights: lights.rectArea.length, 20580 numHemiLights: lights.hemi.length, 20581 20582 numDirLightShadows: lights.directionalShadowMap.length, 20583 numPointLightShadows: lights.pointShadowMap.length, 20584 numSpotLightShadows: lights.spotShadowMap.length, 20585 numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps, 20586 20587 numLightProbes: lights.numLightProbes, 20588 20589 numClippingPlanes: clipping.numPlanes, 20590 numClipIntersection: clipping.numIntersection, 20591 20592 dithering: material.dithering, 20593 20594 shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0, 20595 shadowMapType: renderer.shadowMap.type, 20596 20597 toneMapping: toneMapping, 20598 useLegacyLights: renderer._useLegacyLights, 20599 20600 decodeVideoTexture: HAS_MAP && ( material.map.isVideoTexture === true ) && ( ColorManagement.getTransfer( material.map.colorSpace ) === SRGBTransfer ), 20601 20602 premultipliedAlpha: material.premultipliedAlpha, 20603 20604 doubleSided: material.side === DoubleSide, 20605 flipSided: material.side === BackSide, 20606 20607 useDepthPacking: material.depthPacking >= 0, 20608 depthPacking: material.depthPacking || 0, 20609 20610 index0AttributeName: material.index0AttributeName, 20611 20612 extensionClipCullDistance: HAS_EXTENSIONS && material.extensions.clipCullDistance === true && extensions.has( 'WEBGL_clip_cull_distance' ), 20613 extensionMultiDraw: HAS_EXTENSIONS && material.extensions.multiDraw === true && extensions.has( 'WEBGL_multi_draw' ), 20614 20615 rendererExtensionParallelShaderCompile: extensions.has( 'KHR_parallel_shader_compile' ), 20616 20617 customProgramCacheKey: material.customProgramCacheKey() 20618 20619 }; 20620 20621 // the usage of getChannel() determines the active texture channels for this shader 20622 20623 parameters.vertexUv1s = _activeChannels.has( 1 ); 20624 parameters.vertexUv2s = _activeChannels.has( 2 ); 20625 parameters.vertexUv3s = _activeChannels.has( 3 ); 20626 20627 _activeChannels.clear(); 20628 20629 return parameters; 20630 20631 } 20632 20633 function getProgramCacheKey( parameters ) { 20634 20635 const array = []; 20636 20637 if ( parameters.shaderID ) { 20638 20639 array.push( parameters.shaderID ); 20640 20641 } else { 20642 20643 array.push( parameters.customVertexShaderID ); 20644 array.push( parameters.customFragmentShaderID ); 20645 20646 } 20647 20648 if ( parameters.defines !== undefined ) { 20649 20650 for ( const name in parameters.defines ) { 20651 20652 array.push( name ); 20653 array.push( parameters.defines[ name ] ); 20654 20655 } 20656 20657 } 20658 20659 if ( parameters.isRawShaderMaterial === false ) { 20660 20661 getProgramCacheKeyParameters( array, parameters ); 20662 getProgramCacheKeyBooleans( array, parameters ); 20663 array.push( renderer.outputColorSpace ); 20664 20665 } 20666 20667 array.push( parameters.customProgramCacheKey ); 20668 20669 return array.join(); 20670 20671 } 20672 20673 function getProgramCacheKeyParameters( array, parameters ) { 20674 20675 array.push( parameters.precision ); 20676 array.push( parameters.outputColorSpace ); 20677 array.push( parameters.envMapMode ); 20678 array.push( parameters.envMapCubeUVHeight ); 20679 array.push( parameters.mapUv ); 20680 array.push( parameters.alphaMapUv ); 20681 array.push( parameters.lightMapUv ); 20682 array.push( parameters.aoMapUv ); 20683 array.push( parameters.bumpMapUv ); 20684 array.push( parameters.normalMapUv ); 20685 array.push( parameters.displacementMapUv ); 20686 array.push( parameters.emissiveMapUv ); 20687 array.push( parameters.metalnessMapUv ); 20688 array.push( parameters.roughnessMapUv ); 20689 array.push( parameters.anisotropyMapUv ); 20690 array.push( parameters.clearcoatMapUv ); 20691 array.push( parameters.clearcoatNormalMapUv ); 20692 array.push( parameters.clearcoatRoughnessMapUv ); 20693 array.push( parameters.iridescenceMapUv ); 20694 array.push( parameters.iridescenceThicknessMapUv ); 20695 array.push( parameters.sheenColorMapUv ); 20696 array.push( parameters.sheenRoughnessMapUv ); 20697 array.push( parameters.specularMapUv ); 20698 array.push( parameters.specularColorMapUv ); 20699 array.push( parameters.specularIntensityMapUv ); 20700 array.push( parameters.transmissionMapUv ); 20701 array.push( parameters.thicknessMapUv ); 20702 array.push( parameters.combine ); 20703 array.push( parameters.fogExp2 ); 20704 array.push( parameters.sizeAttenuation ); 20705 array.push( parameters.morphTargetsCount ); 20706 array.push( parameters.morphAttributeCount ); 20707 array.push( parameters.numDirLights ); 20708 array.push( parameters.numPointLights ); 20709 array.push( parameters.numSpotLights ); 20710 array.push( parameters.numSpotLightMaps ); 20711 array.push( parameters.numHemiLights ); 20712 array.push( parameters.numRectAreaLights ); 20713 array.push( parameters.numDirLightShadows ); 20714 array.push( parameters.numPointLightShadows ); 20715 array.push( parameters.numSpotLightShadows ); 20716 array.push( parameters.numSpotLightShadowsWithMaps ); 20717 array.push( parameters.numLightProbes ); 20718 array.push( parameters.shadowMapType ); 20719 array.push( parameters.toneMapping ); 20720 array.push( parameters.numClippingPlanes ); 20721 array.push( parameters.numClipIntersection ); 20722 array.push( parameters.depthPacking ); 20723 20724 } 20725 20726 function getProgramCacheKeyBooleans( array, parameters ) { 20727 20728 _programLayers.disableAll(); 20729 20730 if ( parameters.supportsVertexTextures ) 20731 _programLayers.enable( 0 ); 20732 if ( parameters.instancing ) 20733 _programLayers.enable( 1 ); 20734 if ( parameters.instancingColor ) 20735 _programLayers.enable( 2 ); 20736 if ( parameters.instancingMorph ) 20737 _programLayers.enable( 3 ); 20738 if ( parameters.matcap ) 20739 _programLayers.enable( 4 ); 20740 if ( parameters.envMap ) 20741 _programLayers.enable( 5 ); 20742 if ( parameters.normalMapObjectSpace ) 20743 _programLayers.enable( 6 ); 20744 if ( parameters.normalMapTangentSpace ) 20745 _programLayers.enable( 7 ); 20746 if ( parameters.clearcoat ) 20747 _programLayers.enable( 8 ); 20748 if ( parameters.iridescence ) 20749 _programLayers.enable( 9 ); 20750 if ( parameters.alphaTest ) 20751 _programLayers.enable( 10 ); 20752 if ( parameters.vertexColors ) 20753 _programLayers.enable( 11 ); 20754 if ( parameters.vertexAlphas ) 20755 _programLayers.enable( 12 ); 20756 if ( parameters.vertexUv1s ) 20757 _programLayers.enable( 13 ); 20758 if ( parameters.vertexUv2s ) 20759 _programLayers.enable( 14 ); 20760 if ( parameters.vertexUv3s ) 20761 _programLayers.enable( 15 ); 20762 if ( parameters.vertexTangents ) 20763 _programLayers.enable( 16 ); 20764 if ( parameters.anisotropy ) 20765 _programLayers.enable( 17 ); 20766 if ( parameters.alphaHash ) 20767 _programLayers.enable( 18 ); 20768 if ( parameters.batching ) 20769 _programLayers.enable( 19 ); 20770 20771 array.push( _programLayers.mask ); 20772 _programLayers.disableAll(); 20773 20774 if ( parameters.fog ) 20775 _programLayers.enable( 0 ); 20776 if ( parameters.useFog ) 20777 _programLayers.enable( 1 ); 20778 if ( parameters.flatShading ) 20779 _programLayers.enable( 2 ); 20780 if ( parameters.logarithmicDepthBuffer ) 20781 _programLayers.enable( 3 ); 20782 if ( parameters.skinning ) 20783 _programLayers.enable( 4 ); 20784 if ( parameters.morphTargets ) 20785 _programLayers.enable( 5 ); 20786 if ( parameters.morphNormals ) 20787 _programLayers.enable( 6 ); 20788 if ( parameters.morphColors ) 20789 _programLayers.enable( 7 ); 20790 if ( parameters.premultipliedAlpha ) 20791 _programLayers.enable( 8 ); 20792 if ( parameters.shadowMapEnabled ) 20793 _programLayers.enable( 9 ); 20794 if ( parameters.useLegacyLights ) 20795 _programLayers.enable( 10 ); 20796 if ( parameters.doubleSided ) 20797 _programLayers.enable( 11 ); 20798 if ( parameters.flipSided ) 20799 _programLayers.enable( 12 ); 20800 if ( parameters.useDepthPacking ) 20801 _programLayers.enable( 13 ); 20802 if ( parameters.dithering ) 20803 _programLayers.enable( 14 ); 20804 if ( parameters.transmission ) 20805 _programLayers.enable( 15 ); 20806 if ( parameters.sheen ) 20807 _programLayers.enable( 16 ); 20808 if ( parameters.opaque ) 20809 _programLayers.enable( 17 ); 20810 if ( parameters.pointsUvs ) 20811 _programLayers.enable( 18 ); 20812 if ( parameters.decodeVideoTexture ) 20813 _programLayers.enable( 19 ); 20814 if ( parameters.alphaToCoverage ) 20815 _programLayers.enable( 20 ); 20816 20817 array.push( _programLayers.mask ); 20818 20819 } 20820 20821 function getUniforms( material ) { 20822 20823 const shaderID = shaderIDs[ material.type ]; 20824 let uniforms; 20825 20826 if ( shaderID ) { 20827 20828 const shader = ShaderLib[ shaderID ]; 20829 uniforms = UniformsUtils.clone( shader.uniforms ); 20830 20831 } else { 20832 20833 uniforms = material.uniforms; 20834 20835 } 20836 20837 return uniforms; 20838 20839 } 20840 20841 function acquireProgram( parameters, cacheKey ) { 20842 20843 let program; 20844 20845 // Check if code has been already compiled 20846 for ( let p = 0, pl = programs.length; p < pl; p ++ ) { 20847 20848 const preexistingProgram = programs[ p ]; 20849 20850 if ( preexistingProgram.cacheKey === cacheKey ) { 20851 20852 program = preexistingProgram; 20853 ++ program.usedTimes; 20854 20855 break; 20856 20857 } 20858 20859 } 20860 20861 if ( program === undefined ) { 20862 20863 program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates ); 20864 programs.push( program ); 20865 20866 } 20867 20868 return program; 20869 20870 } 20871 20872 function releaseProgram( program ) { 20873 20874 if ( -- program.usedTimes === 0 ) { 20875 20876 // Remove from unordered set 20877 const i = programs.indexOf( program ); 20878 programs[ i ] = programs[ programs.length - 1 ]; 20879 programs.pop(); 20880 20881 // Free WebGL resources 20882 program.destroy(); 20883 20884 } 20885 20886 } 20887 20888 function releaseShaderCache( material ) { 20889 20890 _customShaders.remove( material ); 20891 20892 } 20893 20894 function dispose() { 20895 20896 _customShaders.dispose(); 20897 20898 } 20899 20900 return { 20901 getParameters: getParameters, 20902 getProgramCacheKey: getProgramCacheKey, 20903 getUniforms: getUniforms, 20904 acquireProgram: acquireProgram, 20905 releaseProgram: releaseProgram, 20906 releaseShaderCache: releaseShaderCache, 20907 // Exposed for resource monitoring & error feedback via renderer.info: 20908 programs: programs,
vendor: 4,538 bytes, lines 20909-21190
20909 dispose: dispose 20910 }; 20911 20912} 20913 20914function WebGLProperties() { 20915 20916 let properties = new WeakMap(); 20917 20918 function get( object ) { 20919 20920 let map = properties.get( object ); 20921 20922 if ( map === undefined ) { 20923 20924 map = {}; 20925 properties.set( object, map ); 20926 20927 } 20928 20929 return map; 20930 20931 } 20932 20933 function remove( object ) { 20934 20935 properties.delete( object ); 20936 20937 } 20938 20939 function update( object, key, value ) { 20940 20941 properties.get( object )[ key ] = value; 20942 20943 } 20944 20945 function dispose() { 20946 20947 properties = new WeakMap(); 20948 20949 } 20950 20951 return { 20952 get: get, 20953 remove: remove, 20954 update: update, 20955 dispose: dispose 20956 }; 20957 20958} 20959 20960function painterSortStable( a, b ) { 20961 20962 if ( a.groupOrder !== b.groupOrder ) { 20963 20964 return a.groupOrder - b.groupOrder; 20965 20966 } else if ( a.renderOrder !== b.renderOrder ) { 20967 20968 return a.renderOrder - b.renderOrder; 20969 20970 } else if ( a.material.id !== b.material.id ) { 20971 20972 return a.material.id - b.material.id; 20973 20974 } else if ( a.z !== b.z ) { 20975 20976 return a.z - b.z; 20977 20978 } else { 20979 20980 return a.id - b.id; 20981 20982 } 20983 20984} 20985 20986function reversePainterSortStable( a, b ) { 20987 20988 if ( a.groupOrder !== b.groupOrder ) { 20989 20990 return a.groupOrder - b.groupOrder; 20991 20992 } else if ( a.renderOrder !== b.renderOrder ) { 20993 20994 return a.renderOrder - b.renderOrder; 20995 20996 } else if ( a.z !== b.z ) { 20997 20998 return b.z - a.z; 20999 21000 } else { 21001 21002 return a.id - b.id; 21003 21004 } 21005 21006} 21007 21008 21009function WebGLRenderList() { 21010 21011 const renderItems = []; 21012 let renderItemsIndex = 0; 21013 21014 const opaque = []; 21015 const transmissive = []; 21016 const transparent = []; 21017 21018 function init() { 21019 21020 renderItemsIndex = 0; 21021 21022 opaque.length = 0; 21023 transmissive.length = 0; 21024 transparent.length = 0; 21025 21026 } 21027 21028 function getNextRenderItem( object, geometry, material, groupOrder, z, group ) { 21029 21030 let renderItem = renderItems[ renderItemsIndex ]; 21031 21032 if ( renderItem === undefined ) { 21033 21034 renderItem = { 21035 id: object.id, 21036 object: object, 21037 geometry: geometry, 21038 material: material, 21039 groupOrder: groupOrder, 21040 renderOrder: object.renderOrder, 21041 z: z, 21042 group: group 21043 }; 21044 21045 renderItems[ renderItemsIndex ] = renderItem; 21046 21047 } else { 21048 21049 renderItem.id = object.id; 21050 renderItem.object = object; 21051 renderItem.geometry = geometry; 21052 renderItem.material = material; 21053 renderItem.groupOrder = groupOrder; 21054 renderItem.renderOrder = object.renderOrder; 21055 renderItem.z = z; 21056 renderItem.group = group; 21057 21058 } 21059 21060 renderItemsIndex ++; 21061 21062 return renderItem; 21063 21064 } 21065 21066 function push( object, geometry, material, groupOrder, z, group ) { 21067 21068 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); 21069 21070 if ( material.transmission > 0.0 ) { 21071 21072 transmissive.push( renderItem ); 21073 21074 } else if ( material.transparent === true ) { 21075 21076 transparent.push( renderItem ); 21077 21078 } else { 21079 21080 opaque.push( renderItem ); 21081 21082 } 21083 21084 } 21085 21086 function unshift( object, geometry, material, groupOrder, z, group ) { 21087 21088 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); 21089 21090 if ( material.transmission > 0.0 ) { 21091 21092 transmissive.unshift( renderItem ); 21093 21094 } else if ( material.transparent === true ) { 21095 21096 transparent.unshift( renderItem ); 21097 21098 } else { 21099 21100 opaque.unshift( renderItem ); 21101 21102 } 21103 21104 } 21105 21106 function sort( customOpaqueSort, customTransparentSort ) { 21107 21108 if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable ); 21109 if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable ); 21110 if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable ); 21111 21112 } 21113 21114 function finish() { 21115 21116 // Clear references from inactive renderItems in the list 21117 21118 for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) { 21119 21120 const renderItem = renderItems[ i ]; 21121 21122 if ( renderItem.id === null ) break; 21123 21124 renderItem.id = null; 21125 renderItem.object = null; 21126 renderItem.geometry = null; 21127 renderItem.material = null; 21128 renderItem.group = null; 21129 21130 } 21131 21132 } 21133 21134 return { 21135 21136 opaque: opaque, 21137 transmissive: transmissive, 21138 transparent: transparent, 21139 21140 init: init, 21141 push: push, 21142 unshift: unshift, 21143 finish: finish, 21144 21145 sort: sort 21146 }; 21147 21148} 21149 21150function WebGLRenderLists() { 21151 21152 let lists = new WeakMap(); 21153 21154 function get( scene, renderCallDepth ) { 21155 21156 const listArray = lists.get( scene ); 21157 let list; 21158 21159 if ( listArray === undefined ) { 21160 21161 list = new WebGLRenderList(); 21162 lists.set( scene, [ list ] ); 21163 21164 } else { 21165 21166 if ( renderCallDepth >= listArray.length ) { 21167 21168 list = new WebGLRenderList(); 21169 listArray.push( list ); 21170 21171 } else { 21172 21173 list = listArray[ renderCallDepth ]; 21174 21175 } 21176 21177 } 21178 21179 return list; 21180 21181 } 21182 21183 function dispose() { 21184 21185 lists = new WeakMap(); 21186 21187 } 21188 21189 return { 21190 get: get,
vendor: 10,595 bytes, lines 21191-21653
21191 dispose: dispose 21192 }; 21193 21194} 21195 21196function UniformsCache() { 21197 21198 const lights = {}; 21199 21200 return { 21201 21202 get: function ( light ) { 21203 21204 if ( lights[ light.id ] !== undefined ) { 21205 21206 return lights[ light.id ]; 21207 21208 } 21209 21210 let uniforms; 21211 21212 switch ( light.type ) { 21213 21214 case 'DirectionalLight': 21215 uniforms = { 21216 direction: new Vector3(), 21217 color: new Color() 21218 }; 21219 break; 21220 21221 case 'SpotLight': 21222 uniforms = { 21223 position: new Vector3(), 21224 direction: new Vector3(), 21225 color: new Color(), 21226 distance: 0, 21227 coneCos: 0, 21228 penumbraCos: 0, 21229 decay: 0 21230 }; 21231 break; 21232 21233 case 'PointLight': 21234 uniforms = { 21235 position: new Vector3(), 21236 color: new Color(), 21237 distance: 0, 21238 decay: 0 21239 }; 21240 break; 21241 21242 case 'HemisphereLight': 21243 uniforms = { 21244 direction: new Vector3(), 21245 skyColor: new Color(), 21246 groundColor: new Color() 21247 }; 21248 break; 21249 21250 case 'RectAreaLight': 21251 uniforms = { 21252 color: new Color(), 21253 position: new Vector3(), 21254 halfWidth: new Vector3(), 21255 halfHeight: new Vector3() 21256 }; 21257 break; 21258 21259 } 21260 21261 lights[ light.id ] = uniforms; 21262 21263 return uniforms; 21264 21265 } 21266 21267 }; 21268 21269} 21270 21271function ShadowUniformsCache() { 21272 21273 const lights = {}; 21274 21275 return { 21276 21277 get: function ( light ) { 21278 21279 if ( lights[ light.id ] !== undefined ) { 21280 21281 return lights[ light.id ]; 21282 21283 } 21284 21285 let uniforms; 21286 21287 switch ( light.type ) { 21288 21289 case 'DirectionalLight': 21290 uniforms = { 21291 shadowBias: 0, 21292 shadowNormalBias: 0, 21293 shadowRadius: 1, 21294 shadowMapSize: new Vector2() 21295 }; 21296 break; 21297 21298 case 'SpotLight': 21299 uniforms = { 21300 shadowBias: 0, 21301 shadowNormalBias: 0, 21302 shadowRadius: 1, 21303 shadowMapSize: new Vector2() 21304 }; 21305 break; 21306 21307 case 'PointLight': 21308 uniforms = { 21309 shadowBias: 0, 21310 shadowNormalBias: 0, 21311 shadowRadius: 1, 21312 shadowMapSize: new Vector2(), 21313 shadowCameraNear: 1, 21314 shadowCameraFar: 1000 21315 }; 21316 break; 21317 21318 // TODO (abelnation): set RectAreaLight shadow uniforms 21319 21320 } 21321 21322 lights[ light.id ] = uniforms; 21323 21324 return uniforms; 21325 21326 } 21327 21328 }; 21329 21330} 21331 21332 21333 21334let nextVersion = 0; 21335 21336function shadowCastingAndTexturingLightsFirst( lightA, lightB ) { 21337 21338 return ( lightB.castShadow ? 2 : 0 ) - ( lightA.castShadow ? 2 : 0 ) + ( lightB.map ? 1 : 0 ) - ( lightA.map ? 1 : 0 ); 21339 21340} 21341 21342function WebGLLights( extensions ) { 21343 21344 const cache = new UniformsCache(); 21345 21346 const shadowCache = ShadowUniformsCache(); 21347 21348 const state = { 21349 21350 version: 0, 21351 21352 hash: { 21353 directionalLength: - 1, 21354 pointLength: - 1, 21355 spotLength: - 1, 21356 rectAreaLength: - 1, 21357 hemiLength: - 1, 21358 21359 numDirectionalShadows: - 1, 21360 numPointShadows: - 1, 21361 numSpotShadows: - 1, 21362 numSpotMaps: - 1, 21363 21364 numLightProbes: - 1 21365 }, 21366 21367 ambient: [ 0, 0, 0 ], 21368 probe: [], 21369 directional: [], 21370 directionalShadow: [], 21371 directionalShadowMap: [], 21372 directionalShadowMatrix: [], 21373 spot: [], 21374 spotLightMap: [], 21375 spotShadow: [], 21376 spotShadowMap: [], 21377 spotLightMatrix: [], 21378 rectArea: [], 21379 rectAreaLTC1: null, 21380 rectAreaLTC2: null, 21381 point: [], 21382 pointShadow: [], 21383 pointShadowMap: [], 21384 pointShadowMatrix: [], 21385 hemi: [], 21386 numSpotLightShadowsWithMaps: 0, 21387 numLightProbes: 0 21388 21389 }; 21390 21391 for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() ); 21392 21393 const vector3 = new Vector3(); 21394 const matrix4 = new Matrix4(); 21395 const matrix42 = new Matrix4(); 21396 21397 function setup( lights, useLegacyLights ) { 21398 21399 let r = 0, g = 0, b = 0; 21400 21401 for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 ); 21402 21403 let directionalLength = 0; 21404 let pointLength = 0; 21405 let spotLength = 0; 21406 let rectAreaLength = 0; 21407 let hemiLength = 0; 21408 21409 let numDirectionalShadows = 0; 21410 let numPointShadows = 0; 21411 let numSpotShadows = 0; 21412 let numSpotMaps = 0; 21413 let numSpotShadowsWithMaps = 0; 21414 21415 let numLightProbes = 0; 21416 21417 // ordering : [shadow casting + map texturing, map texturing, shadow casting, none ] 21418 lights.sort( shadowCastingAndTexturingLightsFirst ); 21419 21420 // artist-friendly light intensity scaling factor 21421 const scaleFactor = ( useLegacyLights === true ) ? Math.PI : 1; 21422 21423 for ( let i = 0, l = lights.length; i < l; i ++ ) { 21424 21425 const light = lights[ i ]; 21426 21427 const color = light.color; 21428 const intensity = light.intensity; 21429 const distance = light.distance; 21430 21431 const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; 21432 21433 if ( light.isAmbientLight ) { 21434 21435 r += color.r * intensity * scaleFactor; 21436 g += color.g * intensity * scaleFactor; 21437 b += color.b * intensity * scaleFactor; 21438 21439 } else if ( light.isLightProbe ) { 21440 21441 for ( let j = 0; j < 9; j ++ ) { 21442 21443 state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity ); 21444 21445 } 21446 21447 numLightProbes ++; 21448 21449 } else if ( light.isDirectionalLight ) { 21450 21451 const uniforms = cache.get( light ); 21452 21453 uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor ); 21454 21455 if ( light.castShadow ) { 21456 21457 const shadow = light.shadow; 21458 21459 const shadowUniforms = shadowCache.get( light ); 21460 21461 shadowUniforms.shadowBias = shadow.bias; 21462 shadowUniforms.shadowNormalBias = shadow.normalBias; 21463 shadowUniforms.shadowRadius = shadow.radius; 21464 shadowUniforms.shadowMapSize = shadow.mapSize; 21465 21466 state.directionalShadow[ directionalLength ] = shadowUniforms; 21467 state.directionalShadowMap[ directionalLength ] = shadowMap; 21468 state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; 21469 21470 numDirectionalShadows ++; 21471 21472 } 21473 21474 state.directional[ directionalLength ] = uniforms; 21475 21476 directionalLength ++; 21477 21478 } else if ( light.isSpotLight ) { 21479 21480 const uniforms = cache.get( light ); 21481 21482 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 21483 21484 uniforms.color.copy( color ).multiplyScalar( intensity * scaleFactor ); 21485 uniforms.distance = distance; 21486 21487 uniforms.coneCos = Math.cos( light.angle ); 21488 uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); 21489 uniforms.decay = light.decay; 21490 21491 state.spot[ spotLength ] = uniforms; 21492 21493 const shadow = light.shadow; 21494 21495 if ( light.map ) { 21496 21497 state.spotLightMap[ numSpotMaps ] = light.map; 21498 numSpotMaps ++; 21499 21500 // make sure the lightMatrix is up to date 21501 // TODO : do it if required only 21502 shadow.updateMatrices( light ); 21503 21504 if ( light.castShadow ) numSpotShadowsWithMaps ++; 21505 21506 } 21507 21508 state.spotLightMatrix[ spotLength ] = shadow.matrix; 21509 21510 if ( light.castShadow ) { 21511 21512 const shadowUniforms = shadowCache.get( light ); 21513 21514 shadowUniforms.shadowBias = shadow.bias; 21515 shadowUniforms.shadowNormalBias = shadow.normalBias; 21516 shadowUniforms.shadowRadius = shadow.radius; 21517 shadowUniforms.shadowMapSize = shadow.mapSize; 21518 21519 state.spotShadow[ spotLength ] = shadowUniforms; 21520 state.spotShadowMap[ spotLength ] = shadowMap; 21521 21522 numSpotShadows ++; 21523 21524 } 21525 21526 spotLength ++; 21527 21528 } else if ( light.isRectAreaLight ) { 21529 21530 const uniforms = cache.get( light ); 21531 21532 uniforms.color.copy( color ).multiplyScalar( intensity ); 21533 21534 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); 21535 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); 21536 21537 state.rectArea[ rectAreaLength ] = uniforms; 21538 21539 rectAreaLength ++; 21540 21541 } else if ( light.isPointLight ) { 21542 21543 const uniforms = cache.get( light ); 21544 21545 uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor ); 21546 uniforms.distance = light.distance; 21547 uniforms.decay = light.decay; 21548 21549 if ( light.castShadow ) { 21550 21551 const shadow = light.shadow; 21552 21553 const shadowUniforms = shadowCache.get( light ); 21554 21555 shadowUniforms.shadowBias = shadow.bias; 21556 shadowUniforms.shadowNormalBias = shadow.normalBias; 21557 shadowUniforms.shadowRadius = shadow.radius; 21558 shadowUniforms.shadowMapSize = shadow.mapSize; 21559 shadowUniforms.shadowCameraNear = shadow.camera.near; 21560 shadowUniforms.shadowCameraFar = shadow.camera.far; 21561 21562 state.pointShadow[ pointLength ] = shadowUniforms; 21563 state.pointShadowMap[ pointLength ] = shadowMap; 21564 state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; 21565 21566 numPointShadows ++; 21567 21568 } 21569 21570 state.point[ pointLength ] = uniforms; 21571 21572 pointLength ++; 21573 21574 } else if ( light.isHemisphereLight ) { 21575 21576 const uniforms = cache.get( light ); 21577 21578 uniforms.skyColor.copy( light.color ).multiplyScalar( intensity * scaleFactor ); 21579 uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity * scaleFactor ); 21580 21581 state.hemi[ hemiLength ] = uniforms; 21582 21583 hemiLength ++; 21584 21585 } 21586 21587 } 21588 21589 if ( rectAreaLength > 0 ) { 21590 21591 if ( extensions.has( 'OES_texture_float_linear' ) === true ) { 21592 21593 state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1; 21594 state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2; 21595 21596 } else { 21597 21598 state.rectAreaLTC1 = UniformsLib.LTC_HALF_1; 21599 state.rectAreaLTC2 = UniformsLib.LTC_HALF_2; 21600 21601 } 21602 21603 } 21604 21605 state.ambient[ 0 ] = r; 21606 state.ambient[ 1 ] = g; 21607 state.ambient[ 2 ] = b; 21608 21609 const hash = state.hash; 21610 21611 if ( hash.directionalLength !== directionalLength || 21612 hash.pointLength !== pointLength || 21613 hash.spotLength !== spotLength || 21614 hash.rectAreaLength !== rectAreaLength || 21615 hash.hemiLength !== hemiLength || 21616 hash.numDirectionalShadows !== numDirectionalShadows || 21617 hash.numPointShadows !== numPointShadows || 21618 hash.numSpotShadows !== numSpotShadows || 21619 hash.numSpotMaps !== numSpotMaps || 21620 hash.numLightProbes !== numLightProbes ) { 21621 21622 state.directional.length = directionalLength; 21623 state.spot.length = spotLength; 21624 state.rectArea.length = rectAreaLength; 21625 state.point.length = pointLength; 21626 state.hemi.length = hemiLength; 21627 21628 state.directionalShadow.length = numDirectionalShadows; 21629 state.directionalShadowMap.length = numDirectionalShadows; 21630 state.pointShadow.length = numPointShadows; 21631 state.pointShadowMap.length = numPointShadows; 21632 state.spotShadow.length = numSpotShadows; 21633 state.spotShadowMap.length = numSpotShadows; 21634 state.directionalShadowMatrix.length = numDirectionalShadows; 21635 state.pointShadowMatrix.length = numPointShadows; 21636 state.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps; 21637 state.spotLightMap.length = numSpotMaps; 21638 state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps; 21639 state.numLightProbes = numLightProbes; 21640 21641 hash.directionalLength = directionalLength; 21642 hash.pointLength = pointLength; 21643 hash.spotLength = spotLength; 21644 hash.rectAreaLength = rectAreaLength; 21645 hash.hemiLength = hemiLength; 21646 21647 hash.numDirectionalShadows = numDirectionalShadows; 21648 hash.numPointShadows = numPointShadows; 21649 hash.numSpotShadows = numSpotShadows; 21650 hash.numSpotMaps = numSpotMaps; 21651 21652 hash.numLightProbes = numLightProbes; 21653
vendor: 4,314 bytes, lines 21654-21877
21654 state.version = nextVersion ++; 21655 21656 } 21657 21658 } 21659 21660 function setupView( lights, camera ) { 21661 21662 let directionalLength = 0; 21663 let pointLength = 0; 21664 let spotLength = 0; 21665 let rectAreaLength = 0; 21666 let hemiLength = 0; 21667 21668 const viewMatrix = camera.matrixWorldInverse; 21669 21670 for ( let i = 0, l = lights.length; i < l; i ++ ) { 21671 21672 const light = lights[ i ]; 21673 21674 if ( light.isDirectionalLight ) { 21675 21676 const uniforms = state.directional[ directionalLength ]; 21677 21678 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 21679 vector3.setFromMatrixPosition( light.target.matrixWorld ); 21680 uniforms.direction.sub( vector3 ); 21681 uniforms.direction.transformDirection( viewMatrix ); 21682 21683 directionalLength ++; 21684 21685 } else if ( light.isSpotLight ) { 21686 21687 const uniforms = state.spot[ spotLength ]; 21688 21689 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 21690 uniforms.position.applyMatrix4( viewMatrix ); 21691 21692 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 21693 vector3.setFromMatrixPosition( light.target.matrixWorld ); 21694 uniforms.direction.sub( vector3 ); 21695 uniforms.direction.transformDirection( viewMatrix ); 21696 21697 spotLength ++; 21698 21699 } else if ( light.isRectAreaLight ) { 21700 21701 const uniforms = state.rectArea[ rectAreaLength ]; 21702 21703 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 21704 uniforms.position.applyMatrix4( viewMatrix ); 21705 21706 // extract local rotation of light to derive width/height half vectors 21707 matrix42.identity(); 21708 matrix4.copy( light.matrixWorld ); 21709 matrix4.premultiply( viewMatrix ); 21710 matrix42.extractRotation( matrix4 ); 21711 21712 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); 21713 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); 21714 21715 uniforms.halfWidth.applyMatrix4( matrix42 ); 21716 uniforms.halfHeight.applyMatrix4( matrix42 ); 21717 21718 rectAreaLength ++; 21719 21720 } else if ( light.isPointLight ) { 21721 21722 const uniforms = state.point[ pointLength ]; 21723 21724 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 21725 uniforms.position.applyMatrix4( viewMatrix ); 21726 21727 pointLength ++; 21728 21729 } else if ( light.isHemisphereLight ) { 21730 21731 const uniforms = state.hemi[ hemiLength ]; 21732 21733 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 21734 uniforms.direction.transformDirection( viewMatrix ); 21735 21736 hemiLength ++; 21737 21738 } 21739 21740 } 21741 21742 } 21743 21744 return { 21745 setup: setup, 21746 setupView: setupView, 21747 state: state 21748 }; 21749 21750} 21751 21752function WebGLRenderState( extensions ) { 21753 21754 const lights = new WebGLLights( extensions ); 21755 21756 const lightsArray = []; 21757 const shadowsArray = []; 21758 21759 function init() { 21760 21761 lightsArray.length = 0; 21762 shadowsArray.length = 0; 21763 21764 } 21765 21766 function pushLight( light ) { 21767 21768 lightsArray.push( light ); 21769 21770 } 21771 21772 function pushShadow( shadowLight ) { 21773 21774 shadowsArray.push( shadowLight ); 21775 21776 } 21777 21778 function setupLights( useLegacyLights ) { 21779 21780 lights.setup( lightsArray, useLegacyLights ); 21781 21782 } 21783 21784 function setupLightsView( camera ) { 21785 21786 lights.setupView( lightsArray, camera ); 21787 21788 } 21789 21790 const state = { 21791 lightsArray: lightsArray, 21792 shadowsArray: shadowsArray, 21793 21794 lights: lights, 21795 21796 transmissionRenderTarget: null 21797 }; 21798 21799 return { 21800 init: init, 21801 state: state, 21802 setupLights: setupLights, 21803 setupLightsView: setupLightsView, 21804 21805 pushLight: pushLight, 21806 pushShadow: pushShadow 21807 }; 21808 21809} 21810 21811function WebGLRenderStates( extensions ) { 21812 21813 let renderStates = new WeakMap(); 21814 21815 function get( scene, renderCallDepth = 0 ) { 21816 21817 const renderStateArray = renderStates.get( scene ); 21818 let renderState; 21819 21820 if ( renderStateArray === undefined ) { 21821 21822 renderState = new WebGLRenderState( extensions ); 21823 renderStates.set( scene, [ renderState ] ); 21824 21825 } else { 21826 21827 if ( renderCallDepth >= renderStateArray.length ) { 21828 21829 renderState = new WebGLRenderState( extensions ); 21830 renderStateArray.push( renderState ); 21831 21832 } else { 21833 21834 renderState = renderStateArray[ renderCallDepth ]; 21835 21836 } 21837 21838 } 21839 21840 return renderState; 21841 21842 } 21843 21844 function dispose() { 21845 21846 renderStates = new WeakMap(); 21847 21848 } 21849 21850 return { 21851 get: get, 21852 dispose: dispose 21853 }; 21854 21855} 21856 21857class MeshDepthMaterial extends Material { 21858 21859 constructor( parameters ) { 21860 21861 super(); 21862 21863 this.isMeshDepthMaterial = true; 21864 21865 this.type = 'MeshDepthMaterial'; 21866 21867 this.depthPacking = BasicDepthPacking; 21868 21869 this.map = null; 21870 21871 this.alphaMap = null; 21872 21873 this.displacementMap = null; 21874 this.displacementScale = 1; 21875 this.displacementBias = 0; 21876 21877 this.wireframe = false;
vendor: 3,393 bytes, lines 21878-21991
21878 this.wireframeLinewidth = 1; 21879 21880 this.setValues( parameters ); 21881 21882 } 21883 21884 copy( source ) { 21885 21886 super.copy( source ); 21887 21888 this.depthPacking = source.depthPacking; 21889 21890 this.map = source.map; 21891 21892 this.alphaMap = source.alphaMap; 21893 21894 this.displacementMap = source.displacementMap; 21895 this.displacementScale = source.displacementScale; 21896 this.displacementBias = source.displacementBias; 21897 21898 this.wireframe = source.wireframe; 21899 this.wireframeLinewidth = source.wireframeLinewidth; 21900 21901 return this; 21902 21903 } 21904 21905} 21906 21907class MeshDistanceMaterial extends Material { 21908 21909 constructor( parameters ) { 21910 21911 super(); 21912 21913 this.isMeshDistanceMaterial = true; 21914 21915 this.type = 'MeshDistanceMaterial'; 21916 21917 this.map = null; 21918 21919 this.alphaMap = null; 21920 21921 this.displacementMap = null; 21922 this.displacementScale = 1; 21923 this.displacementBias = 0; 21924 21925 this.setValues( parameters ); 21926 21927 } 21928 21929 copy( source ) { 21930 21931 super.copy( source ); 21932 21933 this.map = source.map; 21934 21935 this.alphaMap = source.alphaMap; 21936 21937 this.displacementMap = source.displacementMap; 21938 this.displacementScale = source.displacementScale; 21939 this.displacementBias = source.displacementBias; 21940 21941 return this; 21942 21943 } 21944 21945} 21946 21947const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}"; 21948 21949const 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}"; 21950 21951function WebGLShadowMap( _renderer, _objects, _capabilities ) { 21952 21953 let _frustum = new Frustum(); 21954 21955 const _shadowMapSize = new Vector2(), 21956 _viewportSize = new Vector2(), 21957 21958 _viewport = new Vector4(), 21959 21960 _depthMaterial = new MeshDepthMaterial( { depthPacking: RGBADepthPacking } ), 21961 _distanceMaterial = new MeshDistanceMaterial(), 21962 21963 _materialCache = {}, 21964 21965 _maxTextureSize = _capabilities.maxTextureSize; 21966 21967 const shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide }; 21968 21969 const shadowMaterialVertical = new ShaderMaterial( { 21970 defines: { 21971 VSM_SAMPLES: 8 21972 }, 21973 uniforms: { 21974 shadow_pass: { value: null }, 21975 resolution: { value: new Vector2() }, 21976 radius: { value: 4.0 } 21977 }, 21978 21979 vertexShader: vertex, 21980 fragmentShader: fragment 21981 21982 } ); 21983 21984 const shadowMaterialHorizontal = shadowMaterialVertical.clone(); 21985 shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1; 21986 21987 const fullScreenTri = new BufferGeometry(); 21988 fullScreenTri.setAttribute( 21989 'position', 21990 new BufferAttribute( 21991 new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, -
vendor: 9,734 bytes, lines 21991-22359
219911, 3, 0.5 ] ), 21992 3 21993 ) 21994 ); 21995 21996 const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical ); 21997 21998 const scope = this; 21999 22000 this.enabled = false; 22001 22002 this.autoUpdate = true; 22003 this.needsUpdate = false; 22004 22005 this.type = PCFShadowMap; 22006 let _previousType = this.type; 22007 22008 this.render = function ( lights, scene, camera ) { 22009 22010 if ( scope.enabled === false ) return; 22011 if ( scope.autoUpdate === false && scope.needsUpdate === false ) return; 22012 22013 if ( lights.length === 0 ) return; 22014 22015 const currentRenderTarget = _renderer.getRenderTarget(); 22016 const activeCubeFace = _renderer.getActiveCubeFace(); 22017 const activeMipmapLevel = _renderer.getActiveMipmapLevel(); 22018 22019 const _state = _renderer.state; 22020 22021 // Set GL state for depth map. 22022 _state.setBlending( NoBlending ); 22023 _state.buffers.color.setClear( 1, 1, 1, 1 ); 22024 _state.buffers.depth.setTest( true ); 22025 _state.setScissorTest( false ); 22026 22027 // check for shadow map type changes 22028 22029 const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap ); 22030 const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap ); 22031 22032 // render depth map 22033 22034 for ( let i = 0, il = lights.length; i < il; i ++ ) { 22035 22036 const light = lights[ i ]; 22037 const shadow = light.shadow; 22038 22039 if ( shadow === undefined ) { 22040 22041 console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); 22042 continue; 22043 22044 } 22045 22046 if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue; 22047 22048 _shadowMapSize.copy( shadow.mapSize ); 22049 22050 const shadowFrameExtents = shadow.getFrameExtents(); 22051 22052 _shadowMapSize.multiply( shadowFrameExtents ); 22053 22054 _viewportSize.copy( shadow.mapSize ); 22055 22056 if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) { 22057 22058 if ( _shadowMapSize.x > _maxTextureSize ) { 22059 22060 _viewportSize.x = Math.floor( _maxTextureSize / shadowFrameExtents.x ); 22061 _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x; 22062 shadow.mapSize.x = _viewportSize.x; 22063 22064 } 22065 22066 if ( _shadowMapSize.y > _maxTextureSize ) { 22067 22068 _viewportSize.y = Math.floor( _maxTextureSize / shadowFrameExtents.y ); 22069 _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y; 22070 shadow.mapSize.y = _viewportSize.y; 22071 22072 } 22073 22074 } 22075 22076 if ( shadow.map === null || toVSM === true || fromVSM === true ) { 22077 22078 const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; 22079 22080 if ( shadow.map !== null ) { 22081 22082 shadow.map.dispose(); 22083 22084 } 22085 22086 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); 22087 shadow.map.texture.name = light.name + '.shadowMap'; 22088 22089 shadow.camera.updateProjectionMatrix(); 22090 22091 } 22092 22093 _renderer.setRenderTarget( shadow.map ); 22094 _renderer.clear(); 22095 22096 const viewportCount = shadow.getViewportCount(); 22097 22098 for ( let vp = 0; vp < viewportCount; vp ++ ) { 22099 22100 const viewport = shadow.getViewport( vp ); 22101 22102 _viewport.set( 22103 _viewportSize.x * viewport.x, 22104 _viewportSize.y * viewport.y, 22105 _viewportSize.x * viewport.z, 22106 _viewportSize.y * viewport.w 22107 ); 22108 22109 _state.viewport( _viewport ); 22110 22111 shadow.updateMatrices( light, vp ); 22112 22113 _frustum = shadow.getFrustum(); 22114 22115 renderObject( scene, camera, shadow.camera, light, this.type ); 22116 22117 } 22118 22119 // do blur pass for VSM 22120 22121 if ( shadow.isPointLightShadow !== true && this.type === VSMShadowMap ) { 22122 22123 VSMPass( shadow, camera ); 22124 22125 } 22126 22127 shadow.needsUpdate = false; 22128 22129 } 22130 22131 _previousType = this.type; 22132 22133 scope.needsUpdate = false; 22134 22135 _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); 22136 22137 }; 22138 22139 function VSMPass( shadow, camera ) { 22140 22141 const geometry = _objects.update( fullScreenMesh ); 22142 22143 if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) { 22144 22145 shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples; 22146 shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples; 22147 22148 shadowMaterialVertical.needsUpdate = true; 22149 shadowMaterialHorizontal.needsUpdate = true; 22150 22151 } 22152 22153 if ( shadow.mapPass === null ) { 22154 22155 shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y ); 22156 22157 } 22158 22159 // vertical pass 22160 22161 shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture; 22162 shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize; 22163 shadowMaterialVertical.uniforms.radius.value = shadow.radius; 22164 _renderer.setRenderTarget( shadow.mapPass ); 22165 _renderer.clear(); 22166 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null ); 22167 22168 // horizontal pass 22169 22170 shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture; 22171 shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize; 22172 shadowMaterialHorizontal.uniforms.radius.value = shadow.radius; 22173 _renderer.setRenderTarget( shadow.map ); 22174 _renderer.clear(); 22175 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null ); 22176 22177 } 22178 22179 function getDepthMaterial( object, material, light, type ) { 22180 22181 let result = null; 22182 22183 const customMaterial = ( light.isPointLight === true ) ? object.customDistanceMaterial : object.customDepthMaterial; 22184 22185 if ( customMaterial !== undefined ) { 22186 22187 result = customMaterial; 22188 22189 } else { 22190 22191 result = ( light.isPointLight === true ) ? _distanceMaterial : _depthMaterial; 22192 22193 if ( ( _renderer.localClippingEnabled && material.clipShadows === true && Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) || 22194 ( material.displacementMap && material.displacementScale !== 0 ) || 22195 ( material.alphaMap && material.alphaTest > 0 ) || 22196 ( material.map && material.alphaTest > 0 ) ) { 22197 22198 // in this case we need a unique material instance reflecting the 22199 // appropriate state 22200 22201 const keyA = result.uuid, keyB = material.uuid; 22202 22203 let materialsForVariant = _materialCache[ keyA ]; 22204 22205 if ( materialsForVariant === undefined ) { 22206 22207 materialsForVariant = {}; 22208 _materialCache[ keyA ] = materialsForVariant; 22209 22210 } 22211 22212 let cachedMaterial = materialsForVariant[ keyB ]; 22213 22214 if ( cachedMaterial === undefined ) { 22215 22216 cachedMaterial = result.clone(); 22217 materialsForVariant[ keyB ] = cachedMaterial; 22218 material.addEventListener( 'dispose', onMaterialDispose ); 22219 22220 } 22221 22222 result = cachedMaterial; 22223 22224 } 22225 22226 } 22227 22228 result.visible = material.visible; 22229 result.wireframe = material.wireframe; 22230 22231 if ( type === VSMShadowMap ) { 22232 22233 result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side; 22234 22235 } else { 22236 22237 result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ]; 22238 22239 } 22240 22241 result.alphaMap = material.alphaMap; 22242 result.alphaTest = material.alphaTest; 22243 result.map = material.map; 22244 22245 result.clipShadows = material.clipShadows; 22246 result.clippingPlanes = material.clippingPlanes; 22247 result.clipIntersection = material.clipIntersection; 22248 22249 result.displacementMap = material.displacementMap; 22250 result.displacementScale = material.displacementScale; 22251 result.displacementBias = material.displacementBias; 22252 22253 result.wireframeLinewidth = material.wireframeLinewidth; 22254 result.linewidth = material.linewidth; 22255 22256 if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) { 22257 22258 const materialProperties = _renderer.properties.get( result ); 22259 materialProperties.light = light; 22260 22261 } 22262 22263 return result; 22264 22265 } 22266 22267 function renderObject( object, camera, shadowCamera, light, type ) { 22268 22269 if ( object.visible === false ) return; 22270 22271 const visible = object.layers.test( camera.layers ); 22272 22273 if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { 22274 22275 if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { 22276 22277 object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); 22278 22279 const geometry = _objects.update( object ); 22280 const material = object.material; 22281 22282 if ( Array.isArray( material ) ) { 22283 22284 const groups = geometry.groups; 22285 22286 for ( let k = 0, kl = groups.length; k < kl; k ++ ) { 22287 22288 const group = groups[ k ]; 22289 const groupMaterial = material[ group.materialIndex ]; 22290 22291 if ( groupMaterial && groupMaterial.visible ) { 22292 22293 const depthMaterial = getDepthMaterial( object, groupMaterial, light, type ); 22294 22295 object.onBeforeShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); 22296 22297 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); 22298 22299 object.onAfterShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); 22300 22301 } 22302 22303 } 22304 22305 } else if ( material.visible ) { 22306 22307 const depthMaterial = getDepthMaterial( object, material, light, type ); 22308 22309 object.onBeforeShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); 22310 22311 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); 22312 22313 object.onAfterShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); 22314 22315 } 22316 22317 } 22318 22319 } 22320 22321 const children = object.children; 22322 22323 for ( let i = 0, l = children.length; i < l; i ++ ) { 22324 22325 renderObject( children[ i ], camera, shadowCamera, light, type ); 22326 22327 } 22328 22329 } 22330 22331 function onMaterialDispose( event ) { 22332 22333 const material = event.target; 22334 22335 material.removeEventListener( 'dispose', onMaterialDispose ); 22336 22337 // make sure to remove the unique distance/depth materials used for shadow map rendering 22338 22339 for ( const id in _materialCache ) { 22340 22341 const cache = _materialCache[ id ]; 22342 22343 const uuid = event.target.uuid; 22344 22345 if ( uuid in cache ) { 22346 22347 const shadowMaterial = cache[ uuid ]; 22348 shadowMaterial.dispose(); 22349 delete cache[ uuid ]; 22350 22351 } 22352 22353 } 22354 22355 } 22356 22357} 22358 22359function WebGLState( gl
vendor: 9,931 bytes, lines 22359-22898
22359 ) { 22360 22361 function ColorBuffer() { 22362 22363 let locked = false; 22364 22365 const color = new Vector4(); 22366 let currentColorMask = null; 22367 const currentColorClear = new Vector4( 0, 0, 0, 0 ); 22368 22369 return { 22370 22371 setMask: function ( colorMask ) { 22372 22373 if ( currentColorMask !== colorMask && ! locked ) { 22374 22375 gl.colorMask( colorMask, colorMask, colorMask, colorMask ); 22376 currentColorMask = colorMask; 22377 22378 } 22379 22380 }, 22381 22382 setLocked: function ( lock ) { 22383 22384 locked = lock; 22385 22386 }, 22387 22388 setClear: function ( r, g, b, a, premultipliedAlpha ) { 22389 22390 if ( premultipliedAlpha === true ) { 22391 22392 r *= a; g *= a; b *= a; 22393 22394 } 22395 22396 color.set( r, g, b, a ); 22397 22398 if ( currentColorClear.equals( color ) === false ) { 22399 22400 gl.clearColor( r, g, b, a ); 22401 currentColorClear.copy( color ); 22402 22403 } 22404 22405 }, 22406 22407 reset: function () { 22408 22409 locked = false; 22410 22411 currentColorMask = null; 22412 currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state 22413 22414 } 22415 22416 }; 22417 22418 } 22419 22420 function DepthBuffer() { 22421 22422 let locked = false; 22423 22424 let currentDepthMask = null; 22425 let currentDepthFunc = null; 22426 let currentDepthClear = null; 22427 22428 return { 22429 22430 setTest: function ( depthTest ) { 22431 22432 if ( depthTest ) { 22433 22434 enable( gl.DEPTH_TEST ); 22435 22436 } else { 22437 22438 disable( gl.DEPTH_TEST ); 22439 22440 } 22441 22442 }, 22443 22444 setMask: function ( depthMask ) { 22445 22446 if ( currentDepthMask !== depthMask && ! locked ) { 22447 22448 gl.depthMask( depthMask ); 22449 currentDepthMask = depthMask; 22450 22451 } 22452 22453 }, 22454 22455 setFunc: function ( depthFunc ) { 22456 22457 if ( currentDepthFunc !== depthFunc ) { 22458 22459 switch ( depthFunc ) { 22460 22461 case NeverDepth: 22462 22463 gl.depthFunc( gl.NEVER ); 22464 break; 22465 22466 case AlwaysDepth: 22467 22468 gl.depthFunc( gl.ALWAYS ); 22469 break; 22470 22471 case LessDepth: 22472 22473 gl.depthFunc( gl.LESS ); 22474 break; 22475 22476 case LessEqualDepth: 22477 22478 gl.depthFunc( gl.LEQUAL ); 22479 break; 22480 22481 case EqualDepth: 22482 22483 gl.depthFunc( gl.EQUAL ); 22484 break; 22485 22486 case GreaterEqualDepth: 22487 22488 gl.depthFunc( gl.GEQUAL ); 22489 break; 22490 22491 case GreaterDepth: 22492 22493 gl.depthFunc( gl.GREATER ); 22494 break; 22495 22496 case NotEqualDepth: 22497 22498 gl.depthFunc( gl.NOTEQUAL ); 22499 break; 22500 22501 default: 22502 22503 gl.depthFunc( gl.LEQUAL ); 22504 22505 } 22506 22507 currentDepthFunc = depthFunc; 22508 22509 } 22510 22511 }, 22512 22513 setLocked: function ( lock ) { 22514 22515 locked = lock; 22516 22517 }, 22518 22519 setClear: function ( depth ) { 22520 22521 if ( currentDepthClear !== depth ) { 22522 22523 gl.clearDepth( depth ); 22524 currentDepthClear = depth; 22525 22526 } 22527 22528 }, 22529 22530 reset: function () { 22531 22532 locked = false; 22533 22534 currentDepthMask = null; 22535 currentDepthFunc = null; 22536 currentDepthClear = null; 22537 22538 } 22539 22540 }; 22541 22542 } 22543 22544 function StencilBuffer() { 22545 22546 let locked = false; 22547 22548 let currentStencilMask = null; 22549 let currentStencilFunc = null; 22550 let currentStencilRef = null; 22551 let currentStencilFuncMask = null; 22552 let currentStencilFail = null; 22553 let currentStencilZFail = null; 22554 let currentStencilZPass = null; 22555 let currentStencilClear = null; 22556 22557 return { 22558 22559 setTest: function ( stencilTest ) { 22560 22561 if ( ! locked ) { 22562 22563 if ( stencilTest ) { 22564 22565 enable( gl.STENCIL_TEST ); 22566 22567 } else { 22568 22569 disable( gl.STENCIL_TEST ); 22570 22571 } 22572 22573 } 22574 22575 }, 22576 22577 setMask: function ( stencilMask ) { 22578 22579 if ( currentStencilMask !== stencilMask && ! locked ) { 22580 22581 gl.stencilMask( stencilMask ); 22582 currentStencilMask = stencilMask; 22583 22584 } 22585 22586 }, 22587 22588 setFunc: function ( stencilFunc, stencilRef, stencilMask ) { 22589 22590 if ( currentStencilFunc !== stencilFunc || 22591 currentStencilRef !== stencilRef || 22592 currentStencilFuncMask !== stencilMask ) { 22593 22594 gl.stencilFunc( stencilFunc, stencilRef, stencilMask ); 22595 22596 currentStencilFunc = stencilFunc; 22597 currentStencilRef = stencilRef; 22598 currentStencilFuncMask = stencilMask; 22599 22600 } 22601 22602 }, 22603 22604 setOp: function ( stencilFail, stencilZFail, stencilZPass ) { 22605 22606 if ( currentStencilFail !== stencilFail || 22607 currentStencilZFail !== stencilZFail || 22608 currentStencilZPass !== stencilZPass ) { 22609 22610 gl.stencilOp( stencilFail, stencilZFail, stencilZPass ); 22611 22612 currentStencilFail = stencilFail; 22613 currentStencilZFail = stencilZFail; 22614 currentStencilZPass = stencilZPass; 22615 22616 } 22617 22618 }, 22619 22620 setLocked: function ( lock ) { 22621 22622 locked = lock; 22623 22624 }, 22625 22626 setClear: function ( stencil ) { 22627 22628 if ( currentStencilClear !== stencil ) { 22629 22630 gl.clearStencil( stencil ); 22631 currentStencilClear = stencil; 22632 22633 } 22634 22635 }, 22636 22637 reset: function () { 22638 22639 locked = false; 22640 22641 currentStencilMask = null; 22642 currentStencilFunc = null; 22643 currentStencilRef = null; 22644 currentStencilFuncMask = null; 22645 currentStencilFail = null; 22646 currentStencilZFail = null; 22647 currentStencilZPass = null; 22648 currentStencilClear = null; 22649 22650 } 22651 22652 }; 22653 22654 } 22655 22656 // 22657 22658 const colorBuffer = new ColorBuffer(); 22659 const depthBuffer = new DepthBuffer(); 22660 const stencilBuffer = new StencilBuffer(); 22661 22662 const uboBindings = new WeakMap(); 22663 const uboProgramMap = new WeakMap(); 22664 22665 let enabledCapabilities = {}; 22666 22667 let currentBoundFramebuffers = {}; 22668 let currentDrawbuffers = new WeakMap(); 22669 let defaultDrawbuffers = []; 22670 22671 let currentProgram = null; 22672 22673 let currentBlendingEnabled = false; 22674 let currentBlending = null; 22675 let currentBlendEquation = null; 22676 let currentBlendSrc = null; 22677 let currentBlendDst = null; 22678 let currentBlendEquationAlpha = null; 22679 let currentBlendSrcAlpha = null; 22680 let currentBlendDstAlpha = null; 22681 let currentBlendColor = new Color( 0, 0, 0 ); 22682 let currentBlendAlpha = 0; 22683 let currentPremultipledAlpha = false; 22684 22685 let currentFlipSided = null; 22686 let currentCullFace = null; 22687 22688 let currentLineWidth = null; 22689 22690 let currentPolygonOffsetFactor = null; 22691 let currentPolygonOffsetUnits = null; 22692 22693 const maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); 22694 22695 let lineWidthAvailable = false; 22696 let version = 0; 22697 const glVersion = gl.getParameter( gl.VERSION ); 22698 22699 if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) { 22700 22701 version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] ); 22702 lineWidthAvailable = ( version >= 1.0 ); 22703 22704 } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) { 22705 22706 version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] ); 22707 lineWidthAvailable = ( version >= 2.0 ); 22708 22709 } 22710 22711 let currentTextureSlot = null; 22712 let currentBoundTextures = {}; 22713 22714 const scissorParam = gl.getParameter( gl.SCISSOR_BOX ); 22715 const viewportParam = gl.getParameter( gl.VIEWPORT ); 22716 22717 const currentScissor = new Vector4().fromArray( scissorParam ); 22718 const currentViewport = new Vector4().fromArray( viewportParam ); 22719 22720 function createTexture( type, target, count, dimensions ) { 22721 22722 const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. 22723 const texture = gl.createTexture(); 22724 22725 gl.bindTexture( type, texture ); 22726 gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); 22727 gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); 22728 22729 for ( let i = 0; i < count; i ++ ) { 22730 22731 if ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) { 22732 22733 gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); 22734 22735 } else { 22736 22737 gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); 22738 22739 } 22740 22741 } 22742 22743 return texture; 22744 22745 } 22746 22747 const emptyTextures = {}; 22748 emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 ); 22749 emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 ); 22750 emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 ); 22751 emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 ); 22752 22753 // init 22754 22755 colorBuffer.setClear( 0, 0, 0, 1 ); 22756 depthBuffer.setClear( 1 ); 22757 stencilBuffer.setClear( 0 ); 22758 22759 enable( gl.DEPTH_TEST ); 22760 depthBuffer.setFunc( LessEqualDepth ); 22761 22762 setFlipSided( false ); 22763 setCullFace( CullFaceBack ); 22764 enable( gl.CULL_FACE ); 22765 22766 setBlending( NoBlending ); 22767 22768 // 22769 22770 function enable( id ) { 22771 22772 if ( enabledCapabilities[ id ] !== true ) { 22773 22774 gl.enable( id ); 22775 enabledCapabilities[ id ] = true; 22776 22777 } 22778 22779 } 22780 22781 function disable( id ) { 22782 22783 if ( enabledCapabilities[ id ] !== false ) { 22784 22785 gl.disable( id ); 22786 enabledCapabilities[ id ] = false; 22787 22788 } 22789 22790 } 22791 22792 function bindFramebuffer( target, framebuffer ) { 22793 22794 if ( currentBoundFramebuffers[ target ] !== framebuffer ) { 22795 22796 gl.bindFramebuffer( target, framebuffer ); 22797 22798 currentBoundFramebuffers[ target ] = framebuffer; 22799 22800 // gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER 22801 22802 if ( target === gl.DRAW_FRAMEBUFFER ) { 22803 22804 currentBoundFramebuffers[ gl.FRAMEBUFFER ] = framebuffer; 22805 22806 } 22807 22808 if ( target === gl.FRAMEBUFFER ) { 22809 22810 currentBoundFramebuffers[ gl.DRAW_FRAMEBUFFER ] = framebuffer; 22811 22812 } 22813 22814 return true; 22815 22816 } 22817 22818 return false; 22819 22820 } 22821 22822 function drawBuffers( renderTarget, framebuffer ) { 22823 22824 let drawBuffers = defaultDrawbuffers; 22825 22826 let needsUpdate = false; 22827 22828 if ( renderTarget ) { 22829 22830 drawBuffers = currentDrawbuffers.get( framebuffer ); 22831 22832 if ( drawBuffers === undefined ) { 22833 22834 drawBuffers = []; 22835 currentDrawbuffers.set( framebuffer, drawBuffers ); 22836 22837 } 22838 22839 const textures = renderTarget.textures; 22840 22841 if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) { 22842 22843 for ( let i = 0, il = textures.length; i < il; i ++ ) { 22844 22845 drawBuffers[ i ] = gl.COLOR_ATTACHMENT0 + i; 22846 22847 } 22848 22849 drawBuffers.length = textures.length; 22850 22851 needsUpdate = true; 22852 22853 } 22854 22855 } else { 22856 22857 if ( drawBuffers[ 0 ] !== gl.BACK ) { 22858 22859 drawBuffers[ 0 ] = gl.BACK; 22860 22861 needsUpdate = true; 22862 22863 } 22864 22865 } 22866 22867 if ( needsUpdate ) { 22868 22869 gl.drawBuffers( drawBuffers ); 22870 22871 } 22872 22873 } 22874 22875 function useProgram( program ) { 22876 22877 if ( currentProgram !== program ) { 22878 22879 gl.useProgram( program ); 22880 22881 currentProgram = program; 22882 22883 return true; 22884 22885 } 22886 22887 return false; 22888 22889 } 22890 22891 const equationToGL = { 22892 [ AddEquation ]: gl.FUNC_ADD, 22893 [ SubtractEquation ]: gl.FUNC_SUBTRACT, 22894 [ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT 22895 }; 22896 22897 equationToGL[ MinEquation ] = gl.MIN; 22898 equationToGL[ MaxEquation ] = gl.MAX;
vendor: 12,328 bytes, lines 22898-23521
22898 22899 22900 const factorToGL = { 22901 [ ZeroFactor ]: gl.ZERO, 22902 [ OneFactor ]: gl.ONE, 22903 [ SrcColorFactor ]: gl.SRC_COLOR, 22904 [ SrcAlphaFactor ]: gl.SRC_ALPHA, 22905 [ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE, 22906 [ DstColorFactor ]: gl.DST_COLOR, 22907 [ DstAlphaFactor ]: gl.DST_ALPHA, 22908 [ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR, 22909 [ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA, 22910 [ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR, 22911 [ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA, 22912 [ ConstantColorFactor ]: gl.CONSTANT_COLOR, 22913 [ OneMinusConstantColorFactor ]: gl.ONE_MINUS_CONSTANT_COLOR, 22914 [ ConstantAlphaFactor ]: gl.CONSTANT_ALPHA, 22915 [ OneMinusConstantAlphaFactor ]: gl.ONE_MINUS_CONSTANT_ALPHA 22916 }; 22917 22918 function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, blendColor, blendAlpha, premultipliedAlpha ) { 22919 22920 if ( blending === NoBlending ) { 22921 22922 if ( currentBlendingEnabled === true ) { 22923 22924 disable( gl.BLEND ); 22925 currentBlendingEnabled = false; 22926 22927 } 22928 22929 return; 22930 22931 } 22932 22933 if ( currentBlendingEnabled === false ) { 22934 22935 enable( gl.BLEND ); 22936 currentBlendingEnabled = true; 22937 22938 } 22939 22940 if ( blending !== CustomBlending ) { 22941 22942 if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { 22943 22944 if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) { 22945 22946 gl.blendEquation( gl.FUNC_ADD ); 22947 22948 currentBlendEquation = AddEquation; 22949 currentBlendEquationAlpha = AddEquation; 22950 22951 } 22952 22953 if ( premultipliedAlpha ) { 22954 22955 switch ( blending ) { 22956 22957 case NormalBlending: 22958 gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); 22959 break; 22960 22961 case AdditiveBlending: 22962 gl.blendFunc( gl.ONE, gl.ONE ); 22963 break; 22964 22965 case SubtractiveBlending: 22966 gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); 22967 break; 22968 22969 case MultiplyBlending: 22970 gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); 22971 break; 22972 22973 default: 22974 console.error( 'THREE.WebGLState: Invalid blending: ', blending ); 22975 break; 22976 22977 } 22978 22979 } else { 22980 22981 switch ( blending ) { 22982 22983 case NormalBlending: 22984 gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); 22985 break; 22986 22987 case AdditiveBlending: 22988 gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); 22989 break; 22990 22991 case SubtractiveBlending: 22992 gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); 22993 break; 22994 22995 case MultiplyBlending: 22996 gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); 22997 break; 22998 22999 default: 23000 console.error( 'THREE.WebGLState: Invalid blending: ', blending ); 23001 break; 23002 23003 } 23004 23005 } 23006 23007 currentBlendSrc = null; 23008 currentBlendDst = null; 23009 currentBlendSrcAlpha = null; 23010 currentBlendDstAlpha = null; 23011 currentBlendColor.set( 0, 0, 0 ); 23012 currentBlendAlpha = 0; 23013 23014 currentBlending = blending; 23015 currentPremultipledAlpha = premultipliedAlpha; 23016 23017 } 23018 23019 return; 23020 23021 } 23022 23023 // custom blending 23024 23025 blendEquationAlpha = blendEquationAlpha || blendEquation; 23026 blendSrcAlpha = blendSrcAlpha || blendSrc; 23027 blendDstAlpha = blendDstAlpha || blendDst; 23028 23029 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { 23030 23031 gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] ); 23032 23033 currentBlendEquation = blendEquation; 23034 currentBlendEquationAlpha = blendEquationAlpha; 23035 23036 } 23037 23038 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { 23039 23040 gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] ); 23041 23042 currentBlendSrc = blendSrc; 23043 currentBlendDst = blendDst; 23044 currentBlendSrcAlpha = blendSrcAlpha; 23045 currentBlendDstAlpha = blendDstAlpha; 23046 23047 } 23048 23049 if ( blendColor.equals( currentBlendColor ) === false || blendAlpha !== currentBlendAlpha ) { 23050 23051 gl.blendColor( blendColor.r, blendColor.g, blendColor.b, blendAlpha ); 23052 23053 currentBlendColor.copy( blendColor ); 23054 currentBlendAlpha = blendAlpha; 23055 23056 } 23057 23058 currentBlending = blending; 23059 currentPremultipledAlpha = false; 23060 23061 } 23062 23063 function setMaterial( material, frontFaceCW ) { 23064 23065 material.side === DoubleSide 23066 ? disable( gl.CULL_FACE ) 23067 : enable( gl.CULL_FACE ); 23068 23069 let flipSided = ( material.side === BackSide ); 23070 if ( frontFaceCW ) flipSided = ! flipSided; 23071 23072 setFlipSided( flipSided ); 23073 23074 ( material.blending === NormalBlending && material.transparent === false ) 23075 ? setBlending( NoBlending ) 23076 : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.blendColor, material.blendAlpha, material.premultipliedAlpha ); 23077 23078 depthBuffer.setFunc( material.depthFunc ); 23079 depthBuffer.setTest( material.depthTest ); 23080 depthBuffer.setMask( material.depthWrite ); 23081 colorBuffer.setMask( material.colorWrite ); 23082 23083 const stencilWrite = material.stencilWrite; 23084 stencilBuffer.setTest( stencilWrite ); 23085 if ( stencilWrite ) { 23086 23087 stencilBuffer.setMask( material.stencilWriteMask ); 23088 stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask ); 23089 stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass ); 23090 23091 } 23092 23093 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); 23094 23095 material.alphaToCoverage === true 23096 ? enable( gl.SAMPLE_ALPHA_TO_COVERAGE ) 23097 : disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); 23098 23099 } 23100 23101 // 23102 23103 function setFlipSided( flipSided ) { 23104 23105 if ( currentFlipSided !== flipSided ) { 23106 23107 if ( flipSided ) { 23108 23109 gl.frontFace( gl.CW ); 23110 23111 } else { 23112 23113 gl.frontFace( gl.CCW ); 23114 23115 } 23116 23117 currentFlipSided = flipSided; 23118 23119 } 23120 23121 } 23122 23123 function setCullFace( cullFace ) { 23124 23125 if ( cullFace !== CullFaceNone ) { 23126 23127 enable( gl.CULL_FACE ); 23128 23129 if ( cullFace !== currentCullFace ) { 23130 23131 if ( cullFace === CullFaceBack ) { 23132 23133 gl.cullFace( gl.BACK ); 23134 23135 } else if ( cullFace === CullFaceFront ) { 23136 23137 gl.cullFace( gl.FRONT ); 23138 23139 } else { 23140 23141 gl.cullFace( gl.FRONT_AND_BACK ); 23142 23143 } 23144 23145 } 23146 23147 } else { 23148 23149 disable( gl.CULL_FACE ); 23150 23151 } 23152 23153 currentCullFace = cullFace; 23154 23155 } 23156 23157 function setLineWidth( width ) { 23158 23159 if ( width !== currentLineWidth ) { 23160 23161 if ( lineWidthAvailable ) gl.lineWidth( width ); 23162 23163 currentLineWidth = width; 23164 23165 } 23166 23167 } 23168 23169 function setPolygonOffset( polygonOffset, factor, units ) { 23170 23171 if ( polygonOffset ) { 23172 23173 enable( gl.POLYGON_OFFSET_FILL ); 23174 23175 if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { 23176 23177 gl.polygonOffset( factor, units ); 23178 23179 currentPolygonOffsetFactor = factor; 23180 currentPolygonOffsetUnits = units; 23181 23182 } 23183 23184 } else { 23185 23186 disable( gl.POLYGON_OFFSET_FILL ); 23187 23188 } 23189 23190 } 23191 23192 function setScissorTest( scissorTest ) { 23193 23194 if ( scissorTest ) { 23195 23196 enable( gl.SCISSOR_TEST ); 23197 23198 } else { 23199 23200 disable( gl.SCISSOR_TEST ); 23201 23202 } 23203 23204 } 23205 23206 // texture 23207 23208 function activeTexture( webglSlot ) { 23209 23210 if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1; 23211 23212 if ( currentTextureSlot !== webglSlot ) { 23213 23214 gl.activeTexture( webglSlot ); 23215 currentTextureSlot = webglSlot; 23216 23217 } 23218 23219 } 23220 23221 function bindTexture( webglType, webglTexture, webglSlot ) { 23222 23223 if ( webglSlot === undefined ) { 23224 23225 if ( currentTextureSlot === null ) { 23226 23227 webglSlot = gl.TEXTURE0 + maxTextures - 1; 23228 23229 } else { 23230 23231 webglSlot = currentTextureSlot; 23232 23233 } 23234 23235 } 23236 23237 let boundTexture = currentBoundTextures[ webglSlot ]; 23238 23239 if ( boundTexture === undefined ) { 23240 23241 boundTexture = { type: undefined, texture: undefined }; 23242 currentBoundTextures[ webglSlot ] = boundTexture; 23243 23244 } 23245 23246 if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { 23247 23248 if ( currentTextureSlot !== webglSlot ) { 23249 23250 gl.activeTexture( webglSlot ); 23251 currentTextureSlot = webglSlot; 23252 23253 } 23254 23255 gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] ); 23256 23257 boundTexture.type = webglType; 23258 boundTexture.texture = webglTexture; 23259 23260 } 23261 23262 } 23263 23264 function unbindTexture() { 23265 23266 const boundTexture = currentBoundTextures[ currentTextureSlot ]; 23267 23268 if ( boundTexture !== undefined && boundTexture.type !== undefined ) { 23269 23270 gl.bindTexture( boundTexture.type, null ); 23271 23272 boundTexture.type = undefined; 23273 boundTexture.texture = undefined; 23274 23275 } 23276 23277 } 23278 23279 function compressedTexImage2D() { 23280 23281 try { 23282 23283 gl.compressedTexImage2D.apply( gl, arguments ); 23284 23285 } catch ( error ) { 23286 23287 console.error( 'THREE.WebGLState:', error ); 23288 23289 } 23290 23291 } 23292 23293 function compressedTexImage3D() { 23294 23295 try { 23296 23297 gl.compressedTexImage3D.apply( gl, arguments ); 23298 23299 } catch ( error ) { 23300 23301 console.error( 'THREE.WebGLState:', error ); 23302 23303 } 23304 23305 } 23306 23307 function texSubImage2D() { 23308 23309 try { 23310 23311 gl.texSubImage2D.apply( gl, arguments ); 23312 23313 } catch ( error ) { 23314 23315 console.error( 'THREE.WebGLState:', error ); 23316 23317 } 23318 23319 } 23320 23321 function texSubImage3D() { 23322 23323 try { 23324 23325 gl.texSubImage3D.apply( gl, arguments ); 23326 23327 } catch ( error ) { 23328 23329 console.error( 'THREE.WebGLState:', error ); 23330 23331 } 23332 23333 } 23334 23335 function compressedTexSubImage2D() { 23336 23337 try { 23338 23339 gl.compressedTexSubImage2D.apply( gl, arguments ); 23340 23341 } catch ( error ) { 23342 23343 console.error( 'THREE.WebGLState:', error ); 23344 23345 } 23346 23347 } 23348 23349 function compressedTexSubImage3D() { 23350 23351 try { 23352 23353 gl.compressedTexSubImage3D.apply( gl, arguments ); 23354 23355 } catch ( error ) { 23356 23357 console.error( 'THREE.WebGLState:', error ); 23358 23359 } 23360 23361 } 23362 23363 function texStorage2D() { 23364 23365 try { 23366 23367 gl.texStorage2D.apply( gl, arguments ); 23368 23369 } catch ( error ) { 23370 23371 console.error( 'THREE.WebGLState:', error ); 23372 23373 } 23374 23375 } 23376 23377 function texStorage3D() { 23378 23379 try { 23380 23381 gl.texStorage3D.apply( gl, arguments ); 23382 23383 } catch ( error ) { 23384 23385 console.error( 'THREE.WebGLState:', error ); 23386 23387 } 23388 23389 } 23390 23391 function texImage2D() { 23392 23393 try { 23394 23395 gl.texImage2D.apply( gl, arguments ); 23396 23397 } catch ( error ) { 23398 23399 console.error( 'THREE.WebGLState:', error ); 23400 23401 } 23402 23403 } 23404 23405 function texImage3D() { 23406 23407 try { 23408 23409 gl.texImage3D.apply( gl, arguments ); 23410 23411 } catch ( error ) { 23412 23413 console.error( 'THREE.WebGLState:', error ); 23414 23415 } 23416 23417 } 23418 23419 // 23420 23421 function scissor( scissor ) { 23422 23423 if ( currentScissor.equals( scissor ) === false ) { 23424 23425 gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w ); 23426 currentScissor.copy( scissor ); 23427 23428 } 23429 23430 } 23431 23432 function viewport( viewport ) { 23433 23434 if ( currentViewport.equals( viewport ) === false ) { 23435 23436 gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w ); 23437 currentViewport.copy( viewport ); 23438 23439 } 23440 23441 } 23442 23443 function updateUBOMapping( uniformsGroup, program ) { 23444 23445 let mapping = uboProgramMap.get( program ); 23446 23447 if ( mapping === undefined ) { 23448 23449 mapping = new WeakMap(); 23450 23451 uboProgramMap.set( program, mapping ); 23452 23453 } 23454 23455 let blockIndex = mapping.get( uniformsGroup ); 23456 23457 if ( blockIndex === undefined ) { 23458 23459 blockIndex = gl.getUniformBlockIndex( program, uniformsGroup.name ); 23460 23461 mapping.set( uniformsGroup, blockIndex ); 23462 23463 } 23464 23465 } 23466 23467 function uniformBlockBinding( uniformsGroup, program ) { 23468 23469 const mapping = uboProgramMap.get( program ); 23470 const blockIndex = mapping.get( uniformsGroup ); 23471 23472 if ( uboBindings.get( program ) !== blockIndex ) { 23473 23474 // bind shader specific block index to global block point 23475 gl.uniformBlockBinding( program, blockIndex, uniformsGroup.__bindingPointIndex ); 23476 23477 uboBindings.set( program, blockIndex ); 23478 23479 } 23480 23481 } 23482 23483 // 23484 23485 function reset() { 23486 23487 // reset state 23488 23489 gl.disable( gl.BLEND ); 23490 gl.disable( gl.CULL_FACE ); 23491 gl.disable( gl.DEPTH_TEST ); 23492 gl.disable( gl.POLYGON_OFFSET_FILL ); 23493 gl.disable( gl.SCISSOR_TEST ); 23494 gl.disable( gl.STENCIL_TEST ); 23495 gl.disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); 23496 23497 gl.blendEquation( gl.FUNC_ADD ); 23498 gl.blendFunc( gl.ONE, gl.ZERO ); 23499 gl.blendFuncSeparate( gl.ONE, gl.ZERO, gl.ONE, gl.ZERO ); 23500 gl.blendColor( 0, 0, 0, 0 ); 23501 23502 gl.colorMask( true, true, true, true ); 23503 gl.clearColor( 0, 0, 0, 0 ); 23504 23505 gl.depthMask( true ); 23506 gl.depthFunc( gl.LESS ); 23507 gl.clearDepth( 1 ); 23508 23509 gl.stencilMask( 0xffffffff ); 23510 gl.stencilFunc( gl.ALWAYS, 0, 0xffffffff ); 23511 gl.stencilOp( gl.KEEP, gl.KEEP, gl.KEEP ); 23512 gl.clearStencil( 0 ); 23513 23514 gl.cullFace( gl.BACK ); 23515 gl.frontFace( gl.CCW ); 23516 23517 gl.polygonOffset( 0, 0 ); 23518 23519 gl.activeTexture( gl.TEXTURE0 ); 23520 23521 gl.bindFramebuffer( gl.FRAMEBUFFER, null );
vendor: 4,512 bytes, lines 23522-23694
23522 gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null ); 23523 gl.bindFramebuffer( gl.READ_FRAMEBUFFER, null ); 23524 23525 gl.useProgram( null ); 23526 23527 gl.lineWidth( 1 ); 23528 23529 gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height ); 23530 gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height ); 23531 23532 // reset internals 23533 23534 enabledCapabilities = {}; 23535 23536 currentTextureSlot = null; 23537 currentBoundTextures = {}; 23538 23539 currentBoundFramebuffers = {}; 23540 currentDrawbuffers = new WeakMap(); 23541 defaultDrawbuffers = []; 23542 23543 currentProgram = null; 23544 23545 currentBlendingEnabled = false; 23546 currentBlending = null; 23547 currentBlendEquation = null; 23548 currentBlendSrc = null; 23549 currentBlendDst = null; 23550 currentBlendEquationAlpha = null; 23551 currentBlendSrcAlpha = null; 23552 currentBlendDstAlpha = null; 23553 currentBlendColor = new Color( 0, 0, 0 ); 23554 currentBlendAlpha = 0; 23555 currentPremultipledAlpha = false; 23556 23557 currentFlipSided = null; 23558 currentCullFace = null; 23559 23560 currentLineWidth = null; 23561 23562 currentPolygonOffsetFactor = null; 23563 currentPolygonOffsetUnits = null; 23564 23565 currentScissor.set( 0, 0, gl.canvas.width, gl.canvas.height ); 23566 currentViewport.set( 0, 0, gl.canvas.width, gl.canvas.height ); 23567 23568 colorBuffer.reset(); 23569 depthBuffer.reset(); 23570 stencilBuffer.reset(); 23571 23572 } 23573 23574 return { 23575 23576 buffers: { 23577 color: colorBuffer, 23578 depth: depthBuffer, 23579 stencil: stencilBuffer 23580 }, 23581 23582 enable: enable, 23583 disable: disable, 23584 23585 bindFramebuffer: bindFramebuffer, 23586 drawBuffers: drawBuffers, 23587 23588 useProgram: useProgram, 23589 23590 setBlending: setBlending, 23591 setMaterial: setMaterial, 23592 23593 setFlipSided: setFlipSided, 23594 setCullFace: setCullFace, 23595 23596 setLineWidth: setLineWidth, 23597 setPolygonOffset: setPolygonOffset, 23598 23599 setScissorTest: setScissorTest, 23600 23601 activeTexture: activeTexture, 23602 bindTexture: bindTexture, 23603 unbindTexture: unbindTexture, 23604 compressedTexImage2D: compressedTexImage2D, 23605 compressedTexImage3D: compressedTexImage3D, 23606 texImage2D: texImage2D, 23607 texImage3D: texImage3D, 23608 23609 updateUBOMapping: updateUBOMapping, 23610 uniformBlockBinding: uniformBlockBinding, 23611 23612 texStorage2D: texStorage2D, 23613 texStorage3D: texStorage3D, 23614 texSubImage2D: texSubImage2D, 23615 texSubImage3D: texSubImage3D, 23616 compressedTexSubImage2D: compressedTexSubImage2D, 23617 compressedTexSubImage3D: compressedTexSubImage3D, 23618 23619 scissor: scissor, 23620 viewport: viewport, 23621 23622 reset: reset 23623 23624 }; 23625 23626} 23627 23628function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) { 23629 23630 const multisampledRTTExt = extensions.has( 'WEBGL_multisampled_render_to_texture' ) ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : null; 23631 const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test( navigator.userAgent ); 23632 23633 const _imageDimensions = new Vector2(); 23634 const _videoTextures = new WeakMap(); 23635 let _canvas; 23636 23637 const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source 23638 23639 // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas, 23640 // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")! 23641 // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d). 23642 23643 let useOffscreenCanvas = false; 23644 23645 try { 23646 23647 useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' 23648 // eslint-disable-next-line compat/compat 23649 && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null; 23650 23651 } catch ( err ) { 23652 23653 // Ignore any errors 23654 23655 } 23656 23657 function createCanvas( width, height ) { 23658 23659 // Use OffscreenCanvas when available. Specially needed in web workers 23660 23661 return useOffscreenCanvas ? 23662 // eslint-disable-next-line compat/compat 23663 new OffscreenCanvas( width, height ) : createElementNS( 'canvas' ); 23664 23665 } 23666 23667 function resizeImage( image, needsNewCanvas, maxSize ) { 23668 23669 let scale = 1; 23670 23671 const dimensions = getDimensions( image ); 23672 23673 // handle case if texture exceeds max size 23674 23675 if ( dimensions.width > maxSize || dimensions.height > maxSize ) { 23676 23677 scale = maxSize / Math.max( dimensions.width, dimensions.height ); 23678 23679 } 23680 23681 // only perform resize if necessary 23682 23683 if ( scale < 1 ) { 23684 23685 // only perform resize for certain image types 23686 23687 if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || 23688 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || 23689 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) || 23690 ( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) ) { 23691 23692 const width = Math.floor( scale * dimensions.width ); 23693 const height = Math.floor( scale * dimensions.height ); 23694
vendor: 14,080 bytes, lines 23695-24210
23695 if ( _canvas === undefined ) _canvas = createCanvas( width, height ); 23696 23697 // cube textures can't reuse the same canvas 23698 23699 const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas; 23700 23701 canvas.width = width; 23702 canvas.height = height; 23703 23704 const context = canvas.getContext( '2d' ); 23705 context.drawImage( image, 0, 0, width, height ); 23706 23707 console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + dimensions.width + 'x' + dimensions.height + ') to (' + width + 'x' + height + ').' ); 23708 23709 return canvas; 23710 23711 } else { 23712 23713 if ( 'data' in image ) { 23714 23715 console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + dimensions.width + 'x' + dimensions.height + ').' ); 23716 23717 } 23718 23719 return image; 23720 23721 } 23722 23723 } 23724 23725 return image; 23726 23727 } 23728 23729 function textureNeedsGenerateMipmaps( texture ) { 23730 23731 return texture.generateMipmaps && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; 23732 23733 } 23734 23735 function generateMipmap( target ) { 23736 23737 _gl.generateMipmap( target ); 23738 23739 } 23740 23741 function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { 23742 23743 if ( internalFormatName !== null ) { 23744 23745 if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ]; 23746 23747 console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' ); 23748 23749 } 23750 23751 let internalFormat = glFormat; 23752 23753 if ( glFormat === _gl.RED ) { 23754 23755 if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F; 23756 if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F; 23757 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8; 23758 23759 } 23760 23761 if ( glFormat === _gl.RED_INTEGER ) { 23762 23763 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8UI; 23764 if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.R16UI; 23765 if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.R32UI; 23766 if ( glType === _gl.BYTE ) internalFormat = _gl.R8I; 23767 if ( glType === _gl.SHORT ) internalFormat = _gl.R16I; 23768 if ( glType === _gl.INT ) internalFormat = _gl.R32I; 23769 23770 } 23771 23772 if ( glFormat === _gl.RG ) { 23773 23774 if ( glType === _gl.FLOAT ) internalFormat = _gl.RG32F; 23775 if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RG16F; 23776 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8; 23777 23778 } 23779 23780 if ( glFormat === _gl.RG_INTEGER ) { 23781 23782 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8UI; 23783 if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.RG16UI; 23784 if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.RG32UI; 23785 if ( glType === _gl.BYTE ) internalFormat = _gl.RG8I; 23786 if ( glType === _gl.SHORT ) internalFormat = _gl.RG16I; 23787 if ( glType === _gl.INT ) internalFormat = _gl.RG32I; 23788 23789 } 23790 23791 if ( glFormat === _gl.RGB ) { 23792 23793 if ( glType === _gl.UNSIGNED_INT_5_9_9_9_REV ) internalFormat = _gl.RGB9_E5; 23794 23795 } 23796 23797 if ( glFormat === _gl.RGBA ) { 23798 23799 const transfer = forceLinearTransfer ? LinearTransfer : ColorManagement.getTransfer( colorSpace ); 23800 23801 if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; 23802 if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; 23803 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; 23804 if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4; 23805 if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1; 23806 23807 } 23808 23809 if ( internalFormat === _gl.R16F || internalFormat === _gl.R32F || 23810 internalFormat === _gl.RG16F || internalFormat === _gl.RG32F || 23811 internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) { 23812 23813 extensions.get( 'EXT_color_buffer_float' ); 23814 23815 } 23816 23817 return internalFormat; 23818 23819 } 23820 23821 function getMipLevels( texture, image ) { 23822 23823 if ( textureNeedsGenerateMipmaps( texture ) === true || ( texture.isFramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) ) { 23824 23825 return Math.log2( Math.max( image.width, image.height ) ) + 1; 23826 23827 } else if ( texture.mipmaps !== undefined && texture.mipmaps.length > 0 ) { 23828 23829 // user-defined mipmaps 23830 23831 return texture.mipmaps.length; 23832 23833 } else if ( texture.isCompressedTexture && Array.isArray( texture.image ) ) { 23834 23835 return image.mipmaps.length; 23836 23837 } else { 23838 23839 // texture without mipmaps (only base level) 23840 23841 return 1; 23842 23843 } 23844 23845 } 23846 23847 // 23848 23849 function onTextureDispose( event ) { 23850 23851 const texture = event.target; 23852 23853 texture.removeEventListener( 'dispose', onTextureDispose ); 23854 23855 deallocateTexture( texture ); 23856 23857 if ( texture.isVideoTexture ) { 23858 23859 _videoTextures.delete( texture ); 23860 23861 } 23862 23863 } 23864 23865 function onRenderTargetDispose( event ) { 23866 23867 const renderTarget = event.target; 23868 23869 renderTarget.removeEventListener( 'dispose', onRenderTargetDispose ); 23870 23871 deallocateRenderTarget( renderTarget ); 23872 23873 } 23874 23875 // 23876 23877 function deallocateTexture( texture ) { 23878 23879 const textureProperties = properties.get( texture ); 23880 23881 if ( textureProperties.__webglInit === undefined ) return; 23882 23883 // check if it's necessary to remove the WebGLTexture object 23884 23885 const source = texture.source; 23886 const webglTextures = _sources.get( source ); 23887 23888 if ( webglTextures ) { 23889 23890 const webglTexture = webglTextures[ textureProperties.__cacheKey ]; 23891 webglTexture.usedTimes --; 23892 23893 // the WebGLTexture object is not used anymore, remove it 23894 23895 if ( webglTexture.usedTimes === 0 ) { 23896 23897 deleteTexture( texture ); 23898 23899 } 23900 23901 // remove the weak map entry if no WebGLTexture uses the source anymore 23902 23903 if ( Object.keys( webglTextures ).length === 0 ) { 23904 23905 _sources.delete( source ); 23906 23907 } 23908 23909 } 23910 23911 properties.remove( texture ); 23912 23913 } 23914 23915 function deleteTexture( texture ) { 23916 23917 const textureProperties = properties.get( texture ); 23918 _gl.deleteTexture( textureProperties.__webglTexture ); 23919 23920 const source = texture.source; 23921 const webglTextures = _sources.get( source ); 23922 delete webglTextures[ textureProperties.__cacheKey ]; 23923 23924 info.memory.textures --; 23925 23926 } 23927 23928 function deallocateRenderTarget( renderTarget ) { 23929 23930 const renderTargetProperties = properties.get( renderTarget ); 23931 23932 if ( renderTarget.depthTexture ) { 23933 23934 renderTarget.depthTexture.dispose(); 23935 23936 } 23937 23938 if ( renderTarget.isWebGLCubeRenderTarget ) { 23939 23940 for ( let i = 0; i < 6; i ++ ) { 23941 23942 if ( Array.isArray( renderTargetProperties.__webglFramebuffer[ i ] ) ) { 23943 23944 for ( let level = 0; level < renderTargetProperties.__webglFramebuffer[ i ].length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ][ level ] ); 23945 23946 } else { 23947 23948 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] ); 23949 23950 } 23951 23952 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); 23953 23954 } 23955 23956 } else { 23957 23958 if ( Array.isArray( renderTargetProperties.__webglFramebuffer ) ) { 23959 23960 for ( let level = 0; level < renderTargetProperties.__webglFramebuffer.length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ level ] ); 23961 23962 } else { 23963 23964 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer ); 23965 23966 } 23967 23968 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); 23969 if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer ); 23970 23971 if ( renderTargetProperties.__webglColorRenderbuffer ) { 23972 23973 for ( let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i ++ ) { 23974 23975 if ( renderTargetProperties.__webglColorRenderbuffer[ i ] ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer[ i ] ); 23976 23977 } 23978 23979 } 23980 23981 if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer ); 23982 23983 } 23984 23985 const textures = renderTarget.textures; 23986 23987 for ( let i = 0, il = textures.length; i < il; i ++ ) { 23988 23989 const attachmentProperties = properties.get( textures[ i ] ); 23990 23991 if ( attachmentProperties.__webglTexture ) { 23992 23993 _gl.deleteTexture( attachmentProperties.__webglTexture ); 23994 23995 info.memory.textures --; 23996 23997 } 23998 23999 properties.remove( textures[ i ] ); 24000 24001 } 24002 24003 properties.remove( renderTarget ); 24004 24005 } 24006 24007 // 24008 24009 let textureUnits = 0; 24010 24011 function resetTextureUnits() { 24012 24013 textureUnits = 0; 24014 24015 } 24016 24017 function allocateTextureUnit() { 24018 24019 const textureUnit = textureUnits; 24020 24021 if ( textureUnit >= capabilities.maxTextures ) { 24022 24023 console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); 24024 24025 } 24026 24027 textureUnits += 1; 24028 24029 return textureUnit; 24030 24031 } 24032 24033 function getTextureCacheKey( texture ) { 24034 24035 const array = []; 24036 24037 array.push( texture.wrapS ); 24038 array.push( texture.wrapT ); 24039 array.push( texture.wrapR || 0 ); 24040 array.push( texture.magFilter ); 24041 array.push( texture.minFilter ); 24042 array.push( texture.anisotropy ); 24043 array.push( texture.internalFormat ); 24044 array.push( texture.format ); 24045 array.push( texture.type ); 24046 array.push( texture.generateMipmaps ); 24047 array.push( texture.premultiplyAlpha ); 24048 array.push( texture.flipY ); 24049 array.push( texture.unpackAlignment ); 24050 array.push( texture.colorSpace ); 24051 24052 return array.join(); 24053 24054 } 24055 24056 // 24057 24058 function setTexture2D( texture, slot ) { 24059 24060 const textureProperties = properties.get( texture ); 24061 24062 if ( texture.isVideoTexture ) updateVideoTexture( texture ); 24063 24064 if ( texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version ) { 24065 24066 const image = texture.image; 24067 24068 if ( image === null ) { 24069 24070 console.warn( 'THREE.WebGLRenderer: Texture marked for update but no image data found.' ); 24071 24072 } else if ( image.complete === false ) { 24073 24074 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' ); 24075 24076 } else { 24077 24078 uploadTexture( textureProperties, texture, slot ); 24079 return; 24080 24081 } 24082 24083 } 24084 24085 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24086 24087 } 24088 24089 function setTexture2DArray( texture, slot ) { 24090 24091 const textureProperties = properties.get( texture ); 24092 24093 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 24094 24095 uploadTexture( textureProperties, texture, slot ); 24096 return; 24097 24098 } 24099 24100 state.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24101 24102 } 24103 24104 function setTexture3D( texture, slot ) { 24105 24106 const textureProperties = properties.get( texture ); 24107 24108 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 24109 24110 uploadTexture( textureProperties, texture, slot ); 24111 return; 24112 24113 } 24114 24115 state.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24116 24117 } 24118 24119 function setTextureCube( texture, slot ) { 24120 24121 const textureProperties = properties.get( texture ); 24122 24123 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 24124 24125 uploadCubeTexture( textureProperties, texture, slot ); 24126 return; 24127 24128 } 24129 24130 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24131 24132 } 24133 24134 const wrappingToGL = { 24135 [ RepeatWrapping ]: _gl.REPEAT, 24136 [ ClampToEdgeWrapping ]: _gl.CLAMP_TO_EDGE, 24137 [ MirroredRepeatWrapping ]: _gl.MIRRORED_REPEAT 24138 }; 24139 24140 const filterToGL = { 24141 [ NearestFilter ]: _gl.NEAREST, 24142 [ NearestMipmapNearestFilter ]: _gl.NEAREST_MIPMAP_NEAREST, 24143 [ NearestMipmapLinearFilter ]: _gl.NEAREST_MIPMAP_LINEAR, 24144 24145 [ LinearFilter ]: _gl.LINEAR, 24146 [ LinearMipmapNearestFilter ]: _gl.LINEAR_MIPMAP_NEAREST, 24147 [ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR 24148 }; 24149 24150 const compareToGL = { 24151 [ NeverCompare ]: _gl.NEVER, 24152 [ AlwaysCompare ]: _gl.ALWAYS, 24153 [ LessCompare ]: _gl.LESS, 24154 [ LessEqualCompare ]: _gl.LEQUAL, 24155 [ EqualCompare ]: _gl.EQUAL, 24156 [ GreaterEqualCompare ]: _gl.GEQUAL, 24157 [ GreaterCompare ]: _gl.GREATER, 24158 [ NotEqualCompare ]: _gl.NOTEQUAL 24159 }; 24160 24161 function setTextureParameters( textureType, texture ) { 24162 24163 if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false && 24164 ( texture.magFilter === LinearFilter || texture.magFilter === LinearMipmapNearestFilter || texture.magFilter === NearestMipmapLinearFilter || texture.magFilter === LinearMipmapLinearFilter || 24165 texture.minFilter === LinearFilter || texture.minFilter === LinearMipmapNearestFilter || texture.minFilter === NearestMipmapLinearFilter || texture.minFilter === LinearMipmapLinearFilter ) ) { 24166 24167 console.warn( 'THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device.' ); 24168 24169 } 24170 24171 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] ); 24172 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] ); 24173 24174 if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) { 24175 24176 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[ texture.wrapR ] ); 24177 24178 } 24179 24180 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] ); 24181 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[ texture.minFilter ] ); 24182 24183 if ( texture.compareFunction ) { 24184 24185 _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE ); 24186 _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] ); 24187 24188 } 24189 24190 if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { 24191 24192 if ( texture.magFilter === NearestFilter ) return; 24193 if ( texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter ) return; 24194 if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false ) return; // verify extension 24195 24196 if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) { 24197 24198 const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); 24199 _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) ); 24200 properties.get( texture ).__currentAnisotropy = texture.anisotropy; 24201 24202 } 24203 24204 } 24205 24206 } 24207 24208 function initTexture( textureProperties, texture ) { 24209 24210 let forceUpload = false;
vendor: 4,815 bytes, lines 24211-24375
24211 24212 if ( textureProperties.__webglInit === undefined ) { 24213 24214 textureProperties.__webglInit = true; 24215 24216 texture.addEventListener( 'dispose', onTextureDispose ); 24217 24218 } 24219 24220 // create Source <-> WebGLTextures mapping if necessary 24221 24222 const source = texture.source; 24223 let webglTextures = _sources.get( source ); 24224 24225 if ( webglTextures === undefined ) { 24226 24227 webglTextures = {}; 24228 _sources.set( source, webglTextures ); 24229 24230 } 24231 24232 // check if there is already a WebGLTexture object for the given texture parameters 24233 24234 const textureCacheKey = getTextureCacheKey( texture ); 24235 24236 if ( textureCacheKey !== textureProperties.__cacheKey ) { 24237 24238 // if not, create a new instance of WebGLTexture 24239 24240 if ( webglTextures[ textureCacheKey ] === undefined ) { 24241 24242 // create new entry 24243 24244 webglTextures[ textureCacheKey ] = { 24245 texture: _gl.createTexture(), 24246 usedTimes: 0 24247 }; 24248 24249 info.memory.textures ++; 24250 24251 // when a new instance of WebGLTexture was created, a texture upload is required 24252 // even if the image contents are identical 24253 24254 forceUpload = true; 24255 24256 } 24257 24258 webglTextures[ textureCacheKey ].usedTimes ++; 24259 24260 // every time the texture cache key changes, it's necessary to check if an instance of 24261 // WebGLTexture can be deleted in order to avoid a memory leak. 24262 24263 const webglTexture = webglTextures[ textureProperties.__cacheKey ]; 24264 24265 if ( webglTexture !== undefined ) { 24266 24267 webglTextures[ textureProperties.__cacheKey ].usedTimes --; 24268 24269 if ( webglTexture.usedTimes === 0 ) { 24270 24271 deleteTexture( texture ); 24272 24273 } 24274 24275 } 24276 24277 // store references to cache key and WebGLTexture object 24278 24279 textureProperties.__cacheKey = textureCacheKey; 24280 textureProperties.__webglTexture = webglTextures[ textureCacheKey ].texture; 24281 24282 } 24283 24284 return forceUpload; 24285 24286 } 24287 24288 function uploadTexture( textureProperties, texture, slot ) { 24289 24290 let textureType = _gl.TEXTURE_2D; 24291 24292 if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = _gl.TEXTURE_2D_ARRAY; 24293 if ( texture.isData3DTexture ) textureType = _gl.TEXTURE_3D; 24294 24295 const forceUpload = initTexture( textureProperties, texture ); 24296 const source = texture.source; 24297 24298 state.bindTexture( textureType, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24299 24300 const sourceProperties = properties.get( source ); 24301 24302 if ( source.version !== sourceProperties.__version || forceUpload === true ) { 24303 24304 state.activeTexture( _gl.TEXTURE0 + slot ); 24305 24306 const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); 24307 const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); 24308 const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; 24309 24310 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); 24311 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); 24312 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); 24313 _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion ); 24314 24315 let image = resizeImage( texture.image, false, capabilities.maxTextureSize ); 24316 image = verifyColorSpace( texture, image ); 24317 24318 const glFormat = utils.convert( texture.format, texture.colorSpace ); 24319 24320 const glType = utils.convert( texture.type ); 24321 let glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture ); 24322 24323 setTextureParameters( textureType, texture ); 24324 24325 let mipmap; 24326 const mipmaps = texture.mipmaps; 24327 24328 const useTexStorage = ( texture.isVideoTexture !== true && glInternalFormat !== RGB_ETC1_Format ); 24329 const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); 24330 const dataReady = source.dataReady; 24331 const levels = getMipLevels( texture, image ); 24332 24333 if ( texture.isDepthTexture ) { 24334 24335 // populate depth texture with dummy data 24336 24337 glInternalFormat = _gl.DEPTH_COMPONENT16; 24338 24339 if ( texture.type === FloatType ) { 24340 24341 glInternalFormat = _gl.DEPTH_COMPONENT32F; 24342 24343 } else if ( texture.type === UnsignedIntType ) { 24344 24345 glInternalFormat = _gl.DEPTH_COMPONENT24; 24346 24347 } else if ( texture.type === UnsignedInt248Type ) { 24348 24349 glInternalFormat = _gl.DEPTH24_STENCIL8; 24350 24351 } 24352 24353 // 24354 24355 if ( allocateMemory ) { 24356 24357 if ( useTexStorage ) { 24358 24359 state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height ); 24360 24361 } else { 24362 24363 state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ); 24364 24365 } 24366 24367 } 24368 24369 } else if ( texture.isDataTexture ) { 24370 24371 // use manually created mipmaps if available 24372 // if there are no manual mipmaps 24373 // set 0 level mipmap and then use GL to generate other mipmap levels 24374 24375 if ( mipmaps.length > 0
vendor: 5,625 bytes, lines 24375-24622
24375 ) { 24376 24377 if ( useTexStorage && allocateMemory ) { 24378 24379 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); 24380 24381 } 24382 24383 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 24384 24385 mipmap = mipmaps[ i ]; 24386 24387 if ( useTexStorage ) { 24388 24389 if ( dataReady ) { 24390 24391 state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); 24392 24393 } 24394 24395 } else { 24396 24397 state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 24398 24399 } 24400 24401 } 24402 24403 texture.generateMipmaps = false; 24404 24405 } else { 24406 24407 if ( useTexStorage ) { 24408 24409 if ( allocateMemory ) { 24410 24411 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); 24412 24413 } 24414 24415 if ( dataReady ) { 24416 24417 state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data ); 24418 24419 } 24420 24421 } else { 24422 24423 state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data ); 24424 24425 } 24426 24427 } 24428 24429 } else if ( texture.isCompressedTexture ) { 24430 24431 if ( texture.isCompressedArrayTexture ) { 24432 24433 if ( useTexStorage && allocateMemory ) { 24434 24435 state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth ); 24436 24437 } 24438 24439 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 24440 24441 mipmap = mipmaps[ i ]; 24442 24443 if ( texture.format !== RGBAFormat ) { 24444 24445 if ( glFormat !== null ) { 24446 24447 if ( useTexStorage ) { 24448 24449 if ( dataReady ) { 24450 24451 state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); 24452 24453 } 24454 24455 } else { 24456 24457 state.compressedTexImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 ); 24458 24459 } 24460 24461 } else { 24462 24463 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); 24464 24465 } 24466 24467 } else { 24468 24469 if ( useTexStorage ) { 24470 24471 if ( dataReady ) { 24472 24473 state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data ); 24474 24475 } 24476 24477 } else { 24478 24479 state.texImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data ); 24480 24481 } 24482 24483 } 24484 24485 } 24486 24487 } else { 24488 24489 if ( useTexStorage && allocateMemory ) { 24490 24491 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); 24492 24493 } 24494 24495 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 24496 24497 mipmap = mipmaps[ i ]; 24498 24499 if ( texture.format !== RGBAFormat ) { 24500 24501 if ( glFormat !== null ) { 24502 24503 if ( useTexStorage ) { 24504 24505 if ( dataReady ) { 24506 24507 state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); 24508 24509 } 24510 24511 } else { 24512 24513 state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); 24514 24515 } 24516 24517 } else { 24518 24519 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); 24520 24521 } 24522 24523 } else { 24524 24525 if ( useTexStorage ) { 24526 24527 if ( dataReady ) { 24528 24529 state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); 24530 24531 } 24532 24533 } else { 24534 24535 state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 24536 24537 } 24538 24539 } 24540 24541 } 24542 24543 } 24544 24545 } else if ( texture.isDataArrayTexture ) { 24546 24547 if ( useTexStorage ) { 24548 24549 if ( allocateMemory ) { 24550 24551 state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth ); 24552 24553 } 24554 24555 if ( dataReady ) { 24556 24557 state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); 24558 24559 } 24560 24561 } else { 24562 24563 state.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); 24564 24565 } 24566 24567 } else if ( texture.isData3DTexture ) { 24568 24569 if ( useTexStorage ) { 24570 24571 if ( allocateMemory ) { 24572 24573 state.texStorage3D( _gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth ); 24574 24575 } 24576 24577 if ( dataReady ) { 24578 24579 state.texSubImage3D( _gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); 24580 24581 } 24582 24583 } else { 24584 24585 state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); 24586 24587 } 24588 24589 } else if ( texture.isFramebufferTexture ) { 24590 24591 if ( allocateMemory ) { 24592 24593 if ( useTexStorage ) { 24594 24595 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); 24596 24597 } else { 24598 24599 let width = image.width, height = image.height; 24600 24601 for ( let i = 0; i < levels; i ++ ) { 24602 24603 state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, width, height, 0, glFormat, glType, null ); 24604 24605 width >>= 1; 24606 height >>= 1; 24607 24608 } 24609 24610 } 24611 24612 } 24613 24614 } else { 24615 24616 // regular Texture (image, video, canvas) 24617 24618 // use manually created mipmaps if available 24619 // if there are no manual mipmaps 24620 // set 0 level mipmap and then use GL to generate other mipmap levels 24621 24622 if ( mipmaps.length > 0
vendor: 7,841 bytes, lines 24622-24936
24622) { 24623 24624 if ( useTexStorage && allocateMemory ) { 24625 24626 const dimensions = getDimensions( mipmaps[ 0 ] ); 24627 24628 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height ); 24629 24630 } 24631 24632 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 24633 24634 mipmap = mipmaps[ i ]; 24635 24636 if ( useTexStorage ) { 24637 24638 if ( dataReady ) { 24639 24640 state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap ); 24641 24642 } 24643 24644 } else { 24645 24646 state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap ); 24647 24648 } 24649 24650 } 24651 24652 texture.generateMipmaps = false; 24653 24654 } else { 24655 24656 if ( useTexStorage ) { 24657 24658 if ( allocateMemory ) { 24659 24660 const dimensions = getDimensions( image ); 24661 24662 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height ); 24663 24664 } 24665 24666 if ( dataReady ) { 24667 24668 state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image ); 24669 24670 } 24671 24672 } else { 24673 24674 state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image ); 24675 24676 } 24677 24678 } 24679 24680 } 24681 24682 if ( textureNeedsGenerateMipmaps( texture ) ) { 24683 24684 generateMipmap( textureType ); 24685 24686 } 24687 24688 sourceProperties.__version = source.version; 24689 24690 if ( texture.onUpdate ) texture.onUpdate( texture ); 24691 24692 } 24693 24694 textureProperties.__version = texture.version; 24695 24696 } 24697 24698 function uploadCubeTexture( textureProperties, texture, slot ) { 24699 24700 if ( texture.image.length !== 6 ) return; 24701 24702 const forceUpload = initTexture( textureProperties, texture ); 24703 const source = texture.source; 24704 24705 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24706 24707 const sourceProperties = properties.get( source ); 24708 24709 if ( source.version !== sourceProperties.__version || forceUpload === true ) { 24710 24711 state.activeTexture( _gl.TEXTURE0 + slot ); 24712 24713 const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); 24714 const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); 24715 const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; 24716 24717 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); 24718 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); 24719 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); 24720 _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion ); 24721 24722 const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ); 24723 const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); 24724 24725 const cubeImage = []; 24726 24727 for ( let i = 0; i < 6; i ++ ) { 24728 24729 if ( ! isCompressed && ! isDataTexture ) { 24730 24731 cubeImage[ i ] = resizeImage( texture.image[ i ], true, capabilities.maxCubemapSize ); 24732 24733 } else { 24734 24735 cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ]; 24736 24737 } 24738 24739 cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] ); 24740 24741 } 24742 24743 const image = cubeImage[ 0 ], 24744 glFormat = utils.convert( texture.format, texture.colorSpace ), 24745 glType = utils.convert( texture.type ), 24746 glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); 24747 24748 const useTexStorage = ( texture.isVideoTexture !== true ); 24749 const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); 24750 const dataReady = source.dataReady; 24751 let levels = getMipLevels( texture, image ); 24752 24753 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture ); 24754 24755 let mipmaps; 24756 24757 if ( isCompressed ) { 24758 24759 if ( useTexStorage && allocateMemory ) { 24760 24761 state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height ); 24762 24763 } 24764 24765 for ( let i = 0; i < 6; i ++ ) { 24766 24767 mipmaps = cubeImage[ i ].mipmaps; 24768 24769 for ( let j = 0; j < mipmaps.length; j ++ ) { 24770 24771 const mipmap = mipmaps[ j ]; 24772 24773 if ( texture.format !== RGBAFormat ) { 24774 24775 if ( glFormat !== null ) { 24776 24777 if ( useTexStorage ) { 24778 24779 if ( dataReady ) { 24780 24781 state.compressedTexSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); 24782 24783 } 24784 24785 } else { 24786 24787 state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); 24788 24789 } 24790 24791 } else { 24792 24793 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); 24794 24795 } 24796 24797 } else { 24798 24799 if ( useTexStorage ) { 24800 24801 if ( dataReady ) { 24802 24803 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); 24804 24805 } 24806 24807 } else { 24808 24809 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 24810 24811 } 24812 24813 } 24814 24815 } 24816 24817 } 24818 24819 } else { 24820 24821 mipmaps = texture.mipmaps; 24822 24823 if ( useTexStorage && allocateMemory ) { 24824 24825 // TODO: Uniformly handle mipmap definitions 24826 // Normal textures and compressed cube textures define base level + mips with their mipmap array 24827 // Uncompressed cube textures use their mipmap array only for mips (no base level) 24828 24829 if ( mipmaps.length > 0 ) levels ++; 24830 24831 const dimensions = getDimensions( cubeImage[ 0 ] ); 24832 24833 state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, dimensions.width, dimensions.height ); 24834 24835 } 24836 24837 for ( let i = 0; i < 6; i ++ ) { 24838 24839 if ( isDataTexture ) { 24840 24841 if ( useTexStorage ) { 24842 24843 if ( dataReady ) { 24844 24845 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data ); 24846 24847 } 24848 24849 } else { 24850 24851 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); 24852 24853 } 24854 24855 for ( let j = 0; j < mipmaps.length; j ++ ) { 24856 24857 const mipmap = mipmaps[ j ]; 24858 const mipmapImage = mipmap.image[ i ].image; 24859 24860 if ( useTexStorage ) { 24861 24862 if ( dataReady ) { 24863 24864 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data ); 24865 24866 } 24867 24868 } else { 24869 24870 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data ); 24871 24872 } 24873 24874 } 24875 24876 } else { 24877 24878 if ( useTexStorage ) { 24879 24880 if ( dataReady ) { 24881 24882 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] ); 24883 24884 } 24885 24886 } else { 24887 24888 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] ); 24889 24890 } 24891 24892 for ( let j = 0; j < mipmaps.length; j ++ ) { 24893 24894 const mipmap = mipmaps[ j ]; 24895 24896 if ( useTexStorage ) { 24897 24898 if ( dataReady ) { 24899 24900 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] ); 24901 24902 } 24903 24904 } else { 24905 24906 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] ); 24907 24908 } 24909 24910 } 24911 24912 } 24913 24914 } 24915 24916 } 24917 24918 if ( textureNeedsGenerateMipmaps( texture ) ) { 24919 24920 // We assume images for cube map have the same size. 24921 generateMipmap( _gl.TEXTURE_CUBE_MAP ); 24922 24923 } 24924 24925 sourceProperties.__version = source.version; 24926 24927 if ( texture.onUpdate ) texture.onUpdate( texture ); 24928 24929 } 24930 24931 textureProperties.__version = texture.version; 24932 24933 } 24934 24935 // Render targets 24936
vendor: 10,864 bytes, lines 24937-25295
24937 // Setup storage for target texture and bind it to correct framebuffer 24938 function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget, level ) { 24939 24940 const glFormat = utils.convert( texture.format, texture.colorSpace ); 24941 const glType = utils.convert( texture.type ); 24942 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); 24943 const renderTargetProperties = properties.get( renderTarget ); 24944 24945 if ( ! renderTargetProperties.__hasExternalTextures ) { 24946 24947 const width = Math.max( 1, renderTarget.width >> level ); 24948 const height = Math.max( 1, renderTarget.height >> level ); 24949 24950 if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) { 24951 24952 state.texImage3D( textureTarget, level, glInternalFormat, width, height, renderTarget.depth, 0, glFormat, glType, null ); 24953 24954 } else { 24955 24956 state.texImage2D( textureTarget, level, glInternalFormat, width, height, 0, glFormat, glType, null ); 24957 24958 } 24959 24960 } 24961 24962 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 24963 24964 if ( useMultisampledRTT( renderTarget ) ) { 24965 24966 multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); 24967 24968 } else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) { // see #24753 24969 24970 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, level ); 24971 24972 } 24973 24974 state.bindFramebuffer( _gl.FRAMEBUFFER, null ); 24975 24976 } 24977 24978 24979 // Setup storage for internal depth/stencil buffers and bind to correct framebuffer 24980 function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) { 24981 24982 _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); 24983 24984 if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) { 24985 24986 let glInternalFormat = _gl.DEPTH_COMPONENT24; 24987 24988 if ( isMultisample || useMultisampledRTT( renderTarget ) ) { 24989 24990 const depthTexture = renderTarget.depthTexture; 24991 24992 if ( depthTexture && depthTexture.isDepthTexture ) { 24993 24994 if ( depthTexture.type === FloatType ) { 24995 24996 glInternalFormat = _gl.DEPTH_COMPONENT32F; 24997 24998 } else if ( depthTexture.type === UnsignedIntType ) { 24999 25000 glInternalFormat = _gl.DEPTH_COMPONENT24; 25001 25002 } 25003 25004 } 25005 25006 const samples = getRenderTargetSamples( renderTarget ); 25007 25008 if ( useMultisampledRTT( renderTarget ) ) { 25009 25010 multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25011 25012 } else { 25013 25014 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25015 25016 } 25017 25018 } else { 25019 25020 _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); 25021 25022 } 25023 25024 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); 25025 25026 } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) { 25027 25028 const samples = getRenderTargetSamples( renderTarget ); 25029 25030 if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { 25031 25032 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height ); 25033 25034 } else if ( useMultisampledRTT( renderTarget ) ) { 25035 25036 multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height ); 25037 25038 } else { 25039 25040 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height ); 25041 25042 } 25043 25044 25045 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); 25046 25047 } else { 25048 25049 const textures = renderTarget.textures; 25050 25051 for ( let i = 0; i < textures.length; i ++ ) { 25052 25053 const texture = textures[ i ]; 25054 25055 const glFormat = utils.convert( texture.format, texture.colorSpace ); 25056 const glType = utils.convert( texture.type ); 25057 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); 25058 const samples = getRenderTargetSamples( renderTarget ); 25059 25060 if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { 25061 25062 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25063 25064 } else if ( useMultisampledRTT( renderTarget ) ) { 25065 25066 multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25067 25068 } else { 25069 25070 _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); 25071 25072 } 25073 25074 } 25075 25076 } 25077 25078 _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); 25079 25080 } 25081 25082 // Setup resources for a Depth Texture for a FBO (needs an extension) 25083 function setupDepthTexture( framebuffer, renderTarget ) { 25084 25085 const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget ); 25086 if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); 25087 25088 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 25089 25090 if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { 25091 25092 throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); 25093 25094 } 25095 25096 // upload an empty depth texture with framebuffer size 25097 if ( ! properties.get( renderTarget.depthTexture ).__webglTexture || 25098 renderTarget.depthTexture.image.width !== renderTarget.width || 25099 renderTarget.depthTexture.image.height !== renderTarget.height ) { 25100 25101 renderTarget.depthTexture.image.width = renderTarget.width; 25102 renderTarget.depthTexture.image.height = renderTarget.height; 25103 renderTarget.depthTexture.needsUpdate = true; 25104 25105 } 25106 25107 setTexture2D( renderTarget.depthTexture, 0 ); 25108 25109 const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; 25110 const samples = getRenderTargetSamples( renderTarget ); 25111 25112 if ( renderTarget.depthTexture.format === DepthFormat ) { 25113 25114 if ( useMultisampledRTT( renderTarget ) ) { 25115 25116 multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); 25117 25118 } else { 25119 25120 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); 25121 25122 } 25123 25124 } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { 25125 25126 if ( useMultisampledRTT( renderTarget ) ) { 25127 25128 multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); 25129 25130 } else { 25131 25132 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); 25133 25134 } 25135 25136 } else { 25137 25138 throw new Error( 'Unknown depthTexture format' ); 25139 25140 } 25141 25142 } 25143 25144 // Setup GL resources for a non-texture depth buffer 25145 function setupDepthRenderbuffer( renderTarget ) { 25146 25147 const renderTargetProperties = properties.get( renderTarget ); 25148 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); 25149 25150 if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) { 25151 25152 if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); 25153 25154 setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); 25155 25156 } else { 25157 25158 if ( isCube ) { 25159 25160 renderTargetProperties.__webglDepthbuffer = []; 25161 25162 for ( let i = 0; i < 6; i ++ ) { 25163 25164 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); 25165 renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); 25166 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false ); 25167 25168 } 25169 25170 } else { 25171 25172 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 25173 renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); 25174 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false ); 25175 25176 } 25177 25178 } 25179 25180 state.bindFramebuffer( _gl.FRAMEBUFFER, null ); 25181 25182 } 25183 25184 // rebind framebuffer with external textures 25185 function rebindTextures( renderTarget, colorTexture, depthTexture ) { 25186 25187 const renderTargetProperties = properties.get( renderTarget ); 25188 25189 if ( colorTexture !== undefined ) { 25190 25191 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, 0 ); 25192 25193 } 25194 25195 if ( depthTexture !== undefined ) { 25196 25197 setupDepthRenderbuffer( renderTarget ); 25198 25199 } 25200 25201 } 25202 25203 // Set up GL resources for the render target 25204 function setupRenderTarget( renderTarget ) { 25205 25206 const texture = renderTarget.texture; 25207 25208 const renderTargetProperties = properties.get( renderTarget ); 25209 const textureProperties = properties.get( texture ); 25210 25211 renderTarget.addEventListener( 'dispose', onRenderTargetDispose ); 25212 25213 const textures = renderTarget.textures; 25214 25215 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); 25216 const isMultipleRenderTargets = ( textures.length > 1 ); 25217 25218 if ( ! isMultipleRenderTargets ) { 25219 25220 if ( textureProperties.__webglTexture === undefined ) { 25221 25222 textureProperties.__webglTexture = _gl.createTexture(); 25223 25224 } 25225 25226 textureProperties.__version = texture.version; 25227 info.memory.textures ++; 25228 25229 } 25230 25231 // Setup framebuffer 25232 25233 if ( isCube ) { 25234 25235 renderTargetProperties.__webglFramebuffer = []; 25236 25237 for ( let i = 0; i < 6; i ++ ) { 25238 25239 if ( texture.mipmaps && texture.mipmaps.length > 0 ) { 25240 25241 renderTargetProperties.__webglFramebuffer[ i ] = []; 25242 25243 for ( let level = 0; level < texture.mipmaps.length; level ++ ) { 25244 25245 renderTargetProperties.__webglFramebuffer[ i ][ level ] = _gl.createFramebuffer(); 25246 25247 } 25248 25249 } else { 25250 25251 renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer(); 25252 25253 } 25254 25255 } 25256 25257 } else { 25258 25259 if ( texture.mipmaps && texture.mipmaps.length > 0 ) { 25260 25261 renderTargetProperties.__webglFramebuffer = []; 25262 25263 for ( let level = 0; level < texture.mipmaps.length; level ++ ) { 25264 25265 renderTargetProperties.__webglFramebuffer[ level ] = _gl.createFramebuffer(); 25266 25267 } 25268 25269 } else { 25270 25271 renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); 25272 25273 } 25274 25275 if ( isMultipleRenderTargets ) { 25276 25277 for ( let i = 0, il = textures.length; i < il; i ++ ) { 25278 25279 const attachmentProperties = properties.get( textures[ i ] ); 25280 25281 if ( attachmentProperties.__webglTexture === undefined ) { 25282 25283 attachmentProperties.__webglTexture = _gl.createTexture(); 25284 25285 info.memory.textures ++; 25286 25287 } 25288 25289 } 25290 25291 } 25292 25293 if ( ( renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) { 25294 25295 renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
vendor: 4,218 bytes, lines 25296-25442
25296 renderTargetProperties.__webglColorRenderbuffer = []; 25297 25298 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25299 25300 for ( let i = 0; i < textures.length; i ++ ) { 25301 25302 const texture = textures[ i ]; 25303 renderTargetProperties.__webglColorRenderbuffer[ i ] = _gl.createRenderbuffer(); 25304 25305 _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 25306 25307 const glFormat = utils.convert( texture.format, texture.colorSpace ); 25308 const glType = utils.convert( texture.type ); 25309 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true ); 25310 const samples = getRenderTargetSamples( renderTarget ); 25311 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25312 25313 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 25314 25315 } 25316 25317 _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); 25318 25319 if ( renderTarget.depthBuffer ) { 25320 25321 renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer(); 25322 setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true ); 25323 25324 } 25325 25326 state.bindFramebuffer( _gl.FRAMEBUFFER, null ); 25327 25328 } 25329 25330 } 25331 25332 // Setup color buffer 25333 25334 if ( isCube ) { 25335 25336 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); 25337 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture ); 25338 25339 for ( let i = 0; i < 6; i ++ ) { 25340 25341 if ( texture.mipmaps && texture.mipmaps.length > 0 ) { 25342 25343 for ( let level = 0; level < texture.mipmaps.length; level ++ ) { 25344 25345 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ][ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level ); 25346 25347 } 25348 25349 } else { 25350 25351 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0 ); 25352 25353 } 25354 25355 } 25356 25357 if ( textureNeedsGenerateMipmaps( texture ) ) { 25358 25359 generateMipmap( _gl.TEXTURE_CUBE_MAP ); 25360 25361 } 25362 25363 state.unbindTexture(); 25364 25365 } else if ( isMultipleRenderTargets ) { 25366 25367 for ( let i = 0, il = textures.length; i < il; i ++ ) { 25368 25369 const attachment = textures[ i ]; 25370 const attachmentProperties = properties.get( attachment ); 25371 25372 state.bindTexture( _gl.TEXTURE_2D, attachmentProperties.__webglTexture ); 25373 setTextureParameters( _gl.TEXTURE_2D, attachment ); 25374 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, 0 ); 25375 25376 if ( textureNeedsGenerateMipmaps( attachment ) ) { 25377 25378 generateMipmap( _gl.TEXTURE_2D ); 25379 25380 } 25381 25382 } 25383 25384 state.unbindTexture(); 25385 25386 } else { 25387 25388 let glTextureType = _gl.TEXTURE_2D; 25389 25390 if ( renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) { 25391 25392 glTextureType = renderTarget.isWebGL3DRenderTarget ? _gl.TEXTURE_3D : _gl.TEXTURE_2D_ARRAY; 25393 25394 } 25395 25396 state.bindTexture( glTextureType, textureProperties.__webglTexture ); 25397 setTextureParameters( glTextureType, texture ); 25398 25399 if ( texture.mipmaps && texture.mipmaps.length > 0 ) { 25400 25401 for ( let level = 0; level < texture.mipmaps.length; level ++ ) { 25402 25403 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, level ); 25404 25405 } 25406 25407 } else { 25408 25409 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, 0 ); 25410 25411 } 25412 25413 if ( textureNeedsGenerateMipmaps( texture ) ) { 25414 25415 generateMipmap( glTextureType ); 25416 25417 } 25418 25419 state.unbindTexture(); 25420 25421 } 25422 25423 // Setup depth and stencil buffers 25424 25425 if ( renderTarget.depthBuffer ) { 25426 25427 setupDepthRenderbuffer( renderTarget ); 25428 25429 } 25430 25431 } 25432 25433 function updateRenderTargetMipmap( renderTarget ) { 25434 25435 const textures = renderTarget.textures; 25436 25437 for ( let i = 0, il = textures.length; i < il; i ++ ) { 25438 25439 const texture = textures[ i ]; 25440 25441 if ( textureNeedsGenerateMipmaps( texture ) ) { 25442
vendor: 4,748 bytes, lines 25443-25588
25443 const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; 25444 const webglTexture = properties.get( texture ).__webglTexture; 25445 25446 state.bindTexture( target, webglTexture ); 25447 generateMipmap( target ); 25448 state.unbindTexture(); 25449 25450 } 25451 25452 } 25453 25454 } 25455 25456 function updateMultisampleRenderTarget( renderTarget ) { 25457 25458 if ( ( renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) { 25459 25460 const textures = renderTarget.textures; 25461 const width = renderTarget.width; 25462 const height = renderTarget.height; 25463 let mask = _gl.COLOR_BUFFER_BIT; 25464 const invalidationArray = []; 25465 const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; 25466 const renderTargetProperties = properties.get( renderTarget ); 25467 const isMultipleRenderTargets = ( textures.length > 1 ); 25468 25469 // If MRT we need to remove FBO attachments 25470 if ( isMultipleRenderTargets ) { 25471 25472 for ( let i = 0; i < textures.length; i ++ ) { 25473 25474 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25475 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null ); 25476 25477 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 25478 _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0 ); 25479 25480 } 25481 25482 } 25483 25484 state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25485 state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 25486 25487 for ( let i = 0; i < textures.length; i ++ ) { 25488 25489 invalidationArray.push( _gl.COLOR_ATTACHMENT0 + i ); 25490 25491 if ( renderTarget.depthBuffer ) { 25492 25493 invalidationArray.push( depthStyle ); 25494 25495 } 25496 25497 const ignoreDepthValues = ( renderTargetProperties.__ignoreDepthValues !== undefined ) ? renderTargetProperties.__ignoreDepthValues : false; 25498 25499 if ( ignoreDepthValues === false ) { 25500 25501 if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT; 25502 25503 // resolving stencil is slow with a D3D backend. disable it for all transmission render targets (see #27799) 25504 25505 if ( renderTarget.stencilBuffer && renderTargetProperties.__isTransmissionRenderTarget !== true ) mask |= _gl.STENCIL_BUFFER_BIT; 25506 25507 } 25508 25509 if ( isMultipleRenderTargets ) { 25510 25511 _gl.framebufferRenderbuffer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 25512 25513 } 25514 25515 if ( ignoreDepthValues === true ) { 25516 25517 _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, [ depthStyle ] ); 25518 _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] ); 25519 25520 } 25521 25522 if ( isMultipleRenderTargets ) { 25523 25524 const webglTexture = properties.get( textures[ i ] ).__webglTexture; 25525 _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0 ); 25526 25527 } 25528 25529 _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST ); 25530 25531 if ( supportsInvalidateFramebuffer ) { 25532 25533 _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArray ); 25534 25535 } 25536 25537 25538 } 25539 25540 state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null ); 25541 state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null ); 25542 25543 // If MRT since pre-blit we removed the FBO we need to reconstruct the attachments 25544 if ( isMultipleRenderTargets ) { 25545 25546 for ( let i = 0; i < textures.length; i ++ ) { 25547 25548 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25549 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 25550 25551 const webglTexture = properties.get( textures[ i ] ).__webglTexture; 25552 25553 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 25554 _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, webglTexture, 0 ); 25555 25556 } 25557 25558 } 25559 25560 state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25561 25562 } 25563 25564 } 25565 25566 function getRenderTargetSamples( renderTarget ) { 25567 25568 return Math.min( capabilities.maxSamples, renderTarget.samples ); 25569 25570 } 25571 25572 function useMultisampledRTT( renderTarget ) { 25573 25574 const renderTargetProperties = properties.get( renderTarget ); 25575 25576 return renderTarget.samples > 0 && extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true && renderTargetProperties.__useRenderToTexture !== false; 25577 25578 } 25579 25580 function updateVideoTexture( texture ) { 25581 25582 const frame = info.render.frame; 25583 25584 // Check the last frame we updated the VideoTexture 25585 25586 if ( _videoTextures.get( texture ) !== frame ) { 25587 25588 _videoTextures.set( texture, frame );
vendor: 9,717 bytes, lines 25589-25864
25589 texture.update(); 25590 25591 } 25592 25593 } 25594 25595 function verifyColorSpace( texture, image ) { 25596 25597 const colorSpace = texture.colorSpace; 25598 const format = texture.format; 25599 const type = texture.type; 25600 25601 if ( texture.isCompressedTexture === true || texture.isVideoTexture === true ) return image; 25602 25603 if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) { 25604 25605 // sRGB 25606 25607 if ( ColorManagement.getTransfer( colorSpace ) === SRGBTransfer ) { 25608 25609 // in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format 25610 25611 if ( format !== RGBAFormat || type !== UnsignedByteType ) { 25612 25613 console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' ); 25614 25615 } 25616 25617 } else { 25618 25619 console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace ); 25620 25621 } 25622 25623 } 25624 25625 return image; 25626 25627 } 25628 25629 function getDimensions( image ) { 25630 25631 if ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) { 25632 25633 // if intrinsic data are not available, fallback to width/height 25634 25635 _imageDimensions.width = image.naturalWidth || image.width; 25636 _imageDimensions.height = image.naturalHeight || image.height; 25637 25638 } else if ( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) { 25639 25640 _imageDimensions.width = image.displayWidth; 25641 _imageDimensions.height = image.displayHeight; 25642 25643 } else { 25644 25645 _imageDimensions.width = image.width; 25646 _imageDimensions.height = image.height; 25647 25648 } 25649 25650 return _imageDimensions; 25651 25652 } 25653 25654 // 25655 25656 this.allocateTextureUnit = allocateTextureUnit; 25657 this.resetTextureUnits = resetTextureUnits; 25658 25659 this.setTexture2D = setTexture2D; 25660 this.setTexture2DArray = setTexture2DArray; 25661 this.setTexture3D = setTexture3D; 25662 this.setTextureCube = setTextureCube; 25663 this.rebindTextures = rebindTextures; 25664 this.setupRenderTarget = setupRenderTarget; 25665 this.updateRenderTargetMipmap = updateRenderTargetMipmap; 25666 this.updateMultisampleRenderTarget = updateMultisampleRenderTarget; 25667 this.setupDepthRenderbuffer = setupDepthRenderbuffer; 25668 this.setupFrameBufferTexture = setupFrameBufferTexture; 25669 this.useMultisampledRTT = useMultisampledRTT; 25670 25671} 25672 25673function WebGLUtils( gl, extensions ) { 25674 25675 function convert( p, colorSpace = NoColorSpace ) { 25676 25677 let extension; 25678 25679 const transfer = ColorManagement.getTransfer( colorSpace ); 25680 25681 if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; 25682 if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; 25683 if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; 25684 if ( p === UnsignedInt5999Type ) return gl.UNSIGNED_INT_5_9_9_9_REV; 25685 25686 if ( p === ByteType ) return gl.BYTE; 25687 if ( p === ShortType ) return gl.SHORT; 25688 if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; 25689 if ( p === IntType ) return gl.INT; 25690 if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; 25691 if ( p === FloatType ) return gl.FLOAT; 25692 if ( p === HalfFloatType ) return gl.HALF_FLOAT; 25693 25694 if ( p === AlphaFormat ) return gl.ALPHA; 25695 if ( p === RGBFormat ) return gl.RGB; 25696 if ( p === RGBAFormat ) return gl.RGBA; 25697 if ( p === LuminanceFormat ) return gl.LUMINANCE; 25698 if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; 25699 if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; 25700 if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; 25701 25702 // WebGL2 formats. 25703 25704 if ( p === RedFormat ) return gl.RED; 25705 if ( p === RedIntegerFormat ) return gl.RED_INTEGER; 25706 if ( p === RGFormat ) return gl.RG; 25707 if ( p === RGIntegerFormat ) return gl.RG_INTEGER; 25708 if ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER; 25709 25710 // S3TC 25711 25712 if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { 25713 25714 if ( transfer === SRGBTransfer ) { 25715 25716 extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); 25717 25718 if ( extension !== null ) { 25719 25720 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT; 25721 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; 25722 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; 25723 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; 25724 25725 } else { 25726 25727 return null; 25728 25729 } 25730 25731 } else { 25732 25733 extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); 25734 25735 if ( extension !== null ) { 25736 25737 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; 25738 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; 25739 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; 25740 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; 25741 25742 } else { 25743 25744 return null; 25745 25746 } 25747 25748 } 25749 25750 } 25751 25752 // PVRTC 25753 25754 if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { 25755 25756 extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); 25757 25758 if ( extension !== null ) { 25759 25760 if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; 25761 if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; 25762 if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; 25763 if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; 25764 25765 } else { 25766 25767 return null; 25768 25769 } 25770 25771 } 25772 25773 // ETC1 25774 25775 if ( p === RGB_ETC1_Format ) { 25776 25777 extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); 25778 25779 if ( extension !== null ) { 25780 25781 return extension.COMPRESSED_RGB_ETC1_WEBGL; 25782 25783 } else { 25784 25785 return null; 25786 25787 } 25788 25789 } 25790 25791 // ETC2 25792 25793 if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { 25794 25795 extension = extensions.get( 'WEBGL_compressed_texture_etc' ); 25796 25797 if ( extension !== null ) { 25798 25799 if ( p === RGB_ETC2_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; 25800 if ( p === RGBA_ETC2_EAC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; 25801 25802 } else { 25803 25804 return null; 25805 25806 } 25807 25808 } 25809 25810 // ASTC 25811 25812 if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format || 25813 p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format || 25814 p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format || 25815 p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format || 25816 p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) { 25817 25818 extension = extensions.get( 'WEBGL_compressed_texture_astc' ); 25819 25820 if ( extension !== null ) { 25821 25822 if ( p === RGBA_ASTC_4x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; 25823 if ( p === RGBA_ASTC_5x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; 25824 if ( p === RGBA_ASTC_5x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; 25825 if ( p === RGBA_ASTC_6x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; 25826 if ( p === RGBA_ASTC_6x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; 25827 if ( p === RGBA_ASTC_8x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; 25828 if ( p === RGBA_ASTC_8x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; 25829 if ( p === RGBA_ASTC_8x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; 25830 if ( p === RGBA_ASTC_10x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; 25831 if ( p === RGBA_ASTC_10x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; 25832 if ( p === RGBA_ASTC_10x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; 25833 if ( p === RGBA_ASTC_10x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; 25834 if ( p === RGBA_ASTC_12x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; 25835 if ( p === RGBA_ASTC_12x12_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; 25836 25837 } else { 25838 25839 return null; 25840 25841 } 25842 25843 } 25844 25845 // BPTC 25846 25847 if ( p === RGBA_BPTC_Format || p === RGB_BPTC_SIGNED_Format || p === RGB_BPTC_UNSIGNED_Format ) { 25848 25849 extension = extensions.get( 'EXT_texture_compression_bptc' ); 25850 25851 if ( extension !== null ) { 25852 25853 if ( p === RGBA_BPTC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; 25854 if ( p === RGB_BPTC_SIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT; 25855 if ( p === RGB_BPTC_UNSIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT; 25856 25857 } else { 25858 25859 return null; 25860 25861 } 25862 25863 } 25864
vendor: 4,803 bytes, lines 25865-26117
25865 // RGTC 25866 25867 if ( p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format ) { 25868 25869 extension = extensions.get( 'EXT_texture_compression_rgtc' ); 25870 25871 if ( extension !== null ) { 25872 25873 if ( p === RGBA_BPTC_Format ) return extension.COMPRESSED_RED_RGTC1_EXT; 25874 if ( p === SIGNED_RED_RGTC1_Format ) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT; 25875 if ( p === RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT; 25876 if ( p === SIGNED_RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT; 25877 25878 } else { 25879 25880 return null; 25881 25882 } 25883 25884 } 25885 25886 // 25887 25888 if ( p === UnsignedInt248Type ) return gl.UNSIGNED_INT_24_8; 25889 25890 // if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats) 25891 25892 return ( gl[ p ] !== undefined ) ? gl[ p ] : null; 25893 25894 } 25895 25896 return { convert: convert }; 25897 25898} 25899 25900class ArrayCamera extends PerspectiveCamera { 25901 25902 constructor( array = [] ) { 25903 25904 super(); 25905 25906 this.isArrayCamera = true; 25907 25908 this.cameras = array; 25909 25910 } 25911 25912} 25913 25914class Group extends Object3D { 25915 25916 constructor() { 25917 25918 super(); 25919 25920 this.isGroup = true; 25921 25922 this.type = 'Group'; 25923 25924 } 25925 25926} 25927 25928const _moveEvent = { type: 'move' }; 25929 25930class WebXRController { 25931 25932 constructor() { 25933 25934 this._targetRay = null; 25935 this._grip = null; 25936 this._hand = null; 25937 25938 } 25939 25940 getHandSpace() { 25941 25942 if ( this._hand === null ) { 25943 25944 this._hand = new Group(); 25945 this._hand.matrixAutoUpdate = false; 25946 this._hand.visible = false; 25947 25948 this._hand.joints = {}; 25949 this._hand.inputState = { pinching: false }; 25950 25951 } 25952 25953 return this._hand; 25954 25955 } 25956 25957 getTargetRaySpace() { 25958 25959 if ( this._targetRay === null ) { 25960 25961 this._targetRay = new Group(); 25962 this._targetRay.matrixAutoUpdate = false; 25963 this._targetRay.visible = false; 25964 this._targetRay.hasLinearVelocity = false; 25965 this._targetRay.linearVelocity = new Vector3(); 25966 this._targetRay.hasAngularVelocity = false; 25967 this._targetRay.angularVelocity = new Vector3(); 25968 25969 } 25970 25971 return this._targetRay; 25972 25973 } 25974 25975 getGripSpace() { 25976 25977 if ( this._grip === null ) { 25978 25979 this._grip = new Group(); 25980 this._grip.matrixAutoUpdate = false; 25981 this._grip.visible = false; 25982 this._grip.hasLinearVelocity = false; 25983 this._grip.linearVelocity = new Vector3(); 25984 this._grip.hasAngularVelocity = false; 25985 this._grip.angularVelocity = new Vector3(); 25986 25987 } 25988 25989 return this._grip; 25990 25991 } 25992 25993 dispatchEvent( event ) { 25994 25995 if ( this._targetRay !== null ) { 25996 25997 this._targetRay.dispatchEvent( event ); 25998 25999 } 26000 26001 if ( this._grip !== null ) { 26002 26003 this._grip.dispatchEvent( event ); 26004 26005 } 26006 26007 if ( this._hand !== null ) { 26008 26009 this._hand.dispatchEvent( event ); 26010 26011 } 26012 26013 return this; 26014 26015 } 26016 26017 connect( inputSource ) { 26018 26019 if ( inputSource && inputSource.hand ) { 26020 26021 const hand = this._hand; 26022 26023 if ( hand ) { 26024 26025 for ( const inputjoint of inputSource.hand.values() ) { 26026 26027 // Initialize hand with joints when connected 26028 this._getHandJoint( hand, inputjoint ); 26029 26030 } 26031 26032 } 26033 26034 } 26035 26036 this.dispatchEvent( { type: 'connected', data: inputSource } ); 26037 26038 return this; 26039 26040 } 26041 26042 disconnect( inputSource ) { 26043 26044 this.dispatchEvent( { type: 'disconnected', data: inputSource } ); 26045 26046 if ( this._targetRay !== null ) { 26047 26048 this._targetRay.visible = false; 26049 26050 } 26051 26052 if ( this._grip !== null ) { 26053 26054 this._grip.visible = false; 26055 26056 } 26057 26058 if ( this._hand !== null ) { 26059 26060 this._hand.visible = false; 26061 26062 } 26063 26064 return this; 26065 26066 } 26067 26068 update( inputSource, frame, referenceSpace ) { 26069 26070 let inputPose = null; 26071 let gripPose = null; 26072 let handPose = null; 26073 26074 const targetRay = this._targetRay; 26075 const grip = this._grip; 26076 const hand = this._hand; 26077 26078 if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) { 26079 26080 if ( hand && inputSource.hand ) { 26081 26082 handPose = true; 26083 26084 for ( const inputjoint of inputSource.hand.values() ) { 26085 26086 // Update the joints groups with the XRJoint poses 26087 const jointPose = frame.getJointPose( inputjoint, referenceSpace ); 26088 26089 // The transform of this joint will be updated with the joint pose on each frame 26090 const joint = this._getHandJoint( hand, inputjoint ); 26091 26092 if ( jointPose !== null ) { 26093 26094 joint.matrix.fromArray( jointPose.transform.matrix ); 26095 joint.matrix.decompose( joint.position, joint.rotation, joint.scale ); 26096 joint.matrixWorldNeedsUpdate = true; 26097 joint.jointRadius = jointPose.radius; 26098 26099 } 26100 26101 joint.visible = jointPose !== null; 26102 26103 } 26104 26105 // Custom events 26106 26107 // Check pinchz 26108 const indexTip = hand.joints[ 'index-finger-tip' ]; 26109 const thumbTip = hand.joints[ 'thumb-tip' ]; 26110 const distance = indexTip.position.distanceTo( thumbTip.position ); 26111 26112 const distanceToPinch = 0.02; 26113 const threshold = 0.005; 26114 26115 if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) { 26116 26117 hand.inputState.pinching = false;
vendor: 14,152 bytes, lines 26118-26783
26118 this.dispatchEvent( { 26119 type: 'pinchend', 26120 handedness: inputSource.handedness, 26121 target: this 26122 } ); 26123 26124 } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) { 26125 26126 hand.inputState.pinching = true; 26127 this.dispatchEvent( { 26128 type: 'pinchstart', 26129 handedness: inputSource.handedness, 26130 target: this 26131 } ); 26132 26133 } 26134 26135 } else { 26136 26137 if ( grip !== null && inputSource.gripSpace ) { 26138 26139 gripPose = frame.getPose( inputSource.gripSpace, referenceSpace ); 26140 26141 if ( gripPose !== null ) { 26142 26143 grip.matrix.fromArray( gripPose.transform.matrix ); 26144 grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); 26145 grip.matrixWorldNeedsUpdate = true; 26146 26147 if ( gripPose.linearVelocity ) { 26148 26149 grip.hasLinearVelocity = true; 26150 grip.linearVelocity.copy( gripPose.linearVelocity ); 26151 26152 } else { 26153 26154 grip.hasLinearVelocity = false; 26155 26156 } 26157 26158 if ( gripPose.angularVelocity ) { 26159 26160 grip.hasAngularVelocity = true; 26161 grip.angularVelocity.copy( gripPose.angularVelocity ); 26162 26163 } else { 26164 26165 grip.hasAngularVelocity = false; 26166 26167 } 26168 26169 } 26170 26171 } 26172 26173 } 26174 26175 if ( targetRay !== null ) { 26176 26177 inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace ); 26178 26179 // Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it 26180 if ( inputPose === null && gripPose !== null ) { 26181 26182 inputPose = gripPose; 26183 26184 } 26185 26186 if ( inputPose !== null ) { 26187 26188 targetRay.matrix.fromArray( inputPose.transform.matrix ); 26189 targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); 26190 targetRay.matrixWorldNeedsUpdate = true; 26191 26192 if ( inputPose.linearVelocity ) { 26193 26194 targetRay.hasLinearVelocity = true; 26195 targetRay.linearVelocity.copy( inputPose.linearVelocity ); 26196 26197 } else { 26198 26199 targetRay.hasLinearVelocity = false; 26200 26201 } 26202 26203 if ( inputPose.angularVelocity ) { 26204 26205 targetRay.hasAngularVelocity = true; 26206 targetRay.angularVelocity.copy( inputPose.angularVelocity ); 26207 26208 } else { 26209 26210 targetRay.hasAngularVelocity = false; 26211 26212 } 26213 26214 this.dispatchEvent( _moveEvent ); 26215 26216 } 26217 26218 } 26219 26220 26221 } 26222 26223 if ( targetRay !== null ) { 26224 26225 targetRay.visible = ( inputPose !== null ); 26226 26227 } 26228 26229 if ( grip !== null ) { 26230 26231 grip.visible = ( gripPose !== null ); 26232 26233 } 26234 26235 if ( hand !== null ) { 26236 26237 hand.visible = ( handPose !== null ); 26238 26239 } 26240 26241 return this; 26242 26243 } 26244 26245 // private method 26246 26247 _getHandJoint( hand, inputjoint ) { 26248 26249 if ( hand.joints[ inputjoint.jointName ] === undefined ) { 26250 26251 const joint = new Group(); 26252 joint.matrixAutoUpdate = false; 26253 joint.visible = false; 26254 hand.joints[ inputjoint.jointName ] = joint; 26255 26256 hand.add( joint ); 26257 26258 } 26259 26260 return hand.joints[ inputjoint.jointName ]; 26261 26262 } 26263 26264} 26265 26266const _occlusion_vertex = ` 26267void main() { 26268 26269 gl_Position = vec4( position, 1.0 ); 26270 26271}`; 26272 26273const _occlusion_fragment = ` 26274uniform sampler2DArray depthColor; 26275uniform float depthWidth; 26276uniform float depthHeight; 26277 26278void main() { 26279 26280 vec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight ); 26281 26282 if ( coord.x >= 1.0 ) { 26283 26284 gl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r; 26285 26286 } else { 26287 26288 gl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r; 26289 26290 } 26291 26292}`; 26293 26294class WebXRDepthSensing { 26295 26296 constructor() { 26297 26298 this.texture = null; 26299 this.mesh = null; 26300 26301 this.depthNear = 0; 26302 this.depthFar = 0; 26303 26304 } 26305 26306 init( renderer, depthData, renderState ) { 26307 26308 if ( this.texture === null ) { 26309 26310 const texture = new Texture(); 26311 26312 const texProps = renderer.properties.get( texture ); 26313 texProps.__webglTexture = depthData.texture; 26314 26315 if ( ( depthData.depthNear != renderState.depthNear ) || ( depthData.depthFar != renderState.depthFar ) ) { 26316 26317 this.depthNear = depthData.depthNear; 26318 this.depthFar = depthData.depthFar; 26319 26320 } 26321 26322 this.texture = texture; 26323 26324 } 26325 26326 } 26327 26328 render( renderer, cameraXR ) { 26329 26330 if ( this.texture !== null ) { 26331 26332 if ( this.mesh === null ) { 26333 26334 const viewport = cameraXR.cameras[ 0 ].viewport; 26335 const material = new ShaderMaterial( { 26336 vertexShader: _occlusion_vertex, 26337 fragmentShader: _occlusion_fragment, 26338 uniforms: { 26339 depthColor: { value: this.texture }, 26340 depthWidth: { value: viewport.z }, 26341 depthHeight: { value: viewport.w } 26342 } 26343 } ); 26344 26345 this.mesh = new Mesh( new PlaneGeometry( 20, 20 ), material ); 26346 26347 } 26348 26349 renderer.render( this.mesh, cameraXR ); 26350 26351 } 26352 26353 } 26354 26355 reset() { 26356 26357 this.texture = null; 26358 this.mesh = null; 26359 26360 } 26361 26362} 26363 26364class WebXRManager extends EventDispatcher { 26365 26366 constructor( renderer, gl ) { 26367 26368 super(); 26369 26370 const scope = this; 26371 26372 let session = null; 26373 26374 let framebufferScaleFactor = 1.0; 26375 26376 let referenceSpace = null; 26377 let referenceSpaceType = 'local-floor'; 26378 // Set default foveation to maximum. 26379 let foveation = 1.0; 26380 let customReferenceSpace = null; 26381 26382 let pose = null; 26383 let glBinding = null; 26384 let glProjLayer = null; 26385 let glBaseLayer = null; 26386 let xrFrame = null; 26387 26388 const depthSensing = new WebXRDepthSensing(); 26389 const attributes = gl.getContextAttributes(); 26390 26391 let initialRenderTarget = null; 26392 let newRenderTarget = null; 26393 26394 const controllers = []; 26395 const controllerInputSources = []; 26396 26397 const currentSize = new Vector2(); 26398 let currentPixelRatio = null; 26399 26400 // 26401 26402 const cameraL = new PerspectiveCamera(); 26403 cameraL.layers.enable( 1 ); 26404 cameraL.viewport = new Vector4(); 26405 26406 const cameraR = new PerspectiveCamera(); 26407 cameraR.layers.enable( 2 ); 26408 cameraR.viewport = new Vector4(); 26409 26410 const cameras = [ cameraL, cameraR ]; 26411 26412 const cameraXR = new ArrayCamera(); 26413 cameraXR.layers.enable( 1 ); 26414 cameraXR.layers.enable( 2 ); 26415 26416 let _currentDepthNear = null; 26417 let _currentDepthFar = null; 26418 26419 // 26420 26421 this.cameraAutoUpdate = true; 26422 this.enabled = false; 26423 26424 this.isPresenting = false; 26425 26426 this.getController = function ( index ) { 26427 26428 let controller = controllers[ index ]; 26429 26430 if ( controller === undefined ) { 26431 26432 controller = new WebXRController(); 26433 controllers[ index ] = controller; 26434 26435 } 26436 26437 return controller.getTargetRaySpace(); 26438 26439 }; 26440 26441 this.getControllerGrip = function ( index ) { 26442 26443 let controller = controllers[ index ]; 26444 26445 if ( controller === undefined ) { 26446 26447 controller = new WebXRController(); 26448 controllers[ index ] = controller; 26449 26450 } 26451 26452 return controller.getGripSpace(); 26453 26454 }; 26455 26456 this.getHand = function ( index ) { 26457 26458 let controller = controllers[ index ]; 26459 26460 if ( controller === undefined ) { 26461 26462 controller = new WebXRController(); 26463 controllers[ index ] = controller; 26464 26465 } 26466 26467 return controller.getHandSpace(); 26468 26469 }; 26470 26471 // 26472 26473 function onSessionEvent( event ) { 26474 26475 const controllerIndex = controllerInputSources.indexOf( event.inputSource ); 26476 26477 if ( controllerIndex === - 1 ) { 26478 26479 return; 26480 26481 } 26482 26483 const controller = controllers[ controllerIndex ]; 26484 26485 if ( controller !== undefined ) { 26486 26487 controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace ); 26488 controller.dispatchEvent( { type: event.type, data: event.inputSource } ); 26489 26490 } 26491 26492 } 26493 26494 function onSessionEnd() { 26495 26496 session.removeEventListener( 'select', onSessionEvent ); 26497 session.removeEventListener( 'selectstart', onSessionEvent ); 26498 session.removeEventListener( 'selectend', onSessionEvent ); 26499 session.removeEventListener( 'squeeze', onSessionEvent ); 26500 session.removeEventListener( 'squeezestart', onSessionEvent ); 26501 session.removeEventListener( 'squeezeend', onSessionEvent ); 26502 session.removeEventListener( 'end', onSessionEnd ); 26503 session.removeEventListener( 'inputsourceschange', onInputSourcesChange ); 26504 26505 for ( let i = 0; i < controllers.length; i ++ ) { 26506 26507 const inputSource = controllerInputSources[ i ]; 26508 26509 if ( inputSource === null ) continue; 26510 26511 controllerInputSources[ i ] = null; 26512 26513 controllers[ i ].disconnect( inputSource ); 26514 26515 } 26516 26517 _currentDepthNear = null; 26518 _currentDepthFar = null; 26519 26520 depthSensing.reset(); 26521 26522 // restore framebuffer/rendering state 26523 26524 renderer.setRenderTarget( initialRenderTarget ); 26525 26526 glBaseLayer = null; 26527 glProjLayer = null; 26528 glBinding = null; 26529 session = null; 26530 newRenderTarget = null; 26531 26532 // 26533 26534 animation.stop(); 26535 26536 scope.isPresenting = false; 26537 26538 renderer.setPixelRatio( currentPixelRatio ); 26539 renderer.setSize( currentSize.width, currentSize.height, false ); 26540 26541 scope.dispatchEvent( { type: 'sessionend' } ); 26542 26543 } 26544 26545 this.setFramebufferScaleFactor = function ( value ) { 26546 26547 framebufferScaleFactor = value; 26548 26549 if ( scope.isPresenting === true ) { 26550 26551 console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' ); 26552 26553 } 26554 26555 }; 26556 26557 this.setReferenceSpaceType = function ( value ) { 26558 26559 referenceSpaceType = value; 26560 26561 if ( scope.isPresenting === true ) { 26562 26563 console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' ); 26564 26565 } 26566 26567 }; 26568 26569 this.getReferenceSpace = function () { 26570 26571 return customReferenceSpace || referenceSpace; 26572 26573 }; 26574 26575 this.setReferenceSpace = function ( space ) { 26576 26577 customReferenceSpace = space; 26578 26579 }; 26580 26581 this.getBaseLayer = function () { 26582 26583 return glProjLayer !== null ? glProjLayer : glBaseLayer; 26584 26585 }; 26586 26587 this.getBinding = function () { 26588 26589 return glBinding; 26590 26591 }; 26592 26593 this.getFrame = function () { 26594 26595 return xrFrame; 26596 26597 }; 26598 26599 this.getSession = function () { 26600 26601 return session; 26602 26603 }; 26604 26605 this.setSession = async function ( value ) { 26606 26607 session = value; 26608 26609 if ( session !== null ) { 26610 26611 initialRenderTarget = renderer.getRenderTarget(); 26612 26613 session.addEventListener( 'select', onSessionEvent ); 26614 session.addEventListener( 'selectstart', onSessionEvent ); 26615 session.addEventListener( 'selectend', onSessionEvent ); 26616 session.addEventListener( 'squeeze', onSessionEvent ); 26617 session.addEventListener( 'squeezestart', onSessionEvent ); 26618 session.addEventListener( 'squeezeend', onSessionEvent ); 26619 session.addEventListener( 'end', onSessionEnd ); 26620 session.addEventListener( 'inputsourceschange', onInputSourcesChange ); 26621 26622 if ( attributes.xrCompatible !== true ) { 26623 26624 await gl.makeXRCompatible(); 26625 26626 } 26627 26628 currentPixelRatio = renderer.getPixelRatio(); 26629 renderer.getSize( currentSize ); 26630 26631 if ( session.renderState.layers === undefined ) { 26632 26633 const layerInit = { 26634 antialias: attributes.antialias, 26635 alpha: true, 26636 depth: attributes.depth, 26637 stencil: attributes.stencil, 26638 framebufferScaleFactor: framebufferScaleFactor 26639 }; 26640 26641 glBaseLayer = new XRWebGLLayer( session, gl, layerInit ); 26642 26643 session.updateRenderState( { baseLayer: glBaseLayer } ); 26644 26645 renderer.setPixelRatio( 1 ); 26646 renderer.setSize( glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, false ); 26647 26648 newRenderTarget = new WebGLRenderTarget( 26649 glBaseLayer.framebufferWidth, 26650 glBaseLayer.framebufferHeight, 26651 { 26652 format: RGBAFormat, 26653 type: UnsignedByteType, 26654 colorSpace: renderer.outputColorSpace, 26655 stencilBuffer: attributes.stencil 26656 } 26657 ); 26658 26659 } else { 26660 26661 let depthFormat = null; 26662 let depthType = null; 26663 let glDepthFormat = null; 26664 26665 if ( attributes.depth ) { 26666 26667 glDepthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24; 26668 depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat; 26669 depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType; 26670 26671 } 26672 26673 const projectionlayerInit = { 26674 colorFormat: gl.RGBA8, 26675 depthFormat: glDepthFormat, 26676 scaleFactor: framebufferScaleFactor 26677 }; 26678 26679 glBinding = new XRWebGLBinding( session, gl ); 26680 26681 glProjLayer = glBinding.createProjectionLayer( projectionlayerInit ); 26682 26683 session.updateRenderState( { layers: [ glProjLayer ] } ); 26684 26685 renderer.setPixelRatio( 1 ); 26686 renderer.setSize( glProjLayer.textureWidth, glProjLayer.textureHeight, false ); 26687 26688 newRenderTarget = new WebGLRenderTarget( 26689 glProjLayer.textureWidth, 26690 glProjLayer.textureHeight, 26691 { 26692 format: RGBAFormat, 26693 type: UnsignedByteType, 26694 depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), 26695 stencilBuffer: attributes.stencil, 26696 colorSpace: renderer.outputColorSpace, 26697 samples: attributes.antialias ? 4 : 0 26698 } ); 26699 26700 const renderTargetProperties = renderer.properties.get( newRenderTarget ); 26701 renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues; 26702 26703 } 26704 26705 newRenderTarget.isXRRenderTarget = true; // TODO Remove this when possible, see #23278 26706 26707 this.setFoveation( foveation ); 26708 26709 customReferenceSpace = null; 26710 referenceSpace = await session.requestReferenceSpace( referenceSpaceType ); 26711 26712 animation.setContext( session ); 26713 animation.start(); 26714 26715 scope.isPresenting = true; 26716 26717 scope.dispatchEvent( { type: 'sessionstart' } ); 26718 26719 } 26720 26721 }; 26722 26723 this.getEnvironmentBlendMode = function () { 26724 26725 if ( session !== null ) { 26726 26727 return session.environmentBlendMode; 26728 26729 } 26730 26731 }; 26732 26733 function onInputSourcesChange( event ) { 26734 26735 // Notify disconnected 26736 26737 for ( let i = 0; i < event.removed.length; i ++ ) { 26738 26739 const inputSource = event.removed[ i ]; 26740 const index = controllerInputSources.indexOf( inputSource ); 26741 26742 if ( index >= 0 ) { 26743 26744 controllerInputSources[ index ] = null; 26745 controllers[ index ].disconnect( inputSource ); 26746 26747 } 26748 26749 } 26750 26751 // Notify connected 26752 26753 for ( let i = 0; i < event.added.length; i ++ ) { 26754 26755 const inputSource = event.added[ i ]; 26756 26757 let controllerIndex = controllerInputSources.indexOf( inputSource ); 26758 26759 if ( controllerIndex === - 1 ) { 26760 26761 // Assign input source a controller that currently has no input source 26762 26763 for ( let i = 0; i < controllers.length; i ++ ) { 26764 26765 if ( i >= controllerInputSources.length ) { 26766 26767 controllerInputSources.push( inputSource ); 26768 controllerIndex = i; 26769 break; 26770 26771 } else if ( controllerInputSources[ i ] === null ) { 26772 26773 controllerInputSources[ i ] = inputSource; 26774 controllerIndex = i; 26775 break; 26776 26777 } 26778 26779 } 26780 26781 // If all controllers do currently receive input we ignore new ones 26782 26783 if ( controllerIndex === -
vendor: 12,726 bytes, lines 26783-27329
267831 ) break; 26784 26785 } 26786 26787 const controller = controllers[ controllerIndex ]; 26788 26789 if ( controller ) { 26790 26791 controller.connect( inputSource ); 26792 26793 } 26794 26795 } 26796 26797 } 26798 26799 // 26800 26801 const cameraLPos = new Vector3(); 26802 const cameraRPos = new Vector3(); 26803 26804 /** 26805 * Assumes 2 cameras that are parallel and share an X-axis, and that 26806 * the cameras' projection and world matrices have already been set. 26807 * And that near and far planes are identical for both cameras. 26808 * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 26809 */ 26810 function setProjectionFromUnion( camera, cameraL, cameraR ) { 26811 26812 cameraLPos.setFromMatrixPosition( cameraL.matrixWorld ); 26813 cameraRPos.setFromMatrixPosition( cameraR.matrixWorld ); 26814 26815 const ipd = cameraLPos.distanceTo( cameraRPos ); 26816 26817 const projL = cameraL.projectionMatrix.elements; 26818 const projR = cameraR.projectionMatrix.elements; 26819 26820 // VR systems will have identical far and near planes, and 26821 // most likely identical top and bottom frustum extents. 26822 // Use the left camera for these values. 26823 const near = projL[ 14 ] / ( projL[ 10 ] - 1 ); 26824 const far = projL[ 14 ] / ( projL[ 10 ] + 1 ); 26825 const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ]; 26826 const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ]; 26827 26828 const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ]; 26829 const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ]; 26830 const left = near * leftFov; 26831 const right = near * rightFov; 26832 26833 // Calculate the new camera's position offset from the 26834 // left camera. xOffset should be roughly half `ipd`. 26835 const zOffset = ipd / ( - leftFov + rightFov ); 26836 const xOffset = zOffset * - leftFov; 26837 26838 // TODO: Better way to apply this offset? 26839 cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale ); 26840 camera.translateX( xOffset ); 26841 camera.translateZ( zOffset ); 26842 camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale ); 26843 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); 26844 26845 // Find the union of the frustum values of the cameras and scale 26846 // the values so that the near plane's position does not change in world space, 26847 // although must now be relative to the new union camera. 26848 const near2 = near + zOffset; 26849 const far2 = far + zOffset; 26850 const left2 = left - xOffset; 26851 const right2 = right + ( ipd - xOffset ); 26852 const top2 = topFov * far / far2 * near2; 26853 const bottom2 = bottomFov * far / far2 * near2; 26854 26855 camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); 26856 camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); 26857 26858 } 26859 26860 function updateCamera( camera, parent ) { 26861 26862 if ( parent === null ) { 26863 26864 camera.matrixWorld.copy( camera.matrix ); 26865 26866 } else { 26867 26868 camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix ); 26869 26870 } 26871 26872 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); 26873 26874 } 26875 26876 this.updateCamera = function ( camera ) { 26877 26878 if ( session === null ) return; 26879 26880 if ( depthSensing.texture !== null ) { 26881 26882 camera.near = depthSensing.depthNear; 26883 camera.far = depthSensing.depthFar; 26884 26885 } 26886 26887 cameraXR.near = cameraR.near = cameraL.near = camera.near; 26888 cameraXR.far = cameraR.far = cameraL.far = camera.far; 26889 26890 if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) { 26891 26892 // Note that the new renderState won't apply until the next frame. See #18320 26893 26894 session.updateRenderState( { 26895 depthNear: cameraXR.near, 26896 depthFar: cameraXR.far 26897 } ); 26898 26899 _currentDepthNear = cameraXR.near; 26900 _currentDepthFar = cameraXR.far; 26901 26902 cameraL.near = _currentDepthNear; 26903 cameraL.far = _currentDepthFar; 26904 cameraR.near = _currentDepthNear; 26905 cameraR.far = _currentDepthFar; 26906 26907 cameraL.updateProjectionMatrix(); 26908 cameraR.updateProjectionMatrix(); 26909 camera.updateProjectionMatrix(); 26910 26911 } 26912 26913 const parent = camera.parent; 26914 const cameras = cameraXR.cameras; 26915 26916 updateCamera( cameraXR, parent ); 26917 26918 for ( let i = 0; i < cameras.length; i ++ ) { 26919 26920 updateCamera( cameras[ i ], parent ); 26921 26922 } 26923 26924 // update projection matrix for proper view frustum culling 26925 26926 if ( cameras.length === 2 ) { 26927 26928 setProjectionFromUnion( cameraXR, cameraL, cameraR ); 26929 26930 } else { 26931 26932 // assume single camera setup (AR) 26933 26934 cameraXR.projectionMatrix.copy( cameraL.projectionMatrix ); 26935 26936 } 26937 26938 // update user camera and its children 26939 26940 updateUserCamera( camera, cameraXR, parent ); 26941 26942 }; 26943 26944 function updateUserCamera( camera, cameraXR, parent ) { 26945 26946 if ( parent === null ) { 26947 26948 camera.matrix.copy( cameraXR.matrixWorld ); 26949 26950 } else { 26951 26952 camera.matrix.copy( parent.matrixWorld ); 26953 camera.matrix.invert(); 26954 camera.matrix.multiply( cameraXR.matrixWorld ); 26955 26956 } 26957 26958 camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); 26959 camera.updateMatrixWorld( true ); 26960 26961 camera.projectionMatrix.copy( cameraXR.projectionMatrix ); 26962 camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse ); 26963 26964 if ( camera.isPerspectiveCamera ) { 26965 26966 camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] ); 26967 camera.zoom = 1; 26968 26969 } 26970 26971 } 26972 26973 this.getCamera = function () { 26974 26975 return cameraXR; 26976 26977 }; 26978 26979 this.getFoveation = function () { 26980 26981 if ( glProjLayer === null && glBaseLayer === null ) { 26982 26983 return undefined; 26984 26985 } 26986 26987 return foveation; 26988 26989 }; 26990 26991 this.setFoveation = function ( value ) { 26992 26993 // 0 = no foveation = full resolution 26994 // 1 = maximum foveation = the edges render at lower resolution 26995 26996 foveation = value; 26997 26998 if ( glProjLayer !== null ) { 26999 27000 glProjLayer.fixedFoveation = value; 27001 27002 } 27003 27004 if ( glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined ) { 27005 27006 glBaseLayer.fixedFoveation = value; 27007 27008 } 27009 27010 }; 27011 27012 this.hasDepthSensing = function () { 27013 27014 return depthSensing.texture !== null; 27015 27016 }; 27017 27018 // Animation Loop 27019 27020 let onAnimationFrameCallback = null; 27021 27022 function onAnimationFrame( time, frame ) { 27023 27024 pose = frame.getViewerPose( customReferenceSpace || referenceSpace ); 27025 xrFrame = frame; 27026 27027 if ( pose !== null ) { 27028 27029 const views = pose.views; 27030 27031 if ( glBaseLayer !== null ) { 27032 27033 renderer.setRenderTargetFramebuffer( newRenderTarget, glBaseLayer.framebuffer ); 27034 renderer.setRenderTarget( newRenderTarget ); 27035 27036 } 27037 27038 let cameraXRNeedsUpdate = false; 27039 27040 // check if it's necessary to rebuild cameraXR's camera list 27041 27042 if ( views.length !== cameraXR.cameras.length ) { 27043 27044 cameraXR.cameras.length = 0; 27045 cameraXRNeedsUpdate = true; 27046 27047 } 27048 27049 for ( let i = 0; i < views.length; i ++ ) { 27050 27051 const view = views[ i ]; 27052 27053 let viewport = null; 27054 27055 if ( glBaseLayer !== null ) { 27056 27057 viewport = glBaseLayer.getViewport( view ); 27058 27059 } else { 27060 27061 const glSubImage = glBinding.getViewSubImage( glProjLayer, view ); 27062 viewport = glSubImage.viewport; 27063 27064 // For side-by-side projection, we only produce a single texture for both eyes. 27065 if ( i === 0 ) { 27066 27067 renderer.setRenderTargetTextures( 27068 newRenderTarget, 27069 glSubImage.colorTexture, 27070 glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture ); 27071 27072 renderer.setRenderTarget( newRenderTarget ); 27073 27074 } 27075 27076 } 27077 27078 let camera = cameras[ i ]; 27079 27080 if ( camera === undefined ) { 27081 27082 camera = new PerspectiveCamera(); 27083 camera.layers.enable( i ); 27084 camera.viewport = new Vector4(); 27085 cameras[ i ] = camera; 27086 27087 } 27088 27089 camera.matrix.fromArray( view.transform.matrix ); 27090 camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); 27091 camera.projectionMatrix.fromArray( view.projectionMatrix ); 27092 camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); 27093 camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); 27094 27095 if ( i === 0 ) { 27096 27097 cameraXR.matrix.copy( camera.matrix ); 27098 cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale ); 27099 27100 } 27101 27102 if ( cameraXRNeedsUpdate === true ) { 27103 27104 cameraXR.cameras.push( camera ); 27105 27106 } 27107 27108 } 27109 27110 // 27111 27112 const enabledFeatures = session.enabledFeatures; 27113 27114 if ( enabledFeatures && enabledFeatures.includes( 'depth-sensing' ) ) { 27115 27116 const depthData = glBinding.getDepthInformation( views[ 0 ] ); 27117 27118 if ( depthData && depthData.isValid && depthData.texture ) { 27119 27120 depthSensing.init( renderer, depthData, session.renderState ); 27121 27122 } 27123 27124 } 27125 27126 } 27127 27128 // 27129 27130 for ( let i = 0; i < controllers.length; i ++ ) { 27131 27132 const inputSource = controllerInputSources[ i ]; 27133 const controller = controllers[ i ]; 27134 27135 if ( inputSource !== null && controller !== undefined ) { 27136 27137 controller.update( inputSource, frame, customReferenceSpace || referenceSpace ); 27138 27139 } 27140 27141 } 27142 27143 depthSensing.render( renderer, cameraXR ); 27144 27145 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame ); 27146 27147 if ( frame.detectedPlanes ) { 27148 27149 scope.dispatchEvent( { type: 'planesdetected', data: frame } ); 27150 27151 } 27152 27153 xrFrame = null; 27154 27155 } 27156 27157 const animation = new WebGLAnimation(); 27158 27159 animation.setAnimationLoop( onAnimationFrame ); 27160 27161 this.setAnimationLoop = function ( callback ) { 27162 27163 onAnimationFrameCallback = callback; 27164 27165 }; 27166 27167 this.dispose = function () {}; 27168 27169 } 27170 27171} 27172 27173const _e1 = /*@__PURE__*/ new Euler(); 27174const _m1 = /*@__PURE__*/ new Matrix4(); 27175 27176function WebGLMaterials( renderer, properties ) { 27177 27178 function refreshTransformUniform( map, uniform ) { 27179 27180 if ( map.matrixAutoUpdate === true ) { 27181 27182 map.updateMatrix(); 27183 27184 } 27185 27186 uniform.value.copy( map.matrix ); 27187 27188 } 27189 27190 function refreshFogUniforms( uniforms, fog ) { 27191 27192 fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) ); 27193 27194 if ( fog.isFog ) { 27195 27196 uniforms.fogNear.value = fog.near; 27197 uniforms.fogFar.value = fog.far; 27198 27199 } else if ( fog.isFogExp2 ) { 27200 27201 uniforms.fogDensity.value = fog.density; 27202 27203 } 27204 27205 } 27206 27207 function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) { 27208 27209 if ( material.isMeshBasicMaterial ) { 27210 27211 refreshUniformsCommon( uniforms, material ); 27212 27213 } else if ( material.isMeshLambertMaterial ) { 27214 27215 refreshUniformsCommon( uniforms, material ); 27216 27217 } else if ( material.isMeshToonMaterial ) { 27218 27219 refreshUniformsCommon( uniforms, material ); 27220 refreshUniformsToon( uniforms, material ); 27221 27222 } else if ( material.isMeshPhongMaterial ) { 27223 27224 refreshUniformsCommon( uniforms, material ); 27225 refreshUniformsPhong( uniforms, material ); 27226 27227 } else if ( material.isMeshStandardMaterial ) { 27228 27229 refreshUniformsCommon( uniforms, material ); 27230 refreshUniformsStandard( uniforms, material ); 27231 27232 if ( material.isMeshPhysicalMaterial ) { 27233 27234 refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ); 27235 27236 } 27237 27238 } else if ( material.isMeshMatcapMaterial ) { 27239 27240 refreshUniformsCommon( uniforms, material ); 27241 refreshUniformsMatcap( uniforms, material ); 27242 27243 } else if ( material.isMeshDepthMaterial ) { 27244 27245 refreshUniformsCommon( uniforms, material ); 27246 27247 } else if ( material.isMeshDistanceMaterial ) { 27248 27249 refreshUniformsCommon( uniforms, material ); 27250 refreshUniformsDistance( uniforms, material ); 27251 27252 } else if ( material.isMeshNormalMaterial ) { 27253 27254 refreshUniformsCommon( uniforms, material ); 27255 27256 } else if ( material.isLineBasicMaterial ) { 27257 27258 refreshUniformsLine( uniforms, material ); 27259 27260 if ( material.isLineDashedMaterial ) { 27261 27262 refreshUniformsDash( uniforms, material ); 27263 27264 } 27265 27266 } else if ( material.isPointsMaterial ) { 27267 27268 refreshUniformsPoints( uniforms, material, pixelRatio, height ); 27269 27270 } else if ( material.isSpriteMaterial ) { 27271 27272 refreshUniformsSprites( uniforms, material ); 27273 27274 } else if ( material.isShadowMaterial ) { 27275 27276 uniforms.color.value.copy( material.color ); 27277 uniforms.opacity.value = material.opacity; 27278 27279 } else if ( material.isShaderMaterial ) { 27280 27281 material.uniformsNeedUpdate = false; // #15581 27282 27283 } 27284 27285 } 27286 27287 function refreshUniformsCommon( uniforms, material ) { 27288 27289 uniforms.opacity.value = material.opacity; 27290 27291 if ( material.color ) { 27292 27293 uniforms.diffuse.value.copy( material.color ); 27294 27295 } 27296 27297 if ( material.emissive ) { 27298 27299 uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity ); 27300 27301 } 27302 27303 if ( material.map ) { 27304 27305 uniforms.map.value = material.map; 27306 27307 refreshTransformUniform( material.map, uniforms.mapTransform ); 27308 27309 } 27310 27311 if ( material.alphaMap ) { 27312 27313 uniforms.alphaMap.value = material.alphaMap; 27314 27315 refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); 27316 27317 } 27318 27319 if ( material.bumpMap ) { 27320 27321 uniforms.bumpMap.value = material.bumpMap; 27322 27323 refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform ); 27324 27325 uniforms.bumpScale.value = material.bumpScale; 27326 27327 if ( material.side === BackSide ) { 27328 27329 uniforms.bumpScale.value *= -
27329 1; 27330 27331 } 27332 27333 } 27334 27335 if ( material.normalMap ) { 27336 27337 uniforms.normalMap.value = material.normalMap; 27338 27339 refreshTransformUniform( material.normalMap, uniforms.normalMapTransform ); 27340 27341 uniforms.normalScale.value.copy( material.normalScale ); 27342 27343 if ( material.side === BackSide ) { 27344 27345 uniforms.normalScale.value.negate(); 27346 27347 } 27348 27349 } 27350 27351 if ( material.displacementMap ) { 27352 27353 uniforms.displacementMap.value = material.displacementMap; 27354 27355 refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform ); 27356 27357 uniforms.displacementScale.value = material.displacementScale; 27358 uniforms.displacementBias.value = material.displacementBias; 27359 27360 } 27361 27362 if ( material.emissiveMap ) { 27363 27364 uniforms.emissiveMap.value = material.emissiveMap; 27365 27366 refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform ); 27367 27368 } 27369 27370 if ( material.specularMap ) { 27371 27372 uniforms.specularMap.value = material.specularMap; 27373 27374 refreshTransformUniform( material.specularMap, uniforms.specularMapTransform ); 27375 27376 } 27377 27378 if ( material.alphaTest > 0 ) { 27379 27380 uniforms.alphaTest.value = material.alphaTest; 27381 27382 } 27383 27384 const materialProperties = properties.get( material ); 27385 27386 const envMap = materialProperties.envMap; 27387 const envMapRotation = materialProperties.envMapRotation; 27388 27389 if ( envMap ) { 27390 27391 uniforms.envMap.value = envMap; 27392 27393 _e1.copy( envMapRotation ); 27394 27395 // accommodate left-handed frame 27396 _e1.x *= - 1; _e1.y *= - 1; _e1.z *= - 1; 27397 27398 if ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) { 27399 27400 // environment maps which are not cube render targets or PMREMs follow a different c
vendor: 10,580 bytes, lines 27400-27829
27400onvention 27401 _e1.y *= - 1; 27402 _e1.z *= - 1; 27403 27404 } 27405 27406 uniforms.envMapRotation.value.setFromMatrix4( _m1.makeRotationFromEuler( _e1 ) ); 27407 27408 uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; 27409 27410 uniforms.reflectivity.value = material.reflectivity; 27411 uniforms.ior.value = material.ior; 27412 uniforms.refractionRatio.value = material.refractionRatio; 27413 27414 } 27415 27416 if ( material.lightMap ) { 27417 27418 uniforms.lightMap.value = material.lightMap; 27419 27420 // artist-friendly light intensity scaling factor 27421 const scaleFactor = ( renderer._useLegacyLights === true ) ? Math.PI : 1; 27422 27423 uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor; 27424 27425 refreshTransformUniform( material.lightMap, uniforms.lightMapTransform ); 27426 27427 } 27428 27429 if ( material.aoMap ) { 27430 27431 uniforms.aoMap.value = material.aoMap; 27432 uniforms.aoMapIntensity.value = material.aoMapIntensity; 27433 27434 refreshTransformUniform( material.aoMap, uniforms.aoMapTransform ); 27435 27436 } 27437 27438 } 27439 27440 function refreshUniformsLine( uniforms, material ) { 27441 27442 uniforms.diffuse.value.copy( material.color ); 27443 uniforms.opacity.value = material.opacity; 27444 27445 if ( material.map ) { 27446 27447 uniforms.map.value = material.map; 27448 27449 refreshTransformUniform( material.map, uniforms.mapTransform ); 27450 27451 } 27452 27453 } 27454 27455 function refreshUniformsDash( uniforms, material ) { 27456 27457 uniforms.dashSize.value = material.dashSize; 27458 uniforms.totalSize.value = material.dashSize + material.gapSize; 27459 uniforms.scale.value = material.scale; 27460 27461 } 27462 27463 function refreshUniformsPoints( uniforms, material, pixelRatio, height ) { 27464 27465 uniforms.diffuse.value.copy( material.color ); 27466 uniforms.opacity.value = material.opacity; 27467 uniforms.size.value = material.size * pixelRatio; 27468 uniforms.scale.value = height * 0.5; 27469 27470 if ( material.map ) { 27471 27472 uniforms.map.value = material.map; 27473 27474 refreshTransformUniform( material.map, uniforms.uvTransform ); 27475 27476 } 27477 27478 if ( material.alphaMap ) { 27479 27480 uniforms.alphaMap.value = material.alphaMap; 27481 27482 refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); 27483 27484 } 27485 27486 if ( material.alphaTest > 0 ) { 27487 27488 uniforms.alphaTest.value = material.alphaTest; 27489 27490 } 27491 27492 } 27493 27494 function refreshUniformsSprites( uniforms, material ) { 27495 27496 uniforms.diffuse.value.copy( material.color ); 27497 uniforms.opacity.value = material.opacity; 27498 uniforms.rotation.value = material.rotation; 27499 27500 if ( material.map ) { 27501 27502 uniforms.map.value = material.map; 27503 27504 refreshTransformUniform( material.map, uniforms.mapTransform ); 27505 27506 } 27507 27508 if ( material.alphaMap ) { 27509 27510 uniforms.alphaMap.value = material.alphaMap; 27511 27512 refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); 27513 27514 } 27515 27516 if ( material.alphaTest > 0 ) { 27517 27518 uniforms.alphaTest.value = material.alphaTest; 27519 27520 } 27521 27522 } 27523 27524 function refreshUniformsPhong( uniforms, material ) { 27525 27526 uniforms.specular.value.copy( material.specular ); 27527 uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 ) 27528 27529 } 27530 27531 function refreshUniformsToon( uniforms, material ) { 27532 27533 if ( material.gradientMap ) { 27534 27535 uniforms.gradientMap.value = material.gradientMap; 27536 27537 } 27538 27539 } 27540 27541 function refreshUniformsStandard( uniforms, material ) { 27542 27543 uniforms.metalness.value = material.metalness; 27544 27545 if ( material.metalnessMap ) { 27546 27547 uniforms.metalnessMap.value = material.metalnessMap; 27548 27549 refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform ); 27550 27551 } 27552 27553 uniforms.roughness.value = material.roughness; 27554 27555 if ( material.roughnessMap ) { 27556 27557 uniforms.roughnessMap.value = material.roughnessMap; 27558 27559 refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform ); 27560 27561 } 27562 27563 if ( material.envMap ) { 27564 27565 //uniforms.envMap.value = material.envMap; // part of uniforms common 27566 27567 uniforms.envMapIntensity.value = material.envMapIntensity; 27568 27569 } 27570 27571 } 27572 27573 function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) { 27574 27575 uniforms.ior.value = material.ior; // also part of uniforms common 27576 27577 if ( material.sheen > 0 ) { 27578 27579 uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen ); 27580 27581 uniforms.sheenRoughness.value = material.sheenRoughness; 27582 27583 if ( material.sheenColorMap ) { 27584 27585 uniforms.sheenColorMap.value = material.sheenColorMap; 27586 27587 refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform ); 27588 27589 } 27590 27591 if ( material.sheenRoughnessMap ) { 27592 27593 uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; 27594 27595 refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform ); 27596 27597 } 27598 27599 } 27600 27601 if ( material.clearcoat > 0 ) { 27602 27603 uniforms.clearcoat.value = material.clearcoat; 27604 uniforms.clearcoatRoughness.value = material.clearcoatRoughness; 27605 27606 if ( material.clearcoatMap ) { 27607 27608 uniforms.clearcoatMap.value = material.clearcoatMap; 27609 27610 refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform ); 27611 27612 } 27613 27614 if ( material.clearcoatRoughnessMap ) { 27615 27616 uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; 27617 27618 refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform ); 27619 27620 } 27621 27622 if ( material.clearcoatNormalMap ) { 27623 27624 uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; 27625 27626 refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform ); 27627 27628 uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); 27629 27630 if ( material.side === BackSide ) { 27631 27632 uniforms.clearcoatNormalScale.value.negate(); 27633 27634 } 27635 27636 } 27637 27638 } 27639 27640 if ( material.iridescence > 0 ) { 27641 27642 uniforms.iridescence.value = material.iridescence; 27643 uniforms.iridescenceIOR.value = material.iridescenceIOR; 27644 uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[ 0 ]; 27645 uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[ 1 ]; 27646 27647 if ( material.iridescenceMap ) { 27648 27649 uniforms.iridescenceMap.value = material.iridescenceMap; 27650 27651 refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform ); 27652 27653 } 27654 27655 if ( material.iridescenceThicknessMap ) { 27656 27657 uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; 27658 27659 refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform ); 27660 27661 } 27662 27663 } 27664 27665 if ( material.transmission > 0 ) { 27666 27667 uniforms.transmission.value = material.transmission; 27668 uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture; 27669 uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height ); 27670 27671 if ( material.transmissionMap ) { 27672 27673 uniforms.transmissionMap.value = material.transmissionMap; 27674 27675 refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform ); 27676 27677 } 27678 27679 uniforms.thickness.value = material.thickness; 27680 27681 if ( material.thicknessMap ) { 27682 27683 uniforms.thicknessMap.value = material.thicknessMap; 27684 27685 refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform ); 27686 27687 } 27688 27689 uniforms.attenuationDistance.value = material.attenuationDistance; 27690 uniforms.attenuationColor.value.copy( material.attenuationColor ); 27691 27692 } 27693 27694 if ( material.anisotropy > 0 ) { 27695 27696 uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); 27697 27698 if ( material.anisotropyMap ) { 27699 27700 uniforms.anisotropyMap.value = material.anisotropyMap; 27701 27702 refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform ); 27703 27704 } 27705 27706 } 27707 27708 uniforms.specularIntensity.value = material.specularIntensity; 27709 uniforms.specularColor.value.copy( material.specularColor ); 27710 27711 if ( material.specularColorMap ) { 27712 27713 uniforms.specularColorMap.value = material.specularColorMap; 27714 27715 refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform ); 27716 27717 } 27718 27719 if ( material.specularIntensityMap ) { 27720 27721 uniforms.specularIntensityMap.value = material.specularIntensityMap; 27722 27723 refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform ); 27724 27725 } 27726 27727 } 27728 27729 function refreshUniformsMatcap( uniforms, material ) { 27730 27731 if ( material.matcap ) { 27732 27733 uniforms.matcap.value = material.matcap; 27734 27735 } 27736 27737 } 27738 27739 function refreshUniformsDistance( uniforms, material ) { 27740 27741 const light = properties.get( material ).light; 27742 27743 uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld ); 27744 uniforms.nearDistance.value = light.shadow.camera.near; 27745 uniforms.farDistance.value = light.shadow.camera.far; 27746 27747 } 27748 27749 return { 27750 refreshFogUniforms: refreshFogUniforms, 27751 refreshMaterialUniforms: refreshMaterialUniforms 27752 }; 27753 27754} 27755 27756function WebGLUniformsGroups( gl, info, capabilities, state ) { 27757 27758 let buffers = {}; 27759 let updateList = {}; 27760 let allocatedBindingPoints = []; 27761 27762 const maxBindingPoints = gl.getParameter( gl.MAX_UNIFORM_BUFFER_BINDINGS ); // binding points are global whereas block indices are per shader program 27763 27764 function bind( uniformsGroup, program ) { 27765 27766 const webglProgram = program.program; 27767 state.uniformBlockBinding( uniformsGroup, webglProgram ); 27768 27769 } 27770 27771 function update( uniformsGroup, program ) { 27772 27773 let buffer = buffers[ uniformsGroup.id ]; 27774 27775 if ( buffer === undefined ) { 27776 27777 prepareUniformsGroup( uniformsGroup ); 27778 27779 buffer = createBuffer( uniformsGroup ); 27780 buffers[ uniformsGroup.id ] = buffer; 27781 27782 uniformsGroup.addEventListener( 'dispose', onUniformsGroupsDispose ); 27783 27784 } 27785 27786 // ensure to update the binding points/block indices mapping for this program 27787 27788 const webglProgram = program.program; 27789 state.updateUBOMapping( uniformsGroup, webglProgram ); 27790 27791 // update UBO once per frame 27792 27793 const frame = info.render.frame; 27794 27795 if ( updateList[ uniformsGroup.id ] !== frame ) { 27796 27797 updateBufferData( uniformsGroup ); 27798 27799 updateList[ uniformsGroup.id ] = frame; 27800 27801 } 27802 27803 } 27804 27805 function createBuffer( uniformsGroup ) { 27806 27807 // the setup of an UBO is independent of a particular shader program but global 27808 27809 const bindingPointIndex = allocateBindingPointIndex(); 27810 uniformsGroup.__bindingPointIndex = bindingPointIndex; 27811 27812 const buffer = gl.createBuffer(); 27813 const size = uniformsGroup.__size; 27814 const usage = uniformsGroup.usage; 27815 27816 gl.bindBuffer( gl.UNIFORM_BUFFER, buffer ); 27817 gl.bufferData( gl.UNIFORM_BUFFER, size, usage ); 27818 gl.bindBuffer( gl.UNIFORM_BUFFER, null ); 27819 gl.bindBufferBase( gl.UNIFORM_BUFFER, bindingPointIndex, buffer ); 27820 27821 return buffer; 27822 27823 } 27824 27825 function allocateBindingPointIndex() { 27826 27827 for ( let i = 0; i < maxBindingPoints; i ++ ) { 27828 27829 if ( allocatedBindingPoints.indexOf( i ) === -
vendor: 6,630 bytes, lines 27829-28154
278291 ) { 27830 27831 allocatedBindingPoints.push( i ); 27832 return i; 27833 27834 } 27835 27836 } 27837 27838 console.error( 'THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' ); 27839 27840 return 0; 27841 27842 } 27843 27844 function updateBufferData( uniformsGroup ) { 27845 27846 const buffer = buffers[ uniformsGroup.id ]; 27847 const uniforms = uniformsGroup.uniforms; 27848 const cache = uniformsGroup.__cache; 27849 27850 gl.bindBuffer( gl.UNIFORM_BUFFER, buffer ); 27851 27852 for ( let i = 0, il = uniforms.length; i < il; i ++ ) { 27853 27854 const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ]; 27855 27856 for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) { 27857 27858 const uniform = uniformArray[ j ]; 27859 27860 if ( hasUniformChanged( uniform, i, j, cache ) === true ) { 27861 27862 const offset = uniform.__offset; 27863 27864 const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; 27865 27866 let arrayOffset = 0; 27867 27868 for ( let k = 0; k < values.length; k ++ ) { 27869 27870 const value = values[ k ]; 27871 27872 const info = getUniformSize( value ); 27873 27874 // TODO add integer and struct support 27875 if ( typeof value === 'number' || typeof value === 'boolean' ) { 27876 27877 uniform.__data[ 0 ] = value; 27878 gl.bufferSubData( gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data ); 27879 27880 } else if ( value.isMatrix3 ) { 27881 27882 // manually converting 3x3 to 3x4 27883 27884 uniform.__data[ 0 ] = value.elements[ 0 ]; 27885 uniform.__data[ 1 ] = value.elements[ 1 ]; 27886 uniform.__data[ 2 ] = value.elements[ 2 ]; 27887 uniform.__data[ 3 ] = 0; 27888 uniform.__data[ 4 ] = value.elements[ 3 ]; 27889 uniform.__data[ 5 ] = value.elements[ 4 ]; 27890 uniform.__data[ 6 ] = value.elements[ 5 ]; 27891 uniform.__data[ 7 ] = 0; 27892 uniform.__data[ 8 ] = value.elements[ 6 ]; 27893 uniform.__data[ 9 ] = value.elements[ 7 ]; 27894 uniform.__data[ 10 ] = value.elements[ 8 ]; 27895 uniform.__data[ 11 ] = 0; 27896 27897 } else { 27898 27899 value.toArray( uniform.__data, arrayOffset ); 27900 27901 arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT; 27902 27903 } 27904 27905 } 27906 27907 gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data ); 27908 27909 } 27910 27911 } 27912 27913 } 27914 27915 gl.bindBuffer( gl.UNIFORM_BUFFER, null ); 27916 27917 } 27918 27919 function hasUniformChanged( uniform, index, indexArray, cache ) { 27920 27921 const value = uniform.value; 27922 const indexString = index + '_' + indexArray; 27923 27924 if ( cache[ indexString ] === undefined ) { 27925 27926 // cache entry does not exist so far 27927 27928 if ( typeof value === 'number' || typeof value === 'boolean' ) { 27929 27930 cache[ indexString ] = value; 27931 27932 } else { 27933 27934 cache[ indexString ] = value.clone(); 27935 27936 } 27937 27938 return true; 27939 27940 } else { 27941 27942 const cachedObject = cache[ indexString ]; 27943 27944 // compare current value with cached entry 27945 27946 if ( typeof value === 'number' || typeof value === 'boolean' ) { 27947 27948 if ( cachedObject !== value ) { 27949 27950 cache[ indexString ] = value; 27951 return true; 27952 27953 } 27954 27955 } else { 27956 27957 if ( cachedObject.equals( value ) === false ) { 27958 27959 cachedObject.copy( value ); 27960 return true; 27961 27962 } 27963 27964 } 27965 27966 } 27967 27968 return false; 27969 27970 } 27971 27972 function prepareUniformsGroup( uniformsGroup ) { 27973 27974 // determine total buffer size according to the STD140 layout 27975 // Hint: STD140 is the only supported layout in WebGL 2 27976 27977 const uniforms = uniformsGroup.uniforms; 27978 27979 let offset = 0; // global buffer offset in bytes 27980 const chunkSize = 16; // size of a chunk in bytes 27981 27982 for ( let i = 0, l = uniforms.length; i < l; i ++ ) { 27983 27984 const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ]; 27985 27986 for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) { 27987 27988 const uniform = uniformArray[ j ]; 27989 27990 const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; 27991 27992 for ( let k = 0, kl = values.length; k < kl; k ++ ) { 27993 27994 const value = values[ k ]; 27995 27996 const info = getUniformSize( value ); 27997 27998 // Calculate the chunk offset 27999 const chunkOffsetUniform = offset % chunkSize; 28000 28001 // Check for chunk overflow 28002 if ( chunkOffsetUniform !== 0 && ( chunkSize - chunkOffsetUniform ) < info.boundary ) { 28003 28004 // Add padding and adjust offset 28005 offset += ( chunkSize - chunkOffsetUniform ); 28006 28007 } 28008 28009 // the following two properties will be used for partial buffer updates 28010 28011 uniform.__data = new Float32Array( info.storage / Float32Array.BYTES_PER_ELEMENT ); 28012 uniform.__offset = offset; 28013 28014 28015 // Update the global offset 28016 offset += info.storage; 28017 28018 28019 } 28020 28021 } 28022 28023 } 28024 28025 // ensure correct final padding 28026 28027 const chunkOffset = offset % chunkSize; 28028 28029 if ( chunkOffset > 0 ) offset += ( chunkSize - chunkOffset ); 28030 28031 // 28032 28033 uniformsGroup.__size = offset; 28034 uniformsGroup.__cache = {}; 28035 28036 return this; 28037 28038 } 28039 28040 function getUniformSize( value ) { 28041 28042 const info = { 28043 boundary: 0, // bytes 28044 storage: 0 // bytes 28045 }; 28046 28047 // determine sizes according to STD140 28048 28049 if ( typeof value === 'number' || typeof value === 'boolean' ) { 28050 28051 // float/int/bool 28052 28053 info.boundary = 4; 28054 info.storage = 4; 28055 28056 } else if ( value.isVector2 ) { 28057 28058 // vec2 28059 28060 info.boundary = 8; 28061 info.storage = 8; 28062 28063 } else if ( value.isVector3 || value.isColor ) { 28064 28065 // vec3 28066 28067 info.boundary = 16; 28068 info.storage = 12; // evil: vec3 must start on a 16-byte boundary but it only consumes 12 bytes 28069 28070 } else if ( value.isVector4 ) { 28071 28072 // vec4 28073 28074 info.boundary = 16; 28075 info.storage = 16; 28076 28077 } else if ( value.isMatrix3 ) { 28078 28079 // mat3 (in STD140 a 3x3 matrix is represented as 3x4) 28080 28081 info.boundary = 48; 28082 info.storage = 48; 28083 28084 } else if ( value.isMatrix4 ) { 28085 28086 // mat4 28087 28088 info.boundary = 64; 28089 info.storage = 64; 28090 28091 } else if ( value.isTexture ) { 28092 28093 console.warn( 'THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.' ); 28094 28095 } else { 28096 28097 console.warn( 'THREE.WebGLRenderer: Unsupported uniform value type.', value ); 28098 28099 } 28100 28101 return info; 28102 28103 } 28104 28105 function onUniformsGroupsDispose( event ) { 28106 28107 const uniformsGroup = event.target; 28108 28109 uniformsGroup.removeEventListener( 'dispose', onUniformsGroupsDispose ); 28110 28111 const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex ); 28112 allocatedBindingPoints.splice( index, 1 ); 28113 28114 gl.deleteBuffer( buffers[ uniformsGroup.id ] ); 28115 28116 delete buffers[ uniformsGroup.id ]; 28117 delete updateList[ uniformsGroup.id ]; 28118 28119 } 28120 28121 function dispose() { 28122 28123 for ( const id in buffers ) { 28124 28125 gl.deleteBuffer( buffers[ id ] ); 28126 28127 } 28128 28129 allocatedBindingPoints = []; 28130 buffers = {}; 28131 updateList = {}; 28132 28133 } 28134 28135 return { 28136 28137 bind: bind, 28138 update: update, 28139 28140 dispose: dispose 28141 28142 }; 28143 28144} 28145 28146class WebGLRenderer { 28147 28148 constructor( parameters = {} ) { 28149 28150 const { 28151 canvas = createCanvasElement(), 28152 context = null, 28153 depth = true, 28154 stencil =
vendor: 28,003 bytes, lines 28154-29448
28154false, 28155 alpha = false, 28156 antialias = false, 28157 premultipliedAlpha = true, 28158 preserveDrawingBuffer = false, 28159 powerPreference = 'default', 28160 failIfMajorPerformanceCaveat = false, 28161 } = parameters; 28162 28163 this.isWebGLRenderer = true; 28164 28165 let _alpha; 28166 28167 if ( context !== null ) { 28168 28169 if ( typeof WebGLRenderingContext !== 'undefined' && context instanceof WebGLRenderingContext ) { 28170 28171 throw new Error( 'THREE.WebGLRenderer: WebGL 1 is not supported since r163.' ); 28172 28173 } 28174 28175 _alpha = context.getContextAttributes().alpha; 28176 28177 } else { 28178 28179 _alpha = alpha; 28180 28181 } 28182 28183 const uintClearColor = new Uint32Array( 4 ); 28184 const intClearColor = new Int32Array( 4 ); 28185 28186 let currentRenderList = null; 28187 let currentRenderState = null; 28188 28189 // render() can be called from within a callback triggered by another render. 28190 // We track this so that the nested render call gets its list and state isolated from the parent render call. 28191 28192 const renderListStack = []; 28193 const renderStateStack = []; 28194 28195 // public properties 28196 28197 this.domElement = canvas; 28198 28199 // Debug configuration container 28200 this.debug = { 28201 28202 /** 28203 * Enables error checking and reporting when shader programs are being compiled 28204 * @type {boolean} 28205 */ 28206 checkShaderErrors: true, 28207 /** 28208 * Callback for custom error reporting. 28209 * @type {?Function} 28210 */ 28211 onShaderError: null 28212 }; 28213 28214 // clearing 28215 28216 this.autoClear = true; 28217 this.autoClearColor = true; 28218 this.autoClearDepth = true; 28219 this.autoClearStencil = true; 28220 28221 // scene graph 28222 28223 this.sortObjects = true; 28224 28225 // user-defined clipping 28226 28227 this.clippingPlanes = []; 28228 this.localClippingEnabled = false; 28229 28230 // physically based shading 28231 28232 this._outputColorSpace = SRGBColorSpace; 28233 28234 // physical lights 28235 28236 this._useLegacyLights = false; 28237 28238 // tone mapping 28239 28240 this.toneMapping = NoToneMapping; 28241 this.toneMappingExposure = 1.0; 28242 28243 // internal properties 28244 28245 const _this = this; 28246 28247 let _isContextLost = false; 28248 28249 // internal state cache 28250 28251 let _currentActiveCubeFace = 0; 28252 let _currentActiveMipmapLevel = 0; 28253 let _currentRenderTarget = null; 28254 let _currentMaterialId = - 1; 28255 28256 let _currentCamera = null; 28257 28258 const _currentViewport = new Vector4(); 28259 const _currentScissor = new Vector4(); 28260 let _currentScissorTest = null; 28261 28262 const _currentClearColor = new Color( 0x000000 ); 28263 let _currentClearAlpha = 0; 28264 28265 // 28266 28267 let _width = canvas.width; 28268 let _height = canvas.height; 28269 28270 let _pixelRatio = 1; 28271 let _opaqueSort = null; 28272 let _transparentSort = null; 28273 28274 const _viewport = new Vector4( 0, 0, _width, _height ); 28275 const _scissor = new Vector4( 0, 0, _width, _height ); 28276 let _scissorTest = false; 28277 28278 // frustum 28279 28280 const _frustum = new Frustum(); 28281 28282 // clipping 28283 28284 let _clippingEnabled = false; 28285 let _localClippingEnabled = false; 28286 28287 // camera matrices cache 28288 28289 const _projScreenMatrix = new Matrix4(); 28290 28291 const _vector2 = new Vector2(); 28292 const _vector3 = new Vector3(); 28293 28294 const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; 28295 28296 function getTargetPixelRatio() { 28297 28298 return _currentRenderTarget === null ? _pixelRatio : 1; 28299 28300 } 28301 28302 // initialize 28303 28304 let _gl = context; 28305 28306 function getContext( contextName, contextAttributes ) { 28307 28308 const context = canvas.getContext( contextName, contextAttributes ); 28309 if ( context !== null ) return context; 28310 28311 return null; 28312 28313 } 28314 28315 try { 28316 28317 const contextAttributes = { 28318 alpha: true, 28319 depth, 28320 stencil, 28321 antialias, 28322 premultipliedAlpha, 28323 preserveDrawingBuffer, 28324 powerPreference, 28325 failIfMajorPerformanceCaveat, 28326 }; 28327 28328 // OffscreenCanvas does not have setAttribute, see #22811 28329 if ( 'setAttribute' in canvas ) canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); 28330 28331 // event listeners must be registered before WebGL context is created, see #12753 28332 canvas.addEventListener( 'webglcontextlost', onContextLost, false ); 28333 canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); 28334 canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); 28335 28336 if ( _gl === null ) { 28337 28338 const contextName = 'webgl2'; 28339 28340 _gl = getContext( contextName, contextAttributes ); 28341 28342 if ( _gl === null ) { 28343 28344 if ( getContext( contextName ) ) { 28345 28346 throw new Error( 'Error creating WebGL context with your selected attributes.' ); 28347 28348 } else { 28349 28350 throw new Error( 'Error creating WebGL context.' ); 28351 28352 } 28353 28354 } 28355 28356 } 28357 28358 } catch ( error ) { 28359 28360 console.error( 'THREE.WebGLRenderer: ' + error.message ); 28361 throw error; 28362 28363 } 28364 28365 let extensions, capabilities, state, info; 28366 let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; 28367 let programCache, materials, renderLists, renderStates, clipping, shadowMap; 28368 28369 let background, morphtargets, bufferRenderer, indexedBufferRenderer; 28370 28371 let utils, bindingStates, uniformsGroups; 28372 28373 function initGLContext() { 28374 28375 extensions = new WebGLExtensions( _gl ); 28376 extensions.init(); 28377 28378 capabilities = new WebGLCapabilities( _gl, extensions, parameters ); 28379 28380 utils = new WebGLUtils( _gl, extensions ); 28381 28382 state = new WebGLState( _gl ); 28383 28384 info = new WebGLInfo( _gl ); 28385 properties = new WebGLProperties(); 28386 textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); 28387 cubemaps = new WebGLCubeMaps( _this ); 28388 cubeuvmaps = new WebGLCubeUVMaps( _this ); 28389 attributes = new WebGLAttributes( _gl ); 28390 bindingStates = new WebGLBindingStates( _gl, attributes ); 28391 geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); 28392 objects = new WebGLObjects( _gl, geometries, attributes, info ); 28393 morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); 28394 clipping = new WebGLClipping( properties ); 28395 programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); 28396 materials = new WebGLMaterials( _this, properties ); 28397 renderLists = new WebGLRenderLists(); 28398 renderStates = new WebGLRenderStates( extensions ); 28399 background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha ); 28400 shadowMap = new WebGLShadowMap( _this, objects, capabilities ); 28401 uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); 28402 28403 bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info ); 28404 indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info ); 28405 28406 info.programs = programCache.programs; 28407 28408 _this.capabilities = capabilities; 28409 _this.extensions = extensions; 28410 _this.properties = properties; 28411 _this.renderLists = renderLists; 28412 _this.shadowMap = shadowMap; 28413 _this.state = state; 28414 _this.info = info; 28415 28416 } 28417 28418 initGLContext(); 28419 28420 // xr 28421 28422 const xr = new WebXRManager( _this, _gl ); 28423 28424 this.xr = xr; 28425 28426 // API 28427 28428 this.getContext = function () { 28429 28430 return _gl; 28431 28432 }; 28433 28434 this.getContextAttributes = function () { 28435 28436 return _gl.getContextAttributes(); 28437 28438 }; 28439 28440 this.forceContextLoss = function () { 28441 28442 const extension = extensions.get( 'WEBGL_lose_context' ); 28443 if ( extension ) extension.loseContext(); 28444 28445 }; 28446 28447 this.forceContextRestore = function () { 28448 28449 const extension = extensions.get( 'WEBGL_lose_context' ); 28450 if ( extension ) extension.restoreContext(); 28451 28452 }; 28453 28454 this.getPixelRatio = function () { 28455 28456 return _pixelRatio; 28457 28458 }; 28459 28460 this.setPixelRatio = function ( value ) { 28461 28462 if ( value === undefined ) return; 28463 28464 _pixelRatio = value; 28465 28466 this.setSize( _width, _height, false ); 28467 28468 }; 28469 28470 this.getSize = function ( target ) { 28471 28472 return target.set( _width, _height ); 28473 28474 }; 28475 28476 this.setSize = function ( width, height, updateStyle = true ) { 28477 28478 if ( xr.isPresenting ) { 28479 28480 console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); 28481 return; 28482 28483 } 28484 28485 _width = width; 28486 _height = height; 28487 28488 canvas.width = Math.floor( width * _pixelRatio ); 28489 canvas.height = Math.floor( height * _pixelRatio ); 28490 28491 if ( updateStyle === true ) { 28492 28493 canvas.style.width = width + 'px'; 28494 canvas.style.height = height + 'px'; 28495 28496 } 28497 28498 this.setViewport( 0, 0, width, height ); 28499 28500 }; 28501 28502 this.getDrawingBufferSize = function ( target ) { 28503 28504 return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); 28505 28506 }; 28507 28508 this.setDrawingBufferSize = function ( width, height, pixelRatio ) { 28509 28510 _width = width; 28511 _height = height; 28512 28513 _pixelRatio = pixelRatio; 28514 28515 canvas.width = Math.floor( width * pixelRatio ); 28516 canvas.height = Math.floor( height * pixelRatio ); 28517 28518 this.setViewport( 0, 0, width, height ); 28519 28520 }; 28521 28522 this.getCurrentViewport = function ( target ) { 28523 28524 return target.copy( _currentViewport ); 28525 28526 }; 28527 28528 this.getViewport = function ( target ) { 28529 28530 return target.copy( _viewport ); 28531 28532 }; 28533 28534 this.setViewport = function ( x, y, width, height ) { 28535 28536 if ( x.isVector4 ) { 28537 28538 _viewport.set( x.x, x.y, x.z, x.w ); 28539 28540 } else { 28541 28542 _viewport.set( x, y, width, height ); 28543 28544 } 28545 28546 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).round() ); 28547 28548 }; 28549 28550 this.getScissor = function ( target ) { 28551 28552 return target.copy( _scissor ); 28553 28554 }; 28555 28556 this.setScissor = function ( x, y, width, height ) { 28557 28558 if ( x.isVector4 ) { 28559 28560 _scissor.set( x.x, x.y, x.z, x.w ); 28561 28562 } else { 28563 28564 _scissor.set( x, y, width, height ); 28565 28566 } 28567 28568 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).round() ); 28569 28570 }; 28571 28572 this.getScissorTest = function () { 28573 28574 return _scissorTest; 28575 28576 }; 28577 28578 this.setScissorTest = function ( boolean ) { 28579 28580 state.setScissorTest( _scissorTest = boolean ); 28581 28582 }; 28583 28584 this.setOpaqueSort = function ( method ) { 28585 28586 _opaqueSort = method; 28587 28588 }; 28589 28590 this.setTransparentSort = function ( method ) { 28591 28592 _transparentSort = method; 28593 28594 }; 28595 28596 // Clearing 28597 28598 this.getClearColor = function ( target ) { 28599 28600 return target.copy( background.getClearColor() ); 28601 28602 }; 28603 28604 this.setClearColor = function () { 28605 28606 background.setClearColor.apply( background, arguments ); 28607 28608 }; 28609 28610 this.getClearAlpha = function () { 28611 28612 return background.getClearAlpha(); 28613 28614 }; 28615 28616 this.setClearAlpha = function () { 28617 28618 background.setClearAlpha.apply( background, arguments ); 28619 28620 }; 28621 28622 this.clear = function ( color = true, depth = true, stencil = true ) { 28623 28624 let bits = 0; 28625 28626 if ( color ) { 28627 28628 // check if we're trying to clear an integer target 28629 let isIntegerFormat = false; 28630 if ( _currentRenderTarget !== null ) { 28631 28632 const targetFormat = _currentRenderTarget.texture.format; 28633 isIntegerFormat = targetFormat === RGBAIntegerFormat || 28634 targetFormat === RGIntegerFormat || 28635 targetFormat === RedIntegerFormat; 28636 28637 } 28638 28639 // use the appropriate clear functions to clear the target if it's a signed 28640 // or unsigned integer target 28641 if ( isIntegerFormat ) { 28642 28643 const targetType = _currentRenderTarget.texture.type; 28644 const isUnsignedType = targetType === UnsignedByteType || 28645 targetType === UnsignedIntType || 28646 targetType === UnsignedShortType || 28647 targetType === UnsignedInt248Type || 28648 targetType === UnsignedShort4444Type || 28649 targetType === UnsignedShort5551Type; 28650 28651 const clearColor = background.getClearColor(); 28652 const a = background.getClearAlpha(); 28653 const r = clearColor.r; 28654 const g = clearColor.g; 28655 const b = clearColor.b; 28656 28657 if ( isUnsignedType ) { 28658 28659 uintClearColor[ 0 ] = r; 28660 uintClearColor[ 1 ] = g; 28661 uintClearColor[ 2 ] = b; 28662 uintClearColor[ 3 ] = a; 28663 _gl.clearBufferuiv( _gl.COLOR, 0, uintClearColor ); 28664 28665 } else { 28666 28667 intClearColor[ 0 ] = r; 28668 intClearColor[ 1 ] = g; 28669 intClearColor[ 2 ] = b; 28670 intClearColor[ 3 ] = a; 28671 _gl.clearBufferiv( _gl.COLOR, 0, intClearColor ); 28672 28673 } 28674 28675 } else { 28676 28677 bits |= _gl.COLOR_BUFFER_BIT; 28678 28679 } 28680 28681 } 28682 28683 if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; 28684 if ( stencil ) { 28685 28686 bits |= _gl.STENCIL_BUFFER_BIT; 28687 this.state.buffers.stencil.setMask( 0xffffffff ); 28688 28689 } 28690 28691 _gl.clear( bits ); 28692 28693 }; 28694 28695 this.clearColor = function () { 28696 28697 this.clear( true, false, false ); 28698 28699 }; 28700 28701 this.clearDepth = function () { 28702 28703 this.clear( false, true, false ); 28704 28705 }; 28706 28707 this.clearStencil = function () { 28708 28709 this.clear( false, false, true ); 28710 28711 }; 28712 28713 // 28714 28715 this.dispose = function () { 28716 28717 canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); 28718 canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); 28719 canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); 28720 28721 renderLists.dispose(); 28722 renderStates.dispose(); 28723 properties.dispose(); 28724 cubemaps.dispose(); 28725 cubeuvmaps.dispose(); 28726 objects.dispose(); 28727 bindingStates.dispose(); 28728 uniformsGroups.dispose(); 28729 programCache.dispose(); 28730 28731 xr.dispose(); 28732 28733 xr.removeEventListener( 'sessionstart', onXRSessionStart ); 28734 xr.removeEventListener( 'sessionend', onXRSessionEnd ); 28735 28736 animation.stop(); 28737 28738 }; 28739 28740 // Events 28741 28742 function onContextLost( event ) { 28743 28744 event.preventDefault(); 28745 28746 console.log( 'THREE.WebGLRenderer: Context Lost.' ); 28747 28748 _isContextLost = true; 28749 28750 } 28751 28752 function onContextRestore( /* event */ ) { 28753 28754 console.log( 'THREE.WebGLRenderer: Context Restored.' ); 28755 28756 _isContextLost = false; 28757 28758 const infoAutoReset = info.autoReset; 28759 const shadowMapEnabled = shadowMap.enabled; 28760 const shadowMapAutoUpdate = shadowMap.autoUpdate; 28761 const shadowMapNeedsUpdate = shadowMap.needsUpdate; 28762 const shadowMapType = shadowMap.type; 28763 28764 initGLContext(); 28765 28766 info.autoReset = infoAutoReset; 28767 shadowMap.enabled = shadowMapEnabled; 28768 shadowMap.autoUpdate = shadowMapAutoUpdate; 28769 shadowMap.needsUpdate = shadowMapNeedsUpdate; 28770 shadowMap.type = shadowMapType; 28771 28772 } 28773 28774 function onContextCreationError( event ) { 28775 28776 console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); 28777 28778 } 28779 28780 function onMaterialDispose( event ) { 28781 28782 const material = event.target; 28783 28784 material.removeEventListener( 'dispose', onMaterialDispose ); 28785 28786 deallocateMaterial( material ); 28787 28788 } 28789 28790 // Buffer deallocation 28791 28792 function deallocateMaterial( material ) { 28793 28794 releaseMaterialProgramReferences( material ); 28795 28796 properties.remove( material ); 28797 28798 } 28799 28800 28801 function releaseMaterialProgramReferences( material ) { 28802 28803 const programs = properties.get( material ).programs; 28804 28805 if ( programs !== undefined ) { 28806 28807 programs.forEach( function ( program ) { 28808 28809 programCache.releaseProgram( program ); 28810 28811 } ); 28812 28813 if ( material.isShaderMaterial ) { 28814 28815 programCache.releaseShaderCache( material ); 28816 28817 } 28818 28819 } 28820 28821 } 28822 28823 // Buffer rendering 28824 28825 this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { 28826 28827 if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) 28828 28829 const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); 28830 28831 const program = setProgram( camera, scene, geometry, material, object ); 28832 28833 state.setMaterial( material, frontFaceCW ); 28834 28835 // 28836 28837 let index = geometry.index; 28838 let rangeFactor = 1; 28839 28840 if ( material.wireframe === true ) { 28841 28842 index = geometries.getWireframeAttribute( geometry ); 28843 28844 if ( index === undefined ) return; 28845 28846 rangeFactor = 2; 28847 28848 } 28849 28850 // 28851 28852 const drawRange = geometry.drawRange; 28853 const position = geometry.attributes.position; 28854 28855 let drawStart = drawRange.start * rangeFactor; 28856 let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; 28857 28858 if ( group !== null ) { 28859 28860 drawStart = Math.max( drawStart, group.start * rangeFactor ); 28861 drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); 28862 28863 } 28864 28865 if ( index !== null ) { 28866 28867 drawStart = Math.max( drawStart, 0 ); 28868 drawEnd = Math.min( drawEnd, index.count ); 28869 28870 } else if ( position !== undefined && position !== null ) { 28871 28872 drawStart = Math.max( drawStart, 0 ); 28873 drawEnd = Math.min( drawEnd, position.count ); 28874 28875 } 28876 28877 const drawCount = drawEnd - drawStart; 28878 28879 if ( drawCount < 0 || drawCount === Infinity ) return; 28880 28881 // 28882 28883 bindingStates.setup( object, material, program, geometry, index ); 28884 28885 let attribute; 28886 let renderer = bufferRenderer; 28887 28888 if ( index !== null ) { 28889 28890 attribute = attributes.get( index ); 28891 28892 renderer = indexedBufferRenderer; 28893 renderer.setIndex( attribute ); 28894 28895 } 28896 28897 // 28898 28899 if ( object.isMesh ) { 28900 28901 if ( material.wireframe === true ) { 28902 28903 state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); 28904 renderer.setMode( _gl.LINES ); 28905 28906 } else { 28907 28908 renderer.setMode( _gl.TRIANGLES ); 28909 28910 } 28911 28912 } else if ( object.isLine ) { 28913 28914 let lineWidth = material.linewidth; 28915 28916 if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material 28917 28918 state.setLineWidth( lineWidth * getTargetPixelRatio() ); 28919 28920 if ( object.isLineSegments ) { 28921 28922 renderer.setMode( _gl.LINES ); 28923 28924 } else if ( object.isLineLoop ) { 28925 28926 renderer.setMode( _gl.LINE_LOOP ); 28927 28928 } else { 28929 28930 renderer.setMode( _gl.LINE_STRIP ); 28931 28932 } 28933 28934 } else if ( object.isPoints ) { 28935 28936 renderer.setMode( _gl.POINTS ); 28937 28938 } else if ( object.isSprite ) { 28939 28940 renderer.setMode( _gl.TRIANGLES ); 28941 28942 } 28943 28944 if ( object.isBatchedMesh ) { 28945 28946 renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount ); 28947 28948 } else if ( object.isInstancedMesh ) { 28949 28950 renderer.renderInstances( drawStart, drawCount, object.count ); 28951 28952 } else if ( geometry.isInstancedBufferGeometry ) { 28953 28954 const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; 28955 const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); 28956 28957 renderer.renderInstances( drawStart, drawCount, instanceCount ); 28958 28959 } else { 28960 28961 renderer.render( drawStart, drawCount ); 28962 28963 } 28964 28965 }; 28966 28967 // Compile 28968 28969 function prepareMaterial( material, scene, object ) { 28970 28971 if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { 28972 28973 material.side = BackSide; 28974 material.needsUpdate = true; 28975 getProgram( material, scene, object ); 28976 28977 material.side = FrontSide; 28978 material.needsUpdate = true; 28979 getProgram( material, scene, object ); 28980 28981 material.side = DoubleSide; 28982 28983 } else { 28984 28985 getProgram( material, scene, object ); 28986 28987 } 28988 28989 } 28990 28991 this.compile = function ( scene, camera, targetScene = null ) { 28992 28993 if ( targetScene === null ) targetScene = scene; 28994 28995 currentRenderState = renderStates.get( targetScene ); 28996 currentRenderState.init(); 28997 28998 renderStateStack.push( currentRenderState ); 28999 29000 // gather lights from both the target scene and the new object that will be added to the scene. 29001 29002 targetScene.traverseVisible( function ( object ) { 29003 29004 if ( object.isLight && object.layers.test( camera.layers ) ) { 29005 29006 currentRenderState.pushLight( object ); 29007 29008 if ( object.castShadow ) { 29009 29010 currentRenderState.pushShadow( object ); 29011 29012 } 29013 29014 } 29015 29016 } ); 29017 29018 if ( scene !== targetScene ) { 29019 29020 scene.traverseVisible( function ( object ) { 29021 29022 if ( object.isLight && object.layers.test( camera.layers ) ) { 29023 29024 currentRenderState.pushLight( object ); 29025 29026 if ( object.castShadow ) { 29027 29028 currentRenderState.pushShadow( object ); 29029 29030 } 29031 29032 } 29033 29034 } ); 29035 29036 } 29037 29038 currentRenderState.setupLights( _this._useLegacyLights ); 29039 29040 // Only initialize materials in the new scene, not the targetScene. 29041 29042 const materials = new Set(); 29043 29044 scene.traverse( function ( object ) { 29045 29046 const material = object.material; 29047 29048 if ( material ) { 29049 29050 if ( Array.isArray( material ) ) { 29051 29052 for ( let i = 0; i < material.length; i ++ ) { 29053 29054 const material2 = material[ i ]; 29055 29056 prepareMaterial( material2, targetScene, object ); 29057 materials.add( material2 ); 29058 29059 } 29060 29061 } else { 29062 29063 prepareMaterial( material, targetScene, object ); 29064 materials.add( material ); 29065 29066 } 29067 29068 } 29069 29070 } ); 29071 29072 renderStateStack.pop(); 29073 currentRenderState = null; 29074 29075 return materials; 29076 29077 }; 29078 29079 // compileAsync 29080 29081 this.compileAsync = function ( scene, camera, targetScene = null ) { 29082 29083 const materials = this.compile( scene, camera, targetScene ); 29084 29085 // Wait for all the materials in the new object to indicate that they're 29086 // ready to be used before resolving the promise. 29087 29088 return new Promise( ( resolve ) => { 29089 29090 function checkMaterialsReady() { 29091 29092 materials.forEach( function ( material ) { 29093 29094 const materialProperties = properties.get( material ); 29095 const program = materialProperties.currentProgram; 29096 29097 if ( program.isReady() ) { 29098 29099 // remove any programs that report they're ready to use from the list 29100 materials.delete( material ); 29101 29102 } 29103 29104 } ); 29105 29106 // once the list of compiling materials is empty, call the callback 29107 29108 if ( materials.size === 0 ) { 29109 29110 resolve( scene ); 29111 return; 29112 29113 } 29114 29115 // if some materials are still not ready, wait a bit and check again 29116 29117 setTimeout( checkMaterialsReady, 10 ); 29118 29119 } 29120 29121 if ( extensions.get( 'KHR_parallel_shader_compile' ) !== null ) { 29122 29123 // If we can check the compilation status of the materials without 29124 // blocking then do so right away. 29125 29126 checkMaterialsReady(); 29127 29128 } else { 29129 29130 // Otherwise start by waiting a bit to give the materials we just 29131 // initialized a chance to finish. 29132 29133 setTimeout( checkMaterialsReady, 10 ); 29134 29135 } 29136 29137 } ); 29138 29139 }; 29140 29141 // Animation Loop 29142 29143 let onAnimationFrameCallback = null; 29144 29145 function onAnimationFrame( time ) { 29146 29147 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); 29148 29149 } 29150 29151 function onXRSessionStart() { 29152 29153 animation.stop(); 29154 29155 } 29156 29157 function onXRSessionEnd() { 29158 29159 animation.start(); 29160 29161 } 29162 29163 const animation = new WebGLAnimation(); 29164 animation.setAnimationLoop( onAnimationFrame ); 29165 29166 if ( typeof self !== 'undefined' ) animation.setContext( self ); 29167 29168 this.setAnimationLoop = function ( callback ) { 29169 29170 onAnimationFrameCallback = callback; 29171 xr.setAnimationLoop( callback ); 29172 29173 ( callback === null ) ? animation.stop() : animation.start(); 29174 29175 }; 29176 29177 xr.addEventListener( 'sessionstart', onXRSessionStart ); 29178 xr.addEventListener( 'sessionend', onXRSessionEnd ); 29179 29180 // Rendering 29181 29182 this.render = function ( scene, camera ) { 29183 29184 if ( camera !== undefined && camera.isCamera !== true ) { 29185 29186 console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); 29187 return; 29188 29189 } 29190 29191 if ( _isContextLost === true ) return; 29192 29193 // update scene graph 29194 29195 if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); 29196 29197 // update camera matrices and frustum 29198 29199 if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); 29200 29201 if ( xr.enabled === true && xr.isPresenting === true ) { 29202 29203 if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); 29204 29205 camera = xr.getCamera(); // use XR camera for rendering 29206 29207 } 29208 29209 // 29210 if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); 29211 29212 currentRenderState = renderStates.get( scene, renderStateStack.length ); 29213 currentRenderState.init(); 29214 29215 renderStateStack.push( currentRenderState ); 29216 29217 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); 29218 _frustum.setFromProjectionMatrix( _projScreenMatrix ); 29219 29220 _localClippingEnabled = this.localClippingEnabled; 29221 _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); 29222 29223 currentRenderList = renderLists.get( scene, renderListStack.length ); 29224 currentRenderList.init(); 29225 29226 renderListStack.push( currentRenderList ); 29227 29228 projectObject( scene, camera, 0, _this.sortObjects ); 29229 29230 currentRenderList.finish(); 29231 29232 if ( _this.sortObjects === true ) { 29233 29234 currentRenderList.sort( _opaqueSort, _transparentSort ); 29235 29236 } 29237 29238 // 29239 29240 this.info.render.frame ++; 29241 29242 if ( _clippingEnabled === true ) clipping.beginShadows(); 29243 29244 const shadowsArray = currentRenderState.state.shadowsArray; 29245 29246 shadowMap.render( shadowsArray, scene, camera ); 29247 29248 if ( _clippingEnabled === true ) clipping.endShadows(); 29249 29250 // 29251 29252 if ( this.info.autoReset === true ) this.info.reset(); 29253 29254 29255 // 29256 29257 if ( xr.enabled === false || xr.isPresenting === false || xr.hasDepthSensing() === false ) { 29258 29259 background.render( currentRenderList, scene ); 29260 29261 } 29262 29263 // render scene 29264 29265 currentRenderState.setupLights( _this._useLegacyLights ); 29266 29267 if ( camera.isArrayCamera ) { 29268 29269 const cameras = camera.cameras; 29270 29271 for ( let i = 0, l = cameras.length; i < l; i ++ ) { 29272 29273 const camera2 = cameras[ i ]; 29274 29275 renderScene( currentRenderList, scene, camera2, camera2.viewport ); 29276 29277 } 29278 29279 } else { 29280 29281 renderScene( currentRenderList, scene, camera ); 29282 29283 } 29284 29285 // 29286 29287 if ( _currentRenderTarget !== null ) { 29288 29289 // resolve multisample renderbuffers to a single-sample texture if necessary 29290 29291 textures.updateMultisampleRenderTarget( _currentRenderTarget ); 29292 29293 // Generate mipmap if we're using any kind of mipmap filtering 29294 29295 textures.updateRenderTargetMipmap( _currentRenderTarget ); 29296 29297 } 29298 29299 // 29300 29301 if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); 29302 29303 // _gl.finish(); 29304 29305 bindingStates.resetDefaultState(); 29306 _currentMaterialId = - 1; 29307 _currentCamera = null; 29308 29309 renderStateStack.pop(); 29310 29311 if ( renderStateStack.length > 0 ) { 29312 29313 currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; 29314 29315 } else { 29316 29317 currentRenderState = null; 29318 29319 } 29320 29321 renderListStack.pop(); 29322 29323 if ( renderListStack.length > 0 ) { 29324 29325 currentRenderList = renderListStack[ renderListStack.length - 1 ]; 29326 29327 } else { 29328 29329 currentRenderList = null; 29330 29331 } 29332 29333 }; 29334 29335 function projectObject( object, camera, groupOrder, sortObjects ) { 29336 29337 if ( object.visible === false ) return; 29338 29339 const visible = object.layers.test( camera.layers ); 29340 29341 if ( visible ) { 29342 29343 if ( object.isGroup ) { 29344 29345 groupOrder = object.renderOrder; 29346 29347 } else if ( object.isLOD ) { 29348 29349 if ( object.autoUpdate === true ) object.update( camera ); 29350 29351 } else if ( object.isLight ) { 29352 29353 currentRenderState.pushLight( object ); 29354 29355 if ( object.castShadow ) { 29356 29357 currentRenderState.pushShadow( object ); 29358 29359 } 29360 29361 } else if ( object.isSprite ) { 29362 29363 if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { 29364 29365 if ( sortObjects ) { 29366 29367 _vector3.setFromMatrixPosition( object.matrixWorld ) 29368 .applyMatrix4( _projScreenMatrix ); 29369 29370 } 29371 29372 const geometry = objects.update( object ); 29373 const material = object.material; 29374 29375 if ( material.visible ) { 29376 29377 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); 29378 29379 } 29380 29381 } 29382 29383 } else if ( object.isMesh || object.isLine || object.isPoints ) { 29384 29385 if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { 29386 29387 const geometry = objects.update( object ); 29388 const material = object.material; 29389 29390 if ( sortObjects ) { 29391 29392 if ( object.boundingSphere !== undefined ) { 29393 29394 if ( object.boundingSphere === null ) object.computeBoundingSphere(); 29395 _vector3.copy( object.boundingSphere.center ); 29396 29397 } else { 29398 29399 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 29400 _vector3.copy( geometry.boundingSphere.center ); 29401 29402 } 29403 29404 _vector3 29405 .applyMatrix4( object.matrixWorld ) 29406 .applyMatrix4( _projScreenMatrix ); 29407 29408 } 29409 29410 if ( Array.isArray( material ) ) { 29411 29412 const groups = geometry.groups; 29413 29414 for ( let i = 0, l = groups.length; i < l; i ++ ) { 29415 29416 const group = groups[ i ]; 29417 const groupMaterial = material[ group.materialIndex ]; 29418 29419 if ( groupMaterial && groupMaterial.visible ) { 29420 29421 currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); 29422 29423 } 29424 29425 } 29426 29427 } else if ( material.visible ) { 29428 29429 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); 29430 29431 } 29432 29433 } 29434 29435 } 29436 29437 } 29438 29439 const children = object.children; 29440 29441 for ( let i = 0, l = children.length; i < l; i ++ ) { 29442 29443 projectObject( children[ i ], camera, groupOrder, sortObjects ); 29444 29445 } 29446 29447 } 29448
29449 function renderScene( currentRenderList, scene, camera, viewport ) { 29450 29451 const opaqueObjects = currentRenderList.opaque; 29452 const transmissiveObjects = currentRenderList.transmissive; 29453 const transparentObjects = currentRenderList.transparent; 29454 29455 currentRenderState.setupLightsView( camera ); 29456 29457 if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); 29458 29459 if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ); 29460 29461 if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); 29462 29463 if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); 29464 if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); 29465 if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); 29466 29467 // Ensure depth buffer writing is enabled so it can be cleared on next render 29468 29469 state.buffers.depth.setTest( true ); 29470 state.buffers.depth.setMask( true ); 29471 state.buffers.color.setMask( true ); 29472 29473 state.setPolygonOffset( false ); 29474 29475 } 29476 29477 function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) { 29478 29479 const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; 29480 29481 if ( overrideMaterial !== null ) { 29482 29483 return; 29484 29485 } 29486 29487 if ( currentRenderState.state.transmissionRenderTarget === null ) { 29488 29489 currentRenderState.state.transmissionRenderTarget = new WebGLRenderTarget( 1, 1, { 29490 generateMipmaps: true, 29491 type: ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ) ? HalfFloatType : UnsignedByteType, 29492 minFilter: LinearMipmapLinearFilter, 29493 samples: 4, 29494 stencilBuffer: stencil 29495 } ); 29496 29497 const renderTargetProperties = properties.get( currentRenderState.state.transmissionRenderTarget ); 29498 renderTargetProperties.__isTransmissionRenderTarget = true; 29499 29500 // debug 29501 29502 /* 29503 const geometry = new PlaneGeometry(); 29504 const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } ); 29505 29506 const mesh = new Mesh( geometry, material ); 29507 scene.add( mesh ); 29508 */ 29509 29510 } 29511 29512 const transmissionRenderTarget = currentRenderState.state.transmissionRenderTarget; 29513 29514 _this.getDrawingBufferSize( _vector2 ); 29515 transmissionRenderTarget.setSize( _vector2.x, _vector2.y ); 29516 29517 // 29518 29519 const currentRenderTarget = _this.getRenderTarget(); 29520 _this.setRenderTarget( transmissionRenderTarget ); 29521 29522 _this.getClearColor( _currentClearColor ); 29523 _currentClearAlpha = _this.getClearAlpha(); 29524 if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 ); 29525 29526 _this.clear(); 29527 29528 // Turn off the features which can affect the frag color for opaque objects pass. 29529 // Otherwise they are applied twice in opaque objects pass and transmission objects pass. 29530 const currentToneMapping = _this.toneMapping; 29531 _this.toneMapping = NoToneMapping; 29532 29533 renderObjects( opaqueObjects, scene, camera ); 29534 29535 textures.updateMultisampleRenderTarget( transmissionRenderTarget ); 29536 textures.updateRenderTargetMipmap( transmissionRenderTarget ); 29537 29538 let renderTargetNeedsUpdate = false; 29539 29540 for ( let i = 0, l = transmissiveObjects.length; i < l; i ++ ) { 29541 29542 const renderItem = transmissiveObjects[ i ]; 29543 29544 const object = renderItem.object; 29545 const geometry = renderItem.geometry; 29546 const material = renderItem.material; 29547 const group = renderItem.group; 29548 29549 if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) { 29550 29551 const currentSide = material.side; 29552 29553 material.side = BackSide; 29554 material.needsUpdate = true; 29555 29556 renderObject( object, scene, camera, geometry, material, group ); 29557 29558 material.side = currentSide; 29559 material.needsUpdate = true; 29560 29561 renderTargetNeedsUpdate = true; 29562 29563 } 29564 29565 } 29566 29567 if ( renderTargetNeedsUpdate === true ) { 29568 29569 textures.updateMultisampleRenderTarget( transmissionRenderTarget ); 29570 textures.updateRenderTargetMipmap(
vendor: 12,137 bytes, lines 29570-29927
29570transmissionRenderTarget ); 29571 29572 } 29573 29574 _this.setRenderTarget( currentRenderTarget ); 29575 29576 _this.setClearColor( _currentClearColor, _currentClearAlpha ); 29577 29578 _this.toneMapping = currentToneMapping; 29579 29580 } 29581 29582 function renderObjects( renderList, scene, camera ) { 29583 29584 const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; 29585 29586 for ( let i = 0, l = renderList.length; i < l; i ++ ) { 29587 29588 const renderItem = renderList[ i ]; 29589 29590 const object = renderItem.object; 29591 const geometry = renderItem.geometry; 29592 const material = overrideMaterial === null ? renderItem.material : overrideMaterial; 29593 const group = renderItem.group; 29594 29595 if ( object.layers.test( camera.layers ) ) { 29596 29597 renderObject( object, scene, camera, geometry, material, group ); 29598 29599 } 29600 29601 } 29602 29603 } 29604 29605 function renderObject( object, scene, camera, geometry, material, group ) { 29606 29607 object.onBeforeRender( _this, scene, camera, geometry, material, group ); 29608 29609 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); 29610 object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); 29611 29612 material.onBeforeRender( _this, scene, camera, geometry, object, group ); 29613 29614 if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { 29615 29616 material.side = BackSide; 29617 material.needsUpdate = true; 29618 _this.renderBufferDirect( camera, scene, geometry, material, object, group ); 29619 29620 material.side = FrontSide; 29621 material.needsUpdate = true; 29622 _this.renderBufferDirect( camera, scene, geometry, material, object, group ); 29623 29624 material.side = DoubleSide; 29625 29626 } else { 29627 29628 _this.renderBufferDirect( camera, scene, geometry, material, object, group ); 29629 29630 } 29631 29632 object.onAfterRender( _this, scene, camera, geometry, material, group ); 29633 29634 } 29635 29636 function getProgram( material, scene, object ) { 29637 29638 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... 29639 29640 const materialProperties = properties.get( material ); 29641 29642 const lights = currentRenderState.state.lights; 29643 const shadowsArray = currentRenderState.state.shadowsArray; 29644 29645 const lightsStateVersion = lights.state.version; 29646 29647 const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); 29648 const programCacheKey = programCache.getProgramCacheKey( parameters ); 29649 29650 let programs = materialProperties.programs; 29651 29652 // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change 29653 29654 materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; 29655 materialProperties.fog = scene.fog; 29656 materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); 29657 materialProperties.envMapRotation = ( materialProperties.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation; 29658 29659 if ( programs === undefined ) { 29660 29661 // new material 29662 29663 material.addEventListener( 'dispose', onMaterialDispose ); 29664 29665 programs = new Map(); 29666 materialProperties.programs = programs; 29667 29668 } 29669 29670 let program = programs.get( programCacheKey ); 29671 29672 if ( program !== undefined ) { 29673 29674 // early out if program and light state is identical 29675 29676 if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { 29677 29678 updateCommonMaterialProperties( material, parameters ); 29679 29680 return program; 29681 29682 } 29683 29684 } else { 29685 29686 parameters.uniforms = programCache.getUniforms( material ); 29687 29688 material.onBuild( object, parameters, _this ); 29689 29690 material.onBeforeCompile( parameters, _this ); 29691 29692 program = programCache.acquireProgram( parameters, programCacheKey ); 29693 programs.set( programCacheKey, program ); 29694 29695 materialProperties.uniforms = parameters.uniforms; 29696 29697 } 29698 29699 const uniforms = materialProperties.uniforms; 29700 29701 if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { 29702 29703 uniforms.clippingPlanes = clipping.uniform; 29704 29705 } 29706 29707 updateCommonMaterialProperties( material, parameters ); 29708 29709 // store the light setup it was created for 29710 29711 materialProperties.needsLights = materialNeedsLights( material ); 29712 materialProperties.lightsStateVersion = lightsStateVersion; 29713 29714 if ( materialProperties.needsLights ) { 29715 29716 // wire up the material to this renderer's lighting state 29717 29718 uniforms.ambientLightColor.value = lights.state.ambient; 29719 uniforms.lightProbe.value = lights.state.probe; 29720 uniforms.directionalLights.value = lights.state.directional; 29721 uniforms.directionalLightShadows.value = lights.state.directionalShadow; 29722 uniforms.spotLights.value = lights.state.spot; 29723 uniforms.spotLightShadows.value = lights.state.spotShadow; 29724 uniforms.rectAreaLights.value = lights.state.rectArea; 29725 uniforms.ltc_1.value = lights.state.rectAreaLTC1; 29726 uniforms.ltc_2.value = lights.state.rectAreaLTC2; 29727 uniforms.pointLights.value = lights.state.point; 29728 uniforms.pointLightShadows.value = lights.state.pointShadow; 29729 uniforms.hemisphereLights.value = lights.state.hemi; 29730 29731 uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; 29732 uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; 29733 uniforms.spotShadowMap.value = lights.state.spotShadowMap; 29734 uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; 29735 uniforms.spotLightMap.value = lights.state.spotLightMap; 29736 uniforms.pointShadowMap.value = lights.state.pointShadowMap; 29737 uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; 29738 // TODO (abelnation): add area lights shadow info to uniforms 29739 29740 } 29741 29742 materialProperties.currentProgram = program; 29743 materialProperties.uniformsList = null; 29744 29745 return program; 29746 29747 } 29748 29749 function getUniformList( materialProperties ) { 29750 29751 if ( materialProperties.uniformsList === null ) { 29752 29753 const progUniforms = materialProperties.currentProgram.getUniforms(); 29754 materialProperties.uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, materialProperties.uniforms ); 29755 29756 } 29757 29758 return materialProperties.uniformsList; 29759 29760 } 29761 29762 function updateCommonMaterialProperties( material, parameters ) { 29763 29764 const materialProperties = properties.get( material ); 29765 29766 materialProperties.outputColorSpace = parameters.outputColorSpace; 29767 materialProperties.batching = parameters.batching; 29768 materialProperties.instancing = parameters.instancing; 29769 materialProperties.instancingColor = parameters.instancingColor; 29770 materialProperties.instancingMorph = parameters.instancingMorph; 29771 materialProperties.skinning = parameters.skinning; 29772 materialProperties.morphTargets = parameters.morphTargets; 29773 materialProperties.morphNormals = parameters.morphNormals; 29774 materialProperties.morphColors = parameters.morphColors; 29775 materialProperties.morphTargetsCount = parameters.morphTargetsCount; 29776 materialProperties.numClippingPlanes = parameters.numClippingPlanes; 29777 materialProperties.numIntersection = parameters.numClipIntersection; 29778 materialProperties.vertexAlphas = parameters.vertexAlphas; 29779 materialProperties.vertexTangents = parameters.vertexTangents; 29780 materialProperties.toneMapping = parameters.toneMapping; 29781 29782 } 29783 29784 function setProgram( camera, scene, geometry, material, object ) { 29785 29786 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... 29787 29788 textures.resetTextureUnits(); 29789 29790 const fog = scene.fog; 29791 const environment = material.isMeshStandardMaterial ? scene.environment : null; 29792 const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ); 29793 const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); 29794 const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; 29795 const vertexTangents = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 ); 29796 const morphTargets = !! geometry.morphAttributes.position; 29797 const morphNormals = !! geometry.morphAttributes.normal; 29798 const morphColors = !! geometry.morphAttributes.color; 29799 29800 let toneMapping = NoToneMapping; 29801 29802 if ( material.toneMapped ) { 29803 29804 if ( _currentRenderTarget === null || _currentRenderTarget.isXRRenderTarget === true ) { 29805 29806 toneMapping = _this.toneMapping; 29807 29808 } 29809 29810 } 29811 29812 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; 29813 const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; 29814 29815 const materialProperties = properties.get( material ); 29816 const lights = currentRenderState.state.lights; 29817 29818 if ( _clippingEnabled === true ) { 29819 29820 if ( _localClippingEnabled === true || camera !== _currentCamera ) { 29821 29822 const useCache = 29823 camera === _currentCamera && 29824 material.id === _currentMaterialId; 29825 29826 // we might want to call this function with some ClippingGroup 29827 // object instead of the material, once it becomes feasible 29828 // (#8465, #8379) 29829 clipping.setState( material, camera, useCache ); 29830 29831 } 29832 29833 } 29834 29835 // 29836 29837 let needsProgramChange = false; 29838 29839 if ( material.version === materialProperties.__version ) { 29840 29841 if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { 29842 29843 needsProgramChange = true; 29844 29845 } else if ( materialProperties.outputColorSpace !== colorSpace ) { 29846 29847 needsProgramChange = true; 29848 29849 } else if ( object.isBatchedMesh && materialProperties.batching === false ) { 29850 29851 needsProgramChange = true; 29852 29853 } else if ( ! object.isBatchedMesh && materialProperties.batching === true ) { 29854 29855 needsProgramChange = true; 29856 29857 } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { 29858 29859 needsProgramChange = true; 29860 29861 } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { 29862 29863 needsProgramChange = true; 29864 29865 } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { 29866 29867 needsProgramChange = true; 29868 29869 } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { 29870 29871 needsProgramChange = true; 29872 29873 } else if ( object.isInstancedMesh && materialProperties.instancingColor === true && object.instanceColor === null ) { 29874 29875 needsProgramChange = true; 29876 29877 } else if ( object.isInstancedMesh && materialProperties.instancingColor === false && object.instanceColor !== null ) { 29878 29879 needsProgramChange = true; 29880 29881 } else if ( object.isInstancedMesh && materialProperties.instancingMorph === true && object.morphTexture === null ) { 29882 29883 needsProgramChange = true; 29884 29885 } else if ( object.isInstancedMesh && materialProperties.instancingMorph === false && object.morphTexture !== null ) { 29886 29887 needsProgramChange = true; 29888 29889 } else if ( materialProperties.envMap !== envMap ) { 29890 29891 needsProgramChange = true; 29892 29893 } else if ( material.fog === true && materialProperties.fog !== fog ) { 29894 29895 needsProgramChange = true; 29896 29897 } else if ( materialProperties.numClippingPlanes !== undefined && 29898 ( materialProperties.numClippingPlanes !== clipping.numPlanes || 29899 materialProperties.numIntersection !== clipping.numIntersection ) ) { 29900 29901 needsProgramChange = true; 29902 29903 } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { 29904 29905 needsProgramChange = true; 29906 29907 } else if ( materialProperties.vertexTangents !== vertexTangents ) { 29908 29909 needsProgramChange = true; 29910 29911 } else if ( materialProperties.morphTargets !== morphTargets ) { 29912 29913 needsProgramChange = true; 29914 29915 } else if ( materialProperties.morphNormals !== morphNormals ) { 29916 29917 needsProgramChange = true; 29918 29919 } else if ( materialProperties.morphColors !== morphColors ) { 29920 29921 needsProgramChange = true; 29922 29923 } else if ( materialProperties.toneMapping !== toneMapping ) { 29924 29925 needsProgramChange = true; 29926 29927 } else if (
29927materialProperties.morphTargetsCount !== morphTargetsCount ) { 29928 29929 needsProgramChange = true; 29930 29931 } 29932 29933 } else { 29934 29935 needsProgramChange = true; 29936 materialProperties.__version = material.version; 29937 29938 } 29939 29940 // 29941 29942 let program = materialProperties.currentProgram; 29943 29944 if ( needsProgramChange === true ) { 29945 29946 program = getProgram( material, scene, object ); 29947 29948 } 29949 29950 let refreshProgram = false;
vendor: 4,839 bytes, lines 29951-30118
29951 let refreshMaterial = false; 29952 let refreshLights = false; 29953 29954 const p_uniforms = program.getUniforms(), 29955 m_uniforms = materialProperties.uniforms; 29956 29957 if ( state.useProgram( program.program ) ) { 29958 29959 refreshProgram = true; 29960 refreshMaterial = true; 29961 refreshLights = true; 29962 29963 } 29964 29965 if ( material.id !== _currentMaterialId ) { 29966 29967 _currentMaterialId = material.id; 29968 29969 refreshMaterial = true; 29970 29971 } 29972 29973 if ( refreshProgram || _currentCamera !== camera ) { 29974 29975 // common camera uniforms 29976 29977 p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); 29978 p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); 29979 29980 const uCamPos = p_uniforms.map.cameraPosition; 29981 29982 if ( uCamPos !== undefined ) { 29983 29984 uCamPos.setValue( _gl, _vector3.setFromMatrixPosition( camera.matrixWorld ) ); 29985 29986 } 29987 29988 if ( capabilities.logarithmicDepthBuffer ) { 29989 29990 p_uniforms.setValue( _gl, 'logDepthBufFC', 29991 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); 29992 29993 } 29994 29995 // consider moving isOrthographic to UniformLib and WebGLMaterials, see https://github.com/mrdoob/three.js/pull/26467#issuecomment-1645185067 29996 29997 if ( material.isMeshPhongMaterial || 29998 material.isMeshToonMaterial || 29999 material.isMeshLambertMaterial || 30000 material.isMeshBasicMaterial || 30001 material.isMeshStandardMaterial || 30002 material.isShaderMaterial ) { 30003 30004 p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); 30005 30006 } 30007 30008 if ( _currentCamera !== camera ) { 30009 30010 _currentCamera = camera; 30011 30012 // lighting uniforms depend on the camera so enforce an update 30013 // now, in case this material supports lights - or later, when 30014 // the next material that does gets activated: 30015 30016 refreshMaterial = true; // set to true on material change 30017 refreshLights = true; // remains set until update done 30018 30019 } 30020 30021 } 30022 30023 // skinning and morph target uniforms must be set even if material didn't change 30024 // auto-setting of texture unit for bone and morph texture must go before other textures 30025 // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures 30026 30027 if ( object.isSkinnedMesh ) { 30028 30029 p_uniforms.setOptional( _gl, object, 'bindMatrix' ); 30030 p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); 30031 30032 const skeleton = object.skeleton; 30033 30034 if ( skeleton ) { 30035 30036 if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); 30037 30038 p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); 30039 30040 } 30041 30042 } 30043 30044 if ( object.isBatchedMesh ) { 30045 30046 p_uniforms.setOptional( _gl, object, 'batchingTexture' ); 30047 p_uniforms.setValue( _gl, 'batchingTexture', object._matricesTexture, textures ); 30048 30049 } 30050 30051 const morphAttributes = geometry.morphAttributes; 30052 30053 if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined ) ) { 30054 30055 morphtargets.update( object, geometry, program ); 30056 30057 } 30058 30059 if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { 30060 30061 materialProperties.receiveShadow = object.receiveShadow; 30062 p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); 30063 30064 } 30065 30066 // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 30067 30068 if ( material.isMeshGouraudMaterial && material.envMap !== null ) { 30069 30070 m_uniforms.envMap.value = envMap; 30071 30072 m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; 30073 30074 } 30075 30076 if ( material.isMeshStandardMaterial && material.envMap === null && scene.environment !== null ) { 30077 30078 m_uniforms.envMapIntensity.value = scene.environmentIntensity; 30079 30080 } 30081 30082 if ( refreshMaterial ) { 30083 30084 p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); 30085 30086 if ( materialProperties.needsLights ) { 30087 30088 // the current material requires lighting info 30089 30090 // note: all lighting uniforms are always set correctly 30091 // they simply reference the renderer's state for their 30092 // values 30093 // 30094 // use the current material's .needsUpdate flags to set 30095 // the GL state when required 30096 30097 markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); 30098 30099 } 30100 30101 // refresh uniforms common to several materials 30102 30103 if ( fog && material.fog === true ) { 30104 30105 materials.refreshFogUniforms( m_uniforms, fog ); 30106 30107 } 30108 30109 materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, currentRenderState.state.transmissionRenderTarget ); 30110 30111 WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures ); 30112 30113 } 30114 30115 if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { 30116 30117 WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures ); 30118 material.uniformsNeedUpdate = false;
vendor: 15,414 bytes, lines 30119-30622
30119 30120 } 30121 30122 if ( material.isSpriteMaterial ) { 30123 30124 p_uniforms.setValue( _gl, 'center', object.center ); 30125 30126 } 30127 30128 // common matrices 30129 30130 p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); 30131 p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); 30132 p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); 30133 30134 // UBOs 30135 30136 if ( material.isShaderMaterial || material.isRawShaderMaterial ) { 30137 30138 const groups = material.uniformsGroups; 30139 30140 for ( let i = 0, l = groups.length; i < l; i ++ ) { 30141 30142 const group = groups[ i ]; 30143 30144 uniformsGroups.update( group, program ); 30145 uniformsGroups.bind( group, program ); 30146 30147 } 30148 30149 } 30150 30151 return program; 30152 30153 } 30154 30155 // If uniforms are marked as clean, they don't need to be loaded to the GPU. 30156 30157 function markUniformsLightsNeedsUpdate( uniforms, value ) { 30158 30159 uniforms.ambientLightColor.needsUpdate = value; 30160 uniforms.lightProbe.needsUpdate = value; 30161 30162 uniforms.directionalLights.needsUpdate = value; 30163 uniforms.directionalLightShadows.needsUpdate = value; 30164 uniforms.pointLights.needsUpdate = value; 30165 uniforms.pointLightShadows.needsUpdate = value; 30166 uniforms.spotLights.needsUpdate = value; 30167 uniforms.spotLightShadows.needsUpdate = value; 30168 uniforms.rectAreaLights.needsUpdate = value; 30169 uniforms.hemisphereLights.needsUpdate = value; 30170 30171 } 30172 30173 function materialNeedsLights( material ) { 30174 30175 return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || 30176 material.isMeshStandardMaterial || material.isShadowMaterial || 30177 ( material.isShaderMaterial && material.lights === true ); 30178 30179 } 30180 30181 this.getActiveCubeFace = function () { 30182 30183 return _currentActiveCubeFace; 30184 30185 }; 30186 30187 this.getActiveMipmapLevel = function () { 30188 30189 return _currentActiveMipmapLevel; 30190 30191 }; 30192 30193 this.getRenderTarget = function () { 30194 30195 return _currentRenderTarget; 30196 30197 }; 30198 30199 this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { 30200 30201 properties.get( renderTarget.texture ).__webglTexture = colorTexture; 30202 properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; 30203 30204 const renderTargetProperties = properties.get( renderTarget ); 30205 renderTargetProperties.__hasExternalTextures = true; 30206 30207 renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; 30208 30209 if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { 30210 30211 // The multisample_render_to_texture extension doesn't work properly if there 30212 // are midframe flushes and an external depth buffer. Disable use of the extension. 30213 if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { 30214 30215 console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); 30216 renderTargetProperties.__useRenderToTexture = false; 30217 30218 } 30219 30220 } 30221 30222 }; 30223 30224 this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { 30225 30226 const renderTargetProperties = properties.get( renderTarget ); 30227 renderTargetProperties.__webglFramebuffer = defaultFramebuffer; 30228 renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; 30229 30230 }; 30231 30232 this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { 30233 30234 _currentRenderTarget = renderTarget; 30235 _currentActiveCubeFace = activeCubeFace; 30236 _currentActiveMipmapLevel = activeMipmapLevel; 30237 30238 let useDefaultFramebuffer = true; 30239 let framebuffer = null; 30240 let isCube = false; 30241 let isRenderTarget3D = false; 30242 30243 if ( renderTarget ) { 30244 30245 const renderTargetProperties = properties.get( renderTarget ); 30246 30247 if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { 30248 30249 // We need to make sure to rebind the framebuffer. 30250 state.bindFramebuffer( _gl.FRAMEBUFFER, null ); 30251 useDefaultFramebuffer = false; 30252 30253 } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { 30254 30255 textures.setupRenderTarget( renderTarget ); 30256 30257 } else if ( renderTargetProperties.__hasExternalTextures ) { 30258 30259 // Color and depth texture must be rebound in order for the swapchain to update. 30260 textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); 30261 30262 } 30263 30264 const texture = renderTarget.texture; 30265 30266 if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { 30267 30268 isRenderTarget3D = true; 30269 30270 } 30271 30272 const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; 30273 30274 if ( renderTarget.isWebGLCubeRenderTarget ) { 30275 30276 if ( Array.isArray( __webglFramebuffer[ activeCubeFace ] ) ) { 30277 30278 framebuffer = __webglFramebuffer[ activeCubeFace ][ activeMipmapLevel ]; 30279 30280 } else { 30281 30282 framebuffer = __webglFramebuffer[ activeCubeFace ]; 30283 30284 } 30285 30286 isCube = true; 30287 30288 } else if ( ( renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { 30289 30290 framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; 30291 30292 } else { 30293 30294 if ( Array.isArray( __webglFramebuffer ) ) { 30295 30296 framebuffer = __webglFramebuffer[ activeMipmapLevel ]; 30297 30298 } else { 30299 30300 framebuffer = __webglFramebuffer; 30301 30302 } 30303 30304 } 30305 30306 _currentViewport.copy( renderTarget.viewport ); 30307 _currentScissor.copy( renderTarget.scissor ); 30308 _currentScissorTest = renderTarget.scissorTest; 30309 30310 } else { 30311 30312 _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); 30313 _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); 30314 _currentScissorTest = _scissorTest; 30315 30316 } 30317 30318 const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 30319 30320 if ( framebufferBound && useDefaultFramebuffer ) { 30321 30322 state.drawBuffers( renderTarget, framebuffer ); 30323 30324 } 30325 30326 state.viewport( _currentViewport ); 30327 state.scissor( _currentScissor ); 30328 state.setScissorTest( _currentScissorTest ); 30329 30330 if ( isCube ) { 30331 30332 const textureProperties = properties.get( renderTarget.texture ); 30333 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel ); 30334 30335 } else if ( isRenderTarget3D ) { 30336 30337 const textureProperties = properties.get( renderTarget.texture ); 30338 const layer = activeCubeFace || 0; 30339 _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); 30340 30341 } 30342 30343 _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings 30344 30345 }; 30346 30347 this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { 30348 30349 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { 30350 30351 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); 30352 return; 30353 30354 } 30355 30356 let framebuffer = properties.get( renderTarget ).__webglFramebuffer; 30357 30358 if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { 30359 30360 framebuffer = framebuffer[ activeCubeFaceIndex ]; 30361 30362 } 30363 30364 if ( framebuffer ) { 30365 30366 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 30367 30368 try { 30369 30370 const texture = renderTarget.texture; 30371 const textureFormat = texture.format; 30372 const textureType = texture.type; 30373 30374 if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { 30375 30376 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); 30377 return; 30378 30379 } 30380 30381 const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ); 30382 30383 if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) 30384 textureType !== FloatType && ! halfFloatSupportedByExt ) { 30385 30386 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); 30387 return; 30388 30389 } 30390 30391 // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) 30392 30393 if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { 30394 30395 _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); 30396 30397 } 30398 30399 } finally { 30400 30401 // restore framebuffer of current render target if necessary 30402 30403 const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; 30404 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 30405 30406 } 30407 30408 } 30409 30410 }; 30411 30412 this.copyFramebufferToTexture = function ( position, texture, level = 0 ) { 30413 30414 const levelScale = Math.pow( 2, - level ); 30415 const width = Math.floor( texture.image.width * levelScale ); 30416 const height = Math.floor( texture.image.height * levelScale ); 30417 30418 textures.setTexture2D( texture, 0 ); 30419 30420 _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, position.x, position.y, width, height ); 30421 30422 state.unbindTexture(); 30423 30424 }; 30425 30426 this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) { 30427 30428 const width = srcTexture.image.width; 30429 const height = srcTexture.image.height; 30430 const glFormat = utils.convert( dstTexture.format ); 30431 const glType = utils.convert( dstTexture.type ); 30432 30433 textures.setTexture2D( dstTexture, 0 ); 30434 30435 // As another texture upload may have changed pixelStorei 30436 // parameters, make sure they are correct for the dstTexture 30437 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); 30438 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); 30439 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); 30440 30441 if ( srcTexture.isDataTexture ) { 30442 30443 _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data ); 30444 30445 } else { 30446 30447 if ( srcTexture.isCompressedTexture ) { 30448 30449 _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data ); 30450 30451 } else { 30452 30453 _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image ); 30454 30455 } 30456 30457 } 30458 30459 // Generate mipmaps only when copying level 0 30460 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); 30461 30462 state.unbindTexture(); 30463 30464 }; 30465 30466 this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) { 30467 30468 const width = Math.round( sourceBox.max.x - sourceBox.min.x ); 30469 const height = Math.round( sourceBox.max.y - sourceBox.min.y ); 30470 const depth = sourceBox.max.z - sourceBox.min.z + 1; 30471 const glFormat = utils.convert( dstTexture.format ); 30472 const glType = utils.convert( dstTexture.type ); 30473 let glTarget; 30474 30475 if ( dstTexture.isData3DTexture ) { 30476 30477 textures.setTexture3D( dstTexture, 0 ); 30478 glTarget = _gl.TEXTURE_3D; 30479 30480 } else if ( dstTexture.isDataArrayTexture || dstTexture.isCompressedArrayTexture ) { 30481 30482 textures.setTexture2DArray( dstTexture, 0 ); 30483 glTarget = _gl.TEXTURE_2D_ARRAY; 30484 30485 } else { 30486 30487 console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); 30488 return; 30489 30490 } 30491 30492 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); 30493 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); 30494 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); 30495 30496 const unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); 30497 const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); 30498 const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); 30499 const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); 30500 const unpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); 30501 30502 const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image; 30503 30504 _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); 30505 _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); 30506 _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, sourceBox.min.x ); 30507 _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y ); 30508 _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z ); 30509 30510 if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { 30511 30512 _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data ); 30513 30514 } else { 30515 30516 if ( dstTexture.isCompressedArrayTexture ) { 30517 30518 _gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data ); 30519 30520 } else { 30521 30522 _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image ); 30523 30524 } 30525 30526 } 30527 30528 _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen ); 30529 _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight ); 30530 _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels ); 30531 _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows ); 30532 _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages ); 30533 30534 // Generate mipmaps only when copying level 0 30535 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); 30536 30537 state.unbindTexture(); 30538 30539 }; 30540 30541 this.initTexture = function ( texture ) { 30542 30543 if ( texture.isCubeTexture ) { 30544 30545 textures.setTextureCube( texture, 0 ); 30546 30547 } else if ( texture.isData3DTexture ) { 30548 30549 textures.setTexture3D( texture, 0 ); 30550 30551 } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { 30552 30553 textures.setTexture2DArray( texture, 0 ); 30554 30555 } else { 30556 30557 textures.setTexture2D( texture, 0 ); 30558 30559 } 30560 30561 state.unbindTexture(); 30562 30563 }; 30564 30565 this.resetState = function () { 30566 30567 _currentActiveCubeFace = 0; 30568 _currentActiveMipmapLevel = 0; 30569 _currentRenderTarget = null; 30570 30571 state.reset(); 30572 bindingStates.reset(); 30573 30574 }; 30575 30576 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { 30577 30578 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); 30579 30580 } 30581 30582 } 30583 30584 get coordinateSystem() { 30585 30586 return WebGLCoordinateSystem; 30587 30588 } 30589 30590 get outputColorSpace() { 30591 30592 return this._outputColorSpace; 30593 30594 } 30595 30596 set outputColorSpace( colorSpace ) { 30597 30598 this._outputColorSpace = colorSpace; 30599 30600 const gl = this.getContext(); 30601 gl.drawingBufferColorSpace = colorSpace === DisplayP3ColorSpace ? 'display-p3' : 'srgb'; 30602 gl.unpackColorSpace = ColorManagement.workingColorSpace === LinearDisplayP3ColorSpace ? 'display-p3' : 'srgb'; 30603 30604 } 30605 30606 get useLegacyLights() { // @deprecated, r155 30607 30608 console.warn( 'THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733.' ); 30609 return this._useLegacyLights; 30610 30611 } 30612 30613 set useLegacyLights( value ) { // @deprecated, r155 30614 30615 console.warn( 'THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733.' ); 30616 this._useLegacyLights = value; 30617 30618 } 30619 30620} 30621 30622class FogExp2 {
vendor: 11,981 bytes, lines 30623-31309
30623 30624 constructor( color, density = 0.00025 ) { 30625 30626 this.isFogExp2 = true; 30627 30628 this.name = ''; 30629 30630 this.color = new Color( color ); 30631 this.density = density; 30632 30633 } 30634 30635 clone() { 30636 30637 return new FogExp2( this.color, this.density ); 30638 30639 } 30640 30641 toJSON( /* meta */ ) { 30642 30643 return { 30644 type: 'FogExp2', 30645 name: this.name, 30646 color: this.color.getHex(), 30647 density: this.density 30648 }; 30649 30650 } 30651 30652} 30653 30654class Fog { 30655 30656 constructor( color, near = 1, far = 1000 ) { 30657 30658 this.isFog = true; 30659 30660 this.name = ''; 30661 30662 this.color = new Color( color ); 30663 30664 this.near = near; 30665 this.far = far; 30666 30667 } 30668 30669 clone() { 30670 30671 return new Fog( this.color, this.near, this.far ); 30672 30673 } 30674 30675 toJSON( /* meta */ ) { 30676 30677 return { 30678 type: 'Fog', 30679 name: this.name, 30680 color: this.color.getHex(), 30681 near: this.near, 30682 far: this.far 30683 }; 30684 30685 } 30686 30687} 30688 30689class Scene extends Object3D { 30690 30691 constructor() { 30692 30693 super(); 30694 30695 this.isScene = true; 30696 30697 this.type = 'Scene'; 30698 30699 this.background = null; 30700 this.environment = null; 30701 this.fog = null; 30702 30703 this.backgroundBlurriness = 0; 30704 this.backgroundIntensity = 1; 30705 this.backgroundRotation = new Euler(); 30706 30707 this.environmentIntensity = 1; 30708 this.environmentRotation = new Euler(); 30709 30710 this.overrideMaterial = null; 30711 30712 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { 30713 30714 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); 30715 30716 } 30717 30718 } 30719 30720 copy( source, recursive ) { 30721 30722 super.copy( source, recursive ); 30723 30724 if ( source.background !== null ) this.background = source.background.clone(); 30725 if ( source.environment !== null ) this.environment = source.environment.clone(); 30726 if ( source.fog !== null ) this.fog = source.fog.clone(); 30727 30728 this.backgroundBlurriness = source.backgroundBlurriness; 30729 this.backgroundIntensity = source.backgroundIntensity; 30730 this.backgroundRotation.copy( source.backgroundRotation ); 30731 30732 this.environmentIntensity = source.environmentIntensity; 30733 this.environmentRotation.copy( source.environmentRotation ); 30734 30735 if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone(); 30736 30737 this.matrixAutoUpdate = source.matrixAutoUpdate; 30738 30739 return this; 30740 30741 } 30742 30743 toJSON( meta ) { 30744 30745 const data = super.toJSON( meta ); 30746 30747 if ( this.fog !== null ) data.object.fog = this.fog.toJSON(); 30748 30749 if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness; 30750 if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity; 30751 data.object.backgroundRotation = this.backgroundRotation.toArray(); 30752 30753 if ( this.environmentIntensity !== 1 ) data.object.environmentIntensity = this.environmentIntensity; 30754 data.object.environmentRotation = this.environmentRotation.toArray(); 30755 30756 return data; 30757 30758 } 30759 30760} 30761 30762class InterleavedBuffer { 30763 30764 constructor( array, stride ) { 30765 30766 this.isInterleavedBuffer = true; 30767 30768 this.array = array; 30769 this.stride = stride; 30770 this.count = array !== undefined ? array.length / stride : 0; 30771 30772 this.usage = StaticDrawUsage; 30773 this._updateRange = { offset: 0, count: - 1 }; 30774 this.updateRanges = []; 30775 30776 this.version = 0; 30777 30778 this.uuid = generateUUID(); 30779 30780 } 30781 30782 onUploadCallback() {} 30783 30784 set needsUpdate( value ) { 30785 30786 if ( value === true ) this.version ++; 30787 30788 } 30789 30790 get updateRange() { 30791 30792 warnOnce( 'THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 30793 return this._updateRange; 30794 30795 } 30796 30797 setUsage( value ) { 30798 30799 this.usage = value; 30800 30801 return this; 30802 30803 } 30804 30805 addUpdateRange( start, count ) { 30806 30807 this.updateRanges.push( { start, count } ); 30808 30809 } 30810 30811 clearUpdateRanges() { 30812 30813 this.updateRanges.length = 0; 30814 30815 } 30816 30817 copy( source ) { 30818 30819 this.array = new source.array.constructor( source.array ); 30820 this.count = source.count; 30821 this.stride = source.stride; 30822 this.usage = source.usage; 30823 30824 return this; 30825 30826 } 30827 30828 copyAt( index1, attribute, index2 ) { 30829 30830 index1 *= this.stride; 30831 index2 *= attribute.stride; 30832 30833 for ( let i = 0, l = this.stride; i < l; i ++ ) { 30834 30835 this.array[ index1 + i ] = attribute.array[ index2 + i ]; 30836 30837 } 30838 30839 return this; 30840 30841 } 30842 30843 set( value, offset = 0 ) { 30844 30845 this.array.set( value, offset ); 30846 30847 return this; 30848 30849 } 30850 30851 clone( data ) { 30852 30853 if ( data.arrayBuffers === undefined ) { 30854 30855 data.arrayBuffers = {}; 30856 30857 } 30858 30859 if ( this.array.buffer._uuid === undefined ) { 30860 30861 this.array.buffer._uuid = generateUUID(); 30862 30863 } 30864 30865 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { 30866 30867 data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer; 30868 30869 } 30870 30871 const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] ); 30872 30873 const ib = new this.constructor( array, this.stride ); 30874 ib.setUsage( this.usage ); 30875 30876 return ib; 30877 30878 } 30879 30880 onUpload( callback ) { 30881 30882 this.onUploadCallback = callback; 30883 30884 return this; 30885 30886 } 30887 30888 toJSON( data ) { 30889 30890 if ( data.arrayBuffers === undefined ) { 30891 30892 data.arrayBuffers = {}; 30893 30894 } 30895 30896 // generate UUID for array buffer if necessary 30897 30898 if ( this.array.buffer._uuid === undefined ) { 30899 30900 this.array.buffer._uuid = generateUUID(); 30901 30902 } 30903 30904 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { 30905 30906 data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) ); 30907 30908 } 30909 30910 // 30911 30912 return { 30913 uuid: this.uuid, 30914 buffer: this.array.buffer._uuid, 30915 type: this.array.constructor.name, 30916 stride: this.stride 30917 }; 30918 30919 } 30920 30921} 30922 30923const _vector$6 = /*@__PURE__*/ new Vector3(); 30924 30925class InterleavedBufferAttribute { 30926 30927 constructor( interleavedBuffer, itemSize, offset, normalized = false ) { 30928 30929 this.isInterleavedBufferAttribute = true; 30930 30931 this.name = ''; 30932 30933 this.data = interleavedBuffer; 30934 this.itemSize = itemSize; 30935 this.offset = offset; 30936 30937 this.normalized = normalized; 30938 30939 } 30940 30941 get count() { 30942 30943 return this.data.count; 30944 30945 } 30946 30947 get array() { 30948 30949 return this.data.array; 30950 30951 } 30952 30953 set needsUpdate( value ) { 30954 30955 this.data.needsUpdate = value; 30956 30957 } 30958 30959 applyMatrix4( m ) { 30960 30961 for ( let i = 0, l = this.data.count; i < l; i ++ ) { 30962 30963 _vector$6.fromBufferAttribute( this, i ); 30964 30965 _vector$6.applyMatrix4( m ); 30966 30967 this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); 30968 30969 } 30970 30971 return this; 30972 30973 } 30974 30975 applyNormalMatrix( m ) { 30976 30977 for ( let i = 0, l = this.count; i < l; i ++ ) { 30978 30979 _vector$6.fromBufferAttribute( this, i ); 30980 30981 _vector$6.applyNormalMatrix( m ); 30982 30983 this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); 30984 30985 } 30986 30987 return this; 30988 30989 } 30990 30991 transformDirection( m ) { 30992 30993 for ( let i = 0, l = this.count; i < l; i ++ ) { 30994 30995 _vector$6.fromBufferAttribute( this, i ); 30996 30997 _vector$6.transformDirection( m ); 30998 30999 this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); 31000 31001 } 31002 31003 return this; 31004 31005 } 31006 31007 getComponent( index, component ) { 31008 31009 let value = this.array[ index * this.data.stride + this.offset + component ]; 31010 31011 if ( this.normalized ) value = denormalize( value, this.array ); 31012 31013 return value; 31014 31015 } 31016 31017 setComponent( index, component, value ) { 31018 31019 if ( this.normalized ) value = normalize( value, this.array ); 31020 31021 this.data.array[ index * this.data.stride + this.offset + component ] = value; 31022 31023 return this; 31024 31025 } 31026 31027 setX( index, x ) { 31028 31029 if ( this.normalized ) x = normalize( x, this.array ); 31030 31031 this.data.array[ index * this.data.stride + this.offset ] = x; 31032 31033 return this; 31034 31035 } 31036 31037 setY( index, y ) { 31038 31039 if ( this.normalized ) y = normalize( y, this.array ); 31040 31041 this.data.array[ index * this.data.stride + this.offset + 1 ] = y; 31042 31043 return this; 31044 31045 } 31046 31047 setZ( index, z ) { 31048 31049 if ( this.normalized ) z = normalize( z, this.array ); 31050 31051 this.data.array[ index * this.data.stride + this.offset + 2 ] = z; 31052 31053 return this; 31054 31055 } 31056 31057 setW( index, w ) { 31058 31059 if ( this.normalized ) w = normalize( w, this.array ); 31060 31061 this.data.array[ index * this.data.stride + this.offset + 3 ] = w; 31062 31063 return this; 31064 31065 } 31066 31067 getX( index ) { 31068 31069 let x = this.data.array[ index * this.data.stride + this.offset ]; 31070 31071 if ( this.normalized ) x = denormalize( x, this.array ); 31072 31073 return x; 31074 31075 } 31076 31077 getY( index ) { 31078 31079 let y = this.data.array[ index * this.data.stride + this.offset + 1 ]; 31080 31081 if ( this.normalized ) y = denormalize( y, this.array ); 31082 31083 return y; 31084 31085 } 31086 31087 getZ( index ) { 31088 31089 let z = this.data.array[ index * this.data.stride + this.offset + 2 ]; 31090 31091 if ( this.normalized ) z = denormalize( z, this.array ); 31092 31093 return z; 31094 31095 } 31096 31097 getW( index ) { 31098 31099 let w = this.data.array[ index * this.data.stride + this.offset + 3 ]; 31100 31101 if ( this.normalized ) w = denormalize( w, this.array ); 31102 31103 return w; 31104 31105 } 31106 31107 setXY( index, x, y ) { 31108 31109 index = index * this.data.stride + this.offset; 31110 31111 if ( this.normalized ) { 31112 31113 x = normalize( x, this.array ); 31114 y = normalize( y, this.array ); 31115 31116 } 31117 31118 this.data.array[ index + 0 ] = x; 31119 this.data.array[ index + 1 ] = y; 31120 31121 return this; 31122 31123 } 31124 31125 setXYZ( index, x, y, z ) { 31126 31127 index = index * this.data.stride + this.offset; 31128 31129 if ( this.normalized ) { 31130 31131 x = normalize( x, this.array ); 31132 y = normalize( y, this.array ); 31133 z = normalize( z, this.array ); 31134 31135 } 31136 31137 this.data.array[ index + 0 ] = x; 31138 this.data.array[ index + 1 ] = y; 31139 this.data.array[ index + 2 ] = z; 31140 31141 return this; 31142 31143 } 31144 31145 setXYZW( index, x, y, z, w ) { 31146 31147 index = index * this.data.stride + this.offset; 31148 31149 if ( this.normalized ) { 31150 31151 x = normalize( x, this.array ); 31152 y = normalize( y, this.array ); 31153 z = normalize( z, this.array ); 31154 w = normalize( w, this.array ); 31155 31156 } 31157 31158 this.data.array[ index + 0 ] = x; 31159 this.data.array[ index + 1 ] = y; 31160 this.data.array[ index + 2 ] = z; 31161 this.data.array[ index + 3 ] = w; 31162 31163 return this; 31164 31165 } 31166 31167 clone( data ) { 31168 31169 if ( data === undefined ) { 31170 31171 console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' ); 31172 31173 const array = []; 31174 31175 for ( let i = 0; i < this.count; i ++ ) { 31176 31177 const index = i * this.data.stride + this.offset; 31178 31179 for ( let j = 0; j < this.itemSize; j ++ ) { 31180 31181 array.push( this.data.array[ index + j ] ); 31182 31183 } 31184 31185 } 31186 31187 return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized ); 31188 31189 } else { 31190 31191 if ( data.interleavedBuffers === undefined ) { 31192 31193 data.interleavedBuffers = {}; 31194 31195 } 31196 31197 if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { 31198 31199 data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data ); 31200 31201 } 31202 31203 return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized ); 31204 31205 } 31206 31207 } 31208 31209 toJSON( data ) { 31210 31211 if ( data === undefined ) { 31212 31213 console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' ); 31214 31215 const array = []; 31216 31217 for ( let i = 0; i < this.count; i ++ ) { 31218 31219 const index = i * this.data.stride + this.offset; 31220 31221 for ( let j = 0; j < this.itemSize; j ++ ) { 31222 31223 array.push( this.data.array[ index + j ] ); 31224 31225 } 31226 31227 } 31228 31229 // de-interleave data and save it as an ordinary buffer attribute for now 31230 31231 return { 31232 itemSize: this.itemSize, 31233 type: this.array.constructor.name, 31234 array: array, 31235 normalized: this.normalized 31236 }; 31237 31238 } else { 31239 31240 // save as true interleaved attribute 31241 31242 if ( data.interleavedBuffers === undefined ) { 31243 31244 data.interleavedBuffers = {}; 31245 31246 } 31247 31248 if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { 31249 31250 data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data ); 31251 31252 } 31253 31254 return { 31255 isInterleavedBufferAttribute: true, 31256 itemSize: this.itemSize, 31257 data: this.data.uuid, 31258 offset: this.offset, 31259 normalized: this.normalized 31260 }; 31261 31262 } 31263 31264 } 31265 31266} 31267 31268class SpriteMaterial extends Material { 31269 31270 constructor( parameters ) { 31271 31272 super(); 31273 31274 this.isSpriteMaterial = true; 31275 31276 this.type = 'SpriteMaterial'; 31277 31278 this.color = new Color( 0xffffff ); 31279 31280 this.map = null; 31281 31282 this.alphaMap = null; 31283 31284 this.rotation = 0; 31285 31286 this.sizeAttenuation = true; 31287 31288 this.transparent = true; 31289 31290 this.fog = true; 31291 31292 this.setValues( parameters ); 31293 31294 } 31295 31296 copy( source ) { 31297 31298 super.copy( source ); 31299 31300 this.color.copy( source.color ); 31301 31302 this.map = source.map; 31303 31304 this.alphaMap = source.alphaMap; 31305 31306 this.rotation = source.rotation; 31307 31308 this.sizeAttenuation = source.sizeAttenuation; 31309
vendor: 6,736 bytes, lines 31310-31646
31310 this.fog = source.fog; 31311 31312 return this; 31313 31314 } 31315 31316} 31317 31318let _geometry; 31319 31320const _intersectPoint = /*@__PURE__*/ new Vector3(); 31321const _worldScale = /*@__PURE__*/ new Vector3(); 31322const _mvPosition = /*@__PURE__*/ new Vector3(); 31323 31324const _alignedPosition = /*@__PURE__*/ new Vector2(); 31325const _rotatedPosition = /*@__PURE__*/ new Vector2(); 31326const _viewWorldMatrix = /*@__PURE__*/ new Matrix4(); 31327 31328const _vA = /*@__PURE__*/ new Vector3(); 31329const _vB = /*@__PURE__*/ new Vector3(); 31330const _vC = /*@__PURE__*/ new Vector3(); 31331 31332const _uvA = /*@__PURE__*/ new Vector2(); 31333const _uvB = /*@__PURE__*/ new Vector2(); 31334const _uvC = /*@__PURE__*/ new Vector2(); 31335 31336class Sprite extends Object3D { 31337 31338 constructor( material = new SpriteMaterial() ) { 31339 31340 super(); 31341 31342 this.isSprite = true; 31343 31344 this.type = 'Sprite'; 31345 31346 if ( _geometry === undefined ) { 31347 31348 _geometry = new BufferGeometry(); 31349 31350 const float32Array = new Float32Array( [ 31351 - 0.5, - 0.5, 0, 0, 0, 31352 0.5, - 0.5, 0, 1, 0, 31353 0.5, 0.5, 0, 1, 1, 31354 - 0.5, 0.5, 0, 0, 1 31355 ] ); 31356 31357 const interleavedBuffer = new InterleavedBuffer( float32Array, 5 ); 31358 31359 _geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] ); 31360 _geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) ); 31361 _geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) ); 31362 31363 } 31364 31365 this.geometry = _geometry; 31366 this.material = material; 31367 31368 this.center = new Vector2( 0.5, 0.5 ); 31369 31370 } 31371 31372 raycast( raycaster, intersects ) { 31373 31374 if ( raycaster.camera === null ) { 31375 31376 console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' ); 31377 31378 } 31379 31380 _worldScale.setFromMatrixScale( this.matrixWorld ); 31381 31382 _viewWorldMatrix.copy( raycaster.camera.matrixWorld ); 31383 this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld ); 31384 31385 _mvPosition.setFromMatrixPosition( this.modelViewMatrix ); 31386 31387 if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) { 31388 31389 _worldScale.multiplyScalar( - _mvPosition.z ); 31390 31391 } 31392 31393 const rotation = this.material.rotation; 31394 let sin, cos; 31395 31396 if ( rotation !== 0 ) { 31397 31398 cos = Math.cos( rotation ); 31399 sin = Math.sin( rotation ); 31400 31401 } 31402 31403 const center = this.center; 31404 31405 transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 31406 transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 31407 transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 31408 31409 _uvA.set( 0, 0 ); 31410 _uvB.set( 1, 0 ); 31411 _uvC.set( 1, 1 ); 31412 31413 // check first triangle 31414 let intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC, false, _intersectPoint ); 31415 31416 if ( intersect === null ) { 31417 31418 // check second triangle 31419 transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 31420 _uvB.set( 0, 1 ); 31421 31422 intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB, false, _intersectPoint ); 31423 if ( intersect === null ) { 31424 31425 return; 31426 31427 } 31428 31429 } 31430 31431 const distance = raycaster.ray.origin.distanceTo( _intersectPoint ); 31432 31433 if ( distance < raycaster.near || distance > raycaster.far ) return; 31434 31435 intersects.push( { 31436 31437 distance: distance, 31438 point: _intersectPoint.clone(), 31439 uv: Triangle.getInterpolation( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), 31440 face: null, 31441 object: this 31442 31443 } ); 31444 31445 } 31446 31447 copy( source, recursive ) { 31448 31449 super.copy( source, recursive ); 31450 31451 if ( source.center !== undefined ) this.center.copy( source.center ); 31452 31453 this.material = source.material; 31454 31455 return this; 31456 31457 } 31458 31459} 31460 31461function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) { 31462 31463 // compute position in camera space 31464 _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale ); 31465 31466 // to check if rotation is not zero 31467 if ( sin !== undefined ) { 31468 31469 _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y ); 31470 _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y ); 31471 31472 } else { 31473 31474 _rotatedPosition.copy( _alignedPosition ); 31475 31476 } 31477 31478 31479 vertexPosition.copy( mvPosition ); 31480 vertexPosition.x += _rotatedPosition.x; 31481 vertexPosition.y += _rotatedPosition.y; 31482 31483 // transform to world space 31484 vertexPosition.applyMatrix4( _viewWorldMatrix ); 31485 31486} 31487 31488const _v1$2 = /*@__PURE__*/ new Vector3(); 31489const _v2$1 = /*@__PURE__*/ new Vector3(); 31490 31491class LOD extends Object3D { 31492 31493 constructor() { 31494 31495 super(); 31496 31497 this._currentLevel = 0; 31498 31499 this.type = 'LOD'; 31500 31501 Object.defineProperties( this, { 31502 levels: { 31503 enumerable: true, 31504 value: [] 31505 }, 31506 isLOD: { 31507 value: true, 31508 } 31509 } ); 31510 31511 this.autoUpdate = true; 31512 31513 } 31514 31515 copy( source ) { 31516 31517 super.copy( source, false ); 31518 31519 const levels = source.levels; 31520 31521 for ( let i = 0, l = levels.length; i < l; i ++ ) { 31522 31523 const level = levels[ i ]; 31524 31525 this.addLevel( level.object.clone(), level.distance, level.hysteresis ); 31526 31527 } 31528 31529 this.autoUpdate = source.autoUpdate; 31530 31531 return this; 31532 31533 } 31534 31535 addLevel( object, distance = 0, hysteresis = 0 ) { 31536 31537 distance = Math.abs( distance ); 31538 31539 const levels = this.levels; 31540 31541 let l; 31542 31543 for ( l = 0; l < levels.length; l ++ ) { 31544 31545 if ( distance < levels[ l ].distance ) { 31546 31547 break; 31548 31549 } 31550 31551 } 31552 31553 levels.splice( l, 0, { distance: distance, hysteresis: hysteresis, object: object } ); 31554 31555 this.add( object ); 31556 31557 return this; 31558 31559 } 31560 31561 getCurrentLevel() { 31562 31563 return this._currentLevel; 31564 31565 } 31566 31567 31568 31569 getObjectForDistance( distance ) { 31570 31571 const levels = this.levels; 31572 31573 if ( levels.length > 0 ) { 31574 31575 let i, l; 31576 31577 for ( i = 1, l = levels.length; i < l; i ++ ) { 31578 31579 let levelDistance = levels[ i ].distance; 31580 31581 if ( levels[ i ].object.visible ) { 31582 31583 levelDistance -= levelDistance * levels[ i ].hysteresis; 31584 31585 } 31586 31587 if ( distance < levelDistance ) { 31588 31589 break; 31590 31591 } 31592 31593 } 31594 31595 return levels[ i - 1 ].object; 31596 31597 } 31598 31599 return null; 31600 31601 } 31602 31603 raycast( raycaster, intersects ) { 31604 31605 const levels = this.levels; 31606 31607 if ( levels.length > 0 ) { 31608 31609 _v1$2.setFromMatrixPosition( this.matrixWorld ); 31610 31611 const distance = raycaster.ray.origin.distanceTo( _v1$2 ); 31612 31613 this.getObjectForDistance( distance ).raycast( raycaster, intersects ); 31614 31615 } 31616 31617 } 31618 31619 update( camera ) { 31620 31621 const levels = this.levels; 31622 31623 if ( levels.length > 1 ) { 31624 31625 _v1$2.setFromMatrixPosition( camera.matrixWorld ); 31626 _v2$1.setFromMatrixPosition( this.matrixWorld ); 31627 31628 const distance = _v1$2.distanceTo( _v2$1 ) / camera.zoom; 31629 31630 levels[ 0 ].object.visible = true; 31631 31632 let i, l; 31633 31634 for ( i = 1, l = levels.length; i < l; i ++ ) { 31635 31636 let levelDistance = levels[ i ].distance; 31637 31638 if ( levels[ i ].object.visible ) { 31639 31640 levelDistance -= levelDistance * levels[ i ].hysteresis; 31641 31642 } 31643 31644 if ( distance >= levelDistance ) { 31645 31646 levels[ i - 1 ].object.visible = false;
vendor: 4,383 bytes, lines 31647-31880
31647 levels[ i ].object.visible = true; 31648 31649 } else { 31650 31651 break; 31652 31653 } 31654 31655 } 31656 31657 this._currentLevel = i - 1; 31658 31659 for ( ; i < l; i ++ ) { 31660 31661 levels[ i ].object.visible = false; 31662 31663 } 31664 31665 } 31666 31667 } 31668 31669 toJSON( meta ) { 31670 31671 const data = super.toJSON( meta ); 31672 31673 if ( this.autoUpdate === false ) data.object.autoUpdate = false; 31674 31675 data.object.levels = []; 31676 31677 const levels = this.levels; 31678 31679 for ( let i = 0, l = levels.length; i < l; i ++ ) { 31680 31681 const level = levels[ i ]; 31682 31683 data.object.levels.push( { 31684 object: level.object.uuid, 31685 distance: level.distance, 31686 hysteresis: level.hysteresis 31687 } ); 31688 31689 } 31690 31691 return data; 31692 31693 } 31694 31695} 31696 31697const _basePosition = /*@__PURE__*/ new Vector3(); 31698 31699const _skinIndex = /*@__PURE__*/ new Vector4(); 31700const _skinWeight = /*@__PURE__*/ new Vector4(); 31701 31702const _vector3 = /*@__PURE__*/ new Vector3(); 31703const _matrix4 = /*@__PURE__*/ new Matrix4(); 31704const _vertex = /*@__PURE__*/ new Vector3(); 31705 31706const _sphere$4 = /*@__PURE__*/ new Sphere(); 31707const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); 31708const _ray$2 = /*@__PURE__*/ new Ray(); 31709 31710class SkinnedMesh extends Mesh { 31711 31712 constructor( geometry, material ) { 31713 31714 super( geometry, material ); 31715 31716 this.isSkinnedMesh = true; 31717 31718 this.type = 'SkinnedMesh'; 31719 31720 this.bindMode = AttachedBindMode; 31721 this.bindMatrix = new Matrix4(); 31722 this.bindMatrixInverse = new Matrix4(); 31723 31724 this.boundingBox = null; 31725 this.boundingSphere = null; 31726 31727 } 31728 31729 computeBoundingBox() { 31730 31731 const geometry = this.geometry; 31732 31733 if ( this.boundingBox === null ) { 31734 31735 this.boundingBox = new Box3(); 31736 31737 } 31738 31739 this.boundingBox.makeEmpty(); 31740 31741 const positionAttribute = geometry.getAttribute( 'position' ); 31742 31743 for ( let i = 0; i < positionAttribute.count; i ++ ) { 31744 31745 this.getVertexPosition( i, _vertex ); 31746 this.boundingBox.expandByPoint( _vertex ); 31747 31748 } 31749 31750 } 31751 31752 computeBoundingSphere() { 31753 31754 const geometry = this.geometry; 31755 31756 if ( this.boundingSphere === null ) { 31757 31758 this.boundingSphere = new Sphere(); 31759 31760 } 31761 31762 this.boundingSphere.makeEmpty(); 31763 31764 const positionAttribute = geometry.getAttribute( 'position' ); 31765 31766 for ( let i = 0; i < positionAttribute.count; i ++ ) { 31767 31768 this.getVertexPosition( i, _vertex ); 31769 this.boundingSphere.expandByPoint( _vertex ); 31770 31771 } 31772 31773 } 31774 31775 copy( source, recursive ) { 31776 31777 super.copy( source, recursive ); 31778 31779 this.bindMode = source.bindMode; 31780 this.bindMatrix.copy( source.bindMatrix ); 31781 this.bindMatrixInverse.copy( source.bindMatrixInverse ); 31782 31783 this.skeleton = source.skeleton; 31784 31785 if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); 31786 if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); 31787 31788 return this; 31789 31790 } 31791 31792 raycast( raycaster, intersects ) { 31793 31794 const material = this.material; 31795 const matrixWorld = this.matrixWorld; 31796 31797 if ( material === undefined ) return; 31798 31799 // test with bounding sphere in world space 31800 31801 if ( this.boundingSphere === null ) this.computeBoundingSphere(); 31802 31803 _sphere$4.copy( this.boundingSphere ); 31804 _sphere$4.applyMatrix4( matrixWorld ); 31805 31806 if ( raycaster.ray.intersectsSphere( _sphere$4 ) === false ) return; 31807 31808 // convert ray to local space of skinned mesh 31809 31810 _inverseMatrix$2.copy( matrixWorld ).invert(); 31811 _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); 31812 31813 // test with bounding box in local space 31814 31815 if ( this.boundingBox !== null ) { 31816 31817 if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return; 31818 31819 } 31820 31821 // test for intersections with geometry 31822 31823 this._computeIntersections( raycaster, intersects, _ray$2 ); 31824 31825 } 31826 31827 getVertexPosition( index, target ) { 31828 31829 super.getVertexPosition( index, target ); 31830 31831 this.applyBoneTransform( index, target ); 31832 31833 return target; 31834 31835 } 31836 31837 bind( skeleton, bindMatrix ) { 31838 31839 this.skeleton = skeleton; 31840 31841 if ( bindMatrix === undefined ) { 31842 31843 this.updateMatrixWorld( true ); 31844 31845 this.skeleton.calculateInverses(); 31846 31847 bindMatrix = this.matrixWorld; 31848 31849 } 31850 31851 this.bindMatrix.copy( bindMatrix ); 31852 this.bindMatrixInverse.copy( bindMatrix ).invert(); 31853 31854 } 31855 31856 pose() { 31857 31858 this.skeleton.pose(); 31859 31860 } 31861 31862 normalizeSkinWeights() { 31863 31864 const vector = new Vector4(); 31865 31866 const skinWeight = this.geometry.attributes.skinWeight; 31867 31868 for ( let i = 0, l = skinWeight.count; i < l; i ++ ) { 31869 31870 vector.fromBufferAttribute( skinWeight, i ); 31871 31872 const scale = 1.0 / vector.manhattanLength(); 31873 31874 if ( scale !== Infinity ) { 31875 31876 vector.multiplyScalar( scale ); 31877 31878 } else { 31879 31880 vector.set( 1, 0, 0, 0 );
vendor: 12,910 bytes, lines 31880-32552
31880 // do something reasonable 31881 31882 } 31883 31884 skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w ); 31885 31886 } 31887 31888 } 31889 31890 updateMatrixWorld( force ) { 31891 31892 super.updateMatrixWorld( force ); 31893 31894 if ( this.bindMode === AttachedBindMode ) { 31895 31896 this.bindMatrixInverse.copy( this.matrixWorld ).invert(); 31897 31898 } else if ( this.bindMode === DetachedBindMode ) { 31899 31900 this.bindMatrixInverse.copy( this.bindMatrix ).invert(); 31901 31902 } else { 31903 31904 console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); 31905 31906 } 31907 31908 } 31909 31910 applyBoneTransform( index, vector ) { 31911 31912 const skeleton = this.skeleton; 31913 const geometry = this.geometry; 31914 31915 _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); 31916 _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); 31917 31918 _basePosition.copy( vector ).applyMatrix4( this.bindMatrix ); 31919 31920 vector.set( 0, 0, 0 ); 31921 31922 for ( let i = 0; i < 4; i ++ ) { 31923 31924 const weight = _skinWeight.getComponent( i ); 31925 31926 if ( weight !== 0 ) { 31927 31928 const boneIndex = _skinIndex.getComponent( i ); 31929 31930 _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); 31931 31932 vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); 31933 31934 } 31935 31936 } 31937 31938 return vector.applyMatrix4( this.bindMatrixInverse ); 31939 31940 } 31941 31942} 31943 31944class Bone extends Object3D { 31945 31946 constructor() { 31947 31948 super(); 31949 31950 this.isBone = true; 31951 31952 this.type = 'Bone'; 31953 31954 } 31955 31956} 31957 31958class DataTexture extends Texture { 31959 31960 constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { 31961 31962 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); 31963 31964 this.isDataTexture = true; 31965 31966 this.image = { data: data, width: width, height: height }; 31967 31968 this.generateMipmaps = false; 31969 this.flipY = false; 31970 this.unpackAlignment = 1; 31971 31972 } 31973 31974} 31975 31976const _offsetMatrix = /*@__PURE__*/ new Matrix4(); 31977const _identityMatrix$1 = /*@__PURE__*/ new Matrix4(); 31978 31979class Skeleton { 31980 31981 constructor( bones = [], boneInverses = [] ) { 31982 31983 this.uuid = generateUUID(); 31984 31985 this.bones = bones.slice( 0 ); 31986 this.boneInverses = boneInverses; 31987 this.boneMatrices = null; 31988 31989 this.boneTexture = null; 31990 31991 this.init(); 31992 31993 } 31994 31995 init() { 31996 31997 const bones = this.bones; 31998 const boneInverses = this.boneInverses; 31999 32000 this.boneMatrices = new Float32Array( bones.length * 16 ); 32001 32002 // calculate inverse bone matrices if necessary 32003 32004 if ( boneInverses.length === 0 ) { 32005 32006 this.calculateInverses(); 32007 32008 } else { 32009 32010 // handle special case 32011 32012 if ( bones.length !== boneInverses.length ) { 32013 32014 console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' ); 32015 32016 this.boneInverses = []; 32017 32018 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32019 32020 this.boneInverses.push( new Matrix4() ); 32021 32022 } 32023 32024 } 32025 32026 } 32027 32028 } 32029 32030 calculateInverses() { 32031 32032 this.boneInverses.length = 0; 32033 32034 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32035 32036 const inverse = new Matrix4(); 32037 32038 if ( this.bones[ i ] ) { 32039 32040 inverse.copy( this.bones[ i ].matrixWorld ).invert(); 32041 32042 } 32043 32044 this.boneInverses.push( inverse ); 32045 32046 } 32047 32048 } 32049 32050 pose() { 32051 32052 // recover the bind-time world matrices 32053 32054 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32055 32056 const bone = this.bones[ i ]; 32057 32058 if ( bone ) { 32059 32060 bone.matrixWorld.copy( this.boneInverses[ i ] ).invert(); 32061 32062 } 32063 32064 } 32065 32066 // compute the local matrices, positions, rotations and scales 32067 32068 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32069 32070 const bone = this.bones[ i ]; 32071 32072 if ( bone ) { 32073 32074 if ( bone.parent && bone.parent.isBone ) { 32075 32076 bone.matrix.copy( bone.parent.matrixWorld ).invert(); 32077 bone.matrix.multiply( bone.matrixWorld ); 32078 32079 } else { 32080 32081 bone.matrix.copy( bone.matrixWorld ); 32082 32083 } 32084 32085 bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); 32086 32087 } 32088 32089 } 32090 32091 } 32092 32093 update() { 32094 32095 const bones = this.bones; 32096 const boneInverses = this.boneInverses; 32097 const boneMatrices = this.boneMatrices; 32098 const boneTexture = this.boneTexture; 32099 32100 // flatten bone matrices to array 32101 32102 for ( let i = 0, il = bones.length; i < il; i ++ ) { 32103 32104 // compute the offset between the current and the original transform 32105 32106 const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix$1; 32107 32108 _offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); 32109 _offsetMatrix.toArray( boneMatrices, i * 16 ); 32110 32111 } 32112 32113 if ( boneTexture !== null ) { 32114 32115 boneTexture.needsUpdate = true; 32116 32117 } 32118 32119 } 32120 32121 clone() { 32122 32123 return new Skeleton( this.bones, this.boneInverses ); 32124 32125 } 32126 32127 computeBoneTexture() { 32128 32129 // layout (1 matrix = 4 pixels) 32130 // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) 32131 // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) 32132 // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) 32133 // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) 32134 // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) 32135 32136 let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix 32137 size = Math.ceil( size / 4 ) * 4; 32138 size = Math.max( size, 4 ); 32139 32140 const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel 32141 boneMatrices.set( this.boneMatrices ); // copy current values 32142 32143 const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); 32144 boneTexture.needsUpdate = true; 32145 32146 this.boneMatrices = boneMatrices; 32147 this.boneTexture = boneTexture; 32148 32149 return this; 32150 32151 } 32152 32153 getBoneByName( name ) { 32154 32155 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32156 32157 const bone = this.bones[ i ]; 32158 32159 if ( bone.name === name ) { 32160 32161 return bone; 32162 32163 } 32164 32165 } 32166 32167 return undefined; 32168 32169 } 32170 32171 dispose( ) { 32172 32173 if ( this.boneTexture !== null ) { 32174 32175 this.boneTexture.dispose(); 32176 32177 this.boneTexture = null; 32178 32179 } 32180 32181 } 32182 32183 fromJSON( json, bones ) { 32184 32185 this.uuid = json.uuid; 32186 32187 for ( let i = 0, l = json.bones.length; i < l; i ++ ) { 32188 32189 const uuid = json.bones[ i ]; 32190 let bone = bones[ uuid ]; 32191 32192 if ( bone === undefined ) { 32193 32194 console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid ); 32195 bone = new Bone(); 32196 32197 } 32198 32199 this.bones.push( bone ); 32200 this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) ); 32201 32202 } 32203 32204 this.init(); 32205 32206 return this; 32207 32208 } 32209 32210 toJSON() { 32211 32212 const data = { 32213 metadata: { 32214 version: 4.6, 32215 type: 'Skeleton', 32216 generator: 'Skeleton.toJSON' 32217 }, 32218 bones: [], 32219 boneInverses: [] 32220 }; 32221 32222 data.uuid = this.uuid; 32223 32224 const bones = this.bones; 32225 const boneInverses = this.boneInverses; 32226 32227 for ( let i = 0, l = bones.length; i < l; i ++ ) { 32228 32229 const bone = bones[ i ]; 32230 data.bones.push( bone.uuid ); 32231 32232 const boneInverse = boneInverses[ i ]; 32233 data.boneInverses.push( boneInverse.toArray() ); 32234 32235 } 32236 32237 return data; 32238 32239 } 32240 32241} 32242 32243class InstancedBufferAttribute extends BufferAttribute { 32244 32245 constructor( array, itemSize, normalized, meshPerAttribute = 1 ) { 32246 32247 super( array, itemSize, normalized ); 32248 32249 this.isInstancedBufferAttribute = true; 32250 32251 this.meshPerAttribute = meshPerAttribute; 32252 32253 } 32254 32255 copy( source ) { 32256 32257 super.copy( source ); 32258 32259 this.meshPerAttribute = source.meshPerAttribute; 32260 32261 return this; 32262 32263 } 32264 32265 toJSON() { 32266 32267 const data = super.toJSON(); 32268 32269 data.meshPerAttribute = this.meshPerAttribute; 32270 32271 data.isInstancedBufferAttribute = true; 32272 32273 return data; 32274 32275 } 32276 32277} 32278 32279const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4(); 32280const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4(); 32281 32282const _instanceIntersects = []; 32283 32284const _box3 = /*@__PURE__*/ new Box3(); 32285const _identity = /*@__PURE__*/ new Matrix4(); 32286const _mesh$1 = /*@__PURE__*/ new Mesh(); 32287const _sphere$3 = /*@__PURE__*/ new Sphere(); 32288 32289class InstancedMesh extends Mesh { 32290 32291 constructor( geometry, material, count ) { 32292 32293 super( geometry, material ); 32294 32295 this.isInstancedMesh = true; 32296 32297 this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 ); 32298 this.instanceColor = null; 32299 this.morphTexture = null; 32300 32301 this.count = count; 32302 32303 this.boundingBox = null; 32304 this.boundingSphere = null; 32305 32306 for ( let i = 0; i < count; i ++ ) { 32307 32308 this.setMatrixAt( i, _identity ); 32309 32310 } 32311 32312 } 32313 32314 computeBoundingBox() { 32315 32316 const geometry = this.geometry; 32317 const count = this.count; 32318 32319 if ( this.boundingBox === null ) { 32320 32321 this.boundingBox = new Box3(); 32322 32323 } 32324 32325 if ( geometry.boundingBox === null ) { 32326 32327 geometry.computeBoundingBox(); 32328 32329 } 32330 32331 this.boundingBox.makeEmpty(); 32332 32333 for ( let i = 0; i < count; i ++ ) { 32334 32335 this.getMatrixAt( i, _instanceLocalMatrix ); 32336 32337 _box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix ); 32338 32339 this.boundingBox.union( _box3 ); 32340 32341 } 32342 32343 } 32344 32345 computeBoundingSphere() { 32346 32347 const geometry = this.geometry; 32348 const count = this.count; 32349 32350 if ( this.boundingSphere === null ) { 32351 32352 this.boundingSphere = new Sphere(); 32353 32354 } 32355 32356 if ( geometry.boundingSphere === null ) { 32357 32358 geometry.computeBoundingSphere(); 32359 32360 } 32361 32362 this.boundingSphere.makeEmpty(); 32363 32364 for ( let i = 0; i < count; i ++ ) { 32365 32366 this.getMatrixAt( i, _instanceLocalMatrix ); 32367 32368 _sphere$3.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix ); 32369 32370 this.boundingSphere.union( _sphere$3 ); 32371 32372 } 32373 32374 } 32375 32376 copy( source, recursive ) { 32377 32378 super.copy( source, recursive ); 32379 32380 this.instanceMatrix.copy( source.instanceMatrix ); 32381 32382 if ( source.morphTexture !== null ) this.morphTexture = source.morphTexture.clone(); 32383 if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone(); 32384 32385 this.count = source.count; 32386 32387 if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); 32388 if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); 32389 32390 return this; 32391 32392 } 32393 32394 getColorAt( index, color ) { 32395 32396 color.fromArray( this.instanceColor.array, index * 3 ); 32397 32398 } 32399 32400 getMatrixAt( index, matrix ) { 32401 32402 matrix.fromArray( this.instanceMatrix.array, index * 16 ); 32403 32404 } 32405 32406 getMorphAt( index, object ) { 32407 32408 const objectInfluences = object.morphTargetInfluences; 32409 32410 const array = this.morphTexture.source.data.data; 32411 32412 const len = objectInfluences.length + 1; // All influences + the baseInfluenceSum 32413 32414 const dataIndex = index * len + 1; // Skip the baseInfluenceSum at the beginning 32415 32416 for ( let i = 0; i < objectInfluences.length; i ++ ) { 32417 32418 objectInfluences[ i ] = array[ dataIndex + i ]; 32419 32420 } 32421 32422 } 32423 32424 raycast( raycaster, intersects ) { 32425 32426 const matrixWorld = this.matrixWorld; 32427 const raycastTimes = this.count; 32428 32429 _mesh$1.geometry = this.geometry; 32430 _mesh$1.material = this.material; 32431 32432 if ( _mesh$1.material === undefined ) return; 32433 32434 // test with bounding sphere first 32435 32436 if ( this.boundingSphere === null ) this.computeBoundingSphere(); 32437 32438 _sphere$3.copy( this.boundingSphere ); 32439 _sphere$3.applyMatrix4( matrixWorld ); 32440 32441 if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return; 32442 32443 // now test each instance 32444 32445 for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) { 32446 32447 // calculate the world matrix for each instance 32448 32449 this.getMatrixAt( instanceId, _instanceLocalMatrix ); 32450 32451 _instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix ); 32452 32453 // the mesh represents this single instance 32454 32455 _mesh$1.matrixWorld = _instanceWorldMatrix; 32456 32457 _mesh$1.raycast( raycaster, _instanceIntersects ); 32458 32459 // process the result of raycast 32460 32461 for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) { 32462 32463 const intersect = _instanceIntersects[ i ]; 32464 intersect.instanceId = instanceId; 32465 intersect.object = this; 32466 intersects.push( intersect ); 32467 32468 } 32469 32470 _instanceIntersects.length = 0; 32471 32472 } 32473 32474 } 32475 32476 setColorAt( index, color ) { 32477 32478 if ( this.instanceColor === null ) { 32479 32480 this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ), 3 ); 32481 32482 } 32483 32484 color.toArray( this.instanceColor.array, index * 3 ); 32485 32486 } 32487 32488 setMatrixAt( index, matrix ) { 32489 32490 matrix.toArray( this.instanceMatrix.array, index * 16 ); 32491 32492 } 32493 32494 setMorphAt( index, object ) { 32495 32496 const objectInfluences = object.morphTargetInfluences; 32497 32498 const len = objectInfluences.length + 1; // morphBaseInfluence + all influences 32499 32500 if ( this.morphTexture === null ) { 32501 32502 this.morphTexture = new DataTexture( new Float32Array( len * this.count ), len, this.count, RedFormat, FloatType ); 32503 32504 } 32505 32506 const array = this.morphTexture.source.data.data; 32507 32508 let morphInfluencesSum = 0; 32509 32510 for ( let i = 0; i < objectInfluences.length; i ++ ) { 32511 32512 morphInfluencesSum += objectInfluences[ i ]; 32513 32514 } 32515 32516 const morphBaseInfluence = this.geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; 32517 32518 const dataIndex = len * index; 32519 32520 array[ dataIndex ] = morphBaseInfluence; 32521 32522 array.set( objectInfluences, dataIndex + 1 ); 32523 32524 } 32525 32526 updateMorphTargets() { 32527 32528 } 32529 32530 dispose() { 32531 32532 this.dispatchEvent( { type: 'dispose' } ); 32533 32534 if ( this.morphTexture !== null ) { 32535 32536 this.morphTexture.dispose(); 32537 this.morphTexture = null; 32538 32539 } 32540 32541 return this; 32542 32543 } 32544 32545} 32546 32547function sortOpaque( a, b ) { 32548 32549 return a.z - b.z; 32550 32551} 32552
vendor: 5,260 bytes, lines 32553-32761
32553function sortTransparent( a, b ) { 32554 32555 return b.z - a.z; 32556 32557} 32558 32559class MultiDrawRenderList { 32560 32561 constructor() { 32562 32563 this.index = 0; 32564 this.pool = []; 32565 this.list = []; 32566 32567 } 32568 32569 push( drawRange, z ) { 32570 32571 const pool = this.pool; 32572 const list = this.list; 32573 if ( this.index >= pool.length ) { 32574 32575 pool.push( { 32576 32577 start: - 1, 32578 count: - 1, 32579 z: - 1, 32580 32581 } ); 32582 32583 } 32584 32585 const item = pool[ this.index ]; 32586 list.push( item ); 32587 this.index ++; 32588 32589 item.start = drawRange.start; 32590 item.count = drawRange.count; 32591 item.z = z; 32592 32593 } 32594 32595 reset() { 32596 32597 this.list.length = 0; 32598 this.index = 0; 32599 32600 } 32601 32602} 32603 32604const ID_ATTR_NAME = 'batchId'; 32605const _matrix$1 = /*@__PURE__*/ new Matrix4(); 32606const _invMatrixWorld = /*@__PURE__*/ new Matrix4(); 32607const _identityMatrix = /*@__PURE__*/ new Matrix4(); 32608const _projScreenMatrix$2 = /*@__PURE__*/ new Matrix4(); 32609const _frustum = /*@__PURE__*/ new Frustum(); 32610const _box$1 = /*@__PURE__*/ new Box3(); 32611const _sphere$2 = /*@__PURE__*/ new Sphere(); 32612const _vector$5 = /*@__PURE__*/ new Vector3(); 32613const _renderList = /*@__PURE__*/ new MultiDrawRenderList(); 32614const _mesh = /*@__PURE__*/ new Mesh(); 32615const _batchIntersects = []; 32616 32617// @TODO: SkinnedMesh support? 32618// @TODO: geometry.groups support? 32619// @TODO: geometry.drawRange support? 32620// @TODO: geometry.morphAttributes support? 32621// @TODO: Support uniform parameter per geometry 32622// @TODO: Add an "optimize" function to pack geometry and remove data gaps 32623 32624// copies data from attribute "src" into "target" starting at "targetOffset" 32625function copyAttributeData( src, target, targetOffset = 0 ) { 32626 32627 const itemSize = target.itemSize; 32628 if ( src.isInterleavedBufferAttribute || src.array.constructor !== target.array.constructor ) { 32629 32630 // use the component getters and setters if the array data cannot 32631 // be copied directly 32632 const vertexCount = src.count; 32633 for ( let i = 0; i < vertexCount; i ++ ) { 32634 32635 for ( let c = 0; c < itemSize; c ++ ) { 32636 32637 target.setComponent( i + targetOffset, c, src.getComponent( i, c ) ); 32638 32639 } 32640 32641 } 32642 32643 } else { 32644 32645 // faster copy approach using typed array set function 32646 target.array.set( src.array, targetOffset * itemSize ); 32647 32648 } 32649 32650 target.needsUpdate = true; 32651 32652} 32653 32654class BatchedMesh extends Mesh { 32655 32656 get maxGeometryCount() { 32657 32658 return this._maxGeometryCount; 32659 32660 } 32661 32662 constructor( maxGeometryCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material ) { 32663 32664 super( new BufferGeometry(), material ); 32665 32666 this.isBatchedMesh = true; 32667 this.perObjectFrustumCulled = true; 32668 this.sortObjects = true; 32669 this.boundingBox = null; 32670 this.boundingSphere = null; 32671 this.customSort = null; 32672 32673 this._drawRanges = []; 32674 this._reservedRanges = []; 32675 32676 this._visibility = []; 32677 this._active = []; 32678 this._bounds = []; 32679 32680 this._maxGeometryCount = maxGeometryCount; 32681 this._maxVertexCount = maxVertexCount; 32682 this._maxIndexCount = maxIndexCount; 32683 32684 this._geometryInitialized = false; 32685 this._geometryCount = 0; 32686 this._multiDrawCounts = new Int32Array( maxGeometryCount ); 32687 this._multiDrawStarts = new Int32Array( maxGeometryCount ); 32688 this._multiDrawCount = 0; 32689 this._visibilityChanged = true; 32690 32691 // Local matrix per geometry by using data texture 32692 this._matricesTexture = null; 32693 32694 this._initMatricesTexture(); 32695 32696 } 32697 32698 _initMatricesTexture() { 32699 32700 // layout (1 matrix = 4 pixels) 32701 // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) 32702 // with 8x8 pixel texture max 16 matrices * 4 pixels = (8 * 8) 32703 // 16x16 pixel texture max 64 matrices * 4 pixels = (16 * 16) 32704 // 32x32 pixel texture max 256 matrices * 4 pixels = (32 * 32) 32705 // 64x64 pixel texture max 1024 matrices * 4 pixels = (64 * 64) 32706 32707 let size = Math.sqrt( this._maxGeometryCount * 4 ); // 4 pixels needed for 1 matrix 32708 size = Math.ceil( size / 4 ) * 4; 32709 size = Math.max( size, 4 ); 32710 32711 const matricesArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel 32712 const matricesTexture = new DataTexture( matricesArray, size, size, RGBAFormat, FloatType ); 32713 32714 this._matricesTexture = matricesTexture; 32715 32716 } 32717 32718 _initializeGeometry( reference ) { 32719 32720 const geometry = this.geometry; 32721 const maxVertexCount = this._maxVertexCount; 32722 const maxGeometryCount = this._maxGeometryCount; 32723 const maxIndexCount = this._maxIndexCount; 32724 if ( this._geometryInitialized === false ) { 32725 32726 for ( const attributeName in reference.attributes ) { 32727 32728 const srcAttribute = reference.getAttribute( attributeName ); 32729 const { array, itemSize, normalized } = srcAttribute; 32730 32731 const dstArray = new array.constructor( maxVertexCount * itemSize ); 32732 const dstAttribute = new BufferAttribute( dstArray, itemSize, normalized ); 32733 32734 geometry.setAttribute( attributeName, dstAttribute ); 32735 32736 } 32737 32738 if ( reference.getIndex() !== null ) { 32739 32740 const indexArray = maxVertexCount > 65536 32741 ? new Uint32Array( maxIndexCount ) 32742 : new Uint16Array( maxIndexCount ); 32743 32744 geometry.setIndex( new BufferAttribute( indexArray, 1 ) ); 32745 32746 } 32747 32748 const idArray = maxGeometryCount > 65536 32749 ? new Uint32Array( maxVertexCount ) 32750 : new Uint16Array( maxVertexCount ); 32751 geometry.setAttribute( ID_ATTR_NAME, new BufferAttribute( idArray, 1 ) ); 32752 32753 this._geometryInitialized = true; 32754 32755 } 32756 32757 } 32758 32759 // Make sure the geometry is compatible with the existing combined geometry attributes 32760 _validateGeometry( geometry ) { 32761
32762 // check that the geometry doesn't have a version of our reserved id attribute 32763 if ( geometry.getAttribute( ID_ATTR_NAME ) ) { 32764 32765 throw new Error( `BatchedMesh: Geometry cannot use attribute "${ ID_ATTR_NAME }"` ); 32766 32767 } 32768 32769 // check to ensure the geometries are using consistent attributes and indices 32770 const batchGeometry = this.geometry; 32771 if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) { 32772 32773 throw new Error( 'BatchedMesh: All geometries must consistently have "index".' ); 32774 32775 } 32776 32777 for ( const attributeName in batchGeometry.attributes ) { 32778 32779 if ( attributeName === ID_ATTR_NAME ) { 32780 32781 continue; 32782 32783 } 32784 32785 if ( ! geometry.hasAttribute( attributeName ) ) { 32786 32787 throw new Error( `BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` ); 32788 32789 } 32790 32791 const srcAttribute = geometry.getAttribute( attributeName ); 32792 const dstAttribute = batchGeometry.getAttribute( attributeName ); 32793 if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) { 32794 32795 throw new Error( 'BatchedMesh: All attributes must have a consistent itemSize and normalized value.' ); 32796 32797 } 32798 32799 } 32800 32801 } 32802 32803 setCustomSort( func ) { 32804 32805 this.customSort = func; 32806 return this; 32807 32808 } 32809 32810 computeBoundingBox() { 32811 32812 if ( this.boundingBox === null ) { 32813 32814 this.boundingBox = new Box3(); 32815 32816 } 32817 32818 const geometryCount = this._geometryCount; 32819 const boundingBox = this.boundingBox; 32820 const active = this._active; 32821 32822 boundingBox.makeEmpty(); 32823 for ( let i = 0; i < geometryCount; i ++ ) { 32824 32825 if ( active[ i ] === false ) continue; 32826 32827 this.getMatrixAt( i, _matrix$1 ); 32828 this.getBoundingBoxAt( i, _box$1 ).applyMatrix4( _matrix$1 ); 32829 boundingBox.union( _box$1 ); 32830 32831 } 32832 32833 } 32834 32835 computeBoundingSphere() { 32836 32837 if ( this.boundingSphere === null ) { 32838 32839 this.boundingSphere = new Sphere(); 32840 32841 } 32842 32843 const geometryCount = this._geometryCount; 32844 const boundingSphere = this.boundingSphere; 32845 const active = this._active; 32846 32847 boundingSphere.makeEmpty(); 32848 for ( let i = 0; i < geometryCount; i ++ ) { 32849 32850 if ( active[ i ] === false ) continue; 32851 32852 this.getMatrixAt( i, _matrix$1 ); 32853 this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix$1 ); 32854 boundingSphere.union( _sphere$2 ); 32855 32856 } 32857 32858 } 32859 32860 addGeometry( geometry, vertexCount = - 1, indexCount = - 1 ) { 32861 32862 this._initializeGeometry( geometry ); 32863 32864 this._validateGeometry( geometry ); 32865 32866 // ensure we're not over geometry 32867 if ( this._geometryCount >= this._maxGeometryCount ) { 32868 32869 throw new Error( 'BatchedMesh: Maximum geometry count reached.' ); 32870 32871 } 32872 32873 // get the necessary range fo the geometry 32874 const reservedRange = { 32875 vertexStart: - 1, 32876 vertexCount: - 1, 32877 indexStart: - 1, 32878 indexCount: - 1, 32879 }; 32880 32881 let lastRange = null; 32882 const reservedRanges = this._reservedRanges; 32883 const drawRanges = this._drawRanges; 32884 const bounds = this._bounds; 32885 if ( this._geometryCount !== 0 ) { 32886 32887 lastRange = reservedRanges[ reservedRanges.length - 1 ]; 32888 32889 } 32890 32891 if ( vertexCount === - 1 ) { 32892 32893 reservedRange.vertexCount = geometry.getAttribute( 'position' ).count; 32894 32895 } else { 32896 32897 reservedRange.vertexCount = vertexCount; 32898 32899 } 32900 32901 if ( lastRange === null ) { 32902 32903 reservedRange.vertexStart = 0; 32904 32905 } else { 32906 32907 reservedRange.vertexStart = lastRange.vertexStart + lastRange.vertexCount; 32908 32909 } 32910 32911 const index = geometry.getIndex(); 32912 const hasIndex = index !== null; 32913 if ( hasIndex ) { 32914 32915 if ( indexCount === - 1 ) { 32916 32917 reservedRange.indexCount = index.count; 32918 32919 } else { 32920 32921 reservedRange.indexCount = indexCount; 32922 32923 } 32924 32925 if ( lastRange === null ) { 32926 32927 reservedRange.indexStart = 0; 32928 32929 } else { 32930 32931 reservedRange.indexStart = lastRange.indexStart + lastRange.indexCount; 32932 32933 } 32934 32935 } 32936 32937 if ( 32938 reservedRange.indexStart !== - 1 && 32939 reservedRange.indexStart + reservedRange.indexCount > this._maxIndexCount || 32940 reservedRange.vertexStart + reservedRange.vertexCount > this._maxVertexCount 32941 ) { 32942 32943 throw new Error( 'BatchedMesh: Reserved space request exceeds the maximum buffer size.' ); 32944 32945 } 32946 32947 const visibility = this._visibility; 32948 const active = this._active; 32949 const matricesTexture = this._matricesTexture; 32950 const matricesArray = this._matricesTexture.image.data; 32951 32952 // push new visibility states 32953 visibility.push( true ); 32954 active.push( true ); 32955 32956 // update id 32957 const geometryId = this._geometryCount; 32958 this._geometryCount ++; 32959 32960 // initialize matrix information 32961 _identityMatrix.toArray( matricesArray, geometryId * 16 ); 32962 matricesTexture.needsUpdate = true; 32963 32964 // add the reserved range and draw range objects 32965 reservedRanges.push( reservedRange ); 32966 drawRanges.push( { 32967 start: hasIndex ? reservedRange.indexStart : reservedRange.vertexStart, 32968 count: - 1 32969 } ); 32970 bounds.push( { 32971 boxInitialized: false, 32972 box: new Box3(), 32973 32974 sphereInitialized: false, 32975 sphere: new Sphere() 32976 } ); 32977 32978 // set the id for the geometry 32979 const idAttribute = this.geometry.getAttribute( ID_ATTR_NAME ); 32980 for ( let i = 0; i < reservedRange.vertexCount; i ++ ) { 32981 32982 idAttribute.setX( reservedRange.vertexStart + i, geometryId ); 32983 32984 } 32985 32986 idAttribute.needsUpdate = true; 32987 32988 // update the geometry 32989 this.setGeometryAt( geometryId, geometry ); 32990 32991 return geometryId; 32992 32993 } 32994 32995 setGeometryAt( id, geometry ) { 32996 32997 if ( id >= this._geometryCount ) { 32998 32999 throw new Error( 'BatchedMesh: Maximum geometry count reached.' ); 33000 33001 } 33002
33003 this._validateGeometry( geometry ); 33004 33005 const batchGeometry = this.geometry; 33006 const hasIndex = batchGeometry.getIndex() !== null; 33007 const dstIndex = batchGeometry.getIndex(); 33008 const srcIndex = geometry.getIndex(); 33009 const reservedRange = this._reservedRanges[ id ]; 33010 if ( 33011 hasIndex && 33012 srcIndex.count > reservedRange.indexCount || 33013 geometry.attributes.position.count > reservedRange.vertexCount 33014 ) { 33015 33016 throw new Error( 'BatchedMesh: Reserved space not large enough for provided geometry.' ); 33017 33018 } 33019 33020 // copy geometry over 33021 const vertexStart = reservedRange.vertexStart; 33022 const vertexCount = reservedRange.vertexCount; 33023 for ( const attributeName in batchGeometry.attributes ) { 33024 33025 if ( attributeName === ID_ATTR_NAME ) { 33026 33027 continue; 33028 33029 } 33030 33031 // copy attribute data 33032 const srcAttribute = geometry.getAttribute( attributeName ); 33033 const dstAttribute = batchGeometry.getAttribute( attributeName ); 33034 copyAttributeData( srcAttribute, dstAttribute, vertexStart ); 33035 33036 // fill the rest in with zeroes 33037 const itemSize = srcAttribute.itemSize; 33038 for ( let i = srcAttribute.count, l = vertexCount; i < l; i ++ ) { 33039 33040 const index = vertexStart + i; 33041 for ( let c = 0; c < itemSize; c ++ ) { 33042 33043 dstAttribute.setComponent( index, c, 0 ); 33044 33045 } 33046 33047 } 33048 33049 dstAttribute.needsUpdate = true; 33050 dstAttribute.addUpdateRange( vertexStart * itemSize, vertexCount * itemSize ); 33051 33052 } 33053 33054 // copy index 33055 if ( hasIndex ) { 33056 33057 const indexStart = reservedRange.indexStart; 33058 33059 // copy index data over 33060 for ( let i = 0; i < srcIndex.count; i ++ ) { 33061 33062 dstIndex.setX( indexStart + i, vertexStart + srcIndex.getX( i ) ); 33063 33064 } 33065 33066 // fill the rest in with zeroes 33067 for ( let i = srcIndex.count, l = reservedRange.indexCount; i < l; i ++ ) { 33068 33069 dstIndex.setX( indexStart + i, vertexStart ); 33070 33071 } 33072 33073 dstIndex.needsUpdate = true; 33074 dstIndex.addUpdateRange( indexStart, reservedRange.indexCount ); 33075 33076 } 33077 33078 // store the bounding boxes 33079 const bound = this._bounds[ id ]; 33080 if ( geometry.boundingBox !== null ) { 33081 33082 bound.box.copy( geometry.boundingBox ); 33083 bound.boxInitialized = true; 33084 33085 } else { 33086 33087 bound.boxInitialized = false; 33088 33089 } 33090 33091 if ( geometry.boundingSphere !== null ) { 33092 33093 bound.sphere.copy( geometry.boundingSphere ); 33094 bound.sphereInitialized = true; 33095 33096 } else { 33097 33098 bound.sphereInitialized = false; 33099 33100 } 33101 33102 // set drawRange count 33103 const drawRange = this._drawRanges[ id ]; 33104 const posAttr = geometry.getAttribute( 'position' ); 33105 drawRange.count = hasIndex ? srcIndex.count : posAttr.count; 33106 this._visibilityChanged = true; 33107 33108 return id; 33109 33110 } 33111 33112 deleteGeometry( geometryId ) { 33113 33114 // Note: User needs to call optimize() afterward to pack the data. 33115 33116 const active = this._active; 33117 if ( geometryId >= active.length || active[ geometryId ] === false ) { 33118 33119 return this; 33120 33121 } 33122 33123 active[ geometryId ] = false; 33124 this._visibilityChanged = true; 33125 33126 return this; 33127 33128 } 33129 33130 // get bounding box and compute it if it doesn't exist 33131 getBoundingBoxAt( id, target ) { 33132 33133 const active = this._active; 33134 if ( active[ id ] === false ) { 33135 33136 return null; 33137 33138 } 33139 33140 // compute bounding box 33141 const bound = this._bounds[ id ]; 33142 const box = bound.box; 33143 const geometry = this.geometry; 33144 if ( bound.boxInitialized === false ) { 33145 33146 box.makeEmpty(); 33147 33148 const index = geometry.index; 33149 const position = geometry.attributes.position; 33150 const drawRange = this._drawRanges[ id ]; 33151 for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) { 33152 33153 let iv = i; 33154 if ( index ) { 33155 33156 iv = index.getX( iv ); 33157 33158 } 33159 33160 box.expandByPoint( _vector$5.fromBufferAttribute( position, iv ) ); 33161 33162 } 33163 33164 bound.boxInitialized = true; 33165 33166 } 33167 33168 target.copy( box ); 33169 return target; 33170 33171 } 33172 33173 // get bounding sphere and compute it if it doesn't exist 33174 getBoundingSphereAt( id, target ) { 33175 33176 const active = this._active; 33177 if ( active[ id ] === false ) { 33178 33179 return null; 33180 33181 } 33182 33183 // compute bounding sphere 33184 const bound = this._bounds[ id ]; 33185 const sphere = bound.sphere; 33186 const geometry = this.geometry; 33187 if ( bound.sphereInitialized === false ) { 33188 33189 sphere.makeEmpty(); 33190 33191 this.getBoundingBoxAt( id, _box$1 ); 33192 _box$1.getCenter( sphere.center ); 33193 33194 const index = geometry.index; 33195 const position = geometry.attributes.position; 33196 const drawRange = this._drawRanges[ id ]; 33197 33198 let maxRadiusSq = 0; 33199 for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) { 33200 33201 let iv = i; 33202 if ( index ) { 33203 33204 iv = index.getX( iv ); 33205 33206 } 33207 33208 _vector$5.fromBufferAttribute( position, iv ); 33209 maxRadiusSq = Math.max( maxRadiusSq, sphere.center.distanceToSquared( _vector$5 ) ); 33210 33211 } 33212 33213 sphere.radius = Math.sqrt( maxRadiusSq ); 33214 bound.sphereInitialized = true; 33215 33216 } 33217 33218 target.copy( sphere ); 33219 return target; 33220 33221 } 33222
33223 setMatrixAt( geometryId, matrix ) { 33224 33225 // @TODO: Map geometryId to index of the arrays because 33226 // optimize() can make geometryId mismatch the index 33227 33228 const active = this._active; 33229 const matricesTexture = this._matricesTexture; 33230 const matricesArray = this._matricesTexture.image.data; 33231 const geometryCount = this._geometryCount; 33232 if ( geometryId >= geometryCount || active[ geometryId ] === false ) { 33233 33234 return this; 33235 33236 } 33237 33238 matrix.toArray( matricesArray, geometryId * 16 ); 33239 matricesTexture.needsUpdate = true; 33240 33241 return this; 33242 33243 } 33244 33245 getMatrixAt( geometryId, matrix ) { 33246 33247 const active = this._active; 33248 const matricesArray = this._matricesTexture.image.data; 33249 const geometryCount = this._geometryCount; 33250 if ( geometryId >= geometryCount || active[ geometryId ] === false ) { 33251 33252 return null; 33253 33254 } 33255 33256 return matrix.fromArray( matricesArray, geometryId * 16 ); 33257 33258 } 33259 33260 setVisibleAt( geometryId, value ) { 33261 33262 const visibility = this._visibility; 33263 const active = this._active; 33264 const geometryCount = this._geometryCount; 33265 33266 // if the geometry is out of range, not active, or visibility state 33267 // does not change then return early 33268 if ( 33269 geometryId >= geometryCount || 33270 active[ geometryId ] === false || 33271 visibility[ geometryId ] === value 33272 ) { 33273 33274 return this; 33275 33276 } 33277 33278 visibility[ geometryId ] = value; 33279 this._visibilityChanged = true; 33280 33281 return this; 33282 33283 } 33284 33285 getVisibleAt( geometryId ) { 33286 33287 const visibility = this._visibility; 33288 const active = this._active; 33289 const geometryCount = this._geometryCount; 33290 33291 // return early if the geometry is out of range or not active 33292 if ( geometryId >= geometryCount || active[ geometryId ] === false ) { 33293 33294 return false; 33295 33296 } 33297 33298 return visibility[ geometryId ]; 33299 33300 } 33301 33302 raycast( raycaster, intersects ) { 33303 33304 const visibility = this._visibility; 33305 const active = this._active; 33306 const drawRanges = this._drawRanges; 33307 const geometryCount = this._geometryCount; 33308 const matrixWorld = this.matrixWorld; 33309 const batchGeometry = this.geometry; 33310 33311 // iterate over each geometry 33312 _mesh.material = this.material; 33313 _mesh.geometry.index = batchGeometry.index; 33314 _mesh.geometry.attributes = batchGeometry.attributes; 33315 if ( _mesh.geometry.boundingBox === null ) { 33316 33317 _mesh.geometry.boundingBox = new Box3(); 33318 33319 } 33320 33321 if ( _mesh.geometry.boundingSphere === null ) { 33322 33323 _mesh.geometry.boundingSphere = new Sphere(); 33324 33325 } 33326 33327 for ( let i = 0; i < geometryCount; i ++ ) { 33328 33329 if ( ! visibility[ i ] || ! active[ i ] ) { 33330 33331 continue; 33332 33333 } 33334 33335 const drawRange = drawRanges[ i ]; 33336 _mesh.geometry.setDrawRange( drawRange.start, drawRange.count ); 33337 33338 // ge the intersects 33339 this.getMatrixAt( i, _mesh.matrixWorld ).premultiply( matrixWorld ); 33340 this.getBoundingBoxAt( i, _mesh.geometry.boundingBox ); 33341 this.getBoundingSphereAt( i, _mesh.geometry.boundingSphere ); 33342 _mesh.raycast( raycaster, _batchIntersects ); 33343 33344 // add batch id to the intersects 33345 for ( let j = 0, l = _batchIntersects.length; j < l; j ++ ) { 33346 33347 const intersect = _batchIntersects[ j ]; 33348 intersect.object = this; 33349 intersect.batchId = i; 33350 intersects.push( intersect ); 33351 33352 } 33353 33354 _batchIntersects.length = 0; 33355 33356 } 33357 33358 _mesh.material = null; 33359 _mesh.geometry.index = null; 33360 _mesh.geometry.attributes = {}; 33361 _mesh.geometry.setDrawRange( 0, Infinity ); 33362 33363 } 33364 33365 copy( source ) { 33366 33367 super.copy( source ); 33368 33369 this.geometry = source.geometry.clone(); 33370 this.perObjectFrustumCulled = source.perObjectFrustumCulled; 33371 this.sortObjects = source.sortObjects; 33372 this.boundingBox = source.boundingBox !== null ? source.boundingBox.clone() : null; 33373 this.boundingSphere = source.boundingSphere !== null ? source.boundingSphere.clone() : null; 33374 33375 this._drawRanges = source._drawRanges.map( range => ( { ...range } ) ); 33376 this._reservedRanges = source._reservedRanges.map( range => ( { ...range } ) ); 33377 33378 this._visibility = source._visibility.slice(); 33379 this._active = source._active.slice(); 33380 this._bounds = source._bounds.map( bound => ( { 33381 boxInitialized: bound.boxInitialized, 33382 box: bound.box.clone(), 33383 33384 sphereInitialized: bound.sphereInitialized, 33385 sphere: bound.sphere.clone() 33386 } ) ); 33387 33388 this._maxGeometryCount = source._maxGeometryCount; 33389 this._maxVertexCount = source._maxVertexCount; 33390 this._maxIndexCount = source._maxIndexCount; 33391 33392 this._geometryInitialized = source._geometryInitialized; 33393 this._geometryCount = source._geometryCount; 33394 this._multiDrawCounts = source._multiDrawCounts.slice(); 33395 this._multiDrawStarts = source._multiDrawStarts.slice(); 33396 33397 this._matricesTexture = source._matricesTexture.clone(); 33398 this._matricesTexture.image.data = this._matricesTexture.image.slice(); 33399 33400 return this; 33401 33402 } 33403 33404 dispose() { 33405 33406 // Assuming the geometry is not shared with other meshes 33407 this.geometry.dispose(); 33408 33409 this._matricesTexture.dispose(); 33410 this._matricesTexture = null; 33411 return this; 33412 33413 } 33414 33415 onBeforeRender( renderer, scene, camera, geometry, material/*, _group*/ ) { 33416 33417 // if visibility has not changed and frustum culling and object sorting is not required 33418 // then skip iterating over all items 33419 if ( ! this._visibilityChanged && ! this.perObjectFrustumCulled && ! this.sortObjects ) { 33420 33421 return; 33422 33423 } 33424 33425 // the indexed version of the multi draw function requires specifying the start 33426 // offset in bytes. 33427 const index = geometry.getIndex(); 33428 const bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT; 33429 33430 const active = this._active; 33431 const visibility = this._visibility; 33432 const multiDrawStarts = this._multiDrawStarts; 33433 const multiDrawCounts = this._multiDrawCounts; 33434 const drawRanges = this._drawRanges; 33435 const perObjectFrustumCulled = this.perObjectFrustumCulled; 33436 33437 // prepare the frustum in the local frame 33438 if ( perObjectFrustumCulled ) { 33439 33440 _projScreenMatrix$2 33441 .multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ) 33442 .multiply( this.matrixWorld ); 33443 _frustum.setFromProjectionMatrix( 33444 _projScreenMatrix$2, 33445 renderer.coordinateSystem 33446 ); 33447 33448 } 33449 33450 let count = 0; 33451 if ( this.sortObjects ) { 33452 33453 // get the camera position in the local frame 33454 _invMatrixWorld.copy( this.matrixWorld ).invert(); 33455 _vector$5.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4( _invMatrixWorld ); 33456 33457 for ( let i = 0, l = visibility.length; i < l; i ++ ) { 33458 33459 if ( visibility[ i ] && active[ i ] ) { 33460 33461 // get the bounds in world space 33462 this.getMatrixAt( i, _matrix$1 ); 33463 this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix$1 ); 33464 33465 // determine whether the batched geometry is within the frustum
vendor: 13,545 bytes, lines 33466-34086
33466 let culled = false; 33467 if ( perObjectFrustumCulled ) { 33468 33469 culled = ! _frustum.intersectsSphere( _sphere$2 ); 33470 33471 } 33472 33473 if ( ! culled ) { 33474 33475 // get the distance from camera used for sorting 33476 const z = _vector$5.distanceTo( _sphere$2.center ); 33477 _renderList.push( drawRanges[ i ], z ); 33478 33479 } 33480 33481 } 33482 33483 } 33484 33485 // Sort the draw ranges and prep for rendering 33486 const list = _renderList.list; 33487 const customSort = this.customSort; 33488 if ( customSort === null ) { 33489 33490 list.sort( material.transparent ? sortTransparent : sortOpaque ); 33491 33492 } else { 33493 33494 customSort.call( this, list, camera ); 33495 33496 } 33497 33498 for ( let i = 0, l = list.length; i < l; i ++ ) { 33499 33500 const item = list[ i ]; 33501 multiDrawStarts[ count ] = item.start * bytesPerElement; 33502 multiDrawCounts[ count ] = item.count; 33503 count ++; 33504 33505 } 33506 33507 _renderList.reset(); 33508 33509 } else { 33510 33511 for ( let i = 0, l = visibility.length; i < l; i ++ ) { 33512 33513 if ( visibility[ i ] && active[ i ] ) { 33514 33515 // determine whether the batched geometry is within the frustum 33516 let culled = false; 33517 if ( perObjectFrustumCulled ) { 33518 33519 // get the bounds in world space 33520 this.getMatrixAt( i, _matrix$1 ); 33521 this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix$1 ); 33522 culled = ! _frustum.intersectsSphere( _sphere$2 ); 33523 33524 } 33525 33526 if ( ! culled ) { 33527 33528 const range = drawRanges[ i ]; 33529 multiDrawStarts[ count ] = range.start * bytesPerElement; 33530 multiDrawCounts[ count ] = range.count; 33531 count ++; 33532 33533 } 33534 33535 } 33536 33537 } 33538 33539 } 33540 33541 this._multiDrawCount = count; 33542 this._visibilityChanged = false; 33543 33544 } 33545 33546 onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial/* , group */ ) { 33547 33548 this.onBeforeRender( renderer, null, shadowCamera, geometry, depthMaterial ); 33549 33550 } 33551 33552} 33553 33554class LineBasicMaterial extends Material { 33555 33556 constructor( parameters ) { 33557 33558 super(); 33559 33560 this.isLineBasicMaterial = true; 33561 33562 this.type = 'LineBasicMaterial'; 33563 33564 this.color = new Color( 0xffffff ); 33565 33566 this.map = null; 33567 33568 this.linewidth = 1; 33569 this.linecap = 'round'; 33570 this.linejoin = 'round'; 33571 33572 this.fog = true; 33573 33574 this.setValues( parameters ); 33575 33576 } 33577 33578 33579 copy( source ) { 33580 33581 super.copy( source ); 33582 33583 this.color.copy( source.color ); 33584 33585 this.map = source.map; 33586 33587 this.linewidth = source.linewidth; 33588 this.linecap = source.linecap; 33589 this.linejoin = source.linejoin; 33590 33591 this.fog = source.fog; 33592 33593 return this; 33594 33595 } 33596 33597} 33598 33599const _start$1 = /*@__PURE__*/ new Vector3(); 33600const _end$1 = /*@__PURE__*/ new Vector3(); 33601const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4(); 33602const _ray$1 = /*@__PURE__*/ new Ray(); 33603const _sphere$1 = /*@__PURE__*/ new Sphere(); 33604 33605class Line extends Object3D { 33606 33607 constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) { 33608 33609 super(); 33610 33611 this.isLine = true; 33612 33613 this.type = 'Line'; 33614 33615 this.geometry = geometry; 33616 this.material = material; 33617 33618 this.updateMorphTargets(); 33619 33620 } 33621 33622 copy( source, recursive ) { 33623 33624 super.copy( source, recursive ); 33625 33626 this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; 33627 this.geometry = source.geometry; 33628 33629 return this; 33630 33631 } 33632 33633 computeLineDistances() { 33634 33635 const geometry = this.geometry; 33636 33637 // we assume non-indexed geometry 33638 33639 if ( geometry.index === null ) { 33640 33641 const positionAttribute = geometry.attributes.position; 33642 const lineDistances = [ 0 ]; 33643 33644 for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) { 33645 33646 _start$1.fromBufferAttribute( positionAttribute, i - 1 ); 33647 _end$1.fromBufferAttribute( positionAttribute, i ); 33648 33649 lineDistances[ i ] = lineDistances[ i - 1 ]; 33650 lineDistances[ i ] += _start$1.distanceTo( _end$1 ); 33651 33652 } 33653 33654 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); 33655 33656 } else { 33657 33658 console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); 33659 33660 } 33661 33662 return this; 33663 33664 } 33665 33666 raycast( raycaster, intersects ) { 33667 33668 const geometry = this.geometry; 33669 const matrixWorld = this.matrixWorld; 33670 const threshold = raycaster.params.Line.threshold; 33671 const drawRange = geometry.drawRange; 33672 33673 // Checking boundingSphere distance to ray 33674 33675 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 33676 33677 _sphere$1.copy( geometry.boundingSphere ); 33678 _sphere$1.applyMatrix4( matrixWorld ); 33679 _sphere$1.radius += threshold; 33680 33681 if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return; 33682 33683 // 33684 33685 _inverseMatrix$1.copy( matrixWorld ).invert(); 33686 _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 ); 33687 33688 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); 33689 const localThresholdSq = localThreshold * localThreshold; 33690 33691 const vStart = new Vector3(); 33692 const vEnd = new Vector3(); 33693 const interSegment = new Vector3(); 33694 const interRay = new Vector3(); 33695 const step = this.isLineSegments ? 2 : 1; 33696 33697 const index = geometry.index; 33698 const attributes = geometry.attributes; 33699 const positionAttribute = attributes.position; 33700 33701 if ( index !== null ) { 33702 33703 const start = Math.max( 0, drawRange.start ); 33704 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); 33705 33706 for ( let i = start, l = end - 1; i < l; i += step ) { 33707 33708 const a = index.getX( i ); 33709 const b = index.getX( i + 1 ); 33710 33711 vStart.fromBufferAttribute( positionAttribute, a ); 33712 vEnd.fromBufferAttribute( positionAttribute, b ); 33713 33714 const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); 33715 33716 if ( distSq > localThresholdSq ) continue; 33717 33718 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation 33719 33720 const distance = raycaster.ray.origin.distanceTo( interRay ); 33721 33722 if ( distance < raycaster.near || distance > raycaster.far ) continue; 33723 33724 intersects.push( { 33725 33726 distance: distance, 33727 // What do we want? intersection point on the ray or on the segment?? 33728 // point: raycaster.ray.at( distance ), 33729 point: interSegment.clone().applyMatrix4( this.matrixWorld ), 33730 index: i, 33731 face: null, 33732 faceIndex: null, 33733 object: this 33734 33735 } ); 33736 33737 } 33738 33739 } else { 33740 33741 const start = Math.max( 0, drawRange.start ); 33742 const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); 33743 33744 for ( let i = start, l = end - 1; i < l; i += step ) { 33745 33746 vStart.fromBufferAttribute( positionAttribute, i ); 33747 vEnd.fromBufferAttribute( positionAttribute, i + 1 ); 33748 33749 const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); 33750 33751 if ( distSq > localThresholdSq ) continue; 33752 33753 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation 33754 33755 const distance = raycaster.ray.origin.distanceTo( interRay ); 33756 33757 if ( distance < raycaster.near || distance > raycaster.far ) continue; 33758 33759 intersects.push( { 33760 33761 distance: distance, 33762 // What do we want? intersection point on the ray or on the segment?? 33763 // point: raycaster.ray.at( distance ), 33764 point: interSegment.clone().applyMatrix4( this.matrixWorld ), 33765 index: i, 33766 face: null, 33767 faceIndex: null, 33768 object: this 33769 33770 } ); 33771 33772 } 33773 33774 } 33775 33776 } 33777 33778 updateMorphTargets() { 33779 33780 const geometry = this.geometry; 33781 33782 const morphAttributes = geometry.morphAttributes; 33783 const keys = Object.keys( morphAttributes ); 33784 33785 if ( keys.length > 0 ) { 33786 33787 const morphAttribute = morphAttributes[ keys[ 0 ] ]; 33788 33789 if ( morphAttribute !== undefined ) { 33790 33791 this.morphTargetInfluences = []; 33792 this.morphTargetDictionary = {}; 33793 33794 for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 33795 33796 const name = morphAttribute[ m ].name || String( m ); 33797 33798 this.morphTargetInfluences.push( 0 ); 33799 this.morphTargetDictionary[ name ] = m; 33800 33801 } 33802 33803 } 33804 33805 } 33806 33807 } 33808 33809} 33810 33811const _start = /*@__PURE__*/ new Vector3(); 33812const _end = /*@__PURE__*/ new Vector3(); 33813 33814class LineSegments extends Line { 33815 33816 constructor( geometry, material ) { 33817 33818 super( geometry, material ); 33819 33820 this.isLineSegments = true; 33821 33822 this.type = 'LineSegments'; 33823 33824 } 33825 33826 computeLineDistances() { 33827 33828 const geometry = this.geometry; 33829 33830 // we assume non-indexed geometry 33831 33832 if ( geometry.index === null ) { 33833 33834 const positionAttribute = geometry.attributes.position; 33835 const lineDistances = []; 33836 33837 for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) { 33838 33839 _start.fromBufferAttribute( positionAttribute, i ); 33840 _end.fromBufferAttribute( positionAttribute, i + 1 ); 33841 33842 lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ]; 33843 lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end ); 33844 33845 } 33846 33847 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); 33848 33849 } else { 33850 33851 console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); 33852 33853 } 33854 33855 return this; 33856 33857 } 33858 33859} 33860 33861class LineLoop extends Line { 33862 33863 constructor( geometry, material ) { 33864 33865 super( geometry, material ); 33866 33867 this.isLineLoop = true; 33868 33869 this.type = 'LineLoop'; 33870 33871 } 33872 33873} 33874 33875class PointsMaterial extends Material { 33876 33877 constructor( parameters ) { 33878 33879 super(); 33880 33881 this.isPointsMaterial = true; 33882 33883 this.type = 'PointsMaterial'; 33884 33885 this.color = new Color( 0xffffff ); 33886 33887 this.map = null; 33888 33889 this.alphaMap = null; 33890 33891 this.size = 1; 33892 this.sizeAttenuation = true; 33893 33894 this.fog = true; 33895 33896 this.setValues( parameters ); 33897 33898 } 33899 33900 copy( source ) { 33901 33902 super.copy( source ); 33903 33904 this.color.copy( source.color ); 33905 33906 this.map = source.map; 33907 33908 this.alphaMap = source.alphaMap; 33909 33910 this.size = source.size; 33911 this.sizeAttenuation = source.sizeAttenuation; 33912 33913 this.fog = source.fog; 33914 33915 return this; 33916 33917 } 33918 33919} 33920 33921const _inverseMatrix = /*@__PURE__*/ new Matrix4(); 33922const _ray = /*@__PURE__*/ new Ray(); 33923const _sphere = /*@__PURE__*/ new Sphere(); 33924const _position$2 = /*@__PURE__*/ new Vector3(); 33925 33926class Points extends Object3D { 33927 33928 constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) { 33929 33930 super(); 33931 33932 this.isPoints = true; 33933 33934 this.type = 'Points'; 33935 33936 this.geometry = geometry; 33937 this.material = material; 33938 33939 this.updateMorphTargets(); 33940 33941 } 33942 33943 copy( source, recursive ) { 33944 33945 super.copy( source, recursive ); 33946 33947 this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; 33948 this.geometry = source.geometry; 33949 33950 return this; 33951 33952 } 33953 33954 raycast( raycaster, intersects ) { 33955 33956 const geometry = this.geometry; 33957 const matrixWorld = this.matrixWorld; 33958 const threshold = raycaster.params.Points.threshold; 33959 const drawRange = geometry.drawRange; 33960 33961 // Checking boundingSphere distance to ray 33962 33963 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 33964 33965 _sphere.copy( geometry.boundingSphere ); 33966 _sphere.applyMatrix4( matrixWorld ); 33967 _sphere.radius += threshold; 33968 33969 if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return; 33970 33971 // 33972 33973 _inverseMatrix.copy( matrixWorld ).invert(); 33974 _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix ); 33975 33976 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); 33977 const localThresholdSq = localThreshold * localThreshold; 33978 33979 const index = geometry.index; 33980 const attributes = geometry.attributes; 33981 const positionAttribute = attributes.position; 33982 33983 if ( index !== null ) { 33984 33985 const start = Math.max( 0, drawRange.start ); 33986 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); 33987 33988 for ( let i = start, il = end; i < il; i ++ ) { 33989 33990 const a = index.getX( i ); 33991 33992 _position$2.fromBufferAttribute( positionAttribute, a ); 33993 33994 testPoint( _position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this ); 33995 33996 } 33997 33998 } else { 33999 34000 const start = Math.max( 0, drawRange.start ); 34001 const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); 34002 34003 for ( let i = start, l = end; i < l; i ++ ) { 34004 34005 _position$2.fromBufferAttribute( positionAttribute, i ); 34006 34007 testPoint( _position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this ); 34008 34009 } 34010 34011 } 34012 34013 } 34014 34015 updateMorphTargets() { 34016 34017 const geometry = this.geometry; 34018 34019 const morphAttributes = geometry.morphAttributes; 34020 const keys = Object.keys( morphAttributes ); 34021 34022 if ( keys.length > 0 ) { 34023 34024 const morphAttribute = morphAttributes[ keys[ 0 ] ]; 34025 34026 if ( morphAttribute !== undefined ) { 34027 34028 this.morphTargetInfluences = []; 34029 this.morphTargetDictionary = {}; 34030 34031 for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 34032 34033 const name = morphAttribute[ m ].name || String( m ); 34034 34035 this.morphTargetInfluences.push( 0 ); 34036 this.morphTargetDictionary[ name ] = m; 34037 34038 } 34039 34040 } 34041 34042 } 34043 34044 } 34045 34046} 34047 34048function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) { 34049 34050 const rayPointDistanceSq = _ray.distanceSqToPoint( point ); 34051 34052 if ( rayPointDistanceSq < localThresholdSq ) { 34053 34054 const intersectPoint = new Vector3(); 34055 34056 _ray.closestPointToPoint( point, intersectPoint ); 34057 intersectPoint.applyMatrix4( matrixWorld ); 34058 34059 const distance = raycaster.ray.origin.distanceTo( intersectPoint ); 34060 34061 if ( distance < raycaster.near || distance > raycaster.far ) return; 34062 34063 intersects.push( { 34064 34065 distance: distance, 34066 distanceToRay: Math.sqrt( rayPointDistanceSq ), 34067 point: intersectPoint, 34068 index: index, 34069 face: null, 34070 object: object 34071 34072 } ); 34073 34074 } 34075 34076} 34077 34078class VideoTexture extends Texture { 34079 34080 constructor( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { 34081 34082 super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 34083 34084 this.isVideoTexture = true; 34085 34086 this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
34087 this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; 34088 34089 this.generateMipmaps = false; 34090 34091 const scope = this; 34092 34093 function updateVideo() { 34094 34095 scope.needsUpdate = true; 34096 video.requestVideoFrameCallback( updateVideo ); 34097 34098 } 34099 34100 if ( 'requestVideoFrameCallback' in video ) { 34101 34102 video.requestVideoFrameCallback( updateVideo ); 34103 34104 } 34105 34106 } 34107 34108 clone() { 34109 34110 return new this.constructor( this.image ).copy( this ); 34111 34112 } 34113 34114 update() { 34115 34116 const video = this.image; 34117 const hasVideoFrameCallback = 'requestVideoFrameCallback' in video; 34118 34119 if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) { 34120 34121 this.needsUpdate = true; 34122 34123 } 34124 34125 } 34126 34127} 34128 34129class FramebufferTexture extends Texture { 34130 34131 constructor( width, height ) { 34132 34133 super( { width, height } ); 34134 34135 this.isFramebufferTexture = true; 34136 34137 this.magFilter = NearestFilter; 34138 this.minFilter = NearestFilter; 34139 34140 this.generateMipmaps = false; 34141 34142 this.needsUpdate = true; 34143 34144 } 34145 34146} 34147 34148class CompressedTexture extends Texture { 34149 34150 constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) { 34151 34152 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); 34153 34154 this.isCompressedTexture = true; 34155 34156 this.image = { width: width, height: height }; 34157 this.mipmaps = mipmaps; 34158 34159 // no flipping for cube textures 34160 // (also flipping doesn't work for compressed textures ) 34161 34162 this.flipY = false; 34163 34164 // can't generate mipmaps for compressed textures 34165 // mips must be embedded in DDS files 34166 34167 this.generateMipmaps = false; 34168 34169 } 34170 34171} 34172 34173class CompressedArrayTexture extends CompressedTexture { 34174 34175 constructor( mipmaps, width, height, depth, format, type ) { 34176 34177 super( mipmaps, width, height, format, type ); 34178 34179 this.isCompressedArrayTexture = true; 34180 this.image.depth = depth; 34181 this.wrapR = ClampToEdgeWrapping; 34182 34183 } 34184 34185} 34186 34187class CompressedCubeTexture extends CompressedTexture { 34188 34189 constructor( images, format, type ) { 34190 34191 super( undefined, images[ 0 ].width, images[ 0 ].height, format, type, CubeReflectionMapping ); 34192 34193 this.isCompressedCubeTexture = true; 34194 this.isCubeTexture = true; 34195 34196 this.image = images; 34197 34198 } 34199 34200} 34201 34202class CanvasTexture extends Texture { 34203 34204 constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { 34205 34206 super( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 34207 34208 this.isCanvasTexture = true; 34209 34210 this.needsUpdate = true; 34211 34212 } 34213 34214} 34215 34216/** 34217 * Extensible curve object. 34218 * 34219 * Some common of curve methods: 34220 * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget ) 34221 * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget ) 34222 * .getPoints(), .getSpacedPoints() 34223 * .getLength() 34224 * .updateArcLengths() 34225 * 34226 * This following curves inherit from THREE.Curve: 34227 * 34228 * -- 2D curves -- 34229 * THREE.ArcCurve 34230 * THREE.CubicBezierCurve 34231 * THREE.EllipseCurve 34232 * THREE.LineCurve 34233 * THREE.QuadraticBezierCurve 34234 * THREE.SplineCurve 34235 * 34236 * -- 3D curves -- 34237 * THREE.CatmullRomCurve3 34238 * THREE.CubicBezierCurve3 34239 * THREE.LineCurve3 34240 * THREE.QuadraticBezierCurve3 34241 * 34242 * A series of curves can be represented as a THREE.CurvePath. 34243 * 34244 **/ 34245 34246class Curve { 34247 34248 constructor() { 34249 34250 this.type = 'Curve'; 34251 34252 this.arcLengthDivisions = 200; 34253 34254 } 34255 34256 // Virtual base class method to overwrite and implement in subclasses 34257 // - t [0 .. 1] 34258 34259 getPoint( /* t, optionalTarget */ ) { 34260 34261 console.warn( 'THREE.Curve: .getPoint() not implemented.' ); 34262 return null; 34263 34264 } 34265 34266 // Get point at relative position in curve according to arc length 34267 // - u [0 .. 1] 34268 34269 getPointAt( u, optionalTarget ) { 34270 34271 const t = this.getUtoTmapping( u ); 34272 return this.getPoint( t, optionalTarget ); 34273 34274 } 34275 34276 // Get sequence of points using getPoint( t ) 34277 34278 getPoints( divisions = 5 ) { 34279 34280 const points = []; 34281 34282 for ( let d = 0; d <= divisions; d ++ ) { 34283 34284 points.push( this.getPoint( d / divisions ) ); 34285 34286 } 34287 34288 return points; 34289 34290 } 34291 34292 // Get sequence of points using getPointAt( u ) 34293 34294 getSpacedPoints( divisions = 5 ) { 34295 34296 const points = []; 34297 34298 for ( let d = 0; d <= divisions; d ++ ) { 34299 34300 points.push( this.getPointAt( d / divisions ) ); 34301 34302 } 34303 34304 return points; 34305 34306 } 34307 34308 // Get total curve arc length 34309 34310 getLength() { 34311 34312 const lengths = this.getLengths(); 34313 return lengths[ lengths.length - 1 ]; 34314 34315 } 34316 34317 // Get list of cumulative segment lengths 34318 34319 getLengths( divisions = this.arcLengthDivisions ) { 34320 34321 if ( this.cacheArcLengths && 34322 ( this.cacheArcLengths.length === divisions + 1 ) && 34323 ! this.needsUpdate ) { 34324 34325 return this.cacheArcLengths; 34326 34327 } 34328 34329 this.needsUpdate = false;
vendor: 7,517 bytes, lines 34330-34721
34330 34331 const cache = []; 34332 let current, last = this.getPoint( 0 ); 34333 let sum = 0; 34334 34335 cache.push( 0 ); 34336 34337 for ( let p = 1; p <= divisions; p ++ ) { 34338 34339 current = this.getPoint( p / divisions ); 34340 sum += current.distanceTo( last ); 34341 cache.push( sum ); 34342 last = current; 34343 34344 } 34345 34346 this.cacheArcLengths = cache; 34347 34348 return cache; // { sums: cache, sum: sum }; Sum is in the last element. 34349 34350 } 34351 34352 updateArcLengths() { 34353 34354 this.needsUpdate = true; 34355 this.getLengths(); 34356 34357 } 34358 34359 // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant 34360 34361 getUtoTmapping( u, distance ) { 34362 34363 const arcLengths = this.getLengths(); 34364 34365 let i = 0; 34366 const il = arcLengths.length; 34367 34368 let targetArcLength; // The targeted u distance value to get 34369 34370 if ( distance ) { 34371 34372 targetArcLength = distance; 34373 34374 } else { 34375 34376 targetArcLength = u * arcLengths[ il - 1 ]; 34377 34378 } 34379 34380 // binary search for the index with largest value smaller than target u distance 34381 34382 let low = 0, high = il - 1, comparison; 34383 34384 while ( low <= high ) { 34385 34386 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 34387 34388 comparison = arcLengths[ i ] - targetArcLength; 34389 34390 if ( comparison < 0 ) { 34391 34392 low = i + 1; 34393 34394 } else if ( comparison > 0 ) { 34395 34396 high = i - 1; 34397 34398 } else { 34399 34400 high = i; 34401 break; 34402 34403 // DONE 34404 34405 } 34406 34407 } 34408 34409 i = high; 34410 34411 if ( arcLengths[ i ] === targetArcLength ) { 34412 34413 return i / ( il - 1 ); 34414 34415 } 34416 34417 // we could get finer grain at lengths, or use simple interpolation between two points 34418 34419 const lengthBefore = arcLengths[ i ]; 34420 const lengthAfter = arcLengths[ i + 1 ]; 34421 34422 const segmentLength = lengthAfter - lengthBefore; 34423 34424 // determine where we are between the 'before' and 'after' points 34425 34426 const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; 34427 34428 // add that fractional amount to t 34429 34430 const t = ( i + segmentFraction ) / ( il - 1 ); 34431 34432 return t; 34433 34434 } 34435 34436 // Returns a unit vector tangent at t 34437 // In case any sub curve does not implement its tangent derivation, 34438 // 2 points a small delta apart will be used to find its gradient 34439 // which seems to give a reasonable approximation 34440 34441 getTangent( t, optionalTarget ) { 34442 34443 const delta = 0.0001; 34444 let t1 = t - delta; 34445 let t2 = t + delta; 34446 34447 // Capping in case of danger 34448 34449 if ( t1 < 0 ) t1 = 0; 34450 if ( t2 > 1 ) t2 = 1; 34451 34452 const pt1 = this.getPoint( t1 ); 34453 const pt2 = this.getPoint( t2 ); 34454 34455 const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() ); 34456 34457 tangent.copy( pt2 ).sub( pt1 ).normalize(); 34458 34459 return tangent; 34460 34461 } 34462 34463 getTangentAt( u, optionalTarget ) { 34464 34465 const t = this.getUtoTmapping( u ); 34466 return this.getTangent( t, optionalTarget ); 34467 34468 } 34469 34470 computeFrenetFrames( segments, closed ) { 34471 34472 // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf 34473 34474 const normal = new Vector3(); 34475 34476 const tangents = []; 34477 const normals = []; 34478 const binormals = []; 34479 34480 const vec = new Vector3(); 34481 const mat = new Matrix4(); 34482 34483 // compute the tangent vectors for each segment on the curve 34484 34485 for ( let i = 0; i <= segments; i ++ ) { 34486 34487 const u = i / segments; 34488 34489 tangents[ i ] = this.getTangentAt( u, new Vector3() ); 34490 34491 } 34492 34493 // select an initial normal vector perpendicular to the first tangent vector, 34494 // and in the direction of the minimum tangent xyz component 34495 34496 normals[ 0 ] = new Vector3(); 34497 binormals[ 0 ] = new Vector3(); 34498 let min = Number.MAX_VALUE; 34499 const tx = Math.abs( tangents[ 0 ].x ); 34500 const ty = Math.abs( tangents[ 0 ].y ); 34501 const tz = Math.abs( tangents[ 0 ].z ); 34502 34503 if ( tx <= min ) { 34504 34505 min = tx; 34506 normal.set( 1, 0, 0 ); 34507 34508 } 34509 34510 if ( ty <= min ) { 34511 34512 min = ty; 34513 normal.set( 0, 1, 0 ); 34514 34515 } 34516 34517 if ( tz <= min ) { 34518 34519 normal.set( 0, 0, 1 ); 34520 34521 } 34522 34523 vec.crossVectors( tangents[ 0 ], normal ).normalize(); 34524 34525 normals[ 0 ].crossVectors( tangents[ 0 ], vec ); 34526 binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ); 34527 34528 34529 // compute the slowly-varying normal and binormal vectors for each segment on the curve 34530 34531 for ( let i = 1; i <= segments; i ++ ) { 34532 34533 normals[ i ] = normals[ i - 1 ].clone(); 34534 34535 binormals[ i ] = binormals[ i - 1 ].clone(); 34536 34537 vec.crossVectors( tangents[ i - 1 ], tangents[ i ] ); 34538 34539 if ( vec.length() > Number.EPSILON ) { 34540 34541 vec.normalize(); 34542 34543 const theta = Math.acos( clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors 34544 34545 normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) ); 34546 34547 } 34548 34549 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); 34550 34551 } 34552 34553 // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same 34554 34555 if ( closed === true ) { 34556 34557 let theta = Math.acos( clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) ); 34558 theta /= segments; 34559 34560 if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) { 34561 34562 theta = - theta; 34563 34564 } 34565 34566 for ( let i = 1; i <= segments; i ++ ) { 34567 34568 // twist a little... 34569 normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) ); 34570 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); 34571 34572 } 34573 34574 } 34575 34576 return { 34577 tangents: tangents, 34578 normals: normals, 34579 binormals: binormals 34580 }; 34581 34582 } 34583 34584 clone() { 34585 34586 return new this.constructor().copy( this ); 34587 34588 } 34589 34590 copy( source ) { 34591 34592 this.arcLengthDivisions = source.arcLengthDivisions; 34593 34594 return this; 34595 34596 } 34597 34598 toJSON() { 34599 34600 const data = { 34601 metadata: { 34602 version: 4.6, 34603 type: 'Curve', 34604 generator: 'Curve.toJSON' 34605 } 34606 }; 34607 34608 data.arcLengthDivisions = this.arcLengthDivisions; 34609 data.type = this.type; 34610 34611 return data; 34612 34613 } 34614 34615 fromJSON( json ) { 34616 34617 this.arcLengthDivisions = json.arcLengthDivisions; 34618 34619 return this; 34620 34621 } 34622 34623} 34624 34625class EllipseCurve extends Curve { 34626 34627 constructor( aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0 ) { 34628 34629 super(); 34630 34631 this.isEllipseCurve = true; 34632 34633 this.type = 'EllipseCurve'; 34634 34635 this.aX = aX; 34636 this.aY = aY; 34637 34638 this.xRadius = xRadius; 34639 this.yRadius = yRadius; 34640 34641 this.aStartAngle = aStartAngle; 34642 this.aEndAngle = aEndAngle; 34643 34644 this.aClockwise = aClockwise; 34645 34646 this.aRotation = aRotation; 34647 34648 } 34649 34650 getPoint( t, optionalTarget = new Vector2() ) { 34651 34652 const point = optionalTarget; 34653 34654 const twoPi = Math.PI * 2; 34655 let deltaAngle = this.aEndAngle - this.aStartAngle; 34656 const samePoints = Math.abs( deltaAngle ) < Number.EPSILON; 34657 34658 // ensures that deltaAngle is 0 .. 2 PI 34659 while ( deltaAngle < 0 ) deltaAngle += twoPi; 34660 while ( deltaAngle > twoPi ) deltaAngle -= twoPi; 34661 34662 if ( deltaAngle < Number.EPSILON ) { 34663 34664 if ( samePoints ) { 34665 34666 deltaAngle = 0; 34667 34668 } else { 34669 34670 deltaAngle = twoPi; 34671 34672 } 34673 34674 } 34675 34676 if ( this.aClockwise === true && ! samePoints ) { 34677 34678 if ( deltaAngle === twoPi ) { 34679 34680 deltaAngle = - twoPi; 34681 34682 } else { 34683 34684 deltaAngle = deltaAngle - twoPi; 34685 34686 } 34687 34688 } 34689 34690 const angle = this.aStartAngle + t * deltaAngle; 34691 let x = this.aX + this.xRadius * Math.cos( angle ); 34692 let y = this.aY + this.yRadius * Math.sin( angle ); 34693 34694 if ( this.aRotation !== 0 ) { 34695 34696 const cos = Math.cos( this.aRotation ); 34697 const sin = Math.sin( this.aRotation ); 34698 34699 const tx = x - this.aX; 34700 const ty = y - this.aY; 34701 34702 // Rotate the point about the center of the ellipse. 34703 x = tx * cos - ty * sin + this.aX; 34704 y = tx * sin + ty * cos + this.aY; 34705 34706 } 34707 34708 return point.set( x, y ); 34709 34710 } 34711 34712 copy( source ) { 34713 34714 super.copy( source ); 34715 34716 this.aX = source.aX; 34717 this.aY = source.aY; 34718 34719 this.xRadius = source.xRadius; 34720 this.yRadius = source.yRadius; 34721
vendor: 29,619 bytes, lines 34722-36404
34722 this.aStartAngle = source.aStartAngle; 34723 this.aEndAngle = source.aEndAngle; 34724 34725 this.aClockwise = source.aClockwise; 34726 34727 this.aRotation = source.aRotation; 34728 34729 return this; 34730 34731 } 34732 34733 toJSON() { 34734 34735 const data = super.toJSON(); 34736 34737 data.aX = this.aX; 34738 data.aY = this.aY; 34739 34740 data.xRadius = this.xRadius; 34741 data.yRadius = this.yRadius; 34742 34743 data.aStartAngle = this.aStartAngle; 34744 data.aEndAngle = this.aEndAngle; 34745 34746 data.aClockwise = this.aClockwise; 34747 34748 data.aRotation = this.aRotation; 34749 34750 return data; 34751 34752 } 34753 34754 fromJSON( json ) { 34755 34756 super.fromJSON( json ); 34757 34758 this.aX = json.aX; 34759 this.aY = json.aY; 34760 34761 this.xRadius = json.xRadius; 34762 this.yRadius = json.yRadius; 34763 34764 this.aStartAngle = json.aStartAngle; 34765 this.aEndAngle = json.aEndAngle; 34766 34767 this.aClockwise = json.aClockwise; 34768 34769 this.aRotation = json.aRotation; 34770 34771 return this; 34772 34773 } 34774 34775} 34776 34777class ArcCurve extends EllipseCurve { 34778 34779 constructor( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 34780 34781 super( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); 34782 34783 this.isArcCurve = true; 34784 34785 this.type = 'ArcCurve'; 34786 34787 } 34788 34789} 34790 34791/** 34792 * Centripetal CatmullRom Curve - which is useful for avoiding 34793 * cusps and self-intersections in non-uniform catmull rom curves. 34794 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf 34795 * 34796 * curve.type accepts centripetal(default), chordal and catmullrom 34797 * curve.tension is used for catmullrom which defaults to 0.5 34798 */ 34799 34800 34801/* 34802Based on an optimized c++ solution in 34803 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/ 34804 - http://ideone.com/NoEbVM 34805 34806This CubicPoly class could be used for reusing some variables and calculations, 34807but for three.js curve use, it could be possible inlined and flatten into a single function call 34808which can be placed in CurveUtils. 34809*/ 34810 34811function CubicPoly() { 34812 34813 let c0 = 0, c1 = 0, c2 = 0, c3 = 0; 34814 34815 /* 34816 * Compute coefficients for a cubic polynomial 34817 * p(s) = c0 + c1*s + c2*s^2 + c3*s^3 34818 * such that 34819 * p(0) = x0, p(1) = x1 34820 * and 34821 * p'(0) = t0, p'(1) = t1. 34822 */ 34823 function init( x0, x1, t0, t1 ) { 34824 34825 c0 = x0; 34826 c1 = t0; 34827 c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1; 34828 c3 = 2 * x0 - 2 * x1 + t0 + t1; 34829 34830 } 34831 34832 return { 34833 34834 initCatmullRom: function ( x0, x1, x2, x3, tension ) { 34835 34836 init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) ); 34837 34838 }, 34839 34840 initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) { 34841 34842 // compute tangents when parameterized in [t1,t2] 34843 let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1; 34844 let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2; 34845 34846 // rescale tangents for parametrization in [0,1] 34847 t1 *= dt1; 34848 t2 *= dt1; 34849 34850 init( x1, x2, t1, t2 ); 34851 34852 }, 34853 34854 calc: function ( t ) { 34855 34856 const t2 = t * t; 34857 const t3 = t2 * t; 34858 return c0 + c1 * t + c2 * t2 + c3 * t3; 34859 34860 } 34861 34862 }; 34863 34864} 34865 34866// 34867 34868const tmp = /*@__PURE__*/ new Vector3(); 34869const px = /*@__PURE__*/ new CubicPoly(); 34870const py = /*@__PURE__*/ new CubicPoly(); 34871const pz = /*@__PURE__*/ new CubicPoly(); 34872 34873class CatmullRomCurve3 extends Curve { 34874 34875 constructor( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) { 34876 34877 super(); 34878 34879 this.isCatmullRomCurve3 = true; 34880 34881 this.type = 'CatmullRomCurve3'; 34882 34883 this.points = points; 34884 this.closed = closed; 34885 this.curveType = curveType; 34886 this.tension = tension; 34887 34888 } 34889 34890 getPoint( t, optionalTarget = new Vector3() ) { 34891 34892 const point = optionalTarget; 34893 34894 const points = this.points; 34895 const l = points.length; 34896 34897 const p = ( l - ( this.closed ? 0 : 1 ) ) * t; 34898 let intPoint = Math.floor( p ); 34899 let weight = p - intPoint; 34900 34901 if ( this.closed ) { 34902 34903 intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l; 34904 34905 } else if ( weight === 0 && intPoint === l - 1 ) { 34906 34907 intPoint = l - 2; 34908 weight = 1; 34909 34910 } 34911 34912 let p0, p3; // 4 points (p1 & p2 defined below) 34913 34914 if ( this.closed || intPoint > 0 ) { 34915 34916 p0 = points[ ( intPoint - 1 ) % l ]; 34917 34918 } else { 34919 34920 // extrapolate first point 34921 tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] ); 34922 p0 = tmp; 34923 34924 } 34925 34926 const p1 = points[ intPoint % l ]; 34927 const p2 = points[ ( intPoint + 1 ) % l ]; 34928 34929 if ( this.closed || intPoint + 2 < l ) { 34930 34931 p3 = points[ ( intPoint + 2 ) % l ]; 34932 34933 } else { 34934 34935 // extrapolate last point 34936 tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] ); 34937 p3 = tmp; 34938 34939 } 34940 34941 if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) { 34942 34943 // init Centripetal / Chordal Catmull-Rom 34944 const pow = this.curveType === 'chordal' ? 0.5 : 0.25; 34945 let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow ); 34946 let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow ); 34947 let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow ); 34948 34949 // safety check for repeated points 34950 if ( dt1 < 1e-4 ) dt1 = 1.0; 34951 if ( dt0 < 1e-4 ) dt0 = dt1; 34952 if ( dt2 < 1e-4 ) dt2 = dt1; 34953 34954 px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 ); 34955 py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 ); 34956 pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 ); 34957 34958 } else if ( this.curveType === 'catmullrom' ) { 34959 34960 px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension ); 34961 py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension ); 34962 pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension ); 34963 34964 } 34965 34966 point.set( 34967 px.calc( weight ), 34968 py.calc( weight ), 34969 pz.calc( weight ) 34970 ); 34971 34972 return point; 34973 34974 } 34975 34976 copy( source ) { 34977 34978 super.copy( source ); 34979 34980 this.points = []; 34981 34982 for ( let i = 0, l = source.points.length; i < l; i ++ ) { 34983 34984 const point = source.points[ i ]; 34985 34986 this.points.push( point.clone() ); 34987 34988 } 34989 34990 this.closed = source.closed; 34991 this.curveType = source.curveType; 34992 this.tension = source.tension; 34993 34994 return this; 34995 34996 } 34997 34998 toJSON() { 34999 35000 const data = super.toJSON(); 35001 35002 data.points = []; 35003 35004 for ( let i = 0, l = this.points.length; i < l; i ++ ) { 35005 35006 const point = this.points[ i ]; 35007 data.points.push( point.toArray() ); 35008 35009 } 35010 35011 data.closed = this.closed; 35012 data.curveType = this.curveType; 35013 data.tension = this.tension; 35014 35015 return data; 35016 35017 } 35018 35019 fromJSON( json ) { 35020 35021 super.fromJSON( json ); 35022 35023 this.points = []; 35024 35025 for ( let i = 0, l = json.points.length; i < l; i ++ ) { 35026 35027 const point = json.points[ i ]; 35028 this.points.push( new Vector3().fromArray( point ) ); 35029 35030 } 35031 35032 this.closed = json.closed; 35033 this.curveType = json.curveType; 35034 this.tension = json.tension; 35035 35036 return this; 35037 35038 } 35039 35040} 35041 35042/** 35043 * Bezier Curves formulas obtained from 35044 * https://en.wikipedia.org/wiki/B%C3%A9zier_curve 35045 */ 35046 35047function CatmullRom( t, p0, p1, p2, p3 ) { 35048 35049 const v0 = ( p2 - p0 ) * 0.5; 35050 const v1 = ( p3 - p1 ) * 0.5; 35051 const t2 = t * t; 35052 const t3 = t * t2; 35053 return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1; 35054 35055} 35056 35057// 35058 35059function QuadraticBezierP0( t, p ) { 35060 35061 const k = 1 - t; 35062 return k * k * p; 35063 35064} 35065 35066function QuadraticBezierP1( t, p ) { 35067 35068 return 2 * ( 1 - t ) * t * p; 35069 35070} 35071 35072function QuadraticBezierP2( t, p ) { 35073 35074 return t * t * p; 35075 35076} 35077 35078function QuadraticBezier( t, p0, p1, p2 ) { 35079 35080 return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) + 35081 QuadraticBezierP2( t, p2 ); 35082 35083} 35084 35085// 35086 35087function CubicBezierP0( t, p ) { 35088 35089 const k = 1 - t; 35090 return k * k * k * p; 35091 35092} 35093 35094function CubicBezierP1( t, p ) { 35095 35096 const k = 1 - t; 35097 return 3 * k * k * t * p; 35098 35099} 35100 35101function CubicBezierP2( t, p ) { 35102 35103 return 3 * ( 1 - t ) * t * t * p; 35104 35105} 35106 35107function CubicBezierP3( t, p ) { 35108 35109 return t * t * t * p; 35110 35111} 35112 35113function CubicBezier( t, p0, p1, p2, p3 ) { 35114 35115 return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) + 35116 CubicBezierP3( t, p3 ); 35117 35118} 35119 35120class CubicBezierCurve extends Curve { 35121 35122 constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) { 35123 35124 super(); 35125 35126 this.isCubicBezierCurve = true; 35127 35128 this.type = 'CubicBezierCurve'; 35129 35130 this.v0 = v0; 35131 this.v1 = v1; 35132 this.v2 = v2; 35133 this.v3 = v3; 35134 35135 } 35136 35137 getPoint( t, optionalTarget = new Vector2() ) { 35138 35139 const point = optionalTarget; 35140 35141 const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; 35142 35143 point.set( 35144 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), 35145 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ) 35146 ); 35147 35148 return point; 35149 35150 } 35151 35152 copy( source ) { 35153 35154 super.copy( source ); 35155 35156 this.v0.copy( source.v0 ); 35157 this.v1.copy( source.v1 ); 35158 this.v2.copy( source.v2 ); 35159 this.v3.copy( source.v3 ); 35160 35161 return this; 35162 35163 } 35164 35165 toJSON() { 35166 35167 const data = super.toJSON(); 35168 35169 data.v0 = this.v0.toArray(); 35170 data.v1 = this.v1.toArray(); 35171 data.v2 = this.v2.toArray(); 35172 data.v3 = this.v3.toArray(); 35173 35174 return data; 35175 35176 } 35177 35178 fromJSON( json ) { 35179 35180 super.fromJSON( json ); 35181 35182 this.v0.fromArray( json.v0 ); 35183 this.v1.fromArray( json.v1 ); 35184 this.v2.fromArray( json.v2 ); 35185 this.v3.fromArray( json.v3 ); 35186 35187 return this; 35188 35189 } 35190 35191} 35192 35193class CubicBezierCurve3 extends Curve { 35194 35195 constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) { 35196 35197 super(); 35198 35199 this.isCubicBezierCurve3 = true; 35200 35201 this.type = 'CubicBezierCurve3'; 35202 35203 this.v0 = v0; 35204 this.v1 = v1; 35205 this.v2 = v2; 35206 this.v3 = v3; 35207 35208 } 35209 35210 getPoint( t, optionalTarget = new Vector3() ) { 35211 35212 const point = optionalTarget; 35213 35214 const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; 35215 35216 point.set( 35217 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), 35218 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ), 35219 CubicBezier( t, v0.z, v1.z, v2.z, v3.z ) 35220 ); 35221 35222 return point; 35223 35224 } 35225 35226 copy( source ) { 35227 35228 super.copy( source ); 35229 35230 this.v0.copy( source.v0 ); 35231 this.v1.copy( source.v1 ); 35232 this.v2.copy( source.v2 ); 35233 this.v3.copy( source.v3 ); 35234 35235 return this; 35236 35237 } 35238 35239 toJSON() { 35240 35241 const data = super.toJSON(); 35242 35243 data.v0 = this.v0.toArray(); 35244 data.v1 = this.v1.toArray(); 35245 data.v2 = this.v2.toArray(); 35246 data.v3 = this.v3.toArray(); 35247 35248 return data; 35249 35250 } 35251 35252 fromJSON( json ) { 35253 35254 super.fromJSON( json ); 35255 35256 this.v0.fromArray( json.v0 ); 35257 this.v1.fromArray( json.v1 ); 35258 this.v2.fromArray( json.v2 ); 35259 this.v3.fromArray( json.v3 ); 35260 35261 return this; 35262 35263 } 35264 35265} 35266 35267class LineCurve extends Curve { 35268 35269 constructor( v1 = new Vector2(), v2 = new Vector2() ) { 35270 35271 super(); 35272 35273 this.isLineCurve = true; 35274 35275 this.type = 'LineCurve'; 35276 35277 this.v1 = v1; 35278 this.v2 = v2; 35279 35280 } 35281 35282 getPoint( t, optionalTarget = new Vector2() ) { 35283 35284 const point = optionalTarget; 35285 35286 if ( t === 1 ) { 35287 35288 point.copy( this.v2 ); 35289 35290 } else { 35291 35292 point.copy( this.v2 ).sub( this.v1 ); 35293 point.multiplyScalar( t ).add( this.v1 ); 35294 35295 } 35296 35297 return point; 35298 35299 } 35300 35301 // Line curve is linear, so we can overwrite default getPointAt 35302 getPointAt( u, optionalTarget ) { 35303 35304 return this.getPoint( u, optionalTarget ); 35305 35306 } 35307 35308 getTangent( t, optionalTarget = new Vector2() ) { 35309 35310 return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); 35311 35312 } 35313 35314 getTangentAt( u, optionalTarget ) { 35315 35316 return this.getTangent( u, optionalTarget ); 35317 35318 } 35319 35320 copy( source ) { 35321 35322 super.copy( source ); 35323 35324 this.v1.copy( source.v1 ); 35325 this.v2.copy( source.v2 ); 35326 35327 return this; 35328 35329 } 35330 35331 toJSON() { 35332 35333 const data = super.toJSON(); 35334 35335 data.v1 = this.v1.toArray(); 35336 data.v2 = this.v2.toArray(); 35337 35338 return data; 35339 35340 } 35341 35342 fromJSON( json ) { 35343 35344 super.fromJSON( json ); 35345 35346 this.v1.fromArray( json.v1 ); 35347 this.v2.fromArray( json.v2 ); 35348 35349 return this; 35350 35351 } 35352 35353} 35354 35355class LineCurve3 extends Curve { 35356 35357 constructor( v1 = new Vector3(), v2 = new Vector3() ) { 35358 35359 super(); 35360 35361 this.isLineCurve3 = true; 35362 35363 this.type = 'LineCurve3'; 35364 35365 this.v1 = v1; 35366 this.v2 = v2; 35367 35368 } 35369 35370 getPoint( t, optionalTarget = new Vector3() ) { 35371 35372 const point = optionalTarget; 35373 35374 if ( t === 1 ) { 35375 35376 point.copy( this.v2 ); 35377 35378 } else { 35379 35380 point.copy( this.v2 ).sub( this.v1 ); 35381 point.multiplyScalar( t ).add( this.v1 ); 35382 35383 } 35384 35385 return point; 35386 35387 } 35388 35389 // Line curve is linear, so we can overwrite default getPointAt 35390 getPointAt( u, optionalTarget ) { 35391 35392 return this.getPoint( u, optionalTarget ); 35393 35394 } 35395 35396 getTangent( t, optionalTarget = new Vector3() ) { 35397 35398 return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); 35399 35400 } 35401 35402 getTangentAt( u, optionalTarget ) { 35403 35404 return this.getTangent( u, optionalTarget ); 35405 35406 } 35407 35408 copy( source ) { 35409 35410 super.copy( source ); 35411 35412 this.v1.copy( source.v1 ); 35413 this.v2.copy( source.v2 ); 35414 35415 return this; 35416 35417 } 35418 35419 toJSON() { 35420 35421 const data = super.toJSON(); 35422 35423 data.v1 = this.v1.toArray(); 35424 data.v2 = this.v2.toArray(); 35425 35426 return data; 35427 35428 } 35429 35430 fromJSON( json ) { 35431 35432 super.fromJSON( json ); 35433 35434 this.v1.fromArray( json.v1 ); 35435 this.v2.fromArray( json.v2 ); 35436 35437 return this; 35438 35439 } 35440 35441} 35442 35443class QuadraticBezierCurve extends Curve { 35444 35445 constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) { 35446 35447 super(); 35448 35449 this.isQuadraticBezierCurve = true; 35450 35451 this.type = 'QuadraticBezierCurve'; 35452 35453 this.v0 = v0; 35454 this.v1 = v1; 35455 this.v2 = v2; 35456 35457 } 35458 35459 getPoint( t, optionalTarget = new Vector2() ) { 35460 35461 const point = optionalTarget; 35462 35463 const v0 = this.v0, v1 = this.v1, v2 = this.v2; 35464 35465 point.set( 35466 QuadraticBezier( t, v0.x, v1.x, v2.x ), 35467 QuadraticBezier( t, v0.y, v1.y, v2.y ) 35468 ); 35469 35470 return point; 35471 35472 } 35473 35474 copy( source ) { 35475 35476 super.copy( source ); 35477 35478 this.v0.copy( source.v0 ); 35479 this.v1.copy( source.v1 ); 35480 this.v2.copy( source.v2 ); 35481 35482 return this; 35483 35484 } 35485 35486 toJSON() { 35487 35488 const data = super.toJSON(); 35489 35490 data.v0 = this.v0.toArray(); 35491 data.v1 = this.v1.toArray(); 35492 data.v2 = this.v2.toArray(); 35493 35494 return data; 35495 35496 } 35497 35498 fromJSON( json ) { 35499 35500 super.fromJSON( json ); 35501 35502 this.v0.fromArray( json.v0 ); 35503 this.v1.fromArray( json.v1 ); 35504 this.v2.fromArray( json.v2 ); 35505 35506 return this; 35507 35508 } 35509 35510} 35511 35512class QuadraticBezierCurve3 extends Curve { 35513 35514 constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) { 35515 35516 super(); 35517 35518 this.isQuadraticBezierCurve3 = true; 35519 35520 this.type = 'QuadraticBezierCurve3'; 35521 35522 this.v0 = v0; 35523 this.v1 = v1; 35524 this.v2 = v2; 35525 35526 } 35527 35528 getPoint( t, optionalTarget = new Vector3() ) { 35529 35530 const point = optionalTarget; 35531 35532 const v0 = this.v0, v1 = this.v1, v2 = this.v2; 35533 35534 point.set( 35535 QuadraticBezier( t, v0.x, v1.x, v2.x ), 35536 QuadraticBezier( t, v0.y, v1.y, v2.y ), 35537 QuadraticBezier( t, v0.z, v1.z, v2.z ) 35538 ); 35539 35540 return point; 35541 35542 } 35543 35544 copy( source ) { 35545 35546 super.copy( source ); 35547 35548 this.v0.copy( source.v0 ); 35549 this.v1.copy( source.v1 ); 35550 this.v2.copy( source.v2 ); 35551 35552 return this; 35553 35554 } 35555 35556 toJSON() { 35557 35558 const data = super.toJSON(); 35559 35560 data.v0 = this.v0.toArray(); 35561 data.v1 = this.v1.toArray(); 35562 data.v2 = this.v2.toArray(); 35563 35564 return data; 35565 35566 } 35567 35568 fromJSON( json ) { 35569 35570 super.fromJSON( json ); 35571 35572 this.v0.fromArray( json.v0 ); 35573 this.v1.fromArray( json.v1 ); 35574 this.v2.fromArray( json.v2 ); 35575 35576 return this; 35577 35578 } 35579 35580} 35581 35582class SplineCurve extends Curve { 35583 35584 constructor( points = [] ) { 35585 35586 super(); 35587 35588 this.isSplineCurve = true; 35589 35590 this.type = 'SplineCurve'; 35591 35592 this.points = points; 35593 35594 } 35595 35596 getPoint( t, optionalTarget = new Vector2() ) { 35597 35598 const point = optionalTarget; 35599 35600 const points = this.points; 35601 const p = ( points.length - 1 ) * t; 35602 35603 const intPoint = Math.floor( p ); 35604 const weight = p - intPoint; 35605 35606 const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ]; 35607 const p1 = points[ intPoint ]; 35608 const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ]; 35609 const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ]; 35610 35611 point.set( 35612 CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ), 35613 CatmullRom( weight, p0.y, p1.y, p2.y, p3.y ) 35614 ); 35615 35616 return point; 35617 35618 } 35619 35620 copy( source ) { 35621 35622 super.copy( source ); 35623 35624 this.points = []; 35625 35626 for ( let i = 0, l = source.points.length; i < l; i ++ ) { 35627 35628 const point = source.points[ i ]; 35629 35630 this.points.push( point.clone() ); 35631 35632 } 35633 35634 return this; 35635 35636 } 35637 35638 toJSON() { 35639 35640 const data = super.toJSON(); 35641 35642 data.points = []; 35643 35644 for ( let i = 0, l = this.points.length; i < l; i ++ ) { 35645 35646 const point = this.points[ i ]; 35647 data.points.push( point.toArray() ); 35648 35649 } 35650 35651 return data; 35652 35653 } 35654 35655 fromJSON( json ) { 35656 35657 super.fromJSON( json ); 35658 35659 this.points = []; 35660 35661 for ( let i = 0, l = json.points.length; i < l; i ++ ) { 35662 35663 const point = json.points[ i ]; 35664 this.points.push( new Vector2().fromArray( point ) ); 35665 35666 } 35667 35668 return this; 35669 35670 } 35671 35672} 35673 35674var Curves = /*#__PURE__*/Object.freeze({ 35675 __proto__: null, 35676 ArcCurve: ArcCurve, 35677 CatmullRomCurve3: CatmullRomCurve3, 35678 CubicBezierCurve: CubicBezierCurve, 35679 CubicBezierCurve3: CubicBezierCurve3, 35680 EllipseCurve: EllipseCurve, 35681 LineCurve: LineCurve, 35682 LineCurve3: LineCurve3, 35683 QuadraticBezierCurve: QuadraticBezierCurve, 35684 QuadraticBezierCurve3: QuadraticBezierCurve3, 35685 SplineCurve: SplineCurve 35686}); 35687 35688/************************************************************** 35689 * Curved Path - a curve path is simply a array of connected 35690 * curves, but retains the api of a curve 35691 **************************************************************/ 35692 35693class CurvePath extends Curve { 35694 35695 constructor() { 35696 35697 super(); 35698 35699 this.type = 'CurvePath'; 35700 35701 this.curves = []; 35702 this.autoClose = false; // Automatically closes the path 35703 35704 } 35705 35706 add( curve ) { 35707 35708 this.curves.push( curve ); 35709 35710 } 35711 35712 closePath() { 35713 35714 // Add a line curve if start and end of lines are not connected 35715 const startPoint = this.curves[ 0 ].getPoint( 0 ); 35716 const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 ); 35717 35718 if ( ! startPoint.equals( endPoint ) ) { 35719 35720 const lineType = ( startPoint.isVector2 === true ) ? 'LineCurve' : 'LineCurve3'; 35721 this.curves.push( new Curves[ lineType ]( endPoint, startPoint ) ); 35722 35723 } 35724 35725 return this; 35726 35727 } 35728 35729 // To get accurate point with reference to 35730 // entire path distance at time t, 35731 // following has to be done: 35732 35733 // 1. Length of each sub path have to be known 35734 // 2. Locate and identify type of curve 35735 // 3. Get t for the curve 35736 // 4. Return curve.getPointAt(t') 35737 35738 getPoint( t, optionalTarget ) { 35739 35740 const d = t * this.getLength(); 35741 const curveLengths = this.getCurveLengths(); 35742 let i = 0; 35743 35744 // To think about boundaries points. 35745 35746 while ( i < curveLengths.length ) { 35747 35748 if ( curveLengths[ i ] >= d ) { 35749 35750 const diff = curveLengths[ i ] - d; 35751 const curve = this.curves[ i ]; 35752 35753 const segmentLength = curve.getLength(); 35754 const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength; 35755 35756 return curve.getPointAt( u, optionalTarget ); 35757 35758 } 35759 35760 i ++; 35761 35762 } 35763 35764 return null; 35765 35766 // loop where sum != 0, sum > d , sum+1 <d 35767 35768 } 35769 35770 // We cannot use the default THREE.Curve getPoint() with getLength() because in 35771 // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath 35772 // getPoint() depends on getLength 35773 35774 getLength() { 35775 35776 const lens = this.getCurveLengths(); 35777 return lens[ lens.length - 1 ]; 35778 35779 } 35780 35781 // cacheLengths must be recalculated. 35782 updateArcLengths() { 35783 35784 this.needsUpdate = true; 35785 this.cacheLengths = null; 35786 this.getCurveLengths(); 35787 35788 } 35789 35790 // Compute lengths and cache them 35791 // We cannot overwrite getLengths() because UtoT mapping uses it. 35792 35793 getCurveLengths() { 35794 35795 // We use cache values if curves and cache array are same length 35796 35797 if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) { 35798 35799 return this.cacheLengths; 35800 35801 } 35802 35803 // Get length of sub-curve 35804 // Push sums into cached array 35805 35806 const lengths = []; 35807 let sums = 0; 35808 35809 for ( let i = 0, l = this.curves.length; i < l; i ++ ) { 35810 35811 sums += this.curves[ i ].getLength(); 35812 lengths.push( sums ); 35813 35814 } 35815 35816 this.cacheLengths = lengths; 35817 35818 return lengths; 35819 35820 } 35821 35822 getSpacedPoints( divisions = 40 ) { 35823 35824 const points = []; 35825 35826 for ( let i = 0; i <= divisions; i ++ ) { 35827 35828 points.push( this.getPoint( i / divisions ) ); 35829 35830 } 35831 35832 if ( this.autoClose ) { 35833 35834 points.push( points[ 0 ] ); 35835 35836 } 35837 35838 return points; 35839 35840 } 35841 35842 getPoints( divisions = 12 ) { 35843 35844 const points = []; 35845 let last; 35846 35847 for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) { 35848 35849 const curve = curves[ i ]; 35850 const resolution = curve.isEllipseCurve ? divisions * 2 35851 : ( curve.isLineCurve || curve.isLineCurve3 ) ? 1 35852 : curve.isSplineCurve ? divisions * curve.points.length 35853 : divisions; 35854 35855 const pts = curve.getPoints( resolution ); 35856 35857 for ( let j = 0; j < pts.length; j ++ ) { 35858 35859 const point = pts[ j ]; 35860 35861 if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates 35862 35863 points.push( point ); 35864 last = point; 35865 35866 } 35867 35868 } 35869 35870 if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) { 35871 35872 points.push( points[ 0 ] ); 35873 35874 } 35875 35876 return points; 35877 35878 } 35879 35880 copy( source ) { 35881 35882 super.copy( source ); 35883 35884 this.curves = []; 35885 35886 for ( let i = 0, l = source.curves.length; i < l; i ++ ) { 35887 35888 const curve = source.curves[ i ]; 35889 35890 this.curves.push( curve.clone() ); 35891 35892 } 35893 35894 this.autoClose = source.autoClose; 35895 35896 return this; 35897 35898 } 35899 35900 toJSON() { 35901 35902 const data = super.toJSON(); 35903 35904 data.autoClose = this.autoClose; 35905 data.curves = []; 35906 35907 for ( let i = 0, l = this.curves.length; i < l; i ++ ) { 35908 35909 const curve = this.curves[ i ]; 35910 data.curves.push( curve.toJSON() ); 35911 35912 } 35913 35914 return data; 35915 35916 } 35917 35918 fromJSON( json ) { 35919 35920 super.fromJSON( json ); 35921 35922 this.autoClose = json.autoClose; 35923 this.curves = []; 35924 35925 for ( let i = 0, l = json.curves.length; i < l; i ++ ) { 35926 35927 const curve = json.curves[ i ]; 35928 this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) ); 35929 35930 } 35931 35932 return this; 35933 35934 } 35935 35936} 35937 35938class Path extends CurvePath { 35939 35940 constructor( points ) { 35941 35942 super(); 35943 35944 this.type = 'Path'; 35945 35946 this.currentPoint = new Vector2(); 35947 35948 if ( points ) { 35949 35950 this.setFromPoints( points ); 35951 35952 } 35953 35954 } 35955 35956 setFromPoints( points ) { 35957 35958 this.moveTo( points[ 0 ].x, points[ 0 ].y ); 35959 35960 for ( let i = 1, l = points.length; i < l; i ++ ) { 35961 35962 this.lineTo( points[ i ].x, points[ i ].y ); 35963 35964 } 35965 35966 return this; 35967 35968 } 35969 35970 moveTo( x, y ) { 35971 35972 this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying? 35973 35974 return this; 35975 35976 } 35977 35978 lineTo( x, y ) { 35979 35980 const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) ); 35981 this.curves.push( curve ); 35982 35983 this.currentPoint.set( x, y ); 35984 35985 return this; 35986 35987 } 35988 35989 quadraticCurveTo( aCPx, aCPy, aX, aY ) { 35990 35991 const curve = new QuadraticBezierCurve( 35992 this.currentPoint.clone(), 35993 new Vector2( aCPx, aCPy ), 35994 new Vector2( aX, aY ) 35995 ); 35996 35997 this.curves.push( curve ); 35998 35999 this.currentPoint.set( aX, aY ); 36000 36001 return this; 36002 36003 } 36004 36005 bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { 36006 36007 const curve = new CubicBezierCurve( 36008 this.currentPoint.clone(), 36009 new Vector2( aCP1x, aCP1y ), 36010 new Vector2( aCP2x, aCP2y ), 36011 new Vector2( aX, aY ) 36012 ); 36013 36014 this.curves.push( curve ); 36015 36016 this.currentPoint.set( aX, aY ); 36017 36018 return this; 36019 36020 } 36021 36022 splineThru( pts /*Array of Vector*/ ) { 36023 36024 const npts = [ this.currentPoint.clone() ].concat( pts ); 36025 36026 const curve = new SplineCurve( npts ); 36027 this.curves.push( curve ); 36028 36029 this.currentPoint.copy( pts[ pts.length - 1 ] ); 36030 36031 return this; 36032 36033 } 36034 36035 arc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 36036 36037 const x0 = this.currentPoint.x; 36038 const y0 = this.currentPoint.y; 36039 36040 this.absarc( aX + x0, aY + y0, aRadius, 36041 aStartAngle, aEndAngle, aClockwise ); 36042 36043 return this; 36044 36045 } 36046 36047 absarc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 36048 36049 this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); 36050 36051 return this; 36052 36053 } 36054 36055 ellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { 36056 36057 const x0 = this.currentPoint.x; 36058 const y0 = this.currentPoint.y; 36059 36060 this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); 36061 36062 return this; 36063 36064 } 36065 36066 absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { 36067 36068 const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); 36069 36070 if ( this.curves.length > 0 ) { 36071 36072 // if a previous curve is present, attempt to join 36073 const firstPoint = curve.getPoint( 0 ); 36074 36075 if ( ! firstPoint.equals( this.currentPoint ) ) { 36076 36077 this.lineTo( firstPoint.x, firstPoint.y ); 36078 36079 } 36080 36081 } 36082 36083 this.curves.push( curve ); 36084 36085 const lastPoint = curve.getPoint( 1 ); 36086 this.currentPoint.copy( lastPoint ); 36087 36088 return this; 36089 36090 } 36091 36092 copy( source ) { 36093 36094 super.copy( source ); 36095 36096 this.currentPoint.copy( source.currentPoint ); 36097 36098 return this; 36099 36100 } 36101 36102 toJSON() { 36103 36104 const data = super.toJSON(); 36105 36106 data.currentPoint = this.currentPoint.toArray(); 36107 36108 return data; 36109 36110 } 36111 36112 fromJSON( json ) { 36113 36114 super.fromJSON( json ); 36115 36116 this.currentPoint.fromArray( json.currentPoint ); 36117 36118 return this; 36119 36120 } 36121 36122} 36123 36124class LatheGeometry extends BufferGeometry { 36125 36126 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 ) { 36127 36128 super(); 36129 36130 this.type = 'LatheGeometry'; 36131 36132 this.parameters = { 36133 points: points, 36134 segments: segments, 36135 phiStart: phiStart, 36136 phiLength: phiLength 36137 }; 36138 36139 segments = Math.floor( segments ); 36140 36141 // clamp phiLength so it's in range of [ 0, 2PI ] 36142 36143 phiLength = clamp( phiLength, 0, Math.PI * 2 ); 36144 36145 // buffers 36146 36147 const indices = []; 36148 const vertices = []; 36149 const uvs = []; 36150 const initNormals = []; 36151 const normals = []; 36152 36153 // helper variables 36154 36155 const inverseSegments = 1.0 / segments; 36156 const vertex = new Vector3(); 36157 const uv = new Vector2(); 36158 const normal = new Vector3(); 36159 const curNormal = new Vector3(); 36160 const prevNormal = new Vector3(); 36161 let dx = 0; 36162 let dy = 0; 36163 36164 // pre-compute normals for initial "meridian" 36165 36166 for ( let j = 0; j <= ( points.length - 1 ); j ++ ) { 36167 36168 switch ( j ) { 36169 36170 case 0: // special handling for 1st vertex on path 36171 36172 dx = points[ j + 1 ].x - points[ j ].x; 36173 dy = points[ j + 1 ].y - points[ j ].y; 36174 36175 normal.x = dy * 1.0; 36176 normal.y = - dx; 36177 normal.z = dy * 0.0; 36178 36179 prevNormal.copy( normal ); 36180 36181 normal.normalize(); 36182 36183 initNormals.push( normal.x, normal.y, normal.z ); 36184 36185 break; 36186 36187 case ( points.length - 1 ): // special handling for last Vertex on path 36188 36189 initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z ); 36190 36191 break; 36192 36193 default: // default handling for all vertices in between 36194 36195 dx = points[ j + 1 ].x - points[ j ].x; 36196 dy = points[ j + 1 ].y - points[ j ].y; 36197 36198 normal.x = dy * 1.0; 36199 normal.y = - dx; 36200 normal.z = dy * 0.0; 36201 36202 curNormal.copy( normal ); 36203 36204 normal.x += prevNormal.x; 36205 normal.y += prevNormal.y; 36206 normal.z += prevNormal.z; 36207 36208 normal.normalize(); 36209 36210 initNormals.push( normal.x, normal.y, normal.z ); 36211 36212 prevNormal.copy( curNormal ); 36213 36214 } 36215 36216 } 36217 36218 // generate vertices, uvs and normals 36219 36220 for ( let i = 0; i <= segments; i ++ ) { 36221 36222 const phi = phiStart + i * inverseSegments * phiLength; 36223 36224 const sin = Math.sin( phi ); 36225 const cos = Math.cos( phi ); 36226 36227 for ( let j = 0; j <= ( points.length - 1 ); j ++ ) { 36228 36229 // vertex 36230 36231 vertex.x = points[ j ].x * sin; 36232 vertex.y = points[ j ].y; 36233 vertex.z = points[ j ].x * cos; 36234 36235 vertices.push( vertex.x, vertex.y, vertex.z ); 36236 36237 // uv 36238 36239 uv.x = i / segments; 36240 uv.y = j / ( points.length - 1 ); 36241 36242 uvs.push( uv.x, uv.y ); 36243 36244 // normal 36245 36246 const x = initNormals[ 3 * j + 0 ] * sin; 36247 const y = initNormals[ 3 * j + 1 ]; 36248 const z = initNormals[ 3 * j + 0 ] * cos; 36249 36250 normals.push( x, y, z ); 36251 36252 } 36253 36254 } 36255 36256 // indices 36257 36258 for ( let i = 0; i < segments; i ++ ) { 36259 36260 for ( let j = 0; j < ( points.length - 1 ); j ++ ) { 36261 36262 const base = j + i * points.length; 36263 36264 const a = base; 36265 const b = base + points.length; 36266 const c = base + points.length + 1; 36267 const d = base + 1; 36268 36269 // faces 36270 36271 indices.push( a, b, d ); 36272 indices.push( c, d, b ); 36273 36274 } 36275 36276 } 36277 36278 // build geometry 36279 36280 this.setIndex( indices ); 36281 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 36282 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 36283 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 36284 36285 } 36286 36287 copy( source ) { 36288 36289 super.copy( source ); 36290 36291 this.parameters = Object.assign( {}, source.parameters ); 36292 36293 return this; 36294 36295 } 36296 36297 static fromJSON( data ) { 36298 36299 return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength ); 36300 36301 } 36302 36303} 36304 36305class CapsuleGeometry extends LatheGeometry { 36306 36307 constructor( radius = 1, length = 1, capSegments = 4, radialSegments = 8 ) { 36308 36309 const path = new Path(); 36310 path.absarc( 0, - length / 2, radius, Math.PI * 1.5, 0 ); 36311 path.absarc( 0, length / 2, radius, 0, Math.PI * 0.5 ); 36312 36313 super( path.getPoints( capSegments ), radialSegments ); 36314 36315 this.type = 'CapsuleGeometry'; 36316 36317 this.parameters = { 36318 radius: radius, 36319 length: length, 36320 capSegments: capSegments, 36321 radialSegments: radialSegments, 36322 }; 36323 36324 } 36325 36326 static fromJSON( data ) { 36327 36328 return new CapsuleGeometry( data.radius, data.length, data.capSegments, data.radialSegments ); 36329 36330 } 36331 36332} 36333 36334class CircleGeometry extends BufferGeometry { 36335 36336 constructor( radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2 ) { 36337 36338 super(); 36339 36340 this.type = 'CircleGeometry'; 36341 36342 this.parameters = { 36343 radius: radius, 36344 segments: segments, 36345 thetaStart: thetaStart, 36346 thetaLength: thetaLength 36347 }; 36348 36349 segments = Math.max( 3, segments ); 36350 36351 // buffers 36352 36353 const indices = []; 36354 const vertices = []; 36355 const normals = []; 36356 const uvs = []; 36357 36358 // helper variables 36359 36360 const vertex = new Vector3(); 36361 const uv = new Vector2(); 36362 36363 // center point 36364 36365 vertices.push( 0, 0, 0 ); 36366 normals.push( 0, 0, 1 ); 36367 uvs.push( 0.5, 0.5 ); 36368 36369 for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) { 36370 36371 const segment = thetaStart + s / segments * thetaLength; 36372 36373 // vertex 36374 36375 vertex.x = radius * Math.cos( segment ); 36376 vertex.y = radius * Math.sin( segment ); 36377 36378 vertices.push( vertex.x, vertex.y, vertex.z ); 36379 36380 // normal 36381 36382 normals.push( 0, 0, 1 ); 36383 36384 // uvs 36385 36386 uv.x = ( vertices[ i ] / radius + 1 ) / 2; 36387 uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2; 36388 36389 uvs.push( uv.x, uv.y ); 36390 36391 } 36392 36393 // indices 36394 36395 for ( let i = 1; i <= segments; i ++ ) { 36396 36397 indices.push( i, i + 1, 0 ); 36398 36399 } 36400 36401 // build geometry 36402 36403 this.setIndex( indices ); 36404 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,756 bytes, lines 36405-36630
36405 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 36406 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 36407 36408 } 36409 36410 copy( source ) { 36411 36412 super.copy( source ); 36413 36414 this.parameters = Object.assign( {}, source.parameters ); 36415 36416 return this; 36417 36418 } 36419 36420 static fromJSON( data ) { 36421 36422 return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength ); 36423 36424 } 36425 36426} 36427 36428class CylinderGeometry extends BufferGeometry { 36429 36430 constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { 36431 36432 super(); 36433 36434 this.type = 'CylinderGeometry'; 36435 36436 this.parameters = { 36437 radiusTop: radiusTop, 36438 radiusBottom: radiusBottom, 36439 height: height, 36440 radialSegments: radialSegments, 36441 heightSegments: heightSegments, 36442 openEnded: openEnded, 36443 thetaStart: thetaStart, 36444 thetaLength: thetaLength 36445 }; 36446 36447 const scope = this; 36448 36449 radialSegments = Math.floor( radialSegments ); 36450 heightSegments = Math.floor( heightSegments ); 36451 36452 // buffers 36453 36454 const indices = []; 36455 const vertices = []; 36456 const normals = []; 36457 const uvs = []; 36458 36459 // helper variables 36460 36461 let index = 0; 36462 const indexArray = []; 36463 const halfHeight = height / 2; 36464 let groupStart = 0; 36465 36466 // generate geometry 36467 36468 generateTorso(); 36469 36470 if ( openEnded === false ) { 36471 36472 if ( radiusTop > 0 ) generateCap( true ); 36473 if ( radiusBottom > 0 ) generateCap( false ); 36474 36475 } 36476 36477 // build geometry 36478 36479 this.setIndex( indices ); 36480 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 36481 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 36482 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 36483 36484 function generateTorso() { 36485 36486 const normal = new Vector3(); 36487 const vertex = new Vector3(); 36488 36489 let groupCount = 0; 36490 36491 // this will be used to calculate the normal 36492 const slope = ( radiusBottom - radiusTop ) / height; 36493 36494 // generate vertices, normals and uvs 36495 36496 for ( let y = 0; y <= heightSegments; y ++ ) { 36497 36498 const indexRow = []; 36499 36500 const v = y / heightSegments; 36501 36502 // calculate the radius of the current row 36503 36504 const radius = v * ( radiusBottom - radiusTop ) + radiusTop; 36505 36506 for ( let x = 0; x <= radialSegments; x ++ ) { 36507 36508 const u = x / radialSegments; 36509 36510 const theta = u * thetaLength + thetaStart; 36511 36512 const sinTheta = Math.sin( theta ); 36513 const cosTheta = Math.cos( theta ); 36514 36515 // vertex 36516 36517 vertex.x = radius * sinTheta; 36518 vertex.y = - v * height + halfHeight; 36519 vertex.z = radius * cosTheta; 36520 vertices.push( vertex.x, vertex.y, vertex.z ); 36521 36522 // normal 36523 36524 normal.set( sinTheta, slope, cosTheta ).normalize(); 36525 normals.push( normal.x, normal.y, normal.z ); 36526 36527 // uv 36528 36529 uvs.push( u, 1 - v ); 36530 36531 // save index of vertex in respective row 36532 36533 indexRow.push( index ++ ); 36534 36535 } 36536 36537 // now save vertices of the row in our index array 36538 36539 indexArray.push( indexRow ); 36540 36541 } 36542 36543 // generate indices 36544 36545 for ( let x = 0; x < radialSegments; x ++ ) { 36546 36547 for ( let y = 0; y < heightSegments; y ++ ) { 36548 36549 // we use the index array to access the correct indices 36550 36551 const a = indexArray[ y ][ x ]; 36552 const b = indexArray[ y + 1 ][ x ]; 36553 const c = indexArray[ y + 1 ][ x + 1 ]; 36554 const d = indexArray[ y ][ x + 1 ]; 36555 36556 // faces 36557 36558 indices.push( a, b, d ); 36559 indices.push( b, c, d ); 36560 36561 // update group counter 36562 36563 groupCount += 6; 36564 36565 } 36566 36567 } 36568 36569 // add a group to the geometry. this will ensure multi material support 36570 36571 scope.addGroup( groupStart, groupCount, 0 ); 36572 36573 // calculate new start value for groups 36574 36575 groupStart += groupCount; 36576 36577 } 36578 36579 function generateCap( top ) { 36580 36581 // save the index of the first center vertex 36582 const centerIndexStart = index; 36583 36584 const uv = new Vector2(); 36585 const vertex = new Vector3(); 36586 36587 let groupCount = 0; 36588 36589 const radius = ( top === true ) ? radiusTop : radiusBottom; 36590 const sign = ( top === true ) ? 1 : - 1; 36591 36592 // first we generate the center vertex data of the cap. 36593 // because the geometry needs one set of uvs per face, 36594 // we must generate a center vertex per face/segment 36595 36596 for ( let x = 1; x <= radialSegments; x ++ ) { 36597 36598 // vertex 36599 36600 vertices.push( 0, halfHeight * sign, 0 ); 36601 36602 // normal 36603 36604 normals.push( 0, sign, 0 ); 36605 36606 // uv 36607 36608 uvs.push( 0.5, 0.5 ); 36609 36610 // increase index 36611 36612 index ++; 36613 36614 } 36615 36616 // save the index of the last center vertex 36617 const centerIndexEnd = index; 36618 36619 // now we generate the surrounding vertices, normals and uvs 36620 36621 for ( let x = 0; x <= radialSegments; x ++ ) { 36622 36623 const u = x / radialSegments; 36624 const theta = u * thetaLength + thetaStart; 36625 36626 const cosTheta = Math.cos( theta ); 36627 const sinTheta = Math.sin( theta ); 36628 36629 // vertex 36630
vendor: 16,069 bytes, lines 36631-37409
36631 vertex.x = radius * sinTheta; 36632 vertex.y = halfHeight * sign; 36633 vertex.z = radius * cosTheta; 36634 vertices.push( vertex.x, vertex.y, vertex.z ); 36635 36636 // normal 36637 36638 normals.push( 0, sign, 0 ); 36639 36640 // uv 36641 36642 uv.x = ( cosTheta * 0.5 ) + 0.5; 36643 uv.y = ( sinTheta * 0.5 * sign ) + 0.5; 36644 uvs.push( uv.x, uv.y ); 36645 36646 // increase index 36647 36648 index ++; 36649 36650 } 36651 36652 // generate indices 36653 36654 for ( let x = 0; x < radialSegments; x ++ ) { 36655 36656 const c = centerIndexStart + x; 36657 const i = centerIndexEnd + x; 36658 36659 if ( top === true ) { 36660 36661 // face top 36662 36663 indices.push( i, i + 1, c ); 36664 36665 } else { 36666 36667 // face bottom 36668 36669 indices.push( i + 1, i, c ); 36670 36671 } 36672 36673 groupCount += 3; 36674 36675 } 36676 36677 // add a group to the geometry. this will ensure multi material support 36678 36679 scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); 36680 36681 // calculate new start value for groups 36682 36683 groupStart += groupCount; 36684 36685 } 36686 36687 } 36688 36689 copy( source ) { 36690 36691 super.copy( source ); 36692 36693 this.parameters = Object.assign( {}, source.parameters ); 36694 36695 return this; 36696 36697 } 36698 36699 static fromJSON( data ) { 36700 36701 return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); 36702 36703 } 36704 36705} 36706 36707class ConeGeometry extends CylinderGeometry { 36708 36709 constructor( radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { 36710 36711 super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); 36712 36713 this.type = 'ConeGeometry'; 36714 36715 this.parameters = { 36716 radius: radius, 36717 height: height, 36718 radialSegments: radialSegments, 36719 heightSegments: heightSegments, 36720 openEnded: openEnded, 36721 thetaStart: thetaStart, 36722 thetaLength: thetaLength 36723 }; 36724 36725 } 36726 36727 static fromJSON( data ) { 36728 36729 return new ConeGeometry( data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); 36730 36731 } 36732 36733} 36734 36735class PolyhedronGeometry extends BufferGeometry { 36736 36737 constructor( vertices = [], indices = [], radius = 1, detail = 0 ) { 36738 36739 super(); 36740 36741 this.type = 'PolyhedronGeometry'; 36742 36743 this.parameters = { 36744 vertices: vertices, 36745 indices: indices, 36746 radius: radius, 36747 detail: detail 36748 }; 36749 36750 // default buffer data 36751 36752 const vertexBuffer = []; 36753 const uvBuffer = []; 36754 36755 // the subdivision creates the vertex buffer data 36756 36757 subdivide( detail ); 36758 36759 // all vertices should lie on a conceptual sphere with a given radius 36760 36761 applyRadius( radius ); 36762 36763 // finally, create the uv data 36764 36765 generateUVs(); 36766 36767 // build non-indexed geometry 36768 36769 this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) ); 36770 this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) ); 36771 this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) ); 36772 36773 if ( detail === 0 ) { 36774 36775 this.computeVertexNormals(); // flat normals 36776 36777 } else { 36778 36779 this.normalizeNormals(); // smooth normals 36780 36781 } 36782 36783 // helper functions 36784 36785 function subdivide( detail ) { 36786 36787 const a = new Vector3(); 36788 const b = new Vector3(); 36789 const c = new Vector3(); 36790 36791 // iterate over all faces and apply a subdivision with the given detail value 36792 36793 for ( let i = 0; i < indices.length; i += 3 ) { 36794 36795 // get the vertices of the face 36796 36797 getVertexByIndex( indices[ i + 0 ], a ); 36798 getVertexByIndex( indices[ i + 1 ], b ); 36799 getVertexByIndex( indices[ i + 2 ], c ); 36800 36801 // perform subdivision 36802 36803 subdivideFace( a, b, c, detail ); 36804 36805 } 36806 36807 } 36808 36809 function subdivideFace( a, b, c, detail ) { 36810 36811 const cols = detail + 1; 36812 36813 // we use this multidimensional array as a data structure for creating the subdivision 36814 36815 const v = []; 36816 36817 // construct all of the vertices for this subdivision 36818 36819 for ( let i = 0; i <= cols; i ++ ) { 36820 36821 v[ i ] = []; 36822 36823 const aj = a.clone().lerp( c, i / cols ); 36824 const bj = b.clone().lerp( c, i / cols ); 36825 36826 const rows = cols - i; 36827 36828 for ( let j = 0; j <= rows; j ++ ) { 36829 36830 if ( j === 0 && i === cols ) { 36831 36832 v[ i ][ j ] = aj; 36833 36834 } else { 36835 36836 v[ i ][ j ] = aj.clone().lerp( bj, j / rows ); 36837 36838 } 36839 36840 } 36841 36842 } 36843 36844 // construct all of the faces 36845 36846 for ( let i = 0; i < cols; i ++ ) { 36847 36848 for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) { 36849 36850 const k = Math.floor( j / 2 ); 36851 36852 if ( j % 2 === 0 ) { 36853 36854 pushVertex( v[ i ][ k + 1 ] ); 36855 pushVertex( v[ i + 1 ][ k ] ); 36856 pushVertex( v[ i ][ k ] ); 36857 36858 } else { 36859 36860 pushVertex( v[ i ][ k + 1 ] ); 36861 pushVertex( v[ i + 1 ][ k + 1 ] ); 36862 pushVertex( v[ i + 1 ][ k ] ); 36863 36864 } 36865 36866 } 36867 36868 } 36869 36870 } 36871 36872 function applyRadius( radius ) { 36873 36874 const vertex = new Vector3(); 36875 36876 // iterate over the entire buffer and apply the radius to each vertex 36877 36878 for ( let i = 0; i < vertexBuffer.length; i += 3 ) { 36879 36880 vertex.x = vertexBuffer[ i + 0 ]; 36881 vertex.y = vertexBuffer[ i + 1 ]; 36882 vertex.z = vertexBuffer[ i + 2 ]; 36883 36884 vertex.normalize().multiplyScalar( radius ); 36885 36886 vertexBuffer[ i + 0 ] = vertex.x; 36887 vertexBuffer[ i + 1 ] = vertex.y; 36888 vertexBuffer[ i + 2 ] = vertex.z; 36889 36890 } 36891 36892 } 36893 36894 function generateUVs() { 36895 36896 const vertex = new Vector3(); 36897 36898 for ( let i = 0; i < vertexBuffer.length; i += 3 ) { 36899 36900 vertex.x = vertexBuffer[ i + 0 ]; 36901 vertex.y = vertexBuffer[ i + 1 ]; 36902 vertex.z = vertexBuffer[ i + 2 ]; 36903 36904 const u = azimuth( vertex ) / 2 / Math.PI + 0.5; 36905 const v = inclination( vertex ) / Math.PI + 0.5; 36906 uvBuffer.push( u, 1 - v ); 36907 36908 } 36909 36910 correctUVs(); 36911 36912 correctSeam(); 36913 36914 } 36915 36916 function correctSeam() { 36917 36918 // handle case when face straddles the seam, see #3269 36919 36920 for ( let i = 0; i < uvBuffer.length; i += 6 ) { 36921 36922 // uv data of a single face 36923 36924 const x0 = uvBuffer[ i + 0 ]; 36925 const x1 = uvBuffer[ i + 2 ]; 36926 const x2 = uvBuffer[ i + 4 ]; 36927 36928 const max = Math.max( x0, x1, x2 ); 36929 const min = Math.min( x0, x1, x2 ); 36930 36931 // 0.9 is somewhat arbitrary 36932 36933 if ( max > 0.9 && min < 0.1 ) { 36934 36935 if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1; 36936 if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1; 36937 if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1; 36938 36939 } 36940 36941 } 36942 36943 } 36944 36945 function pushVertex( vertex ) { 36946 36947 vertexBuffer.push( vertex.x, vertex.y, vertex.z ); 36948 36949 } 36950 36951 function getVertexByIndex( index, vertex ) { 36952 36953 const stride = index * 3; 36954 36955 vertex.x = vertices[ stride + 0 ]; 36956 vertex.y = vertices[ stride + 1 ]; 36957 vertex.z = vertices[ stride + 2 ]; 36958 36959 } 36960 36961 function correctUVs() { 36962 36963 const a = new Vector3(); 36964 const b = new Vector3(); 36965 const c = new Vector3(); 36966 36967 const centroid = new Vector3(); 36968 36969 const uvA = new Vector2(); 36970 const uvB = new Vector2(); 36971 const uvC = new Vector2(); 36972 36973 for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) { 36974 36975 a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] ); 36976 b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] ); 36977 c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] ); 36978 36979 uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] ); 36980 uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] ); 36981 uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] ); 36982 36983 centroid.copy( a ).add( b ).add( c ).divideScalar( 3 ); 36984 36985 const azi = azimuth( centroid ); 36986 36987 correctUV( uvA, j + 0, a, azi ); 36988 correctUV( uvB, j + 2, b, azi ); 36989 correctUV( uvC, j + 4, c, azi ); 36990 36991 } 36992 36993 } 36994 36995 function correctUV( uv, stride, vector, azimuth ) { 36996 36997 if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) { 36998 36999 uvBuffer[ stride ] = uv.x - 1; 37000 37001 } 37002 37003 if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) { 37004 37005 uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5; 37006 37007 } 37008 37009 } 37010 37011 // Angle around the Y axis, counter-clockwise when looking from above. 37012 37013 function azimuth( vector ) { 37014 37015 return Math.atan2( vector.z, - vector.x ); 37016 37017 } 37018 37019 37020 // Angle above the XZ plane. 37021 37022 function inclination( vector ) { 37023 37024 return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) ); 37025 37026 } 37027 37028 } 37029 37030 copy( source ) { 37031 37032 super.copy( source ); 37033 37034 this.parameters = Object.assign( {}, source.parameters ); 37035 37036 return this; 37037 37038 } 37039 37040 static fromJSON( data ) { 37041 37042 return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details ); 37043 37044 } 37045 37046} 37047 37048class DodecahedronGeometry extends PolyhedronGeometry { 37049 37050 constructor( radius = 1, detail = 0 ) { 37051 37052 const t = ( 1 + Math.sqrt( 5 ) ) / 2; 37053 const r = 1 / t; 37054 37055 const vertices = [ 37056 37057 // (±1, ±1, ±1) 37058 - 1, - 1, - 1, - 1, - 1, 1, 37059 - 1, 1, - 1, - 1, 1, 1, 37060 1, - 1, - 1, 1, - 1, 1, 37061 1, 1, - 1, 1, 1, 1, 37062 37063 // (0, ±1/Ï, ±Ï) 37064 0, - r, - t, 0, - r, t, 37065 0, r, - t, 0, r, t, 37066 37067 // (±1/Ï, ±Ï, 0) 37068 - r, - t, 0, - r, t, 0, 37069 r, - t, 0, r, t, 0, 37070 37071 // (±Ï, 0, ±1/Ï) 37072 - t, 0, - r, t, 0, - r, 37073 - t, 0, r, t, 0, r 37074 ]; 37075 37076 const indices = [ 37077 3, 11, 7, 3, 7, 15, 3, 15, 13, 37078 7, 19, 17, 7, 17, 6, 7, 6, 15, 37079 17, 4, 8, 17, 8, 10, 17, 10, 6, 37080 8, 0, 16, 8, 16, 2, 8, 2, 10, 37081 0, 12, 1, 0, 1, 18, 0, 18, 16, 37082 6, 10, 2, 6, 2, 13, 6, 13, 15, 37083 2, 16, 18, 2, 18, 3, 2, 3, 13, 37084 18, 1, 9, 18, 9, 11, 18, 11, 3, 37085 4, 14, 12, 4, 12, 0, 4, 0, 8, 37086 11, 9, 5, 11, 5, 19, 11, 19, 7, 37087 19, 5, 14, 19, 14, 4, 19, 4, 17, 37088 1, 12, 14, 1, 14, 5, 1, 5, 9 37089 ]; 37090 37091 super( vertices, indices, radius, detail ); 37092 37093 this.type = 'DodecahedronGeometry'; 37094 37095 this.parameters = { 37096 radius: radius, 37097 detail: detail 37098 }; 37099 37100 } 37101 37102 static fromJSON( data ) { 37103 37104 return new DodecahedronGeometry( data.radius, data.detail ); 37105 37106 } 37107 37108} 37109 37110const _v0 = /*@__PURE__*/ new Vector3(); 37111const _v1$1 = /*@__PURE__*/ new Vector3(); 37112const _normal = /*@__PURE__*/ new Vector3(); 37113const _triangle = /*@__PURE__*/ new Triangle(); 37114 37115class EdgesGeometry extends BufferGeometry { 37116 37117 constructor( geometry = null, thresholdAngle = 1 ) { 37118 37119 super(); 37120 37121 this.type = 'EdgesGeometry'; 37122 37123 this.parameters = { 37124 geometry: geometry, 37125 thresholdAngle: thresholdAngle 37126 }; 37127 37128 if ( geometry !== null ) { 37129 37130 const precisionPoints = 4; 37131 const precision = Math.pow( 10, precisionPoints ); 37132 const thresholdDot = Math.cos( DEG2RAD * thresholdAngle ); 37133 37134 const indexAttr = geometry.getIndex(); 37135 const positionAttr = geometry.getAttribute( 'position' ); 37136 const indexCount = indexAttr ? indexAttr.count : positionAttr.count; 37137 37138 const indexArr = [ 0, 0, 0 ]; 37139 const vertKeys = [ 'a', 'b', 'c' ]; 37140 const hashes = new Array( 3 ); 37141 37142 const edgeData = {}; 37143 const vertices = []; 37144 for ( let i = 0; i < indexCount; i += 3 ) { 37145 37146 if ( indexAttr ) { 37147 37148 indexArr[ 0 ] = indexAttr.getX( i ); 37149 indexArr[ 1 ] = indexAttr.getX( i + 1 ); 37150 indexArr[ 2 ] = indexAttr.getX( i + 2 ); 37151 37152 } else { 37153 37154 indexArr[ 0 ] = i; 37155 indexArr[ 1 ] = i + 1; 37156 indexArr[ 2 ] = i + 2; 37157 37158 } 37159 37160 const { a, b, c } = _triangle; 37161 a.fromBufferAttribute( positionAttr, indexArr[ 0 ] ); 37162 b.fromBufferAttribute( positionAttr, indexArr[ 1 ] ); 37163 c.fromBufferAttribute( positionAttr, indexArr[ 2 ] ); 37164 _triangle.getNormal( _normal ); 37165 37166 // create hashes for the edge from the vertices 37167 hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`; 37168 hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`; 37169 hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`; 37170 37171 // skip degenerate triangles 37172 if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) { 37173 37174 continue; 37175 37176 } 37177 37178 // iterate over every edge 37179 for ( let j = 0; j < 3; j ++ ) { 37180 37181 // get the first and next vertex making up the edge 37182 const jNext = ( j + 1 ) % 3; 37183 const vecHash0 = hashes[ j ]; 37184 const vecHash1 = hashes[ jNext ]; 37185 const v0 = _triangle[ vertKeys[ j ] ]; 37186 const v1 = _triangle[ vertKeys[ jNext ] ]; 37187 37188 const hash = `${ vecHash0 }_${ vecHash1 }`; 37189 const reverseHash = `${ vecHash1 }_${ vecHash0 }`; 37190 37191 if ( reverseHash in edgeData && edgeData[ reverseHash ] ) { 37192 37193 // if we found a sibling edge add it into the vertex array if 37194 // it meets the angle threshold and delete the edge from the map. 37195 if ( _normal.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) { 37196 37197 vertices.push( v0.x, v0.y, v0.z ); 37198 vertices.push( v1.x, v1.y, v1.z ); 37199 37200 } 37201 37202 edgeData[ reverseHash ] = null; 37203 37204 } else if ( ! ( hash in edgeData ) ) { 37205 37206 // if we've already got an edge here then skip adding a new one 37207 edgeData[ hash ] = { 37208 37209 index0: indexArr[ j ], 37210 index1: indexArr[ jNext ], 37211 normal: _normal.clone(), 37212 37213 }; 37214 37215 } 37216 37217 } 37218 37219 } 37220 37221 // iterate over all remaining, unmatched edges and add them to the vertex array 37222 for ( const key in edgeData ) { 37223 37224 if ( edgeData[ key ] ) { 37225 37226 const { index0, index1 } = edgeData[ key ]; 37227 _v0.fromBufferAttribute( positionAttr, index0 ); 37228 _v1$1.fromBufferAttribute( positionAttr, index1 ); 37229 37230 vertices.push( _v0.x, _v0.y, _v0.z ); 37231 vertices.push( _v1$1.x, _v1$1.y, _v1$1.z ); 37232 37233 } 37234 37235 } 37236 37237 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 37238 37239 } 37240 37241 } 37242 37243 copy( source ) { 37244 37245 super.copy( source ); 37246 37247 this.parameters = Object.assign( {}, source.parameters ); 37248 37249 return this; 37250 37251 } 37252 37253} 37254 37255class Shape extends Path { 37256 37257 constructor( points ) { 37258 37259 super( points ); 37260 37261 this.uuid = generateUUID(); 37262 37263 this.type = 'Shape'; 37264 37265 this.holes = []; 37266 37267 } 37268 37269 getPointsHoles( divisions ) { 37270 37271 const holesPts = []; 37272 37273 for ( let i = 0, l = this.holes.length; i < l; i ++ ) { 37274 37275 holesPts[ i ] = this.holes[ i ].getPoints( divisions ); 37276 37277 } 37278 37279 return holesPts; 37280 37281 } 37282 37283 // get points of shape and holes (keypoints based on segments parameter) 37284 37285 extractPoints( divisions ) { 37286 37287 return { 37288 37289 shape: this.getPoints( divisions ), 37290 holes: this.getPointsHoles( divisions ) 37291 37292 }; 37293 37294 } 37295 37296 copy( source ) { 37297 37298 super.copy( source ); 37299 37300 this.holes = []; 37301 37302 for ( let i = 0, l = source.holes.length; i < l; i ++ ) { 37303 37304 const hole = source.holes[ i ]; 37305 37306 this.holes.push( hole.clone() ); 37307 37308 } 37309 37310 return this; 37311 37312 } 37313 37314 toJSON() { 37315 37316 const data = super.toJSON(); 37317 37318 data.uuid = this.uuid; 37319 data.holes = []; 37320 37321 for ( let i = 0, l = this.holes.length; i < l; i ++ ) { 37322 37323 const hole = this.holes[ i ]; 37324 data.holes.push( hole.toJSON() ); 37325 37326 } 37327 37328 return data; 37329 37330 } 37331 37332 fromJSON( json ) { 37333 37334 super.fromJSON( json ); 37335 37336 this.uuid = json.uuid; 37337 this.holes = []; 37338 37339 for ( let i = 0, l = json.holes.length; i < l; i ++ ) { 37340 37341 const hole = json.holes[ i ]; 37342 this.holes.push( new Path().fromJSON( hole ) ); 37343 37344 } 37345 37346 return this; 37347 37348 } 37349 37350} 37351 37352/** 37353 * Port from https://github.com/mapbox/earcut (v2.2.4) 37354 */ 37355 37356const Earcut = { 37357 37358 triangulate: function ( data, holeIndices, dim = 2 ) { 37359 37360 const hasHoles = holeIndices && holeIndices.length; 37361 const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length; 37362 let outerNode = linkedList( data, 0, outerLen, dim, true ); 37363 const triangles = []; 37364 37365 if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles; 37366 37367 let minX, minY, maxX, maxY, x, y, invSize; 37368 37369 if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim ); 37370 37371 // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox 37372 if ( data.length > 80 * dim ) { 37373 37374 minX = maxX = data[ 0 ]; 37375 minY = maxY = data[ 1 ]; 37376 37377 for ( let i = dim; i < outerLen; i += dim ) { 37378 37379 x = data[ i ]; 37380 y = data[ i + 1 ]; 37381 if ( x < minX ) minX = x; 37382 if ( y < minY ) minY = y; 37383 if ( x > maxX ) maxX = x; 37384 if ( y > maxY ) maxY = y; 37385 37386 } 37387 37388 // minX, minY and invSize are later used to transform coords into integers for z-order calculation 37389 invSize = Math.max( maxX - minX, maxY - minY ); 37390 invSize = invSize !== 0 ? 32767 / invSize : 0; 37391 37392 } 37393 37394 earcutLinked( outerNode, triangles, dim, minX, minY, invSize, 0 ); 37395 37396 return triangles; 37397 37398 } 37399 37400}; 37401 37402// create a circular doubly linked list from polygon points in the specified winding order 37403function linkedList( data, start, end, dim, clockwise ) { 37404 37405 let i, last; 37406 37407 if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) { 37408 37409 for ( i = start; i < end;
vendor: 10,405 bytes, lines 37409-37882
37409 i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); 37410 37411 } else { 37412 37413 for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); 37414 37415 } 37416 37417 if ( last && equals( last, last.next ) ) { 37418 37419 removeNode( last ); 37420 last = last.next; 37421 37422 } 37423 37424 return last; 37425 37426} 37427 37428// eliminate colinear or duplicate points 37429function filterPoints( start, end ) { 37430 37431 if ( ! start ) return start; 37432 if ( ! end ) end = start; 37433 37434 let p = start, 37435 again; 37436 do { 37437 37438 again = false; 37439 37440 if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) { 37441 37442 removeNode( p ); 37443 p = end = p.prev; 37444 if ( p === p.next ) break; 37445 again = true; 37446 37447 } else { 37448 37449 p = p.next; 37450 37451 } 37452 37453 } while ( again || p !== end ); 37454 37455 return end; 37456 37457} 37458 37459// main ear slicing loop which triangulates a polygon (given as a linked list) 37460function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) { 37461 37462 if ( ! ear ) return; 37463 37464 // interlink polygon nodes in z-order 37465 if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize ); 37466 37467 let stop = ear, 37468 prev, next; 37469 37470 // iterate through ears, slicing them one by one 37471 while ( ear.prev !== ear.next ) { 37472 37473 prev = ear.prev; 37474 next = ear.next; 37475 37476 if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) { 37477 37478 // cut off the triangle 37479 triangles.push( prev.i / dim | 0 ); 37480 triangles.push( ear.i / dim | 0 ); 37481 triangles.push( next.i / dim | 0 ); 37482 37483 removeNode( ear ); 37484 37485 // skipping the next vertex leads to less sliver triangles 37486 ear = next.next; 37487 stop = next.next; 37488 37489 continue; 37490 37491 } 37492 37493 ear = next; 37494 37495 // if we looped through the whole remaining polygon and can't find any more ears 37496 if ( ear === stop ) { 37497 37498 // try filtering points and slicing again 37499 if ( ! pass ) { 37500 37501 earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 ); 37502 37503 // if this didn't work, try curing all small self-intersections locally 37504 37505 } else if ( pass === 1 ) { 37506 37507 ear = cureLocalIntersections( filterPoints( ear ), triangles, dim ); 37508 earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 ); 37509 37510 // as a last resort, try splitting the remaining polygon into two 37511 37512 } else if ( pass === 2 ) { 37513 37514 splitEarcut( ear, triangles, dim, minX, minY, invSize ); 37515 37516 } 37517 37518 break; 37519 37520 } 37521 37522 } 37523 37524} 37525 37526// check whether a polygon node forms a valid ear with adjacent nodes 37527function isEar( ear ) { 37528 37529 const a = ear.prev, 37530 b = ear, 37531 c = ear.next; 37532 37533 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear 37534 37535 // now make sure we don't have other points inside the potential ear 37536 const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; 37537 37538 // triangle bbox; min & max are calculated like this for speed 37539 const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ), 37540 y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ), 37541 x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ), 37542 y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy ); 37543 37544 let p = c.next; 37545 while ( p !== a ) { 37546 37547 if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && 37548 pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && 37549 area( p.prev, p, p.next ) >= 0 ) return false; 37550 p = p.next; 37551 37552 } 37553 37554 return true; 37555 37556} 37557 37558function isEarHashed( ear, minX, minY, invSize ) { 37559 37560 const a = ear.prev, 37561 b = ear, 37562 c = ear.next; 37563 37564 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear 37565 37566 const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; 37567 37568 // triangle bbox; min & max are calculated like this for speed 37569 const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ), 37570 y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ), 37571 x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ), 37572 y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy ); 37573 37574 // z-order range for the current triangle bbox; 37575 const minZ = zOrder( x0, y0, minX, minY, invSize ), 37576 maxZ = zOrder( x1, y1, minX, minY, invSize ); 37577 37578 let p = ear.prevZ, 37579 n = ear.nextZ; 37580 37581 // look for points inside the triangle in both directions 37582 while ( p && p.z >= minZ && n && n.z <= maxZ ) { 37583 37584 if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && 37585 pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false; 37586 p = p.prevZ; 37587 37588 if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && 37589 pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false; 37590 n = n.nextZ; 37591 37592 } 37593 37594 // look for remaining points in decreasing z-order 37595 while ( p && p.z >= minZ ) { 37596 37597 if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && 37598 pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false; 37599 p = p.prevZ; 37600 37601 } 37602 37603 // look for remaining points in increasing z-order 37604 while ( n && n.z <= maxZ ) { 37605 37606 if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && 37607 pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false; 37608 n = n.nextZ; 37609 37610 } 37611 37612 return true; 37613 37614} 37615 37616// go through all polygon nodes and cure small local self-intersections 37617function cureLocalIntersections( start, triangles, dim ) { 37618 37619 let p = start; 37620 do { 37621 37622 const a = p.prev, 37623 b = p.next.next; 37624 37625 if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) { 37626 37627 triangles.push( a.i / dim | 0 ); 37628 triangles.push( p.i / dim | 0 ); 37629 triangles.push( b.i / dim | 0 ); 37630 37631 // remove two nodes involved 37632 removeNode( p ); 37633 removeNode( p.next ); 37634 37635 p = start = b; 37636 37637 } 37638 37639 p = p.next; 37640 37641 } while ( p !== start ); 37642 37643 return filterPoints( p ); 37644 37645} 37646 37647// try splitting polygon into two and triangulate them independently 37648function splitEarcut( start, triangles, dim, minX, minY, invSize ) { 37649 37650 // look for a valid diagonal that divides the polygon into two 37651 let a = start; 37652 do { 37653 37654 let b = a.next.next; 37655 while ( b !== a.prev ) { 37656 37657 if ( a.i !== b.i && isValidDiagonal( a, b ) ) { 37658 37659 // split the polygon in two by the diagonal 37660 let c = splitPolygon( a, b ); 37661 37662 // filter colinear points around the cuts 37663 a = filterPoints( a, a.next ); 37664 c = filterPoints( c, c.next ); 37665 37666 // run earcut on each half 37667 earcutLinked( a, triangles, dim, minX, minY, invSize, 0 ); 37668 earcutLinked( c, triangles, dim, minX, minY, invSize, 0 ); 37669 return; 37670 37671 } 37672 37673 b = b.next; 37674 37675 } 37676 37677 a = a.next; 37678 37679 } while ( a !== start ); 37680 37681} 37682 37683// link every hole into the outer loop, producing a single-ring polygon without holes 37684function eliminateHoles( data, holeIndices, outerNode, dim ) { 37685 37686 const queue = []; 37687 let i, len, start, end, list; 37688 37689 for ( i = 0, len = holeIndices.length; i < len; i ++ ) { 37690 37691 start = holeIndices[ i ] * dim; 37692 end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length; 37693 list = linkedList( data, start, end, dim, false ); 37694 if ( list === list.next ) list.steiner = true; 37695 queue.push( getLeftmost( list ) ); 37696 37697 } 37698 37699 queue.sort( compareX ); 37700 37701 // process holes from left to right 37702 for ( i = 0; i < queue.length; i ++ ) { 37703 37704 outerNode = eliminateHole( queue[ i ], outerNode ); 37705 37706 } 37707 37708 return outerNode; 37709 37710} 37711 37712function compareX( a, b ) { 37713 37714 return a.x - b.x; 37715 37716} 37717 37718// find a bridge between vertices that connects hole with an outer ring and link it 37719function eliminateHole( hole, outerNode ) { 37720 37721 const bridge = findHoleBridge( hole, outerNode ); 37722 if ( ! bridge ) { 37723 37724 return outerNode; 37725 37726 } 37727 37728 const bridgeReverse = splitPolygon( bridge, hole ); 37729 37730 // filter collinear points around the cuts 37731 filterPoints( bridgeReverse, bridgeReverse.next ); 37732 return filterPoints( bridge, bridge.next ); 37733 37734} 37735 37736// David Eberly's algorithm for finding a bridge between hole and outer polygon 37737function findHoleBridge( hole, outerNode ) { 37738 37739 let p = outerNode, 37740 qx = - Infinity, 37741 m; 37742 37743 const hx = hole.x, hy = hole.y; 37744 37745 // find a segment intersected by a ray from the hole's leftmost point to the left; 37746 // segment's endpoint with lesser x will be potential connection point 37747 do { 37748 37749 if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) { 37750 37751 const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y ); 37752 if ( x <= hx && x > qx ) { 37753 37754 qx = x; 37755 m = p.x < p.next.x ? p : p.next; 37756 if ( x === hx ) return m; // hole touches outer segment; pick leftmost endpoint 37757 37758 } 37759 37760 } 37761 37762 p = p.next; 37763 37764 } while ( p !== outerNode ); 37765 37766 if ( ! m ) return null; 37767 37768 // look for points inside the triangle of hole point, segment intersection and endpoint; 37769 // if there are no points found, we have a valid connection; 37770 // otherwise choose the point of the minimum angle with the ray as connection point 37771 37772 const stop = m, 37773 mx = m.x, 37774 my = m.y; 37775 let tanMin = Infinity, tan; 37776 37777 p = m; 37778 37779 do { 37780 37781 if ( hx >= p.x && p.x >= mx && hx !== p.x && 37782 pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) { 37783 37784 tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential 37785 37786 if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) { 37787 37788 m = p; 37789 tanMin = tan; 37790 37791 } 37792 37793 } 37794 37795 p = p.next; 37796 37797 } while ( p !== stop ); 37798 37799 return m; 37800 37801} 37802 37803// whether sector in vertex m contains sector in vertex p in the same coordinates 37804function sectorContainsSector( m, p ) { 37805 37806 return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0; 37807 37808} 37809 37810// interlink polygon nodes in z-order 37811function indexCurve( start, minX, minY, invSize ) { 37812 37813 let p = start; 37814 do { 37815 37816 if ( p.z === 0 ) p.z = zOrder( p.x, p.y, minX, minY, invSize ); 37817 p.prevZ = p.prev; 37818 p.nextZ = p.next; 37819 p = p.next; 37820 37821 } while ( p !== start ); 37822 37823 p.prevZ.nextZ = null; 37824 p.prevZ = null; 37825 37826 sortLinked( p ); 37827 37828} 37829 37830// Simon Tatham's linked list merge sort algorithm 37831// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html 37832function sortLinked( list ) { 37833 37834 let i, p, q, e, tail, numMerges, pSize, qSize, 37835 inSize = 1; 37836 37837 do { 37838 37839 p = list; 37840 list = null; 37841 tail = null; 37842 numMerges = 0; 37843 37844 while ( p ) { 37845 37846 numMerges ++; 37847 q = p; 37848 pSize = 0; 37849 for ( i = 0; i < inSize; i ++ ) { 37850 37851 pSize ++; 37852 q = q.nextZ; 37853 if ( ! q ) break; 37854 37855 } 37856 37857 qSize = inSize; 37858 37859 while ( pSize > 0 || ( qSize > 0 && q ) ) { 37860 37861 if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) { 37862 37863 e = p; 37864 p = p.nextZ; 37865 pSize --; 37866 37867 } else { 37868 37869 e = q; 37870 q = q.nextZ; 37871 qSize --; 37872 37873 } 37874 37875 if ( tail ) tail.nextZ = e; 37876 else list = e; 37877 37878 e.prevZ = tail; 37879 tail = e; 37880 37881 } 37882
vendor: 9,707 bytes, lines 37883-38310
37883 p = q; 37884 37885 } 37886 37887 tail.nextZ = null; 37888 inSize *= 2; 37889 37890 } while ( numMerges > 1 ); 37891 37892 return list; 37893 37894} 37895 37896// z-order of a point given coords and inverse of the longer side of data bbox 37897function zOrder( x, y, minX, minY, invSize ) { 37898 37899 // coords are transformed into non-negative 15-bit integer range 37900 x = ( x - minX ) * invSize | 0; 37901 y = ( y - minY ) * invSize | 0; 37902 37903 x = ( x | ( x << 8 ) ) & 0x00FF00FF; 37904 x = ( x | ( x << 4 ) ) & 0x0F0F0F0F; 37905 x = ( x | ( x << 2 ) ) & 0x33333333; 37906 x = ( x | ( x << 1 ) ) & 0x55555555; 37907 37908 y = ( y | ( y << 8 ) ) & 0x00FF00FF; 37909 y = ( y | ( y << 4 ) ) & 0x0F0F0F0F; 37910 y = ( y | ( y << 2 ) ) & 0x33333333; 37911 y = ( y | ( y << 1 ) ) & 0x55555555; 37912 37913 return x | ( y << 1 ); 37914 37915} 37916 37917// find the leftmost node of a polygon ring 37918function getLeftmost( start ) { 37919 37920 let p = start, 37921 leftmost = start; 37922 do { 37923 37924 if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p; 37925 p = p.next; 37926 37927 } while ( p !== start ); 37928 37929 return leftmost; 37930 37931} 37932 37933// check if a point lies within a convex triangle 37934function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) { 37935 37936 return ( cx - px ) * ( ay - py ) >= ( ax - px ) * ( cy - py ) && 37937 ( ax - px ) * ( by - py ) >= ( bx - px ) * ( ay - py ) && 37938 ( bx - px ) * ( cy - py ) >= ( cx - px ) * ( by - py ); 37939 37940} 37941 37942// check if a diagonal between two polygon nodes is valid (lies in polygon interior) 37943function isValidDiagonal( a, b ) { 37944 37945 return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges 37946 ( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible 37947 ( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors 37948 equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case 37949 37950} 37951 37952// signed area of a triangle 37953function area( p, q, r ) { 37954 37955 return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y ); 37956 37957} 37958 37959// check if two points are equal 37960function equals( p1, p2 ) { 37961 37962 return p1.x === p2.x && p1.y === p2.y; 37963 37964} 37965 37966// check if two segments intersect 37967function intersects( p1, q1, p2, q2 ) { 37968 37969 const o1 = sign( area( p1, q1, p2 ) ); 37970 const o2 = sign( area( p1, q1, q2 ) ); 37971 const o3 = sign( area( p2, q2, p1 ) ); 37972 const o4 = sign( area( p2, q2, q1 ) ); 37973 37974 if ( o1 !== o2 && o3 !== o4 ) return true; // general case 37975 37976 if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1 37977 if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1 37978 if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2 37979 if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2 37980 37981 return false; 37982 37983} 37984 37985// for collinear points p, q, r, check if point q lies on segment pr 37986function onSegment( p, q, r ) { 37987 37988 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 ); 37989 37990} 37991 37992function sign( num ) { 37993 37994 return num > 0 ? 1 : num < 0 ? - 1 : 0; 37995 37996} 37997 37998// check if a polygon diagonal intersects any polygon segments 37999function intersectsPolygon( a, b ) { 38000 38001 let p = a; 38002 do { 38003 38004 if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && 38005 intersects( p, p.next, a, b ) ) return true; 38006 p = p.next; 38007 38008 } while ( p !== a ); 38009 38010 return false; 38011 38012} 38013 38014// check if a polygon diagonal is locally inside the polygon 38015function locallyInside( a, b ) { 38016 38017 return area( a.prev, a, a.next ) < 0 ? 38018 area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 : 38019 area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0; 38020 38021} 38022 38023// check if the middle point of a polygon diagonal is inside the polygon 38024function middleInside( a, b ) { 38025 38026 let p = a, 38027 inside = false; 38028 const px = ( a.x + b.x ) / 2, 38029 py = ( a.y + b.y ) / 2; 38030 do { 38031 38032 if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y && 38033 ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) 38034 inside = ! inside; 38035 p = p.next; 38036 38037 } while ( p !== a ); 38038 38039 return inside; 38040 38041} 38042 38043// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; 38044// if one belongs to the outer ring and another to a hole, it merges it into a single ring 38045function splitPolygon( a, b ) { 38046 38047 const a2 = new Node( a.i, a.x, a.y ), 38048 b2 = new Node( b.i, b.x, b.y ), 38049 an = a.next, 38050 bp = b.prev; 38051 38052 a.next = b; 38053 b.prev = a; 38054 38055 a2.next = an; 38056 an.prev = a2; 38057 38058 b2.next = a2; 38059 a2.prev = b2; 38060 38061 bp.next = b2; 38062 b2.prev = bp; 38063 38064 return b2; 38065 38066} 38067 38068// create a node and optionally link it with previous one (in a circular doubly linked list) 38069function insertNode( i, x, y, last ) { 38070 38071 const p = new Node( i, x, y ); 38072 38073 if ( ! last ) { 38074 38075 p.prev = p; 38076 p.next = p; 38077 38078 } else { 38079 38080 p.next = last.next; 38081 p.prev = last; 38082 last.next.prev = p; 38083 last.next = p; 38084 38085 } 38086 38087 return p; 38088 38089} 38090 38091function removeNode( p ) { 38092 38093 p.next.prev = p.prev; 38094 p.prev.next = p.next; 38095 38096 if ( p.prevZ ) p.prevZ.nextZ = p.nextZ; 38097 if ( p.nextZ ) p.nextZ.prevZ = p.prevZ; 38098 38099} 38100 38101function Node( i, x, y ) { 38102 38103 // vertex index in coordinates array 38104 this.i = i; 38105 38106 // vertex coordinates 38107 this.x = x; 38108 this.y = y; 38109 38110 // previous and next vertex nodes in a polygon ring 38111 this.prev = null; 38112 this.next = null; 38113 38114 // z-order curve value 38115 this.z = 0; 38116 38117 // previous and next nodes in z-order 38118 this.prevZ = null; 38119 this.nextZ = null; 38120 38121 // indicates whether this is a steiner point 38122 this.steiner = false; 38123 38124} 38125 38126function signedArea( data, start, end, dim ) { 38127 38128 let sum = 0; 38129 for ( let i = start, j = end - dim; i < end; i += dim ) { 38130 38131 sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] ); 38132 j = i; 38133 38134 } 38135 38136 return sum; 38137 38138} 38139 38140class ShapeUtils { 38141 38142 // calculate area of the contour polygon 38143 38144 static area( contour ) { 38145 38146 const n = contour.length; 38147 let a = 0.0; 38148 38149 for ( let p = n - 1, q = 0; q < n; p = q ++ ) { 38150 38151 a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y; 38152 38153 } 38154 38155 return a * 0.5; 38156 38157 } 38158 38159 static isClockWise( pts ) { 38160 38161 return ShapeUtils.area( pts ) < 0; 38162 38163 } 38164 38165 static triangulateShape( contour, holes ) { 38166 38167 const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ] 38168 const holeIndices = []; // array of hole indices 38169 const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ] 38170 38171 removeDupEndPts( contour ); 38172 addContour( vertices, contour ); 38173 38174 // 38175 38176 let holeIndex = contour.length; 38177 38178 holes.forEach( removeDupEndPts ); 38179 38180 for ( let i = 0; i < holes.length; i ++ ) { 38181 38182 holeIndices.push( holeIndex ); 38183 holeIndex += holes[ i ].length; 38184 addContour( vertices, holes[ i ] ); 38185 38186 } 38187 38188 // 38189 38190 const triangles = Earcut.triangulate( vertices, holeIndices ); 38191 38192 // 38193 38194 for ( let i = 0; i < triangles.length; i += 3 ) { 38195 38196 faces.push( triangles.slice( i, i + 3 ) ); 38197 38198 } 38199 38200 return faces; 38201 38202 } 38203 38204} 38205 38206function removeDupEndPts( points ) { 38207 38208 const l = points.length; 38209 38210 if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) { 38211 38212 points.pop(); 38213 38214 } 38215 38216} 38217 38218function addContour( vertices, contour ) { 38219 38220 for ( let i = 0; i < contour.length; i ++ ) { 38221 38222 vertices.push( contour[ i ].x ); 38223 vertices.push( contour[ i ].y ); 38224 38225 } 38226 38227} 38228 38229/** 38230 * Creates extruded geometry from a path shape. 38231 * 38232 * parameters = { 38233 * 38234 * curveSegments: <int>, // number of points on the curves 38235 * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too 38236 * depth: <float>, // Depth to extrude the shape 38237 * 38238 * bevelEnabled: <bool>, // turn on bevel 38239 * bevelThickness: <float>, // how deep into the original shape bevel goes 38240 * bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel 38241 * bevelOffset: <float>, // how far from shape outline does bevel start 38242 * bevelSegments: <int>, // number of bevel layers 38243 * 38244 * extrudePath: <THREE.Curve> // curve to extrude shape along 38245 * 38246 * UVGenerator: <Object> // object that provides UV generator functions 38247 * 38248 * } 38249 */ 38250 38251 38252class ExtrudeGeometry extends BufferGeometry { 38253 38254 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 = {} ) { 38255 38256 super(); 38257 38258 this.type = 'ExtrudeGeometry'; 38259 38260 this.parameters = { 38261 shapes: shapes, 38262 options: options 38263 }; 38264 38265 shapes = Array.isArray( shapes ) ? shapes : [ shapes ]; 38266 38267 const scope = this; 38268 38269 const verticesArray = []; 38270 const uvArray = []; 38271 38272 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 38273 38274 const shape = shapes[ i ]; 38275 addShape( shape ); 38276 38277 } 38278 38279 // build geometry 38280 38281 this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) ); 38282 this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) ); 38283 38284 this.computeVertexNormals(); 38285 38286 // functions 38287 38288 function addShape( shape ) { 38289 38290 const placeholder = []; 38291 38292 // options 38293 38294 const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12; 38295 const steps = options.steps !== undefined ? options.steps : 1; 38296 const depth = options.depth !== undefined ? options.depth : 1; 38297 38298 let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; 38299 let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2; 38300 let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1; 38301 let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0; 38302 let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3; 38303 38304 const extrudePath = options.extrudePath; 38305 38306 const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator; 38307 38308 // 38309 38310 let extrudePts, extrudeByPath = false;
vendor: 2,791 bytes, lines 38311-38424
38311 let splineTube, binormal, normal, position2; 38312 38313 if ( extrudePath ) { 38314 38315 extrudePts = extrudePath.getSpacedPoints( steps ); 38316 38317 extrudeByPath = true; 38318 bevelEnabled = false; // bevels not supported for path extrusion 38319 38320 // SETUP TNB variables 38321 38322 // TODO1 - have a .isClosed in spline? 38323 38324 splineTube = extrudePath.computeFrenetFrames( steps, false ); 38325 38326 // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length); 38327 38328 binormal = new Vector3(); 38329 normal = new Vector3(); 38330 position2 = new Vector3(); 38331 38332 } 38333 38334 // Safeguards if bevels are not enabled 38335 38336 if ( ! bevelEnabled ) { 38337 38338 bevelSegments = 0; 38339 bevelThickness = 0; 38340 bevelSize = 0; 38341 bevelOffset = 0; 38342 38343 } 38344 38345 // Variables initialization 38346 38347 const shapePoints = shape.extractPoints( curveSegments ); 38348 38349 let vertices = shapePoints.shape; 38350 const holes = shapePoints.holes; 38351 38352 const reverse = ! ShapeUtils.isClockWise( vertices ); 38353 38354 if ( reverse ) { 38355 38356 vertices = vertices.reverse(); 38357 38358 // Maybe we should also check if holes are in the opposite direction, just to be safe ... 38359 38360 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 38361 38362 const ahole = holes[ h ]; 38363 38364 if ( ShapeUtils.isClockWise( ahole ) ) { 38365 38366 holes[ h ] = ahole.reverse(); 38367 38368 } 38369 38370 } 38371 38372 } 38373 38374 38375 const faces = ShapeUtils.triangulateShape( vertices, holes ); 38376 38377 /* Vertices */ 38378 38379 const contour = vertices; // vertices has all points but contour has only points of circumference 38380 38381 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 38382 38383 const ahole = holes[ h ]; 38384 38385 vertices = vertices.concat( ahole ); 38386 38387 } 38388 38389 38390 function scalePt2( pt, vec, size ) { 38391 38392 if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' ); 38393 38394 return pt.clone().addScaledVector( vec, size ); 38395 38396 } 38397 38398 const vlen = vertices.length, flen = faces.length; 38399 38400 38401 // Find directions for point movement 38402 38403 38404 function getBevelVec( inPt, inPrev, inNext ) { 38405 38406 // computes for inPt the corresponding point inPt' on a new contour 38407 // shifted by 1 unit (length of normalized vector) to the left 38408 // if we walk along contour clockwise, this new contour is outside the old one 38409 // 38410 // inPt' is the intersection of the two lines parallel to the two 38411 // adjacent edges of inPt at a distance of 1 unit on the left side. 38412 38413 let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt 38414 38415 // good reading for geometry algorithms (here: line-line intersection) 38416 // http://geomalgorithms.com/a05-_intersect-1.html 38417 38418 const v_prev_x = inPt.x - inPrev.x, 38419 v_prev_y = inPt.y - inPrev.y; 38420 const v_next_x = inNext.x - inPt.x, 38421 v_next_y = inNext.y - inPt.y; 38422 38423 const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y ); 38424
vendor: 17,452 bytes, lines 38425-39276
38425 // check for collinear edges 38426 const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x ); 38427 38428 if ( Math.abs( collinear0 ) > Number.EPSILON ) { 38429 38430 // not collinear 38431 38432 // length of vectors for normalizing 38433 38434 const v_prev_len = Math.sqrt( v_prev_lensq ); 38435 const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y ); 38436 38437 // shift adjacent points by unit vectors to the left 38438 38439 const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len ); 38440 const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len ); 38441 38442 const ptNextShift_x = ( inNext.x - v_next_y / v_next_len ); 38443 const ptNextShift_y = ( inNext.y + v_next_x / v_next_len ); 38444 38445 // scaling factor for v_prev to intersection point 38446 38447 const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y - 38448 ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) / 38449 ( v_prev_x * v_next_y - v_prev_y * v_next_x ); 38450 38451 // vector from inPt to intersection point 38452 38453 v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x ); 38454 v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y ); 38455 38456 // Don't normalize!, otherwise sharp corners become ugly 38457 // but prevent crazy spikes 38458 const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y ); 38459 if ( v_trans_lensq <= 2 ) { 38460 38461 return new Vector2( v_trans_x, v_trans_y ); 38462 38463 } else { 38464 38465 shrink_by = Math.sqrt( v_trans_lensq / 2 ); 38466 38467 } 38468 38469 } else { 38470 38471 // handle special case of collinear edges 38472 38473 let direction_eq = false; // assumes: opposite 38474 38475 if ( v_prev_x > Number.EPSILON ) { 38476 38477 if ( v_next_x > Number.EPSILON ) { 38478 38479 direction_eq = true; 38480 38481 } 38482 38483 } else { 38484 38485 if ( v_prev_x < - Number.EPSILON ) { 38486 38487 if ( v_next_x < - Number.EPSILON ) { 38488 38489 direction_eq = true; 38490 38491 } 38492 38493 } else { 38494 38495 if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) { 38496 38497 direction_eq = true; 38498 38499 } 38500 38501 } 38502 38503 } 38504 38505 if ( direction_eq ) { 38506 38507 // console.log("Warning: lines are a straight sequence"); 38508 v_trans_x = - v_prev_y; 38509 v_trans_y = v_prev_x; 38510 shrink_by = Math.sqrt( v_prev_lensq ); 38511 38512 } else { 38513 38514 // console.log("Warning: lines are a straight spike"); 38515 v_trans_x = v_prev_x; 38516 v_trans_y = v_prev_y; 38517 shrink_by = Math.sqrt( v_prev_lensq / 2 ); 38518 38519 } 38520 38521 } 38522 38523 return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by ); 38524 38525 } 38526 38527 38528 const contourMovements = []; 38529 38530 for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { 38531 38532 if ( j === il ) j = 0; 38533 if ( k === il ) k = 0; 38534 38535 // (j)---(i)---(k) 38536 // console.log('i,j,k', i, j , k) 38537 38538 contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); 38539 38540 } 38541 38542 const holesMovements = []; 38543 let oneHoleMovements, verticesMovements = contourMovements.concat(); 38544 38545 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 38546 38547 const ahole = holes[ h ]; 38548 38549 oneHoleMovements = []; 38550 38551 for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { 38552 38553 if ( j === il ) j = 0; 38554 if ( k === il ) k = 0; 38555 38556 // (j)---(i)---(k) 38557 oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] ); 38558 38559 } 38560 38561 holesMovements.push( oneHoleMovements ); 38562 verticesMovements = verticesMovements.concat( oneHoleMovements ); 38563 38564 } 38565 38566 38567 // Loop bevelSegments, 1 for the front, 1 for the back 38568 38569 for ( let b = 0; b < bevelSegments; b ++ ) { 38570 38571 //for ( b = bevelSegments; b > 0; b -- ) { 38572 38573 const t = b / bevelSegments; 38574 const z = bevelThickness * Math.cos( t * Math.PI / 2 ); 38575 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset; 38576 38577 // contract shape 38578 38579 for ( let i = 0, il = contour.length; i < il; i ++ ) { 38580 38581 const vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); 38582 38583 v( vert.x, vert.y, - z ); 38584 38585 } 38586 38587 // expand holes 38588 38589 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 38590 38591 const ahole = holes[ h ]; 38592 oneHoleMovements = holesMovements[ h ]; 38593 38594 for ( let i = 0, il = ahole.length; i < il; i ++ ) { 38595 38596 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); 38597 38598 v( vert.x, vert.y, - z ); 38599 38600 } 38601 38602 } 38603 38604 } 38605 38606 const bs = bevelSize + bevelOffset; 38607 38608 // Back facing vertices 38609 38610 for ( let i = 0; i < vlen; i ++ ) { 38611 38612 const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; 38613 38614 if ( ! extrudeByPath ) { 38615 38616 v( vert.x, vert.y, 0 ); 38617 38618 } else { 38619 38620 // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x ); 38621 38622 normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x ); 38623 binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y ); 38624 38625 position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal ); 38626 38627 v( position2.x, position2.y, position2.z ); 38628 38629 } 38630 38631 } 38632 38633 // Add stepped vertices... 38634 // Including front facing vertices 38635 38636 for ( let s = 1; s <= steps; s ++ ) { 38637 38638 for ( let i = 0; i < vlen; i ++ ) { 38639 38640 const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; 38641 38642 if ( ! extrudeByPath ) { 38643 38644 v( vert.x, vert.y, depth / steps * s ); 38645 38646 } else { 38647 38648 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x ); 38649 38650 normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x ); 38651 binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y ); 38652 38653 position2.copy( extrudePts[ s ] ).add( normal ).add( binormal ); 38654 38655 v( position2.x, position2.y, position2.z ); 38656 38657 } 38658 38659 } 38660 38661 } 38662 38663 38664 // Add bevel segments planes 38665 38666 //for ( b = 1; b <= bevelSegments; b ++ ) { 38667 for ( let b = bevelSegments - 1; b >= 0; b -- ) { 38668 38669 const t = b / bevelSegments; 38670 const z = bevelThickness * Math.cos( t * Math.PI / 2 ); 38671 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset; 38672 38673 // contract shape 38674 38675 for ( let i = 0, il = contour.length; i < il; i ++ ) { 38676 38677 const vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); 38678 v( vert.x, vert.y, depth + z ); 38679 38680 } 38681 38682 // expand holes 38683 38684 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 38685 38686 const ahole = holes[ h ]; 38687 oneHoleMovements = holesMovements[ h ]; 38688 38689 for ( let i = 0, il = ahole.length; i < il; i ++ ) { 38690 38691 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); 38692 38693 if ( ! extrudeByPath ) { 38694 38695 v( vert.x, vert.y, depth + z ); 38696 38697 } else { 38698 38699 v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z ); 38700 38701 } 38702 38703 } 38704 38705 } 38706 38707 } 38708 38709 /* Faces */ 38710 38711 // Top and bottom faces 38712 38713 buildLidFaces(); 38714 38715 // Sides faces 38716 38717 buildSideFaces(); 38718 38719 38720 ///// Internal functions 38721 38722 function buildLidFaces() { 38723 38724 const start = verticesArray.length / 3; 38725 38726 if ( bevelEnabled ) { 38727 38728 let layer = 0; // steps + 1 38729 let offset = vlen * layer; 38730 38731 // Bottom faces 38732 38733 for ( let i = 0; i < flen; i ++ ) { 38734 38735 const face = faces[ i ]; 38736 f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset ); 38737 38738 } 38739 38740 layer = steps + bevelSegments * 2; 38741 offset = vlen * layer; 38742 38743 // Top faces 38744 38745 for ( let i = 0; i < flen; i ++ ) { 38746 38747 const face = faces[ i ]; 38748 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset ); 38749 38750 } 38751 38752 } else { 38753 38754 // Bottom faces 38755 38756 for ( let i = 0; i < flen; i ++ ) { 38757 38758 const face = faces[ i ]; 38759 f3( face[ 2 ], face[ 1 ], face[ 0 ] ); 38760 38761 } 38762 38763 // Top faces 38764 38765 for ( let i = 0; i < flen; i ++ ) { 38766 38767 const face = faces[ i ]; 38768 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps ); 38769 38770 } 38771 38772 } 38773 38774 scope.addGroup( start, verticesArray.length / 3 - start, 0 ); 38775 38776 } 38777 38778 // Create faces for the z-sides of the shape 38779 38780 function buildSideFaces() { 38781 38782 const start = verticesArray.length / 3; 38783 let layeroffset = 0; 38784 sidewalls( contour, layeroffset ); 38785 layeroffset += contour.length; 38786 38787 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 38788 38789 const ahole = holes[ h ]; 38790 sidewalls( ahole, layeroffset ); 38791 38792 //, true 38793 layeroffset += ahole.length; 38794 38795 } 38796 38797 38798 scope.addGroup( start, verticesArray.length / 3 - start, 1 ); 38799 38800 38801 } 38802 38803 function sidewalls( contour, layeroffset ) { 38804 38805 let i = contour.length; 38806 38807 while ( -- i >= 0 ) { 38808 38809 const j = i; 38810 let k = i - 1; 38811 if ( k < 0 ) k = contour.length - 1; 38812 38813 //console.log('b', i,j, i-1, k,vertices.length); 38814 38815 for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) { 38816 38817 const slen1 = vlen * s; 38818 const slen2 = vlen * ( s + 1 ); 38819 38820 const a = layeroffset + j + slen1, 38821 b = layeroffset + k + slen1, 38822 c = layeroffset + k + slen2, 38823 d = layeroffset + j + slen2; 38824 38825 f4( a, b, c, d ); 38826 38827 } 38828 38829 } 38830 38831 } 38832 38833 function v( x, y, z ) { 38834 38835 placeholder.push( x ); 38836 placeholder.push( y ); 38837 placeholder.push( z ); 38838 38839 } 38840 38841 38842 function f3( a, b, c ) { 38843 38844 addVertex( a ); 38845 addVertex( b ); 38846 addVertex( c ); 38847 38848 const nextIndex = verticesArray.length / 3; 38849 const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); 38850 38851 addUV( uvs[ 0 ] ); 38852 addUV( uvs[ 1 ] ); 38853 addUV( uvs[ 2 ] ); 38854 38855 } 38856 38857 function f4( a, b, c, d ) { 38858 38859 addVertex( a ); 38860 addVertex( b ); 38861 addVertex( d ); 38862 38863 addVertex( b ); 38864 addVertex( c ); 38865 addVertex( d ); 38866 38867 38868 const nextIndex = verticesArray.length / 3; 38869 const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); 38870 38871 addUV( uvs[ 0 ] ); 38872 addUV( uvs[ 1 ] ); 38873 addUV( uvs[ 3 ] ); 38874 38875 addUV( uvs[ 1 ] ); 38876 addUV( uvs[ 2 ] ); 38877 addUV( uvs[ 3 ] ); 38878 38879 } 38880 38881 function addVertex( index ) { 38882 38883 verticesArray.push( placeholder[ index * 3 + 0 ] ); 38884 verticesArray.push( placeholder[ index * 3 + 1 ] ); 38885 verticesArray.push( placeholder[ index * 3 + 2 ] ); 38886 38887 } 38888 38889 38890 function addUV( vector2 ) { 38891 38892 uvArray.push( vector2.x ); 38893 uvArray.push( vector2.y ); 38894 38895 } 38896 38897 } 38898 38899 } 38900 38901 copy( source ) { 38902 38903 super.copy( source ); 38904 38905 this.parameters = Object.assign( {}, source.parameters ); 38906 38907 return this; 38908 38909 } 38910 38911 toJSON() { 38912 38913 const data = super.toJSON(); 38914 38915 const shapes = this.parameters.shapes; 38916 const options = this.parameters.options; 38917 38918 return toJSON$1( shapes, options, data ); 38919 38920 } 38921 38922 static fromJSON( data, shapes ) { 38923 38924 const geometryShapes = []; 38925 38926 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) { 38927 38928 const shape = shapes[ data.shapes[ j ] ]; 38929 38930 geometryShapes.push( shape ); 38931 38932 } 38933 38934 const extrudePath = data.options.extrudePath; 38935 38936 if ( extrudePath !== undefined ) { 38937 38938 data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath ); 38939 38940 } 38941 38942 return new ExtrudeGeometry( geometryShapes, data.options ); 38943 38944 } 38945 38946} 38947 38948const WorldUVGenerator = { 38949 38950 generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) { 38951 38952 const a_x = vertices[ indexA * 3 ]; 38953 const a_y = vertices[ indexA * 3 + 1 ]; 38954 const b_x = vertices[ indexB * 3 ]; 38955 const b_y = vertices[ indexB * 3 + 1 ]; 38956 const c_x = vertices[ indexC * 3 ]; 38957 const c_y = vertices[ indexC * 3 + 1 ]; 38958 38959 return [ 38960 new Vector2( a_x, a_y ), 38961 new Vector2( b_x, b_y ), 38962 new Vector2( c_x, c_y ) 38963 ]; 38964 38965 }, 38966 38967 generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) { 38968 38969 const a_x = vertices[ indexA * 3 ]; 38970 const a_y = vertices[ indexA * 3 + 1 ]; 38971 const a_z = vertices[ indexA * 3 + 2 ]; 38972 const b_x = vertices[ indexB * 3 ]; 38973 const b_y = vertices[ indexB * 3 + 1 ]; 38974 const b_z = vertices[ indexB * 3 + 2 ]; 38975 const c_x = vertices[ indexC * 3 ]; 38976 const c_y = vertices[ indexC * 3 + 1 ]; 38977 const c_z = vertices[ indexC * 3 + 2 ]; 38978 const d_x = vertices[ indexD * 3 ]; 38979 const d_y = vertices[ indexD * 3 + 1 ]; 38980 const d_z = vertices[ indexD * 3 + 2 ]; 38981 38982 if ( Math.abs( a_y - b_y ) < Math.abs( a_x - b_x ) ) { 38983 38984 return [ 38985 new Vector2( a_x, 1 - a_z ), 38986 new Vector2( b_x, 1 - b_z ), 38987 new Vector2( c_x, 1 - c_z ), 38988 new Vector2( d_x, 1 - d_z ) 38989 ]; 38990 38991 } else { 38992 38993 return [ 38994 new Vector2( a_y, 1 - a_z ), 38995 new Vector2( b_y, 1 - b_z ), 38996 new Vector2( c_y, 1 - c_z ), 38997 new Vector2( d_y, 1 - d_z ) 38998 ]; 38999 39000 } 39001 39002 } 39003 39004}; 39005 39006function toJSON$1( shapes, options, data ) { 39007 39008 data.shapes = []; 39009 39010 if ( Array.isArray( shapes ) ) { 39011 39012 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 39013 39014 const shape = shapes[ i ]; 39015 39016 data.shapes.push( shape.uuid ); 39017 39018 } 39019 39020 } else { 39021 39022 data.shapes.push( shapes.uuid ); 39023 39024 } 39025 39026 data.options = Object.assign( {}, options ); 39027 39028 if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON(); 39029 39030 return data; 39031 39032} 39033 39034class IcosahedronGeometry extends PolyhedronGeometry { 39035 39036 constructor( radius = 1, detail = 0 ) { 39037 39038 const t = ( 1 + Math.sqrt( 5 ) ) / 2; 39039 39040 const vertices = [ 39041 - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0, 39042 0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 39043 t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1 39044 ]; 39045 39046 const indices = [ 39047 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 39048 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, 39049 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 39050 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1 39051 ]; 39052 39053 super( vertices, indices, radius, detail ); 39054 39055 this.type = 'IcosahedronGeometry'; 39056 39057 this.parameters = { 39058 radius: radius, 39059 detail: detail 39060 }; 39061 39062 } 39063 39064 static fromJSON( data ) { 39065 39066 return new IcosahedronGeometry( data.radius, data.detail ); 39067 39068 } 39069 39070} 39071 39072class OctahedronGeometry extends PolyhedronGeometry { 39073 39074 constructor( radius = 1, detail = 0 ) { 39075 39076 const vertices = [ 39077 1, 0, 0, - 1, 0, 0, 0, 1, 0, 39078 0, - 1, 0, 0, 0, 1, 0, 0, - 1 39079 ]; 39080 39081 const indices = [ 39082 0, 2, 4, 0, 4, 3, 0, 3, 5, 39083 0, 5, 2, 1, 2, 5, 1, 5, 3, 39084 1, 3, 4, 1, 4, 2 39085 ]; 39086 39087 super( vertices, indices, radius, detail ); 39088 39089 this.type = 'OctahedronGeometry'; 39090 39091 this.parameters = { 39092 radius: radius, 39093 detail: detail 39094 }; 39095 39096 } 39097 39098 static fromJSON( data ) { 39099 39100 return new OctahedronGeometry( data.radius, data.detail ); 39101 39102 } 39103 39104} 39105 39106class RingGeometry extends BufferGeometry { 39107 39108 constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) { 39109 39110 super(); 39111 39112 this.type = 'RingGeometry'; 39113 39114 this.parameters = { 39115 innerRadius: innerRadius, 39116 outerRadius: outerRadius, 39117 thetaSegments: thetaSegments, 39118 phiSegments: phiSegments, 39119 thetaStart: thetaStart, 39120 thetaLength: thetaLength 39121 }; 39122 39123 thetaSegments = Math.max( 3, thetaSegments ); 39124 phiSegments = Math.max( 1, phiSegments ); 39125 39126 // buffers 39127 39128 const indices = []; 39129 const vertices = []; 39130 const normals = []; 39131 const uvs = []; 39132 39133 // some helper variables 39134 39135 let radius = innerRadius; 39136 const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments ); 39137 const vertex = new Vector3(); 39138 const uv = new Vector2(); 39139 39140 // generate vertices, normals and uvs 39141 39142 for ( let j = 0; j <= phiSegments; j ++ ) { 39143 39144 for ( let i = 0; i <= thetaSegments; i ++ ) { 39145 39146 // values are generate from the inside of the ring to the outside 39147 39148 const segment = thetaStart + i / thetaSegments * thetaLength; 39149 39150 // vertex 39151 39152 vertex.x = radius * Math.cos( segment ); 39153 vertex.y = radius * Math.sin( segment ); 39154 39155 vertices.push( vertex.x, vertex.y, vertex.z ); 39156 39157 // normal 39158 39159 normals.push( 0, 0, 1 ); 39160 39161 // uv 39162 39163 uv.x = ( vertex.x / outerRadius + 1 ) / 2; 39164 uv.y = ( vertex.y / outerRadius + 1 ) / 2; 39165 39166 uvs.push( uv.x, uv.y ); 39167 39168 } 39169 39170 // increase the radius for next row of vertices 39171 39172 radius += radiusStep; 39173 39174 } 39175 39176 // indices 39177 39178 for ( let j = 0; j < phiSegments; j ++ ) { 39179 39180 const thetaSegmentLevel = j * ( thetaSegments + 1 ); 39181 39182 for ( let i = 0; i < thetaSegments; i ++ ) { 39183 39184 const segment = i + thetaSegmentLevel; 39185 39186 const a = segment; 39187 const b = segment + thetaSegments + 1; 39188 const c = segment + thetaSegments + 2; 39189 const d = segment + 1; 39190 39191 // faces 39192 39193 indices.push( a, b, d ); 39194 indices.push( b, c, d ); 39195 39196 } 39197 39198 } 39199 39200 // build geometry 39201 39202 this.setIndex( indices ); 39203 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 39204 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 39205 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 39206 39207 } 39208 39209 copy( source ) { 39210 39211 super.copy( source ); 39212 39213 this.parameters = Object.assign( {}, source.parameters ); 39214 39215 return this; 39216 39217 } 39218 39219 static fromJSON( data ) { 39220 39221 return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength ); 39222 39223 } 39224 39225} 39226 39227class ShapeGeometry extends BufferGeometry { 39228 39229 constructor( shapes = new Shape( [ new Vector2( 0, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), curveSegments = 12 ) { 39230 39231 super(); 39232 39233 this.type = 'ShapeGeometry'; 39234 39235 this.parameters = { 39236 shapes: shapes, 39237 curveSegments: curveSegments 39238 }; 39239 39240 // buffers 39241 39242 const indices = []; 39243 const vertices = []; 39244 const normals = []; 39245 const uvs = []; 39246 39247 // helper variables 39248 39249 let groupStart = 0; 39250 let groupCount = 0; 39251 39252 // allow single and array values for "shapes" parameter 39253 39254 if ( Array.isArray( shapes ) === false ) { 39255 39256 addShape( shapes ); 39257 39258 } else { 39259 39260 for ( let i = 0; i < shapes.length; i ++ ) { 39261 39262 addShape( shapes[ i ] ); 39263 39264 this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support 39265 39266 groupStart += groupCount; 39267 groupCount = 0; 39268 39269 } 39270 39271 } 39272 39273 // build geometry 39274 39275 this.setIndex( indices ); 39276 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,878 bytes, lines 39277-39523
39277 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 39278 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 39279 39280 39281 // helper functions 39282 39283 function addShape( shape ) { 39284 39285 const indexOffset = vertices.length / 3; 39286 const points = shape.extractPoints( curveSegments ); 39287 39288 let shapeVertices = points.shape; 39289 const shapeHoles = points.holes; 39290 39291 // check direction of vertices 39292 39293 if ( ShapeUtils.isClockWise( shapeVertices ) === false ) { 39294 39295 shapeVertices = shapeVertices.reverse(); 39296 39297 } 39298 39299 for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) { 39300 39301 const shapeHole = shapeHoles[ i ]; 39302 39303 if ( ShapeUtils.isClockWise( shapeHole ) === true ) { 39304 39305 shapeHoles[ i ] = shapeHole.reverse(); 39306 39307 } 39308 39309 } 39310 39311 const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles ); 39312 39313 // join vertices of inner and outer paths to a single array 39314 39315 for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) { 39316 39317 const shapeHole = shapeHoles[ i ]; 39318 shapeVertices = shapeVertices.concat( shapeHole ); 39319 39320 } 39321 39322 // vertices, normals, uvs 39323 39324 for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) { 39325 39326 const vertex = shapeVertices[ i ]; 39327 39328 vertices.push( vertex.x, vertex.y, 0 ); 39329 normals.push( 0, 0, 1 ); 39330 uvs.push( vertex.x, vertex.y ); // world uvs 39331 39332 } 39333 39334 // indices 39335 39336 for ( let i = 0, l = faces.length; i < l; i ++ ) { 39337 39338 const face = faces[ i ]; 39339 39340 const a = face[ 0 ] + indexOffset; 39341 const b = face[ 1 ] + indexOffset; 39342 const c = face[ 2 ] + indexOffset; 39343 39344 indices.push( a, b, c ); 39345 groupCount += 3; 39346 39347 } 39348 39349 } 39350 39351 } 39352 39353 copy( source ) { 39354 39355 super.copy( source ); 39356 39357 this.parameters = Object.assign( {}, source.parameters ); 39358 39359 return this; 39360 39361 } 39362 39363 toJSON() { 39364 39365 const data = super.toJSON(); 39366 39367 const shapes = this.parameters.shapes; 39368 39369 return toJSON( shapes, data ); 39370 39371 } 39372 39373 static fromJSON( data, shapes ) { 39374 39375 const geometryShapes = []; 39376 39377 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) { 39378 39379 const shape = shapes[ data.shapes[ j ] ]; 39380 39381 geometryShapes.push( shape ); 39382 39383 } 39384 39385 return new ShapeGeometry( geometryShapes, data.curveSegments ); 39386 39387 } 39388 39389} 39390 39391function toJSON( shapes, data ) { 39392 39393 data.shapes = []; 39394 39395 if ( Array.isArray( shapes ) ) { 39396 39397 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 39398 39399 const shape = shapes[ i ]; 39400 39401 data.shapes.push( shape.uuid ); 39402 39403 } 39404 39405 } else { 39406 39407 data.shapes.push( shapes.uuid ); 39408 39409 } 39410 39411 return data; 39412 39413} 39414 39415class SphereGeometry extends BufferGeometry { 39416 39417 constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) { 39418 39419 super(); 39420 39421 this.type = 'SphereGeometry'; 39422 39423 this.parameters = { 39424 radius: radius, 39425 widthSegments: widthSegments, 39426 heightSegments: heightSegments, 39427 phiStart: phiStart, 39428 phiLength: phiLength, 39429 thetaStart: thetaStart, 39430 thetaLength: thetaLength 39431 }; 39432 39433 widthSegments = Math.max( 3, Math.floor( widthSegments ) ); 39434 heightSegments = Math.max( 2, Math.floor( heightSegments ) ); 39435 39436 const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI ); 39437 39438 let index = 0; 39439 const grid = []; 39440 39441 const vertex = new Vector3(); 39442 const normal = new Vector3(); 39443 39444 // buffers 39445 39446 const indices = []; 39447 const vertices = []; 39448 const normals = []; 39449 const uvs = []; 39450 39451 // generate vertices, normals and uvs 39452 39453 for ( let iy = 0; iy <= heightSegments; iy ++ ) { 39454 39455 const verticesRow = []; 39456 39457 const v = iy / heightSegments; 39458 39459 // special case for the poles 39460 39461 let uOffset = 0; 39462 39463 if ( iy === 0 && thetaStart === 0 ) { 39464 39465 uOffset = 0.5 / widthSegments; 39466 39467 } else if ( iy === heightSegments && thetaEnd === Math.PI ) { 39468 39469 uOffset = - 0.5 / widthSegments; 39470 39471 } 39472 39473 for ( let ix = 0; ix <= widthSegments; ix ++ ) { 39474 39475 const u = ix / widthSegments; 39476 39477 // vertex 39478 39479 vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); 39480 vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); 39481 vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); 39482 39483 vertices.push( vertex.x, vertex.y, vertex.z ); 39484 39485 // normal 39486 39487 normal.copy( vertex ).normalize(); 39488 normals.push( normal.x, normal.y, normal.z ); 39489 39490 // uv 39491 39492 uvs.push( u + uOffset, 1 - v ); 39493 39494 verticesRow.push( index ++ ); 39495 39496 } 39497 39498 grid.push( verticesRow ); 39499 39500 } 39501 39502 // indices 39503 39504 for ( let iy = 0; iy < heightSegments; iy ++ ) { 39505 39506 for ( let ix = 0; ix < widthSegments; ix ++ ) { 39507 39508 const a = grid[ iy ][ ix + 1 ]; 39509 const b = grid[ iy ][ ix ]; 39510 const c = grid[ iy + 1 ][ ix ]; 39511 const d = grid[ iy + 1 ][ ix + 1 ]; 39512 39513 if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d ); 39514 if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d ); 39515 39516 } 39517 39518 } 39519 39520 // build geometry 39521 39522 this.setIndex( indices ); 39523 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 6,566 bytes, lines 39524-39816
39524 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 39525 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 39526 39527 } 39528 39529 copy( source ) { 39530 39531 super.copy( source ); 39532 39533 this.parameters = Object.assign( {}, source.parameters ); 39534 39535 return this; 39536 39537 } 39538 39539 static fromJSON( data ) { 39540 39541 return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); 39542 39543 } 39544 39545} 39546 39547class TetrahedronGeometry extends PolyhedronGeometry { 39548 39549 constructor( radius = 1, detail = 0 ) { 39550 39551 const vertices = [ 39552 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1 39553 ]; 39554 39555 const indices = [ 39556 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 39557 ]; 39558 39559 super( vertices, indices, radius, detail ); 39560 39561 this.type = 'TetrahedronGeometry'; 39562 39563 this.parameters = { 39564 radius: radius, 39565 detail: detail 39566 }; 39567 39568 } 39569 39570 static fromJSON( data ) { 39571 39572 return new TetrahedronGeometry( data.radius, data.detail ); 39573 39574 } 39575 39576} 39577 39578class TorusGeometry extends BufferGeometry { 39579 39580 constructor( radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2 ) { 39581 39582 super(); 39583 39584 this.type = 'TorusGeometry'; 39585 39586 this.parameters = { 39587 radius: radius, 39588 tube: tube, 39589 radialSegments: radialSegments, 39590 tubularSegments: tubularSegments, 39591 arc: arc 39592 }; 39593 39594 radialSegments = Math.floor( radialSegments ); 39595 tubularSegments = Math.floor( tubularSegments ); 39596 39597 // buffers 39598 39599 const indices = []; 39600 const vertices = []; 39601 const normals = []; 39602 const uvs = []; 39603 39604 // helper variables 39605 39606 const center = new Vector3(); 39607 const vertex = new Vector3(); 39608 const normal = new Vector3(); 39609 39610 // generate vertices, normals and uvs 39611 39612 for ( let j = 0; j <= radialSegments; j ++ ) { 39613 39614 for ( let i = 0; i <= tubularSegments; i ++ ) { 39615 39616 const u = i / tubularSegments * arc; 39617 const v = j / radialSegments * Math.PI * 2; 39618 39619 // vertex 39620 39621 vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u ); 39622 vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u ); 39623 vertex.z = tube * Math.sin( v ); 39624 39625 vertices.push( vertex.x, vertex.y, vertex.z ); 39626 39627 // normal 39628 39629 center.x = radius * Math.cos( u ); 39630 center.y = radius * Math.sin( u ); 39631 normal.subVectors( vertex, center ).normalize(); 39632 39633 normals.push( normal.x, normal.y, normal.z ); 39634 39635 // uv 39636 39637 uvs.push( i / tubularSegments ); 39638 uvs.push( j / radialSegments ); 39639 39640 } 39641 39642 } 39643 39644 // generate indices 39645 39646 for ( let j = 1; j <= radialSegments; j ++ ) { 39647 39648 for ( let i = 1; i <= tubularSegments; i ++ ) { 39649 39650 // indices 39651 39652 const a = ( tubularSegments + 1 ) * j + i - 1; 39653 const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1; 39654 const c = ( tubularSegments + 1 ) * ( j - 1 ) + i; 39655 const d = ( tubularSegments + 1 ) * j + i; 39656 39657 // faces 39658 39659 indices.push( a, b, d ); 39660 indices.push( b, c, d ); 39661 39662 } 39663 39664 } 39665 39666 // build geometry 39667 39668 this.setIndex( indices ); 39669 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 39670 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 39671 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 39672 39673 } 39674 39675 copy( source ) { 39676 39677 super.copy( source ); 39678 39679 this.parameters = Object.assign( {}, source.parameters ); 39680 39681 return this; 39682 39683 } 39684 39685 static fromJSON( data ) { 39686 39687 return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc ); 39688 39689 } 39690 39691} 39692 39693class TorusKnotGeometry extends BufferGeometry { 39694 39695 constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) { 39696 39697 super(); 39698 39699 this.type = 'TorusKnotGeometry'; 39700 39701 this.parameters = { 39702 radius: radius, 39703 tube: tube, 39704 tubularSegments: tubularSegments, 39705 radialSegments: radialSegments, 39706 p: p, 39707 q: q 39708 }; 39709 39710 tubularSegments = Math.floor( tubularSegments ); 39711 radialSegments = Math.floor( radialSegments ); 39712 39713 // buffers 39714 39715 const indices = []; 39716 const vertices = []; 39717 const normals = []; 39718 const uvs = []; 39719 39720 // helper variables 39721 39722 const vertex = new Vector3(); 39723 const normal = new Vector3(); 39724 39725 const P1 = new Vector3(); 39726 const P2 = new Vector3(); 39727 39728 const B = new Vector3(); 39729 const T = new Vector3(); 39730 const N = new Vector3(); 39731 39732 // generate vertices, normals and uvs 39733 39734 for ( let i = 0; i <= tubularSegments; ++ i ) { 39735 39736 // the radian "u" is used to calculate the position on the torus curve of the current tubular segment 39737 39738 const u = i / tubularSegments * p * Math.PI * 2; 39739 39740 // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead. 39741 // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions 39742 39743 calculatePositionOnCurve( u, p, q, radius, P1 ); 39744 calculatePositionOnCurve( u + 0.01, p, q, radius, P2 ); 39745 39746 // calculate orthonormal basis 39747 39748 T.subVectors( P2, P1 ); 39749 N.addVectors( P2, P1 ); 39750 B.crossVectors( T, N ); 39751 N.crossVectors( B, T ); 39752 39753 // normalize B, N. T can be ignored, we don't use it 39754 39755 B.normalize(); 39756 N.normalize(); 39757 39758 for ( let j = 0; j <= radialSegments; ++ j ) { 39759 39760 // now calculate the vertices. they are nothing more than an extrusion of the torus curve. 39761 // because we extrude a shape in the xy-plane, there is no need to calculate a z-value. 39762 39763 const v = j / radialSegments * Math.PI * 2; 39764 const cx = - tube * Math.cos( v ); 39765 const cy = tube * Math.sin( v ); 39766 39767 // now calculate the final vertex position. 39768 // first we orient the extrusion with our basis vectors, then we add it to the current position on the curve 39769 39770 vertex.x = P1.x + ( cx * N.x + cy * B.x ); 39771 vertex.y = P1.y + ( cx * N.y + cy * B.y ); 39772 vertex.z = P1.z + ( cx * N.z + cy * B.z ); 39773 39774 vertices.push( vertex.x, vertex.y, vertex.z ); 39775 39776 // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal) 39777 39778 normal.subVectors( vertex, P1 ).normalize(); 39779 39780 normals.push( normal.x, normal.y, normal.z ); 39781 39782 // uv 39783 39784 uvs.push( i / tubularSegments ); 39785 uvs.push( j / radialSegments ); 39786 39787 } 39788 39789 } 39790 39791 // generate indices 39792 39793 for ( let j = 1; j <= tubularSegments; j ++ ) { 39794 39795 for ( let i = 1; i <= radialSegments; i ++ ) { 39796 39797 // indices 39798 39799 const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); 39800 const b = ( radialSegments + 1 ) * j + ( i - 1 ); 39801 const c = ( radialSegments + 1 ) * j + i; 39802 const d = ( radialSegments + 1 ) * ( j - 1 ) + i; 39803 39804 // faces 39805 39806 indices.push( a, b, d ); 39807 indices.push( b, c, d ); 39808 39809 } 39810 39811 } 39812 39813 // build geometry 39814 39815 this.setIndex( indices ); 39816 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 7,450 bytes, lines 39817-40175
39817 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 39818 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 39819 39820 // this function calculates the current position on the torus curve 39821 39822 function calculatePositionOnCurve( u, p, q, radius, position ) { 39823 39824 const cu = Math.cos( u ); 39825 const su = Math.sin( u ); 39826 const quOverP = q / p * u; 39827 const cs = Math.cos( quOverP ); 39828 39829 position.x = radius * ( 2 + cs ) * 0.5 * cu; 39830 position.y = radius * ( 2 + cs ) * su * 0.5; 39831 position.z = radius * Math.sin( quOverP ) * 0.5; 39832 39833 } 39834 39835 } 39836 39837 copy( source ) { 39838 39839 super.copy( source ); 39840 39841 this.parameters = Object.assign( {}, source.parameters ); 39842 39843 return this; 39844 39845 } 39846 39847 static fromJSON( data ) { 39848 39849 return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q ); 39850 39851 } 39852 39853} 39854 39855class TubeGeometry extends BufferGeometry { 39856 39857 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 ) { 39858 39859 super(); 39860 39861 this.type = 'TubeGeometry'; 39862 39863 this.parameters = { 39864 path: path, 39865 tubularSegments: tubularSegments, 39866 radius: radius, 39867 radialSegments: radialSegments, 39868 closed: closed 39869 }; 39870 39871 const frames = path.computeFrenetFrames( tubularSegments, closed ); 39872 39873 // expose internals 39874 39875 this.tangents = frames.tangents; 39876 this.normals = frames.normals; 39877 this.binormals = frames.binormals; 39878 39879 // helper variables 39880 39881 const vertex = new Vector3(); 39882 const normal = new Vector3(); 39883 const uv = new Vector2(); 39884 let P = new Vector3(); 39885 39886 // buffer 39887 39888 const vertices = []; 39889 const normals = []; 39890 const uvs = []; 39891 const indices = []; 39892 39893 // create buffer data 39894 39895 generateBufferData(); 39896 39897 // build geometry 39898 39899 this.setIndex( indices ); 39900 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 39901 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 39902 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 39903 39904 // functions 39905 39906 function generateBufferData() { 39907 39908 for ( let i = 0; i < tubularSegments; i ++ ) { 39909 39910 generateSegment( i ); 39911 39912 } 39913 39914 // if the geometry is not closed, generate the last row of vertices and normals 39915 // at the regular position on the given path 39916 // 39917 // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ) 39918 39919 generateSegment( ( closed === false ) ? tubularSegments : 0 ); 39920 39921 // uvs are generated in a separate function. 39922 // this makes it easy compute correct values for closed geometries 39923 39924 generateUVs(); 39925 39926 // finally create faces 39927 39928 generateIndices(); 39929 39930 } 39931 39932 function generateSegment( i ) { 39933 39934 // we use getPointAt to sample evenly distributed points from the given path 39935 39936 P = path.getPointAt( i / tubularSegments, P ); 39937 39938 // retrieve corresponding normal and binormal 39939 39940 const N = frames.normals[ i ]; 39941 const B = frames.binormals[ i ]; 39942 39943 // generate normals and vertices for the current segment 39944 39945 for ( let j = 0; j <= radialSegments; j ++ ) { 39946 39947 const v = j / radialSegments * Math.PI * 2; 39948 39949 const sin = Math.sin( v ); 39950 const cos = - Math.cos( v ); 39951 39952 // normal 39953 39954 normal.x = ( cos * N.x + sin * B.x ); 39955 normal.y = ( cos * N.y + sin * B.y ); 39956 normal.z = ( cos * N.z + sin * B.z ); 39957 normal.normalize(); 39958 39959 normals.push( normal.x, normal.y, normal.z ); 39960 39961 // vertex 39962 39963 vertex.x = P.x + radius * normal.x; 39964 vertex.y = P.y + radius * normal.y; 39965 vertex.z = P.z + radius * normal.z; 39966 39967 vertices.push( vertex.x, vertex.y, vertex.z ); 39968 39969 } 39970 39971 } 39972 39973 function generateIndices() { 39974 39975 for ( let j = 1; j <= tubularSegments; j ++ ) { 39976 39977 for ( let i = 1; i <= radialSegments; i ++ ) { 39978 39979 const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); 39980 const b = ( radialSegments + 1 ) * j + ( i - 1 ); 39981 const c = ( radialSegments + 1 ) * j + i; 39982 const d = ( radialSegments + 1 ) * ( j - 1 ) + i; 39983 39984 // faces 39985 39986 indices.push( a, b, d ); 39987 indices.push( b, c, d ); 39988 39989 } 39990 39991 } 39992 39993 } 39994 39995 function generateUVs() { 39996 39997 for ( let i = 0; i <= tubularSegments; i ++ ) { 39998 39999 for ( let j = 0; j <= radialSegments; j ++ ) { 40000 40001 uv.x = i / tubularSegments; 40002 uv.y = j / radialSegments; 40003 40004 uvs.push( uv.x, uv.y ); 40005 40006 } 40007 40008 } 40009 40010 } 40011 40012 } 40013 40014 copy( source ) { 40015 40016 super.copy( source ); 40017 40018 this.parameters = Object.assign( {}, source.parameters ); 40019 40020 return this; 40021 40022 } 40023 40024 toJSON() { 40025 40026 const data = super.toJSON(); 40027 40028 data.path = this.parameters.path.toJSON(); 40029 40030 return data; 40031 40032 } 40033 40034 static fromJSON( data ) { 40035 40036 // This only works for built-in curves (e.g. CatmullRomCurve3). 40037 // User defined curves or instances of CurvePath will not be deserialized. 40038 return new TubeGeometry( 40039 new Curves[ data.path.type ]().fromJSON( data.path ), 40040 data.tubularSegments, 40041 data.radius, 40042 data.radialSegments, 40043 data.closed 40044 ); 40045 40046 } 40047 40048} 40049 40050class WireframeGeometry extends BufferGeometry { 40051 40052 constructor( geometry = null ) { 40053 40054 super(); 40055 40056 this.type = 'WireframeGeometry'; 40057 40058 this.parameters = { 40059 geometry: geometry 40060 }; 40061 40062 if ( geometry !== null ) { 40063 40064 // buffer 40065 40066 const vertices = []; 40067 const edges = new Set(); 40068 40069 // helper variables 40070 40071 const start = new Vector3(); 40072 const end = new Vector3(); 40073 40074 if ( geometry.index !== null ) { 40075 40076 // indexed BufferGeometry 40077 40078 const position = geometry.attributes.position; 40079 const indices = geometry.index; 40080 let groups = geometry.groups; 40081 40082 if ( groups.length === 0 ) { 40083 40084 groups = [ { start: 0, count: indices.count, materialIndex: 0 } ]; 40085 40086 } 40087 40088 // create a data structure that contains all edges without duplicates 40089 40090 for ( let o = 0, ol = groups.length; o < ol; ++ o ) { 40091 40092 const group = groups[ o ]; 40093 40094 const groupStart = group.start; 40095 const groupCount = group.count; 40096 40097 for ( let i = groupStart, l = ( groupStart + groupCount ); i < l; i += 3 ) { 40098 40099 for ( let j = 0; j < 3; j ++ ) { 40100 40101 const index1 = indices.getX( i + j ); 40102 const index2 = indices.getX( i + ( j + 1 ) % 3 ); 40103 40104 start.fromBufferAttribute( position, index1 ); 40105 end.fromBufferAttribute( position, index2 ); 40106 40107 if ( isUniqueEdge( start, end, edges ) === true ) { 40108 40109 vertices.push( start.x, start.y, start.z ); 40110 vertices.push( end.x, end.y, end.z ); 40111 40112 } 40113 40114 } 40115 40116 } 40117 40118 } 40119 40120 } else { 40121 40122 // non-indexed BufferGeometry 40123 40124 const position = geometry.attributes.position; 40125 40126 for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) { 40127 40128 for ( let j = 0; j < 3; j ++ ) { 40129 40130 // three edges per triangle, an edge is represented as (index1, index2) 40131 // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0) 40132 40133 const index1 = 3 * i + j; 40134 const index2 = 3 * i + ( ( j + 1 ) % 3 ); 40135 40136 start.fromBufferAttribute( position, index1 ); 40137 end.fromBufferAttribute( position, index2 ); 40138 40139 if ( isUniqueEdge( start, end, edges ) === true ) { 40140 40141 vertices.push( start.x, start.y, start.z ); 40142 vertices.push( end.x, end.y, end.z ); 40143 40144 } 40145 40146 } 40147 40148 } 40149 40150 } 40151 40152 // build geometry 40153 40154 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 40155 40156 } 40157 40158 } 40159 40160 copy( source ) { 40161 40162 super.copy( source ); 40163 40164 this.parameters = Object.assign( {}, source.parameters ); 40165 40166 return this; 40167 40168 } 40169 40170} 40171 40172function isUniqueEdge( start, end, edges ) { 40173 40174 const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`; 40175 const hash2 = `${end.x}
40175,${end.y},${end.z}-${start.x},${start.y},${start.z}`; // coincident edge 40176 40177 if ( edges.has( hash1 ) === true || edges.has( hash2 ) === true ) { 40178 40179 return false; 40180 40181 } else { 40182 40183 edges.add( hash1 ); 40184 edges.add( hash2 ); 40185 return true; 40186 40187 } 40188 40189} 40190 40191var Geometries = /*#__PURE__*/Object.freeze({ 40192 __proto__: null, 40193 BoxGeometry: BoxGeometry, 40194 CapsuleGeometry: CapsuleGeometry, 40195 CircleGeometry: CircleGeometry, 40196 ConeGeometry: ConeGeometry, 40197 CylinderGeometry: CylinderGeometry, 40198 DodecahedronGeometry: DodecahedronGeometry, 40199 EdgesGeometry: EdgesGeometry, 40200 ExtrudeGeometry: ExtrudeGeometry, 40201 IcosahedronGeometry: IcosahedronGeometry, 40202 LatheGeometry: LatheGeometry, 40203 OctahedronGeometry: OctahedronGeometry, 40204 PlaneGeometry: PlaneGeometry, 40205 PolyhedronGeometry: PolyhedronGeometry, 40206 RingGeometry: RingGeometry, 40207 ShapeGeometry: ShapeGeometry, 40208 SphereGeometry: SphereGeometry, 40209 TetrahedronGeometry: TetrahedronGeometry, 40210 TorusGeometry: TorusGeometry, 40211 TorusKnotGeometry: TorusKnotGeometry, 40212 TubeGeometry: TubeGeometry, 40213 WireframeGeometry: WireframeGeometry 40214}); 40215 40216class ShadowMaterial extends Material { 40217 40218 constructor( parameters ) { 40219 40220 super(); 40221 40222 this.isShadowMaterial = true; 40223 40224 this.type = 'ShadowMaterial'; 40225 40226 this.color = new Color( 0x000000 ); 40227 this.transparent = true; 40228 40229 this.fog = true; 40230 40231 this.setValues( parameters ); 40232 40233 } 40234 40235 copy( source ) { 40236 40237 super.copy( source ); 40238 40239 this.color.copy( source.color ); 40240 40241 this.fog = source.fog; 40242 40243 return this; 40244 40245 } 40246 40247} 40248 40249class RawShaderMaterial extends ShaderMaterial { 40250 40251 constructor( parameters ) { 40252 40253 super( parameters ); 40254 40255 this.isRawShaderMaterial = true; 40256 40257 this.type = 'RawShaderMaterial'; 40258 40259 } 40260 40261} 40262 40263class MeshStandardMaterial extends Material { 40264 40265 constructor( parameters ) { 40266 40267 super(); 40268 40269 this.isMeshStandardMaterial = true; 40270 40271 this.defines = { 'STANDARD': '' }; 40272 40273 this.type = 'MeshStandardMaterial'; 40274 40275 this.color = new Color( 0xffffff ); // diffuse 40276 this.roughness = 1.0; 40277 this.metalness = 0.0; 40278 40279 this.map = null; 40280 40281 this.lightMap = null; 40282 this.lightMapIntensity = 1.0; 40283 40284 this.aoMap = null; 40285 this.aoMapIntensity = 1.0; 40286 40287 this.emissive = new Color( 0x000000 ); 40288 this.emissiveIntensity = 1.0; 40289 this.emissiveMap = null; 40290 40291 this.bumpMap = null; 40292 this.bumpScale = 1; 40293 40294 this.normalMap = null; 40295 this.normalMapType = TangentSpaceNormalMap; 40296 this.normalScale = new Vector2( 1, 1 ); 40297 40298 this.displacementMap = null; 40299 this.displacementScale = 1; 40300 this.displacementBias = 0; 40301 40302 this.roughnessMap = null; 40303 40304 this.metalnessMap = null; 40305 40306 this.alphaMap = null; 40307 40308 this.envMap = null; 40309 this.envMapRotation = new Euler(); 40310 this.envMapIntensity = 1.0; 40311 40312 this.wireframe = false; 40313 this.wireframeLinewidth = 1; 40314 this.wireframeLinecap = 'round'; 40315 this.wireframeLinejoin = 'round'; 40316 40317 this.flatShading = false; 40318 40319 this.fog = true; 40320 40321 this.setValues( parameters ); 40322 40323 } 40324 40325 copy( source ) { 40326 40327 super.copy( source ); 40328 40329 this.defines = { 'STANDARD': '' }; 40330 40331 this.color.copy( source.color ); 40332 this.roughness = source.roughness; 40333 this.metalness = source.metalness; 40334 40335 this.map = source.map; 40336 40337 this.lightMap = source.lightMap; 40338 this.lightMapIntensity = source.lightMapIntensity; 40339 40340 this.aoMap = source.aoMap; 40341 this.aoMapIntensity = source.aoMapIntensity; 40342 40343 this.emissive.copy( source.emissive ); 40344 this.emissiveMap = source.emissiveMap; 40345 this.emissiveIntensity = source.emissiveIntensity; 40346 40347 this.bumpMap = source.bumpMap; 40348 this.bumpScale = source.bumpScale; 40349 40350 this.normalMap = source.normalMap; 40351 this.normalMapType = source.normalMapType; 40352 this.normalScale.copy( source.normalScale ); 40353 40354 this.displacementMap = source.displacementMap; 40355 this.displacementScale = source.displacementScale; 40356 this.displacementBias = source.displacementBias; 40357 40358 this.roughnessMap = source.roughnessMap; 40359 40360 this.metalnessMap = source.metalnessMap; 40361 40362 this.alphaMap = source.alphaMap; 40363 40364 this.envMap = source.envMap; 40365 this.envMapRotation.copy( source.envMapRotation ); 40366 this.envMapIntensity = source.envMapIntensity; 40367 40368 this.wireframe = source.wireframe; 40369 this.wireframeLinewidth = source.wireframeLinewidth; 40370 this.wireframeLinecap = source.wireframeLinecap; 40371 this.wireframeLinejoin = source.wireframeLinejoin; 40372
vendor: 5,146 bytes, lines 40373-40648
40373 this.flatShading = source.flatShading; 40374 40375 this.fog = source.fog; 40376 40377 return this; 40378 40379 } 40380 40381} 40382 40383class MeshPhysicalMaterial extends MeshStandardMaterial { 40384 40385 constructor( parameters ) { 40386 40387 super(); 40388 40389 this.isMeshPhysicalMaterial = true; 40390 40391 this.defines = { 40392 40393 'STANDARD': '', 40394 'PHYSICAL': '' 40395 40396 }; 40397 40398 this.type = 'MeshPhysicalMaterial'; 40399 40400 this.anisotropyRotation = 0; 40401 this.anisotropyMap = null; 40402 40403 this.clearcoatMap = null; 40404 this.clearcoatRoughness = 0.0; 40405 this.clearcoatRoughnessMap = null; 40406 this.clearcoatNormalScale = new Vector2( 1, 1 ); 40407 this.clearcoatNormalMap = null; 40408 40409 this.ior = 1.5; 40410 40411 Object.defineProperty( this, 'reflectivity', { 40412 get: function () { 40413 40414 return ( clamp( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) ); 40415 40416 }, 40417 set: function ( reflectivity ) { 40418 40419 this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity ); 40420 40421 } 40422 } ); 40423 40424 this.iridescenceMap = null; 40425 this.iridescenceIOR = 1.3; 40426 this.iridescenceThicknessRange = [ 100, 400 ]; 40427 this.iridescenceThicknessMap = null; 40428 40429 this.sheenColor = new Color( 0x000000 ); 40430 this.sheenColorMap = null; 40431 this.sheenRoughness = 1.0; 40432 this.sheenRoughnessMap = null; 40433 40434 this.transmissionMap = null; 40435 40436 this.thickness = 0; 40437 this.thicknessMap = null; 40438 this.attenuationDistance = Infinity; 40439 this.attenuationColor = new Color( 1, 1, 1 ); 40440 40441 this.specularIntensity = 1.0; 40442 this.specularIntensityMap = null; 40443 this.specularColor = new Color( 1, 1, 1 ); 40444 this.specularColorMap = null; 40445 40446 this._anisotropy = 0; 40447 this._clearcoat = 0; 40448 this._iridescence = 0; 40449 this._sheen = 0.0; 40450 this._transmission = 0; 40451 40452 this.setValues( parameters ); 40453 40454 } 40455 40456 get anisotropy() { 40457 40458 return this._anisotropy; 40459 40460 } 40461 40462 set anisotropy( value ) { 40463 40464 if ( this._anisotropy > 0 !== value > 0 ) { 40465 40466 this.version ++; 40467 40468 } 40469 40470 this._anisotropy = value; 40471 40472 } 40473 40474 get clearcoat() { 40475 40476 return this._clearcoat; 40477 40478 } 40479 40480 set clearcoat( value ) { 40481 40482 if ( this._clearcoat > 0 !== value > 0 ) { 40483 40484 this.version ++; 40485 40486 } 40487 40488 this._clearcoat = value; 40489 40490 } 40491 40492 get iridescence() { 40493 40494 return this._iridescence; 40495 40496 } 40497 40498 set iridescence( value ) { 40499 40500 if ( this._iridescence > 0 !== value > 0 ) { 40501 40502 this.version ++; 40503 40504 } 40505 40506 this._iridescence = value; 40507 40508 } 40509 40510 get sheen() { 40511 40512 return this._sheen; 40513 40514 } 40515 40516 set sheen( value ) { 40517 40518 if ( this._sheen > 0 !== value > 0 ) { 40519 40520 this.version ++; 40521 40522 } 40523 40524 this._sheen = value; 40525 40526 } 40527 40528 get transmission() { 40529 40530 return this._transmission; 40531 40532 } 40533 40534 set transmission( value ) { 40535 40536 if ( this._transmission > 0 !== value > 0 ) { 40537 40538 this.version ++; 40539 40540 } 40541 40542 this._transmission = value; 40543 40544 } 40545 40546 copy( source ) { 40547 40548 super.copy( source ); 40549 40550 this.defines = { 40551 40552 'STANDARD': '', 40553 'PHYSICAL': '' 40554 40555 }; 40556 40557 this.anisotropy = source.anisotropy; 40558 this.anisotropyRotation = source.anisotropyRotation; 40559 this.anisotropyMap = source.anisotropyMap; 40560 40561 this.clearcoat = source.clearcoat; 40562 this.clearcoatMap = source.clearcoatMap; 40563 this.clearcoatRoughness = source.clearcoatRoughness; 40564 this.clearcoatRoughnessMap = source.clearcoatRoughnessMap; 40565 this.clearcoatNormalMap = source.clearcoatNormalMap; 40566 this.clearcoatNormalScale.copy( source.clearcoatNormalScale ); 40567 40568 this.ior = source.ior; 40569 40570 this.iridescence = source.iridescence; 40571 this.iridescenceMap = source.iridescenceMap; 40572 this.iridescenceIOR = source.iridescenceIOR; 40573 this.iridescenceThicknessRange = [ ...source.iridescenceThicknessRange ]; 40574 this.iridescenceThicknessMap = source.iridescenceThicknessMap; 40575 40576 this.sheen = source.sheen; 40577 this.sheenColor.copy( source.sheenColor ); 40578 this.sheenColorMap = source.sheenColorMap; 40579 this.sheenRoughness = source.sheenRoughness; 40580 this.sheenRoughnessMap = source.sheenRoughnessMap; 40581 40582 this.transmission = source.transmission; 40583 this.transmissionMap = source.transmissionMap; 40584 40585 this.thickness = source.thickness; 40586 this.thicknessMap = source.thicknessMap; 40587 this.attenuationDistance = source.attenuationDistance; 40588 this.attenuationColor.copy( source.attenuationColor ); 40589 40590 this.specularIntensity = source.specularIntensity; 40591 this.specularIntensityMap = source.specularIntensityMap; 40592 this.specularColor.copy( source.specularColor ); 40593 this.specularColorMap = source.specularColorMap; 40594 40595 return this; 40596 40597 } 40598 40599} 40600 40601class MeshPhongMaterial extends Material { 40602 40603 constructor( parameters ) { 40604 40605 super(); 40606 40607 this.isMeshPhongMaterial = true; 40608 40609 this.type = 'MeshPhongMaterial'; 40610 40611 this.color = new Color( 0xffffff ); // diffuse 40612 this.specular = new Color( 0x111111 ); 40613 this.shininess = 30; 40614 40615 this.map = null; 40616 40617 this.lightMap = null; 40618 this.lightMapIntensity = 1.0; 40619 40620 this.aoMap = null; 40621 this.aoMapIntensity = 1.0; 40622 40623 this.emissive = new Color( 0x000000 ); 40624 this.emissiveIntensity = 1.0; 40625 this.emissiveMap = null; 40626 40627 this.bumpMap = null; 40628 this.bumpScale = 1; 40629 40630 this.normalMap = null; 40631 this.normalMapType = TangentSpaceNormalMap; 40632 this.normalScale = new Vector2( 1, 1 ); 40633 40634 this.displacementMap = null; 40635 this.displacementScale = 1; 40636 this.displacementBias = 0; 40637 40638 this.specularMap = null; 40639 40640 this.alphaMap = null; 40641 40642 this.envMap = null; 40643 this.envMapRotation = new Euler(); 40644 this.combine = MultiplyOperation; 40645 this.reflectivity = 1; 40646 this.refractionRatio = 0.98; 40647 40648 this.wireframe = false;
40649 this.wireframeLinewidth = 1; 40650 this.wireframeLinecap = 'round'; 40651 this.wireframeLinejoin = 'round'; 40652 40653 this.flatShading = false; 40654 40655 this.fog = true; 40656 40657 this.setValues( parameters ); 40658 40659 } 40660 40661 copy( source ) { 40662 40663 super.copy( source ); 40664 40665 this.color.copy( source.color ); 40666 this.specular.copy( source.specular ); 40667 this.shininess = source.shininess; 40668 40669 this.map = source.map; 40670 40671 this.lightMap = source.lightMap; 40672 this.lightMapIntensity = source.lightMapIntensity; 40673 40674 this.aoMap = source.aoMap; 40675 this.aoMapIntensity = source.aoMapIntensity; 40676 40677 this.emissive.copy( source.emissive ); 40678 this.emissiveMap = source.emissiveMap; 40679 this.emissiveIntensity = source.emissiveIntensity; 40680 40681 this.bumpMap = source.bumpMap; 40682 this.bumpScale = source.bumpScale; 40683 40684 this.normalMap = source.normalMap; 40685 this.normalMapType = source.normalMapType; 40686 this.normalScale.copy( source.normalScale ); 40687 40688 this.displacementMap = source.displacementMap; 40689 this.displacementScale = source.displacementScale; 40690 this.displacementBias = source.displacementBias; 40691 40692 this.specularMap = source.specularMap; 40693 40694 this.alphaMap = source.alphaMap; 40695 40696 this.envMap = source.envMap; 40697 this.envMapRotation.copy( source.envMapRotation ); 40698 this.combine = source.combine; 40699 this.reflectivity = source.reflectivity; 40700 this.refractionRatio = source.refractionRatio; 40701 40702 this.wireframe = source.wireframe; 40703 this.wireframeLinewidth = source.wireframeLinewidth; 40704 this.wireframeLinecap = source.wireframeLinecap; 40705 this.wireframeLinejoin = source.wireframeLinejoin; 40706 40707 this.flatShading = source.flatShading; 40708 40709 this.fog = source.fog; 40710 40711 return this; 40712 40713 } 40714 40715} 40716 40717class MeshToonMaterial extends Material { 40718 40719 constructor( parameters ) { 40720 40721 super(); 40722 40723 this.isMeshToonMaterial = true; 40724 40725 this.defines = { 'TOON': '' }; 40726 40727 this.type = 'MeshToonMaterial'; 40728 40729 this.color = new Color( 0xffffff ); 40730 40731 this.map = null; 40732 this.gradientMap = null; 40733 40734 this.lightMap = null; 40735 this.lightMapIntensity = 1.0; 40736 40737 this.aoMap = null; 40738 this.aoMapIntensity = 1.0; 40739 40740 this.emissive = new Color( 0x000000 ); 40741 this.emissiveIntensity = 1.0; 40742 this.emissiveMap = null; 40743 40744 this.bumpMap = null; 40745 this.bumpScale = 1; 40746 40747 this.normalMap = null; 40748 this.normalMapType = TangentSpaceNormalMap; 40749 this.normalScale = new Vector2( 1, 1 ); 40750 40751 this.displacementMap = null; 40752 this.displacementScale = 1; 40753 this.displacementBias = 0; 40754 40755 this.alphaMap = null; 40756 40757 this.wireframe = false; 40758 this.wireframeLinewidth = 1; 40759 this.wireframeLinecap = 'round'; 40760 this.wireframeLinejoin = 'round'; 40761 40762 this.fog = true; 40763 40764 this.setValues( parameters ); 40765 40766 } 40767 40768 copy( source ) { 40769 40770 super.copy( source ); 40771 40772 this.color.copy( source.color ); 40773 40774 this.map = source.map; 40775 this.gradientMap = source.gradientMap; 40776 40777 this.lightMap = source.lightMap; 40778 this.lightMapIntensity = source.lightMapIntensity; 40779 40780 this.aoMap = source.aoMap; 40781 this.aoMapIntensity = source.aoMapIntensity; 40782 40783 this.emissive.copy( source.emissive ); 40784 this.emissiveMap = source.emissiveMap; 40785 this.emissiveIntensity = source.emissiveIntensity; 40786 40787 this.bumpMap = source.bumpMap; 40788 this.bumpScale = source.bumpScale; 40789 40790 this.normalMap = source.normalMap; 40791 this.normalMapType = source.normalMapType; 40792 this.normalScale.copy( source.normalScale ); 40793 40794 this.displacementMap = source.displacementMap; 40795 this.displacementScale = source.displacementScale; 40796 this.displacementBias = source.displacementBias; 40797 40798 this.alphaMap = source.alphaMap; 40799 40800 this.wireframe = source.wireframe; 40801 this.wireframeLinewidth = source.wireframeLinewidth; 40802 this.wireframeLinecap = source.wireframeLinecap; 40803 this.wireframeLinejoin = source.wireframeLinejoin; 40804 40805 this.fog = source.fog; 40806 40807 return this; 40808 40809 } 40810 40811} 40812 40813class MeshNormalMaterial extends Material { 40814 40815 constructor( parameters ) { 40816 40817 super(); 40818 40819 this.isMeshNormalMaterial = true; 40820 40821 this.type = 'MeshNormalMaterial'; 40822 40823 this.bumpMap = null; 40824 this.bumpScale = 1; 40825 40826 this.normalMap = null; 40827 this.normalMapType = TangentSpaceNormalMap; 40828 this.normalScale = new Vector2( 1, 1 ); 40829 40830 this.displacementMap = null; 40831 this.displacementScale = 1; 40832 this.displacementBias = 0; 40833 40834 this.wireframe = false; 40835 this.wireframeLinewidth = 1; 40836 40837 this.flatShading = false;
vendor: 20,656 bytes, lines 40838-41878
40838 40839 this.setValues( parameters ); 40840 40841 } 40842 40843 copy( source ) { 40844 40845 super.copy( source ); 40846 40847 this.bumpMap = source.bumpMap; 40848 this.bumpScale = source.bumpScale; 40849 40850 this.normalMap = source.normalMap; 40851 this.normalMapType = source.normalMapType; 40852 this.normalScale.copy( source.normalScale ); 40853 40854 this.displacementMap = source.displacementMap; 40855 this.displacementScale = source.displacementScale; 40856 this.displacementBias = source.displacementBias; 40857 40858 this.wireframe = source.wireframe; 40859 this.wireframeLinewidth = source.wireframeLinewidth; 40860 40861 this.flatShading = source.flatShading; 40862 40863 return this; 40864 40865 } 40866 40867} 40868 40869class MeshLambertMaterial extends Material { 40870 40871 constructor( parameters ) { 40872 40873 super(); 40874 40875 this.isMeshLambertMaterial = true; 40876 40877 this.type = 'MeshLambertMaterial'; 40878 40879 this.color = new Color( 0xffffff ); // diffuse 40880 40881 this.map = null; 40882 40883 this.lightMap = null; 40884 this.lightMapIntensity = 1.0; 40885 40886 this.aoMap = null; 40887 this.aoMapIntensity = 1.0; 40888 40889 this.emissive = new Color( 0x000000 ); 40890 this.emissiveIntensity = 1.0; 40891 this.emissiveMap = null; 40892 40893 this.bumpMap = null; 40894 this.bumpScale = 1; 40895 40896 this.normalMap = null; 40897 this.normalMapType = TangentSpaceNormalMap; 40898 this.normalScale = new Vector2( 1, 1 ); 40899 40900 this.displacementMap = null; 40901 this.displacementScale = 1; 40902 this.displacementBias = 0; 40903 40904 this.specularMap = null; 40905 40906 this.alphaMap = null; 40907 40908 this.envMap = null; 40909 this.envMapRotation = new Euler(); 40910 this.combine = MultiplyOperation; 40911 this.reflectivity = 1; 40912 this.refractionRatio = 0.98; 40913 40914 this.wireframe = false; 40915 this.wireframeLinewidth = 1; 40916 this.wireframeLinecap = 'round'; 40917 this.wireframeLinejoin = 'round'; 40918 40919 this.flatShading = false; 40920 40921 this.fog = true; 40922 40923 this.setValues( parameters ); 40924 40925 } 40926 40927 copy( source ) { 40928 40929 super.copy( source ); 40930 40931 this.color.copy( source.color ); 40932 40933 this.map = source.map; 40934 40935 this.lightMap = source.lightMap; 40936 this.lightMapIntensity = source.lightMapIntensity; 40937 40938 this.aoMap = source.aoMap; 40939 this.aoMapIntensity = source.aoMapIntensity; 40940 40941 this.emissive.copy( source.emissive ); 40942 this.emissiveMap = source.emissiveMap; 40943 this.emissiveIntensity = source.emissiveIntensity; 40944 40945 this.bumpMap = source.bumpMap; 40946 this.bumpScale = source.bumpScale; 40947 40948 this.normalMap = source.normalMap; 40949 this.normalMapType = source.normalMapType; 40950 this.normalScale.copy( source.normalScale ); 40951 40952 this.displacementMap = source.displacementMap; 40953 this.displacementScale = source.displacementScale; 40954 this.displacementBias = source.displacementBias; 40955 40956 this.specularMap = source.specularMap; 40957 40958 this.alphaMap = source.alphaMap; 40959 40960 this.envMap = source.envMap; 40961 this.envMapRotation.copy( source.envMapRotation ); 40962 this.combine = source.combine; 40963 this.reflectivity = source.reflectivity; 40964 this.refractionRatio = source.refractionRatio; 40965 40966 this.wireframe = source.wireframe; 40967 this.wireframeLinewidth = source.wireframeLinewidth; 40968 this.wireframeLinecap = source.wireframeLinecap; 40969 this.wireframeLinejoin = source.wireframeLinejoin; 40970 40971 this.flatShading = source.flatShading; 40972 40973 this.fog = source.fog; 40974 40975 return this; 40976 40977 } 40978 40979} 40980 40981class MeshMatcapMaterial extends Material { 40982 40983 constructor( parameters ) { 40984 40985 super(); 40986 40987 this.isMeshMatcapMaterial = true; 40988 40989 this.defines = { 'MATCAP': '' }; 40990 40991 this.type = 'MeshMatcapMaterial'; 40992 40993 this.color = new Color( 0xffffff ); // diffuse 40994 40995 this.matcap = null; 40996 40997 this.map = null; 40998 40999 this.bumpMap = null; 41000 this.bumpScale = 1; 41001 41002 this.normalMap = null; 41003 this.normalMapType = TangentSpaceNormalMap; 41004 this.normalScale = new Vector2( 1, 1 ); 41005 41006 this.displacementMap = null; 41007 this.displacementScale = 1; 41008 this.displacementBias = 0; 41009 41010 this.alphaMap = null; 41011 41012 this.flatShading = false; 41013 41014 this.fog = true; 41015 41016 this.setValues( parameters ); 41017 41018 } 41019 41020 41021 copy( source ) { 41022 41023 super.copy( source ); 41024 41025 this.defines = { 'MATCAP': '' }; 41026 41027 this.color.copy( source.color ); 41028 41029 this.matcap = source.matcap; 41030 41031 this.map = source.map; 41032 41033 this.bumpMap = source.bumpMap; 41034 this.bumpScale = source.bumpScale; 41035 41036 this.normalMap = source.normalMap; 41037 this.normalMapType = source.normalMapType; 41038 this.normalScale.copy( source.normalScale ); 41039 41040 this.displacementMap = source.displacementMap; 41041 this.displacementScale = source.displacementScale; 41042 this.displacementBias = source.displacementBias; 41043 41044 this.alphaMap = source.alphaMap; 41045 41046 this.flatShading = source.flatShading; 41047 41048 this.fog = source.fog; 41049 41050 return this; 41051 41052 } 41053 41054} 41055 41056class LineDashedMaterial extends LineBasicMaterial { 41057 41058 constructor( parameters ) { 41059 41060 super(); 41061 41062 this.isLineDashedMaterial = true; 41063 41064 this.type = 'LineDashedMaterial'; 41065 41066 this.scale = 1; 41067 this.dashSize = 3; 41068 this.gapSize = 1; 41069 41070 this.setValues( parameters ); 41071 41072 } 41073 41074 copy( source ) { 41075 41076 super.copy( source ); 41077 41078 this.scale = source.scale; 41079 this.dashSize = source.dashSize; 41080 this.gapSize = source.gapSize; 41081 41082 return this; 41083 41084 } 41085 41086} 41087 41088// converts an array to a specific type 41089function convertArray( array, type, forceClone ) { 41090 41091 if ( ! array || // let 'undefined' and 'null' pass 41092 ! forceClone && array.constructor === type ) return array; 41093 41094 if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { 41095 41096 return new type( array ); // create typed array 41097 41098 } 41099 41100 return Array.prototype.slice.call( array ); // create Array 41101 41102} 41103 41104function isTypedArray( object ) { 41105 41106 return ArrayBuffer.isView( object ) && 41107 ! ( object instanceof DataView ); 41108 41109} 41110 41111// returns an array by which times and values can be sorted 41112function getKeyframeOrder( times ) { 41113 41114 function compareTime( i, j ) { 41115 41116 return times[ i ] - times[ j ]; 41117 41118 } 41119 41120 const n = times.length; 41121 const result = new Array( n ); 41122 for ( let i = 0; i !== n; ++ i ) result[ i ] = i; 41123 41124 result.sort( compareTime ); 41125 41126 return result; 41127 41128} 41129 41130// uses the array previously returned by 'getKeyframeOrder' to sort data 41131function sortedArray( values, stride, order ) { 41132 41133 const nValues = values.length; 41134 const result = new values.constructor( nValues ); 41135 41136 for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { 41137 41138 const srcOffset = order[ i ] * stride; 41139 41140 for ( let j = 0; j !== stride; ++ j ) { 41141 41142 result[ dstOffset ++ ] = values[ srcOffset + j ]; 41143 41144 } 41145 41146 } 41147 41148 return result; 41149 41150} 41151 41152// function for parsing AOS keyframe formats 41153function flattenJSON( jsonKeys, times, values, valuePropertyName ) { 41154 41155 let i = 1, key = jsonKeys[ 0 ]; 41156 41157 while ( key !== undefined && key[ valuePropertyName ] === undefined ) { 41158 41159 key = jsonKeys[ i ++ ]; 41160 41161 } 41162 41163 if ( key === undefined ) return; // no data 41164 41165 let value = key[ valuePropertyName ]; 41166 if ( value === undefined ) return; // no data 41167 41168 if ( Array.isArray( value ) ) { 41169 41170 do { 41171 41172 value = key[ valuePropertyName ]; 41173 41174 if ( value !== undefined ) { 41175 41176 times.push( key.time ); 41177 values.push.apply( values, value ); // push all elements 41178 41179 } 41180 41181 key = jsonKeys[ i ++ ]; 41182 41183 } while ( key !== undefined ); 41184 41185 } else if ( value.toArray !== undefined ) { 41186 41187 // ...assume THREE.Math-ish 41188 41189 do { 41190 41191 value = key[ valuePropertyName ]; 41192 41193 if ( value !== undefined ) { 41194 41195 times.push( key.time ); 41196 value.toArray( values, values.length ); 41197 41198 } 41199 41200 key = jsonKeys[ i ++ ]; 41201 41202 } while ( key !== undefined ); 41203 41204 } else { 41205 41206 // otherwise push as-is 41207 41208 do { 41209 41210 value = key[ valuePropertyName ]; 41211 41212 if ( value !== undefined ) { 41213 41214 times.push( key.time ); 41215 values.push( value ); 41216 41217 } 41218 41219 key = jsonKeys[ i ++ ]; 41220 41221 } while ( key !== undefined ); 41222 41223 } 41224 41225} 41226 41227function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) { 41228 41229 const clip = sourceClip.clone(); 41230 41231 clip.name = name; 41232 41233 const tracks = []; 41234 41235 for ( let i = 0; i < clip.tracks.length; ++ i ) { 41236 41237 const track = clip.tracks[ i ]; 41238 const valueSize = track.getValueSize(); 41239 41240 const times = []; 41241 const values = []; 41242 41243 for ( let j = 0; j < track.times.length; ++ j ) { 41244 41245 const frame = track.times[ j ] * fps; 41246 41247 if ( frame < startFrame || frame >= endFrame ) continue; 41248 41249 times.push( track.times[ j ] ); 41250 41251 for ( let k = 0; k < valueSize; ++ k ) { 41252 41253 values.push( track.values[ j * valueSize + k ] ); 41254 41255 } 41256 41257 } 41258 41259 if ( times.length === 0 ) continue; 41260 41261 track.times = convertArray( times, track.times.constructor ); 41262 track.values = convertArray( values, track.values.constructor ); 41263 41264 tracks.push( track ); 41265 41266 } 41267 41268 clip.tracks = tracks; 41269 41270 // find minimum .times value across all tracks in the trimmed clip 41271 41272 let minStartTime = Infinity; 41273 41274 for ( let i = 0; i < clip.tracks.length; ++ i ) { 41275 41276 if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) { 41277 41278 minStartTime = clip.tracks[ i ].times[ 0 ]; 41279 41280 } 41281 41282 } 41283 41284 // shift all tracks such that clip begins at t=0 41285 41286 for ( let i = 0; i < clip.tracks.length; ++ i ) { 41287 41288 clip.tracks[ i ].shift( - 1 * minStartTime ); 41289 41290 } 41291 41292 clip.resetDuration(); 41293 41294 return clip; 41295 41296} 41297 41298function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) { 41299 41300 if ( fps <= 0 ) fps = 30; 41301 41302 const numTracks = referenceClip.tracks.length; 41303 const referenceTime = referenceFrame / fps; 41304 41305 // Make each track's values relative to the values at the reference frame 41306 for ( let i = 0; i < numTracks; ++ i ) { 41307 41308 const referenceTrack = referenceClip.tracks[ i ]; 41309 const referenceTrackType = referenceTrack.ValueTypeName; 41310 41311 // Skip this track if it's non-numeric 41312 if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue; 41313 41314 // Find the track in the target clip whose name and type matches the reference track 41315 const targetTrack = targetClip.tracks.find( function ( track ) { 41316 41317 return track.name === referenceTrack.name 41318 && track.ValueTypeName === referenceTrackType; 41319 41320 } ); 41321 41322 if ( targetTrack === undefined ) continue; 41323 41324 let referenceOffset = 0; 41325 const referenceValueSize = referenceTrack.getValueSize(); 41326 41327 if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { 41328 41329 referenceOffset = referenceValueSize / 3; 41330 41331 } 41332 41333 let targetOffset = 0; 41334 const targetValueSize = targetTrack.getValueSize(); 41335 41336 if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { 41337 41338 targetOffset = targetValueSize / 3; 41339 41340 } 41341 41342 const lastIndex = referenceTrack.times.length - 1; 41343 let referenceValue; 41344 41345 // Find the value to subtract out of the track 41346 if ( referenceTime <= referenceTrack.times[ 0 ] ) { 41347 41348 // Reference frame is earlier than the first keyframe, so just use the first keyframe 41349 const startIndex = referenceOffset; 41350 const endIndex = referenceValueSize - referenceOffset; 41351 referenceValue = referenceTrack.values.slice( startIndex, endIndex ); 41352 41353 } else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) { 41354 41355 // Reference frame is after the last keyframe, so just use the last keyframe 41356 const startIndex = lastIndex * referenceValueSize + referenceOffset; 41357 const endIndex = startIndex + referenceValueSize - referenceOffset; 41358 referenceValue = referenceTrack.values.slice( startIndex, endIndex ); 41359 41360 } else { 41361 41362 // Interpolate to the reference value 41363 const interpolant = referenceTrack.createInterpolant(); 41364 const startIndex = referenceOffset; 41365 const endIndex = referenceValueSize - referenceOffset; 41366 interpolant.evaluate( referenceTime ); 41367 referenceValue = interpolant.resultBuffer.slice( startIndex, endIndex ); 41368 41369 } 41370 41371 // Conjugate the quaternion 41372 if ( referenceTrackType === 'quaternion' ) { 41373 41374 const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate(); 41375 referenceQuat.toArray( referenceValue ); 41376 41377 } 41378 41379 // Subtract the reference value from all of the track values 41380 41381 const numTimes = targetTrack.times.length; 41382 for ( let j = 0; j < numTimes; ++ j ) { 41383 41384 const valueStart = j * targetValueSize + targetOffset; 41385 41386 if ( referenceTrackType === 'quaternion' ) { 41387 41388 // Multiply the conjugate for quaternion track types 41389 Quaternion.multiplyQuaternionsFlat( 41390 targetTrack.values, 41391 valueStart, 41392 referenceValue, 41393 0, 41394 targetTrack.values, 41395 valueStart 41396 ); 41397 41398 } else { 41399 41400 const valueEnd = targetValueSize - targetOffset * 2; 41401 41402 // Subtract each value for all other numeric track types 41403 for ( let k = 0; k < valueEnd; ++ k ) { 41404 41405 targetTrack.values[ valueStart + k ] -= referenceValue[ k ]; 41406 41407 } 41408 41409 } 41410 41411 } 41412 41413 } 41414 41415 targetClip.blendMode = AdditiveAnimationBlendMode; 41416 41417 return targetClip; 41418 41419} 41420 41421const AnimationUtils = { 41422 convertArray: convertArray, 41423 isTypedArray: isTypedArray, 41424 getKeyframeOrder: getKeyframeOrder, 41425 sortedArray: sortedArray, 41426 flattenJSON: flattenJSON, 41427 subclip: subclip, 41428 makeClipAdditive: makeClipAdditive 41429}; 41430 41431/** 41432 * Abstract base class of interpolants over parametric samples. 41433 * 41434 * The parameter domain is one dimensional, typically the time or a path 41435 * along a curve defined by the data. 41436 * 41437 * The sample values can have any dimensionality and derived classes may 41438 * apply special interpretations to the data. 41439 * 41440 * This class provides the interval seek in a Template Method, deferring 41441 * the actual interpolation to derived classes. 41442 * 41443 * Time complexity is O(1) for linear access crossing at most two points 41444 * and O(log N) for random access, where N is the number of positions. 41445 * 41446 * References: 41447 * 41448 * http://www.oodesign.com/template-method-pattern.html 41449 * 41450 */ 41451 41452class Interpolant { 41453 41454 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 41455 41456 this.parameterPositions = parameterPositions; 41457 this._cachedIndex = 0; 41458 41459 this.resultBuffer = resultBuffer !== undefined ? 41460 resultBuffer : new sampleValues.constructor( sampleSize ); 41461 this.sampleValues = sampleValues; 41462 this.valueSize = sampleSize; 41463 41464 this.settings = null; 41465 this.DefaultSettings_ = {}; 41466 41467 } 41468 41469 evaluate( t ) { 41470 41471 const pp = this.parameterPositions; 41472 let i1 = this._cachedIndex, 41473 t1 = pp[ i1 ], 41474 t0 = pp[ i1 - 1 ]; 41475 41476 validate_interval: { 41477 41478 seek: { 41479 41480 let right; 41481 41482 linear_scan: { 41483 41484 //- See http://jsperf.com/comparison-to-undefined/3 41485 //- slower code: 41486 //- 41487 //- if ( t >= t1 || t1 === undefined ) { 41488 forward_scan: if ( ! ( t < t1 ) ) { 41489 41490 for ( let giveUpAt = i1 + 2; ; ) { 41491 41492 if ( t1 === undefined ) { 41493 41494 if ( t < t0 ) break forward_scan; 41495 41496 // after end 41497 41498 i1 = pp.length; 41499 this._cachedIndex = i1; 41500 return this.copySampleValue_( i1 - 1 ); 41501 41502 } 41503 41504 if ( i1 === giveUpAt ) break; // this loop 41505 41506 t0 = t1; 41507 t1 = pp[ ++ i1 ]; 41508 41509 if ( t < t1 ) { 41510 41511 // we have arrived at the sought interval 41512 break seek; 41513 41514 } 41515 41516 } 41517 41518 // prepare binary search on the right side of the index 41519 right = pp.length; 41520 break linear_scan; 41521 41522 } 41523 41524 //- slower code: 41525 //- if ( t < t0 || t0 === undefined ) { 41526 if ( ! ( t >= t0 ) ) { 41527 41528 // looping? 41529 41530 const t1global = pp[ 1 ]; 41531 41532 if ( t < t1global ) { 41533 41534 i1 = 2; // + 1, using the scan for the details 41535 t0 = t1global; 41536 41537 } 41538 41539 // linear reverse scan 41540 41541 for ( let giveUpAt = i1 - 2; ; ) { 41542 41543 if ( t0 === undefined ) { 41544 41545 // before start 41546 41547 this._cachedIndex = 0; 41548 return this.copySampleValue_( 0 ); 41549 41550 } 41551 41552 if ( i1 === giveUpAt ) break; // this loop 41553 41554 t1 = t0; 41555 t0 = pp[ -- i1 - 1 ]; 41556 41557 if ( t >= t0 ) { 41558 41559 // we have arrived at the sought interval 41560 break seek; 41561 41562 } 41563 41564 } 41565 41566 // prepare binary search on the left side of the index 41567 right = i1; 41568 i1 = 0; 41569 break linear_scan; 41570 41571 } 41572 41573 // the interval is valid 41574 41575 break validate_interval; 41576 41577 } // linear scan 41578 41579 // binary search 41580 41581 while ( i1 < right ) { 41582 41583 const mid = ( i1 + right ) >>> 1; 41584 41585 if ( t < pp[ mid ] ) { 41586 41587 right = mid; 41588 41589 } else { 41590 41591 i1 = mid + 1; 41592 41593 } 41594 41595 } 41596 41597 t1 = pp[ i1 ]; 41598 t0 = pp[ i1 - 1 ]; 41599 41600 // check boundary cases, again 41601 41602 if ( t0 === undefined ) { 41603 41604 this._cachedIndex = 0; 41605 return this.copySampleValue_( 0 ); 41606 41607 } 41608 41609 if ( t1 === undefined ) { 41610 41611 i1 = pp.length; 41612 this._cachedIndex = i1; 41613 return this.copySampleValue_( i1 - 1 ); 41614 41615 } 41616 41617 } // seek 41618 41619 this._cachedIndex = i1; 41620 41621 this.intervalChanged_( i1, t0, t1 ); 41622 41623 } // validate_interval 41624 41625 return this.interpolate_( i1, t0, t, t1 ); 41626 41627 } 41628 41629 getSettings_() { 41630 41631 return this.settings || this.DefaultSettings_; 41632 41633 } 41634 41635 copySampleValue_( index ) { 41636 41637 // copies a sample value to the result buffer 41638 41639 const result = this.resultBuffer, 41640 values = this.sampleValues, 41641 stride = this.valueSize, 41642 offset = index * stride; 41643 41644 for ( let i = 0; i !== stride; ++ i ) { 41645 41646 result[ i ] = values[ offset + i ]; 41647 41648 } 41649 41650 return result; 41651 41652 } 41653 41654 // Template methods for derived classes: 41655 41656 interpolate_( /* i1, t0, t, t1 */ ) { 41657 41658 throw new Error( 'call to abstract method' ); 41659 // implementations shall return this.resultBuffer 41660 41661 } 41662 41663 intervalChanged_( /* i1, t0, t1 */ ) { 41664 41665 // empty 41666 41667 } 41668 41669} 41670 41671/** 41672 * Fast and simple cubic spline interpolant. 41673 * 41674 * It was derived from a Hermitian construction setting the first derivative 41675 * at each sample position to the linear slope between neighboring positions 41676 * over their parameter interval. 41677 */ 41678 41679class CubicInterpolant extends Interpolant { 41680 41681 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 41682 41683 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 41684 41685 this._weightPrev = - 0; 41686 this._offsetPrev = - 0; 41687 this._weightNext = - 0; 41688 this._offsetNext = - 0; 41689 41690 this.DefaultSettings_ = { 41691 41692 endingStart: ZeroCurvatureEnding, 41693 endingEnd: ZeroCurvatureEnding 41694 41695 }; 41696 41697 } 41698 41699 intervalChanged_( i1, t0, t1 ) { 41700 41701 const pp = this.parameterPositions; 41702 let iPrev = i1 - 2, 41703 iNext = i1 + 1, 41704 41705 tPrev = pp[ iPrev ], 41706 tNext = pp[ iNext ]; 41707 41708 if ( tPrev === undefined ) { 41709 41710 switch ( this.getSettings_().endingStart ) { 41711 41712 case ZeroSlopeEnding: 41713 41714 // f'(t0) = 0 41715 iPrev = i1; 41716 tPrev = 2 * t0 - t1; 41717 41718 break; 41719 41720 case WrapAroundEnding: 41721 41722 // use the other end of the curve 41723 iPrev = pp.length - 2; 41724 tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; 41725 41726 break; 41727 41728 default: // ZeroCurvatureEnding 41729 41730 // f''(t0) = 0 a.k.a. Natural Spline 41731 iPrev = i1; 41732 tPrev = t1; 41733 41734 } 41735 41736 } 41737 41738 if ( tNext === undefined ) { 41739 41740 switch ( this.getSettings_().endingEnd ) { 41741 41742 case ZeroSlopeEnding: 41743 41744 // f'(tN) = 0 41745 iNext = i1; 41746 tNext = 2 * t1 - t0; 41747 41748 break; 41749 41750 case WrapAroundEnding: 41751 41752 // use the other end of the curve 41753 iNext = 1; 41754 tNext = t1 + pp[ 1 ] - pp[ 0 ]; 41755 41756 break; 41757 41758 default: // ZeroCurvatureEnding 41759 41760 // f''(tN) = 0, a.k.a. Natural Spline 41761 iNext = i1 - 1; 41762 tNext = t0; 41763 41764 } 41765 41766 } 41767 41768 const halfDt = ( t1 - t0 ) * 0.5, 41769 stride = this.valueSize; 41770 41771 this._weightPrev = halfDt / ( t0 - tPrev ); 41772 this._weightNext = halfDt / ( tNext - t1 ); 41773 this._offsetPrev = iPrev * stride; 41774 this._offsetNext = iNext * stride; 41775 41776 } 41777 41778 interpolate_( i1, t0, t, t1 ) { 41779 41780 const result = this.resultBuffer, 41781 values = this.sampleValues, 41782 stride = this.valueSize, 41783 41784 o1 = i1 * stride, o0 = o1 - stride, 41785 oP = this._offsetPrev, oN = this._offsetNext, 41786 wP = this._weightPrev, wN = this._weightNext, 41787 41788 p = ( t - t0 ) / ( t1 - t0 ), 41789 pp = p * p, 41790 ppp = pp * p; 41791 41792 // evaluate polynomials 41793 41794 const sP = - wP * ppp + 2 * wP * pp - wP * p; 41795 const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1; 41796 const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p; 41797 const sN = wN * ppp - wN * pp; 41798 41799 // combine data linearly 41800 41801 for ( let i = 0; i !== stride; ++ i ) { 41802 41803 result[ i ] = 41804 sP * values[ oP + i ] + 41805 s0 * values[ o0 + i ] + 41806 s1 * values[ o1 + i ] + 41807 sN * values[ oN + i ]; 41808 41809 } 41810 41811 return result; 41812 41813 } 41814 41815} 41816 41817class LinearInterpolant extends Interpolant { 41818 41819 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 41820 41821 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 41822 41823 } 41824 41825 interpolate_( i1, t0, t, t1 ) { 41826 41827 const result = this.resultBuffer, 41828 values = this.sampleValues, 41829 stride = this.valueSize, 41830 41831 offset1 = i1 * stride, 41832 offset0 = offset1 - stride, 41833 41834 weight1 = ( t - t0 ) / ( t1 - t0 ), 41835 weight0 = 1 - weight1; 41836 41837 for ( let i = 0; i !== stride; ++ i ) { 41838 41839 result[ i ] = 41840 values[ offset0 + i ] * weight0 + 41841 values[ offset1 + i ] * weight1; 41842 41843 } 41844 41845 return result; 41846 41847 } 41848 41849} 41850 41851/** 41852 * 41853 * Interpolant that evaluates to the sample value at the position preceding 41854 * the parameter. 41855 */ 41856 41857class DiscreteInterpolant extends Interpolant { 41858 41859 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 41860 41861 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 41862 41863 } 41864 41865 interpolate_( i1 /*, t0, t, t1 */ ) { 41866 41867 return this.copySampleValue_( i1 - 1 ); 41868 41869 } 41870 41871} 41872 41873class KeyframeTrack { 41874 41875 constructor( name, times, values, interpolation ) { 41876 41877 if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); 41878 if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + n
vendor: 22,253 bytes, lines 41878-43068
41878ame ); 41879 41880 this.name = name; 41881 41882 this.times = convertArray( times, this.TimeBufferType ); 41883 this.values = convertArray( values, this.ValueBufferType ); 41884 41885 this.setInterpolation( interpolation || this.DefaultInterpolation ); 41886 41887 } 41888 41889 // Serialization (in static context, because of constructor invocation 41890 // and automatic invocation of .toJSON): 41891 41892 static toJSON( track ) { 41893 41894 const trackType = track.constructor; 41895 41896 let json; 41897 41898 // derived classes can define a static toJSON method 41899 if ( trackType.toJSON !== this.toJSON ) { 41900 41901 json = trackType.toJSON( track ); 41902 41903 } else { 41904 41905 // by default, we assume the data can be serialized as-is 41906 json = { 41907 41908 'name': track.name, 41909 'times': convertArray( track.times, Array ), 41910 'values': convertArray( track.values, Array ) 41911 41912 }; 41913 41914 const interpolation = track.getInterpolation(); 41915 41916 if ( interpolation !== track.DefaultInterpolation ) { 41917 41918 json.interpolation = interpolation; 41919 41920 } 41921 41922 } 41923 41924 json.type = track.ValueTypeName; // mandatory 41925 41926 return json; 41927 41928 } 41929 41930 InterpolantFactoryMethodDiscrete( result ) { 41931 41932 return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); 41933 41934 } 41935 41936 InterpolantFactoryMethodLinear( result ) { 41937 41938 return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); 41939 41940 } 41941 41942 InterpolantFactoryMethodSmooth( result ) { 41943 41944 return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); 41945 41946 } 41947 41948 setInterpolation( interpolation ) { 41949 41950 let factoryMethod; 41951 41952 switch ( interpolation ) { 41953 41954 case InterpolateDiscrete: 41955 41956 factoryMethod = this.InterpolantFactoryMethodDiscrete; 41957 41958 break; 41959 41960 case InterpolateLinear: 41961 41962 factoryMethod = this.InterpolantFactoryMethodLinear; 41963 41964 break; 41965 41966 case InterpolateSmooth: 41967 41968 factoryMethod = this.InterpolantFactoryMethodSmooth; 41969 41970 break; 41971 41972 } 41973 41974 if ( factoryMethod === undefined ) { 41975 41976 const message = 'unsupported interpolation for ' + 41977 this.ValueTypeName + ' keyframe track named ' + this.name; 41978 41979 if ( this.createInterpolant === undefined ) { 41980 41981 // fall back to default, unless the default itself is messed up 41982 if ( interpolation !== this.DefaultInterpolation ) { 41983 41984 this.setInterpolation( this.DefaultInterpolation ); 41985 41986 } else { 41987 41988 throw new Error( message ); // fatal, in this case 41989 41990 } 41991 41992 } 41993 41994 console.warn( 'THREE.KeyframeTrack:', message ); 41995 return this; 41996 41997 } 41998 41999 this.createInterpolant = factoryMethod; 42000 42001 return this; 42002 42003 } 42004 42005 getInterpolation() { 42006 42007 switch ( this.createInterpolant ) { 42008 42009 case this.InterpolantFactoryMethodDiscrete: 42010 42011 return InterpolateDiscrete; 42012 42013 case this.InterpolantFactoryMethodLinear: 42014 42015 return InterpolateLinear; 42016 42017 case this.InterpolantFactoryMethodSmooth: 42018 42019 return InterpolateSmooth; 42020 42021 } 42022 42023 } 42024 42025 getValueSize() { 42026 42027 return this.values.length / this.times.length; 42028 42029 } 42030 42031 // move all keyframes either forwards or backwards in time 42032 shift( timeOffset ) { 42033 42034 if ( timeOffset !== 0.0 ) { 42035 42036 const times = this.times; 42037 42038 for ( let i = 0, n = times.length; i !== n; ++ i ) { 42039 42040 times[ i ] += timeOffset; 42041 42042 } 42043 42044 } 42045 42046 return this; 42047 42048 } 42049 42050 // scale all keyframe times by a factor (useful for frame <-> seconds conversions) 42051 scale( timeScale ) { 42052 42053 if ( timeScale !== 1.0 ) { 42054 42055 const times = this.times; 42056 42057 for ( let i = 0, n = times.length; i !== n; ++ i ) { 42058 42059 times[ i ] *= timeScale; 42060 42061 } 42062 42063 } 42064 42065 return this; 42066 42067 } 42068 42069 // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. 42070 // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values 42071 trim( startTime, endTime ) { 42072 42073 const times = this.times, 42074 nKeys = times.length; 42075 42076 let from = 0, 42077 to = nKeys - 1; 42078 42079 while ( from !== nKeys && times[ from ] < startTime ) { 42080 42081 ++ from; 42082 42083 } 42084 42085 while ( to !== - 1 && times[ to ] > endTime ) { 42086 42087 -- to; 42088 42089 } 42090 42091 ++ to; // inclusive -> exclusive bound 42092 42093 if ( from !== 0 || to !== nKeys ) { 42094 42095 // empty tracks are forbidden, so keep at least one keyframe 42096 if ( from >= to ) { 42097 42098 to = Math.max( to, 1 ); 42099 from = to - 1; 42100 42101 } 42102 42103 const stride = this.getValueSize(); 42104 this.times = times.slice( from, to ); 42105 this.values = this.values.slice( from * stride, to * stride ); 42106 42107 } 42108 42109 return this; 42110 42111 } 42112 42113 // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable 42114 validate() { 42115 42116 let valid = true; 42117 42118 const valueSize = this.getValueSize(); 42119 if ( valueSize - Math.floor( valueSize ) !== 0 ) { 42120 42121 console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); 42122 valid = false; 42123 42124 } 42125 42126 const times = this.times, 42127 values = this.values, 42128 42129 nKeys = times.length; 42130 42131 if ( nKeys === 0 ) { 42132 42133 console.error( 'THREE.KeyframeTrack: Track is empty.', this ); 42134 valid = false; 42135 42136 } 42137 42138 let prevTime = null; 42139 42140 for ( let i = 0; i !== nKeys; i ++ ) { 42141 42142 const currTime = times[ i ]; 42143 42144 if ( typeof currTime === 'number' && isNaN( currTime ) ) { 42145 42146 console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); 42147 valid = false; 42148 break; 42149 42150 } 42151 42152 if ( prevTime !== null && prevTime > currTime ) { 42153 42154 console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); 42155 valid = false; 42156 break; 42157 42158 } 42159 42160 prevTime = currTime; 42161 42162 } 42163 42164 if ( values !== undefined ) { 42165 42166 if ( isTypedArray( values ) ) { 42167 42168 for ( let i = 0, n = values.length; i !== n; ++ i ) { 42169 42170 const value = values[ i ]; 42171 42172 if ( isNaN( value ) ) { 42173 42174 console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); 42175 valid = false; 42176 break; 42177 42178 } 42179 42180 } 42181 42182 } 42183 42184 } 42185 42186 return valid; 42187 42188 } 42189 42190 // removes equivalent sequential keys as common in morph target sequences 42191 // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) 42192 optimize() { 42193 42194 // times or values may be shared with other tracks, so overwriting is unsafe 42195 const times = this.times.slice(), 42196 values = this.values.slice(), 42197 stride = this.getValueSize(), 42198 42199 smoothInterpolation = this.getInterpolation() === InterpolateSmooth, 42200 42201 lastIndex = times.length - 1; 42202 42203 let writeIndex = 1; 42204 42205 for ( let i = 1; i < lastIndex; ++ i ) { 42206 42207 let keep = false; 42208 42209 const time = times[ i ]; 42210 const timeNext = times[ i + 1 ]; 42211 42212 // remove adjacent keyframes scheduled at the same time 42213 42214 if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) { 42215 42216 if ( ! smoothInterpolation ) { 42217 42218 // remove unnecessary keyframes same as their neighbors 42219 42220 const offset = i * stride, 42221 offsetP = offset - stride, 42222 offsetN = offset + stride; 42223 42224 for ( let j = 0; j !== stride; ++ j ) { 42225 42226 const value = values[ offset + j ]; 42227 42228 if ( value !== values[ offsetP + j ] || 42229 value !== values[ offsetN + j ] ) { 42230 42231 keep = true; 42232 break; 42233 42234 } 42235 42236 } 42237 42238 } else { 42239 42240 keep = true; 42241 42242 } 42243 42244 } 42245 42246 // in-place compaction 42247 42248 if ( keep ) { 42249 42250 if ( i !== writeIndex ) { 42251 42252 times[ writeIndex ] = times[ i ]; 42253 42254 const readOffset = i * stride, 42255 writeOffset = writeIndex * stride; 42256 42257 for ( let j = 0; j !== stride; ++ j ) { 42258 42259 values[ writeOffset + j ] = values[ readOffset + j ]; 42260 42261 } 42262 42263 } 42264 42265 ++ writeIndex; 42266 42267 } 42268 42269 } 42270 42271 // flush last keyframe (compaction looks ahead) 42272 42273 if ( lastIndex > 0 ) { 42274 42275 times[ writeIndex ] = times[ lastIndex ]; 42276 42277 for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { 42278 42279 values[ writeOffset + j ] = values[ readOffset + j ]; 42280 42281 } 42282 42283 ++ writeIndex; 42284 42285 } 42286 42287 if ( writeIndex !== times.length ) { 42288 42289 this.times = times.slice( 0, writeIndex ); 42290 this.values = values.slice( 0, writeIndex * stride ); 42291 42292 } else { 42293 42294 this.times = times; 42295 this.values = values; 42296 42297 } 42298 42299 return this; 42300 42301 } 42302 42303 clone() { 42304 42305 const times = this.times.slice(); 42306 const values = this.values.slice(); 42307 42308 const TypedKeyframeTrack = this.constructor; 42309 const track = new TypedKeyframeTrack( this.name, times, values ); 42310 42311 // Interpolant argument to constructor is not saved, so copy the factory method directly. 42312 track.createInterpolant = this.createInterpolant; 42313 42314 return track; 42315 42316 } 42317 42318} 42319 42320KeyframeTrack.prototype.TimeBufferType = Float32Array; 42321KeyframeTrack.prototype.ValueBufferType = Float32Array; 42322KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; 42323 42324/** 42325 * A Track of Boolean keyframe values. 42326 */ 42327class BooleanKeyframeTrack extends KeyframeTrack {} 42328 42329BooleanKeyframeTrack.prototype.ValueTypeName = 'bool'; 42330BooleanKeyframeTrack.prototype.ValueBufferType = Array; 42331BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; 42332BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; 42333BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; 42334 42335/** 42336 * A Track of keyframe values that represent color. 42337 */ 42338class ColorKeyframeTrack extends KeyframeTrack {} 42339 42340ColorKeyframeTrack.prototype.ValueTypeName = 'color'; 42341 42342/** 42343 * A Track of numeric keyframe values. 42344 */ 42345class NumberKeyframeTrack extends KeyframeTrack {} 42346 42347NumberKeyframeTrack.prototype.ValueTypeName = 'number'; 42348 42349/** 42350 * Spherical linear unit quaternion interpolant. 42351 */ 42352 42353class QuaternionLinearInterpolant extends Interpolant { 42354 42355 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 42356 42357 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 42358 42359 } 42360 42361 interpolate_( i1, t0, t, t1 ) { 42362 42363 const result = this.resultBuffer, 42364 values = this.sampleValues, 42365 stride = this.valueSize, 42366 42367 alpha = ( t - t0 ) / ( t1 - t0 ); 42368 42369 let offset = i1 * stride; 42370 42371 for ( let end = offset + stride; offset !== end; offset += 4 ) { 42372 42373 Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); 42374 42375 } 42376 42377 return result; 42378 42379 } 42380 42381} 42382 42383/** 42384 * A Track of quaternion keyframe values. 42385 */ 42386class QuaternionKeyframeTrack extends KeyframeTrack { 42387 42388 InterpolantFactoryMethodLinear( result ) { 42389 42390 return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); 42391 42392 } 42393 42394} 42395 42396QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion'; 42397// ValueBufferType is inherited 42398QuaternionKeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; 42399QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; 42400 42401/** 42402 * A Track that interpolates Strings 42403 */ 42404class StringKeyframeTrack extends KeyframeTrack {} 42405 42406StringKeyframeTrack.prototype.ValueTypeName = 'string'; 42407StringKeyframeTrack.prototype.ValueBufferType = Array; 42408StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; 42409StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; 42410StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; 42411 42412/** 42413 * A Track of vectored keyframe values. 42414 */ 42415class VectorKeyframeTrack extends KeyframeTrack {} 42416 42417VectorKeyframeTrack.prototype.ValueTypeName = 'vector'; 42418 42419class AnimationClip { 42420 42421 constructor( name = '', duration = - 1, tracks = [], blendMode = NormalAnimationBlendMode ) { 42422 42423 this.name = name; 42424 this.tracks = tracks; 42425 this.duration = duration; 42426 this.blendMode = blendMode; 42427 42428 this.uuid = generateUUID(); 42429 42430 // this means it should figure out its duration by scanning the tracks 42431 if ( this.duration < 0 ) { 42432 42433 this.resetDuration(); 42434 42435 } 42436 42437 } 42438 42439 42440 static parse( json ) { 42441 42442 const tracks = [], 42443 jsonTracks = json.tracks, 42444 frameTime = 1.0 / ( json.fps || 1.0 ); 42445 42446 for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) { 42447 42448 tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) ); 42449 42450 } 42451 42452 const clip = new this( json.name, json.duration, tracks, json.blendMode ); 42453 clip.uuid = json.uuid; 42454 42455 return clip; 42456 42457 } 42458 42459 static toJSON( clip ) { 42460 42461 const tracks = [], 42462 clipTracks = clip.tracks; 42463 42464 const json = { 42465 42466 'name': clip.name, 42467 'duration': clip.duration, 42468 'tracks': tracks, 42469 'uuid': clip.uuid, 42470 'blendMode': clip.blendMode 42471 42472 }; 42473 42474 for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) { 42475 42476 tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); 42477 42478 } 42479 42480 return json; 42481 42482 } 42483 42484 static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) { 42485 42486 const numMorphTargets = morphTargetSequence.length; 42487 const tracks = []; 42488 42489 for ( let i = 0; i < numMorphTargets; i ++ ) { 42490 42491 let times = []; 42492 let values = []; 42493 42494 times.push( 42495 ( i + numMorphTargets - 1 ) % numMorphTargets, 42496 i, 42497 ( i + 1 ) % numMorphTargets ); 42498 42499 values.push( 0, 1, 0 ); 42500 42501 const order = getKeyframeOrder( times ); 42502 times = sortedArray( times, 1, order ); 42503 values = sortedArray( values, 1, order ); 42504 42505 // if there is a key at the first frame, duplicate it as the 42506 // last frame as well for perfect loop. 42507 if ( ! noLoop && times[ 0 ] === 0 ) { 42508 42509 times.push( numMorphTargets ); 42510 values.push( values[ 0 ] ); 42511 42512 } 42513 42514 tracks.push( 42515 new NumberKeyframeTrack( 42516 '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', 42517 times, values 42518 ).scale( 1.0 / fps ) ); 42519 42520 } 42521 42522 return new this( name, - 1, tracks ); 42523 42524 } 42525 42526 static findByName( objectOrClipArray, name ) { 42527 42528 let clipArray = objectOrClipArray; 42529 42530 if ( ! Array.isArray( objectOrClipArray ) ) { 42531 42532 const o = objectOrClipArray; 42533 clipArray = o.geometry && o.geometry.animations || o.animations; 42534 42535 } 42536 42537 for ( let i = 0; i < clipArray.length; i ++ ) { 42538 42539 if ( clipArray[ i ].name === name ) { 42540 42541 return clipArray[ i ]; 42542 42543 } 42544 42545 } 42546 42547 return null; 42548 42549 } 42550 42551 static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) { 42552 42553 const animationToMorphTargets = {}; 42554 42555 // tested with https://regex101.com/ on trick sequences 42556 // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 42557 const pattern = /^([\w-]*?)([\d]+)$/; 42558 42559 // sort morph target names into animation groups based 42560 // patterns like Walk_001, Walk_002, Run_001, Run_002 42561 for ( let i = 0, il = morphTargets.length; i < il; i ++ ) { 42562 42563 const morphTarget = morphTargets[ i ]; 42564 const parts = morphTarget.name.match( pattern ); 42565 42566 if ( parts && parts.length > 1 ) { 42567 42568 const name = parts[ 1 ]; 42569 42570 let animationMorphTargets = animationToMorphTargets[ name ]; 42571 42572 if ( ! animationMorphTargets ) { 42573 42574 animationToMorphTargets[ name ] = animationMorphTargets = []; 42575 42576 } 42577 42578 animationMorphTargets.push( morphTarget ); 42579 42580 } 42581 42582 } 42583 42584 const clips = []; 42585 42586 for ( const name in animationToMorphTargets ) { 42587 42588 clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); 42589 42590 } 42591 42592 return clips; 42593 42594 } 42595 42596 // parse the animation.hierarchy format 42597 static parseAnimation( animation, bones ) { 42598 42599 if ( ! animation ) { 42600 42601 console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); 42602 return null; 42603 42604 } 42605 42606 const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { 42607 42608 // only return track if there are actually keys. 42609 if ( animationKeys.length !== 0 ) { 42610 42611 const times = []; 42612 const values = []; 42613 42614 flattenJSON( animationKeys, times, values, propertyName ); 42615 42616 // empty keys are filtered out, so check again 42617 if ( times.length !== 0 ) { 42618 42619 destTracks.push( new trackType( trackName, times, values ) ); 42620 42621 } 42622 42623 } 42624 42625 }; 42626 42627 const tracks = []; 42628 42629 const clipName = animation.name || 'default'; 42630 const fps = animation.fps || 30; 42631 const blendMode = animation.blendMode; 42632 42633 // automatic length determination in AnimationClip. 42634 let duration = animation.length || - 1; 42635 42636 const hierarchyTracks = animation.hierarchy || []; 42637 42638 for ( let h = 0; h < hierarchyTracks.length; h ++ ) { 42639 42640 const animationKeys = hierarchyTracks[ h ].keys; 42641 42642 // skip empty tracks 42643 if ( ! animationKeys || animationKeys.length === 0 ) continue; 42644 42645 // process morph targets 42646 if ( animationKeys[ 0 ].morphTargets ) { 42647 42648 // figure out all morph targets used in this track 42649 const morphTargetNames = {}; 42650 42651 let k; 42652 42653 for ( k = 0; k < animationKeys.length; k ++ ) { 42654 42655 if ( animationKeys[ k ].morphTargets ) { 42656 42657 for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { 42658 42659 morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; 42660 42661 } 42662 42663 } 42664 42665 } 42666 42667 // create a track for each morph target with all zero 42668 // morphTargetInfluences except for the keys in which 42669 // the morphTarget is named. 42670 for ( const morphTargetName in morphTargetNames ) { 42671 42672 const times = []; 42673 const values = []; 42674 42675 for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { 42676 42677 const animationKey = animationKeys[ k ]; 42678 42679 times.push( animationKey.time ); 42680 values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); 42681 42682 } 42683 42684 tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); 42685 42686 } 42687 42688 duration = morphTargetNames.length * fps; 42689 42690 } else { 42691 42692 // ...assume skeletal animation 42693 42694 const boneName = '.bones[' + bones[ h ].name + ']'; 42695 42696 addNonemptyTrack( 42697 VectorKeyframeTrack, boneName + '.position', 42698 animationKeys, 'pos', tracks ); 42699 42700 addNonemptyTrack( 42701 QuaternionKeyframeTrack, boneName + '.quaternion', 42702 animationKeys, 'rot', tracks ); 42703 42704 addNonemptyTrack( 42705 VectorKeyframeTrack, boneName + '.scale', 42706 animationKeys, 'scl', tracks ); 42707 42708 } 42709 42710 } 42711 42712 if ( tracks.length === 0 ) { 42713 42714 return null; 42715 42716 } 42717 42718 const clip = new this( clipName, duration, tracks, blendMode ); 42719 42720 return clip; 42721 42722 } 42723 42724 resetDuration() { 42725 42726 const tracks = this.tracks; 42727 let duration = 0; 42728 42729 for ( let i = 0, n = tracks.length; i !== n; ++ i ) { 42730 42731 const track = this.tracks[ i ]; 42732 42733 duration = Math.max( duration, track.times[ track.times.length - 1 ] ); 42734 42735 } 42736 42737 this.duration = duration; 42738 42739 return this; 42740 42741 } 42742 42743 trim() { 42744 42745 for ( let i = 0; i < this.tracks.length; i ++ ) { 42746 42747 this.tracks[ i ].trim( 0, this.duration ); 42748 42749 } 42750 42751 return this; 42752 42753 } 42754 42755 validate() { 42756 42757 let valid = true; 42758 42759 for ( let i = 0; i < this.tracks.length; i ++ ) { 42760 42761 valid = valid && this.tracks[ i ].validate(); 42762 42763 } 42764 42765 return valid; 42766 42767 } 42768 42769 optimize() { 42770 42771 for ( let i = 0; i < this.tracks.length; i ++ ) { 42772 42773 this.tracks[ i ].optimize(); 42774 42775 } 42776 42777 return this; 42778 42779 } 42780 42781 clone() { 42782 42783 const tracks = []; 42784 42785 for ( let i = 0; i < this.tracks.length; i ++ ) { 42786 42787 tracks.push( this.tracks[ i ].clone() ); 42788 42789 } 42790 42791 return new this.constructor( this.name, this.duration, tracks, this.blendMode ); 42792 42793 } 42794 42795 toJSON() { 42796 42797 return this.constructor.toJSON( this ); 42798 42799 } 42800 42801} 42802 42803function getTrackTypeForValueTypeName( typeName ) { 42804 42805 switch ( typeName.toLowerCase() ) { 42806 42807 case 'scalar': 42808 case 'double': 42809 case 'float': 42810 case 'number': 42811 case 'integer': 42812 42813 return NumberKeyframeTrack; 42814 42815 case 'vector': 42816 case 'vector2': 42817 case 'vector3': 42818 case 'vector4': 42819 42820 return VectorKeyframeTrack; 42821 42822 case 'color': 42823 42824 return ColorKeyframeTrack; 42825 42826 case 'quaternion': 42827 42828 return QuaternionKeyframeTrack; 42829 42830 case 'bool': 42831 case 'boolean': 42832 42833 return BooleanKeyframeTrack; 42834 42835 case 'string': 42836 42837 return StringKeyframeTrack; 42838 42839 } 42840 42841 throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); 42842 42843} 42844 42845function parseKeyframeTrack( json ) { 42846 42847 if ( json.type === undefined ) { 42848 42849 throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); 42850 42851 } 42852 42853 const trackType = getTrackTypeForValueTypeName( json.type ); 42854 42855 if ( json.times === undefined ) { 42856 42857 const times = [], values = []; 42858 42859 flattenJSON( json.keys, times, values, 'value' ); 42860 42861 json.times = times; 42862 json.values = values; 42863 42864 } 42865 42866 // derived classes can define a static parse method 42867 if ( trackType.parse !== undefined ) { 42868 42869 return trackType.parse( json ); 42870 42871 } else { 42872 42873 // by default, we assume a constructor compatible with the base 42874 return new trackType( json.name, json.times, json.values, json.interpolation ); 42875 42876 } 42877 42878} 42879 42880const Cache = { 42881 42882 enabled: false, 42883 42884 files: {}, 42885 42886 add: function ( key, file ) { 42887 42888 if ( this.enabled === false ) return; 42889 42890 // console.log( 'THREE.Cache', 'Adding key:', key ); 42891 42892 this.files[ key ] = file; 42893 42894 }, 42895 42896 get: function ( key ) { 42897 42898 if ( this.enabled === false ) return; 42899 42900 // console.log( 'THREE.Cache', 'Checking key:', key ); 42901 42902 return this.files[ key ]; 42903 42904 }, 42905 42906 remove: function ( key ) { 42907 42908 delete this.files[ key ]; 42909 42910 }, 42911 42912 clear: function () { 42913 42914 this.files = {}; 42915 42916 } 42917 42918}; 42919 42920class LoadingManager { 42921 42922 constructor( onLoad, onProgress, onError ) { 42923 42924 const scope = this; 42925 42926 let isLoading = false; 42927 let itemsLoaded = 0; 42928 let itemsTotal = 0; 42929 let urlModifier = undefined; 42930 const handlers = []; 42931 42932 // Refer to #5689 for the reason why we don't set .onStart 42933 // in the constructor 42934 42935 this.onStart = undefined; 42936 this.onLoad = onLoad; 42937 this.onProgress = onProgress; 42938 this.onError = onError; 42939 42940 this.itemStart = function ( url ) { 42941 42942 itemsTotal ++; 42943 42944 if ( isLoading === false ) { 42945 42946 if ( scope.onStart !== undefined ) { 42947 42948 scope.onStart( url, itemsLoaded, itemsTotal ); 42949 42950 } 42951 42952 } 42953 42954 isLoading = true; 42955 42956 }; 42957 42958 this.itemEnd = function ( url ) { 42959 42960 itemsLoaded ++; 42961 42962 if ( scope.onProgress !== undefined ) { 42963 42964 scope.onProgress( url, itemsLoaded, itemsTotal ); 42965 42966 } 42967 42968 if ( itemsLoaded === itemsTotal ) { 42969 42970 isLoading = false; 42971 42972 if ( scope.onLoad !== undefined ) { 42973 42974 scope.onLoad(); 42975 42976 } 42977 42978 } 42979 42980 }; 42981 42982 this.itemError = function ( url ) { 42983 42984 if ( scope.onError !== undefined ) { 42985 42986 scope.onError( url ); 42987 42988 } 42989 42990 }; 42991 42992 this.resolveURL = function ( url ) { 42993 42994 if ( urlModifier ) { 42995 42996 return urlModifier( url ); 42997 42998 } 42999 43000 return url; 43001 43002 }; 43003 43004 this.setURLModifier = function ( transform ) { 43005 43006 urlModifier = transform; 43007 43008 return this; 43009 43010 }; 43011 43012 this.addHandler = function ( regex, loader ) { 43013 43014 handlers.push( regex, loader ); 43015 43016 return this; 43017 43018 }; 43019 43020 this.removeHandler = function ( regex ) { 43021 43022 const index = handlers.indexOf( regex ); 43023 43024 if ( index !== - 1 ) { 43025 43026 handlers.splice( index, 2 ); 43027 43028 } 43029 43030 return this; 43031 43032 }; 43033 43034 this.getHandler = function ( file ) { 43035 43036 for ( let i = 0, l = handlers.length; i < l; i += 2 ) { 43037 43038 const regex = handlers[ i ]; 43039 const loader = handlers[ i + 1 ]; 43040 43041 if ( regex.global ) regex.lastIndex = 0; // see #17920 43042 43043 if ( regex.test( file ) ) { 43044 43045 return loader; 43046 43047 } 43048 43049 } 43050 43051 return null; 43052 43053 }; 43054 43055 } 43056 43057} 43058 43059const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager(); 43060 43061class Loader { 43062 43063 constructor( manager ) { 43064 43065 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 43066 43067 this.crossOrigin = 'anonymous'; 43068 this.withCredentials = false;
vendor: 12,888 bytes, lines 43069-43794
43069 this.path = ''; 43070 this.resourcePath = ''; 43071 this.requestHeader = {}; 43072 43073 } 43074 43075 load( /* url, onLoad, onProgress, onError */ ) {} 43076 43077 loadAsync( url, onProgress ) { 43078 43079 const scope = this; 43080 43081 return new Promise( function ( resolve, reject ) { 43082 43083 scope.load( url, resolve, onProgress, reject ); 43084 43085 } ); 43086 43087 } 43088 43089 parse( /* data */ ) {} 43090 43091 setCrossOrigin( crossOrigin ) { 43092 43093 this.crossOrigin = crossOrigin; 43094 return this; 43095 43096 } 43097 43098 setWithCredentials( value ) { 43099 43100 this.withCredentials = value; 43101 return this; 43102 43103 } 43104 43105 setPath( path ) { 43106 43107 this.path = path; 43108 return this; 43109 43110 } 43111 43112 setResourcePath( resourcePath ) { 43113 43114 this.resourcePath = resourcePath; 43115 return this; 43116 43117 } 43118 43119 setRequestHeader( requestHeader ) { 43120 43121 this.requestHeader = requestHeader; 43122 return this; 43123 43124 } 43125 43126} 43127 43128Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT'; 43129 43130const loading = {}; 43131 43132class HttpError extends Error { 43133 43134 constructor( message, response ) { 43135 43136 super( message ); 43137 this.response = response; 43138 43139 } 43140 43141} 43142 43143class FileLoader extends Loader { 43144 43145 constructor( manager ) { 43146 43147 super( manager ); 43148 43149 } 43150 43151 load( url, onLoad, onProgress, onError ) { 43152 43153 if ( url === undefined ) url = ''; 43154 43155 if ( this.path !== undefined ) url = this.path + url; 43156 43157 url = this.manager.resolveURL( url ); 43158 43159 const cached = Cache.get( url ); 43160 43161 if ( cached !== undefined ) { 43162 43163 this.manager.itemStart( url ); 43164 43165 setTimeout( () => { 43166 43167 if ( onLoad ) onLoad( cached ); 43168 43169 this.manager.itemEnd( url ); 43170 43171 }, 0 ); 43172 43173 return cached; 43174 43175 } 43176 43177 // Check if request is duplicate 43178 43179 if ( loading[ url ] !== undefined ) { 43180 43181 loading[ url ].push( { 43182 43183 onLoad: onLoad, 43184 onProgress: onProgress, 43185 onError: onError 43186 43187 } ); 43188 43189 return; 43190 43191 } 43192 43193 // Initialise array for duplicate requests 43194 loading[ url ] = []; 43195 43196 loading[ url ].push( { 43197 onLoad: onLoad, 43198 onProgress: onProgress, 43199 onError: onError, 43200 } ); 43201 43202 // create request 43203 const req = new Request( url, { 43204 headers: new Headers( this.requestHeader ), 43205 credentials: this.withCredentials ? 'include' : 'same-origin', 43206 // An abort controller could be added within a future PR 43207 } ); 43208 43209 // record states ( avoid data race ) 43210 const mimeType = this.mimeType; 43211 const responseType = this.responseType; 43212 43213 // start the fetch 43214 fetch( req ) 43215 .then( response => { 43216 43217 if ( response.status === 200 || response.status === 0 ) { 43218 43219 // Some browsers return HTTP Status 0 when using non-http protocol 43220 // e.g. 'file://' or 'data://'. Handle as success. 43221 43222 if ( response.status === 0 ) { 43223 43224 console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); 43225 43226 } 43227 43228 // Workaround: Checking if response.body === undefined for Alipay browser #23548 43229 43230 if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) { 43231 43232 return response; 43233 43234 } 43235 43236 const callbacks = loading[ url ]; 43237 const reader = response.body.getReader(); 43238 43239 // Nginx needs X-File-Size check 43240 // https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content 43241 const contentLength = response.headers.get( 'Content-Length' ) || response.headers.get( 'X-File-Size' ); 43242 const total = contentLength ? parseInt( contentLength ) : 0; 43243 const lengthComputable = total !== 0; 43244 let loaded = 0; 43245 43246 // periodically read data into the new stream tracking while download progress 43247 const stream = new ReadableStream( { 43248 start( controller ) { 43249 43250 readData(); 43251 43252 function readData() { 43253 43254 reader.read().then( ( { done, value } ) => { 43255 43256 if ( done ) { 43257 43258 controller.close(); 43259 43260 } else { 43261 43262 loaded += value.byteLength; 43263 43264 const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } ); 43265 for ( let i = 0, il = callbacks.length; i < il; i ++ ) { 43266 43267 const callback = callbacks[ i ]; 43268 if ( callback.onProgress ) callback.onProgress( event ); 43269 43270 } 43271 43272 controller.enqueue( value ); 43273 readData(); 43274 43275 } 43276 43277 } ); 43278 43279 } 43280 43281 } 43282 43283 } ); 43284 43285 return new Response( stream ); 43286 43287 } else { 43288 43289 throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response ); 43290 43291 } 43292 43293 } ) 43294 .then( response => { 43295 43296 switch ( responseType ) { 43297 43298 case 'arraybuffer': 43299 43300 return response.arrayBuffer(); 43301 43302 case 'blob': 43303 43304 return response.blob(); 43305 43306 case 'document': 43307 43308 return response.text() 43309 .then( text => { 43310 43311 const parser = new DOMParser(); 43312 return parser.parseFromString( text, mimeType ); 43313 43314 } ); 43315 43316 case 'json': 43317 43318 return response.json(); 43319 43320 default: 43321 43322 if ( mimeType === undefined ) { 43323 43324 return response.text(); 43325 43326 } else { 43327 43328 // sniff encoding 43329 const re = /charset="?([^;"\s]*)"?/i; 43330 const exec = re.exec( mimeType ); 43331 const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined; 43332 const decoder = new TextDecoder( label ); 43333 return response.arrayBuffer().then( ab => decoder.decode( ab ) ); 43334 43335 } 43336 43337 } 43338 43339 } ) 43340 .then( data => { 43341 43342 // Add to cache only on HTTP success, so that we do not cache 43343 // error response bodies as proper responses to requests. 43344 Cache.add( url, data ); 43345 43346 const callbacks = loading[ url ]; 43347 delete loading[ url ]; 43348 43349 for ( let i = 0, il = callbacks.length; i < il; i ++ ) { 43350 43351 const callback = callbacks[ i ]; 43352 if ( callback.onLoad ) callback.onLoad( data ); 43353 43354 } 43355 43356 } ) 43357 .catch( err => { 43358 43359 // Abort errors and other errors are handled the same 43360 43361 const callbacks = loading[ url ]; 43362 43363 if ( callbacks === undefined ) { 43364 43365 // When onLoad was called and url was deleted in `loading` 43366 this.manager.itemError( url ); 43367 throw err; 43368 43369 } 43370 43371 delete loading[ url ]; 43372 43373 for ( let i = 0, il = callbacks.length; i < il; i ++ ) { 43374 43375 const callback = callbacks[ i ]; 43376 if ( callback.onError ) callback.onError( err ); 43377 43378 } 43379 43380 this.manager.itemError( url ); 43381 43382 } ) 43383 .finally( () => { 43384 43385 this.manager.itemEnd( url ); 43386 43387 } ); 43388 43389 this.manager.itemStart( url ); 43390 43391 } 43392 43393 setResponseType( value ) { 43394 43395 this.responseType = value; 43396 return this; 43397 43398 } 43399 43400 setMimeType( value ) { 43401 43402 this.mimeType = value; 43403 return this; 43404 43405 } 43406 43407} 43408 43409class AnimationLoader extends Loader { 43410 43411 constructor( manager ) { 43412 43413 super( manager ); 43414 43415 } 43416 43417 load( url, onLoad, onProgress, onError ) { 43418 43419 const scope = this; 43420 43421 const loader = new FileLoader( this.manager ); 43422 loader.setPath( this.path ); 43423 loader.setRequestHeader( this.requestHeader ); 43424 loader.setWithCredentials( this.withCredentials ); 43425 loader.load( url, function ( text ) { 43426 43427 try { 43428 43429 onLoad( scope.parse( JSON.parse( text ) ) ); 43430 43431 } catch ( e ) { 43432 43433 if ( onError ) { 43434 43435 onError( e ); 43436 43437 } else { 43438 43439 console.error( e ); 43440 43441 } 43442 43443 scope.manager.itemError( url ); 43444 43445 } 43446 43447 }, onProgress, onError ); 43448 43449 } 43450 43451 parse( json ) { 43452 43453 const animations = []; 43454 43455 for ( let i = 0; i < json.length; i ++ ) { 43456 43457 const clip = AnimationClip.parse( json[ i ] ); 43458 43459 animations.push( clip ); 43460 43461 } 43462 43463 return animations; 43464 43465 } 43466 43467} 43468 43469/** 43470 * Abstract Base class to block based textures loader (dds, pvr, ...) 43471 * 43472 * Sub classes have to implement the parse() method which will be used in load(). 43473 */ 43474 43475class CompressedTextureLoader extends Loader { 43476 43477 constructor( manager ) { 43478 43479 super( manager ); 43480 43481 } 43482 43483 load( url, onLoad, onProgress, onError ) { 43484 43485 const scope = this; 43486 43487 const images = []; 43488 43489 const texture = new CompressedTexture(); 43490 43491 const loader = new FileLoader( this.manager ); 43492 loader.setPath( this.path ); 43493 loader.setResponseType( 'arraybuffer' ); 43494 loader.setRequestHeader( this.requestHeader ); 43495 loader.setWithCredentials( scope.withCredentials ); 43496 43497 let loaded = 0; 43498 43499 function loadTexture( i ) { 43500 43501 loader.load( url[ i ], function ( buffer ) { 43502 43503 const texDatas = scope.parse( buffer, true ); 43504 43505 images[ i ] = { 43506 width: texDatas.width, 43507 height: texDatas.height, 43508 format: texDatas.format, 43509 mipmaps: texDatas.mipmaps 43510 }; 43511 43512 loaded += 1; 43513 43514 if ( loaded === 6 ) { 43515 43516 if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter; 43517 43518 texture.image = images; 43519 texture.format = texDatas.format; 43520 texture.needsUpdate = true; 43521 43522 if ( onLoad ) onLoad( texture ); 43523 43524 } 43525 43526 }, onProgress, onError ); 43527 43528 } 43529 43530 if ( Array.isArray( url ) ) { 43531 43532 for ( let i = 0, il = url.length; i < il; ++ i ) { 43533 43534 loadTexture( i ); 43535 43536 } 43537 43538 } else { 43539 43540 // compressed cubemap texture stored in a single DDS file 43541 43542 loader.load( url, function ( buffer ) { 43543 43544 const texDatas = scope.parse( buffer, true ); 43545 43546 if ( texDatas.isCubemap ) { 43547 43548 const faces = texDatas.mipmaps.length / texDatas.mipmapCount; 43549 43550 for ( let f = 0; f < faces; f ++ ) { 43551 43552 images[ f ] = { mipmaps: [] }; 43553 43554 for ( let i = 0; i < texDatas.mipmapCount; i ++ ) { 43555 43556 images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] ); 43557 images[ f ].format = texDatas.format; 43558 images[ f ].width = texDatas.width; 43559 images[ f ].height = texDatas.height; 43560 43561 } 43562 43563 } 43564 43565 texture.image = images; 43566 43567 } else { 43568 43569 texture.image.width = texDatas.width; 43570 texture.image.height = texDatas.height; 43571 texture.mipmaps = texDatas.mipmaps; 43572 43573 } 43574 43575 if ( texDatas.mipmapCount === 1 ) { 43576 43577 texture.minFilter = LinearFilter; 43578 43579 } 43580 43581 texture.format = texDatas.format; 43582 texture.needsUpdate = true; 43583 43584 if ( onLoad ) onLoad( texture ); 43585 43586 }, onProgress, onError ); 43587 43588 } 43589 43590 return texture; 43591 43592 } 43593 43594} 43595 43596class ImageLoader extends Loader { 43597 43598 constructor( manager ) { 43599 43600 super( manager ); 43601 43602 } 43603 43604 load( url, onLoad, onProgress, onError ) { 43605 43606 if ( this.path !== undefined ) url = this.path + url; 43607 43608 url = this.manager.resolveURL( url ); 43609 43610 const scope = this; 43611 43612 const cached = Cache.get( url ); 43613 43614 if ( cached !== undefined ) { 43615 43616 scope.manager.itemStart( url ); 43617 43618 setTimeout( function () { 43619 43620 if ( onLoad ) onLoad( cached ); 43621 43622 scope.manager.itemEnd( url ); 43623 43624 }, 0 ); 43625 43626 return cached; 43627 43628 } 43629 43630 const image = createElementNS( 'img' ); 43631 43632 function onImageLoad() { 43633 43634 removeEventListeners(); 43635 43636 Cache.add( url, this ); 43637 43638 if ( onLoad ) onLoad( this ); 43639 43640 scope.manager.itemEnd( url ); 43641 43642 } 43643 43644 function onImageError( event ) { 43645 43646 removeEventListeners(); 43647 43648 if ( onError ) onError( event ); 43649 43650 scope.manager.itemError( url ); 43651 scope.manager.itemEnd( url ); 43652 43653 } 43654 43655 function removeEventListeners() { 43656 43657 image.removeEventListener( 'load', onImageLoad, false ); 43658 image.removeEventListener( 'error', onImageError, false ); 43659 43660 } 43661 43662 image.addEventListener( 'load', onImageLoad, false ); 43663 image.addEventListener( 'error', onImageError, false ); 43664 43665 if ( url.slice( 0, 5 ) !== 'data:' ) { 43666 43667 if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; 43668 43669 } 43670 43671 scope.manager.itemStart( url ); 43672 43673 image.src = url; 43674 43675 return image; 43676 43677 } 43678 43679} 43680 43681class CubeTextureLoader extends Loader { 43682 43683 constructor( manager ) { 43684 43685 super( manager ); 43686 43687 } 43688 43689 load( urls, onLoad, onProgress, onError ) { 43690 43691 const texture = new CubeTexture(); 43692 texture.colorSpace = SRGBColorSpace; 43693 43694 const loader = new ImageLoader( this.manager ); 43695 loader.setCrossOrigin( this.crossOrigin ); 43696 loader.setPath( this.path ); 43697 43698 let loaded = 0; 43699 43700 function loadTexture( i ) { 43701 43702 loader.load( urls[ i ], function ( image ) { 43703 43704 texture.images[ i ] = image; 43705 43706 loaded ++; 43707 43708 if ( loaded === 6 ) { 43709 43710 texture.needsUpdate = true; 43711 43712 if ( onLoad ) onLoad( texture ); 43713 43714 } 43715 43716 }, undefined, onError ); 43717 43718 } 43719 43720 for ( let i = 0; i < urls.length; ++ i ) { 43721 43722 loadTexture( i ); 43723 43724 } 43725 43726 return texture; 43727 43728 } 43729 43730} 43731 43732/** 43733 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) 43734 * 43735 * Sub classes have to implement the parse() method which will be used in load(). 43736 */ 43737 43738class DataTextureLoader extends Loader { 43739 43740 constructor( manager ) { 43741 43742 super( manager ); 43743 43744 } 43745 43746 load( url, onLoad, onProgress, onError ) { 43747 43748 const scope = this; 43749 43750 const texture = new DataTexture(); 43751 43752 const loader = new FileLoader( this.manager ); 43753 loader.setResponseType( 'arraybuffer' ); 43754 loader.setRequestHeader( this.requestHeader ); 43755 loader.setPath( this.path ); 43756 loader.setWithCredentials( scope.withCredentials ); 43757 loader.load( url, function ( buffer ) { 43758 43759 let texData; 43760 43761 try { 43762 43763 texData = scope.parse( buffer ); 43764 43765 } catch ( error ) { 43766 43767 if ( onError !== undefined ) { 43768 43769 onError( error ); 43770 43771 } else { 43772 43773 console.error( error ); 43774 return; 43775 43776 } 43777 43778 } 43779 43780 if ( texData.image !== undefined ) { 43781 43782 texture.image = texData.image; 43783 43784 } else if ( texData.data !== undefined ) { 43785 43786 texture.image.width = texData.width; 43787 texture.image.height = texData.height; 43788 texture.image.data = texData.data; 43789 43790 } 43791 43792 texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping; 43793 texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping; 43794
vendor: 4,953 bytes, lines 43795-44081
43795 texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter; 43796 texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter; 43797 43798 texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; 43799 43800 if ( texData.colorSpace !== undefined ) { 43801 43802 texture.colorSpace = texData.colorSpace; 43803 43804 } 43805 43806 if ( texData.flipY !== undefined ) { 43807 43808 texture.flipY = texData.flipY; 43809 43810 } 43811 43812 if ( texData.format !== undefined ) { 43813 43814 texture.format = texData.format; 43815 43816 } 43817 43818 if ( texData.type !== undefined ) { 43819 43820 texture.type = texData.type; 43821 43822 } 43823 43824 if ( texData.mipmaps !== undefined ) { 43825 43826 texture.mipmaps = texData.mipmaps; 43827 texture.minFilter = LinearMipmapLinearFilter; // presumably... 43828 43829 } 43830 43831 if ( texData.mipmapCount === 1 ) { 43832 43833 texture.minFilter = LinearFilter; 43834 43835 } 43836 43837 if ( texData.generateMipmaps !== undefined ) { 43838 43839 texture.generateMipmaps = texData.generateMipmaps; 43840 43841 } 43842 43843 texture.needsUpdate = true; 43844 43845 if ( onLoad ) onLoad( texture, texData ); 43846 43847 }, onProgress, onError ); 43848 43849 43850 return texture; 43851 43852 } 43853 43854} 43855 43856class TextureLoader extends Loader { 43857 43858 constructor( manager ) { 43859 43860 super( manager ); 43861 43862 } 43863 43864 load( url, onLoad, onProgress, onError ) { 43865 43866 const texture = new Texture(); 43867 43868 const loader = new ImageLoader( this.manager ); 43869 loader.setCrossOrigin( this.crossOrigin ); 43870 loader.setPath( this.path ); 43871 43872 loader.load( url, function ( image ) { 43873 43874 texture.image = image; 43875 texture.needsUpdate = true; 43876 43877 if ( onLoad !== undefined ) { 43878 43879 onLoad( texture ); 43880 43881 } 43882 43883 }, onProgress, onError ); 43884 43885 return texture; 43886 43887 } 43888 43889} 43890 43891class Light extends Object3D { 43892 43893 constructor( color, intensity = 1 ) { 43894 43895 super(); 43896 43897 this.isLight = true; 43898 43899 this.type = 'Light'; 43900 43901 this.color = new Color( color ); 43902 this.intensity = intensity; 43903 43904 } 43905 43906 dispose() { 43907 43908 // Empty here in base class; some subclasses override. 43909 43910 } 43911 43912 copy( source, recursive ) { 43913 43914 super.copy( source, recursive ); 43915 43916 this.color.copy( source.color ); 43917 this.intensity = source.intensity; 43918 43919 return this; 43920 43921 } 43922 43923 toJSON( meta ) { 43924 43925 const data = super.toJSON( meta ); 43926 43927 data.object.color = this.color.getHex(); 43928 data.object.intensity = this.intensity; 43929 43930 if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); 43931 43932 if ( this.distance !== undefined ) data.object.distance = this.distance; 43933 if ( this.angle !== undefined ) data.object.angle = this.angle; 43934 if ( this.decay !== undefined ) data.object.decay = this.decay; 43935 if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; 43936 43937 if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); 43938 43939 return data; 43940 43941 } 43942 43943} 43944 43945class HemisphereLight extends Light { 43946 43947 constructor( skyColor, groundColor, intensity ) { 43948 43949 super( skyColor, intensity ); 43950 43951 this.isHemisphereLight = true; 43952 43953 this.type = 'HemisphereLight'; 43954 43955 this.position.copy( Object3D.DEFAULT_UP ); 43956 this.updateMatrix(); 43957 43958 this.groundColor = new Color( groundColor ); 43959 43960 } 43961 43962 copy( source, recursive ) { 43963 43964 super.copy( source, recursive ); 43965 43966 this.groundColor.copy( source.groundColor ); 43967 43968 return this; 43969 43970 } 43971 43972} 43973 43974const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4(); 43975const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3(); 43976const _lookTarget$1 = /*@__PURE__*/ new Vector3(); 43977 43978class LightShadow { 43979 43980 constructor( camera ) { 43981 43982 this.camera = camera; 43983 43984 this.bias = 0; 43985 this.normalBias = 0; 43986 this.radius = 1; 43987 this.blurSamples = 8; 43988 43989 this.mapSize = new Vector2( 512, 512 ); 43990 43991 this.map = null; 43992 this.mapPass = null; 43993 this.matrix = new Matrix4(); 43994 43995 this.autoUpdate = true; 43996 this.needsUpdate = false; 43997 43998 this._frustum = new Frustum(); 43999 this._frameExtents = new Vector2( 1, 1 ); 44000 44001 this._viewportCount = 1; 44002 44003 this._viewports = [ 44004 44005 new Vector4( 0, 0, 1, 1 ) 44006 44007 ]; 44008 44009 } 44010 44011 getViewportCount() { 44012 44013 return this._viewportCount; 44014 44015 } 44016 44017 getFrustum() { 44018 44019 return this._frustum; 44020 44021 } 44022 44023 updateMatrices( light ) { 44024 44025 const shadowCamera = this.camera; 44026 const shadowMatrix = this.matrix; 44027 44028 _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld ); 44029 shadowCamera.position.copy( _lightPositionWorld$1 ); 44030 44031 _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld ); 44032 shadowCamera.lookAt( _lookTarget$1 ); 44033 shadowCamera.updateMatrixWorld(); 44034 44035 _projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); 44036 this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 ); 44037 44038 shadowMatrix.set( 44039 0.5, 0.0, 0.0, 0.5, 44040 0.0, 0.5, 0.0, 0.5, 44041 0.0, 0.0, 0.5, 0.5, 44042 0.0, 0.0, 0.0, 1.0 44043 ); 44044 44045 shadowMatrix.multiply( _projScreenMatrix$1 ); 44046 44047 } 44048 44049 getViewport( viewportIndex ) { 44050 44051 return this._viewports[ viewportIndex ]; 44052 44053 } 44054 44055 getFrameExtents() { 44056 44057 return this._frameExtents; 44058 44059 } 44060 44061 dispose() { 44062 44063 if ( this.map ) { 44064 44065 this.map.dispose(); 44066 44067 } 44068 44069 if ( this.mapPass ) { 44070 44071 this.mapPass.dispose(); 44072 44073 } 44074 44075 } 44076 44077 copy( source ) { 44078 44079 this.camera = source.camera.clone(); 44080 44081 this.bias = source.bias;
vendor: 5,709 bytes, lines 44082-44369
44082 this.radius = source.radius; 44083 44084 this.mapSize.copy( source.mapSize ); 44085 44086 return this; 44087 44088 } 44089 44090 clone() { 44091 44092 return new this.constructor().copy( this ); 44093 44094 } 44095 44096 toJSON() { 44097 44098 const object = {}; 44099 44100 if ( this.bias !== 0 ) object.bias = this.bias; 44101 if ( this.normalBias !== 0 ) object.normalBias = this.normalBias; 44102 if ( this.radius !== 1 ) object.radius = this.radius; 44103 if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray(); 44104 44105 object.camera = this.camera.toJSON( false ).object; 44106 delete object.camera.matrix; 44107 44108 return object; 44109 44110 } 44111 44112} 44113 44114class SpotLightShadow extends LightShadow { 44115 44116 constructor() { 44117 44118 super( new PerspectiveCamera( 50, 1, 0.5, 500 ) ); 44119 44120 this.isSpotLightShadow = true; 44121 44122 this.focus = 1; 44123 44124 } 44125 44126 updateMatrices( light ) { 44127 44128 const camera = this.camera; 44129 44130 const fov = RAD2DEG * 2 * light.angle * this.focus; 44131 const aspect = this.mapSize.width / this.mapSize.height; 44132 const far = light.distance || camera.far; 44133 44134 if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { 44135 44136 camera.fov = fov; 44137 camera.aspect = aspect; 44138 camera.far = far; 44139 camera.updateProjectionMatrix(); 44140 44141 } 44142 44143 super.updateMatrices( light ); 44144 44145 } 44146 44147 copy( source ) { 44148 44149 super.copy( source ); 44150 44151 this.focus = source.focus; 44152 44153 return this; 44154 44155 } 44156 44157} 44158 44159class SpotLight extends Light { 44160 44161 constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) { 44162 44163 super( color, intensity ); 44164 44165 this.isSpotLight = true; 44166 44167 this.type = 'SpotLight'; 44168 44169 this.position.copy( Object3D.DEFAULT_UP ); 44170 this.updateMatrix(); 44171 44172 this.target = new Object3D(); 44173 44174 this.distance = distance; 44175 this.angle = angle; 44176 this.penumbra = penumbra; 44177 this.decay = decay; 44178 44179 this.map = null; 44180 44181 this.shadow = new SpotLightShadow(); 44182 44183 } 44184 44185 get power() { 44186 44187 // compute the light's luminous power (in lumens) from its intensity (in candela) 44188 // by convention for a spotlight, luminous power (lm) = Ï * luminous intensity (cd) 44189 return this.intensity * Math.PI; 44190 44191 } 44192 44193 set power( power ) { 44194 44195 // set the light's intensity (in candela) from the desired luminous power (in lumens) 44196 this.intensity = power / Math.PI; 44197 44198 } 44199 44200 dispose() { 44201 44202 this.shadow.dispose(); 44203 44204 } 44205 44206 copy( source, recursive ) { 44207 44208 super.copy( source, recursive ); 44209 44210 this.distance = source.distance; 44211 this.angle = source.angle; 44212 this.penumbra = source.penumbra; 44213 this.decay = source.decay; 44214 44215 this.target = source.target.clone(); 44216 44217 this.shadow = source.shadow.clone(); 44218 44219 return this; 44220 44221 } 44222 44223} 44224 44225const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); 44226const _lightPositionWorld = /*@__PURE__*/ new Vector3(); 44227const _lookTarget = /*@__PURE__*/ new Vector3(); 44228 44229class PointLightShadow extends LightShadow { 44230 44231 constructor() { 44232 44233 super( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); 44234 44235 this.isPointLightShadow = true; 44236 44237 this._frameExtents = new Vector2( 4, 2 ); 44238 44239 this._viewportCount = 6; 44240 44241 this._viewports = [ 44242 // These viewports map a cube-map onto a 2D texture with the 44243 // following orientation: 44244 // 44245 // xzXZ 44246 // y Y 44247 // 44248 // X - Positive x direction 44249 // x - Negative x direction 44250 // Y - Positive y direction 44251 // y - Negative y direction 44252 // Z - Positive z direction 44253 // z - Negative z direction 44254 44255 // positive X 44256 new Vector4( 2, 1, 1, 1 ), 44257 // negative X 44258 new Vector4( 0, 1, 1, 1 ), 44259 // positive Z 44260 new Vector4( 3, 1, 1, 1 ), 44261 // negative Z 44262 new Vector4( 1, 1, 1, 1 ), 44263 // positive Y 44264 new Vector4( 3, 0, 1, 1 ), 44265 // negative Y 44266 new Vector4( 1, 0, 1, 1 ) 44267 ]; 44268 44269 this._cubeDirections = [ 44270 new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), 44271 new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) 44272 ]; 44273 44274 this._cubeUps = [ 44275 new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), 44276 new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) 44277 ]; 44278 44279 } 44280 44281 updateMatrices( light, viewportIndex = 0 ) { 44282 44283 const camera = this.camera; 44284 const shadowMatrix = this.matrix; 44285 44286 const far = light.distance || camera.far; 44287 44288 if ( far !== camera.far ) { 44289 44290 camera.far = far; 44291 camera.updateProjectionMatrix(); 44292 44293 } 44294 44295 _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); 44296 camera.position.copy( _lightPositionWorld ); 44297 44298 _lookTarget.copy( camera.position ); 44299 _lookTarget.add( this._cubeDirections[ viewportIndex ] ); 44300 camera.up.copy( this._cubeUps[ viewportIndex ] ); 44301 camera.lookAt( _lookTarget ); 44302 camera.updateMatrixWorld(); 44303 44304 shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); 44305 44306 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); 44307 this._frustum.setFromProjectionMatrix( _projScreenMatrix ); 44308 44309 } 44310 44311} 44312 44313class PointLight extends Light { 44314 44315 constructor( color, intensity, distance = 0, decay = 2 ) { 44316 44317 super( color, intensity ); 44318 44319 this.isPointLight = true; 44320 44321 this.type = 'PointLight'; 44322 44323 this.distance = distance; 44324 this.decay = decay; 44325 44326 this.shadow = new PointLightShadow(); 44327 44328 } 44329 44330 get power() { 44331 44332 // compute the light's luminous power (in lumens) from its intensity (in candela) 44333 // for an isotropic light source, luminous power (lm) = 4 Ï luminous intensity (cd) 44334 return this.intensity * 4 * Math.PI; 44335 44336 } 44337 44338 set power( power ) { 44339 44340 // set the light's intensity (in candela) from the desired luminous power (in lumens) 44341 this.intensity = power / ( 4 * Math.PI ); 44342 44343 } 44344 44345 dispose() { 44346 44347 this.shadow.dispose(); 44348 44349 } 44350 44351 copy( source, recursive ) { 44352 44353 super.copy( source, recursive ); 44354 44355 this.distance = source.distance; 44356 this.decay = source.decay; 44357 44358 this.shadow = source.shadow.clone(); 44359 44360 return this; 44361 44362 } 44363 44364} 44365 44366class DirectionalLightShadow extends LightShadow { 44367 44368 constructor() { 44369
vendor: 4,273 bytes, lines 44370-44591
44370 super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); 44371 44372 this.isDirectionalLightShadow = true; 44373 44374 } 44375 44376} 44377 44378class DirectionalLight extends Light { 44379 44380 constructor( color, intensity ) { 44381 44382 super( color, intensity ); 44383 44384 this.isDirectionalLight = true; 44385 44386 this.type = 'DirectionalLight'; 44387 44388 this.position.copy( Object3D.DEFAULT_UP ); 44389 this.updateMatrix(); 44390 44391 this.target = new Object3D(); 44392 44393 this.shadow = new DirectionalLightShadow(); 44394 44395 } 44396 44397 dispose() { 44398 44399 this.shadow.dispose(); 44400 44401 } 44402 44403 copy( source ) { 44404 44405 super.copy( source ); 44406 44407 this.target = source.target.clone(); 44408 this.shadow = source.shadow.clone(); 44409 44410 return this; 44411 44412 } 44413 44414} 44415 44416class AmbientLight extends Light { 44417 44418 constructor( color, intensity ) { 44419 44420 super( color, intensity ); 44421 44422 this.isAmbientLight = true; 44423 44424 this.type = 'AmbientLight'; 44425 44426 } 44427 44428} 44429 44430class RectAreaLight extends Light { 44431 44432 constructor( color, intensity, width = 10, height = 10 ) { 44433 44434 super( color, intensity ); 44435 44436 this.isRectAreaLight = true; 44437 44438 this.type = 'RectAreaLight'; 44439 44440 this.width = width; 44441 this.height = height; 44442 44443 } 44444 44445 get power() { 44446 44447 // compute the light's luminous power (in lumens) from its intensity (in nits) 44448 return this.intensity * this.width * this.height * Math.PI; 44449 44450 } 44451 44452 set power( power ) { 44453 44454 // set the light's intensity (in nits) from the desired luminous power (in lumens) 44455 this.intensity = power / ( this.width * this.height * Math.PI ); 44456 44457 } 44458 44459 copy( source ) { 44460 44461 super.copy( source ); 44462 44463 this.width = source.width; 44464 this.height = source.height; 44465 44466 return this; 44467 44468 } 44469 44470 toJSON( meta ) { 44471 44472 const data = super.toJSON( meta ); 44473 44474 data.object.width = this.width; 44475 data.object.height = this.height; 44476 44477 return data; 44478 44479 } 44480 44481} 44482 44483/** 44484 * Primary reference: 44485 * https://graphics.stanford.edu/papers/envmap/envmap.pdf 44486 * 44487 * Secondary reference: 44488 * https://www.ppsloan.org/publications/StupidSH36.pdf 44489 */ 44490 44491// 3-band SH defined by 9 coefficients 44492 44493class SphericalHarmonics3 { 44494 44495 constructor() { 44496 44497 this.isSphericalHarmonics3 = true; 44498 44499 this.coefficients = []; 44500 44501 for ( let i = 0; i < 9; i ++ ) { 44502 44503 this.coefficients.push( new Vector3() ); 44504 44505 } 44506 44507 } 44508 44509 set( coefficients ) { 44510 44511 for ( let i = 0; i < 9; i ++ ) { 44512 44513 this.coefficients[ i ].copy( coefficients[ i ] ); 44514 44515 } 44516 44517 return this; 44518 44519 } 44520 44521 zero() { 44522 44523 for ( let i = 0; i < 9; i ++ ) { 44524 44525 this.coefficients[ i ].set( 0, 0, 0 ); 44526 44527 } 44528 44529 return this; 44530 44531 } 44532 44533 // get the radiance in the direction of the normal 44534 // target is a Vector3 44535 getAt( normal, target ) { 44536 44537 // normal is assumed to be unit length 44538 44539 const x = normal.x, y = normal.y, z = normal.z; 44540 44541 const coeff = this.coefficients; 44542 44543 // band 0 44544 target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 ); 44545 44546 // band 1 44547 target.addScaledVector( coeff[ 1 ], 0.488603 * y ); 44548 target.addScaledVector( coeff[ 2 ], 0.488603 * z ); 44549 target.addScaledVector( coeff[ 3 ], 0.488603 * x ); 44550 44551 // band 2 44552 target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) ); 44553 target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) ); 44554 target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) ); 44555 target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) ); 44556 target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) ); 44557 44558 return target; 44559 44560 } 44561 44562 // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal 44563 // target is a Vector3 44564 // https://graphics.stanford.edu/papers/envmap/envmap.pdf 44565 getIrradianceAt( normal, target ) { 44566 44567 // normal is assumed to be unit length 44568 44569 const x = normal.x, y = normal.y, z = normal.z; 44570 44571 const coeff = this.coefficients; 44572 44573 // band 0 44574 target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // Ï * 0.282095 44575 44576 // band 1 44577 target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * Ï / 3 ) * 0.488603 44578 target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z ); 44579 target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x ); 44580 44581 // band 2 44582 target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( Ï / 4 ) * 1.092548 44583 target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z ); 44584 target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( Ï / 4 ) * 0.315392 * 3 44585 target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z ); 44586 target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( Ï / 4 ) * 0.546274 44587 44588 return target; 44589 44590 } 44591
vendor: 39,804 bytes, lines 44592-46235
44592 add( sh ) { 44593 44594 for ( let i = 0; i < 9; i ++ ) { 44595 44596 this.coefficients[ i ].add( sh.coefficients[ i ] ); 44597 44598 } 44599 44600 return this; 44601 44602 } 44603 44604 addScaledSH( sh, s ) { 44605 44606 for ( let i = 0; i < 9; i ++ ) { 44607 44608 this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s ); 44609 44610 } 44611 44612 return this; 44613 44614 } 44615 44616 scale( s ) { 44617 44618 for ( let i = 0; i < 9; i ++ ) { 44619 44620 this.coefficients[ i ].multiplyScalar( s ); 44621 44622 } 44623 44624 return this; 44625 44626 } 44627 44628 lerp( sh, alpha ) { 44629 44630 for ( let i = 0; i < 9; i ++ ) { 44631 44632 this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha ); 44633 44634 } 44635 44636 return this; 44637 44638 } 44639 44640 equals( sh ) { 44641 44642 for ( let i = 0; i < 9; i ++ ) { 44643 44644 if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) { 44645 44646 return false; 44647 44648 } 44649 44650 } 44651 44652 return true; 44653 44654 } 44655 44656 copy( sh ) { 44657 44658 return this.set( sh.coefficients ); 44659 44660 } 44661 44662 clone() { 44663 44664 return new this.constructor().copy( this ); 44665 44666 } 44667 44668 fromArray( array, offset = 0 ) { 44669 44670 const coefficients = this.coefficients; 44671 44672 for ( let i = 0; i < 9; i ++ ) { 44673 44674 coefficients[ i ].fromArray( array, offset + ( i * 3 ) ); 44675 44676 } 44677 44678 return this; 44679 44680 } 44681 44682 toArray( array = [], offset = 0 ) { 44683 44684 const coefficients = this.coefficients; 44685 44686 for ( let i = 0; i < 9; i ++ ) { 44687 44688 coefficients[ i ].toArray( array, offset + ( i * 3 ) ); 44689 44690 } 44691 44692 return array; 44693 44694 } 44695 44696 // evaluate the basis functions 44697 // shBasis is an Array[ 9 ] 44698 static getBasisAt( normal, shBasis ) { 44699 44700 // normal is assumed to be unit length 44701 44702 const x = normal.x, y = normal.y, z = normal.z; 44703 44704 // band 0 44705 shBasis[ 0 ] = 0.282095; 44706 44707 // band 1 44708 shBasis[ 1 ] = 0.488603 * y; 44709 shBasis[ 2 ] = 0.488603 * z; 44710 shBasis[ 3 ] = 0.488603 * x; 44711 44712 // band 2 44713 shBasis[ 4 ] = 1.092548 * x * y; 44714 shBasis[ 5 ] = 1.092548 * y * z; 44715 shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 ); 44716 shBasis[ 7 ] = 1.092548 * x * z; 44717 shBasis[ 8 ] = 0.546274 * ( x * x - y * y ); 44718 44719 } 44720 44721} 44722 44723class LightProbe extends Light { 44724 44725 constructor( sh = new SphericalHarmonics3(), intensity = 1 ) { 44726 44727 super( undefined, intensity ); 44728 44729 this.isLightProbe = true; 44730 44731 this.sh = sh; 44732 44733 } 44734 44735 copy( source ) { 44736 44737 super.copy( source ); 44738 44739 this.sh.copy( source.sh ); 44740 44741 return this; 44742 44743 } 44744 44745 fromJSON( json ) { 44746 44747 this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON(); 44748 this.sh.fromArray( json.sh ); 44749 44750 return this; 44751 44752 } 44753 44754 toJSON( meta ) { 44755 44756 const data = super.toJSON( meta ); 44757 44758 data.object.sh = this.sh.toArray(); 44759 44760 return data; 44761 44762 } 44763 44764} 44765 44766class MaterialLoader extends Loader { 44767 44768 constructor( manager ) { 44769 44770 super( manager ); 44771 this.textures = {}; 44772 44773 } 44774 44775 load( url, onLoad, onProgress, onError ) { 44776 44777 const scope = this; 44778 44779 const loader = new FileLoader( scope.manager ); 44780 loader.setPath( scope.path ); 44781 loader.setRequestHeader( scope.requestHeader ); 44782 loader.setWithCredentials( scope.withCredentials ); 44783 loader.load( url, function ( text ) { 44784 44785 try { 44786 44787 onLoad( scope.parse( JSON.parse( text ) ) ); 44788 44789 } catch ( e ) { 44790 44791 if ( onError ) { 44792 44793 onError( e ); 44794 44795 } else { 44796 44797 console.error( e ); 44798 44799 } 44800 44801 scope.manager.itemError( url ); 44802 44803 } 44804 44805 }, onProgress, onError ); 44806 44807 } 44808 44809 parse( json ) { 44810 44811 const textures = this.textures; 44812 44813 function getTexture( name ) { 44814 44815 if ( textures[ name ] === undefined ) { 44816 44817 console.warn( 'THREE.MaterialLoader: Undefined texture', name ); 44818 44819 } 44820 44821 return textures[ name ]; 44822 44823 } 44824 44825 const material = MaterialLoader.createMaterialFromType( json.type ); 44826 44827 if ( json.uuid !== undefined ) material.uuid = json.uuid; 44828 if ( json.name !== undefined ) material.name = json.name; 44829 if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color ); 44830 if ( json.roughness !== undefined ) material.roughness = json.roughness; 44831 if ( json.metalness !== undefined ) material.metalness = json.metalness; 44832 if ( json.sheen !== undefined ) material.sheen = json.sheen; 44833 if ( json.sheenColor !== undefined ) material.sheenColor = new Color().setHex( json.sheenColor ); 44834 if ( json.sheenRoughness !== undefined ) material.sheenRoughness = json.sheenRoughness; 44835 if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive ); 44836 if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular ); 44837 if ( json.specularIntensity !== undefined ) material.specularIntensity = json.specularIntensity; 44838 if ( json.specularColor !== undefined && material.specularColor !== undefined ) material.specularColor.setHex( json.specularColor ); 44839 if ( json.shininess !== undefined ) material.shininess = json.shininess; 44840 if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat; 44841 if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness; 44842 if ( json.iridescence !== undefined ) material.iridescence = json.iridescence; 44843 if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR; 44844 if ( json.iridescenceThicknessRange !== undefined ) material.iridescenceThicknessRange = json.iridescenceThicknessRange; 44845 if ( json.transmission !== undefined ) material.transmission = json.transmission; 44846 if ( json.thickness !== undefined ) material.thickness = json.thickness; 44847 if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance; 44848 if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor ); 44849 if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy; 44850 if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation; 44851 if ( json.fog !== undefined ) material.fog = json.fog; 44852 if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; 44853 if ( json.blending !== undefined ) material.blending = json.blending; 44854 if ( json.combine !== undefined ) material.combine = json.combine; 44855 if ( json.side !== undefined ) material.side = json.side; 44856 if ( json.shadowSide !== undefined ) material.shadowSide = json.shadowSide; 44857 if ( json.opacity !== undefined ) material.opacity = json.opacity; 44858 if ( json.transparent !== undefined ) material.transparent = json.transparent; 44859 if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest; 44860 if ( json.alphaHash !== undefined ) material.alphaHash = json.alphaHash; 44861 if ( json.depthFunc !== undefined ) material.depthFunc = json.depthFunc; 44862 if ( json.depthTest !== undefined ) material.depthTest = json.depthTest; 44863 if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite; 44864 if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite; 44865 if ( json.blendSrc !== undefined ) material.blendSrc = json.blendSrc; 44866 if ( json.blendDst !== undefined ) material.blendDst = json.blendDst; 44867 if ( json.blendEquation !== undefined ) material.blendEquation = json.blendEquation; 44868 if ( json.blendSrcAlpha !== undefined ) material.blendSrcAlpha = json.blendSrcAlpha; 44869 if ( json.blendDstAlpha !== undefined ) material.blendDstAlpha = json.blendDstAlpha; 44870 if ( json.blendEquationAlpha !== undefined ) material.blendEquationAlpha = json.blendEquationAlpha; 44871 if ( json.blendColor !== undefined && material.blendColor !== undefined ) material.blendColor.setHex( json.blendColor ); 44872 if ( json.blendAlpha !== undefined ) material.blendAlpha = json.blendAlpha; 44873 if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask; 44874 if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc; 44875 if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef; 44876 if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask; 44877 if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail; 44878 if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail; 44879 if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass; 44880 if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite; 44881 44882 if ( json.wireframe !== undefined ) material.wireframe = json.wireframe; 44883 if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth; 44884 if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap; 44885 if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin; 44886 44887 if ( json.rotation !== undefined ) material.rotation = json.rotation; 44888 44889 if ( json.linewidth !== undefined ) material.linewidth = json.linewidth; 44890 if ( json.dashSize !== undefined ) material.dashSize = json.dashSize; 44891 if ( json.gapSize !== undefined ) material.gapSize = json.gapSize; 44892 if ( json.scale !== undefined ) material.scale = json.scale; 44893 44894 if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset; 44895 if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor; 44896 if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits; 44897 44898 if ( json.dithering !== undefined ) material.dithering = json.dithering; 44899 44900 if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage; 44901 if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha; 44902 if ( json.forceSinglePass !== undefined ) material.forceSinglePass = json.forceSinglePass; 44903 44904 if ( json.visible !== undefined ) material.visible = json.visible; 44905 44906 if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped; 44907 44908 if ( json.userData !== undefined ) material.userData = json.userData; 44909 44910 if ( json.vertexColors !== undefined ) { 44911 44912 if ( typeof json.vertexColors === 'number' ) { 44913 44914 material.vertexColors = ( json.vertexColors > 0 ) ? true : false; 44915 44916 } else { 44917 44918 material.vertexColors = json.vertexColors; 44919 44920 } 44921 44922 } 44923 44924 // Shader Material 44925 44926 if ( json.uniforms !== undefined ) { 44927 44928 for ( const name in json.uniforms ) { 44929 44930 const uniform = json.uniforms[ name ]; 44931 44932 material.uniforms[ name ] = {}; 44933 44934 switch ( uniform.type ) { 44935 44936 case 't': 44937 material.uniforms[ name ].value = getTexture( uniform.value ); 44938 break; 44939 44940 case 'c': 44941 material.uniforms[ name ].value = new Color().setHex( uniform.value ); 44942 break; 44943 44944 case 'v2': 44945 material.uniforms[ name ].value = new Vector2().fromArray( uniform.value ); 44946 break; 44947 44948 case 'v3': 44949 material.uniforms[ name ].value = new Vector3().fromArray( uniform.value ); 44950 break; 44951 44952 case 'v4': 44953 material.uniforms[ name ].value = new Vector4().fromArray( uniform.value ); 44954 break; 44955 44956 case 'm3': 44957 material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value ); 44958 break; 44959 44960 case 'm4': 44961 material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value ); 44962 break; 44963 44964 default: 44965 material.uniforms[ name ].value = uniform.value; 44966 44967 } 44968 44969 } 44970 44971 } 44972 44973 if ( json.defines !== undefined ) material.defines = json.defines; 44974 if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader; 44975 if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; 44976 if ( json.glslVersion !== undefined ) material.glslVersion = json.glslVersion; 44977 44978 if ( json.extensions !== undefined ) { 44979 44980 for ( const key in json.extensions ) { 44981 44982 material.extensions[ key ] = json.extensions[ key ]; 44983 44984 } 44985 44986 } 44987 44988 if ( json.lights !== undefined ) material.lights = json.lights; 44989 if ( json.clipping !== undefined ) material.clipping = json.clipping; 44990 44991 // for PointsMaterial 44992 44993 if ( json.size !== undefined ) material.size = json.size; 44994 if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation; 44995 44996 // maps 44997 44998 if ( json.map !== undefined ) material.map = getTexture( json.map ); 44999 if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap ); 45000 45001 if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap ); 45002 45003 if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap ); 45004 if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale; 45005 45006 if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap ); 45007 if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType; 45008 if ( json.normalScale !== undefined ) { 45009 45010 let normalScale = json.normalScale; 45011 45012 if ( Array.isArray( normalScale ) === false ) { 45013 45014 // Blender exporter used to export a scalar. See #7459 45015 45016 normalScale = [ normalScale, normalScale ]; 45017 45018 } 45019 45020 material.normalScale = new Vector2().fromArray( normalScale ); 45021 45022 } 45023 45024 if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap ); 45025 if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale; 45026 if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias; 45027 45028 if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap ); 45029 if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap ); 45030 45031 if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap ); 45032 if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity; 45033 45034 if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap ); 45035 if ( json.specularIntensityMap !== undefined ) material.specularIntensityMap = getTexture( json.specularIntensityMap ); 45036 if ( json.specularColorMap !== undefined ) material.specularColorMap = getTexture( json.specularColorMap ); 45037 45038 if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap ); 45039 if ( json.envMapRotation !== undefined ) material.envMapRotation.fromArray( json.envMapRotation ); 45040 if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity; 45041 45042 if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity; 45043 if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio; 45044 45045 if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap ); 45046 if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity; 45047 45048 if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap ); 45049 if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity; 45050 45051 if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap ); 45052 45053 if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap ); 45054 if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap ); 45055 if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap ); 45056 if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale ); 45057 45058 if ( json.iridescenceMap !== undefined ) material.iridescenceMap = getTexture( json.iridescenceMap ); 45059 if ( json.iridescenceThicknessMap !== undefined ) material.iridescenceThicknessMap = getTexture( json.iridescenceThicknessMap ); 45060 45061 if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap ); 45062 if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap ); 45063 45064 if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap ); 45065 45066 if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap ); 45067 if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap ); 45068 45069 return material; 45070 45071 } 45072 45073 setTextures( value ) { 45074 45075 this.textures = value; 45076 return this; 45077 45078 } 45079 45080 static createMaterialFromType( type ) { 45081 45082 const materialLib = { 45083 ShadowMaterial, 45084 SpriteMaterial, 45085 RawShaderMaterial, 45086 ShaderMaterial, 45087 PointsMaterial, 45088 MeshPhysicalMaterial, 45089 MeshStandardMaterial, 45090 MeshPhongMaterial, 45091 MeshToonMaterial, 45092 MeshNormalMaterial, 45093 MeshLambertMaterial, 45094 MeshDepthMaterial, 45095 MeshDistanceMaterial, 45096 MeshBasicMaterial, 45097 MeshMatcapMaterial, 45098 LineDashedMaterial, 45099 LineBasicMaterial, 45100 Material 45101 }; 45102 45103 return new materialLib[ type ](); 45104 45105 } 45106 45107} 45108 45109class LoaderUtils { 45110 45111 static decodeText( array ) { 45112 45113 if ( typeof TextDecoder !== 'undefined' ) { 45114 45115 return new TextDecoder().decode( array ); 45116 45117 } 45118 45119 // Avoid the String.fromCharCode.apply(null, array) shortcut, which 45120 // throws a "maximum call stack size exceeded" error for large arrays. 45121 45122 let s = ''; 45123 45124 for ( let i = 0, il = array.length; i < il; i ++ ) { 45125 45126 // Implicitly assumes little-endian. 45127 s += String.fromCharCode( array[ i ] ); 45128 45129 } 45130 45131 try { 45132 45133 // merges multi-byte utf-8 characters. 45134 45135 return decodeURIComponent( escape( s ) ); 45136 45137 } catch ( e ) { // see #16358 45138 45139 return s; 45140 45141 } 45142 45143 } 45144 45145 static extractUrlBase( url ) { 45146 45147 const index = url.lastIndexOf( '/' ); 45148 45149 if ( index === - 1 ) return './'; 45150 45151 return url.slice( 0, index + 1 ); 45152 45153 } 45154 45155 static resolveURL( url, path ) { 45156 45157 // Invalid URL 45158 if ( typeof url !== 'string' || url === '' ) return ''; 45159 45160 // Host Relative URL 45161 if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) { 45162 45163 path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' ); 45164 45165 } 45166 45167 // Absolute URL http://,https://,// 45168 if ( /^(https?:)?\/\//i.test( url ) ) return url; 45169 45170 // Data URI 45171 if ( /^data:.*,.*$/i.test( url ) ) return url; 45172 45173 // Blob URL 45174 if ( /^blob:.*$/i.test( url ) ) return url; 45175 45176 // Relative URL 45177 return path + url; 45178 45179 } 45180 45181} 45182 45183class InstancedBufferGeometry extends BufferGeometry { 45184 45185 constructor() { 45186 45187 super(); 45188 45189 this.isInstancedBufferGeometry = true; 45190 45191 this.type = 'InstancedBufferGeometry'; 45192 this.instanceCount = Infinity; 45193 45194 } 45195 45196 copy( source ) { 45197 45198 super.copy( source ); 45199 45200 this.instanceCount = source.instanceCount; 45201 45202 return this; 45203 45204 } 45205 45206 toJSON() { 45207 45208 const data = super.toJSON(); 45209 45210 data.instanceCount = this.instanceCount; 45211 45212 data.isInstancedBufferGeometry = true; 45213 45214 return data; 45215 45216 } 45217 45218} 45219 45220class BufferGeometryLoader extends Loader { 45221 45222 constructor( manager ) { 45223 45224 super( manager ); 45225 45226 } 45227 45228 load( url, onLoad, onProgress, onError ) { 45229 45230 const scope = this; 45231 45232 const loader = new FileLoader( scope.manager ); 45233 loader.setPath( scope.path ); 45234 loader.setRequestHeader( scope.requestHeader ); 45235 loader.setWithCredentials( scope.withCredentials ); 45236 loader.load( url, function ( text ) { 45237 45238 try { 45239 45240 onLoad( scope.parse( JSON.parse( text ) ) ); 45241 45242 } catch ( e ) { 45243 45244 if ( onError ) { 45245 45246 onError( e ); 45247 45248 } else { 45249 45250 console.error( e ); 45251 45252 } 45253 45254 scope.manager.itemError( url ); 45255 45256 } 45257 45258 }, onProgress, onError ); 45259 45260 } 45261 45262 parse( json ) { 45263 45264 const interleavedBufferMap = {}; 45265 const arrayBufferMap = {}; 45266 45267 function getInterleavedBuffer( json, uuid ) { 45268 45269 if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ]; 45270 45271 const interleavedBuffers = json.interleavedBuffers; 45272 const interleavedBuffer = interleavedBuffers[ uuid ]; 45273 45274 const buffer = getArrayBuffer( json, interleavedBuffer.buffer ); 45275 45276 const array = getTypedArray( interleavedBuffer.type, buffer ); 45277 const ib = new InterleavedBuffer( array, interleavedBuffer.stride ); 45278 ib.uuid = interleavedBuffer.uuid; 45279 45280 interleavedBufferMap[ uuid ] = ib; 45281 45282 return ib; 45283 45284 } 45285 45286 function getArrayBuffer( json, uuid ) { 45287 45288 if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ]; 45289 45290 const arrayBuffers = json.arrayBuffers; 45291 const arrayBuffer = arrayBuffers[ uuid ]; 45292 45293 const ab = new Uint32Array( arrayBuffer ).buffer; 45294 45295 arrayBufferMap[ uuid ] = ab; 45296 45297 return ab; 45298 45299 } 45300 45301 const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry(); 45302 45303 const index = json.data.index; 45304 45305 if ( index !== undefined ) { 45306 45307 const typedArray = getTypedArray( index.type, index.array ); 45308 geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); 45309 45310 } 45311 45312 const attributes = json.data.attributes; 45313 45314 for ( const key in attributes ) { 45315 45316 const attribute = attributes[ key ]; 45317 let bufferAttribute; 45318 45319 if ( attribute.isInterleavedBufferAttribute ) { 45320 45321 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); 45322 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); 45323 45324 } else { 45325 45326 const typedArray = getTypedArray( attribute.type, attribute.array ); 45327 const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute; 45328 bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized ); 45329 45330 } 45331 45332 if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; 45333 if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage ); 45334 45335 geometry.setAttribute( key, bufferAttribute ); 45336 45337 } 45338 45339 const morphAttributes = json.data.morphAttributes; 45340 45341 if ( morphAttributes ) { 45342 45343 for ( const key in morphAttributes ) { 45344 45345 const attributeArray = morphAttributes[ key ]; 45346 45347 const array = []; 45348 45349 for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { 45350 45351 const attribute = attributeArray[ i ]; 45352 let bufferAttribute; 45353 45354 if ( attribute.isInterleavedBufferAttribute ) { 45355 45356 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); 45357 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); 45358 45359 } else { 45360 45361 const typedArray = getTypedArray( attribute.type, attribute.array ); 45362 bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ); 45363 45364 } 45365 45366 if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; 45367 array.push( bufferAttribute ); 45368 45369 } 45370 45371 geometry.morphAttributes[ key ] = array; 45372 45373 } 45374 45375 } 45376 45377 const morphTargetsRelative = json.data.morphTargetsRelative; 45378 45379 if ( morphTargetsRelative ) { 45380 45381 geometry.morphTargetsRelative = true; 45382 45383 } 45384 45385 const groups = json.data.groups || json.data.drawcalls || json.data.offsets; 45386 45387 if ( groups !== undefined ) { 45388 45389 for ( let i = 0, n = groups.length; i !== n; ++ i ) { 45390 45391 const group = groups[ i ]; 45392 45393 geometry.addGroup( group.start, group.count, group.materialIndex ); 45394 45395 } 45396 45397 } 45398 45399 const boundingSphere = json.data.boundingSphere; 45400 45401 if ( boundingSphere !== undefined ) { 45402 45403 const center = new Vector3(); 45404 45405 if ( boundingSphere.center !== undefined ) { 45406 45407 center.fromArray( boundingSphere.center ); 45408 45409 } 45410 45411 geometry.boundingSphere = new Sphere( center, boundingSphere.radius ); 45412 45413 } 45414 45415 if ( json.name ) geometry.name = json.name; 45416 if ( json.userData ) geometry.userData = json.userData; 45417 45418 return geometry; 45419 45420 } 45421 45422} 45423 45424class ObjectLoader extends Loader { 45425 45426 constructor( manager ) { 45427 45428 super( manager ); 45429 45430 } 45431 45432 load( url, onLoad, onProgress, onError ) { 45433 45434 const scope = this; 45435 45436 const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; 45437 this.resourcePath = this.resourcePath || path; 45438 45439 const loader = new FileLoader( this.manager ); 45440 loader.setPath( this.path ); 45441 loader.setRequestHeader( this.requestHeader ); 45442 loader.setWithCredentials( this.withCredentials ); 45443 loader.load( url, function ( text ) { 45444 45445 let json = null; 45446 45447 try { 45448 45449 json = JSON.parse( text ); 45450 45451 } catch ( error ) { 45452 45453 if ( onError !== undefined ) onError( error ); 45454 45455 console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); 45456 45457 return; 45458 45459 } 45460 45461 const metadata = json.metadata; 45462 45463 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { 45464 45465 if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) ); 45466 45467 console.error( 'THREE.ObjectLoader: Can\'t load ' + url ); 45468 return; 45469 45470 } 45471 45472 scope.parse( json, onLoad ); 45473 45474 }, onProgress, onError ); 45475 45476 } 45477 45478 async loadAsync( url, onProgress ) { 45479 45480 const scope = this; 45481 45482 const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; 45483 this.resourcePath = this.resourcePath || path; 45484 45485 const loader = new FileLoader( this.manager ); 45486 loader.setPath( this.path ); 45487 loader.setRequestHeader( this.requestHeader ); 45488 loader.setWithCredentials( this.withCredentials ); 45489 45490 const text = await loader.loadAsync( url, onProgress ); 45491 45492 const json = JSON.parse( text ); 45493 45494 const metadata = json.metadata; 45495 45496 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { 45497 45498 throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url ); 45499 45500 } 45501 45502 return await scope.parseAsync( json ); 45503 45504 } 45505 45506 parse( json, onLoad ) { 45507 45508 const animations = this.parseAnimations( json.animations ); 45509 const shapes = this.parseShapes( json.shapes ); 45510 const geometries = this.parseGeometries( json.geometries, shapes ); 45511 45512 const images = this.parseImages( json.images, function () { 45513 45514 if ( onLoad !== undefined ) onLoad( object ); 45515 45516 } ); 45517 45518 const textures = this.parseTextures( json.textures, images ); 45519 const materials = this.parseMaterials( json.materials, textures ); 45520 45521 const object = this.parseObject( json.object, geometries, materials, textures, animations ); 45522 const skeletons = this.parseSkeletons( json.skeletons, object ); 45523 45524 this.bindSkeletons( object, skeletons ); 45525 45526 // 45527 45528 if ( onLoad !== undefined ) { 45529 45530 let hasImages = false; 45531 45532 for ( const uuid in images ) { 45533 45534 if ( images[ uuid ].data instanceof HTMLImageElement ) { 45535 45536 hasImages = true; 45537 break; 45538 45539 } 45540 45541 } 45542 45543 if ( hasImages === false ) onLoad( object ); 45544 45545 } 45546 45547 return object; 45548 45549 } 45550 45551 async parseAsync( json ) { 45552 45553 const animations = this.parseAnimations( json.animations ); 45554 const shapes = this.parseShapes( json.shapes ); 45555 const geometries = this.parseGeometries( json.geometries, shapes ); 45556 45557 const images = await this.parseImagesAsync( json.images ); 45558 45559 const textures = this.parseTextures( json.textures, images ); 45560 const materials = this.parseMaterials( json.materials, textures ); 45561 45562 const object = this.parseObject( json.object, geometries, materials, textures, animations ); 45563 const skeletons = this.parseSkeletons( json.skeletons, object ); 45564 45565 this.bindSkeletons( object, skeletons ); 45566 45567 return object; 45568 45569 } 45570 45571 parseShapes( json ) { 45572 45573 const shapes = {}; 45574 45575 if ( json !== undefined ) { 45576 45577 for ( let i = 0, l = json.length; i < l; i ++ ) { 45578 45579 const shape = new Shape().fromJSON( json[ i ] ); 45580 45581 shapes[ shape.uuid ] = shape; 45582 45583 } 45584 45585 } 45586 45587 return shapes; 45588 45589 } 45590 45591 parseSkeletons( json, object ) { 45592 45593 const skeletons = {}; 45594 const bones = {}; 45595 45596 // generate bone lookup table 45597 45598 object.traverse( function ( child ) { 45599 45600 if ( child.isBone ) bones[ child.uuid ] = child; 45601 45602 } ); 45603 45604 // create skeletons 45605 45606 if ( json !== undefined ) { 45607 45608 for ( let i = 0, l = json.length; i < l; i ++ ) { 45609 45610 const skeleton = new Skeleton().fromJSON( json[ i ], bones ); 45611 45612 skeletons[ skeleton.uuid ] = skeleton; 45613 45614 } 45615 45616 } 45617 45618 return skeletons; 45619 45620 } 45621 45622 parseGeometries( json, shapes ) { 45623 45624 const geometries = {}; 45625 45626 if ( json !== undefined ) { 45627 45628 const bufferGeometryLoader = new BufferGeometryLoader(); 45629 45630 for ( let i = 0, l = json.length; i < l; i ++ ) { 45631 45632 let geometry; 45633 const data = json[ i ]; 45634 45635 switch ( data.type ) { 45636 45637 case 'BufferGeometry': 45638 case 'InstancedBufferGeometry': 45639 45640 geometry = bufferGeometryLoader.parse( data ); 45641 break; 45642 45643 default: 45644 45645 if ( data.type in Geometries ) { 45646 45647 geometry = Geometries[ data.type ].fromJSON( data, shapes ); 45648 45649 } else { 45650 45651 console.warn( `THREE.ObjectLoader: Unsupported geometry type "${ data.type }"` ); 45652 45653 } 45654 45655 } 45656 45657 geometry.uuid = data.uuid; 45658 45659 if ( data.name !== undefined ) geometry.name = data.name; 45660 if ( data.userData !== undefined ) geometry.userData = data.userData; 45661 45662 geometries[ data.uuid ] = geometry; 45663 45664 } 45665 45666 } 45667 45668 return geometries; 45669 45670 } 45671 45672 parseMaterials( json, textures ) { 45673 45674 const cache = {}; // MultiMaterial 45675 const materials = {}; 45676 45677 if ( json !== undefined ) { 45678 45679 const loader = new MaterialLoader(); 45680 loader.setTextures( textures ); 45681 45682 for ( let i = 0, l = json.length; i < l; i ++ ) { 45683 45684 const data = json[ i ]; 45685 45686 if ( cache[ data.uuid ] === undefined ) { 45687 45688 cache[ data.uuid ] = loader.parse( data ); 45689 45690 } 45691 45692 materials[ data.uuid ] = cache[ data.uuid ]; 45693 45694 } 45695 45696 } 45697 45698 return materials; 45699 45700 } 45701 45702 parseAnimations( json ) { 45703 45704 const animations = {}; 45705 45706 if ( json !== undefined ) { 45707 45708 for ( let i = 0; i < json.length; i ++ ) { 45709 45710 const data = json[ i ]; 45711 45712 const clip = AnimationClip.parse( data ); 45713 45714 animations[ clip.uuid ] = clip; 45715 45716 } 45717 45718 } 45719 45720 return animations; 45721 45722 } 45723 45724 parseImages( json, onLoad ) { 45725 45726 const scope = this; 45727 const images = {}; 45728 45729 let loader; 45730 45731 function loadImage( url ) { 45732 45733 scope.manager.itemStart( url ); 45734 45735 return loader.load( url, function () { 45736 45737 scope.manager.itemEnd( url ); 45738 45739 }, undefined, function () { 45740 45741 scope.manager.itemError( url ); 45742 scope.manager.itemEnd( url ); 45743 45744 } ); 45745 45746 } 45747 45748 function deserializeImage( image ) { 45749 45750 if ( typeof image === 'string' ) { 45751 45752 const url = image; 45753 45754 const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; 45755 45756 return loadImage( path ); 45757 45758 } else { 45759 45760 if ( image.data ) { 45761 45762 return { 45763 data: getTypedArray( image.type, image.data ), 45764 width: image.width, 45765 height: image.height 45766 }; 45767 45768 } else { 45769 45770 return null; 45771 45772 } 45773 45774 } 45775 45776 } 45777 45778 if ( json !== undefined && json.length > 0 ) { 45779 45780 const manager = new LoadingManager( onLoad ); 45781 45782 loader = new ImageLoader( manager ); 45783 loader.setCrossOrigin( this.crossOrigin ); 45784 45785 for ( let i = 0, il = json.length; i < il; i ++ ) { 45786 45787 const image = json[ i ]; 45788 const url = image.url; 45789 45790 if ( Array.isArray( url ) ) { 45791 45792 // load array of images e.g CubeTexture 45793 45794 const imageArray = []; 45795 45796 for ( let j = 0, jl = url.length; j < jl; j ++ ) { 45797 45798 const currentUrl = url[ j ]; 45799 45800 const deserializedImage = deserializeImage( currentUrl ); 45801 45802 if ( deserializedImage !== null ) { 45803 45804 if ( deserializedImage instanceof HTMLImageElement ) { 45805 45806 imageArray.push( deserializedImage ); 45807 45808 } else { 45809 45810 // special case: handle array of data textures for cube textures 45811 45812 imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); 45813 45814 } 45815 45816 } 45817 45818 } 45819 45820 images[ image.uuid ] = new Source( imageArray ); 45821 45822 } else { 45823 45824 // load single image 45825 45826 const deserializedImage = deserializeImage( image.url ); 45827 images[ image.uuid ] = new Source( deserializedImage ); 45828 45829 45830 } 45831 45832 } 45833 45834 } 45835 45836 return images; 45837 45838 } 45839 45840 async parseImagesAsync( json ) { 45841 45842 const scope = this; 45843 const images = {}; 45844 45845 let loader; 45846 45847 async function deserializeImage( image ) { 45848 45849 if ( typeof image === 'string' ) { 45850 45851 const url = image; 45852 45853 const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; 45854 45855 return await loader.loadAsync( path ); 45856 45857 } else { 45858 45859 if ( image.data ) { 45860 45861 return { 45862 data: getTypedArray( image.type, image.data ), 45863 width: image.width, 45864 height: image.height 45865 }; 45866 45867 } else { 45868 45869 return null; 45870 45871 } 45872 45873 } 45874 45875 } 45876 45877 if ( json !== undefined && json.length > 0 ) { 45878 45879 loader = new ImageLoader( this.manager ); 45880 loader.setCrossOrigin( this.crossOrigin ); 45881 45882 for ( let i = 0, il = json.length; i < il; i ++ ) { 45883 45884 const image = json[ i ]; 45885 const url = image.url; 45886 45887 if ( Array.isArray( url ) ) { 45888 45889 // load array of images e.g CubeTexture 45890 45891 const imageArray = []; 45892 45893 for ( let j = 0, jl = url.length; j < jl; j ++ ) { 45894 45895 const currentUrl = url[ j ]; 45896 45897 const deserializedImage = await deserializeImage( currentUrl ); 45898 45899 if ( deserializedImage !== null ) { 45900 45901 if ( deserializedImage instanceof HTMLImageElement ) { 45902 45903 imageArray.push( deserializedImage ); 45904 45905 } else { 45906 45907 // special case: handle array of data textures for cube textures 45908 45909 imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); 45910 45911 } 45912 45913 } 45914 45915 } 45916 45917 images[ image.uuid ] = new Source( imageArray ); 45918 45919 } else { 45920 45921 // load single image 45922 45923 const deserializedImage = await deserializeImage( image.url ); 45924 images[ image.uuid ] = new Source( deserializedImage ); 45925 45926 } 45927 45928 } 45929 45930 } 45931 45932 return images; 45933 45934 } 45935 45936 parseTextures( json, images ) { 45937 45938 function parseConstant( value, type ) { 45939 45940 if ( typeof value === 'number' ) return value; 45941 45942 console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); 45943 45944 return type[ value ]; 45945 45946 } 45947 45948 const textures = {}; 45949 45950 if ( json !== undefined ) { 45951 45952 for ( let i = 0, l = json.length; i < l; i ++ ) { 45953 45954 const data = json[ i ]; 45955 45956 if ( data.image === undefined ) { 45957 45958 console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); 45959 45960 } 45961 45962 if ( images[ data.image ] === undefined ) { 45963 45964 console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); 45965 45966 } 45967 45968 const source = images[ data.image ]; 45969 const image = source.data; 45970 45971 let texture; 45972 45973 if ( Array.isArray( image ) ) { 45974 45975 texture = new CubeTexture(); 45976 45977 if ( image.length === 6 ) texture.needsUpdate = true; 45978 45979 } else { 45980 45981 if ( image && image.data ) { 45982 45983 texture = new DataTexture(); 45984 45985 } else { 45986 45987 texture = new Texture(); 45988 45989 } 45990 45991 if ( image ) texture.needsUpdate = true; // textures can have undefined image data 45992 45993 } 45994 45995 texture.source = source; 45996 45997 texture.uuid = data.uuid; 45998 45999 if ( data.name !== undefined ) texture.name = data.name; 46000 46001 if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); 46002 if ( data.channel !== undefined ) texture.channel = data.channel; 46003 46004 if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); 46005 if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); 46006 if ( data.center !== undefined ) texture.center.fromArray( data.center ); 46007 if ( data.rotation !== undefined ) texture.rotation = data.rotation; 46008 46009 if ( data.wrap !== undefined ) { 46010 46011 texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); 46012 texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); 46013 46014 } 46015 46016 if ( data.format !== undefined ) texture.format = data.format; 46017 if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat; 46018 if ( data.type !== undefined ) texture.type = data.type; 46019 if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace; 46020 46021 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); 46022 if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); 46023 if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy; 46024 46025 if ( data.flipY !== undefined ) texture.flipY = data.flipY; 46026 46027 if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps; 46028 if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha; 46029 if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment; 46030 if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction; 46031 46032 if ( data.userData !== undefined ) texture.userData = data.userData; 46033 46034 textures[ data.uuid ] = texture; 46035 46036 } 46037 46038 } 46039 46040 return textures; 46041 46042 } 46043 46044 parseObject( data, geometries, materials, textures, animations ) { 46045 46046 let object; 46047 46048 function getGeometry( name ) { 46049 46050 if ( geometries[ name ] === undefined ) { 46051 46052 console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); 46053 46054 } 46055 46056 return geometries[ name ]; 46057 46058 } 46059 46060 function getMaterial( name ) { 46061 46062 if ( name === undefined ) return undefined; 46063 46064 if ( Array.isArray( name ) ) { 46065 46066 const array = []; 46067 46068 for ( let i = 0, l = name.length; i < l; i ++ ) { 46069 46070 const uuid = name[ i ]; 46071 46072 if ( materials[ uuid ] === undefined ) { 46073 46074 console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); 46075 46076 } 46077 46078 array.push( materials[ uuid ] ); 46079 46080 } 46081 46082 return array; 46083 46084 } 46085 46086 if ( materials[ name ] === undefined ) { 46087 46088 console.warn( 'THREE.ObjectLoader: Undefined material', name ); 46089 46090 } 46091 46092 return materials[ name ]; 46093 46094 } 46095 46096 function getTexture( uuid ) { 46097 46098 if ( textures[ uuid ] === undefined ) { 46099 46100 console.warn( 'THREE.ObjectLoader: Undefined texture', uuid ); 46101 46102 } 46103 46104 return textures[ uuid ]; 46105 46106 } 46107 46108 let geometry, material; 46109 46110 switch ( data.type ) { 46111 46112 case 'Scene': 46113 46114 object = new Scene(); 46115 46116 if ( data.background !== undefined ) { 46117 46118 if ( Number.isInteger( data.background ) ) { 46119 46120 object.background = new Color( data.background ); 46121 46122 } else { 46123 46124 object.background = getTexture( data.background ); 46125 46126 } 46127 46128 } 46129 46130 if ( data.environment !== undefined ) { 46131 46132 object.environment = getTexture( data.environment ); 46133 46134 } 46135 46136 if ( data.fog !== undefined ) { 46137 46138 if ( data.fog.type === 'Fog' ) { 46139 46140 object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); 46141 46142 } else if ( data.fog.type === 'FogExp2' ) { 46143 46144 object.fog = new FogExp2( data.fog.color, data.fog.density ); 46145 46146 } 46147 46148 if ( data.fog.name !== '' ) { 46149 46150 object.fog.name = data.fog.name; 46151 46152 } 46153 46154 } 46155 46156 if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness; 46157 if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity; 46158 if ( data.backgroundRotation !== undefined ) object.backgroundRotation.fromArray( data.backgroundRotation ); 46159 46160 if ( data.environmentIntensity !== undefined ) object.environmentIntensity = data.environmentIntensity; 46161 if ( data.environmentRotation !== undefined ) object.environmentRotation.fromArray( data.environmentRotation ); 46162 46163 break; 46164 46165 case 'PerspectiveCamera': 46166 46167 object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); 46168 46169 if ( data.focus !== undefined ) object.focus = data.focus; 46170 if ( data.zoom !== undefined ) object.zoom = data.zoom; 46171 if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge; 46172 if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset; 46173 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); 46174 46175 break; 46176 46177 case 'OrthographicCamera': 46178 46179 object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); 46180 46181 if ( data.zoom !== undefined ) object.zoom = data.zoom; 46182 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); 46183 46184 break; 46185 46186 case 'AmbientLight': 46187 46188 object = new AmbientLight( data.color, data.intensity ); 46189 46190 break; 46191 46192 case 'DirectionalLight': 46193 46194 object = new DirectionalLight( data.color, data.intensity ); 46195 46196 break; 46197 46198 case 'PointLight': 46199 46200 object = new PointLight( data.color, data.intensity, data.distance, data.decay ); 46201 46202 break; 46203 46204 case 'RectAreaLight': 46205 46206 object = new RectAreaLight( data.color, data.intensity, data.width, data.height ); 46207 46208 break; 46209 46210 case 'SpotLight': 46211 46212 object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay ); 46213 46214 break; 46215 46216 case 'HemisphereLight': 46217 46218 object = new HemisphereLight( data.color, data.groundColor, data.intensity ); 46219 46220 break; 46221 46222 case 'LightProbe': 46223 46224 object = new LightProbe().fromJSON( data ); 46225 46226 break; 46227 46228 case 'SkinnedMesh': 46229 46230 geometry = getGeometry( data.geometry ); 46231 material = getMaterial( data.material ); 46232 46233 object = new SkinnedMesh( geometry, material ); 46234 46235 if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
vendor: 17,451 bytes, lines 46236-47066
46236 if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix ); 46237 if ( data.skeleton !== undefined ) object.skeleton = data.skeleton; 46238 46239 break; 46240 46241 case 'Mesh': 46242 46243 geometry = getGeometry( data.geometry ); 46244 material = getMaterial( data.material ); 46245 46246 object = new Mesh( geometry, material ); 46247 46248 break; 46249 46250 case 'InstancedMesh': 46251 46252 geometry = getGeometry( data.geometry ); 46253 material = getMaterial( data.material ); 46254 const count = data.count; 46255 const instanceMatrix = data.instanceMatrix; 46256 const instanceColor = data.instanceColor; 46257 46258 object = new InstancedMesh( geometry, material, count ); 46259 object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 ); 46260 if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize ); 46261 46262 break; 46263 46264 case 'BatchedMesh': 46265 46266 geometry = getGeometry( data.geometry ); 46267 material = getMaterial( data.material ); 46268 46269 object = new BatchedMesh( data.maxGeometryCount, data.maxVertexCount, data.maxIndexCount, material ); 46270 object.geometry = geometry; 46271 object.perObjectFrustumCulled = data.perObjectFrustumCulled; 46272 object.sortObjects = data.sortObjects; 46273 46274 object._drawRanges = data.drawRanges; 46275 object._reservedRanges = data.reservedRanges; 46276 46277 object._visibility = data.visibility; 46278 object._active = data.active; 46279 object._bounds = data.bounds.map( bound => { 46280 46281 const box = new Box3(); 46282 box.min.fromArray( bound.boxMin ); 46283 box.max.fromArray( bound.boxMax ); 46284 46285 const sphere = new Sphere(); 46286 sphere.radius = bound.sphereRadius; 46287 sphere.center.fromArray( bound.sphereCenter ); 46288 46289 return { 46290 boxInitialized: bound.boxInitialized, 46291 box: box, 46292 46293 sphereInitialized: bound.sphereInitialized, 46294 sphere: sphere 46295 }; 46296 46297 } ); 46298 46299 object._maxGeometryCount = data.maxGeometryCount; 46300 object._maxVertexCount = data.maxVertexCount; 46301 object._maxIndexCount = data.maxIndexCount; 46302 46303 object._geometryInitialized = data.geometryInitialized; 46304 object._geometryCount = data.geometryCount; 46305 46306 object._matricesTexture = getTexture( data.matricesTexture.uuid ); 46307 46308 break; 46309 46310 case 'LOD': 46311 46312 object = new LOD(); 46313 46314 break; 46315 46316 case 'Line': 46317 46318 object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) ); 46319 46320 break; 46321 46322 case 'LineLoop': 46323 46324 object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); 46325 46326 break; 46327 46328 case 'LineSegments': 46329 46330 object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); 46331 46332 break; 46333 46334 case 'PointCloud': 46335 case 'Points': 46336 46337 object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) ); 46338 46339 break; 46340 46341 case 'Sprite': 46342 46343 object = new Sprite( getMaterial( data.material ) ); 46344 46345 break; 46346 46347 case 'Group': 46348 46349 object = new Group(); 46350 46351 break; 46352 46353 case 'Bone': 46354 46355 object = new Bone(); 46356 46357 break; 46358 46359 default: 46360 46361 object = new Object3D(); 46362 46363 } 46364 46365 object.uuid = data.uuid; 46366 46367 if ( data.name !== undefined ) object.name = data.name; 46368 46369 if ( data.matrix !== undefined ) { 46370 46371 object.matrix.fromArray( data.matrix ); 46372 46373 if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate; 46374 if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale ); 46375 46376 } else { 46377 46378 if ( data.position !== undefined ) object.position.fromArray( data.position ); 46379 if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation ); 46380 if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion ); 46381 if ( data.scale !== undefined ) object.scale.fromArray( data.scale ); 46382 46383 } 46384 46385 if ( data.up !== undefined ) object.up.fromArray( data.up ); 46386 46387 if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; 46388 if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; 46389 46390 if ( data.shadow ) { 46391 46392 if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias; 46393 if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias; 46394 if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius; 46395 if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize ); 46396 if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera ); 46397 46398 } 46399 46400 if ( data.visible !== undefined ) object.visible = data.visible; 46401 if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled; 46402 if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder; 46403 if ( data.userData !== undefined ) object.userData = data.userData; 46404 if ( data.layers !== undefined ) object.layers.mask = data.layers; 46405 46406 if ( data.children !== undefined ) { 46407 46408 const children = data.children; 46409 46410 for ( let i = 0; i < children.length; i ++ ) { 46411 46412 object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) ); 46413 46414 } 46415 46416 } 46417 46418 if ( data.animations !== undefined ) { 46419 46420 const objectAnimations = data.animations; 46421 46422 for ( let i = 0; i < objectAnimations.length; i ++ ) { 46423 46424 const uuid = objectAnimations[ i ]; 46425 46426 object.animations.push( animations[ uuid ] ); 46427 46428 } 46429 46430 } 46431 46432 if ( data.type === 'LOD' ) { 46433 46434 if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate; 46435 46436 const levels = data.levels; 46437 46438 for ( let l = 0; l < levels.length; l ++ ) { 46439 46440 const level = levels[ l ]; 46441 const child = object.getObjectByProperty( 'uuid', level.object ); 46442 46443 if ( child !== undefined ) { 46444 46445 object.addLevel( child, level.distance, level.hysteresis ); 46446 46447 } 46448 46449 } 46450 46451 } 46452 46453 return object; 46454 46455 } 46456 46457 bindSkeletons( object, skeletons ) { 46458 46459 if ( Object.keys( skeletons ).length === 0 ) return; 46460 46461 object.traverse( function ( child ) { 46462 46463 if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) { 46464 46465 const skeleton = skeletons[ child.skeleton ]; 46466 46467 if ( skeleton === undefined ) { 46468 46469 console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton ); 46470 46471 } else { 46472 46473 child.bind( skeleton, child.bindMatrix ); 46474 46475 } 46476 46477 } 46478 46479 } ); 46480 46481 } 46482 46483} 46484 46485const TEXTURE_MAPPING = { 46486 UVMapping: UVMapping, 46487 CubeReflectionMapping: CubeReflectionMapping, 46488 CubeRefractionMapping: CubeRefractionMapping, 46489 EquirectangularReflectionMapping: EquirectangularReflectionMapping, 46490 EquirectangularRefractionMapping: EquirectangularRefractionMapping, 46491 CubeUVReflectionMapping: CubeUVReflectionMapping 46492}; 46493 46494const TEXTURE_WRAPPING = { 46495 RepeatWrapping: RepeatWrapping, 46496 ClampToEdgeWrapping: ClampToEdgeWrapping, 46497 MirroredRepeatWrapping: MirroredRepeatWrapping 46498}; 46499 46500const TEXTURE_FILTER = { 46501 NearestFilter: NearestFilter, 46502 NearestMipmapNearestFilter: NearestMipmapNearestFilter, 46503 NearestMipmapLinearFilter: NearestMipmapLinearFilter, 46504 LinearFilter: LinearFilter, 46505 LinearMipmapNearestFilter: LinearMipmapNearestFilter, 46506 LinearMipmapLinearFilter: LinearMipmapLinearFilter 46507}; 46508 46509class ImageBitmapLoader extends Loader { 46510 46511 constructor( manager ) { 46512 46513 super( manager ); 46514 46515 this.isImageBitmapLoader = true; 46516 46517 if ( typeof createImageBitmap === 'undefined' ) { 46518 46519 console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' ); 46520 46521 } 46522 46523 if ( typeof fetch === 'undefined' ) { 46524 46525 console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' ); 46526 46527 } 46528 46529 this.options = { premultiplyAlpha: 'none' }; 46530 46531 } 46532 46533 setOptions( options ) { 46534 46535 this.options = options; 46536 46537 return this; 46538 46539 } 46540 46541 load( url, onLoad, onProgress, onError ) { 46542 46543 if ( url === undefined ) url = ''; 46544 46545 if ( this.path !== undefined ) url = this.path + url; 46546 46547 url = this.manager.resolveURL( url ); 46548 46549 const scope = this; 46550 46551 const cached = Cache.get( url ); 46552 46553 if ( cached !== undefined ) { 46554 46555 scope.manager.itemStart( url ); 46556 46557 // If cached is a promise, wait for it to resolve 46558 if ( cached.then ) { 46559 46560 cached.then( imageBitmap => { 46561 46562 if ( onLoad ) onLoad( imageBitmap ); 46563 46564 scope.manager.itemEnd( url ); 46565 46566 } ).catch( e => { 46567 46568 if ( onError ) onError( e ); 46569 46570 } ); 46571 return; 46572 46573 } 46574 46575 // If cached is not a promise (i.e., it's already an imageBitmap) 46576 setTimeout( function () { 46577 46578 if ( onLoad ) onLoad( cached ); 46579 46580 scope.manager.itemEnd( url ); 46581 46582 }, 0 ); 46583 46584 return cached; 46585 46586 } 46587 46588 const fetchOptions = {}; 46589 fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include'; 46590 fetchOptions.headers = this.requestHeader; 46591 46592 const promise = fetch( url, fetchOptions ).then( function ( res ) { 46593 46594 return res.blob(); 46595 46596 } ).then( function ( blob ) { 46597 46598 return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) ); 46599 46600 } ).then( function ( imageBitmap ) { 46601 46602 Cache.add( url, imageBitmap ); 46603 46604 if ( onLoad ) onLoad( imageBitmap ); 46605 46606 scope.manager.itemEnd( url ); 46607 46608 return imageBitmap; 46609 46610 } ).catch( function ( e ) { 46611 46612 if ( onError ) onError( e ); 46613 46614 Cache.remove( url ); 46615 46616 scope.manager.itemError( url ); 46617 scope.manager.itemEnd( url ); 46618 46619 } ); 46620 46621 Cache.add( url, promise ); 46622 scope.manager.itemStart( url ); 46623 46624 } 46625 46626} 46627 46628let _context; 46629 46630class AudioContext { 46631 46632 static getContext() { 46633 46634 if ( _context === undefined ) { 46635 46636 _context = new ( window.AudioContext || window.webkitAudioContext )(); 46637 46638 } 46639 46640 return _context; 46641 46642 } 46643 46644 static setContext( value ) { 46645 46646 _context = value; 46647 46648 } 46649 46650} 46651 46652class AudioLoader extends Loader { 46653 46654 constructor( manager ) { 46655 46656 super( manager ); 46657 46658 } 46659 46660 load( url, onLoad, onProgress, onError ) { 46661 46662 const scope = this; 46663 46664 const loader = new FileLoader( this.manager ); 46665 loader.setResponseType( 'arraybuffer' ); 46666 loader.setPath( this.path ); 46667 loader.setRequestHeader( this.requestHeader ); 46668 loader.setWithCredentials( this.withCredentials ); 46669 loader.load( url, function ( buffer ) { 46670 46671 try { 46672 46673 // Create a copy of the buffer. The `decodeAudioData` method 46674 // detaches the buffer when complete, preventing reuse. 46675 const bufferCopy = buffer.slice( 0 ); 46676 46677 const context = AudioContext.getContext(); 46678 context.decodeAudioData( bufferCopy, function ( audioBuffer ) { 46679 46680 onLoad( audioBuffer ); 46681 46682 } ).catch( handleError ); 46683 46684 } catch ( e ) { 46685 46686 handleError( e ); 46687 46688 } 46689 46690 }, onProgress, onError ); 46691 46692 function handleError( e ) { 46693 46694 if ( onError ) { 46695 46696 onError( e ); 46697 46698 } else { 46699 46700 console.error( e ); 46701 46702 } 46703 46704 scope.manager.itemError( url ); 46705 46706 } 46707 46708 } 46709 46710} 46711 46712const _eyeRight = /*@__PURE__*/ new Matrix4(); 46713const _eyeLeft = /*@__PURE__*/ new Matrix4(); 46714const _projectionMatrix = /*@__PURE__*/ new Matrix4(); 46715 46716class StereoCamera { 46717 46718 constructor() { 46719 46720 this.type = 'StereoCamera'; 46721 46722 this.aspect = 1; 46723 46724 this.eyeSep = 0.064; 46725 46726 this.cameraL = new PerspectiveCamera(); 46727 this.cameraL.layers.enable( 1 ); 46728 this.cameraL.matrixAutoUpdate = false; 46729 46730 this.cameraR = new PerspectiveCamera(); 46731 this.cameraR.layers.enable( 2 ); 46732 this.cameraR.matrixAutoUpdate = false; 46733 46734 this._cache = { 46735 focus: null, 46736 fov: null, 46737 aspect: null, 46738 near: null, 46739 far: null, 46740 zoom: null, 46741 eyeSep: null 46742 }; 46743 46744 } 46745 46746 update( camera ) { 46747 46748 const cache = this._cache; 46749 46750 const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov || 46751 cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near || 46752 cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep; 46753 46754 if ( needsUpdate ) { 46755 46756 cache.focus = camera.focus; 46757 cache.fov = camera.fov; 46758 cache.aspect = camera.aspect * this.aspect; 46759 cache.near = camera.near; 46760 cache.far = camera.far; 46761 cache.zoom = camera.zoom; 46762 cache.eyeSep = this.eyeSep; 46763 46764 // Off-axis stereoscopic effect based on 46765 // http://paulbourke.net/stereographics/stereorender/ 46766 46767 _projectionMatrix.copy( camera.projectionMatrix ); 46768 const eyeSepHalf = cache.eyeSep / 2; 46769 const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus; 46770 const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom; 46771 let xmin, xmax; 46772 46773 // translate xOffset 46774 46775 _eyeLeft.elements[ 12 ] = - eyeSepHalf; 46776 _eyeRight.elements[ 12 ] = eyeSepHalf; 46777 46778 // for left eye 46779 46780 xmin = - ymax * cache.aspect + eyeSepOnProjection; 46781 xmax = ymax * cache.aspect + eyeSepOnProjection; 46782 46783 _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); 46784 _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); 46785 46786 this.cameraL.projectionMatrix.copy( _projectionMatrix ); 46787 46788 // for right eye 46789 46790 xmin = - ymax * cache.aspect - eyeSepOnProjection; 46791 xmax = ymax * cache.aspect - eyeSepOnProjection; 46792 46793 _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); 46794 _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); 46795 46796 this.cameraR.projectionMatrix.copy( _projectionMatrix ); 46797 46798 } 46799 46800 this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft ); 46801 this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight ); 46802 46803 } 46804 46805} 46806 46807class Clock { 46808 46809 constructor( autoStart = true ) { 46810 46811 this.autoStart = autoStart; 46812 46813 this.startTime = 0; 46814 this.oldTime = 0; 46815 this.elapsedTime = 0; 46816 46817 this.running = false; 46818 46819 } 46820 46821 start() { 46822 46823 this.startTime = now(); 46824 46825 this.oldTime = this.startTime; 46826 this.elapsedTime = 0; 46827 this.running = true; 46828 46829 } 46830 46831 stop() { 46832 46833 this.getElapsedTime(); 46834 this.running = false; 46835 this.autoStart = false; 46836 46837 } 46838 46839 getElapsedTime() { 46840 46841 this.getDelta(); 46842 return this.elapsedTime; 46843 46844 } 46845 46846 getDelta() { 46847 46848 let diff = 0; 46849 46850 if ( this.autoStart && ! this.running ) { 46851 46852 this.start(); 46853 return 0; 46854 46855 } 46856 46857 if ( this.running ) { 46858 46859 const newTime = now(); 46860 46861 diff = ( newTime - this.oldTime ) / 1000; 46862 this.oldTime = newTime; 46863 46864 this.elapsedTime += diff; 46865 46866 } 46867 46868 return diff; 46869 46870 } 46871 46872} 46873 46874function now() { 46875 46876 return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732 46877 46878} 46879 46880const _position$1 = /*@__PURE__*/ new Vector3(); 46881const _quaternion$1 = /*@__PURE__*/ new Quaternion(); 46882const _scale$1 = /*@__PURE__*/ new Vector3(); 46883const _orientation$1 = /*@__PURE__*/ new Vector3(); 46884 46885class AudioListener extends Object3D { 46886 46887 constructor() { 46888 46889 super(); 46890 46891 this.type = 'AudioListener'; 46892 46893 this.context = AudioContext.getContext(); 46894 46895 this.gain = this.context.createGain(); 46896 this.gain.connect( this.context.destination ); 46897 46898 this.filter = null; 46899 46900 this.timeDelta = 0; 46901 46902 // private 46903 46904 this._clock = new Clock(); 46905 46906 } 46907 46908 getInput() { 46909 46910 return this.gain; 46911 46912 } 46913 46914 removeFilter() { 46915 46916 if ( this.filter !== null ) { 46917 46918 this.gain.disconnect( this.filter ); 46919 this.filter.disconnect( this.context.destination ); 46920 this.gain.connect( this.context.destination ); 46921 this.filter = null; 46922 46923 } 46924 46925 return this; 46926 46927 } 46928 46929 getFilter() { 46930 46931 return this.filter; 46932 46933 } 46934 46935 setFilter( value ) { 46936 46937 if ( this.filter !== null ) { 46938 46939 this.gain.disconnect( this.filter ); 46940 this.filter.disconnect( this.context.destination ); 46941 46942 } else { 46943 46944 this.gain.disconnect( this.context.destination ); 46945 46946 } 46947 46948 this.filter = value; 46949 this.gain.connect( this.filter ); 46950 this.filter.connect( this.context.destination ); 46951 46952 return this; 46953 46954 } 46955 46956 getMasterVolume() { 46957 46958 return this.gain.gain.value; 46959 46960 } 46961 46962 setMasterVolume( value ) { 46963 46964 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); 46965 46966 return this; 46967 46968 } 46969 46970 updateMatrixWorld( force ) { 46971 46972 super.updateMatrixWorld( force ); 46973 46974 const listener = this.context.listener; 46975 const up = this.up; 46976 46977 this.timeDelta = this._clock.getDelta(); 46978 46979 this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 ); 46980 46981 _orientation$1.set( 0, 0, - 1 ).applyQuaternion( _quaternion$1 ); 46982 46983 if ( listener.positionX ) { 46984 46985 // code path for Chrome (see #14393) 46986 46987 const endTime = this.context.currentTime + this.timeDelta; 46988 46989 listener.positionX.linearRampToValueAtTime( _position$1.x, endTime ); 46990 listener.positionY.linearRampToValueAtTime( _position$1.y, endTime ); 46991 listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime ); 46992 listener.forwardX.linearRampToValueAtTime( _orientation$1.x, endTime ); 46993 listener.forwardY.linearRampToValueAtTime( _orientation$1.y, endTime ); 46994 listener.forwardZ.linearRampToValueAtTime( _orientation$1.z, endTime ); 46995 listener.upX.linearRampToValueAtTime( up.x, endTime ); 46996 listener.upY.linearRampToValueAtTime( up.y, endTime ); 46997 listener.upZ.linearRampToValueAtTime( up.z, endTime ); 46998 46999 } else { 47000 47001 listener.setPosition( _position$1.x, _position$1.y, _position$1.z ); 47002 listener.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z ); 47003 47004 } 47005 47006 } 47007 47008} 47009 47010class Audio extends Object3D { 47011 47012 constructor( listener ) { 47013 47014 super(); 47015 47016 this.type = 'Audio'; 47017 47018 this.listener = listener; 47019 this.context = listener.context; 47020 47021 this.gain = this.context.createGain(); 47022 this.gain.connect( listener.getInput() ); 47023 47024 this.autoplay = false; 47025 47026 this.buffer = null; 47027 this.detune = 0; 47028 this.loop = false; 47029 this.loopStart = 0; 47030 this.loopEnd = 0; 47031 this.offset = 0; 47032 this.duration = undefined; 47033 this.playbackRate = 1; 47034 this.isPlaying = false; 47035 this.hasPlaybackControl = true; 47036 this.source = null; 47037 this.sourceType = 'empty'; 47038 47039 this._startedAt = 0; 47040 this._progress = 0; 47041 this._connected = false; 47042 47043 this.filters = []; 47044 47045 } 47046 47047 getOutput() { 47048 47049 return this.gain; 47050 47051 } 47052 47053 setNodeSource( audioNode ) { 47054 47055 this.hasPlaybackControl = false; 47056 this.sourceType = 'audioNode'; 47057 this.source = audioNode; 47058 this.connect(); 47059 47060 return this; 47061 47062 } 47063 47064 setMediaElementSource( mediaElement ) { 47065 47066 this.hasPlaybackControl = false;
vendor: 8,682 bytes, lines 47067-47610
47067 this.sourceType = 'mediaNode'; 47068 this.source = this.context.createMediaElementSource( mediaElement ); 47069 this.connect(); 47070 47071 return this; 47072 47073 } 47074 47075 setMediaStreamSource( mediaStream ) { 47076 47077 this.hasPlaybackControl = false; 47078 this.sourceType = 'mediaStreamNode'; 47079 this.source = this.context.createMediaStreamSource( mediaStream ); 47080 this.connect(); 47081 47082 return this; 47083 47084 } 47085 47086 setBuffer( audioBuffer ) { 47087 47088 this.buffer = audioBuffer; 47089 this.sourceType = 'buffer'; 47090 47091 if ( this.autoplay ) this.play(); 47092 47093 return this; 47094 47095 } 47096 47097 play( delay = 0 ) { 47098 47099 if ( this.isPlaying === true ) { 47100 47101 console.warn( 'THREE.Audio: Audio is already playing.' ); 47102 return; 47103 47104 } 47105 47106 if ( this.hasPlaybackControl === false ) { 47107 47108 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47109 return; 47110 47111 } 47112 47113 this._startedAt = this.context.currentTime + delay; 47114 47115 const source = this.context.createBufferSource(); 47116 source.buffer = this.buffer; 47117 source.loop = this.loop; 47118 source.loopStart = this.loopStart; 47119 source.loopEnd = this.loopEnd; 47120 source.onended = this.onEnded.bind( this ); 47121 source.start( this._startedAt, this._progress + this.offset, this.duration ); 47122 47123 this.isPlaying = true; 47124 47125 this.source = source; 47126 47127 this.setDetune( this.detune ); 47128 this.setPlaybackRate( this.playbackRate ); 47129 47130 return this.connect(); 47131 47132 } 47133 47134 pause() { 47135 47136 if ( this.hasPlaybackControl === false ) { 47137 47138 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47139 return; 47140 47141 } 47142 47143 if ( this.isPlaying === true ) { 47144 47145 // update current progress 47146 47147 this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate; 47148 47149 if ( this.loop === true ) { 47150 47151 // ensure _progress does not exceed duration with looped audios 47152 47153 this._progress = this._progress % ( this.duration || this.buffer.duration ); 47154 47155 } 47156 47157 this.source.stop(); 47158 this.source.onended = null; 47159 47160 this.isPlaying = false; 47161 47162 } 47163 47164 return this; 47165 47166 } 47167 47168 stop() { 47169 47170 if ( this.hasPlaybackControl === false ) { 47171 47172 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47173 return; 47174 47175 } 47176 47177 this._progress = 0; 47178 47179 if ( this.source !== null ) { 47180 47181 this.source.stop(); 47182 this.source.onended = null; 47183 47184 } 47185 47186 this.isPlaying = false; 47187 47188 return this; 47189 47190 } 47191 47192 connect() { 47193 47194 if ( this.filters.length > 0 ) { 47195 47196 this.source.connect( this.filters[ 0 ] ); 47197 47198 for ( let i = 1, l = this.filters.length; i < l; i ++ ) { 47199 47200 this.filters[ i - 1 ].connect( this.filters[ i ] ); 47201 47202 } 47203 47204 this.filters[ this.filters.length - 1 ].connect( this.getOutput() ); 47205 47206 } else { 47207 47208 this.source.connect( this.getOutput() ); 47209 47210 } 47211 47212 this._connected = true; 47213 47214 return this; 47215 47216 } 47217 47218 disconnect() { 47219 47220 if ( this._connected === false ) { 47221 47222 return; 47223 47224 } 47225 47226 if ( this.filters.length > 0 ) { 47227 47228 this.source.disconnect( this.filters[ 0 ] ); 47229 47230 for ( let i = 1, l = this.filters.length; i < l; i ++ ) { 47231 47232 this.filters[ i - 1 ].disconnect( this.filters[ i ] ); 47233 47234 } 47235 47236 this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() ); 47237 47238 } else { 47239 47240 this.source.disconnect( this.getOutput() ); 47241 47242 } 47243 47244 this._connected = false; 47245 47246 return this; 47247 47248 } 47249 47250 getFilters() { 47251 47252 return this.filters; 47253 47254 } 47255 47256 setFilters( value ) { 47257 47258 if ( ! value ) value = []; 47259 47260 if ( this._connected === true ) { 47261 47262 this.disconnect(); 47263 this.filters = value.slice(); 47264 this.connect(); 47265 47266 } else { 47267 47268 this.filters = value.slice(); 47269 47270 } 47271 47272 return this; 47273 47274 } 47275 47276 setDetune( value ) { 47277 47278 this.detune = value; 47279 47280 if ( this.isPlaying === true && this.source.detune !== undefined ) { 47281 47282 this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 ); 47283 47284 } 47285 47286 return this; 47287 47288 } 47289 47290 getDetune() { 47291 47292 return this.detune; 47293 47294 } 47295 47296 getFilter() { 47297 47298 return this.getFilters()[ 0 ]; 47299 47300 } 47301 47302 setFilter( filter ) { 47303 47304 return this.setFilters( filter ? [ filter ] : [] ); 47305 47306 } 47307 47308 setPlaybackRate( value ) { 47309 47310 if ( this.hasPlaybackControl === false ) { 47311 47312 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47313 return; 47314 47315 } 47316 47317 this.playbackRate = value; 47318 47319 if ( this.isPlaying === true ) { 47320 47321 this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 ); 47322 47323 } 47324 47325 return this; 47326 47327 } 47328 47329 getPlaybackRate() { 47330 47331 return this.playbackRate; 47332 47333 } 47334 47335 onEnded() { 47336 47337 this.isPlaying = false; 47338 47339 } 47340 47341 getLoop() { 47342 47343 if ( this.hasPlaybackControl === false ) { 47344 47345 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47346 return false; 47347 47348 } 47349 47350 return this.loop; 47351 47352 } 47353 47354 setLoop( value ) { 47355 47356 if ( this.hasPlaybackControl === false ) { 47357 47358 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47359 return; 47360 47361 } 47362 47363 this.loop = value; 47364 47365 if ( this.isPlaying === true ) { 47366 47367 this.source.loop = this.loop; 47368 47369 } 47370 47371 return this; 47372 47373 } 47374 47375 setLoopStart( value ) { 47376 47377 this.loopStart = value; 47378 47379 return this; 47380 47381 } 47382 47383 setLoopEnd( value ) { 47384 47385 this.loopEnd = value; 47386 47387 return this; 47388 47389 } 47390 47391 getVolume() { 47392 47393 return this.gain.gain.value; 47394 47395 } 47396 47397 setVolume( value ) { 47398 47399 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); 47400 47401 return this; 47402 47403 } 47404 47405} 47406 47407const _position = /*@__PURE__*/ new Vector3(); 47408const _quaternion = /*@__PURE__*/ new Quaternion(); 47409const _scale = /*@__PURE__*/ new Vector3(); 47410const _orientation = /*@__PURE__*/ new Vector3(); 47411 47412class PositionalAudio extends Audio { 47413 47414 constructor( listener ) { 47415 47416 super( listener ); 47417 47418 this.panner = this.context.createPanner(); 47419 this.panner.panningModel = 'HRTF'; 47420 this.panner.connect( this.gain ); 47421 47422 } 47423 47424 connect() { 47425 47426 super.connect(); 47427 47428 this.panner.connect( this.gain ); 47429 47430 } 47431 47432 disconnect() { 47433 47434 super.disconnect(); 47435 47436 this.panner.disconnect( this.gain ); 47437 47438 } 47439 47440 getOutput() { 47441 47442 return this.panner; 47443 47444 } 47445 47446 getRefDistance() { 47447 47448 return this.panner.refDistance; 47449 47450 } 47451 47452 setRefDistance( value ) { 47453 47454 this.panner.refDistance = value; 47455 47456 return this; 47457 47458 } 47459 47460 getRolloffFactor() { 47461 47462 return this.panner.rolloffFactor; 47463 47464 } 47465 47466 setRolloffFactor( value ) { 47467 47468 this.panner.rolloffFactor = value; 47469 47470 return this; 47471 47472 } 47473 47474 getDistanceModel() { 47475 47476 return this.panner.distanceModel; 47477 47478 } 47479 47480 setDistanceModel( value ) { 47481 47482 this.panner.distanceModel = value; 47483 47484 return this; 47485 47486 } 47487 47488 getMaxDistance() { 47489 47490 return this.panner.maxDistance; 47491 47492 } 47493 47494 setMaxDistance( value ) { 47495 47496 this.panner.maxDistance = value; 47497 47498 return this; 47499 47500 } 47501 47502 setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) { 47503 47504 this.panner.coneInnerAngle = coneInnerAngle; 47505 this.panner.coneOuterAngle = coneOuterAngle; 47506 this.panner.coneOuterGain = coneOuterGain; 47507 47508 return this; 47509 47510 } 47511 47512 updateMatrixWorld( force ) { 47513 47514 super.updateMatrixWorld( force ); 47515 47516 if ( this.hasPlaybackControl === true && this.isPlaying === false ) return; 47517 47518 this.matrixWorld.decompose( _position, _quaternion, _scale ); 47519 47520 _orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion ); 47521 47522 const panner = this.panner; 47523 47524 if ( panner.positionX ) { 47525 47526 // code path for Chrome and Firefox (see #14393) 47527 47528 const endTime = this.context.currentTime + this.listener.timeDelta; 47529 47530 panner.positionX.linearRampToValueAtTime( _position.x, endTime ); 47531 panner.positionY.linearRampToValueAtTime( _position.y, endTime ); 47532 panner.positionZ.linearRampToValueAtTime( _position.z, endTime ); 47533 panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime ); 47534 panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime ); 47535 panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime ); 47536 47537 } else { 47538 47539 panner.setPosition( _position.x, _position.y, _position.z ); 47540 panner.setOrientation( _orientation.x, _orientation.y, _orientation.z ); 47541 47542 } 47543 47544 } 47545 47546} 47547 47548class AudioAnalyser { 47549 47550 constructor( audio, fftSize = 2048 ) { 47551 47552 this.analyser = audio.context.createAnalyser(); 47553 this.analyser.fftSize = fftSize; 47554 47555 this.data = new Uint8Array( this.analyser.frequencyBinCount ); 47556 47557 audio.getOutput().connect( this.analyser ); 47558 47559 } 47560 47561 47562 getFrequencyData() { 47563 47564 this.analyser.getByteFrequencyData( this.data ); 47565 47566 return this.data; 47567 47568 } 47569 47570 getAverageFrequency() { 47571 47572 let value = 0; 47573 const data = this.getFrequencyData(); 47574 47575 for ( let i = 0; i < data.length; i ++ ) { 47576 47577 value += data[ i ]; 47578 47579 } 47580 47581 return value / data.length; 47582 47583 } 47584 47585} 47586 47587class PropertyMixer { 47588 47589 constructor( binding, typeName, valueSize ) { 47590 47591 this.binding = binding; 47592 this.valueSize = valueSize; 47593 47594 let mixFunction, 47595 mixFunctionAdditive, 47596 setIdentity; 47597 47598 // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ] 47599 // 47600 // interpolators can use .buffer as their .result 47601 // the data then goes to 'incoming' 47602 // 47603 // 'accu0' and 'accu1' are used frame-interleaved for 47604 // the cumulative result and are compared to detect 47605 // changes 47606 // 47607 // 'orig' stores the original state of the property 47608 // 47609 // 'add' is used for additive cumulative results 47610 //
vendor: 13,778 bytes, lines 47611-48241
47611 // 'work' is optional and is only present for quaternion types. It is used 47612 // to store intermediate quaternion multiplication results 47613 47614 switch ( typeName ) { 47615 47616 case 'quaternion': 47617 mixFunction = this._slerp; 47618 mixFunctionAdditive = this._slerpAdditive; 47619 setIdentity = this._setAdditiveIdentityQuaternion; 47620 47621 this.buffer = new Float64Array( valueSize * 6 ); 47622 this._workIndex = 5; 47623 break; 47624 47625 case 'string': 47626 case 'bool': 47627 mixFunction = this._select; 47628 47629 // Use the regular mix function and for additive on these types, 47630 // additive is not relevant for non-numeric types 47631 mixFunctionAdditive = this._select; 47632 47633 setIdentity = this._setAdditiveIdentityOther; 47634 47635 this.buffer = new Array( valueSize * 5 ); 47636 break; 47637 47638 default: 47639 mixFunction = this._lerp; 47640 mixFunctionAdditive = this._lerpAdditive; 47641 setIdentity = this._setAdditiveIdentityNumeric; 47642 47643 this.buffer = new Float64Array( valueSize * 5 ); 47644 47645 } 47646 47647 this._mixBufferRegion = mixFunction; 47648 this._mixBufferRegionAdditive = mixFunctionAdditive; 47649 this._setIdentity = setIdentity; 47650 this._origIndex = 3; 47651 this._addIndex = 4; 47652 47653 this.cumulativeWeight = 0; 47654 this.cumulativeWeightAdditive = 0; 47655 47656 this.useCount = 0; 47657 this.referenceCount = 0; 47658 47659 } 47660 47661 // accumulate data in the 'incoming' region into 'accu<i>' 47662 accumulate( accuIndex, weight ) { 47663 47664 // note: happily accumulating nothing when weight = 0, the caller knows 47665 // the weight and shouldn't have made the call in the first place 47666 47667 const buffer = this.buffer, 47668 stride = this.valueSize, 47669 offset = accuIndex * stride + stride; 47670 47671 let currentWeight = this.cumulativeWeight; 47672 47673 if ( currentWeight === 0 ) { 47674 47675 // accuN := incoming * weight 47676 47677 for ( let i = 0; i !== stride; ++ i ) { 47678 47679 buffer[ offset + i ] = buffer[ i ]; 47680 47681 } 47682 47683 currentWeight = weight; 47684 47685 } else { 47686 47687 // accuN := accuN + incoming * weight 47688 47689 currentWeight += weight; 47690 const mix = weight / currentWeight; 47691 this._mixBufferRegion( buffer, offset, 0, mix, stride ); 47692 47693 } 47694 47695 this.cumulativeWeight = currentWeight; 47696 47697 } 47698 47699 // accumulate data in the 'incoming' region into 'add' 47700 accumulateAdditive( weight ) { 47701 47702 const buffer = this.buffer, 47703 stride = this.valueSize, 47704 offset = stride * this._addIndex; 47705 47706 if ( this.cumulativeWeightAdditive === 0 ) { 47707 47708 // add = identity 47709 47710 this._setIdentity(); 47711 47712 } 47713 47714 // add := add + incoming * weight 47715 47716 this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride ); 47717 this.cumulativeWeightAdditive += weight; 47718 47719 } 47720 47721 // apply the state of 'accu<i>' to the binding when accus differ 47722 apply( accuIndex ) { 47723 47724 const stride = this.valueSize, 47725 buffer = this.buffer, 47726 offset = accuIndex * stride + stride, 47727 47728 weight = this.cumulativeWeight, 47729 weightAdditive = this.cumulativeWeightAdditive, 47730 47731 binding = this.binding; 47732 47733 this.cumulativeWeight = 0; 47734 this.cumulativeWeightAdditive = 0; 47735 47736 if ( weight < 1 ) { 47737 47738 // accuN := accuN + original * ( 1 - cumulativeWeight ) 47739 47740 const originalValueOffset = stride * this._origIndex; 47741 47742 this._mixBufferRegion( 47743 buffer, offset, originalValueOffset, 1 - weight, stride ); 47744 47745 } 47746 47747 if ( weightAdditive > 0 ) { 47748 47749 // accuN := accuN + additive accuN 47750 47751 this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride ); 47752 47753 } 47754 47755 for ( let i = stride, e = stride + stride; i !== e; ++ i ) { 47756 47757 if ( buffer[ i ] !== buffer[ i + stride ] ) { 47758 47759 // value has changed -> update scene graph 47760 47761 binding.setValue( buffer, offset ); 47762 break; 47763 47764 } 47765 47766 } 47767 47768 } 47769 47770 // remember the state of the bound property and copy it to both accus 47771 saveOriginalState() { 47772 47773 const binding = this.binding; 47774 47775 const buffer = this.buffer, 47776 stride = this.valueSize, 47777 47778 originalValueOffset = stride * this._origIndex; 47779 47780 binding.getValue( buffer, originalValueOffset ); 47781 47782 // accu[0..1] := orig -- initially detect changes against the original 47783 for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) { 47784 47785 buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ]; 47786 47787 } 47788 47789 // Add to identity for additive 47790 this._setIdentity(); 47791 47792 this.cumulativeWeight = 0; 47793 this.cumulativeWeightAdditive = 0; 47794 47795 } 47796 47797 // apply the state previously taken via 'saveOriginalState' to the binding 47798 restoreOriginalState() { 47799 47800 const originalValueOffset = this.valueSize * 3; 47801 this.binding.setValue( this.buffer, originalValueOffset ); 47802 47803 } 47804 47805 _setAdditiveIdentityNumeric() { 47806 47807 const startIndex = this._addIndex * this.valueSize; 47808 const endIndex = startIndex + this.valueSize; 47809 47810 for ( let i = startIndex; i < endIndex; i ++ ) { 47811 47812 this.buffer[ i ] = 0; 47813 47814 } 47815 47816 } 47817 47818 _setAdditiveIdentityQuaternion() { 47819 47820 this._setAdditiveIdentityNumeric(); 47821 this.buffer[ this._addIndex * this.valueSize + 3 ] = 1; 47822 47823 } 47824 47825 _setAdditiveIdentityOther() { 47826 47827 const startIndex = this._origIndex * this.valueSize; 47828 const targetIndex = this._addIndex * this.valueSize; 47829 47830 for ( let i = 0; i < this.valueSize; i ++ ) { 47831 47832 this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ]; 47833 47834 } 47835 47836 } 47837 47838 47839 // mix functions 47840 47841 _select( buffer, dstOffset, srcOffset, t, stride ) { 47842 47843 if ( t >= 0.5 ) { 47844 47845 for ( let i = 0; i !== stride; ++ i ) { 47846 47847 buffer[ dstOffset + i ] = buffer[ srcOffset + i ]; 47848 47849 } 47850 47851 } 47852 47853 } 47854 47855 _slerp( buffer, dstOffset, srcOffset, t ) { 47856 47857 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t ); 47858 47859 } 47860 47861 _slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { 47862 47863 const workOffset = this._workIndex * stride; 47864 47865 // Store result in intermediate buffer offset 47866 Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset ); 47867 47868 // Slerp to the intermediate result 47869 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t ); 47870 47871 } 47872 47873 _lerp( buffer, dstOffset, srcOffset, t, stride ) { 47874 47875 const s = 1 - t; 47876 47877 for ( let i = 0; i !== stride; ++ i ) { 47878 47879 const j = dstOffset + i; 47880 47881 buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t; 47882 47883 } 47884 47885 } 47886 47887 _lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { 47888 47889 for ( let i = 0; i !== stride; ++ i ) { 47890 47891 const j = dstOffset + i; 47892 47893 buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t; 47894 47895 } 47896 47897 } 47898 47899} 47900 47901// Characters [].:/ are reserved for track binding syntax. 47902const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/'; 47903const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' ); 47904 47905// Attempts to allow node names from any language. ES5's `\w` regexp matches 47906// only latin characters, and the unicode \p{L} is not yet supported. So 47907// instead, we exclude reserved characters and match everything else. 47908const _wordChar = '[^' + _RESERVED_CHARS_RE + ']'; 47909const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']'; 47910 47911// Parent directories, delimited by '/' or ':'. Currently unused, but must 47912// be matched to parse the rest of the track name. 47913const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar ); 47914 47915// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'. 47916const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot ); 47917 47918// Object on target node, and accessor. May not contain reserved 47919// characters. Accessor may contain any character except closing bracket. 47920const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar ); 47921 47922// Property and accessor. May not contain reserved characters. Accessor may 47923// contain any non-bracket characters. 47924const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar ); 47925 47926const _trackRe = new RegExp( '' 47927 + '^' 47928 + _directoryRe 47929 + _nodeRe 47930 + _objectRe 47931 + _propertyRe 47932 + '$' 47933); 47934 47935const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ]; 47936 47937class Composite { 47938 47939 constructor( targetGroup, path, optionalParsedPath ) { 47940 47941 const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); 47942 47943 this._targetGroup = targetGroup; 47944 this._bindings = targetGroup.subscribe_( path, parsedPath ); 47945 47946 } 47947 47948 getValue( array, offset ) { 47949 47950 this.bind(); // bind all binding 47951 47952 const firstValidIndex = this._targetGroup.nCachedObjects_, 47953 binding = this._bindings[ firstValidIndex ]; 47954 47955 // and only call .getValue on the first 47956 if ( binding !== undefined ) binding.getValue( array, offset ); 47957 47958 } 47959 47960 setValue( array, offset ) { 47961 47962 const bindings = this._bindings; 47963 47964 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { 47965 47966 bindings[ i ].setValue( array, offset ); 47967 47968 } 47969 47970 } 47971 47972 bind() { 47973 47974 const bindings = this._bindings; 47975 47976 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { 47977 47978 bindings[ i ].bind(); 47979 47980 } 47981 47982 } 47983 47984 unbind() { 47985 47986 const bindings = this._bindings; 47987 47988 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { 47989 47990 bindings[ i ].unbind(); 47991 47992 } 47993 47994 } 47995 47996} 47997 47998// Note: This class uses a State pattern on a per-method basis: 47999// 'bind' sets 'this.getValue' / 'setValue' and shadows the 48000// prototype version of these methods with one that represents 48001// the bound state. When the property is not found, the methods 48002// become no-ops. 48003class PropertyBinding { 48004 48005 constructor( rootNode, path, parsedPath ) { 48006 48007 this.path = path; 48008 this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); 48009 48010 this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ); 48011 48012 this.rootNode = rootNode; 48013 48014 // initial state of these methods that calls 'bind' 48015 this.getValue = this._getValue_unbound; 48016 this.setValue = this._setValue_unbound; 48017 48018 } 48019 48020 48021 static create( root, path, parsedPath ) { 48022 48023 if ( ! ( root && root.isAnimationObjectGroup ) ) { 48024 48025 return new PropertyBinding( root, path, parsedPath ); 48026 48027 } else { 48028 48029 return new PropertyBinding.Composite( root, path, parsedPath ); 48030 48031 } 48032 48033 } 48034 48035 /** 48036 * Replaces spaces with underscores and removes unsupported characters from 48037 * node names, to ensure compatibility with parseTrackName(). 48038 * 48039 * @param {string} name Node name to be sanitized. 48040 * @return {string} 48041 */ 48042 static sanitizeNodeName( name ) { 48043 48044 return name.replace( /\s/g, '_' ).replace( _reservedRe, '' ); 48045 48046 } 48047 48048 static parseTrackName( trackName ) { 48049 48050 const matches = _trackRe.exec( trackName ); 48051 48052 if ( matches === null ) { 48053 48054 throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName ); 48055 48056 } 48057 48058 const results = { 48059 // directoryName: matches[ 1 ], // (tschw) currently unused 48060 nodeName: matches[ 2 ], 48061 objectName: matches[ 3 ], 48062 objectIndex: matches[ 4 ], 48063 propertyName: matches[ 5 ], // required 48064 propertyIndex: matches[ 6 ] 48065 }; 48066 48067 const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' ); 48068 48069 if ( lastDot !== undefined && lastDot !== - 1 ) { 48070 48071 const objectName = results.nodeName.substring( lastDot + 1 ); 48072 48073 // Object names must be checked against an allowlist. Otherwise, there 48074 // is no way to parse 'foo.bar.baz': 'baz' must be a property, but 48075 // 'bar' could be the objectName, or part of a nodeName (which can 48076 // include '.' characters). 48077 if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) { 48078 48079 results.nodeName = results.nodeName.substring( 0, lastDot ); 48080 results.objectName = objectName; 48081 48082 } 48083 48084 } 48085 48086 if ( results.propertyName === null || results.propertyName.length === 0 ) { 48087 48088 throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName ); 48089 48090 } 48091 48092 return results; 48093 48094 } 48095 48096 static findNode( root, nodeName ) { 48097 48098 if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { 48099 48100 return root; 48101 48102 } 48103 48104 // search into skeleton bones. 48105 if ( root.skeleton ) { 48106 48107 const bone = root.skeleton.getBoneByName( nodeName ); 48108 48109 if ( bone !== undefined ) { 48110 48111 return bone; 48112 48113 } 48114 48115 } 48116 48117 // search into node subtree. 48118 if ( root.children ) { 48119 48120 const searchNodeSubtree = function ( children ) { 48121 48122 for ( let i = 0; i < children.length; i ++ ) { 48123 48124 const childNode = children[ i ]; 48125 48126 if ( childNode.name === nodeName || childNode.uuid === nodeName ) { 48127 48128 return childNode; 48129 48130 } 48131 48132 const result = searchNodeSubtree( childNode.children ); 48133 48134 if ( result ) return result; 48135 48136 } 48137 48138 return null; 48139 48140 }; 48141 48142 const subTreeNode = searchNodeSubtree( root.children ); 48143 48144 if ( subTreeNode ) { 48145 48146 return subTreeNode; 48147 48148 } 48149 48150 } 48151 48152 return null; 48153 48154 } 48155 48156 // these are used to "bind" a nonexistent property 48157 _getValue_unavailable() {} 48158 _setValue_unavailable() {} 48159 48160 // Getters 48161 48162 _getValue_direct( buffer, offset ) { 48163 48164 buffer[ offset ] = this.targetObject[ this.propertyName ]; 48165 48166 } 48167 48168 _getValue_array( buffer, offset ) { 48169 48170 const source = this.resolvedProperty; 48171 48172 for ( let i = 0, n = source.length; i !== n; ++ i ) { 48173 48174 buffer[ offset ++ ] = source[ i ]; 48175 48176 } 48177 48178 } 48179 48180 _getValue_arrayElement( buffer, offset ) { 48181 48182 buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; 48183 48184 } 48185 48186 _getValue_toArray( buffer, offset ) { 48187 48188 this.resolvedProperty.toArray( buffer, offset ); 48189 48190 } 48191 48192 // Direct 48193 48194 _setValue_direct( buffer, offset ) { 48195 48196 this.targetObject[ this.propertyName ] = buffer[ offset ]; 48197 48198 } 48199 48200 _setValue_direct_setNeedsUpdate( buffer, offset ) { 48201 48202 this.targetObject[ this.propertyName ] = buffer[ offset ]; 48203 this.targetObject.needsUpdate = true; 48204 48205 } 48206 48207 _setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { 48208 48209 this.targetObject[ this.propertyName ] = buffer[ offset ]; 48210 this.targetObject.matrixWorldNeedsUpdate = true; 48211 48212 } 48213 48214 // EntireArray 48215 48216 _setValue_array( buffer, offset ) { 48217 48218 const dest = this.resolvedProperty; 48219 48220 for ( let i = 0, n = dest.length; i !== n; ++ i ) { 48221 48222 dest[ i ] = buffer[ offset ++ ]; 48223 48224 } 48225 48226 } 48227 48228 _setValue_array_setNeedsUpdate( buffer, offset ) { 48229 48230 const dest = this.resolvedProperty; 48231 48232 for ( let i = 0, n = dest.length; i !== n; ++ i ) { 48233 48234 dest[ i ] = buffer[ offset ++ ]; 48235 48236 } 48237 48238 this.targetObject.needsUpdate = true; 48239 48240 } 48241
vendor: 8,185 bytes, lines 48242-48597
48242 _setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { 48243 48244 const dest = this.resolvedProperty; 48245 48246 for ( let i = 0, n = dest.length; i !== n; ++ i ) { 48247 48248 dest[ i ] = buffer[ offset ++ ]; 48249 48250 } 48251 48252 this.targetObject.matrixWorldNeedsUpdate = true; 48253 48254 } 48255 48256 // ArrayElement 48257 48258 _setValue_arrayElement( buffer, offset ) { 48259 48260 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 48261 48262 } 48263 48264 _setValue_arrayElement_setNeedsUpdate( buffer, offset ) { 48265 48266 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 48267 this.targetObject.needsUpdate = true; 48268 48269 } 48270 48271 _setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { 48272 48273 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 48274 this.targetObject.matrixWorldNeedsUpdate = true; 48275 48276 } 48277 48278 // HasToFromArray 48279 48280 _setValue_fromArray( buffer, offset ) { 48281 48282 this.resolvedProperty.fromArray( buffer, offset ); 48283 48284 } 48285 48286 _setValue_fromArray_setNeedsUpdate( buffer, offset ) { 48287 48288 this.resolvedProperty.fromArray( buffer, offset ); 48289 this.targetObject.needsUpdate = true; 48290 48291 } 48292 48293 _setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { 48294 48295 this.resolvedProperty.fromArray( buffer, offset ); 48296 this.targetObject.matrixWorldNeedsUpdate = true; 48297 48298 } 48299 48300 _getValue_unbound( targetArray, offset ) { 48301 48302 this.bind(); 48303 this.getValue( targetArray, offset ); 48304 48305 } 48306 48307 _setValue_unbound( sourceArray, offset ) { 48308 48309 this.bind(); 48310 this.setValue( sourceArray, offset ); 48311 48312 } 48313 48314 // create getter / setter pair for a property in the scene graph 48315 bind() { 48316 48317 let targetObject = this.node; 48318 const parsedPath = this.parsedPath; 48319 48320 const objectName = parsedPath.objectName; 48321 const propertyName = parsedPath.propertyName; 48322 let propertyIndex = parsedPath.propertyIndex; 48323 48324 if ( ! targetObject ) { 48325 48326 targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ); 48327 48328 this.node = targetObject; 48329 48330 } 48331 48332 // set fail state so we can just 'return' on error 48333 this.getValue = this._getValue_unavailable; 48334 this.setValue = this._setValue_unavailable; 48335 48336 // ensure there is a value node 48337 if ( ! targetObject ) { 48338 48339 console.warn( 'THREE.PropertyBinding: No target node found for track: ' + this.path + '.' ); 48340 return; 48341 48342 } 48343 48344 if ( objectName ) { 48345 48346 let objectIndex = parsedPath.objectIndex; 48347 48348 // special cases were we need to reach deeper into the hierarchy to get the face materials.... 48349 switch ( objectName ) { 48350 48351 case 'materials': 48352 48353 if ( ! targetObject.material ) { 48354 48355 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); 48356 return; 48357 48358 } 48359 48360 if ( ! targetObject.material.materials ) { 48361 48362 console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this ); 48363 return; 48364 48365 } 48366 48367 targetObject = targetObject.material.materials; 48368 48369 break; 48370 48371 case 'bones': 48372 48373 if ( ! targetObject.skeleton ) { 48374 48375 console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this ); 48376 return; 48377 48378 } 48379 48380 // potential future optimization: skip this if propertyIndex is already an integer 48381 // and convert the integer string to a true integer. 48382 48383 targetObject = targetObject.skeleton.bones; 48384 48385 // support resolving morphTarget names into indices. 48386 for ( let i = 0; i < targetObject.length; i ++ ) { 48387 48388 if ( targetObject[ i ].name === objectIndex ) { 48389 48390 objectIndex = i; 48391 break; 48392 48393 } 48394 48395 } 48396 48397 break; 48398 48399 case 'map': 48400 48401 if ( 'map' in targetObject ) { 48402 48403 targetObject = targetObject.map; 48404 break; 48405 48406 } 48407 48408 if ( ! targetObject.material ) { 48409 48410 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); 48411 return; 48412 48413 } 48414 48415 if ( ! targetObject.material.map ) { 48416 48417 console.error( 'THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.', this ); 48418 return; 48419 48420 } 48421 48422 targetObject = targetObject.material.map; 48423 break; 48424 48425 default: 48426 48427 if ( targetObject[ objectName ] === undefined ) { 48428 48429 console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this ); 48430 return; 48431 48432 } 48433 48434 targetObject = targetObject[ objectName ]; 48435 48436 } 48437 48438 48439 if ( objectIndex !== undefined ) { 48440 48441 if ( targetObject[ objectIndex ] === undefined ) { 48442 48443 console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject ); 48444 return; 48445 48446 } 48447 48448 targetObject = targetObject[ objectIndex ]; 48449 48450 } 48451 48452 } 48453 48454 // resolve property 48455 const nodeProperty = targetObject[ propertyName ]; 48456 48457 if ( nodeProperty === undefined ) { 48458 48459 const nodeName = parsedPath.nodeName; 48460 48461 console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName + 48462 '.' + propertyName + ' but it wasn\'t found.', targetObject ); 48463 return; 48464 48465 } 48466 48467 // determine versioning scheme 48468 let versioning = this.Versioning.None; 48469 48470 this.targetObject = targetObject; 48471 48472 if ( targetObject.needsUpdate !== undefined ) { // material 48473 48474 versioning = this.Versioning.NeedsUpdate; 48475 48476 } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform 48477 48478 versioning = this.Versioning.MatrixWorldNeedsUpdate; 48479 48480 } 48481 48482 // determine how the property gets bound 48483 let bindingType = this.BindingType.Direct; 48484 48485 if ( propertyIndex !== undefined ) { 48486 48487 // access a sub element of the property array (only primitives are supported right now) 48488 48489 if ( propertyName === 'morphTargetInfluences' ) { 48490 48491 // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer. 48492 48493 // support resolving morphTarget names into indices. 48494 if ( ! targetObject.geometry ) { 48495 48496 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this ); 48497 return; 48498 48499 } 48500 48501 if ( ! targetObject.geometry.morphAttributes ) { 48502 48503 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this ); 48504 return; 48505 48506 } 48507 48508 if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) { 48509 48510 propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ]; 48511 48512 } 48513 48514 } 48515 48516 bindingType = this.BindingType.ArrayElement; 48517 48518 this.resolvedProperty = nodeProperty; 48519 this.propertyIndex = propertyIndex; 48520 48521 } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) { 48522 48523 // must use copy for Object3D.Euler/Quaternion 48524 48525 bindingType = this.BindingType.HasFromToArray; 48526 48527 this.resolvedProperty = nodeProperty; 48528 48529 } else if ( Array.isArray( nodeProperty ) ) { 48530 48531 bindingType = this.BindingType.EntireArray; 48532 48533 this.resolvedProperty = nodeProperty; 48534 48535 } else { 48536 48537 this.propertyName = propertyName; 48538 48539 } 48540 48541 // select getter / setter 48542 this.getValue = this.GetterByBindingType[ bindingType ]; 48543 this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; 48544 48545 } 48546 48547 unbind() { 48548 48549 this.node = null; 48550 48551 // back to the prototype version of getValue / setValue 48552 // note: avoiding to mutate the shape of 'this' via 'delete' 48553 this.getValue = this._getValue_unbound; 48554 this.setValue = this._setValue_unbound; 48555 48556 } 48557 48558} 48559 48560PropertyBinding.Composite = Composite; 48561 48562PropertyBinding.prototype.BindingType = { 48563 Direct: 0, 48564 EntireArray: 1, 48565 ArrayElement: 2, 48566 HasFromToArray: 3 48567}; 48568 48569PropertyBinding.prototype.Versioning = { 48570 None: 0, 48571 NeedsUpdate: 1, 48572 MatrixWorldNeedsUpdate: 2 48573}; 48574 48575PropertyBinding.prototype.GetterByBindingType = [ 48576 48577 PropertyBinding.prototype._getValue_direct, 48578 PropertyBinding.prototype._getValue_array, 48579 PropertyBinding.prototype._getValue_arrayElement, 48580 PropertyBinding.prototype._getValue_toArray, 48581 48582]; 48583 48584PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [ 48585 48586 [ 48587 // Direct 48588 PropertyBinding.prototype._setValue_direct, 48589 PropertyBinding.prototype._setValue_direct_setNeedsUpdate, 48590 PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate, 48591 48592 ], [ 48593 48594 // EntireArray 48595 48596 PropertyBinding.prototype._setValue_array, 48597 PropertyBinding.prototype._setValue_array_setNeedsUpdate,
vendor: 4,282 bytes, lines 48598-48778
48598 PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate, 48599 48600 ], [ 48601 48602 // ArrayElement 48603 PropertyBinding.prototype._setValue_arrayElement, 48604 PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate, 48605 PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate, 48606 48607 ], [ 48608 48609 // HasToFromArray 48610 PropertyBinding.prototype._setValue_fromArray, 48611 PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate, 48612 PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate, 48613 48614 ] 48615 48616]; 48617 48618/** 48619 * 48620 * A group of objects that receives a shared animation state. 48621 * 48622 * Usage: 48623 * 48624 * - Add objects you would otherwise pass as 'root' to the 48625 * constructor or the .clipAction method of AnimationMixer. 48626 * 48627 * - Instead pass this object as 'root'. 48628 * 48629 * - You can also add and remove objects later when the mixer 48630 * is running. 48631 * 48632 * Note: 48633 * 48634 * Objects of this class appear as one object to the mixer, 48635 * so cache control of the individual objects must be done 48636 * on the group. 48637 * 48638 * Limitation: 48639 * 48640 * - The animated properties must be compatible among the 48641 * all objects in the group. 48642 * 48643 * - A single property can either be controlled through a 48644 * target group or directly, but not both. 48645 */ 48646 48647class AnimationObjectGroup { 48648 48649 constructor() { 48650 48651 this.isAnimationObjectGroup = true; 48652 48653 this.uuid = generateUUID(); 48654 48655 // cached objects followed by the active ones 48656 this._objects = Array.prototype.slice.call( arguments ); 48657 48658 this.nCachedObjects_ = 0; // threshold 48659 // note: read by PropertyBinding.Composite 48660 48661 const indices = {}; 48662 this._indicesByUUID = indices; // for bookkeeping 48663 48664 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 48665 48666 indices[ arguments[ i ].uuid ] = i; 48667 48668 } 48669 48670 this._paths = []; // inside: string 48671 this._parsedPaths = []; // inside: { we don't care, here } 48672 this._bindings = []; // inside: Array< PropertyBinding > 48673 this._bindingsIndicesByPath = {}; // inside: indices in these arrays 48674 48675 const scope = this; 48676 48677 this.stats = { 48678 48679 objects: { 48680 get total() { 48681 48682 return scope._objects.length; 48683 48684 }, 48685 get inUse() { 48686 48687 return this.total - scope.nCachedObjects_; 48688 48689 } 48690 }, 48691 get bindingsPerObject() { 48692 48693 return scope._bindings.length; 48694 48695 } 48696 48697 }; 48698 48699 } 48700 48701 add() { 48702 48703 const objects = this._objects, 48704 indicesByUUID = this._indicesByUUID, 48705 paths = this._paths, 48706 parsedPaths = this._parsedPaths, 48707 bindings = this._bindings, 48708 nBindings = bindings.length; 48709 48710 let knownObject = undefined, 48711 nObjects = objects.length, 48712 nCachedObjects = this.nCachedObjects_; 48713 48714 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 48715 48716 const object = arguments[ i ], 48717 uuid = object.uuid; 48718 let index = indicesByUUID[ uuid ]; 48719 48720 if ( index === undefined ) { 48721 48722 // unknown object -> add it to the ACTIVE region 48723 48724 index = nObjects ++; 48725 indicesByUUID[ uuid ] = index; 48726 objects.push( object ); 48727 48728 // accounting is done, now do the same for all bindings 48729 48730 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 48731 48732 bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); 48733 48734 } 48735 48736 } else if ( index < nCachedObjects ) { 48737 48738 knownObject = objects[ index ]; 48739 48740 // move existing object to the ACTIVE region 48741 48742 const firstActiveIndex = -- nCachedObjects, 48743 lastCachedObject = objects[ firstActiveIndex ]; 48744 48745 indicesByUUID[ lastCachedObject.uuid ] = index; 48746 objects[ index ] = lastCachedObject; 48747 48748 indicesByUUID[ uuid ] = firstActiveIndex; 48749 objects[ firstActiveIndex ] = object; 48750 48751 // accounting is done, now do the same for all bindings 48752 48753 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 48754 48755 const bindingsForPath = bindings[ j ], 48756 lastCached = bindingsForPath[ firstActiveIndex ]; 48757 48758 let binding = bindingsForPath[ index ]; 48759 48760 bindingsForPath[ index ] = lastCached; 48761 48762 if ( binding === undefined ) { 48763 48764 // since we do not bother to create new bindings 48765 // for objects that are cached, the binding may 48766 // or may not exist 48767 48768 binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); 48769 48770 } 48771 48772 bindingsForPath[ firstActiveIndex ] = binding; 48773 48774 } 48775 48776 } else if ( objects[ index ] !== knownObject ) { 48777 48778 console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
vendor: 4,120 bytes, lines 48779-48945
48779 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); 48780 48781 } // else the object is already where we want it to be 48782 48783 } // for arguments 48784 48785 this.nCachedObjects_ = nCachedObjects; 48786 48787 } 48788 48789 remove() { 48790 48791 const objects = this._objects, 48792 indicesByUUID = this._indicesByUUID, 48793 bindings = this._bindings, 48794 nBindings = bindings.length; 48795 48796 let nCachedObjects = this.nCachedObjects_; 48797 48798 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 48799 48800 const object = arguments[ i ], 48801 uuid = object.uuid, 48802 index = indicesByUUID[ uuid ]; 48803 48804 if ( index !== undefined && index >= nCachedObjects ) { 48805 48806 // move existing object into the CACHED region 48807 48808 const lastCachedIndex = nCachedObjects ++, 48809 firstActiveObject = objects[ lastCachedIndex ]; 48810 48811 indicesByUUID[ firstActiveObject.uuid ] = index; 48812 objects[ index ] = firstActiveObject; 48813 48814 indicesByUUID[ uuid ] = lastCachedIndex; 48815 objects[ lastCachedIndex ] = object; 48816 48817 // accounting is done, now do the same for all bindings 48818 48819 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 48820 48821 const bindingsForPath = bindings[ j ], 48822 firstActive = bindingsForPath[ lastCachedIndex ], 48823 binding = bindingsForPath[ index ]; 48824 48825 bindingsForPath[ index ] = firstActive; 48826 bindingsForPath[ lastCachedIndex ] = binding; 48827 48828 } 48829 48830 } 48831 48832 } // for arguments 48833 48834 this.nCachedObjects_ = nCachedObjects; 48835 48836 } 48837 48838 // remove & forget 48839 uncache() { 48840 48841 const objects = this._objects, 48842 indicesByUUID = this._indicesByUUID, 48843 bindings = this._bindings, 48844 nBindings = bindings.length; 48845 48846 let nCachedObjects = this.nCachedObjects_, 48847 nObjects = objects.length; 48848 48849 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 48850 48851 const object = arguments[ i ], 48852 uuid = object.uuid, 48853 index = indicesByUUID[ uuid ]; 48854 48855 if ( index !== undefined ) { 48856 48857 delete indicesByUUID[ uuid ]; 48858 48859 if ( index < nCachedObjects ) { 48860 48861 // object is cached, shrink the CACHED region 48862 48863 const firstActiveIndex = -- nCachedObjects, 48864 lastCachedObject = objects[ firstActiveIndex ], 48865 lastIndex = -- nObjects, 48866 lastObject = objects[ lastIndex ]; 48867 48868 // last cached object takes this object's place 48869 indicesByUUID[ lastCachedObject.uuid ] = index; 48870 objects[ index ] = lastCachedObject; 48871 48872 // last object goes to the activated slot and pop 48873 indicesByUUID[ lastObject.uuid ] = firstActiveIndex; 48874 objects[ firstActiveIndex ] = lastObject; 48875 objects.pop(); 48876 48877 // accounting is done, now do the same for all bindings 48878 48879 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 48880 48881 const bindingsForPath = bindings[ j ], 48882 lastCached = bindingsForPath[ firstActiveIndex ], 48883 last = bindingsForPath[ lastIndex ]; 48884 48885 bindingsForPath[ index ] = lastCached; 48886 bindingsForPath[ firstActiveIndex ] = last; 48887 bindingsForPath.pop(); 48888 48889 } 48890 48891 } else { 48892 48893 // object is active, just swap with the last and pop 48894 48895 const lastIndex = -- nObjects, 48896 lastObject = objects[ lastIndex ]; 48897 48898 if ( lastIndex > 0 ) { 48899 48900 indicesByUUID[ lastObject.uuid ] = index; 48901 48902 } 48903 48904 objects[ index ] = lastObject; 48905 objects.pop(); 48906 48907 // accounting is done, now do the same for all bindings 48908 48909 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 48910 48911 const bindingsForPath = bindings[ j ]; 48912 48913 bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; 48914 bindingsForPath.pop(); 48915 48916 } 48917 48918 } // cached or active 48919 48920 } // if object is known 48921 48922 } // for arguments 48923 48924 this.nCachedObjects_ = nCachedObjects; 48925 48926 } 48927 48928 // Internal interface used by befriended PropertyBinding.Composite: 48929 48930 subscribe_( path, parsedPath ) { 48931 48932 // returns an array of bindings for the given path that is changed 48933 // according to the contained objects in the group 48934 48935 const indicesByPath = this._bindingsIndicesByPath; 48936 let index = indicesByPath[ path ]; 48937 const bindings = this._bindings; 48938 48939 if ( index !== undefined ) return bindings[ index ]; 48940 48941 const paths = this._paths, 48942 parsedPaths = this._parsedPaths, 48943 objects = this._objects, 48944 nObjects = objects.length, 48945 nCachedObjects = this.nCachedObjects_,
vendor: 7,613 bytes, lines 48946-49339
48946 bindingsForPath = new Array( nObjects ); 48947 48948 index = bindings.length; 48949 48950 indicesByPath[ path ] = index; 48951 48952 paths.push( path ); 48953 parsedPaths.push( parsedPath ); 48954 bindings.push( bindingsForPath ); 48955 48956 for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) { 48957 48958 const object = objects[ i ]; 48959 bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); 48960 48961 } 48962 48963 return bindingsForPath; 48964 48965 } 48966 48967 unsubscribe_( path ) { 48968 48969 // tells the group to forget about a property path and no longer 48970 // update the array previously obtained with 'subscribe_' 48971 48972 const indicesByPath = this._bindingsIndicesByPath, 48973 index = indicesByPath[ path ]; 48974 48975 if ( index !== undefined ) { 48976 48977 const paths = this._paths, 48978 parsedPaths = this._parsedPaths, 48979 bindings = this._bindings, 48980 lastBindingsIndex = bindings.length - 1, 48981 lastBindings = bindings[ lastBindingsIndex ], 48982 lastBindingsPath = path[ lastBindingsIndex ]; 48983 48984 indicesByPath[ lastBindingsPath ] = index; 48985 48986 bindings[ index ] = lastBindings; 48987 bindings.pop(); 48988 48989 parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; 48990 parsedPaths.pop(); 48991 48992 paths[ index ] = paths[ lastBindingsIndex ]; 48993 paths.pop(); 48994 48995 } 48996 48997 } 48998 48999} 49000 49001class AnimationAction { 49002 49003 constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) { 49004 49005 this._mixer = mixer; 49006 this._clip = clip; 49007 this._localRoot = localRoot; 49008 this.blendMode = blendMode; 49009 49010 const tracks = clip.tracks, 49011 nTracks = tracks.length, 49012 interpolants = new Array( nTracks ); 49013 49014 const interpolantSettings = { 49015 endingStart: ZeroCurvatureEnding, 49016 endingEnd: ZeroCurvatureEnding 49017 }; 49018 49019 for ( let i = 0; i !== nTracks; ++ i ) { 49020 49021 const interpolant = tracks[ i ].createInterpolant( null ); 49022 interpolants[ i ] = interpolant; 49023 interpolant.settings = interpolantSettings; 49024 49025 } 49026 49027 this._interpolantSettings = interpolantSettings; 49028 49029 this._interpolants = interpolants; // bound by the mixer 49030 49031 // inside: PropertyMixer (managed by the mixer) 49032 this._propertyBindings = new Array( nTracks ); 49033 49034 this._cacheIndex = null; // for the memory manager 49035 this._byClipCacheIndex = null; // for the memory manager 49036 49037 this._timeScaleInterpolant = null; 49038 this._weightInterpolant = null; 49039 49040 this.loop = LoopRepeat; 49041 this._loopCount = - 1; 49042 49043 // global mixer time when the action is to be started 49044 // it's set back to 'null' upon start of the action 49045 this._startTime = null; 49046 49047 // scaled local time of the action 49048 // gets clamped or wrapped to 0..clip.duration according to loop 49049 this.time = 0; 49050 49051 this.timeScale = 1; 49052 this._effectiveTimeScale = 1; 49053 49054 this.weight = 1; 49055 this._effectiveWeight = 1; 49056 49057 this.repetitions = Infinity; // no. of repetitions when looping 49058 49059 this.paused = false; // true -> zero effective time scale 49060 this.enabled = true; // false -> zero effective weight 49061 49062 this.clampWhenFinished = false;// keep feeding the last frame? 49063 49064 this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate 49065 this.zeroSlopeAtEnd = true;// clips for start, loop and end 49066 49067 } 49068 49069 // State & Scheduling 49070 49071 play() { 49072 49073 this._mixer._activateAction( this ); 49074 49075 return this; 49076 49077 } 49078 49079 stop() { 49080 49081 this._mixer._deactivateAction( this ); 49082 49083 return this.reset(); 49084 49085 } 49086 49087 reset() { 49088 49089 this.paused = false; 49090 this.enabled = true; 49091 49092 this.time = 0; // restart clip 49093 this._loopCount = - 1;// forget previous loops 49094 this._startTime = null;// forget scheduling 49095 49096 return this.stopFading().stopWarping(); 49097 49098 } 49099 49100 isRunning() { 49101 49102 return this.enabled && ! this.paused && this.timeScale !== 0 && 49103 this._startTime === null && this._mixer._isActiveAction( this ); 49104 49105 } 49106 49107 // return true when play has been called 49108 isScheduled() { 49109 49110 return this._mixer._isActiveAction( this ); 49111 49112 } 49113 49114 startAt( time ) { 49115 49116 this._startTime = time; 49117 49118 return this; 49119 49120 } 49121 49122 setLoop( mode, repetitions ) { 49123 49124 this.loop = mode; 49125 this.repetitions = repetitions; 49126 49127 return this; 49128 49129 } 49130 49131 // Weight 49132 49133 // set the weight stopping any scheduled fading 49134 // although .enabled = false yields an effective weight of zero, this 49135 // method does *not* change .enabled, because it would be confusing 49136 setEffectiveWeight( weight ) { 49137 49138 this.weight = weight; 49139 49140 // note: same logic as when updated at runtime 49141 this._effectiveWeight = this.enabled ? weight : 0; 49142 49143 return this.stopFading(); 49144 49145 } 49146 49147 // return the weight considering fading and .enabled 49148 getEffectiveWeight() { 49149 49150 return this._effectiveWeight; 49151 49152 } 49153 49154 fadeIn( duration ) { 49155 49156 return this._scheduleFading( duration, 0, 1 ); 49157 49158 } 49159 49160 fadeOut( duration ) { 49161 49162 return this._scheduleFading( duration, 1, 0 ); 49163 49164 } 49165 49166 crossFadeFrom( fadeOutAction, duration, warp ) { 49167 49168 fadeOutAction.fadeOut( duration ); 49169 this.fadeIn( duration ); 49170 49171 if ( warp ) { 49172 49173 const fadeInDuration = this._clip.duration, 49174 fadeOutDuration = fadeOutAction._clip.duration, 49175 49176 startEndRatio = fadeOutDuration / fadeInDuration, 49177 endStartRatio = fadeInDuration / fadeOutDuration; 49178 49179 fadeOutAction.warp( 1.0, startEndRatio, duration ); 49180 this.warp( endStartRatio, 1.0, duration ); 49181 49182 } 49183 49184 return this; 49185 49186 } 49187 49188 crossFadeTo( fadeInAction, duration, warp ) { 49189 49190 return fadeInAction.crossFadeFrom( this, duration, warp ); 49191 49192 } 49193 49194 stopFading() { 49195 49196 const weightInterpolant = this._weightInterpolant; 49197 49198 if ( weightInterpolant !== null ) { 49199 49200 this._weightInterpolant = null; 49201 this._mixer._takeBackControlInterpolant( weightInterpolant ); 49202 49203 } 49204 49205 return this; 49206 49207 } 49208 49209 // Time Scale Control 49210 49211 // set the time scale stopping any scheduled warping 49212 // although .paused = true yields an effective time scale of zero, this 49213 // method does *not* change .paused, because it would be confusing 49214 setEffectiveTimeScale( timeScale ) { 49215 49216 this.timeScale = timeScale; 49217 this._effectiveTimeScale = this.paused ? 0 : timeScale; 49218 49219 return this.stopWarping(); 49220 49221 } 49222 49223 // return the time scale considering warping and .paused 49224 getEffectiveTimeScale() { 49225 49226 return this._effectiveTimeScale; 49227 49228 } 49229 49230 setDuration( duration ) { 49231 49232 this.timeScale = this._clip.duration / duration; 49233 49234 return this.stopWarping(); 49235 49236 } 49237 49238 syncWith( action ) { 49239 49240 this.time = action.time; 49241 this.timeScale = action.timeScale; 49242 49243 return this.stopWarping(); 49244 49245 } 49246 49247 halt( duration ) { 49248 49249 return this.warp( this._effectiveTimeScale, 0, duration ); 49250 49251 } 49252 49253 warp( startTimeScale, endTimeScale, duration ) { 49254 49255 const mixer = this._mixer, 49256 now = mixer.time, 49257 timeScale = this.timeScale; 49258 49259 let interpolant = this._timeScaleInterpolant; 49260 49261 if ( interpolant === null ) { 49262 49263 interpolant = mixer._lendControlInterpolant(); 49264 this._timeScaleInterpolant = interpolant; 49265 49266 } 49267 49268 const times = interpolant.parameterPositions, 49269 values = interpolant.sampleValues; 49270 49271 times[ 0 ] = now; 49272 times[ 1 ] = now + duration; 49273 49274 values[ 0 ] = startTimeScale / timeScale; 49275 values[ 1 ] = endTimeScale / timeScale; 49276 49277 return this; 49278 49279 } 49280 49281 stopWarping() { 49282 49283 const timeScaleInterpolant = this._timeScaleInterpolant; 49284 49285 if ( timeScaleInterpolant !== null ) { 49286 49287 this._timeScaleInterpolant = null; 49288 this._mixer._takeBackControlInterpolant( timeScaleInterpolant ); 49289 49290 } 49291 49292 return this; 49293 49294 } 49295 49296 // Object Accessors 49297 49298 getMixer() { 49299 49300 return this._mixer; 49301 49302 } 49303 49304 getClip() { 49305 49306 return this._clip; 49307 49308 } 49309 49310 getRoot() { 49311 49312 return this._localRoot || this._mixer._root; 49313 49314 } 49315 49316 // Interna 49317 49318 _update( time, deltaTime, timeDirection, accuIndex ) { 49319 49320 // called by the mixer 49321 49322 if ( ! this.enabled ) { 49323 49324 // call ._updateWeight() to update ._effectiveWeight 49325 49326 this._updateWeight( time ); 49327 return; 49328 49329 } 49330 49331 const startTime = this._startTime; 49332 49333 if ( startTime !== null ) { 49334 49335 // check for scheduled start of action 49336 49337 const timeRunning = ( time - startTime ) * timeDirection; 49338 if ( timeRunning < 0 || timeDirection === 0 ) { 49339
vendor: 6,044 bytes, lines 49340-49698
49340 deltaTime = 0; 49341 49342 } else { 49343 49344 49345 this._startTime = null; // unschedule 49346 deltaTime = timeDirection * timeRunning; 49347 49348 } 49349 49350 } 49351 49352 // apply time scale and advance time 49353 49354 deltaTime *= this._updateTimeScale( time ); 49355 const clipTime = this._updateTime( deltaTime ); 49356 49357 // note: _updateTime may disable the action resulting in 49358 // an effective weight of 0 49359 49360 const weight = this._updateWeight( time ); 49361 49362 if ( weight > 0 ) { 49363 49364 const interpolants = this._interpolants; 49365 const propertyMixers = this._propertyBindings; 49366 49367 switch ( this.blendMode ) { 49368 49369 case AdditiveAnimationBlendMode: 49370 49371 for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { 49372 49373 interpolants[ j ].evaluate( clipTime ); 49374 propertyMixers[ j ].accumulateAdditive( weight ); 49375 49376 } 49377 49378 break; 49379 49380 case NormalAnimationBlendMode: 49381 default: 49382 49383 for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { 49384 49385 interpolants[ j ].evaluate( clipTime ); 49386 propertyMixers[ j ].accumulate( accuIndex, weight ); 49387 49388 } 49389 49390 } 49391 49392 } 49393 49394 } 49395 49396 _updateWeight( time ) { 49397 49398 let weight = 0; 49399 49400 if ( this.enabled ) { 49401 49402 weight = this.weight; 49403 const interpolant = this._weightInterpolant; 49404 49405 if ( interpolant !== null ) { 49406 49407 const interpolantValue = interpolant.evaluate( time )[ 0 ]; 49408 49409 weight *= interpolantValue; 49410 49411 if ( time > interpolant.parameterPositions[ 1 ] ) { 49412 49413 this.stopFading(); 49414 49415 if ( interpolantValue === 0 ) { 49416 49417 // faded out, disable 49418 this.enabled = false; 49419 49420 } 49421 49422 } 49423 49424 } 49425 49426 } 49427 49428 this._effectiveWeight = weight; 49429 return weight; 49430 49431 } 49432 49433 _updateTimeScale( time ) { 49434 49435 let timeScale = 0; 49436 49437 if ( ! this.paused ) { 49438 49439 timeScale = this.timeScale; 49440 49441 const interpolant = this._timeScaleInterpolant; 49442 49443 if ( interpolant !== null ) { 49444 49445 const interpolantValue = interpolant.evaluate( time )[ 0 ]; 49446 49447 timeScale *= interpolantValue; 49448 49449 if ( time > interpolant.parameterPositions[ 1 ] ) { 49450 49451 this.stopWarping(); 49452 49453 if ( timeScale === 0 ) { 49454 49455 // motion has halted, pause 49456 this.paused = true; 49457 49458 } else { 49459 49460 // warp done - apply final time scale 49461 this.timeScale = timeScale; 49462 49463 } 49464 49465 } 49466 49467 } 49468 49469 } 49470 49471 this._effectiveTimeScale = timeScale; 49472 return timeScale; 49473 49474 } 49475 49476 _updateTime( deltaTime ) { 49477 49478 const duration = this._clip.duration; 49479 const loop = this.loop; 49480 49481 let time = this.time + deltaTime; 49482 let loopCount = this._loopCount; 49483 49484 const pingPong = ( loop === LoopPingPong ); 49485 49486 if ( deltaTime === 0 ) { 49487 49488 if ( loopCount === - 1 ) return time; 49489 49490 return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time; 49491 49492 } 49493 49494 if ( loop === LoopOnce ) { 49495 49496 if ( loopCount === - 1 ) { 49497 49498 // just started 49499 49500 this._loopCount = 0; 49501 this._setEndings( true, true, false ); 49502 49503 } 49504 49505 handle_stop: { 49506 49507 if ( time >= duration ) { 49508 49509 time = duration; 49510 49511 } else if ( time < 0 ) { 49512 49513 time = 0; 49514 49515 } else { 49516 49517 this.time = time; 49518 49519 break handle_stop; 49520 49521 } 49522 49523 if ( this.clampWhenFinished ) this.paused = true; 49524 else this.enabled = false; 49525 49526 this.time = time; 49527 49528 this._mixer.dispatchEvent( { 49529 type: 'finished', action: this, 49530 direction: deltaTime < 0 ? - 1 : 1 49531 } ); 49532 49533 } 49534 49535 } else { // repetitive Repeat or PingPong 49536 49537 if ( loopCount === - 1 ) { 49538 49539 // just started 49540 49541 if ( deltaTime >= 0 ) { 49542 49543 loopCount = 0; 49544 49545 this._setEndings( true, this.repetitions === 0, pingPong ); 49546 49547 } else { 49548 49549 // when looping in reverse direction, the initial 49550 // transition through zero counts as a repetition, 49551 // so leave loopCount at -1 49552 49553 this._setEndings( this.repetitions === 0, true, pingPong ); 49554 49555 } 49556 49557 } 49558 49559 if ( time >= duration || time < 0 ) { 49560 49561 // wrap around 49562 49563 const loopDelta = Math.floor( time / duration ); // signed 49564 time -= duration * loopDelta; 49565 49566 loopCount += Math.abs( loopDelta ); 49567 49568 const pending = this.repetitions - loopCount; 49569 49570 if ( pending <= 0 ) { 49571 49572 // have to stop (switch state, clamp time, fire event) 49573 49574 if ( this.clampWhenFinished ) this.paused = true; 49575 else this.enabled = false; 49576 49577 time = deltaTime > 0 ? duration : 0; 49578 49579 this.time = time; 49580 49581 this._mixer.dispatchEvent( { 49582 type: 'finished', action: this, 49583 direction: deltaTime > 0 ? 1 : - 1 49584 } ); 49585 49586 } else { 49587 49588 // keep running 49589 49590 if ( pending === 1 ) { 49591 49592 // entering the last round 49593 49594 const atStart = deltaTime < 0; 49595 this._setEndings( atStart, ! atStart, pingPong ); 49596 49597 } else { 49598 49599 this._setEndings( false, false, pingPong ); 49600 49601 } 49602 49603 this._loopCount = loopCount; 49604 49605 this.time = time; 49606 49607 this._mixer.dispatchEvent( { 49608 type: 'loop', action: this, loopDelta: loopDelta 49609 } ); 49610 49611 } 49612 49613 } else { 49614 49615 this.time = time; 49616 49617 } 49618 49619 if ( pingPong && ( loopCount & 1 ) === 1 ) { 49620 49621 // invert time for the "pong round" 49622 49623 return duration - time; 49624 49625 } 49626 49627 } 49628 49629 return time; 49630 49631 } 49632 49633 _setEndings( atStart, atEnd, pingPong ) { 49634 49635 const settings = this._interpolantSettings; 49636 49637 if ( pingPong ) { 49638 49639 settings.endingStart = ZeroSlopeEnding; 49640 settings.endingEnd = ZeroSlopeEnding; 49641 49642 } else { 49643 49644 // assuming for LoopOnce atStart == atEnd == true 49645 49646 if ( atStart ) { 49647 49648 settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding; 49649 49650 } else { 49651 49652 settings.endingStart = WrapAroundEnding; 49653 49654 } 49655 49656 if ( atEnd ) { 49657 49658 settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding; 49659 49660 } else { 49661 49662 settings.endingEnd = WrapAroundEnding; 49663 49664 } 49665 49666 } 49667 49668 } 49669 49670 _scheduleFading( duration, weightNow, weightThen ) { 49671 49672 const mixer = this._mixer, now = mixer.time; 49673 let interpolant = this._weightInterpolant; 49674 49675 if ( interpolant === null ) { 49676 49677 interpolant = mixer._lendControlInterpolant(); 49678 this._weightInterpolant = interpolant; 49679 49680 } 49681 49682 const times = interpolant.parameterPositions, 49683 values = interpolant.sampleValues; 49684 49685 times[ 0 ] = now; 49686 values[ 0 ] = weightNow; 49687 times[ 1 ] = now + duration; 49688 values[ 1 ] = weightThen; 49689 49690 return this; 49691 49692 } 49693 49694} 49695 49696const _controlInterpolantsResultBuffer = new Float32Array( 1 ); 49697 49698
vendor: 13,381 bytes, lines 49699-50339
49699class AnimationMixer extends EventDispatcher { 49700 49701 constructor( root ) { 49702 49703 super(); 49704 49705 this._root = root; 49706 this._initMemoryManager(); 49707 this._accuIndex = 0; 49708 this.time = 0; 49709 this.timeScale = 1.0; 49710 49711 } 49712 49713 _bindAction( action, prototypeAction ) { 49714 49715 const root = action._localRoot || this._root, 49716 tracks = action._clip.tracks, 49717 nTracks = tracks.length, 49718 bindings = action._propertyBindings, 49719 interpolants = action._interpolants, 49720 rootUuid = root.uuid, 49721 bindingsByRoot = this._bindingsByRootAndName; 49722 49723 let bindingsByName = bindingsByRoot[ rootUuid ]; 49724 49725 if ( bindingsByName === undefined ) { 49726 49727 bindingsByName = {}; 49728 bindingsByRoot[ rootUuid ] = bindingsByName; 49729 49730 } 49731 49732 for ( let i = 0; i !== nTracks; ++ i ) { 49733 49734 const track = tracks[ i ], 49735 trackName = track.name; 49736 49737 let binding = bindingsByName[ trackName ]; 49738 49739 if ( binding !== undefined ) { 49740 49741 ++ binding.referenceCount; 49742 bindings[ i ] = binding; 49743 49744 } else { 49745 49746 binding = bindings[ i ]; 49747 49748 if ( binding !== undefined ) { 49749 49750 // existing binding, make sure the cache knows 49751 49752 if ( binding._cacheIndex === null ) { 49753 49754 ++ binding.referenceCount; 49755 this._addInactiveBinding( binding, rootUuid, trackName ); 49756 49757 } 49758 49759 continue; 49760 49761 } 49762 49763 const path = prototypeAction && prototypeAction. 49764 _propertyBindings[ i ].binding.parsedPath; 49765 49766 binding = new PropertyMixer( 49767 PropertyBinding.create( root, trackName, path ), 49768 track.ValueTypeName, track.getValueSize() ); 49769 49770 ++ binding.referenceCount; 49771 this._addInactiveBinding( binding, rootUuid, trackName ); 49772 49773 bindings[ i ] = binding; 49774 49775 } 49776 49777 interpolants[ i ].resultBuffer = binding.buffer; 49778 49779 } 49780 49781 } 49782 49783 _activateAction( action ) { 49784 49785 if ( ! this._isActiveAction( action ) ) { 49786 49787 if ( action._cacheIndex === null ) { 49788 49789 // this action has been forgotten by the cache, but the user 49790 // appears to be still using it -> rebind 49791 49792 const rootUuid = ( action._localRoot || this._root ).uuid, 49793 clipUuid = action._clip.uuid, 49794 actionsForClip = this._actionsByClip[ clipUuid ]; 49795 49796 this._bindAction( action, 49797 actionsForClip && actionsForClip.knownActions[ 0 ] ); 49798 49799 this._addInactiveAction( action, clipUuid, rootUuid ); 49800 49801 } 49802 49803 const bindings = action._propertyBindings; 49804 49805 // increment reference counts / sort out state 49806 for ( let i = 0, n = bindings.length; i !== n; ++ i ) { 49807 49808 const binding = bindings[ i ]; 49809 49810 if ( binding.useCount ++ === 0 ) { 49811 49812 this._lendBinding( binding ); 49813 binding.saveOriginalState(); 49814 49815 } 49816 49817 } 49818 49819 this._lendAction( action ); 49820 49821 } 49822 49823 } 49824 49825 _deactivateAction( action ) { 49826 49827 if ( this._isActiveAction( action ) ) { 49828 49829 const bindings = action._propertyBindings; 49830 49831 // decrement reference counts / sort out state 49832 for ( let i = 0, n = bindings.length; i !== n; ++ i ) { 49833 49834 const binding = bindings[ i ]; 49835 49836 if ( -- binding.useCount === 0 ) { 49837 49838 binding.restoreOriginalState(); 49839 this._takeBackBinding( binding ); 49840 49841 } 49842 49843 } 49844 49845 this._takeBackAction( action ); 49846 49847 } 49848 49849 } 49850 49851 // Memory manager 49852 49853 _initMemoryManager() { 49854 49855 this._actions = []; // 'nActiveActions' followed by inactive ones 49856 this._nActiveActions = 0; 49857 49858 this._actionsByClip = {}; 49859 // inside: 49860 // { 49861 // knownActions: Array< AnimationAction > - used as prototypes 49862 // actionByRoot: AnimationAction - lookup 49863 // } 49864 49865 49866 this._bindings = []; // 'nActiveBindings' followed by inactive ones 49867 this._nActiveBindings = 0; 49868 49869 this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer > 49870 49871 49872 this._controlInterpolants = []; // same game as above 49873 this._nActiveControlInterpolants = 0; 49874 49875 const scope = this; 49876 49877 this.stats = { 49878 49879 actions: { 49880 get total() { 49881 49882 return scope._actions.length; 49883 49884 }, 49885 get inUse() { 49886 49887 return scope._nActiveActions; 49888 49889 } 49890 }, 49891 bindings: { 49892 get total() { 49893 49894 return scope._bindings.length; 49895 49896 }, 49897 get inUse() { 49898 49899 return scope._nActiveBindings; 49900 49901 } 49902 }, 49903 controlInterpolants: { 49904 get total() { 49905 49906 return scope._controlInterpolants.length; 49907 49908 }, 49909 get inUse() { 49910 49911 return scope._nActiveControlInterpolants; 49912 49913 } 49914 } 49915 49916 }; 49917 49918 } 49919 49920 // Memory management for AnimationAction objects 49921 49922 _isActiveAction( action ) { 49923 49924 const index = action._cacheIndex; 49925 return index !== null && index < this._nActiveActions; 49926 49927 } 49928 49929 _addInactiveAction( action, clipUuid, rootUuid ) { 49930 49931 const actions = this._actions, 49932 actionsByClip = this._actionsByClip; 49933 49934 let actionsForClip = actionsByClip[ clipUuid ]; 49935 49936 if ( actionsForClip === undefined ) { 49937 49938 actionsForClip = { 49939 49940 knownActions: [ action ], 49941 actionByRoot: {} 49942 49943 }; 49944 49945 action._byClipCacheIndex = 0; 49946 49947 actionsByClip[ clipUuid ] = actionsForClip; 49948 49949 } else { 49950 49951 const knownActions = actionsForClip.knownActions; 49952 49953 action._byClipCacheIndex = knownActions.length; 49954 knownActions.push( action ); 49955 49956 } 49957 49958 action._cacheIndex = actions.length; 49959 actions.push( action ); 49960 49961 actionsForClip.actionByRoot[ rootUuid ] = action; 49962 49963 } 49964 49965 _removeInactiveAction( action ) { 49966 49967 const actions = this._actions, 49968 lastInactiveAction = actions[ actions.length - 1 ], 49969 cacheIndex = action._cacheIndex; 49970 49971 lastInactiveAction._cacheIndex = cacheIndex; 49972 actions[ cacheIndex ] = lastInactiveAction; 49973 actions.pop(); 49974 49975 action._cacheIndex = null; 49976 49977 49978 const clipUuid = action._clip.uuid, 49979 actionsByClip = this._actionsByClip, 49980 actionsForClip = actionsByClip[ clipUuid ], 49981 knownActionsForClip = actionsForClip.knownActions, 49982 49983 lastKnownAction = 49984 knownActionsForClip[ knownActionsForClip.length - 1 ], 49985 49986 byClipCacheIndex = action._byClipCacheIndex; 49987 49988 lastKnownAction._byClipCacheIndex = byClipCacheIndex; 49989 knownActionsForClip[ byClipCacheIndex ] = lastKnownAction; 49990 knownActionsForClip.pop(); 49991 49992 action._byClipCacheIndex = null; 49993 49994 49995 const actionByRoot = actionsForClip.actionByRoot, 49996 rootUuid = ( action._localRoot || this._root ).uuid; 49997 49998 delete actionByRoot[ rootUuid ]; 49999 50000 if ( knownActionsForClip.length === 0 ) { 50001 50002 delete actionsByClip[ clipUuid ]; 50003 50004 } 50005 50006 this._removeInactiveBindingsForAction( action ); 50007 50008 } 50009 50010 _removeInactiveBindingsForAction( action ) { 50011 50012 const bindings = action._propertyBindings; 50013 50014 for ( let i = 0, n = bindings.length; i !== n; ++ i ) { 50015 50016 const binding = bindings[ i ]; 50017 50018 if ( -- binding.referenceCount === 0 ) { 50019 50020 this._removeInactiveBinding( binding ); 50021 50022 } 50023 50024 } 50025 50026 } 50027 50028 _lendAction( action ) { 50029 50030 // [ active actions | inactive actions ] 50031 // [ active actions >| inactive actions ] 50032 // s a 50033 // <-swap-> 50034 // a s 50035 50036 const actions = this._actions, 50037 prevIndex = action._cacheIndex, 50038 50039 lastActiveIndex = this._nActiveActions ++, 50040 50041 firstInactiveAction = actions[ lastActiveIndex ]; 50042 50043 action._cacheIndex = lastActiveIndex; 50044 actions[ lastActiveIndex ] = action; 50045 50046 firstInactiveAction._cacheIndex = prevIndex; 50047 actions[ prevIndex ] = firstInactiveAction; 50048 50049 } 50050 50051 _takeBackAction( action ) { 50052 50053 // [ active actions | inactive actions ] 50054 // [ active actions |< inactive actions ] 50055 // a s 50056 // <-swap-> 50057 // s a 50058 50059 const actions = this._actions, 50060 prevIndex = action._cacheIndex, 50061 50062 firstInactiveIndex = -- this._nActiveActions, 50063 50064 lastActiveAction = actions[ firstInactiveIndex ]; 50065 50066 action._cacheIndex = firstInactiveIndex; 50067 actions[ firstInactiveIndex ] = action; 50068 50069 lastActiveAction._cacheIndex = prevIndex; 50070 actions[ prevIndex ] = lastActiveAction; 50071 50072 } 50073 50074 // Memory management for PropertyMixer objects 50075 50076 _addInactiveBinding( binding, rootUuid, trackName ) { 50077 50078 const bindingsByRoot = this._bindingsByRootAndName, 50079 bindings = this._bindings; 50080 50081 let bindingByName = bindingsByRoot[ rootUuid ]; 50082 50083 if ( bindingByName === undefined ) { 50084 50085 bindingByName = {}; 50086 bindingsByRoot[ rootUuid ] = bindingByName; 50087 50088 } 50089 50090 bindingByName[ trackName ] = binding; 50091 50092 binding._cacheIndex = bindings.length; 50093 bindings.push( binding ); 50094 50095 } 50096 50097 _removeInactiveBinding( binding ) { 50098 50099 const bindings = this._bindings, 50100 propBinding = binding.binding, 50101 rootUuid = propBinding.rootNode.uuid, 50102 trackName = propBinding.path, 50103 bindingsByRoot = this._bindingsByRootAndName, 50104 bindingByName = bindingsByRoot[ rootUuid ], 50105 50106 lastInactiveBinding = bindings[ bindings.length - 1 ], 50107 cacheIndex = binding._cacheIndex; 50108 50109 lastInactiveBinding._cacheIndex = cacheIndex; 50110 bindings[ cacheIndex ] = lastInactiveBinding; 50111 bindings.pop(); 50112 50113 delete bindingByName[ trackName ]; 50114 50115 if ( Object.keys( bindingByName ).length === 0 ) { 50116 50117 delete bindingsByRoot[ rootUuid ]; 50118 50119 } 50120 50121 } 50122 50123 _lendBinding( binding ) { 50124 50125 const bindings = this._bindings, 50126 prevIndex = binding._cacheIndex, 50127 50128 lastActiveIndex = this._nActiveBindings ++, 50129 50130 firstInactiveBinding = bindings[ lastActiveIndex ]; 50131 50132 binding._cacheIndex = lastActiveIndex; 50133 bindings[ lastActiveIndex ] = binding; 50134 50135 firstInactiveBinding._cacheIndex = prevIndex; 50136 bindings[ prevIndex ] = firstInactiveBinding; 50137 50138 } 50139 50140 _takeBackBinding( binding ) { 50141 50142 const bindings = this._bindings, 50143 prevIndex = binding._cacheIndex, 50144 50145 firstInactiveIndex = -- this._nActiveBindings, 50146 50147 lastActiveBinding = bindings[ firstInactiveIndex ]; 50148 50149 binding._cacheIndex = firstInactiveIndex; 50150 bindings[ firstInactiveIndex ] = binding; 50151 50152 lastActiveBinding._cacheIndex = prevIndex; 50153 bindings[ prevIndex ] = lastActiveBinding; 50154 50155 } 50156 50157 50158 // Memory management of Interpolants for weight and time scale 50159 50160 _lendControlInterpolant() { 50161 50162 const interpolants = this._controlInterpolants, 50163 lastActiveIndex = this._nActiveControlInterpolants ++; 50164 50165 let interpolant = interpolants[ lastActiveIndex ]; 50166 50167 if ( interpolant === undefined ) { 50168 50169 interpolant = new LinearInterpolant( 50170 new Float32Array( 2 ), new Float32Array( 2 ), 50171 1, _controlInterpolantsResultBuffer ); 50172 50173 interpolant.__cacheIndex = lastActiveIndex; 50174 interpolants[ lastActiveIndex ] = interpolant; 50175 50176 } 50177 50178 return interpolant; 50179 50180 } 50181 50182 _takeBackControlInterpolant( interpolant ) { 50183 50184 const interpolants = this._controlInterpolants, 50185 prevIndex = interpolant.__cacheIndex, 50186 50187 firstInactiveIndex = -- this._nActiveControlInterpolants, 50188 50189 lastActiveInterpolant = interpolants[ firstInactiveIndex ]; 50190 50191 interpolant.__cacheIndex = firstInactiveIndex; 50192 interpolants[ firstInactiveIndex ] = interpolant; 50193 50194 lastActiveInterpolant.__cacheIndex = prevIndex; 50195 interpolants[ prevIndex ] = lastActiveInterpolant; 50196 50197 } 50198 50199 // return an action for a clip optionally using a custom root target 50200 // object (this method allocates a lot of dynamic memory in case a 50201 // previously unknown clip/root combination is specified) 50202 clipAction( clip, optionalRoot, blendMode ) { 50203 50204 const root = optionalRoot || this._root, 50205 rootUuid = root.uuid; 50206 50207 let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip; 50208 50209 const clipUuid = clipObject !== null ? clipObject.uuid : clip; 50210 50211 const actionsForClip = this._actionsByClip[ clipUuid ]; 50212 let prototypeAction = null; 50213 50214 if ( blendMode === undefined ) { 50215 50216 if ( clipObject !== null ) { 50217 50218 blendMode = clipObject.blendMode; 50219 50220 } else { 50221 50222 blendMode = NormalAnimationBlendMode; 50223 50224 } 50225 50226 } 50227 50228 if ( actionsForClip !== undefined ) { 50229 50230 const existingAction = actionsForClip.actionByRoot[ rootUuid ]; 50231 50232 if ( existingAction !== undefined && existingAction.blendMode === blendMode ) { 50233 50234 return existingAction; 50235 50236 } 50237 50238 // we know the clip, so we don't have to parse all 50239 // the bindings again but can just copy 50240 prototypeAction = actionsForClip.knownActions[ 0 ]; 50241 50242 // also, take the clip from the prototype action 50243 if ( clipObject === null ) 50244 clipObject = prototypeAction._clip; 50245 50246 } 50247 50248 // clip must be known when specified via string 50249 if ( clipObject === null ) return null; 50250 50251 // allocate all resources required to run it 50252 const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode ); 50253 50254 this._bindAction( newAction, prototypeAction ); 50255 50256 // and make the action known to the memory manager 50257 this._addInactiveAction( newAction, clipUuid, rootUuid ); 50258 50259 return newAction; 50260 50261 } 50262 50263 // get an existing action 50264 existingAction( clip, optionalRoot ) { 50265 50266 const root = optionalRoot || this._root, 50267 rootUuid = root.uuid, 50268 50269 clipObject = typeof clip === 'string' ? 50270 AnimationClip.findByName( root, clip ) : clip, 50271 50272 clipUuid = clipObject ? clipObject.uuid : clip, 50273 50274 actionsForClip = this._actionsByClip[ clipUuid ]; 50275 50276 if ( actionsForClip !== undefined ) { 50277 50278 return actionsForClip.actionByRoot[ rootUuid ] || null; 50279 50280 } 50281 50282 return null; 50283 50284 } 50285 50286 // deactivates all previously scheduled actions 50287 stopAllAction() { 50288 50289 const actions = this._actions, 50290 nActions = this._nActiveActions; 50291 50292 for ( let i = nActions - 1; i >= 0; -- i ) { 50293 50294 actions[ i ].stop(); 50295 50296 } 50297 50298 return this; 50299 50300 } 50301 50302 // advance the time and update apply the animation 50303 update( deltaTime ) { 50304 50305 deltaTime *= this.timeScale; 50306 50307 const actions = this._actions, 50308 nActions = this._nActiveActions, 50309 50310 time = this.time += deltaTime, 50311 timeDirection = Math.sign( deltaTime ), 50312 50313 accuIndex = this._accuIndex ^= 1; 50314 50315 // run active actions 50316 50317 for ( let i = 0; i !== nActions; ++ i ) { 50318 50319 const action = actions[ i ]; 50320 50321 action._update( time, deltaTime, timeDirection, accuIndex ); 50322 50323 } 50324 50325 // update scene graph 50326 50327 const bindings = this._bindings, 50328 nBindings = this._nActiveBindings; 50329 50330 for ( let i = 0; i !== nBindings; ++ i ) { 50331 50332 bindings[ i ].apply( accuIndex ); 50333 50334 } 50335 50336 return this; 50337 50338 } 50339
vendor: 2,763 bytes, lines 50340-50473
50340 // Allows you to seek to a specific time in an animation. 50341 setTime( timeInSeconds ) { 50342 50343 this.time = 0; // Zero out time attribute for AnimationMixer object; 50344 for ( let i = 0; i < this._actions.length; i ++ ) { 50345 50346 this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects. 50347 50348 } 50349 50350 return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object. 50351 50352 } 50353 50354 // return this mixer's root target object 50355 getRoot() { 50356 50357 return this._root; 50358 50359 } 50360 50361 // free all resources specific to a particular clip 50362 uncacheClip( clip ) { 50363 50364 const actions = this._actions, 50365 clipUuid = clip.uuid, 50366 actionsByClip = this._actionsByClip, 50367 actionsForClip = actionsByClip[ clipUuid ]; 50368 50369 if ( actionsForClip !== undefined ) { 50370 50371 // note: just calling _removeInactiveAction would mess up the 50372 // iteration state and also require updating the state we can 50373 // just throw away 50374 50375 const actionsToRemove = actionsForClip.knownActions; 50376 50377 for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) { 50378 50379 const action = actionsToRemove[ i ]; 50380 50381 this._deactivateAction( action ); 50382 50383 const cacheIndex = action._cacheIndex, 50384 lastInactiveAction = actions[ actions.length - 1 ]; 50385 50386 action._cacheIndex = null; 50387 action._byClipCacheIndex = null; 50388 50389 lastInactiveAction._cacheIndex = cacheIndex; 50390 actions[ cacheIndex ] = lastInactiveAction; 50391 actions.pop(); 50392 50393 this._removeInactiveBindingsForAction( action ); 50394 50395 } 50396 50397 delete actionsByClip[ clipUuid ]; 50398 50399 } 50400 50401 } 50402 50403 // free all resources specific to a particular root target object 50404 uncacheRoot( root ) { 50405 50406 const rootUuid = root.uuid, 50407 actionsByClip = this._actionsByClip; 50408 50409 for ( const clipUuid in actionsByClip ) { 50410 50411 const actionByRoot = actionsByClip[ clipUuid ].actionByRoot, 50412 action = actionByRoot[ rootUuid ]; 50413 50414 if ( action !== undefined ) { 50415 50416 this._deactivateAction( action ); 50417 this._removeInactiveAction( action ); 50418 50419 } 50420 50421 } 50422 50423 const bindingsByRoot = this._bindingsByRootAndName, 50424 bindingByName = bindingsByRoot[ rootUuid ]; 50425 50426 if ( bindingByName !== undefined ) { 50427 50428 for ( const trackName in bindingByName ) { 50429 50430 const binding = bindingByName[ trackName ]; 50431 binding.restoreOriginalState(); 50432 this._removeInactiveBinding( binding ); 50433 50434 } 50435 50436 } 50437 50438 } 50439 50440 // remove a targeted clip from the cache 50441 uncacheAction( clip, optionalRoot ) { 50442 50443 const action = this.existingAction( clip, optionalRoot ); 50444 50445 if ( action !== null ) { 50446 50447 this._deactivateAction( action ); 50448 this._removeInactiveAction( action ); 50449 50450 } 50451 50452 } 50453 50454} 50455 50456class Uniform { 50457 50458 constructor( value ) { 50459 50460 this.value = value; 50461 50462 } 50463 50464 clone() { 50465 50466 return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() ); 50467 50468 } 50469 50470} 50471 50472let _id = 0; 50473
vendor: 5,200 bytes, lines 50474-50796
50474class UniformsGroup extends EventDispatcher { 50475 50476 constructor() { 50477 50478 super(); 50479 50480 this.isUniformsGroup = true; 50481 50482 Object.defineProperty( this, 'id', { value: _id ++ } ); 50483 50484 this.name = ''; 50485 50486 this.usage = StaticDrawUsage; 50487 this.uniforms = []; 50488 50489 } 50490 50491 add( uniform ) { 50492 50493 this.uniforms.push( uniform ); 50494 50495 return this; 50496 50497 } 50498 50499 remove( uniform ) { 50500 50501 const index = this.uniforms.indexOf( uniform ); 50502 50503 if ( index !== - 1 ) this.uniforms.splice( index, 1 ); 50504 50505 return this; 50506 50507 } 50508 50509 setName( name ) { 50510 50511 this.name = name; 50512 50513 return this; 50514 50515 } 50516 50517 setUsage( value ) { 50518 50519 this.usage = value; 50520 50521 return this; 50522 50523 } 50524 50525 dispose() { 50526 50527 this.dispatchEvent( { type: 'dispose' } ); 50528 50529 return this; 50530 50531 } 50532 50533 copy( source ) { 50534 50535 this.name = source.name; 50536 this.usage = source.usage; 50537 50538 const uniformsSource = source.uniforms; 50539 50540 this.uniforms.length = 0; 50541 50542 for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) { 50543 50544 const uniforms = Array.isArray( uniformsSource[ i ] ) ? uniformsSource[ i ] : [ uniformsSource[ i ] ]; 50545 50546 for ( let j = 0; j < uniforms.length; j ++ ) { 50547 50548 this.uniforms.push( uniforms[ j ].clone() ); 50549 50550 } 50551 50552 } 50553 50554 return this; 50555 50556 } 50557 50558 clone() { 50559 50560 return new this.constructor().copy( this ); 50561 50562 } 50563 50564} 50565 50566class InstancedInterleavedBuffer extends InterleavedBuffer { 50567 50568 constructor( array, stride, meshPerAttribute = 1 ) { 50569 50570 super( array, stride ); 50571 50572 this.isInstancedInterleavedBuffer = true; 50573 50574 this.meshPerAttribute = meshPerAttribute; 50575 50576 } 50577 50578 copy( source ) { 50579 50580 super.copy( source ); 50581 50582 this.meshPerAttribute = source.meshPerAttribute; 50583 50584 return this; 50585 50586 } 50587 50588 clone( data ) { 50589 50590 const ib = super.clone( data ); 50591 50592 ib.meshPerAttribute = this.meshPerAttribute; 50593 50594 return ib; 50595 50596 } 50597 50598 toJSON( data ) { 50599 50600 const json = super.toJSON( data ); 50601 50602 json.isInstancedInterleavedBuffer = true; 50603 json.meshPerAttribute = this.meshPerAttribute; 50604 50605 return json; 50606 50607 } 50608 50609} 50610 50611class GLBufferAttribute { 50612 50613 constructor( buffer, type, itemSize, elementSize, count ) { 50614 50615 this.isGLBufferAttribute = true; 50616 50617 this.name = ''; 50618 50619 this.buffer = buffer; 50620 this.type = type; 50621 this.itemSize = itemSize; 50622 this.elementSize = elementSize; 50623 this.count = count; 50624 50625 this.version = 0; 50626 50627 } 50628 50629 set needsUpdate( value ) { 50630 50631 if ( value === true ) this.version ++; 50632 50633 } 50634 50635 setBuffer( buffer ) { 50636 50637 this.buffer = buffer; 50638 50639 return this; 50640 50641 } 50642 50643 setType( type, elementSize ) { 50644 50645 this.type = type; 50646 this.elementSize = elementSize; 50647 50648 return this; 50649 50650 } 50651 50652 setItemSize( itemSize ) { 50653 50654 this.itemSize = itemSize; 50655 50656 return this; 50657 50658 } 50659 50660 setCount( count ) { 50661 50662 this.count = count; 50663 50664 return this; 50665 50666 } 50667 50668} 50669 50670const _matrix = /*@__PURE__*/ new Matrix4(); 50671 50672class Raycaster { 50673 50674 constructor( origin, direction, near = 0, far = Infinity ) { 50675 50676 this.ray = new Ray( origin, direction ); 50677 // direction is assumed to be normalized (for accurate distance calculations) 50678 50679 this.near = near; 50680 this.far = far; 50681 this.camera = null; 50682 this.layers = new Layers(); 50683 50684 this.params = { 50685 Mesh: {}, 50686 Line: { threshold: 1 }, 50687 LOD: {}, 50688 Points: { threshold: 1 }, 50689 Sprite: {} 50690 }; 50691 50692 } 50693 50694 set( origin, direction ) { 50695 50696 // direction is assumed to be normalized (for accurate distance calculations) 50697 50698 this.ray.set( origin, direction ); 50699 50700 } 50701 50702 setFromCamera( coords, camera ) { 50703 50704 if ( camera.isPerspectiveCamera ) { 50705 50706 this.ray.origin.setFromMatrixPosition( camera.matrixWorld ); 50707 this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize(); 50708 this.camera = camera; 50709 50710 } else if ( camera.isOrthographicCamera ) { 50711 50712 this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera 50713 this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); 50714 this.camera = camera; 50715 50716 } else { 50717 50718 console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type ); 50719 50720 } 50721 50722 } 50723 50724 setFromXRController( controller ) { 50725 50726 _matrix.identity().extractRotation( controller.matrixWorld ); 50727 50728 this.ray.origin.setFromMatrixPosition( controller.matrixWorld ); 50729 this.ray.direction.set( 0, 0, - 1 ).applyMatrix4( _matrix ); 50730 50731 return this; 50732 50733 } 50734 50735 intersectObject( object, recursive = true, intersects = [] ) { 50736 50737 intersect( object, this, intersects, recursive ); 50738 50739 intersects.sort( ascSort ); 50740 50741 return intersects; 50742 50743 } 50744 50745 intersectObjects( objects, recursive = true, intersects = [] ) { 50746 50747 for ( let i = 0, l = objects.length; i < l; i ++ ) { 50748 50749 intersect( objects[ i ], this, intersects, recursive ); 50750 50751 } 50752 50753 intersects.sort( ascSort ); 50754 50755 return intersects; 50756 50757 } 50758 50759} 50760 50761function ascSort( a, b ) { 50762 50763 return a.distance - b.distance; 50764 50765} 50766 50767function intersect( object, raycaster, intersects, recursive ) { 50768 50769 if ( object.layers.test( raycaster.layers ) ) { 50770 50771 object.raycast( raycaster, intersects ); 50772 50773 } 50774 50775 if ( recursive === true ) { 50776 50777 const children = object.children; 50778 50779 for ( let i = 0, l = children.length; i < l; i ++ ) { 50780 50781 intersect( children[ i ], raycaster, intersects, true ); 50782 50783 } 50784 50785 } 50786 50787} 50788 50789/** 50790 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system 50791 * 50792 * phi (the polar angle) is measured from the positive y-axis. The positive y-axis is up. 50793 * theta (the azimuthal angle) is measured from the positive z-axis. 50794 */ 50795class Spherical { 50796
vendor: 21,135 bytes, lines 50797-51949
50797 constructor( radius = 1, phi = 0, theta = 0 ) { 50798 50799 this.radius = radius; 50800 this.phi = phi; // polar angle 50801 this.theta = theta; // azimuthal angle 50802 50803 return this; 50804 50805 } 50806 50807 set( radius, phi, theta ) { 50808 50809 this.radius = radius; 50810 this.phi = phi; 50811 this.theta = theta; 50812 50813 return this; 50814 50815 } 50816 50817 copy( other ) { 50818 50819 this.radius = other.radius; 50820 this.phi = other.phi; 50821 this.theta = other.theta; 50822 50823 return this; 50824 50825 } 50826 50827 // restrict phi to be between EPS and PI-EPS 50828 makeSafe() { 50829 50830 const EPS = 0.000001; 50831 this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) ); 50832 50833 return this; 50834 50835 } 50836 50837 setFromVector3( v ) { 50838 50839 return this.setFromCartesianCoords( v.x, v.y, v.z ); 50840 50841 } 50842 50843 setFromCartesianCoords( x, y, z ) { 50844 50845 this.radius = Math.sqrt( x * x + y * y + z * z ); 50846 50847 if ( this.radius === 0 ) { 50848 50849 this.theta = 0; 50850 this.phi = 0; 50851 50852 } else { 50853 50854 this.theta = Math.atan2( x, z ); 50855 this.phi = Math.acos( clamp( y / this.radius, - 1, 1 ) ); 50856 50857 } 50858 50859 return this; 50860 50861 } 50862 50863 clone() { 50864 50865 return new this.constructor().copy( this ); 50866 50867 } 50868 50869} 50870 50871/** 50872 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system 50873 */ 50874 50875class Cylindrical { 50876 50877 constructor( radius = 1, theta = 0, y = 0 ) { 50878 50879 this.radius = radius; // distance from the origin to a point in the x-z plane 50880 this.theta = theta; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis 50881 this.y = y; // height above the x-z plane 50882 50883 return this; 50884 50885 } 50886 50887 set( radius, theta, y ) { 50888 50889 this.radius = radius; 50890 this.theta = theta; 50891 this.y = y; 50892 50893 return this; 50894 50895 } 50896 50897 copy( other ) { 50898 50899 this.radius = other.radius; 50900 this.theta = other.theta; 50901 this.y = other.y; 50902 50903 return this; 50904 50905 } 50906 50907 setFromVector3( v ) { 50908 50909 return this.setFromCartesianCoords( v.x, v.y, v.z ); 50910 50911 } 50912 50913 setFromCartesianCoords( x, y, z ) { 50914 50915 this.radius = Math.sqrt( x * x + z * z ); 50916 this.theta = Math.atan2( x, z ); 50917 this.y = y; 50918 50919 return this; 50920 50921 } 50922 50923 clone() { 50924 50925 return new this.constructor().copy( this ); 50926 50927 } 50928 50929} 50930 50931const _vector$4 = /*@__PURE__*/ new Vector2(); 50932 50933class Box2 { 50934 50935 constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) { 50936 50937 this.isBox2 = true; 50938 50939 this.min = min; 50940 this.max = max; 50941 50942 } 50943 50944 set( min, max ) { 50945 50946 this.min.copy( min ); 50947 this.max.copy( max ); 50948 50949 return this; 50950 50951 } 50952 50953 setFromPoints( points ) { 50954 50955 this.makeEmpty(); 50956 50957 for ( let i = 0, il = points.length; i < il; i ++ ) { 50958 50959 this.expandByPoint( points[ i ] ); 50960 50961 } 50962 50963 return this; 50964 50965 } 50966 50967 setFromCenterAndSize( center, size ) { 50968 50969 const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 ); 50970 this.min.copy( center ).sub( halfSize ); 50971 this.max.copy( center ).add( halfSize ); 50972 50973 return this; 50974 50975 } 50976 50977 clone() { 50978 50979 return new this.constructor().copy( this ); 50980 50981 } 50982 50983 copy( box ) { 50984 50985 this.min.copy( box.min ); 50986 this.max.copy( box.max ); 50987 50988 return this; 50989 50990 } 50991 50992 makeEmpty() { 50993 50994 this.min.x = this.min.y = + Infinity; 50995 this.max.x = this.max.y = - Infinity; 50996 50997 return this; 50998 50999 } 51000 51001 isEmpty() { 51002 51003 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes 51004 51005 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); 51006 51007 } 51008 51009 getCenter( target ) { 51010 51011 return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); 51012 51013 } 51014 51015 getSize( target ) { 51016 51017 return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min ); 51018 51019 } 51020 51021 expandByPoint( point ) { 51022 51023 this.min.min( point ); 51024 this.max.max( point ); 51025 51026 return this; 51027 51028 } 51029 51030 expandByVector( vector ) { 51031 51032 this.min.sub( vector ); 51033 this.max.add( vector ); 51034 51035 return this; 51036 51037 } 51038 51039 expandByScalar( scalar ) { 51040 51041 this.min.addScalar( - scalar ); 51042 this.max.addScalar( scalar ); 51043 51044 return this; 51045 51046 } 51047 51048 containsPoint( point ) { 51049 51050 return point.x < this.min.x || point.x > this.max.x || 51051 point.y < this.min.y || point.y > this.max.y ? false : true; 51052 51053 } 51054 51055 containsBox( box ) { 51056 51057 return this.min.x <= box.min.x && box.max.x <= this.max.x && 51058 this.min.y <= box.min.y && box.max.y <= this.max.y; 51059 51060 } 51061 51062 getParameter( point, target ) { 51063 51064 // This can potentially have a divide by zero if the box 51065 // has a size dimension of 0. 51066 51067 return target.set( 51068 ( point.x - this.min.x ) / ( this.max.x - this.min.x ), 51069 ( point.y - this.min.y ) / ( this.max.y - this.min.y ) 51070 ); 51071 51072 } 51073 51074 intersectsBox( box ) { 51075 51076 // using 4 splitting planes to rule out intersections 51077 51078 return box.max.x < this.min.x || box.min.x > this.max.x || 51079 box.max.y < this.min.y || box.min.y > this.max.y ? false : true; 51080 51081 } 51082 51083 clampPoint( point, target ) { 51084 51085 return target.copy( point ).clamp( this.min, this.max ); 51086 51087 } 51088 51089 distanceToPoint( point ) { 51090 51091 return this.clampPoint( point, _vector$4 ).distanceTo( point ); 51092 51093 } 51094 51095 intersect( box ) { 51096 51097 this.min.max( box.min ); 51098 this.max.min( box.max ); 51099 51100 if ( this.isEmpty() ) this.makeEmpty(); 51101 51102 return this; 51103 51104 } 51105 51106 union( box ) { 51107 51108 this.min.min( box.min ); 51109 this.max.max( box.max ); 51110 51111 return this; 51112 51113 } 51114 51115 translate( offset ) { 51116 51117 this.min.add( offset ); 51118 this.max.add( offset ); 51119 51120 return this; 51121 51122 } 51123 51124 equals( box ) { 51125 51126 return box.min.equals( this.min ) && box.max.equals( this.max ); 51127 51128 } 51129 51130} 51131 51132const _startP = /*@__PURE__*/ new Vector3(); 51133const _startEnd = /*@__PURE__*/ new Vector3(); 51134 51135class Line3 { 51136 51137 constructor( start = new Vector3(), end = new Vector3() ) { 51138 51139 this.start = start; 51140 this.end = end; 51141 51142 } 51143 51144 set( start, end ) { 51145 51146 this.start.copy( start ); 51147 this.end.copy( end ); 51148 51149 return this; 51150 51151 } 51152 51153 copy( line ) { 51154 51155 this.start.copy( line.start ); 51156 this.end.copy( line.end ); 51157 51158 return this; 51159 51160 } 51161 51162 getCenter( target ) { 51163 51164 return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); 51165 51166 } 51167 51168 delta( target ) { 51169 51170 return target.subVectors( this.end, this.start ); 51171 51172 } 51173 51174 distanceSq() { 51175 51176 return this.start.distanceToSquared( this.end ); 51177 51178 } 51179 51180 distance() { 51181 51182 return this.start.distanceTo( this.end ); 51183 51184 } 51185 51186 at( t, target ) { 51187 51188 return this.delta( target ).multiplyScalar( t ).add( this.start ); 51189 51190 } 51191 51192 closestPointToPointParameter( point, clampToLine ) { 51193 51194 _startP.subVectors( point, this.start ); 51195 _startEnd.subVectors( this.end, this.start ); 51196 51197 const startEnd2 = _startEnd.dot( _startEnd ); 51198 const startEnd_startP = _startEnd.dot( _startP ); 51199 51200 let t = startEnd_startP / startEnd2; 51201 51202 if ( clampToLine ) { 51203 51204 t = clamp( t, 0, 1 ); 51205 51206 } 51207 51208 return t; 51209 51210 } 51211 51212 closestPointToPoint( point, clampToLine, target ) { 51213 51214 const t = this.closestPointToPointParameter( point, clampToLine ); 51215 51216 return this.delta( target ).multiplyScalar( t ).add( this.start ); 51217 51218 } 51219 51220 applyMatrix4( matrix ) { 51221 51222 this.start.applyMatrix4( matrix ); 51223 this.end.applyMatrix4( matrix ); 51224 51225 return this; 51226 51227 } 51228 51229 equals( line ) { 51230 51231 return line.start.equals( this.start ) && line.end.equals( this.end ); 51232 51233 } 51234 51235 clone() { 51236 51237 return new this.constructor().copy( this ); 51238 51239 } 51240 51241} 51242 51243const _vector$3 = /*@__PURE__*/ new Vector3(); 51244 51245class SpotLightHelper extends Object3D { 51246 51247 constructor( light, color ) { 51248 51249 super(); 51250 51251 this.light = light; 51252 51253 this.matrixAutoUpdate = false; 51254 51255 this.color = color; 51256 51257 this.type = 'SpotLightHelper'; 51258 51259 const geometry = new BufferGeometry(); 51260 51261 const positions = [ 51262 0, 0, 0, 0, 0, 1, 51263 0, 0, 0, 1, 0, 1, 51264 0, 0, 0, - 1, 0, 1, 51265 0, 0, 0, 0, 1, 1, 51266 0, 0, 0, 0, - 1, 1 51267 ]; 51268 51269 for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) { 51270 51271 const p1 = ( i / l ) * Math.PI * 2; 51272 const p2 = ( j / l ) * Math.PI * 2; 51273 51274 positions.push( 51275 Math.cos( p1 ), Math.sin( p1 ), 1, 51276 Math.cos( p2 ), Math.sin( p2 ), 1 51277 ); 51278 51279 } 51280 51281 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 51282 51283 const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); 51284 51285 this.cone = new LineSegments( geometry, material ); 51286 this.add( this.cone ); 51287 51288 this.update(); 51289 51290 } 51291 51292 dispose() { 51293 51294 this.cone.geometry.dispose(); 51295 this.cone.material.dispose(); 51296 51297 } 51298 51299 update() { 51300 51301 this.light.updateWorldMatrix( true, false ); 51302 this.light.target.updateWorldMatrix( true, false ); 51303 51304 // update the local matrix based on the parent and light target transforms 51305 if ( this.parent ) { 51306 51307 this.parent.updateWorldMatrix( true ); 51308 51309 this.matrix 51310 .copy( this.parent.matrixWorld ) 51311 .invert() 51312 .multiply( this.light.matrixWorld ); 51313 51314 } else { 51315 51316 this.matrix.copy( this.light.matrixWorld ); 51317 51318 } 51319 51320 this.matrixWorld.copy( this.light.matrixWorld ); 51321 51322 const coneLength = this.light.distance ? this.light.distance : 1000; 51323 const coneWidth = coneLength * Math.tan( this.light.angle ); 51324 51325 this.cone.scale.set( coneWidth, coneWidth, coneLength ); 51326 51327 _vector$3.setFromMatrixPosition( this.light.target.matrixWorld ); 51328 51329 this.cone.lookAt( _vector$3 ); 51330 51331 if ( this.color !== undefined ) { 51332 51333 this.cone.material.color.set( this.color ); 51334 51335 } else { 51336 51337 this.cone.material.color.copy( this.light.color ); 51338 51339 } 51340 51341 } 51342 51343} 51344 51345const _vector$2 = /*@__PURE__*/ new Vector3(); 51346const _boneMatrix = /*@__PURE__*/ new Matrix4(); 51347const _matrixWorldInv = /*@__PURE__*/ new Matrix4(); 51348 51349 51350class SkeletonHelper extends LineSegments { 51351 51352 constructor( object ) { 51353 51354 const bones = getBoneList( object ); 51355 51356 const geometry = new BufferGeometry(); 51357 51358 const vertices = []; 51359 const colors = []; 51360 51361 const color1 = new Color( 0, 0, 1 ); 51362 const color2 = new Color( 0, 1, 0 ); 51363 51364 for ( let i = 0; i < bones.length; i ++ ) { 51365 51366 const bone = bones[ i ]; 51367 51368 if ( bone.parent && bone.parent.isBone ) { 51369 51370 vertices.push( 0, 0, 0 ); 51371 vertices.push( 0, 0, 0 ); 51372 colors.push( color1.r, color1.g, color1.b ); 51373 colors.push( color2.r, color2.g, color2.b ); 51374 51375 } 51376 51377 } 51378 51379 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 51380 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 51381 51382 const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } ); 51383 51384 super( geometry, material ); 51385 51386 this.isSkeletonHelper = true; 51387 51388 this.type = 'SkeletonHelper'; 51389 51390 this.root = object; 51391 this.bones = bones; 51392 51393 this.matrix = object.matrixWorld; 51394 this.matrixAutoUpdate = false; 51395 51396 } 51397 51398 updateMatrixWorld( force ) { 51399 51400 const bones = this.bones; 51401 51402 const geometry = this.geometry; 51403 const position = geometry.getAttribute( 'position' ); 51404 51405 _matrixWorldInv.copy( this.root.matrixWorld ).invert(); 51406 51407 for ( let i = 0, j = 0; i < bones.length; i ++ ) { 51408 51409 const bone = bones[ i ]; 51410 51411 if ( bone.parent && bone.parent.isBone ) { 51412 51413 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld ); 51414 _vector$2.setFromMatrixPosition( _boneMatrix ); 51415 position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z ); 51416 51417 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld ); 51418 _vector$2.setFromMatrixPosition( _boneMatrix ); 51419 position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z ); 51420 51421 j += 2; 51422 51423 } 51424 51425 } 51426 51427 geometry.getAttribute( 'position' ).needsUpdate = true; 51428 51429 super.updateMatrixWorld( force ); 51430 51431 } 51432 51433 dispose() { 51434 51435 this.geometry.dispose(); 51436 this.material.dispose(); 51437 51438 } 51439 51440} 51441 51442 51443function getBoneList( object ) { 51444 51445 const boneList = []; 51446 51447 if ( object.isBone === true ) { 51448 51449 boneList.push( object ); 51450 51451 } 51452 51453 for ( let i = 0; i < object.children.length; i ++ ) { 51454 51455 boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); 51456 51457 } 51458 51459 return boneList; 51460 51461} 51462 51463class PointLightHelper extends Mesh { 51464 51465 constructor( light, sphereSize, color ) { 51466 51467 const geometry = new SphereGeometry( sphereSize, 4, 2 ); 51468 const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); 51469 51470 super( geometry, material ); 51471 51472 this.light = light; 51473 51474 this.color = color; 51475 51476 this.type = 'PointLightHelper'; 51477 51478 this.matrix = this.light.matrixWorld; 51479 this.matrixAutoUpdate = false; 51480 51481 this.update(); 51482 51483 51484 /* 51485 // TODO: delete this comment? 51486 const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); 51487 const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); 51488 51489 this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); 51490 this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); 51491 51492 const d = light.distance; 51493 51494 if ( d === 0.0 ) { 51495 51496 this.lightDistance.visible = false; 51497 51498 } else { 51499 51500 this.lightDistance.scale.set( d, d, d ); 51501 51502 } 51503 51504 this.add( this.lightDistance ); 51505 */ 51506 51507 } 51508 51509 dispose() { 51510 51511 this.geometry.dispose(); 51512 this.material.dispose(); 51513 51514 } 51515 51516 update() { 51517 51518 this.light.updateWorldMatrix( true, false ); 51519 51520 if ( this.color !== undefined ) { 51521 51522 this.material.color.set( this.color ); 51523 51524 } else { 51525 51526 this.material.color.copy( this.light.color ); 51527 51528 } 51529 51530 /* 51531 const d = this.light.distance; 51532 51533 if ( d === 0.0 ) { 51534 51535 this.lightDistance.visible = false; 51536 51537 } else { 51538 51539 this.lightDistance.visible = true; 51540 this.lightDistance.scale.set( d, d, d ); 51541 51542 } 51543 */ 51544 51545 } 51546 51547} 51548 51549const _vector$1 = /*@__PURE__*/ new Vector3(); 51550const _color1 = /*@__PURE__*/ new Color(); 51551const _color2 = /*@__PURE__*/ new Color(); 51552 51553class HemisphereLightHelper extends Object3D { 51554 51555 constructor( light, size, color ) { 51556 51557 super(); 51558 51559 this.light = light; 51560 51561 this.matrix = light.matrixWorld; 51562 this.matrixAutoUpdate = false; 51563 51564 this.color = color; 51565 51566 this.type = 'HemisphereLightHelper'; 51567 51568 const geometry = new OctahedronGeometry( size ); 51569 geometry.rotateY( Math.PI * 0.5 ); 51570 51571 this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); 51572 if ( this.color === undefined ) this.material.vertexColors = true; 51573 51574 const position = geometry.getAttribute( 'position' ); 51575 const colors = new Float32Array( position.count * 3 ); 51576 51577 geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) ); 51578 51579 this.add( new Mesh( geometry, this.material ) ); 51580 51581 this.update(); 51582 51583 } 51584 51585 dispose() { 51586 51587 this.children[ 0 ].geometry.dispose(); 51588 this.children[ 0 ].material.dispose(); 51589 51590 } 51591 51592 update() { 51593 51594 const mesh = this.children[ 0 ]; 51595 51596 if ( this.color !== undefined ) { 51597 51598 this.material.color.set( this.color ); 51599 51600 } else { 51601 51602 const colors = mesh.geometry.getAttribute( 'color' ); 51603 51604 _color1.copy( this.light.color ); 51605 _color2.copy( this.light.groundColor ); 51606 51607 for ( let i = 0, l = colors.count; i < l; i ++ ) { 51608 51609 const color = ( i < ( l / 2 ) ) ? _color1 : _color2; 51610 51611 colors.setXYZ( i, color.r, color.g, color.b ); 51612 51613 } 51614 51615 colors.needsUpdate = true; 51616 51617 } 51618 51619 this.light.updateWorldMatrix( true, false ); 51620 51621 mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() ); 51622 51623 } 51624 51625} 51626 51627class GridHelper extends LineSegments { 51628 51629 constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) { 51630 51631 color1 = new Color( color1 ); 51632 color2 = new Color( color2 ); 51633 51634 const center = divisions / 2; 51635 const step = size / divisions; 51636 const halfSize = size / 2; 51637 51638 const vertices = [], colors = []; 51639 51640 for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) { 51641 51642 vertices.push( - halfSize, 0, k, halfSize, 0, k ); 51643 vertices.push( k, 0, - halfSize, k, 0, halfSize ); 51644 51645 const color = i === center ? color1 : color2; 51646 51647 color.toArray( colors, j ); j += 3; 51648 color.toArray( colors, j ); j += 3; 51649 color.toArray( colors, j ); j += 3; 51650 color.toArray( colors, j ); j += 3; 51651 51652 } 51653 51654 const geometry = new BufferGeometry(); 51655 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 51656 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 51657 51658 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); 51659 51660 super( geometry, material ); 51661 51662 this.type = 'GridHelper'; 51663 51664 } 51665 51666 dispose() { 51667 51668 this.geometry.dispose(); 51669 this.material.dispose(); 51670 51671 } 51672 51673} 51674 51675class PolarGridHelper extends LineSegments { 51676 51677 constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) { 51678 51679 color1 = new Color( color1 ); 51680 color2 = new Color( color2 ); 51681 51682 const vertices = []; 51683 const colors = []; 51684 51685 // create the sectors 51686 51687 if ( sectors > 1 ) { 51688 51689 for ( let i = 0; i < sectors; i ++ ) { 51690 51691 const v = ( i / sectors ) * ( Math.PI * 2 ); 51692 51693 const x = Math.sin( v ) * radius; 51694 const z = Math.cos( v ) * radius; 51695 51696 vertices.push( 0, 0, 0 ); 51697 vertices.push( x, 0, z ); 51698 51699 const color = ( i & 1 ) ? color1 : color2; 51700 51701 colors.push( color.r, color.g, color.b ); 51702 colors.push( color.r, color.g, color.b ); 51703 51704 } 51705 51706 } 51707 51708 // create the rings 51709 51710 for ( let i = 0; i < rings; i ++ ) { 51711 51712 const color = ( i & 1 ) ? color1 : color2; 51713 51714 const r = radius - ( radius / rings * i ); 51715 51716 for ( let j = 0; j < divisions; j ++ ) { 51717 51718 // first vertex 51719 51720 let v = ( j / divisions ) * ( Math.PI * 2 ); 51721 51722 let x = Math.sin( v ) * r; 51723 let z = Math.cos( v ) * r; 51724 51725 vertices.push( x, 0, z ); 51726 colors.push( color.r, color.g, color.b ); 51727 51728 // second vertex 51729 51730 v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 ); 51731 51732 x = Math.sin( v ) * r; 51733 z = Math.cos( v ) * r; 51734 51735 vertices.push( x, 0, z ); 51736 colors.push( color.r, color.g, color.b ); 51737 51738 } 51739 51740 } 51741 51742 const geometry = new BufferGeometry(); 51743 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 51744 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 51745 51746 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); 51747 51748 super( geometry, material ); 51749 51750 this.type = 'PolarGridHelper'; 51751 51752 } 51753 51754 dispose() { 51755 51756 this.geometry.dispose(); 51757 this.material.dispose(); 51758 51759 } 51760 51761} 51762 51763const _v1 = /*@__PURE__*/ new Vector3(); 51764const _v2 = /*@__PURE__*/ new Vector3(); 51765const _v3 = /*@__PURE__*/ new Vector3(); 51766 51767class DirectionalLightHelper extends Object3D { 51768 51769 constructor( light, size, color ) { 51770 51771 super(); 51772 51773 this.light = light; 51774 51775 this.matrix = light.matrixWorld; 51776 this.matrixAutoUpdate = false; 51777 51778 this.color = color; 51779 51780 this.type = 'DirectionalLightHelper'; 51781 51782 if ( size === undefined ) size = 1; 51783 51784 let geometry = new BufferGeometry(); 51785 geometry.setAttribute( 'position', new Float32BufferAttribute( [ 51786 - size, size, 0, 51787 size, size, 0, 51788 size, - size, 0, 51789 - size, - size, 0, 51790 - size, size, 0 51791 ], 3 ) ); 51792 51793 const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); 51794 51795 this.lightPlane = new Line( geometry, material ); 51796 this.add( this.lightPlane ); 51797 51798 geometry = new BufferGeometry(); 51799 geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); 51800 51801 this.targetLine = new Line( geometry, material ); 51802 this.add( this.targetLine ); 51803 51804 this.update(); 51805 51806 } 51807 51808 dispose() { 51809 51810 this.lightPlane.geometry.dispose(); 51811 this.lightPlane.material.dispose(); 51812 this.targetLine.geometry.dispose(); 51813 this.targetLine.material.dispose(); 51814 51815 } 51816 51817 update() { 51818 51819 this.light.updateWorldMatrix( true, false ); 51820 this.light.target.updateWorldMatrix( true, false ); 51821 51822 _v1.setFromMatrixPosition( this.light.matrixWorld ); 51823 _v2.setFromMatrixPosition( this.light.target.matrixWorld ); 51824 _v3.subVectors( _v2, _v1 ); 51825 51826 this.lightPlane.lookAt( _v2 ); 51827 51828 if ( this.color !== undefined ) { 51829 51830 this.lightPlane.material.color.set( this.color ); 51831 this.targetLine.material.color.set( this.color ); 51832 51833 } else { 51834 51835 this.lightPlane.material.color.copy( this.light.color ); 51836 this.targetLine.material.color.copy( this.light.color ); 51837 51838 } 51839 51840 this.targetLine.lookAt( _v2 ); 51841 this.targetLine.scale.z = _v3.length(); 51842 51843 } 51844 51845} 51846 51847const _vector = /*@__PURE__*/ new Vector3(); 51848const _camera = /*@__PURE__*/ new Camera(); 51849 51850/** 51851 * - shows frustum, line of sight and up of the camera 51852 * - suitable for fast updates 51853 * - based on frustum visualization in lightgl.js shadowmap example 51854 * https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html 51855 */ 51856 51857class CameraHelper extends LineSegments { 51858 51859 constructor( camera ) { 51860 51861 const geometry = new BufferGeometry(); 51862 const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } ); 51863 51864 const vertices = []; 51865 const colors = []; 51866 51867 const pointMap = {}; 51868 51869 // near 51870 51871 addLine( 'n1', 'n2' ); 51872 addLine( 'n2', 'n4' ); 51873 addLine( 'n4', 'n3' ); 51874 addLine( 'n3', 'n1' ); 51875 51876 // far 51877 51878 addLine( 'f1', 'f2' ); 51879 addLine( 'f2', 'f4' ); 51880 addLine( 'f4', 'f3' ); 51881 addLine( 'f3', 'f1' ); 51882 51883 // sides 51884 51885 addLine( 'n1', 'f1' ); 51886 addLine( 'n2', 'f2' ); 51887 addLine( 'n3', 'f3' ); 51888 addLine( 'n4', 'f4' ); 51889 51890 // cone 51891 51892 addLine( 'p', 'n1' ); 51893 addLine( 'p', 'n2' ); 51894 addLine( 'p', 'n3' ); 51895 addLine( 'p', 'n4' ); 51896 51897 // up 51898 51899 addLine( 'u1', 'u2' ); 51900 addLine( 'u2', 'u3' ); 51901 addLine( 'u3', 'u1' ); 51902 51903 // target 51904 51905 addLine( 'c', 't' ); 51906 addLine( 'p', 'c' ); 51907 51908 // cross 51909 51910 addLine( 'cn1', 'cn2' ); 51911 addLine( 'cn3', 'cn4' ); 51912 51913 addLine( 'cf1', 'cf2' ); 51914 addLine( 'cf3', 'cf4' ); 51915 51916 function addLine( a, b ) { 51917 51918 addPoint( a ); 51919 addPoint( b ); 51920 51921 } 51922 51923 function addPoint( id ) { 51924 51925 vertices.push( 0, 0, 0 ); 51926 colors.push( 0, 0, 0 ); 51927 51928 if ( pointMap[ id ] === undefined ) { 51929 51930 pointMap[ id ] = []; 51931 51932 } 51933 51934 pointMap[ id ].push( ( vertices.length / 3 ) - 1 ); 51935 51936 } 51937 51938 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 51939 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 51940 51941 super( geometry, material ); 51942 51943 this.type = 'CameraHelper'; 51944 51945 this.camera = camera; 51946 if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix(); 51947 51948 this.matrix = camera.matrixWorld; 51949 this.matrixAutoUpdate = false;
51950 51951 this.pointMap = pointMap; 51952 51953 this.update(); 51954 51955 // colors 51956 51957 const colorFrustum = new Color( 0xffaa00 ); 51958 const colorCone = new Color( 0xff0000 ); 51959 const colorUp = new Color( 0x00aaff ); 51960 const colorTarget = new Color( 0xffffff ); 51961 const colorCross = new Color( 0x333333 ); 51962 51963 this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross ); 51964 51965 } 51966 51967 setColors( frustum, cone, up, target, cross ) { 51968 51969 const geometry = this.geometry; 51970 51971 const colorAttribute = geometry.getAttribute( 'color' ); 51972 51973 // near 51974 51975 colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2 51976 colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4 51977 colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3 51978 colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1 51979 51980 // far 51981 51982 colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2 51983 colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4 51984 colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3 51985 colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1 51986 51987 // sides 51988 51989 colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1 51990 colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2 51991 colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3 51992 colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4 51993 51994 // cone 51995 51996 colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1 51997 colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2 51998 colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3 51999 colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4 52000 52001 // up 52002 52003 colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2 52004 colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3 52005 colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1 52006 52007 // target 52008 52009 colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t 52010 colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c 52011 52012 // cross 52013 52014 colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2 52015 colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4 52016 52017 colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2 52018 colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4 52019 52020 colorAttribute.needsUpdate = true; 52021 52022 } 52023 52024 update() { 52025 52026 const geometry = this.geometry; 52027 const pointMap = this.pointMap; 52028 52029 const w = 1, h = 1; 52030 52031 // we need just camera projection matrix inverse 52032 // world matrix must be identity 52033 52034 _camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse ); 52035 52036 // center / target 52037 52038 setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 ); 52039 setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 ); 52040 52041 // near 52042 52043 setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 ); 52044 setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 ); 52045 setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 ); 52046 setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 ); 52047 52048 // far 52049 52050 setPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 ); 52051 setPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 ); 52052 setPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 ); 52053 setPoint( 'f4', pointMap, geometry, _camera, w, h, 1 ); 52054 52055 // up 52056 52057 setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 ); 52058 setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 ); 52059 setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 ); 52060 52061 // cross 52062 52063 setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 ); 52064 setPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 ); 52065 setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 ); 52066 setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 ); 52067 52068 setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 ); 52069 setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 ); 52070 setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 ); 52071 setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 ); 52072 52073 geometry.getAttribute( 'position' ).needsUpdate = true; 52074 52075 } 52076 52077 dispose() { 52078 52079 this.geometry.dispose(); 52080 this.material.dispose(); 52081 52082 } 52083 52084} 52085 52086 52087function setPoint( point, pointMap, geometry, camera, x, y, z ) { 52088 52089 _vector.set( x, y, z ).unproject( camera ); 52090 52091 const points = pointMap[ point ]; 52092 52093 if ( points !== undefined ) { 52094 52095 const position = geometry.getAttribute( 'position' ); 52096 52097 for ( let i = 0, l = points.length; i < l; i ++ ) { 52098 52099 position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z ); 52100 52101 } 52102 52103 } 52104 52105} 52106 52107const _box = /*@__PURE__*/ new Box3(); 52108 52109class BoxHelper extends LineSegments { 52110 52111 constructor( object, color = 0xffff00 ) { 52112 52113 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 ] ); 52114 const positions = new Float32Array( 8 * 3 ); 52115 52116 const geometry = new BufferGeometry(); 52117 geometry.setIndex( new BufferAttribute( indices, 1 ) ); 52118 geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) ); 52119 52120 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 52121 52122 this.object = object; 52123 this.type = 'BoxHelper'; 52124 52125 this.matrixAutoUpdate = false;
vendor: 4,705 bytes, lines 52126-52342
52126 52127 this.update(); 52128 52129 } 52130 52131 update( object ) { 52132 52133 if ( object !== undefined ) { 52134 52135 console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' ); 52136 52137 } 52138 52139 if ( this.object !== undefined ) { 52140 52141 _box.setFromObject( this.object ); 52142 52143 } 52144 52145 if ( _box.isEmpty() ) return; 52146 52147 const min = _box.min; 52148 const max = _box.max; 52149 52150 /* 52151 5____4 52152 1/___0/| 52153 | 6__|_7 52154 2/___3/ 52155 52156 0: max.x, max.y, max.z 52157 1: min.x, max.y, max.z 52158 2: min.x, min.y, max.z 52159 3: max.x, min.y, max.z 52160 4: max.x, max.y, min.z 52161 5: min.x, max.y, min.z 52162 6: min.x, min.y, min.z 52163 7: max.x, min.y, min.z 52164 */ 52165 52166 const position = this.geometry.attributes.position; 52167 const array = position.array; 52168 52169 array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z; 52170 array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z; 52171 array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z; 52172 array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z; 52173 array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z; 52174 array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z; 52175 array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z; 52176 array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z; 52177 52178 position.needsUpdate = true; 52179 52180 this.geometry.computeBoundingSphere(); 52181 52182 } 52183 52184 setFromObject( object ) { 52185 52186 this.object = object; 52187 this.update(); 52188 52189 return this; 52190 52191 } 52192 52193 copy( source, recursive ) { 52194 52195 super.copy( source, recursive ); 52196 52197 this.object = source.object; 52198 52199 return this; 52200 52201 } 52202 52203 dispose() { 52204 52205 this.geometry.dispose(); 52206 this.material.dispose(); 52207 52208 } 52209 52210} 52211 52212class Box3Helper extends LineSegments { 52213 52214 constructor( box, color = 0xffff00 ) { 52215 52216 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 ] ); 52217 52218 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 ]; 52219 52220 const geometry = new BufferGeometry(); 52221 52222 geometry.setIndex( new BufferAttribute( indices, 1 ) ); 52223 52224 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 52225 52226 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 52227 52228 this.box = box; 52229 52230 this.type = 'Box3Helper'; 52231 52232 this.geometry.computeBoundingSphere(); 52233 52234 } 52235 52236 updateMatrixWorld( force ) { 52237 52238 const box = this.box; 52239 52240 if ( box.isEmpty() ) return; 52241 52242 box.getCenter( this.position ); 52243 52244 box.getSize( this.scale ); 52245 52246 this.scale.multiplyScalar( 0.5 ); 52247 52248 super.updateMatrixWorld( force ); 52249 52250 } 52251 52252 dispose() { 52253 52254 this.geometry.dispose(); 52255 this.material.dispose(); 52256 52257 } 52258 52259} 52260 52261class PlaneHelper extends Line { 52262 52263 constructor( plane, size = 1, hex = 0xffff00 ) { 52264 52265 const color = hex; 52266 52267 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 ]; 52268 52269 const geometry = new BufferGeometry(); 52270 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 52271 geometry.computeBoundingSphere(); 52272 52273 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 52274 52275 this.type = 'PlaneHelper'; 52276 52277 this.plane = plane; 52278 52279 this.size = size; 52280 52281 const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ]; 52282 52283 const geometry2 = new BufferGeometry(); 52284 geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); 52285 geometry2.computeBoundingSphere(); 52286 52287 this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) ); 52288 52289 } 52290 52291 updateMatrixWorld( force ) { 52292 52293 this.position.set( 0, 0, 0 ); 52294 52295 this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 ); 52296 52297 this.lookAt( this.plane.normal ); 52298 52299 this.translateZ( - this.plane.constant ); 52300 52301 super.updateMatrixWorld( force ); 52302 52303 } 52304 52305 dispose() { 52306 52307 this.geometry.dispose(); 52308 this.material.dispose(); 52309 this.children[ 0 ].geometry.dispose(); 52310 this.children[ 0 ].material.dispose(); 52311 52312 } 52313 52314} 52315 52316const _axis = /*@__PURE__*/ new Vector3(); 52317let _lineGeometry, _coneGeometry; 52318 52319class ArrowHelper extends Object3D { 52320 52321 // dir is assumed to be normalized 52322 52323 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 ) { 52324 52325 super(); 52326 52327 this.type = 'ArrowHelper'; 52328 52329 if ( _lineGeometry === undefined ) { 52330 52331 _lineGeometry = new BufferGeometry(); 52332 _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); 52333 52334 _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 ); 52335 _coneGeometry.translate( 0, - 0.5, 0 ); 52336 52337 } 52338 52339 this.position.copy( origin ); 52340 52341 this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 52342 this.line.matrixAutoUpdate = false;
vendor: 3,957 bytes, lines 52343-52562
52343 this.add( this.line ); 52344 52345 this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) ); 52346 this.cone.matrixAutoUpdate = false; 52347 this.add( this.cone ); 52348 52349 this.setDirection( dir ); 52350 this.setLength( length, headLength, headWidth ); 52351 52352 } 52353 52354 setDirection( dir ) { 52355 52356 // dir is assumed to be normalized 52357 52358 if ( dir.y > 0.99999 ) { 52359 52360 this.quaternion.set( 0, 0, 0, 1 ); 52361 52362 } else if ( dir.y < - 0.99999 ) { 52363 52364 this.quaternion.set( 1, 0, 0, 0 ); 52365 52366 } else { 52367 52368 _axis.set( dir.z, 0, - dir.x ).normalize(); 52369 52370 const radians = Math.acos( dir.y ); 52371 52372 this.quaternion.setFromAxisAngle( _axis, radians ); 52373 52374 } 52375 52376 } 52377 52378 setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) { 52379 52380 this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458 52381 this.line.updateMatrix(); 52382 52383 this.cone.scale.set( headWidth, headLength, headWidth ); 52384 this.cone.position.y = length; 52385 this.cone.updateMatrix(); 52386 52387 } 52388 52389 setColor( color ) { 52390 52391 this.line.material.color.set( color ); 52392 this.cone.material.color.set( color ); 52393 52394 } 52395 52396 copy( source ) { 52397 52398 super.copy( source, false ); 52399 52400 this.line.copy( source.line ); 52401 this.cone.copy( source.cone ); 52402 52403 return this; 52404 52405 } 52406 52407 dispose() { 52408 52409 this.line.geometry.dispose(); 52410 this.line.material.dispose(); 52411 this.cone.geometry.dispose(); 52412 this.cone.material.dispose(); 52413 52414 } 52415 52416} 52417 52418class AxesHelper extends LineSegments { 52419 52420 constructor( size = 1 ) { 52421 52422 const vertices = [ 52423 0, 0, 0, size, 0, 0, 52424 0, 0, 0, 0, size, 0, 52425 0, 0, 0, 0, 0, size 52426 ]; 52427 52428 const colors = [ 52429 1, 0, 0, 1, 0.6, 0, 52430 0, 1, 0, 0.6, 1, 0, 52431 0, 0, 1, 0, 0.6, 1 52432 ]; 52433 52434 const geometry = new BufferGeometry(); 52435 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 52436 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 52437 52438 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); 52439 52440 super( geometry, material ); 52441 52442 this.type = 'AxesHelper'; 52443 52444 } 52445 52446 setColors( xAxisColor, yAxisColor, zAxisColor ) { 52447 52448 const color = new Color(); 52449 const array = this.geometry.attributes.color.array; 52450 52451 color.set( xAxisColor ); 52452 color.toArray( array, 0 ); 52453 color.toArray( array, 3 ); 52454 52455 color.set( yAxisColor ); 52456 color.toArray( array, 6 ); 52457 color.toArray( array, 9 ); 52458 52459 color.set( zAxisColor ); 52460 color.toArray( array, 12 ); 52461 color.toArray( array, 15 ); 52462 52463 this.geometry.attributes.color.needsUpdate = true; 52464 52465 return this; 52466 52467 } 52468 52469 dispose() { 52470 52471 this.geometry.dispose(); 52472 this.material.dispose(); 52473 52474 } 52475 52476} 52477 52478class ShapePath { 52479 52480 constructor() { 52481 52482 this.type = 'ShapePath'; 52483 52484 this.color = new Color(); 52485 52486 this.subPaths = []; 52487 this.currentPath = null; 52488 52489 } 52490 52491 moveTo( x, y ) { 52492 52493 this.currentPath = new Path(); 52494 this.subPaths.push( this.currentPath ); 52495 this.currentPath.moveTo( x, y ); 52496 52497 return this; 52498 52499 } 52500 52501 lineTo( x, y ) { 52502 52503 this.currentPath.lineTo( x, y ); 52504 52505 return this; 52506 52507 } 52508 52509 quadraticCurveTo( aCPx, aCPy, aX, aY ) { 52510 52511 this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY ); 52512 52513 return this; 52514 52515 } 52516 52517 bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { 52518 52519 this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ); 52520 52521 return this; 52522 52523 } 52524 52525 splineThru( pts ) { 52526 52527 this.currentPath.splineThru( pts ); 52528 52529 return this; 52530 52531 } 52532 52533 toShapes( isCCW ) { 52534 52535 function toShapesNoHoles( inSubpaths ) { 52536 52537 const shapes = []; 52538 52539 for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) { 52540 52541 const tmpPath = inSubpaths[ i ]; 52542 52543 const tmpShape = new Shape(); 52544 tmpShape.curves = tmpPath.curves; 52545 52546 shapes.push( tmpShape ); 52547 52548 } 52549 52550 return shapes; 52551 52552 } 52553 52554 function isPointInsidePolygon( inPt, inPolygon ) { 52555 52556 const polyLen = inPolygon.length; 52557 52558 // inPt on polygon contour => immediate success or 52559 // toggling of inside/outside at every single! intersection point of an edge 52560 // with the horizontal line through inPt, left of inPt 52561 // not counting lowerY endpoints of edges and whole edges on that line 52562 let inside = false;
52563 for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { 52564 52565 let edgeLowPt = inPolygon[ p ]; 52566 let edgeHighPt = inPolygon[ q ]; 52567 52568 let edgeDx = edgeHighPt.x - edgeLowPt.x; 52569 let edgeDy = edgeHighPt.y - edgeLowPt.y; 52570 52571 if ( Math.abs( edgeDy ) > Number.EPSILON ) { 52572 52573 // not parallel 52574 if ( edgeDy < 0 ) { 52575 52576 edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx; 52577 edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy; 52578 52579 } 52580 52581 if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue; 52582 52583 if ( inPt.y === edgeLowPt.y ) { 52584 52585 if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ? 52586 // continue; // no intersection or edgeLowPt => doesn't count !!! 52587 52588 } else { 52589 52590 const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y ); 52591 if ( perpEdge === 0 ) return true; // inPt is on contour ? 52592 if ( perpEdge < 0 ) continue; 52593 inside = ! inside; // true intersection left of inPt 52594 52595 } 52596 52597 } else { 52598 52599 // parallel or collinear 52600 if ( inPt.y !== edgeLowPt.y ) continue; // parallel 52601 // edge lies on the same horizontal line as inPt 52602 if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || 52603 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour ! 52604 // continue; 52605 52606 } 52607 52608 } 52609 52610 return inside; 52611 52612 } 52613 52614 const isClockWise = ShapeUtils.isClockWise; 52615 52616 const subPaths = this.subPaths; 52617 if ( subPaths.length === 0 ) return []; 52618 52619 let solid, tmpPath, tmpShape; 52620 const shapes = []; 52621 52622 if ( subPaths.length === 1 ) { 52623 52624 tmpPath = subPaths[ 0 ]; 52625 tmpShape = new Shape(); 52626 tmpShape.curves = tmpPath.curves; 52627 shapes.push( tmpShape ); 52628 return shapes; 52629 52630 } 52631 52632 let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); 52633 holesFirst = isCCW ? ! holesFirst : holesFirst; 52634 52635 // console.log("Holes first", holesFirst); 52636 52637 const betterShapeHoles = []; 52638 const newShapes = []; 52639 let newShapeHoles = []; 52640 let mainIdx = 0; 52641 let tmpPoints; 52642 52643 newShapes[ mainIdx ] = undefined; 52644 newShapeHoles[ mainIdx ] = []; 52645 52646 for ( let i = 0, l = subPaths.length; i < l; i ++ ) { 52647 52648 tmpPath = subPaths[ i ]; 52649 tmpPoints = tmpPath.getPoints(); 52650 solid = isClockWise( tmpPoints ); 52651 solid = isCCW ? ! solid : solid; 52652 52653 if ( solid ) { 52654 52655 if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++; 52656 52657 newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints }; 52658 newShapes[ mainIdx ].s.curves = tmpPath.curves; 52659 52660 if ( holesFirst ) mainIdx ++; 52661 newShapeHoles[ mainIdx ] = []; 52662 52663 //console.log('cw', i); 52664 52665 } else { 52666 52667 newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); 52668 52669 //console.log('ccw', i); 52670 52671 } 52672 52673 } 52674 52675 // only Holes? -> probably all Shapes with wrong orientation 52676 if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths ); 52677 52678 52679 if ( newShapes.length > 1 ) { 52680 52681 let ambiguous = false; 52682 let toChange = 0; 52683 52684 for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { 52685 52686 betterShapeHoles[ sIdx ] = []; 52687 52688 } 52689 52690 for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { 52691 52692 const sho = newShapeHoles[ sIdx ]; 52693 52694 for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) { 52695 52696 const ho = sho[ hIdx ]; 52697 let hole_unassigned = true; 52698 52699 for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) { 52700 52701 if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) { 52702 52703 if ( sIdx !== s2Idx ) toChange ++; 52704 52705 if ( hole_unassigned ) { 52706 52707 hole_unassigned = false; 52708 betterShapeHoles[ s2Idx ].push( ho ); 52709 52710 } else { 52711 52712 ambiguous = true; 52713 52714 } 52715 52716 } 52717 52718 } 52719 52720 if ( hole_unassigned ) { 52721 52722 betterShapeHoles[ sIdx ].push( ho ); 52723 52724 } 52725 52726 } 52727 52728 } 52729 52730 if ( toChange > 0 && ambiguous === false ) { 52731 52732 newShapeHoles = betterShapeHoles; 52733 52734 } 52735 52736 } 52737 52738 let tmpHoles; 52739 52740 for ( let i = 0, il = newShapes.length; i < il; i ++ ) { 52741 52742 tmpShape = newShapes[ i ].s; 52743 shapes.push( tmpShape ); 52744 tmpHoles = newShapeHoles[ i ]; 52745 52746 for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) { 52747 52748 tmpShape.holes.push( tmpHoles[ j ].h ); 52749 52750 } 52751 52752 } 52753 52754 //console.log("shape", shapes); 52755 52756 return shapes; 52757 52758 } 52759 52760} 52761 52762class WebGLMultipleRenderTargets extends WebGLRenderTarget { // @deprecated, r162 52763 52764 constructor( width = 1, height = 1, count = 1, options = {} ) { 52765 52766 console.warn( 'THREE.WebGLMultipleRenderTargets has been deprecated and will be removed in r172. Use THREE.WebGLRenderTarget and set the "count" parameter to enable MRT.' ); 52767 52768 super( width, height, { ...options, count } ); 52769
52770 this.isWebGLMultipleRenderTargets = true; 52771 52772 } 52773 52774 get texture() { 52775 52776 return this.textures; 52777 52778 } 52779 52780} 52781 52782if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { 52783 52784 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: { 52785 revision: REVISION, 52786 } } ) ); 52787 52788} 52789 52790if ( typeof window !== 'undefined' ) { 52791 52792 if ( window.__THREE__ ) { 52793 52794 console.warn( 'WARNING: Multiple instances of Three.js being imported.' ); 52795 52796 } else { 52797 52798 window.__THREE__ = REVISION; 52799 52800 } 52801 52802} 52803 52804export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BackSide, BasicDepthPacking, BasicShadowMap, BatchedMesh, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, ColorManagement, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, ConstantAlphaFactor, ConstantColorFactor, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry, Cylindrical, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DisplayP3ColorSpace, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualCompare, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, FloatType, Fog, FogExp2, FramebufferTexture, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearDisplayP3ColorSpace, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, LinearTransfer, 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, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, Orthogra
52804phicCamera, P3Primaries, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, Path, PerspectiveCamera, Plane, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, 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, RGBFormat, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, Rec709Primaries, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RenderTarget, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingGeometry, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, SRGBTransfer, Scene, ShaderChunk, ShaderLib, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronGeometry, Texture, TextureLoader, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLRenderTarget, WebGLRenderer, WebGLUtils, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, createCanvasElement };
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.