1/** 2 * @license 3 * Copyright 2010-2024 Three.js Authors 4 * SPDX-License-Identifier: MIT 5 */ 6const REVISION = '165'; 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
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 1563function probeAsync( gl, sync, interval ) { 1564 1565 return new Promise( function ( resolve, reject ) { 1566 1567 function probe() { 1568 1569 switch ( gl.clientWaitSync( sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0 ) ) { 1570 1571 case gl.WAIT_FAILED: 1572 reject(); 1573 break; 1574 1575 case gl.TIMEOUT_EXPIRED: 1576 setTimeout( probe, interval ); 1577 break; 1578 1579 default: 1580 resolve(); 1581 1582 } 1583 1584 } 1585 1586 setTimeout( probe, interval ); 1587 1588 } ); 1589 1590} 1591 1592/** 1593 * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping 1594 * or clipping. Based on W3C specifications for sRGB and Display P3, 1595 * and ICC specifications for the D50 connection space. Values in/out 1596 * are _linear_ sRGB and _linear_ Display P3. 1597 * 1598 * Note that both sRGB and Display P3 use the sRGB transfer functions. 1599 * 1600 * Reference: 1601 * - http://www.russellcottrell.com/photo/matrixCalculator.htm 1602 */ 1603 1604const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().set( 1605 0.8224621, 0.177538, 0.0, 1606 0.0331941, 0.9668058, 0.0, 1607 0.0170827, 0.0723974, 0.9105199, 1608); 1609 1610const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().set( 1611 1.2249401, - 0.2249404, 0.0, 1612 - 0.0420569, 1.0420571, 0.0, 1613 - 0.0196376, - 0.0786361, 1.0982735 1614); 1615 1616/** 1617 * Defines supported color spaces by transfer function and primaries, 1618 * and provides conversions to/from the Linear-sRGB reference space. 1619 */ 1620const COLOR_SPACES = { 1621 [ LinearSRGBColorSpace ]: { 1622 transfer: LinearTransfer, 1623 primaries: Rec709Primaries, 1624 toReference: ( color ) => color, 1625 fromReference: ( color ) => color, 1626 }, 1627 [ SRGBColorSpace ]: {
vendor: 8,719 bytes, lines 1628-2067
1628 transfer: SRGBTransfer, 1629 primaries: Rec709Primaries, 1630 toReference: ( color ) => color.convertSRGBToLinear(), 1631 fromReference: ( color ) => color.convertLinearToSRGB(), 1632 }, 1633 [ LinearDisplayP3ColorSpace ]: { 1634 transfer: LinearTransfer, 1635 primaries: P3Primaries, 1636 toReference: ( color ) => color.applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), 1637 fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ), 1638 }, 1639 [ DisplayP3ColorSpace ]: { 1640 transfer: SRGBTransfer, 1641 primaries: P3Primaries, 1642 toReference: ( color ) => color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), 1643 fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(), 1644 }, 1645}; 1646 1647const SUPPORTED_WORKING_COLOR_SPACES = new Set( [ LinearSRGBColorSpace, LinearDisplayP3ColorSpace ] ); 1648 1649const ColorManagement = { 1650 1651 enabled: true, 1652 1653 _workingColorSpace: LinearSRGBColorSpace, 1654 1655 get workingColorSpace() { 1656 1657 return this._workingColorSpace; 1658 1659 }, 1660 1661 set workingColorSpace( colorSpace ) { 1662 1663 if ( ! SUPPORTED_WORKING_COLOR_SPACES.has( colorSpace ) ) { 1664 1665 throw new Error( `Unsupported working color space, "${ colorSpace }".` ); 1666 1667 } 1668 1669 this._workingColorSpace = colorSpace; 1670 1671 }, 1672 1673 convert: function ( color, sourceColorSpace, targetColorSpace ) { 1674 1675 if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { 1676 1677 return color; 1678 1679 } 1680 1681 const sourceToReference = COLOR_SPACES[ sourceColorSpace ].toReference; 1682 const targetFromReference = COLOR_SPACES[ targetColorSpace ].fromReference; 1683 1684 return targetFromReference( sourceToReference( color ) ); 1685 1686 }, 1687 1688 fromWorkingColorSpace: function ( color, targetColorSpace ) { 1689 1690 return this.convert( color, this._workingColorSpace, targetColorSpace ); 1691 1692 }, 1693 1694 toWorkingColorSpace: function ( color, sourceColorSpace ) { 1695 1696 return this.convert( color, sourceColorSpace, this._workingColorSpace ); 1697 1698 }, 1699 1700 getPrimaries: function ( colorSpace ) { 1701 1702 return COLOR_SPACES[ colorSpace ].primaries; 1703 1704 }, 1705 1706 getTransfer: function ( colorSpace ) { 1707 1708 if ( colorSpace === NoColorSpace ) return LinearTransfer; 1709 1710 return COLOR_SPACES[ colorSpace ].transfer; 1711 1712 }, 1713 1714}; 1715 1716 1717function SRGBToLinear( c ) { 1718 1719 return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 ); 1720 1721} 1722 1723function LinearToSRGB( c ) { 1724 1725 return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055; 1726 1727} 1728 1729let _canvas; 1730 1731class ImageUtils { 1732 1733 static getDataURL( image ) { 1734 1735 if ( /^data:/i.test( image.src ) ) { 1736 1737 return image.src; 1738 1739 } 1740 1741 if ( typeof HTMLCanvasElement === 'undefined' ) { 1742 1743 return image.src; 1744 1745 } 1746 1747 let canvas; 1748 1749 if ( image instanceof HTMLCanvasElement ) { 1750 1751 canvas = image; 1752 1753 } else { 1754 1755 if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); 1756 1757 _canvas.width = image.width; 1758 _canvas.height = image.height; 1759 1760 const context = _canvas.getContext( '2d' ); 1761 1762 if ( image instanceof ImageData ) { 1763 1764 context.putImageData( image, 0, 0 ); 1765 1766 } else { 1767 1768 context.drawImage( image, 0, 0, image.width, image.height ); 1769 1770 } 1771 1772 canvas = _canvas; 1773 1774 } 1775 1776 if ( canvas.width > 2048 || canvas.height > 2048 ) { 1777 1778 console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); 1779 1780 return canvas.toDataURL( 'image/jpeg', 0.6 ); 1781 1782 } else { 1783 1784 return canvas.toDataURL( 'image/png' ); 1785 1786 } 1787 1788 } 1789 1790 static sRGBToLinear( image ) { 1791 1792 if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || 1793 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || 1794 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { 1795 1796 const canvas = createElementNS( 'canvas' ); 1797 1798 canvas.width = image.width; 1799 canvas.height = image.height; 1800 1801 const context = canvas.getContext( '2d' ); 1802 context.drawImage( image, 0, 0, image.width, image.height ); 1803 1804 const imageData = context.getImageData( 0, 0, image.width, image.height ); 1805 const data = imageData.data; 1806 1807 for ( let i = 0; i < data.length; i ++ ) { 1808 1809 data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; 1810 1811 } 1812 1813 context.putImageData( imageData, 0, 0 ); 1814 1815 return canvas; 1816 1817 } else if ( image.data ) { 1818 1819 const data = image.data.slice( 0 ); 1820 1821 for ( let i = 0; i < data.length; i ++ ) { 1822 1823 if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { 1824 1825 data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); 1826 1827 } else { 1828 1829 // assuming float 1830 1831 data[ i ] = SRGBToLinear( data[ i ] ); 1832 1833 } 1834 1835 } 1836 1837 return { 1838 data: data, 1839 width: image.width, 1840 height: image.height 1841 }; 1842 1843 } else { 1844 1845 console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); 1846 return image; 1847 1848 } 1849 1850 } 1851 1852} 1853 1854let _sourceId = 0; 1855 1856class Source { 1857 1858 constructor( data = null ) { 1859 1860 this.isSource = true; 1861 1862 Object.defineProperty( this, 'id', { value: _sourceId ++ } ); 1863 1864 this.uuid = generateUUID(); 1865 1866 this.data = data; 1867 this.dataReady = true; 1868 1869 this.version = 0; 1870 1871 } 1872 1873 set needsUpdate( value ) { 1874 1875 if ( value === true ) this.version ++; 1876 1877 } 1878 1879 toJSON( meta ) { 1880 1881 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 1882 1883 if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { 1884 1885 return meta.images[ this.uuid ]; 1886 1887 } 1888 1889 const output = { 1890 uuid: this.uuid, 1891 url: '' 1892 }; 1893 1894 const data = this.data; 1895 1896 if ( data !== null ) { 1897 1898 let url; 1899 1900 if ( Array.isArray( data ) ) { 1901 1902 // cube texture 1903 1904 url = []; 1905 1906 for ( let i = 0, l = data.length; i < l; i ++ ) { 1907 1908 if ( data[ i ].isDataTexture ) { 1909 1910 url.push( serializeImage( data[ i ].image ) ); 1911 1912 } else { 1913 1914 url.push( serializeImage( data[ i ] ) ); 1915 1916 } 1917 1918 } 1919 1920 } else { 1921 1922 // texture 1923 1924 url = serializeImage( data ); 1925 1926 } 1927 1928 output.url = url; 1929 1930 } 1931 1932 if ( ! isRootObject ) { 1933 1934 meta.images[ this.uuid ] = output; 1935 1936 } 1937 1938 return output; 1939 1940 } 1941 1942} 1943 1944function serializeImage( image ) { 1945 1946 if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || 1947 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || 1948 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { 1949 1950 // default images 1951 1952 return ImageUtils.getDataURL( image ); 1953 1954 } else { 1955 1956 if ( image.data ) { 1957 1958 // images of DataTexture 1959 1960 return { 1961 data: Array.from( image.data ), 1962 width: image.width, 1963 height: image.height, 1964 type: image.data.constructor.name 1965 }; 1966 1967 } else { 1968 1969 console.warn( 'THREE.Texture: Unable to serialize Texture.' ); 1970 return {}; 1971 1972 } 1973 1974 } 1975 1976} 1977 1978let _textureId = 0; 1979 1980class Texture extends EventDispatcher { 1981 1982 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 ) { 1983 1984 super(); 1985 1986 this.isTexture = true; 1987 1988 Object.defineProperty( this, 'id', { value: _textureId ++ } ); 1989 1990 this.uuid = generateUUID(); 1991 1992 this.name = ''; 1993 1994 this.source = new Source( image ); 1995 this.mipmaps = []; 1996 1997 this.mapping = mapping; 1998 this.channel = 0; 1999 2000 this.wrapS = wrapS; 2001 this.wrapT = wrapT; 2002 2003 this.magFilter = magFilter; 2004 this.minFilter = minFilter; 2005 2006 this.anisotropy = anisotropy; 2007 2008 this.format = format; 2009 this.internalFormat = null; 2010 this.type = type; 2011 2012 this.offset = new Vector2( 0, 0 ); 2013 this.repeat = new Vector2( 1, 1 ); 2014 this.center = new Vector2( 0, 0 ); 2015 this.rotation = 0; 2016 2017 this.matrixAutoUpdate = true; 2018 this.matrix = new Matrix3(); 2019 2020 this.generateMipmaps = true; 2021 this.premultiplyAlpha = false; 2022 this.flipY = true; 2023 this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) 2024 2025 this.colorSpace = colorSpace; 2026 2027 this.userData = {}; 2028 2029 this.version = 0; 2030 this.onUpdate = null; 2031 2032 this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not 2033 this.pmremVersion = 0; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) 2034 2035 } 2036 2037 get image() { 2038 2039 return this.source.data; 2040 2041 } 2042 2043 set image( value = null ) { 2044 2045 this.source.data = value; 2046 2047 } 2048 2049 updateMatrix() { 2050 2051 this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); 2052 2053 } 2054 2055 clone() { 2056 2057 return new this.constructor().copy( this ); 2058 2059 } 2060 2061 copy( source ) { 2062 2063 this.name = source.name; 2064 2065 this.source = source.source; 2066 this.mipmaps = source.mipmaps.slice( 0 ); 2067
vendor: 3,428 bytes, lines 2068-2268
2068 this.mapping = source.mapping; 2069 this.channel = source.channel; 2070 2071 this.wrapS = source.wrapS; 2072 this.wrapT = source.wrapT; 2073 2074 this.magFilter = source.magFilter; 2075 this.minFilter = source.minFilter; 2076 2077 this.anisotropy = source.anisotropy; 2078 2079 this.format = source.format; 2080 this.internalFormat = source.internalFormat; 2081 this.type = source.type; 2082 2083 this.offset.copy( source.offset ); 2084 this.repeat.copy( source.repeat ); 2085 this.center.copy( source.center ); 2086 this.rotation = source.rotation; 2087 2088 this.matrixAutoUpdate = source.matrixAutoUpdate; 2089 this.matrix.copy( source.matrix ); 2090 2091 this.generateMipmaps = source.generateMipmaps; 2092 this.premultiplyAlpha = source.premultiplyAlpha; 2093 this.flipY = source.flipY; 2094 this.unpackAlignment = source.unpackAlignment; 2095 this.colorSpace = source.colorSpace; 2096 2097 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 2098 2099 this.needsUpdate = true; 2100 2101 return this; 2102 2103 } 2104 2105 toJSON( meta ) { 2106 2107 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 2108 2109 if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { 2110 2111 return meta.textures[ this.uuid ]; 2112 2113 } 2114 2115 const output = { 2116 2117 metadata: { 2118 version: 4.6, 2119 type: 'Texture', 2120 generator: 'Texture.toJSON' 2121 }, 2122 2123 uuid: this.uuid, 2124 name: this.name, 2125 2126 image: this.source.toJSON( meta ).uuid, 2127 2128 mapping: this.mapping, 2129 channel: this.channel, 2130 2131 repeat: [ this.repeat.x, this.repeat.y ], 2132 offset: [ this.offset.x, this.offset.y ], 2133 center: [ this.center.x, this.center.y ], 2134 rotation: this.rotation, 2135 2136 wrap: [ this.wrapS, this.wrapT ], 2137 2138 format: this.format, 2139 internalFormat: this.internalFormat, 2140 type: this.type, 2141 colorSpace: this.colorSpace, 2142 2143 minFilter: this.minFilter, 2144 magFilter: this.magFilter, 2145 anisotropy: this.anisotropy, 2146 2147 flipY: this.flipY, 2148 2149 generateMipmaps: this.generateMipmaps, 2150 premultiplyAlpha: this.premultiplyAlpha, 2151 unpackAlignment: this.unpackAlignment 2152 2153 }; 2154 2155 if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; 2156 2157 if ( ! isRootObject ) { 2158 2159 meta.textures[ this.uuid ] = output; 2160 2161 } 2162 2163 return output; 2164 2165 } 2166 2167 dispose() { 2168 2169 this.dispatchEvent( { type: 'dispose' } ); 2170 2171 } 2172 2173 transformUv( uv ) { 2174 2175 if ( this.mapping !== UVMapping ) return uv; 2176 2177 uv.applyMatrix3( this.matrix ); 2178 2179 if ( uv.x < 0 || uv.x > 1 ) { 2180 2181 switch ( this.wrapS ) { 2182 2183 case RepeatWrapping: 2184 2185 uv.x = uv.x - Math.floor( uv.x ); 2186 break; 2187 2188 case ClampToEdgeWrapping: 2189 2190 uv.x = uv.x < 0 ? 0 : 1; 2191 break; 2192 2193 case MirroredRepeatWrapping: 2194 2195 if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { 2196 2197 uv.x = Math.ceil( uv.x ) - uv.x; 2198 2199 } else { 2200 2201 uv.x = uv.x - Math.floor( uv.x ); 2202 2203 } 2204 2205 break; 2206 2207 } 2208 2209 } 2210 2211 if ( uv.y < 0 || uv.y > 1 ) { 2212 2213 switch ( this.wrapT ) { 2214 2215 case RepeatWrapping: 2216 2217 uv.y = uv.y - Math.floor( uv.y ); 2218 break; 2219 2220 case ClampToEdgeWrapping: 2221 2222 uv.y = uv.y < 0 ? 0 : 1; 2223 break; 2224 2225 case MirroredRepeatWrapping: 2226 2227 if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { 2228 2229 uv.y = Math.ceil( uv.y ) - uv.y; 2230 2231 } else { 2232 2233 uv.y = uv.y - Math.floor( uv.y ); 2234 2235 } 2236 2237 break; 2238 2239 } 2240 2241 } 2242 2243 if ( this.flipY ) { 2244 2245 uv.y = 1 - uv.y; 2246 2247 } 2248 2249 return uv; 2250 2251 } 2252 2253 set needsUpdate( value ) { 2254 2255 if ( value === true ) { 2256 2257 this.version ++; 2258 this.source.needsUpdate = true; 2259 2260 } 2261 2262 } 2263 2264 set needsPMREMUpdate( value ) { 2265 2266 if ( value === true ) { 2267 2268 this.pmremVersion ++
vendor: 10,919 bytes, lines 2268-2953
2268; 2269 2270 } 2271 2272 } 2273 2274} 2275 2276Texture.DEFAULT_IMAGE = null; 2277Texture.DEFAULT_MAPPING = UVMapping; 2278Texture.DEFAULT_ANISOTROPY = 1; 2279 2280class Vector4 { 2281 2282 constructor( x = 0, y = 0, z = 0, w = 1 ) { 2283 2284 Vector4.prototype.isVector4 = true; 2285 2286 this.x = x; 2287 this.y = y; 2288 this.z = z; 2289 this.w = w; 2290 2291 } 2292 2293 get width() { 2294 2295 return this.z; 2296 2297 } 2298 2299 set width( value ) { 2300 2301 this.z = value; 2302 2303 } 2304 2305 get height() { 2306 2307 return this.w; 2308 2309 } 2310 2311 set height( value ) { 2312 2313 this.w = value; 2314 2315 } 2316 2317 set( x, y, z, w ) { 2318 2319 this.x = x; 2320 this.y = y; 2321 this.z = z; 2322 this.w = w; 2323 2324 return this; 2325 2326 } 2327 2328 setScalar( scalar ) { 2329 2330 this.x = scalar; 2331 this.y = scalar; 2332 this.z = scalar; 2333 this.w = scalar; 2334 2335 return this; 2336 2337 } 2338 2339 setX( x ) { 2340 2341 this.x = x; 2342 2343 return this; 2344 2345 } 2346 2347 setY( y ) { 2348 2349 this.y = y; 2350 2351 return this; 2352 2353 } 2354 2355 setZ( z ) { 2356 2357 this.z = z; 2358 2359 return this; 2360 2361 } 2362 2363 setW( w ) { 2364 2365 this.w = w; 2366 2367 return this; 2368 2369 } 2370 2371 setComponent( index, value ) { 2372 2373 switch ( index ) { 2374 2375 case 0: this.x = value; break; 2376 case 1: this.y = value; break; 2377 case 2: this.z = value; break; 2378 case 3: this.w = value; break; 2379 default: throw new Error( 'index is out of range: ' + index ); 2380 2381 } 2382 2383 return this; 2384 2385 } 2386 2387 getComponent( index ) { 2388 2389 switch ( index ) { 2390 2391 case 0: return this.x; 2392 case 1: return this.y; 2393 case 2: return this.z; 2394 case 3: return this.w; 2395 default: throw new Error( 'index is out of range: ' + index ); 2396 2397 } 2398 2399 } 2400 2401 clone() { 2402 2403 return new this.constructor( this.x, this.y, this.z, this.w ); 2404 2405 } 2406 2407 copy( v ) { 2408 2409 this.x = v.x; 2410 this.y = v.y; 2411 this.z = v.z; 2412 this.w = ( v.w !== undefined ) ? v.w : 1; 2413 2414 return this; 2415 2416 } 2417 2418 add( v ) { 2419 2420 this.x += v.x; 2421 this.y += v.y; 2422 this.z += v.z; 2423 this.w += v.w; 2424 2425 return this; 2426 2427 } 2428 2429 addScalar( s ) { 2430 2431 this.x += s; 2432 this.y += s; 2433 this.z += s; 2434 this.w += s; 2435 2436 return this; 2437 2438 } 2439 2440 addVectors( a, b ) { 2441 2442 this.x = a.x + b.x; 2443 this.y = a.y + b.y; 2444 this.z = a.z + b.z; 2445 this.w = a.w + b.w; 2446 2447 return this; 2448 2449 } 2450 2451 addScaledVector( v, s ) { 2452 2453 this.x += v.x * s; 2454 this.y += v.y * s; 2455 this.z += v.z * s; 2456 this.w += v.w * s; 2457 2458 return this; 2459 2460 } 2461 2462 sub( v ) { 2463 2464 this.x -= v.x; 2465 this.y -= v.y; 2466 this.z -= v.z; 2467 this.w -= v.w; 2468 2469 return this; 2470 2471 } 2472 2473 subScalar( s ) { 2474 2475 this.x -= s; 2476 this.y -= s; 2477 this.z -= s; 2478 this.w -= s; 2479 2480 return this; 2481 2482 } 2483 2484 subVectors( a, b ) { 2485 2486 this.x = a.x - b.x; 2487 this.y = a.y - b.y; 2488 this.z = a.z - b.z; 2489 this.w = a.w - b.w; 2490 2491 return this; 2492 2493 } 2494 2495 multiply( v ) { 2496 2497 this.x *= v.x; 2498 this.y *= v.y; 2499 this.z *= v.z; 2500 this.w *= v.w; 2501 2502 return this; 2503 2504 } 2505 2506 multiplyScalar( scalar ) { 2507 2508 this.x *= scalar; 2509 this.y *= scalar; 2510 this.z *= scalar; 2511 this.w *= scalar; 2512 2513 return this; 2514 2515 } 2516 2517 applyMatrix4( m ) { 2518 2519 const x = this.x, y = this.y, z = this.z, w = this.w; 2520 const e = m.elements; 2521 2522 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; 2523 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; 2524 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; 2525 this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; 2526 2527 return this; 2528 2529 } 2530 2531 divideScalar( scalar ) { 2532 2533 return this.multiplyScalar( 1 / scalar ); 2534 2535 } 2536 2537 setAxisAngleFromQuaternion( q ) { 2538 2539 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm 2540 2541 // q is assumed to be normalized 2542 2543 this.w = 2 * Math.acos( q.w ); 2544 2545 const s = Math.sqrt( 1 - q.w * q.w ); 2546 2547 if ( s < 0.0001 ) { 2548 2549 this.x = 1; 2550 this.y = 0; 2551 this.z = 0; 2552 2553 } else { 2554 2555 this.x = q.x / s; 2556 this.y = q.y / s; 2557 this.z = q.z / s; 2558 2559 } 2560 2561 return this; 2562 2563 } 2564 2565 setAxisAngleFromRotationMatrix( m ) { 2566 2567 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm 2568 2569 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 2570 2571 let angle, x, y, z; // variables for result 2572 const epsilon = 0.01, // margin to allow for rounding errors 2573 epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees 2574 2575 te = m.elements, 2576 2577 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], 2578 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], 2579 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; 2580 2581 if ( ( Math.abs( m12 - m21 ) < epsilon ) && 2582 ( Math.abs( m13 - m31 ) < epsilon ) && 2583 ( Math.abs( m23 - m32 ) < epsilon ) ) { 2584 2585 // singularity found 2586 // first check for identity matrix which must have +1 for all terms 2587 // in leading diagonal and zero in other terms 2588 2589 if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && 2590 ( Math.abs( m13 + m31 ) < epsilon2 ) && 2591 ( Math.abs( m23 + m32 ) < epsilon2 ) && 2592 ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { 2593 2594 // this singularity is identity matrix so angle = 0 2595 2596 this.set( 1, 0, 0, 0 ); 2597 2598 return this; // zero angle, arbitrary axis 2599 2600 } 2601 2602 // otherwise this singularity is angle = 180 2603 2604 angle = Math.PI; 2605 2606 const xx = ( m11 + 1 ) / 2; 2607 const yy = ( m22 + 1 ) / 2; 2608 const zz = ( m33 + 1 ) / 2; 2609 const xy = ( m12 + m21 ) / 4; 2610 const xz = ( m13 + m31 ) / 4; 2611 const yz = ( m23 + m32 ) / 4; 2612 2613 if ( ( xx > yy ) && ( xx > zz ) ) { 2614 2615 // m11 is the largest diagonal term 2616 2617 if ( xx < epsilon ) { 2618 2619 x = 0; 2620 y = 0.707106781; 2621 z = 0.707106781; 2622 2623 } else { 2624 2625 x = Math.sqrt( xx ); 2626 y = xy / x; 2627 z = xz / x; 2628 2629 } 2630 2631 } else if ( yy > zz ) { 2632 2633 // m22 is the largest diagonal term 2634 2635 if ( yy < epsilon ) { 2636 2637 x = 0.707106781; 2638 y = 0; 2639 z = 0.707106781; 2640 2641 } else { 2642 2643 y = Math.sqrt( yy ); 2644 x = xy / y; 2645 z = yz / y; 2646 2647 } 2648 2649 } else { 2650 2651 // m33 is the largest diagonal term so base result on this 2652 2653 if ( zz < epsilon ) { 2654 2655 x = 0.707106781; 2656 y = 0.707106781; 2657 z = 0; 2658 2659 } else { 2660 2661 z = Math.sqrt( zz ); 2662 x = xz / z; 2663 y = yz / z; 2664 2665 } 2666 2667 } 2668 2669 this.set( x, y, z, angle ); 2670 2671 return this; // return 180 deg rotation 2672 2673 } 2674 2675 // as we have reached here there are no singularities so we can handle normally 2676 2677 let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + 2678 ( m13 - m31 ) * ( m13 - m31 ) + 2679 ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize 2680 2681 if ( Math.abs( s ) < 0.001 ) s = 1; 2682 2683 // prevent divide by zero, should not happen if matrix is orthogonal and should be 2684 // caught by singularity test above, but I've left it in just in case 2685 2686 this.x = ( m32 - m23 ) / s; 2687 this.y = ( m13 - m31 ) / s; 2688 this.z = ( m21 - m12 ) / s; 2689 this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); 2690 2691 return this; 2692 2693 } 2694 2695 min( v ) { 2696 2697 this.x = Math.min( this.x, v.x ); 2698 this.y = Math.min( this.y, v.y ); 2699 this.z = Math.min( this.z, v.z ); 2700 this.w = Math.min( this.w, v.w ); 2701 2702 return this; 2703 2704 } 2705 2706 max( v ) { 2707 2708 this.x = Math.max( this.x, v.x ); 2709 this.y = Math.max( this.y, v.y ); 2710 this.z = Math.max( this.z, v.z ); 2711 this.w = Math.max( this.w, v.w ); 2712 2713 return this; 2714 2715 } 2716 2717 clamp( min, max ) { 2718 2719 // assumes min < max, componentwise 2720 2721 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 2722 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 2723 this.z = Math.max( min.z, Math.min( max.z, this.z ) ); 2724 this.w = Math.max( min.w, Math.min( max.w, this.w ) ); 2725 2726 return this; 2727 2728 } 2729 2730 clampScalar( minVal, maxVal ) { 2731 2732 this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); 2733 this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); 2734 this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); 2735 this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); 2736 2737 return this; 2738 2739 } 2740 2741 clampLength( min, max ) { 2742 2743 const length = this.length(); 2744 2745 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 2746 2747 } 2748 2749 floor() { 2750 2751 this.x = Math.floor( this.x ); 2752 this.y = Math.floor( this.y ); 2753 this.z = Math.floor( this.z ); 2754 this.w = Math.floor( this.w ); 2755 2756 return this; 2757 2758 } 2759 2760 ceil() { 2761 2762 this.x = Math.ceil( this.x ); 2763 this.y = Math.ceil( this.y ); 2764 this.z = Math.ceil( this.z ); 2765 this.w = Math.ceil( this.w ); 2766 2767 return this; 2768 2769 } 2770 2771 round() { 2772 2773 this.x = Math.round( this.x ); 2774 this.y = Math.round( this.y ); 2775 this.z = Math.round( this.z ); 2776 this.w = Math.round( this.w ); 2777 2778 return this; 2779 2780 } 2781 2782 roundToZero() { 2783 2784 this.x = Math.trunc( this.x ); 2785 this.y = Math.trunc( this.y ); 2786 this.z = Math.trunc( this.z ); 2787 this.w = Math.trunc( this.w ); 2788 2789 return this; 2790 2791 } 2792 2793 negate() { 2794 2795 this.x = - this.x; 2796 this.y = - this.y; 2797 this.z = - this.z; 2798 this.w = - this.w; 2799 2800 return this; 2801 2802 } 2803 2804 dot( v ) { 2805 2806 return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; 2807 2808 } 2809 2810 lengthSq() { 2811 2812 return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; 2813 2814 } 2815 2816 length() { 2817 2818 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); 2819 2820 } 2821 2822 manhattanLength() { 2823 2824 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); 2825 2826 } 2827 2828 normalize() { 2829 2830 return this.divideScalar( this.length() || 1 ); 2831 2832 } 2833 2834 setLength( length ) { 2835 2836 return this.normalize().multiplyScalar( length ); 2837 2838 } 2839 2840 lerp( v, alpha ) { 2841 2842 this.x += ( v.x - this.x ) * alpha; 2843 this.y += ( v.y - this.y ) * alpha; 2844 this.z += ( v.z - this.z ) * alpha; 2845 this.w += ( v.w - this.w ) * alpha; 2846 2847 return this; 2848 2849 } 2850 2851 lerpVectors( v1, v2, alpha ) { 2852 2853 this.x = v1.x + ( v2.x - v1.x ) * alpha; 2854 this.y = v1.y + ( v2.y - v1.y ) * alpha; 2855 this.z = v1.z + ( v2.z - v1.z ) * alpha; 2856 this.w = v1.w + ( v2.w - v1.w ) * alpha; 2857 2858 return this; 2859 2860 } 2861 2862 equals( v ) { 2863 2864 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); 2865 2866 } 2867 2868 fromArray( array, offset = 0 ) { 2869 2870 this.x = array[ offset ]; 2871 this.y = array[ offset + 1 ]; 2872 this.z = array[ offset + 2 ]; 2873 this.w = array[ offset + 3 ]; 2874 2875 return this; 2876 2877 } 2878 2879 toArray( array = [], offset = 0 ) { 2880 2881 array[ offset ] = this.x; 2882 array[ offset + 1 ] = this.y; 2883 array[ offset + 2 ] = this.z; 2884 array[ offset + 3 ] = this.w; 2885 2886 return array; 2887 2888 } 2889 2890 fromBufferAttribute( attribute, index ) { 2891 2892 this.x = attribute.getX( index ); 2893 this.y = attribute.getY( index ); 2894 this.z = attribute.getZ( index ); 2895 this.w = attribute.getW( index ); 2896 2897 return this; 2898 2899 } 2900 2901 random() { 2902 2903 this.x = Math.random(); 2904 this.y = Math.random(); 2905 this.z = Math.random(); 2906 this.w = Math.random(); 2907 2908 return this; 2909 2910 } 2911 2912 *[ Symbol.iterator ]() { 2913 2914 yield this.x; 2915 yield this.y; 2916 yield this.z; 2917 yield this.w; 2918 2919 } 2920 2921} 2922 2923/* 2924 In options, we can specify: 2925 * Texture parameters for an auto-generated target texture 2926 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers 2927*/ 2928class RenderTarget extends EventDispatcher { 2929 2930 constructor( width = 1, height = 1, options = {} ) { 2931 2932 super(); 2933 2934 this.isRenderTarget = true; 2935 2936 this.width = width; 2937 this.height = height; 2938 this.depth = 1; 2939 2940 this.scissor = new Vector4( 0, 0, width, height ); 2941 this.scissorTest = false; 2942 2943 this.viewport = new Vector4( 0, 0, width, height ); 2944 2945 const image = { width: width, height: height, depth: 1 }; 2946 2947 options = Object.assign( { 2948 generateMipmaps: false, 2949 internalFormat: null, 2950 minFilter: LinearFilter, 2951 depthBuffer: true, 2952 stencilBuffer: false, 2953
vendor: 25,148 bytes, lines 2953-4406
2953resolveDepthBuffer: true, 2954 resolveStencilBuffer: true, 2955 depthTexture: null, 2956 samples: 0, 2957 count: 1 2958 }, options ); 2959 2960 const texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); 2961 2962 texture.flipY = false; 2963 texture.generateMipmaps = options.generateMipmaps; 2964 texture.internalFormat = options.internalFormat; 2965 2966 this.textures = []; 2967 2968 const count = options.count; 2969 for ( let i = 0; i < count; i ++ ) { 2970 2971 this.textures[ i ] = texture.clone(); 2972 this.textures[ i ].isRenderTargetTexture = true; 2973 2974 } 2975 2976 this.depthBuffer = options.depthBuffer; 2977 this.stencilBuffer = options.stencilBuffer; 2978 2979 this.resolveDepthBuffer = options.resolveDepthBuffer; 2980 this.resolveStencilBuffer = options.resolveStencilBuffer; 2981 2982 this.depthTexture = options.depthTexture; 2983 2984 this.samples = options.samples; 2985 2986 } 2987 2988 get texture() { 2989 2990 return this.textures[ 0 ]; 2991 2992 } 2993 2994 set texture( value ) { 2995 2996 this.textures[ 0 ] = value; 2997 2998 } 2999 3000 setSize( width, height, depth = 1 ) { 3001 3002 if ( this.width !== width || this.height !== height || this.depth !== depth ) { 3003 3004 this.width = width; 3005 this.height = height; 3006 this.depth = depth; 3007 3008 for ( let i = 0, il = this.textures.length; i < il; i ++ ) { 3009 3010 this.textures[ i ].image.width = width; 3011 this.textures[ i ].image.height = height; 3012 this.textures[ i ].image.depth = depth; 3013 3014 } 3015 3016 this.dispose(); 3017 3018 } 3019 3020 this.viewport.set( 0, 0, width, height ); 3021 this.scissor.set( 0, 0, width, height ); 3022 3023 } 3024 3025 clone() { 3026 3027 return new this.constructor().copy( this ); 3028 3029 } 3030 3031 copy( source ) { 3032 3033 this.width = source.width; 3034 this.height = source.height; 3035 this.depth = source.depth; 3036 3037 this.scissor.copy( source.scissor ); 3038 this.scissorTest = source.scissorTest; 3039 3040 this.viewport.copy( source.viewport ); 3041 3042 this.textures.length = 0; 3043 3044 for ( let i = 0, il = source.textures.length; i < il; i ++ ) { 3045 3046 this.textures[ i ] = source.textures[ i ].clone(); 3047 this.textures[ i ].isRenderTargetTexture = true; 3048 3049 } 3050 3051 // ensure image object is not shared, see #20328 3052 3053 const image = Object.assign( {}, source.texture.image ); 3054 this.texture.source = new Source( image ); 3055 3056 this.depthBuffer = source.depthBuffer; 3057 this.stencilBuffer = source.stencilBuffer; 3058 3059 this.resolveDepthBuffer = source.resolveDepthBuffer; 3060 this.resolveStencilBuffer = source.resolveStencilBuffer; 3061 3062 if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); 3063 3064 this.samples = source.samples; 3065 3066 return this; 3067 3068 } 3069 3070 dispose() { 3071 3072 this.dispatchEvent( { type: 'dispose' } ); 3073 3074 } 3075 3076} 3077 3078class WebGLRenderTarget extends RenderTarget { 3079 3080 constructor( width = 1, height = 1, options = {} ) { 3081 3082 super( width, height, options ); 3083 3084 this.isWebGLRenderTarget = true; 3085 3086 } 3087 3088} 3089 3090class DataArrayTexture extends Texture { 3091 3092 constructor( data = null, width = 1, height = 1, depth = 1 ) { 3093 3094 super( null ); 3095 3096 this.isDataArrayTexture = true; 3097 3098 this.image = { data, width, height, depth }; 3099 3100 this.magFilter = NearestFilter; 3101 this.minFilter = NearestFilter; 3102 3103 this.wrapR = ClampToEdgeWrapping; 3104 3105 this.generateMipmaps = false; 3106 this.flipY = false; 3107 this.unpackAlignment = 1; 3108 3109 this.layerUpdates = new Set(); 3110 3111 } 3112 3113 addLayerUpdate( layerIndex ) { 3114 3115 this.layerUpdates.add( layerIndex ); 3116 3117 } 3118 3119 clearLayerUpdates() { 3120 3121 this.layerUpdates.clear(); 3122 3123 } 3124 3125} 3126 3127class WebGLArrayRenderTarget extends WebGLRenderTarget { 3128 3129 constructor( width = 1, height = 1, depth = 1, options = {} ) { 3130 3131 super( width, height, options ); 3132 3133 this.isWebGLArrayRenderTarget = true; 3134 3135 this.depth = depth; 3136 3137 this.texture = new DataArrayTexture( null, width, height, depth ); 3138 3139 this.texture.isRenderTargetTexture = true; 3140 3141 } 3142 3143} 3144 3145class Data3DTexture extends Texture { 3146 3147 constructor( data = null, width = 1, height = 1, depth = 1 ) { 3148 3149 // We're going to add .setXXX() methods for setting properties later. 3150 // Users can still set in DataTexture3D directly. 3151 // 3152 // const texture = new THREE.DataTexture3D( data, width, height, depth ); 3153 // texture.anisotropy = 16; 3154 // 3155 // See #14839 3156 3157 super( null ); 3158 3159 this.isData3DTexture = true; 3160 3161 this.image = { data, width, height, depth }; 3162 3163 this.magFilter = NearestFilter; 3164 this.minFilter = NearestFilter; 3165 3166 this.wrapR = ClampToEdgeWrapping; 3167 3168 this.generateMipmaps = false; 3169 this.flipY = false; 3170 this.unpackAlignment = 1; 3171 3172 } 3173 3174} 3175 3176class WebGL3DRenderTarget extends WebGLRenderTarget { 3177 3178 constructor( width = 1, height = 1, depth = 1, options = {} ) { 3179 3180 super( width, height, options ); 3181 3182 this.isWebGL3DRenderTarget = true; 3183 3184 this.depth = depth; 3185 3186 this.texture = new Data3DTexture( null, width, height, depth ); 3187 3188 this.texture.isRenderTargetTexture = true; 3189 3190 } 3191 3192} 3193 3194class Quaternion { 3195 3196 constructor( x = 0, y = 0, z = 0, w = 1 ) { 3197 3198 this.isQuaternion = true; 3199 3200 this._x = x; 3201 this._y = y; 3202 this._z = z; 3203 this._w = w; 3204 3205 } 3206 3207 static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { 3208 3209 // fuzz-free, array-based Quaternion SLERP operation 3210 3211 let x0 = src0[ srcOffset0 + 0 ], 3212 y0 = src0[ srcOffset0 + 1 ], 3213 z0 = src0[ srcOffset0 + 2 ], 3214 w0 = src0[ srcOffset0 + 3 ]; 3215 3216 const x1 = src1[ srcOffset1 + 0 ], 3217 y1 = src1[ srcOffset1 + 1 ], 3218 z1 = src1[ srcOffset1 + 2 ], 3219 w1 = src1[ srcOffset1 + 3 ]; 3220 3221 if ( t === 0 ) { 3222 3223 dst[ dstOffset + 0 ] = x0; 3224 dst[ dstOffset + 1 ] = y0; 3225 dst[ dstOffset + 2 ] = z0; 3226 dst[ dstOffset + 3 ] = w0; 3227 return; 3228 3229 } 3230 3231 if ( t === 1 ) { 3232 3233 dst[ dstOffset + 0 ] = x1; 3234 dst[ dstOffset + 1 ] = y1; 3235 dst[ dstOffset + 2 ] = z1; 3236 dst[ dstOffset + 3 ] = w1; 3237 return; 3238 3239 } 3240 3241 if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { 3242 3243 let s = 1 - t; 3244 const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, 3245 dir = ( cos >= 0 ? 1 : - 1 ), 3246 sqrSin = 1 - cos * cos; 3247 3248 // Skip the Slerp for tiny steps to avoid numeric problems: 3249 if ( sqrSin > Number.EPSILON ) { 3250 3251 const sin = Math.sqrt( sqrSin ), 3252 len = Math.atan2( sin, cos * dir ); 3253 3254 s = Math.sin( s * len ) / sin; 3255 t = Math.sin( t * len ) / sin; 3256 3257 } 3258 3259 const tDir = t * dir; 3260 3261 x0 = x0 * s + x1 * tDir; 3262 y0 = y0 * s + y1 * tDir; 3263 z0 = z0 * s + z1 * tDir; 3264 w0 = w0 * s + w1 * tDir; 3265 3266 // Normalize in case we just did a lerp: 3267 if ( s === 1 - t ) { 3268 3269 const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); 3270 3271 x0 *= f; 3272 y0 *= f; 3273 z0 *= f; 3274 w0 *= f; 3275 3276 } 3277 3278 } 3279 3280 dst[ dstOffset ] = x0; 3281 dst[ dstOffset + 1 ] = y0; 3282 dst[ dstOffset + 2 ] = z0; 3283 dst[ dstOffset + 3 ] = w0; 3284 3285 } 3286 3287 static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { 3288 3289 const x0 = src0[ srcOffset0 ]; 3290 const y0 = src0[ srcOffset0 + 1 ]; 3291 const z0 = src0[ srcOffset0 + 2 ]; 3292 const w0 = src0[ srcOffset0 + 3 ]; 3293 3294 const x1 = src1[ srcOffset1 ]; 3295 const y1 = src1[ srcOffset1 + 1 ]; 3296 const z1 = src1[ srcOffset1 + 2 ]; 3297 const w1 = src1[ srcOffset1 + 3 ]; 3298 3299 dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; 3300 dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; 3301 dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; 3302 dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; 3303 3304 return dst; 3305 3306 } 3307 3308 get x() { 3309 3310 return this._x; 3311 3312 } 3313 3314 set x( value ) { 3315 3316 this._x = value; 3317 this._onChangeCallback(); 3318 3319 } 3320 3321 get y() { 3322 3323 return this._y; 3324 3325 } 3326 3327 set y( value ) { 3328 3329 this._y = value; 3330 this._onChangeCallback(); 3331 3332 } 3333 3334 get z() { 3335 3336 return this._z; 3337 3338 } 3339 3340 set z( value ) { 3341 3342 this._z = value; 3343 this._onChangeCallback(); 3344 3345 } 3346 3347 get w() { 3348 3349 return this._w; 3350 3351 } 3352 3353 set w( value ) { 3354 3355 this._w = value; 3356 this._onChangeCallback(); 3357 3358 } 3359 3360 set( x, y, z, w ) { 3361 3362 this._x = x; 3363 this._y = y; 3364 this._z = z; 3365 this._w = w; 3366 3367 this._onChangeCallback(); 3368 3369 return this; 3370 3371 } 3372 3373 clone() { 3374 3375 return new this.constructor( this._x, this._y, this._z, this._w ); 3376 3377 } 3378 3379 copy( quaternion ) { 3380 3381 this._x = quaternion.x; 3382 this._y = quaternion.y; 3383 this._z = quaternion.z; 3384 this._w = quaternion.w; 3385 3386 this._onChangeCallback(); 3387 3388 return this; 3389 3390 } 3391 3392 setFromEuler( euler, update = true ) { 3393 3394 const x = euler._x, y = euler._y, z = euler._z, order = euler._order; 3395 3396 // http://www.mathworks.com/matlabcentral/fileexchange/ 3397 // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ 3398 // content/SpinCalc.m 3399 3400 const cos = Math.cos; 3401 const sin = Math.sin; 3402 3403 const c1 = cos( x / 2 ); 3404 const c2 = cos( y / 2 ); 3405 const c3 = cos( z / 2 ); 3406 3407 const s1 = sin( x / 2 ); 3408 const s2 = sin( y / 2 ); 3409 const s3 = sin( z / 2 ); 3410 3411 switch ( order ) { 3412 3413 case 'XYZ': 3414 this._x = s1 * c2 * c3 + c1 * s2 * s3; 3415 this._y = c1 * s2 * c3 - s1 * c2 * s3; 3416 this._z = c1 * c2 * s3 + s1 * s2 * c3; 3417 this._w = c1 * c2 * c3 - s1 * s2 * s3; 3418 break; 3419 3420 case 'YXZ': 3421 this._x = s1 * c2 * c3 + c1 * s2 * s3; 3422 this._y = c1 * s2 * c3 - s1 * c2 * s3; 3423 this._z = c1 * c2 * s3 - s1 * s2 * c3; 3424 this._w = c1 * c2 * c3 + s1 * s2 * s3; 3425 break; 3426 3427 case 'ZXY': 3428 this._x = s1 * c2 * c3 - c1 * s2 * s3; 3429 this._y = c1 * s2 * c3 + s1 * c2 * s3; 3430 this._z = c1 * c2 * s3 + s1 * s2 * c3; 3431 this._w = c1 * c2 * c3 - s1 * s2 * s3; 3432 break; 3433 3434 case 'ZYX': 3435 this._x = s1 * c2 * c3 - c1 * s2 * s3; 3436 this._y = c1 * s2 * c3 + s1 * c2 * s3; 3437 this._z = c1 * c2 * s3 - s1 * s2 * c3; 3438 this._w = c1 * c2 * c3 + s1 * s2 * s3; 3439 break; 3440 3441 case 'YZX': 3442 this._x = s1 * c2 * c3 + c1 * s2 * s3; 3443 this._y = c1 * s2 * c3 + s1 * c2 * s3; 3444 this._z = c1 * c2 * s3 - s1 * s2 * c3; 3445 this._w = c1 * c2 * c3 - s1 * s2 * s3; 3446 break; 3447 3448 case 'XZY': 3449 this._x = s1 * c2 * c3 - c1 * s2 * s3; 3450 this._y = c1 * s2 * c3 - s1 * c2 * s3; 3451 this._z = c1 * c2 * s3 + s1 * s2 * c3; 3452 this._w = c1 * c2 * c3 + s1 * s2 * s3; 3453 break; 3454 3455 default: 3456 console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); 3457 3458 } 3459 3460 if ( update === true ) this._onChangeCallback(); 3461 3462 return this; 3463 3464 } 3465 3466 setFromAxisAngle( axis, angle ) { 3467 3468 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm 3469 3470 // assumes axis is normalized 3471 3472 const halfAngle = angle / 2, s = Math.sin( halfAngle ); 3473 3474 this._x = axis.x * s; 3475 this._y = axis.y * s; 3476 this._z = axis.z * s; 3477 this._w = Math.cos( halfAngle ); 3478 3479 this._onChangeCallback(); 3480 3481 return this; 3482 3483 } 3484 3485 setFromRotationMatrix( m ) { 3486 3487 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm 3488 3489 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 3490 3491 const te = m.elements, 3492 3493 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], 3494 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], 3495 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], 3496 3497 trace = m11 + m22 + m33; 3498 3499 if ( trace > 0 ) { 3500 3501 const s = 0.5 / Math.sqrt( trace + 1.0 ); 3502 3503 this._w = 0.25 / s; 3504 this._x = ( m32 - m23 ) * s; 3505 this._y = ( m13 - m31 ) * s; 3506 this._z = ( m21 - m12 ) * s; 3507 3508 } else if ( m11 > m22 && m11 > m33 ) { 3509 3510 const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); 3511 3512 this._w = ( m32 - m23 ) / s; 3513 this._x = 0.25 * s; 3514 this._y = ( m12 + m21 ) / s; 3515 this._z = ( m13 + m31 ) / s; 3516 3517 } else if ( m22 > m33 ) { 3518 3519 const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); 3520 3521 this._w = ( m13 - m31 ) / s; 3522 this._x = ( m12 + m21 ) / s; 3523 this._y = 0.25 * s; 3524 this._z = ( m23 + m32 ) / s; 3525 3526 } else { 3527 3528 const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); 3529 3530 this._w = ( m21 - m12 ) / s; 3531 this._x = ( m13 + m31 ) / s; 3532 this._y = ( m23 + m32 ) / s; 3533 this._z = 0.25 * s; 3534 3535 } 3536 3537 this._onChangeCallback(); 3538 3539 return this; 3540 3541 } 3542 3543 setFromUnitVectors( vFrom, vTo ) { 3544 3545 // assumes direction vectors vFrom and vTo are normalized 3546 3547 let r = vFrom.dot( vTo ) + 1; 3548 3549 if ( r < Number.EPSILON ) { 3550 3551 // vFrom and vTo point in opposite directions 3552 3553 r = 0; 3554 3555 if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { 3556 3557 this._x = - vFrom.y; 3558 this._y = vFrom.x; 3559 this._z = 0; 3560 this._w = r; 3561 3562 } else { 3563 3564 this._x = 0; 3565 this._y = - vFrom.z; 3566 this._z = vFrom.y; 3567 this._w = r; 3568 3569 } 3570 3571 } else { 3572 3573 // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 3574 3575 this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; 3576 this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; 3577 this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; 3578 this._w = r; 3579 3580 } 3581 3582 return this.normalize(); 3583 3584 } 3585 3586 angleTo( q ) { 3587 3588 return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); 3589 3590 } 3591 3592 rotateTowards( q, step ) { 3593 3594 const angle = this.angleTo( q ); 3595 3596 if ( angle === 0 ) return this; 3597 3598 const t = Math.min( 1, step / angle ); 3599 3600 this.slerp( q, t ); 3601 3602 return this; 3603 3604 } 3605 3606 identity() { 3607 3608 return this.set( 0, 0, 0, 1 ); 3609 3610 } 3611 3612 invert() { 3613 3614 // quaternion is assumed to have unit length 3615 3616 return this.conjugate(); 3617 3618 } 3619 3620 conjugate() { 3621 3622 this._x *= - 1; 3623 this._y *= - 1; 3624 this._z *= - 1; 3625 3626 this._onChangeCallback(); 3627 3628 return this; 3629 3630 } 3631 3632 dot( v ) { 3633 3634 return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; 3635 3636 } 3637 3638 lengthSq() { 3639 3640 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; 3641 3642 } 3643 3644 length() { 3645 3646 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); 3647 3648 } 3649 3650 normalize() { 3651 3652 let l = this.length(); 3653 3654 if ( l === 0 ) { 3655 3656 this._x = 0; 3657 this._y = 0; 3658 this._z = 0; 3659 this._w = 1; 3660 3661 } else { 3662 3663 l = 1 / l; 3664 3665 this._x = this._x * l; 3666 this._y = this._y * l; 3667 this._z = this._z * l; 3668 this._w = this._w * l; 3669 3670 } 3671 3672 this._onChangeCallback(); 3673 3674 return this; 3675 3676 } 3677 3678 multiply( q ) { 3679 3680 return this.multiplyQuaternions( this, q ); 3681 3682 } 3683 3684 premultiply( q ) { 3685 3686 return this.multiplyQuaternions( q, this ); 3687 3688 } 3689 3690 multiplyQuaternions( a, b ) { 3691 3692 // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm 3693 3694 const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; 3695 const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; 3696 3697 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; 3698 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; 3699 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; 3700 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; 3701 3702 this._onChangeCallback(); 3703 3704 return this; 3705 3706 } 3707 3708 slerp( qb, t ) { 3709 3710 if ( t === 0 ) return this; 3711 if ( t === 1 ) return this.copy( qb ); 3712 3713 const x = this._x, y = this._y, z = this._z, w = this._w; 3714 3715 // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ 3716 3717 let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; 3718 3719 if ( cosHalfTheta < 0 ) { 3720 3721 this._w = - qb._w; 3722 this._x = - qb._x; 3723 this._y = - qb._y; 3724 this._z = - qb._z; 3725 3726 cosHalfTheta = - cosHalfTheta; 3727 3728 } else { 3729 3730 this.copy( qb ); 3731 3732 } 3733 3734 if ( cosHalfTheta >= 1.0 ) { 3735 3736 this._w = w; 3737 this._x = x; 3738 this._y = y; 3739 this._z = z; 3740 3741 return this; 3742 3743 } 3744 3745 const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; 3746 3747 if ( sqrSinHalfTheta <= Number.EPSILON ) { 3748 3749 const s = 1 - t; 3750 this._w = s * w + t * this._w; 3751 this._x = s * x + t * this._x; 3752 this._y = s * y + t * this._y; 3753 this._z = s * z + t * this._z; 3754 3755 this.normalize(); // normalize calls _onChangeCallback() 3756 3757 return this; 3758 3759 } 3760 3761 const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); 3762 const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); 3763 const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, 3764 ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; 3765 3766 this._w = ( w * ratioA + this._w * ratioB ); 3767 this._x = ( x * ratioA + this._x * ratioB ); 3768 this._y = ( y * ratioA + this._y * ratioB ); 3769 this._z = ( z * ratioA + this._z * ratioB ); 3770 3771 this._onChangeCallback(); 3772 3773 return this; 3774 3775 } 3776 3777 slerpQuaternions( qa, qb, t ) { 3778 3779 return this.copy( qa ).slerp( qb, t ); 3780 3781 } 3782 3783 random() { 3784 3785 // sets this quaternion to a uniform random unit quaternnion 3786 3787 // Ken Shoemake 3788 // Uniform random rotations 3789 // D. Kirk, editor, Graphics Gems III, pages 124-132. Academic Press, New York, 1992. 3790 3791 const theta1 = 2 * Math.PI * Math.random(); 3792 const theta2 = 2 * Math.PI * Math.random(); 3793 3794 const x0 = Math.random(); 3795 const r1 = Math.sqrt( 1 - x0 ); 3796 const r2 = Math.sqrt( x0 ); 3797 3798 return this.set( 3799 r1 * Math.sin( theta1 ), 3800 r1 * Math.cos( theta1 ), 3801 r2 * Math.sin( theta2 ), 3802 r2 * Math.cos( theta2 ), 3803 ); 3804 3805 } 3806 3807 equals( quaternion ) { 3808 3809 return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); 3810 3811 } 3812 3813 fromArray( array, offset = 0 ) { 3814 3815 this._x = array[ offset ]; 3816 this._y = array[ offset + 1 ]; 3817 this._z = array[ offset + 2 ]; 3818 this._w = array[ offset + 3 ]; 3819 3820 this._onChangeCallback(); 3821 3822 return this; 3823 3824 } 3825 3826 toArray( array = [], offset = 0 ) { 3827 3828 array[ offset ] = this._x; 3829 array[ offset + 1 ] = this._y; 3830 array[ offset + 2 ] = this._z; 3831 array[ offset + 3 ] = this._w; 3832 3833 return array; 3834 3835 } 3836 3837 fromBufferAttribute( attribute, index ) { 3838 3839 this._x = attribute.getX( index ); 3840 this._y = attribute.getY( index ); 3841 this._z = attribute.getZ( index ); 3842 this._w = attribute.getW( index ); 3843 3844 this._onChangeCallback(); 3845 3846 return this; 3847 3848 } 3849 3850 toJSON() { 3851 3852 return this.toArray(); 3853 3854 } 3855 3856 _onChange( callback ) { 3857 3858 this._onChangeCallback = callback; 3859 3860 return this; 3861 3862 } 3863 3864 _onChangeCallback() {} 3865 3866 *[ Symbol.iterator ]() { 3867 3868 yield this._x; 3869 yield this._y; 3870 yield this._z; 3871 yield this._w; 3872 3873 } 3874 3875} 3876 3877class Vector3 { 3878 3879 constructor( x = 0, y = 0, z = 0 ) { 3880 3881 Vector3.prototype.isVector3 = true; 3882 3883 this.x = x; 3884 this.y = y; 3885 this.z = z; 3886 3887 } 3888 3889 set( x, y, z ) { 3890 3891 if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) 3892 3893 this.x = x; 3894 this.y = y; 3895 this.z = z; 3896 3897 return this; 3898 3899 } 3900 3901 setScalar( scalar ) { 3902 3903 this.x = scalar; 3904 this.y = scalar; 3905 this.z = scalar; 3906 3907 return this; 3908 3909 } 3910 3911 setX( x ) { 3912 3913 this.x = x; 3914 3915 return this; 3916 3917 } 3918 3919 setY( y ) { 3920 3921 this.y = y; 3922 3923 return this; 3924 3925 } 3926 3927 setZ( z ) { 3928 3929 this.z = z; 3930 3931 return this; 3932 3933 } 3934 3935 setComponent( index, value ) { 3936 3937 switch ( index ) { 3938 3939 case 0: this.x = value; break; 3940 case 1: this.y = value; break; 3941 case 2: this.z = value; break; 3942 default: throw new Error( 'index is out of range: ' + index ); 3943 3944 } 3945 3946 return this; 3947 3948 } 3949 3950 getComponent( index ) { 3951 3952 switch ( index ) { 3953 3954 case 0: return this.x; 3955 case 1: return this.y; 3956 case 2: return this.z; 3957 default: throw new Error( 'index is out of range: ' + index ); 3958 3959 } 3960 3961 } 3962 3963 clone() { 3964 3965 return new this.constructor( this.x, this.y, this.z ); 3966 3967 } 3968 3969 copy( v ) { 3970 3971 this.x = v.x; 3972 this.y = v.y; 3973 this.z = v.z; 3974 3975 return this; 3976 3977 } 3978 3979 add( v ) { 3980 3981 this.x += v.x; 3982 this.y += v.y; 3983 this.z += v.z; 3984 3985 return this; 3986 3987 } 3988 3989 addScalar( s ) { 3990 3991 this.x += s; 3992 this.y += s; 3993 this.z += s; 3994 3995 return this; 3996 3997 } 3998 3999 addVectors( a, b ) { 4000 4001 this.x = a.x + b.x; 4002 this.y = a.y + b.y; 4003 this.z = a.z + b.z; 4004 4005 return this; 4006 4007 } 4008 4009 addScaledVector( v, s ) { 4010 4011 this.x += v.x * s; 4012 this.y += v.y * s; 4013 this.z += v.z * s; 4014 4015 return this; 4016 4017 } 4018 4019 sub( v ) { 4020 4021 this.x -= v.x; 4022 this.y -= v.y; 4023 this.z -= v.z; 4024 4025 return this; 4026 4027 } 4028 4029 subScalar( s ) { 4030 4031 this.x -= s; 4032 this.y -= s; 4033 this.z -= s; 4034 4035 return this; 4036 4037 } 4038 4039 subVectors( a, b ) { 4040 4041 this.x = a.x - b.x; 4042 this.y = a.y - b.y; 4043 this.z = a.z - b.z; 4044 4045 return this; 4046 4047 } 4048 4049 multiply( v ) { 4050 4051 this.x *= v.x; 4052 this.y *= v.y; 4053 this.z *= v.z; 4054 4055 return this; 4056 4057 } 4058 4059 multiplyScalar( scalar ) { 4060 4061 this.x *= scalar; 4062 this.y *= scalar; 4063 this.z *= scalar; 4064 4065 return this; 4066 4067 } 4068 4069 multiplyVectors( a, b ) { 4070 4071 this.x = a.x * b.x; 4072 this.y = a.y * b.y; 4073 this.z = a.z * b.z; 4074 4075 return this; 4076 4077 } 4078 4079 applyEuler( euler ) { 4080 4081 return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); 4082 4083 } 4084 4085 applyAxisAngle( axis, angle ) { 4086 4087 return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); 4088 4089 } 4090 4091 applyMatrix3( m ) { 4092 4093 const x = this.x, y = this.y, z = this.z; 4094 const e = m.elements; 4095 4096 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; 4097 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; 4098 this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; 4099 4100 return this; 4101 4102 } 4103 4104 applyNormalMatrix( m ) { 4105 4106 return this.applyMatrix3( m ).normalize(); 4107 4108 } 4109 4110 applyMatrix4( m ) { 4111 4112 const x = this.x, y = this.y, z = this.z; 4113 const e = m.elements; 4114 4115 const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); 4116 4117 this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; 4118 this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; 4119 this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; 4120 4121 return this; 4122 4123 } 4124 4125 applyQuaternion( q ) { 4126 4127 // quaternion q is assumed to have unit length 4128 4129 const vx = this.x, vy = this.y, vz = this.z; 4130 const qx = q.x, qy = q.y, qz = q.z, qw = q.w; 4131 4132 // t = 2 * cross( q.xyz, v ); 4133 const tx = 2 * ( qy * vz - qz * vy ); 4134 const ty = 2 * ( qz * vx - qx * vz ); 4135 const tz = 2 * ( qx * vy - qy * vx ); 4136 4137 // v + q.w * t + cross( q.xyz, t ); 4138 this.x = vx + qw * tx + qy * tz - qz * ty; 4139 this.y = vy + qw * ty + qz * tx - qx * tz; 4140 this.z = vz + qw * tz + qx * ty - qy * tx; 4141 4142 return this; 4143 4144 } 4145 4146 project( camera ) { 4147 4148 return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); 4149 4150 } 4151 4152 unproject( camera ) { 4153 4154 return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); 4155 4156 } 4157 4158 transformDirection( m ) { 4159 4160 // input: THREE.Matrix4 affine matrix 4161 // vector interpreted as a direction 4162 4163 const x = this.x, y = this.y, z = this.z; 4164 const e = m.elements; 4165 4166 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; 4167 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; 4168 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; 4169 4170 return this.normalize(); 4171 4172 } 4173 4174 divide( v ) { 4175 4176 this.x /= v.x; 4177 this.y /= v.y; 4178 this.z /= v.z; 4179 4180 return this; 4181 4182 } 4183 4184 divideScalar( scalar ) { 4185 4186 return this.multiplyScalar( 1 / scalar ); 4187 4188 } 4189 4190 min( v ) { 4191 4192 this.x = Math.min( this.x, v.x ); 4193 this.y = Math.min( this.y, v.y ); 4194 this.z = Math.min( this.z, v.z ); 4195 4196 return this; 4197 4198 } 4199 4200 max( v ) { 4201 4202 this.x = Math.max( this.x, v.x ); 4203 this.y = Math.max( this.y, v.y ); 4204 this.z = Math.max( this.z, v.z ); 4205 4206 return this; 4207 4208 } 4209 4210 clamp( min, max ) { 4211 4212 // assumes min < max, componentwise 4213 4214 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 4215 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 4216 this.z = Math.max( min.z, Math.min( max.z, this.z ) ); 4217 4218 return this; 4219 4220 } 4221 4222 clampScalar( minVal, maxVal ) { 4223 4224 this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); 4225 this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); 4226 this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); 4227 4228 return this; 4229 4230 } 4231 4232 clampLength( min, max ) { 4233 4234 const length = this.length(); 4235 4236 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 4237 4238 } 4239 4240 floor() { 4241 4242 this.x = Math.floor( this.x ); 4243 this.y = Math.floor( this.y ); 4244 this.z = Math.floor( this.z ); 4245 4246 return this; 4247 4248 } 4249 4250 ceil() { 4251 4252 this.x = Math.ceil( this.x ); 4253 this.y = Math.ceil( this.y ); 4254 this.z = Math.ceil( this.z ); 4255 4256 return this; 4257 4258 } 4259 4260 round() { 4261 4262 this.x = Math.round( this.x ); 4263 this.y = Math.round( this.y ); 4264 this.z = Math.round( this.z ); 4265 4266 return this; 4267 4268 } 4269 4270 roundToZero() { 4271 4272 this.x = Math.trunc( this.x ); 4273 this.y = Math.trunc( this.y ); 4274 this.z = Math.trunc( this.z ); 4275 4276 return this; 4277 4278 } 4279 4280 negate() { 4281 4282 this.x = - this.x; 4283 this.y = - this.y; 4284 this.z = - this.z; 4285 4286 return this; 4287 4288 } 4289 4290 dot( v ) { 4291 4292 return this.x * v.x + this.y * v.y + this.z * v.z; 4293 4294 } 4295 4296 // TODO lengthSquared? 4297 4298 lengthSq() { 4299 4300 return this.x * this.x + this.y * this.y + this.z * this.z; 4301 4302 } 4303 4304 length() { 4305 4306 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); 4307 4308 } 4309 4310 manhattanLength() { 4311 4312 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); 4313 4314 } 4315 4316 normalize() { 4317 4318 return this.divideScalar( this.length() || 1 ); 4319 4320 } 4321 4322 setLength( length ) { 4323 4324 return this.normalize().multiplyScalar( length ); 4325 4326 } 4327 4328 lerp( v, alpha ) { 4329 4330 this.x += ( v.x - this.x ) * alpha; 4331 this.y += ( v.y - this.y ) * alpha; 4332 this.z += ( v.z - this.z ) * alpha; 4333 4334 return this; 4335 4336 } 4337 4338 lerpVectors( v1, v2, alpha ) { 4339 4340 this.x = v1.x + ( v2.x - v1.x ) * alpha; 4341 this.y = v1.y + ( v2.y - v1.y ) * alpha; 4342 this.z = v1.z + ( v2.z - v1.z ) * alpha; 4343 4344 return this; 4345 4346 } 4347 4348 cross( v ) { 4349 4350 return this.crossVectors( this, v ); 4351 4352 } 4353 4354 crossVectors( a, b ) { 4355 4356 const ax = a.x, ay = a.y, az = a.z; 4357 const bx = b.x, by = b.y, bz = b.z; 4358 4359 this.x = ay * bz - az * by; 4360 this.y = az * bx - ax * bz; 4361 this.z = ax * by - ay * bx; 4362 4363 return this; 4364 4365 } 4366 4367 projectOnVector( v ) { 4368 4369 const denominator = v.lengthSq(); 4370 4371 if ( denominator === 0 ) return this.set( 0, 0, 0 ); 4372 4373 const scalar = v.dot( this ) / denominator; 4374 4375 return this.copy( v ).multiplyScalar( scalar ); 4376 4377 } 4378 4379 projectOnPlane( planeNormal ) { 4380 4381 _vector$c.copy( this ).projectOnVector( planeNormal ); 4382 4383 return this.sub( _vector$c ); 4384 4385 } 4386 4387 reflect( normal ) { 4388 4389 // reflect incident vector off plane orthogonal to normal 4390 // normal is assumed to have unit length 4391 4392 return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); 4393 4394 } 4395 4396 angleTo( v ) { 4397 4398 const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); 4399 4400 if ( denominator === 0 ) return Math.PI / 2; 4401 4402 const theta = this.dot( v ) / denominator; 4403 4404 // clamp, to handle numerical problems 4405 4406 return Math.acos( clamp( theta, -
vendor: 14,574 bytes, lines 4406-5134
44061, 1 ) ); 4407 4408 } 4409 4410 distanceTo( v ) { 4411 4412 return Math.sqrt( this.distanceToSquared( v ) ); 4413 4414 } 4415 4416 distanceToSquared( v ) { 4417 4418 const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; 4419 4420 return dx * dx + dy * dy + dz * dz; 4421 4422 } 4423 4424 manhattanDistanceTo( v ) { 4425 4426 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); 4427 4428 } 4429 4430 setFromSpherical( s ) { 4431 4432 return this.setFromSphericalCoords( s.radius, s.phi, s.theta ); 4433 4434 } 4435 4436 setFromSphericalCoords( radius, phi, theta ) { 4437 4438 const sinPhiRadius = Math.sin( phi ) * radius; 4439 4440 this.x = sinPhiRadius * Math.sin( theta ); 4441 this.y = Math.cos( phi ) * radius; 4442 this.z = sinPhiRadius * Math.cos( theta ); 4443 4444 return this; 4445 4446 } 4447 4448 setFromCylindrical( c ) { 4449 4450 return this.setFromCylindricalCoords( c.radius, c.theta, c.y ); 4451 4452 } 4453 4454 setFromCylindricalCoords( radius, theta, y ) { 4455 4456 this.x = radius * Math.sin( theta ); 4457 this.y = y; 4458 this.z = radius * Math.cos( theta ); 4459 4460 return this; 4461 4462 } 4463 4464 setFromMatrixPosition( m ) { 4465 4466 const e = m.elements; 4467 4468 this.x = e[ 12 ]; 4469 this.y = e[ 13 ]; 4470 this.z = e[ 14 ]; 4471 4472 return this; 4473 4474 } 4475 4476 setFromMatrixScale( m ) { 4477 4478 const sx = this.setFromMatrixColumn( m, 0 ).length(); 4479 const sy = this.setFromMatrixColumn( m, 1 ).length(); 4480 const sz = this.setFromMatrixColumn( m, 2 ).length(); 4481 4482 this.x = sx; 4483 this.y = sy; 4484 this.z = sz; 4485 4486 return this; 4487 4488 } 4489 4490 setFromMatrixColumn( m, index ) { 4491 4492 return this.fromArray( m.elements, index * 4 ); 4493 4494 } 4495 4496 setFromMatrix3Column( m, index ) { 4497 4498 return this.fromArray( m.elements, index * 3 ); 4499 4500 } 4501 4502 setFromEuler( e ) { 4503 4504 this.x = e._x; 4505 this.y = e._y; 4506 this.z = e._z; 4507 4508 return this; 4509 4510 } 4511 4512 setFromColor( c ) { 4513 4514 this.x = c.r; 4515 this.y = c.g; 4516 this.z = c.b; 4517 4518 return this; 4519 4520 } 4521 4522 equals( v ) { 4523 4524 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); 4525 4526 } 4527 4528 fromArray( array, offset = 0 ) { 4529 4530 this.x = array[ offset ]; 4531 this.y = array[ offset + 1 ]; 4532 this.z = array[ offset + 2 ]; 4533 4534 return this; 4535 4536 } 4537 4538 toArray( array = [], offset = 0 ) { 4539 4540 array[ offset ] = this.x; 4541 array[ offset + 1 ] = this.y; 4542 array[ offset + 2 ] = this.z; 4543 4544 return array; 4545 4546 } 4547 4548 fromBufferAttribute( attribute, index ) { 4549 4550 this.x = attribute.getX( index ); 4551 this.y = attribute.getY( index ); 4552 this.z = attribute.getZ( index ); 4553 4554 return this; 4555 4556 } 4557 4558 random() { 4559 4560 this.x = Math.random(); 4561 this.y = Math.random(); 4562 this.z = Math.random(); 4563 4564 return this; 4565 4566 } 4567 4568 randomDirection() { 4569 4570 // https://mathworld.wolfram.com/SpherePointPicking.html 4571 4572 const theta = Math.random() * Math.PI * 2; 4573 const u = Math.random() * 2 - 1; 4574 const c = Math.sqrt( 1 - u * u ); 4575 4576 this.x = c * Math.cos( theta ); 4577 this.y = u; 4578 this.z = c * Math.sin( theta ); 4579 4580 return this; 4581 4582 } 4583 4584 *[ Symbol.iterator ]() { 4585 4586 yield this.x; 4587 yield this.y; 4588 yield this.z; 4589 4590 } 4591 4592} 4593 4594const _vector$c = /*@__PURE__*/ new Vector3(); 4595const _quaternion$4 = /*@__PURE__*/ new Quaternion(); 4596 4597class Box3 { 4598 4599 constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) { 4600 4601 this.isBox3 = true; 4602 4603 this.min = min; 4604 this.max = max; 4605 4606 } 4607 4608 set( min, max ) { 4609 4610 this.min.copy( min ); 4611 this.max.copy( max ); 4612 4613 return this; 4614 4615 } 4616 4617 setFromArray( array ) { 4618 4619 this.makeEmpty(); 4620 4621 for ( let i = 0, il = array.length; i < il; i += 3 ) { 4622 4623 this.expandByPoint( _vector$b.fromArray( array, i ) ); 4624 4625 } 4626 4627 return this; 4628 4629 } 4630 4631 setFromBufferAttribute( attribute ) { 4632 4633 this.makeEmpty(); 4634 4635 for ( let i = 0, il = attribute.count; i < il; i ++ ) { 4636 4637 this.expandByPoint( _vector$b.fromBufferAttribute( attribute, i ) ); 4638 4639 } 4640 4641 return this; 4642 4643 } 4644 4645 setFromPoints( points ) { 4646 4647 this.makeEmpty(); 4648 4649 for ( let i = 0, il = points.length; i < il; i ++ ) { 4650 4651 this.expandByPoint( points[ i ] ); 4652 4653 } 4654 4655 return this; 4656 4657 } 4658 4659 setFromCenterAndSize( center, size ) { 4660 4661 const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); 4662 4663 this.min.copy( center ).sub( halfSize ); 4664 this.max.copy( center ).add( halfSize ); 4665 4666 return this; 4667 4668 } 4669 4670 setFromObject( object, precise = false ) { 4671 4672 this.makeEmpty(); 4673 4674 return this.expandByObject( object, precise ); 4675 4676 } 4677 4678 clone() { 4679 4680 return new this.constructor().copy( this ); 4681 4682 } 4683 4684 copy( box ) { 4685 4686 this.min.copy( box.min ); 4687 this.max.copy( box.max ); 4688 4689 return this; 4690 4691 } 4692 4693 makeEmpty() { 4694 4695 this.min.x = this.min.y = this.min.z = + Infinity; 4696 this.max.x = this.max.y = this.max.z = - Infinity; 4697 4698 return this; 4699 4700 } 4701 4702 isEmpty() { 4703 4704 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes 4705 4706 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); 4707 4708 } 4709 4710 getCenter( target ) { 4711 4712 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); 4713 4714 } 4715 4716 getSize( target ) { 4717 4718 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min ); 4719 4720 } 4721 4722 expandByPoint( point ) { 4723 4724 this.min.min( point ); 4725 this.max.max( point ); 4726 4727 return this; 4728 4729 } 4730 4731 expandByVector( vector ) { 4732 4733 this.min.sub( vector ); 4734 this.max.add( vector ); 4735 4736 return this; 4737 4738 } 4739 4740 expandByScalar( scalar ) { 4741 4742 this.min.addScalar( - scalar ); 4743 this.max.addScalar( scalar ); 4744 4745 return this; 4746 4747 } 4748 4749 expandByObject( object, precise = false ) { 4750 4751 // Computes the world-axis-aligned bounding box of an object (including its children), 4752 // accounting for both the object's, and children's, world transforms 4753 4754 object.updateWorldMatrix( false, false ); 4755 4756 const geometry = object.geometry; 4757 4758 if ( geometry !== undefined ) { 4759 4760 const positionAttribute = geometry.getAttribute( 'position' ); 4761 4762 // precise AABB computation based on vertex data requires at least a position attribute. 4763 // instancing isn't supported so far and uses the normal (conservative) code path. 4764 4765 if ( precise === true && positionAttribute !== undefined && object.isInstancedMesh !== true ) { 4766 4767 for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) { 4768 4769 if ( object.isMesh === true ) { 4770 4771 object.getVertexPosition( i, _vector$b ); 4772 4773 } else { 4774 4775 _vector$b.fromBufferAttribute( positionAttribute, i ); 4776 4777 } 4778 4779 _vector$b.applyMatrix4( object.matrixWorld ); 4780 this.expandByPoint( _vector$b ); 4781 4782 } 4783 4784 } else { 4785 4786 if ( object.boundingBox !== undefined ) { 4787 4788 // object-level bounding box 4789 4790 if ( object.boundingBox === null ) { 4791 4792 object.computeBoundingBox(); 4793 4794 } 4795 4796 _box$4.copy( object.boundingBox ); 4797 4798 4799 } else { 4800 4801 // geometry-level bounding box 4802 4803 if ( geometry.boundingBox === null ) { 4804 4805 geometry.computeBoundingBox(); 4806 4807 } 4808 4809 _box$4.copy( geometry.boundingBox ); 4810 4811 } 4812 4813 _box$4.applyMatrix4( object.matrixWorld ); 4814 4815 this.union( _box$4 ); 4816 4817 } 4818 4819 } 4820 4821 const children = object.children; 4822 4823 for ( let i = 0, l = children.length; i < l; i ++ ) { 4824 4825 this.expandByObject( children[ i ], precise ); 4826 4827 } 4828 4829 return this; 4830 4831 } 4832 4833 containsPoint( point ) { 4834 4835 return point.x < this.min.x || point.x > this.max.x || 4836 point.y < this.min.y || point.y > this.max.y || 4837 point.z < this.min.z || point.z > this.max.z ? false : true; 4838 4839 } 4840 4841 containsBox( box ) { 4842 4843 return this.min.x <= box.min.x && box.max.x <= this.max.x && 4844 this.min.y <= box.min.y && box.max.y <= this.max.y && 4845 this.min.z <= box.min.z && box.max.z <= this.max.z; 4846 4847 } 4848 4849 getParameter( point, target ) { 4850 4851 // This can potentially have a divide by zero if the box 4852 // has a size dimension of 0. 4853 4854 return target.set( 4855 ( point.x - this.min.x ) / ( this.max.x - this.min.x ), 4856 ( point.y - this.min.y ) / ( this.max.y - this.min.y ), 4857 ( point.z - this.min.z ) / ( this.max.z - this.min.z ) 4858 ); 4859 4860 } 4861 4862 intersectsBox( box ) { 4863 4864 // using 6 splitting planes to rule out intersections. 4865 return box.max.x < this.min.x || box.min.x > this.max.x || 4866 box.max.y < this.min.y || box.min.y > this.max.y || 4867 box.max.z < this.min.z || box.min.z > this.max.z ? false : true; 4868 4869 } 4870 4871 intersectsSphere( sphere ) { 4872 4873 // Find the point on the AABB closest to the sphere center. 4874 this.clampPoint( sphere.center, _vector$b ); 4875 4876 // If that point is inside the sphere, the AABB and sphere intersect. 4877 return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); 4878 4879 } 4880 4881 intersectsPlane( plane ) { 4882 4883 // We compute the minimum and maximum dot product values. If those values 4884 // are on the same side (back or front) of the plane, then there is no intersection. 4885 4886 let min, max; 4887 4888 if ( plane.normal.x > 0 ) { 4889 4890 min = plane.normal.x * this.min.x; 4891 max = plane.normal.x * this.max.x; 4892 4893 } else { 4894 4895 min = plane.normal.x * this.max.x; 4896 max = plane.normal.x * this.min.x; 4897 4898 } 4899 4900 if ( plane.normal.y > 0 ) { 4901 4902 min += plane.normal.y * this.min.y; 4903 max += plane.normal.y * this.max.y; 4904 4905 } else { 4906 4907 min += plane.normal.y * this.max.y; 4908 max += plane.normal.y * this.min.y; 4909 4910 } 4911 4912 if ( plane.normal.z > 0 ) { 4913 4914 min += plane.normal.z * this.min.z; 4915 max += plane.normal.z * this.max.z; 4916 4917 } else { 4918 4919 min += plane.normal.z * this.max.z; 4920 max += plane.normal.z * this.min.z; 4921 4922 } 4923 4924 return ( min <= - plane.constant && max >= - plane.constant ); 4925 4926 } 4927 4928 intersectsTriangle( triangle ) { 4929 4930 if ( this.isEmpty() ) { 4931 4932 return false; 4933 4934 } 4935 4936 // compute box center and extents 4937 this.getCenter( _center ); 4938 _extents.subVectors( this.max, _center ); 4939 4940 // translate triangle to aabb origin 4941 _v0$2.subVectors( triangle.a, _center ); 4942 _v1$7.subVectors( triangle.b, _center ); 4943 _v2$4.subVectors( triangle.c, _center ); 4944 4945 // compute edge vectors for triangle 4946 _f0.subVectors( _v1$7, _v0$2 ); 4947 _f1.subVectors( _v2$4, _v1$7 ); 4948 _f2.subVectors( _v0$2, _v2$4 ); 4949 4950 // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb 4951 // 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 4952 // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned) 4953 let axes = [ 4954 0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y, 4955 _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x, 4956 - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0 4957 ]; 4958 if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) { 4959 4960 return false; 4961 4962 } 4963 4964 // test 3 face normals from the aabb 4965 axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; 4966 if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) { 4967 4968 return false; 4969 4970 } 4971 4972 // finally testing the face normal of the triangle 4973 // use already existing triangle edge vectors here 4974 _triangleNormal.crossVectors( _f0, _f1 ); 4975 axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ]; 4976 4977 return satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ); 4978 4979 } 4980 4981 clampPoint( point, target ) { 4982 4983 return target.copy( point ).clamp( this.min, this.max ); 4984 4985 } 4986 4987 distanceToPoint( point ) { 4988 4989 return this.clampPoint( point, _vector$b ).distanceTo( point ); 4990 4991 } 4992 4993 getBoundingSphere( target ) { 4994 4995 if ( this.isEmpty() ) { 4996 4997 target.makeEmpty(); 4998 4999 } else { 5000 5001 this.getCenter( target.center ); 5002 5003 target.radius = this.getSize( _vector$b ).length() * 0.5; 5004 5005 } 5006 5007 return target; 5008 5009 } 5010 5011 intersect( box ) { 5012 5013 this.min.max( box.min ); 5014 this.max.min( box.max ); 5015 5016 // 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. 5017 if ( this.isEmpty() ) this.makeEmpty(); 5018 5019 return this; 5020 5021 } 5022 5023 union( box ) { 5024 5025 this.min.min( box.min ); 5026 this.max.max( box.max ); 5027 5028 return this; 5029 5030 } 5031 5032 applyMatrix4( matrix ) { 5033 5034 // transform of empty box is an empty box. 5035 if ( this.isEmpty() ) return this; 5036 5037 // NOTE: I am using a binary pattern to specify all 2^3 combinations below 5038 _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 5039 _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 5040 _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 5041 _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 5042 _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 5043 _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 5044 _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 5045 _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 5046 5047 this.setFromPoints( _points ); 5048 5049 return this; 5050 5051 } 5052 5053 translate( offset ) { 5054 5055 this.min.add( offset ); 5056 this.max.add( offset ); 5057 5058 return this; 5059 5060 } 5061 5062 equals( box ) { 5063 5064 return box.min.equals( this.min ) && box.max.equals( this.max ); 5065 5066 } 5067 5068} 5069 5070const _points = [ 5071 /*@__PURE__*/ new Vector3(), 5072 /*@__PURE__*/ new Vector3(), 5073 /*@__PURE__*/ new Vector3(), 5074 /*@__PURE__*/ new Vector3(), 5075 /*@__PURE__*/ new Vector3(), 5076 /*@__PURE__*/ new Vector3(), 5077 /*@__PURE__*/ new Vector3(), 5078 /*@__PURE__*/ new Vector3() 5079]; 5080 5081const _vector$b = /*@__PURE__*/ new Vector3(); 5082 5083const _box$4 = /*@__PURE__*/ new Box3(); 5084 5085// triangle centered vertices 5086 5087const _v0$2 = /*@__PURE__*/ new Vector3(); 5088const _v1$7 = /*@__PURE__*/ new Vector3(); 5089const _v2$4 = /*@__PURE__*/ new Vector3(); 5090 5091// triangle edge vectors 5092 5093const _f0 = /*@__PURE__*/ new Vector3(); 5094const _f1 = /*@__PURE__*/ new Vector3(); 5095const _f2 = /*@__PURE__*/ new Vector3(); 5096 5097const _center = /*@__PURE__*/ new Vector3(); 5098const _extents = /*@__PURE__*/ new Vector3(); 5099const _triangleNormal = /*@__PURE__*/ new Vector3(); 5100const _testAxis = /*@__PURE__*/ new Vector3(); 5101 5102function satForAxes( axes, v0, v1, v2, extents ) { 5103 5104 for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) { 5105 5106 _testAxis.fromArray( axes, i ); 5107 // project the aabb onto the separating axis 5108 const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z ); 5109 // project all 3 vertices of the triangle onto the separating axis 5110 const p0 = v0.dot( _testAxis ); 5111 const p1 = v1.dot( _testAxis ); 5112 const p2 = v2.dot( _testAxis ); 5113 // actual test, basically see if either of the most extreme of the triangle points intersects r 5114 if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) { 5115 5116 // points of the projected triangle are outside the projected half-length of the aabb 5117 // the axis is separating and we can exit 5118 return false; 5119 5120 } 5121 5122 } 5123 5124 return true; 5125 5126} 5127 5128const _box$3 = /*@__PURE__*/ new Box3(); 5129const _v1$6 = /*@__PURE__*/ new Vector3(); 5130const _v2$3 = /*@__PURE__*/ new Vector3(); 5131 5132class Sphere { 5133 5134 constructor( center = new Vector3(), radius = -
vendor: 3,824 bytes, lines 5134-5380
5134 1 ) { 5135 5136 this.isSphere = true; 5137 5138 this.center = center; 5139 this.radius = radius; 5140 5141 } 5142 5143 set( center, radius ) { 5144 5145 this.center.copy( center ); 5146 this.radius = radius; 5147 5148 return this; 5149 5150 } 5151 5152 setFromPoints( points, optionalCenter ) { 5153 5154 const center = this.center; 5155 5156 if ( optionalCenter !== undefined ) { 5157 5158 center.copy( optionalCenter ); 5159 5160 } else { 5161 5162 _box$3.setFromPoints( points ).getCenter( center ); 5163 5164 } 5165 5166 let maxRadiusSq = 0; 5167 5168 for ( let i = 0, il = points.length; i < il; i ++ ) { 5169 5170 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); 5171 5172 } 5173 5174 this.radius = Math.sqrt( maxRadiusSq ); 5175 5176 return this; 5177 5178 } 5179 5180 copy( sphere ) { 5181 5182 this.center.copy( sphere.center ); 5183 this.radius = sphere.radius; 5184 5185 return this; 5186 5187 } 5188 5189 isEmpty() { 5190 5191 return ( this.radius < 0 ); 5192 5193 } 5194 5195 makeEmpty() { 5196 5197 this.center.set( 0, 0, 0 ); 5198 this.radius = - 1; 5199 5200 return this; 5201 5202 } 5203 5204 containsPoint( point ) { 5205 5206 return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); 5207 5208 } 5209 5210 distanceToPoint( point ) { 5211 5212 return ( point.distanceTo( this.center ) - this.radius ); 5213 5214 } 5215 5216 intersectsSphere( sphere ) { 5217 5218 const radiusSum = this.radius + sphere.radius; 5219 5220 return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); 5221 5222 } 5223 5224 intersectsBox( box ) { 5225 5226 return box.intersectsSphere( this ); 5227 5228 } 5229 5230 intersectsPlane( plane ) { 5231 5232 return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; 5233 5234 } 5235 5236 clampPoint( point, target ) { 5237 5238 const deltaLengthSq = this.center.distanceToSquared( point ); 5239 5240 target.copy( point ); 5241 5242 if ( deltaLengthSq > ( this.radius * this.radius ) ) { 5243 5244 target.sub( this.center ).normalize(); 5245 target.multiplyScalar( this.radius ).add( this.center ); 5246 5247 } 5248 5249 return target; 5250 5251 } 5252 5253 getBoundingBox( target ) { 5254 5255 if ( this.isEmpty() ) { 5256 5257 // Empty sphere produces empty bounding box 5258 target.makeEmpty(); 5259 return target; 5260 5261 } 5262 5263 target.set( this.center, this.center ); 5264 target.expandByScalar( this.radius ); 5265 5266 return target; 5267 5268 } 5269 5270 applyMatrix4( matrix ) { 5271 5272 this.center.applyMatrix4( matrix ); 5273 this.radius = this.radius * matrix.getMaxScaleOnAxis(); 5274 5275 return this; 5276 5277 } 5278 5279 translate( offset ) { 5280 5281 this.center.add( offset ); 5282 5283 return this; 5284 5285 } 5286 5287 expandByPoint( point ) { 5288 5289 if ( this.isEmpty() ) { 5290 5291 this.center.copy( point ); 5292 5293 this.radius = 0; 5294 5295 return this; 5296 5297 } 5298 5299 _v1$6.subVectors( point, this.center ); 5300 5301 const lengthSq = _v1$6.lengthSq(); 5302 5303 if ( lengthSq > ( this.radius * this.radius ) ) { 5304 5305 // calculate the minimal sphere 5306 5307 const length = Math.sqrt( lengthSq ); 5308 5309 const delta = ( length - this.radius ) * 0.5; 5310 5311 this.center.addScaledVector( _v1$6, delta / length ); 5312 5313 this.radius += delta; 5314 5315 } 5316 5317 return this; 5318 5319 } 5320 5321 union( sphere ) { 5322 5323 if ( sphere.isEmpty() ) { 5324 5325 return this; 5326 5327 } 5328 5329 if ( this.isEmpty() ) { 5330 5331 this.copy( sphere ); 5332 5333 return this; 5334 5335 } 5336 5337 if ( this.center.equals( sphere.center ) === true ) { 5338 5339 this.radius = Math.max( this.radius, sphere.radius ); 5340 5341 } else { 5342 5343 _v2$3.subVectors( sphere.center, this.center ).setLength( sphere.radius ); 5344 5345 this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) ); 5346 5347 this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) ); 5348 5349 } 5350 5351 return this; 5352 5353 } 5354 5355 equals( sphere ) { 5356 5357 return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); 5358 5359 } 5360 5361 clone() { 5362 5363 return new this.constructor().copy( this ); 5364 5365 } 5366 5367} 5368 5369const _vector$a = /*@__PURE__*/ new Vector3(); 5370const _segCenter = /*@__PURE__*/ new Vector3(); 5371const _segDir = /*@__PURE__*/ new Vector3(); 5372const _diff = /*@__PURE__*/ new Vector3(); 5373 5374const _edge1 = /*@__PURE__*/ new Vector3(); 5375const _edge2 = /*@__PURE__*/ new Vector3(); 5376const _normal$1 = /*@__PURE__*/ new Vector3(); 5377 5378class Ray { 5379 5380 constructor( origin = new Vector3(), direction = new Vector3( 0, 0, -
vendor: 8,510 bytes, lines 5380-5786
53801 ) ) { 5381 5382 this.origin = origin; 5383 this.direction = direction; 5384 5385 } 5386 5387 set( origin, direction ) { 5388 5389 this.origin.copy( origin ); 5390 this.direction.copy( direction ); 5391 5392 return this; 5393 5394 } 5395 5396 copy( ray ) { 5397 5398 this.origin.copy( ray.origin ); 5399 this.direction.copy( ray.direction ); 5400 5401 return this; 5402 5403 } 5404 5405 at( t, target ) { 5406 5407 return target.copy( this.origin ).addScaledVector( this.direction, t ); 5408 5409 } 5410 5411 lookAt( v ) { 5412 5413 this.direction.copy( v ).sub( this.origin ).normalize(); 5414 5415 return this; 5416 5417 } 5418 5419 recast( t ) { 5420 5421 this.origin.copy( this.at( t, _vector$a ) ); 5422 5423 return this; 5424 5425 } 5426 5427 closestPointToPoint( point, target ) { 5428 5429 target.subVectors( point, this.origin ); 5430 5431 const directionDistance = target.dot( this.direction ); 5432 5433 if ( directionDistance < 0 ) { 5434 5435 return target.copy( this.origin ); 5436 5437 } 5438 5439 return target.copy( this.origin ).addScaledVector( this.direction, directionDistance ); 5440 5441 } 5442 5443 distanceToPoint( point ) { 5444 5445 return Math.sqrt( this.distanceSqToPoint( point ) ); 5446 5447 } 5448 5449 distanceSqToPoint( point ) { 5450 5451 const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); 5452 5453 // point behind the ray 5454 5455 if ( directionDistance < 0 ) { 5456 5457 return this.origin.distanceToSquared( point ); 5458 5459 } 5460 5461 _vector$a.copy( this.origin ).addScaledVector( this.direction, directionDistance ); 5462 5463 return _vector$a.distanceToSquared( point ); 5464 5465 } 5466 5467 distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { 5468 5469 // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h 5470 // It returns the min distance between the ray and the segment 5471 // defined by v0 and v1 5472 // It can also set two optional targets : 5473 // - The closest point on the ray 5474 // - The closest point on the segment 5475 5476 _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); 5477 _segDir.copy( v1 ).sub( v0 ).normalize(); 5478 _diff.copy( this.origin ).sub( _segCenter ); 5479 5480 const segExtent = v0.distanceTo( v1 ) * 0.5; 5481 const a01 = - this.direction.dot( _segDir ); 5482 const b0 = _diff.dot( this.direction ); 5483 const b1 = - _diff.dot( _segDir ); 5484 const c = _diff.lengthSq(); 5485 const det = Math.abs( 1 - a01 * a01 ); 5486 let s0, s1, sqrDist, extDet; 5487 5488 if ( det > 0 ) { 5489 5490 // The ray and segment are not parallel. 5491 5492 s0 = a01 * b1 - b0; 5493 s1 = a01 * b0 - b1; 5494 extDet = segExtent * det; 5495 5496 if ( s0 >= 0 ) { 5497 5498 if ( s1 >= - extDet ) { 5499 5500 if ( s1 <= extDet ) { 5501 5502 // region 0 5503 // Minimum at interior points of ray and segment. 5504 5505 const invDet = 1 / det; 5506 s0 *= invDet; 5507 s1 *= invDet; 5508 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; 5509 5510 } else { 5511 5512 // region 1 5513 5514 s1 = segExtent; 5515 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 5516 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5517 5518 } 5519 5520 } else { 5521 5522 // region 5 5523 5524 s1 = - segExtent; 5525 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 5526 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5527 5528 } 5529 5530 } else { 5531 5532 if ( s1 <= - extDet ) { 5533 5534 // region 4 5535 5536 s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) ); 5537 s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); 5538 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5539 5540 } else if ( s1 <= extDet ) { 5541 5542 // region 3 5543 5544 s0 = 0; 5545 s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); 5546 sqrDist = s1 * ( s1 + 2 * b1 ) + c; 5547 5548 } else { 5549 5550 // region 2 5551 5552 s0 = Math.max( 0, - ( a01 * segExtent + b0 ) ); 5553 s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); 5554 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5555 5556 } 5557 5558 } 5559 5560 } else { 5561 5562 // Ray and segment are parallel. 5563 5564 s1 = ( a01 > 0 ) ? - segExtent : segExtent; 5565 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 5566 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5567 5568 } 5569 5570 if ( optionalPointOnRay ) { 5571 5572 optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 ); 5573 5574 } 5575 5576 if ( optionalPointOnSegment ) { 5577 5578 optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 ); 5579 5580 } 5581 5582 return sqrDist; 5583 5584 } 5585 5586 intersectSphere( sphere, target ) { 5587 5588 _vector$a.subVectors( sphere.center, this.origin ); 5589 const tca = _vector$a.dot( this.direction ); 5590 const d2 = _vector$a.dot( _vector$a ) - tca * tca; 5591 const radius2 = sphere.radius * sphere.radius; 5592 5593 if ( d2 > radius2 ) return null; 5594 5595 const thc = Math.sqrt( radius2 - d2 ); 5596 5597 // t0 = first intersect point - entrance on front of sphere 5598 const t0 = tca - thc; 5599 5600 // t1 = second intersect point - exit point on back of sphere 5601 const t1 = tca + thc; 5602 5603 // test to see if t1 is behind the ray - if so, return null 5604 if ( t1 < 0 ) return null; 5605 5606 // test to see if t0 is behind the ray: 5607 // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, 5608 // in order to always return an intersect point that is in front of the ray. 5609 if ( t0 < 0 ) return this.at( t1, target ); 5610 5611 // else t0 is in front of the ray, so return the first collision point scaled by t0 5612 return this.at( t0, target ); 5613 5614 } 5615 5616 intersectsSphere( sphere ) { 5617 5618 return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius ); 5619 5620 } 5621 5622 distanceToPlane( plane ) { 5623 5624 const denominator = plane.normal.dot( this.direction ); 5625 5626 if ( denominator === 0 ) { 5627 5628 // line is coplanar, return origin 5629 if ( plane.distanceToPoint( this.origin ) === 0 ) { 5630 5631 return 0; 5632 5633 } 5634 5635 // Null is preferable to undefined since undefined means.... it is undefined 5636 5637 return null; 5638 5639 } 5640 5641 const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; 5642 5643 // Return if the ray never intersects the plane 5644 5645 return t >= 0 ? t : null; 5646 5647 } 5648 5649 intersectPlane( plane, target ) { 5650 5651 const t = this.distanceToPlane( plane ); 5652 5653 if ( t === null ) { 5654 5655 return null; 5656 5657 } 5658 5659 return this.at( t, target ); 5660 5661 } 5662 5663 intersectsPlane( plane ) { 5664 5665 // check if the ray lies on the plane first 5666 5667 const distToPoint = plane.distanceToPoint( this.origin ); 5668 5669 if ( distToPoint === 0 ) { 5670 5671 return true; 5672 5673 } 5674 5675 const denominator = plane.normal.dot( this.direction ); 5676 5677 if ( denominator * distToPoint < 0 ) { 5678 5679 return true; 5680 5681 } 5682 5683 // ray origin is behind the plane (and is pointing behind it) 5684 5685 return false; 5686 5687 } 5688 5689 intersectBox( box, target ) { 5690 5691 let tmin, tmax, tymin, tymax, tzmin, tzmax; 5692 5693 const invdirx = 1 / this.direction.x, 5694 invdiry = 1 / this.direction.y, 5695 invdirz = 1 / this.direction.z; 5696 5697 const origin = this.origin; 5698 5699 if ( invdirx >= 0 ) { 5700 5701 tmin = ( box.min.x - origin.x ) * invdirx; 5702 tmax = ( box.max.x - origin.x ) * invdirx; 5703 5704 } else { 5705 5706 tmin = ( box.max.x - origin.x ) * invdirx; 5707 tmax = ( box.min.x - origin.x ) * invdirx; 5708 5709 } 5710 5711 if ( invdiry >= 0 ) { 5712 5713 tymin = ( box.min.y - origin.y ) * invdiry; 5714 tymax = ( box.max.y - origin.y ) * invdiry; 5715 5716 } else { 5717 5718 tymin = ( box.max.y - origin.y ) * invdiry; 5719 tymax = ( box.min.y - origin.y ) * invdiry; 5720 5721 } 5722 5723 if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; 5724 5725 if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin; 5726 5727 if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax; 5728 5729 if ( invdirz >= 0 ) { 5730 5731 tzmin = ( box.min.z - origin.z ) * invdirz; 5732 tzmax = ( box.max.z - origin.z ) * invdirz; 5733 5734 } else { 5735 5736 tzmin = ( box.max.z - origin.z ) * invdirz; 5737 tzmax = ( box.min.z - origin.z ) * invdirz; 5738 5739 } 5740 5741 if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; 5742 5743 if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; 5744 5745 if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; 5746 5747 //return point closest to the ray (positive side) 5748 5749 if ( tmax < 0 ) return null; 5750 5751 return this.at( tmin >= 0 ? tmin : tmax, target ); 5752 5753 } 5754 5755 intersectsBox( box ) { 5756 5757 return this.intersectBox( box, _vector$a ) !== null; 5758 5759 } 5760 5761 intersectTriangle( a, b, c, backfaceCulling, target ) { 5762 5763 // Compute the offset origin, edges, and normal. 5764 5765 // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h 5766 5767 _edge1.subVectors( b, a ); 5768 _edge2.subVectors( c, a ); 5769 _normal$1.crossVectors( _edge1, _edge2 ); 5770 5771 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, 5772 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by 5773 // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) 5774 // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) 5775 // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) 5776 let DdN = this.direction.dot( _normal$1 ); 5777 let sign; 5778 5779 if ( DdN > 0 ) { 5780 5781 if ( backfaceCulling ) return null; 5782 sign = 1; 5783 5784 } else if ( DdN < 0 ) { 5785 5786 sign = -
5786
vendor: 17,907 bytes, lines 5786-6646
57861; 5787 DdN = - DdN; 5788 5789 } else { 5790 5791 return null; 5792 5793 } 5794 5795 _diff.subVectors( this.origin, a ); 5796 const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) ); 5797 5798 // b1 < 0, no intersection 5799 if ( DdQxE2 < 0 ) { 5800 5801 return null; 5802 5803 } 5804 5805 const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) ); 5806 5807 // b2 < 0, no intersection 5808 if ( DdE1xQ < 0 ) { 5809 5810 return null; 5811 5812 } 5813 5814 // b1+b2 > 1, no intersection 5815 if ( DdQxE2 + DdE1xQ > DdN ) { 5816 5817 return null; 5818 5819 } 5820 5821 // Line intersects triangle, check if ray does. 5822 const QdN = - sign * _diff.dot( _normal$1 ); 5823 5824 // t < 0, no intersection 5825 if ( QdN < 0 ) { 5826 5827 return null; 5828 5829 } 5830 5831 // Ray intersects triangle. 5832 return this.at( QdN / DdN, target ); 5833 5834 } 5835 5836 applyMatrix4( matrix4 ) { 5837 5838 this.origin.applyMatrix4( matrix4 ); 5839 this.direction.transformDirection( matrix4 ); 5840 5841 return this; 5842 5843 } 5844 5845 equals( ray ) { 5846 5847 return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); 5848 5849 } 5850 5851 clone() { 5852 5853 return new this.constructor().copy( this ); 5854 5855 } 5856 5857} 5858 5859class Matrix4 { 5860 5861 constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { 5862 5863 Matrix4.prototype.isMatrix4 = true; 5864 5865 this.elements = [ 5866 5867 1, 0, 0, 0, 5868 0, 1, 0, 0, 5869 0, 0, 1, 0, 5870 0, 0, 0, 1 5871 5872 ]; 5873 5874 if ( n11 !== undefined ) { 5875 5876 this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ); 5877 5878 } 5879 5880 } 5881 5882 set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { 5883 5884 const te = this.elements; 5885 5886 te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14; 5887 te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24; 5888 te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34; 5889 te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44; 5890 5891 return this; 5892 5893 } 5894 5895 identity() { 5896 5897 this.set( 5898 5899 1, 0, 0, 0, 5900 0, 1, 0, 0, 5901 0, 0, 1, 0, 5902 0, 0, 0, 1 5903 5904 ); 5905 5906 return this; 5907 5908 } 5909 5910 clone() { 5911 5912 return new Matrix4().fromArray( this.elements ); 5913 5914 } 5915 5916 copy( m ) { 5917 5918 const te = this.elements; 5919 const me = m.elements; 5920 5921 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ]; 5922 te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; 5923 te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ]; 5924 te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ]; 5925 5926 return this; 5927 5928 } 5929 5930 copyPosition( m ) { 5931 5932 const te = this.elements, me = m.elements; 5933 5934 te[ 12 ] = me[ 12 ]; 5935 te[ 13 ] = me[ 13 ]; 5936 te[ 14 ] = me[ 14 ]; 5937 5938 return this; 5939 5940 } 5941 5942 setFromMatrix3( m ) { 5943 5944 const me = m.elements; 5945 5946 this.set( 5947 5948 me[ 0 ], me[ 3 ], me[ 6 ], 0, 5949 me[ 1 ], me[ 4 ], me[ 7 ], 0, 5950 me[ 2 ], me[ 5 ], me[ 8 ], 0, 5951 0, 0, 0, 1 5952 5953 ); 5954 5955 return this; 5956 5957 } 5958 5959 extractBasis( xAxis, yAxis, zAxis ) { 5960 5961 xAxis.setFromMatrixColumn( this, 0 ); 5962 yAxis.setFromMatrixColumn( this, 1 ); 5963 zAxis.setFromMatrixColumn( this, 2 ); 5964 5965 return this; 5966 5967 } 5968 5969 makeBasis( xAxis, yAxis, zAxis ) { 5970 5971 this.set( 5972 xAxis.x, yAxis.x, zAxis.x, 0, 5973 xAxis.y, yAxis.y, zAxis.y, 0, 5974 xAxis.z, yAxis.z, zAxis.z, 0, 5975 0, 0, 0, 1 5976 ); 5977 5978 return this; 5979 5980 } 5981 5982 extractRotation( m ) { 5983 5984 // this method does not support reflection matrices 5985 5986 const te = this.elements; 5987 const me = m.elements; 5988 5989 const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length(); 5990 const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length(); 5991 const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length(); 5992 5993 te[ 0 ] = me[ 0 ] * scaleX; 5994 te[ 1 ] = me[ 1 ] * scaleX; 5995 te[ 2 ] = me[ 2 ] * scaleX; 5996 te[ 3 ] = 0; 5997 5998 te[ 4 ] = me[ 4 ] * scaleY; 5999 te[ 5 ] = me[ 5 ] * scaleY; 6000 te[ 6 ] = me[ 6 ] * scaleY; 6001 te[ 7 ] = 0; 6002 6003 te[ 8 ] = me[ 8 ] * scaleZ; 6004 te[ 9 ] = me[ 9 ] * scaleZ; 6005 te[ 10 ] = me[ 10 ] * scaleZ; 6006 te[ 11 ] = 0; 6007 6008 te[ 12 ] = 0; 6009 te[ 13 ] = 0; 6010 te[ 14 ] = 0; 6011 te[ 15 ] = 1; 6012 6013 return this; 6014 6015 } 6016 6017 makeRotationFromEuler( euler ) { 6018 6019 const te = this.elements; 6020 6021 const x = euler.x, y = euler.y, z = euler.z; 6022 const a = Math.cos( x ), b = Math.sin( x ); 6023 const c = Math.cos( y ), d = Math.sin( y ); 6024 const e = Math.cos( z ), f = Math.sin( z ); 6025 6026 if ( euler.order === 'XYZ' ) { 6027 6028 const ae = a * e, af = a * f, be = b * e, bf = b * f; 6029 6030 te[ 0 ] = c * e; 6031 te[ 4 ] = - c * f; 6032 te[ 8 ] = d; 6033 6034 te[ 1 ] = af + be * d; 6035 te[ 5 ] = ae - bf * d; 6036 te[ 9 ] = - b * c; 6037 6038 te[ 2 ] = bf - ae * d; 6039 te[ 6 ] = be + af * d; 6040 te[ 10 ] = a * c; 6041 6042 } else if ( euler.order === 'YXZ' ) { 6043 6044 const ce = c * e, cf = c * f, de = d * e, df = d * f; 6045 6046 te[ 0 ] = ce + df * b; 6047 te[ 4 ] = de * b - cf; 6048 te[ 8 ] = a * d; 6049 6050 te[ 1 ] = a * f; 6051 te[ 5 ] = a * e; 6052 te[ 9 ] = - b; 6053 6054 te[ 2 ] = cf * b - de; 6055 te[ 6 ] = df + ce * b; 6056 te[ 10 ] = a * c; 6057 6058 } else if ( euler.order === 'ZXY' ) { 6059 6060 const ce = c * e, cf = c * f, de = d * e, df = d * f; 6061 6062 te[ 0 ] = ce - df * b; 6063 te[ 4 ] = - a * f; 6064 te[ 8 ] = de + cf * b; 6065 6066 te[ 1 ] = cf + de * b; 6067 te[ 5 ] = a * e; 6068 te[ 9 ] = df - ce * b; 6069 6070 te[ 2 ] = - a * d; 6071 te[ 6 ] = b; 6072 te[ 10 ] = a * c; 6073 6074 } else if ( euler.order === 'ZYX' ) { 6075 6076 const ae = a * e, af = a * f, be = b * e, bf = b * f; 6077 6078 te[ 0 ] = c * e; 6079 te[ 4 ] = be * d - af; 6080 te[ 8 ] = ae * d + bf; 6081 6082 te[ 1 ] = c * f; 6083 te[ 5 ] = bf * d + ae; 6084 te[ 9 ] = af * d - be; 6085 6086 te[ 2 ] = - d; 6087 te[ 6 ] = b * c; 6088 te[ 10 ] = a * c; 6089 6090 } else if ( euler.order === 'YZX' ) { 6091 6092 const ac = a * c, ad = a * d, bc = b * c, bd = b * d; 6093 6094 te[ 0 ] = c * e; 6095 te[ 4 ] = bd - ac * f; 6096 te[ 8 ] = bc * f + ad; 6097 6098 te[ 1 ] = f; 6099 te[ 5 ] = a * e; 6100 te[ 9 ] = - b * e; 6101 6102 te[ 2 ] = - d * e; 6103 te[ 6 ] = ad * f + bc; 6104 te[ 10 ] = ac - bd * f; 6105 6106 } else if ( euler.order === 'XZY' ) { 6107 6108 const ac = a * c, ad = a * d, bc = b * c, bd = b * d; 6109 6110 te[ 0 ] = c * e; 6111 te[ 4 ] = - f; 6112 te[ 8 ] = d * e; 6113 6114 te[ 1 ] = ac * f + bd; 6115 te[ 5 ] = a * e; 6116 te[ 9 ] = ad * f - bc; 6117 6118 te[ 2 ] = bc * f - ad; 6119 te[ 6 ] = b * e; 6120 te[ 10 ] = bd * f + ac; 6121 6122 } 6123 6124 // bottom row 6125 te[ 3 ] = 0; 6126 te[ 7 ] = 0; 6127 te[ 11 ] = 0; 6128 6129 // last column 6130 te[ 12 ] = 0; 6131 te[ 13 ] = 0; 6132 te[ 14 ] = 0; 6133 te[ 15 ] = 1; 6134 6135 return this; 6136 6137 } 6138 6139 makeRotationFromQuaternion( q ) { 6140 6141 return this.compose( _zero, q, _one ); 6142 6143 } 6144 6145 lookAt( eye, target, up ) { 6146 6147 const te = this.elements; 6148 6149 _z.subVectors( eye, target ); 6150 6151 if ( _z.lengthSq() === 0 ) { 6152 6153 // eye and target are in the same position 6154 6155 _z.z = 1; 6156 6157 } 6158 6159 _z.normalize(); 6160 _x.crossVectors( up, _z ); 6161 6162 if ( _x.lengthSq() === 0 ) { 6163 6164 // up and z are parallel 6165 6166 if ( Math.abs( up.z ) === 1 ) { 6167 6168 _z.x += 0.0001; 6169 6170 } else { 6171 6172 _z.z += 0.0001; 6173 6174 } 6175 6176 _z.normalize(); 6177 _x.crossVectors( up, _z ); 6178 6179 } 6180 6181 _x.normalize(); 6182 _y.crossVectors( _z, _x ); 6183 6184 te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x; 6185 te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y; 6186 te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z; 6187 6188 return this; 6189 6190 } 6191 6192 multiply( m ) { 6193 6194 return this.multiplyMatrices( this, m ); 6195 6196 } 6197 6198 premultiply( m ) { 6199 6200 return this.multiplyMatrices( m, this ); 6201 6202 } 6203 6204 multiplyMatrices( a, b ) { 6205 6206 const ae = a.elements; 6207 const be = b.elements; 6208 const te = this.elements; 6209 6210 const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ]; 6211 const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ]; 6212 const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ]; 6213 const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ]; 6214 6215 const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ]; 6216 const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ]; 6217 const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ]; 6218 const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ]; 6219 6220 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; 6221 te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; 6222 te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; 6223 te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; 6224 6225 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; 6226 te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; 6227 te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; 6228 te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; 6229 6230 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; 6231 te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; 6232 te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; 6233 te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; 6234 6235 te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; 6236 te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; 6237 te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; 6238 te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; 6239 6240 return this; 6241 6242 } 6243 6244 multiplyScalar( s ) { 6245 6246 const te = this.elements; 6247 6248 te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s; 6249 te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s; 6250 te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s; 6251 te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s; 6252 6253 return this; 6254 6255 } 6256 6257 determinant() { 6258 6259 const te = this.elements; 6260 6261 const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ]; 6262 const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ]; 6263 const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ]; 6264 const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ]; 6265 6266 //TODO: make this more efficient 6267 //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) 6268 6269 return ( 6270 n41 * ( 6271 + n14 * n23 * n32 6272 - n13 * n24 * n32 6273 - n14 * n22 * n33 6274 + n12 * n24 * n33 6275 + n13 * n22 * n34 6276 - n12 * n23 * n34 6277 ) + 6278 n42 * ( 6279 + n11 * n23 * n34 6280 - n11 * n24 * n33 6281 + n14 * n21 * n33 6282 - n13 * n21 * n34 6283 + n13 * n24 * n31 6284 - n14 * n23 * n31 6285 ) + 6286 n43 * ( 6287 + n11 * n24 * n32 6288 - n11 * n22 * n34 6289 - n14 * n21 * n32 6290 + n12 * n21 * n34 6291 + n14 * n22 * n31 6292 - n12 * n24 * n31 6293 ) + 6294 n44 * ( 6295 - n13 * n22 * n31 6296 - n11 * n23 * n32 6297 + n11 * n22 * n33 6298 + n13 * n21 * n32 6299 - n12 * n21 * n33 6300 + n12 * n23 * n31 6301 ) 6302 6303 ); 6304 6305 } 6306 6307 transpose() { 6308 6309 const te = this.elements; 6310 let tmp; 6311 6312 tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp; 6313 tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp; 6314 tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp; 6315 6316 tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp; 6317 tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp; 6318 tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp; 6319 6320 return this; 6321 6322 } 6323 6324 setPosition( x, y, z ) { 6325 6326 const te = this.elements; 6327 6328 if ( x.isVector3 ) { 6329 6330 te[ 12 ] = x.x; 6331 te[ 13 ] = x.y; 6332 te[ 14 ] = x.z; 6333 6334 } else { 6335 6336 te[ 12 ] = x; 6337 te[ 13 ] = y; 6338 te[ 14 ] = z; 6339 6340 } 6341 6342 return this; 6343 6344 } 6345 6346 invert() { 6347 6348 // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm 6349 const te = this.elements, 6350 6351 n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ], 6352 n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ], 6353 n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ], 6354 n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ], 6355 6356 t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44, 6357 t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44, 6358 t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44, 6359 t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34; 6360 6361 const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; 6362 6363 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); 6364 6365 const detInv = 1 / det; 6366 6367 te[ 0 ] = t11 * detInv; 6368 te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv; 6369 te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv; 6370 te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv; 6371 6372 te[ 4 ] = t12 * detInv; 6373 te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv; 6374 te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv; 6375 te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv; 6376 6377 te[ 8 ] = t13 * detInv; 6378 te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv; 6379 te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv; 6380 te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv; 6381 6382 te[ 12 ] = t14 * detInv; 6383 te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv; 6384 te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv; 6385 te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv; 6386 6387 return this; 6388 6389 } 6390 6391 scale( v ) { 6392 6393 const te = this.elements; 6394 const x = v.x, y = v.y, z = v.z; 6395 6396 te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; 6397 te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; 6398 te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; 6399 te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; 6400 6401 return this; 6402 6403 } 6404 6405 getMaxScaleOnAxis() { 6406 6407 const te = this.elements; 6408 6409 const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ]; 6410 const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ]; 6411 const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ]; 6412 6413 return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); 6414 6415 } 6416 6417 makeTranslation( x, y, z ) { 6418 6419 if ( x.isVector3 ) { 6420 6421 this.set( 6422 6423 1, 0, 0, x.x, 6424 0, 1, 0, x.y, 6425 0, 0, 1, x.z, 6426 0, 0, 0, 1 6427 6428 ); 6429 6430 } else { 6431 6432 this.set( 6433 6434 1, 0, 0, x, 6435 0, 1, 0, y, 6436 0, 0, 1, z, 6437 0, 0, 0, 1 6438 6439 ); 6440 6441 } 6442 6443 return this; 6444 6445 } 6446 6447 makeRotationX( theta ) { 6448 6449 const c = Math.cos( theta ), s = Math.sin( theta ); 6450 6451 this.set( 6452 6453 1, 0, 0, 0, 6454 0, c, - s, 0, 6455 0, s, c, 0, 6456 0, 0, 0, 1 6457 6458 ); 6459 6460 return this; 6461 6462 } 6463 6464 makeRotationY( theta ) { 6465 6466 const c = Math.cos( theta ), s = Math.sin( theta ); 6467 6468 this.set( 6469 6470 c, 0, s, 0, 6471 0, 1, 0, 0, 6472 - s, 0, c, 0, 6473 0, 0, 0, 1 6474 6475 ); 6476 6477 return this; 6478 6479 } 6480 6481 makeRotationZ( theta ) { 6482 6483 const c = Math.cos( theta ), s = Math.sin( theta ); 6484 6485 this.set( 6486 6487 c, - s, 0, 0, 6488 s, c, 0, 0, 6489 0, 0, 1, 0, 6490 0, 0, 0, 1 6491 6492 ); 6493 6494 return this; 6495 6496 } 6497 6498 makeRotationAxis( axis, angle ) { 6499 6500 // Based on http://www.gamedev.net/reference/articles/article1199.asp 6501 6502 const c = Math.cos( angle ); 6503 const s = Math.sin( angle ); 6504 const t = 1 - c; 6505 const x = axis.x, y = axis.y, z = axis.z; 6506 const tx = t * x, ty = t * y; 6507 6508 this.set( 6509 6510 tx * x + c, tx * y - s * z, tx * z + s * y, 0, 6511 tx * y + s * z, ty * y + c, ty * z - s * x, 0, 6512 tx * z - s * y, ty * z + s * x, t * z * z + c, 0, 6513 0, 0, 0, 1 6514 6515 ); 6516 6517 return this; 6518 6519 } 6520 6521 makeScale( x, y, z ) { 6522 6523 this.set( 6524 6525 x, 0, 0, 0, 6526 0, y, 0, 0, 6527 0, 0, z, 0, 6528 0, 0, 0, 1 6529 6530 ); 6531 6532 return this; 6533 6534 } 6535 6536 makeShear( xy, xz, yx, yz, zx, zy ) { 6537 6538 this.set( 6539 6540 1, yx, zx, 0, 6541 xy, 1, zy, 0, 6542 xz, yz, 1, 0, 6543 0, 0, 0, 1 6544 6545 ); 6546 6547 return this; 6548 6549 } 6550 6551 compose( position, quaternion, scale ) { 6552 6553 const te = this.elements; 6554 6555 const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w; 6556 const x2 = x + x, y2 = y + y, z2 = z + z; 6557 const xx = x * x2, xy = x * y2, xz = x * z2; 6558 const yy = y * y2, yz = y * z2, zz = z * z2; 6559 const wx = w * x2, wy = w * y2, wz = w * z2; 6560 6561 const sx = scale.x, sy = scale.y, sz = scale.z; 6562 6563 te[ 0 ] = ( 1 - ( yy + zz ) ) * sx; 6564 te[ 1 ] = ( xy + wz ) * sx; 6565 te[ 2 ] = ( xz - wy ) * sx; 6566 te[ 3 ] = 0; 6567 6568 te[ 4 ] = ( xy - wz ) * sy; 6569 te[ 5 ] = ( 1 - ( xx + zz ) ) * sy; 6570 te[ 6 ] = ( yz + wx ) * sy; 6571 te[ 7 ] = 0; 6572 6573 te[ 8 ] = ( xz + wy ) * sz; 6574 te[ 9 ] = ( yz - wx ) * sz; 6575 te[ 10 ] = ( 1 - ( xx + yy ) ) * sz; 6576 te[ 11 ] = 0; 6577 6578 te[ 12 ] = position.x; 6579 te[ 13 ] = position.y; 6580 te[ 14 ] = position.z; 6581 te[ 15 ] = 1; 6582 6583 return this; 6584 6585 } 6586 6587 decompose( position, quaternion, scale ) { 6588 6589 const te = this.elements; 6590 6591 let sx = _v1$5.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); 6592 const sy = _v1$5.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); 6593 const sz = _v1$5.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); 6594 6595 // if determine is negative, we need to invert one scale 6596 const det = this.determinant(); 6597 if ( det < 0 ) sx = - sx; 6598 6599 position.x = te[ 12 ]; 6600 position.y = te[ 13 ]; 6601 position.z = te[ 14 ]; 6602 6603 // scale the rotation part 6604 _m1$4.copy( this ); 6605 6606 const invSX = 1 / sx; 6607 const invSY = 1 / sy; 6608 const invSZ = 1 / sz; 6609 6610 _m1$4.elements[ 0 ] *= invSX; 6611 _m1$4.elements[ 1 ] *= invSX; 6612 _m1$4.elements[ 2 ] *= invSX; 6613 6614 _m1$4.elements[ 4 ] *= invSY; 6615 _m1$4.elements[ 5 ] *= invSY; 6616 _m1$4.elements[ 6 ] *= invSY; 6617 6618 _m1$4.elements[ 8 ] *= invSZ; 6619 _m1$4.elements[ 9 ] *= invSZ; 6620 _m1$4.elements[ 10 ] *= invSZ; 6621 6622 quaternion.setFromRotationMatrix( _m1$4 ); 6623 6624 scale.x = sx; 6625 scale.y = sy; 6626 scale.z = sz; 6627 6628 return this; 6629 6630 } 6631 6632 makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { 6633 6634 const te = this.elements; 6635 const x = 2 * near / ( right - left ); 6636 const y = 2 * near / ( top - bottom ); 6637 6638 const a = ( right + left ) / ( right - left ); 6639 const b = ( top + bottom ) / ( top - bottom ); 6640 6641 let c, d; 6642 6643 if ( coordinateSystem === WebGLCoordinateSystem ) { 6644 6645 c = - ( far + near ) / ( far - near ); 6646 d = ( -
vendor: 8,642 bytes, lines 6646-7158
6646 2 * far * near ) / ( far - near ); 6647 6648 } else if ( coordinateSystem === WebGPUCoordinateSystem ) { 6649 6650 c = - far / ( far - near ); 6651 d = ( - far * near ) / ( far - near ); 6652 6653 } else { 6654 6655 throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem ); 6656 6657 } 6658 6659 te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; 6660 te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; 6661 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; 6662 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; 6663 6664 return this; 6665 6666 } 6667 6668 makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { 6669 6670 const te = this.elements; 6671 const w = 1.0 / ( right - left ); 6672 const h = 1.0 / ( top - bottom ); 6673 const p = 1.0 / ( far - near ); 6674 6675 const x = ( right + left ) * w; 6676 const y = ( top + bottom ) * h; 6677 6678 let z, zInv; 6679 6680 if ( coordinateSystem === WebGLCoordinateSystem ) { 6681 6682 z = ( far + near ) * p; 6683 zInv = - 2 * p; 6684 6685 } else if ( coordinateSystem === WebGPUCoordinateSystem ) { 6686 6687 z = near * p; 6688 zInv = - 1 * p; 6689 6690 } else { 6691 6692 throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem ); 6693 6694 } 6695 6696 te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; 6697 te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; 6698 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = zInv; te[ 14 ] = - z; 6699 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; 6700 6701 return this; 6702 6703 } 6704 6705 equals( matrix ) { 6706 6707 const te = this.elements; 6708 const me = matrix.elements; 6709 6710 for ( let i = 0; i < 16; i ++ ) { 6711 6712 if ( te[ i ] !== me[ i ] ) return false; 6713 6714 } 6715 6716 return true; 6717 6718 } 6719 6720 fromArray( array, offset = 0 ) { 6721 6722 for ( let i = 0; i < 16; i ++ ) { 6723 6724 this.elements[ i ] = array[ i + offset ]; 6725 6726 } 6727 6728 return this; 6729 6730 } 6731 6732 toArray( array = [], offset = 0 ) { 6733 6734 const te = this.elements; 6735 6736 array[ offset ] = te[ 0 ]; 6737 array[ offset + 1 ] = te[ 1 ]; 6738 array[ offset + 2 ] = te[ 2 ]; 6739 array[ offset + 3 ] = te[ 3 ]; 6740 6741 array[ offset + 4 ] = te[ 4 ]; 6742 array[ offset + 5 ] = te[ 5 ]; 6743 array[ offset + 6 ] = te[ 6 ]; 6744 array[ offset + 7 ] = te[ 7 ]; 6745 6746 array[ offset + 8 ] = te[ 8 ]; 6747 array[ offset + 9 ] = te[ 9 ]; 6748 array[ offset + 10 ] = te[ 10 ]; 6749 array[ offset + 11 ] = te[ 11 ]; 6750 6751 array[ offset + 12 ] = te[ 12 ]; 6752 array[ offset + 13 ] = te[ 13 ]; 6753 array[ offset + 14 ] = te[ 14 ]; 6754 array[ offset + 15 ] = te[ 15 ]; 6755 6756 return array; 6757 6758 } 6759 6760} 6761 6762const _v1$5 = /*@__PURE__*/ new Vector3(); 6763const _m1$4 = /*@__PURE__*/ new Matrix4(); 6764const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 ); 6765const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 ); 6766const _x = /*@__PURE__*/ new Vector3(); 6767const _y = /*@__PURE__*/ new Vector3(); 6768const _z = /*@__PURE__*/ new Vector3(); 6769 6770const _matrix$2 = /*@__PURE__*/ new Matrix4(); 6771const _quaternion$3 = /*@__PURE__*/ new Quaternion(); 6772 6773class Euler { 6774 6775 constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) { 6776 6777 this.isEuler = true; 6778 6779 this._x = x; 6780 this._y = y; 6781 this._z = z; 6782 this._order = order; 6783 6784 } 6785 6786 get x() { 6787 6788 return this._x; 6789 6790 } 6791 6792 set x( value ) { 6793 6794 this._x = value; 6795 this._onChangeCallback(); 6796 6797 } 6798 6799 get y() { 6800 6801 return this._y; 6802 6803 } 6804 6805 set y( value ) { 6806 6807 this._y = value; 6808 this._onChangeCallback(); 6809 6810 } 6811 6812 get z() { 6813 6814 return this._z; 6815 6816 } 6817 6818 set z( value ) { 6819 6820 this._z = value; 6821 this._onChangeCallback(); 6822 6823 } 6824 6825 get order() { 6826 6827 return this._order; 6828 6829 } 6830 6831 set order( value ) { 6832 6833 this._order = value; 6834 this._onChangeCallback(); 6835 6836 } 6837 6838 set( x, y, z, order = this._order ) { 6839 6840 this._x = x; 6841 this._y = y; 6842 this._z = z; 6843 this._order = order; 6844 6845 this._onChangeCallback(); 6846 6847 return this; 6848 6849 } 6850 6851 clone() { 6852 6853 return new this.constructor( this._x, this._y, this._z, this._order ); 6854 6855 } 6856 6857 copy( euler ) { 6858 6859 this._x = euler._x; 6860 this._y = euler._y; 6861 this._z = euler._z; 6862 this._order = euler._order; 6863 6864 this._onChangeCallback(); 6865 6866 return this; 6867 6868 } 6869 6870 setFromRotationMatrix( m, order = this._order, update = true ) { 6871 6872 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 6873 6874 const te = m.elements; 6875 const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ]; 6876 const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ]; 6877 const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; 6878 6879 switch ( order ) { 6880 6881 case 'XYZ': 6882 6883 this._y = Math.asin( clamp( m13, - 1, 1 ) ); 6884 6885 if ( Math.abs( m13 ) < 0.9999999 ) { 6886 6887 this._x = Math.atan2( - m23, m33 ); 6888 this._z = Math.atan2( - m12, m11 ); 6889 6890 } else { 6891 6892 this._x = Math.atan2( m32, m22 ); 6893 this._z = 0; 6894 6895 } 6896 6897 break; 6898 6899 case 'YXZ': 6900 6901 this._x = Math.asin( - clamp( m23, - 1, 1 ) ); 6902 6903 if ( Math.abs( m23 ) < 0.9999999 ) { 6904 6905 this._y = Math.atan2( m13, m33 ); 6906 this._z = Math.atan2( m21, m22 ); 6907 6908 } else { 6909 6910 this._y = Math.atan2( - m31, m11 ); 6911 this._z = 0; 6912 6913 } 6914 6915 break; 6916 6917 case 'ZXY': 6918 6919 this._x = Math.asin( clamp( m32, - 1, 1 ) ); 6920 6921 if ( Math.abs( m32 ) < 0.9999999 ) { 6922 6923 this._y = Math.atan2( - m31, m33 ); 6924 this._z = Math.atan2( - m12, m22 ); 6925 6926 } else { 6927 6928 this._y = 0; 6929 this._z = Math.atan2( m21, m11 ); 6930 6931 } 6932 6933 break; 6934 6935 case 'ZYX': 6936 6937 this._y = Math.asin( - clamp( m31, - 1, 1 ) ); 6938 6939 if ( Math.abs( m31 ) < 0.9999999 ) { 6940 6941 this._x = Math.atan2( m32, m33 ); 6942 this._z = Math.atan2( m21, m11 ); 6943 6944 } else { 6945 6946 this._x = 0; 6947 this._z = Math.atan2( - m12, m22 ); 6948 6949 } 6950 6951 break; 6952 6953 case 'YZX': 6954 6955 this._z = Math.asin( clamp( m21, - 1, 1 ) ); 6956 6957 if ( Math.abs( m21 ) < 0.9999999 ) { 6958 6959 this._x = Math.atan2( - m23, m22 ); 6960 this._y = Math.atan2( - m31, m11 ); 6961 6962 } else { 6963 6964 this._x = 0; 6965 this._y = Math.atan2( m13, m33 ); 6966 6967 } 6968 6969 break; 6970 6971 case 'XZY': 6972 6973 this._z = Math.asin( - clamp( m12, - 1, 1 ) ); 6974 6975 if ( Math.abs( m12 ) < 0.9999999 ) { 6976 6977 this._x = Math.atan2( m32, m22 ); 6978 this._y = Math.atan2( m13, m11 ); 6979 6980 } else { 6981 6982 this._x = Math.atan2( - m23, m33 ); 6983 this._y = 0; 6984 6985 } 6986 6987 break; 6988 6989 default: 6990 6991 console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order ); 6992 6993 } 6994 6995 this._order = order; 6996 6997 if ( update === true ) this._onChangeCallback(); 6998 6999 return this; 7000 7001 } 7002 7003 setFromQuaternion( q, order, update ) { 7004 7005 _matrix$2.makeRotationFromQuaternion( q ); 7006 7007 return this.setFromRotationMatrix( _matrix$2, order, update ); 7008 7009 } 7010 7011 setFromVector3( v, order = this._order ) { 7012 7013 return this.set( v.x, v.y, v.z, order ); 7014 7015 } 7016 7017 reorder( newOrder ) { 7018 7019 // WARNING: this discards revolution information -bhouston 7020 7021 _quaternion$3.setFromEuler( this ); 7022 7023 return this.setFromQuaternion( _quaternion$3, newOrder ); 7024 7025 } 7026 7027 equals( euler ) { 7028 7029 return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); 7030 7031 } 7032 7033 fromArray( array ) { 7034 7035 this._x = array[ 0 ]; 7036 this._y = array[ 1 ]; 7037 this._z = array[ 2 ]; 7038 if ( array[ 3 ] !== undefined ) this._order = array[ 3 ]; 7039 7040 this._onChangeCallback(); 7041 7042 return this; 7043 7044 } 7045 7046 toArray( array = [], offset = 0 ) { 7047 7048 array[ offset ] = this._x; 7049 array[ offset + 1 ] = this._y; 7050 array[ offset + 2 ] = this._z; 7051 array[ offset + 3 ] = this._order; 7052 7053 return array; 7054 7055 } 7056 7057 _onChange( callback ) { 7058 7059 this._onChangeCallback = callback; 7060 7061 return this; 7062 7063 } 7064 7065 _onChangeCallback() {} 7066 7067 *[ Symbol.iterator ]() { 7068 7069 yield this._x; 7070 yield this._y; 7071 yield this._z; 7072 yield this._order; 7073 7074 } 7075 7076} 7077 7078Euler.DEFAULT_ORDER = 'XYZ'; 7079 7080class Layers { 7081 7082 constructor() { 7083 7084 this.mask = 1 | 0; 7085 7086 } 7087 7088 set( channel ) { 7089 7090 this.mask = ( 1 << channel | 0 ) >>> 0; 7091 7092 } 7093 7094 enable( channel ) { 7095 7096 this.mask |= 1 << channel | 0; 7097 7098 } 7099 7100 enableAll() { 7101 7102 this.mask = 0xffffffff | 0; 7103 7104 } 7105 7106 toggle( channel ) { 7107 7108 this.mask ^= 1 << channel | 0; 7109 7110 } 7111 7112 disable( channel ) { 7113 7114 this.mask &= ~ ( 1 << channel | 0 ); 7115 7116 } 7117 7118 disableAll() { 7119 7120 this.mask = 0; 7121 7122 } 7123 7124 test( layers ) { 7125 7126 return ( this.mask & layers.mask ) !== 0; 7127 7128 } 7129 7130 isEnabled( channel ) { 7131 7132 return ( this.mask & ( 1 << channel | 0 ) ) !== 0; 7133 7134 } 7135 7136} 7137 7138let _object3DId = 0; 7139 7140const _v1$4 = /*@__PURE__*/ new Vector3(); 7141const _q1 = /*@__PURE__*/ new Quaternion(); 7142const _m1$3 = /*@__PURE__*/ new Matrix4(); 7143const _target = /*@__PURE__*/ new Vector3(); 7144 7145const _position$3 = /*@__PURE__*/ new Vector3(); 7146const _scale$2 = /*@__PURE__*/ new Vector3(); 7147const _quaternion$2 = /*@__PURE__*/ new Quaternion(); 7148 7149const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 ); 7150const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 ); 7151const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 ); 7152 7153const _addedEvent = { type: 'added' }; 7154const _removedEvent = { type: 'removed' }; 7155 7156const _childaddedEvent = { type: 'childadded', child: null }; 7157const _childremovedEvent = { type: 'childremoved', child: null }; 7158
vendor: 9,737 bytes, lines 7159-7730
7159class Object3D extends EventDispatcher { 7160 7161 constructor() { 7162 7163 super(); 7164 7165 this.isObject3D = true; 7166 7167 Object.defineProperty( this, 'id', { value: _object3DId ++ } ); 7168 7169 this.uuid = generateUUID(); 7170 7171 this.name = ''; 7172 this.type = 'Object3D'; 7173 7174 this.parent = null; 7175 this.children = []; 7176 7177 this.up = Object3D.DEFAULT_UP.clone(); 7178 7179 const position = new Vector3(); 7180 const rotation = new Euler(); 7181 const quaternion = new Quaternion(); 7182 const scale = new Vector3( 1, 1, 1 ); 7183 7184 function onRotationChange() { 7185 7186 quaternion.setFromEuler( rotation, false ); 7187 7188 } 7189 7190 function onQuaternionChange() { 7191 7192 rotation.setFromQuaternion( quaternion, undefined, false ); 7193 7194 } 7195 7196 rotation._onChange( onRotationChange ); 7197 quaternion._onChange( onQuaternionChange ); 7198 7199 Object.defineProperties( this, { 7200 position: { 7201 configurable: true, 7202 enumerable: true, 7203 value: position 7204 }, 7205 rotation: { 7206 configurable: true, 7207 enumerable: true, 7208 value: rotation 7209 }, 7210 quaternion: { 7211 configurable: true, 7212 enumerable: true, 7213 value: quaternion 7214 }, 7215 scale: { 7216 configurable: true, 7217 enumerable: true, 7218 value: scale 7219 }, 7220 modelViewMatrix: { 7221 value: new Matrix4() 7222 }, 7223 normalMatrix: { 7224 value: new Matrix3() 7225 } 7226 } ); 7227 7228 this.matrix = new Matrix4(); 7229 this.matrixWorld = new Matrix4(); 7230 7231 this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE; 7232 7233 this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer 7234 this.matrixWorldNeedsUpdate = false; 7235 7236 this.layers = new Layers(); 7237 this.visible = true; 7238 7239 this.castShadow = false; 7240 this.receiveShadow = false; 7241 7242 this.frustumCulled = true; 7243 this.renderOrder = 0; 7244 7245 this.animations = []; 7246 7247 this.userData = {}; 7248 7249 } 7250 7251 onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} 7252 7253 onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} 7254 7255 onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {} 7256 7257 onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {} 7258 7259 applyMatrix4( matrix ) { 7260 7261 if ( this.matrixAutoUpdate ) this.updateMatrix(); 7262 7263 this.matrix.premultiply( matrix ); 7264 7265 this.matrix.decompose( this.position, this.quaternion, this.scale ); 7266 7267 } 7268 7269 applyQuaternion( q ) { 7270 7271 this.quaternion.premultiply( q ); 7272 7273 return this; 7274 7275 } 7276 7277 setRotationFromAxisAngle( axis, angle ) { 7278 7279 // assumes axis is normalized 7280 7281 this.quaternion.setFromAxisAngle( axis, angle ); 7282 7283 } 7284 7285 setRotationFromEuler( euler ) { 7286 7287 this.quaternion.setFromEuler( euler, true ); 7288 7289 } 7290 7291 setRotationFromMatrix( m ) { 7292 7293 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 7294 7295 this.quaternion.setFromRotationMatrix( m ); 7296 7297 } 7298 7299 setRotationFromQuaternion( q ) { 7300 7301 // assumes q is normalized 7302 7303 this.quaternion.copy( q ); 7304 7305 } 7306 7307 rotateOnAxis( axis, angle ) { 7308 7309 // rotate object on axis in object space 7310 // axis is assumed to be normalized 7311 7312 _q1.setFromAxisAngle( axis, angle ); 7313 7314 this.quaternion.multiply( _q1 ); 7315 7316 return this; 7317 7318 } 7319 7320 rotateOnWorldAxis( axis, angle ) { 7321 7322 // rotate object on axis in world space 7323 // axis is assumed to be normalized 7324 // method assumes no rotated parent 7325 7326 _q1.setFromAxisAngle( axis, angle ); 7327 7328 this.quaternion.premultiply( _q1 ); 7329 7330 return this; 7331 7332 } 7333 7334 rotateX( angle ) { 7335 7336 return this.rotateOnAxis( _xAxis, angle ); 7337 7338 } 7339 7340 rotateY( angle ) { 7341 7342 return this.rotateOnAxis( _yAxis, angle ); 7343 7344 } 7345 7346 rotateZ( angle ) { 7347 7348 return this.rotateOnAxis( _zAxis, angle ); 7349 7350 } 7351 7352 translateOnAxis( axis, distance ) { 7353 7354 // translate object by distance along axis in object space 7355 // axis is assumed to be normalized 7356 7357 _v1$4.copy( axis ).applyQuaternion( this.quaternion ); 7358 7359 this.position.add( _v1$4.multiplyScalar( distance ) ); 7360 7361 return this; 7362 7363 } 7364 7365 translateX( distance ) { 7366 7367 return this.translateOnAxis( _xAxis, distance ); 7368 7369 } 7370 7371 translateY( distance ) { 7372 7373 return this.translateOnAxis( _yAxis, distance ); 7374 7375 } 7376 7377 translateZ( distance ) { 7378 7379 return this.translateOnAxis( _zAxis, distance ); 7380 7381 } 7382 7383 localToWorld( vector ) { 7384 7385 this.updateWorldMatrix( true, false ); 7386 7387 return vector.applyMatrix4( this.matrixWorld ); 7388 7389 } 7390 7391 worldToLocal( vector ) { 7392 7393 this.updateWorldMatrix( true, false ); 7394 7395 return vector.applyMatrix4( _m1$3.copy( this.matrixWorld ).invert() ); 7396 7397 } 7398 7399 lookAt( x, y, z ) { 7400 7401 // This method does not support objects having non-uniformly-scaled parent(s) 7402 7403 if ( x.isVector3 ) { 7404 7405 _target.copy( x ); 7406 7407 } else { 7408 7409 _target.set( x, y, z ); 7410 7411 } 7412 7413 const parent = this.parent; 7414 7415 this.updateWorldMatrix( true, false ); 7416 7417 _position$3.setFromMatrixPosition( this.matrixWorld ); 7418 7419 if ( this.isCamera || this.isLight ) { 7420 7421 _m1$3.lookAt( _position$3, _target, this.up ); 7422 7423 } else { 7424 7425 _m1$3.lookAt( _target, _position$3, this.up ); 7426 7427 } 7428 7429 this.quaternion.setFromRotationMatrix( _m1$3 ); 7430 7431 if ( parent ) { 7432 7433 _m1$3.extractRotation( parent.matrixWorld ); 7434 _q1.setFromRotationMatrix( _m1$3 ); 7435 this.quaternion.premultiply( _q1.invert() ); 7436 7437 } 7438 7439 } 7440 7441 add( object ) { 7442 7443 if ( arguments.length > 1 ) { 7444 7445 for ( let i = 0; i < arguments.length; i ++ ) { 7446 7447 this.add( arguments[ i ] ); 7448 7449 } 7450 7451 return this; 7452 7453 } 7454 7455 if ( object === this ) { 7456 7457 console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object ); 7458 return this; 7459 7460 } 7461 7462 if ( object && object.isObject3D ) { 7463 7464 object.removeFromParent(); 7465 object.parent = this; 7466 this.children.push( object ); 7467 7468 object.dispatchEvent( _addedEvent ); 7469 7470 _childaddedEvent.child = object; 7471 this.dispatchEvent( _childaddedEvent ); 7472 _childaddedEvent.child = null; 7473 7474 } else { 7475 7476 console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object ); 7477 7478 } 7479 7480 return this; 7481 7482 } 7483 7484 remove( object ) { 7485 7486 if ( arguments.length > 1 ) { 7487 7488 for ( let i = 0; i < arguments.length; i ++ ) { 7489 7490 this.remove( arguments[ i ] ); 7491 7492 } 7493 7494 return this; 7495 7496 } 7497 7498 const index = this.children.indexOf( object ); 7499 7500 if ( index !== - 1 ) { 7501 7502 object.parent = null; 7503 this.children.splice( index, 1 ); 7504 7505 object.dispatchEvent( _removedEvent ); 7506 7507 _childremovedEvent.child = object; 7508 this.dispatchEvent( _childremovedEvent ); 7509 _childremovedEvent.child = null; 7510 7511 } 7512 7513 return this; 7514 7515 } 7516 7517 removeFromParent() { 7518 7519 const parent = this.parent; 7520 7521 if ( parent !== null ) { 7522 7523 parent.remove( this ); 7524 7525 } 7526 7527 return this; 7528 7529 } 7530 7531 clear() { 7532 7533 return this.remove( ... this.children ); 7534 7535 } 7536 7537 attach( object ) { 7538 7539 // adds object as a child of this, while maintaining the object's world transform 7540 7541 // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s) 7542 7543 this.updateWorldMatrix( true, false ); 7544 7545 _m1$3.copy( this.matrixWorld ).invert(); 7546 7547 if ( object.parent !== null ) { 7548 7549 object.parent.updateWorldMatrix( true, false ); 7550 7551 _m1$3.multiply( object.parent.matrixWorld ); 7552 7553 } 7554 7555 object.applyMatrix4( _m1$3 ); 7556 7557 object.removeFromParent(); 7558 object.parent = this; 7559 this.children.push( object ); 7560 7561 object.updateWorldMatrix( false, true ); 7562 7563 object.dispatchEvent( _addedEvent ); 7564 7565 _childaddedEvent.child = object; 7566 this.dispatchEvent( _childaddedEvent ); 7567 _childaddedEvent.child = null; 7568 7569 return this; 7570 7571 } 7572 7573 getObjectById( id ) { 7574 7575 return this.getObjectByProperty( 'id', id ); 7576 7577 } 7578 7579 getObjectByName( name ) { 7580 7581 return this.getObjectByProperty( 'name', name ); 7582 7583 } 7584 7585 getObjectByProperty( name, value ) { 7586 7587 if ( this[ name ] === value ) return this; 7588 7589 for ( let i = 0, l = this.children.length; i < l; i ++ ) { 7590 7591 const child = this.children[ i ]; 7592 const object = child.getObjectByProperty( name, value ); 7593 7594 if ( object !== undefined ) { 7595 7596 return object; 7597 7598 } 7599 7600 } 7601 7602 return undefined; 7603 7604 } 7605 7606 getObjectsByProperty( name, value, result = [] ) { 7607 7608 if ( this[ name ] === value ) result.push( this ); 7609 7610 const children = this.children; 7611 7612 for ( let i = 0, l = children.length; i < l; i ++ ) { 7613 7614 children[ i ].getObjectsByProperty( name, value, result ); 7615 7616 } 7617 7618 return result; 7619 7620 } 7621 7622 getWorldPosition( target ) { 7623 7624 this.updateWorldMatrix( true, false ); 7625 7626 return target.setFromMatrixPosition( this.matrixWorld ); 7627 7628 } 7629 7630 getWorldQuaternion( target ) { 7631 7632 this.updateWorldMatrix( true, false ); 7633 7634 this.matrixWorld.decompose( _position$3, target, _scale$2 ); 7635 7636 return target; 7637 7638 } 7639 7640 getWorldScale( target ) { 7641 7642 this.updateWorldMatrix( true, false ); 7643 7644 this.matrixWorld.decompose( _position$3, _quaternion$2, target ); 7645 7646 return target; 7647 7648 } 7649 7650 getWorldDirection( target ) { 7651 7652 this.updateWorldMatrix( true, false ); 7653 7654 const e = this.matrixWorld.elements; 7655 7656 return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize(); 7657 7658 } 7659 7660 raycast( /* raycaster, intersects */ ) {} 7661 7662 traverse( callback ) { 7663 7664 callback( this ); 7665 7666 const children = this.children; 7667 7668 for ( let i = 0, l = children.length; i < l; i ++ ) { 7669 7670 children[ i ].traverse( callback ); 7671 7672 } 7673 7674 } 7675 7676 traverseVisible( callback ) { 7677 7678 if ( this.visible === false ) return; 7679 7680 callback( this ); 7681 7682 const children = this.children; 7683 7684 for ( let i = 0, l = children.length; i < l; i ++ ) { 7685 7686 children[ i ].traverseVisible( callback ); 7687 7688 } 7689 7690 } 7691 7692 traverseAncestors( callback ) { 7693 7694 const parent = this.parent; 7695 7696 if ( parent !== null ) { 7697 7698 callback( parent ); 7699 7700 parent.traverseAncestors( callback ); 7701 7702 } 7703 7704 } 7705 7706 updateMatrix() { 7707 7708 this.matrix.compose( this.position, this.quaternion, this.scale ); 7709 7710 this.matrixWorldNeedsUpdate = true; 7711 7712 } 7713 7714 updateMatrixWorld( force ) { 7715 7716 if ( this.matrixAutoUpdate ) this.updateMatrix(); 7717 7718 if ( this.matrixWorldNeedsUpdate || force ) { 7719 7720 if ( this.parent === null ) { 7721 7722 this.matrixWorld.copy( this.matrix ); 7723 7724 } else { 7725 7726 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); 7727 7728 } 7729 7730 this.matrixWorldNeedsUpdate = false;
vendor: 3,767 bytes, lines 7731-7892
7731 7732 force = true; 7733 7734 } 7735 7736 // update children 7737 7738 const children = this.children; 7739 7740 for ( let i = 0, l = children.length; i < l; i ++ ) { 7741 7742 const child = children[ i ]; 7743 7744 if ( child.matrixWorldAutoUpdate === true || force === true ) { 7745 7746 child.updateMatrixWorld( force ); 7747 7748 } 7749 7750 } 7751 7752 } 7753 7754 updateWorldMatrix( updateParents, updateChildren ) { 7755 7756 const parent = this.parent; 7757 7758 if ( updateParents === true && parent !== null && parent.matrixWorldAutoUpdate === true ) { 7759 7760 parent.updateWorldMatrix( true, false ); 7761 7762 } 7763 7764 if ( this.matrixAutoUpdate ) this.updateMatrix(); 7765 7766 if ( this.parent === null ) { 7767 7768 this.matrixWorld.copy( this.matrix ); 7769 7770 } else { 7771 7772 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); 7773 7774 } 7775 7776 // update children 7777 7778 if ( updateChildren === true ) { 7779 7780 const children = this.children; 7781 7782 for ( let i = 0, l = children.length; i < l; i ++ ) { 7783 7784 const child = children[ i ]; 7785 7786 if ( child.matrixWorldAutoUpdate === true ) { 7787 7788 child.updateWorldMatrix( false, true ); 7789 7790 } 7791 7792 } 7793 7794 } 7795 7796 } 7797 7798 toJSON( meta ) { 7799 7800 // meta is a string when called from JSON.stringify 7801 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 7802 7803 const output = {}; 7804 7805 // meta is a hash used to collect geometries, materials. 7806 // not providing it implies that this is the root object 7807 // being serialized. 7808 if ( isRootObject ) { 7809 7810 // initialize meta obj 7811 meta = { 7812 geometries: {}, 7813 materials: {}, 7814 textures: {}, 7815 images: {}, 7816 shapes: {}, 7817 skeletons: {}, 7818 animations: {}, 7819 nodes: {} 7820 }; 7821 7822 output.metadata = { 7823 version: 4.6, 7824 type: 'Object', 7825 generator: 'Object3D.toJSON' 7826 }; 7827 7828 } 7829 7830 // standard Object3D serialization 7831 7832 const object = {}; 7833 7834 object.uuid = this.uuid; 7835 object.type = this.type; 7836 7837 if ( this.name !== '' ) object.name = this.name; 7838 if ( this.castShadow === true ) object.castShadow = true; 7839 if ( this.receiveShadow === true ) object.receiveShadow = true; 7840 if ( this.visible === false ) object.visible = false; 7841 if ( this.frustumCulled === false ) object.frustumCulled = false; 7842 if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder; 7843 if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData; 7844 7845 object.layers = this.layers.mask; 7846 object.matrix = this.matrix.toArray(); 7847 object.up = this.up.toArray(); 7848 7849 if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; 7850 7851 // object specific properties 7852 7853 if ( this.isInstancedMesh ) { 7854 7855 object.type = 'InstancedMesh'; 7856 object.count = this.count; 7857 object.instanceMatrix = this.instanceMatrix.toJSON(); 7858 if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON(); 7859 7860 } 7861 7862 if ( this.isBatchedMesh ) { 7863 7864 object.type = 'BatchedMesh'; 7865 object.perObjectFrustumCulled = this.perObjectFrustumCulled; 7866 object.sortObjects = this.sortObjects; 7867 7868 object.drawRanges = this._drawRanges; 7869 object.reservedRanges = this._reservedRanges; 7870 7871 object.visibility = this._visibility; 7872 object.active = this._active; 7873 object.bounds = this._bounds.map( bound => ( { 7874 boxInitialized: bound.boxInitialized, 7875 boxMin: bound.box.min.toArray(), 7876 boxMax: bound.box.max.toArray(), 7877 7878 sphereInitialized: bound.sphereInitialized, 7879 sphereRadius: bound.sphere.radius, 7880 sphereCenter: bound.sphere.center.toArray() 7881 } ) ); 7882 7883 object.maxGeometryCount = this._maxGeometryCount; 7884 object.maxVertexCount = this._maxVertexCount; 7885 object.maxIndexCount = this._maxIndexCount; 7886 7887 object.geometryInitialized = this._geometryInitialized; 7888 object.geometryCount = this._geometryCount; 7889 7890 object.matricesTexture = this._matricesTexture.toJSON( meta ); 7891 7892 if ( this._colorsTexture !== null ) object.colorsTexture = this._color
vendor: 16,800 bytes, lines 7892-8585
7892sTexture.toJSON( meta ); 7893 7894 if ( this.boundingSphere !== null ) { 7895 7896 object.boundingSphere = { 7897 center: object.boundingSphere.center.toArray(), 7898 radius: object.boundingSphere.radius 7899 }; 7900 7901 } 7902 7903 if ( this.boundingBox !== null ) { 7904 7905 object.boundingBox = { 7906 min: object.boundingBox.min.toArray(), 7907 max: object.boundingBox.max.toArray() 7908 }; 7909 7910 } 7911 7912 } 7913 7914 // 7915 7916 function serialize( library, element ) { 7917 7918 if ( library[ element.uuid ] === undefined ) { 7919 7920 library[ element.uuid ] = element.toJSON( meta ); 7921 7922 } 7923 7924 return element.uuid; 7925 7926 } 7927 7928 if ( this.isScene ) { 7929 7930 if ( this.background ) { 7931 7932 if ( this.background.isColor ) { 7933 7934 object.background = this.background.toJSON(); 7935 7936 } else if ( this.background.isTexture ) { 7937 7938 object.background = this.background.toJSON( meta ).uuid; 7939 7940 } 7941 7942 } 7943 7944 if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) { 7945 7946 object.environment = this.environment.toJSON( meta ).uuid; 7947 7948 } 7949 7950 } else if ( this.isMesh || this.isLine || this.isPoints ) { 7951 7952 object.geometry = serialize( meta.geometries, this.geometry ); 7953 7954 const parameters = this.geometry.parameters; 7955 7956 if ( parameters !== undefined && parameters.shapes !== undefined ) { 7957 7958 const shapes = parameters.shapes; 7959 7960 if ( Array.isArray( shapes ) ) { 7961 7962 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 7963 7964 const shape = shapes[ i ]; 7965 7966 serialize( meta.shapes, shape ); 7967 7968 } 7969 7970 } else { 7971 7972 serialize( meta.shapes, shapes ); 7973 7974 } 7975 7976 } 7977 7978 } 7979 7980 if ( this.isSkinnedMesh ) { 7981 7982 object.bindMode = this.bindMode; 7983 object.bindMatrix = this.bindMatrix.toArray(); 7984 7985 if ( this.skeleton !== undefined ) { 7986 7987 serialize( meta.skeletons, this.skeleton ); 7988 7989 object.skeleton = this.skeleton.uuid; 7990 7991 } 7992 7993 } 7994 7995 if ( this.material !== undefined ) { 7996 7997 if ( Array.isArray( this.material ) ) { 7998 7999 const uuids = []; 8000 8001 for ( let i = 0, l = this.material.length; i < l; i ++ ) { 8002 8003 uuids.push( serialize( meta.materials, this.material[ i ] ) ); 8004 8005 } 8006 8007 object.material = uuids; 8008 8009 } else { 8010 8011 object.material = serialize( meta.materials, this.material ); 8012 8013 } 8014 8015 } 8016 8017 // 8018 8019 if ( this.children.length > 0 ) { 8020 8021 object.children = []; 8022 8023 for ( let i = 0; i < this.children.length; i ++ ) { 8024 8025 object.children.push( this.children[ i ].toJSON( meta ).object ); 8026 8027 } 8028 8029 } 8030 8031 // 8032 8033 if ( this.animations.length > 0 ) { 8034 8035 object.animations = []; 8036 8037 for ( let i = 0; i < this.animations.length; i ++ ) { 8038 8039 const animation = this.animations[ i ]; 8040 8041 object.animations.push( serialize( meta.animations, animation ) ); 8042 8043 } 8044 8045 } 8046 8047 if ( isRootObject ) { 8048 8049 const geometries = extractFromCache( meta.geometries ); 8050 const materials = extractFromCache( meta.materials ); 8051 const textures = extractFromCache( meta.textures ); 8052 const images = extractFromCache( meta.images ); 8053 const shapes = extractFromCache( meta.shapes ); 8054 const skeletons = extractFromCache( meta.skeletons ); 8055 const animations = extractFromCache( meta.animations ); 8056 const nodes = extractFromCache( meta.nodes ); 8057 8058 if ( geometries.length > 0 ) output.geometries = geometries; 8059 if ( materials.length > 0 ) output.materials = materials; 8060 if ( textures.length > 0 ) output.textures = textures; 8061 if ( images.length > 0 ) output.images = images; 8062 if ( shapes.length > 0 ) output.shapes = shapes; 8063 if ( skeletons.length > 0 ) output.skeletons = skeletons; 8064 if ( animations.length > 0 ) output.animations = animations; 8065 if ( nodes.length > 0 ) output.nodes = nodes; 8066 8067 } 8068 8069 output.object = object; 8070 8071 return output; 8072 8073 // extract data from the cache hash 8074 // remove metadata on each item 8075 // and return as array 8076 function extractFromCache( cache ) { 8077 8078 const values = []; 8079 for ( const key in cache ) { 8080 8081 const data = cache[ key ]; 8082 delete data.metadata; 8083 values.push( data ); 8084 8085 } 8086 8087 return values; 8088 8089 } 8090 8091 } 8092 8093 clone( recursive ) { 8094 8095 return new this.constructor().copy( this, recursive ); 8096 8097 } 8098 8099 copy( source, recursive = true ) { 8100 8101 this.name = source.name; 8102 8103 this.up.copy( source.up ); 8104 8105 this.position.copy( source.position ); 8106 this.rotation.order = source.rotation.order; 8107 this.quaternion.copy( source.quaternion ); 8108 this.scale.copy( source.scale ); 8109 8110 this.matrix.copy( source.matrix ); 8111 this.matrixWorld.copy( source.matrixWorld ); 8112 8113 this.matrixAutoUpdate = source.matrixAutoUpdate; 8114 8115 this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate; 8116 this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; 8117 8118 this.layers.mask = source.layers.mask; 8119 this.visible = source.visible; 8120 8121 this.castShadow = source.castShadow; 8122 this.receiveShadow = source.receiveShadow; 8123 8124 this.frustumCulled = source.frustumCulled; 8125 this.renderOrder = source.renderOrder; 8126 8127 this.animations = source.animations.slice(); 8128 8129 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 8130 8131 if ( recursive === true ) { 8132 8133 for ( let i = 0; i < source.children.length; i ++ ) { 8134 8135 const child = source.children[ i ]; 8136 this.add( child.clone() ); 8137 8138 } 8139 8140 } 8141 8142 return this; 8143 8144 } 8145 8146} 8147 8148Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 ); 8149Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true; 8150Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true; 8151 8152const _v0$1 = /*@__PURE__*/ new Vector3(); 8153const _v1$3 = /*@__PURE__*/ new Vector3(); 8154const _v2$2 = /*@__PURE__*/ new Vector3(); 8155const _v3$2 = /*@__PURE__*/ new Vector3(); 8156 8157const _vab = /*@__PURE__*/ new Vector3(); 8158const _vac = /*@__PURE__*/ new Vector3(); 8159const _vbc = /*@__PURE__*/ new Vector3(); 8160const _vap = /*@__PURE__*/ new Vector3(); 8161const _vbp = /*@__PURE__*/ new Vector3(); 8162const _vcp = /*@__PURE__*/ new Vector3(); 8163 8164class Triangle { 8165 8166 constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { 8167 8168 this.a = a; 8169 this.b = b; 8170 this.c = c; 8171 8172 } 8173 8174 static getNormal( a, b, c, target ) { 8175 8176 target.subVectors( c, b ); 8177 _v0$1.subVectors( a, b ); 8178 target.cross( _v0$1 ); 8179 8180 const targetLengthSq = target.lengthSq(); 8181 if ( targetLengthSq > 0 ) { 8182 8183 return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) ); 8184 8185 } 8186 8187 return target.set( 0, 0, 0 ); 8188 8189 } 8190 8191 // static/instance method to calculate barycentric coordinates 8192 // based on: http://www.blackpawn.com/texts/pointinpoly/default.html 8193 static getBarycoord( point, a, b, c, target ) { 8194 8195 _v0$1.subVectors( c, a ); 8196 _v1$3.subVectors( b, a ); 8197 _v2$2.subVectors( point, a ); 8198 8199 const dot00 = _v0$1.dot( _v0$1 ); 8200 const dot01 = _v0$1.dot( _v1$3 ); 8201 const dot02 = _v0$1.dot( _v2$2 ); 8202 const dot11 = _v1$3.dot( _v1$3 ); 8203 const dot12 = _v1$3.dot( _v2$2 ); 8204 8205 const denom = ( dot00 * dot11 - dot01 * dot01 ); 8206 8207 // collinear or singular triangle 8208 if ( denom === 0 ) { 8209 8210 target.set( 0, 0, 0 ); 8211 return null; 8212 8213 } 8214 8215 const invDenom = 1 / denom; 8216 const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; 8217 const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; 8218 8219 // barycentric coordinates must always sum to 1 8220 return target.set( 1 - u - v, v, u ); 8221 8222 } 8223 8224 static containsPoint( point, a, b, c ) { 8225 8226 // if the triangle is degenerate then we can't contain a point 8227 if ( this.getBarycoord( point, a, b, c, _v3$2 ) === null ) { 8228 8229 return false; 8230 8231 } 8232 8233 return ( _v3$2.x >= 0 ) && ( _v3$2.y >= 0 ) && ( ( _v3$2.x + _v3$2.y ) <= 1 ); 8234 8235 } 8236 8237 static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) { 8238 8239 if ( this.getBarycoord( point, p1, p2, p3, _v3$2 ) === null ) { 8240 8241 target.x = 0; 8242 target.y = 0; 8243 if ( 'z' in target ) target.z = 0; 8244 if ( 'w' in target ) target.w = 0; 8245 return null; 8246 8247 } 8248 8249 target.setScalar( 0 ); 8250 target.addScaledVector( v1, _v3$2.x ); 8251 target.addScaledVector( v2, _v3$2.y ); 8252 target.addScaledVector( v3, _v3$2.z ); 8253 8254 return target; 8255 8256 } 8257 8258 static isFrontFacing( a, b, c, direction ) { 8259 8260 _v0$1.subVectors( c, b ); 8261 _v1$3.subVectors( a, b ); 8262 8263 // strictly front facing 8264 return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false; 8265 8266 } 8267 8268 set( a, b, c ) { 8269 8270 this.a.copy( a ); 8271 this.b.copy( b ); 8272 this.c.copy( c ); 8273 8274 return this; 8275 8276 } 8277 8278 setFromPointsAndIndices( points, i0, i1, i2 ) { 8279 8280 this.a.copy( points[ i0 ] ); 8281 this.b.copy( points[ i1 ] ); 8282 this.c.copy( points[ i2 ] ); 8283 8284 return this; 8285 8286 } 8287 8288 setFromAttributeAndIndices( attribute, i0, i1, i2 ) { 8289 8290 this.a.fromBufferAttribute( attribute, i0 ); 8291 this.b.fromBufferAttribute( attribute, i1 ); 8292 this.c.fromBufferAttribute( attribute, i2 ); 8293 8294 return this; 8295 8296 } 8297 8298 clone() { 8299 8300 return new this.constructor().copy( this ); 8301 8302 } 8303 8304 copy( triangle ) { 8305 8306 this.a.copy( triangle.a ); 8307 this.b.copy( triangle.b ); 8308 this.c.copy( triangle.c ); 8309 8310 return this; 8311 8312 } 8313 8314 getArea() { 8315 8316 _v0$1.subVectors( this.c, this.b ); 8317 _v1$3.subVectors( this.a, this.b ); 8318 8319 return _v0$1.cross( _v1$3 ).length() * 0.5; 8320 8321 } 8322 8323 getMidpoint( target ) { 8324 8325 return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); 8326 8327 } 8328 8329 getNormal( target ) { 8330 8331 return Triangle.getNormal( this.a, this.b, this.c, target ); 8332 8333 } 8334 8335 getPlane( target ) { 8336 8337 return target.setFromCoplanarPoints( this.a, this.b, this.c ); 8338 8339 } 8340 8341 getBarycoord( point, target ) { 8342 8343 return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); 8344 8345 } 8346 8347 getInterpolation( point, v1, v2, v3, target ) { 8348 8349 return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target ); 8350 8351 } 8352 8353 containsPoint( point ) { 8354 8355 return Triangle.containsPoint( point, this.a, this.b, this.c ); 8356 8357 } 8358 8359 isFrontFacing( direction ) { 8360 8361 return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); 8362 8363 } 8364 8365 intersectsBox( box ) { 8366 8367 return box.intersectsTriangle( this ); 8368 8369 } 8370 8371 closestPointToPoint( p, target ) { 8372 8373 const a = this.a, b = this.b, c = this.c; 8374 let v, w; 8375 8376 // algorithm thanks to Real-Time Collision Detection by Christer Ericson, 8377 // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., 8378 // under the accompanying license; see chapter 5.1.5 for detailed explanation. 8379 // basically, we're distinguishing which of the voronoi regions of the triangle 8380 // the point lies in with the minimum amount of redundant computation. 8381 8382 _vab.subVectors( b, a ); 8383 _vac.subVectors( c, a ); 8384 _vap.subVectors( p, a ); 8385 const d1 = _vab.dot( _vap ); 8386 const d2 = _vac.dot( _vap ); 8387 if ( d1 <= 0 && d2 <= 0 ) { 8388 8389 // vertex region of A; barycentric coords (1, 0, 0) 8390 return target.copy( a ); 8391 8392 } 8393 8394 _vbp.subVectors( p, b ); 8395 const d3 = _vab.dot( _vbp ); 8396 const d4 = _vac.dot( _vbp ); 8397 if ( d3 >= 0 && d4 <= d3 ) { 8398 8399 // vertex region of B; barycentric coords (0, 1, 0) 8400 return target.copy( b ); 8401 8402 } 8403 8404 const vc = d1 * d4 - d3 * d2; 8405 if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { 8406 8407 v = d1 / ( d1 - d3 ); 8408 // edge region of AB; barycentric coords (1-v, v, 0) 8409 return target.copy( a ).addScaledVector( _vab, v ); 8410 8411 } 8412 8413 _vcp.subVectors( p, c ); 8414 const d5 = _vab.dot( _vcp ); 8415 const d6 = _vac.dot( _vcp ); 8416 if ( d6 >= 0 && d5 <= d6 ) { 8417 8418 // vertex region of C; barycentric coords (0, 0, 1) 8419 return target.copy( c ); 8420 8421 } 8422 8423 const vb = d5 * d2 - d1 * d6; 8424 if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { 8425 8426 w = d2 / ( d2 - d6 ); 8427 // edge region of AC; barycentric coords (1-w, 0, w) 8428 return target.copy( a ).addScaledVector( _vac, w ); 8429 8430 } 8431 8432 const va = d3 * d6 - d5 * d4; 8433 if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { 8434 8435 _vbc.subVectors( c, b ); 8436 w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); 8437 // edge region of BC; barycentric coords (0, 1-w, w) 8438 return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC 8439 8440 } 8441 8442 // face region 8443 const denom = 1 / ( va + vb + vc ); 8444 // u = va * denom 8445 v = vb * denom; 8446 w = vc * denom; 8447 8448 return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); 8449 8450 } 8451 8452 equals( triangle ) { 8453 8454 return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); 8455 8456 } 8457 8458} 8459 8460const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, 8461 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, 8462 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, 8463 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, 8464 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, 8465 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, 8466 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, 8467 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, 8468 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, 8469 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, 8470 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, 8471 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, 8472 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, 8473 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, 8474 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, 8475 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, 8476 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, 8477 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, 8478 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, 8479 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, 8480 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, 8481 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, 8482 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, 8483 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; 8484 8485const _hslA = { h: 0, s: 0, l: 0 }; 8486const _hslB = { h: 0, s: 0, l: 0 }; 8487 8488function hue2rgb( p, q, t ) { 8489 8490 if ( t < 0 ) t += 1; 8491 if ( t > 1 ) t -= 1; 8492 if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; 8493 if ( t < 1 / 2 ) return q; 8494 if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); 8495 return p; 8496 8497} 8498 8499class Color { 8500 8501 constructor( r, g, b ) { 8502 8503 this.isColor = true; 8504 8505 this.r = 1; 8506 this.g = 1; 8507 this.b = 1; 8508 8509 return this.set( r, g, b ); 8510 8511 } 8512 8513 set( r, g, b ) { 8514 8515 if ( g === undefined && b === undefined ) { 8516 8517 // r is THREE.Color, hex or string 8518 8519 const value = r; 8520 8521 if ( value && value.isColor ) { 8522 8523 this.copy( value ); 8524 8525 } else if ( typeof value === 'number' ) { 8526 8527 this.setHex( value ); 8528 8529 } else if ( typeof value === 'string' ) { 8530 8531 this.setStyle( value ); 8532 8533 } 8534 8535 } else { 8536 8537 this.setRGB( r, g, b ); 8538 8539 } 8540 8541 return this; 8542 8543 } 8544 8545 setScalar( scalar ) { 8546 8547 this.r = scalar; 8548 this.g = scalar; 8549 this.b = scalar; 8550 8551 return this; 8552 8553 } 8554 8555 setHex( hex, colorSpace = SRGBColorSpace ) { 8556 8557 hex = Math.floor( hex ); 8558 8559 this.r = ( hex >> 16 & 255 ) / 255; 8560 this.g = ( hex >> 8 & 255 ) / 255; 8561 this.b = ( hex & 255 ) / 255; 8562 8563 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8564 8565 return this; 8566 8567 } 8568 8569 setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { 8570 8571 this.r = r; 8572 this.g = g; 8573 this.b = b; 8574 8575 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8576 8577 return this; 8578 8579 } 8580 8581 setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { 8582 8583 // h,s,l ranges are in 0.0 - 1.0 8584 h = euclideanModulo( h, 1 ); 8585 s = clamp
vendor: 13,496 bytes, lines 8585-9293
8585( s, 0, 1 ); 8586 l = clamp( l, 0, 1 ); 8587 8588 if ( s === 0 ) { 8589 8590 this.r = this.g = this.b = l; 8591 8592 } else { 8593 8594 const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); 8595 const q = ( 2 * l ) - p; 8596 8597 this.r = hue2rgb( q, p, h + 1 / 3 ); 8598 this.g = hue2rgb( q, p, h ); 8599 this.b = hue2rgb( q, p, h - 1 / 3 ); 8600 8601 } 8602 8603 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8604 8605 return this; 8606 8607 } 8608 8609 setStyle( style, colorSpace = SRGBColorSpace ) { 8610 8611 function handleAlpha( string ) { 8612 8613 if ( string === undefined ) return; 8614 8615 if ( parseFloat( string ) < 1 ) { 8616 8617 console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); 8618 8619 } 8620 8621 } 8622 8623 8624 let m; 8625 8626 if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) { 8627 8628 // rgb / hsl 8629 8630 let color; 8631 const name = m[ 1 ]; 8632 const components = m[ 2 ]; 8633 8634 switch ( name ) { 8635 8636 case 'rgb': 8637 case 'rgba': 8638 8639 if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { 8640 8641 // rgb(255,0,0) rgba(255,0,0,0.5) 8642 8643 handleAlpha( color[ 4 ] ); 8644 8645 return this.setRGB( 8646 Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255, 8647 Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255, 8648 Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255, 8649 colorSpace 8650 ); 8651 8652 } 8653 8654 if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { 8655 8656 // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) 8657 8658 handleAlpha( color[ 4 ] ); 8659 8660 return this.setRGB( 8661 Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100, 8662 Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100, 8663 Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100, 8664 colorSpace 8665 ); 8666 8667 } 8668 8669 break; 8670 8671 case 'hsl': 8672 case 'hsla': 8673 8674 if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { 8675 8676 // hsl(120,50%,50%) hsla(120,50%,50%,0.5) 8677 8678 handleAlpha( color[ 4 ] ); 8679 8680 return this.setHSL( 8681 parseFloat( color[ 1 ] ) / 360, 8682 parseFloat( color[ 2 ] ) / 100, 8683 parseFloat( color[ 3 ] ) / 100, 8684 colorSpace 8685 ); 8686 8687 } 8688 8689 break; 8690 8691 default: 8692 8693 console.warn( 'THREE.Color: Unknown color model ' + style ); 8694 8695 } 8696 8697 } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { 8698 8699 // hex color 8700 8701 const hex = m[ 1 ]; 8702 const size = hex.length; 8703 8704 if ( size === 3 ) { 8705 8706 // #ff0 8707 return this.setRGB( 8708 parseInt( hex.charAt( 0 ), 16 ) / 15, 8709 parseInt( hex.charAt( 1 ), 16 ) / 15, 8710 parseInt( hex.charAt( 2 ), 16 ) / 15, 8711 colorSpace 8712 ); 8713 8714 } else if ( size === 6 ) { 8715 8716 // #ff0000 8717 return this.setHex( parseInt( hex, 16 ), colorSpace ); 8718 8719 } else { 8720 8721 console.warn( 'THREE.Color: Invalid hex color ' + style ); 8722 8723 } 8724 8725 } else if ( style && style.length > 0 ) { 8726 8727 return this.setColorName( style, colorSpace ); 8728 8729 } 8730 8731 return this; 8732 8733 } 8734 8735 setColorName( style, colorSpace = SRGBColorSpace ) { 8736 8737 // color keywords 8738 const hex = _colorKeywords[ style.toLowerCase() ]; 8739 8740 if ( hex !== undefined ) { 8741 8742 // red 8743 this.setHex( hex, colorSpace ); 8744 8745 } else { 8746 8747 // unknown color 8748 console.warn( 'THREE.Color: Unknown color ' + style ); 8749 8750 } 8751 8752 return this; 8753 8754 } 8755 8756 clone() { 8757 8758 return new this.constructor( this.r, this.g, this.b ); 8759 8760 } 8761 8762 copy( color ) { 8763 8764 this.r = color.r; 8765 this.g = color.g; 8766 this.b = color.b; 8767 8768 return this; 8769 8770 } 8771 8772 copySRGBToLinear( color ) { 8773 8774 this.r = SRGBToLinear( color.r ); 8775 this.g = SRGBToLinear( color.g ); 8776 this.b = SRGBToLinear( color.b ); 8777 8778 return this; 8779 8780 } 8781 8782 copyLinearToSRGB( color ) { 8783 8784 this.r = LinearToSRGB( color.r ); 8785 this.g = LinearToSRGB( color.g ); 8786 this.b = LinearToSRGB( color.b ); 8787 8788 return this; 8789 8790 } 8791 8792 convertSRGBToLinear() { 8793 8794 this.copySRGBToLinear( this ); 8795 8796 return this; 8797 8798 } 8799 8800 convertLinearToSRGB() { 8801 8802 this.copyLinearToSRGB( this ); 8803 8804 return this; 8805 8806 } 8807 8808 getHex( colorSpace = SRGBColorSpace ) { 8809 8810 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 8811 8812 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 ) ); 8813 8814 } 8815 8816 getHexString( colorSpace = SRGBColorSpace ) { 8817 8818 return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); 8819 8820 } 8821 8822 getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { 8823 8824 // h,s,l ranges are in 0.0 - 1.0 8825 8826 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 8827 8828 const r = _color.r, g = _color.g, b = _color.b; 8829 8830 const max = Math.max( r, g, b ); 8831 const min = Math.min( r, g, b ); 8832 8833 let hue, saturation; 8834 const lightness = ( min + max ) / 2.0; 8835 8836 if ( min === max ) { 8837 8838 hue = 0; 8839 saturation = 0; 8840 8841 } else { 8842 8843 const delta = max - min; 8844 8845 saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); 8846 8847 switch ( max ) { 8848 8849 case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; 8850 case g: hue = ( b - r ) / delta + 2; break; 8851 case b: hue = ( r - g ) / delta + 4; break; 8852 8853 } 8854 8855 hue /= 6; 8856 8857 } 8858 8859 target.h = hue; 8860 target.s = saturation; 8861 target.l = lightness; 8862 8863 return target; 8864 8865 } 8866 8867 getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { 8868 8869 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 8870 8871 target.r = _color.r; 8872 target.g = _color.g; 8873 target.b = _color.b; 8874 8875 return target; 8876 8877 } 8878 8879 getStyle( colorSpace = SRGBColorSpace ) { 8880 8881 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 8882 8883 const r = _color.r, g = _color.g, b = _color.b; 8884 8885 if ( colorSpace !== SRGBColorSpace ) { 8886 8887 // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). 8888 return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`; 8889 8890 } 8891 8892 return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`; 8893 8894 } 8895 8896 offsetHSL( h, s, l ) { 8897 8898 this.getHSL( _hslA ); 8899 8900 return this.setHSL( _hslA.h + h, _hslA.s + s, _hslA.l + l ); 8901 8902 } 8903 8904 add( color ) { 8905 8906 this.r += color.r; 8907 this.g += color.g; 8908 this.b += color.b; 8909 8910 return this; 8911 8912 } 8913 8914 addColors( color1, color2 ) { 8915 8916 this.r = color1.r + color2.r; 8917 this.g = color1.g + color2.g; 8918 this.b = color1.b + color2.b; 8919 8920 return this; 8921 8922 } 8923 8924 addScalar( s ) { 8925 8926 this.r += s; 8927 this.g += s; 8928 this.b += s; 8929 8930 return this; 8931 8932 } 8933 8934 sub( color ) { 8935 8936 this.r = Math.max( 0, this.r - color.r ); 8937 this.g = Math.max( 0, this.g - color.g ); 8938 this.b = Math.max( 0, this.b - color.b ); 8939 8940 return this; 8941 8942 } 8943 8944 multiply( color ) { 8945 8946 this.r *= color.r; 8947 this.g *= color.g; 8948 this.b *= color.b; 8949 8950 return this; 8951 8952 } 8953 8954 multiplyScalar( s ) { 8955 8956 this.r *= s; 8957 this.g *= s; 8958 this.b *= s; 8959 8960 return this; 8961 8962 } 8963 8964 lerp( color, alpha ) { 8965 8966 this.r += ( color.r - this.r ) * alpha; 8967 this.g += ( color.g - this.g ) * alpha; 8968 this.b += ( color.b - this.b ) * alpha; 8969 8970 return this; 8971 8972 } 8973 8974 lerpColors( color1, color2, alpha ) { 8975 8976 this.r = color1.r + ( color2.r - color1.r ) * alpha; 8977 this.g = color1.g + ( color2.g - color1.g ) * alpha; 8978 this.b = color1.b + ( color2.b - color1.b ) * alpha; 8979 8980 return this; 8981 8982 } 8983 8984 lerpHSL( color, alpha ) { 8985 8986 this.getHSL( _hslA ); 8987 color.getHSL( _hslB ); 8988 8989 const h = lerp( _hslA.h, _hslB.h, alpha ); 8990 const s = lerp( _hslA.s, _hslB.s, alpha ); 8991 const l = lerp( _hslA.l, _hslB.l, alpha ); 8992 8993 this.setHSL( h, s, l ); 8994 8995 return this; 8996 8997 } 8998 8999 setFromVector3( v ) { 9000 9001 this.r = v.x; 9002 this.g = v.y; 9003 this.b = v.z; 9004 9005 return this; 9006 9007 } 9008 9009 applyMatrix3( m ) { 9010 9011 const r = this.r, g = this.g, b = this.b; 9012 const e = m.elements; 9013 9014 this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b; 9015 this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b; 9016 this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b; 9017 9018 return this; 9019 9020 } 9021 9022 equals( c ) { 9023 9024 return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); 9025 9026 } 9027 9028 fromArray( array, offset = 0 ) { 9029 9030 this.r = array[ offset ]; 9031 this.g = array[ offset + 1 ]; 9032 this.b = array[ offset + 2 ]; 9033 9034 return this; 9035 9036 } 9037 9038 toArray( array = [], offset = 0 ) { 9039 9040 array[ offset ] = this.r; 9041 array[ offset + 1 ] = this.g; 9042 array[ offset + 2 ] = this.b; 9043 9044 return array; 9045 9046 } 9047 9048 fromBufferAttribute( attribute, index ) { 9049 9050 this.r = attribute.getX( index ); 9051 this.g = attribute.getY( index ); 9052 this.b = attribute.getZ( index ); 9053 9054 return this; 9055 9056 } 9057 9058 toJSON() { 9059 9060 return this.getHex(); 9061 9062 } 9063 9064 *[ Symbol.iterator ]() { 9065 9066 yield this.r; 9067 yield this.g; 9068 yield this.b; 9069 9070 } 9071 9072} 9073 9074const _color = /*@__PURE__*/ new Color(); 9075 9076Color.NAMES = _colorKeywords; 9077 9078let _materialId = 0; 9079 9080class Material extends EventDispatcher { 9081 9082 constructor() { 9083 9084 super(); 9085 9086 this.isMaterial = true; 9087 9088 Object.defineProperty( this, 'id', { value: _materialId ++ } ); 9089 9090 this.uuid = generateUUID(); 9091 9092 this.name = ''; 9093 this.type = 'Material'; 9094 9095 this.blending = NormalBlending; 9096 this.side = FrontSide; 9097 this.vertexColors = false; 9098 9099 this.opacity = 1; 9100 this.transparent = false; 9101 this.alphaHash = false; 9102 9103 this.blendSrc = SrcAlphaFactor; 9104 this.blendDst = OneMinusSrcAlphaFactor; 9105 this.blendEquation = AddEquation; 9106 this.blendSrcAlpha = null; 9107 this.blendDstAlpha = null; 9108 this.blendEquationAlpha = null; 9109 this.blendColor = new Color( 0, 0, 0 ); 9110 this.blendAlpha = 0; 9111 9112 this.depthFunc = LessEqualDepth; 9113 this.depthTest = true; 9114 this.depthWrite = true; 9115 9116 this.stencilWriteMask = 0xff; 9117 this.stencilFunc = AlwaysStencilFunc; 9118 this.stencilRef = 0; 9119 this.stencilFuncMask = 0xff; 9120 this.stencilFail = KeepStencilOp; 9121 this.stencilZFail = KeepStencilOp; 9122 this.stencilZPass = KeepStencilOp; 9123 this.stencilWrite = false; 9124 9125 this.clippingPlanes = null; 9126 this.clipIntersection = false; 9127 this.clipShadows = false; 9128 9129 this.shadowSide = null; 9130 9131 this.colorWrite = true; 9132 9133 this.precision = null; // override the renderer's default precision for this material 9134 9135 this.polygonOffset = false; 9136 this.polygonOffsetFactor = 0; 9137 this.polygonOffsetUnits = 0; 9138 9139 this.dithering = false; 9140 9141 this.alphaToCoverage = false; 9142 this.premultipliedAlpha = false; 9143 this.forceSinglePass = false; 9144 9145 this.visible = true; 9146 9147 this.toneMapped = true; 9148 9149 this.userData = {}; 9150 9151 this.version = 0; 9152 9153 this._alphaTest = 0; 9154 9155 } 9156 9157 get alphaTest() { 9158 9159 return this._alphaTest; 9160 9161 } 9162 9163 set alphaTest( value ) { 9164 9165 if ( this._alphaTest > 0 !== value > 0 ) { 9166 9167 this.version ++; 9168 9169 } 9170 9171 this._alphaTest = value; 9172 9173 } 9174 9175 onBuild( /* shaderobject, renderer */ ) {} 9176 9177 onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} 9178 9179 onBeforeCompile( /* shaderobject, renderer */ ) {} 9180 9181 customProgramCacheKey() { 9182 9183 return this.onBeforeCompile.toString(); 9184 9185 } 9186 9187 setValues( values ) { 9188 9189 if ( values === undefined ) return; 9190 9191 for ( const key in values ) { 9192 9193 const newValue = values[ key ]; 9194 9195 if ( newValue === undefined ) { 9196 9197 console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` ); 9198 continue; 9199 9200 } 9201 9202 const currentValue = this[ key ]; 9203 9204 if ( currentValue === undefined ) { 9205 9206 console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` ); 9207 continue; 9208 9209 } 9210 9211 if ( currentValue && currentValue.isColor ) { 9212 9213 currentValue.set( newValue ); 9214 9215 } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { 9216 9217 currentValue.copy( newValue ); 9218 9219 } else { 9220 9221 this[ key ] = newValue; 9222 9223 } 9224 9225 } 9226 9227 } 9228 9229 toJSON( meta ) { 9230 9231 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 9232 9233 if ( isRootObject ) { 9234 9235 meta = { 9236 textures: {}, 9237 images: {} 9238 }; 9239 9240 } 9241 9242 const data = { 9243 metadata: { 9244 version: 4.6, 9245 type: 'Material', 9246 generator: 'Material.toJSON' 9247 } 9248 }; 9249 9250 // standard Material serialization 9251 data.uuid = this.uuid; 9252 data.type = this.type; 9253 9254 if ( this.name !== '' ) data.name = this.name; 9255 9256 if ( this.color && this.color.isColor ) data.color = this.color.getHex(); 9257 9258 if ( this.roughness !== undefined ) data.roughness = this.roughness; 9259 if ( this.metalness !== undefined ) data.metalness = this.metalness; 9260 9261 if ( this.sheen !== undefined ) data.sheen = this.sheen; 9262 if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); 9263 if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; 9264 if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); 9265 if ( this.emissiveIntensity !== undefined && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; 9266 9267 if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); 9268 if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; 9269 if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); 9270 if ( this.shininess !== undefined ) data.shininess = this.shininess; 9271 if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; 9272 if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; 9273 9274 if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { 9275 9276 data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; 9277 9278 } 9279 9280 if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { 9281 9282 data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; 9283 9284 } 9285 9286 if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { 9287 9288 data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; 9289 data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); 9290 9291 } 9292 9293 if ( this.dispersion !== undefined ) data.dispersion = this.dispersion;
vendor: 12,287 bytes, lines 9293-9674
9293 9294 9295 if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; 9296 if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; 9297 if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; 9298 9299 if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { 9300 9301 data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; 9302 9303 } 9304 9305 if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { 9306 9307 data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; 9308 9309 } 9310 9311 if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy; 9312 if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation; 9313 9314 if ( this.anisotropyMap && this.anisotropyMap.isTexture ) { 9315 9316 data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid; 9317 9318 } 9319 9320 if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; 9321 if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; 9322 if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; 9323 9324 if ( this.lightMap && this.lightMap.isTexture ) { 9325 9326 data.lightMap = this.lightMap.toJSON( meta ).uuid; 9327 data.lightMapIntensity = this.lightMapIntensity; 9328 9329 } 9330 9331 if ( this.aoMap && this.aoMap.isTexture ) { 9332 9333 data.aoMap = this.aoMap.toJSON( meta ).uuid; 9334 data.aoMapIntensity = this.aoMapIntensity; 9335 9336 } 9337 9338 if ( this.bumpMap && this.bumpMap.isTexture ) { 9339 9340 data.bumpMap = this.bumpMap.toJSON( meta ).uuid; 9341 data.bumpScale = this.bumpScale; 9342 9343 } 9344 9345 if ( this.normalMap && this.normalMap.isTexture ) { 9346 9347 data.normalMap = this.normalMap.toJSON( meta ).uuid; 9348 data.normalMapType = this.normalMapType; 9349 data.normalScale = this.normalScale.toArray(); 9350 9351 } 9352 9353 if ( this.displacementMap && this.displacementMap.isTexture ) { 9354 9355 data.displacementMap = this.displacementMap.toJSON( meta ).uuid; 9356 data.displacementScale = this.displacementScale; 9357 data.displacementBias = this.displacementBias; 9358 9359 } 9360 9361 if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; 9362 if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; 9363 9364 if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; 9365 if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; 9366 if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; 9367 if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; 9368 9369 if ( this.envMap && this.envMap.isTexture ) { 9370 9371 data.envMap = this.envMap.toJSON( meta ).uuid; 9372 9373 if ( this.combine !== undefined ) data.combine = this.combine; 9374 9375 } 9376 9377 if ( this.envMapRotation !== undefined ) data.envMapRotation = this.envMapRotation.toArray(); 9378 if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; 9379 if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; 9380 if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; 9381 9382 if ( this.gradientMap && this.gradientMap.isTexture ) { 9383 9384 data.gradientMap = this.gradientMap.toJSON( meta ).uuid; 9385 9386 } 9387 9388 if ( this.transmission !== undefined ) data.transmission = this.transmission; 9389 if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; 9390 if ( this.thickness !== undefined ) data.thickness = this.thickness; 9391 if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; 9392 if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; 9393 if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); 9394 9395 if ( this.size !== undefined ) data.size = this.size; 9396 if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; 9397 if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; 9398 9399 if ( this.blending !== NormalBlending ) data.blending = this.blending; 9400 if ( this.side !== FrontSide ) data.side = this.side; 9401 if ( this.vertexColors === true ) data.vertexColors = true; 9402 9403 if ( this.opacity < 1 ) data.opacity = this.opacity; 9404 if ( this.transparent === true ) data.transparent = true; 9405 9406 if ( this.blendSrc !== SrcAlphaFactor ) data.blendSrc = this.blendSrc; 9407 if ( this.blendDst !== OneMinusSrcAlphaFactor ) data.blendDst = this.blendDst; 9408 if ( this.blendEquation !== AddEquation ) data.blendEquation = this.blendEquation; 9409 if ( this.blendSrcAlpha !== null ) data.blendSrcAlpha = this.blendSrcAlpha; 9410 if ( this.blendDstAlpha !== null ) data.blendDstAlpha = this.blendDstAlpha; 9411 if ( this.blendEquationAlpha !== null ) data.blendEquationAlpha = this.blendEquationAlpha; 9412 if ( this.blendColor && this.blendColor.isColor ) data.blendColor = this.blendColor.getHex(); 9413 if ( this.blendAlpha !== 0 ) data.blendAlpha = this.blendAlpha; 9414 9415 if ( this.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc; 9416 if ( this.depthTest === false ) data.depthTest = this.depthTest; 9417 if ( this.depthWrite === false ) data.depthWrite = this.depthWrite; 9418 if ( this.colorWrite === false ) data.colorWrite = this.colorWrite; 9419 9420 if ( this.stencilWriteMask !== 0xff ) data.stencilWriteMask = this.stencilWriteMask; 9421 if ( this.stencilFunc !== AlwaysStencilFunc ) data.stencilFunc = this.stencilFunc; 9422 if ( this.stencilRef !== 0 ) data.stencilRef = this.stencilRef; 9423 if ( this.stencilFuncMask !== 0xff ) data.stencilFuncMask = this.stencilFuncMask; 9424 if ( this.stencilFail !== KeepStencilOp ) data.stencilFail = this.stencilFail; 9425 if ( this.stencilZFail !== KeepStencilOp ) data.stencilZFail = this.stencilZFail; 9426 if ( this.stencilZPass !== KeepStencilOp ) data.stencilZPass = this.stencilZPass; 9427 if ( this.stencilWrite === true ) data.stencilWrite = this.stencilWrite; 9428 9429 // rotation (SpriteMaterial) 9430 if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; 9431 9432 if ( this.polygonOffset === true ) data.polygonOffset = true; 9433 if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; 9434 if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; 9435 9436 if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; 9437 if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; 9438 if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; 9439 if ( this.scale !== undefined ) data.scale = this.scale; 9440 9441 if ( this.dithering === true ) data.dithering = true; 9442 9443 if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; 9444 if ( this.alphaHash === true ) data.alphaHash = true; 9445 if ( this.alphaToCoverage === true ) data.alphaToCoverage = true; 9446 if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = true; 9447 if ( this.forceSinglePass === true ) data.forceSinglePass = true; 9448 9449 if ( this.wireframe === true ) data.wireframe = true; 9450 if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; 9451 if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; 9452 if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; 9453 9454 if ( this.flatShading === true ) data.flatShading = true; 9455 9456 if ( this.visible === false ) data.visible = false; 9457 9458 if ( this.toneMapped === false ) data.toneMapped = false; 9459 9460 if ( this.fog === false ) data.fog = false; 9461 9462 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; 9463 9464 // TODO: Copied from Object3D.toJSON 9465 9466 function extractFromCache( cache ) { 9467 9468 const values = []; 9469 9470 for ( const key in cache ) { 9471 9472 const data = cache[ key ]; 9473 delete data.metadata; 9474 values.push( data ); 9475 9476 } 9477 9478 return values; 9479 9480 } 9481 9482 if ( isRootObject ) { 9483 9484 const textures = extractFromCache( meta.textures ); 9485 const images = extractFromCache( meta.images ); 9486 9487 if ( textures.length > 0 ) data.textures = textures; 9488 if ( images.length > 0 ) data.images = images; 9489 9490 } 9491 9492 return data; 9493 9494 } 9495 9496 clone() { 9497 9498 return new this.constructor().copy( this ); 9499 9500 } 9501 9502 copy( source ) { 9503 9504 this.name = source.name; 9505 9506 this.blending = source.blending; 9507 this.side = source.side; 9508 this.vertexColors = source.vertexColors; 9509 9510 this.opacity = source.opacity; 9511 this.transparent = source.transparent; 9512 9513 this.blendSrc = source.blendSrc; 9514 this.blendDst = source.blendDst; 9515 this.blendEquation = source.blendEquation; 9516 this.blendSrcAlpha = source.blendSrcAlpha; 9517 this.blendDstAlpha = source.blendDstAlpha; 9518 this.blendEquationAlpha = source.blendEquationAlpha; 9519 this.blendColor.copy( source.blendColor ); 9520 this.blendAlpha = source.blendAlpha; 9521 9522 this.depthFunc = source.depthFunc; 9523 this.depthTest = source.depthTest; 9524 this.depthWrite = source.depthWrite; 9525 9526 this.stencilWriteMask = source.stencilWriteMask; 9527 this.stencilFunc = source.stencilFunc; 9528 this.stencilRef = source.stencilRef; 9529 this.stencilFuncMask = source.stencilFuncMask; 9530 this.stencilFail = source.stencilFail; 9531 this.stencilZFail = source.stencilZFail; 9532 this.stencilZPass = source.stencilZPass; 9533 this.stencilWrite = source.stencilWrite; 9534 9535 const srcPlanes = source.clippingPlanes; 9536 let dstPlanes = null; 9537 9538 if ( srcPlanes !== null ) { 9539 9540 const n = srcPlanes.length; 9541 dstPlanes = new Array( n ); 9542 9543 for ( let i = 0; i !== n; ++ i ) { 9544 9545 dstPlanes[ i ] = srcPlanes[ i ].clone(); 9546 9547 } 9548 9549 } 9550 9551 this.clippingPlanes = dstPlanes; 9552 this.clipIntersection = source.clipIntersection; 9553 this.clipShadows = source.clipShadows; 9554 9555 this.shadowSide = source.shadowSide; 9556 9557 this.colorWrite = source.colorWrite; 9558 9559 this.precision = source.precision; 9560 9561 this.polygonOffset = source.polygonOffset; 9562 this.polygonOffsetFactor = source.polygonOffsetFactor; 9563 this.polygonOffsetUnits = source.polygonOffsetUnits; 9564 9565 this.dithering = source.dithering; 9566 9567 this.alphaTest = source.alphaTest; 9568 this.alphaHash = source.alphaHash; 9569 this.alphaToCoverage = source.alphaToCoverage; 9570 this.premultipliedAlpha = source.premultipliedAlpha; 9571 this.forceSinglePass = source.forceSinglePass; 9572 9573 this.visible = source.visible; 9574 9575 this.toneMapped = source.toneMapped; 9576 9577 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 9578 9579 return this; 9580 9581 } 9582 9583 dispose() { 9584 9585 this.dispatchEvent( { type: 'dispose' } ); 9586 9587 } 9588 9589 set needsUpdate( value ) { 9590 9591 if ( value === true ) this.version ++; 9592 9593 } 9594 9595} 9596 9597class MeshBasicMaterial extends Material { 9598 9599 constructor( parameters ) { 9600 9601 super(); 9602 9603 this.isMeshBasicMaterial = true; 9604 9605 this.type = 'MeshBasicMaterial'; 9606 9607 this.color = new Color( 0xffffff ); // emissive 9608 9609 this.map = null; 9610 9611 this.lightMap = null; 9612 this.lightMapIntensity = 1.0; 9613 9614 this.aoMap = null; 9615 this.aoMapIntensity = 1.0; 9616 9617 this.specularMap = null; 9618 9619 this.alphaMap = null; 9620 9621 this.envMap = null; 9622 this.envMapRotation = new Euler(); 9623 this.combine = MultiplyOperation; 9624 this.reflectivity = 1; 9625 this.refractionRatio = 0.98; 9626 9627 this.wireframe = false; 9628 this.wireframeLinewidth = 1; 9629 this.wireframeLinecap = 'round'; 9630 this.wireframeLinejoin = 'round'; 9631 9632 this.fog = true; 9633 9634 this.setValues( parameters ); 9635 9636 } 9637 9638 copy( source ) { 9639 9640 super.copy( source ); 9641 9642 this.color.copy( source.color ); 9643 9644 this.map = source.map; 9645 9646 this.lightMap = source.lightMap; 9647 this.lightMapIntensity = source.lightMapIntensity; 9648 9649 this.aoMap = source.aoMap; 9650 this.aoMapIntensity = source.aoMapIntensity; 9651 9652 this.specularMap = source.specularMap; 9653 9654 this.alphaMap = source.alphaMap; 9655 9656 this.envMap = source.envMap; 9657 this.envMapRotation.copy( source.envMapRotation ); 9658 this.combine = source.combine; 9659 this.reflectivity = source.reflectivity; 9660 this.refractionRatio = source.refractionRatio; 9661 9662 this.wireframe = source.wireframe; 9663 this.wireframeLinewidth = source.wireframeLinewidth; 9664 this.wireframeLinecap = source.wireframeLinecap; 9665 this.wireframeLinejoin = source.wireframeLinejoin; 9666 9667 this.fog = source.fog; 9668 9669 return this; 9670 9671 } 9672 9673} 9674
vendor: 4,666 bytes, lines 9675-9913
9675// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf 9676 9677const _tables = /*@__PURE__*/ _generateTables(); 9678 9679function _generateTables() { 9680 9681 // float32 to float16 helpers 9682 9683 const buffer = new ArrayBuffer( 4 ); 9684 const floatView = new Float32Array( buffer ); 9685 const uint32View = new Uint32Array( buffer ); 9686 9687 const baseTable = new Uint32Array( 512 ); 9688 const shiftTable = new Uint32Array( 512 ); 9689 9690 for ( let i = 0; i < 256; ++ i ) { 9691 9692 const e = i - 127; 9693 9694 // very small number (0, -0) 9695 9696 if ( e < - 27 ) { 9697 9698 baseTable[ i ] = 0x0000; 9699 baseTable[ i | 0x100 ] = 0x8000; 9700 shiftTable[ i ] = 24; 9701 shiftTable[ i | 0x100 ] = 24; 9702 9703 // small number (denorm) 9704 9705 } else if ( e < - 14 ) { 9706 9707 baseTable[ i ] = 0x0400 >> ( - e - 14 ); 9708 baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000; 9709 shiftTable[ i ] = - e - 1; 9710 shiftTable[ i | 0x100 ] = - e - 1; 9711 9712 // normal number 9713 9714 } else if ( e <= 15 ) { 9715 9716 baseTable[ i ] = ( e + 15 ) << 10; 9717 baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000; 9718 shiftTable[ i ] = 13; 9719 shiftTable[ i | 0x100 ] = 13; 9720 9721 // large number (Infinity, -Infinity) 9722 9723 } else if ( e < 128 ) { 9724 9725 baseTable[ i ] = 0x7c00; 9726 baseTable[ i | 0x100 ] = 0xfc00; 9727 shiftTable[ i ] = 24; 9728 shiftTable[ i | 0x100 ] = 24; 9729 9730 // stay (NaN, Infinity, -Infinity) 9731 9732 } else { 9733 9734 baseTable[ i ] = 0x7c00; 9735 baseTable[ i | 0x100 ] = 0xfc00; 9736 shiftTable[ i ] = 13; 9737 shiftTable[ i | 0x100 ] = 13; 9738 9739 } 9740 9741 } 9742 9743 // float16 to float32 helpers 9744 9745 const mantissaTable = new Uint32Array( 2048 ); 9746 const exponentTable = new Uint32Array( 64 ); 9747 const offsetTable = new Uint32Array( 64 ); 9748 9749 for ( let i = 1; i < 1024; ++ i ) { 9750 9751 let m = i << 13; // zero pad mantissa bits 9752 let e = 0; // zero exponent 9753 9754 // normalized 9755 while ( ( m & 0x00800000 ) === 0 ) { 9756 9757 m <<= 1; 9758 e -= 0x00800000; // decrement exponent 9759 9760 } 9761 9762 m &= ~ 0x00800000; // clear leading 1 bit 9763 e += 0x38800000; // adjust bias 9764 9765 mantissaTable[ i ] = m | e; 9766 9767 } 9768 9769 for ( let i = 1024; i < 2048; ++ i ) { 9770 9771 mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 ); 9772 9773 } 9774 9775 for ( let i = 1; i < 31; ++ i ) { 9776 9777 exponentTable[ i ] = i << 23; 9778 9779 } 9780 9781 exponentTable[ 31 ] = 0x47800000; 9782 exponentTable[ 32 ] = 0x80000000; 9783 9784 for ( let i = 33; i < 63; ++ i ) { 9785 9786 exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 ); 9787 9788 } 9789 9790 exponentTable[ 63 ] = 0xc7800000; 9791 9792 for ( let i = 1; i < 64; ++ i ) { 9793 9794 if ( i !== 32 ) { 9795 9796 offsetTable[ i ] = 1024; 9797 9798 } 9799 9800 } 9801 9802 return { 9803 floatView: floatView, 9804 uint32View: uint32View, 9805 baseTable: baseTable, 9806 shiftTable: shiftTable, 9807 mantissaTable: mantissaTable, 9808 exponentTable: exponentTable, 9809 offsetTable: offsetTable 9810 }; 9811 9812} 9813 9814// float32 to float16 9815 9816function toHalfFloat( val ) { 9817 9818 if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' ); 9819 9820 val = clamp( val, - 65504, 65504 ); 9821 9822 _tables.floatView[ 0 ] = val; 9823 const f = _tables.uint32View[ 0 ]; 9824 const e = ( f >> 23 ) & 0x1ff; 9825 return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] ); 9826 9827} 9828 9829// float16 to float32 9830 9831function fromHalfFloat( val ) { 9832 9833 const m = val >> 10; 9834 _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ]; 9835 return _tables.floatView[ 0 ]; 9836 9837} 9838 9839const DataUtils = { 9840 toHalfFloat: toHalfFloat, 9841 fromHalfFloat: fromHalfFloat, 9842}; 9843 9844const _vector$9 = /*@__PURE__*/ new Vector3(); 9845const _vector2$1 = /*@__PURE__*/ new Vector2(); 9846 9847class BufferAttribute { 9848 9849 constructor( array, itemSize, normalized = false ) { 9850 9851 if ( Array.isArray( array ) ) { 9852 9853 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); 9854 9855 } 9856 9857 this.isBufferAttribute = true; 9858 9859 this.name = ''; 9860 9861 this.array = array; 9862 this.itemSize = itemSize; 9863 this.count = array !== undefined ? array.length / itemSize : 0; 9864 this.normalized = normalized; 9865 9866 this.usage = StaticDrawUsage; 9867 this._updateRange = { offset: 0, count: - 1 }; 9868 this.updateRanges = []; 9869 this.gpuType = FloatType; 9870 9871 this.version = 0; 9872 9873 } 9874 9875 onUploadCallback() {} 9876 9877 set needsUpdate( value ) { 9878 9879 if ( value === true ) this.version ++; 9880 9881 } 9882 9883 get updateRange() { 9884 9885 warnOnce( 'THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 9886 return this._updateRange; 9887 9888 } 9889 9890 setUsage( value ) { 9891 9892 this.usage = value; 9893 9894 return this; 9895 9896 } 9897 9898 addUpdateRange( start, count ) { 9899 9900 this.updateRanges.push( { start, count } ); 9901 9902 } 9903 9904 clearUpdateRanges() { 9905 9906 this.updateRanges.length = 0; 9907 9908 } 9909 9910 copy( source ) { 9911 9912 this.name = source.name; 9913 this.array = new source.array.constructor( source.array );
vendor: 8,607 bytes, lines 9914-10445
9914 this.itemSize = source.itemSize; 9915 this.count = source.count; 9916 this.normalized = source.normalized; 9917 9918 this.usage = source.usage; 9919 this.gpuType = source.gpuType; 9920 9921 return this; 9922 9923 } 9924 9925 copyAt( index1, attribute, index2 ) { 9926 9927 index1 *= this.itemSize; 9928 index2 *= attribute.itemSize; 9929 9930 for ( let i = 0, l = this.itemSize; i < l; i ++ ) { 9931 9932 this.array[ index1 + i ] = attribute.array[ index2 + i ]; 9933 9934 } 9935 9936 return this; 9937 9938 } 9939 9940 copyArray( array ) { 9941 9942 this.array.set( array ); 9943 9944 return this; 9945 9946 } 9947 9948 applyMatrix3( m ) { 9949 9950 if ( this.itemSize === 2 ) { 9951 9952 for ( let i = 0, l = this.count; i < l; i ++ ) { 9953 9954 _vector2$1.fromBufferAttribute( this, i ); 9955 _vector2$1.applyMatrix3( m ); 9956 9957 this.setXY( i, _vector2$1.x, _vector2$1.y ); 9958 9959 } 9960 9961 } else if ( this.itemSize === 3 ) { 9962 9963 for ( let i = 0, l = this.count; i < l; i ++ ) { 9964 9965 _vector$9.fromBufferAttribute( this, i ); 9966 _vector$9.applyMatrix3( m ); 9967 9968 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 9969 9970 } 9971 9972 } 9973 9974 return this; 9975 9976 } 9977 9978 applyMatrix4( m ) { 9979 9980 for ( let i = 0, l = this.count; i < l; i ++ ) { 9981 9982 _vector$9.fromBufferAttribute( this, i ); 9983 9984 _vector$9.applyMatrix4( m ); 9985 9986 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 9987 9988 } 9989 9990 return this; 9991 9992 } 9993 9994 applyNormalMatrix( m ) { 9995 9996 for ( let i = 0, l = this.count; i < l; i ++ ) { 9997 9998 _vector$9.fromBufferAttribute( this, i ); 9999 10000 _vector$9.applyNormalMatrix( m ); 10001 10002 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 10003 10004 } 10005 10006 return this; 10007 10008 } 10009 10010 transformDirection( m ) { 10011 10012 for ( let i = 0, l = this.count; i < l; i ++ ) { 10013 10014 _vector$9.fromBufferAttribute( this, i ); 10015 10016 _vector$9.transformDirection( m ); 10017 10018 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 10019 10020 } 10021 10022 return this; 10023 10024 } 10025 10026 set( value, offset = 0 ) { 10027 10028 // Matching BufferAttribute constructor, do not normalize the array. 10029 this.array.set( value, offset ); 10030 10031 return this; 10032 10033 } 10034 10035 getComponent( index, component ) { 10036 10037 let value = this.array[ index * this.itemSize + component ]; 10038 10039 if ( this.normalized ) value = denormalize( value, this.array ); 10040 10041 return value; 10042 10043 } 10044 10045 setComponent( index, component, value ) { 10046 10047 if ( this.normalized ) value = normalize( value, this.array ); 10048 10049 this.array[ index * this.itemSize + component ] = value; 10050 10051 return this; 10052 10053 } 10054 10055 getX( index ) { 10056 10057 let x = this.array[ index * this.itemSize ]; 10058 10059 if ( this.normalized ) x = denormalize( x, this.array ); 10060 10061 return x; 10062 10063 } 10064 10065 setX( index, x ) { 10066 10067 if ( this.normalized ) x = normalize( x, this.array ); 10068 10069 this.array[ index * this.itemSize ] = x; 10070 10071 return this; 10072 10073 } 10074 10075 getY( index ) { 10076 10077 let y = this.array[ index * this.itemSize + 1 ]; 10078 10079 if ( this.normalized ) y = denormalize( y, this.array ); 10080 10081 return y; 10082 10083 } 10084 10085 setY( index, y ) { 10086 10087 if ( this.normalized ) y = normalize( y, this.array ); 10088 10089 this.array[ index * this.itemSize + 1 ] = y; 10090 10091 return this; 10092 10093 } 10094 10095 getZ( index ) { 10096 10097 let z = this.array[ index * this.itemSize + 2 ]; 10098 10099 if ( this.normalized ) z = denormalize( z, this.array ); 10100 10101 return z; 10102 10103 } 10104 10105 setZ( index, z ) { 10106 10107 if ( this.normalized ) z = normalize( z, this.array ); 10108 10109 this.array[ index * this.itemSize + 2 ] = z; 10110 10111 return this; 10112 10113 } 10114 10115 getW( index ) { 10116 10117 let w = this.array[ index * this.itemSize + 3 ]; 10118 10119 if ( this.normalized ) w = denormalize( w, this.array ); 10120 10121 return w; 10122 10123 } 10124 10125 setW( index, w ) { 10126 10127 if ( this.normalized ) w = normalize( w, this.array ); 10128 10129 this.array[ index * this.itemSize + 3 ] = w; 10130 10131 return this; 10132 10133 } 10134 10135 setXY( index, x, y ) { 10136 10137 index *= this.itemSize; 10138 10139 if ( this.normalized ) { 10140 10141 x = normalize( x, this.array ); 10142 y = normalize( y, this.array ); 10143 10144 } 10145 10146 this.array[ index + 0 ] = x; 10147 this.array[ index + 1 ] = y; 10148 10149 return this; 10150 10151 } 10152 10153 setXYZ( index, x, y, z ) { 10154 10155 index *= this.itemSize; 10156 10157 if ( this.normalized ) { 10158 10159 x = normalize( x, this.array ); 10160 y = normalize( y, this.array ); 10161 z = normalize( z, this.array ); 10162 10163 } 10164 10165 this.array[ index + 0 ] = x; 10166 this.array[ index + 1 ] = y; 10167 this.array[ index + 2 ] = z; 10168 10169 return this; 10170 10171 } 10172 10173 setXYZW( index, x, y, z, w ) { 10174 10175 index *= this.itemSize; 10176 10177 if ( this.normalized ) { 10178 10179 x = normalize( x, this.array ); 10180 y = normalize( y, this.array ); 10181 z = normalize( z, this.array ); 10182 w = normalize( w, this.array ); 10183 10184 } 10185 10186 this.array[ index + 0 ] = x; 10187 this.array[ index + 1 ] = y; 10188 this.array[ index + 2 ] = z; 10189 this.array[ index + 3 ] = w; 10190 10191 return this; 10192 10193 } 10194 10195 onUpload( callback ) { 10196 10197 this.onUploadCallback = callback; 10198 10199 return this; 10200 10201 } 10202 10203 clone() { 10204 10205 return new this.constructor( this.array, this.itemSize ).copy( this ); 10206 10207 } 10208 10209 toJSON() { 10210 10211 const data = { 10212 itemSize: this.itemSize, 10213 type: this.array.constructor.name, 10214 array: Array.from( this.array ), 10215 normalized: this.normalized 10216 }; 10217 10218 if ( this.name !== '' ) data.name = this.name; 10219 if ( this.usage !== StaticDrawUsage ) data.usage = this.usage; 10220 10221 return data; 10222 10223 } 10224 10225} 10226 10227// 10228 10229class Int8BufferAttribute extends BufferAttribute { 10230 10231 constructor( array, itemSize, normalized ) { 10232 10233 super( new Int8Array( array ), itemSize, normalized ); 10234 10235 } 10236 10237} 10238 10239class Uint8BufferAttribute extends BufferAttribute { 10240 10241 constructor( array, itemSize, normalized ) { 10242 10243 super( new Uint8Array( array ), itemSize, normalized ); 10244 10245 } 10246 10247} 10248 10249class Uint8ClampedBufferAttribute extends BufferAttribute { 10250 10251 constructor( array, itemSize, normalized ) { 10252 10253 super( new Uint8ClampedArray( array ), itemSize, normalized ); 10254 10255 } 10256 10257} 10258 10259class Int16BufferAttribute extends BufferAttribute { 10260 10261 constructor( array, itemSize, normalized ) { 10262 10263 super( new Int16Array( array ), itemSize, normalized ); 10264 10265 } 10266 10267} 10268 10269class Uint16BufferAttribute extends BufferAttribute { 10270 10271 constructor( array, itemSize, normalized ) { 10272 10273 super( new Uint16Array( array ), itemSize, normalized ); 10274 10275 } 10276 10277} 10278 10279class Int32BufferAttribute extends BufferAttribute { 10280 10281 constructor( array, itemSize, normalized ) { 10282 10283 super( new Int32Array( array ), itemSize, normalized ); 10284 10285 } 10286 10287} 10288 10289class Uint32BufferAttribute extends BufferAttribute { 10290 10291 constructor( array, itemSize, normalized ) { 10292 10293 super( new Uint32Array( array ), itemSize, normalized ); 10294 10295 } 10296 10297} 10298 10299class Float16BufferAttribute extends BufferAttribute { 10300 10301 constructor( array, itemSize, normalized ) { 10302 10303 super( new Uint16Array( array ), itemSize, normalized ); 10304 10305 this.isFloat16BufferAttribute = true; 10306 10307 } 10308 10309 getX( index ) { 10310 10311 let x = fromHalfFloat( this.array[ index * this.itemSize ] ); 10312 10313 if ( this.normalized ) x = denormalize( x, this.array ); 10314 10315 return x; 10316 10317 } 10318 10319 setX( index, x ) { 10320 10321 if ( this.normalized ) x = normalize( x, this.array ); 10322 10323 this.array[ index * this.itemSize ] = toHalfFloat( x ); 10324 10325 return this; 10326 10327 } 10328 10329 getY( index ) { 10330 10331 let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] ); 10332 10333 if ( this.normalized ) y = denormalize( y, this.array ); 10334 10335 return y; 10336 10337 } 10338 10339 setY( index, y ) { 10340 10341 if ( this.normalized ) y = normalize( y, this.array ); 10342 10343 this.array[ index * this.itemSize + 1 ] = toHalfFloat( y ); 10344 10345 return this; 10346 10347 } 10348 10349 getZ( index ) { 10350 10351 let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] ); 10352 10353 if ( this.normalized ) z = denormalize( z, this.array ); 10354 10355 return z; 10356 10357 } 10358 10359 setZ( index, z ) { 10360 10361 if ( this.normalized ) z = normalize( z, this.array ); 10362 10363 this.array[ index * this.itemSize + 2 ] = toHalfFloat( z ); 10364 10365 return this; 10366 10367 } 10368 10369 getW( index ) { 10370 10371 let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] ); 10372 10373 if ( this.normalized ) w = denormalize( w, this.array ); 10374 10375 return w; 10376 10377 } 10378 10379 setW( index, w ) { 10380 10381 if ( this.normalized ) w = normalize( w, this.array ); 10382 10383 this.array[ index * this.itemSize + 3 ] = toHalfFloat( w ); 10384 10385 return this; 10386 10387 } 10388 10389 setXY( index, x, y ) { 10390 10391 index *= this.itemSize; 10392 10393 if ( this.normalized ) { 10394 10395 x = normalize( x, this.array ); 10396 y = normalize( y, this.array ); 10397 10398 } 10399 10400 this.array[ index + 0 ] = toHalfFloat( x ); 10401 this.array[ index + 1 ] = toHalfFloat( y ); 10402 10403 return this; 10404 10405 } 10406 10407 setXYZ( index, x, y, z ) { 10408 10409 index *= this.itemSize; 10410 10411 if ( this.normalized ) { 10412 10413 x = normalize( x, this.array ); 10414 y = normalize( y, this.array ); 10415 z = normalize( z, this.array ); 10416 10417 } 10418 10419 this.array[ index + 0 ] = toHalfFloat( x ); 10420 this.array[ index + 1 ] = toHalfFloat( y ); 10421 this.array[ index + 2 ] = toHalfFloat( z ); 10422 10423 return this; 10424 10425 } 10426 10427 setXYZW( index, x, y, z, w ) { 10428 10429 index *= this.itemSize; 10430 10431 if ( this.normalized ) { 10432 10433 x = normalize( x, this.array ); 10434 y = normalize( y, this.array ); 10435 z = normalize( z, this.array ); 10436 w = normalize( w, this.array ); 10437 10438 } 10439 10440 this.array[ index + 0 ] = toHalfFloat( x ); 10441 this.array[ index + 1 ] = toHalfFloat( y ); 10442 this.array[ index + 2 ] = toHalfFloat( z ); 10443 this.array[ index + 3 ] = toHalfFloat( w ); 10444 10445 return this
vendor: 11,366 bytes, lines 10445-11055
10445; 10446 10447 } 10448 10449} 10450 10451 10452class Float32BufferAttribute extends BufferAttribute { 10453 10454 constructor( array, itemSize, normalized ) { 10455 10456 super( new Float32Array( array ), itemSize, normalized ); 10457 10458 } 10459 10460} 10461 10462let _id$2 = 0; 10463 10464const _m1$2 = /*@__PURE__*/ new Matrix4(); 10465const _obj = /*@__PURE__*/ new Object3D(); 10466const _offset = /*@__PURE__*/ new Vector3(); 10467const _box$2 = /*@__PURE__*/ new Box3(); 10468const _boxMorphTargets = /*@__PURE__*/ new Box3(); 10469const _vector$8 = /*@__PURE__*/ new Vector3(); 10470 10471class BufferGeometry extends EventDispatcher { 10472 10473 constructor() { 10474 10475 super(); 10476 10477 this.isBufferGeometry = true; 10478 10479 Object.defineProperty( this, 'id', { value: _id$2 ++ } ); 10480 10481 this.uuid = generateUUID(); 10482 10483 this.name = ''; 10484 this.type = 'BufferGeometry'; 10485 10486 this.index = null; 10487 this.attributes = {}; 10488 10489 this.morphAttributes = {}; 10490 this.morphTargetsRelative = false; 10491 10492 this.groups = []; 10493 10494 this.boundingBox = null; 10495 this.boundingSphere = null; 10496 10497 this.drawRange = { start: 0, count: Infinity }; 10498 10499 this.userData = {}; 10500 10501 } 10502 10503 getIndex() { 10504 10505 return this.index; 10506 10507 } 10508 10509 setIndex( index ) { 10510 10511 if ( Array.isArray( index ) ) { 10512 10513 this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); 10514 10515 } else { 10516 10517 this.index = index; 10518 10519 } 10520 10521 return this; 10522 10523 } 10524 10525 getAttribute( name ) { 10526 10527 return this.attributes[ name ]; 10528 10529 } 10530 10531 setAttribute( name, attribute ) { 10532 10533 this.attributes[ name ] = attribute; 10534 10535 return this; 10536 10537 } 10538 10539 deleteAttribute( name ) { 10540 10541 delete this.attributes[ name ]; 10542 10543 return this; 10544 10545 } 10546 10547 hasAttribute( name ) { 10548 10549 return this.attributes[ name ] !== undefined; 10550 10551 } 10552 10553 addGroup( start, count, materialIndex = 0 ) { 10554 10555 this.groups.push( { 10556 10557 start: start, 10558 count: count, 10559 materialIndex: materialIndex 10560 10561 } ); 10562 10563 } 10564 10565 clearGroups() { 10566 10567 this.groups = []; 10568 10569 } 10570 10571 setDrawRange( start, count ) { 10572 10573 this.drawRange.start = start; 10574 this.drawRange.count = count; 10575 10576 } 10577 10578 applyMatrix4( matrix ) { 10579 10580 const position = this.attributes.position; 10581 10582 if ( position !== undefined ) { 10583 10584 position.applyMatrix4( matrix ); 10585 10586 position.needsUpdate = true; 10587 10588 } 10589 10590 const normal = this.attributes.normal; 10591 10592 if ( normal !== undefined ) { 10593 10594 const normalMatrix = new Matrix3().getNormalMatrix( matrix ); 10595 10596 normal.applyNormalMatrix( normalMatrix ); 10597 10598 normal.needsUpdate = true; 10599 10600 } 10601 10602 const tangent = this.attributes.tangent; 10603 10604 if ( tangent !== undefined ) { 10605 10606 tangent.transformDirection( matrix ); 10607 10608 tangent.needsUpdate = true; 10609 10610 } 10611 10612 if ( this.boundingBox !== null ) { 10613 10614 this.computeBoundingBox(); 10615 10616 } 10617 10618 if ( this.boundingSphere !== null ) { 10619 10620 this.computeBoundingSphere(); 10621 10622 } 10623 10624 return this; 10625 10626 } 10627 10628 applyQuaternion( q ) { 10629 10630 _m1$2.makeRotationFromQuaternion( q ); 10631 10632 this.applyMatrix4( _m1$2 ); 10633 10634 return this; 10635 10636 } 10637 10638 rotateX( angle ) { 10639 10640 // rotate geometry around world x-axis 10641 10642 _m1$2.makeRotationX( angle ); 10643 10644 this.applyMatrix4( _m1$2 ); 10645 10646 return this; 10647 10648 } 10649 10650 rotateY( angle ) { 10651 10652 // rotate geometry around world y-axis 10653 10654 _m1$2.makeRotationY( angle ); 10655 10656 this.applyMatrix4( _m1$2 ); 10657 10658 return this; 10659 10660 } 10661 10662 rotateZ( angle ) { 10663 10664 // rotate geometry around world z-axis 10665 10666 _m1$2.makeRotationZ( angle ); 10667 10668 this.applyMatrix4( _m1$2 ); 10669 10670 return this; 10671 10672 } 10673 10674 translate( x, y, z ) { 10675 10676 // translate geometry 10677 10678 _m1$2.makeTranslation( x, y, z ); 10679 10680 this.applyMatrix4( _m1$2 ); 10681 10682 return this; 10683 10684 } 10685 10686 scale( x, y, z ) { 10687 10688 // scale geometry 10689 10690 _m1$2.makeScale( x, y, z ); 10691 10692 this.applyMatrix4( _m1$2 ); 10693 10694 return this; 10695 10696 } 10697 10698 lookAt( vector ) { 10699 10700 _obj.lookAt( vector ); 10701 10702 _obj.updateMatrix(); 10703 10704 this.applyMatrix4( _obj.matrix ); 10705 10706 return this; 10707 10708 } 10709 10710 center() { 10711 10712 this.computeBoundingBox(); 10713 10714 this.boundingBox.getCenter( _offset ).negate(); 10715 10716 this.translate( _offset.x, _offset.y, _offset.z ); 10717 10718 return this; 10719 10720 } 10721 10722 setFromPoints( points ) { 10723 10724 const position = []; 10725 10726 for ( let i = 0, l = points.length; i < l; i ++ ) { 10727 10728 const point = points[ i ]; 10729 position.push( point.x, point.y, point.z || 0 ); 10730 10731 } 10732 10733 this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); 10734 10735 return this; 10736 10737 } 10738 10739 computeBoundingBox() { 10740 10741 if ( this.boundingBox === null ) { 10742 10743 this.boundingBox = new Box3(); 10744 10745 } 10746 10747 const position = this.attributes.position; 10748 const morphAttributesPosition = this.morphAttributes.position; 10749 10750 if ( position && position.isGLBufferAttribute ) { 10751 10752 console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.', this ); 10753 10754 this.boundingBox.set( 10755 new Vector3( - Infinity, - Infinity, - Infinity ), 10756 new Vector3( + Infinity, + Infinity, + Infinity ) 10757 ); 10758 10759 return; 10760 10761 } 10762 10763 if ( position !== undefined ) { 10764 10765 this.boundingBox.setFromBufferAttribute( position ); 10766 10767 // process morph attributes if present 10768 10769 if ( morphAttributesPosition ) { 10770 10771 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { 10772 10773 const morphAttribute = morphAttributesPosition[ i ]; 10774 _box$2.setFromBufferAttribute( morphAttribute ); 10775 10776 if ( this.morphTargetsRelative ) { 10777 10778 _vector$8.addVectors( this.boundingBox.min, _box$2.min ); 10779 this.boundingBox.expandByPoint( _vector$8 ); 10780 10781 _vector$8.addVectors( this.boundingBox.max, _box$2.max ); 10782 this.boundingBox.expandByPoint( _vector$8 ); 10783 10784 } else { 10785 10786 this.boundingBox.expandByPoint( _box$2.min ); 10787 this.boundingBox.expandByPoint( _box$2.max ); 10788 10789 } 10790 10791 } 10792 10793 } 10794 10795 } else { 10796 10797 this.boundingBox.makeEmpty(); 10798 10799 } 10800 10801 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { 10802 10803 console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); 10804 10805 } 10806 10807 } 10808 10809 computeBoundingSphere() { 10810 10811 if ( this.boundingSphere === null ) { 10812 10813 this.boundingSphere = new Sphere(); 10814 10815 } 10816 10817 const position = this.attributes.position; 10818 const morphAttributesPosition = this.morphAttributes.position; 10819 10820 if ( position && position.isGLBufferAttribute ) { 10821 10822 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere.', this ); 10823 10824 this.boundingSphere.set( new Vector3(), Infinity ); 10825 10826 return; 10827 10828 } 10829 10830 if ( position ) { 10831 10832 // first, find the center of the bounding sphere 10833 10834 const center = this.boundingSphere.center; 10835 10836 _box$2.setFromBufferAttribute( position ); 10837 10838 // process morph attributes if present 10839 10840 if ( morphAttributesPosition ) { 10841 10842 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { 10843 10844 const morphAttribute = morphAttributesPosition[ i ]; 10845 _boxMorphTargets.setFromBufferAttribute( morphAttribute ); 10846 10847 if ( this.morphTargetsRelative ) { 10848 10849 _vector$8.addVectors( _box$2.min, _boxMorphTargets.min ); 10850 _box$2.expandByPoint( _vector$8 ); 10851 10852 _vector$8.addVectors( _box$2.max, _boxMorphTargets.max ); 10853 _box$2.expandByPoint( _vector$8 ); 10854 10855 } else { 10856 10857 _box$2.expandByPoint( _boxMorphTargets.min ); 10858 _box$2.expandByPoint( _boxMorphTargets.max ); 10859 10860 } 10861 10862 } 10863 10864 } 10865 10866 _box$2.getCenter( center ); 10867 10868 // second, try to find a boundingSphere with a radius smaller than the 10869 // boundingSphere of the boundingBox: sqrt(3) smaller in the best case 10870 10871 let maxRadiusSq = 0; 10872 10873 for ( let i = 0, il = position.count; i < il; i ++ ) { 10874 10875 _vector$8.fromBufferAttribute( position, i ); 10876 10877 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); 10878 10879 } 10880 10881 // process morph attributes if present 10882 10883 if ( morphAttributesPosition ) { 10884 10885 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { 10886 10887 const morphAttribute = morphAttributesPosition[ i ]; 10888 const morphTargetsRelative = this.morphTargetsRelative; 10889 10890 for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) { 10891 10892 _vector$8.fromBufferAttribute( morphAttribute, j ); 10893 10894 if ( morphTargetsRelative ) { 10895 10896 _offset.fromBufferAttribute( position, j ); 10897 _vector$8.add( _offset ); 10898 10899 } 10900 10901 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); 10902 10903 } 10904 10905 } 10906 10907 } 10908 10909 this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); 10910 10911 if ( isNaN( this.boundingSphere.radius ) ) { 10912 10913 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); 10914 10915 } 10916 10917 } 10918 10919 } 10920 10921 computeTangents() { 10922 10923 const index = this.index; 10924 const attributes = this.attributes; 10925 10926 // based on http://www.terathon.com/code/tangent.html 10927 // (per vertex tangents) 10928 10929 if ( index === null || 10930 attributes.position === undefined || 10931 attributes.normal === undefined || 10932 attributes.uv === undefined ) { 10933 10934 console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' ); 10935 return; 10936 10937 } 10938 10939 const positionAttribute = attributes.position; 10940 const normalAttribute = attributes.normal; 10941 const uvAttribute = attributes.uv; 10942 10943 if ( this.hasAttribute( 'tangent' ) === false ) { 10944 10945 this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * positionAttribute.count ), 4 ) ); 10946 10947 } 10948 10949 const tangentAttribute = this.getAttribute( 'tangent' ); 10950 10951 const tan1 = [], tan2 = []; 10952 10953 for ( let i = 0; i < positionAttribute.count; i ++ ) { 10954 10955 tan1[ i ] = new Vector3(); 10956 tan2[ i ] = new Vector3(); 10957 10958 } 10959 10960 const vA = new Vector3(), 10961 vB = new Vector3(), 10962 vC = new Vector3(), 10963 10964 uvA = new Vector2(), 10965 uvB = new Vector2(), 10966 uvC = new Vector2(), 10967 10968 sdir = new Vector3(), 10969 tdir = new Vector3(); 10970 10971 function handleTriangle( a, b, c ) { 10972 10973 vA.fromBufferAttribute( positionAttribute, a ); 10974 vB.fromBufferAttribute( positionAttribute, b ); 10975 vC.fromBufferAttribute( positionAttribute, c ); 10976 10977 uvA.fromBufferAttribute( uvAttribute, a ); 10978 uvB.fromBufferAttribute( uvAttribute, b ); 10979 uvC.fromBufferAttribute( uvAttribute, c ); 10980 10981 vB.sub( vA ); 10982 vC.sub( vA ); 10983 10984 uvB.sub( uvA ); 10985 uvC.sub( uvA ); 10986 10987 const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y ); 10988 10989 // silently ignore degenerate uv triangles having coincident or colinear vertices 10990 10991 if ( ! isFinite( r ) ) return; 10992 10993 sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r ); 10994 tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r ); 10995 10996 tan1[ a ].add( sdir ); 10997 tan1[ b ].add( sdir ); 10998 tan1[ c ].add( sdir ); 10999 11000 tan2[ a ].add( tdir ); 11001 tan2[ b ].add( tdir ); 11002 tan2[ c ].add( tdir ); 11003 11004 } 11005 11006 let groups = this.groups; 11007 11008 if ( groups.length === 0 ) { 11009 11010 groups = [ { 11011 start: 0, 11012 count: index.count 11013 } ]; 11014 11015 } 11016 11017 for ( let i = 0, il = groups.length; i < il; ++ i ) { 11018 11019 const group = groups[ i ]; 11020 11021 const start = group.start; 11022 const count = group.count; 11023 11024 for ( let j = start, jl = start + count; j < jl; j += 3 ) { 11025 11026 handleTriangle( 11027 index.getX( j + 0 ), 11028 index.getX( j + 1 ), 11029 index.getX( j + 2 ) 11030 ); 11031 11032 } 11033 11034 } 11035 11036 const tmp = new Vector3(), tmp2 = new Vector3(); 11037 const n = new Vector3(), n2 = new Vector3(); 11038 11039 function handleVertex( v ) { 11040 11041 n.fromBufferAttribute( normalAttribute, v ); 11042 n2.copy( n ); 11043 11044 const t = tan1[ v ]; 11045 11046 // Gram-Schmidt orthogonalize 11047 11048 tmp.copy( t ); 11049 tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize(); 11050 11051 // Calculate handedness 11052 11053 tmp2.crossVectors( n2, t ); 11054 const test = tmp2.dot( tan2[ v ] ); 11055 const w = ( test < 0.0 ) ? -
11055 1.0
vendor: 16,831 bytes, lines 11055-11843
11055 : 1.0; 11056 11057 tangentAttribute.setXYZW( v, tmp.x, tmp.y, tmp.z, w ); 11058 11059 } 11060 11061 for ( let i = 0, il = groups.length; i < il; ++ i ) { 11062 11063 const group = groups[ i ]; 11064 11065 const start = group.start; 11066 const count = group.count; 11067 11068 for ( let j = start, jl = start + count; j < jl; j += 3 ) { 11069 11070 handleVertex( index.getX( j + 0 ) ); 11071 handleVertex( index.getX( j + 1 ) ); 11072 handleVertex( index.getX( j + 2 ) ); 11073 11074 } 11075 11076 } 11077 11078 } 11079 11080 computeVertexNormals() { 11081 11082 const index = this.index; 11083 const positionAttribute = this.getAttribute( 'position' ); 11084 11085 if ( positionAttribute !== undefined ) { 11086 11087 let normalAttribute = this.getAttribute( 'normal' ); 11088 11089 if ( normalAttribute === undefined ) { 11090 11091 normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 ); 11092 this.setAttribute( 'normal', normalAttribute ); 11093 11094 } else { 11095 11096 // reset existing normals to zero 11097 11098 for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) { 11099 11100 normalAttribute.setXYZ( i, 0, 0, 0 ); 11101 11102 } 11103 11104 } 11105 11106 const pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); 11107 const nA = new Vector3(), nB = new Vector3(), nC = new Vector3(); 11108 const cb = new Vector3(), ab = new Vector3(); 11109 11110 // indexed elements 11111 11112 if ( index ) { 11113 11114 for ( let i = 0, il = index.count; i < il; i += 3 ) { 11115 11116 const vA = index.getX( i + 0 ); 11117 const vB = index.getX( i + 1 ); 11118 const vC = index.getX( i + 2 ); 11119 11120 pA.fromBufferAttribute( positionAttribute, vA ); 11121 pB.fromBufferAttribute( positionAttribute, vB ); 11122 pC.fromBufferAttribute( positionAttribute, vC ); 11123 11124 cb.subVectors( pC, pB ); 11125 ab.subVectors( pA, pB ); 11126 cb.cross( ab ); 11127 11128 nA.fromBufferAttribute( normalAttribute, vA ); 11129 nB.fromBufferAttribute( normalAttribute, vB ); 11130 nC.fromBufferAttribute( normalAttribute, vC ); 11131 11132 nA.add( cb ); 11133 nB.add( cb ); 11134 nC.add( cb ); 11135 11136 normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z ); 11137 normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z ); 11138 normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z ); 11139 11140 } 11141 11142 } else { 11143 11144 // non-indexed elements (unconnected triangle soup) 11145 11146 for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) { 11147 11148 pA.fromBufferAttribute( positionAttribute, i + 0 ); 11149 pB.fromBufferAttribute( positionAttribute, i + 1 ); 11150 pC.fromBufferAttribute( positionAttribute, i + 2 ); 11151 11152 cb.subVectors( pC, pB ); 11153 ab.subVectors( pA, pB ); 11154 cb.cross( ab ); 11155 11156 normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z ); 11157 normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z ); 11158 normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z ); 11159 11160 } 11161 11162 } 11163 11164 this.normalizeNormals(); 11165 11166 normalAttribute.needsUpdate = true; 11167 11168 } 11169 11170 } 11171 11172 normalizeNormals() { 11173 11174 const normals = this.attributes.normal; 11175 11176 for ( let i = 0, il = normals.count; i < il; i ++ ) { 11177 11178 _vector$8.fromBufferAttribute( normals, i ); 11179 11180 _vector$8.normalize(); 11181 11182 normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); 11183 11184 } 11185 11186 } 11187 11188 toNonIndexed() { 11189 11190 function convertBufferAttribute( attribute, indices ) { 11191 11192 const array = attribute.array; 11193 const itemSize = attribute.itemSize; 11194 const normalized = attribute.normalized; 11195 11196 const array2 = new array.constructor( indices.length * itemSize ); 11197 11198 let index = 0, index2 = 0; 11199 11200 for ( let i = 0, l = indices.length; i < l; i ++ ) { 11201 11202 if ( attribute.isInterleavedBufferAttribute ) { 11203 11204 index = indices[ i ] * attribute.data.stride + attribute.offset; 11205 11206 } else { 11207 11208 index = indices[ i ] * itemSize; 11209 11210 } 11211 11212 for ( let j = 0; j < itemSize; j ++ ) { 11213 11214 array2[ index2 ++ ] = array[ index ++ ]; 11215 11216 } 11217 11218 } 11219 11220 return new BufferAttribute( array2, itemSize, normalized ); 11221 11222 } 11223 11224 // 11225 11226 if ( this.index === null ) { 11227 11228 console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' ); 11229 return this; 11230 11231 } 11232 11233 const geometry2 = new BufferGeometry(); 11234 11235 const indices = this.index.array; 11236 const attributes = this.attributes; 11237 11238 // attributes 11239 11240 for ( const name in attributes ) { 11241 11242 const attribute = attributes[ name ]; 11243 11244 const newAttribute = convertBufferAttribute( attribute, indices ); 11245 11246 geometry2.setAttribute( name, newAttribute ); 11247 11248 } 11249 11250 // morph attributes 11251 11252 const morphAttributes = this.morphAttributes; 11253 11254 for ( const name in morphAttributes ) { 11255 11256 const morphArray = []; 11257 const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes 11258 11259 for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) { 11260 11261 const attribute = morphAttribute[ i ]; 11262 11263 const newAttribute = convertBufferAttribute( attribute, indices ); 11264 11265 morphArray.push( newAttribute ); 11266 11267 } 11268 11269 geometry2.morphAttributes[ name ] = morphArray; 11270 11271 } 11272 11273 geometry2.morphTargetsRelative = this.morphTargetsRelative; 11274 11275 // groups 11276 11277 const groups = this.groups; 11278 11279 for ( let i = 0, l = groups.length; i < l; i ++ ) { 11280 11281 const group = groups[ i ]; 11282 geometry2.addGroup( group.start, group.count, group.materialIndex ); 11283 11284 } 11285 11286 return geometry2; 11287 11288 } 11289 11290 toJSON() { 11291 11292 const data = { 11293 metadata: { 11294 version: 4.6, 11295 type: 'BufferGeometry', 11296 generator: 'BufferGeometry.toJSON' 11297 } 11298 }; 11299 11300 // standard BufferGeometry serialization 11301 11302 data.uuid = this.uuid; 11303 data.type = this.type; 11304 if ( this.name !== '' ) data.name = this.name; 11305 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; 11306 11307 if ( this.parameters !== undefined ) { 11308 11309 const parameters = this.parameters; 11310 11311 for ( const key in parameters ) { 11312 11313 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; 11314 11315 } 11316 11317 return data; 11318 11319 } 11320 11321 // for simplicity the code assumes attributes are not shared across geometries, see #15811 11322 11323 data.data = { attributes: {} }; 11324 11325 const index = this.index; 11326 11327 if ( index !== null ) { 11328 11329 data.data.index = { 11330 type: index.array.constructor.name, 11331 array: Array.prototype.slice.call( index.array ) 11332 }; 11333 11334 } 11335 11336 const attributes = this.attributes; 11337 11338 for ( const key in attributes ) { 11339 11340 const attribute = attributes[ key ]; 11341 11342 data.data.attributes[ key ] = attribute.toJSON( data.data ); 11343 11344 } 11345 11346 const morphAttributes = {}; 11347 let hasMorphAttributes = false; 11348 11349 for ( const key in this.morphAttributes ) { 11350 11351 const attributeArray = this.morphAttributes[ key ]; 11352 11353 const array = []; 11354 11355 for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { 11356 11357 const attribute = attributeArray[ i ]; 11358 11359 array.push( attribute.toJSON( data.data ) ); 11360 11361 } 11362 11363 if ( array.length > 0 ) { 11364 11365 morphAttributes[ key ] = array; 11366 11367 hasMorphAttributes = true; 11368 11369 } 11370 11371 } 11372 11373 if ( hasMorphAttributes ) { 11374 11375 data.data.morphAttributes = morphAttributes; 11376 data.data.morphTargetsRelative = this.morphTargetsRelative; 11377 11378 } 11379 11380 const groups = this.groups; 11381 11382 if ( groups.length > 0 ) { 11383 11384 data.data.groups = JSON.parse( JSON.stringify( groups ) ); 11385 11386 } 11387 11388 const boundingSphere = this.boundingSphere; 11389 11390 if ( boundingSphere !== null ) { 11391 11392 data.data.boundingSphere = { 11393 center: boundingSphere.center.toArray(), 11394 radius: boundingSphere.radius 11395 }; 11396 11397 } 11398 11399 return data; 11400 11401 } 11402 11403 clone() { 11404 11405 return new this.constructor().copy( this ); 11406 11407 } 11408 11409 copy( source ) { 11410 11411 // reset 11412 11413 this.index = null; 11414 this.attributes = {}; 11415 this.morphAttributes = {}; 11416 this.groups = []; 11417 this.boundingBox = null; 11418 this.boundingSphere = null; 11419 11420 // used for storing cloned, shared data 11421 11422 const data = {}; 11423 11424 // name 11425 11426 this.name = source.name; 11427 11428 // index 11429 11430 const index = source.index; 11431 11432 if ( index !== null ) { 11433 11434 this.setIndex( index.clone( data ) ); 11435 11436 } 11437 11438 // attributes 11439 11440 const attributes = source.attributes; 11441 11442 for ( const name in attributes ) { 11443 11444 const attribute = attributes[ name ]; 11445 this.setAttribute( name, attribute.clone( data ) ); 11446 11447 } 11448 11449 // morph attributes 11450 11451 const morphAttributes = source.morphAttributes; 11452 11453 for ( const name in morphAttributes ) { 11454 11455 const array = []; 11456 const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes 11457 11458 for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) { 11459 11460 array.push( morphAttribute[ i ].clone( data ) ); 11461 11462 } 11463 11464 this.morphAttributes[ name ] = array; 11465 11466 } 11467 11468 this.morphTargetsRelative = source.morphTargetsRelative; 11469 11470 // groups 11471 11472 const groups = source.groups; 11473 11474 for ( let i = 0, l = groups.length; i < l; i ++ ) { 11475 11476 const group = groups[ i ]; 11477 this.addGroup( group.start, group.count, group.materialIndex ); 11478 11479 } 11480 11481 // bounding box 11482 11483 const boundingBox = source.boundingBox; 11484 11485 if ( boundingBox !== null ) { 11486 11487 this.boundingBox = boundingBox.clone(); 11488 11489 } 11490 11491 // bounding sphere 11492 11493 const boundingSphere = source.boundingSphere; 11494 11495 if ( boundingSphere !== null ) { 11496 11497 this.boundingSphere = boundingSphere.clone(); 11498 11499 } 11500 11501 // draw range 11502 11503 this.drawRange.start = source.drawRange.start; 11504 this.drawRange.count = source.drawRange.count; 11505 11506 // user data 11507 11508 this.userData = source.userData; 11509 11510 return this; 11511 11512 } 11513 11514 dispose() { 11515 11516 this.dispatchEvent( { type: 'dispose' } ); 11517 11518 } 11519 11520} 11521 11522const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4(); 11523const _ray$3 = /*@__PURE__*/ new Ray(); 11524const _sphere$6 = /*@__PURE__*/ new Sphere(); 11525const _sphereHitAt = /*@__PURE__*/ new Vector3(); 11526 11527const _vA$1 = /*@__PURE__*/ new Vector3(); 11528const _vB$1 = /*@__PURE__*/ new Vector3(); 11529const _vC$1 = /*@__PURE__*/ new Vector3(); 11530 11531const _tempA = /*@__PURE__*/ new Vector3(); 11532const _morphA = /*@__PURE__*/ new Vector3(); 11533 11534const _uvA$1 = /*@__PURE__*/ new Vector2(); 11535const _uvB$1 = /*@__PURE__*/ new Vector2(); 11536const _uvC$1 = /*@__PURE__*/ new Vector2(); 11537 11538const _normalA = /*@__PURE__*/ new Vector3(); 11539const _normalB = /*@__PURE__*/ new Vector3(); 11540const _normalC = /*@__PURE__*/ new Vector3(); 11541 11542const _intersectionPoint = /*@__PURE__*/ new Vector3(); 11543const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); 11544 11545class Mesh extends Object3D { 11546 11547 constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) { 11548 11549 super(); 11550 11551 this.isMesh = true; 11552 11553 this.type = 'Mesh'; 11554 11555 this.geometry = geometry; 11556 this.material = material; 11557 11558 this.updateMorphTargets(); 11559 11560 } 11561 11562 copy( source, recursive ) { 11563 11564 super.copy( source, recursive ); 11565 11566 if ( source.morphTargetInfluences !== undefined ) { 11567 11568 this.morphTargetInfluences = source.morphTargetInfluences.slice(); 11569 11570 } 11571 11572 if ( source.morphTargetDictionary !== undefined ) { 11573 11574 this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); 11575 11576 } 11577 11578 this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; 11579 this.geometry = source.geometry; 11580 11581 return this; 11582 11583 } 11584 11585 updateMorphTargets() { 11586 11587 const geometry = this.geometry; 11588 11589 const morphAttributes = geometry.morphAttributes; 11590 const keys = Object.keys( morphAttributes ); 11591 11592 if ( keys.length > 0 ) { 11593 11594 const morphAttribute = morphAttributes[ keys[ 0 ] ]; 11595 11596 if ( morphAttribute !== undefined ) { 11597 11598 this.morphTargetInfluences = []; 11599 this.morphTargetDictionary = {}; 11600 11601 for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 11602 11603 const name = morphAttribute[ m ].name || String( m ); 11604 11605 this.morphTargetInfluences.push( 0 ); 11606 this.morphTargetDictionary[ name ] = m; 11607 11608 } 11609 11610 } 11611 11612 } 11613 11614 } 11615 11616 getVertexPosition( index, target ) { 11617 11618 const geometry = this.geometry; 11619 const position = geometry.attributes.position; 11620 const morphPosition = geometry.morphAttributes.position; 11621 const morphTargetsRelative = geometry.morphTargetsRelative; 11622 11623 target.fromBufferAttribute( position, index ); 11624 11625 const morphInfluences = this.morphTargetInfluences; 11626 11627 if ( morphPosition && morphInfluences ) { 11628 11629 _morphA.set( 0, 0, 0 ); 11630 11631 for ( let i = 0, il = morphPosition.length; i < il; i ++ ) { 11632 11633 const influence = morphInfluences[ i ]; 11634 const morphAttribute = morphPosition[ i ]; 11635 11636 if ( influence === 0 ) continue; 11637 11638 _tempA.fromBufferAttribute( morphAttribute, index ); 11639 11640 if ( morphTargetsRelative ) { 11641 11642 _morphA.addScaledVector( _tempA, influence ); 11643 11644 } else { 11645 11646 _morphA.addScaledVector( _tempA.sub( target ), influence ); 11647 11648 } 11649 11650 } 11651 11652 target.add( _morphA ); 11653 11654 } 11655 11656 return target; 11657 11658 } 11659 11660 raycast( raycaster, intersects ) { 11661 11662 const geometry = this.geometry; 11663 const material = this.material; 11664 const matrixWorld = this.matrixWorld; 11665 11666 if ( material === undefined ) return; 11667 11668 // test with bounding sphere in world space 11669 11670 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 11671 11672 _sphere$6.copy( geometry.boundingSphere ); 11673 _sphere$6.applyMatrix4( matrixWorld ); 11674 11675 // check distance from ray origin to bounding sphere 11676 11677 _ray$3.copy( raycaster.ray ).recast( raycaster.near ); 11678 11679 if ( _sphere$6.containsPoint( _ray$3.origin ) === false ) { 11680 11681 if ( _ray$3.intersectSphere( _sphere$6, _sphereHitAt ) === null ) return; 11682 11683 if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return; 11684 11685 } 11686 11687 // convert ray to local space of mesh 11688 11689 _inverseMatrix$3.copy( matrixWorld ).invert(); 11690 _ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 ); 11691 11692 // test with bounding box in local space 11693 11694 if ( geometry.boundingBox !== null ) { 11695 11696 if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return; 11697 11698 } 11699 11700 // test for intersections with geometry 11701 11702 this._computeIntersections( raycaster, intersects, _ray$3 ); 11703 11704 } 11705 11706 _computeIntersections( raycaster, intersects, rayLocalSpace ) { 11707 11708 let intersection; 11709 11710 const geometry = this.geometry; 11711 const material = this.material; 11712 11713 const index = geometry.index; 11714 const position = geometry.attributes.position; 11715 const uv = geometry.attributes.uv; 11716 const uv1 = geometry.attributes.uv1; 11717 const normal = geometry.attributes.normal; 11718 const groups = geometry.groups; 11719 const drawRange = geometry.drawRange; 11720 11721 if ( index !== null ) { 11722 11723 // indexed buffer geometry 11724 11725 if ( Array.isArray( material ) ) { 11726 11727 for ( let i = 0, il = groups.length; i < il; i ++ ) { 11728 11729 const group = groups[ i ]; 11730 const groupMaterial = material[ group.materialIndex ]; 11731 11732 const start = Math.max( group.start, drawRange.start ); 11733 const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); 11734 11735 for ( let j = start, jl = end; j < jl; j += 3 ) { 11736 11737 const a = index.getX( j ); 11738 const b = index.getX( j + 1 ); 11739 const c = index.getX( j + 2 ); 11740 11741 intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); 11742 11743 if ( intersection ) { 11744 11745 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics 11746 intersection.face.materialIndex = group.materialIndex; 11747 intersects.push( intersection ); 11748 11749 } 11750 11751 } 11752 11753 } 11754 11755 } else { 11756 11757 const start = Math.max( 0, drawRange.start ); 11758 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); 11759 11760 for ( let i = start, il = end; i < il; i += 3 ) { 11761 11762 const a = index.getX( i ); 11763 const b = index.getX( i + 1 ); 11764 const c = index.getX( i + 2 ); 11765 11766 intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); 11767 11768 if ( intersection ) { 11769 11770 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics 11771 intersects.push( intersection ); 11772 11773 } 11774 11775 } 11776 11777 } 11778 11779 } else if ( position !== undefined ) { 11780 11781 // non-indexed buffer geometry 11782 11783 if ( Array.isArray( material ) ) { 11784 11785 for ( let i = 0, il = groups.length; i < il; i ++ ) { 11786 11787 const group = groups[ i ]; 11788 const groupMaterial = material[ group.materialIndex ]; 11789 11790 const start = Math.max( group.start, drawRange.start ); 11791 const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); 11792 11793 for ( let j = start, jl = end; j < jl; j += 3 ) { 11794 11795 const a = j; 11796 const b = j + 1; 11797 const c = j + 2; 11798 11799 intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); 11800 11801 if ( intersection ) { 11802 11803 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics 11804 intersection.face.materialIndex = group.materialIndex; 11805 intersects.push( intersection ); 11806 11807 } 11808 11809 } 11810 11811 } 11812 11813 } else { 11814 11815 const start = Math.max( 0, drawRange.start ); 11816 const end = Math.min( position.count, ( drawRange.start + drawRange.count ) ); 11817 11818 for ( let i = start, il = end; i < il; i += 3 ) { 11819 11820 const a = i; 11821 const b = i + 1; 11822 const c = i + 2; 11823 11824 intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); 11825 11826 if ( intersection ) { 11827 11828 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics 11829 intersects.push( intersection ); 11830 11831 } 11832 11833 } 11834 11835 } 11836 11837 } 11838 11839 } 11840 11841} 11842 11843function checkIntersection
11843$1( object, material, raycaster, ray, pA, pB, pC, point ) { 11844 11845 let intersect; 11846 11847 if ( material.side === BackSide ) { 11848 11849 intersect = ray.intersectTriangle( pC, pB, pA, true, point ); 11850 11851 } else { 11852 11853 intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point ); 11854 11855 } 11856 11857 if ( intersect === null ) return null; 11858 11859 _intersectionPointWorld.copy( point ); 11860 _intersectionPointWorld.applyMatrix4( object.matrixWorld ); 11861 11862 const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld ); 11863 11864 if ( distance < raycaster.near || distance > raycaster.far ) return null; 11865 11866 return { 11867 distance: distance, 11868 point: _intersectionPointWorld.clone(), 11869 object: object 11870 }; 11871 11872} 11873 11874function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) { 11875 11876 object.getVertexPosition( a, _vA$1 ); 11877 object.getVertexPosition( b, _vB$1 ); 11878 object.getVertexPosition( c, _vC$1 ); 11879 11880 const intersection = checkIntersection$1( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint ); 11881 11882 if ( intersection ) { 11883 11884 if ( uv ) { 11885 11886 _uvA$1.fromBufferAttribute( uv, a ); 11887 _uvB$1.fromBufferAttribute( uv, b ); 11888 _uvC$1.fromBufferAttribute( uv, c ); 11889 11890 intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); 11891 11892 } 11893 11894 if ( uv1 ) { 11895 11896 _uvA$1.fromBufferAttribute( uv1, a ); 11897 _uvB$1.fromBufferAttribute( uv1, b ); 11898 _uvC$1.fromBufferAttribute( uv1, c ); 11899 11900 intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); 11901 11902 } 11903 11904 if ( normal ) { 11905 11906 _normalA.fromBufferAttribute( normal, a ); 11907 _normalB.fromBufferAttribute( normal, b ); 11908 _normalC.fromBufferAttribute( normal, c ); 11909
vendor: 6,950 bytes, lines 11910-12246
11910 intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() ); 11911 11912 if ( intersection.normal.dot( ray.direction ) > 0 ) { 11913 11914 intersection.normal.multiplyScalar( - 1 ); 11915 11916 } 11917 11918 } 11919 11920 const face = { 11921 a: a, 11922 b: b, 11923 c: c, 11924 normal: new Vector3(), 11925 materialIndex: 0 11926 }; 11927 11928 Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal ); 11929 11930 intersection.face = face; 11931 11932 } 11933 11934 return intersection; 11935 11936} 11937 11938class BoxGeometry extends BufferGeometry { 11939 11940 constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) { 11941 11942 super(); 11943 11944 this.type = 'BoxGeometry'; 11945 11946 this.parameters = { 11947 width: width, 11948 height: height, 11949 depth: depth, 11950 widthSegments: widthSegments, 11951 heightSegments: heightSegments, 11952 depthSegments: depthSegments 11953 }; 11954 11955 const scope = this; 11956 11957 // segments 11958 11959 widthSegments = Math.floor( widthSegments ); 11960 heightSegments = Math.floor( heightSegments ); 11961 depthSegments = Math.floor( depthSegments ); 11962 11963 // buffers 11964 11965 const indices = []; 11966 const vertices = []; 11967 const normals = []; 11968 const uvs = []; 11969 11970 // helper variables 11971 11972 let numberOfVertices = 0; 11973 let groupStart = 0; 11974 11975 // build each side of the box geometry 11976 11977 buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px 11978 buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx 11979 buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py 11980 buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny 11981 buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz 11982 buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz 11983 11984 // build geometry 11985 11986 this.setIndex( indices ); 11987 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 11988 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 11989 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 11990 11991 function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { 11992 11993 const segmentWidth = width / gridX; 11994 const segmentHeight = height / gridY; 11995 11996 const widthHalf = width / 2; 11997 const heightHalf = height / 2; 11998 const depthHalf = depth / 2; 11999 12000 const gridX1 = gridX + 1; 12001 const gridY1 = gridY + 1; 12002 12003 let vertexCounter = 0; 12004 let groupCount = 0; 12005 12006 const vector = new Vector3(); 12007 12008 // generate vertices, normals and uvs 12009 12010 for ( let iy = 0; iy < gridY1; iy ++ ) { 12011 12012 const y = iy * segmentHeight - heightHalf; 12013 12014 for ( let ix = 0; ix < gridX1; ix ++ ) { 12015 12016 const x = ix * segmentWidth - widthHalf; 12017 12018 // set values to correct vector component 12019 12020 vector[ u ] = x * udir; 12021 vector[ v ] = y * vdir; 12022 vector[ w ] = depthHalf; 12023 12024 // now apply vector to vertex buffer 12025 12026 vertices.push( vector.x, vector.y, vector.z ); 12027 12028 // set values to correct vector component 12029 12030 vector[ u ] = 0; 12031 vector[ v ] = 0; 12032 vector[ w ] = depth > 0 ? 1 : - 1; 12033 12034 // now apply vector to normal buffer 12035 12036 normals.push( vector.x, vector.y, vector.z ); 12037 12038 // uvs 12039 12040 uvs.push( ix / gridX ); 12041 uvs.push( 1 - ( iy / gridY ) ); 12042 12043 // counters 12044 12045 vertexCounter += 1; 12046 12047 } 12048 12049 } 12050 12051 // indices 12052 12053 // 1. you need three indices to draw a single face 12054 // 2. a single segment consists of two faces 12055 // 3. so we need to generate six (2*3) indices per segment 12056 12057 for ( let iy = 0; iy < gridY; iy ++ ) { 12058 12059 for ( let ix = 0; ix < gridX; ix ++ ) { 12060 12061 const a = numberOfVertices + ix + gridX1 * iy; 12062 const b = numberOfVertices + ix + gridX1 * ( iy + 1 ); 12063 const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); 12064 const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; 12065 12066 // faces 12067 12068 indices.push( a, b, d ); 12069 indices.push( b, c, d ); 12070 12071 // increase counter 12072 12073 groupCount += 6; 12074 12075 } 12076 12077 } 12078 12079 // add a group to the geometry. this will ensure multi material support 12080 12081 scope.addGroup( groupStart, groupCount, materialIndex ); 12082 12083 // calculate new start value for groups 12084 12085 groupStart += groupCount; 12086 12087 // update total number of vertices 12088 12089 numberOfVertices += vertexCounter; 12090 12091 } 12092 12093 } 12094 12095 copy( source ) { 12096 12097 super.copy( source ); 12098 12099 this.parameters = Object.assign( {}, source.parameters ); 12100 12101 return this; 12102 12103 } 12104 12105 static fromJSON( data ) { 12106 12107 return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); 12108 12109 } 12110 12111} 12112 12113/** 12114 * Uniform Utilities 12115 */ 12116 12117function cloneUniforms( src ) { 12118 12119 const dst = {}; 12120 12121 for ( const u in src ) { 12122 12123 dst[ u ] = {}; 12124 12125 for ( const p in src[ u ] ) { 12126 12127 const property = src[ u ][ p ]; 12128 12129 if ( property && ( property.isColor || 12130 property.isMatrix3 || property.isMatrix4 || 12131 property.isVector2 || property.isVector3 || property.isVector4 || 12132 property.isTexture || property.isQuaternion ) ) { 12133 12134 if ( property.isRenderTargetTexture ) { 12135 12136 console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); 12137 dst[ u ][ p ] = null; 12138 12139 } else { 12140 12141 dst[ u ][ p ] = property.clone(); 12142 12143 } 12144 12145 } else if ( Array.isArray( property ) ) { 12146 12147 dst[ u ][ p ] = property.slice(); 12148 12149 } else { 12150 12151 dst[ u ][ p ] = property; 12152 12153 } 12154 12155 } 12156 12157 } 12158 12159 return dst; 12160 12161} 12162 12163function mergeUniforms( uniforms ) { 12164 12165 const merged = {}; 12166 12167 for ( let u = 0; u < uniforms.length; u ++ ) { 12168 12169 const tmp = cloneUniforms( uniforms[ u ] ); 12170 12171 for ( const p in tmp ) { 12172 12173 merged[ p ] = tmp[ p ]; 12174 12175 } 12176 12177 } 12178 12179 return merged; 12180 12181} 12182 12183function cloneUniformsGroups( src ) { 12184 12185 const dst = []; 12186 12187 for ( let u = 0; u < src.length; u ++ ) { 12188 12189 dst.push( src[ u ].clone() ); 12190 12191 } 12192 12193 return dst; 12194 12195} 12196 12197function getUnlitUniformColorSpace( renderer ) { 12198 12199 const currentRenderTarget = renderer.getRenderTarget(); 12200 12201 if ( currentRenderTarget === null ) { 12202 12203 // https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398 12204 return renderer.outputColorSpace; 12205 12206 } 12207 12208 // https://github.com/mrdoob/three.js/issues/27868 12209 if ( currentRenderTarget.isXRRenderTarget === true ) { 12210 12211 return currentRenderTarget.texture.colorSpace; 12212 12213 } 12214 12215 return ColorManagement.workingColorSpace; 12216 12217} 12218 12219// Legacy 12220 12221const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms }; 12222 12223var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"; 12224 12225var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}"; 12226 12227class ShaderMaterial extends Material { 12228 12229 constructor( parameters ) { 12230 12231 super(); 12232 12233 this.isShaderMaterial = true; 12234 12235 this.type = 'ShaderMaterial'; 12236 12237 this.defines = {}; 12238 this.uniforms = {}; 12239 this.uniformsGroups = []; 12240 12241 this.vertexShader = default_vertex; 12242 this.fragmentShader = default_fragment; 12243 12244 this.linewidth = 1; 12245 12246 this.wireframe = false;
vendor: 5,162 bytes, lines 12247-12509
12247 this.wireframeLinewidth = 1; 12248 12249 this.fog = false; // set to use scene fog 12250 this.lights = false; // set to use scene lights 12251 this.clipping = false; // set to use user-defined clipping planes 12252 12253 this.forceSinglePass = true; 12254 12255 this.extensions = { 12256 clipCullDistance: false, // set to use vertex shader clipping 12257 multiDraw: false // set to use vertex shader multi_draw / enable gl_DrawID 12258 }; 12259 12260 // When rendered geometry doesn't include these attributes but the material does, 12261 // use these default values in WebGL. This avoids errors when buffer data is missing. 12262 this.defaultAttributeValues = { 12263 'color': [ 1, 1, 1 ], 12264 'uv': [ 0, 0 ], 12265 'uv1': [ 0, 0 ] 12266 }; 12267 12268 this.index0AttributeName = undefined; 12269 this.uniformsNeedUpdate = false; 12270 12271 this.glslVersion = null; 12272 12273 if ( parameters !== undefined ) { 12274 12275 this.setValues( parameters ); 12276 12277 } 12278 12279 } 12280 12281 copy( source ) { 12282 12283 super.copy( source ); 12284 12285 this.fragmentShader = source.fragmentShader; 12286 this.vertexShader = source.vertexShader; 12287 12288 this.uniforms = cloneUniforms( source.uniforms ); 12289 this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups ); 12290 12291 this.defines = Object.assign( {}, source.defines ); 12292 12293 this.wireframe = source.wireframe; 12294 this.wireframeLinewidth = source.wireframeLinewidth; 12295 12296 this.fog = source.fog; 12297 this.lights = source.lights; 12298 this.clipping = source.clipping; 12299 12300 this.extensions = Object.assign( {}, source.extensions ); 12301 12302 this.glslVersion = source.glslVersion; 12303 12304 return this; 12305 12306 } 12307 12308 toJSON( meta ) { 12309 12310 const data = super.toJSON( meta ); 12311 12312 data.glslVersion = this.glslVersion; 12313 data.uniforms = {}; 12314 12315 for ( const name in this.uniforms ) { 12316 12317 const uniform = this.uniforms[ name ]; 12318 const value = uniform.value; 12319 12320 if ( value && value.isTexture ) { 12321 12322 data.uniforms[ name ] = { 12323 type: 't', 12324 value: value.toJSON( meta ).uuid 12325 }; 12326 12327 } else if ( value && value.isColor ) { 12328 12329 data.uniforms[ name ] = { 12330 type: 'c', 12331 value: value.getHex() 12332 }; 12333 12334 } else if ( value && value.isVector2 ) { 12335 12336 data.uniforms[ name ] = { 12337 type: 'v2', 12338 value: value.toArray() 12339 }; 12340 12341 } else if ( value && value.isVector3 ) { 12342 12343 data.uniforms[ name ] = { 12344 type: 'v3', 12345 value: value.toArray() 12346 }; 12347 12348 } else if ( value && value.isVector4 ) { 12349 12350 data.uniforms[ name ] = { 12351 type: 'v4', 12352 value: value.toArray() 12353 }; 12354 12355 } else if ( value && value.isMatrix3 ) { 12356 12357 data.uniforms[ name ] = { 12358 type: 'm3', 12359 value: value.toArray() 12360 }; 12361 12362 } else if ( value && value.isMatrix4 ) { 12363 12364 data.uniforms[ name ] = { 12365 type: 'm4', 12366 value: value.toArray() 12367 }; 12368 12369 } else { 12370 12371 data.uniforms[ name ] = { 12372 value: value 12373 }; 12374 12375 // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far 12376 12377 } 12378 12379 } 12380 12381 if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines; 12382 12383 data.vertexShader = this.vertexShader; 12384 data.fragmentShader = this.fragmentShader; 12385 12386 data.lights = this.lights; 12387 data.clipping = this.clipping; 12388 12389 const extensions = {}; 12390 12391 for ( const key in this.extensions ) { 12392 12393 if ( this.extensions[ key ] === true ) extensions[ key ] = true; 12394 12395 } 12396 12397 if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions; 12398 12399 return data; 12400 12401 } 12402 12403} 12404 12405class Camera extends Object3D { 12406 12407 constructor() { 12408 12409 super(); 12410 12411 this.isCamera = true; 12412 12413 this.type = 'Camera'; 12414 12415 this.matrixWorldInverse = new Matrix4(); 12416 12417 this.projectionMatrix = new Matrix4(); 12418 this.projectionMatrixInverse = new Matrix4(); 12419 12420 this.coordinateSystem = WebGLCoordinateSystem; 12421 12422 } 12423 12424 copy( source, recursive ) { 12425 12426 super.copy( source, recursive ); 12427 12428 this.matrixWorldInverse.copy( source.matrixWorldInverse ); 12429 12430 this.projectionMatrix.copy( source.projectionMatrix ); 12431 this.projectionMatrixInverse.copy( source.projectionMatrixInverse ); 12432 12433 this.coordinateSystem = source.coordinateSystem; 12434 12435 return this; 12436 12437 } 12438 12439 getWorldDirection( target ) { 12440 12441 return super.getWorldDirection( target ).negate(); 12442 12443 } 12444 12445 updateMatrixWorld( force ) { 12446 12447 super.updateMatrixWorld( force ); 12448 12449 this.matrixWorldInverse.copy( this.matrixWorld ).invert(); 12450 12451 } 12452 12453 updateWorldMatrix( updateParents, updateChildren ) { 12454 12455 super.updateWorldMatrix( updateParents, updateChildren ); 12456 12457 this.matrixWorldInverse.copy( this.matrixWorld ).invert(); 12458 12459 } 12460 12461 clone() { 12462 12463 return new this.constructor().copy( this ); 12464 12465 } 12466 12467} 12468 12469const _v3$1 = /*@__PURE__*/ new Vector3(); 12470const _minTarget = /*@__PURE__*/ new Vector2(); 12471const _maxTarget = /*@__PURE__*/ new Vector2(); 12472 12473 12474class PerspectiveCamera extends Camera { 12475 12476 constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) { 12477 12478 super(); 12479 12480 this.isPerspectiveCamera = true; 12481 12482 this.type = 'PerspectiveCamera'; 12483 12484 this.fov = fov; 12485 this.zoom = 1; 12486 12487 this.near = near; 12488 this.far = far; 12489 this.focus = 10; 12490 12491 this.aspect = aspect; 12492 this.view = null; 12493 12494 this.filmGauge = 35; // width of the film (default in millimeters) 12495 this.filmOffset = 0; // horizontal film offset (same unit as gauge) 12496 12497 this.updateProjectionMatrix(); 12498 12499 } 12500 12501 copy( source, recursive ) { 12502 12503 super.copy( source, recursive ); 12504 12505 this.fov = source.fov; 12506 this.zoom = source.zoom; 12507 12508 this.near = source.near; 12509 this.far = source.far;
vendor: 4,346 bytes, lines 12510-12683
12510 this.focus = source.focus; 12511 12512 this.aspect = source.aspect; 12513 this.view = source.view === null ? null : Object.assign( {}, source.view ); 12514 12515 this.filmGauge = source.filmGauge; 12516 this.filmOffset = source.filmOffset; 12517 12518 return this; 12519 12520 } 12521 12522 /** 12523 * Sets the FOV by focal length in respect to the current .filmGauge. 12524 * 12525 * The default film gauge is 35, so that the focal length can be specified for 12526 * a 35mm (full frame) camera. 12527 * 12528 * Values for focal length and film gauge must have the same unit. 12529 */ 12530 setFocalLength( focalLength ) { 12531 12532 /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */ 12533 const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; 12534 12535 this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope ); 12536 this.updateProjectionMatrix(); 12537 12538 } 12539 12540 /** 12541 * Calculates the focal length from the current .fov and .filmGauge. 12542 */ 12543 getFocalLength() { 12544 12545 const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov ); 12546 12547 return 0.5 * this.getFilmHeight() / vExtentSlope; 12548 12549 } 12550 12551 getEffectiveFOV() { 12552 12553 return RAD2DEG * 2 * Math.atan( 12554 Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom ); 12555 12556 } 12557 12558 getFilmWidth() { 12559 12560 // film not completely covered in portrait format (aspect < 1) 12561 return this.filmGauge * Math.min( this.aspect, 1 ); 12562 12563 } 12564 12565 getFilmHeight() { 12566 12567 // film not completely covered in landscape format (aspect > 1) 12568 return this.filmGauge / Math.max( this.aspect, 1 ); 12569 12570 } 12571 12572 /** 12573 * Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction. 12574 * Sets minTarget and maxTarget to the coordinates of the lower-left and upper-right corners of the view rectangle. 12575 */ 12576 getViewBounds( distance, minTarget, maxTarget ) { 12577 12578 _v3$1.set( - 1, - 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse ); 12579 12580 minTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z ); 12581 12582 _v3$1.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse ); 12583 12584 maxTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z ); 12585 12586 } 12587 12588 /** 12589 * Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction. 12590 * Copies the result into the target Vector2, where x is width and y is height. 12591 */ 12592 getViewSize( distance, target ) { 12593 12594 this.getViewBounds( distance, _minTarget, _maxTarget ); 12595 12596 return target.subVectors( _maxTarget, _minTarget ); 12597 12598 } 12599 12600 /** 12601 * Sets an offset in a larger frustum. This is useful for multi-window or 12602 * multi-monitor/multi-machine setups. 12603 * 12604 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and 12605 * the monitors are in grid like this 12606 * 12607 * +---+---+---+ 12608 * | A | B | C | 12609 * +---+---+---+ 12610 * | D | E | F | 12611 * +---+---+---+ 12612 * 12613 * then for each monitor you would call it like this 12614 * 12615 * const w = 1920; 12616 * const h = 1080; 12617 * const fullWidth = w * 3; 12618 * const fullHeight = h * 2; 12619 * 12620 * --A-- 12621 * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); 12622 * --B-- 12623 * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); 12624 * --C-- 12625 * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); 12626 * --D-- 12627 * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); 12628 * --E-- 12629 * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); 12630 * --F-- 12631 * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); 12632 * 12633 * Note there is no reason monitors have to be the same size or in a grid. 12634 */ 12635 setViewOffset( fullWidth, fullHeight, x, y, width, height ) { 12636 12637 this.aspect = fullWidth / fullHeight; 12638 12639 if ( this.view === null ) { 12640 12641 this.view = { 12642 enabled: true, 12643 fullWidth: 1, 12644 fullHeight: 1, 12645 offsetX: 0, 12646 offsetY: 0, 12647 width: 1, 12648 height: 1 12649 }; 12650 12651 } 12652 12653 this.view.enabled = true; 12654 this.view.fullWidth = fullWidth; 12655 this.view.fullHeight = fullHeight; 12656 this.view.offsetX = x; 12657 this.view.offsetY = y; 12658 this.view.width = width; 12659 this.view.height = height; 12660 12661 this.updateProjectionMatrix(); 12662 12663 } 12664 12665 clearViewOffset() { 12666 12667 if ( this.view !== null ) { 12668 12669 this.view.enabled = false; 12670 12671 } 12672 12673 this.updateProjectionMatrix(); 12674 12675 } 12676 12677 updateProjectionMatrix() { 12678 12679 const near = this.near; 12680 let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom; 12681 let height = 2 * top; 12682 let width = this.aspect * height; 12683 let left = - 0.5 * width;
vendor: 3,266 bytes, lines 12684-12820
12684 const view = this.view; 12685 12686 if ( this.view !== null && this.view.enabled ) { 12687 12688 const fullWidth = view.fullWidth, 12689 fullHeight = view.fullHeight; 12690 12691 left += view.offsetX * width / fullWidth; 12692 top -= view.offsetY * height / fullHeight; 12693 width *= view.width / fullWidth; 12694 height *= view.height / fullHeight; 12695 12696 } 12697 12698 const skew = this.filmOffset; 12699 if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); 12700 12701 this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem ); 12702 12703 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); 12704 12705 } 12706 12707 toJSON( meta ) { 12708 12709 const data = super.toJSON( meta ); 12710 12711 data.object.fov = this.fov; 12712 data.object.zoom = this.zoom; 12713 12714 data.object.near = this.near; 12715 data.object.far = this.far; 12716 data.object.focus = this.focus; 12717 12718 data.object.aspect = this.aspect; 12719 12720 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); 12721 12722 data.object.filmGauge = this.filmGauge; 12723 data.object.filmOffset = this.filmOffset; 12724 12725 return data; 12726 12727 } 12728 12729} 12730 12731const fov = - 90; // negative fov is not an error 12732const aspect = 1; 12733 12734class CubeCamera extends Object3D { 12735 12736 constructor( near, far, renderTarget ) { 12737 12738 super(); 12739 12740 this.type = 'CubeCamera'; 12741 12742 this.renderTarget = renderTarget; 12743 this.coordinateSystem = null; 12744 this.activeMipmapLevel = 0; 12745 12746 const cameraPX = new PerspectiveCamera( fov, aspect, near, far ); 12747 cameraPX.layers = this.layers; 12748 this.add( cameraPX ); 12749 12750 const cameraNX = new PerspectiveCamera( fov, aspect, near, far ); 12751 cameraNX.layers = this.layers; 12752 this.add( cameraNX ); 12753 12754 const cameraPY = new PerspectiveCamera( fov, aspect, near, far ); 12755 cameraPY.layers = this.layers; 12756 this.add( cameraPY ); 12757 12758 const cameraNY = new PerspectiveCamera( fov, aspect, near, far ); 12759 cameraNY.layers = this.layers; 12760 this.add( cameraNY ); 12761 12762 const cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); 12763 cameraPZ.layers = this.layers; 12764 this.add( cameraPZ ); 12765 12766 const cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); 12767 cameraNZ.layers = this.layers; 12768 this.add( cameraNZ ); 12769 12770 } 12771 12772 updateCoordinateSystem() { 12773 12774 const coordinateSystem = this.coordinateSystem; 12775 12776 const cameras = this.children.concat(); 12777 12778 const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras; 12779 12780 for ( const camera of cameras ) this.remove( camera ); 12781 12782 if ( coordinateSystem === WebGLCoordinateSystem ) { 12783 12784 cameraPX.up.set( 0, 1, 0 ); 12785 cameraPX.lookAt( 1, 0, 0 ); 12786 12787 cameraNX.up.set( 0, 1, 0 ); 12788 cameraNX.lookAt( - 1, 0, 0 ); 12789 12790 cameraPY.up.set( 0, 0, - 1 ); 12791 cameraPY.lookAt( 0, 1, 0 ); 12792 12793 cameraNY.up.set( 0, 0, 1 ); 12794 cameraNY.lookAt( 0, - 1, 0 ); 12795 12796 cameraPZ.up.set( 0, 1, 0 ); 12797 cameraPZ.lookAt( 0, 0, 1 ); 12798 12799 cameraNZ.up.set( 0, 1, 0 ); 12800 cameraNZ.lookAt( 0, 0, - 1 ); 12801 12802 } else if ( coordinateSystem === WebGPUCoordinateSystem ) { 12803 12804 cameraPX.up.set( 0, - 1, 0 ); 12805 cameraPX.lookAt( - 1, 0, 0 ); 12806 12807 cameraNX.up.set( 0, - 1, 0 ); 12808 cameraNX.lookAt( 1, 0, 0 ); 12809 12810 cameraPY.up.set( 0, 0, 1 ); 12811 cameraPY.lookAt( 0, 1, 0 ); 12812 12813 cameraNY.up.set( 0, 0, - 1 ); 12814 cameraNY.lookAt( 0, - 1, 0 ); 12815 12816 cameraPZ.up.set( 0, - 1, 0 ); 12817 cameraPZ.lookAt( 0, 0, 1 ); 12818 12819 cameraNZ.up.set( 0, - 1, 0 ); 12820 cameraNZ.lookAt( 0, 0, -
vendor: 7,494 bytes, lines 12820-13143
128201 ); 12821 12822 } else { 12823 12824 throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem ); 12825 12826 } 12827 12828 for ( const camera of cameras ) { 12829 12830 this.add( camera ); 12831 12832 camera.updateMatrixWorld(); 12833 12834 } 12835 12836 } 12837 12838 update( renderer, scene ) { 12839 12840 if ( this.parent === null ) this.updateMatrixWorld(); 12841 12842 const { renderTarget, activeMipmapLevel } = this; 12843 12844 if ( this.coordinateSystem !== renderer.coordinateSystem ) { 12845 12846 this.coordinateSystem = renderer.coordinateSystem; 12847 12848 this.updateCoordinateSystem(); 12849 12850 } 12851 12852 const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children; 12853 12854 const currentRenderTarget = renderer.getRenderTarget(); 12855 const currentActiveCubeFace = renderer.getActiveCubeFace(); 12856 const currentActiveMipmapLevel = renderer.getActiveMipmapLevel(); 12857 12858 const currentXrEnabled = renderer.xr.enabled; 12859 12860 renderer.xr.enabled = false; 12861 12862 const generateMipmaps = renderTarget.texture.generateMipmaps; 12863 12864 renderTarget.texture.generateMipmaps = false; 12865 12866 renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel ); 12867 renderer.render( scene, cameraPX ); 12868 12869 renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel ); 12870 renderer.render( scene, cameraNX ); 12871 12872 renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel ); 12873 renderer.render( scene, cameraPY ); 12874 12875 renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel ); 12876 renderer.render( scene, cameraNY ); 12877 12878 renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel ); 12879 renderer.render( scene, cameraPZ ); 12880 12881 // mipmaps are generated during the last call of render() 12882 // at this point, all sides of the cube render target are defined 12883 12884 renderTarget.texture.generateMipmaps = generateMipmaps; 12885 12886 renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel ); 12887 renderer.render( scene, cameraNZ ); 12888 12889 renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel ); 12890 12891 renderer.xr.enabled = currentXrEnabled; 12892 12893 renderTarget.texture.needsPMREMUpdate = true; 12894 12895 } 12896 12897} 12898 12899class CubeTexture extends Texture { 12900 12901 constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { 12902 12903 images = images !== undefined ? images : []; 12904 mapping = mapping !== undefined ? mapping : CubeReflectionMapping; 12905 12906 super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); 12907 12908 this.isCubeTexture = true; 12909 12910 this.flipY = false; 12911 12912 } 12913 12914 get images() { 12915 12916 return this.image; 12917 12918 } 12919 12920 set images( value ) { 12921 12922 this.image = value; 12923 12924 } 12925 12926} 12927 12928class WebGLCubeRenderTarget extends WebGLRenderTarget { 12929 12930 constructor( size = 1, options = {} ) { 12931 12932 super( size, size, options ); 12933 12934 this.isWebGLCubeRenderTarget = true; 12935 12936 const image = { width: size, height: size, depth: 1 }; 12937 const images = [ image, image, image, image, image, image ]; 12938 12939 this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); 12940 12941 // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) 12942 // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, 12943 // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly. 12944 12945 // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped 12946 // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture 12947 // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures). 12948 12949 this.texture.isRenderTargetTexture = true; 12950 12951 this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; 12952 this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; 12953 12954 } 12955 12956 fromEquirectangularTexture( renderer, texture ) { 12957 12958 this.texture.type = texture.type; 12959 this.texture.colorSpace = texture.colorSpace; 12960 12961 this.texture.generateMipmaps = texture.generateMipmaps; 12962 this.texture.minFilter = texture.minFilter; 12963 this.texture.magFilter = texture.magFilter; 12964 12965 const shader = { 12966 12967 uniforms: { 12968 tEquirect: { value: null }, 12969 }, 12970 12971 vertexShader: /* glsl */` 12972 12973 varying vec3 vWorldDirection; 12974 12975 vec3 transformDirection( in vec3 dir, in mat4 matrix ) { 12976 12977 return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); 12978 12979 } 12980 12981 void main() { 12982 12983 vWorldDirection = transformDirection( position, modelMatrix ); 12984 12985 #include <begin_vertex> 12986 #include <project_vertex> 12987 12988 } 12989 `, 12990 12991 fragmentShader: /* glsl */` 12992 12993 uniform sampler2D tEquirect; 12994 12995 varying vec3 vWorldDirection; 12996 12997 #include <common> 12998 12999 void main() { 13000 13001 vec3 direction = normalize( vWorldDirection ); 13002 13003 vec2 sampleUV = equirectUv( direction ); 13004 13005 gl_FragColor = texture2D( tEquirect, sampleUV ); 13006 13007 } 13008 ` 13009 }; 13010 13011 const geometry = new BoxGeometry( 5, 5, 5 ); 13012 13013 const material = new ShaderMaterial( { 13014 13015 name: 'CubemapFromEquirect', 13016 13017 uniforms: cloneUniforms( shader.uniforms ), 13018 vertexShader: shader.vertexShader, 13019 fragmentShader: shader.fragmentShader, 13020 side: BackSide, 13021 blending: NoBlending 13022 13023 } ); 13024 13025 material.uniforms.tEquirect.value = texture; 13026 13027 const mesh = new Mesh( geometry, material ); 13028 13029 const currentMinFilter = texture.minFilter; 13030 13031 // Avoid blurred poles 13032 if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter; 13033 13034 const camera = new CubeCamera( 1, 10, this ); 13035 camera.update( renderer, mesh ); 13036 13037 texture.minFilter = currentMinFilter; 13038 13039 mesh.geometry.dispose(); 13040 mesh.material.dispose(); 13041 13042 return this; 13043 13044 } 13045 13046 clear( renderer, color, depth, stencil ) { 13047 13048 const currentRenderTarget = renderer.getRenderTarget(); 13049 13050 for ( let i = 0; i < 6; i ++ ) { 13051 13052 renderer.setRenderTarget( this, i ); 13053 13054 renderer.clear( color, depth, stencil ); 13055 13056 } 13057 13058 renderer.setRenderTarget( currentRenderTarget ); 13059 13060 } 13061 13062} 13063 13064const _vector1 = /*@__PURE__*/ new Vector3(); 13065const _vector2 = /*@__PURE__*/ new Vector3(); 13066const _normalMatrix = /*@__PURE__*/ new Matrix3(); 13067 13068class Plane { 13069 13070 constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) { 13071 13072 this.isPlane = true; 13073 13074 // normal is assumed to be normalized 13075 13076 this.normal = normal; 13077 this.constant = constant; 13078 13079 } 13080 13081 set( normal, constant ) { 13082 13083 this.normal.copy( normal ); 13084 this.constant = constant; 13085 13086 return this; 13087 13088 } 13089 13090 setComponents( x, y, z, w ) { 13091 13092 this.normal.set( x, y, z ); 13093 this.constant = w; 13094 13095 return this; 13096 13097 } 13098 13099 setFromNormalAndCoplanarPoint( normal, point ) { 13100 13101 this.normal.copy( normal ); 13102 this.constant = - point.dot( this.normal ); 13103 13104 return this; 13105 13106 } 13107 13108 setFromCoplanarPoints( a, b, c ) { 13109 13110 const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize(); 13111 13112 // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? 13113 13114 this.setFromNormalAndCoplanarPoint( normal, a ); 13115 13116 return this; 13117 13118 } 13119 13120 copy( plane ) { 13121 13122 this.normal.copy( plane.normal ); 13123 this.constant = plane.constant; 13124 13125 return this; 13126 13127 } 13128 13129 normalize() { 13130 13131 // Note: will lead to a divide by zero if the plane is invalid. 13132 13133 const inverseNormalLength = 1.0 / this.normal.length(); 13134 this.normal.multiplyScalar( inverseNormalLength ); 13135 this.constant *= inverseNormalLength; 13136 13137 return this; 13138 13139 } 13140 13141 negate() { 13142 13143 this.constant *= -
vendor: 15,925 bytes, lines 13143-13806
13143 1; 13144 this.normal.negate(); 13145 13146 return this; 13147 13148 } 13149 13150 distanceToPoint( point ) { 13151 13152 return this.normal.dot( point ) + this.constant; 13153 13154 } 13155 13156 distanceToSphere( sphere ) { 13157 13158 return this.distanceToPoint( sphere.center ) - sphere.radius; 13159 13160 } 13161 13162 projectPoint( point, target ) { 13163 13164 return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) ); 13165 13166 } 13167 13168 intersectLine( line, target ) { 13169 13170 const direction = line.delta( _vector1 ); 13171 13172 const denominator = this.normal.dot( direction ); 13173 13174 if ( denominator === 0 ) { 13175 13176 // line is coplanar, return origin 13177 if ( this.distanceToPoint( line.start ) === 0 ) { 13178 13179 return target.copy( line.start ); 13180 13181 } 13182 13183 // Unsure if this is the correct method to handle this case. 13184 return null; 13185 13186 } 13187 13188 const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; 13189 13190 if ( t < 0 || t > 1 ) { 13191 13192 return null; 13193 13194 } 13195 13196 return target.copy( line.start ).addScaledVector( direction, t ); 13197 13198 } 13199 13200 intersectsLine( line ) { 13201 13202 // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. 13203 13204 const startSign = this.distanceToPoint( line.start ); 13205 const endSign = this.distanceToPoint( line.end ); 13206 13207 return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); 13208 13209 } 13210 13211 intersectsBox( box ) { 13212 13213 return box.intersectsPlane( this ); 13214 13215 } 13216 13217 intersectsSphere( sphere ) { 13218 13219 return sphere.intersectsPlane( this ); 13220 13221 } 13222 13223 coplanarPoint( target ) { 13224 13225 return target.copy( this.normal ).multiplyScalar( - this.constant ); 13226 13227 } 13228 13229 applyMatrix4( matrix, optionalNormalMatrix ) { 13230 13231 const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix ); 13232 13233 const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix ); 13234 13235 const normal = this.normal.applyMatrix3( normalMatrix ).normalize(); 13236 13237 this.constant = - referencePoint.dot( normal ); 13238 13239 return this; 13240 13241 } 13242 13243 translate( offset ) { 13244 13245 this.constant -= offset.dot( this.normal ); 13246 13247 return this; 13248 13249 } 13250 13251 equals( plane ) { 13252 13253 return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); 13254 13255 } 13256 13257 clone() { 13258 13259 return new this.constructor().copy( this ); 13260 13261 } 13262 13263} 13264 13265const _sphere$5 = /*@__PURE__*/ new Sphere(); 13266const _vector$7 = /*@__PURE__*/ new Vector3(); 13267 13268class Frustum { 13269 13270 constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) { 13271 13272 this.planes = [ p0, p1, p2, p3, p4, p5 ]; 13273 13274 } 13275 13276 set( p0, p1, p2, p3, p4, p5 ) { 13277 13278 const planes = this.planes; 13279 13280 planes[ 0 ].copy( p0 ); 13281 planes[ 1 ].copy( p1 ); 13282 planes[ 2 ].copy( p2 ); 13283 planes[ 3 ].copy( p3 ); 13284 planes[ 4 ].copy( p4 ); 13285 planes[ 5 ].copy( p5 ); 13286 13287 return this; 13288 13289 } 13290 13291 copy( frustum ) { 13292 13293 const planes = this.planes; 13294 13295 for ( let i = 0; i < 6; i ++ ) { 13296 13297 planes[ i ].copy( frustum.planes[ i ] ); 13298 13299 } 13300 13301 return this; 13302 13303 } 13304 13305 setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem ) { 13306 13307 const planes = this.planes; 13308 const me = m.elements; 13309 const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ]; 13310 const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ]; 13311 const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ]; 13312 const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ]; 13313 13314 planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize(); 13315 planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize(); 13316 planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize(); 13317 planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize(); 13318 planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize(); 13319 13320 if ( coordinateSystem === WebGLCoordinateSystem ) { 13321 13322 planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); 13323 13324 } else if ( coordinateSystem === WebGPUCoordinateSystem ) { 13325 13326 planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize(); 13327 13328 } else { 13329 13330 throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem ); 13331 13332 } 13333 13334 return this; 13335 13336 } 13337 13338 intersectsObject( object ) { 13339 13340 if ( object.boundingSphere !== undefined ) { 13341 13342 if ( object.boundingSphere === null ) object.computeBoundingSphere(); 13343 13344 _sphere$5.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld ); 13345 13346 } else { 13347 13348 const geometry = object.geometry; 13349 13350 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 13351 13352 _sphere$5.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); 13353 13354 } 13355 13356 return this.intersectsSphere( _sphere$5 ); 13357 13358 } 13359 13360 intersectsSprite( sprite ) { 13361 13362 _sphere$5.center.set( 0, 0, 0 ); 13363 _sphere$5.radius = 0.7071067811865476; 13364 _sphere$5.applyMatrix4( sprite.matrixWorld ); 13365 13366 return this.intersectsSphere( _sphere$5 ); 13367 13368 } 13369 13370 intersectsSphere( sphere ) { 13371 13372 const planes = this.planes; 13373 const center = sphere.center; 13374 const negRadius = - sphere.radius; 13375 13376 for ( let i = 0; i < 6; i ++ ) { 13377 13378 const distance = planes[ i ].distanceToPoint( center ); 13379 13380 if ( distance < negRadius ) { 13381 13382 return false; 13383 13384 } 13385 13386 } 13387 13388 return true; 13389 13390 } 13391 13392 intersectsBox( box ) { 13393 13394 const planes = this.planes; 13395 13396 for ( let i = 0; i < 6; i ++ ) { 13397 13398 const plane = planes[ i ]; 13399 13400 // corner at max distance 13401 13402 _vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x; 13403 _vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y; 13404 _vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z; 13405 13406 if ( plane.distanceToPoint( _vector$7 ) < 0 ) { 13407 13408 return false; 13409 13410 } 13411 13412 } 13413 13414 return true; 13415 13416 } 13417 13418 containsPoint( point ) { 13419 13420 const planes = this.planes; 13421 13422 for ( let i = 0; i < 6; i ++ ) { 13423 13424 if ( planes[ i ].distanceToPoint( point ) < 0 ) { 13425 13426 return false; 13427 13428 } 13429 13430 } 13431 13432 return true; 13433 13434 } 13435 13436 clone() { 13437 13438 return new this.constructor().copy( this ); 13439 13440 } 13441 13442} 13443 13444function WebGLAnimation() { 13445 13446 let context = null; 13447 let isAnimating = false; 13448 let animationLoop = null; 13449 let requestId = null; 13450 13451 function onAnimationFrame( time, frame ) { 13452 13453 animationLoop( time, frame ); 13454 13455 requestId = context.requestAnimationFrame( onAnimationFrame ); 13456 13457 } 13458 13459 return { 13460 13461 start: function () { 13462 13463 if ( isAnimating === true ) return; 13464 if ( animationLoop === null ) return; 13465 13466 requestId = context.requestAnimationFrame( onAnimationFrame ); 13467 13468 isAnimating = true; 13469 13470 }, 13471 13472 stop: function () { 13473 13474 context.cancelAnimationFrame( requestId ); 13475 13476 isAnimating = false; 13477 13478 }, 13479 13480 setAnimationLoop: function ( callback ) { 13481 13482 animationLoop = callback; 13483 13484 }, 13485 13486 setContext: function ( value ) { 13487 13488 context = value; 13489 13490 } 13491 13492 }; 13493 13494} 13495 13496function WebGLAttributes( gl ) { 13497 13498 const buffers = new WeakMap(); 13499 13500 function createBuffer( attribute, bufferType ) { 13501 13502 const array = attribute.array; 13503 const usage = attribute.usage; 13504 const size = array.byteLength; 13505 13506 const buffer = gl.createBuffer(); 13507 13508 gl.bindBuffer( bufferType, buffer ); 13509 gl.bufferData( bufferType, array, usage ); 13510 13511 attribute.onUploadCallback(); 13512 13513 let type; 13514 13515 if ( array instanceof Float32Array ) { 13516 13517 type = gl.FLOAT; 13518 13519 } else if ( array instanceof Uint16Array ) { 13520 13521 if ( attribute.isFloat16BufferAttribute ) { 13522 13523 type = gl.HALF_FLOAT; 13524 13525 } else { 13526 13527 type = gl.UNSIGNED_SHORT; 13528 13529 } 13530 13531 } else if ( array instanceof Int16Array ) { 13532 13533 type = gl.SHORT; 13534 13535 } else if ( array instanceof Uint32Array ) { 13536 13537 type = gl.UNSIGNED_INT; 13538 13539 } else if ( array instanceof Int32Array ) { 13540 13541 type = gl.INT; 13542 13543 } else if ( array instanceof Int8Array ) { 13544 13545 type = gl.BYTE; 13546 13547 } else if ( array instanceof Uint8Array ) { 13548 13549 type = gl.UNSIGNED_BYTE; 13550 13551 } else if ( array instanceof Uint8ClampedArray ) { 13552 13553 type = gl.UNSIGNED_BYTE; 13554 13555 } else { 13556 13557 throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array ); 13558 13559 } 13560 13561 return { 13562 buffer: buffer, 13563 type: type, 13564 bytesPerElement: array.BYTES_PER_ELEMENT, 13565 version: attribute.version, 13566 size: size 13567 }; 13568 13569 } 13570 13571 function updateBuffer( buffer, attribute, bufferType ) { 13572 13573 const array = attribute.array; 13574 const updateRange = attribute._updateRange; // @deprecated, r159 13575 const updateRanges = attribute.updateRanges; 13576 13577 gl.bindBuffer( bufferType, buffer ); 13578 13579 if ( updateRange.count === - 1 && updateRanges.length === 0 ) { 13580 13581 // Not using update ranges 13582 gl.bufferSubData( bufferType, 0, array ); 13583 13584 } 13585 13586 if ( updateRanges.length !== 0 ) { 13587 13588 for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { 13589 13590 const range = updateRanges[ i ]; 13591 13592 gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, 13593 array, range.start, range.count ); 13594 13595 } 13596 13597 attribute.clearUpdateRanges(); 13598 13599 } 13600 13601 // @deprecated, r159 13602 if ( updateRange.count !== - 1 ) { 13603 13604 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, 13605 array, updateRange.offset, updateRange.count ); 13606 13607 updateRange.count = - 1; // reset range 13608 13609 } 13610 13611 attribute.onUploadCallback(); 13612 13613 } 13614 13615 // 13616 13617 function get( attribute ) { 13618 13619 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 13620 13621 return buffers.get( attribute ); 13622 13623 } 13624 13625 function remove( attribute ) { 13626 13627 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 13628 13629 const data = buffers.get( attribute ); 13630 13631 if ( data ) { 13632 13633 gl.deleteBuffer( data.buffer ); 13634 13635 buffers.delete( attribute ); 13636 13637 } 13638 13639 } 13640 13641 function update( attribute, bufferType ) { 13642 13643 if ( attribute.isGLBufferAttribute ) { 13644 13645 const cached = buffers.get( attribute ); 13646 13647 if ( ! cached || cached.version < attribute.version ) { 13648 13649 buffers.set( attribute, { 13650 buffer: attribute.buffer, 13651 type: attribute.type, 13652 bytesPerElement: attribute.elementSize, 13653 version: attribute.version 13654 } ); 13655 13656 } 13657 13658 return; 13659 13660 } 13661 13662 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 13663 13664 const data = buffers.get( attribute ); 13665 13666 if ( data === undefined ) { 13667 13668 buffers.set( attribute, createBuffer( attribute, bufferType ) ); 13669 13670 } else if ( data.version < attribute.version ) { 13671 13672 if ( data.size !== attribute.array.byteLength ) { 13673 13674 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.' ); 13675 13676 } 13677 13678 updateBuffer( data.buffer, attribute, bufferType ); 13679 13680 data.version = attribute.version; 13681 13682 } 13683 13684 } 13685 13686 return { 13687 13688 get: get, 13689 remove: remove, 13690 update: update 13691 13692 }; 13693 13694} 13695 13696class PlaneGeometry extends BufferGeometry { 13697 13698 constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) { 13699 13700 super(); 13701 13702 this.type = 'PlaneGeometry'; 13703 13704 this.parameters = { 13705 width: width, 13706 height: height, 13707 widthSegments: widthSegments, 13708 heightSegments: heightSegments 13709 }; 13710 13711 const width_half = width / 2; 13712 const height_half = height / 2; 13713 13714 const gridX = Math.floor( widthSegments ); 13715 const gridY = Math.floor( heightSegments ); 13716 13717 const gridX1 = gridX + 1; 13718 const gridY1 = gridY + 1; 13719 13720 const segment_width = width / gridX; 13721 const segment_height = height / gridY; 13722 13723 // 13724 13725 const indices = []; 13726 const vertices = []; 13727 const normals = []; 13728 const uvs = []; 13729 13730 for ( let iy = 0; iy < gridY1; iy ++ ) { 13731 13732 const y = iy * segment_height - height_half; 13733 13734 for ( let ix = 0; ix < gridX1; ix ++ ) { 13735 13736 const x = ix * segment_width - width_half; 13737 13738 vertices.push( x, - y, 0 ); 13739 13740 normals.push( 0, 0, 1 ); 13741 13742 uvs.push( ix / gridX ); 13743 uvs.push( 1 - ( iy / gridY ) ); 13744 13745 } 13746 13747 } 13748 13749 for ( let iy = 0; iy < gridY; iy ++ ) { 13750 13751 for ( let ix = 0; ix < gridX; ix ++ ) { 13752 13753 const a = ix + gridX1 * iy; 13754 const b = ix + gridX1 * ( iy + 1 ); 13755 const c = ( ix + 1 ) + gridX1 * ( iy + 1 ); 13756 const d = ( ix + 1 ) + gridX1 * iy; 13757 13758 indices.push( a, b, d ); 13759 indices.push( b, c, d ); 13760 13761 } 13762 13763 } 13764 13765 this.setIndex( indices ); 13766 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 13767 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 13768 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 13769 13770 } 13771 13772 copy( source ) { 13773 13774 super.copy( source ); 13775 13776 this.parameters = Object.assign( {}, source.parameters ); 13777 13778 return this; 13779 13780 } 13781 13782 static fromJSON( data ) { 13783 13784 return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments ); 13785 13786 } 13787 13788} 13789 13790var alphahash_fragment = "#ifdef USE_ALPHAHASH\n\tif ( diffuseColor.a < getAlphaHashThreshold( vPosition ) ) discard;\n#endif"; 13791 13792var 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"; 13793 13794var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif"; 13795 13796var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; 13797 13798var 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"; 13799 13800var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif"; 13801 13802var 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"; 13803 13804var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; 13805 13806var 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\n#ifdef USE_BATCHING_COLOR\n\tuniform sampler2D batchingColorTexture;\n\tvec3 getBatchingColor( const in float i ) {\n\t\tint size = textureSize( batchingColorTexture, 0 ).x;\n\t\tint j = int( i );\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\treturn texelFetch( batchingColorTexture, ivec2( x, y ), 0 ).rgb
vendor: 7,693 bytes, lines 13806-13832
13806;\n\t}\n#endif"; 13807 13808var batching_vertex = "#ifdef USE_BATCHING\n\tmat4 batchingMatrix = getBatchingMatrix( batchId );\n#endif"; 13809 13810var begin_vertex = "vec3 transformed = vec3( position );\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif"; 13811 13812var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif"; 13813 13814var 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"; 13815 13816var 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"; 13817 13818var 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"; 13819 13820var 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"; 13821 13822var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif"; 13823 13824var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif"; 13825 13826var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif"; 13827 13828var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif"; 13829 13830var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif"; 13831 13832var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )
13832 || defined( USE_BATCHING_COLOR )\n\tvarying vec3 vColor;\n#endif"; 13833 13834var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_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\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( batchId );\n\tvColor.xyz *= batching
vendor: 11,862 bytes, lines 13834-13862
13834Color.xyz;\n#endif"; 13835 13836var 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"; 13837 13838var 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"; 13839 13840var 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"; 13841 13842var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif"; 13843 13844var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif"; 13845 13846var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; 13847 13848var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif"; 13849 13850var colorspace_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );"; 13851 13852var 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}"; 13853 13854var 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"; 13855 13856var 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"; 13857 13858var 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"; 13859 13860var 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"; 13861 13862var 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}
vendor: 5,745 bytes, lines 13862-13880
13862 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"; 13863 13864var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif"; 13865 13866var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif"; 13867 13868var 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"; 13869 13870var 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"; 13871 13872var 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}"; 13873 13874var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; 13875 13876var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;"; 13877 13878var 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"; 13879 13880var 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\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\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}
vendor: 8,222 bytes, lines 13880-13892
13880\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"; 13881 13882var 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"; 13883 13884var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; 13885 13886var 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"; 13887 13888var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;"; 13889 13890var 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"; 13891 13892var 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_
13892DISPERSION\n\tmaterial.dispersion = dispersion;\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"; 13893 13894var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion
vendor: 22,309 bytes, lines 13894-13902
13894;\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}"; 13895 13896var 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"; 13897 13898var 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"; 13899 13900var 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"; 13901 13902var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF )
13902\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; 13903 13904var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif"; 13905 13906var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif"; 13907 13908var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n#endif"; 13909 13910var 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"; 13911 13912var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif"; 13913 13914var 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"; 13915 13916var 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"; 13917 13918var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; 13919 13920var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; 13921 13922var 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"; 13923 13924var morphcolor_vertex = "#if defined( USE_MORPHCOLORS )\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"; 13925 13926var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif"; 13927 13928var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t#endif\n\tuniform sampler2DArray morphTargetsTexture;\n\tuniform ivec2 morphTargetsTextureSize;\n\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t}\n#endif"; 13929 13930var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t}
vendor: 15,324 bytes, lines 13930-13968
13930\n#endif"; 13931 13932var 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;"; 13933 13934var 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"; 13935 13936var 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"; 13937 13938var 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"; 13939 13940var 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"; 13941 13942var 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"; 13943 13944var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif"; 13945 13946var 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"; 13947 13948var 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"; 13949 13950var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif"; 13951 13952var 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 );"; 13953 13954var 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}"; 13955 13956var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif"; 13957 13958var 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;"; 13959 13960var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif"; 13961 13962var 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"; 13963 13964var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; 13965 13966var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; 13967 13968var 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
13968float 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: 9,652 bytes, lines 13968-13990
13968\n\t}\n#endif"; 13969 13970var 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"; 13971 13972var 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"; 13973 13974var 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}"; 13975 13976var 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"; 13977 13978var 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"; 13979 13980var 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"; 13981 13982var 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"; 13983 13984var 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"; 13985 13986var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; 13987 13988var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif"; 13989 13990var 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\t
13990const float StartCompression = 0.8 - 0.04;\n\tconst float 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, vec3( newPeak ), g );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; 13991 13992var 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.dispersion, 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"; 13993 13994var 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 dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t\n\t\t#else\n\t\t\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t
vendor: 6,265 bytes, lines 13994-14000
13994\n\t\t#endif\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"; 13995 13996var 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"; 13997 13998var 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"; 13999 14000var 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: 25,481 bytes, lines 14000-14054
14000\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"; 14001 14002var 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"; 14003 14004const 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}"; 14005 14006const 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}"; 14007 14008const 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}"; 14009 14010const 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}"; 14011 14012const 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}"; 14013 14014const 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}"; 14015 14016const 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}"; 14017 14018const 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}"; 14019 14020const 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}"; 14021 14022const 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}"; 14023 14024const 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}"; 14025 14026const 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}"; 14027 14028const 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}"; 14029 14030const 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}"; 14031 14032const 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}"; 14033 14034const 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}"; 14035 14036const 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}"; 14037 14038const 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}"; 14039 14040const 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}"; 14041 14042const 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}"; 14043 14044const 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}"; 14045 14046const 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}"; 14047 14048const 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}"; 14049 14050const 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}"; 14051 14052const 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}"; 14053 14054const 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;
vendor: 3,685 bytes, line 14054
14054\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\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}"
vendor: 20,991 bytes, lines 14054-14570
14054; 14055 14056const 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}"; 14057 14058const 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}"; 14059 14060const 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}"; 14061 14062const 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}"; 14063 14064const 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}"; 14065 14066const 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}"; 14067 14068const 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}"; 14069 14070const 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}"; 14071 14072const ShaderChunk = { 14073 alphahash_fragment: alphahash_fragment, 14074 alphahash_pars_fragment: alphahash_pars_fragment, 14075 alphamap_fragment: alphamap_fragment, 14076 alphamap_pars_fragment: alphamap_pars_fragment, 14077 alphatest_fragment: alphatest_fragment, 14078 alphatest_pars_fragment: alphatest_pars_fragment, 14079 aomap_fragment: aomap_fragment, 14080 aomap_pars_fragment: aomap_pars_fragment, 14081 batching_pars_vertex: batching_pars_vertex, 14082 batching_vertex: batching_vertex, 14083 begin_vertex: begin_vertex, 14084 beginnormal_vertex: beginnormal_vertex, 14085 bsdfs: bsdfs, 14086 iridescence_fragment: iridescence_fragment, 14087 bumpmap_pars_fragment: bumpmap_pars_fragment, 14088 clipping_planes_fragment: clipping_planes_fragment, 14089 clipping_planes_pars_fragment: clipping_planes_pars_fragment, 14090 clipping_planes_pars_vertex: clipping_planes_pars_vertex, 14091 clipping_planes_vertex: clipping_planes_vertex, 14092 color_fragment: color_fragment, 14093 color_pars_fragment: color_pars_fragment, 14094 color_pars_vertex: color_pars_vertex, 14095 color_vertex: color_vertex, 14096 common: common, 14097 cube_uv_reflection_fragment: cube_uv_reflection_fragment, 14098 defaultnormal_vertex: defaultnormal_vertex, 14099 displacementmap_pars_vertex: displacementmap_pars_vertex, 14100 displacementmap_vertex: displacementmap_vertex, 14101 emissivemap_fragment: emissivemap_fragment, 14102 emissivemap_pars_fragment: emissivemap_pars_fragment, 14103 colorspace_fragment: colorspace_fragment, 14104 colorspace_pars_fragment: colorspace_pars_fragment, 14105 envmap_fragment: envmap_fragment, 14106 envmap_common_pars_fragment: envmap_common_pars_fragment, 14107 envmap_pars_fragment: envmap_pars_fragment, 14108 envmap_pars_vertex: envmap_pars_vertex, 14109 envmap_physical_pars_fragment: envmap_physical_pars_fragment, 14110 envmap_vertex: envmap_vertex, 14111 fog_vertex: fog_vertex, 14112 fog_pars_vertex: fog_pars_vertex, 14113 fog_fragment: fog_fragment, 14114 fog_pars_fragment: fog_pars_fragment, 14115 gradientmap_pars_fragment: gradientmap_pars_fragment, 14116 lightmap_pars_fragment: lightmap_pars_fragment, 14117 lights_lambert_fragment: lights_lambert_fragment, 14118 lights_lambert_pars_fragment: lights_lambert_pars_fragment, 14119 lights_pars_begin: lights_pars_begin, 14120 lights_toon_fragment: lights_toon_fragment, 14121 lights_toon_pars_fragment: lights_toon_pars_fragment, 14122 lights_phong_fragment: lights_phong_fragment, 14123 lights_phong_pars_fragment: lights_phong_pars_fragment, 14124 lights_physical_fragment: lights_physical_fragment, 14125 lights_physical_pars_fragment: lights_physical_pars_fragment, 14126 lights_fragment_begin: lights_fragment_begin, 14127 lights_fragment_maps: lights_fragment_maps, 14128 lights_fragment_end: lights_fragment_end, 14129 logdepthbuf_fragment: logdepthbuf_fragment, 14130 logdepthbuf_pars_fragment: logdepthbuf_pars_fragment, 14131 logdepthbuf_pars_vertex: logdepthbuf_pars_vertex, 14132 logdepthbuf_vertex: logdepthbuf_vertex, 14133 map_fragment: map_fragment, 14134 map_pars_fragment: map_pars_fragment, 14135 map_particle_fragment: map_particle_fragment, 14136 map_particle_pars_fragment: map_particle_pars_fragment, 14137 metalnessmap_fragment: metalnessmap_fragment, 14138 metalnessmap_pars_fragment: metalnessmap_pars_fragment, 14139 morphinstance_vertex: morphinstance_vertex, 14140 morphcolor_vertex: morphcolor_vertex, 14141 morphnormal_vertex: morphnormal_vertex, 14142 morphtarget_pars_vertex: morphtarget_pars_vertex, 14143 morphtarget_vertex: morphtarget_vertex, 14144 normal_fragment_begin: normal_fragment_begin, 14145 normal_fragment_maps: normal_fragment_maps, 14146 normal_pars_fragment: normal_pars_fragment, 14147 normal_pars_vertex: normal_pars_vertex, 14148 normal_vertex: normal_vertex, 14149 normalmap_pars_fragment: normalmap_pars_fragment, 14150 clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin, 14151 clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps, 14152 clearcoat_pars_fragment: clearcoat_pars_fragment, 14153 iridescence_pars_fragment: iridescence_pars_fragment, 14154 opaque_fragment: opaque_fragment, 14155 packing: packing, 14156 premultiplied_alpha_fragment: premultiplied_alpha_fragment, 14157 project_vertex: project_vertex, 14158 dithering_fragment: dithering_fragment, 14159 dithering_pars_fragment: dithering_pars_fragment, 14160 roughnessmap_fragment: roughnessmap_fragment, 14161 roughnessmap_pars_fragment: roughnessmap_pars_fragment, 14162 shadowmap_pars_fragment: shadowmap_pars_fragment, 14163 shadowmap_pars_vertex: shadowmap_pars_vertex, 14164 shadowmap_vertex: shadowmap_vertex, 14165 shadowmask_pars_fragment: shadowmask_pars_fragment, 14166 skinbase_vertex: skinbase_vertex, 14167 skinning_pars_vertex: skinning_pars_vertex, 14168 skinning_vertex: skinning_vertex, 14169 skinnormal_vertex: skinnormal_vertex, 14170 specularmap_fragment: specularmap_fragment, 14171 specularmap_pars_fragment: specularmap_pars_fragment, 14172 tonemapping_fragment: tonemapping_fragment, 14173 tonemapping_pars_fragment: tonemapping_pars_fragment, 14174 transmission_fragment: transmission_fragment, 14175 transmission_pars_fragment: transmission_pars_fragment, 14176 uv_pars_fragment: uv_pars_fragment, 14177 uv_pars_vertex: uv_pars_vertex, 14178 uv_vertex: uv_vertex, 14179 worldpos_vertex: worldpos_vertex, 14180 14181 background_vert: vertex$h, 14182 background_frag: fragment$h, 14183 backgroundCube_vert: vertex$g, 14184 backgroundCube_frag: fragment$g, 14185 cube_vert: vertex$f, 14186 cube_frag: fragment$f, 14187 depth_vert: vertex$e, 14188 depth_frag: fragment$e, 14189 distanceRGBA_vert: vertex$d, 14190 distanceRGBA_frag: fragment$d, 14191 equirect_vert: vertex$c, 14192 equirect_frag: fragment$c, 14193 linedashed_vert: vertex$b, 14194 linedashed_frag: fragment$b, 14195 meshbasic_vert: vertex$a, 14196 meshbasic_frag: fragment$a, 14197 meshlambert_vert: vertex$9, 14198 meshlambert_frag: fragment$9, 14199 meshmatcap_vert: vertex$8, 14200 meshmatcap_frag: fragment$8, 14201 meshnormal_vert: vertex$7, 14202 meshnormal_frag: fragment$7, 14203 meshphong_vert: vertex$6, 14204 meshphong_frag: fragment$6, 14205 meshphysical_vert: vertex$5, 14206 meshphysical_frag: fragment$5, 14207 meshtoon_vert: vertex$4, 14208 meshtoon_frag: fragment$4, 14209 points_vert: vertex$3, 14210 points_frag: fragment$3, 14211 shadow_vert: vertex$2, 14212 shadow_frag: fragment$2, 14213 sprite_vert: vertex$1, 14214 sprite_frag: fragment$1 14215}; 14216 14217/** 14218 * Uniforms library for shared webgl shaders 14219 */ 14220 14221const UniformsLib = { 14222 14223 common: { 14224 14225 diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, 14226 opacity: { value: 1.0 }, 14227 14228 map: { value: null }, 14229 mapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14230 14231 alphaMap: { value: null }, 14232 alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14233 14234 alphaTest: { value: 0 } 14235 14236 }, 14237 14238 specularmap: { 14239 14240 specularMap: { value: null }, 14241 specularMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14242 14243 }, 14244 14245 envmap: { 14246 14247 envMap: { value: null }, 14248 envMapRotation: { value: /*@__PURE__*/ new Matrix3() }, 14249 flipEnvMap: { value: - 1 }, 14250 reflectivity: { value: 1.0 }, // basic, lambert, phong 14251 ior: { value: 1.5 }, // physical 14252 refractionRatio: { value: 0.98 }, // basic, lambert, phong 14253 14254 }, 14255 14256 aomap: { 14257 14258 aoMap: { value: null }, 14259 aoMapIntensity: { value: 1 }, 14260 aoMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14261 14262 }, 14263 14264 lightmap: { 14265 14266 lightMap: { value: null }, 14267 lightMapIntensity: { value: 1 }, 14268 lightMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14269 14270 }, 14271 14272 bumpmap: { 14273 14274 bumpMap: { value: null }, 14275 bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14276 bumpScale: { value: 1 } 14277 14278 }, 14279 14280 normalmap: { 14281 14282 normalMap: { value: null }, 14283 normalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14284 normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) } 14285 14286 }, 14287 14288 displacementmap: { 14289 14290 displacementMap: { value: null }, 14291 displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14292 displacementScale: { value: 1 }, 14293 displacementBias: { value: 0 } 14294 14295 }, 14296 14297 emissivemap: { 14298 14299 emissiveMap: { value: null }, 14300 emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14301 14302 }, 14303 14304 metalnessmap: { 14305 14306 metalnessMap: { value: null }, 14307 metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14308 14309 }, 14310 14311 roughnessmap: { 14312 14313 roughnessMap: { value: null }, 14314 roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14315 14316 }, 14317 14318 gradientmap: { 14319 14320 gradientMap: { value: null } 14321 14322 }, 14323 14324 fog: { 14325 14326 fogDensity: { value: 0.00025 }, 14327 fogNear: { value: 1 }, 14328 fogFar: { value: 2000 }, 14329 fogColor: { value: /*@__PURE__*/ new Color( 0xffffff ) } 14330 14331 }, 14332 14333 lights: { 14334 14335 ambientLightColor: { value: [] }, 14336 14337 lightProbe: { value: [] }, 14338 14339 directionalLights: { value: [], properties: { 14340 direction: {}, 14341 color: {} 14342 } }, 14343 14344 directionalLightShadows: { value: [], properties: { 14345 shadowBias: {}, 14346 shadowNormalBias: {}, 14347 shadowRadius: {}, 14348 shadowMapSize: {} 14349 } }, 14350 14351 directionalShadowMap: { value: [] }, 14352 directionalShadowMatrix: { value: [] }, 14353 14354 spotLights: { value: [], properties: { 14355 color: {}, 14356 position: {}, 14357 direction: {}, 14358 distance: {}, 14359 coneCos: {}, 14360 penumbraCos: {}, 14361 decay: {} 14362 } }, 14363 14364 spotLightShadows: { value: [], properties: { 14365 shadowBias: {}, 14366 shadowNormalBias: {}, 14367 shadowRadius: {}, 14368 shadowMapSize: {} 14369 } }, 14370 14371 spotLightMap: { value: [] }, 14372 spotShadowMap: { value: [] }, 14373 spotLightMatrix: { value: [] }, 14374 14375 pointLights: { value: [], properties: { 14376 color: {}, 14377 position: {}, 14378 decay: {}, 14379 distance: {} 14380 } }, 14381 14382 pointLightShadows: { value: [], properties: { 14383 shadowBias: {}, 14384 shadowNormalBias: {}, 14385 shadowRadius: {}, 14386 shadowMapSize: {}, 14387 shadowCameraNear: {}, 14388 shadowCameraFar: {} 14389 } }, 14390 14391 pointShadowMap: { value: [] }, 14392 pointShadowMatrix: { value: [] }, 14393 14394 hemisphereLights: { value: [], properties: { 14395 direction: {}, 14396 skyColor: {}, 14397 groundColor: {} 14398 } }, 14399 14400 // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src 14401 rectAreaLights: { value: [], properties: { 14402 color: {}, 14403 position: {}, 14404 width: {}, 14405 height: {} 14406 } }, 14407 14408 ltc_1: { value: null }, 14409 ltc_2: { value: null } 14410 14411 }, 14412 14413 points: { 14414 14415 diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, 14416 opacity: { value: 1.0 }, 14417 size: { value: 1.0 }, 14418 scale: { value: 1.0 }, 14419 map: { value: null }, 14420 alphaMap: { value: null }, 14421 alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14422 alphaTest: { value: 0 }, 14423 uvTransform: { value: /*@__PURE__*/ new Matrix3() } 14424 14425 }, 14426 14427 sprite: { 14428 14429 diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, 14430 opacity: { value: 1.0 }, 14431 center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) }, 14432 rotation: { value: 0.0 }, 14433 map: { value: null }, 14434 mapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14435 alphaMap: { value: null }, 14436 alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14437 alphaTest: { value: 0 } 14438 14439 } 14440 14441}; 14442 14443const ShaderLib = { 14444 14445 basic: { 14446 14447 uniforms: /*@__PURE__*/ mergeUniforms( [ 14448 UniformsLib.common, 14449 UniformsLib.specularmap, 14450 UniformsLib.envmap, 14451 UniformsLib.aomap, 14452 UniformsLib.lightmap, 14453 UniformsLib.fog 14454 ] ), 14455 14456 vertexShader: ShaderChunk.meshbasic_vert, 14457 fragmentShader: ShaderChunk.meshbasic_frag 14458 14459 }, 14460 14461 lambert: { 14462 14463 uniforms: /*@__PURE__*/ mergeUniforms( [ 14464 UniformsLib.common, 14465 UniformsLib.specularmap, 14466 UniformsLib.envmap, 14467 UniformsLib.aomap, 14468 UniformsLib.lightmap, 14469 UniformsLib.emissivemap, 14470 UniformsLib.bumpmap, 14471 UniformsLib.normalmap, 14472 UniformsLib.displacementmap, 14473 UniformsLib.fog, 14474 UniformsLib.lights, 14475 { 14476 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) } 14477 } 14478 ] ), 14479 14480 vertexShader: ShaderChunk.meshlambert_vert, 14481 fragmentShader: ShaderChunk.meshlambert_frag 14482 14483 }, 14484 14485 phong: { 14486 14487 uniforms: /*@__PURE__*/ mergeUniforms( [ 14488 UniformsLib.common, 14489 UniformsLib.specularmap, 14490 UniformsLib.envmap, 14491 UniformsLib.aomap, 14492 UniformsLib.lightmap, 14493 UniformsLib.emissivemap, 14494 UniformsLib.bumpmap, 14495 UniformsLib.normalmap, 14496 UniformsLib.displacementmap, 14497 UniformsLib.fog, 14498 UniformsLib.lights, 14499 { 14500 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 14501 specular: { value: /*@__PURE__*/ new Color( 0x111111 ) }, 14502 shininess: { value: 30 } 14503 } 14504 ] ), 14505 14506 vertexShader: ShaderChunk.meshphong_vert, 14507 fragmentShader: ShaderChunk.meshphong_frag 14508 14509 }, 14510 14511 standard: { 14512 14513 uniforms: /*@__PURE__*/ mergeUniforms( [ 14514 UniformsLib.common, 14515 UniformsLib.envmap, 14516 UniformsLib.aomap, 14517 UniformsLib.lightmap, 14518 UniformsLib.emissivemap, 14519 UniformsLib.bumpmap, 14520 UniformsLib.normalmap, 14521 UniformsLib.displacementmap, 14522 UniformsLib.roughnessmap, 14523 UniformsLib.metalnessmap, 14524 UniformsLib.fog, 14525 UniformsLib.lights, 14526 { 14527 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 14528 roughness: { value: 1.0 }, 14529 metalness: { value: 0.0 }, 14530 envMapIntensity: { value: 1 } 14531 } 14532 ] ), 14533 14534 vertexShader: ShaderChunk.meshphysical_vert, 14535 fragmentShader: ShaderChunk.meshphysical_frag 14536 14537 }, 14538 14539 toon: { 14540 14541 uniforms: /*@__PURE__*/ mergeUniforms( [ 14542 UniformsLib.common, 14543 UniformsLib.aomap, 14544 UniformsLib.lightmap, 14545 UniformsLib.emissivemap, 14546 UniformsLib.bumpmap, 14547 UniformsLib.normalmap, 14548 UniformsLib.displacementmap, 14549 UniformsLib.gradientmap, 14550 UniformsLib.fog, 14551 UniformsLib.lights, 14552 { 14553 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) } 14554 } 14555 ] ), 14556 14557 vertexShader: ShaderChunk.meshtoon_vert, 14558 fragmentShader: ShaderChunk.meshtoon_frag 14559 14560 }, 14561 14562 matcap: { 14563 14564 uniforms: /*@__PURE__*/ mergeUniforms( [ 14565 UniformsLib.common, 14566 UniformsLib.bumpmap, 14567 UniformsLib.normalmap, 14568 UniformsLib.displacementmap, 14569 UniformsLib.fog, 14570 {
vendor: 5,447 bytes, lines 14571-14797
14571 matcap: { value: null } 14572 } 14573 ] ), 14574 14575 vertexShader: ShaderChunk.meshmatcap_vert, 14576 fragmentShader: ShaderChunk.meshmatcap_frag 14577 14578 }, 14579 14580 points: { 14581 14582 uniforms: /*@__PURE__*/ mergeUniforms( [ 14583 UniformsLib.points, 14584 UniformsLib.fog 14585 ] ), 14586 14587 vertexShader: ShaderChunk.points_vert, 14588 fragmentShader: ShaderChunk.points_frag 14589 14590 }, 14591 14592 dashed: { 14593 14594 uniforms: /*@__PURE__*/ mergeUniforms( [ 14595 UniformsLib.common, 14596 UniformsLib.fog, 14597 { 14598 scale: { value: 1 }, 14599 dashSize: { value: 1 }, 14600 totalSize: { value: 2 } 14601 } 14602 ] ), 14603 14604 vertexShader: ShaderChunk.linedashed_vert, 14605 fragmentShader: ShaderChunk.linedashed_frag 14606 14607 }, 14608 14609 depth: { 14610 14611 uniforms: /*@__PURE__*/ mergeUniforms( [ 14612 UniformsLib.common, 14613 UniformsLib.displacementmap 14614 ] ), 14615 14616 vertexShader: ShaderChunk.depth_vert, 14617 fragmentShader: ShaderChunk.depth_frag 14618 14619 }, 14620 14621 normal: { 14622 14623 uniforms: /*@__PURE__*/ mergeUniforms( [ 14624 UniformsLib.common, 14625 UniformsLib.bumpmap, 14626 UniformsLib.normalmap, 14627 UniformsLib.displacementmap, 14628 { 14629 opacity: { value: 1.0 } 14630 } 14631 ] ), 14632 14633 vertexShader: ShaderChunk.meshnormal_vert, 14634 fragmentShader: ShaderChunk.meshnormal_frag 14635 14636 }, 14637 14638 sprite: { 14639 14640 uniforms: /*@__PURE__*/ mergeUniforms( [ 14641 UniformsLib.sprite, 14642 UniformsLib.fog 14643 ] ), 14644 14645 vertexShader: ShaderChunk.sprite_vert, 14646 fragmentShader: ShaderChunk.sprite_frag 14647 14648 }, 14649 14650 background: { 14651 14652 uniforms: { 14653 uvTransform: { value: /*@__PURE__*/ new Matrix3() }, 14654 t2D: { value: null }, 14655 backgroundIntensity: { value: 1 } 14656 }, 14657 14658 vertexShader: ShaderChunk.background_vert, 14659 fragmentShader: ShaderChunk.background_frag 14660 14661 }, 14662 14663 backgroundCube: { 14664 14665 uniforms: { 14666 envMap: { value: null }, 14667 flipEnvMap: { value: - 1 }, 14668 backgroundBlurriness: { value: 0 }, 14669 backgroundIntensity: { value: 1 }, 14670 backgroundRotation: { value: /*@__PURE__*/ new Matrix3() } 14671 }, 14672 14673 vertexShader: ShaderChunk.backgroundCube_vert, 14674 fragmentShader: ShaderChunk.backgroundCube_frag 14675 14676 }, 14677 14678 cube: { 14679 14680 uniforms: { 14681 tCube: { value: null }, 14682 tFlip: { value: - 1 }, 14683 opacity: { value: 1.0 } 14684 }, 14685 14686 vertexShader: ShaderChunk.cube_vert, 14687 fragmentShader: ShaderChunk.cube_frag 14688 14689 }, 14690 14691 equirect: { 14692 14693 uniforms: { 14694 tEquirect: { value: null }, 14695 }, 14696 14697 vertexShader: ShaderChunk.equirect_vert, 14698 fragmentShader: ShaderChunk.equirect_frag 14699 14700 }, 14701 14702 distanceRGBA: { 14703 14704 uniforms: /*@__PURE__*/ mergeUniforms( [ 14705 UniformsLib.common, 14706 UniformsLib.displacementmap, 14707 { 14708 referencePosition: { value: /*@__PURE__*/ new Vector3() }, 14709 nearDistance: { value: 1 }, 14710 farDistance: { value: 1000 } 14711 } 14712 ] ), 14713 14714 vertexShader: ShaderChunk.distanceRGBA_vert, 14715 fragmentShader: ShaderChunk.distanceRGBA_frag 14716 14717 }, 14718 14719 shadow: { 14720 14721 uniforms: /*@__PURE__*/ mergeUniforms( [ 14722 UniformsLib.lights, 14723 UniformsLib.fog, 14724 { 14725 color: { value: /*@__PURE__*/ new Color( 0x00000 ) }, 14726 opacity: { value: 1.0 } 14727 }, 14728 ] ), 14729 14730 vertexShader: ShaderChunk.shadow_vert, 14731 fragmentShader: ShaderChunk.shadow_frag 14732 14733 } 14734 14735}; 14736 14737ShaderLib.physical = { 14738 14739 uniforms: /*@__PURE__*/ mergeUniforms( [ 14740 ShaderLib.standard.uniforms, 14741 { 14742 clearcoat: { value: 0 }, 14743 clearcoatMap: { value: null }, 14744 clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14745 clearcoatNormalMap: { value: null }, 14746 clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14747 clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, 14748 clearcoatRoughness: { value: 0 }, 14749 clearcoatRoughnessMap: { value: null }, 14750 clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14751 dispersion: { value: 0 }, 14752 iridescence: { value: 0 }, 14753 iridescenceMap: { value: null }, 14754 iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14755 iridescenceIOR: { value: 1.3 }, 14756 iridescenceThicknessMinimum: { value: 100 }, 14757 iridescenceThicknessMaximum: { value: 400 }, 14758 iridescenceThicknessMap: { value: null }, 14759 iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14760 sheen: { value: 0 }, 14761 sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 14762 sheenColorMap: { value: null }, 14763 sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14764 sheenRoughness: { value: 1 }, 14765 sheenRoughnessMap: { value: null }, 14766 sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14767 transmission: { value: 0 }, 14768 transmissionMap: { value: null }, 14769 transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14770 transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() }, 14771 transmissionSamplerMap: { value: null }, 14772 thickness: { value: 0 }, 14773 thicknessMap: { value: null }, 14774 thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14775 attenuationDistance: { value: 0 }, 14776 attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 14777 specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) }, 14778 specularColorMap: { value: null }, 14779 specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14780 specularIntensity: { value: 1 }, 14781 specularIntensityMap: { value: null }, 14782 specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14783 anisotropyVector: { value: /*@__PURE__*/ new Vector2() }, 14784 anisotropyMap: { value: null }, 14785 anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14786 } 14787 ] ), 14788 14789 vertexShader: ShaderChunk.meshphysical_vert, 14790 fragmentShader: ShaderChunk.meshphysical_frag 14791 14792}; 14793 14794const _rgb = { r: 0, b: 0, g: 0 }; 14795const _e1$1 = /*@__PURE__*/ new Euler(); 14796const _m1$1 = /*@__PURE__*/ new Matrix4(); 14797
vendor: 4,415 bytes, lines 14798-14956
14798function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) { 14799 14800 const clearColor = new Color( 0x000000 ); 14801 let clearAlpha = alpha === true ? 0 : 1; 14802 14803 let planeMesh; 14804 let boxMesh; 14805 14806 let currentBackground = null; 14807 let currentBackgroundVersion = 0; 14808 let currentTonemapping = null; 14809 14810 function getBackground( scene ) { 14811 14812 let background = scene.isScene === true ? scene.background : null; 14813 14814 if ( background && background.isTexture ) { 14815 14816 const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background 14817 background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background ); 14818 14819 } 14820 14821 return background; 14822 14823 } 14824 14825 function render( scene ) { 14826 14827 let forceClear = false; 14828 const background = getBackground( scene ); 14829 14830 if ( background === null ) { 14831 14832 setClear( clearColor, clearAlpha ); 14833 14834 } else if ( background && background.isColor ) { 14835 14836 setClear( background, 1 ); 14837 forceClear = true; 14838 14839 } 14840 14841 const environmentBlendMode = renderer.xr.getEnvironmentBlendMode(); 14842 14843 if ( environmentBlendMode === 'additive' ) { 14844 14845 state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha ); 14846 14847 } else if ( environmentBlendMode === 'alpha-blend' ) { 14848 14849 state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha ); 14850 14851 } 14852 14853 if ( renderer.autoClear || forceClear ) { 14854 14855 // buffers might not be writable which is required to ensure a correct clear 14856 14857 state.buffers.depth.setTest( true ); 14858 state.buffers.depth.setMask( true ); 14859 state.buffers.color.setMask( true ); 14860 14861 renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); 14862 14863 } 14864 14865 } 14866 14867 function addToRenderList( renderList, scene ) { 14868 14869 const background = getBackground( scene ); 14870 14871 if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) { 14872 14873 if ( boxMesh === undefined ) { 14874 14875 boxMesh = new Mesh( 14876 new BoxGeometry( 1, 1, 1 ), 14877 new ShaderMaterial( { 14878 name: 'BackgroundCubeMaterial', 14879 uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ), 14880 vertexShader: ShaderLib.backgroundCube.vertexShader, 14881 fragmentShader: ShaderLib.backgroundCube.fragmentShader, 14882 side: BackSide, 14883 depthTest: false, 14884 depthWrite: false, 14885 fog: false 14886 } ) 14887 ); 14888 14889 boxMesh.geometry.deleteAttribute( 'normal' ); 14890 boxMesh.geometry.deleteAttribute( 'uv' ); 14891 14892 boxMesh.onBeforeRender = function ( renderer, scene, camera ) { 14893 14894 this.matrixWorld.copyPosition( camera.matrixWorld ); 14895 14896 }; 14897 14898 // add "envMap" material property so the renderer can evaluate it like for built-in materials 14899 Object.defineProperty( boxMesh.material, 'envMap', { 14900 14901 get: function () { 14902 14903 return this.uniforms.envMap.value; 14904 14905 } 14906 14907 } ); 14908 14909 objects.update( boxMesh ); 14910 14911 } 14912 14913 _e1$1.copy( scene.backgroundRotation ); 14914 14915 // accommodate left-handed frame 14916 _e1$1.x *= - 1; _e1$1.y *= - 1; _e1$1.z *= - 1; 14917 14918 if ( background.isCubeTexture && background.isRenderTargetTexture === false ) { 14919 14920 // environment maps which are not cube render targets or PMREMs follow a different convention 14921 _e1$1.y *= - 1; 14922 _e1$1.z *= - 1; 14923 14924 } 14925 14926 boxMesh.material.uniforms.envMap.value = background; 14927 boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1; 14928 boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness; 14929 boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; 14930 boxMesh.material.uniforms.backgroundRotation.value.setFromMatrix4( _m1$1.makeRotationFromEuler( _e1$1 ) ); 14931 boxMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer; 14932 14933 if ( currentBackground !== background || 14934 currentBackgroundVersion !== background.version || 14935 currentTonemapping !== renderer.toneMapping ) { 14936 14937 boxMesh.material.needsUpdate = true; 14938 14939 currentBackground = background; 14940 currentBackgroundVersion = background.version; 14941 currentTonemapping = renderer.toneMapping; 14942 14943 } 14944 14945 boxMesh.layers.enableAll(); 14946 14947 // push to the pre-sorted opaque render list 14948 renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null ); 14949 14950 } else if ( background && background.isTexture ) { 14951 14952 if ( planeMesh === undefined ) { 14953 14954 planeMesh = new Mesh( 14955 new PlaneGeometry( 2, 2 ), 14956 new ShaderMaterial( {
vendor: 14,224 bytes, lines 14957-15627
14957 name: 'BackgroundMaterial', 14958 uniforms: cloneUniforms( ShaderLib.background.uniforms ), 14959 vertexShader: ShaderLib.background.vertexShader, 14960 fragmentShader: ShaderLib.background.fragmentShader, 14961 side: FrontSide, 14962 depthTest: false, 14963 depthWrite: false, 14964 fog: false 14965 } ) 14966 ); 14967 14968 planeMesh.geometry.deleteAttribute( 'normal' ); 14969 14970 // add "map" material property so the renderer can evaluate it like for built-in materials 14971 Object.defineProperty( planeMesh.material, 'map', { 14972 14973 get: function () { 14974 14975 return this.uniforms.t2D.value; 14976 14977 } 14978 14979 } ); 14980 14981 objects.update( planeMesh ); 14982 14983 } 14984 14985 planeMesh.material.uniforms.t2D.value = background; 14986 planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; 14987 planeMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer; 14988 14989 if ( background.matrixAutoUpdate === true ) { 14990 14991 background.updateMatrix(); 14992 14993 } 14994 14995 planeMesh.material.uniforms.uvTransform.value.copy( background.matrix ); 14996 14997 if ( currentBackground !== background || 14998 currentBackgroundVersion !== background.version || 14999 currentTonemapping !== renderer.toneMapping ) { 15000 15001 planeMesh.material.needsUpdate = true; 15002 15003 currentBackground = background; 15004 currentBackgroundVersion = background.version; 15005 currentTonemapping = renderer.toneMapping; 15006 15007 } 15008 15009 planeMesh.layers.enableAll(); 15010 15011 // push to the pre-sorted opaque render list 15012 renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null ); 15013 15014 } 15015 15016 } 15017 15018 function setClear( color, alpha ) { 15019 15020 color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) ); 15021 15022 state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha ); 15023 15024 } 15025 15026 return { 15027 15028 getClearColor: function () { 15029 15030 return clearColor; 15031 15032 }, 15033 setClearColor: function ( color, alpha = 1 ) { 15034 15035 clearColor.set( color ); 15036 clearAlpha = alpha; 15037 setClear( clearColor, clearAlpha ); 15038 15039 }, 15040 getClearAlpha: function () { 15041 15042 return clearAlpha; 15043 15044 }, 15045 setClearAlpha: function ( alpha ) { 15046 15047 clearAlpha = alpha; 15048 setClear( clearColor, clearAlpha ); 15049 15050 }, 15051 render: render, 15052 addToRenderList: addToRenderList 15053 15054 }; 15055 15056} 15057 15058function WebGLBindingStates( gl, attributes ) { 15059 15060 const maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); 15061 15062 const bindingStates = {}; 15063 15064 const defaultState = createBindingState( null ); 15065 let currentState = defaultState; 15066 let forceUpdate = false; 15067 15068 function setup( object, material, program, geometry, index ) { 15069 15070 let updateBuffers = false; 15071 15072 const state = getBindingState( geometry, program, material ); 15073 15074 if ( currentState !== state ) { 15075 15076 currentState = state; 15077 bindVertexArrayObject( currentState.object ); 15078 15079 } 15080 15081 updateBuffers = needsUpdate( object, geometry, program, index ); 15082 15083 if ( updateBuffers ) saveCache( object, geometry, program, index ); 15084 15085 if ( index !== null ) { 15086 15087 attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); 15088 15089 } 15090 15091 if ( updateBuffers || forceUpdate ) { 15092 15093 forceUpdate = false; 15094 15095 setupVertexAttributes( object, material, program, geometry ); 15096 15097 if ( index !== null ) { 15098 15099 gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer ); 15100 15101 } 15102 15103 } 15104 15105 } 15106 15107 function createVertexArrayObject() { 15108 15109 return gl.createVertexArray(); 15110 15111 } 15112 15113 function bindVertexArrayObject( vao ) { 15114 15115 return gl.bindVertexArray( vao ); 15116 15117 } 15118 15119 function deleteVertexArrayObject( vao ) { 15120 15121 return gl.deleteVertexArray( vao ); 15122 15123 } 15124 15125 function getBindingState( geometry, program, material ) { 15126 15127 const wireframe = ( material.wireframe === true ); 15128 15129 let programMap = bindingStates[ geometry.id ]; 15130 15131 if ( programMap === undefined ) { 15132 15133 programMap = {}; 15134 bindingStates[ geometry.id ] = programMap; 15135 15136 } 15137 15138 let stateMap = programMap[ program.id ]; 15139 15140 if ( stateMap === undefined ) { 15141 15142 stateMap = {}; 15143 programMap[ program.id ] = stateMap; 15144 15145 } 15146 15147 let state = stateMap[ wireframe ]; 15148 15149 if ( state === undefined ) { 15150 15151 state = createBindingState( createVertexArrayObject() ); 15152 stateMap[ wireframe ] = state; 15153 15154 } 15155 15156 return state; 15157 15158 } 15159 15160 function createBindingState( vao ) { 15161 15162 const newAttributes = []; 15163 const enabledAttributes = []; 15164 const attributeDivisors = []; 15165 15166 for ( let i = 0; i < maxVertexAttributes; i ++ ) { 15167 15168 newAttributes[ i ] = 0; 15169 enabledAttributes[ i ] = 0; 15170 attributeDivisors[ i ] = 0; 15171 15172 } 15173 15174 return { 15175 15176 // for backward compatibility on non-VAO support browser 15177 geometry: null, 15178 program: null, 15179 wireframe: false, 15180 15181 newAttributes: newAttributes, 15182 enabledAttributes: enabledAttributes, 15183 attributeDivisors: attributeDivisors, 15184 object: vao, 15185 attributes: {}, 15186 index: null 15187 15188 }; 15189 15190 } 15191 15192 function needsUpdate( object, geometry, program, index ) { 15193 15194 const cachedAttributes = currentState.attributes; 15195 const geometryAttributes = geometry.attributes; 15196 15197 let attributesNum = 0; 15198 15199 const programAttributes = program.getAttributes(); 15200 15201 for ( const name in programAttributes ) { 15202 15203 const programAttribute = programAttributes[ name ]; 15204 15205 if ( programAttribute.location >= 0 ) { 15206 15207 const cachedAttribute = cachedAttributes[ name ]; 15208 let geometryAttribute = geometryAttributes[ name ]; 15209 15210 if ( geometryAttribute === undefined ) { 15211 15212 if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; 15213 if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; 15214 15215 } 15216 15217 if ( cachedAttribute === undefined ) return true; 15218 15219 if ( cachedAttribute.attribute !== geometryAttribute ) return true; 15220 15221 if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data ) return true; 15222 15223 attributesNum ++; 15224 15225 } 15226 15227 } 15228 15229 if ( currentState.attributesNum !== attributesNum ) return true; 15230 15231 if ( currentState.index !== index ) return true; 15232 15233 return false; 15234 15235 } 15236 15237 function saveCache( object, geometry, program, index ) { 15238 15239 const cache = {}; 15240 const attributes = geometry.attributes; 15241 let attributesNum = 0; 15242 15243 const programAttributes = program.getAttributes(); 15244 15245 for ( const name in programAttributes ) { 15246 15247 const programAttribute = programAttributes[ name ]; 15248 15249 if ( programAttribute.location >= 0 ) { 15250 15251 let attribute = attributes[ name ]; 15252 15253 if ( attribute === undefined ) { 15254 15255 if ( name === 'instanceMatrix' && object.instanceMatrix ) attribute = object.instanceMatrix; 15256 if ( name === 'instanceColor' && object.instanceColor ) attribute = object.instanceColor; 15257 15258 } 15259 15260 const data = {}; 15261 data.attribute = attribute; 15262 15263 if ( attribute && attribute.data ) { 15264 15265 data.data = attribute.data; 15266 15267 } 15268 15269 cache[ name ] = data; 15270 15271 attributesNum ++; 15272 15273 } 15274 15275 } 15276 15277 currentState.attributes = cache; 15278 currentState.attributesNum = attributesNum; 15279 15280 currentState.index = index; 15281 15282 } 15283 15284 function initAttributes() { 15285 15286 const newAttributes = currentState.newAttributes; 15287 15288 for ( let i = 0, il = newAttributes.length; i < il; i ++ ) { 15289 15290 newAttributes[ i ] = 0; 15291 15292 } 15293 15294 } 15295 15296 function enableAttribute( attribute ) { 15297 15298 enableAttributeAndDivisor( attribute, 0 ); 15299 15300 } 15301 15302 function enableAttributeAndDivisor( attribute, meshPerAttribute ) { 15303 15304 const newAttributes = currentState.newAttributes; 15305 const enabledAttributes = currentState.enabledAttributes; 15306 const attributeDivisors = currentState.attributeDivisors; 15307 15308 newAttributes[ attribute ] = 1; 15309 15310 if ( enabledAttributes[ attribute ] === 0 ) { 15311 15312 gl.enableVertexAttribArray( attribute ); 15313 enabledAttributes[ attribute ] = 1; 15314 15315 } 15316 15317 if ( attributeDivisors[ attribute ] !== meshPerAttribute ) { 15318 15319 gl.vertexAttribDivisor( attribute, meshPerAttribute ); 15320 attributeDivisors[ attribute ] = meshPerAttribute; 15321 15322 } 15323 15324 } 15325 15326 function disableUnusedAttributes() { 15327 15328 const newAttributes = currentState.newAttributes; 15329 const enabledAttributes = currentState.enabledAttributes; 15330 15331 for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) { 15332 15333 if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { 15334 15335 gl.disableVertexAttribArray( i ); 15336 enabledAttributes[ i ] = 0; 15337 15338 } 15339 15340 } 15341 15342 } 15343 15344 function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) { 15345 15346 if ( integer === true ) { 15347 15348 gl.vertexAttribIPointer( index, size, type, stride, offset ); 15349 15350 } else { 15351 15352 gl.vertexAttribPointer( index, size, type, normalized, stride, offset ); 15353 15354 } 15355 15356 } 15357 15358 function setupVertexAttributes( object, material, program, geometry ) { 15359 15360 initAttributes(); 15361 15362 const geometryAttributes = geometry.attributes; 15363 15364 const programAttributes = program.getAttributes(); 15365 15366 const materialDefaultAttributeValues = material.defaultAttributeValues; 15367 15368 for ( const name in programAttributes ) { 15369 15370 const programAttribute = programAttributes[ name ]; 15371 15372 if ( programAttribute.location >= 0 ) { 15373 15374 let geometryAttribute = geometryAttributes[ name ]; 15375 15376 if ( geometryAttribute === undefined ) { 15377 15378 if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; 15379 if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; 15380 15381 } 15382 15383 if ( geometryAttribute !== undefined ) { 15384 15385 const normalized = geometryAttribute.normalized; 15386 const size = geometryAttribute.itemSize; 15387 15388 const attribute = attributes.get( geometryAttribute ); 15389 15390 // TODO Attribute may not be available on context restore 15391 15392 if ( attribute === undefined ) continue; 15393 15394 const buffer = attribute.buffer; 15395 const type = attribute.type; 15396 const bytesPerElement = attribute.bytesPerElement; 15397 15398 // check for integer attributes 15399 15400 const integer = ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType ); 15401 15402 if ( geometryAttribute.isInterleavedBufferAttribute ) { 15403 15404 const data = geometryAttribute.data; 15405 const stride = data.stride; 15406 const offset = geometryAttribute.offset; 15407 15408 if ( data.isInstancedInterleavedBuffer ) { 15409 15410 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15411 15412 enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute ); 15413 15414 } 15415 15416 if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { 15417 15418 geometry._maxInstanceCount = data.meshPerAttribute * data.count; 15419 15420 } 15421 15422 } else { 15423 15424 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15425 15426 enableAttribute( programAttribute.location + i ); 15427 15428 } 15429 15430 } 15431 15432 gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); 15433 15434 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15435 15436 vertexAttribPointer( 15437 programAttribute.location + i, 15438 size / programAttribute.locationSize, 15439 type, 15440 normalized, 15441 stride * bytesPerElement, 15442 ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement, 15443 integer 15444 ); 15445 15446 } 15447 15448 } else { 15449 15450 if ( geometryAttribute.isInstancedBufferAttribute ) { 15451 15452 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15453 15454 enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute ); 15455 15456 } 15457 15458 if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { 15459 15460 geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; 15461 15462 } 15463 15464 } else { 15465 15466 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15467 15468 enableAttribute( programAttribute.location + i ); 15469 15470 } 15471 15472 } 15473 15474 gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); 15475 15476 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15477 15478 vertexAttribPointer( 15479 programAttribute.location + i, 15480 size / programAttribute.locationSize, 15481 type, 15482 normalized, 15483 size * bytesPerElement, 15484 ( size / programAttribute.locationSize ) * i * bytesPerElement, 15485 integer 15486 ); 15487 15488 } 15489 15490 } 15491 15492 } else if ( materialDefaultAttributeValues !== undefined ) { 15493 15494 const value = materialDefaultAttributeValues[ name ]; 15495 15496 if ( value !== undefined ) { 15497 15498 switch ( value.length ) { 15499 15500 case 2: 15501 gl.vertexAttrib2fv( programAttribute.location, value ); 15502 break; 15503 15504 case 3: 15505 gl.vertexAttrib3fv( programAttribute.location, value ); 15506 break; 15507 15508 case 4: 15509 gl.vertexAttrib4fv( programAttribute.location, value ); 15510 break; 15511 15512 default: 15513 gl.vertexAttrib1fv( programAttribute.location, value ); 15514 15515 } 15516 15517 } 15518 15519 } 15520 15521 } 15522 15523 } 15524 15525 disableUnusedAttributes(); 15526 15527 } 15528 15529 function dispose() { 15530 15531 reset(); 15532 15533 for ( const geometryId in bindingStates ) { 15534 15535 const programMap = bindingStates[ geometryId ]; 15536 15537 for ( const programId in programMap ) { 15538 15539 const stateMap = programMap[ programId ]; 15540 15541 for ( const wireframe in stateMap ) { 15542 15543 deleteVertexArrayObject( stateMap[ wireframe ].object ); 15544 15545 delete stateMap[ wireframe ]; 15546 15547 } 15548 15549 delete programMap[ programId ]; 15550 15551 } 15552 15553 delete bindingStates[ geometryId ]; 15554 15555 } 15556 15557 } 15558 15559 function releaseStatesOfGeometry( geometry ) { 15560 15561 if ( bindingStates[ geometry.id ] === undefined ) return; 15562 15563 const programMap = bindingStates[ geometry.id ]; 15564 15565 for ( const programId in programMap ) { 15566 15567 const stateMap = programMap[ programId ]; 15568 15569 for ( const wireframe in stateMap ) { 15570 15571 deleteVertexArrayObject( stateMap[ wireframe ].object ); 15572 15573 delete stateMap[ wireframe ]; 15574 15575 } 15576 15577 delete programMap[ programId ]; 15578 15579 } 15580 15581 delete bindingStates[ geometry.id ]; 15582 15583 } 15584 15585 function releaseStatesOfProgram( program ) { 15586 15587 for ( const geometryId in bindingStates ) { 15588 15589 const programMap = bindingStates[ geometryId ]; 15590 15591 if ( programMap[ program.id ] === undefined ) continue; 15592 15593 const stateMap = programMap[ program.id ]; 15594 15595 for ( const wireframe in stateMap ) { 15596 15597 deleteVertexArrayObject( stateMap[ wireframe ].object ); 15598 15599 delete stateMap[ wireframe ]; 15600 15601 } 15602 15603 delete programMap[ program.id ]; 15604 15605 } 15606 15607 } 15608 15609 function reset() { 15610 15611 resetDefaultState(); 15612 forceUpdate = true; 15613 15614 if ( currentState === defaultState ) return; 15615 15616 currentState = defaultState; 15617 bindVertexArrayObject( currentState.object ); 15618 15619 } 15620 15621 // for backward-compatibility 15622 15623 function resetDefaultState() { 15624 15625 defaultState.geometry = null; 15626 defaultState.program = null; 15627 defaultState.wireframe = false;
vendor: 1,634 bytes, lines 15628-15722
15628 15629 } 15630 15631 return { 15632 15633 setup: setup, 15634 reset: reset, 15635 resetDefaultState: resetDefaultState, 15636 dispose: dispose, 15637 releaseStatesOfGeometry: releaseStatesOfGeometry, 15638 releaseStatesOfProgram: releaseStatesOfProgram, 15639 15640 initAttributes: initAttributes, 15641 enableAttribute: enableAttribute, 15642 disableUnusedAttributes: disableUnusedAttributes 15643 15644 }; 15645 15646} 15647 15648function WebGLBufferRenderer( gl, extensions, info ) { 15649 15650 let mode; 15651 15652 function setMode( value ) { 15653 15654 mode = value; 15655 15656 } 15657 15658 function render( start, count ) { 15659 15660 gl.drawArrays( mode, start, count ); 15661 15662 info.update( count, mode, 1 ); 15663 15664 } 15665 15666 function renderInstances( start, count, primcount ) { 15667 15668 if ( primcount === 0 ) return; 15669 15670 gl.drawArraysInstanced( mode, start, count, primcount ); 15671 15672 info.update( count, mode, primcount ); 15673 15674 } 15675 15676 function renderMultiDraw( starts, counts, drawCount ) { 15677 15678 if ( drawCount === 0 ) return; 15679 15680 const extension = extensions.get( 'WEBGL_multi_draw' ); 15681 15682 if ( extension === null ) { 15683 15684 for ( let i = 0; i < drawCount; i ++ ) { 15685 15686 this.render( starts[ i ], counts[ i ] ); 15687 15688 } 15689 15690 } else { 15691 15692 extension.multiDrawArraysWEBGL( mode, starts, 0, counts, 0, drawCount ); 15693 15694 let elementCount = 0; 15695 for ( let i = 0; i < drawCount; i ++ ) { 15696 15697 elementCount += counts[ i ]; 15698 15699 } 15700 15701 info.update( elementCount, mode, 1 ); 15702 15703 } 15704 15705 } 15706 15707 function renderMultiDrawInstances( starts, counts, drawCount, primcount ) { 15708 15709 if ( drawCount === 0 ) return; 15710 15711 const extension = extensions.get( 'WEBGL_multi_draw' ); 15712 15713 if ( extension === null ) { 15714 15715 for ( let i = 0; i < starts.length; i ++ ) { 15716 15717 renderInstances( starts[ i ], counts[ i ], primcount[ i ] ); 15718 15719 } 15720 15721 } else { 15722
vendor: 3,529 bytes, lines 15723-15864
15723 extension.multiDrawArraysInstancedWEBGL( mode, starts, 0, counts, 0, primcount, 0, drawCount ); 15724 15725 let elementCount = 0; 15726 for ( let i = 0; i < drawCount; i ++ ) { 15727 15728 elementCount += counts[ i ]; 15729 15730 } 15731 15732 for ( let i = 0; i < primcount.length; i ++ ) { 15733 15734 info.update( elementCount, mode, primcount[ i ] ); 15735 15736 } 15737 15738 } 15739 15740 } 15741 15742 // 15743 15744 this.setMode = setMode; 15745 this.render = render; 15746 this.renderInstances = renderInstances; 15747 this.renderMultiDraw = renderMultiDraw; 15748 this.renderMultiDrawInstances = renderMultiDrawInstances; 15749 15750} 15751 15752function WebGLCapabilities( gl, extensions, parameters, utils ) { 15753 15754 let maxAnisotropy; 15755 15756 function getMaxAnisotropy() { 15757 15758 if ( maxAnisotropy !== undefined ) return maxAnisotropy; 15759 15760 if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { 15761 15762 const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); 15763 15764 maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); 15765 15766 } else { 15767 15768 maxAnisotropy = 0; 15769 15770 } 15771 15772 return maxAnisotropy; 15773 15774 } 15775 15776 function textureFormatReadable( textureFormat ) { 15777 15778 if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { 15779 15780 return false; 15781 15782 } 15783 15784 return true; 15785 15786 } 15787 15788 function textureTypeReadable( textureType ) { 15789 15790 const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ); 15791 15792 if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) 15793 textureType !== FloatType && ! halfFloatSupportedByExt ) { 15794 15795 return false; 15796 15797 } 15798 15799 return true; 15800 15801 } 15802 15803 function getMaxPrecision( precision ) { 15804 15805 if ( precision === 'highp' ) { 15806 15807 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 && 15808 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) { 15809 15810 return 'highp'; 15811 15812 } 15813 15814 precision = 'mediump'; 15815 15816 } 15817 15818 if ( precision === 'mediump' ) { 15819 15820 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 && 15821 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) { 15822 15823 return 'mediump'; 15824 15825 } 15826 15827 } 15828 15829 return 'lowp'; 15830 15831 } 15832 15833 let precision = parameters.precision !== undefined ? parameters.precision : 'highp'; 15834 const maxPrecision = getMaxPrecision( precision ); 15835 15836 if ( maxPrecision !== precision ) { 15837 15838 console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); 15839 precision = maxPrecision; 15840 15841 } 15842 15843 const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; 15844 15845 const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); 15846 const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); 15847 const maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE ); 15848 const maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE ); 15849 15850 const maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); 15851 const maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS ); 15852 const maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS ); 15853 const maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS ); 15854 15855 const vertexTextures = maxVertexTextures > 0; 15856 15857 const maxSamples = gl.getParameter( gl.MAX_SAMPLES ); 15858 15859 return { 15860 15861 isWebGL2: true, // keeping this for backwards compatibility 15862 15863 getMaxAnisotropy: getMaxAnisotropy, 15864 getMaxPrecision: getMaxPrecision,
vendor: 1,710 bytes, lines 15865-15948
15865 15866 textureFormatReadable: textureFormatReadable, 15867 textureTypeReadable: textureTypeReadable, 15868 15869 precision: precision, 15870 logarithmicDepthBuffer: logarithmicDepthBuffer, 15871 15872 maxTextures: maxTextures, 15873 maxVertexTextures: maxVertexTextures, 15874 maxTextureSize: maxTextureSize, 15875 maxCubemapSize: maxCubemapSize, 15876 15877 maxAttributes: maxAttributes, 15878 maxVertexUniforms: maxVertexUniforms, 15879 maxVaryings: maxVaryings, 15880 maxFragmentUniforms: maxFragmentUniforms, 15881 15882 vertexTextures: vertexTextures, 15883 15884 maxSamples: maxSamples 15885 15886 }; 15887 15888} 15889 15890function WebGLClipping( properties ) { 15891 15892 const scope = this; 15893 15894 let globalState = null, 15895 numGlobalPlanes = 0, 15896 localClippingEnabled = false, 15897 renderingShadows = false; 15898 15899 const plane = new Plane(), 15900 viewNormalMatrix = new Matrix3(), 15901 15902 uniform = { value: null, needsUpdate: false }; 15903 15904 this.uniform = uniform; 15905 this.numPlanes = 0; 15906 this.numIntersection = 0; 15907 15908 this.init = function ( planes, enableLocalClipping ) { 15909 15910 const enabled = 15911 planes.length !== 0 || 15912 enableLocalClipping || 15913 // enable state of previous frame - the clipping code has to 15914 // run another frame in order to reset the state: 15915 numGlobalPlanes !== 0 || 15916 localClippingEnabled; 15917 15918 localClippingEnabled = enableLocalClipping; 15919 15920 numGlobalPlanes = planes.length; 15921 15922 return enabled; 15923 15924 }; 15925 15926 this.beginShadows = function () { 15927 15928 renderingShadows = true; 15929 projectPlanes( null ); 15930 15931 }; 15932 15933 this.endShadows = function () { 15934 15935 renderingShadows = false; 15936 15937 }; 15938 15939 this.setGlobalState = function ( planes, camera ) { 15940 15941 globalState = projectPlanes( planes, camera, 0 ); 15942 15943 }; 15944 15945 this.setState = function ( material, camera, useCache ) { 15946 15947 const planes = material.clippingPlanes, 15948 clipIntersection = material.clipIntersection,
vendor: 9,736 bytes, lines 15949-16371
15949 clipShadows = material.clipShadows; 15950 15951 const materialProperties = properties.get( material ); 15952 15953 if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) { 15954 15955 // there's no local clipping 15956 15957 if ( renderingShadows ) { 15958 15959 // there's no global clipping 15960 15961 projectPlanes( null ); 15962 15963 } else { 15964 15965 resetGlobalState(); 15966 15967 } 15968 15969 } else { 15970 15971 const nGlobal = renderingShadows ? 0 : numGlobalPlanes, 15972 lGlobal = nGlobal * 4; 15973 15974 let dstArray = materialProperties.clippingState || null; 15975 15976 uniform.value = dstArray; // ensure unique state 15977 15978 dstArray = projectPlanes( planes, camera, lGlobal, useCache ); 15979 15980 for ( let i = 0; i !== lGlobal; ++ i ) { 15981 15982 dstArray[ i ] = globalState[ i ]; 15983 15984 } 15985 15986 materialProperties.clippingState = dstArray; 15987 this.numIntersection = clipIntersection ? this.numPlanes : 0; 15988 this.numPlanes += nGlobal; 15989 15990 } 15991 15992 15993 }; 15994 15995 function resetGlobalState() { 15996 15997 if ( uniform.value !== globalState ) { 15998 15999 uniform.value = globalState; 16000 uniform.needsUpdate = numGlobalPlanes > 0; 16001 16002 } 16003 16004 scope.numPlanes = numGlobalPlanes; 16005 scope.numIntersection = 0; 16006 16007 } 16008 16009 function projectPlanes( planes, camera, dstOffset, skipTransform ) { 16010 16011 const nPlanes = planes !== null ? planes.length : 0; 16012 let dstArray = null; 16013 16014 if ( nPlanes !== 0 ) { 16015 16016 dstArray = uniform.value; 16017 16018 if ( skipTransform !== true || dstArray === null ) { 16019 16020 const flatSize = dstOffset + nPlanes * 4, 16021 viewMatrix = camera.matrixWorldInverse; 16022 16023 viewNormalMatrix.getNormalMatrix( viewMatrix ); 16024 16025 if ( dstArray === null || dstArray.length < flatSize ) { 16026 16027 dstArray = new Float32Array( flatSize ); 16028 16029 } 16030 16031 for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) { 16032 16033 plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix ); 16034 16035 plane.normal.toArray( dstArray, i4 ); 16036 dstArray[ i4 + 3 ] = plane.constant; 16037 16038 } 16039 16040 } 16041 16042 uniform.value = dstArray; 16043 uniform.needsUpdate = true; 16044 16045 } 16046 16047 scope.numPlanes = nPlanes; 16048 scope.numIntersection = 0; 16049 16050 return dstArray; 16051 16052 } 16053 16054} 16055 16056function WebGLCubeMaps( renderer ) { 16057 16058 let cubemaps = new WeakMap(); 16059 16060 function mapTextureMapping( texture, mapping ) { 16061 16062 if ( mapping === EquirectangularReflectionMapping ) { 16063 16064 texture.mapping = CubeReflectionMapping; 16065 16066 } else if ( mapping === EquirectangularRefractionMapping ) { 16067 16068 texture.mapping = CubeRefractionMapping; 16069 16070 } 16071 16072 return texture; 16073 16074 } 16075 16076 function get( texture ) { 16077 16078 if ( texture && texture.isTexture ) { 16079 16080 const mapping = texture.mapping; 16081 16082 if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) { 16083 16084 if ( cubemaps.has( texture ) ) { 16085 16086 const cubemap = cubemaps.get( texture ).texture; 16087 return mapTextureMapping( cubemap, texture.mapping ); 16088 16089 } else { 16090 16091 const image = texture.image; 16092 16093 if ( image && image.height > 0 ) { 16094 16095 const renderTarget = new WebGLCubeRenderTarget( image.height ); 16096 renderTarget.fromEquirectangularTexture( renderer, texture ); 16097 cubemaps.set( texture, renderTarget ); 16098 16099 texture.addEventListener( 'dispose', onTextureDispose ); 16100 16101 return mapTextureMapping( renderTarget.texture, texture.mapping ); 16102 16103 } else { 16104 16105 // image not yet ready. try the conversion next frame 16106 16107 return null; 16108 16109 } 16110 16111 } 16112 16113 } 16114 16115 } 16116 16117 return texture; 16118 16119 } 16120 16121 function onTextureDispose( event ) { 16122 16123 const texture = event.target; 16124 16125 texture.removeEventListener( 'dispose', onTextureDispose ); 16126 16127 const cubemap = cubemaps.get( texture ); 16128 16129 if ( cubemap !== undefined ) { 16130 16131 cubemaps.delete( texture ); 16132 cubemap.dispose(); 16133 16134 } 16135 16136 } 16137 16138 function dispose() { 16139 16140 cubemaps = new WeakMap(); 16141 16142 } 16143 16144 return { 16145 get: get, 16146 dispose: dispose 16147 }; 16148 16149} 16150 16151class OrthographicCamera extends Camera { 16152 16153 constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) { 16154 16155 super(); 16156 16157 this.isOrthographicCamera = true; 16158 16159 this.type = 'OrthographicCamera'; 16160 16161 this.zoom = 1; 16162 this.view = null; 16163 16164 this.left = left; 16165 this.right = right; 16166 this.top = top; 16167 this.bottom = bottom; 16168 16169 this.near = near; 16170 this.far = far; 16171 16172 this.updateProjectionMatrix(); 16173 16174 } 16175 16176 copy( source, recursive ) { 16177 16178 super.copy( source, recursive ); 16179 16180 this.left = source.left; 16181 this.right = source.right; 16182 this.top = source.top; 16183 this.bottom = source.bottom; 16184 this.near = source.near; 16185 this.far = source.far; 16186 16187 this.zoom = source.zoom; 16188 this.view = source.view === null ? null : Object.assign( {}, source.view ); 16189 16190 return this; 16191 16192 } 16193 16194 setViewOffset( fullWidth, fullHeight, x, y, width, height ) { 16195 16196 if ( this.view === null ) { 16197 16198 this.view = { 16199 enabled: true, 16200 fullWidth: 1, 16201 fullHeight: 1, 16202 offsetX: 0, 16203 offsetY: 0, 16204 width: 1, 16205 height: 1 16206 }; 16207 16208 } 16209 16210 this.view.enabled = true; 16211 this.view.fullWidth = fullWidth; 16212 this.view.fullHeight = fullHeight; 16213 this.view.offsetX = x; 16214 this.view.offsetY = y; 16215 this.view.width = width; 16216 this.view.height = height; 16217 16218 this.updateProjectionMatrix(); 16219 16220 } 16221 16222 clearViewOffset() { 16223 16224 if ( this.view !== null ) { 16225 16226 this.view.enabled = false; 16227 16228 } 16229 16230 this.updateProjectionMatrix(); 16231 16232 } 16233 16234 updateProjectionMatrix() { 16235 16236 const dx = ( this.right - this.left ) / ( 2 * this.zoom ); 16237 const dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); 16238 const cx = ( this.right + this.left ) / 2; 16239 const cy = ( this.top + this.bottom ) / 2; 16240 16241 let left = cx - dx; 16242 let right = cx + dx; 16243 let top = cy + dy; 16244 let bottom = cy - dy; 16245 16246 if ( this.view !== null && this.view.enabled ) { 16247 16248 const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom; 16249 const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom; 16250 16251 left += scaleW * this.view.offsetX; 16252 right = left + scaleW * this.view.width; 16253 top -= scaleH * this.view.offsetY; 16254 bottom = top - scaleH * this.view.height; 16255 16256 } 16257 16258 this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem ); 16259 16260 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); 16261 16262 } 16263 16264 toJSON( meta ) { 16265 16266 const data = super.toJSON( meta ); 16267 16268 data.object.zoom = this.zoom; 16269 data.object.left = this.left; 16270 data.object.right = this.right; 16271 data.object.top = this.top; 16272 data.object.bottom = this.bottom; 16273 data.object.near = this.near; 16274 data.object.far = this.far; 16275 16276 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); 16277 16278 return data; 16279 16280 } 16281 16282} 16283 16284const LOD_MIN = 4; 16285 16286// The standard deviations (radians) associated with the extra mips. These are 16287// chosen to approximate a Trowbridge-Reitz distribution function times the 16288// geometric shadowing function. These sigma values squared must match the 16289// variance #defines in cube_uv_reflection_fragment.glsl.js. 16290const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ]; 16291 16292// The maximum length of the blur for loop. Smaller sigmas will use fewer 16293// samples and exit early, but not recompile the shader. 16294const MAX_SAMPLES = 20; 16295 16296const _flatCamera = /*@__PURE__*/ new OrthographicCamera(); 16297const _clearColor = /*@__PURE__*/ new Color(); 16298let _oldTarget = null; 16299let _oldActiveCubeFace = 0; 16300let _oldActiveMipmapLevel = 0; 16301let _oldXrEnabled = false; 16302 16303// Golden Ratio 16304const PHI = ( 1 + Math.sqrt( 5 ) ) / 2; 16305const INV_PHI = 1 / PHI; 16306 16307// Vertices of a dodecahedron (except the opposites, which represent the 16308// same axis), used as axis directions evenly spread on a sphere. 16309const _axisDirections = [ 16310 /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ), 16311 /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), 16312 /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), 16313 /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), 16314 /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), 16315 /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), 16316 /*@__PURE__*/ new Vector3( - 1, 1, - 1 ), 16317 /*@__PURE__*/ new Vector3( 1, 1, - 1 ), 16318 /*@__PURE__*/ new Vector3( - 1, 1, 1 ), 16319 /*@__PURE__*/ new Vector3( 1, 1, 1 ) ]; 16320 16321/** 16322 * This class generates a Prefiltered, Mipmapped Radiance Environment Map 16323 * (PMREM) from a cubeMap environment texture. This allows different levels of 16324 * blur to be quickly accessed based on material roughness. It is packed into a 16325 * special CubeUV format that allows us to perform custom interpolation so that 16326 * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap 16327 * chain, it only goes down to the LOD_MIN level (above), and then creates extra 16328 * even more filtered 'mips' at the same LOD_MIN resolution, associated with 16329 * higher roughness levels. In this way we maintain resolution to smoothly 16330 * interpolate diffuse lighting while limiting sampling computation. 16331 * 16332 * Paper: Fast, Accurate Image-Based Lighting 16333 * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view 16334*/ 16335 16336class PMREMGenerator { 16337 16338 constructor( renderer ) { 16339 16340 this._renderer = renderer; 16341 this._pingPongRenderTarget = null; 16342 16343 this._lodMax = 0; 16344 this._cubeSize = 0; 16345 this._lodPlanes = []; 16346 this._sizeLods = []; 16347 this._sigmas = []; 16348 16349 this._blurMaterial = null; 16350 this._cubemapMaterial = null; 16351 this._equirectMaterial = null; 16352 16353 this._compileMaterial( this._blurMaterial ); 16354 16355 } 16356 16357 /** 16358 * Generates a PMREM from a supplied Scene, which can be faster than using an 16359 * image if networking bandwidth is low. Optional sigma specifies a blur radius 16360 * in radians to be applied to the scene before PMREM generation. Optional near 16361 * and far planes ensure the scene is rendered in its entirety (the cubeCamera 16362 * is placed at the origin). 16363 */ 16364 fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { 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;
vendor: 5,454 bytes, lines 16372-16581
16372 16373 this._setSize( 256 ); 16374 16375 const cubeUVRenderTarget = this._allocateTargets(); 16376 cubeUVRenderTarget.depthBuffer = true; 16377 16378 this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); 16379 16380 if ( sigma > 0 ) { 16381 16382 this._blur( cubeUVRenderTarget, 0, 0, sigma ); 16383 16384 } 16385 16386 this._applyPMREM( cubeUVRenderTarget ); 16387 this._cleanup( cubeUVRenderTarget ); 16388 16389 return cubeUVRenderTarget; 16390 16391 } 16392 16393 /** 16394 * Generates a PMREM from an equirectangular texture, which can be either LDR 16395 * or HDR. The ideal input image size is 1k (1024 x 512), 16396 * as this matches best with the 256 x 256 cubemap output. 16397 * The smallest supported equirectangular image size is 64 x 32. 16398 */ 16399 fromEquirectangular( equirectangular, renderTarget = null ) { 16400 16401 return this._fromTexture( equirectangular, renderTarget ); 16402 16403 } 16404 16405 /** 16406 * Generates a PMREM from an cubemap texture, which can be either LDR 16407 * or HDR. The ideal input cube size is 256 x 256, 16408 * as this matches best with the 256 x 256 cubemap output. 16409 * The smallest supported cube size is 16 x 16. 16410 */ 16411 fromCubemap( cubemap, renderTarget = null ) { 16412 16413 return this._fromTexture( cubemap, renderTarget ); 16414 16415 } 16416 16417 /** 16418 * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during 16419 * your texture's network fetch for increased concurrency. 16420 */ 16421 compileCubemapShader() { 16422 16423 if ( this._cubemapMaterial === null ) { 16424 16425 this._cubemapMaterial = _getCubemapMaterial(); 16426 this._compileMaterial( this._cubemapMaterial ); 16427 16428 } 16429 16430 } 16431 16432 /** 16433 * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during 16434 * your texture's network fetch for increased concurrency. 16435 */ 16436 compileEquirectangularShader() { 16437 16438 if ( this._equirectMaterial === null ) { 16439 16440 this._equirectMaterial = _getEquirectMaterial(); 16441 this._compileMaterial( this._equirectMaterial ); 16442 16443 } 16444 16445 } 16446 16447 /** 16448 * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class, 16449 * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on 16450 * one of them will cause any others to also become unusable. 16451 */ 16452 dispose() { 16453 16454 this._dispose(); 16455 16456 if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose(); 16457 if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose(); 16458 16459 } 16460 16461 // private interface 16462 16463 _setSize( cubeSize ) { 16464 16465 this._lodMax = Math.floor( Math.log2( cubeSize ) ); 16466 this._cubeSize = Math.pow( 2, this._lodMax ); 16467 16468 } 16469 16470 _dispose() { 16471 16472 if ( this._blurMaterial !== null ) this._blurMaterial.dispose(); 16473 16474 if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose(); 16475 16476 for ( let i = 0; i < this._lodPlanes.length; i ++ ) { 16477 16478 this._lodPlanes[ i ].dispose(); 16479 16480 } 16481 16482 } 16483 16484 _cleanup( outputTarget ) { 16485 16486 this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel ); 16487 this._renderer.xr.enabled = _oldXrEnabled; 16488 16489 outputTarget.scissorTest = false; 16490 _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height ); 16491 16492 } 16493 16494 _fromTexture( texture, renderTarget ) { 16495 16496 if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) { 16497 16498 this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) ); 16499 16500 } else { // Equirectangular 16501 16502 this._setSize( texture.image.width / 4 ); 16503 16504 } 16505 16506 _oldTarget = this._renderer.getRenderTarget(); 16507 _oldActiveCubeFace = this._renderer.getActiveCubeFace(); 16508 _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); 16509 _oldXrEnabled = this._renderer.xr.enabled; 16510 16511 this._renderer.xr.enabled = false; 16512 16513 const cubeUVRenderTarget = renderTarget || this._allocateTargets(); 16514 this._textureToCubeUV( texture, cubeUVRenderTarget ); 16515 this._applyPMREM( cubeUVRenderTarget ); 16516 this._cleanup( cubeUVRenderTarget ); 16517 16518 return cubeUVRenderTarget; 16519 16520 } 16521 16522 _allocateTargets() { 16523 16524 const width = 3 * Math.max( this._cubeSize, 16 * 7 ); 16525 const height = 4 * this._cubeSize; 16526 16527 const params = { 16528 magFilter: LinearFilter, 16529 minFilter: LinearFilter, 16530 generateMipmaps: false, 16531 type: HalfFloatType, 16532 format: RGBAFormat, 16533 colorSpace: LinearSRGBColorSpace, 16534 depthBuffer: false 16535 }; 16536 16537 const cubeUVRenderTarget = _createRenderTarget( width, height, params ); 16538 16539 if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) { 16540 16541 if ( this._pingPongRenderTarget !== null ) { 16542 16543 this._dispose(); 16544 16545 } 16546 16547 this._pingPongRenderTarget = _createRenderTarget( width, height, params ); 16548 16549 const { _lodMax } = this; 16550 ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) ); 16551 16552 this._blurMaterial = _getBlurShader( _lodMax, width, height ); 16553 16554 } 16555 16556 return cubeUVRenderTarget; 16557 16558 } 16559 16560 _compileMaterial( material ) { 16561 16562 const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material ); 16563 this._renderer.compile( tmpMesh, _flatCamera ); 16564 16565 } 16566 16567 _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) { 16568 16569 const fov = 90; 16570 const aspect = 1; 16571 const cubeCamera = new PerspectiveCamera( fov, aspect, near, far ); 16572 const upSign = [ 1, - 1, 1, 1, 1, 1 ]; 16573 const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ]; 16574 const renderer = this._renderer; 16575 16576 const originalAutoClear = renderer.autoClear; 16577 const toneMapping = renderer.toneMapping; 16578 renderer.getClearColor( _clearColor ); 16579 16580 renderer.toneMapping = NoToneMapping; 16581 renderer.autoClear = false;
vendor: 8,464 bytes, lines 16582-16938
16582 16583 const backgroundMaterial = new MeshBasicMaterial( { 16584 name: 'PMREM.Background', 16585 side: BackSide, 16586 depthWrite: false, 16587 depthTest: false, 16588 } ); 16589 16590 const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial ); 16591 16592 let useSolidColor = false; 16593 const background = scene.background; 16594 16595 if ( background ) { 16596 16597 if ( background.isColor ) { 16598 16599 backgroundMaterial.color.copy( background ); 16600 scene.background = null; 16601 useSolidColor = true; 16602 16603 } 16604 16605 } else { 16606 16607 backgroundMaterial.color.copy( _clearColor ); 16608 useSolidColor = true; 16609 16610 } 16611 16612 for ( let i = 0; i < 6; i ++ ) { 16613 16614 const col = i % 3; 16615 16616 if ( col === 0 ) { 16617 16618 cubeCamera.up.set( 0, upSign[ i ], 0 ); 16619 cubeCamera.lookAt( forwardSign[ i ], 0, 0 ); 16620 16621 } else if ( col === 1 ) { 16622 16623 cubeCamera.up.set( 0, 0, upSign[ i ] ); 16624 cubeCamera.lookAt( 0, forwardSign[ i ], 0 ); 16625 16626 } else { 16627 16628 cubeCamera.up.set( 0, upSign[ i ], 0 ); 16629 cubeCamera.lookAt( 0, 0, forwardSign[ i ] ); 16630 16631 } 16632 16633 const size = this._cubeSize; 16634 16635 _setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size ); 16636 16637 renderer.setRenderTarget( cubeUVRenderTarget ); 16638 16639 if ( useSolidColor ) { 16640 16641 renderer.render( backgroundBox, cubeCamera ); 16642 16643 } 16644 16645 renderer.render( scene, cubeCamera ); 16646 16647 } 16648 16649 backgroundBox.geometry.dispose(); 16650 backgroundBox.material.dispose(); 16651 16652 renderer.toneMapping = toneMapping; 16653 renderer.autoClear = originalAutoClear; 16654 scene.background = background; 16655 16656 } 16657 16658 _textureToCubeUV( texture, cubeUVRenderTarget ) { 16659 16660 const renderer = this._renderer; 16661 16662 const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ); 16663 16664 if ( isCubeTexture ) { 16665 16666 if ( this._cubemapMaterial === null ) { 16667 16668 this._cubemapMaterial = _getCubemapMaterial(); 16669 16670 } 16671 16672 this._cubemapMaterial.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? - 1 : 1; 16673 16674 } else { 16675 16676 if ( this._equirectMaterial === null ) { 16677 16678 this._equirectMaterial = _getEquirectMaterial(); 16679 16680 } 16681 16682 } 16683 16684 const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; 16685 const mesh = new Mesh( this._lodPlanes[ 0 ], material ); 16686 16687 const uniforms = material.uniforms; 16688 16689 uniforms[ 'envMap' ].value = texture; 16690 16691 const size = this._cubeSize; 16692 16693 _setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size ); 16694 16695 renderer.setRenderTarget( cubeUVRenderTarget ); 16696 renderer.render( mesh, _flatCamera ); 16697 16698 } 16699 16700 _applyPMREM( cubeUVRenderTarget ) { 16701 16702 const renderer = this._renderer; 16703 const autoClear = renderer.autoClear; 16704 renderer.autoClear = false; 16705 const n = this._lodPlanes.length; 16706 16707 for ( let i = 1; i < n; i ++ ) { 16708 16709 const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); 16710 16711 const poleAxis = _axisDirections[ ( n - i - 1 ) % _axisDirections.length ]; 16712 16713 this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); 16714 16715 } 16716 16717 renderer.autoClear = autoClear; 16718 16719 } 16720 16721 /** 16722 * This is a two-pass Gaussian blur for a cubemap. Normally this is done 16723 * vertically and horizontally, but this breaks down on a cube. Here we apply 16724 * the blur latitudinally (around the poles), and then longitudinally (towards 16725 * the poles) to approximate the orthogonally-separable blur. It is least 16726 * accurate at the poles, but still does a decent job. 16727 */ 16728 _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) { 16729 16730 const pingPongRenderTarget = this._pingPongRenderTarget; 16731 16732 this._halfBlur( 16733 cubeUVRenderTarget, 16734 pingPongRenderTarget, 16735 lodIn, 16736 lodOut, 16737 sigma, 16738 'latitudinal', 16739 poleAxis ); 16740 16741 this._halfBlur( 16742 pingPongRenderTarget, 16743 cubeUVRenderTarget, 16744 lodOut, 16745 lodOut, 16746 sigma, 16747 'longitudinal', 16748 poleAxis ); 16749 16750 } 16751 16752 _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) { 16753 16754 const renderer = this._renderer; 16755 const blurMaterial = this._blurMaterial; 16756 16757 if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { 16758 16759 console.error( 16760 'blur direction must be either latitudinal or longitudinal!' ); 16761 16762 } 16763 16764 // Number of standard deviations at which to cut off the discrete approximation. 16765 const STANDARD_DEVIATIONS = 3; 16766 16767 const blurMesh = new Mesh( this._lodPlanes[ lodOut ], blurMaterial ); 16768 const blurUniforms = blurMaterial.uniforms; 16769 16770 const pixels = this._sizeLods[ lodIn ] - 1; 16771 const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 ); 16772 const sigmaPixels = sigmaRadians / radiansPerPixel; 16773 const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES; 16774 16775 if ( samples > MAX_SAMPLES ) { 16776 16777 console.warn( `sigmaRadians, ${ 16778 sigmaRadians}, is too large and will clip, as it requested ${ 16779 samples} samples when the maximum is set to ${MAX_SAMPLES}` ); 16780 16781 } 16782 16783 const weights = []; 16784 let sum = 0; 16785 16786 for ( let i = 0; i < MAX_SAMPLES; ++ i ) { 16787 16788 const x = i / sigmaPixels; 16789 const weight = Math.exp( - x * x / 2 ); 16790 weights.push( weight ); 16791 16792 if ( i === 0 ) { 16793 16794 sum += weight; 16795 16796 } else if ( i < samples ) { 16797 16798 sum += 2 * weight; 16799 16800 } 16801 16802 } 16803 16804 for ( let i = 0; i < weights.length; i ++ ) { 16805 16806 weights[ i ] = weights[ i ] / sum; 16807 16808 } 16809 16810 blurUniforms[ 'envMap' ].value = targetIn.texture; 16811 blurUniforms[ 'samples' ].value = samples; 16812 blurUniforms[ 'weights' ].value = weights; 16813 blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal'; 16814 16815 if ( poleAxis ) { 16816 16817 blurUniforms[ 'poleAxis' ].value = poleAxis; 16818 16819 } 16820 16821 const { _lodMax } = this; 16822 blurUniforms[ 'dTheta' ].value = radiansPerPixel; 16823 blurUniforms[ 'mipInt' ].value = _lodMax - lodIn; 16824 16825 const outputSize = this._sizeLods[ lodOut ]; 16826 const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); 16827 const y = 4 * ( this._cubeSize - outputSize ); 16828 16829 _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize ); 16830 renderer.setRenderTarget( targetOut ); 16831 renderer.render( blurMesh, _flatCamera ); 16832 16833 } 16834 16835} 16836 16837 16838 16839function _createPlanes( lodMax ) { 16840 16841 const lodPlanes = []; 16842 const sizeLods = []; 16843 const sigmas = []; 16844 16845 let lod = lodMax; 16846 16847 const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length; 16848 16849 for ( let i = 0; i < totalLods; i ++ ) { 16850 16851 const sizeLod = Math.pow( 2, lod ); 16852 sizeLods.push( sizeLod ); 16853 let sigma = 1.0 / sizeLod; 16854 16855 if ( i > lodMax - LOD_MIN ) { 16856 16857 sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ]; 16858 16859 } else if ( i === 0 ) { 16860 16861 sigma = 0; 16862 16863 } 16864 16865 sigmas.push( sigma ); 16866 16867 const texelSize = 1.0 / ( sizeLod - 2 ); 16868 const min = - texelSize; 16869 const max = 1 + texelSize; 16870 const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ]; 16871 16872 const cubeFaces = 6; 16873 const vertices = 6; 16874 const positionSize = 3; 16875 const uvSize = 2; 16876 const faceIndexSize = 1; 16877 16878 const position = new Float32Array( positionSize * vertices * cubeFaces ); 16879 const uv = new Float32Array( uvSize * vertices * cubeFaces ); 16880 const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces ); 16881 16882 for ( let face = 0; face < cubeFaces; face ++ ) { 16883 16884 const x = ( face % 3 ) * 2 / 3 - 1; 16885 const y = face > 2 ? 0 : - 1; 16886 const coordinates = [ 16887 x, y, 0, 16888 x + 2 / 3, y, 0, 16889 x + 2 / 3, y + 1, 0, 16890 x, y, 0, 16891 x + 2 / 3, y + 1, 0, 16892 x, y + 1, 0 16893 ]; 16894 position.set( coordinates, positionSize * vertices * face ); 16895 uv.set( uv1, uvSize * vertices * face ); 16896 const fill = [ face, face, face, face, face, face ]; 16897 faceIndex.set( fill, faceIndexSize * vertices * face ); 16898 16899 } 16900 16901 const planes = new BufferGeometry(); 16902 planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) ); 16903 planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) ); 16904 planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) ); 16905 lodPlanes.push( planes ); 16906 16907 if ( lod > LOD_MIN ) { 16908 16909 lod --; 16910 16911 } 16912 16913 } 16914 16915 return { lodPlanes, sizeLods, sigmas }; 16916 16917} 16918 16919function _createRenderTarget( width, height, params ) { 16920 16921 const cubeUVRenderTarget = new WebGLRenderTarget( width, height, params ); 16922 cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping; 16923 cubeUVRenderTarget.texture.name = 'PMREM.cubeUv'; 16924 cubeUVRenderTarget.scissorTest = true; 16925 return cubeUVRenderTarget; 16926 16927} 16928 16929function _setViewport( target, x, y, width, height ) { 16930 16931 target.viewport.set( x, y, width, height ); 16932 target.scissor.set( x, y, width, height ); 16933 16934} 16935 16936function _getBlurShader( lodMax, width, height ) { 16937 16938 const weights = new Float32Array( MAX_SAMPLES );
vendor: 4,417 bytes, lines 16939-17177
16939 const poleAxis = new Vector3( 0, 1, 0 ); 16940 const shaderMaterial = new ShaderMaterial( { 16941 16942 name: 'SphericalGaussianBlur', 16943 16944 defines: { 16945 'n': MAX_SAMPLES, 16946 'CUBEUV_TEXEL_WIDTH': 1.0 / width, 16947 'CUBEUV_TEXEL_HEIGHT': 1.0 / height, 16948 'CUBEUV_MAX_MIP': `${lodMax}.0`, 16949 }, 16950 16951 uniforms: { 16952 'envMap': { value: null }, 16953 'samples': { value: 1 }, 16954 'weights': { value: weights }, 16955 'latitudinal': { value: false }, 16956 'dTheta': { value: 0 }, 16957 'mipInt': { value: 0 }, 16958 'poleAxis': { value: poleAxis } 16959 }, 16960 16961 vertexShader: _getCommonVertexShader(), 16962 16963 fragmentShader: /* glsl */` 16964 16965 precision mediump float; 16966 precision mediump int; 16967 16968 varying vec3 vOutputDirection; 16969 16970 uniform sampler2D envMap; 16971 uniform int samples; 16972 uniform float weights[ n ]; 16973 uniform bool latitudinal; 16974 uniform float dTheta; 16975 uniform float mipInt; 16976 uniform vec3 poleAxis; 16977 16978 #define ENVMAP_TYPE_CUBE_UV 16979 #include <cube_uv_reflection_fragment> 16980 16981 vec3 getSample( float theta, vec3 axis ) { 16982 16983 float cosTheta = cos( theta ); 16984 // Rodrigues' axis-angle rotation 16985 vec3 sampleDirection = vOutputDirection * cosTheta 16986 + cross( axis, vOutputDirection ) * sin( theta ) 16987 + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta ); 16988 16989 return bilinearCubeUV( envMap, sampleDirection, mipInt ); 16990 16991 } 16992 16993 void main() { 16994 16995 vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection ); 16996 16997 if ( all( equal( axis, vec3( 0.0 ) ) ) ) { 16998 16999 axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x ); 17000 17001 } 17002 17003 axis = normalize( axis ); 17004 17005 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); 17006 gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis ); 17007 17008 for ( int i = 1; i < n; i++ ) { 17009 17010 if ( i >= samples ) { 17011 17012 break; 17013 17014 } 17015 17016 float theta = dTheta * float( i ); 17017 gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis ); 17018 gl_FragColor.rgb += weights[ i ] * getSample( theta, axis ); 17019 17020 } 17021 17022 } 17023 `, 17024 17025 blending: NoBlending, 17026 depthTest: false, 17027 depthWrite: false 17028 17029 } ); 17030 17031 return shaderMaterial; 17032 17033} 17034 17035function _getEquirectMaterial() { 17036 17037 return new ShaderMaterial( { 17038 17039 name: 'EquirectangularToCubeUV', 17040 17041 uniforms: { 17042 'envMap': { value: null } 17043 }, 17044 17045 vertexShader: _getCommonVertexShader(), 17046 17047 fragmentShader: /* glsl */` 17048 17049 precision mediump float; 17050 precision mediump int; 17051 17052 varying vec3 vOutputDirection; 17053 17054 uniform sampler2D envMap; 17055 17056 #include <common> 17057 17058 void main() { 17059 17060 vec3 outputDirection = normalize( vOutputDirection ); 17061 vec2 uv = equirectUv( outputDirection ); 17062 17063 gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); 17064 17065 } 17066 `, 17067 17068 blending: NoBlending, 17069 depthTest: false, 17070 depthWrite: false 17071 17072 } ); 17073 17074} 17075 17076function _getCubemapMaterial() { 17077 17078 return new ShaderMaterial( { 17079 17080 name: 'CubemapToCubeUV', 17081 17082 uniforms: { 17083 'envMap': { value: null }, 17084 'flipEnvMap': { value: - 1 } 17085 }, 17086 17087 vertexShader: _getCommonVertexShader(), 17088 17089 fragmentShader: /* glsl */` 17090 17091 precision mediump float; 17092 precision mediump int; 17093 17094 uniform float flipEnvMap; 17095 17096 varying vec3 vOutputDirection; 17097 17098 uniform samplerCube envMap; 17099 17100 void main() { 17101 17102 gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); 17103 17104 } 17105 `, 17106 17107 blending: NoBlending, 17108 depthTest: false, 17109 depthWrite: false 17110 17111 } ); 17112 17113} 17114 17115function _getCommonVertexShader() { 17116 17117 return /* glsl */` 17118 17119 precision mediump float; 17120 precision mediump int; 17121 17122 attribute float faceIndex; 17123 17124 varying vec3 vOutputDirection; 17125 17126 // RH coordinate system; PMREM face-indexing convention 17127 vec3 getDirection( vec2 uv, float face ) { 17128 17129 uv = 2.0 * uv - 1.0; 17130 17131 vec3 direction = vec3( uv, 1.0 ); 17132 17133 if ( face == 0.0 ) { 17134 17135 direction = direction.zyx; // ( 1, v, u ) pos x 17136 17137 } else if ( face == 1.0 ) { 17138 17139 direction = direction.xzy; 17140 direction.xz *= -1.0; // ( -u, 1, -v ) pos y 17141 17142 } else if ( face == 2.0 ) { 17143 17144 direction.x *= -1.0; // ( -u, v, 1 ) pos z 17145 17146 } else if ( face == 3.0 ) { 17147 17148 direction = direction.zyx; 17149 direction.xz *= -1.0; // ( -1, v, -u ) neg x 17150 17151 } else if ( face == 4.0 ) { 17152 17153 direction = direction.xzy; 17154 direction.xy *= -1.0; // ( -u, -1, v ) neg y 17155 17156 } else if ( face == 5.0 ) { 17157 17158 direction.z *= -1.0; // ( u, v, -1 ) neg z 17159 17160 } 17161 17162 return direction; 17163 17164 } 17165 17166 void main() { 17167 17168 vOutputDirection = getDirection( uv, faceIndex ); 17169 gl_Position = vec4( position, 1.0 ); 17170 17171 } 17172 `; 17173 17174} 17175 17176function WebGLCubeUVMaps( renderer ) { 17177
vendor: 9,737 bytes, lines 17178-17675
17178 let cubeUVmaps = new WeakMap(); 17179 17180 let pmremGenerator = null; 17181 17182 function get( texture ) { 17183 17184 if ( texture && texture.isTexture ) { 17185 17186 const mapping = texture.mapping; 17187 17188 const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ); 17189 const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); 17190 17191 // equirect/cube map to cubeUV conversion 17192 17193 if ( isEquirectMap || isCubeMap ) { 17194 17195 let renderTarget = cubeUVmaps.get( texture ); 17196 17197 const currentPMREMVersion = renderTarget !== undefined ? renderTarget.texture.pmremVersion : 0; 17198 17199 if ( texture.isRenderTargetTexture && texture.pmremVersion !== currentPMREMVersion ) { 17200 17201 if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); 17202 17203 renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget ); 17204 renderTarget.texture.pmremVersion = texture.pmremVersion; 17205 17206 cubeUVmaps.set( texture, renderTarget ); 17207 17208 return renderTarget.texture; 17209 17210 } else { 17211 17212 if ( renderTarget !== undefined ) { 17213 17214 return renderTarget.texture; 17215 17216 } else { 17217 17218 const image = texture.image; 17219 17220 if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) { 17221 17222 if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); 17223 17224 renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture ); 17225 renderTarget.texture.pmremVersion = texture.pmremVersion; 17226 17227 cubeUVmaps.set( texture, renderTarget ); 17228 17229 texture.addEventListener( 'dispose', onTextureDispose ); 17230 17231 return renderTarget.texture; 17232 17233 } else { 17234 17235 // image not yet ready. try the conversion next frame 17236 17237 return null; 17238 17239 } 17240 17241 } 17242 17243 } 17244 17245 } 17246 17247 } 17248 17249 return texture; 17250 17251 } 17252 17253 function isCubeTextureComplete( image ) { 17254 17255 let count = 0; 17256 const length = 6; 17257 17258 for ( let i = 0; i < length; i ++ ) { 17259 17260 if ( image[ i ] !== undefined ) count ++; 17261 17262 } 17263 17264 return count === length; 17265 17266 17267 } 17268 17269 function onTextureDispose( event ) { 17270 17271 const texture = event.target; 17272 17273 texture.removeEventListener( 'dispose', onTextureDispose ); 17274 17275 const cubemapUV = cubeUVmaps.get( texture ); 17276 17277 if ( cubemapUV !== undefined ) { 17278 17279 cubeUVmaps.delete( texture ); 17280 cubemapUV.dispose(); 17281 17282 } 17283 17284 } 17285 17286 function dispose() { 17287 17288 cubeUVmaps = new WeakMap(); 17289 17290 if ( pmremGenerator !== null ) { 17291 17292 pmremGenerator.dispose(); 17293 pmremGenerator = null; 17294 17295 } 17296 17297 } 17298 17299 return { 17300 get: get, 17301 dispose: dispose 17302 }; 17303 17304} 17305 17306function WebGLExtensions( gl ) { 17307 17308 const extensions = {}; 17309 17310 function getExtension( name ) { 17311 17312 if ( extensions[ name ] !== undefined ) { 17313 17314 return extensions[ name ]; 17315 17316 } 17317 17318 let extension; 17319 17320 switch ( name ) { 17321 17322 case 'WEBGL_depth_texture': 17323 extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' ); 17324 break; 17325 17326 case 'EXT_texture_filter_anisotropic': 17327 extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' ); 17328 break; 17329 17330 case 'WEBGL_compressed_texture_s3tc': 17331 extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' ); 17332 break; 17333 17334 case 'WEBGL_compressed_texture_pvrtc': 17335 extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' ); 17336 break; 17337 17338 default: 17339 extension = gl.getExtension( name ); 17340 17341 } 17342 17343 extensions[ name ] = extension; 17344 17345 return extension; 17346 17347 } 17348 17349 return { 17350 17351 has: function ( name ) { 17352 17353 return getExtension( name ) !== null; 17354 17355 }, 17356 17357 init: function () { 17358 17359 getExtension( 'EXT_color_buffer_float' ); 17360 getExtension( 'WEBGL_clip_cull_distance' ); 17361 getExtension( 'OES_texture_float_linear' ); 17362 getExtension( 'EXT_color_buffer_half_float' ); 17363 getExtension( 'WEBGL_multisampled_render_to_texture' ); 17364 getExtension( 'WEBGL_render_shared_exponent' ); 17365 17366 }, 17367 17368 get: function ( name ) { 17369 17370 const extension = getExtension( name ); 17371 17372 if ( extension === null ) { 17373 17374 warnOnce( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); 17375 17376 } 17377 17378 return extension; 17379 17380 } 17381 17382 }; 17383 17384} 17385 17386function WebGLGeometries( gl, attributes, info, bindingStates ) { 17387 17388 const geometries = {}; 17389 const wireframeAttributes = new WeakMap(); 17390 17391 function onGeometryDispose( event ) { 17392 17393 const geometry = event.target; 17394 17395 if ( geometry.index !== null ) { 17396 17397 attributes.remove( geometry.index ); 17398 17399 } 17400 17401 for ( const name in geometry.attributes ) { 17402 17403 attributes.remove( geometry.attributes[ name ] ); 17404 17405 } 17406 17407 for ( const name in geometry.morphAttributes ) { 17408 17409 const array = geometry.morphAttributes[ name ]; 17410 17411 for ( let i = 0, l = array.length; i < l; i ++ ) { 17412 17413 attributes.remove( array[ i ] ); 17414 17415 } 17416 17417 } 17418 17419 geometry.removeEventListener( 'dispose', onGeometryDispose ); 17420 17421 delete geometries[ geometry.id ]; 17422 17423 const attribute = wireframeAttributes.get( geometry ); 17424 17425 if ( attribute ) { 17426 17427 attributes.remove( attribute ); 17428 wireframeAttributes.delete( geometry ); 17429 17430 } 17431 17432 bindingStates.releaseStatesOfGeometry( geometry ); 17433 17434 if ( geometry.isInstancedBufferGeometry === true ) { 17435 17436 delete geometry._maxInstanceCount; 17437 17438 } 17439 17440 // 17441 17442 info.memory.geometries --; 17443 17444 } 17445 17446 function get( object, geometry ) { 17447 17448 if ( geometries[ geometry.id ] === true ) return geometry; 17449 17450 geometry.addEventListener( 'dispose', onGeometryDispose ); 17451 17452 geometries[ geometry.id ] = true; 17453 17454 info.memory.geometries ++; 17455 17456 return geometry; 17457 17458 } 17459 17460 function update( geometry ) { 17461 17462 const geometryAttributes = geometry.attributes; 17463 17464 // Updating index buffer in VAO now. See WebGLBindingStates. 17465 17466 for ( const name in geometryAttributes ) { 17467 17468 attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER ); 17469 17470 } 17471 17472 // morph targets 17473 17474 const morphAttributes = geometry.morphAttributes; 17475 17476 for ( const name in morphAttributes ) { 17477 17478 const array = morphAttributes[ name ]; 17479 17480 for ( let i = 0, l = array.length; i < l; i ++ ) { 17481 17482 attributes.update( array[ i ], gl.ARRAY_BUFFER ); 17483 17484 } 17485 17486 } 17487 17488 } 17489 17490 function updateWireframeAttribute( geometry ) { 17491 17492 const indices = []; 17493 17494 const geometryIndex = geometry.index; 17495 const geometryPosition = geometry.attributes.position; 17496 let version = 0; 17497 17498 if ( geometryIndex !== null ) { 17499 17500 const array = geometryIndex.array; 17501 version = geometryIndex.version; 17502 17503 for ( let i = 0, l = array.length; i < l; i += 3 ) { 17504 17505 const a = array[ i + 0 ]; 17506 const b = array[ i + 1 ]; 17507 const c = array[ i + 2 ]; 17508 17509 indices.push( a, b, b, c, c, a ); 17510 17511 } 17512 17513 } else if ( geometryPosition !== undefined ) { 17514 17515 const array = geometryPosition.array; 17516 version = geometryPosition.version; 17517 17518 for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { 17519 17520 const a = i + 0; 17521 const b = i + 1; 17522 const c = i + 2; 17523 17524 indices.push( a, b, b, c, c, a ); 17525 17526 } 17527 17528 } else { 17529 17530 return; 17531 17532 } 17533 17534 const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); 17535 attribute.version = version; 17536 17537 // Updating index buffer in VAO now. See WebGLBindingStates 17538 17539 // 17540 17541 const previousAttribute = wireframeAttributes.get( geometry ); 17542 17543 if ( previousAttribute ) attributes.remove( previousAttribute ); 17544 17545 // 17546 17547 wireframeAttributes.set( geometry, attribute ); 17548 17549 } 17550 17551 function getWireframeAttribute( geometry ) { 17552 17553 const currentAttribute = wireframeAttributes.get( geometry ); 17554 17555 if ( currentAttribute ) { 17556 17557 const geometryIndex = geometry.index; 17558 17559 if ( geometryIndex !== null ) { 17560 17561 // if the attribute is obsolete, create a new one 17562 17563 if ( currentAttribute.version < geometryIndex.version ) { 17564 17565 updateWireframeAttribute( geometry ); 17566 17567 } 17568 17569 } 17570 17571 } else { 17572 17573 updateWireframeAttribute( geometry ); 17574 17575 } 17576 17577 return wireframeAttributes.get( geometry ); 17578 17579 } 17580 17581 return { 17582 17583 get: get, 17584 update: update, 17585 17586 getWireframeAttribute: getWireframeAttribute 17587 17588 }; 17589 17590} 17591 17592function WebGLIndexedBufferRenderer( gl, extensions, info ) { 17593 17594 let mode; 17595 17596 function setMode( value ) { 17597 17598 mode = value; 17599 17600 } 17601 17602 let type, bytesPerElement; 17603 17604 function setIndex( value ) { 17605 17606 type = value.type; 17607 bytesPerElement = value.bytesPerElement; 17608 17609 } 17610 17611 function render( start, count ) { 17612 17613 gl.drawElements( mode, count, type, start * bytesPerElement ); 17614 17615 info.update( count, mode, 1 ); 17616 17617 } 17618 17619 function renderInstances( start, count, primcount ) { 17620 17621 if ( primcount === 0 ) return; 17622 17623 gl.drawElementsInstanced( mode, count, type, start * bytesPerElement, primcount ); 17624 17625 info.update( count, mode, primcount ); 17626 17627 } 17628 17629 function renderMultiDraw( starts, counts, drawCount ) { 17630 17631 if ( drawCount === 0 ) return; 17632 17633 const extension = extensions.get( 'WEBGL_multi_draw' ); 17634 17635 if ( extension === null ) { 17636 17637 for ( let i = 0; i < drawCount; i ++ ) { 17638 17639 this.render( starts[ i ] / bytesPerElement, counts[ i ] ); 17640 17641 } 17642 17643 } else { 17644 17645 extension.multiDrawElementsWEBGL( mode, counts, 0, type, starts, 0, drawCount ); 17646 17647 let elementCount = 0; 17648 for ( let i = 0; i < drawCount; i ++ ) { 17649 17650 elementCount += counts[ i ]; 17651 17652 } 17653 17654 info.update( elementCount, mode, 1 ); 17655 17656 } 17657 17658 } 17659 17660 function renderMultiDrawInstances( starts, counts, drawCount, primcount ) { 17661 17662 if ( drawCount === 0 ) return; 17663 17664 const extension = extensions.get( 'WEBGL_multi_draw' ); 17665 17666 if ( extension === null ) { 17667 17668 for ( let i = 0; i < starts.length; i ++ ) { 17669 17670 renderInstances( starts[ i ] / bytesPerElement, counts[ i ], primcount[ i ] ); 17671 17672 } 17673 17674 } else { 17675
vendor: 7,412 bytes, lines 17676-18019
17676 extension.multiDrawElementsInstancedWEBGL( mode, counts, 0, type, starts, 0, primcount, 0, drawCount ); 17677 17678 let elementCount = 0; 17679 for ( let i = 0; i < drawCount; i ++ ) { 17680 17681 elementCount += counts[ i ]; 17682 17683 } 17684 17685 for ( let i = 0; i < primcount.length; i ++ ) { 17686 17687 info.update( elementCount, mode, primcount[ i ] ); 17688 17689 } 17690 17691 } 17692 17693 } 17694 17695 // 17696 17697 this.setMode = setMode; 17698 this.setIndex = setIndex; 17699 this.render = render; 17700 this.renderInstances = renderInstances; 17701 this.renderMultiDraw = renderMultiDraw; 17702 this.renderMultiDrawInstances = renderMultiDrawInstances; 17703 17704} 17705 17706function WebGLInfo( gl ) { 17707 17708 const memory = { 17709 geometries: 0, 17710 textures: 0 17711 }; 17712 17713 const render = { 17714 frame: 0, 17715 calls: 0, 17716 triangles: 0, 17717 points: 0, 17718 lines: 0 17719 }; 17720 17721 function update( count, mode, instanceCount ) { 17722 17723 render.calls ++; 17724 17725 switch ( mode ) { 17726 17727 case gl.TRIANGLES: 17728 render.triangles += instanceCount * ( count / 3 ); 17729 break; 17730 17731 case gl.LINES: 17732 render.lines += instanceCount * ( count / 2 ); 17733 break; 17734 17735 case gl.LINE_STRIP: 17736 render.lines += instanceCount * ( count - 1 ); 17737 break; 17738 17739 case gl.LINE_LOOP: 17740 render.lines += instanceCount * count; 17741 break; 17742 17743 case gl.POINTS: 17744 render.points += instanceCount * count; 17745 break; 17746 17747 default: 17748 console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode ); 17749 break; 17750 17751 } 17752 17753 } 17754 17755 function reset() { 17756 17757 render.calls = 0; 17758 render.triangles = 0; 17759 render.points = 0; 17760 render.lines = 0; 17761 17762 } 17763 17764 return { 17765 memory: memory, 17766 render: render, 17767 programs: null, 17768 autoReset: true, 17769 reset: reset, 17770 update: update 17771 }; 17772 17773} 17774 17775function WebGLMorphtargets( gl, capabilities, textures ) { 17776 17777 const morphTextures = new WeakMap(); 17778 const morph = new Vector4(); 17779 17780 function update( object, geometry, program ) { 17781 17782 const objectInfluences = object.morphTargetInfluences; 17783 17784 // the following encodes morph targets into an array of data textures. Each layer represents a single morph target. 17785 17786 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; 17787 const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; 17788 17789 let entry = morphTextures.get( geometry ); 17790 17791 if ( entry === undefined || entry.count !== morphTargetsCount ) { 17792 17793 if ( entry !== undefined ) entry.texture.dispose(); 17794 17795 const hasMorphPosition = geometry.morphAttributes.position !== undefined; 17796 const hasMorphNormals = geometry.morphAttributes.normal !== undefined; 17797 const hasMorphColors = geometry.morphAttributes.color !== undefined; 17798 17799 const morphTargets = geometry.morphAttributes.position || []; 17800 const morphNormals = geometry.morphAttributes.normal || []; 17801 const morphColors = geometry.morphAttributes.color || []; 17802 17803 let vertexDataCount = 0; 17804 17805 if ( hasMorphPosition === true ) vertexDataCount = 1; 17806 if ( hasMorphNormals === true ) vertexDataCount = 2; 17807 if ( hasMorphColors === true ) vertexDataCount = 3; 17808 17809 let width = geometry.attributes.position.count * vertexDataCount; 17810 let height = 1; 17811 17812 if ( width > capabilities.maxTextureSize ) { 17813 17814 height = Math.ceil( width / capabilities.maxTextureSize ); 17815 width = capabilities.maxTextureSize; 17816 17817 } 17818 17819 const buffer = new Float32Array( width * height * 4 * morphTargetsCount ); 17820 17821 const texture = new DataArrayTexture( buffer, width, height, morphTargetsCount ); 17822 texture.type = FloatType; 17823 texture.needsUpdate = true; 17824 17825 // fill buffer 17826 17827 const vertexDataStride = vertexDataCount * 4; 17828 17829 for ( let i = 0; i < morphTargetsCount; i ++ ) { 17830 17831 const morphTarget = morphTargets[ i ]; 17832 const morphNormal = morphNormals[ i ]; 17833 const morphColor = morphColors[ i ]; 17834 17835 const offset = width * height * 4 * i; 17836 17837 for ( let j = 0; j < morphTarget.count; j ++ ) { 17838 17839 const stride = j * vertexDataStride; 17840 17841 if ( hasMorphPosition === true ) { 17842 17843 morph.fromBufferAttribute( morphTarget, j ); 17844 17845 buffer[ offset + stride + 0 ] = morph.x; 17846 buffer[ offset + stride + 1 ] = morph.y; 17847 buffer[ offset + stride + 2 ] = morph.z; 17848 buffer[ offset + stride + 3 ] = 0; 17849 17850 } 17851 17852 if ( hasMorphNormals === true ) { 17853 17854 morph.fromBufferAttribute( morphNormal, j ); 17855 17856 buffer[ offset + stride + 4 ] = morph.x; 17857 buffer[ offset + stride + 5 ] = morph.y; 17858 buffer[ offset + stride + 6 ] = morph.z; 17859 buffer[ offset + stride + 7 ] = 0; 17860 17861 } 17862 17863 if ( hasMorphColors === true ) { 17864 17865 morph.fromBufferAttribute( morphColor, j ); 17866 17867 buffer[ offset + stride + 8 ] = morph.x; 17868 buffer[ offset + stride + 9 ] = morph.y; 17869 buffer[ offset + stride + 10 ] = morph.z; 17870 buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? morph.w : 1; 17871 17872 } 17873 17874 } 17875 17876 } 17877 17878 entry = { 17879 count: morphTargetsCount, 17880 texture: texture, 17881 size: new Vector2( width, height ) 17882 }; 17883 17884 morphTextures.set( geometry, entry ); 17885 17886 function disposeTexture() { 17887 17888 texture.dispose(); 17889 17890 morphTextures.delete( geometry ); 17891 17892 geometry.removeEventListener( 'dispose', disposeTexture ); 17893 17894 } 17895 17896 geometry.addEventListener( 'dispose', disposeTexture ); 17897 17898 } 17899 17900 // 17901 if ( object.isInstancedMesh === true && object.morphTexture !== null ) { 17902 17903 program.getUniforms().setValue( gl, 'morphTexture', object.morphTexture, textures ); 17904 17905 } else { 17906 17907 let morphInfluencesSum = 0; 17908 17909 for ( let i = 0; i < objectInfluences.length; i ++ ) { 17910 17911 morphInfluencesSum += objectInfluences[ i ]; 17912 17913 } 17914 17915 const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; 17916 17917 17918 program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence ); 17919 program.getUniforms().setValue( gl, 'morphTargetInfluences', objectInfluences ); 17920 17921 } 17922 17923 program.getUniforms().setValue( gl, 'morphTargetsTexture', entry.texture, textures ); 17924 program.getUniforms().setValue( gl, 'morphTargetsTextureSize', entry.size ); 17925 17926 } 17927 17928 return { 17929 17930 update: update 17931 17932 }; 17933 17934} 17935 17936function WebGLObjects( gl, geometries, attributes, info ) { 17937 17938 let updateMap = new WeakMap(); 17939 17940 function update( object ) { 17941 17942 const frame = info.render.frame; 17943 17944 const geometry = object.geometry; 17945 const buffergeometry = geometries.get( object, geometry ); 17946 17947 // Update once per frame 17948 17949 if ( updateMap.get( buffergeometry ) !== frame ) { 17950 17951 geometries.update( buffergeometry ); 17952 17953 updateMap.set( buffergeometry, frame ); 17954 17955 } 17956 17957 if ( object.isInstancedMesh ) { 17958 17959 if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) { 17960 17961 object.addEventListener( 'dispose', onInstancedMeshDispose ); 17962 17963 } 17964 17965 if ( updateMap.get( object ) !== frame ) { 17966 17967 attributes.update( object.instanceMatrix, gl.ARRAY_BUFFER ); 17968 17969 if ( object.instanceColor !== null ) { 17970 17971 attributes.update( object.instanceColor, gl.ARRAY_BUFFER ); 17972 17973 } 17974 17975 updateMap.set( object, frame ); 17976 17977 } 17978 17979 } 17980 17981 if ( object.isSkinnedMesh ) { 17982 17983 const skeleton = object.skeleton; 17984 17985 if ( updateMap.get( skeleton ) !== frame ) { 17986 17987 skeleton.update(); 17988 17989 updateMap.set( skeleton, frame ); 17990 17991 } 17992 17993 } 17994 17995 return buffergeometry; 17996 17997 } 17998 17999 function dispose() { 18000 18001 updateMap = new WeakMap(); 18002 18003 } 18004 18005 function onInstancedMeshDispose( event ) { 18006 18007 const instancedMesh = event.target; 18008 18009 instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose ); 18010 18011 attributes.remove( instancedMesh.instanceMatrix ); 18012 18013 if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor ); 18014 18015 } 18016 18017 return { 18018 18019 update: update,
18020 dispose: dispose 18021 18022 }; 18023 18024} 18025 18026class DepthTexture extends Texture { 18027 18028 constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format = DepthFormat ) {
vendor: 24,805 bytes, lines 18028-19376
18028 18029 18030 if ( format !== DepthFormat && format !== DepthStencilFormat ) { 18031 18032 throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); 18033 18034 } 18035 18036 if ( type === undefined && format === DepthFormat ) type = UnsignedIntType; 18037 if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type; 18038 18039 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 18040 18041 this.isDepthTexture = true; 18042 18043 this.image = { width: width, height: height }; 18044 18045 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; 18046 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; 18047 18048 this.flipY = false; 18049 this.generateMipmaps = false; 18050 18051 this.compareFunction = null; 18052 18053 } 18054 18055 18056 copy( source ) { 18057 18058 super.copy( source ); 18059 18060 this.compareFunction = source.compareFunction; 18061 18062 return this; 18063 18064 } 18065 18066 toJSON( meta ) { 18067 18068 const data = super.toJSON( meta ); 18069 18070 if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction; 18071 18072 return data; 18073 18074 } 18075 18076} 18077 18078/** 18079 * Uniforms of a program. 18080 * Those form a tree structure with a special top-level container for the root, 18081 * which you get by calling 'new WebGLUniforms( gl, program )'. 18082 * 18083 * 18084 * Properties of inner nodes including the top-level container: 18085 * 18086 * .seq - array of nested uniforms 18087 * .map - nested uniforms by name 18088 * 18089 * 18090 * Methods of all nodes except the top-level container: 18091 * 18092 * .setValue( gl, value, [textures] ) 18093 * 18094 * uploads a uniform value(s) 18095 * the 'textures' parameter is needed for sampler uniforms 18096 * 18097 * 18098 * Static methods of the top-level container (textures factorizations): 18099 * 18100 * .upload( gl, seq, values, textures ) 18101 * 18102 * sets uniforms in 'seq' to 'values[id].value' 18103 * 18104 * .seqWithValue( seq, values ) : filteredSeq 18105 * 18106 * filters 'seq' entries with corresponding entry in values 18107 * 18108 * 18109 * Methods of the top-level container (textures factorizations): 18110 * 18111 * .setValue( gl, name, value, textures ) 18112 * 18113 * sets uniform with name 'name' to 'value' 18114 * 18115 * .setOptional( gl, obj, prop ) 18116 * 18117 * like .set for an optional property of the object 18118 * 18119 */ 18120 18121 18122const emptyTexture = /*@__PURE__*/ new Texture(); 18123 18124const emptyShadowTexture = /*@__PURE__*/ new DepthTexture( 1, 1 ); 18125emptyShadowTexture.compareFunction = LessEqualCompare; 18126 18127const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture(); 18128const empty3dTexture = /*@__PURE__*/ new Data3DTexture(); 18129const emptyCubeTexture = /*@__PURE__*/ new CubeTexture(); 18130 18131// --- Utilities --- 18132 18133// Array Caches (provide typed arrays for temporary by size) 18134 18135const arrayCacheF32 = []; 18136const arrayCacheI32 = []; 18137 18138// Float32Array caches used for uploading Matrix uniforms 18139 18140const mat4array = new Float32Array( 16 ); 18141const mat3array = new Float32Array( 9 ); 18142const mat2array = new Float32Array( 4 ); 18143 18144// Flattening for arrays of vectors and matrices 18145 18146function flatten( array, nBlocks, blockSize ) { 18147 18148 const firstElem = array[ 0 ]; 18149 18150 if ( firstElem <= 0 || firstElem > 0 ) return array; 18151 // unoptimized: ! isNaN( firstElem ) 18152 // see http://jacksondunstan.com/articles/983 18153 18154 const n = nBlocks * blockSize; 18155 let r = arrayCacheF32[ n ]; 18156 18157 if ( r === undefined ) { 18158 18159 r = new Float32Array( n ); 18160 arrayCacheF32[ n ] = r; 18161 18162 } 18163 18164 if ( nBlocks !== 0 ) { 18165 18166 firstElem.toArray( r, 0 ); 18167 18168 for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) { 18169 18170 offset += blockSize; 18171 array[ i ].toArray( r, offset ); 18172 18173 } 18174 18175 } 18176 18177 return r; 18178 18179} 18180 18181function arraysEqual( a, b ) { 18182 18183 if ( a.length !== b.length ) return false; 18184 18185 for ( let i = 0, l = a.length; i < l; i ++ ) { 18186 18187 if ( a[ i ] !== b[ i ] ) return false; 18188 18189 } 18190 18191 return true; 18192 18193} 18194 18195function copyArray( a, b ) { 18196 18197 for ( let i = 0, l = b.length; i < l; i ++ ) { 18198 18199 a[ i ] = b[ i ]; 18200 18201 } 18202 18203} 18204 18205// Texture unit allocation 18206 18207function allocTexUnits( textures, n ) { 18208 18209 let r = arrayCacheI32[ n ]; 18210 18211 if ( r === undefined ) { 18212 18213 r = new Int32Array( n ); 18214 arrayCacheI32[ n ] = r; 18215 18216 } 18217 18218 for ( let i = 0; i !== n; ++ i ) { 18219 18220 r[ i ] = textures.allocateTextureUnit(); 18221 18222 } 18223 18224 return r; 18225 18226} 18227 18228// --- Setters --- 18229 18230// Note: Defining these methods externally, because they come in a bunch 18231// and this way their names minify. 18232 18233// Single scalar 18234 18235function setValueV1f( gl, v ) { 18236 18237 const cache = this.cache; 18238 18239 if ( cache[ 0 ] === v ) return; 18240 18241 gl.uniform1f( this.addr, v ); 18242 18243 cache[ 0 ] = v; 18244 18245} 18246 18247// Single float vector (from flat array or THREE.VectorN) 18248 18249function setValueV2f( gl, v ) { 18250 18251 const cache = this.cache; 18252 18253 if ( v.x !== undefined ) { 18254 18255 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 18256 18257 gl.uniform2f( this.addr, v.x, v.y ); 18258 18259 cache[ 0 ] = v.x; 18260 cache[ 1 ] = v.y; 18261 18262 } 18263 18264 } else { 18265 18266 if ( arraysEqual( cache, v ) ) return; 18267 18268 gl.uniform2fv( this.addr, v ); 18269 18270 copyArray( cache, v ); 18271 18272 } 18273 18274} 18275 18276function setValueV3f( gl, v ) { 18277 18278 const cache = this.cache; 18279 18280 if ( v.x !== undefined ) { 18281 18282 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 18283 18284 gl.uniform3f( this.addr, v.x, v.y, v.z ); 18285 18286 cache[ 0 ] = v.x; 18287 cache[ 1 ] = v.y; 18288 cache[ 2 ] = v.z; 18289 18290 } 18291 18292 } else if ( v.r !== undefined ) { 18293 18294 if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) { 18295 18296 gl.uniform3f( this.addr, v.r, v.g, v.b ); 18297 18298 cache[ 0 ] = v.r; 18299 cache[ 1 ] = v.g; 18300 cache[ 2 ] = v.b; 18301 18302 } 18303 18304 } else { 18305 18306 if ( arraysEqual( cache, v ) ) return; 18307 18308 gl.uniform3fv( this.addr, v ); 18309 18310 copyArray( cache, v ); 18311 18312 } 18313 18314} 18315 18316function setValueV4f( gl, v ) { 18317 18318 const cache = this.cache; 18319 18320 if ( v.x !== undefined ) { 18321 18322 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 18323 18324 gl.uniform4f( this.addr, v.x, v.y, v.z, v.w ); 18325 18326 cache[ 0 ] = v.x; 18327 cache[ 1 ] = v.y; 18328 cache[ 2 ] = v.z; 18329 cache[ 3 ] = v.w; 18330 18331 } 18332 18333 } else { 18334 18335 if ( arraysEqual( cache, v ) ) return; 18336 18337 gl.uniform4fv( this.addr, v ); 18338 18339 copyArray( cache, v ); 18340 18341 } 18342 18343} 18344 18345// Single matrix (from flat array or THREE.MatrixN) 18346 18347function setValueM2( gl, v ) { 18348 18349 const cache = this.cache; 18350 const elements = v.elements; 18351 18352 if ( elements === undefined ) { 18353 18354 if ( arraysEqual( cache, v ) ) return; 18355 18356 gl.uniformMatrix2fv( this.addr, false, v ); 18357 18358 copyArray( cache, v ); 18359 18360 } else { 18361 18362 if ( arraysEqual( cache, elements ) ) return; 18363 18364 mat2array.set( elements ); 18365 18366 gl.uniformMatrix2fv( this.addr, false, mat2array ); 18367 18368 copyArray( cache, elements ); 18369 18370 } 18371 18372} 18373 18374function setValueM3( gl, v ) { 18375 18376 const cache = this.cache; 18377 const elements = v.elements; 18378 18379 if ( elements === undefined ) { 18380 18381 if ( arraysEqual( cache, v ) ) return; 18382 18383 gl.uniformMatrix3fv( this.addr, false, v ); 18384 18385 copyArray( cache, v ); 18386 18387 } else { 18388 18389 if ( arraysEqual( cache, elements ) ) return; 18390 18391 mat3array.set( elements ); 18392 18393 gl.uniformMatrix3fv( this.addr, false, mat3array ); 18394 18395 copyArray( cache, elements ); 18396 18397 } 18398 18399} 18400 18401function setValueM4( gl, v ) { 18402 18403 const cache = this.cache; 18404 const elements = v.elements; 18405 18406 if ( elements === undefined ) { 18407 18408 if ( arraysEqual( cache, v ) ) return; 18409 18410 gl.uniformMatrix4fv( this.addr, false, v ); 18411 18412 copyArray( cache, v ); 18413 18414 } else { 18415 18416 if ( arraysEqual( cache, elements ) ) return; 18417 18418 mat4array.set( elements ); 18419 18420 gl.uniformMatrix4fv( this.addr, false, mat4array ); 18421 18422 copyArray( cache, elements ); 18423 18424 } 18425 18426} 18427 18428// Single integer / boolean 18429 18430function setValueV1i( gl, v ) { 18431 18432 const cache = this.cache; 18433 18434 if ( cache[ 0 ] === v ) return; 18435 18436 gl.uniform1i( this.addr, v ); 18437 18438 cache[ 0 ] = v; 18439 18440} 18441 18442// Single integer / boolean vector (from flat array or THREE.VectorN) 18443 18444function setValueV2i( gl, v ) { 18445 18446 const cache = this.cache; 18447 18448 if ( v.x !== undefined ) { 18449 18450 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 18451 18452 gl.uniform2i( this.addr, v.x, v.y ); 18453 18454 cache[ 0 ] = v.x; 18455 cache[ 1 ] = v.y; 18456 18457 } 18458 18459 } else { 18460 18461 if ( arraysEqual( cache, v ) ) return; 18462 18463 gl.uniform2iv( this.addr, v ); 18464 18465 copyArray( cache, v ); 18466 18467 } 18468 18469} 18470 18471function setValueV3i( gl, v ) { 18472 18473 const cache = this.cache; 18474 18475 if ( v.x !== undefined ) { 18476 18477 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 18478 18479 gl.uniform3i( this.addr, v.x, v.y, v.z ); 18480 18481 cache[ 0 ] = v.x; 18482 cache[ 1 ] = v.y; 18483 cache[ 2 ] = v.z; 18484 18485 } 18486 18487 } else { 18488 18489 if ( arraysEqual( cache, v ) ) return; 18490 18491 gl.uniform3iv( this.addr, v ); 18492 18493 copyArray( cache, v ); 18494 18495 } 18496 18497} 18498 18499function setValueV4i( gl, v ) { 18500 18501 const cache = this.cache; 18502 18503 if ( v.x !== undefined ) { 18504 18505 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 18506 18507 gl.uniform4i( this.addr, v.x, v.y, v.z, v.w ); 18508 18509 cache[ 0 ] = v.x; 18510 cache[ 1 ] = v.y; 18511 cache[ 2 ] = v.z; 18512 cache[ 3 ] = v.w; 18513 18514 } 18515 18516 } else { 18517 18518 if ( arraysEqual( cache, v ) ) return; 18519 18520 gl.uniform4iv( this.addr, v ); 18521 18522 copyArray( cache, v ); 18523 18524 } 18525 18526} 18527 18528// Single unsigned integer 18529 18530function setValueV1ui( gl, v ) { 18531 18532 const cache = this.cache; 18533 18534 if ( cache[ 0 ] === v ) return; 18535 18536 gl.uniform1ui( this.addr, v ); 18537 18538 cache[ 0 ] = v; 18539 18540} 18541 18542// Single unsigned integer vector (from flat array or THREE.VectorN) 18543 18544function setValueV2ui( gl, v ) { 18545 18546 const cache = this.cache; 18547 18548 if ( v.x !== undefined ) { 18549 18550 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 18551 18552 gl.uniform2ui( this.addr, v.x, v.y ); 18553 18554 cache[ 0 ] = v.x; 18555 cache[ 1 ] = v.y; 18556 18557 } 18558 18559 } else { 18560 18561 if ( arraysEqual( cache, v ) ) return; 18562 18563 gl.uniform2uiv( this.addr, v ); 18564 18565 copyArray( cache, v ); 18566 18567 } 18568 18569} 18570 18571function setValueV3ui( gl, v ) { 18572 18573 const cache = this.cache; 18574 18575 if ( v.x !== undefined ) { 18576 18577 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 18578 18579 gl.uniform3ui( this.addr, v.x, v.y, v.z ); 18580 18581 cache[ 0 ] = v.x; 18582 cache[ 1 ] = v.y; 18583 cache[ 2 ] = v.z; 18584 18585 } 18586 18587 } else { 18588 18589 if ( arraysEqual( cache, v ) ) return; 18590 18591 gl.uniform3uiv( this.addr, v ); 18592 18593 copyArray( cache, v ); 18594 18595 } 18596 18597} 18598 18599function setValueV4ui( gl, v ) { 18600 18601 const cache = this.cache; 18602 18603 if ( v.x !== undefined ) { 18604 18605 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 18606 18607 gl.uniform4ui( this.addr, v.x, v.y, v.z, v.w ); 18608 18609 cache[ 0 ] = v.x; 18610 cache[ 1 ] = v.y; 18611 cache[ 2 ] = v.z; 18612 cache[ 3 ] = v.w; 18613 18614 } 18615 18616 } else { 18617 18618 if ( arraysEqual( cache, v ) ) return; 18619 18620 gl.uniform4uiv( this.addr, v ); 18621 18622 copyArray( cache, v ); 18623 18624 } 18625 18626} 18627 18628 18629// Single texture (2D / Cube) 18630 18631function setValueT1( gl, v, textures ) { 18632 18633 const cache = this.cache; 18634 const unit = textures.allocateTextureUnit(); 18635 18636 if ( cache[ 0 ] !== unit ) { 18637 18638 gl.uniform1i( this.addr, unit ); 18639 cache[ 0 ] = unit; 18640 18641 } 18642 18643 const emptyTexture2D = ( this.type === gl.SAMPLER_2D_SHADOW ) ? emptyShadowTexture : emptyTexture; 18644 18645 textures.setTexture2D( v || emptyTexture2D, unit ); 18646 18647} 18648 18649function setValueT3D1( gl, v, textures ) { 18650 18651 const cache = this.cache; 18652 const unit = textures.allocateTextureUnit(); 18653 18654 if ( cache[ 0 ] !== unit ) { 18655 18656 gl.uniform1i( this.addr, unit ); 18657 cache[ 0 ] = unit; 18658 18659 } 18660 18661 textures.setTexture3D( v || empty3dTexture, unit ); 18662 18663} 18664 18665function setValueT6( gl, v, textures ) { 18666 18667 const cache = this.cache; 18668 const unit = textures.allocateTextureUnit(); 18669 18670 if ( cache[ 0 ] !== unit ) { 18671 18672 gl.uniform1i( this.addr, unit ); 18673 cache[ 0 ] = unit; 18674 18675 } 18676 18677 textures.setTextureCube( v || emptyCubeTexture, unit ); 18678 18679} 18680 18681function setValueT2DArray1( gl, v, textures ) { 18682 18683 const cache = this.cache; 18684 const unit = textures.allocateTextureUnit(); 18685 18686 if ( cache[ 0 ] !== unit ) { 18687 18688 gl.uniform1i( this.addr, unit ); 18689 cache[ 0 ] = unit; 18690 18691 } 18692 18693 textures.setTexture2DArray( v || emptyArrayTexture, unit ); 18694 18695} 18696 18697// Helper to pick the right setter for the singular case 18698 18699function getSingularSetter( type ) { 18700 18701 switch ( type ) { 18702 18703 case 0x1406: return setValueV1f; // FLOAT 18704 case 0x8b50: return setValueV2f; // _VEC2 18705 case 0x8b51: return setValueV3f; // _VEC3 18706 case 0x8b52: return setValueV4f; // _VEC4 18707 18708 case 0x8b5a: return setValueM2; // _MAT2 18709 case 0x8b5b: return setValueM3; // _MAT3 18710 case 0x8b5c: return setValueM4; // _MAT4 18711 18712 case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL 18713 case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2 18714 case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3 18715 case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4 18716 18717 case 0x1405: return setValueV1ui; // UINT 18718 case 0x8dc6: return setValueV2ui; // _VEC2 18719 case 0x8dc7: return setValueV3ui; // _VEC3 18720 case 0x8dc8: return setValueV4ui; // _VEC4 18721 18722 case 0x8b5e: // SAMPLER_2D 18723 case 0x8d66: // SAMPLER_EXTERNAL_OES 18724 case 0x8dca: // INT_SAMPLER_2D 18725 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D 18726 case 0x8b62: // SAMPLER_2D_SHADOW 18727 return setValueT1; 18728 18729 case 0x8b5f: // SAMPLER_3D 18730 case 0x8dcb: // INT_SAMPLER_3D 18731 case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D 18732 return setValueT3D1; 18733 18734 case 0x8b60: // SAMPLER_CUBE 18735 case 0x8dcc: // INT_SAMPLER_CUBE 18736 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE 18737 case 0x8dc5: // SAMPLER_CUBE_SHADOW 18738 return setValueT6; 18739 18740 case 0x8dc1: // SAMPLER_2D_ARRAY 18741 case 0x8dcf: // INT_SAMPLER_2D_ARRAY 18742 case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY 18743 case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW 18744 return setValueT2DArray1; 18745 18746 } 18747 18748} 18749 18750 18751// Array of scalars 18752 18753function setValueV1fArray( gl, v ) { 18754 18755 gl.uniform1fv( this.addr, v ); 18756 18757} 18758 18759// Array of vectors (from flat array or array of THREE.VectorN) 18760 18761function setValueV2fArray( gl, v ) { 18762 18763 const data = flatten( v, this.size, 2 ); 18764 18765 gl.uniform2fv( this.addr, data ); 18766 18767} 18768 18769function setValueV3fArray( gl, v ) { 18770 18771 const data = flatten( v, this.size, 3 ); 18772 18773 gl.uniform3fv( this.addr, data ); 18774 18775} 18776 18777function setValueV4fArray( gl, v ) { 18778 18779 const data = flatten( v, this.size, 4 ); 18780 18781 gl.uniform4fv( this.addr, data ); 18782 18783} 18784 18785// Array of matrices (from flat array or array of THREE.MatrixN) 18786 18787function setValueM2Array( gl, v ) { 18788 18789 const data = flatten( v, this.size, 4 ); 18790 18791 gl.uniformMatrix2fv( this.addr, false, data ); 18792 18793} 18794 18795function setValueM3Array( gl, v ) { 18796 18797 const data = flatten( v, this.size, 9 ); 18798 18799 gl.uniformMatrix3fv( this.addr, false, data ); 18800 18801} 18802 18803function setValueM4Array( gl, v ) { 18804 18805 const data = flatten( v, this.size, 16 ); 18806 18807 gl.uniformMatrix4fv( this.addr, false, data ); 18808 18809} 18810 18811// Array of integer / boolean 18812 18813function setValueV1iArray( gl, v ) { 18814 18815 gl.uniform1iv( this.addr, v ); 18816 18817} 18818 18819// Array of integer / boolean vectors (from flat array) 18820 18821function setValueV2iArray( gl, v ) { 18822 18823 gl.uniform2iv( this.addr, v ); 18824 18825} 18826 18827function setValueV3iArray( gl, v ) { 18828 18829 gl.uniform3iv( this.addr, v ); 18830 18831} 18832 18833function setValueV4iArray( gl, v ) { 18834 18835 gl.uniform4iv( this.addr, v ); 18836 18837} 18838 18839// Array of unsigned integer 18840 18841function setValueV1uiArray( gl, v ) { 18842 18843 gl.uniform1uiv( this.addr, v ); 18844 18845} 18846 18847// Array of unsigned integer vectors (from flat array) 18848 18849function setValueV2uiArray( gl, v ) { 18850 18851 gl.uniform2uiv( this.addr, v ); 18852 18853} 18854 18855function setValueV3uiArray( gl, v ) { 18856 18857 gl.uniform3uiv( this.addr, v ); 18858 18859} 18860 18861function setValueV4uiArray( gl, v ) { 18862 18863 gl.uniform4uiv( this.addr, v ); 18864 18865} 18866 18867 18868// Array of textures (2D / 3D / Cube / 2DArray) 18869 18870function setValueT1Array( gl, v, textures ) { 18871 18872 const cache = this.cache; 18873 18874 const n = v.length; 18875 18876 const units = allocTexUnits( textures, n ); 18877 18878 if ( ! arraysEqual( cache, units ) ) { 18879 18880 gl.uniform1iv( this.addr, units ); 18881 18882 copyArray( cache, units ); 18883 18884 } 18885 18886 for ( let i = 0; i !== n; ++ i ) { 18887 18888 textures.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); 18889 18890 } 18891 18892} 18893 18894function setValueT3DArray( gl, v, textures ) { 18895 18896 const cache = this.cache; 18897 18898 const n = v.length; 18899 18900 const units = allocTexUnits( textures, n ); 18901 18902 if ( ! arraysEqual( cache, units ) ) { 18903 18904 gl.uniform1iv( this.addr, units ); 18905 18906 copyArray( cache, units ); 18907 18908 } 18909 18910 for ( let i = 0; i !== n; ++ i ) { 18911 18912 textures.setTexture3D( v[ i ] || empty3dTexture, units[ i ] ); 18913 18914 } 18915 18916} 18917 18918function setValueT6Array( gl, v, textures ) { 18919 18920 const cache = this.cache; 18921 18922 const n = v.length; 18923 18924 const units = allocTexUnits( textures, n ); 18925 18926 if ( ! arraysEqual( cache, units ) ) { 18927 18928 gl.uniform1iv( this.addr, units ); 18929 18930 copyArray( cache, units ); 18931 18932 } 18933 18934 for ( let i = 0; i !== n; ++ i ) { 18935 18936 textures.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] ); 18937 18938 } 18939 18940} 18941 18942function setValueT2DArrayArray( gl, v, textures ) { 18943 18944 const cache = this.cache; 18945 18946 const n = v.length; 18947 18948 const units = allocTexUnits( textures, n ); 18949 18950 if ( ! arraysEqual( cache, units ) ) { 18951 18952 gl.uniform1iv( this.addr, units ); 18953 18954 copyArray( cache, units ); 18955 18956 } 18957 18958 for ( let i = 0; i !== n; ++ i ) { 18959 18960 textures.setTexture2DArray( v[ i ] || emptyArrayTexture, units[ i ] ); 18961 18962 } 18963 18964} 18965 18966 18967// Helper to pick the right setter for a pure (bottom-level) array 18968 18969function getPureArraySetter( type ) { 18970 18971 switch ( type ) { 18972 18973 case 0x1406: return setValueV1fArray; // FLOAT 18974 case 0x8b50: return setValueV2fArray; // _VEC2 18975 case 0x8b51: return setValueV3fArray; // _VEC3 18976 case 0x8b52: return setValueV4fArray; // _VEC4 18977 18978 case 0x8b5a: return setValueM2Array; // _MAT2 18979 case 0x8b5b: return setValueM3Array; // _MAT3 18980 case 0x8b5c: return setValueM4Array; // _MAT4 18981 18982 case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL 18983 case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2 18984 case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3 18985 case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4 18986 18987 case 0x1405: return setValueV1uiArray; // UINT 18988 case 0x8dc6: return setValueV2uiArray; // _VEC2 18989 case 0x8dc7: return setValueV3uiArray; // _VEC3 18990 case 0x8dc8: return setValueV4uiArray; // _VEC4 18991 18992 case 0x8b5e: // SAMPLER_2D 18993 case 0x8d66: // SAMPLER_EXTERNAL_OES 18994 case 0x8dca: // INT_SAMPLER_2D 18995 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D 18996 case 0x8b62: // SAMPLER_2D_SHADOW 18997 return setValueT1Array; 18998 18999 case 0x8b5f: // SAMPLER_3D 19000 case 0x8dcb: // INT_SAMPLER_3D 19001 case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D 19002 return setValueT3DArray; 19003 19004 case 0x8b60: // SAMPLER_CUBE 19005 case 0x8dcc: // INT_SAMPLER_CUBE 19006 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE 19007 case 0x8dc5: // SAMPLER_CUBE_SHADOW 19008 return setValueT6Array; 19009 19010 case 0x8dc1: // SAMPLER_2D_ARRAY 19011 case 0x8dcf: // INT_SAMPLER_2D_ARRAY 19012 case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY 19013 case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW 19014 return setValueT2DArrayArray; 19015 19016 } 19017 19018} 19019 19020// --- Uniform Classes --- 19021 19022class SingleUniform { 19023 19024 constructor( id, activeInfo, addr ) { 19025 19026 this.id = id; 19027 this.addr = addr; 19028 this.cache = []; 19029 this.type = activeInfo.type; 19030 this.setValue = getSingularSetter( activeInfo.type ); 19031 19032 // this.path = activeInfo.name; // DEBUG 19033 19034 } 19035 19036} 19037 19038class PureArrayUniform { 19039 19040 constructor( id, activeInfo, addr ) { 19041 19042 this.id = id; 19043 this.addr = addr; 19044 this.cache = []; 19045 this.type = activeInfo.type; 19046 this.size = activeInfo.size; 19047 this.setValue = getPureArraySetter( activeInfo.type ); 19048 19049 // this.path = activeInfo.name; // DEBUG 19050 19051 } 19052 19053} 19054 19055class StructuredUniform { 19056 19057 constructor( id ) { 19058 19059 this.id = id; 19060 19061 this.seq = []; 19062 this.map = {}; 19063 19064 } 19065 19066 setValue( gl, value, textures ) { 19067 19068 const seq = this.seq; 19069 19070 for ( let i = 0, n = seq.length; i !== n; ++ i ) { 19071 19072 const u = seq[ i ]; 19073 u.setValue( gl, value[ u.id ], textures ); 19074 19075 } 19076 19077 } 19078 19079} 19080 19081// --- Top-level --- 19082 19083// Parser - builds up the property tree from the path strings 19084 19085const RePathPart = /(\w+)(\])?(\[|\.)?/g; 19086 19087// extracts 19088// - the identifier (member name or array index) 19089// - followed by an optional right bracket (found when array index) 19090// - followed by an optional left bracket or dot (type of subscript) 19091// 19092// Note: These portions can be read in a non-overlapping fashion and 19093// allow straightforward parsing of the hierarchy that WebGL encodes 19094// in the uniform names. 19095 19096function addUniform( container, uniformObject ) { 19097 19098 container.seq.push( uniformObject ); 19099 container.map[ uniformObject.id ] = uniformObject; 19100 19101} 19102 19103function parseUniform( activeInfo, addr, container ) { 19104 19105 const path = activeInfo.name, 19106 pathLength = path.length; 19107 19108 // reset RegExp object, because of the early exit of a previous run 19109 RePathPart.lastIndex = 0; 19110 19111 while ( true ) { 19112 19113 const match = RePathPart.exec( path ), 19114 matchEnd = RePathPart.lastIndex; 19115 19116 let id = match[ 1 ]; 19117 const idIsIndex = match[ 2 ] === ']', 19118 subscript = match[ 3 ]; 19119 19120 if ( idIsIndex ) id = id | 0; // convert to integer 19121 19122 if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) { 19123 19124 // bare name or "pure" bottom-level array "[0]" suffix 19125 19126 addUniform( container, subscript === undefined ? 19127 new SingleUniform( id, activeInfo, addr ) : 19128 new PureArrayUniform( id, activeInfo, addr ) ); 19129 19130 break; 19131 19132 } else { 19133 19134 // step into inner node / create it in case it doesn't exist 19135 19136 const map = container.map; 19137 let next = map[ id ]; 19138 19139 if ( next === undefined ) { 19140 19141 next = new StructuredUniform( id ); 19142 addUniform( container, next ); 19143 19144 } 19145 19146 container = next; 19147 19148 } 19149 19150 } 19151 19152} 19153 19154// Root Container 19155 19156class WebGLUniforms { 19157 19158 constructor( gl, program ) { 19159 19160 this.seq = []; 19161 this.map = {}; 19162 19163 const n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS ); 19164 19165 for ( let i = 0; i < n; ++ i ) { 19166 19167 const info = gl.getActiveUniform( program, i ), 19168 addr = gl.getUniformLocation( program, info.name ); 19169 19170 parseUniform( info, addr, this ); 19171 19172 } 19173 19174 } 19175 19176 setValue( gl, name, value, textures ) { 19177 19178 const u = this.map[ name ]; 19179 19180 if ( u !== undefined ) u.setValue( gl, value, textures ); 19181 19182 } 19183 19184 setOptional( gl, object, name ) { 19185 19186 const v = object[ name ]; 19187 19188 if ( v !== undefined ) this.setValue( gl, name, v ); 19189 19190 } 19191 19192 static upload( gl, seq, values, textures ) { 19193 19194 for ( let i = 0, n = seq.length; i !== n; ++ i ) { 19195 19196 const u = seq[ i ], 19197 v = values[ u.id ]; 19198 19199 if ( v.needsUpdate !== false ) { 19200 19201 // note: always updating when .needsUpdate is undefined 19202 u.setValue( gl, v.value, textures ); 19203 19204 } 19205 19206 } 19207 19208 } 19209 19210 static seqWithValue( seq, values ) { 19211 19212 const r = []; 19213 19214 for ( let i = 0, n = seq.length; i !== n; ++ i ) { 19215 19216 const u = seq[ i ]; 19217 if ( u.id in values ) r.push( u ); 19218 19219 } 19220 19221 return r; 19222 19223 } 19224 19225} 19226 19227function WebGLShader( gl, type, string ) { 19228 19229 const shader = gl.createShader( type ); 19230 19231 gl.shaderSource( shader, string ); 19232 gl.compileShader( shader ); 19233 19234 return shader; 19235 19236} 19237 19238// From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/ 19239const COMPLETION_STATUS_KHR = 0x91B1; 19240 19241let programIdCount = 0; 19242 19243function handleSource( string, errorLine ) { 19244 19245 const lines = string.split( '\n' ); 19246 const lines2 = []; 19247 19248 const from = Math.max( errorLine - 6, 0 ); 19249 const to = Math.min( errorLine + 6, lines.length ); 19250 19251 for ( let i = from; i < to; i ++ ) { 19252 19253 const line = i + 1; 19254 lines2.push( `${line === errorLine ? '>' : ' '} ${line}: ${lines[ i ]}` ); 19255 19256 } 19257 19258 return lines2.join( '\n' ); 19259 19260} 19261 19262function getEncodingComponents( colorSpace ) { 19263 19264 const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); 19265 const encodingPrimaries = ColorManagement.getPrimaries( colorSpace ); 19266 19267 let gamutMapping; 19268 19269 if ( workingPrimaries === encodingPrimaries ) { 19270 19271 gamutMapping = ''; 19272 19273 } else if ( workingPrimaries === P3Primaries && encodingPrimaries === Rec709Primaries ) { 19274 19275 gamutMapping = 'LinearDisplayP3ToLinearSRGB'; 19276 19277 } else if ( workingPrimaries === Rec709Primaries && encodingPrimaries === P3Primaries ) { 19278 19279 gamutMapping = 'LinearSRGBToLinearDisplayP3'; 19280 19281 } 19282 19283 switch ( colorSpace ) { 19284 19285 case LinearSRGBColorSpace: 19286 case LinearDisplayP3ColorSpace: 19287 return [ gamutMapping, 'LinearTransferOETF' ]; 19288 19289 case SRGBColorSpace: 19290 case DisplayP3ColorSpace: 19291 return [ gamutMapping, 'sRGBTransferOETF' ]; 19292 19293 default: 19294 console.warn( 'THREE.WebGLProgram: Unsupported color space:', colorSpace ); 19295 return [ gamutMapping, 'LinearTransferOETF' ]; 19296 19297 } 19298 19299} 19300 19301function getShaderErrors( gl, shader, type ) { 19302 19303 const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS ); 19304 const errors = gl.getShaderInfoLog( shader ).trim(); 19305 19306 if ( status && errors === '' ) return ''; 19307 19308 const errorMatches = /ERROR: 0:(\d+)/.exec( errors ); 19309 if ( errorMatches ) { 19310 19311 // --enable-privileged-webgl-extension 19312 // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); 19313 19314 const errorLine = parseInt( errorMatches[ 1 ] ); 19315 return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine ); 19316 19317 } else { 19318 19319 return errors; 19320 19321 } 19322 19323} 19324 19325function getTexelEncodingFunction( functionName, colorSpace ) { 19326 19327 const components = getEncodingComponents( colorSpace ); 19328 return `vec4 ${functionName}( vec4 value ) { return ${components[ 0 ]}( ${components[ 1 ]}( value ) ); }`; 19329 19330} 19331 19332function getToneMappingFunction( functionName, toneMapping ) { 19333 19334 let toneMappingName; 19335 19336 switch ( toneMapping ) { 19337 19338 case LinearToneMapping: 19339 toneMappingName = 'Linear'; 19340 break; 19341 19342 case ReinhardToneMapping: 19343 toneMappingName = 'Reinhard'; 19344 break; 19345 19346 case CineonToneMapping: 19347 toneMappingName = 'OptimizedCineon'; 19348 break; 19349 19350 case ACESFilmicToneMapping: 19351 toneMappingName = 'ACESFilmic'; 19352 break; 19353 19354 case AgXToneMapping: 19355 toneMappingName = 'AgX'; 19356 break; 19357 19358 case NeutralToneMapping: 19359 toneMappingName = 'Neutral'; 19360 break; 19361 19362 case CustomToneMapping: 19363 toneMappingName = 'Custom'; 19364 break; 19365 19366 default: 19367 console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping ); 19368 toneMappingName = 'Linear'; 19369 19370 } 19371 19372 return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }'; 19373 19374} 19375 19376function generate
19376VertexExtensions( parameters ) { 19377 19378 const chunks = [
vendor: 7,072 bytes, lines 19379-19686
19379 parameters.extensionClipCullDistance ? '#extension GL_ANGLE_clip_cull_distance : require' : '', 19380 parameters.extensionMultiDraw ? '#extension GL_ANGLE_multi_draw : require' : '', 19381 ]; 19382 19383 return chunks.filter( filterEmptyLine ).join( '\n' ); 19384 19385} 19386 19387function generateDefines( defines ) { 19388 19389 const chunks = []; 19390 19391 for ( const name in defines ) { 19392 19393 const value = defines[ name ]; 19394 19395 if ( value === false ) continue; 19396 19397 chunks.push( '#define ' + name + ' ' + value ); 19398 19399 } 19400 19401 return chunks.join( '\n' ); 19402 19403} 19404 19405function fetchAttributeLocations( gl, program ) { 19406 19407 const attributes = {}; 19408 19409 const n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES ); 19410 19411 for ( let i = 0; i < n; i ++ ) { 19412 19413 const info = gl.getActiveAttrib( program, i ); 19414 const name = info.name; 19415 19416 let locationSize = 1; 19417 if ( info.type === gl.FLOAT_MAT2 ) locationSize = 2; 19418 if ( info.type === gl.FLOAT_MAT3 ) locationSize = 3; 19419 if ( info.type === gl.FLOAT_MAT4 ) locationSize = 4; 19420 19421 // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); 19422 19423 attributes[ name ] = { 19424 type: info.type, 19425 location: gl.getAttribLocation( program, name ), 19426 locationSize: locationSize 19427 }; 19428 19429 } 19430 19431 return attributes; 19432 19433} 19434 19435function filterEmptyLine( string ) { 19436 19437 return string !== ''; 19438 19439} 19440 19441function replaceLightNums( string, parameters ) { 19442 19443 const numSpotLightCoords = parameters.numSpotLightShadows + parameters.numSpotLightMaps - parameters.numSpotLightShadowsWithMaps; 19444 19445 return string 19446 .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights ) 19447 .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights ) 19448 .replace( /NUM_SPOT_LIGHT_MAPS/g, parameters.numSpotLightMaps ) 19449 .replace( /NUM_SPOT_LIGHT_COORDS/g, numSpotLightCoords ) 19450 .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights ) 19451 .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights ) 19452 .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights ) 19453 .replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows ) 19454 .replace( /NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g, parameters.numSpotLightShadowsWithMaps ) 19455 .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows ) 19456 .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows ); 19457 19458} 19459 19460function replaceClippingPlaneNums( string, parameters ) { 19461 19462 return string 19463 .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes ) 19464 .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) ); 19465 19466} 19467 19468// Resolve Includes 19469 19470const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm; 19471 19472function resolveIncludes( string ) { 19473 19474 return string.replace( includePattern, includeReplacer ); 19475 19476} 19477 19478const shaderChunkMap = new Map(); 19479 19480function includeReplacer( match, include ) { 19481 19482 let string = ShaderChunk[ include ]; 19483 19484 if ( string === undefined ) { 19485 19486 const newInclude = shaderChunkMap.get( include ); 19487 19488 if ( newInclude !== undefined ) { 19489 19490 string = ShaderChunk[ newInclude ]; 19491 console.warn( 'THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude ); 19492 19493 } else { 19494 19495 throw new Error( 'Can not resolve #include <' + include + '>' ); 19496 19497 } 19498 19499 } 19500 19501 return resolveIncludes( string ); 19502 19503} 19504 19505// Unroll Loops 19506 19507const 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; 19508 19509function unrollLoops( string ) { 19510 19511 return string.replace( unrollLoopPattern, loopReplacer ); 19512 19513} 19514 19515function loopReplacer( match, start, end, snippet ) { 19516 19517 let string = ''; 19518 19519 for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) { 19520 19521 string += snippet 19522 .replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' ) 19523 .replace( /UNROLLED_LOOP_INDEX/g, i ); 19524 19525 } 19526 19527 return string; 19528 19529} 19530 19531// 19532 19533function generatePrecision( parameters ) { 19534 19535 let precisionstring = `precision ${parameters.precision} float; 19536 precision ${parameters.precision} int; 19537 precision ${parameters.precision} sampler2D; 19538 precision ${parameters.precision} samplerCube; 19539 precision ${parameters.precision} sampler3D; 19540 precision ${parameters.precision} sampler2DArray; 19541 precision ${parameters.precision} sampler2DShadow; 19542 precision ${parameters.precision} samplerCubeShadow; 19543 precision ${parameters.precision} sampler2DArrayShadow; 19544 precision ${parameters.precision} isampler2D; 19545 precision ${parameters.precision} isampler3D; 19546 precision ${parameters.precision} isamplerCube; 19547 precision ${parameters.precision} isampler2DArray; 19548 precision ${parameters.precision} usampler2D; 19549 precision ${parameters.precision} usampler3D; 19550 precision ${parameters.precision} usamplerCube; 19551 precision ${parameters.precision} usampler2DArray; 19552 `; 19553 19554 if ( parameters.precision === 'highp' ) { 19555 19556 precisionstring += '\n#define HIGH_PRECISION'; 19557 19558 } else if ( parameters.precision === 'mediump' ) { 19559 19560 precisionstring += '\n#define MEDIUM_PRECISION'; 19561 19562 } else if ( parameters.precision === 'lowp' ) { 19563 19564 precisionstring += '\n#define LOW_PRECISION'; 19565 19566 } 19567 19568 return precisionstring; 19569 19570} 19571 19572function generateShadowMapTypeDefine( parameters ) { 19573 19574 let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; 19575 19576 if ( parameters.shadowMapType === PCFShadowMap ) { 19577 19578 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; 19579 19580 } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { 19581 19582 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; 19583 19584 } else if ( parameters.shadowMapType === VSMShadowMap ) { 19585 19586 shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM'; 19587 19588 } 19589 19590 return shadowMapTypeDefine; 19591 19592} 19593 19594function generateEnvMapTypeDefine( parameters ) { 19595 19596 let envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; 19597 19598 if ( parameters.envMap ) { 19599 19600 switch ( parameters.envMapMode ) { 19601 19602 case CubeReflectionMapping: 19603 case CubeRefractionMapping: 19604 envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; 19605 break; 19606 19607 case CubeUVReflectionMapping: 19608 envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; 19609 break; 19610 19611 } 19612 19613 } 19614 19615 return envMapTypeDefine; 19616 19617} 19618 19619function generateEnvMapModeDefine( parameters ) { 19620 19621 let envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; 19622 19623 if ( parameters.envMap ) { 19624 19625 switch ( parameters.envMapMode ) { 19626 19627 case CubeRefractionMapping: 19628 19629 envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; 19630 break; 19631 19632 } 19633 19634 } 19635 19636 return envMapModeDefine; 19637 19638} 19639 19640function generateEnvMapBlendingDefine( parameters ) { 19641 19642 let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE'; 19643 19644 if ( parameters.envMap ) { 19645 19646 switch ( parameters.combine ) { 19647 19648 case MultiplyOperation: 19649 envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; 19650 break; 19651 19652 case MixOperation: 19653 envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; 19654 break; 19655 19656 case AddOperation: 19657 envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; 19658 break; 19659 19660 } 19661 19662 } 19663 19664 return envMapBlendingDefine; 19665 19666} 19667 19668function generateCubeUVSize( parameters ) { 19669 19670 const imageHeight = parameters.envMapCubeUVHeight; 19671 19672 if ( imageHeight === null ) return null; 19673 19674 const maxMip = Math.log2( imageHeight ) - 2; 19675 19676 const texelHeight = 1.0 / imageHeight; 19677 19678 const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) ); 19679 19680 return { texelWidth, texelHeight, maxMip }; 19681 19682} 19683 19684function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { 19685 19686 // TODO Send this event to Three.js DevTools
vendor: 14,731 bytes, lines 19687-20078
19687 // console.log( 'WebGLProgram', cacheKey ); 19688 19689 const gl = renderer.getContext(); 19690 19691 const defines = parameters.defines; 19692 19693 let vertexShader = parameters.vertexShader; 19694 let fragmentShader = parameters.fragmentShader; 19695 19696 const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters ); 19697 const envMapTypeDefine = generateEnvMapTypeDefine( parameters ); 19698 const envMapModeDefine = generateEnvMapModeDefine( parameters ); 19699 const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters ); 19700 const envMapCubeUVSize = generateCubeUVSize( parameters ); 19701 19702 const customVertexExtensions = generateVertexExtensions( parameters ); 19703 19704 const customDefines = generateDefines( defines ); 19705 19706 const program = gl.createProgram(); 19707 19708 let prefixVertex, prefixFragment; 19709 let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : ''; 19710 19711 if ( parameters.isRawShaderMaterial ) { 19712 19713 prefixVertex = [ 19714 19715 '#define SHADER_TYPE ' + parameters.shaderType, 19716 '#define SHADER_NAME ' + parameters.shaderName, 19717 19718 customDefines 19719 19720 ].filter( filterEmptyLine ).join( '\n' ); 19721 19722 if ( prefixVertex.length > 0 ) { 19723 19724 prefixVertex += '\n'; 19725 19726 } 19727 19728 prefixFragment = [ 19729 19730 '#define SHADER_TYPE ' + parameters.shaderType, 19731 '#define SHADER_NAME ' + parameters.shaderName, 19732 19733 customDefines 19734 19735 ].filter( filterEmptyLine ).join( '\n' ); 19736 19737 if ( prefixFragment.length > 0 ) { 19738 19739 prefixFragment += '\n'; 19740 19741 } 19742 19743 } else { 19744 19745 prefixVertex = [ 19746 19747 generatePrecision( parameters ), 19748 19749 '#define SHADER_TYPE ' + parameters.shaderType, 19750 '#define SHADER_NAME ' + parameters.shaderName, 19751 19752 customDefines, 19753 19754 parameters.extensionClipCullDistance ? '#define USE_CLIP_DISTANCE' : '', 19755 parameters.batching ? '#define USE_BATCHING' : '', 19756 parameters.batchingColor ? '#define USE_BATCHING_COLOR' : '', 19757 parameters.instancing ? '#define USE_INSTANCING' : '', 19758 parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', 19759 parameters.instancingMorph ? '#define USE_INSTANCING_MORPH' : '', 19760 19761 parameters.useFog && parameters.fog ? '#define USE_FOG' : '', 19762 parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', 19763 19764 parameters.map ? '#define USE_MAP' : '', 19765 parameters.envMap ? '#define USE_ENVMAP' : '', 19766 parameters.envMap ? '#define ' + envMapModeDefine : '', 19767 parameters.lightMap ? '#define USE_LIGHTMAP' : '', 19768 parameters.aoMap ? '#define USE_AOMAP' : '', 19769 parameters.bumpMap ? '#define USE_BUMPMAP' : '', 19770 parameters.normalMap ? '#define USE_NORMALMAP' : '', 19771 parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', 19772 parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', 19773 parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '', 19774 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', 19775 19776 parameters.anisotropy ? '#define USE_ANISOTROPY' : '', 19777 parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', 19778 19779 parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', 19780 parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', 19781 parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', 19782 19783 parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', 19784 parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', 19785 19786 parameters.specularMap ? '#define USE_SPECULARMAP' : '', 19787 parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', 19788 parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', 19789 19790 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', 19791 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', 19792 parameters.alphaMap ? '#define USE_ALPHAMAP' : '', 19793 parameters.alphaHash ? '#define USE_ALPHAHASH' : '', 19794 19795 parameters.transmission ? '#define USE_TRANSMISSION' : '', 19796 parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', 19797 parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', 19798 19799 parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', 19800 parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', 19801 19802 // 19803 19804 parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '', 19805 parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '', 19806 parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '', 19807 parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '', 19808 parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '', 19809 parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '', 19810 parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '', 19811 parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '', 19812 19813 parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '', 19814 parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '', 19815 19816 parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '', 19817 19818 parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '', 19819 parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '', 19820 parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '', 19821 19822 parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '', 19823 parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '', 19824 19825 parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '', 19826 parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '', 19827 19828 parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '', 19829 parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '', 19830 parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '', 19831 19832 parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '', 19833 parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '', 19834 19835 // 19836 19837 parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', 19838 parameters.vertexColors ? '#define USE_COLOR' : '', 19839 parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', 19840 parameters.vertexUv1s ? '#define USE_UV1' : '', 19841 parameters.vertexUv2s ? '#define USE_UV2' : '', 19842 parameters.vertexUv3s ? '#define USE_UV3' : '', 19843 19844 parameters.pointsUvs ? '#define USE_POINTS_UV' : '', 19845 19846 parameters.flatShading ? '#define FLAT_SHADED' : '', 19847 19848 parameters.skinning ? '#define USE_SKINNING' : '', 19849 19850 parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', 19851 parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', 19852 ( parameters.morphColors ) ? '#define USE_MORPHCOLORS' : '', 19853 ( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '', 19854 ( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '', 19855 parameters.doubleSided ? '#define DOUBLE_SIDED' : '', 19856 parameters.flipSided ? '#define FLIP_SIDED' : '', 19857 19858 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', 19859 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', 19860 19861 parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', 19862 19863 parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', 19864 19865 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', 19866 19867 'uniform mat4 modelMatrix;', 19868 'uniform mat4 modelViewMatrix;', 19869 'uniform mat4 projectionMatrix;', 19870 'uniform mat4 viewMatrix;', 19871 'uniform mat3 normalMatrix;', 19872 'uniform vec3 cameraPosition;', 19873 'uniform bool isOrthographic;', 19874 19875 '#ifdef USE_INSTANCING', 19876 19877 ' attribute mat4 instanceMatrix;', 19878 19879 '#endif', 19880 19881 '#ifdef USE_INSTANCING_COLOR', 19882 19883 ' attribute vec3 instanceColor;', 19884 19885 '#endif', 19886 19887 '#ifdef USE_INSTANCING_MORPH', 19888 19889 ' uniform sampler2D morphTexture;', 19890 19891 '#endif', 19892 19893 'attribute vec3 position;', 19894 'attribute vec3 normal;', 19895 'attribute vec2 uv;', 19896 19897 '#ifdef USE_UV1', 19898 19899 ' attribute vec2 uv1;', 19900 19901 '#endif', 19902 19903 '#ifdef USE_UV2', 19904 19905 ' attribute vec2 uv2;', 19906 19907 '#endif', 19908 19909 '#ifdef USE_UV3', 19910 19911 ' attribute vec2 uv3;', 19912 19913 '#endif', 19914 19915 '#ifdef USE_TANGENT', 19916 19917 ' attribute vec4 tangent;', 19918 19919 '#endif', 19920 19921 '#if defined( USE_COLOR_ALPHA )', 19922 19923 ' attribute vec4 color;', 19924 19925 '#elif defined( USE_COLOR )', 19926 19927 ' attribute vec3 color;', 19928 19929 '#endif', 19930 19931 '#ifdef USE_SKINNING', 19932 19933 ' attribute vec4 skinIndex;', 19934 ' attribute vec4 skinWeight;', 19935 19936 '#endif', 19937 19938 '\n' 19939 19940 ].filter( filterEmptyLine ).join( '\n' ); 19941 19942 prefixFragment = [ 19943 19944 generatePrecision( parameters ), 19945 19946 '#define SHADER_TYPE ' + parameters.shaderType, 19947 '#define SHADER_NAME ' + parameters.shaderName, 19948 19949 customDefines, 19950 19951 parameters.useFog && parameters.fog ? '#define USE_FOG' : '', 19952 parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', 19953 19954 parameters.alphaToCoverage ? '#define ALPHA_TO_COVERAGE' : '', 19955 parameters.map ? '#define USE_MAP' : '', 19956 parameters.matcap ? '#define USE_MATCAP' : '', 19957 parameters.envMap ? '#define USE_ENVMAP' : '', 19958 parameters.envMap ? '#define ' + envMapTypeDefine : '', 19959 parameters.envMap ? '#define ' + envMapModeDefine : '', 19960 parameters.envMap ? '#define ' + envMapBlendingDefine : '', 19961 envMapCubeUVSize ? '#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth : '', 19962 envMapCubeUVSize ? '#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight : '', 19963 envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '', 19964 parameters.lightMap ? '#define USE_LIGHTMAP' : '', 19965 parameters.aoMap ? '#define USE_AOMAP' : '', 19966 parameters.bumpMap ? '#define USE_BUMPMAP' : '', 19967 parameters.normalMap ? '#define USE_NORMALMAP' : '', 19968 parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', 19969 parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', 19970 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', 19971 19972 parameters.anisotropy ? '#define USE_ANISOTROPY' : '', 19973 parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', 19974 19975 parameters.clearcoat ? '#define USE_CLEARCOAT' : '', 19976 parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', 19977 parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', 19978 parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', 19979 19980 parameters.dispersion ? '#define USE_DISPERSION' : '', 19981 19982 parameters.iridescence ? '#define USE_IRIDESCENCE' : '', 19983 parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', 19984 parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', 19985 19986 parameters.specularMap ? '#define USE_SPECULARMAP' : '', 19987 parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', 19988 parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', 19989 19990 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', 19991 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', 19992 19993 parameters.alphaMap ? '#define USE_ALPHAMAP' : '', 19994 parameters.alphaTest ? '#define USE_ALPHATEST' : '', 19995 parameters.alphaHash ? '#define USE_ALPHAHASH' : '', 19996 19997 parameters.sheen ? '#define USE_SHEEN' : '', 19998 parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', 19999 parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', 20000 20001 parameters.transmission ? '#define USE_TRANSMISSION' : '', 20002 parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', 20003 parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', 20004 20005 parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', 20006 parameters.vertexColors || parameters.instancingColor || parameters.batchingColor ? '#define USE_COLOR' : '', 20007 parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', 20008 parameters.vertexUv1s ? '#define USE_UV1' : '', 20009 parameters.vertexUv2s ? '#define USE_UV2' : '', 20010 parameters.vertexUv3s ? '#define USE_UV3' : '', 20011 20012 parameters.pointsUvs ? '#define USE_POINTS_UV' : '', 20013 20014 parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', 20015 20016 parameters.flatShading ? '#define FLAT_SHADED' : '', 20017 20018 parameters.doubleSided ? '#define DOUBLE_SIDED' : '', 20019 parameters.flipSided ? '#define FLIP_SIDED' : '', 20020 20021 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', 20022 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', 20023 20024 parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', 20025 20026 parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', 20027 20028 parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', 20029 20030 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', 20031 20032 'uniform mat4 viewMatrix;', 20033 'uniform vec3 cameraPosition;', 20034 'uniform bool isOrthographic;', 20035 20036 ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '', 20037 ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below 20038 ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '', 20039 20040 parameters.dithering ? '#define DITHERING' : '', 20041 parameters.opaque ? '#define OPAQUE' : '', 20042 20043 ShaderChunk[ 'colorspace_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below 20044 getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputColorSpace ), 20045 20046 parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', 20047 20048 '\n' 20049 20050 ].filter( filterEmptyLine ).join( '\n' ); 20051 20052 } 20053 20054 vertexShader = resolveIncludes( vertexShader ); 20055 vertexShader = replaceLightNums( vertexShader, parameters ); 20056 vertexShader = replaceClippingPlaneNums( vertexShader, parameters ); 20057 20058 fragmentShader = resolveIncludes( fragmentShader ); 20059 fragmentShader = replaceLightNums( fragmentShader, parameters ); 20060 fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters ); 20061 20062 vertexShader = unrollLoops( vertexShader ); 20063 fragmentShader = unrollLoops( fragmentShader ); 20064 20065 if ( parameters.isRawShaderMaterial !== true ) { 20066 20067 // GLSL 3.0 conversion for built-in materials and ShaderMaterial 20068 20069 versionString = '#version 300 es\n'; 20070 20071 prefixVertex = [ 20072 customVertexExtensions, 20073 '#define attribute in', 20074 '#define varying out', 20075 '#define texture2D texture' 20076 ].join( '\n' ) + '\n' + prefixVertex; 20077 20078 prefixFragment = [
vendor: 7,213 bytes, lines 20078-20421
20078 20079 '#define varying in', 20080 ( parameters.glslVersion === GLSL3 ) ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;', 20081 ( parameters.glslVersion === GLSL3 ) ? '' : '#define gl_FragColor pc_fragColor', 20082 '#define gl_FragDepthEXT gl_FragDepth', 20083 '#define texture2D texture', 20084 '#define textureCube texture', 20085 '#define texture2DProj textureProj', 20086 '#define texture2DLodEXT textureLod', 20087 '#define texture2DProjLodEXT textureProjLod', 20088 '#define textureCubeLodEXT textureLod', 20089 '#define texture2DGradEXT textureGrad', 20090 '#define texture2DProjGradEXT textureProjGrad', 20091 '#define textureCubeGradEXT textureGrad' 20092 ].join( '\n' ) + '\n' + prefixFragment; 20093 20094 } 20095 20096 const vertexGlsl = versionString + prefixVertex + vertexShader; 20097 const fragmentGlsl = versionString + prefixFragment + fragmentShader; 20098 20099 // console.log( '*VERTEX*', vertexGlsl ); 20100 // console.log( '*FRAGMENT*', fragmentGlsl ); 20101 20102 const glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); 20103 const glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); 20104 20105 gl.attachShader( program, glVertexShader ); 20106 gl.attachShader( program, glFragmentShader ); 20107 20108 // Force a particular attribute to index 0. 20109 20110 if ( parameters.index0AttributeName !== undefined ) { 20111 20112 gl.bindAttribLocation( program, 0, parameters.index0AttributeName ); 20113 20114 } else if ( parameters.morphTargets === true ) { 20115 20116 // programs with morphTargets displace position out of attribute 0 20117 gl.bindAttribLocation( program, 0, 'position' ); 20118 20119 } 20120 20121 gl.linkProgram( program ); 20122 20123 function onFirstUse( self ) { 20124 20125 // check for link errors 20126 if ( renderer.debug.checkShaderErrors ) { 20127 20128 const programLog = gl.getProgramInfoLog( program ).trim(); 20129 const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim(); 20130 const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim(); 20131 20132 let runnable = true; 20133 let haveDiagnostics = true; 20134 20135 if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { 20136 20137 runnable = false; 20138 20139 if ( typeof renderer.debug.onShaderError === 'function' ) { 20140 20141 renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader ); 20142 20143 } else { 20144 20145 // default error reporting 20146 20147 const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); 20148 const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); 20149 20150 console.error( 20151 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + 20152 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + 20153 'Material Name: ' + self.name + '\n' + 20154 'Material Type: ' + self.type + '\n\n' + 20155 'Program Info Log: ' + programLog + '\n' + 20156 vertexErrors + '\n' + 20157 fragmentErrors 20158 ); 20159 20160 } 20161 20162 } else if ( programLog !== '' ) { 20163 20164 console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog ); 20165 20166 } else if ( vertexLog === '' || fragmentLog === '' ) { 20167 20168 haveDiagnostics = false; 20169 20170 } 20171 20172 if ( haveDiagnostics ) { 20173 20174 self.diagnostics = { 20175 20176 runnable: runnable, 20177 20178 programLog: programLog, 20179 20180 vertexShader: { 20181 20182 log: vertexLog, 20183 prefix: prefixVertex 20184 20185 }, 20186 20187 fragmentShader: { 20188 20189 log: fragmentLog, 20190 prefix: prefixFragment 20191 20192 } 20193 20194 }; 20195 20196 } 20197 20198 } 20199 20200 // Clean up 20201 20202 // Crashes in iOS9 and iOS10. #18402 20203 // gl.detachShader( program, glVertexShader ); 20204 // gl.detachShader( program, glFragmentShader ); 20205 20206 gl.deleteShader( glVertexShader ); 20207 gl.deleteShader( glFragmentShader ); 20208 20209 cachedUniforms = new WebGLUniforms( gl, program ); 20210 cachedAttributes = fetchAttributeLocations( gl, program ); 20211 20212 } 20213 20214 // set up caching for uniform locations 20215 20216 let cachedUniforms; 20217 20218 this.getUniforms = function () { 20219 20220 if ( cachedUniforms === undefined ) { 20221 20222 // Populates cachedUniforms and cachedAttributes 20223 onFirstUse( this ); 20224 20225 } 20226 20227 return cachedUniforms; 20228 20229 }; 20230 20231 // set up caching for attribute locations 20232 20233 let cachedAttributes; 20234 20235 this.getAttributes = function () { 20236 20237 if ( cachedAttributes === undefined ) { 20238 20239 // Populates cachedAttributes and cachedUniforms 20240 onFirstUse( this ); 20241 20242 } 20243 20244 return cachedAttributes; 20245 20246 }; 20247 20248 // indicate when the program is ready to be used. if the KHR_parallel_shader_compile extension isn't supported, 20249 // flag the program as ready immediately. It may cause a stall when it's first used. 20250 20251 let programReady = ( parameters.rendererExtensionParallelShaderCompile === false ); 20252 20253 this.isReady = function () { 20254 20255 if ( programReady === false ) { 20256 20257 programReady = gl.getProgramParameter( program, COMPLETION_STATUS_KHR ); 20258 20259 } 20260 20261 return programReady; 20262 20263 }; 20264 20265 // free resource 20266 20267 this.destroy = function () { 20268 20269 bindingStates.releaseStatesOfProgram( this ); 20270 20271 gl.deleteProgram( program ); 20272 this.program = undefined; 20273 20274 }; 20275 20276 // 20277 20278 this.type = parameters.shaderType; 20279 this.name = parameters.shaderName; 20280 this.id = programIdCount ++; 20281 this.cacheKey = cacheKey; 20282 this.usedTimes = 1; 20283 this.program = program; 20284 this.vertexShader = glVertexShader; 20285 this.fragmentShader = glFragmentShader; 20286 20287 return this; 20288 20289} 20290 20291let _id$1 = 0; 20292 20293class WebGLShaderCache { 20294 20295 constructor() { 20296 20297 this.shaderCache = new Map(); 20298 this.materialCache = new Map(); 20299 20300 } 20301 20302 update( material ) { 20303 20304 const vertexShader = material.vertexShader; 20305 const fragmentShader = material.fragmentShader; 20306 20307 const vertexShaderStage = this._getShaderStage( vertexShader ); 20308 const fragmentShaderStage = this._getShaderStage( fragmentShader ); 20309 20310 const materialShaders = this._getShaderCacheForMaterial( material ); 20311 20312 if ( materialShaders.has( vertexShaderStage ) === false ) { 20313 20314 materialShaders.add( vertexShaderStage ); 20315 vertexShaderStage.usedTimes ++; 20316 20317 } 20318 20319 if ( materialShaders.has( fragmentShaderStage ) === false ) { 20320 20321 materialShaders.add( fragmentShaderStage ); 20322 fragmentShaderStage.usedTimes ++; 20323 20324 } 20325 20326 return this; 20327 20328 } 20329 20330 remove( material ) { 20331 20332 const materialShaders = this.materialCache.get( material ); 20333 20334 for ( const shaderStage of materialShaders ) { 20335 20336 shaderStage.usedTimes --; 20337 20338 if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage.code ); 20339 20340 } 20341 20342 this.materialCache.delete( material ); 20343 20344 return this; 20345 20346 } 20347 20348 getVertexShaderID( material ) { 20349 20350 return this._getShaderStage( material.vertexShader ).id; 20351 20352 } 20353 20354 getFragmentShaderID( material ) { 20355 20356 return this._getShaderStage( material.fragmentShader ).id; 20357 20358 } 20359 20360 dispose() { 20361 20362 this.shaderCache.clear(); 20363 this.materialCache.clear(); 20364 20365 } 20366 20367 _getShaderCacheForMaterial( material ) { 20368 20369 const cache = this.materialCache; 20370 let set = cache.get( material ); 20371 20372 if ( set === undefined ) { 20373 20374 set = new Set(); 20375 cache.set( material, set ); 20376 20377 } 20378 20379 return set; 20380 20381 } 20382 20383 _getShaderStage( code ) { 20384 20385 const cache = this.shaderCache; 20386 let stage = cache.get( code ); 20387 20388 if ( stage === undefined ) { 20389 20390 stage = new WebGLShaderStage( code ); 20391 cache.set( code, stage ); 20392 20393 } 20394 20395 return stage; 20396 20397 } 20398 20399} 20400 20401class WebGLShaderStage { 20402 20403 constructor( code ) { 20404 20405 this.id = _id$1 ++; 20406 20407 this.code = code; 20408 this.usedTimes = 0; 20409 20410 } 20411 20412} 20413 20414function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) { 20415 20416 const _programLayers = new Layers(); 20417 const _customShaders = new WebGLShaderCache(); 20418 const _activeChannels = new Set(); 20419 const programs = []; 20420 20421 const
vendor: 20,058 bytes, lines 20421-21056
20421logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; 20422 const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures; 20423 20424 let precision = capabilities.precision; 20425 20426 const shaderIDs = { 20427 MeshDepthMaterial: 'depth', 20428 MeshDistanceMaterial: 'distanceRGBA', 20429 MeshNormalMaterial: 'normal', 20430 MeshBasicMaterial: 'basic', 20431 MeshLambertMaterial: 'lambert', 20432 MeshPhongMaterial: 'phong', 20433 MeshToonMaterial: 'toon', 20434 MeshStandardMaterial: 'physical', 20435 MeshPhysicalMaterial: 'physical', 20436 MeshMatcapMaterial: 'matcap', 20437 LineBasicMaterial: 'basic', 20438 LineDashedMaterial: 'dashed', 20439 PointsMaterial: 'points', 20440 ShadowMaterial: 'shadow', 20441 SpriteMaterial: 'sprite' 20442 }; 20443 20444 function getChannel( value ) { 20445 20446 _activeChannels.add( value ); 20447 20448 if ( value === 0 ) return 'uv'; 20449 20450 return `uv${ value }`; 20451 20452 } 20453 20454 function getParameters( material, lights, shadows, scene, object ) { 20455 20456 const fog = scene.fog; 20457 const geometry = object.geometry; 20458 const environment = material.isMeshStandardMaterial ? scene.environment : null; 20459 20460 const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); 20461 const envMapCubeUVHeight = ( !! envMap ) && ( envMap.mapping === CubeUVReflectionMapping ) ? envMap.image.height : null; 20462 20463 const shaderID = shaderIDs[ material.type ]; 20464 20465 // heuristics to create shader parameters according to lights in the scene 20466 // (not to blow over maxLights budget) 20467 20468 if ( material.precision !== null ) { 20469 20470 precision = capabilities.getMaxPrecision( material.precision ); 20471 20472 if ( precision !== material.precision ) { 20473 20474 console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); 20475 20476 } 20477 20478 } 20479 20480 // 20481 20482 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; 20483 const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; 20484 20485 let morphTextureStride = 0; 20486 20487 if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 1; 20488 if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 2; 20489 if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 3; 20490 20491 // 20492 20493 let vertexShader, fragmentShader; 20494 let customVertexShaderID, customFragmentShaderID; 20495 20496 if ( shaderID ) { 20497 20498 const shader = ShaderLib[ shaderID ]; 20499 20500 vertexShader = shader.vertexShader; 20501 fragmentShader = shader.fragmentShader; 20502 20503 } else { 20504 20505 vertexShader = material.vertexShader; 20506 fragmentShader = material.fragmentShader; 20507 20508 _customShaders.update( material ); 20509 20510 customVertexShaderID = _customShaders.getVertexShaderID( material ); 20511 customFragmentShaderID = _customShaders.getFragmentShaderID( material ); 20512 20513 } 20514 20515 const currentRenderTarget = renderer.getRenderTarget(); 20516 20517 const IS_INSTANCEDMESH = object.isInstancedMesh === true; 20518 const IS_BATCHEDMESH = object.isBatchedMesh === true; 20519 20520 const HAS_MAP = !! material.map; 20521 const HAS_MATCAP = !! material.matcap; 20522 const HAS_ENVMAP = !! envMap; 20523 const HAS_AOMAP = !! material.aoMap; 20524 const HAS_LIGHTMAP = !! material.lightMap; 20525 const HAS_BUMPMAP = !! material.bumpMap; 20526 const HAS_NORMALMAP = !! material.normalMap; 20527 const HAS_DISPLACEMENTMAP = !! material.displacementMap; 20528 const HAS_EMISSIVEMAP = !! material.emissiveMap; 20529 20530 const HAS_METALNESSMAP = !! material.metalnessMap; 20531 const HAS_ROUGHNESSMAP = !! material.roughnessMap; 20532 20533 const HAS_ANISOTROPY = material.anisotropy > 0; 20534 const HAS_CLEARCOAT = material.clearcoat > 0; 20535 const HAS_DISPERSION = material.dispersion > 0; 20536 const HAS_IRIDESCENCE = material.iridescence > 0; 20537 const HAS_SHEEN = material.sheen > 0; 20538 const HAS_TRANSMISSION = material.transmission > 0; 20539 20540 const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap; 20541 20542 const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap; 20543 const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap; 20544 const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap; 20545 20546 const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap; 20547 const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap; 20548 20549 const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap; 20550 const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap; 20551 20552 const HAS_SPECULARMAP = !! material.specularMap; 20553 const HAS_SPECULAR_COLORMAP = !! material.specularColorMap; 20554 const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap; 20555 20556 const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap; 20557 const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap; 20558 20559 const HAS_GRADIENTMAP = !! material.gradientMap; 20560 20561 const HAS_ALPHAMAP = !! material.alphaMap; 20562 20563 const HAS_ALPHATEST = material.alphaTest > 0; 20564 20565 const HAS_ALPHAHASH = !! material.alphaHash; 20566 20567 const HAS_EXTENSIONS = !! material.extensions; 20568 20569 let toneMapping = NoToneMapping; 20570 20571 if ( material.toneMapped ) { 20572 20573 if ( currentRenderTarget === null || currentRenderTarget.isXRRenderTarget === true ) { 20574 20575 toneMapping = renderer.toneMapping; 20576 20577 } 20578 20579 } 20580 20581 const parameters = { 20582 20583 shaderID: shaderID, 20584 shaderType: material.type, 20585 shaderName: material.name, 20586 20587 vertexShader: vertexShader, 20588 fragmentShader: fragmentShader, 20589 defines: material.defines, 20590 20591 customVertexShaderID: customVertexShaderID, 20592 customFragmentShaderID: customFragmentShaderID, 20593 20594 isRawShaderMaterial: material.isRawShaderMaterial === true, 20595 glslVersion: material.glslVersion, 20596 20597 precision: precision, 20598 20599 batching: IS_BATCHEDMESH, 20600 batchingColor: IS_BATCHEDMESH && object._colorsTexture !== null, 20601 instancing: IS_INSTANCEDMESH, 20602 instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, 20603 instancingMorph: IS_INSTANCEDMESH && object.morphTexture !== null, 20604 20605 supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES, 20606 outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ), 20607 alphaToCoverage: !! material.alphaToCoverage, 20608 20609 map: HAS_MAP, 20610 matcap: HAS_MATCAP, 20611 envMap: HAS_ENVMAP, 20612 envMapMode: HAS_ENVMAP && envMap.mapping, 20613 envMapCubeUVHeight: envMapCubeUVHeight, 20614 aoMap: HAS_AOMAP, 20615 lightMap: HAS_LIGHTMAP, 20616 bumpMap: HAS_BUMPMAP, 20617 normalMap: HAS_NORMALMAP, 20618 displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP, 20619 emissiveMap: HAS_EMISSIVEMAP, 20620 20621 normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap, 20622 normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap, 20623 20624 metalnessMap: HAS_METALNESSMAP, 20625 roughnessMap: HAS_ROUGHNESSMAP, 20626 20627 anisotropy: HAS_ANISOTROPY, 20628 anisotropyMap: HAS_ANISOTROPYMAP, 20629 20630 clearcoat: HAS_CLEARCOAT, 20631 clearcoatMap: HAS_CLEARCOATMAP, 20632 clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP, 20633 clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP, 20634 20635 dispersion: HAS_DISPERSION, 20636 20637 iridescence: HAS_IRIDESCENCE, 20638 iridescenceMap: HAS_IRIDESCENCEMAP, 20639 iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP, 20640 20641 sheen: HAS_SHEEN, 20642 sheenColorMap: HAS_SHEEN_COLORMAP, 20643 sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP, 20644 20645 specularMap: HAS_SPECULARMAP, 20646 specularColorMap: HAS_SPECULAR_COLORMAP, 20647 specularIntensityMap: HAS_SPECULAR_INTENSITYMAP, 20648 20649 transmission: HAS_TRANSMISSION, 20650 transmissionMap: HAS_TRANSMISSIONMAP, 20651 thicknessMap: HAS_THICKNESSMAP, 20652 20653 gradientMap: HAS_GRADIENTMAP, 20654 20655 opaque: material.transparent === false && material.blending === NormalBlending && material.alphaToCoverage === false, 20656 20657 alphaMap: HAS_ALPHAMAP, 20658 alphaTest: HAS_ALPHATEST, 20659 alphaHash: HAS_ALPHAHASH, 20660 20661 combine: material.combine, 20662 20663 // 20664 20665 mapUv: HAS_MAP && getChannel( material.map.channel ), 20666 aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ), 20667 lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ), 20668 bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ), 20669 normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ), 20670 displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ), 20671 emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ), 20672 20673 metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ), 20674 roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ), 20675 20676 anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ), 20677 20678 clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ), 20679 clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ), 20680 clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ), 20681 20682 iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ), 20683 iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ), 20684 20685 sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ), 20686 sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ), 20687 20688 specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ), 20689 specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ), 20690 specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ), 20691 20692 transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ), 20693 thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ), 20694 20695 alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ), 20696 20697 // 20698 20699 vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ), 20700 vertexColors: material.vertexColors, 20701 vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4, 20702 20703 pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ), 20704 20705 fog: !! fog, 20706 useFog: material.fog === true, 20707 fogExp2: ( !! fog && fog.isFogExp2 ), 20708 20709 flatShading: material.flatShading === true, 20710 20711 sizeAttenuation: material.sizeAttenuation === true, 20712 logarithmicDepthBuffer: logarithmicDepthBuffer, 20713 20714 skinning: object.isSkinnedMesh === true, 20715 20716 morphTargets: geometry.morphAttributes.position !== undefined, 20717 morphNormals: geometry.morphAttributes.normal !== undefined, 20718 morphColors: geometry.morphAttributes.color !== undefined, 20719 morphTargetsCount: morphTargetsCount, 20720 morphTextureStride: morphTextureStride, 20721 20722 numDirLights: lights.directional.length, 20723 numPointLights: lights.point.length, 20724 numSpotLights: lights.spot.length, 20725 numSpotLightMaps: lights.spotLightMap.length, 20726 numRectAreaLights: lights.rectArea.length, 20727 numHemiLights: lights.hemi.length, 20728 20729 numDirLightShadows: lights.directionalShadowMap.length, 20730 numPointLightShadows: lights.pointShadowMap.length, 20731 numSpotLightShadows: lights.spotShadowMap.length, 20732 numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps, 20733 20734 numLightProbes: lights.numLightProbes, 20735 20736 numClippingPlanes: clipping.numPlanes, 20737 numClipIntersection: clipping.numIntersection, 20738 20739 dithering: material.dithering, 20740 20741 shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0, 20742 shadowMapType: renderer.shadowMap.type, 20743 20744 toneMapping: toneMapping, 20745 20746 decodeVideoTexture: HAS_MAP && ( material.map.isVideoTexture === true ) && ( ColorManagement.getTransfer( material.map.colorSpace ) === SRGBTransfer ), 20747 20748 premultipliedAlpha: material.premultipliedAlpha, 20749 20750 doubleSided: material.side === DoubleSide, 20751 flipSided: material.side === BackSide, 20752 20753 useDepthPacking: material.depthPacking >= 0, 20754 depthPacking: material.depthPacking || 0, 20755 20756 index0AttributeName: material.index0AttributeName, 20757 20758 extensionClipCullDistance: HAS_EXTENSIONS && material.extensions.clipCullDistance === true && extensions.has( 'WEBGL_clip_cull_distance' ), 20759 extensionMultiDraw: HAS_EXTENSIONS && material.extensions.multiDraw === true && extensions.has( 'WEBGL_multi_draw' ), 20760 20761 rendererExtensionParallelShaderCompile: extensions.has( 'KHR_parallel_shader_compile' ), 20762 20763 customProgramCacheKey: material.customProgramCacheKey() 20764 20765 }; 20766 20767 // the usage of getChannel() determines the active texture channels for this shader 20768 20769 parameters.vertexUv1s = _activeChannels.has( 1 ); 20770 parameters.vertexUv2s = _activeChannels.has( 2 ); 20771 parameters.vertexUv3s = _activeChannels.has( 3 ); 20772 20773 _activeChannels.clear(); 20774 20775 return parameters; 20776 20777 } 20778 20779 function getProgramCacheKey( parameters ) { 20780 20781 const array = []; 20782 20783 if ( parameters.shaderID ) { 20784 20785 array.push( parameters.shaderID ); 20786 20787 } else { 20788 20789 array.push( parameters.customVertexShaderID ); 20790 array.push( parameters.customFragmentShaderID ); 20791 20792 } 20793 20794 if ( parameters.defines !== undefined ) { 20795 20796 for ( const name in parameters.defines ) { 20797 20798 array.push( name ); 20799 array.push( parameters.defines[ name ] ); 20800 20801 } 20802 20803 } 20804 20805 if ( parameters.isRawShaderMaterial === false ) { 20806 20807 getProgramCacheKeyParameters( array, parameters ); 20808 getProgramCacheKeyBooleans( array, parameters ); 20809 array.push( renderer.outputColorSpace ); 20810 20811 } 20812 20813 array.push( parameters.customProgramCacheKey ); 20814 20815 return array.join(); 20816 20817 } 20818 20819 function getProgramCacheKeyParameters( array, parameters ) { 20820 20821 array.push( parameters.precision ); 20822 array.push( parameters.outputColorSpace ); 20823 array.push( parameters.envMapMode ); 20824 array.push( parameters.envMapCubeUVHeight ); 20825 array.push( parameters.mapUv ); 20826 array.push( parameters.alphaMapUv ); 20827 array.push( parameters.lightMapUv ); 20828 array.push( parameters.aoMapUv ); 20829 array.push( parameters.bumpMapUv ); 20830 array.push( parameters.normalMapUv ); 20831 array.push( parameters.displacementMapUv ); 20832 array.push( parameters.emissiveMapUv ); 20833 array.push( parameters.metalnessMapUv ); 20834 array.push( parameters.roughnessMapUv ); 20835 array.push( parameters.anisotropyMapUv ); 20836 array.push( parameters.clearcoatMapUv ); 20837 array.push( parameters.clearcoatNormalMapUv ); 20838 array.push( parameters.clearcoatRoughnessMapUv ); 20839 array.push( parameters.iridescenceMapUv ); 20840 array.push( parameters.iridescenceThicknessMapUv ); 20841 array.push( parameters.sheenColorMapUv ); 20842 array.push( parameters.sheenRoughnessMapUv ); 20843 array.push( parameters.specularMapUv ); 20844 array.push( parameters.specularColorMapUv ); 20845 array.push( parameters.specularIntensityMapUv ); 20846 array.push( parameters.transmissionMapUv ); 20847 array.push( parameters.thicknessMapUv ); 20848 array.push( parameters.combine ); 20849 array.push( parameters.fogExp2 ); 20850 array.push( parameters.sizeAttenuation ); 20851 array.push( parameters.morphTargetsCount ); 20852 array.push( parameters.morphAttributeCount ); 20853 array.push( parameters.numDirLights ); 20854 array.push( parameters.numPointLights ); 20855 array.push( parameters.numSpotLights ); 20856 array.push( parameters.numSpotLightMaps ); 20857 array.push( parameters.numHemiLights ); 20858 array.push( parameters.numRectAreaLights ); 20859 array.push( parameters.numDirLightShadows ); 20860 array.push( parameters.numPointLightShadows ); 20861 array.push( parameters.numSpotLightShadows ); 20862 array.push( parameters.numSpotLightShadowsWithMaps ); 20863 array.push( parameters.numLightProbes ); 20864 array.push( parameters.shadowMapType ); 20865 array.push( parameters.toneMapping ); 20866 array.push( parameters.numClippingPlanes ); 20867 array.push( parameters.numClipIntersection ); 20868 array.push( parameters.depthPacking ); 20869 20870 } 20871 20872 function getProgramCacheKeyBooleans( array, parameters ) { 20873 20874 _programLayers.disableAll(); 20875 20876 if ( parameters.supportsVertexTextures ) 20877 _programLayers.enable( 0 ); 20878 if ( parameters.instancing ) 20879 _programLayers.enable( 1 ); 20880 if ( parameters.instancingColor ) 20881 _programLayers.enable( 2 ); 20882 if ( parameters.instancingMorph ) 20883 _programLayers.enable( 3 ); 20884 if ( parameters.matcap ) 20885 _programLayers.enable( 4 ); 20886 if ( parameters.envMap ) 20887 _programLayers.enable( 5 ); 20888 if ( parameters.normalMapObjectSpace ) 20889 _programLayers.enable( 6 ); 20890 if ( parameters.normalMapTangentSpace ) 20891 _programLayers.enable( 7 ); 20892 if ( parameters.clearcoat ) 20893 _programLayers.enable( 8 ); 20894 if ( parameters.iridescence ) 20895 _programLayers.enable( 9 ); 20896 if ( parameters.alphaTest ) 20897 _programLayers.enable( 10 ); 20898 if ( parameters.vertexColors ) 20899 _programLayers.enable( 11 ); 20900 if ( parameters.vertexAlphas ) 20901 _programLayers.enable( 12 ); 20902 if ( parameters.vertexUv1s ) 20903 _programLayers.enable( 13 ); 20904 if ( parameters.vertexUv2s ) 20905 _programLayers.enable( 14 ); 20906 if ( parameters.vertexUv3s ) 20907 _programLayers.enable( 15 ); 20908 if ( parameters.vertexTangents ) 20909 _programLayers.enable( 16 ); 20910 if ( parameters.anisotropy ) 20911 _programLayers.enable( 17 ); 20912 if ( parameters.alphaHash ) 20913 _programLayers.enable( 18 ); 20914 if ( parameters.batching ) 20915 _programLayers.enable( 19 ); 20916 if ( parameters.dispersion ) 20917 _programLayers.enable( 20 ); 20918 if ( parameters.batchingColor ) 20919 _programLayers.enable( 21 ); 20920 20921 array.push( _programLayers.mask ); 20922 _programLayers.disableAll(); 20923 20924 if ( parameters.fog ) 20925 _programLayers.enable( 0 ); 20926 if ( parameters.useFog ) 20927 _programLayers.enable( 1 ); 20928 if ( parameters.flatShading ) 20929 _programLayers.enable( 2 ); 20930 if ( parameters.logarithmicDepthBuffer ) 20931 _programLayers.enable( 3 ); 20932 if ( parameters.skinning ) 20933 _programLayers.enable( 4 ); 20934 if ( parameters.morphTargets ) 20935 _programLayers.enable( 5 ); 20936 if ( parameters.morphNormals ) 20937 _programLayers.enable( 6 ); 20938 if ( parameters.morphColors ) 20939 _programLayers.enable( 7 ); 20940 if ( parameters.premultipliedAlpha ) 20941 _programLayers.enable( 8 ); 20942 if ( parameters.shadowMapEnabled ) 20943 _programLayers.enable( 9 ); 20944 if ( parameters.doubleSided ) 20945 _programLayers.enable( 10 ); 20946 if ( parameters.flipSided ) 20947 _programLayers.enable( 11 ); 20948 if ( parameters.useDepthPacking ) 20949 _programLayers.enable( 12 ); 20950 if ( parameters.dithering ) 20951 _programLayers.enable( 13 ); 20952 if ( parameters.transmission ) 20953 _programLayers.enable( 14 ); 20954 if ( parameters.sheen ) 20955 _programLayers.enable( 15 ); 20956 if ( parameters.opaque ) 20957 _programLayers.enable( 16 ); 20958 if ( parameters.pointsUvs ) 20959 _programLayers.enable( 17 ); 20960 if ( parameters.decodeVideoTexture ) 20961 _programLayers.enable( 18 ); 20962 if ( parameters.alphaToCoverage ) 20963 _programLayers.enable( 19 ); 20964 20965 array.push( _programLayers.mask ); 20966 20967 } 20968 20969 function getUniforms( material ) { 20970 20971 const shaderID = shaderIDs[ material.type ]; 20972 let uniforms; 20973 20974 if ( shaderID ) { 20975 20976 const shader = ShaderLib[ shaderID ]; 20977 uniforms = UniformsUtils.clone( shader.uniforms ); 20978 20979 } else { 20980 20981 uniforms = material.uniforms; 20982 20983 } 20984 20985 return uniforms; 20986 20987 } 20988 20989 function acquireProgram( parameters, cacheKey ) { 20990 20991 let program; 20992 20993 // Check if code has been already compiled 20994 for ( let p = 0, pl = programs.length; p < pl; p ++ ) { 20995 20996 const preexistingProgram = programs[ p ]; 20997 20998 if ( preexistingProgram.cacheKey === cacheKey ) { 20999 21000 program = preexistingProgram; 21001 ++ program.usedTimes; 21002 21003 break; 21004 21005 } 21006 21007 } 21008 21009 if ( program === undefined ) { 21010 21011 program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates ); 21012 programs.push( program ); 21013 21014 } 21015 21016 return program; 21017 21018 } 21019 21020 function releaseProgram( program ) { 21021 21022 if ( -- program.usedTimes === 0 ) { 21023 21024 // Remove from unordered set 21025 const i = programs.indexOf( program ); 21026 programs[ i ] = programs[ programs.length - 1 ]; 21027 programs.pop(); 21028 21029 // Free WebGL resources 21030 program.destroy(); 21031 21032 } 21033 21034 } 21035 21036 function releaseShaderCache( material ) { 21037 21038 _customShaders.remove( material ); 21039 21040 } 21041 21042 function dispose() { 21043 21044 _customShaders.dispose(); 21045 21046 } 21047 21048 return { 21049 getParameters: getParameters, 21050 getProgramCacheKey: getProgramCacheKey, 21051 getUniforms: getUniforms, 21052 acquireProgram: acquireProgram, 21053 releaseProgram: releaseProgram, 21054 releaseShaderCache: releaseShaderCache, 21055 // Exposed for resource monitoring & error feedback via renderer.info: 21056 programs: programs,
vendor: 4,538 bytes, lines 21057-21338
21057 dispose: dispose 21058 }; 21059 21060} 21061 21062function WebGLProperties() { 21063 21064 let properties = new WeakMap(); 21065 21066 function get( object ) { 21067 21068 let map = properties.get( object ); 21069 21070 if ( map === undefined ) { 21071 21072 map = {}; 21073 properties.set( object, map ); 21074 21075 } 21076 21077 return map; 21078 21079 } 21080 21081 function remove( object ) { 21082 21083 properties.delete( object ); 21084 21085 } 21086 21087 function update( object, key, value ) { 21088 21089 properties.get( object )[ key ] = value; 21090 21091 } 21092 21093 function dispose() { 21094 21095 properties = new WeakMap(); 21096 21097 } 21098 21099 return { 21100 get: get, 21101 remove: remove, 21102 update: update, 21103 dispose: dispose 21104 }; 21105 21106} 21107 21108function painterSortStable( a, b ) { 21109 21110 if ( a.groupOrder !== b.groupOrder ) { 21111 21112 return a.groupOrder - b.groupOrder; 21113 21114 } else if ( a.renderOrder !== b.renderOrder ) { 21115 21116 return a.renderOrder - b.renderOrder; 21117 21118 } else if ( a.material.id !== b.material.id ) { 21119 21120 return a.material.id - b.material.id; 21121 21122 } else if ( a.z !== b.z ) { 21123 21124 return a.z - b.z; 21125 21126 } else { 21127 21128 return a.id - b.id; 21129 21130 } 21131 21132} 21133 21134function reversePainterSortStable( a, b ) { 21135 21136 if ( a.groupOrder !== b.groupOrder ) { 21137 21138 return a.groupOrder - b.groupOrder; 21139 21140 } else if ( a.renderOrder !== b.renderOrder ) { 21141 21142 return a.renderOrder - b.renderOrder; 21143 21144 } else if ( a.z !== b.z ) { 21145 21146 return b.z - a.z; 21147 21148 } else { 21149 21150 return a.id - b.id; 21151 21152 } 21153 21154} 21155 21156 21157function WebGLRenderList() { 21158 21159 const renderItems = []; 21160 let renderItemsIndex = 0; 21161 21162 const opaque = []; 21163 const transmissive = []; 21164 const transparent = []; 21165 21166 function init() { 21167 21168 renderItemsIndex = 0; 21169 21170 opaque.length = 0; 21171 transmissive.length = 0; 21172 transparent.length = 0; 21173 21174 } 21175 21176 function getNextRenderItem( object, geometry, material, groupOrder, z, group ) { 21177 21178 let renderItem = renderItems[ renderItemsIndex ]; 21179 21180 if ( renderItem === undefined ) { 21181 21182 renderItem = { 21183 id: object.id, 21184 object: object, 21185 geometry: geometry, 21186 material: material, 21187 groupOrder: groupOrder, 21188 renderOrder: object.renderOrder, 21189 z: z, 21190 group: group 21191 }; 21192 21193 renderItems[ renderItemsIndex ] = renderItem; 21194 21195 } else { 21196 21197 renderItem.id = object.id; 21198 renderItem.object = object; 21199 renderItem.geometry = geometry; 21200 renderItem.material = material; 21201 renderItem.groupOrder = groupOrder; 21202 renderItem.renderOrder = object.renderOrder; 21203 renderItem.z = z; 21204 renderItem.group = group; 21205 21206 } 21207 21208 renderItemsIndex ++; 21209 21210 return renderItem; 21211 21212 } 21213 21214 function push( object, geometry, material, groupOrder, z, group ) { 21215 21216 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); 21217 21218 if ( material.transmission > 0.0 ) { 21219 21220 transmissive.push( renderItem ); 21221 21222 } else if ( material.transparent === true ) { 21223 21224 transparent.push( renderItem ); 21225 21226 } else { 21227 21228 opaque.push( renderItem ); 21229 21230 } 21231 21232 } 21233 21234 function unshift( object, geometry, material, groupOrder, z, group ) { 21235 21236 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); 21237 21238 if ( material.transmission > 0.0 ) { 21239 21240 transmissive.unshift( renderItem ); 21241 21242 } else if ( material.transparent === true ) { 21243 21244 transparent.unshift( renderItem ); 21245 21246 } else { 21247 21248 opaque.unshift( renderItem ); 21249 21250 } 21251 21252 } 21253 21254 function sort( customOpaqueSort, customTransparentSort ) { 21255 21256 if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable ); 21257 if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable ); 21258 if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable ); 21259 21260 } 21261 21262 function finish() { 21263 21264 // Clear references from inactive renderItems in the list 21265 21266 for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) { 21267 21268 const renderItem = renderItems[ i ]; 21269 21270 if ( renderItem.id === null ) break; 21271 21272 renderItem.id = null; 21273 renderItem.object = null; 21274 renderItem.geometry = null; 21275 renderItem.material = null; 21276 renderItem.group = null; 21277 21278 } 21279 21280 } 21281 21282 return { 21283 21284 opaque: opaque, 21285 transmissive: transmissive, 21286 transparent: transparent, 21287 21288 init: init, 21289 push: push, 21290 unshift: unshift, 21291 finish: finish, 21292 21293 sort: sort 21294 }; 21295 21296} 21297 21298function WebGLRenderLists() { 21299 21300 let lists = new WeakMap(); 21301 21302 function get( scene, renderCallDepth ) { 21303 21304 const listArray = lists.get( scene ); 21305 let list; 21306 21307 if ( listArray === undefined ) { 21308 21309 list = new WebGLRenderList(); 21310 lists.set( scene, [ list ] ); 21311 21312 } else { 21313 21314 if ( renderCallDepth >= listArray.length ) { 21315 21316 list = new WebGLRenderList(); 21317 listArray.push( list ); 21318 21319 } else { 21320 21321 list = listArray[ renderCallDepth ]; 21322 21323 } 21324 21325 } 21326 21327 return list; 21328 21329 } 21330 21331 function dispose() { 21332 21333 lists = new WeakMap(); 21334 21335 } 21336 21337 return { 21338 get: get,
vendor: 10,347 bytes, lines 21339-21798
21339 dispose: dispose 21340 }; 21341 21342} 21343 21344function UniformsCache() { 21345 21346 const lights = {}; 21347 21348 return { 21349 21350 get: function ( light ) { 21351 21352 if ( lights[ light.id ] !== undefined ) { 21353 21354 return lights[ light.id ]; 21355 21356 } 21357 21358 let uniforms; 21359 21360 switch ( light.type ) { 21361 21362 case 'DirectionalLight': 21363 uniforms = { 21364 direction: new Vector3(), 21365 color: new Color() 21366 }; 21367 break; 21368 21369 case 'SpotLight': 21370 uniforms = { 21371 position: new Vector3(), 21372 direction: new Vector3(), 21373 color: new Color(), 21374 distance: 0, 21375 coneCos: 0, 21376 penumbraCos: 0, 21377 decay: 0 21378 }; 21379 break; 21380 21381 case 'PointLight': 21382 uniforms = { 21383 position: new Vector3(), 21384 color: new Color(), 21385 distance: 0, 21386 decay: 0 21387 }; 21388 break; 21389 21390 case 'HemisphereLight': 21391 uniforms = { 21392 direction: new Vector3(), 21393 skyColor: new Color(), 21394 groundColor: new Color() 21395 }; 21396 break; 21397 21398 case 'RectAreaLight': 21399 uniforms = { 21400 color: new Color(), 21401 position: new Vector3(), 21402 halfWidth: new Vector3(), 21403 halfHeight: new Vector3() 21404 }; 21405 break; 21406 21407 } 21408 21409 lights[ light.id ] = uniforms; 21410 21411 return uniforms; 21412 21413 } 21414 21415 }; 21416 21417} 21418 21419function ShadowUniformsCache() { 21420 21421 const lights = {}; 21422 21423 return { 21424 21425 get: function ( light ) { 21426 21427 if ( lights[ light.id ] !== undefined ) { 21428 21429 return lights[ light.id ]; 21430 21431 } 21432 21433 let uniforms; 21434 21435 switch ( light.type ) { 21436 21437 case 'DirectionalLight': 21438 uniforms = { 21439 shadowBias: 0, 21440 shadowNormalBias: 0, 21441 shadowRadius: 1, 21442 shadowMapSize: new Vector2() 21443 }; 21444 break; 21445 21446 case 'SpotLight': 21447 uniforms = { 21448 shadowBias: 0, 21449 shadowNormalBias: 0, 21450 shadowRadius: 1, 21451 shadowMapSize: new Vector2() 21452 }; 21453 break; 21454 21455 case 'PointLight': 21456 uniforms = { 21457 shadowBias: 0, 21458 shadowNormalBias: 0, 21459 shadowRadius: 1, 21460 shadowMapSize: new Vector2(), 21461 shadowCameraNear: 1, 21462 shadowCameraFar: 1000 21463 }; 21464 break; 21465 21466 // TODO (abelnation): set RectAreaLight shadow uniforms 21467 21468 } 21469 21470 lights[ light.id ] = uniforms; 21471 21472 return uniforms; 21473 21474 } 21475 21476 }; 21477 21478} 21479 21480 21481 21482let nextVersion = 0; 21483 21484function shadowCastingAndTexturingLightsFirst( lightA, lightB ) { 21485 21486 return ( lightB.castShadow ? 2 : 0 ) - ( lightA.castShadow ? 2 : 0 ) + ( lightB.map ? 1 : 0 ) - ( lightA.map ? 1 : 0 ); 21487 21488} 21489 21490function WebGLLights( extensions ) { 21491 21492 const cache = new UniformsCache(); 21493 21494 const shadowCache = ShadowUniformsCache(); 21495 21496 const state = { 21497 21498 version: 0, 21499 21500 hash: { 21501 directionalLength: - 1, 21502 pointLength: - 1, 21503 spotLength: - 1, 21504 rectAreaLength: - 1, 21505 hemiLength: - 1, 21506 21507 numDirectionalShadows: - 1, 21508 numPointShadows: - 1, 21509 numSpotShadows: - 1, 21510 numSpotMaps: - 1, 21511 21512 numLightProbes: - 1 21513 }, 21514 21515 ambient: [ 0, 0, 0 ], 21516 probe: [], 21517 directional: [], 21518 directionalShadow: [], 21519 directionalShadowMap: [], 21520 directionalShadowMatrix: [], 21521 spot: [], 21522 spotLightMap: [], 21523 spotShadow: [], 21524 spotShadowMap: [], 21525 spotLightMatrix: [], 21526 rectArea: [], 21527 rectAreaLTC1: null, 21528 rectAreaLTC2: null, 21529 point: [], 21530 pointShadow: [], 21531 pointShadowMap: [], 21532 pointShadowMatrix: [], 21533 hemi: [], 21534 numSpotLightShadowsWithMaps: 0, 21535 numLightProbes: 0 21536 21537 }; 21538 21539 for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() ); 21540 21541 const vector3 = new Vector3(); 21542 const matrix4 = new Matrix4(); 21543 const matrix42 = new Matrix4(); 21544 21545 function setup( lights ) { 21546 21547 let r = 0, g = 0, b = 0; 21548 21549 for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 ); 21550 21551 let directionalLength = 0; 21552 let pointLength = 0; 21553 let spotLength = 0; 21554 let rectAreaLength = 0; 21555 let hemiLength = 0; 21556 21557 let numDirectionalShadows = 0; 21558 let numPointShadows = 0; 21559 let numSpotShadows = 0; 21560 let numSpotMaps = 0; 21561 let numSpotShadowsWithMaps = 0; 21562 21563 let numLightProbes = 0; 21564 21565 // ordering : [shadow casting + map texturing, map texturing, shadow casting, none ] 21566 lights.sort( shadowCastingAndTexturingLightsFirst ); 21567 21568 for ( let i = 0, l = lights.length; i < l; i ++ ) { 21569 21570 const light = lights[ i ]; 21571 21572 const color = light.color; 21573 const intensity = light.intensity; 21574 const distance = light.distance; 21575 21576 const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; 21577 21578 if ( light.isAmbientLight ) { 21579 21580 r += color.r * intensity; 21581 g += color.g * intensity; 21582 b += color.b * intensity; 21583 21584 } else if ( light.isLightProbe ) { 21585 21586 for ( let j = 0; j < 9; j ++ ) { 21587 21588 state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity ); 21589 21590 } 21591 21592 numLightProbes ++; 21593 21594 } else if ( light.isDirectionalLight ) { 21595 21596 const uniforms = cache.get( light ); 21597 21598 uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); 21599 21600 if ( light.castShadow ) { 21601 21602 const shadow = light.shadow; 21603 21604 const shadowUniforms = shadowCache.get( light ); 21605 21606 shadowUniforms.shadowBias = shadow.bias; 21607 shadowUniforms.shadowNormalBias = shadow.normalBias; 21608 shadowUniforms.shadowRadius = shadow.radius; 21609 shadowUniforms.shadowMapSize = shadow.mapSize; 21610 21611 state.directionalShadow[ directionalLength ] = shadowUniforms; 21612 state.directionalShadowMap[ directionalLength ] = shadowMap; 21613 state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; 21614 21615 numDirectionalShadows ++; 21616 21617 } 21618 21619 state.directional[ directionalLength ] = uniforms; 21620 21621 directionalLength ++; 21622 21623 } else if ( light.isSpotLight ) { 21624 21625 const uniforms = cache.get( light ); 21626 21627 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 21628 21629 uniforms.color.copy( color ).multiplyScalar( intensity ); 21630 uniforms.distance = distance; 21631 21632 uniforms.coneCos = Math.cos( light.angle ); 21633 uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); 21634 uniforms.decay = light.decay; 21635 21636 state.spot[ spotLength ] = uniforms; 21637 21638 const shadow = light.shadow; 21639 21640 if ( light.map ) { 21641 21642 state.spotLightMap[ numSpotMaps ] = light.map; 21643 numSpotMaps ++; 21644 21645 // make sure the lightMatrix is up to date 21646 // TODO : do it if required only 21647 shadow.updateMatrices( light ); 21648 21649 if ( light.castShadow ) numSpotShadowsWithMaps ++; 21650 21651 } 21652 21653 state.spotLightMatrix[ spotLength ] = shadow.matrix; 21654 21655 if ( light.castShadow ) { 21656 21657 const shadowUniforms = shadowCache.get( light ); 21658 21659 shadowUniforms.shadowBias = shadow.bias; 21660 shadowUniforms.shadowNormalBias = shadow.normalBias; 21661 shadowUniforms.shadowRadius = shadow.radius; 21662 shadowUniforms.shadowMapSize = shadow.mapSize; 21663 21664 state.spotShadow[ spotLength ] = shadowUniforms; 21665 state.spotShadowMap[ spotLength ] = shadowMap; 21666 21667 numSpotShadows ++; 21668 21669 } 21670 21671 spotLength ++; 21672 21673 } else if ( light.isRectAreaLight ) { 21674 21675 const uniforms = cache.get( light ); 21676 21677 uniforms.color.copy( color ).multiplyScalar( intensity ); 21678 21679 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); 21680 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); 21681 21682 state.rectArea[ rectAreaLength ] = uniforms; 21683 21684 rectAreaLength ++; 21685 21686 } else if ( light.isPointLight ) { 21687 21688 const uniforms = cache.get( light ); 21689 21690 uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); 21691 uniforms.distance = light.distance; 21692 uniforms.decay = light.decay; 21693 21694 if ( light.castShadow ) { 21695 21696 const shadow = light.shadow; 21697 21698 const shadowUniforms = shadowCache.get( light ); 21699 21700 shadowUniforms.shadowBias = shadow.bias; 21701 shadowUniforms.shadowNormalBias = shadow.normalBias; 21702 shadowUniforms.shadowRadius = shadow.radius; 21703 shadowUniforms.shadowMapSize = shadow.mapSize; 21704 shadowUniforms.shadowCameraNear = shadow.camera.near; 21705 shadowUniforms.shadowCameraFar = shadow.camera.far; 21706 21707 state.pointShadow[ pointLength ] = shadowUniforms; 21708 state.pointShadowMap[ pointLength ] = shadowMap; 21709 state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; 21710 21711 numPointShadows ++; 21712 21713 } 21714 21715 state.point[ pointLength ] = uniforms; 21716 21717 pointLength ++; 21718 21719 } else if ( light.isHemisphereLight ) { 21720 21721 const uniforms = cache.get( light ); 21722 21723 uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); 21724 uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); 21725 21726 state.hemi[ hemiLength ] = uniforms; 21727 21728 hemiLength ++; 21729 21730 } 21731 21732 } 21733 21734 if ( rectAreaLength > 0 ) { 21735 21736 if ( extensions.has( 'OES_texture_float_linear' ) === true ) { 21737 21738 state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1; 21739 state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2; 21740 21741 } else { 21742 21743 state.rectAreaLTC1 = UniformsLib.LTC_HALF_1; 21744 state.rectAreaLTC2 = UniformsLib.LTC_HALF_2; 21745 21746 } 21747 21748 } 21749 21750 state.ambient[ 0 ] = r; 21751 state.ambient[ 1 ] = g; 21752 state.ambient[ 2 ] = b; 21753 21754 const hash = state.hash; 21755 21756 if ( hash.directionalLength !== directionalLength || 21757 hash.pointLength !== pointLength || 21758 hash.spotLength !== spotLength || 21759 hash.rectAreaLength !== rectAreaLength || 21760 hash.hemiLength !== hemiLength || 21761 hash.numDirectionalShadows !== numDirectionalShadows || 21762 hash.numPointShadows !== numPointShadows || 21763 hash.numSpotShadows !== numSpotShadows || 21764 hash.numSpotMaps !== numSpotMaps || 21765 hash.numLightProbes !== numLightProbes ) { 21766 21767 state.directional.length = directionalLength; 21768 state.spot.length = spotLength; 21769 state.rectArea.length = rectAreaLength; 21770 state.point.length = pointLength; 21771 state.hemi.length = hemiLength; 21772 21773 state.directionalShadow.length = numDirectionalShadows; 21774 state.directionalShadowMap.length = numDirectionalShadows; 21775 state.pointShadow.length = numPointShadows; 21776 state.pointShadowMap.length = numPointShadows; 21777 state.spotShadow.length = numSpotShadows; 21778 state.spotShadowMap.length = numSpotShadows; 21779 state.directionalShadowMatrix.length = numDirectionalShadows; 21780 state.pointShadowMatrix.length = numPointShadows; 21781 state.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps; 21782 state.spotLightMap.length = numSpotMaps; 21783 state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps; 21784 state.numLightProbes = numLightProbes; 21785 21786 hash.directionalLength = directionalLength; 21787 hash.pointLength = pointLength; 21788 hash.spotLength = spotLength; 21789 hash.rectAreaLength = rectAreaLength; 21790 hash.hemiLength = hemiLength; 21791 21792 hash.numDirectionalShadows = numDirectionalShadows; 21793 hash.numPointShadows = numPointShadows; 21794 hash.numSpotShadows = numSpotShadows; 21795 hash.numSpotMaps = numSpotMaps; 21796 21797 hash.numLightProbes = numLightProbes; 21798
vendor: 4,329 bytes, lines 21799-22026
21799 state.version = nextVersion ++; 21800 21801 } 21802 21803 } 21804 21805 function setupView( lights, camera ) { 21806 21807 let directionalLength = 0; 21808 let pointLength = 0; 21809 let spotLength = 0; 21810 let rectAreaLength = 0; 21811 let hemiLength = 0; 21812 21813 const viewMatrix = camera.matrixWorldInverse; 21814 21815 for ( let i = 0, l = lights.length; i < l; i ++ ) { 21816 21817 const light = lights[ i ]; 21818 21819 if ( light.isDirectionalLight ) { 21820 21821 const uniforms = state.directional[ directionalLength ]; 21822 21823 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 21824 vector3.setFromMatrixPosition( light.target.matrixWorld ); 21825 uniforms.direction.sub( vector3 ); 21826 uniforms.direction.transformDirection( viewMatrix ); 21827 21828 directionalLength ++; 21829 21830 } else if ( light.isSpotLight ) { 21831 21832 const uniforms = state.spot[ spotLength ]; 21833 21834 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 21835 uniforms.position.applyMatrix4( viewMatrix ); 21836 21837 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 21838 vector3.setFromMatrixPosition( light.target.matrixWorld ); 21839 uniforms.direction.sub( vector3 ); 21840 uniforms.direction.transformDirection( viewMatrix ); 21841 21842 spotLength ++; 21843 21844 } else if ( light.isRectAreaLight ) { 21845 21846 const uniforms = state.rectArea[ rectAreaLength ]; 21847 21848 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 21849 uniforms.position.applyMatrix4( viewMatrix ); 21850 21851 // extract local rotation of light to derive width/height half vectors 21852 matrix42.identity(); 21853 matrix4.copy( light.matrixWorld ); 21854 matrix4.premultiply( viewMatrix ); 21855 matrix42.extractRotation( matrix4 ); 21856 21857 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); 21858 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); 21859 21860 uniforms.halfWidth.applyMatrix4( matrix42 ); 21861 uniforms.halfHeight.applyMatrix4( matrix42 ); 21862 21863 rectAreaLength ++; 21864 21865 } else if ( light.isPointLight ) { 21866 21867 const uniforms = state.point[ pointLength ]; 21868 21869 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 21870 uniforms.position.applyMatrix4( viewMatrix ); 21871 21872 pointLength ++; 21873 21874 } else if ( light.isHemisphereLight ) { 21875 21876 const uniforms = state.hemi[ hemiLength ]; 21877 21878 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 21879 uniforms.direction.transformDirection( viewMatrix ); 21880 21881 hemiLength ++; 21882 21883 } 21884 21885 } 21886 21887 } 21888 21889 return { 21890 setup: setup, 21891 setupView: setupView, 21892 state: state 21893 }; 21894 21895} 21896 21897function WebGLRenderState( extensions ) { 21898 21899 const lights = new WebGLLights( extensions ); 21900 21901 const lightsArray = []; 21902 const shadowsArray = []; 21903 21904 function init( camera ) { 21905 21906 state.camera = camera; 21907 21908 lightsArray.length = 0; 21909 shadowsArray.length = 0; 21910 21911 } 21912 21913 function pushLight( light ) { 21914 21915 lightsArray.push( light ); 21916 21917 } 21918 21919 function pushShadow( shadowLight ) { 21920 21921 shadowsArray.push( shadowLight ); 21922 21923 } 21924 21925 function setupLights() { 21926 21927 lights.setup( lightsArray ); 21928 21929 } 21930 21931 function setupLightsView( camera ) { 21932 21933 lights.setupView( lightsArray, camera ); 21934 21935 } 21936 21937 const state = { 21938 lightsArray: lightsArray, 21939 shadowsArray: shadowsArray, 21940 21941 camera: null, 21942 21943 lights: lights, 21944 21945 transmissionRenderTarget: {} 21946 }; 21947 21948 return { 21949 init: init, 21950 state: state, 21951 setupLights: setupLights, 21952 setupLightsView: setupLightsView, 21953 21954 pushLight: pushLight, 21955 pushShadow: pushShadow 21956 }; 21957 21958} 21959 21960function WebGLRenderStates( extensions ) { 21961 21962 let renderStates = new WeakMap(); 21963 21964 function get( scene, renderCallDepth = 0 ) { 21965 21966 const renderStateArray = renderStates.get( scene ); 21967 let renderState; 21968 21969 if ( renderStateArray === undefined ) { 21970 21971 renderState = new WebGLRenderState( extensions ); 21972 renderStates.set( scene, [ renderState ] ); 21973 21974 } else { 21975 21976 if ( renderCallDepth >= renderStateArray.length ) { 21977 21978 renderState = new WebGLRenderState( extensions ); 21979 renderStateArray.push( renderState ); 21980 21981 } else { 21982 21983 renderState = renderStateArray[ renderCallDepth ]; 21984 21985 } 21986 21987 } 21988 21989 return renderState; 21990 21991 } 21992 21993 function dispose() { 21994 21995 renderStates = new WeakMap(); 21996 21997 } 21998 21999 return { 22000 get: get, 22001 dispose: dispose 22002 }; 22003 22004} 22005 22006class MeshDepthMaterial extends Material { 22007 22008 constructor( parameters ) { 22009 22010 super(); 22011 22012 this.isMeshDepthMaterial = true; 22013 22014 this.type = 'MeshDepthMaterial'; 22015 22016 this.depthPacking = BasicDepthPacking; 22017 22018 this.map = null; 22019 22020 this.alphaMap = null; 22021 22022 this.displacementMap = null; 22023 this.displacementScale = 1; 22024 this.displacementBias = 0; 22025 22026 this.wireframe = false;
vendor: 10,058 bytes, lines 22027-22393
22027 this.wireframeLinewidth = 1; 22028 22029 this.setValues( parameters ); 22030 22031 } 22032 22033 copy( source ) { 22034 22035 super.copy( source ); 22036 22037 this.depthPacking = source.depthPacking; 22038 22039 this.map = source.map; 22040 22041 this.alphaMap = source.alphaMap; 22042 22043 this.displacementMap = source.displacementMap; 22044 this.displacementScale = source.displacementScale; 22045 this.displacementBias = source.displacementBias; 22046 22047 this.wireframe = source.wireframe; 22048 this.wireframeLinewidth = source.wireframeLinewidth; 22049 22050 return this; 22051 22052 } 22053 22054} 22055 22056class MeshDistanceMaterial extends Material { 22057 22058 constructor( parameters ) { 22059 22060 super(); 22061 22062 this.isMeshDistanceMaterial = true; 22063 22064 this.type = 'MeshDistanceMaterial'; 22065 22066 this.map = null; 22067 22068 this.alphaMap = null; 22069 22070 this.displacementMap = null; 22071 this.displacementScale = 1; 22072 this.displacementBias = 0; 22073 22074 this.setValues( parameters ); 22075 22076 } 22077 22078 copy( source ) { 22079 22080 super.copy( source ); 22081 22082 this.map = source.map; 22083 22084 this.alphaMap = source.alphaMap; 22085 22086 this.displacementMap = source.displacementMap; 22087 this.displacementScale = source.displacementScale; 22088 this.displacementBias = source.displacementBias; 22089 22090 return this; 22091 22092 } 22093 22094} 22095 22096const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}"; 22097 22098const 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}"; 22099 22100function WebGLShadowMap( renderer, objects, capabilities ) { 22101 22102 let _frustum = new Frustum(); 22103 22104 const _shadowMapSize = new Vector2(), 22105 _viewportSize = new Vector2(), 22106 22107 _viewport = new Vector4(), 22108 22109 _depthMaterial = new MeshDepthMaterial( { depthPacking: RGBADepthPacking } ), 22110 _distanceMaterial = new MeshDistanceMaterial(), 22111 22112 _materialCache = {}, 22113 22114 _maxTextureSize = capabilities.maxTextureSize; 22115 22116 const shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide }; 22117 22118 const shadowMaterialVertical = new ShaderMaterial( { 22119 defines: { 22120 VSM_SAMPLES: 8 22121 }, 22122 uniforms: { 22123 shadow_pass: { value: null }, 22124 resolution: { value: new Vector2() }, 22125 radius: { value: 4.0 } 22126 }, 22127 22128 vertexShader: vertex, 22129 fragmentShader: fragment 22130 22131 } ); 22132 22133 const shadowMaterialHorizontal = shadowMaterialVertical.clone(); 22134 shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1; 22135 22136 const fullScreenTri = new BufferGeometry(); 22137 fullScreenTri.setAttribute( 22138 'position', 22139 new BufferAttribute( 22140 new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ), 22141 3 22142 ) 22143 ); 22144 22145 const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical ); 22146 22147 const scope = this; 22148 22149 this.enabled = false; 22150 22151 this.autoUpdate = true; 22152 this.needsUpdate = false; 22153 22154 this.type = PCFShadowMap; 22155 let _previousType = this.type; 22156 22157 this.render = function ( lights, scene, camera ) { 22158 22159 if ( scope.enabled === false ) return; 22160 if ( scope.autoUpdate === false && scope.needsUpdate === false ) return; 22161 22162 if ( lights.length === 0 ) return; 22163 22164 const currentRenderTarget = renderer.getRenderTarget(); 22165 const activeCubeFace = renderer.getActiveCubeFace(); 22166 const activeMipmapLevel = renderer.getActiveMipmapLevel(); 22167 22168 const _state = renderer.state; 22169 22170 // Set GL state for depth map. 22171 _state.setBlending( NoBlending ); 22172 _state.buffers.color.setClear( 1, 1, 1, 1 ); 22173 _state.buffers.depth.setTest( true ); 22174 _state.setScissorTest( false ); 22175 22176 // check for shadow map type changes 22177 22178 const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap ); 22179 const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap ); 22180 22181 // render depth map 22182 22183 for ( let i = 0, il = lights.length; i < il; i ++ ) { 22184 22185 const light = lights[ i ]; 22186 const shadow = light.shadow; 22187 22188 if ( shadow === undefined ) { 22189 22190 console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); 22191 continue; 22192 22193 } 22194 22195 if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue; 22196 22197 _shadowMapSize.copy( shadow.mapSize ); 22198 22199 const shadowFrameExtents = shadow.getFrameExtents(); 22200 22201 _shadowMapSize.multiply( shadowFrameExtents ); 22202 22203 _viewportSize.copy( shadow.mapSize ); 22204 22205 if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) { 22206 22207 if ( _shadowMapSize.x > _maxTextureSize ) { 22208 22209 _viewportSize.x = Math.floor( _maxTextureSize / shadowFrameExtents.x ); 22210 _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x; 22211 shadow.mapSize.x = _viewportSize.x; 22212 22213 } 22214 22215 if ( _shadowMapSize.y > _maxTextureSize ) { 22216 22217 _viewportSize.y = Math.floor( _maxTextureSize / shadowFrameExtents.y ); 22218 _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y; 22219 shadow.mapSize.y = _viewportSize.y; 22220 22221 } 22222 22223 } 22224 22225 if ( shadow.map === null || toVSM === true || fromVSM === true ) { 22226 22227 const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; 22228 22229 if ( shadow.map !== null ) { 22230 22231 shadow.map.dispose(); 22232 22233 } 22234 22235 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); 22236 shadow.map.texture.name = light.name + '.shadowMap'; 22237 22238 shadow.camera.updateProjectionMatrix(); 22239 22240 } 22241 22242 renderer.setRenderTarget( shadow.map ); 22243 renderer.clear(); 22244 22245 const viewportCount = shadow.getViewportCount(); 22246 22247 for ( let vp = 0; vp < viewportCount; vp ++ ) { 22248 22249 const viewport = shadow.getViewport( vp ); 22250 22251 _viewport.set( 22252 _viewportSize.x * viewport.x, 22253 _viewportSize.y * viewport.y, 22254 _viewportSize.x * viewport.z, 22255 _viewportSize.y * viewport.w 22256 ); 22257 22258 _state.viewport( _viewport ); 22259 22260 shadow.updateMatrices( light, vp ); 22261 22262 _frustum = shadow.getFrustum(); 22263 22264 renderObject( scene, camera, shadow.camera, light, this.type ); 22265 22266 } 22267 22268 // do blur pass for VSM 22269 22270 if ( shadow.isPointLightShadow !== true && this.type === VSMShadowMap ) { 22271 22272 VSMPass( shadow, camera ); 22273 22274 } 22275 22276 shadow.needsUpdate = false; 22277 22278 } 22279 22280 _previousType = this.type; 22281 22282 scope.needsUpdate = false; 22283 22284 renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); 22285 22286 }; 22287 22288 function VSMPass( shadow, camera ) { 22289 22290 const geometry = objects.update( fullScreenMesh ); 22291 22292 if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) { 22293 22294 shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples; 22295 shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples; 22296 22297 shadowMaterialVertical.needsUpdate = true; 22298 shadowMaterialHorizontal.needsUpdate = true; 22299 22300 } 22301 22302 if ( shadow.mapPass === null ) { 22303 22304 shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y ); 22305 22306 } 22307 22308 // vertical pass 22309 22310 shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture; 22311 shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize; 22312 shadowMaterialVertical.uniforms.radius.value = shadow.radius; 22313 renderer.setRenderTarget( shadow.mapPass ); 22314 renderer.clear(); 22315 renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null ); 22316 22317 // horizontal pass 22318 22319 shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture; 22320 shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize; 22321 shadowMaterialHorizontal.uniforms.radius.value = shadow.radius; 22322 renderer.setRenderTarget( shadow.map ); 22323 renderer.clear(); 22324 renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null ); 22325 22326 } 22327 22328 function getDepthMaterial( object, material, light, type ) { 22329 22330 let result = null; 22331 22332 const customMaterial = ( light.isPointLight === true ) ? object.customDistanceMaterial : object.customDepthMaterial; 22333 22334 if ( customMaterial !== undefined ) { 22335 22336 result = customMaterial; 22337 22338 } else { 22339 22340 result = ( light.isPointLight === true ) ? _distanceMaterial : _depthMaterial; 22341 22342 if ( ( renderer.localClippingEnabled && material.clipShadows === true && Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) || 22343 ( material.displacementMap && material.displacementScale !== 0 ) || 22344 ( material.alphaMap && material.alphaTest > 0 ) || 22345 ( material.map && material.alphaTest > 0 ) ) { 22346 22347 // in this case we need a unique material instance reflecting the 22348 // appropriate state 22349 22350 const keyA = result.uuid, keyB = material.uuid; 22351 22352 let materialsForVariant = _materialCache[ keyA ]; 22353 22354 if ( materialsForVariant === undefined ) { 22355 22356 materialsForVariant = {}; 22357 _materialCache[ keyA ] = materialsForVariant; 22358 22359 } 22360 22361 let cachedMaterial = materialsForVariant[ keyB ]; 22362 22363 if ( cachedMaterial === undefined ) { 22364 22365 cachedMaterial = result.clone(); 22366 materialsForVariant[ keyB ] = cachedMaterial; 22367 material.addEventListener( 'dispose', onMaterialDispose ); 22368 22369 } 22370 22371 result = cachedMaterial; 22372 22373 } 22374 22375 } 22376 22377 result.visible = material.visible; 22378 result.wireframe = material.wireframe; 22379 22380 if ( type === VSMShadowMap ) { 22381 22382 result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side; 22383 22384 } else { 22385 22386 result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ]; 22387 22388 } 22389 22390 result.alphaMap = material.alphaMap; 22391 result.alphaTest = material.alphaTest; 22392 result.map = material.map; 22393
vendor: 12,973 bytes, lines 22394-23047
22394 result.clipShadows = material.clipShadows; 22395 result.clippingPlanes = material.clippingPlanes; 22396 result.clipIntersection = material.clipIntersection; 22397 22398 result.displacementMap = material.displacementMap; 22399 result.displacementScale = material.displacementScale; 22400 result.displacementBias = material.displacementBias; 22401 22402 result.wireframeLinewidth = material.wireframeLinewidth; 22403 result.linewidth = material.linewidth; 22404 22405 if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) { 22406 22407 const materialProperties = renderer.properties.get( result ); 22408 materialProperties.light = light; 22409 22410 } 22411 22412 return result; 22413 22414 } 22415 22416 function renderObject( object, camera, shadowCamera, light, type ) { 22417 22418 if ( object.visible === false ) return; 22419 22420 const visible = object.layers.test( camera.layers ); 22421 22422 if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { 22423 22424 if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { 22425 22426 object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); 22427 22428 const geometry = objects.update( object ); 22429 const material = object.material; 22430 22431 if ( Array.isArray( material ) ) { 22432 22433 const groups = geometry.groups; 22434 22435 for ( let k = 0, kl = groups.length; k < kl; k ++ ) { 22436 22437 const group = groups[ k ]; 22438 const groupMaterial = material[ group.materialIndex ]; 22439 22440 if ( groupMaterial && groupMaterial.visible ) { 22441 22442 const depthMaterial = getDepthMaterial( object, groupMaterial, light, type ); 22443 22444 object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); 22445 22446 renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); 22447 22448 object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); 22449 22450 } 22451 22452 } 22453 22454 } else if ( material.visible ) { 22455 22456 const depthMaterial = getDepthMaterial( object, material, light, type ); 22457 22458 object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); 22459 22460 renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); 22461 22462 object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); 22463 22464 } 22465 22466 } 22467 22468 } 22469 22470 const children = object.children; 22471 22472 for ( let i = 0, l = children.length; i < l; i ++ ) { 22473 22474 renderObject( children[ i ], camera, shadowCamera, light, type ); 22475 22476 } 22477 22478 } 22479 22480 function onMaterialDispose( event ) { 22481 22482 const material = event.target; 22483 22484 material.removeEventListener( 'dispose', onMaterialDispose ); 22485 22486 // make sure to remove the unique distance/depth materials used for shadow map rendering 22487 22488 for ( const id in _materialCache ) { 22489 22490 const cache = _materialCache[ id ]; 22491 22492 const uuid = event.target.uuid; 22493 22494 if ( uuid in cache ) { 22495 22496 const shadowMaterial = cache[ uuid ]; 22497 shadowMaterial.dispose(); 22498 delete cache[ uuid ]; 22499 22500 } 22501 22502 } 22503 22504 } 22505 22506} 22507 22508function WebGLState( gl ) { 22509 22510 function ColorBuffer() { 22511 22512 let locked = false; 22513 22514 const color = new Vector4(); 22515 let currentColorMask = null; 22516 const currentColorClear = new Vector4( 0, 0, 0, 0 ); 22517 22518 return { 22519 22520 setMask: function ( colorMask ) { 22521 22522 if ( currentColorMask !== colorMask && ! locked ) { 22523 22524 gl.colorMask( colorMask, colorMask, colorMask, colorMask ); 22525 currentColorMask = colorMask; 22526 22527 } 22528 22529 }, 22530 22531 setLocked: function ( lock ) { 22532 22533 locked = lock; 22534 22535 }, 22536 22537 setClear: function ( r, g, b, a, premultipliedAlpha ) { 22538 22539 if ( premultipliedAlpha === true ) { 22540 22541 r *= a; g *= a; b *= a; 22542 22543 } 22544 22545 color.set( r, g, b, a ); 22546 22547 if ( currentColorClear.equals( color ) === false ) { 22548 22549 gl.clearColor( r, g, b, a ); 22550 currentColorClear.copy( color ); 22551 22552 } 22553 22554 }, 22555 22556 reset: function () { 22557 22558 locked = false; 22559 22560 currentColorMask = null; 22561 currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state 22562 22563 } 22564 22565 }; 22566 22567 } 22568 22569 function DepthBuffer() { 22570 22571 let locked = false; 22572 22573 let currentDepthMask = null; 22574 let currentDepthFunc = null; 22575 let currentDepthClear = null; 22576 22577 return { 22578 22579 setTest: function ( depthTest ) { 22580 22581 if ( depthTest ) { 22582 22583 enable( gl.DEPTH_TEST ); 22584 22585 } else { 22586 22587 disable( gl.DEPTH_TEST ); 22588 22589 } 22590 22591 }, 22592 22593 setMask: function ( depthMask ) { 22594 22595 if ( currentDepthMask !== depthMask && ! locked ) { 22596 22597 gl.depthMask( depthMask ); 22598 currentDepthMask = depthMask; 22599 22600 } 22601 22602 }, 22603 22604 setFunc: function ( depthFunc ) { 22605 22606 if ( currentDepthFunc !== depthFunc ) { 22607 22608 switch ( depthFunc ) { 22609 22610 case NeverDepth: 22611 22612 gl.depthFunc( gl.NEVER ); 22613 break; 22614 22615 case AlwaysDepth: 22616 22617 gl.depthFunc( gl.ALWAYS ); 22618 break; 22619 22620 case LessDepth: 22621 22622 gl.depthFunc( gl.LESS ); 22623 break; 22624 22625 case LessEqualDepth: 22626 22627 gl.depthFunc( gl.LEQUAL ); 22628 break; 22629 22630 case EqualDepth: 22631 22632 gl.depthFunc( gl.EQUAL ); 22633 break; 22634 22635 case GreaterEqualDepth: 22636 22637 gl.depthFunc( gl.GEQUAL ); 22638 break; 22639 22640 case GreaterDepth: 22641 22642 gl.depthFunc( gl.GREATER ); 22643 break; 22644 22645 case NotEqualDepth: 22646 22647 gl.depthFunc( gl.NOTEQUAL ); 22648 break; 22649 22650 default: 22651 22652 gl.depthFunc( gl.LEQUAL ); 22653 22654 } 22655 22656 currentDepthFunc = depthFunc; 22657 22658 } 22659 22660 }, 22661 22662 setLocked: function ( lock ) { 22663 22664 locked = lock; 22665 22666 }, 22667 22668 setClear: function ( depth ) { 22669 22670 if ( currentDepthClear !== depth ) { 22671 22672 gl.clearDepth( depth ); 22673 currentDepthClear = depth; 22674 22675 } 22676 22677 }, 22678 22679 reset: function () { 22680 22681 locked = false; 22682 22683 currentDepthMask = null; 22684 currentDepthFunc = null; 22685 currentDepthClear = null; 22686 22687 } 22688 22689 }; 22690 22691 } 22692 22693 function StencilBuffer() { 22694 22695 let locked = false; 22696 22697 let currentStencilMask = null; 22698 let currentStencilFunc = null; 22699 let currentStencilRef = null; 22700 let currentStencilFuncMask = null; 22701 let currentStencilFail = null; 22702 let currentStencilZFail = null; 22703 let currentStencilZPass = null; 22704 let currentStencilClear = null; 22705 22706 return { 22707 22708 setTest: function ( stencilTest ) { 22709 22710 if ( ! locked ) { 22711 22712 if ( stencilTest ) { 22713 22714 enable( gl.STENCIL_TEST ); 22715 22716 } else { 22717 22718 disable( gl.STENCIL_TEST ); 22719 22720 } 22721 22722 } 22723 22724 }, 22725 22726 setMask: function ( stencilMask ) { 22727 22728 if ( currentStencilMask !== stencilMask && ! locked ) { 22729 22730 gl.stencilMask( stencilMask ); 22731 currentStencilMask = stencilMask; 22732 22733 } 22734 22735 }, 22736 22737 setFunc: function ( stencilFunc, stencilRef, stencilMask ) { 22738 22739 if ( currentStencilFunc !== stencilFunc || 22740 currentStencilRef !== stencilRef || 22741 currentStencilFuncMask !== stencilMask ) { 22742 22743 gl.stencilFunc( stencilFunc, stencilRef, stencilMask ); 22744 22745 currentStencilFunc = stencilFunc; 22746 currentStencilRef = stencilRef; 22747 currentStencilFuncMask = stencilMask; 22748 22749 } 22750 22751 }, 22752 22753 setOp: function ( stencilFail, stencilZFail, stencilZPass ) { 22754 22755 if ( currentStencilFail !== stencilFail || 22756 currentStencilZFail !== stencilZFail || 22757 currentStencilZPass !== stencilZPass ) { 22758 22759 gl.stencilOp( stencilFail, stencilZFail, stencilZPass ); 22760 22761 currentStencilFail = stencilFail; 22762 currentStencilZFail = stencilZFail; 22763 currentStencilZPass = stencilZPass; 22764 22765 } 22766 22767 }, 22768 22769 setLocked: function ( lock ) { 22770 22771 locked = lock; 22772 22773 }, 22774 22775 setClear: function ( stencil ) { 22776 22777 if ( currentStencilClear !== stencil ) { 22778 22779 gl.clearStencil( stencil ); 22780 currentStencilClear = stencil; 22781 22782 } 22783 22784 }, 22785 22786 reset: function () { 22787 22788 locked = false; 22789 22790 currentStencilMask = null; 22791 currentStencilFunc = null; 22792 currentStencilRef = null; 22793 currentStencilFuncMask = null; 22794 currentStencilFail = null; 22795 currentStencilZFail = null; 22796 currentStencilZPass = null; 22797 currentStencilClear = null; 22798 22799 } 22800 22801 }; 22802 22803 } 22804 22805 // 22806 22807 const colorBuffer = new ColorBuffer(); 22808 const depthBuffer = new DepthBuffer(); 22809 const stencilBuffer = new StencilBuffer(); 22810 22811 const uboBindings = new WeakMap(); 22812 const uboProgramMap = new WeakMap(); 22813 22814 let enabledCapabilities = {}; 22815 22816 let currentBoundFramebuffers = {}; 22817 let currentDrawbuffers = new WeakMap(); 22818 let defaultDrawbuffers = []; 22819 22820 let currentProgram = null; 22821 22822 let currentBlendingEnabled = false; 22823 let currentBlending = null; 22824 let currentBlendEquation = null; 22825 let currentBlendSrc = null; 22826 let currentBlendDst = null; 22827 let currentBlendEquationAlpha = null; 22828 let currentBlendSrcAlpha = null; 22829 let currentBlendDstAlpha = null; 22830 let currentBlendColor = new Color( 0, 0, 0 ); 22831 let currentBlendAlpha = 0; 22832 let currentPremultipledAlpha = false; 22833 22834 let currentFlipSided = null; 22835 let currentCullFace = null; 22836 22837 let currentLineWidth = null; 22838 22839 let currentPolygonOffsetFactor = null; 22840 let currentPolygonOffsetUnits = null; 22841 22842 const maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); 22843 22844 let lineWidthAvailable = false; 22845 let version = 0; 22846 const glVersion = gl.getParameter( gl.VERSION ); 22847 22848 if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) { 22849 22850 version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] ); 22851 lineWidthAvailable = ( version >= 1.0 ); 22852 22853 } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) { 22854 22855 version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] ); 22856 lineWidthAvailable = ( version >= 2.0 ); 22857 22858 } 22859 22860 let currentTextureSlot = null; 22861 let currentBoundTextures = {}; 22862 22863 const scissorParam = gl.getParameter( gl.SCISSOR_BOX ); 22864 const viewportParam = gl.getParameter( gl.VIEWPORT ); 22865 22866 const currentScissor = new Vector4().fromArray( scissorParam ); 22867 const currentViewport = new Vector4().fromArray( viewportParam ); 22868 22869 function createTexture( type, target, count, dimensions ) { 22870 22871 const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. 22872 const texture = gl.createTexture(); 22873 22874 gl.bindTexture( type, texture ); 22875 gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); 22876 gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); 22877 22878 for ( let i = 0; i < count; i ++ ) { 22879 22880 if ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) { 22881 22882 gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); 22883 22884 } else { 22885 22886 gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); 22887 22888 } 22889 22890 } 22891 22892 return texture; 22893 22894 } 22895 22896 const emptyTextures = {}; 22897 emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 ); 22898 emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 ); 22899 emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 ); 22900 emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 ); 22901 22902 // init 22903 22904 colorBuffer.setClear( 0, 0, 0, 1 ); 22905 depthBuffer.setClear( 1 ); 22906 stencilBuffer.setClear( 0 ); 22907 22908 enable( gl.DEPTH_TEST ); 22909 depthBuffer.setFunc( LessEqualDepth ); 22910 22911 setFlipSided( false ); 22912 setCullFace( CullFaceBack ); 22913 enable( gl.CULL_FACE ); 22914 22915 setBlending( NoBlending ); 22916 22917 // 22918 22919 function enable( id ) { 22920 22921 if ( enabledCapabilities[ id ] !== true ) { 22922 22923 gl.enable( id ); 22924 enabledCapabilities[ id ] = true; 22925 22926 } 22927 22928 } 22929 22930 function disable( id ) { 22931 22932 if ( enabledCapabilities[ id ] !== false ) { 22933 22934 gl.disable( id ); 22935 enabledCapabilities[ id ] = false; 22936 22937 } 22938 22939 } 22940 22941 function bindFramebuffer( target, framebuffer ) { 22942 22943 if ( currentBoundFramebuffers[ target ] !== framebuffer ) { 22944 22945 gl.bindFramebuffer( target, framebuffer ); 22946 22947 currentBoundFramebuffers[ target ] = framebuffer; 22948 22949 // gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER 22950 22951 if ( target === gl.DRAW_FRAMEBUFFER ) { 22952 22953 currentBoundFramebuffers[ gl.FRAMEBUFFER ] = framebuffer; 22954 22955 } 22956 22957 if ( target === gl.FRAMEBUFFER ) { 22958 22959 currentBoundFramebuffers[ gl.DRAW_FRAMEBUFFER ] = framebuffer; 22960 22961 } 22962 22963 return true; 22964 22965 } 22966 22967 return false; 22968 22969 } 22970 22971 function drawBuffers( renderTarget, framebuffer ) { 22972 22973 let drawBuffers = defaultDrawbuffers; 22974 22975 let needsUpdate = false; 22976 22977 if ( renderTarget ) { 22978 22979 drawBuffers = currentDrawbuffers.get( framebuffer ); 22980 22981 if ( drawBuffers === undefined ) { 22982 22983 drawBuffers = []; 22984 currentDrawbuffers.set( framebuffer, drawBuffers ); 22985 22986 } 22987 22988 const textures = renderTarget.textures; 22989 22990 if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) { 22991 22992 for ( let i = 0, il = textures.length; i < il; i ++ ) { 22993 22994 drawBuffers[ i ] = gl.COLOR_ATTACHMENT0 + i; 22995 22996 } 22997 22998 drawBuffers.length = textures.length; 22999 23000 needsUpdate = true; 23001 23002 } 23003 23004 } else { 23005 23006 if ( drawBuffers[ 0 ] !== gl.BACK ) { 23007 23008 drawBuffers[ 0 ] = gl.BACK; 23009 23010 needsUpdate = true; 23011 23012 } 23013 23014 } 23015 23016 if ( needsUpdate ) { 23017 23018 gl.drawBuffers( drawBuffers ); 23019 23020 } 23021 23022 } 23023 23024 function useProgram( program ) { 23025 23026 if ( currentProgram !== program ) { 23027 23028 gl.useProgram( program ); 23029 23030 currentProgram = program; 23031 23032 return true; 23033 23034 } 23035 23036 return false; 23037 23038 } 23039 23040 const equationToGL = { 23041 [ AddEquation ]: gl.FUNC_ADD, 23042 [ SubtractEquation ]: gl.FUNC_SUBTRACT, 23043 [ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT 23044 }; 23045 23046 equationToGL[ MinEquation ] = gl.MIN; 23047 equationToGL[ MaxEquation ] = gl.MAX;
vendor: 12,328 bytes, lines 23047-23670
23047 23048 23049 const factorToGL = { 23050 [ ZeroFactor ]: gl.ZERO, 23051 [ OneFactor ]: gl.ONE, 23052 [ SrcColorFactor ]: gl.SRC_COLOR, 23053 [ SrcAlphaFactor ]: gl.SRC_ALPHA, 23054 [ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE, 23055 [ DstColorFactor ]: gl.DST_COLOR, 23056 [ DstAlphaFactor ]: gl.DST_ALPHA, 23057 [ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR, 23058 [ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA, 23059 [ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR, 23060 [ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA, 23061 [ ConstantColorFactor ]: gl.CONSTANT_COLOR, 23062 [ OneMinusConstantColorFactor ]: gl.ONE_MINUS_CONSTANT_COLOR, 23063 [ ConstantAlphaFactor ]: gl.CONSTANT_ALPHA, 23064 [ OneMinusConstantAlphaFactor ]: gl.ONE_MINUS_CONSTANT_ALPHA 23065 }; 23066 23067 function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, blendColor, blendAlpha, premultipliedAlpha ) { 23068 23069 if ( blending === NoBlending ) { 23070 23071 if ( currentBlendingEnabled === true ) { 23072 23073 disable( gl.BLEND ); 23074 currentBlendingEnabled = false; 23075 23076 } 23077 23078 return; 23079 23080 } 23081 23082 if ( currentBlendingEnabled === false ) { 23083 23084 enable( gl.BLEND ); 23085 currentBlendingEnabled = true; 23086 23087 } 23088 23089 if ( blending !== CustomBlending ) { 23090 23091 if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { 23092 23093 if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) { 23094 23095 gl.blendEquation( gl.FUNC_ADD ); 23096 23097 currentBlendEquation = AddEquation; 23098 currentBlendEquationAlpha = AddEquation; 23099 23100 } 23101 23102 if ( premultipliedAlpha ) { 23103 23104 switch ( blending ) { 23105 23106 case NormalBlending: 23107 gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); 23108 break; 23109 23110 case AdditiveBlending: 23111 gl.blendFunc( gl.ONE, gl.ONE ); 23112 break; 23113 23114 case SubtractiveBlending: 23115 gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); 23116 break; 23117 23118 case MultiplyBlending: 23119 gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); 23120 break; 23121 23122 default: 23123 console.error( 'THREE.WebGLState: Invalid blending: ', blending ); 23124 break; 23125 23126 } 23127 23128 } else { 23129 23130 switch ( blending ) { 23131 23132 case NormalBlending: 23133 gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); 23134 break; 23135 23136 case AdditiveBlending: 23137 gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); 23138 break; 23139 23140 case SubtractiveBlending: 23141 gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); 23142 break; 23143 23144 case MultiplyBlending: 23145 gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); 23146 break; 23147 23148 default: 23149 console.error( 'THREE.WebGLState: Invalid blending: ', blending ); 23150 break; 23151 23152 } 23153 23154 } 23155 23156 currentBlendSrc = null; 23157 currentBlendDst = null; 23158 currentBlendSrcAlpha = null; 23159 currentBlendDstAlpha = null; 23160 currentBlendColor.set( 0, 0, 0 ); 23161 currentBlendAlpha = 0; 23162 23163 currentBlending = blending; 23164 currentPremultipledAlpha = premultipliedAlpha; 23165 23166 } 23167 23168 return; 23169 23170 } 23171 23172 // custom blending 23173 23174 blendEquationAlpha = blendEquationAlpha || blendEquation; 23175 blendSrcAlpha = blendSrcAlpha || blendSrc; 23176 blendDstAlpha = blendDstAlpha || blendDst; 23177 23178 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { 23179 23180 gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] ); 23181 23182 currentBlendEquation = blendEquation; 23183 currentBlendEquationAlpha = blendEquationAlpha; 23184 23185 } 23186 23187 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { 23188 23189 gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] ); 23190 23191 currentBlendSrc = blendSrc; 23192 currentBlendDst = blendDst; 23193 currentBlendSrcAlpha = blendSrcAlpha; 23194 currentBlendDstAlpha = blendDstAlpha; 23195 23196 } 23197 23198 if ( blendColor.equals( currentBlendColor ) === false || blendAlpha !== currentBlendAlpha ) { 23199 23200 gl.blendColor( blendColor.r, blendColor.g, blendColor.b, blendAlpha ); 23201 23202 currentBlendColor.copy( blendColor ); 23203 currentBlendAlpha = blendAlpha; 23204 23205 } 23206 23207 currentBlending = blending; 23208 currentPremultipledAlpha = false; 23209 23210 } 23211 23212 function setMaterial( material, frontFaceCW ) { 23213 23214 material.side === DoubleSide 23215 ? disable( gl.CULL_FACE ) 23216 : enable( gl.CULL_FACE ); 23217 23218 let flipSided = ( material.side === BackSide ); 23219 if ( frontFaceCW ) flipSided = ! flipSided; 23220 23221 setFlipSided( flipSided ); 23222 23223 ( material.blending === NormalBlending && material.transparent === false ) 23224 ? setBlending( NoBlending ) 23225 : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.blendColor, material.blendAlpha, material.premultipliedAlpha ); 23226 23227 depthBuffer.setFunc( material.depthFunc ); 23228 depthBuffer.setTest( material.depthTest ); 23229 depthBuffer.setMask( material.depthWrite ); 23230 colorBuffer.setMask( material.colorWrite ); 23231 23232 const stencilWrite = material.stencilWrite; 23233 stencilBuffer.setTest( stencilWrite ); 23234 if ( stencilWrite ) { 23235 23236 stencilBuffer.setMask( material.stencilWriteMask ); 23237 stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask ); 23238 stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass ); 23239 23240 } 23241 23242 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); 23243 23244 material.alphaToCoverage === true 23245 ? enable( gl.SAMPLE_ALPHA_TO_COVERAGE ) 23246 : disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); 23247 23248 } 23249 23250 // 23251 23252 function setFlipSided( flipSided ) { 23253 23254 if ( currentFlipSided !== flipSided ) { 23255 23256 if ( flipSided ) { 23257 23258 gl.frontFace( gl.CW ); 23259 23260 } else { 23261 23262 gl.frontFace( gl.CCW ); 23263 23264 } 23265 23266 currentFlipSided = flipSided; 23267 23268 } 23269 23270 } 23271 23272 function setCullFace( cullFace ) { 23273 23274 if ( cullFace !== CullFaceNone ) { 23275 23276 enable( gl.CULL_FACE ); 23277 23278 if ( cullFace !== currentCullFace ) { 23279 23280 if ( cullFace === CullFaceBack ) { 23281 23282 gl.cullFace( gl.BACK ); 23283 23284 } else if ( cullFace === CullFaceFront ) { 23285 23286 gl.cullFace( gl.FRONT ); 23287 23288 } else { 23289 23290 gl.cullFace( gl.FRONT_AND_BACK ); 23291 23292 } 23293 23294 } 23295 23296 } else { 23297 23298 disable( gl.CULL_FACE ); 23299 23300 } 23301 23302 currentCullFace = cullFace; 23303 23304 } 23305 23306 function setLineWidth( width ) { 23307 23308 if ( width !== currentLineWidth ) { 23309 23310 if ( lineWidthAvailable ) gl.lineWidth( width ); 23311 23312 currentLineWidth = width; 23313 23314 } 23315 23316 } 23317 23318 function setPolygonOffset( polygonOffset, factor, units ) { 23319 23320 if ( polygonOffset ) { 23321 23322 enable( gl.POLYGON_OFFSET_FILL ); 23323 23324 if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { 23325 23326 gl.polygonOffset( factor, units ); 23327 23328 currentPolygonOffsetFactor = factor; 23329 currentPolygonOffsetUnits = units; 23330 23331 } 23332 23333 } else { 23334 23335 disable( gl.POLYGON_OFFSET_FILL ); 23336 23337 } 23338 23339 } 23340 23341 function setScissorTest( scissorTest ) { 23342 23343 if ( scissorTest ) { 23344 23345 enable( gl.SCISSOR_TEST ); 23346 23347 } else { 23348 23349 disable( gl.SCISSOR_TEST ); 23350 23351 } 23352 23353 } 23354 23355 // texture 23356 23357 function activeTexture( webglSlot ) { 23358 23359 if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1; 23360 23361 if ( currentTextureSlot !== webglSlot ) { 23362 23363 gl.activeTexture( webglSlot ); 23364 currentTextureSlot = webglSlot; 23365 23366 } 23367 23368 } 23369 23370 function bindTexture( webglType, webglTexture, webglSlot ) { 23371 23372 if ( webglSlot === undefined ) { 23373 23374 if ( currentTextureSlot === null ) { 23375 23376 webglSlot = gl.TEXTURE0 + maxTextures - 1; 23377 23378 } else { 23379 23380 webglSlot = currentTextureSlot; 23381 23382 } 23383 23384 } 23385 23386 let boundTexture = currentBoundTextures[ webglSlot ]; 23387 23388 if ( boundTexture === undefined ) { 23389 23390 boundTexture = { type: undefined, texture: undefined }; 23391 currentBoundTextures[ webglSlot ] = boundTexture; 23392 23393 } 23394 23395 if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { 23396 23397 if ( currentTextureSlot !== webglSlot ) { 23398 23399 gl.activeTexture( webglSlot ); 23400 currentTextureSlot = webglSlot; 23401 23402 } 23403 23404 gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] ); 23405 23406 boundTexture.type = webglType; 23407 boundTexture.texture = webglTexture; 23408 23409 } 23410 23411 } 23412 23413 function unbindTexture() { 23414 23415 const boundTexture = currentBoundTextures[ currentTextureSlot ]; 23416 23417 if ( boundTexture !== undefined && boundTexture.type !== undefined ) { 23418 23419 gl.bindTexture( boundTexture.type, null ); 23420 23421 boundTexture.type = undefined; 23422 boundTexture.texture = undefined; 23423 23424 } 23425 23426 } 23427 23428 function compressedTexImage2D() { 23429 23430 try { 23431 23432 gl.compressedTexImage2D.apply( gl, arguments ); 23433 23434 } catch ( error ) { 23435 23436 console.error( 'THREE.WebGLState:', error ); 23437 23438 } 23439 23440 } 23441 23442 function compressedTexImage3D() { 23443 23444 try { 23445 23446 gl.compressedTexImage3D.apply( gl, arguments ); 23447 23448 } catch ( error ) { 23449 23450 console.error( 'THREE.WebGLState:', error ); 23451 23452 } 23453 23454 } 23455 23456 function texSubImage2D() { 23457 23458 try { 23459 23460 gl.texSubImage2D.apply( gl, arguments ); 23461 23462 } catch ( error ) { 23463 23464 console.error( 'THREE.WebGLState:', error ); 23465 23466 } 23467 23468 } 23469 23470 function texSubImage3D() { 23471 23472 try { 23473 23474 gl.texSubImage3D.apply( gl, arguments ); 23475 23476 } catch ( error ) { 23477 23478 console.error( 'THREE.WebGLState:', error ); 23479 23480 } 23481 23482 } 23483 23484 function compressedTexSubImage2D() { 23485 23486 try { 23487 23488 gl.compressedTexSubImage2D.apply( gl, arguments ); 23489 23490 } catch ( error ) { 23491 23492 console.error( 'THREE.WebGLState:', error ); 23493 23494 } 23495 23496 } 23497 23498 function compressedTexSubImage3D() { 23499 23500 try { 23501 23502 gl.compressedTexSubImage3D.apply( gl, arguments ); 23503 23504 } catch ( error ) { 23505 23506 console.error( 'THREE.WebGLState:', error ); 23507 23508 } 23509 23510 } 23511 23512 function texStorage2D() { 23513 23514 try { 23515 23516 gl.texStorage2D.apply( gl, arguments ); 23517 23518 } catch ( error ) { 23519 23520 console.error( 'THREE.WebGLState:', error ); 23521 23522 } 23523 23524 } 23525 23526 function texStorage3D() { 23527 23528 try { 23529 23530 gl.texStorage3D.apply( gl, arguments ); 23531 23532 } catch ( error ) { 23533 23534 console.error( 'THREE.WebGLState:', error ); 23535 23536 } 23537 23538 } 23539 23540 function texImage2D() { 23541 23542 try { 23543 23544 gl.texImage2D.apply( gl, arguments ); 23545 23546 } catch ( error ) { 23547 23548 console.error( 'THREE.WebGLState:', error ); 23549 23550 } 23551 23552 } 23553 23554 function texImage3D() { 23555 23556 try { 23557 23558 gl.texImage3D.apply( gl, arguments ); 23559 23560 } catch ( error ) { 23561 23562 console.error( 'THREE.WebGLState:', error ); 23563 23564 } 23565 23566 } 23567 23568 // 23569 23570 function scissor( scissor ) { 23571 23572 if ( currentScissor.equals( scissor ) === false ) { 23573 23574 gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w ); 23575 currentScissor.copy( scissor ); 23576 23577 } 23578 23579 } 23580 23581 function viewport( viewport ) { 23582 23583 if ( currentViewport.equals( viewport ) === false ) { 23584 23585 gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w ); 23586 currentViewport.copy( viewport ); 23587 23588 } 23589 23590 } 23591 23592 function updateUBOMapping( uniformsGroup, program ) { 23593 23594 let mapping = uboProgramMap.get( program ); 23595 23596 if ( mapping === undefined ) { 23597 23598 mapping = new WeakMap(); 23599 23600 uboProgramMap.set( program, mapping ); 23601 23602 } 23603 23604 let blockIndex = mapping.get( uniformsGroup ); 23605 23606 if ( blockIndex === undefined ) { 23607 23608 blockIndex = gl.getUniformBlockIndex( program, uniformsGroup.name ); 23609 23610 mapping.set( uniformsGroup, blockIndex ); 23611 23612 } 23613 23614 } 23615 23616 function uniformBlockBinding( uniformsGroup, program ) { 23617 23618 const mapping = uboProgramMap.get( program ); 23619 const blockIndex = mapping.get( uniformsGroup ); 23620 23621 if ( uboBindings.get( program ) !== blockIndex ) { 23622 23623 // bind shader specific block index to global block point 23624 gl.uniformBlockBinding( program, blockIndex, uniformsGroup.__bindingPointIndex ); 23625 23626 uboBindings.set( program, blockIndex ); 23627 23628 } 23629 23630 } 23631 23632 // 23633 23634 function reset() { 23635 23636 // reset state 23637 23638 gl.disable( gl.BLEND ); 23639 gl.disable( gl.CULL_FACE ); 23640 gl.disable( gl.DEPTH_TEST ); 23641 gl.disable( gl.POLYGON_OFFSET_FILL ); 23642 gl.disable( gl.SCISSOR_TEST ); 23643 gl.disable( gl.STENCIL_TEST ); 23644 gl.disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); 23645 23646 gl.blendEquation( gl.FUNC_ADD ); 23647 gl.blendFunc( gl.ONE, gl.ZERO ); 23648 gl.blendFuncSeparate( gl.ONE, gl.ZERO, gl.ONE, gl.ZERO ); 23649 gl.blendColor( 0, 0, 0, 0 ); 23650 23651 gl.colorMask( true, true, true, true ); 23652 gl.clearColor( 0, 0, 0, 0 ); 23653 23654 gl.depthMask( true ); 23655 gl.depthFunc( gl.LESS ); 23656 gl.clearDepth( 1 ); 23657 23658 gl.stencilMask( 0xffffffff ); 23659 gl.stencilFunc( gl.ALWAYS, 0, 0xffffffff ); 23660 gl.stencilOp( gl.KEEP, gl.KEEP, gl.KEEP ); 23661 gl.clearStencil( 0 ); 23662 23663 gl.cullFace( gl.BACK ); 23664 gl.frontFace( gl.CCW ); 23665 23666 gl.polygonOffset( 0, 0 ); 23667 23668 gl.activeTexture( gl.TEXTURE0 ); 23669 23670 gl.bindFramebuffer( gl.FRAMEBUFFER, null );
vendor: 9,248 bytes, lines 23671-24014
23671 gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null ); 23672 gl.bindFramebuffer( gl.READ_FRAMEBUFFER, null ); 23673 23674 gl.useProgram( null ); 23675 23676 gl.lineWidth( 1 ); 23677 23678 gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height ); 23679 gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height ); 23680 23681 // reset internals 23682 23683 enabledCapabilities = {}; 23684 23685 currentTextureSlot = null; 23686 currentBoundTextures = {}; 23687 23688 currentBoundFramebuffers = {}; 23689 currentDrawbuffers = new WeakMap(); 23690 defaultDrawbuffers = []; 23691 23692 currentProgram = null; 23693 23694 currentBlendingEnabled = false; 23695 currentBlending = null; 23696 currentBlendEquation = null; 23697 currentBlendSrc = null; 23698 currentBlendDst = null; 23699 currentBlendEquationAlpha = null; 23700 currentBlendSrcAlpha = null; 23701 currentBlendDstAlpha = null; 23702 currentBlendColor = new Color( 0, 0, 0 ); 23703 currentBlendAlpha = 0; 23704 currentPremultipledAlpha = false; 23705 23706 currentFlipSided = null; 23707 currentCullFace = null; 23708 23709 currentLineWidth = null; 23710 23711 currentPolygonOffsetFactor = null; 23712 currentPolygonOffsetUnits = null; 23713 23714 currentScissor.set( 0, 0, gl.canvas.width, gl.canvas.height ); 23715 currentViewport.set( 0, 0, gl.canvas.width, gl.canvas.height ); 23716 23717 colorBuffer.reset(); 23718 depthBuffer.reset(); 23719 stencilBuffer.reset(); 23720 23721 } 23722 23723 return { 23724 23725 buffers: { 23726 color: colorBuffer, 23727 depth: depthBuffer, 23728 stencil: stencilBuffer 23729 }, 23730 23731 enable: enable, 23732 disable: disable, 23733 23734 bindFramebuffer: bindFramebuffer, 23735 drawBuffers: drawBuffers, 23736 23737 useProgram: useProgram, 23738 23739 setBlending: setBlending, 23740 setMaterial: setMaterial, 23741 23742 setFlipSided: setFlipSided, 23743 setCullFace: setCullFace, 23744 23745 setLineWidth: setLineWidth, 23746 setPolygonOffset: setPolygonOffset, 23747 23748 setScissorTest: setScissorTest, 23749 23750 activeTexture: activeTexture, 23751 bindTexture: bindTexture, 23752 unbindTexture: unbindTexture, 23753 compressedTexImage2D: compressedTexImage2D, 23754 compressedTexImage3D: compressedTexImage3D, 23755 texImage2D: texImage2D, 23756 texImage3D: texImage3D, 23757 23758 updateUBOMapping: updateUBOMapping, 23759 uniformBlockBinding: uniformBlockBinding, 23760 23761 texStorage2D: texStorage2D, 23762 texStorage3D: texStorage3D, 23763 texSubImage2D: texSubImage2D, 23764 texSubImage3D: texSubImage3D, 23765 compressedTexSubImage2D: compressedTexSubImage2D, 23766 compressedTexSubImage3D: compressedTexSubImage3D, 23767 23768 scissor: scissor, 23769 viewport: viewport, 23770 23771 reset: reset 23772 23773 }; 23774 23775} 23776 23777function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) { 23778 23779 const multisampledRTTExt = extensions.has( 'WEBGL_multisampled_render_to_texture' ) ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : null; 23780 const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test( navigator.userAgent ); 23781 23782 const _imageDimensions = new Vector2(); 23783 const _videoTextures = new WeakMap(); 23784 let _canvas; 23785 23786 const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source 23787 23788 // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas, 23789 // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")! 23790 // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d). 23791 23792 let useOffscreenCanvas = false; 23793 23794 try { 23795 23796 useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' 23797 // eslint-disable-next-line compat/compat 23798 && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null; 23799 23800 } catch ( err ) { 23801 23802 // Ignore any errors 23803 23804 } 23805 23806 function createCanvas( width, height ) { 23807 23808 // Use OffscreenCanvas when available. Specially needed in web workers 23809 23810 return useOffscreenCanvas ? 23811 // eslint-disable-next-line compat/compat 23812 new OffscreenCanvas( width, height ) : createElementNS( 'canvas' ); 23813 23814 } 23815 23816 function resizeImage( image, needsNewCanvas, maxSize ) { 23817 23818 let scale = 1; 23819 23820 const dimensions = getDimensions( image ); 23821 23822 // handle case if texture exceeds max size 23823 23824 if ( dimensions.width > maxSize || dimensions.height > maxSize ) { 23825 23826 scale = maxSize / Math.max( dimensions.width, dimensions.height ); 23827 23828 } 23829 23830 // only perform resize if necessary 23831 23832 if ( scale < 1 ) { 23833 23834 // only perform resize for certain image types 23835 23836 if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || 23837 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || 23838 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) || 23839 ( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) ) { 23840 23841 const width = Math.floor( scale * dimensions.width ); 23842 const height = Math.floor( scale * dimensions.height ); 23843 23844 if ( _canvas === undefined ) _canvas = createCanvas( width, height ); 23845 23846 // cube textures can't reuse the same canvas 23847 23848 const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas; 23849 23850 canvas.width = width; 23851 canvas.height = height; 23852 23853 const context = canvas.getContext( '2d' ); 23854 context.drawImage( image, 0, 0, width, height ); 23855 23856 console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + dimensions.width + 'x' + dimensions.height + ') to (' + width + 'x' + height + ').' ); 23857 23858 return canvas; 23859 23860 } else { 23861 23862 if ( 'data' in image ) { 23863 23864 console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + dimensions.width + 'x' + dimensions.height + ').' ); 23865 23866 } 23867 23868 return image; 23869 23870 } 23871 23872 } 23873 23874 return image; 23875 23876 } 23877 23878 function textureNeedsGenerateMipmaps( texture ) { 23879 23880 return texture.generateMipmaps && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; 23881 23882 } 23883 23884 function generateMipmap( target ) { 23885 23886 _gl.generateMipmap( target ); 23887 23888 } 23889 23890 function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { 23891 23892 if ( internalFormatName !== null ) { 23893 23894 if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ]; 23895 23896 console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' ); 23897 23898 } 23899 23900 let internalFormat = glFormat; 23901 23902 if ( glFormat === _gl.RED ) { 23903 23904 if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F; 23905 if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F; 23906 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8; 23907 23908 } 23909 23910 if ( glFormat === _gl.RED_INTEGER ) { 23911 23912 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8UI; 23913 if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.R16UI; 23914 if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.R32UI; 23915 if ( glType === _gl.BYTE ) internalFormat = _gl.R8I; 23916 if ( glType === _gl.SHORT ) internalFormat = _gl.R16I; 23917 if ( glType === _gl.INT ) internalFormat = _gl.R32I; 23918 23919 } 23920 23921 if ( glFormat === _gl.RG ) { 23922 23923 if ( glType === _gl.FLOAT ) internalFormat = _gl.RG32F; 23924 if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RG16F; 23925 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8; 23926 23927 } 23928 23929 if ( glFormat === _gl.RG_INTEGER ) { 23930 23931 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8UI; 23932 if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.RG16UI; 23933 if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.RG32UI; 23934 if ( glType === _gl.BYTE ) internalFormat = _gl.RG8I; 23935 if ( glType === _gl.SHORT ) internalFormat = _gl.RG16I; 23936 if ( glType === _gl.INT ) internalFormat = _gl.RG32I; 23937 23938 } 23939 23940 if ( glFormat === _gl.RGB ) { 23941 23942 if ( glType === _gl.UNSIGNED_INT_5_9_9_9_REV ) internalFormat = _gl.RGB9_E5; 23943 23944 } 23945 23946 if ( glFormat === _gl.RGBA ) { 23947 23948 const transfer = forceLinearTransfer ? LinearTransfer : ColorManagement.getTransfer( colorSpace ); 23949 23950 if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; 23951 if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; 23952 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; 23953 if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4; 23954 if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1; 23955 23956 } 23957 23958 if ( internalFormat === _gl.R16F || internalFormat === _gl.R32F || 23959 internalFormat === _gl.RG16F || internalFormat === _gl.RG32F || 23960 internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) { 23961 23962 extensions.get( 'EXT_color_buffer_float' ); 23963 23964 } 23965 23966 return internalFormat; 23967 23968 } 23969 23970 function getInternalDepthFormat( useStencil, depthType ) { 23971 23972 let glInternalFormat; 23973 if ( useStencil ) { 23974 23975 if ( depthType === null || depthType === UnsignedIntType || depthType === UnsignedInt248Type ) { 23976 23977 glInternalFormat = _gl.DEPTH24_STENCIL8; 23978 23979 } else if ( depthType === FloatType ) { 23980 23981 glInternalFormat = _gl.DEPTH32F_STENCIL8; 23982 23983 } else if ( depthType === UnsignedShortType ) { 23984 23985 glInternalFormat = _gl.DEPTH24_STENCIL8; 23986 console.warn( 'DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.' ); 23987 23988 } 23989 23990 } else { 23991 23992 if ( depthType === null || depthType === UnsignedIntType || depthType === UnsignedInt248Type ) { 23993 23994 glInternalFormat = _gl.DEPTH_COMPONENT24; 23995 23996 } else if ( depthType === FloatType ) { 23997 23998 glInternalFormat = _gl.DEPTH_COMPONENT32F; 23999 24000 } else if ( depthType === UnsignedShortType ) { 24001 24002 glInternalFormat = _gl.DEPTH_COMPONENT16; 24003 24004 } 24005 24006 } 24007 24008 return glInternalFormat; 24009 24010 } 24011 24012 function getMipLevels( texture, image ) { 24013 24014 if ( textureNeedsGenerateMipmaps( texture ) === true || ( texture.is
vendor: 10,305 bytes, lines 24014-24401
24014FramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) ) { 24015 24016 return Math.log2( Math.max( image.width, image.height ) ) + 1; 24017 24018 } else if ( texture.mipmaps !== undefined && texture.mipmaps.length > 0 ) { 24019 24020 // user-defined mipmaps 24021 24022 return texture.mipmaps.length; 24023 24024 } else if ( texture.isCompressedTexture && Array.isArray( texture.image ) ) { 24025 24026 return image.mipmaps.length; 24027 24028 } else { 24029 24030 // texture without mipmaps (only base level) 24031 24032 return 1; 24033 24034 } 24035 24036 } 24037 24038 // 24039 24040 function onTextureDispose( event ) { 24041 24042 const texture = event.target; 24043 24044 texture.removeEventListener( 'dispose', onTextureDispose ); 24045 24046 deallocateTexture( texture ); 24047 24048 if ( texture.isVideoTexture ) { 24049 24050 _videoTextures.delete( texture ); 24051 24052 } 24053 24054 } 24055 24056 function onRenderTargetDispose( event ) { 24057 24058 const renderTarget = event.target; 24059 24060 renderTarget.removeEventListener( 'dispose', onRenderTargetDispose ); 24061 24062 deallocateRenderTarget( renderTarget ); 24063 24064 } 24065 24066 // 24067 24068 function deallocateTexture( texture ) { 24069 24070 const textureProperties = properties.get( texture ); 24071 24072 if ( textureProperties.__webglInit === undefined ) return; 24073 24074 // check if it's necessary to remove the WebGLTexture object 24075 24076 const source = texture.source; 24077 const webglTextures = _sources.get( source ); 24078 24079 if ( webglTextures ) { 24080 24081 const webglTexture = webglTextures[ textureProperties.__cacheKey ]; 24082 webglTexture.usedTimes --; 24083 24084 // the WebGLTexture object is not used anymore, remove it 24085 24086 if ( webglTexture.usedTimes === 0 ) { 24087 24088 deleteTexture( texture ); 24089 24090 } 24091 24092 // remove the weak map entry if no WebGLTexture uses the source anymore 24093 24094 if ( Object.keys( webglTextures ).length === 0 ) { 24095 24096 _sources.delete( source ); 24097 24098 } 24099 24100 } 24101 24102 properties.remove( texture ); 24103 24104 } 24105 24106 function deleteTexture( texture ) { 24107 24108 const textureProperties = properties.get( texture ); 24109 _gl.deleteTexture( textureProperties.__webglTexture ); 24110 24111 const source = texture.source; 24112 const webglTextures = _sources.get( source ); 24113 delete webglTextures[ textureProperties.__cacheKey ]; 24114 24115 info.memory.textures --; 24116 24117 } 24118 24119 function deallocateRenderTarget( renderTarget ) { 24120 24121 const renderTargetProperties = properties.get( renderTarget ); 24122 24123 if ( renderTarget.depthTexture ) { 24124 24125 renderTarget.depthTexture.dispose(); 24126 24127 } 24128 24129 if ( renderTarget.isWebGLCubeRenderTarget ) { 24130 24131 for ( let i = 0; i < 6; i ++ ) { 24132 24133 if ( Array.isArray( renderTargetProperties.__webglFramebuffer[ i ] ) ) { 24134 24135 for ( let level = 0; level < renderTargetProperties.__webglFramebuffer[ i ].length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ][ level ] ); 24136 24137 } else { 24138 24139 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] ); 24140 24141 } 24142 24143 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); 24144 24145 } 24146 24147 } else { 24148 24149 if ( Array.isArray( renderTargetProperties.__webglFramebuffer ) ) { 24150 24151 for ( let level = 0; level < renderTargetProperties.__webglFramebuffer.length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ level ] ); 24152 24153 } else { 24154 24155 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer ); 24156 24157 } 24158 24159 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); 24160 if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer ); 24161 24162 if ( renderTargetProperties.__webglColorRenderbuffer ) { 24163 24164 for ( let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i ++ ) { 24165 24166 if ( renderTargetProperties.__webglColorRenderbuffer[ i ] ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer[ i ] ); 24167 24168 } 24169 24170 } 24171 24172 if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer ); 24173 24174 } 24175 24176 const textures = renderTarget.textures; 24177 24178 for ( let i = 0, il = textures.length; i < il; i ++ ) { 24179 24180 const attachmentProperties = properties.get( textures[ i ] ); 24181 24182 if ( attachmentProperties.__webglTexture ) { 24183 24184 _gl.deleteTexture( attachmentProperties.__webglTexture ); 24185 24186 info.memory.textures --; 24187 24188 } 24189 24190 properties.remove( textures[ i ] ); 24191 24192 } 24193 24194 properties.remove( renderTarget ); 24195 24196 } 24197 24198 // 24199 24200 let textureUnits = 0; 24201 24202 function resetTextureUnits() { 24203 24204 textureUnits = 0; 24205 24206 } 24207 24208 function allocateTextureUnit() { 24209 24210 const textureUnit = textureUnits; 24211 24212 if ( textureUnit >= capabilities.maxTextures ) { 24213 24214 console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); 24215 24216 } 24217 24218 textureUnits += 1; 24219 24220 return textureUnit; 24221 24222 } 24223 24224 function getTextureCacheKey( texture ) { 24225 24226 const array = []; 24227 24228 array.push( texture.wrapS ); 24229 array.push( texture.wrapT ); 24230 array.push( texture.wrapR || 0 ); 24231 array.push( texture.magFilter ); 24232 array.push( texture.minFilter ); 24233 array.push( texture.anisotropy ); 24234 array.push( texture.internalFormat ); 24235 array.push( texture.format ); 24236 array.push( texture.type ); 24237 array.push( texture.generateMipmaps ); 24238 array.push( texture.premultiplyAlpha ); 24239 array.push( texture.flipY ); 24240 array.push( texture.unpackAlignment ); 24241 array.push( texture.colorSpace ); 24242 24243 return array.join(); 24244 24245 } 24246 24247 // 24248 24249 function setTexture2D( texture, slot ) { 24250 24251 const textureProperties = properties.get( texture ); 24252 24253 if ( texture.isVideoTexture ) updateVideoTexture( texture ); 24254 24255 if ( texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version ) { 24256 24257 const image = texture.image; 24258 24259 if ( image === null ) { 24260 24261 console.warn( 'THREE.WebGLRenderer: Texture marked for update but no image data found.' ); 24262 24263 } else if ( image.complete === false ) { 24264 24265 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' ); 24266 24267 } else { 24268 24269 uploadTexture( textureProperties, texture, slot ); 24270 return; 24271 24272 } 24273 24274 } 24275 24276 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24277 24278 } 24279 24280 function setTexture2DArray( texture, slot ) { 24281 24282 const textureProperties = properties.get( texture ); 24283 24284 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 24285 24286 uploadTexture( textureProperties, texture, slot ); 24287 return; 24288 24289 } 24290 24291 state.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24292 24293 } 24294 24295 function setTexture3D( texture, slot ) { 24296 24297 const textureProperties = properties.get( texture ); 24298 24299 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 24300 24301 uploadTexture( textureProperties, texture, slot ); 24302 return; 24303 24304 } 24305 24306 state.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24307 24308 } 24309 24310 function setTextureCube( texture, slot ) { 24311 24312 const textureProperties = properties.get( texture ); 24313 24314 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 24315 24316 uploadCubeTexture( textureProperties, texture, slot ); 24317 return; 24318 24319 } 24320 24321 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24322 24323 } 24324 24325 const wrappingToGL = { 24326 [ RepeatWrapping ]: _gl.REPEAT, 24327 [ ClampToEdgeWrapping ]: _gl.CLAMP_TO_EDGE, 24328 [ MirroredRepeatWrapping ]: _gl.MIRRORED_REPEAT 24329 }; 24330 24331 const filterToGL = { 24332 [ NearestFilter ]: _gl.NEAREST, 24333 [ NearestMipmapNearestFilter ]: _gl.NEAREST_MIPMAP_NEAREST, 24334 [ NearestMipmapLinearFilter ]: _gl.NEAREST_MIPMAP_LINEAR, 24335 24336 [ LinearFilter ]: _gl.LINEAR, 24337 [ LinearMipmapNearestFilter ]: _gl.LINEAR_MIPMAP_NEAREST, 24338 [ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR 24339 }; 24340 24341 const compareToGL = { 24342 [ NeverCompare ]: _gl.NEVER, 24343 [ AlwaysCompare ]: _gl.ALWAYS, 24344 [ LessCompare ]: _gl.LESS, 24345 [ LessEqualCompare ]: _gl.LEQUAL, 24346 [ EqualCompare ]: _gl.EQUAL, 24347 [ GreaterEqualCompare ]: _gl.GEQUAL, 24348 [ GreaterCompare ]: _gl.GREATER, 24349 [ NotEqualCompare ]: _gl.NOTEQUAL 24350 }; 24351 24352 function setTextureParameters( textureType, texture ) { 24353 24354 if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false && 24355 ( texture.magFilter === LinearFilter || texture.magFilter === LinearMipmapNearestFilter || texture.magFilter === NearestMipmapLinearFilter || texture.magFilter === LinearMipmapLinearFilter || 24356 texture.minFilter === LinearFilter || texture.minFilter === LinearMipmapNearestFilter || texture.minFilter === NearestMipmapLinearFilter || texture.minFilter === LinearMipmapLinearFilter ) ) { 24357 24358 console.warn( 'THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device.' ); 24359 24360 } 24361 24362 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] ); 24363 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] ); 24364 24365 if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) { 24366 24367 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[ texture.wrapR ] ); 24368 24369 } 24370 24371 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] ); 24372 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[ texture.minFilter ] ); 24373 24374 if ( texture.compareFunction ) { 24375 24376 _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE ); 24377 _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] ); 24378 24379 } 24380 24381 if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { 24382 24383 if ( texture.magFilter === NearestFilter ) return; 24384 if ( texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter ) return; 24385 if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false ) return; // verify extension 24386 24387 if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) { 24388 24389 const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); 24390 _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) ); 24391 properties.get( texture ).__currentAnisotropy = texture.anisotropy; 24392 24393 } 24394 24395 } 24396 24397 } 24398 24399 function initTexture( textureProperties, texture ) { 24400 24401 let forceUpload = false;
vendor: 5,128 bytes, lines 24402-24578
24402 24403 if ( textureProperties.__webglInit === undefined ) { 24404 24405 textureProperties.__webglInit = true; 24406 24407 texture.addEventListener( 'dispose', onTextureDispose ); 24408 24409 } 24410 24411 // create Source <-> WebGLTextures mapping if necessary 24412 24413 const source = texture.source; 24414 let webglTextures = _sources.get( source ); 24415 24416 if ( webglTextures === undefined ) { 24417 24418 webglTextures = {}; 24419 _sources.set( source, webglTextures ); 24420 24421 } 24422 24423 // check if there is already a WebGLTexture object for the given texture parameters 24424 24425 const textureCacheKey = getTextureCacheKey( texture ); 24426 24427 if ( textureCacheKey !== textureProperties.__cacheKey ) { 24428 24429 // if not, create a new instance of WebGLTexture 24430 24431 if ( webglTextures[ textureCacheKey ] === undefined ) { 24432 24433 // create new entry 24434 24435 webglTextures[ textureCacheKey ] = { 24436 texture: _gl.createTexture(), 24437 usedTimes: 0 24438 }; 24439 24440 info.memory.textures ++; 24441 24442 // when a new instance of WebGLTexture was created, a texture upload is required 24443 // even if the image contents are identical 24444 24445 forceUpload = true; 24446 24447 } 24448 24449 webglTextures[ textureCacheKey ].usedTimes ++; 24450 24451 // every time the texture cache key changes, it's necessary to check if an instance of 24452 // WebGLTexture can be deleted in order to avoid a memory leak. 24453 24454 const webglTexture = webglTextures[ textureProperties.__cacheKey ]; 24455 24456 if ( webglTexture !== undefined ) { 24457 24458 webglTextures[ textureProperties.__cacheKey ].usedTimes --; 24459 24460 if ( webglTexture.usedTimes === 0 ) { 24461 24462 deleteTexture( texture ); 24463 24464 } 24465 24466 } 24467 24468 // store references to cache key and WebGLTexture object 24469 24470 textureProperties.__cacheKey = textureCacheKey; 24471 textureProperties.__webglTexture = webglTextures[ textureCacheKey ].texture; 24472 24473 } 24474 24475 return forceUpload; 24476 24477 } 24478 24479 function uploadTexture( textureProperties, texture, slot ) { 24480 24481 let textureType = _gl.TEXTURE_2D; 24482 24483 if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = _gl.TEXTURE_2D_ARRAY; 24484 if ( texture.isData3DTexture ) textureType = _gl.TEXTURE_3D; 24485 24486 const forceUpload = initTexture( textureProperties, texture ); 24487 const source = texture.source; 24488 24489 state.bindTexture( textureType, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24490 24491 const sourceProperties = properties.get( source ); 24492 24493 if ( source.version !== sourceProperties.__version || forceUpload === true ) { 24494 24495 state.activeTexture( _gl.TEXTURE0 + slot ); 24496 24497 const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); 24498 const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); 24499 const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; 24500 24501 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); 24502 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); 24503 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); 24504 _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion ); 24505 24506 let image = resizeImage( texture.image, false, capabilities.maxTextureSize ); 24507 image = verifyColorSpace( texture, image ); 24508 24509 const glFormat = utils.convert( texture.format, texture.colorSpace ); 24510 24511 const glType = utils.convert( texture.type ); 24512 let glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture ); 24513 24514 setTextureParameters( textureType, texture ); 24515 24516 let mipmap; 24517 const mipmaps = texture.mipmaps; 24518 24519 const useTexStorage = ( texture.isVideoTexture !== true ); 24520 const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); 24521 const dataReady = source.dataReady; 24522 const levels = getMipLevels( texture, image ); 24523 24524 if ( texture.isDepthTexture ) { 24525 24526 glInternalFormat = getInternalDepthFormat( texture.format === DepthStencilFormat, texture.type ); 24527 24528 // 24529 24530 if ( allocateMemory ) { 24531 24532 if ( useTexStorage ) { 24533 24534 state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height ); 24535 24536 } else { 24537 24538 state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ); 24539 24540 } 24541 24542 } 24543 24544 } else if ( texture.isDataTexture ) { 24545 24546 // use manually created mipmaps if available 24547 // if there are no manual mipmaps 24548 // set 0 level mipmap and then use GL to generate other mipmap levels 24549 24550 if ( mipmaps.length > 0 ) { 24551 24552 if ( useTexStorage && allocateMemory ) { 24553 24554 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); 24555 24556 } 24557 24558 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 24559 24560 mipmap = mipmaps[ i ]; 24561 24562 if ( useTexStorage ) { 24563 24564 if ( dataReady ) { 24565 24566 state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); 24567 24568 } 24569 24570 } else { 24571 24572 state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 24573 24574 } 24575 24576 } 24577 24578 texture.generateMipmaps = false;
24579 24580 } else { 24581 24582 if ( useTexStorage ) { 24583 24584 if ( allocateMemory ) { 24585 24586 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); 24587 24588 } 24589 24590 if ( dataReady ) { 24591 24592 state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data ); 24593 24594 } 24595 24596 } else { 24597 24598 state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data ); 24599 24600 } 24601 24602 } 24603 24604 } else if ( texture.isCompressedTexture ) { 24605 24606 if ( texture.isCompressedArrayTexture ) { 24607 24608 if ( useTexStorage && allocateMemory ) { 24609 24610 state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth ); 24611 24612 } 24613 24614 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 24615 24616 mipmap = mipmaps[ i ]; 24617 24618 if ( texture.format !== RGBAFormat ) { 24619 24620 if ( glFormat !== null ) { 24621 24622 if ( useTexStorage ) { 24623 24624 if ( dataReady ) { 24625 24626 if ( texture.layerUpdates.size > 0 ) { 24627 24628 for ( const layerIndex of texture.layerUpdates ) { 24629 24630 const layerSize = mipmap.width * mipmap.height; 24631 state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, layerIndex, mipmap.width, mipmap.height, 1, glFormat, mipmap.data.slice( layerSize * layerIndex, layerSize * ( layerIndex + 1 ) ), 0, 0 ); 24632 24633 } 24634 24635 texture.clearLayerUpdates(); 24636 24637 } else { 24638 24639 state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); 24640 24641 } 24642 24643 } 24644 24645 } else { 24646 24647 state.compressedTexImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 ); 24648 24649 } 24650 24651 } else { 24652 24653 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); 24654 24655 } 24656 24657 } else { 24658 24659 if ( useTexStorage ) { 24660 24661 if ( dataReady ) { 24662 24663 state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data ); 24664 24665 } 24666 24667 } else { 24668 24669 state.texImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data ); 24670 24671 } 24672 24673 } 24674 24675 } 24676 24677 } else { 24678 24679 if ( useTexStorage && allocateMemory ) { 24680 24681 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); 24682 24683 } 24684 24685 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 24686 24687 mipmap = mipmaps[ i ]; 24688 24689 if ( texture.format !== RGBAFormat ) { 24690 24691 if ( glFormat !== null ) { 24692 24693 if ( useTexStorage ) { 24694 24695 if ( dataReady ) { 24696 24697 state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); 24698 24699 } 24700 24701 } else { 24702 24703 state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); 24704 24705 } 24706 24707 } else { 24708 24709 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); 24710 24711 } 24712 24713 } else { 24714 24715 if ( useTexStorage ) { 24716 24717 if ( dataReady ) { 24718 24719 state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); 24720 24721 } 24722 24723 } else { 24724 24725 state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 24726 24727 } 24728 24729 } 24730 24731 } 24732 24733 } 24734 24735 } else if ( texture.isDataArrayTexture ) { 24736 24737 if ( useTexStorage ) { 24738 24739 if ( allocateMemory ) { 24740 24741 state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth ); 24742 24743 } 24744 24745 if ( dataReady ) { 24746 24747 if ( texture.layerUpdates.size > 0 ) { 24748 24749 // When type is GL_UNSIGNED_BYTE, each of these bytes is 24750 // interpreted as one color component, depending on format. When 24751 // type is one of GL_UNSIGNED_SHORT_5_6_5, 24752 // GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1, each 24753 // unsigned value is interpreted as containing all the components 24754 // for a single pixel, with the color components arranged 24755 // according to format. 24756 // 24757 // See https://registry.khronos.org/OpenGL-Refpages/es1.1/xhtml/glTexImage2D.xml 24758 let texelSize; 24759 switch ( glType ) { 24760 24761 case _gl.UNSIGNED_BYTE: 24762 switch ( glFormat ) { 24763 24764 case _gl.ALPHA: 24765 texelSize = 1; 24766 break; 24767 case _gl.LUMINANCE: 24768 texelSize = 1; 24769 break; 24770 case _gl.LUMINANCE_ALPHA: 24771 texelSize = 2; 24772 break; 24773 case _gl.RGB: 24774 texelSize = 3; 24775 break; 24776 case _gl.RGBA: 24777 texelSize = 4; 24778 break; 24779 24780 default: 24781 throw new Error( `Unknown texel size for format ${glFormat}.` ); 24782 24783 } 24784 24785 break; 24786 24787 case _gl.UNSIGNED_SHORT_4_4_4_4: 24788 case _gl.UNSIGNED_SHORT_5_5_5_1: 24789 case _gl.UNSIGNED_SHORT_5_6_5: 24790 texelSize = 1; 24791 break; 24792 24793 default: 24794 throw new Error( `Unknown texel size for type ${glType}.` ); 24795 24796 } 24797 24798 const layerSize = image.width * image.height * texelSize; 24799 24800 for ( const layerIndex of texture.layerUpdates ) { 24801 24802 state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, layerIndex, image.width, image.height, 1, glFormat, glType, image.data.slice( layerSize * layerIndex, layerSize * ( layerIndex + 1 ) ) ); 24803 24804 } 24805 24806 texture.clearLayerUpdates(); 24807 24808 } else { 24809 24810 state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); 24811 24812 } 24813 24814 } 24815 24816 } else { 24817 24818 state.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); 24819 24820 } 24821 24822 } else if ( texture.isData3DTexture ) { 24823 24824 if ( useTexStorage ) { 24825 24826 if ( allocateMemory ) { 24827 24828 state.texStorage3D( _gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth ); 24829 24830 } 24831 24832 if ( dataReady ) { 24833 24834 state.texSubImage3D( _gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); 24835 24836 } 24837 24838 } else { 24839 24840 state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); 24841 24842 } 24843 24844 }
vendor: 8,580 bytes, lines 24844-25191
24844 else if ( texture.isFramebufferTexture ) { 24845 24846 if ( allocateMemory ) { 24847 24848 if ( useTexStorage ) { 24849 24850 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); 24851 24852 } else { 24853 24854 let width = image.width, height = image.height; 24855 24856 for ( let i = 0; i < levels; i ++ ) { 24857 24858 state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, width, height, 0, glFormat, glType, null ); 24859 24860 width >>= 1; 24861 height >>= 1; 24862 24863 } 24864 24865 } 24866 24867 } 24868 24869 } else { 24870 24871 // regular Texture (image, video, canvas) 24872 24873 // use manually created mipmaps if available 24874 // if there are no manual mipmaps 24875 // set 0 level mipmap and then use GL to generate other mipmap levels 24876 24877 if ( mipmaps.length > 0 ) { 24878 24879 if ( useTexStorage && allocateMemory ) { 24880 24881 const dimensions = getDimensions( mipmaps[ 0 ] ); 24882 24883 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height ); 24884 24885 } 24886 24887 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 24888 24889 mipmap = mipmaps[ i ]; 24890 24891 if ( useTexStorage ) { 24892 24893 if ( dataReady ) { 24894 24895 state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap ); 24896 24897 } 24898 24899 } else { 24900 24901 state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap ); 24902 24903 } 24904 24905 } 24906 24907 texture.generateMipmaps = false; 24908 24909 } else { 24910 24911 if ( useTexStorage ) { 24912 24913 if ( allocateMemory ) { 24914 24915 const dimensions = getDimensions( image ); 24916 24917 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height ); 24918 24919 } 24920 24921 if ( dataReady ) { 24922 24923 state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image ); 24924 24925 } 24926 24927 } else { 24928 24929 state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image ); 24930 24931 } 24932 24933 } 24934 24935 } 24936 24937 if ( textureNeedsGenerateMipmaps( texture ) ) { 24938 24939 generateMipmap( textureType ); 24940 24941 } 24942 24943 sourceProperties.__version = source.version; 24944 24945 if ( texture.onUpdate ) texture.onUpdate( texture ); 24946 24947 } 24948 24949 textureProperties.__version = texture.version; 24950 24951 } 24952 24953 function uploadCubeTexture( textureProperties, texture, slot ) { 24954 24955 if ( texture.image.length !== 6 ) return; 24956 24957 const forceUpload = initTexture( textureProperties, texture ); 24958 const source = texture.source; 24959 24960 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24961 24962 const sourceProperties = properties.get( source ); 24963 24964 if ( source.version !== sourceProperties.__version || forceUpload === true ) { 24965 24966 state.activeTexture( _gl.TEXTURE0 + slot ); 24967 24968 const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); 24969 const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); 24970 const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; 24971 24972 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); 24973 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); 24974 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); 24975 _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion ); 24976 24977 const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ); 24978 const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); 24979 24980 const cubeImage = []; 24981 24982 for ( let i = 0; i < 6; i ++ ) { 24983 24984 if ( ! isCompressed && ! isDataTexture ) { 24985 24986 cubeImage[ i ] = resizeImage( texture.image[ i ], true, capabilities.maxCubemapSize ); 24987 24988 } else { 24989 24990 cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ]; 24991 24992 } 24993 24994 cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] ); 24995 24996 } 24997 24998 const image = cubeImage[ 0 ], 24999 glFormat = utils.convert( texture.format, texture.colorSpace ), 25000 glType = utils.convert( texture.type ), 25001 glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); 25002 25003 const useTexStorage = ( texture.isVideoTexture !== true ); 25004 const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); 25005 const dataReady = source.dataReady; 25006 let levels = getMipLevels( texture, image ); 25007 25008 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture ); 25009 25010 let mipmaps; 25011 25012 if ( isCompressed ) { 25013 25014 if ( useTexStorage && allocateMemory ) { 25015 25016 state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height ); 25017 25018 } 25019 25020 for ( let i = 0; i < 6; i ++ ) { 25021 25022 mipmaps = cubeImage[ i ].mipmaps; 25023 25024 for ( let j = 0; j < mipmaps.length; j ++ ) { 25025 25026 const mipmap = mipmaps[ j ]; 25027 25028 if ( texture.format !== RGBAFormat ) { 25029 25030 if ( glFormat !== null ) { 25031 25032 if ( useTexStorage ) { 25033 25034 if ( dataReady ) { 25035 25036 state.compressedTexSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); 25037 25038 } 25039 25040 } else { 25041 25042 state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); 25043 25044 } 25045 25046 } else { 25047 25048 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); 25049 25050 } 25051 25052 } else { 25053 25054 if ( useTexStorage ) { 25055 25056 if ( dataReady ) { 25057 25058 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); 25059 25060 } 25061 25062 } else { 25063 25064 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 25065 25066 } 25067 25068 } 25069 25070 } 25071 25072 } 25073 25074 } else { 25075 25076 mipmaps = texture.mipmaps; 25077 25078 if ( useTexStorage && allocateMemory ) { 25079 25080 // TODO: Uniformly handle mipmap definitions 25081 // Normal textures and compressed cube textures define base level + mips with their mipmap array 25082 // Uncompressed cube textures use their mipmap array only for mips (no base level) 25083 25084 if ( mipmaps.length > 0 ) levels ++; 25085 25086 const dimensions = getDimensions( cubeImage[ 0 ] ); 25087 25088 state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, dimensions.width, dimensions.height ); 25089 25090 } 25091 25092 for ( let i = 0; i < 6; i ++ ) { 25093 25094 if ( isDataTexture ) { 25095 25096 if ( useTexStorage ) { 25097 25098 if ( dataReady ) { 25099 25100 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data ); 25101 25102 } 25103 25104 } else { 25105 25106 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); 25107 25108 } 25109 25110 for ( let j = 0; j < mipmaps.length; j ++ ) { 25111 25112 const mipmap = mipmaps[ j ]; 25113 const mipmapImage = mipmap.image[ i ].image; 25114 25115 if ( useTexStorage ) { 25116 25117 if ( dataReady ) { 25118 25119 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data ); 25120 25121 } 25122 25123 } else { 25124 25125 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data ); 25126 25127 } 25128 25129 } 25130 25131 } else { 25132 25133 if ( useTexStorage ) { 25134 25135 if ( dataReady ) { 25136 25137 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] ); 25138 25139 } 25140 25141 } else { 25142 25143 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] ); 25144 25145 } 25146 25147 for ( let j = 0; j < mipmaps.length; j ++ ) { 25148 25149 const mipmap = mipmaps[ j ]; 25150 25151 if ( useTexStorage ) { 25152 25153 if ( dataReady ) { 25154 25155 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] ); 25156 25157 } 25158 25159 } else { 25160 25161 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] ); 25162 25163 } 25164 25165 } 25166 25167 } 25168 25169 } 25170 25171 } 25172 25173 if ( textureNeedsGenerateMipmaps( texture ) ) { 25174 25175 // We assume images for cube map have the same size. 25176 generateMipmap( _gl.TEXTURE_CUBE_MAP ); 25177 25178 } 25179 25180 sourceProperties.__version = source.version; 25181 25182 if ( texture.onUpdate ) texture.onUpdate( texture ); 25183 25184 } 25185 25186 textureProperties.__version = texture.version; 25187 25188 } 25189 25190 // Render targets 25191
vendor: 10,068 bytes, lines 25192-25513
25192 // Setup storage for target texture and bind it to correct framebuffer 25193 function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget, level ) { 25194 25195 const glFormat = utils.convert( texture.format, texture.colorSpace ); 25196 const glType = utils.convert( texture.type ); 25197 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); 25198 const renderTargetProperties = properties.get( renderTarget ); 25199 25200 if ( ! renderTargetProperties.__hasExternalTextures ) { 25201 25202 const width = Math.max( 1, renderTarget.width >> level ); 25203 const height = Math.max( 1, renderTarget.height >> level ); 25204 25205 if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) { 25206 25207 state.texImage3D( textureTarget, level, glInternalFormat, width, height, renderTarget.depth, 0, glFormat, glType, null ); 25208 25209 } else { 25210 25211 state.texImage2D( textureTarget, level, glInternalFormat, width, height, 0, glFormat, glType, null ); 25212 25213 } 25214 25215 } 25216 25217 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 25218 25219 if ( useMultisampledRTT( renderTarget ) ) { 25220 25221 multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); 25222 25223 } else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) { // see #24753 25224 25225 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, level ); 25226 25227 } 25228 25229 state.bindFramebuffer( _gl.FRAMEBUFFER, null ); 25230 25231 } 25232 25233 // Setup storage for internal depth/stencil buffers and bind to correct framebuffer 25234 function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) { 25235 25236 _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); 25237 25238 if ( renderTarget.depthBuffer ) { 25239 25240 // retrieve the depth attachment types 25241 const depthTexture = renderTarget.depthTexture; 25242 const depthType = depthTexture && depthTexture.isDepthTexture ? depthTexture.type : null; 25243 const glInternalFormat = getInternalDepthFormat( renderTarget.stencilBuffer, depthType ); 25244 const glAttachmentType = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; 25245 25246 // set up the attachment 25247 const samples = getRenderTargetSamples( renderTarget ); 25248 const isUseMultisampledRTT = useMultisampledRTT( renderTarget ); 25249 if ( isUseMultisampledRTT ) { 25250 25251 multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25252 25253 } else if ( isMultisample ) { 25254 25255 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25256 25257 } else { 25258 25259 _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); 25260 25261 } 25262 25263 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, glAttachmentType, _gl.RENDERBUFFER, renderbuffer ); 25264 25265 } else { 25266 25267 const textures = renderTarget.textures; 25268 25269 for ( let i = 0; i < textures.length; i ++ ) { 25270 25271 const texture = textures[ i ]; 25272 25273 const glFormat = utils.convert( texture.format, texture.colorSpace ); 25274 const glType = utils.convert( texture.type ); 25275 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); 25276 const samples = getRenderTargetSamples( renderTarget ); 25277 25278 if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { 25279 25280 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25281 25282 } else if ( useMultisampledRTT( renderTarget ) ) { 25283 25284 multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25285 25286 } else { 25287 25288 _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); 25289 25290 } 25291 25292 } 25293 25294 } 25295 25296 _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); 25297 25298 } 25299 25300 // Setup resources for a Depth Texture for a FBO (needs an extension) 25301 function setupDepthTexture( framebuffer, renderTarget ) { 25302 25303 const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget ); 25304 if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); 25305 25306 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 25307 25308 if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { 25309 25310 throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); 25311 25312 } 25313 25314 // upload an empty depth texture with framebuffer size 25315 if ( ! properties.get( renderTarget.depthTexture ).__webglTexture || 25316 renderTarget.depthTexture.image.width !== renderTarget.width || 25317 renderTarget.depthTexture.image.height !== renderTarget.height ) { 25318 25319 renderTarget.depthTexture.image.width = renderTarget.width; 25320 renderTarget.depthTexture.image.height = renderTarget.height; 25321 renderTarget.depthTexture.needsUpdate = true; 25322 25323 } 25324 25325 setTexture2D( renderTarget.depthTexture, 0 ); 25326 25327 const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; 25328 const samples = getRenderTargetSamples( renderTarget ); 25329 25330 if ( renderTarget.depthTexture.format === DepthFormat ) { 25331 25332 if ( useMultisampledRTT( renderTarget ) ) { 25333 25334 multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); 25335 25336 } else { 25337 25338 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); 25339 25340 } 25341 25342 } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { 25343 25344 if ( useMultisampledRTT( renderTarget ) ) { 25345 25346 multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); 25347 25348 } else { 25349 25350 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); 25351 25352 } 25353 25354 } else { 25355 25356 throw new Error( 'Unknown depthTexture format' ); 25357 25358 } 25359 25360 } 25361 25362 // Setup GL resources for a non-texture depth buffer 25363 function setupDepthRenderbuffer( renderTarget ) { 25364 25365 const renderTargetProperties = properties.get( renderTarget ); 25366 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); 25367 25368 if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) { 25369 25370 if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); 25371 25372 setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); 25373 25374 } else { 25375 25376 if ( isCube ) { 25377 25378 renderTargetProperties.__webglDepthbuffer = []; 25379 25380 for ( let i = 0; i < 6; i ++ ) { 25381 25382 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); 25383 renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); 25384 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false ); 25385 25386 } 25387 25388 } else { 25389 25390 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 25391 renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); 25392 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false ); 25393 25394 } 25395 25396 } 25397 25398 state.bindFramebuffer( _gl.FRAMEBUFFER, null ); 25399 25400 } 25401 25402 // rebind framebuffer with external textures 25403 function rebindTextures( renderTarget, colorTexture, depthTexture ) { 25404 25405 const renderTargetProperties = properties.get( renderTarget ); 25406 25407 if ( colorTexture !== undefined ) { 25408 25409 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, 0 ); 25410 25411 } 25412 25413 if ( depthTexture !== undefined ) { 25414 25415 setupDepthRenderbuffer( renderTarget ); 25416 25417 } 25418 25419 } 25420 25421 // Set up GL resources for the render target 25422 function setupRenderTarget( renderTarget ) { 25423 25424 const texture = renderTarget.texture; 25425 25426 const renderTargetProperties = properties.get( renderTarget ); 25427 const textureProperties = properties.get( texture ); 25428 25429 renderTarget.addEventListener( 'dispose', onRenderTargetDispose ); 25430 25431 const textures = renderTarget.textures; 25432 25433 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); 25434 const isMultipleRenderTargets = ( textures.length > 1 ); 25435 25436 if ( ! isMultipleRenderTargets ) { 25437 25438 if ( textureProperties.__webglTexture === undefined ) { 25439 25440 textureProperties.__webglTexture = _gl.createTexture(); 25441 25442 } 25443 25444 textureProperties.__version = texture.version; 25445 info.memory.textures ++; 25446 25447 } 25448 25449 // Setup framebuffer 25450 25451 if ( isCube ) { 25452 25453 renderTargetProperties.__webglFramebuffer = []; 25454 25455 for ( let i = 0; i < 6; i ++ ) { 25456 25457 if ( texture.mipmaps && texture.mipmaps.length > 0 ) { 25458 25459 renderTargetProperties.__webglFramebuffer[ i ] = []; 25460 25461 for ( let level = 0; level < texture.mipmaps.length; level ++ ) { 25462 25463 renderTargetProperties.__webglFramebuffer[ i ][ level ] = _gl.createFramebuffer(); 25464 25465 } 25466 25467 } else { 25468 25469 renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer(); 25470 25471 } 25472 25473 } 25474 25475 } else { 25476 25477 if ( texture.mipmaps && texture.mipmaps.length > 0 ) { 25478 25479 renderTargetProperties.__webglFramebuffer = []; 25480 25481 for ( let level = 0; level < texture.mipmaps.length; level ++ ) { 25482 25483 renderTargetProperties.__webglFramebuffer[ level ] = _gl.createFramebuffer(); 25484 25485 } 25486 25487 } else { 25488 25489 renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); 25490 25491 } 25492 25493 if ( isMultipleRenderTargets ) { 25494 25495 for ( let i = 0, il = textures.length; i < il; i ++ ) { 25496 25497 const attachmentProperties = properties.get( textures[ i ] ); 25498 25499 if ( attachmentProperties.__webglTexture === undefined ) { 25500 25501 attachmentProperties.__webglTexture = _gl.createTexture(); 25502 25503 info.memory.textures ++; 25504 25505 } 25506 25507 } 25508 25509 } 25510 25511 if ( ( renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) { 25512 25513 renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
vendor: 4,218 bytes, lines 25514-25660
25514 renderTargetProperties.__webglColorRenderbuffer = []; 25515 25516 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25517 25518 for ( let i = 0; i < textures.length; i ++ ) { 25519 25520 const texture = textures[ i ]; 25521 renderTargetProperties.__webglColorRenderbuffer[ i ] = _gl.createRenderbuffer(); 25522 25523 _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 25524 25525 const glFormat = utils.convert( texture.format, texture.colorSpace ); 25526 const glType = utils.convert( texture.type ); 25527 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true ); 25528 const samples = getRenderTargetSamples( renderTarget ); 25529 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25530 25531 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 25532 25533 } 25534 25535 _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); 25536 25537 if ( renderTarget.depthBuffer ) { 25538 25539 renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer(); 25540 setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true ); 25541 25542 } 25543 25544 state.bindFramebuffer( _gl.FRAMEBUFFER, null ); 25545 25546 } 25547 25548 } 25549 25550 // Setup color buffer 25551 25552 if ( isCube ) { 25553 25554 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); 25555 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture ); 25556 25557 for ( let i = 0; i < 6; i ++ ) { 25558 25559 if ( texture.mipmaps && texture.mipmaps.length > 0 ) { 25560 25561 for ( let level = 0; level < texture.mipmaps.length; level ++ ) { 25562 25563 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ][ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level ); 25564 25565 } 25566 25567 } else { 25568 25569 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0 ); 25570 25571 } 25572 25573 } 25574 25575 if ( textureNeedsGenerateMipmaps( texture ) ) { 25576 25577 generateMipmap( _gl.TEXTURE_CUBE_MAP ); 25578 25579 } 25580 25581 state.unbindTexture(); 25582 25583 } else if ( isMultipleRenderTargets ) { 25584 25585 for ( let i = 0, il = textures.length; i < il; i ++ ) { 25586 25587 const attachment = textures[ i ]; 25588 const attachmentProperties = properties.get( attachment ); 25589 25590 state.bindTexture( _gl.TEXTURE_2D, attachmentProperties.__webglTexture ); 25591 setTextureParameters( _gl.TEXTURE_2D, attachment ); 25592 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, 0 ); 25593 25594 if ( textureNeedsGenerateMipmaps( attachment ) ) { 25595 25596 generateMipmap( _gl.TEXTURE_2D ); 25597 25598 } 25599 25600 } 25601 25602 state.unbindTexture(); 25603 25604 } else { 25605 25606 let glTextureType = _gl.TEXTURE_2D; 25607 25608 if ( renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) { 25609 25610 glTextureType = renderTarget.isWebGL3DRenderTarget ? _gl.TEXTURE_3D : _gl.TEXTURE_2D_ARRAY; 25611 25612 } 25613 25614 state.bindTexture( glTextureType, textureProperties.__webglTexture ); 25615 setTextureParameters( glTextureType, texture ); 25616 25617 if ( texture.mipmaps && texture.mipmaps.length > 0 ) { 25618 25619 for ( let level = 0; level < texture.mipmaps.length; level ++ ) { 25620 25621 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, level ); 25622 25623 } 25624 25625 } else { 25626 25627 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, 0 ); 25628 25629 } 25630 25631 if ( textureNeedsGenerateMipmaps( texture ) ) { 25632 25633 generateMipmap( glTextureType ); 25634 25635 } 25636 25637 state.unbindTexture(); 25638 25639 } 25640 25641 // Setup depth and stencil buffers 25642 25643 if ( renderTarget.depthBuffer ) { 25644 25645 setupDepthRenderbuffer( renderTarget ); 25646 25647 } 25648 25649 } 25650 25651 function updateRenderTargetMipmap( renderTarget ) { 25652 25653 const textures = renderTarget.textures; 25654 25655 for ( let i = 0, il = textures.length; i < il; i ++ ) { 25656 25657 const texture = textures[ i ]; 25658 25659 if ( textureNeedsGenerateMipmaps( texture ) ) { 25660
vendor: 4,313 bytes, lines 25661-25781
25661 const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; 25662 const webglTexture = properties.get( texture ).__webglTexture; 25663 25664 state.bindTexture( target, webglTexture ); 25665 generateMipmap( target ); 25666 state.unbindTexture(); 25667 25668 } 25669 25670 } 25671 25672 } 25673 25674 const invalidationArrayRead = []; 25675 const invalidationArrayDraw = []; 25676 25677 function updateMultisampleRenderTarget( renderTarget ) { 25678 25679 if ( renderTarget.samples > 0 ) { 25680 25681 if ( useMultisampledRTT( renderTarget ) === false ) { 25682 25683 const textures = renderTarget.textures; 25684 const width = renderTarget.width; 25685 const height = renderTarget.height; 25686 let mask = _gl.COLOR_BUFFER_BIT; 25687 const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; 25688 const renderTargetProperties = properties.get( renderTarget ); 25689 const isMultipleRenderTargets = ( textures.length > 1 ); 25690 25691 // If MRT we need to remove FBO attachments 25692 if ( isMultipleRenderTargets ) { 25693 25694 for ( let i = 0; i < textures.length; i ++ ) { 25695 25696 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25697 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null ); 25698 25699 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 25700 _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0 ); 25701 25702 } 25703 25704 } 25705 25706 state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25707 state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 25708 25709 for ( let i = 0; i < textures.length; i ++ ) { 25710 25711 if ( renderTarget.resolveDepthBuffer ) { 25712 25713 if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT; 25714 25715 // resolving stencil is slow with a D3D backend. disable it for all transmission render targets (see #27799) 25716 25717 if ( renderTarget.stencilBuffer && renderTarget.resolveStencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT; 25718 25719 } 25720 25721 if ( isMultipleRenderTargets ) { 25722 25723 _gl.framebufferRenderbuffer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 25724 25725 const webglTexture = properties.get( textures[ i ] ).__webglTexture; 25726 _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0 ); 25727 25728 } 25729 25730 _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST ); 25731 25732 if ( supportsInvalidateFramebuffer === true ) { 25733 25734 invalidationArrayRead.length = 0; 25735 invalidationArrayDraw.length = 0; 25736 25737 invalidationArrayRead.push( _gl.COLOR_ATTACHMENT0 + i ); 25738 25739 if ( renderTarget.depthBuffer && renderTarget.resolveDepthBuffer === false ) { 25740 25741 invalidationArrayRead.push( depthStyle ); 25742 invalidationArrayDraw.push( depthStyle ); 25743 25744 _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, invalidationArrayDraw ); 25745 25746 } 25747 25748 _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArrayRead ); 25749 25750 } 25751 25752 } 25753 25754 state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null ); 25755 state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null ); 25756 25757 // If MRT since pre-blit we removed the FBO we need to reconstruct the attachments 25758 if ( isMultipleRenderTargets ) { 25759 25760 for ( let i = 0; i < textures.length; i ++ ) { 25761 25762 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25763 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 25764 25765 const webglTexture = properties.get( textures[ i ] ).__webglTexture; 25766 25767 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 25768 _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, webglTexture, 0 ); 25769 25770 } 25771 25772 } 25773 25774 state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25775 25776 } else { 25777 25778 if ( renderTarget.depthBuffer && renderTarget.resolveDepthBuffer === false && supportsInvalidateFramebuffer ) { 25779 25780 const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; 25781
vendor: 15,061 bytes, lines 25782-26325
25782 _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] ); 25783 25784 } 25785 25786 } 25787 25788 } 25789 25790 } 25791 25792 function getRenderTargetSamples( renderTarget ) { 25793 25794 return Math.min( capabilities.maxSamples, renderTarget.samples ); 25795 25796 } 25797 25798 function useMultisampledRTT( renderTarget ) { 25799 25800 const renderTargetProperties = properties.get( renderTarget ); 25801 25802 return renderTarget.samples > 0 && extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true && renderTargetProperties.__useRenderToTexture !== false; 25803 25804 } 25805 25806 function updateVideoTexture( texture ) { 25807 25808 const frame = info.render.frame; 25809 25810 // Check the last frame we updated the VideoTexture 25811 25812 if ( _videoTextures.get( texture ) !== frame ) { 25813 25814 _videoTextures.set( texture, frame ); 25815 texture.update(); 25816 25817 } 25818 25819 } 25820 25821 function verifyColorSpace( texture, image ) { 25822 25823 const colorSpace = texture.colorSpace; 25824 const format = texture.format; 25825 const type = texture.type; 25826 25827 if ( texture.isCompressedTexture === true || texture.isVideoTexture === true ) return image; 25828 25829 if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) { 25830 25831 // sRGB 25832 25833 if ( ColorManagement.getTransfer( colorSpace ) === SRGBTransfer ) { 25834 25835 // in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format 25836 25837 if ( format !== RGBAFormat || type !== UnsignedByteType ) { 25838 25839 console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' ); 25840 25841 } 25842 25843 } else { 25844 25845 console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace ); 25846 25847 } 25848 25849 } 25850 25851 return image; 25852 25853 } 25854 25855 function getDimensions( image ) { 25856 25857 if ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) { 25858 25859 // if intrinsic data are not available, fallback to width/height 25860 25861 _imageDimensions.width = image.naturalWidth || image.width; 25862 _imageDimensions.height = image.naturalHeight || image.height; 25863 25864 } else if ( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) { 25865 25866 _imageDimensions.width = image.displayWidth; 25867 _imageDimensions.height = image.displayHeight; 25868 25869 } else { 25870 25871 _imageDimensions.width = image.width; 25872 _imageDimensions.height = image.height; 25873 25874 } 25875 25876 return _imageDimensions; 25877 25878 } 25879 25880 // 25881 25882 this.allocateTextureUnit = allocateTextureUnit; 25883 this.resetTextureUnits = resetTextureUnits; 25884 25885 this.setTexture2D = setTexture2D; 25886 this.setTexture2DArray = setTexture2DArray; 25887 this.setTexture3D = setTexture3D; 25888 this.setTextureCube = setTextureCube; 25889 this.rebindTextures = rebindTextures; 25890 this.setupRenderTarget = setupRenderTarget; 25891 this.updateRenderTargetMipmap = updateRenderTargetMipmap; 25892 this.updateMultisampleRenderTarget = updateMultisampleRenderTarget; 25893 this.setupDepthRenderbuffer = setupDepthRenderbuffer; 25894 this.setupFrameBufferTexture = setupFrameBufferTexture; 25895 this.useMultisampledRTT = useMultisampledRTT; 25896 25897} 25898 25899function WebGLUtils( gl, extensions ) { 25900 25901 function convert( p, colorSpace = NoColorSpace ) { 25902 25903 let extension; 25904 25905 const transfer = ColorManagement.getTransfer( colorSpace ); 25906 25907 if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; 25908 if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; 25909 if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; 25910 if ( p === UnsignedInt5999Type ) return gl.UNSIGNED_INT_5_9_9_9_REV; 25911 25912 if ( p === ByteType ) return gl.BYTE; 25913 if ( p === ShortType ) return gl.SHORT; 25914 if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; 25915 if ( p === IntType ) return gl.INT; 25916 if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; 25917 if ( p === FloatType ) return gl.FLOAT; 25918 if ( p === HalfFloatType ) return gl.HALF_FLOAT; 25919 25920 if ( p === AlphaFormat ) return gl.ALPHA; 25921 if ( p === RGBFormat ) return gl.RGB; 25922 if ( p === RGBAFormat ) return gl.RGBA; 25923 if ( p === LuminanceFormat ) return gl.LUMINANCE; 25924 if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; 25925 if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; 25926 if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; 25927 25928 // WebGL2 formats. 25929 25930 if ( p === RedFormat ) return gl.RED; 25931 if ( p === RedIntegerFormat ) return gl.RED_INTEGER; 25932 if ( p === RGFormat ) return gl.RG; 25933 if ( p === RGIntegerFormat ) return gl.RG_INTEGER; 25934 if ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER; 25935 25936 // S3TC 25937 25938 if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { 25939 25940 if ( transfer === SRGBTransfer ) { 25941 25942 extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); 25943 25944 if ( extension !== null ) { 25945 25946 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT; 25947 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; 25948 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; 25949 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; 25950 25951 } else { 25952 25953 return null; 25954 25955 } 25956 25957 } else { 25958 25959 extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); 25960 25961 if ( extension !== null ) { 25962 25963 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; 25964 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; 25965 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; 25966 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; 25967 25968 } else { 25969 25970 return null; 25971 25972 } 25973 25974 } 25975 25976 } 25977 25978 // PVRTC 25979 25980 if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { 25981 25982 extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); 25983 25984 if ( extension !== null ) { 25985 25986 if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; 25987 if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; 25988 if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; 25989 if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; 25990 25991 } else { 25992 25993 return null; 25994 25995 } 25996 25997 } 25998 25999 // ETC 26000 26001 if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { 26002 26003 extension = extensions.get( 'WEBGL_compressed_texture_etc' ); 26004 26005 if ( extension !== null ) { 26006 26007 if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; 26008 if ( p === RGBA_ETC2_EAC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; 26009 26010 } else { 26011 26012 return null; 26013 26014 } 26015 26016 } 26017 26018 // ASTC 26019 26020 if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format || 26021 p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format || 26022 p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format || 26023 p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format || 26024 p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) { 26025 26026 extension = extensions.get( 'WEBGL_compressed_texture_astc' ); 26027 26028 if ( extension !== null ) { 26029 26030 if ( p === RGBA_ASTC_4x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; 26031 if ( p === RGBA_ASTC_5x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; 26032 if ( p === RGBA_ASTC_5x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; 26033 if ( p === RGBA_ASTC_6x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; 26034 if ( p === RGBA_ASTC_6x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; 26035 if ( p === RGBA_ASTC_8x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; 26036 if ( p === RGBA_ASTC_8x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; 26037 if ( p === RGBA_ASTC_8x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; 26038 if ( p === RGBA_ASTC_10x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; 26039 if ( p === RGBA_ASTC_10x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; 26040 if ( p === RGBA_ASTC_10x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; 26041 if ( p === RGBA_ASTC_10x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; 26042 if ( p === RGBA_ASTC_12x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; 26043 if ( p === RGBA_ASTC_12x12_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; 26044 26045 } else { 26046 26047 return null; 26048 26049 } 26050 26051 } 26052 26053 // BPTC 26054 26055 if ( p === RGBA_BPTC_Format || p === RGB_BPTC_SIGNED_Format || p === RGB_BPTC_UNSIGNED_Format ) { 26056 26057 extension = extensions.get( 'EXT_texture_compression_bptc' ); 26058 26059 if ( extension !== null ) { 26060 26061 if ( p === RGBA_BPTC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; 26062 if ( p === RGB_BPTC_SIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT; 26063 if ( p === RGB_BPTC_UNSIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT; 26064 26065 } else { 26066 26067 return null; 26068 26069 } 26070 26071 } 26072 26073 // RGTC 26074 26075 if ( p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format ) { 26076 26077 extension = extensions.get( 'EXT_texture_compression_rgtc' ); 26078 26079 if ( extension !== null ) { 26080 26081 if ( p === RGBA_BPTC_Format ) return extension.COMPRESSED_RED_RGTC1_EXT; 26082 if ( p === SIGNED_RED_RGTC1_Format ) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT; 26083 if ( p === RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT; 26084 if ( p === SIGNED_RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT; 26085 26086 } else { 26087 26088 return null; 26089 26090 } 26091 26092 } 26093 26094 // 26095 26096 if ( p === UnsignedInt248Type ) return gl.UNSIGNED_INT_24_8; 26097 26098 // if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats) 26099 26100 return ( gl[ p ] !== undefined ) ? gl[ p ] : null; 26101 26102 } 26103 26104 return { convert: convert }; 26105 26106} 26107 26108class ArrayCamera extends PerspectiveCamera { 26109 26110 constructor( array = [] ) { 26111 26112 super(); 26113 26114 this.isArrayCamera = true; 26115 26116 this.cameras = array; 26117 26118 } 26119 26120} 26121 26122class Group extends Object3D { 26123 26124 constructor() { 26125 26126 super(); 26127 26128 this.isGroup = true; 26129 26130 this.type = 'Group'; 26131 26132 } 26133 26134} 26135 26136const _moveEvent = { type: 'move' }; 26137 26138class WebXRController { 26139 26140 constructor() { 26141 26142 this._targetRay = null; 26143 this._grip = null; 26144 this._hand = null; 26145 26146 } 26147 26148 getHandSpace() { 26149 26150 if ( this._hand === null ) { 26151 26152 this._hand = new Group(); 26153 this._hand.matrixAutoUpdate = false; 26154 this._hand.visible = false; 26155 26156 this._hand.joints = {}; 26157 this._hand.inputState = { pinching: false }; 26158 26159 } 26160 26161 return this._hand; 26162 26163 } 26164 26165 getTargetRaySpace() { 26166 26167 if ( this._targetRay === null ) { 26168 26169 this._targetRay = new Group(); 26170 this._targetRay.matrixAutoUpdate = false; 26171 this._targetRay.visible = false; 26172 this._targetRay.hasLinearVelocity = false; 26173 this._targetRay.linearVelocity = new Vector3(); 26174 this._targetRay.hasAngularVelocity = false; 26175 this._targetRay.angularVelocity = new Vector3(); 26176 26177 } 26178 26179 return this._targetRay; 26180 26181 } 26182 26183 getGripSpace() { 26184 26185 if ( this._grip === null ) { 26186 26187 this._grip = new Group(); 26188 this._grip.matrixAutoUpdate = false; 26189 this._grip.visible = false; 26190 this._grip.hasLinearVelocity = false; 26191 this._grip.linearVelocity = new Vector3(); 26192 this._grip.hasAngularVelocity = false; 26193 this._grip.angularVelocity = new Vector3(); 26194 26195 } 26196 26197 return this._grip; 26198 26199 } 26200 26201 dispatchEvent( event ) { 26202 26203 if ( this._targetRay !== null ) { 26204 26205 this._targetRay.dispatchEvent( event ); 26206 26207 } 26208 26209 if ( this._grip !== null ) { 26210 26211 this._grip.dispatchEvent( event ); 26212 26213 } 26214 26215 if ( this._hand !== null ) { 26216 26217 this._hand.dispatchEvent( event ); 26218 26219 } 26220 26221 return this; 26222 26223 } 26224 26225 connect( inputSource ) { 26226 26227 if ( inputSource && inputSource.hand ) { 26228 26229 const hand = this._hand; 26230 26231 if ( hand ) { 26232 26233 for ( const inputjoint of inputSource.hand.values() ) { 26234 26235 // Initialize hand with joints when connected 26236 this._getHandJoint( hand, inputjoint ); 26237 26238 } 26239 26240 } 26241 26242 } 26243 26244 this.dispatchEvent( { type: 'connected', data: inputSource } ); 26245 26246 return this; 26247 26248 } 26249 26250 disconnect( inputSource ) { 26251 26252 this.dispatchEvent( { type: 'disconnected', data: inputSource } ); 26253 26254 if ( this._targetRay !== null ) { 26255 26256 this._targetRay.visible = false; 26257 26258 } 26259 26260 if ( this._grip !== null ) { 26261 26262 this._grip.visible = false; 26263 26264 } 26265 26266 if ( this._hand !== null ) { 26267 26268 this._hand.visible = false; 26269 26270 } 26271 26272 return this; 26273 26274 } 26275 26276 update( inputSource, frame, referenceSpace ) { 26277 26278 let inputPose = null; 26279 let gripPose = null; 26280 let handPose = null; 26281 26282 const targetRay = this._targetRay; 26283 const grip = this._grip; 26284 const hand = this._hand; 26285 26286 if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) { 26287 26288 if ( hand && inputSource.hand ) { 26289 26290 handPose = true; 26291 26292 for ( const inputjoint of inputSource.hand.values() ) { 26293 26294 // Update the joints groups with the XRJoint poses 26295 const jointPose = frame.getJointPose( inputjoint, referenceSpace ); 26296 26297 // The transform of this joint will be updated with the joint pose on each frame 26298 const joint = this._getHandJoint( hand, inputjoint ); 26299 26300 if ( jointPose !== null ) { 26301 26302 joint.matrix.fromArray( jointPose.transform.matrix ); 26303 joint.matrix.decompose( joint.position, joint.rotation, joint.scale ); 26304 joint.matrixWorldNeedsUpdate = true; 26305 joint.jointRadius = jointPose.radius; 26306 26307 } 26308 26309 joint.visible = jointPose !== null; 26310 26311 } 26312 26313 // Custom events 26314 26315 // Check pinchz 26316 const indexTip = hand.joints[ 'index-finger-tip' ]; 26317 const thumbTip = hand.joints[ 'thumb-tip' ]; 26318 const distance = indexTip.position.distanceTo( thumbTip.position ); 26319 26320 const distanceToPinch = 0.02; 26321 const threshold = 0.005; 26322 26323 if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) { 26324 26325 hand.inputState.pinching = false;
vendor: 24,774 bytes, lines 26326-27448
26326 this.dispatchEvent( { 26327 type: 'pinchend', 26328 handedness: inputSource.handedness, 26329 target: this 26330 } ); 26331 26332 } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) { 26333 26334 hand.inputState.pinching = true; 26335 this.dispatchEvent( { 26336 type: 'pinchstart', 26337 handedness: inputSource.handedness, 26338 target: this 26339 } ); 26340 26341 } 26342 26343 } else { 26344 26345 if ( grip !== null && inputSource.gripSpace ) { 26346 26347 gripPose = frame.getPose( inputSource.gripSpace, referenceSpace ); 26348 26349 if ( gripPose !== null ) { 26350 26351 grip.matrix.fromArray( gripPose.transform.matrix ); 26352 grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); 26353 grip.matrixWorldNeedsUpdate = true; 26354 26355 if ( gripPose.linearVelocity ) { 26356 26357 grip.hasLinearVelocity = true; 26358 grip.linearVelocity.copy( gripPose.linearVelocity ); 26359 26360 } else { 26361 26362 grip.hasLinearVelocity = false; 26363 26364 } 26365 26366 if ( gripPose.angularVelocity ) { 26367 26368 grip.hasAngularVelocity = true; 26369 grip.angularVelocity.copy( gripPose.angularVelocity ); 26370 26371 } else { 26372 26373 grip.hasAngularVelocity = false; 26374 26375 } 26376 26377 } 26378 26379 } 26380 26381 } 26382 26383 if ( targetRay !== null ) { 26384 26385 inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace ); 26386 26387 // Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it 26388 if ( inputPose === null && gripPose !== null ) { 26389 26390 inputPose = gripPose; 26391 26392 } 26393 26394 if ( inputPose !== null ) { 26395 26396 targetRay.matrix.fromArray( inputPose.transform.matrix ); 26397 targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); 26398 targetRay.matrixWorldNeedsUpdate = true; 26399 26400 if ( inputPose.linearVelocity ) { 26401 26402 targetRay.hasLinearVelocity = true; 26403 targetRay.linearVelocity.copy( inputPose.linearVelocity ); 26404 26405 } else { 26406 26407 targetRay.hasLinearVelocity = false; 26408 26409 } 26410 26411 if ( inputPose.angularVelocity ) { 26412 26413 targetRay.hasAngularVelocity = true; 26414 targetRay.angularVelocity.copy( inputPose.angularVelocity ); 26415 26416 } else { 26417 26418 targetRay.hasAngularVelocity = false; 26419 26420 } 26421 26422 this.dispatchEvent( _moveEvent ); 26423 26424 } 26425 26426 } 26427 26428 26429 } 26430 26431 if ( targetRay !== null ) { 26432 26433 targetRay.visible = ( inputPose !== null ); 26434 26435 } 26436 26437 if ( grip !== null ) { 26438 26439 grip.visible = ( gripPose !== null ); 26440 26441 } 26442 26443 if ( hand !== null ) { 26444 26445 hand.visible = ( handPose !== null ); 26446 26447 } 26448 26449 return this; 26450 26451 } 26452 26453 // private method 26454 26455 _getHandJoint( hand, inputjoint ) { 26456 26457 if ( hand.joints[ inputjoint.jointName ] === undefined ) { 26458 26459 const joint = new Group(); 26460 joint.matrixAutoUpdate = false; 26461 joint.visible = false; 26462 hand.joints[ inputjoint.jointName ] = joint; 26463 26464 hand.add( joint ); 26465 26466 } 26467 26468 return hand.joints[ inputjoint.jointName ]; 26469 26470 } 26471 26472} 26473 26474const _occlusion_vertex = ` 26475void main() { 26476 26477 gl_Position = vec4( position, 1.0 ); 26478 26479}`; 26480 26481const _occlusion_fragment = ` 26482uniform sampler2DArray depthColor; 26483uniform float depthWidth; 26484uniform float depthHeight; 26485 26486void main() { 26487 26488 vec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight ); 26489 26490 if ( coord.x >= 1.0 ) { 26491 26492 gl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r; 26493 26494 } else { 26495 26496 gl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r; 26497 26498 } 26499 26500}`; 26501 26502class WebXRDepthSensing { 26503 26504 constructor() { 26505 26506 this.texture = null; 26507 this.mesh = null; 26508 26509 this.depthNear = 0; 26510 this.depthFar = 0; 26511 26512 } 26513 26514 init( renderer, depthData, renderState ) { 26515 26516 if ( this.texture === null ) { 26517 26518 const texture = new Texture(); 26519 26520 const texProps = renderer.properties.get( texture ); 26521 texProps.__webglTexture = depthData.texture; 26522 26523 if ( ( depthData.depthNear != renderState.depthNear ) || ( depthData.depthFar != renderState.depthFar ) ) { 26524 26525 this.depthNear = depthData.depthNear; 26526 this.depthFar = depthData.depthFar; 26527 26528 } 26529 26530 this.texture = texture; 26531 26532 } 26533 26534 } 26535 26536 getMesh( cameraXR ) { 26537 26538 if ( this.texture !== null ) { 26539 26540 if ( this.mesh === null ) { 26541 26542 const viewport = cameraXR.cameras[ 0 ].viewport; 26543 const material = new ShaderMaterial( { 26544 vertexShader: _occlusion_vertex, 26545 fragmentShader: _occlusion_fragment, 26546 uniforms: { 26547 depthColor: { value: this.texture }, 26548 depthWidth: { value: viewport.z }, 26549 depthHeight: { value: viewport.w } 26550 } 26551 } ); 26552 26553 this.mesh = new Mesh( new PlaneGeometry( 20, 20 ), material ); 26554 26555 } 26556 26557 } 26558 26559 return this.mesh; 26560 26561 } 26562 26563 reset() { 26564 26565 this.texture = null; 26566 this.mesh = null; 26567 26568 } 26569 26570} 26571 26572class WebXRManager extends EventDispatcher { 26573 26574 constructor( renderer, gl ) { 26575 26576 super(); 26577 26578 const scope = this; 26579 26580 let session = null; 26581 26582 let framebufferScaleFactor = 1.0; 26583 26584 let referenceSpace = null; 26585 let referenceSpaceType = 'local-floor'; 26586 // Set default foveation to maximum. 26587 let foveation = 1.0; 26588 let customReferenceSpace = null; 26589 26590 let pose = null; 26591 let glBinding = null; 26592 let glProjLayer = null; 26593 let glBaseLayer = null; 26594 let xrFrame = null; 26595 26596 const depthSensing = new WebXRDepthSensing(); 26597 const attributes = gl.getContextAttributes(); 26598 26599 let initialRenderTarget = null; 26600 let newRenderTarget = null; 26601 26602 const controllers = []; 26603 const controllerInputSources = []; 26604 26605 const currentSize = new Vector2(); 26606 let currentPixelRatio = null; 26607 26608 // 26609 26610 const cameraL = new PerspectiveCamera(); 26611 cameraL.layers.enable( 1 ); 26612 cameraL.viewport = new Vector4(); 26613 26614 const cameraR = new PerspectiveCamera(); 26615 cameraR.layers.enable( 2 ); 26616 cameraR.viewport = new Vector4(); 26617 26618 const cameras = [ cameraL, cameraR ]; 26619 26620 const cameraXR = new ArrayCamera(); 26621 cameraXR.layers.enable( 1 ); 26622 cameraXR.layers.enable( 2 ); 26623 26624 let _currentDepthNear = null; 26625 let _currentDepthFar = null; 26626 26627 // 26628 26629 this.cameraAutoUpdate = true; 26630 this.enabled = false; 26631 26632 this.isPresenting = false; 26633 26634 this.getController = function ( index ) { 26635 26636 let controller = controllers[ index ]; 26637 26638 if ( controller === undefined ) { 26639 26640 controller = new WebXRController(); 26641 controllers[ index ] = controller; 26642 26643 } 26644 26645 return controller.getTargetRaySpace(); 26646 26647 }; 26648 26649 this.getControllerGrip = function ( index ) { 26650 26651 let controller = controllers[ index ]; 26652 26653 if ( controller === undefined ) { 26654 26655 controller = new WebXRController(); 26656 controllers[ index ] = controller; 26657 26658 } 26659 26660 return controller.getGripSpace(); 26661 26662 }; 26663 26664 this.getHand = function ( index ) { 26665 26666 let controller = controllers[ index ]; 26667 26668 if ( controller === undefined ) { 26669 26670 controller = new WebXRController(); 26671 controllers[ index ] = controller; 26672 26673 } 26674 26675 return controller.getHandSpace(); 26676 26677 }; 26678 26679 // 26680 26681 function onSessionEvent( event ) { 26682 26683 const controllerIndex = controllerInputSources.indexOf( event.inputSource ); 26684 26685 if ( controllerIndex === - 1 ) { 26686 26687 return; 26688 26689 } 26690 26691 const controller = controllers[ controllerIndex ]; 26692 26693 if ( controller !== undefined ) { 26694 26695 controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace ); 26696 controller.dispatchEvent( { type: event.type, data: event.inputSource } ); 26697 26698 } 26699 26700 } 26701 26702 function onSessionEnd() { 26703 26704 session.removeEventListener( 'select', onSessionEvent ); 26705 session.removeEventListener( 'selectstart', onSessionEvent ); 26706 session.removeEventListener( 'selectend', onSessionEvent ); 26707 session.removeEventListener( 'squeeze', onSessionEvent ); 26708 session.removeEventListener( 'squeezestart', onSessionEvent ); 26709 session.removeEventListener( 'squeezeend', onSessionEvent ); 26710 session.removeEventListener( 'end', onSessionEnd ); 26711 session.removeEventListener( 'inputsourceschange', onInputSourcesChange ); 26712 26713 for ( let i = 0; i < controllers.length; i ++ ) { 26714 26715 const inputSource = controllerInputSources[ i ]; 26716 26717 if ( inputSource === null ) continue; 26718 26719 controllerInputSources[ i ] = null; 26720 26721 controllers[ i ].disconnect( inputSource ); 26722 26723 } 26724 26725 _currentDepthNear = null; 26726 _currentDepthFar = null; 26727 26728 depthSensing.reset(); 26729 26730 // restore framebuffer/rendering state 26731 26732 renderer.setRenderTarget( initialRenderTarget ); 26733 26734 glBaseLayer = null; 26735 glProjLayer = null; 26736 glBinding = null; 26737 session = null; 26738 newRenderTarget = null; 26739 26740 // 26741 26742 animation.stop(); 26743 26744 scope.isPresenting = false; 26745 26746 renderer.setPixelRatio( currentPixelRatio ); 26747 renderer.setSize( currentSize.width, currentSize.height, false ); 26748 26749 scope.dispatchEvent( { type: 'sessionend' } ); 26750 26751 } 26752 26753 this.setFramebufferScaleFactor = function ( value ) { 26754 26755 framebufferScaleFactor = value; 26756 26757 if ( scope.isPresenting === true ) { 26758 26759 console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' ); 26760 26761 } 26762 26763 }; 26764 26765 this.setReferenceSpaceType = function ( value ) { 26766 26767 referenceSpaceType = value; 26768 26769 if ( scope.isPresenting === true ) { 26770 26771 console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' ); 26772 26773 } 26774 26775 }; 26776 26777 this.getReferenceSpace = function () { 26778 26779 return customReferenceSpace || referenceSpace; 26780 26781 }; 26782 26783 this.setReferenceSpace = function ( space ) { 26784 26785 customReferenceSpace = space; 26786 26787 }; 26788 26789 this.getBaseLayer = function () { 26790 26791 return glProjLayer !== null ? glProjLayer : glBaseLayer; 26792 26793 }; 26794 26795 this.getBinding = function () { 26796 26797 return glBinding; 26798 26799 }; 26800 26801 this.getFrame = function () { 26802 26803 return xrFrame; 26804 26805 }; 26806 26807 this.getSession = function () { 26808 26809 return session; 26810 26811 }; 26812 26813 this.setSession = async function ( value ) { 26814 26815 session = value; 26816 26817 if ( session !== null ) { 26818 26819 initialRenderTarget = renderer.getRenderTarget(); 26820 26821 session.addEventListener( 'select', onSessionEvent ); 26822 session.addEventListener( 'selectstart', onSessionEvent ); 26823 session.addEventListener( 'selectend', onSessionEvent ); 26824 session.addEventListener( 'squeeze', onSessionEvent ); 26825 session.addEventListener( 'squeezestart', onSessionEvent ); 26826 session.addEventListener( 'squeezeend', onSessionEvent ); 26827 session.addEventListener( 'end', onSessionEnd ); 26828 session.addEventListener( 'inputsourceschange', onInputSourcesChange ); 26829 26830 if ( attributes.xrCompatible !== true ) { 26831 26832 await gl.makeXRCompatible(); 26833 26834 } 26835 26836 currentPixelRatio = renderer.getPixelRatio(); 26837 renderer.getSize( currentSize ); 26838 26839 if ( session.renderState.layers === undefined ) { 26840 26841 const layerInit = { 26842 antialias: attributes.antialias, 26843 alpha: true, 26844 depth: attributes.depth, 26845 stencil: attributes.stencil, 26846 framebufferScaleFactor: framebufferScaleFactor 26847 }; 26848 26849 glBaseLayer = new XRWebGLLayer( session, gl, layerInit ); 26850 26851 session.updateRenderState( { baseLayer: glBaseLayer } ); 26852 26853 renderer.setPixelRatio( 1 ); 26854 renderer.setSize( glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, false ); 26855 26856 newRenderTarget = new WebGLRenderTarget( 26857 glBaseLayer.framebufferWidth, 26858 glBaseLayer.framebufferHeight, 26859 { 26860 format: RGBAFormat, 26861 type: UnsignedByteType, 26862 colorSpace: renderer.outputColorSpace, 26863 stencilBuffer: attributes.stencil 26864 } 26865 ); 26866 26867 } else { 26868 26869 let depthFormat = null; 26870 let depthType = null; 26871 let glDepthFormat = null; 26872 26873 if ( attributes.depth ) { 26874 26875 glDepthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24; 26876 depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat; 26877 depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType; 26878 26879 } 26880 26881 const projectionlayerInit = { 26882 colorFormat: gl.RGBA8, 26883 depthFormat: glDepthFormat, 26884 scaleFactor: framebufferScaleFactor 26885 }; 26886 26887 glBinding = new XRWebGLBinding( session, gl ); 26888 26889 glProjLayer = glBinding.createProjectionLayer( projectionlayerInit ); 26890 26891 session.updateRenderState( { layers: [ glProjLayer ] } ); 26892 26893 renderer.setPixelRatio( 1 ); 26894 renderer.setSize( glProjLayer.textureWidth, glProjLayer.textureHeight, false ); 26895 26896 newRenderTarget = new WebGLRenderTarget( 26897 glProjLayer.textureWidth, 26898 glProjLayer.textureHeight, 26899 { 26900 format: RGBAFormat, 26901 type: UnsignedByteType, 26902 depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), 26903 stencilBuffer: attributes.stencil, 26904 colorSpace: renderer.outputColorSpace, 26905 samples: attributes.antialias ? 4 : 0, 26906 resolveDepthBuffer: ( glProjLayer.ignoreDepthValues === false ) 26907 } ); 26908 26909 } 26910 26911 newRenderTarget.isXRRenderTarget = true; // TODO Remove this when possible, see #23278 26912 26913 this.setFoveation( foveation ); 26914 26915 customReferenceSpace = null; 26916 referenceSpace = await session.requestReferenceSpace( referenceSpaceType ); 26917 26918 animation.setContext( session ); 26919 animation.start(); 26920 26921 scope.isPresenting = true; 26922 26923 scope.dispatchEvent( { type: 'sessionstart' } ); 26924 26925 } 26926 26927 }; 26928 26929 this.getEnvironmentBlendMode = function () { 26930 26931 if ( session !== null ) { 26932 26933 return session.environmentBlendMode; 26934 26935 } 26936 26937 }; 26938 26939 function onInputSourcesChange( event ) { 26940 26941 // Notify disconnected 26942 26943 for ( let i = 0; i < event.removed.length; i ++ ) { 26944 26945 const inputSource = event.removed[ i ]; 26946 const index = controllerInputSources.indexOf( inputSource ); 26947 26948 if ( index >= 0 ) { 26949 26950 controllerInputSources[ index ] = null; 26951 controllers[ index ].disconnect( inputSource ); 26952 26953 } 26954 26955 } 26956 26957 // Notify connected 26958 26959 for ( let i = 0; i < event.added.length; i ++ ) { 26960 26961 const inputSource = event.added[ i ]; 26962 26963 let controllerIndex = controllerInputSources.indexOf( inputSource ); 26964 26965 if ( controllerIndex === - 1 ) { 26966 26967 // Assign input source a controller that currently has no input source 26968 26969 for ( let i = 0; i < controllers.length; i ++ ) { 26970 26971 if ( i >= controllerInputSources.length ) { 26972 26973 controllerInputSources.push( inputSource ); 26974 controllerIndex = i; 26975 break; 26976 26977 } else if ( controllerInputSources[ i ] === null ) { 26978 26979 controllerInputSources[ i ] = inputSource; 26980 controllerIndex = i; 26981 break; 26982 26983 } 26984 26985 } 26986 26987 // If all controllers do currently receive input we ignore new ones 26988 26989 if ( controllerIndex === - 1 ) break; 26990 26991 } 26992 26993 const controller = controllers[ controllerIndex ]; 26994 26995 if ( controller ) { 26996 26997 controller.connect( inputSource ); 26998 26999 } 27000 27001 } 27002 27003 } 27004 27005 // 27006 27007 const cameraLPos = new Vector3(); 27008 const cameraRPos = new Vector3(); 27009 27010 /** 27011 * Assumes 2 cameras that are parallel and share an X-axis, and that 27012 * the cameras' projection and world matrices have already been set. 27013 * And that near and far planes are identical for both cameras. 27014 * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 27015 */ 27016 function setProjectionFromUnion( camera, cameraL, cameraR ) { 27017 27018 cameraLPos.setFromMatrixPosition( cameraL.matrixWorld ); 27019 cameraRPos.setFromMatrixPosition( cameraR.matrixWorld ); 27020 27021 const ipd = cameraLPos.distanceTo( cameraRPos ); 27022 27023 const projL = cameraL.projectionMatrix.elements; 27024 const projR = cameraR.projectionMatrix.elements; 27025 27026 // VR systems will have identical far and near planes, and 27027 // most likely identical top and bottom frustum extents. 27028 // Use the left camera for these values. 27029 const near = projL[ 14 ] / ( projL[ 10 ] - 1 ); 27030 const far = projL[ 14 ] / ( projL[ 10 ] + 1 ); 27031 const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ]; 27032 const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ]; 27033 27034 const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ]; 27035 const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ]; 27036 const left = near * leftFov; 27037 const right = near * rightFov; 27038 27039 // Calculate the new camera's position offset from the 27040 // left camera. xOffset should be roughly half `ipd`. 27041 const zOffset = ipd / ( - leftFov + rightFov ); 27042 const xOffset = zOffset * - leftFov; 27043 27044 // TODO: Better way to apply this offset? 27045 cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale ); 27046 camera.translateX( xOffset ); 27047 camera.translateZ( zOffset ); 27048 camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale ); 27049 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); 27050 27051 // Find the union of the frustum values of the cameras and scale 27052 // the values so that the near plane's position does not change in world space, 27053 // although must now be relative to the new union camera. 27054 const near2 = near + zOffset; 27055 const far2 = far + zOffset; 27056 const left2 = left - xOffset; 27057 const right2 = right + ( ipd - xOffset ); 27058 const top2 = topFov * far / far2 * near2; 27059 const bottom2 = bottomFov * far / far2 * near2; 27060 27061 camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); 27062 camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); 27063 27064 } 27065 27066 function updateCamera( camera, parent ) { 27067 27068 if ( parent === null ) { 27069 27070 camera.matrixWorld.copy( camera.matrix ); 27071 27072 } else { 27073 27074 camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix ); 27075 27076 } 27077 27078 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); 27079 27080 } 27081 27082 this.updateCamera = function ( camera ) { 27083 27084 if ( session === null ) return; 27085 27086 if ( depthSensing.texture !== null ) { 27087 27088 camera.near = depthSensing.depthNear; 27089 camera.far = depthSensing.depthFar; 27090 27091 } 27092 27093 cameraXR.near = cameraR.near = cameraL.near = camera.near; 27094 cameraXR.far = cameraR.far = cameraL.far = camera.far; 27095 27096 if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) { 27097 27098 // Note that the new renderState won't apply until the next frame. See #18320 27099 27100 session.updateRenderState( { 27101 depthNear: cameraXR.near, 27102 depthFar: cameraXR.far 27103 } ); 27104 27105 _currentDepthNear = cameraXR.near; 27106 _currentDepthFar = cameraXR.far; 27107 27108 cameraL.near = _currentDepthNear; 27109 cameraL.far = _currentDepthFar; 27110 cameraR.near = _currentDepthNear; 27111 cameraR.far = _currentDepthFar; 27112 27113 cameraL.updateProjectionMatrix(); 27114 cameraR.updateProjectionMatrix(); 27115 camera.updateProjectionMatrix(); 27116 27117 } 27118 27119 const parent = camera.parent; 27120 const cameras = cameraXR.cameras; 27121 27122 updateCamera( cameraXR, parent ); 27123 27124 for ( let i = 0; i < cameras.length; i ++ ) { 27125 27126 updateCamera( cameras[ i ], parent ); 27127 27128 } 27129 27130 // update projection matrix for proper view frustum culling 27131 27132 if ( cameras.length === 2 ) { 27133 27134 setProjectionFromUnion( cameraXR, cameraL, cameraR ); 27135 27136 } else { 27137 27138 // assume single camera setup (AR) 27139 27140 cameraXR.projectionMatrix.copy( cameraL.projectionMatrix ); 27141 27142 } 27143 27144 // update user camera and its children 27145 27146 updateUserCamera( camera, cameraXR, parent ); 27147 27148 }; 27149 27150 function updateUserCamera( camera, cameraXR, parent ) { 27151 27152 if ( parent === null ) { 27153 27154 camera.matrix.copy( cameraXR.matrixWorld ); 27155 27156 } else { 27157 27158 camera.matrix.copy( parent.matrixWorld ); 27159 camera.matrix.invert(); 27160 camera.matrix.multiply( cameraXR.matrixWorld ); 27161 27162 } 27163 27164 camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); 27165 camera.updateMatrixWorld( true ); 27166 27167 camera.projectionMatrix.copy( cameraXR.projectionMatrix ); 27168 camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse ); 27169 27170 if ( camera.isPerspectiveCamera ) { 27171 27172 camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] ); 27173 camera.zoom = 1; 27174 27175 } 27176 27177 } 27178 27179 this.getCamera = function () { 27180 27181 return cameraXR; 27182 27183 }; 27184 27185 this.getFoveation = function () { 27186 27187 if ( glProjLayer === null && glBaseLayer === null ) { 27188 27189 return undefined; 27190 27191 } 27192 27193 return foveation; 27194 27195 }; 27196 27197 this.setFoveation = function ( value ) { 27198 27199 // 0 = no foveation = full resolution 27200 // 1 = maximum foveation = the edges render at lower resolution 27201 27202 foveation = value; 27203 27204 if ( glProjLayer !== null ) { 27205 27206 glProjLayer.fixedFoveation = value; 27207 27208 } 27209 27210 if ( glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined ) { 27211 27212 glBaseLayer.fixedFoveation = value; 27213 27214 } 27215 27216 }; 27217 27218 this.hasDepthSensing = function () { 27219 27220 return depthSensing.texture !== null; 27221 27222 }; 27223 27224 this.getDepthSensingMesh = function () { 27225 27226 return depthSensing.getMesh( cameraXR ); 27227 27228 }; 27229 27230 // Animation Loop 27231 27232 let onAnimationFrameCallback = null; 27233 27234 function onAnimationFrame( time, frame ) { 27235 27236 pose = frame.getViewerPose( customReferenceSpace || referenceSpace ); 27237 xrFrame = frame; 27238 27239 if ( pose !== null ) { 27240 27241 const views = pose.views; 27242 27243 if ( glBaseLayer !== null ) { 27244 27245 renderer.setRenderTargetFramebuffer( newRenderTarget, glBaseLayer.framebuffer ); 27246 renderer.setRenderTarget( newRenderTarget ); 27247 27248 } 27249 27250 let cameraXRNeedsUpdate = false; 27251 27252 // check if it's necessary to rebuild cameraXR's camera list 27253 27254 if ( views.length !== cameraXR.cameras.length ) { 27255 27256 cameraXR.cameras.length = 0; 27257 cameraXRNeedsUpdate = true; 27258 27259 } 27260 27261 for ( let i = 0; i < views.length; i ++ ) { 27262 27263 const view = views[ i ]; 27264 27265 let viewport = null; 27266 27267 if ( glBaseLayer !== null ) { 27268 27269 viewport = glBaseLayer.getViewport( view ); 27270 27271 } else { 27272 27273 const glSubImage = glBinding.getViewSubImage( glProjLayer, view ); 27274 viewport = glSubImage.viewport; 27275 27276 // For side-by-side projection, we only produce a single texture for both eyes. 27277 if ( i === 0 ) { 27278 27279 renderer.setRenderTargetTextures( 27280 newRenderTarget, 27281 glSubImage.colorTexture, 27282 glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture ); 27283 27284 renderer.setRenderTarget( newRenderTarget ); 27285 27286 } 27287 27288 } 27289 27290 let camera = cameras[ i ]; 27291 27292 if ( camera === undefined ) { 27293 27294 camera = new PerspectiveCamera(); 27295 camera.layers.enable( i ); 27296 camera.viewport = new Vector4(); 27297 cameras[ i ] = camera; 27298 27299 } 27300 27301 camera.matrix.fromArray( view.transform.matrix ); 27302 camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); 27303 camera.projectionMatrix.fromArray( view.projectionMatrix ); 27304 camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); 27305 camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); 27306 27307 if ( i === 0 ) { 27308 27309 cameraXR.matrix.copy( camera.matrix ); 27310 cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale ); 27311 27312 } 27313 27314 if ( cameraXRNeedsUpdate === true ) { 27315 27316 cameraXR.cameras.push( camera ); 27317 27318 } 27319 27320 } 27321 27322 // 27323 27324 const enabledFeatures = session.enabledFeatures; 27325 27326 if ( enabledFeatures && enabledFeatures.includes( 'depth-sensing' ) ) { 27327 27328 const depthData = glBinding.getDepthInformation( views[ 0 ] ); 27329 27330 if ( depthData && depthData.isValid && depthData.texture ) { 27331 27332 depthSensing.init( renderer, depthData, session.renderState ); 27333 27334 } 27335 27336 } 27337 27338 } 27339 27340 // 27341 27342 for ( let i = 0; i < controllers.length; i ++ ) { 27343 27344 const inputSource = controllerInputSources[ i ]; 27345 const controller = controllers[ i ]; 27346 27347 if ( inputSource !== null && controller !== undefined ) { 27348 27349 controller.update( inputSource, frame, customReferenceSpace || referenceSpace ); 27350 27351 } 27352 27353 } 27354 27355 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame ); 27356 27357 if ( frame.detectedPlanes ) { 27358 27359 scope.dispatchEvent( { type: 'planesdetected', data: frame } ); 27360 27361 } 27362 27363 xrFrame = null; 27364 27365 } 27366 27367 const animation = new WebGLAnimation(); 27368 27369 animation.setAnimationLoop( onAnimationFrame ); 27370 27371 this.setAnimationLoop = function ( callback ) { 27372 27373 onAnimationFrameCallback = callback; 27374 27375 }; 27376 27377 this.dispose = function () {}; 27378 27379 } 27380 27381} 27382 27383const _e1 = /*@__PURE__*/ new Euler(); 27384const _m1 = /*@__PURE__*/ new Matrix4(); 27385 27386function WebGLMaterials( renderer, properties ) { 27387 27388 function refreshTransformUniform( map, uniform ) { 27389 27390 if ( map.matrixAutoUpdate === true ) { 27391 27392 map.updateMatrix(); 27393 27394 } 27395 27396 uniform.value.copy( map.matrix ); 27397 27398 } 27399 27400 function refreshFogUniforms( uniforms, fog ) { 27401 27402 fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) ); 27403 27404 if ( fog.isFog ) { 27405 27406 uniforms.fogNear.value = fog.near; 27407 uniforms.fogFar.value = fog.far; 27408 27409 } else if ( fog.isFogExp2 ) { 27410 27411 uniforms.fogDensity.value = fog.density; 27412 27413 } 27414 27415 } 27416 27417 function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) { 27418 27419 if ( material.isMeshBasicMaterial ) { 27420 27421 refreshUniformsCommon( uniforms, material ); 27422 27423 } else if ( material.isMeshLambertMaterial ) { 27424 27425 refreshUniformsCommon( uniforms, material ); 27426 27427 } else if ( material.isMeshToonMaterial ) { 27428 27429 refreshUniformsCommon( uniforms, material ); 27430 refreshUniformsToon( uniforms, material ); 27431 27432 } else if ( material.isMeshPhongMaterial ) { 27433 27434 refreshUniformsCommon( uniforms, material ); 27435 refreshUniformsPhong( uniforms, material ); 27436 27437 } else if ( material.isMeshStandardMaterial ) { 27438 27439 refreshUniformsCommon( uniforms, material ); 27440 refreshUniformsStandard( uniforms, material ); 27441 27442 if ( material.isMeshPhysicalMaterial ) { 27443 27444 refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ); 27445 27446 } 27447 27448 }
vendor: 14,159 bytes, lines 27448-28041
27448 else if ( material.isMeshMatcapMaterial ) { 27449 27450 refreshUniformsCommon( uniforms, material ); 27451 refreshUniformsMatcap( uniforms, material ); 27452 27453 } else if ( material.isMeshDepthMaterial ) { 27454 27455 refreshUniformsCommon( uniforms, material ); 27456 27457 } else if ( material.isMeshDistanceMaterial ) { 27458 27459 refreshUniformsCommon( uniforms, material ); 27460 refreshUniformsDistance( uniforms, material ); 27461 27462 } else if ( material.isMeshNormalMaterial ) { 27463 27464 refreshUniformsCommon( uniforms, material ); 27465 27466 } else if ( material.isLineBasicMaterial ) { 27467 27468 refreshUniformsLine( uniforms, material ); 27469 27470 if ( material.isLineDashedMaterial ) { 27471 27472 refreshUniformsDash( uniforms, material ); 27473 27474 } 27475 27476 } else if ( material.isPointsMaterial ) { 27477 27478 refreshUniformsPoints( uniforms, material, pixelRatio, height ); 27479 27480 } else if ( material.isSpriteMaterial ) { 27481 27482 refreshUniformsSprites( uniforms, material ); 27483 27484 } else if ( material.isShadowMaterial ) { 27485 27486 uniforms.color.value.copy( material.color ); 27487 uniforms.opacity.value = material.opacity; 27488 27489 } else if ( material.isShaderMaterial ) { 27490 27491 material.uniformsNeedUpdate = false; // #15581 27492 27493 } 27494 27495 } 27496 27497 function refreshUniformsCommon( uniforms, material ) { 27498 27499 uniforms.opacity.value = material.opacity; 27500 27501 if ( material.color ) { 27502 27503 uniforms.diffuse.value.copy( material.color ); 27504 27505 } 27506 27507 if ( material.emissive ) { 27508 27509 uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity ); 27510 27511 } 27512 27513 if ( material.map ) { 27514 27515 uniforms.map.value = material.map; 27516 27517 refreshTransformUniform( material.map, uniforms.mapTransform ); 27518 27519 } 27520 27521 if ( material.alphaMap ) { 27522 27523 uniforms.alphaMap.value = material.alphaMap; 27524 27525 refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); 27526 27527 } 27528 27529 if ( material.bumpMap ) { 27530 27531 uniforms.bumpMap.value = material.bumpMap; 27532 27533 refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform ); 27534 27535 uniforms.bumpScale.value = material.bumpScale; 27536 27537 if ( material.side === BackSide ) { 27538 27539 uniforms.bumpScale.value *= - 1; 27540 27541 } 27542 27543 } 27544 27545 if ( material.normalMap ) { 27546 27547 uniforms.normalMap.value = material.normalMap; 27548 27549 refreshTransformUniform( material.normalMap, uniforms.normalMapTransform ); 27550 27551 uniforms.normalScale.value.copy( material.normalScale ); 27552 27553 if ( material.side === BackSide ) { 27554 27555 uniforms.normalScale.value.negate(); 27556 27557 } 27558 27559 } 27560 27561 if ( material.displacementMap ) { 27562 27563 uniforms.displacementMap.value = material.displacementMap; 27564 27565 refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform ); 27566 27567 uniforms.displacementScale.value = material.displacementScale; 27568 uniforms.displacementBias.value = material.displacementBias; 27569 27570 } 27571 27572 if ( material.emissiveMap ) { 27573 27574 uniforms.emissiveMap.value = material.emissiveMap; 27575 27576 refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform ); 27577 27578 } 27579 27580 if ( material.specularMap ) { 27581 27582 uniforms.specularMap.value = material.specularMap; 27583 27584 refreshTransformUniform( material.specularMap, uniforms.specularMapTransform ); 27585 27586 } 27587 27588 if ( material.alphaTest > 0 ) { 27589 27590 uniforms.alphaTest.value = material.alphaTest; 27591 27592 } 27593 27594 const materialProperties = properties.get( material ); 27595 27596 const envMap = materialProperties.envMap; 27597 const envMapRotation = materialProperties.envMapRotation; 27598 27599 if ( envMap ) { 27600 27601 uniforms.envMap.value = envMap; 27602 27603 _e1.copy( envMapRotation ); 27604 27605 // accommodate left-handed frame 27606 _e1.x *= - 1; _e1.y *= - 1; _e1.z *= - 1; 27607 27608 if ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) { 27609 27610 // environment maps which are not cube render targets or PMREMs follow a different convention 27611 _e1.y *= - 1; 27612 _e1.z *= - 1; 27613 27614 } 27615 27616 uniforms.envMapRotation.value.setFromMatrix4( _m1.makeRotationFromEuler( _e1 ) ); 27617 27618 uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; 27619 27620 uniforms.reflectivity.value = material.reflectivity; 27621 uniforms.ior.value = material.ior; 27622 uniforms.refractionRatio.value = material.refractionRatio; 27623 27624 } 27625 27626 if ( material.lightMap ) { 27627 27628 uniforms.lightMap.value = material.lightMap; 27629 uniforms.lightMapIntensity.value = material.lightMapIntensity; 27630 27631 refreshTransformUniform( material.lightMap, uniforms.lightMapTransform ); 27632 27633 } 27634 27635 if ( material.aoMap ) { 27636 27637 uniforms.aoMap.value = material.aoMap; 27638 uniforms.aoMapIntensity.value = material.aoMapIntensity; 27639 27640 refreshTransformUniform( material.aoMap, uniforms.aoMapTransform ); 27641 27642 } 27643 27644 } 27645 27646 function refreshUniformsLine( uniforms, material ) { 27647 27648 uniforms.diffuse.value.copy( material.color ); 27649 uniforms.opacity.value = material.opacity; 27650 27651 if ( material.map ) { 27652 27653 uniforms.map.value = material.map; 27654 27655 refreshTransformUniform( material.map, uniforms.mapTransform ); 27656 27657 } 27658 27659 } 27660 27661 function refreshUniformsDash( uniforms, material ) { 27662 27663 uniforms.dashSize.value = material.dashSize; 27664 uniforms.totalSize.value = material.dashSize + material.gapSize; 27665 uniforms.scale.value = material.scale; 27666 27667 } 27668 27669 function refreshUniformsPoints( uniforms, material, pixelRatio, height ) { 27670 27671 uniforms.diffuse.value.copy( material.color ); 27672 uniforms.opacity.value = material.opacity; 27673 uniforms.size.value = material.size * pixelRatio; 27674 uniforms.scale.value = height * 0.5; 27675 27676 if ( material.map ) { 27677 27678 uniforms.map.value = material.map; 27679 27680 refreshTransformUniform( material.map, uniforms.uvTransform ); 27681 27682 } 27683 27684 if ( material.alphaMap ) { 27685 27686 uniforms.alphaMap.value = material.alphaMap; 27687 27688 refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); 27689 27690 } 27691 27692 if ( material.alphaTest > 0 ) { 27693 27694 uniforms.alphaTest.value = material.alphaTest; 27695 27696 } 27697 27698 } 27699 27700 function refreshUniformsSprites( uniforms, material ) { 27701 27702 uniforms.diffuse.value.copy( material.color ); 27703 uniforms.opacity.value = material.opacity; 27704 uniforms.rotation.value = material.rotation; 27705 27706 if ( material.map ) { 27707 27708 uniforms.map.value = material.map; 27709 27710 refreshTransformUniform( material.map, uniforms.mapTransform ); 27711 27712 } 27713 27714 if ( material.alphaMap ) { 27715 27716 uniforms.alphaMap.value = material.alphaMap; 27717 27718 refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); 27719 27720 } 27721 27722 if ( material.alphaTest > 0 ) { 27723 27724 uniforms.alphaTest.value = material.alphaTest; 27725 27726 } 27727 27728 } 27729 27730 function refreshUniformsPhong( uniforms, material ) { 27731 27732 uniforms.specular.value.copy( material.specular ); 27733 uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 ) 27734 27735 } 27736 27737 function refreshUniformsToon( uniforms, material ) { 27738 27739 if ( material.gradientMap ) { 27740 27741 uniforms.gradientMap.value = material.gradientMap; 27742 27743 } 27744 27745 } 27746 27747 function refreshUniformsStandard( uniforms, material ) { 27748 27749 uniforms.metalness.value = material.metalness; 27750 27751 if ( material.metalnessMap ) { 27752 27753 uniforms.metalnessMap.value = material.metalnessMap; 27754 27755 refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform ); 27756 27757 } 27758 27759 uniforms.roughness.value = material.roughness; 27760 27761 if ( material.roughnessMap ) { 27762 27763 uniforms.roughnessMap.value = material.roughnessMap; 27764 27765 refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform ); 27766 27767 } 27768 27769 if ( material.envMap ) { 27770 27771 //uniforms.envMap.value = material.envMap; // part of uniforms common 27772 27773 uniforms.envMapIntensity.value = material.envMapIntensity; 27774 27775 } 27776 27777 } 27778 27779 function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) { 27780 27781 uniforms.ior.value = material.ior; // also part of uniforms common 27782 27783 if ( material.sheen > 0 ) { 27784 27785 uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen ); 27786 27787 uniforms.sheenRoughness.value = material.sheenRoughness; 27788 27789 if ( material.sheenColorMap ) { 27790 27791 uniforms.sheenColorMap.value = material.sheenColorMap; 27792 27793 refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform ); 27794 27795 } 27796 27797 if ( material.sheenRoughnessMap ) { 27798 27799 uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; 27800 27801 refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform ); 27802 27803 } 27804 27805 } 27806 27807 if ( material.clearcoat > 0 ) { 27808 27809 uniforms.clearcoat.value = material.clearcoat; 27810 uniforms.clearcoatRoughness.value = material.clearcoatRoughness; 27811 27812 if ( material.clearcoatMap ) { 27813 27814 uniforms.clearcoatMap.value = material.clearcoatMap; 27815 27816 refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform ); 27817 27818 } 27819 27820 if ( material.clearcoatRoughnessMap ) { 27821 27822 uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; 27823 27824 refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform ); 27825 27826 } 27827 27828 if ( material.clearcoatNormalMap ) { 27829 27830 uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; 27831 27832 refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform ); 27833 27834 uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); 27835 27836 if ( material.side === BackSide ) { 27837 27838 uniforms.clearcoatNormalScale.value.negate(); 27839 27840 } 27841 27842 } 27843 27844 } 27845 27846 if ( material.dispersion > 0 ) { 27847 27848 uniforms.dispersion.value = material.dispersion; 27849 27850 } 27851 27852 if ( material.iridescence > 0 ) { 27853 27854 uniforms.iridescence.value = material.iridescence; 27855 uniforms.iridescenceIOR.value = material.iridescenceIOR; 27856 uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[ 0 ]; 27857 uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[ 1 ]; 27858 27859 if ( material.iridescenceMap ) { 27860 27861 uniforms.iridescenceMap.value = material.iridescenceMap; 27862 27863 refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform ); 27864 27865 } 27866 27867 if ( material.iridescenceThicknessMap ) { 27868 27869 uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; 27870 27871 refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform ); 27872 27873 } 27874 27875 } 27876 27877 if ( material.transmission > 0 ) { 27878 27879 uniforms.transmission.value = material.transmission; 27880 uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture; 27881 uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height ); 27882 27883 if ( material.transmissionMap ) { 27884 27885 uniforms.transmissionMap.value = material.transmissionMap; 27886 27887 refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform ); 27888 27889 } 27890 27891 uniforms.thickness.value = material.thickness; 27892 27893 if ( material.thicknessMap ) { 27894 27895 uniforms.thicknessMap.value = material.thicknessMap; 27896 27897 refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform ); 27898 27899 } 27900 27901 uniforms.attenuationDistance.value = material.attenuationDistance; 27902 uniforms.attenuationColor.value.copy( material.attenuationColor ); 27903 27904 } 27905 27906 if ( material.anisotropy > 0 ) { 27907 27908 uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); 27909 27910 if ( material.anisotropyMap ) { 27911 27912 uniforms.anisotropyMap.value = material.anisotropyMap; 27913 27914 refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform ); 27915 27916 } 27917 27918 } 27919 27920 uniforms.specularIntensity.value = material.specularIntensity; 27921 uniforms.specularColor.value.copy( material.specularColor ); 27922 27923 if ( material.specularColorMap ) { 27924 27925 uniforms.specularColorMap.value = material.specularColorMap; 27926 27927 refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform ); 27928 27929 } 27930 27931 if ( material.specularIntensityMap ) { 27932 27933 uniforms.specularIntensityMap.value = material.specularIntensityMap; 27934 27935 refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform ); 27936 27937 } 27938 27939 } 27940 27941 function refreshUniformsMatcap( uniforms, material ) { 27942 27943 if ( material.matcap ) { 27944 27945 uniforms.matcap.value = material.matcap; 27946 27947 } 27948 27949 } 27950 27951 function refreshUniformsDistance( uniforms, material ) { 27952 27953 const light = properties.get( material ).light; 27954 27955 uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld ); 27956 uniforms.nearDistance.value = light.shadow.camera.near; 27957 uniforms.farDistance.value = light.shadow.camera.far; 27958 27959 } 27960 27961 return { 27962 refreshFogUniforms: refreshFogUniforms, 27963 refreshMaterialUniforms: refreshMaterialUniforms 27964 }; 27965 27966} 27967 27968function WebGLUniformsGroups( gl, info, capabilities, state ) { 27969 27970 let buffers = {}; 27971 let updateList = {}; 27972 let allocatedBindingPoints = []; 27973 27974 const maxBindingPoints = gl.getParameter( gl.MAX_UNIFORM_BUFFER_BINDINGS ); // binding points are global whereas block indices are per shader program 27975 27976 function bind( uniformsGroup, program ) { 27977 27978 const webglProgram = program.program; 27979 state.uniformBlockBinding( uniformsGroup, webglProgram ); 27980 27981 } 27982 27983 function update( uniformsGroup, program ) { 27984 27985 let buffer = buffers[ uniformsGroup.id ]; 27986 27987 if ( buffer === undefined ) { 27988 27989 prepareUniformsGroup( uniformsGroup ); 27990 27991 buffer = createBuffer( uniformsGroup ); 27992 buffers[ uniformsGroup.id ] = buffer; 27993 27994 uniformsGroup.addEventListener( 'dispose', onUniformsGroupsDispose ); 27995 27996 } 27997 27998 // ensure to update the binding points/block indices mapping for this program 27999 28000 const webglProgram = program.program; 28001 state.updateUBOMapping( uniformsGroup, webglProgram ); 28002 28003 // update UBO once per frame 28004 28005 const frame = info.render.frame; 28006 28007 if ( updateList[ uniformsGroup.id ] !== frame ) { 28008 28009 updateBufferData( uniformsGroup ); 28010 28011 updateList[ uniformsGroup.id ] = frame; 28012 28013 } 28014 28015 } 28016 28017 function createBuffer( uniformsGroup ) { 28018 28019 // the setup of an UBO is independent of a particular shader program but global 28020 28021 const bindingPointIndex = allocateBindingPointIndex(); 28022 uniformsGroup.__bindingPointIndex = bindingPointIndex; 28023 28024 const buffer = gl.createBuffer(); 28025 const size = uniformsGroup.__size; 28026 const usage = uniformsGroup.usage; 28027 28028 gl.bindBuffer( gl.UNIFORM_BUFFER, buffer ); 28029 gl.bufferData( gl.UNIFORM_BUFFER, size, usage ); 28030 gl.bindBuffer( gl.UNIFORM_BUFFER, null ); 28031 gl.bindBufferBase( gl.UNIFORM_BUFFER, bindingPointIndex, buffer ); 28032 28033 return buffer; 28034 28035 } 28036 28037 function allocateBindingPointIndex() { 28038 28039 for ( let i = 0; i < maxBindingPoints; i ++ ) { 28040 28041 if ( allocatedBindingPoints.indexOf( i ) === -
vendor: 6,630 bytes, lines 28041-28366
280411 ) { 28042 28043 allocatedBindingPoints.push( i ); 28044 return i; 28045 28046 } 28047 28048 } 28049 28050 console.error( 'THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' ); 28051 28052 return 0; 28053 28054 } 28055 28056 function updateBufferData( uniformsGroup ) { 28057 28058 const buffer = buffers[ uniformsGroup.id ]; 28059 const uniforms = uniformsGroup.uniforms; 28060 const cache = uniformsGroup.__cache; 28061 28062 gl.bindBuffer( gl.UNIFORM_BUFFER, buffer ); 28063 28064 for ( let i = 0, il = uniforms.length; i < il; i ++ ) { 28065 28066 const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ]; 28067 28068 for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) { 28069 28070 const uniform = uniformArray[ j ]; 28071 28072 if ( hasUniformChanged( uniform, i, j, cache ) === true ) { 28073 28074 const offset = uniform.__offset; 28075 28076 const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; 28077 28078 let arrayOffset = 0; 28079 28080 for ( let k = 0; k < values.length; k ++ ) { 28081 28082 const value = values[ k ]; 28083 28084 const info = getUniformSize( value ); 28085 28086 // TODO add integer and struct support 28087 if ( typeof value === 'number' || typeof value === 'boolean' ) { 28088 28089 uniform.__data[ 0 ] = value; 28090 gl.bufferSubData( gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data ); 28091 28092 } else if ( value.isMatrix3 ) { 28093 28094 // manually converting 3x3 to 3x4 28095 28096 uniform.__data[ 0 ] = value.elements[ 0 ]; 28097 uniform.__data[ 1 ] = value.elements[ 1 ]; 28098 uniform.__data[ 2 ] = value.elements[ 2 ]; 28099 uniform.__data[ 3 ] = 0; 28100 uniform.__data[ 4 ] = value.elements[ 3 ]; 28101 uniform.__data[ 5 ] = value.elements[ 4 ]; 28102 uniform.__data[ 6 ] = value.elements[ 5 ]; 28103 uniform.__data[ 7 ] = 0; 28104 uniform.__data[ 8 ] = value.elements[ 6 ]; 28105 uniform.__data[ 9 ] = value.elements[ 7 ]; 28106 uniform.__data[ 10 ] = value.elements[ 8 ]; 28107 uniform.__data[ 11 ] = 0; 28108 28109 } else { 28110 28111 value.toArray( uniform.__data, arrayOffset ); 28112 28113 arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT; 28114 28115 } 28116 28117 } 28118 28119 gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data ); 28120 28121 } 28122 28123 } 28124 28125 } 28126 28127 gl.bindBuffer( gl.UNIFORM_BUFFER, null ); 28128 28129 } 28130 28131 function hasUniformChanged( uniform, index, indexArray, cache ) { 28132 28133 const value = uniform.value; 28134 const indexString = index + '_' + indexArray; 28135 28136 if ( cache[ indexString ] === undefined ) { 28137 28138 // cache entry does not exist so far 28139 28140 if ( typeof value === 'number' || typeof value === 'boolean' ) { 28141 28142 cache[ indexString ] = value; 28143 28144 } else { 28145 28146 cache[ indexString ] = value.clone(); 28147 28148 } 28149 28150 return true; 28151 28152 } else { 28153 28154 const cachedObject = cache[ indexString ]; 28155 28156 // compare current value with cached entry 28157 28158 if ( typeof value === 'number' || typeof value === 'boolean' ) { 28159 28160 if ( cachedObject !== value ) { 28161 28162 cache[ indexString ] = value; 28163 return true; 28164 28165 } 28166 28167 } else { 28168 28169 if ( cachedObject.equals( value ) === false ) { 28170 28171 cachedObject.copy( value ); 28172 return true; 28173 28174 } 28175 28176 } 28177 28178 } 28179 28180 return false; 28181 28182 } 28183 28184 function prepareUniformsGroup( uniformsGroup ) { 28185 28186 // determine total buffer size according to the STD140 layout 28187 // Hint: STD140 is the only supported layout in WebGL 2 28188 28189 const uniforms = uniformsGroup.uniforms; 28190 28191 let offset = 0; // global buffer offset in bytes 28192 const chunkSize = 16; // size of a chunk in bytes 28193 28194 for ( let i = 0, l = uniforms.length; i < l; i ++ ) { 28195 28196 const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ]; 28197 28198 for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) { 28199 28200 const uniform = uniformArray[ j ]; 28201 28202 const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; 28203 28204 for ( let k = 0, kl = values.length; k < kl; k ++ ) { 28205 28206 const value = values[ k ]; 28207 28208 const info = getUniformSize( value ); 28209 28210 // Calculate the chunk offset 28211 const chunkOffsetUniform = offset % chunkSize; 28212 28213 // Check for chunk overflow 28214 if ( chunkOffsetUniform !== 0 && ( chunkSize - chunkOffsetUniform ) < info.boundary ) { 28215 28216 // Add padding and adjust offset 28217 offset += ( chunkSize - chunkOffsetUniform ); 28218 28219 } 28220 28221 // the following two properties will be used for partial buffer updates 28222 28223 uniform.__data = new Float32Array( info.storage / Float32Array.BYTES_PER_ELEMENT ); 28224 uniform.__offset = offset; 28225 28226 28227 // Update the global offset 28228 offset += info.storage; 28229 28230 28231 } 28232 28233 } 28234 28235 } 28236 28237 // ensure correct final padding 28238 28239 const chunkOffset = offset % chunkSize; 28240 28241 if ( chunkOffset > 0 ) offset += ( chunkSize - chunkOffset ); 28242 28243 // 28244 28245 uniformsGroup.__size = offset; 28246 uniformsGroup.__cache = {}; 28247 28248 return this; 28249 28250 } 28251 28252 function getUniformSize( value ) { 28253 28254 const info = { 28255 boundary: 0, // bytes 28256 storage: 0 // bytes 28257 }; 28258 28259 // determine sizes according to STD140 28260 28261 if ( typeof value === 'number' || typeof value === 'boolean' ) { 28262 28263 // float/int/bool 28264 28265 info.boundary = 4; 28266 info.storage = 4; 28267 28268 } else if ( value.isVector2 ) { 28269 28270 // vec2 28271 28272 info.boundary = 8; 28273 info.storage = 8; 28274 28275 } else if ( value.isVector3 || value.isColor ) { 28276 28277 // vec3 28278 28279 info.boundary = 16; 28280 info.storage = 12; // evil: vec3 must start on a 16-byte boundary but it only consumes 12 bytes 28281 28282 } else if ( value.isVector4 ) { 28283 28284 // vec4 28285 28286 info.boundary = 16; 28287 info.storage = 16; 28288 28289 } else if ( value.isMatrix3 ) { 28290 28291 // mat3 (in STD140 a 3x3 matrix is represented as 3x4) 28292 28293 info.boundary = 48; 28294 info.storage = 48; 28295 28296 } else if ( value.isMatrix4 ) { 28297 28298 // mat4 28299 28300 info.boundary = 64; 28301 info.storage = 64; 28302 28303 } else if ( value.isTexture ) { 28304 28305 console.warn( 'THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.' ); 28306 28307 } else { 28308 28309 console.warn( 'THREE.WebGLRenderer: Unsupported uniform value type.', value ); 28310 28311 } 28312 28313 return info; 28314 28315 } 28316 28317 function onUniformsGroupsDispose( event ) { 28318 28319 const uniformsGroup = event.target; 28320 28321 uniformsGroup.removeEventListener( 'dispose', onUniformsGroupsDispose ); 28322 28323 const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex ); 28324 allocatedBindingPoints.splice( index, 1 ); 28325 28326 gl.deleteBuffer( buffers[ uniformsGroup.id ] ); 28327 28328 delete buffers[ uniformsGroup.id ]; 28329 delete updateList[ uniformsGroup.id ]; 28330 28331 } 28332 28333 function dispose() { 28334 28335 for ( const id in buffers ) { 28336 28337 gl.deleteBuffer( buffers[ id ] ); 28338 28339 } 28340 28341 allocatedBindingPoints = []; 28342 buffers = {}; 28343 updateList = {}; 28344 28345 } 28346 28347 return { 28348 28349 bind: bind, 28350 update: update, 28351 28352 dispose: dispose 28353 28354 }; 28355 28356} 28357 28358class WebGLRenderer { 28359 28360 constructor( parameters = {} ) { 28361 28362 const { 28363 canvas = createCanvasElement(), 28364 context = null, 28365 depth = true, 28366 stencil =
vendor: 5,855 bytes, lines 28366-28604
28366false, 28367 alpha = false, 28368 antialias = false, 28369 premultipliedAlpha = true, 28370 preserveDrawingBuffer = false, 28371 powerPreference = 'default', 28372 failIfMajorPerformanceCaveat = false, 28373 } = parameters; 28374 28375 this.isWebGLRenderer = true; 28376 28377 let _alpha; 28378 28379 if ( context !== null ) { 28380 28381 if ( typeof WebGLRenderingContext !== 'undefined' && context instanceof WebGLRenderingContext ) { 28382 28383 throw new Error( 'THREE.WebGLRenderer: WebGL 1 is not supported since r163.' ); 28384 28385 } 28386 28387 _alpha = context.getContextAttributes().alpha; 28388 28389 } else { 28390 28391 _alpha = alpha; 28392 28393 } 28394 28395 const uintClearColor = new Uint32Array( 4 ); 28396 const intClearColor = new Int32Array( 4 ); 28397 28398 let currentRenderList = null; 28399 let currentRenderState = null; 28400 28401 // render() can be called from within a callback triggered by another render. 28402 // We track this so that the nested render call gets its list and state isolated from the parent render call. 28403 28404 const renderListStack = []; 28405 const renderStateStack = []; 28406 28407 // public properties 28408 28409 this.domElement = canvas; 28410 28411 // Debug configuration container 28412 this.debug = { 28413 28414 /** 28415 * Enables error checking and reporting when shader programs are being compiled 28416 * @type {boolean} 28417 */ 28418 checkShaderErrors: true, 28419 /** 28420 * Callback for custom error reporting. 28421 * @type {?Function} 28422 */ 28423 onShaderError: null 28424 }; 28425 28426 // clearing 28427 28428 this.autoClear = true; 28429 this.autoClearColor = true; 28430 this.autoClearDepth = true; 28431 this.autoClearStencil = true; 28432 28433 // scene graph 28434 28435 this.sortObjects = true; 28436 28437 // user-defined clipping 28438 28439 this.clippingPlanes = []; 28440 this.localClippingEnabled = false; 28441 28442 // physically based shading 28443 28444 this._outputColorSpace = SRGBColorSpace; 28445 28446 // tone mapping 28447 28448 this.toneMapping = NoToneMapping; 28449 this.toneMappingExposure = 1.0; 28450 28451 // internal properties 28452 28453 const _this = this; 28454 28455 let _isContextLost = false; 28456 28457 // internal state cache 28458 28459 let _currentActiveCubeFace = 0; 28460 let _currentActiveMipmapLevel = 0; 28461 let _currentRenderTarget = null; 28462 let _currentMaterialId = - 1; 28463 28464 let _currentCamera = null; 28465 28466 const _currentViewport = new Vector4(); 28467 const _currentScissor = new Vector4(); 28468 let _currentScissorTest = null; 28469 28470 const _currentClearColor = new Color( 0x000000 ); 28471 let _currentClearAlpha = 0; 28472 28473 // 28474 28475 let _width = canvas.width; 28476 let _height = canvas.height; 28477 28478 let _pixelRatio = 1; 28479 let _opaqueSort = null; 28480 let _transparentSort = null; 28481 28482 const _viewport = new Vector4( 0, 0, _width, _height ); 28483 const _scissor = new Vector4( 0, 0, _width, _height ); 28484 let _scissorTest = false; 28485 28486 // frustum 28487 28488 const _frustum = new Frustum(); 28489 28490 // clipping 28491 28492 let _clippingEnabled = false; 28493 let _localClippingEnabled = false; 28494 28495 // camera matrices cache 28496 28497 const _projScreenMatrix = new Matrix4(); 28498 28499 const _vector3 = new Vector3(); 28500 28501 const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; 28502 28503 let _renderBackground = false; 28504 28505 function getTargetPixelRatio() { 28506 28507 return _currentRenderTarget === null ? _pixelRatio : 1; 28508 28509 } 28510 28511 // initialize 28512 28513 let _gl = context; 28514 28515 function getContext( contextName, contextAttributes ) { 28516 28517 return canvas.getContext( contextName, contextAttributes ); 28518 28519 } 28520 28521 try { 28522 28523 const contextAttributes = { 28524 alpha: true, 28525 depth, 28526 stencil, 28527 antialias, 28528 premultipliedAlpha, 28529 preserveDrawingBuffer, 28530 powerPreference, 28531 failIfMajorPerformanceCaveat, 28532 }; 28533 28534 // OffscreenCanvas does not have setAttribute, see #22811 28535 if ( 'setAttribute' in canvas ) canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); 28536 28537 // event listeners must be registered before WebGL context is created, see #12753 28538 canvas.addEventListener( 'webglcontextlost', onContextLost, false ); 28539 canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); 28540 canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); 28541 28542 if ( _gl === null ) { 28543 28544 const contextName = 'webgl2'; 28545 28546 _gl = getContext( contextName, contextAttributes ); 28547 28548 if ( _gl === null ) { 28549 28550 if ( getContext( contextName ) ) { 28551 28552 throw new Error( 'Error creating WebGL context with your selected attributes.' ); 28553 28554 } else { 28555 28556 throw new Error( 'Error creating WebGL context.' ); 28557 28558 } 28559 28560 } 28561 28562 } 28563 28564 } catch ( error ) { 28565 28566 console.error( 'THREE.WebGLRenderer: ' + error.message ); 28567 throw error; 28568 28569 } 28570 28571 let extensions, capabilities, state, info; 28572 let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; 28573 let programCache, materials, renderLists, renderStates, clipping, shadowMap; 28574 28575 let background, morphtargets, bufferRenderer, indexedBufferRenderer; 28576 28577 let utils, bindingStates, uniformsGroups; 28578 28579 function initGLContext() { 28580 28581 extensions = new WebGLExtensions( _gl ); 28582 extensions.init(); 28583 28584 utils = new WebGLUtils( _gl, extensions ); 28585 28586 capabilities = new WebGLCapabilities( _gl, extensions, parameters, utils ); 28587 28588 state = new WebGLState( _gl ); 28589 28590 info = new WebGLInfo( _gl ); 28591 properties = new WebGLProperties(); 28592 textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); 28593 cubemaps = new WebGLCubeMaps( _this ); 28594 cubeuvmaps = new WebGLCubeUVMaps( _this ); 28595 attributes = new WebGLAttributes( _gl ); 28596 bindingStates = new WebGLBindingStates( _gl, attributes ); 28597 geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); 28598 objects = new WebGLObjects( _gl, geometries, attributes, info ); 28599 morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); 28600 clipping = new WebGLClipping( properties ); 28601 programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); 28602 materials = new WebGLMaterials( _this, properties ); 28603 renderLists = new WebGLRenderLists(); 28604 renderStates = new WebGLRenderStates( extensions );
vendor: 16,914 bytes, lines 28605-29418
28605 background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha ); 28606 shadowMap = new WebGLShadowMap( _this, objects, capabilities ); 28607 uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); 28608 28609 bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info ); 28610 indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info ); 28611 28612 info.programs = programCache.programs; 28613 28614 _this.capabilities = capabilities; 28615 _this.extensions = extensions; 28616 _this.properties = properties; 28617 _this.renderLists = renderLists; 28618 _this.shadowMap = shadowMap; 28619 _this.state = state; 28620 _this.info = info; 28621 28622 } 28623 28624 initGLContext(); 28625 28626 // xr 28627 28628 const xr = new WebXRManager( _this, _gl ); 28629 28630 this.xr = xr; 28631 28632 // API 28633 28634 this.getContext = function () { 28635 28636 return _gl; 28637 28638 }; 28639 28640 this.getContextAttributes = function () { 28641 28642 return _gl.getContextAttributes(); 28643 28644 }; 28645 28646 this.forceContextLoss = function () { 28647 28648 const extension = extensions.get( 'WEBGL_lose_context' ); 28649 if ( extension ) extension.loseContext(); 28650 28651 }; 28652 28653 this.forceContextRestore = function () { 28654 28655 const extension = extensions.get( 'WEBGL_lose_context' ); 28656 if ( extension ) extension.restoreContext(); 28657 28658 }; 28659 28660 this.getPixelRatio = function () { 28661 28662 return _pixelRatio; 28663 28664 }; 28665 28666 this.setPixelRatio = function ( value ) { 28667 28668 if ( value === undefined ) return; 28669 28670 _pixelRatio = value; 28671 28672 this.setSize( _width, _height, false ); 28673 28674 }; 28675 28676 this.getSize = function ( target ) { 28677 28678 return target.set( _width, _height ); 28679 28680 }; 28681 28682 this.setSize = function ( width, height, updateStyle = true ) { 28683 28684 if ( xr.isPresenting ) { 28685 28686 console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); 28687 return; 28688 28689 } 28690 28691 _width = width; 28692 _height = height; 28693 28694 canvas.width = Math.floor( width * _pixelRatio ); 28695 canvas.height = Math.floor( height * _pixelRatio ); 28696 28697 if ( updateStyle === true ) { 28698 28699 canvas.style.width = width + 'px'; 28700 canvas.style.height = height + 'px'; 28701 28702 } 28703 28704 this.setViewport( 0, 0, width, height ); 28705 28706 }; 28707 28708 this.getDrawingBufferSize = function ( target ) { 28709 28710 return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); 28711 28712 }; 28713 28714 this.setDrawingBufferSize = function ( width, height, pixelRatio ) { 28715 28716 _width = width; 28717 _height = height; 28718 28719 _pixelRatio = pixelRatio; 28720 28721 canvas.width = Math.floor( width * pixelRatio ); 28722 canvas.height = Math.floor( height * pixelRatio ); 28723 28724 this.setViewport( 0, 0, width, height ); 28725 28726 }; 28727 28728 this.getCurrentViewport = function ( target ) { 28729 28730 return target.copy( _currentViewport ); 28731 28732 }; 28733 28734 this.getViewport = function ( target ) { 28735 28736 return target.copy( _viewport ); 28737 28738 }; 28739 28740 this.setViewport = function ( x, y, width, height ) { 28741 28742 if ( x.isVector4 ) { 28743 28744 _viewport.set( x.x, x.y, x.z, x.w ); 28745 28746 } else { 28747 28748 _viewport.set( x, y, width, height ); 28749 28750 } 28751 28752 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).round() ); 28753 28754 }; 28755 28756 this.getScissor = function ( target ) { 28757 28758 return target.copy( _scissor ); 28759 28760 }; 28761 28762 this.setScissor = function ( x, y, width, height ) { 28763 28764 if ( x.isVector4 ) { 28765 28766 _scissor.set( x.x, x.y, x.z, x.w ); 28767 28768 } else { 28769 28770 _scissor.set( x, y, width, height ); 28771 28772 } 28773 28774 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).round() ); 28775 28776 }; 28777 28778 this.getScissorTest = function () { 28779 28780 return _scissorTest; 28781 28782 }; 28783 28784 this.setScissorTest = function ( boolean ) { 28785 28786 state.setScissorTest( _scissorTest = boolean ); 28787 28788 }; 28789 28790 this.setOpaqueSort = function ( method ) { 28791 28792 _opaqueSort = method; 28793 28794 }; 28795 28796 this.setTransparentSort = function ( method ) { 28797 28798 _transparentSort = method; 28799 28800 }; 28801 28802 // Clearing 28803 28804 this.getClearColor = function ( target ) { 28805 28806 return target.copy( background.getClearColor() ); 28807 28808 }; 28809 28810 this.setClearColor = function () { 28811 28812 background.setClearColor.apply( background, arguments ); 28813 28814 }; 28815 28816 this.getClearAlpha = function () { 28817 28818 return background.getClearAlpha(); 28819 28820 }; 28821 28822 this.setClearAlpha = function () { 28823 28824 background.setClearAlpha.apply( background, arguments ); 28825 28826 }; 28827 28828 this.clear = function ( color = true, depth = true, stencil = true ) { 28829 28830 let bits = 0; 28831 28832 if ( color ) { 28833 28834 // check if we're trying to clear an integer target 28835 let isIntegerFormat = false; 28836 if ( _currentRenderTarget !== null ) { 28837 28838 const targetFormat = _currentRenderTarget.texture.format; 28839 isIntegerFormat = targetFormat === RGBAIntegerFormat || 28840 targetFormat === RGIntegerFormat || 28841 targetFormat === RedIntegerFormat; 28842 28843 } 28844 28845 // use the appropriate clear functions to clear the target if it's a signed 28846 // or unsigned integer target 28847 if ( isIntegerFormat ) { 28848 28849 const targetType = _currentRenderTarget.texture.type; 28850 const isUnsignedType = targetType === UnsignedByteType || 28851 targetType === UnsignedIntType || 28852 targetType === UnsignedShortType || 28853 targetType === UnsignedInt248Type || 28854 targetType === UnsignedShort4444Type || 28855 targetType === UnsignedShort5551Type; 28856 28857 const clearColor = background.getClearColor(); 28858 const a = background.getClearAlpha(); 28859 const r = clearColor.r; 28860 const g = clearColor.g; 28861 const b = clearColor.b; 28862 28863 if ( isUnsignedType ) { 28864 28865 uintClearColor[ 0 ] = r; 28866 uintClearColor[ 1 ] = g; 28867 uintClearColor[ 2 ] = b; 28868 uintClearColor[ 3 ] = a; 28869 _gl.clearBufferuiv( _gl.COLOR, 0, uintClearColor ); 28870 28871 } else { 28872 28873 intClearColor[ 0 ] = r; 28874 intClearColor[ 1 ] = g; 28875 intClearColor[ 2 ] = b; 28876 intClearColor[ 3 ] = a; 28877 _gl.clearBufferiv( _gl.COLOR, 0, intClearColor ); 28878 28879 } 28880 28881 } else { 28882 28883 bits |= _gl.COLOR_BUFFER_BIT; 28884 28885 } 28886 28887 } 28888 28889 if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; 28890 if ( stencil ) { 28891 28892 bits |= _gl.STENCIL_BUFFER_BIT; 28893 this.state.buffers.stencil.setMask( 0xffffffff ); 28894 28895 } 28896 28897 _gl.clear( bits ); 28898 28899 }; 28900 28901 this.clearColor = function () { 28902 28903 this.clear( true, false, false ); 28904 28905 }; 28906 28907 this.clearDepth = function () { 28908 28909 this.clear( false, true, false ); 28910 28911 }; 28912 28913 this.clearStencil = function () { 28914 28915 this.clear( false, false, true ); 28916 28917 }; 28918 28919 // 28920 28921 this.dispose = function () { 28922 28923 canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); 28924 canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); 28925 canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); 28926 28927 renderLists.dispose(); 28928 renderStates.dispose(); 28929 properties.dispose(); 28930 cubemaps.dispose(); 28931 cubeuvmaps.dispose(); 28932 objects.dispose(); 28933 bindingStates.dispose(); 28934 uniformsGroups.dispose(); 28935 programCache.dispose(); 28936 28937 xr.dispose(); 28938 28939 xr.removeEventListener( 'sessionstart', onXRSessionStart ); 28940 xr.removeEventListener( 'sessionend', onXRSessionEnd ); 28941 28942 animation.stop(); 28943 28944 }; 28945 28946 // Events 28947 28948 function onContextLost( event ) { 28949 28950 event.preventDefault(); 28951 28952 console.log( 'THREE.WebGLRenderer: Context Lost.' ); 28953 28954 _isContextLost = true; 28955 28956 } 28957 28958 function onContextRestore( /* event */ ) { 28959 28960 console.log( 'THREE.WebGLRenderer: Context Restored.' ); 28961 28962 _isContextLost = false; 28963 28964 const infoAutoReset = info.autoReset; 28965 const shadowMapEnabled = shadowMap.enabled; 28966 const shadowMapAutoUpdate = shadowMap.autoUpdate; 28967 const shadowMapNeedsUpdate = shadowMap.needsUpdate; 28968 const shadowMapType = shadowMap.type; 28969 28970 initGLContext(); 28971 28972 info.autoReset = infoAutoReset; 28973 shadowMap.enabled = shadowMapEnabled; 28974 shadowMap.autoUpdate = shadowMapAutoUpdate; 28975 shadowMap.needsUpdate = shadowMapNeedsUpdate; 28976 shadowMap.type = shadowMapType; 28977 28978 } 28979 28980 function onContextCreationError( event ) { 28981 28982 console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); 28983 28984 } 28985 28986 function onMaterialDispose( event ) { 28987 28988 const material = event.target; 28989 28990 material.removeEventListener( 'dispose', onMaterialDispose ); 28991 28992 deallocateMaterial( material ); 28993 28994 } 28995 28996 // Buffer deallocation 28997 28998 function deallocateMaterial( material ) { 28999 29000 releaseMaterialProgramReferences( material ); 29001 29002 properties.remove( material ); 29003 29004 } 29005 29006 29007 function releaseMaterialProgramReferences( material ) { 29008 29009 const programs = properties.get( material ).programs; 29010 29011 if ( programs !== undefined ) { 29012 29013 programs.forEach( function ( program ) { 29014 29015 programCache.releaseProgram( program ); 29016 29017 } ); 29018 29019 if ( material.isShaderMaterial ) { 29020 29021 programCache.releaseShaderCache( material ); 29022 29023 } 29024 29025 } 29026 29027 } 29028 29029 // Buffer rendering 29030 29031 this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { 29032 29033 if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) 29034 29035 const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); 29036 29037 const program = setProgram( camera, scene, geometry, material, object ); 29038 29039 state.setMaterial( material, frontFaceCW ); 29040 29041 // 29042 29043 let index = geometry.index; 29044 let rangeFactor = 1; 29045 29046 if ( material.wireframe === true ) { 29047 29048 index = geometries.getWireframeAttribute( geometry ); 29049 29050 if ( index === undefined ) return; 29051 29052 rangeFactor = 2; 29053 29054 } 29055 29056 // 29057 29058 const drawRange = geometry.drawRange; 29059 const position = geometry.attributes.position; 29060 29061 let drawStart = drawRange.start * rangeFactor; 29062 let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; 29063 29064 if ( group !== null ) { 29065 29066 drawStart = Math.max( drawStart, group.start * rangeFactor ); 29067 drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); 29068 29069 } 29070 29071 if ( index !== null ) { 29072 29073 drawStart = Math.max( drawStart, 0 ); 29074 drawEnd = Math.min( drawEnd, index.count ); 29075 29076 } else if ( position !== undefined && position !== null ) { 29077 29078 drawStart = Math.max( drawStart, 0 ); 29079 drawEnd = Math.min( drawEnd, position.count ); 29080 29081 } 29082 29083 const drawCount = drawEnd - drawStart; 29084 29085 if ( drawCount < 0 || drawCount === Infinity ) return; 29086 29087 // 29088 29089 bindingStates.setup( object, material, program, geometry, index ); 29090 29091 let attribute; 29092 let renderer = bufferRenderer; 29093 29094 if ( index !== null ) { 29095 29096 attribute = attributes.get( index ); 29097 29098 renderer = indexedBufferRenderer; 29099 renderer.setIndex( attribute ); 29100 29101 } 29102 29103 // 29104 29105 if ( object.isMesh ) { 29106 29107 if ( material.wireframe === true ) { 29108 29109 state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); 29110 renderer.setMode( _gl.LINES ); 29111 29112 } else { 29113 29114 renderer.setMode( _gl.TRIANGLES ); 29115 29116 } 29117 29118 } else if ( object.isLine ) { 29119 29120 let lineWidth = material.linewidth; 29121 29122 if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material 29123 29124 state.setLineWidth( lineWidth * getTargetPixelRatio() ); 29125 29126 if ( object.isLineSegments ) { 29127 29128 renderer.setMode( _gl.LINES ); 29129 29130 } else if ( object.isLineLoop ) { 29131 29132 renderer.setMode( _gl.LINE_LOOP ); 29133 29134 } else { 29135 29136 renderer.setMode( _gl.LINE_STRIP ); 29137 29138 } 29139 29140 } else if ( object.isPoints ) { 29141 29142 renderer.setMode( _gl.POINTS ); 29143 29144 } else if ( object.isSprite ) { 29145 29146 renderer.setMode( _gl.TRIANGLES ); 29147 29148 } 29149 29150 if ( object.isBatchedMesh ) { 29151 29152 if ( object._multiDrawInstances !== null ) { 29153 29154 renderer.renderMultiDrawInstances( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount, object._multiDrawInstances ); 29155 29156 } else { 29157 29158 renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount ); 29159 29160 } 29161 29162 } else if ( object.isInstancedMesh ) { 29163 29164 renderer.renderInstances( drawStart, drawCount, object.count ); 29165 29166 } else if ( geometry.isInstancedBufferGeometry ) { 29167 29168 const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; 29169 const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); 29170 29171 renderer.renderInstances( drawStart, drawCount, instanceCount ); 29172 29173 } else { 29174 29175 renderer.render( drawStart, drawCount ); 29176 29177 } 29178 29179 }; 29180 29181 // Compile 29182 29183 function prepareMaterial( material, scene, object ) { 29184 29185 if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { 29186 29187 material.side = BackSide; 29188 material.needsUpdate = true; 29189 getProgram( material, scene, object ); 29190 29191 material.side = FrontSide; 29192 material.needsUpdate = true; 29193 getProgram( material, scene, object ); 29194 29195 material.side = DoubleSide; 29196 29197 } else { 29198 29199 getProgram( material, scene, object ); 29200 29201 } 29202 29203 } 29204 29205 this.compile = function ( scene, camera, targetScene = null ) { 29206 29207 if ( targetScene === null ) targetScene = scene; 29208 29209 currentRenderState = renderStates.get( targetScene ); 29210 currentRenderState.init( camera ); 29211 29212 renderStateStack.push( currentRenderState ); 29213 29214 // gather lights from both the target scene and the new object that will be added to the scene. 29215 29216 targetScene.traverseVisible( function ( object ) { 29217 29218 if ( object.isLight && object.layers.test( camera.layers ) ) { 29219 29220 currentRenderState.pushLight( object ); 29221 29222 if ( object.castShadow ) { 29223 29224 currentRenderState.pushShadow( object ); 29225 29226 } 29227 29228 } 29229 29230 } ); 29231 29232 if ( scene !== targetScene ) { 29233 29234 scene.traverseVisible( function ( object ) { 29235 29236 if ( object.isLight && object.layers.test( camera.layers ) ) { 29237 29238 currentRenderState.pushLight( object ); 29239 29240 if ( object.castShadow ) { 29241 29242 currentRenderState.pushShadow( object ); 29243 29244 } 29245 29246 } 29247 29248 } ); 29249 29250 } 29251 29252 currentRenderState.setupLights(); 29253 29254 // Only initialize materials in the new scene, not the targetScene. 29255 29256 const materials = new Set(); 29257 29258 scene.traverse( function ( object ) { 29259 29260 const material = object.material; 29261 29262 if ( material ) { 29263 29264 if ( Array.isArray( material ) ) { 29265 29266 for ( let i = 0; i < material.length; i ++ ) { 29267 29268 const material2 = material[ i ]; 29269 29270 prepareMaterial( material2, targetScene, object ); 29271 materials.add( material2 ); 29272 29273 } 29274 29275 } else { 29276 29277 prepareMaterial( material, targetScene, object ); 29278 materials.add( material ); 29279 29280 } 29281 29282 } 29283 29284 } ); 29285 29286 renderStateStack.pop(); 29287 currentRenderState = null; 29288 29289 return materials; 29290 29291 }; 29292 29293 // compileAsync 29294 29295 this.compileAsync = function ( scene, camera, targetScene = null ) { 29296 29297 const materials = this.compile( scene, camera, targetScene ); 29298 29299 // Wait for all the materials in the new object to indicate that they're 29300 // ready to be used before resolving the promise. 29301 29302 return new Promise( ( resolve ) => { 29303 29304 function checkMaterialsReady() { 29305 29306 materials.forEach( function ( material ) { 29307 29308 const materialProperties = properties.get( material ); 29309 const program = materialProperties.currentProgram; 29310 29311 if ( program.isReady() ) { 29312 29313 // remove any programs that report they're ready to use from the list 29314 materials.delete( material ); 29315 29316 } 29317 29318 } ); 29319 29320 // once the list of compiling materials is empty, call the callback 29321 29322 if ( materials.size === 0 ) { 29323 29324 resolve( scene ); 29325 return; 29326 29327 } 29328 29329 // if some materials are still not ready, wait a bit and check again 29330 29331 setTimeout( checkMaterialsReady, 10 ); 29332 29333 } 29334 29335 if ( extensions.get( 'KHR_parallel_shader_compile' ) !== null ) { 29336 29337 // If we can check the compilation status of the materials without 29338 // blocking then do so right away. 29339 29340 checkMaterialsReady(); 29341 29342 } else { 29343 29344 // Otherwise start by waiting a bit to give the materials we just 29345 // initialized a chance to finish. 29346 29347 setTimeout( checkMaterialsReady, 10 ); 29348 29349 } 29350 29351 } ); 29352 29353 }; 29354 29355 // Animation Loop 29356 29357 let onAnimationFrameCallback = null; 29358 29359 function onAnimationFrame( time ) { 29360 29361 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); 29362 29363 } 29364 29365 function onXRSessionStart() { 29366 29367 animation.stop(); 29368 29369 } 29370 29371 function onXRSessionEnd() { 29372 29373 animation.start(); 29374 29375 } 29376 29377 const animation = new WebGLAnimation(); 29378 animation.setAnimationLoop( onAnimationFrame ); 29379 29380 if ( typeof self !== 'undefined' ) animation.setContext( self ); 29381 29382 this.setAnimationLoop = function ( callback ) { 29383 29384 onAnimationFrameCallback = callback; 29385 xr.setAnimationLoop( callback ); 29386 29387 ( callback === null ) ? animation.stop() : animation.start(); 29388 29389 }; 29390 29391 xr.addEventListener( 'sessionstart', onXRSessionStart ); 29392 xr.addEventListener( 'sessionend', onXRSessionEnd ); 29393 29394 // Rendering 29395 29396 this.render = function ( scene, camera ) { 29397 29398 if ( camera !== undefined && camera.isCamera !== true ) { 29399 29400 console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); 29401 return; 29402 29403 } 29404 29405 if ( _isContextLost === true ) return; 29406 29407 // update scene graph 29408 29409 if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); 29410 29411 // update camera matrices and frustum 29412 29413 if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); 29414 29415 if ( xr.enabled === true && xr.isPresenting === true ) { 29416 29417 if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); 29418
vendor: 13,080 bytes, lines 29419-29912
29419 camera = xr.getCamera(); // use XR camera for rendering 29420 29421 } 29422 29423 // 29424 if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); 29425 29426 currentRenderState = renderStates.get( scene, renderStateStack.length ); 29427 currentRenderState.init( camera ); 29428 29429 renderStateStack.push( currentRenderState ); 29430 29431 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); 29432 _frustum.setFromProjectionMatrix( _projScreenMatrix ); 29433 29434 _localClippingEnabled = this.localClippingEnabled; 29435 _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); 29436 29437 currentRenderList = renderLists.get( scene, renderListStack.length ); 29438 currentRenderList.init(); 29439 29440 renderListStack.push( currentRenderList ); 29441 29442 if ( xr.enabled === true && xr.isPresenting === true ) { 29443 29444 const depthSensingMesh = _this.xr.getDepthSensingMesh(); 29445 29446 if ( depthSensingMesh !== null ) { 29447 29448 projectObject( depthSensingMesh, camera, - Infinity, _this.sortObjects ); 29449 29450 } 29451 29452 } 29453 29454 projectObject( scene, camera, 0, _this.sortObjects ); 29455 29456 currentRenderList.finish(); 29457 29458 if ( _this.sortObjects === true ) { 29459 29460 currentRenderList.sort( _opaqueSort, _transparentSort ); 29461 29462 } 29463 29464 _renderBackground = xr.enabled === false || xr.isPresenting === false || xr.hasDepthSensing() === false; 29465 if ( _renderBackground ) { 29466 29467 background.addToRenderList( currentRenderList, scene ); 29468 29469 } 29470 29471 // 29472 29473 this.info.render.frame ++; 29474 29475 if ( _clippingEnabled === true ) clipping.beginShadows(); 29476 29477 const shadowsArray = currentRenderState.state.shadowsArray; 29478 29479 shadowMap.render( shadowsArray, scene, camera ); 29480 29481 if ( _clippingEnabled === true ) clipping.endShadows(); 29482 29483 // 29484 29485 if ( this.info.autoReset === true ) this.info.reset(); 29486 29487 // render scene 29488 29489 const opaqueObjects = currentRenderList.opaque; 29490 const transmissiveObjects = currentRenderList.transmissive; 29491 29492 currentRenderState.setupLights(); 29493 29494 if ( camera.isArrayCamera ) { 29495 29496 const cameras = camera.cameras; 29497 29498 if ( transmissiveObjects.length > 0 ) { 29499 29500 for ( let i = 0, l = cameras.length; i < l; i ++ ) { 29501 29502 const camera2 = cameras[ i ]; 29503 29504 renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera2 ); 29505 29506 } 29507 29508 } 29509 29510 if ( _renderBackground ) background.render( scene ); 29511 29512 for ( let i = 0, l = cameras.length; i < l; i ++ ) { 29513 29514 const camera2 = cameras[ i ]; 29515 29516 renderScene( currentRenderList, scene, camera2, camera2.viewport ); 29517 29518 } 29519 29520 } else { 29521 29522 if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ); 29523 29524 if ( _renderBackground ) background.render( scene ); 29525 29526 renderScene( currentRenderList, scene, camera ); 29527 29528 } 29529 29530 // 29531 29532 if ( _currentRenderTarget !== null ) { 29533 29534 // resolve multisample renderbuffers to a single-sample texture if necessary 29535 29536 textures.updateMultisampleRenderTarget( _currentRenderTarget ); 29537 29538 // Generate mipmap if we're using any kind of mipmap filtering 29539 29540 textures.updateRenderTargetMipmap( _currentRenderTarget ); 29541 29542 } 29543 29544 // 29545 29546 if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); 29547 29548 // _gl.finish(); 29549 29550 bindingStates.resetDefaultState(); 29551 _currentMaterialId = - 1; 29552 _currentCamera = null; 29553 29554 renderStateStack.pop(); 29555 29556 if ( renderStateStack.length > 0 ) { 29557 29558 currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; 29559 29560 if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, currentRenderState.state.camera ); 29561 29562 } else { 29563 29564 currentRenderState = null; 29565 29566 } 29567 29568 renderListStack.pop(); 29569 29570 if ( renderListStack.length > 0 ) { 29571 29572 currentRenderList = renderListStack[ renderListStack.length - 1 ]; 29573 29574 } else { 29575 29576 currentRenderList = null; 29577 29578 } 29579 29580 }; 29581 29582 function projectObject( object, camera, groupOrder, sortObjects ) { 29583 29584 if ( object.visible === false ) return; 29585 29586 const visible = object.layers.test( camera.layers ); 29587 29588 if ( visible ) { 29589 29590 if ( object.isGroup ) { 29591 29592 groupOrder = object.renderOrder; 29593 29594 } else if ( object.isLOD ) { 29595 29596 if ( object.autoUpdate === true ) object.update( camera ); 29597 29598 } else if ( object.isLight ) { 29599 29600 currentRenderState.pushLight( object ); 29601 29602 if ( object.castShadow ) { 29603 29604 currentRenderState.pushShadow( object ); 29605 29606 } 29607 29608 } else if ( object.isSprite ) { 29609 29610 if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { 29611 29612 if ( sortObjects ) { 29613 29614 _vector3.setFromMatrixPosition( object.matrixWorld ) 29615 .applyMatrix4( _projScreenMatrix ); 29616 29617 } 29618 29619 const geometry = objects.update( object ); 29620 const material = object.material; 29621 29622 if ( material.visible ) { 29623 29624 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); 29625 29626 } 29627 29628 } 29629 29630 } else if ( object.isMesh || object.isLine || object.isPoints ) { 29631 29632 if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { 29633 29634 const geometry = objects.update( object ); 29635 const material = object.material; 29636 29637 if ( sortObjects ) { 29638 29639 if ( object.boundingSphere !== undefined ) { 29640 29641 if ( object.boundingSphere === null ) object.computeBoundingSphere(); 29642 _vector3.copy( object.boundingSphere.center ); 29643 29644 } else { 29645 29646 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 29647 _vector3.copy( geometry.boundingSphere.center ); 29648 29649 } 29650 29651 _vector3 29652 .applyMatrix4( object.matrixWorld ) 29653 .applyMatrix4( _projScreenMatrix ); 29654 29655 } 29656 29657 if ( Array.isArray( material ) ) { 29658 29659 const groups = geometry.groups; 29660 29661 for ( let i = 0, l = groups.length; i < l; i ++ ) { 29662 29663 const group = groups[ i ]; 29664 const groupMaterial = material[ group.materialIndex ]; 29665 29666 if ( groupMaterial && groupMaterial.visible ) { 29667 29668 currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); 29669 29670 } 29671 29672 } 29673 29674 } else if ( material.visible ) { 29675 29676 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); 29677 29678 } 29679 29680 } 29681 29682 } 29683 29684 } 29685 29686 const children = object.children; 29687 29688 for ( let i = 0, l = children.length; i < l; i ++ ) { 29689 29690 projectObject( children[ i ], camera, groupOrder, sortObjects ); 29691 29692 } 29693 29694 } 29695 29696 function renderScene( currentRenderList, scene, camera, viewport ) { 29697 29698 const opaqueObjects = currentRenderList.opaque; 29699 const transmissiveObjects = currentRenderList.transmissive; 29700 const transparentObjects = currentRenderList.transparent; 29701 29702 currentRenderState.setupLightsView( camera ); 29703 29704 if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); 29705 29706 if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); 29707 29708 if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); 29709 if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); 29710 if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); 29711 29712 // Ensure depth buffer writing is enabled so it can be cleared on next render 29713 29714 state.buffers.depth.setTest( true ); 29715 state.buffers.depth.setMask( true ); 29716 state.buffers.color.setMask( true ); 29717 29718 state.setPolygonOffset( false ); 29719 29720 } 29721 29722 function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) { 29723 29724 const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; 29725 29726 if ( overrideMaterial !== null ) { 29727 29728 return; 29729 29730 } 29731 29732 if ( currentRenderState.state.transmissionRenderTarget[ camera.id ] === undefined ) { 29733 29734 currentRenderState.state.transmissionRenderTarget[ camera.id ] = new WebGLRenderTarget( 1, 1, { 29735 generateMipmaps: true, 29736 type: ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ) ? HalfFloatType : UnsignedByteType, 29737 minFilter: LinearMipmapLinearFilter, 29738 samples: 4, 29739 stencilBuffer: stencil, 29740 resolveDepthBuffer: false, 29741 resolveStencilBuffer: false, 29742 colorSpace: ColorManagement.workingColorSpace, 29743 } ); 29744 29745 // debug 29746 29747 /* 29748 const geometry = new PlaneGeometry(); 29749 const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } ); 29750 29751 const mesh = new Mesh( geometry, material ); 29752 scene.add( mesh ); 29753 */ 29754 29755 } 29756 29757 const transmissionRenderTarget = currentRenderState.state.transmissionRenderTarget[ camera.id ]; 29758 29759 const activeViewport = camera.viewport || _currentViewport; 29760 transmissionRenderTarget.setSize( activeViewport.z, activeViewport.w ); 29761 29762 // 29763 29764 const currentRenderTarget = _this.getRenderTarget(); 29765 _this.setRenderTarget( transmissionRenderTarget ); 29766 29767 _this.getClearColor( _currentClearColor ); 29768 _currentClearAlpha = _this.getClearAlpha(); 29769 if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 ); 29770 29771 if ( _renderBackground ) { 29772 29773 background.render( scene ); 29774 29775 } else { 29776 29777 _this.clear(); 29778 29779 } 29780 29781 // Turn off the features which can affect the frag color for opaque objects pass. 29782 // Otherwise they are applied twice in opaque objects pass and transmission objects pass. 29783 const currentToneMapping = _this.toneMapping; 29784 _this.toneMapping = NoToneMapping; 29785 29786 // Remove viewport from camera to avoid nested render calls resetting viewport to it (e.g Reflector). 29787 // Transmission render pass requires viewport to match the transmissionRenderTarget. 29788 const currentCameraViewport = camera.viewport; 29789 if ( camera.viewport !== undefined ) camera.viewport = undefined; 29790 29791 currentRenderState.setupLightsView( camera ); 29792 29793 if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); 29794 29795 renderObjects( opaqueObjects, scene, camera ); 29796 29797 textures.updateMultisampleRenderTarget( transmissionRenderTarget ); 29798 textures.updateRenderTargetMipmap( transmissionRenderTarget ); 29799 29800 if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === false ) { // see #28131 29801 29802 let renderTargetNeedsUpdate = false; 29803 29804 for ( let i = 0, l = transmissiveObjects.length; i < l; i ++ ) { 29805 29806 const renderItem = transmissiveObjects[ i ]; 29807 29808 const object = renderItem.object; 29809 const geometry = renderItem.geometry; 29810 const material = renderItem.material; 29811 const group = renderItem.group; 29812 29813 if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) { 29814 29815 const currentSide = material.side; 29816 29817 material.side = BackSide; 29818 material.needsUpdate = true; 29819 29820 renderObject( object, scene, camera, geometry, material, group ); 29821 29822 material.side = currentSide; 29823 material.needsUpdate = true; 29824 29825 renderTargetNeedsUpdate = true; 29826 29827 } 29828 29829 } 29830 29831 if ( renderTargetNeedsUpdate === true ) { 29832 29833 textures.updateMultisampleRenderTarget( transmissionRenderTarget ); 29834 textures.updateRenderTargetMipmap( transmissionRenderTarget ); 29835 29836 } 29837 29838 } 29839 29840 _this.setRenderTarget( currentRenderTarget ); 29841 29842 _this.setClearColor( _currentClearColor, _currentClearAlpha ); 29843 29844 if ( currentCameraViewport !== undefined ) camera.viewport = currentCameraViewport; 29845 29846 _this.toneMapping = currentToneMapping; 29847 29848 } 29849 29850 function renderObjects( renderList, scene, camera ) { 29851 29852 const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; 29853 29854 for ( let i = 0, l = renderList.length; i < l; i ++ ) { 29855 29856 const renderItem = renderList[ i ]; 29857 29858 const object = renderItem.object; 29859 const geometry = renderItem.geometry; 29860 const material = overrideMaterial === null ? renderItem.material : overrideMaterial; 29861 const group = renderItem.group; 29862 29863 if ( object.layers.test( camera.layers ) ) { 29864 29865 renderObject( object, scene, camera, geometry, material, group ); 29866 29867 } 29868 29869 } 29870 29871 } 29872 29873 function renderObject( object, scene, camera, geometry, material, group ) { 29874 29875 object.onBeforeRender( _this, scene, camera, geometry, material, group ); 29876 29877 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); 29878 object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); 29879 29880 material.onBeforeRender( _this, scene, camera, geometry, object, group ); 29881 29882 if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { 29883 29884 material.side = BackSide; 29885 material.needsUpdate = true; 29886 _this.renderBufferDirect( camera, scene, geometry, material, object, group ); 29887 29888 material.side = FrontSide; 29889 material.needsUpdate = true; 29890 _this.renderBufferDirect( camera, scene, geometry, material, object, group ); 29891 29892 material.side = DoubleSide; 29893 29894 } else { 29895 29896 _this.renderBufferDirect( camera, scene, geometry, material, object, group ); 29897 29898 } 29899 29900 object.onAfterRender( _this, scene, camera, geometry, material, group ); 29901 29902 } 29903 29904 function getProgram( material, scene, object ) { 29905 29906 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... 29907 29908 const materialProperties = properties.get( material ); 29909 29910 const lights = currentRenderState.state.lights; 29911 const shadowsArray = currentRenderState.state.shadowsArray; 29912
vendor: 5,874 bytes, lines 29913-30062
29913 const lightsStateVersion = lights.state.version; 29914 29915 const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); 29916 const programCacheKey = programCache.getProgramCacheKey( parameters ); 29917 29918 let programs = materialProperties.programs; 29919 29920 // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change 29921 29922 materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; 29923 materialProperties.fog = scene.fog; 29924 materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment ); 29925 materialProperties.envMapRotation = ( materialProperties.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation; 29926 29927 if ( programs === undefined ) { 29928 29929 // new material 29930 29931 material.addEventListener( 'dispose', onMaterialDispose ); 29932 29933 programs = new Map(); 29934 materialProperties.programs = programs; 29935 29936 } 29937 29938 let program = programs.get( programCacheKey ); 29939 29940 if ( program !== undefined ) { 29941 29942 // early out if program and light state is identical 29943 29944 if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { 29945 29946 updateCommonMaterialProperties( material, parameters ); 29947 29948 return program; 29949 29950 } 29951 29952 } else { 29953 29954 parameters.uniforms = programCache.getUniforms( material ); 29955 29956 material.onBuild( object, parameters, _this ); 29957 29958 material.onBeforeCompile( parameters, _this ); 29959 29960 program = programCache.acquireProgram( parameters, programCacheKey ); 29961 programs.set( programCacheKey, program ); 29962 29963 materialProperties.uniforms = parameters.uniforms; 29964 29965 } 29966 29967 const uniforms = materialProperties.uniforms; 29968 29969 if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { 29970 29971 uniforms.clippingPlanes = clipping.uniform; 29972 29973 } 29974 29975 updateCommonMaterialProperties( material, parameters ); 29976 29977 // store the light setup it was created for 29978 29979 materialProperties.needsLights = materialNeedsLights( material ); 29980 materialProperties.lightsStateVersion = lightsStateVersion; 29981 29982 if ( materialProperties.needsLights ) { 29983 29984 // wire up the material to this renderer's lighting state 29985 29986 uniforms.ambientLightColor.value = lights.state.ambient; 29987 uniforms.lightProbe.value = lights.state.probe; 29988 uniforms.directionalLights.value = lights.state.directional; 29989 uniforms.directionalLightShadows.value = lights.state.directionalShadow; 29990 uniforms.spotLights.value = lights.state.spot; 29991 uniforms.spotLightShadows.value = lights.state.spotShadow; 29992 uniforms.rectAreaLights.value = lights.state.rectArea; 29993 uniforms.ltc_1.value = lights.state.rectAreaLTC1; 29994 uniforms.ltc_2.value = lights.state.rectAreaLTC2; 29995 uniforms.pointLights.value = lights.state.point; 29996 uniforms.pointLightShadows.value = lights.state.pointShadow; 29997 uniforms.hemisphereLights.value = lights.state.hemi; 29998 29999 uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; 30000 uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; 30001 uniforms.spotShadowMap.value = lights.state.spotShadowMap; 30002 uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; 30003 uniforms.spotLightMap.value = lights.state.spotLightMap; 30004 uniforms.pointShadowMap.value = lights.state.pointShadowMap; 30005 uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; 30006 // TODO (abelnation): add area lights shadow info to uniforms 30007 30008 } 30009 30010 materialProperties.currentProgram = program; 30011 materialProperties.uniformsList = null; 30012 30013 return program; 30014 30015 } 30016 30017 function getUniformList( materialProperties ) { 30018 30019 if ( materialProperties.uniformsList === null ) { 30020 30021 const progUniforms = materialProperties.currentProgram.getUniforms(); 30022 materialProperties.uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, materialProperties.uniforms ); 30023 30024 } 30025 30026 return materialProperties.uniformsList; 30027 30028 } 30029 30030 function updateCommonMaterialProperties( material, parameters ) { 30031 30032 const materialProperties = properties.get( material ); 30033 30034 materialProperties.outputColorSpace = parameters.outputColorSpace; 30035 materialProperties.batching = parameters.batching; 30036 materialProperties.batchingColor = parameters.batchingColor; 30037 materialProperties.instancing = parameters.instancing; 30038 materialProperties.instancingColor = parameters.instancingColor; 30039 materialProperties.instancingMorph = parameters.instancingMorph; 30040 materialProperties.skinning = parameters.skinning; 30041 materialProperties.morphTargets = parameters.morphTargets; 30042 materialProperties.morphNormals = parameters.morphNormals; 30043 materialProperties.morphColors = parameters.morphColors; 30044 materialProperties.morphTargetsCount = parameters.morphTargetsCount; 30045 materialProperties.numClippingPlanes = parameters.numClippingPlanes; 30046 materialProperties.numIntersection = parameters.numClipIntersection; 30047 materialProperties.vertexAlphas = parameters.vertexAlphas; 30048 materialProperties.vertexTangents = parameters.vertexTangents; 30049 materialProperties.toneMapping = parameters.toneMapping; 30050 30051 } 30052 30053 function setProgram( camera, scene, geometry, material, object ) { 30054 30055 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... 30056 30057 textures.resetTextureUnits(); 30058 30059 const fog = scene.fog; 30060 const environment = material.isMeshStandardMaterial ? scene.environment : null; 30061 const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ); 30062 const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment
vendor: 5,405 bytes, lines 30062-30254
30062 ); 30063 const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; 30064 const vertexTangents = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 ); 30065 const morphTargets = !! geometry.morphAttributes.position; 30066 const morphNormals = !! geometry.morphAttributes.normal; 30067 const morphColors = !! geometry.morphAttributes.color; 30068 30069 let toneMapping = NoToneMapping; 30070 30071 if ( material.toneMapped ) { 30072 30073 if ( _currentRenderTarget === null || _currentRenderTarget.isXRRenderTarget === true ) { 30074 30075 toneMapping = _this.toneMapping; 30076 30077 } 30078 30079 } 30080 30081 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; 30082 const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; 30083 30084 const materialProperties = properties.get( material ); 30085 const lights = currentRenderState.state.lights; 30086 30087 if ( _clippingEnabled === true ) { 30088 30089 if ( _localClippingEnabled === true || camera !== _currentCamera ) { 30090 30091 const useCache = 30092 camera === _currentCamera && 30093 material.id === _currentMaterialId; 30094 30095 // we might want to call this function with some ClippingGroup 30096 // object instead of the material, once it becomes feasible 30097 // (#8465, #8379) 30098 clipping.setState( material, camera, useCache ); 30099 30100 } 30101 30102 } 30103 30104 // 30105 30106 let needsProgramChange = false; 30107 30108 if ( material.version === materialProperties.__version ) { 30109 30110 if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { 30111 30112 needsProgramChange = true; 30113 30114 } else if ( materialProperties.outputColorSpace !== colorSpace ) { 30115 30116 needsProgramChange = true; 30117 30118 } else if ( object.isBatchedMesh && materialProperties.batching === false ) { 30119 30120 needsProgramChange = true; 30121 30122 } else if ( ! object.isBatchedMesh && materialProperties.batching === true ) { 30123 30124 needsProgramChange = true; 30125 30126 } else if ( object.isBatchedMesh && materialProperties.batchingColor === true && object.colorTexture === null ) { 30127 30128 needsProgramChange = true; 30129 30130 } else if ( object.isBatchedMesh && materialProperties.batchingColor === false && object.colorTexture !== null ) { 30131 30132 needsProgramChange = true; 30133 30134 } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { 30135 30136 needsProgramChange = true; 30137 30138 } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { 30139 30140 needsProgramChange = true; 30141 30142 } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { 30143 30144 needsProgramChange = true; 30145 30146 } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { 30147 30148 needsProgramChange = true; 30149 30150 } else if ( object.isInstancedMesh && materialProperties.instancingColor === true && object.instanceColor === null ) { 30151 30152 needsProgramChange = true; 30153 30154 } else if ( object.isInstancedMesh && materialProperties.instancingColor === false && object.instanceColor !== null ) { 30155 30156 needsProgramChange = true; 30157 30158 } else if ( object.isInstancedMesh && materialProperties.instancingMorph === true && object.morphTexture === null ) { 30159 30160 needsProgramChange = true; 30161 30162 } else if ( object.isInstancedMesh && materialProperties.instancingMorph === false && object.morphTexture !== null ) { 30163 30164 needsProgramChange = true; 30165 30166 } else if ( materialProperties.envMap !== envMap ) { 30167 30168 needsProgramChange = true; 30169 30170 } else if ( material.fog === true && materialProperties.fog !== fog ) { 30171 30172 needsProgramChange = true; 30173 30174 } else if ( materialProperties.numClippingPlanes !== undefined && 30175 ( materialProperties.numClippingPlanes !== clipping.numPlanes || 30176 materialProperties.numIntersection !== clipping.numIntersection ) ) { 30177 30178 needsProgramChange = true; 30179 30180 } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { 30181 30182 needsProgramChange = true; 30183 30184 } else if ( materialProperties.vertexTangents !== vertexTangents ) { 30185 30186 needsProgramChange = true; 30187 30188 } else if ( materialProperties.morphTargets !== morphTargets ) { 30189 30190 needsProgramChange = true; 30191 30192 } else if ( materialProperties.morphNormals !== morphNormals ) { 30193 30194 needsProgramChange = true; 30195 30196 } else if ( materialProperties.morphColors !== morphColors ) { 30197 30198 needsProgramChange = true; 30199 30200 } else if ( materialProperties.toneMapping !== toneMapping ) { 30201 30202 needsProgramChange = true; 30203 30204 } else if ( materialProperties.morphTargetsCount !== morphTargetsCount ) { 30205 30206 needsProgramChange = true; 30207 30208 } 30209 30210 } else { 30211 30212 needsProgramChange = true; 30213 materialProperties.__version = material.version; 30214 30215 } 30216 30217 // 30218 30219 let program = materialProperties.currentProgram; 30220 30221 if ( needsProgramChange === true ) { 30222 30223 program = getProgram( material, scene, object ); 30224 30225 } 30226 30227 let refreshProgram = false; 30228 let refreshMaterial = false; 30229 let refreshLights = false; 30230 30231 const p_uniforms = program.getUniforms(), 30232 m_uniforms = materialProperties.uniforms; 30233 30234 if ( state.useProgram( program.program ) ) { 30235 30236 refreshProgram = true; 30237 refreshMaterial = true; 30238 refreshLights = true; 30239 30240 } 30241 30242 if ( material.id !== _currentMaterialId ) { 30243 30244 _currentMaterialId = material.id; 30245 30246 refreshMaterial = true; 30247 30248 } 30249 30250 if ( refreshProgram || _currentCamera !== camera ) { 30251 30252 // common camera uniforms 30253 30254
vendor: 4,556 bytes, lines 30254-30402
30254p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); 30255 p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); 30256 30257 const uCamPos = p_uniforms.map.cameraPosition; 30258 30259 if ( uCamPos !== undefined ) { 30260 30261 uCamPos.setValue( _gl, _vector3.setFromMatrixPosition( camera.matrixWorld ) ); 30262 30263 } 30264 30265 if ( capabilities.logarithmicDepthBuffer ) { 30266 30267 p_uniforms.setValue( _gl, 'logDepthBufFC', 30268 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); 30269 30270 } 30271 30272 // consider moving isOrthographic to UniformLib and WebGLMaterials, see https://github.com/mrdoob/three.js/pull/26467#issuecomment-1645185067 30273 30274 if ( material.isMeshPhongMaterial || 30275 material.isMeshToonMaterial || 30276 material.isMeshLambertMaterial || 30277 material.isMeshBasicMaterial || 30278 material.isMeshStandardMaterial || 30279 material.isShaderMaterial ) { 30280 30281 p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); 30282 30283 } 30284 30285 if ( _currentCamera !== camera ) { 30286 30287 _currentCamera = camera; 30288 30289 // lighting uniforms depend on the camera so enforce an update 30290 // now, in case this material supports lights - or later, when 30291 // the next material that does gets activated: 30292 30293 refreshMaterial = true; // set to true on material change 30294 refreshLights = true; // remains set until update done 30295 30296 } 30297 30298 } 30299 30300 // skinning and morph target uniforms must be set even if material didn't change 30301 // auto-setting of texture unit for bone and morph texture must go before other textures 30302 // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures 30303 30304 if ( object.isSkinnedMesh ) { 30305 30306 p_uniforms.setOptional( _gl, object, 'bindMatrix' ); 30307 p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); 30308 30309 const skeleton = object.skeleton; 30310 30311 if ( skeleton ) { 30312 30313 if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); 30314 30315 p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); 30316 30317 } 30318 30319 } 30320 30321 if ( object.isBatchedMesh ) { 30322 30323 p_uniforms.setOptional( _gl, object, 'batchingTexture' ); 30324 p_uniforms.setValue( _gl, 'batchingTexture', object._matricesTexture, textures ); 30325 30326 p_uniforms.setOptional( _gl, object, 'batchingColorTexture' ); 30327 if ( object._colorsTexture !== null ) { 30328 30329 p_uniforms.setValue( _gl, 'batchingColorTexture', object._colorsTexture, textures ); 30330 30331 } 30332 30333 } 30334 30335 const morphAttributes = geometry.morphAttributes; 30336 30337 if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined ) ) { 30338 30339 morphtargets.update( object, geometry, program ); 30340 30341 } 30342 30343 if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { 30344 30345 materialProperties.receiveShadow = object.receiveShadow; 30346 p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); 30347 30348 } 30349 30350 // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 30351 30352 if ( material.isMeshGouraudMaterial && material.envMap !== null ) { 30353 30354 m_uniforms.envMap.value = envMap; 30355 30356 m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; 30357 30358 } 30359 30360 if ( material.isMeshStandardMaterial && material.envMap === null && scene.environment !== null ) { 30361 30362 m_uniforms.envMapIntensity.value = scene.environmentIntensity; 30363 30364 } 30365 30366 if ( refreshMaterial ) { 30367 30368 p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); 30369 30370 if ( materialProperties.needsLights ) { 30371 30372 // the current material requires lighting info 30373 30374 // note: all lighting uniforms are always set correctly 30375 // they simply reference the renderer's state for their 30376 // values 30377 // 30378 // use the current material's .needsUpdate flags to set 30379 // the GL state when required 30380 30381 markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); 30382 30383 } 30384 30385 // refresh uniforms common to several materials 30386 30387 if ( fog && material.fog === true ) { 30388 30389 materials.refreshFogUniforms( m_uniforms, fog ); 30390 30391 } 30392 30393 materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, currentRenderState.state.transmissionRenderTarget[ camera.id ] ); 30394 30395 WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures ); 30396 30397 } 30398 30399 if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { 30400 30401 WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures ); 30402 material.uniformsNeedUpdate = false;
vendor: 4,533 bytes, lines 30403-30557
30403 30404 } 30405 30406 if ( material.isSpriteMaterial ) { 30407 30408 p_uniforms.setValue( _gl, 'center', object.center ); 30409 30410 } 30411 30412 // common matrices 30413 30414 p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); 30415 p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); 30416 p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); 30417 30418 // UBOs 30419 30420 if ( material.isShaderMaterial || material.isRawShaderMaterial ) { 30421 30422 const groups = material.uniformsGroups; 30423 30424 for ( let i = 0, l = groups.length; i < l; i ++ ) { 30425 30426 const group = groups[ i ]; 30427 30428 uniformsGroups.update( group, program ); 30429 uniformsGroups.bind( group, program ); 30430 30431 } 30432 30433 } 30434 30435 return program; 30436 30437 } 30438 30439 // If uniforms are marked as clean, they don't need to be loaded to the GPU. 30440 30441 function markUniformsLightsNeedsUpdate( uniforms, value ) { 30442 30443 uniforms.ambientLightColor.needsUpdate = value; 30444 uniforms.lightProbe.needsUpdate = value; 30445 30446 uniforms.directionalLights.needsUpdate = value; 30447 uniforms.directionalLightShadows.needsUpdate = value; 30448 uniforms.pointLights.needsUpdate = value; 30449 uniforms.pointLightShadows.needsUpdate = value; 30450 uniforms.spotLights.needsUpdate = value; 30451 uniforms.spotLightShadows.needsUpdate = value; 30452 uniforms.rectAreaLights.needsUpdate = value; 30453 uniforms.hemisphereLights.needsUpdate = value; 30454 30455 } 30456 30457 function materialNeedsLights( material ) { 30458 30459 return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || 30460 material.isMeshStandardMaterial || material.isShadowMaterial || 30461 ( material.isShaderMaterial && material.lights === true ); 30462 30463 } 30464 30465 this.getActiveCubeFace = function () { 30466 30467 return _currentActiveCubeFace; 30468 30469 }; 30470 30471 this.getActiveMipmapLevel = function () { 30472 30473 return _currentActiveMipmapLevel; 30474 30475 }; 30476 30477 this.getRenderTarget = function () { 30478 30479 return _currentRenderTarget; 30480 30481 }; 30482 30483 this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { 30484 30485 properties.get( renderTarget.texture ).__webglTexture = colorTexture; 30486 properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; 30487 30488 const renderTargetProperties = properties.get( renderTarget ); 30489 renderTargetProperties.__hasExternalTextures = true; 30490 30491 renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; 30492 30493 if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { 30494 30495 // The multisample_render_to_texture extension doesn't work properly if there 30496 // are midframe flushes and an external depth buffer. Disable use of the extension. 30497 if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { 30498 30499 console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); 30500 renderTargetProperties.__useRenderToTexture = false; 30501 30502 } 30503 30504 } 30505 30506 }; 30507 30508 this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { 30509 30510 const renderTargetProperties = properties.get( renderTarget ); 30511 renderTargetProperties.__webglFramebuffer = defaultFramebuffer; 30512 renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; 30513 30514 }; 30515 30516 this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { 30517 30518 _currentRenderTarget = renderTarget; 30519 _currentActiveCubeFace = activeCubeFace; 30520 _currentActiveMipmapLevel = activeMipmapLevel; 30521 30522 let useDefaultFramebuffer = true; 30523 let framebuffer = null; 30524 let isCube = false; 30525 let isRenderTarget3D = false; 30526 30527 if ( renderTarget ) { 30528 30529 const renderTargetProperties = properties.get( renderTarget ); 30530 30531 if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { 30532 30533 // We need to make sure to rebind the framebuffer. 30534 state.bindFramebuffer( _gl.FRAMEBUFFER, null ); 30535 useDefaultFramebuffer = false; 30536 30537 } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { 30538 30539 textures.setupRenderTarget( renderTarget ); 30540 30541 } else if ( renderTargetProperties.__hasExternalTextures ) { 30542 30543 // Color and depth texture must be rebound in order for the swapchain to update. 30544 textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); 30545 30546 } 30547 30548 const texture = renderTarget.texture; 30549 30550 if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { 30551 30552 isRenderTarget3D = true; 30553 30554 } 30555 30556 const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; 30557
vendor: 4,267 bytes, lines 30558-30701
30558 if ( renderTarget.isWebGLCubeRenderTarget ) { 30559 30560 if ( Array.isArray( __webglFramebuffer[ activeCubeFace ] ) ) { 30561 30562 framebuffer = __webglFramebuffer[ activeCubeFace ][ activeMipmapLevel ]; 30563 30564 } else { 30565 30566 framebuffer = __webglFramebuffer[ activeCubeFace ]; 30567 30568 } 30569 30570 isCube = true; 30571 30572 } else if ( ( renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { 30573 30574 framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; 30575 30576 } else { 30577 30578 if ( Array.isArray( __webglFramebuffer ) ) { 30579 30580 framebuffer = __webglFramebuffer[ activeMipmapLevel ]; 30581 30582 } else { 30583 30584 framebuffer = __webglFramebuffer; 30585 30586 } 30587 30588 } 30589 30590 _currentViewport.copy( renderTarget.viewport ); 30591 _currentScissor.copy( renderTarget.scissor ); 30592 _currentScissorTest = renderTarget.scissorTest; 30593 30594 } else { 30595 30596 _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); 30597 _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); 30598 _currentScissorTest = _scissorTest; 30599 30600 } 30601 30602 const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 30603 30604 if ( framebufferBound && useDefaultFramebuffer ) { 30605 30606 state.drawBuffers( renderTarget, framebuffer ); 30607 30608 } 30609 30610 state.viewport( _currentViewport ); 30611 state.scissor( _currentScissor ); 30612 state.setScissorTest( _currentScissorTest ); 30613 30614 if ( isCube ) { 30615 30616 const textureProperties = properties.get( renderTarget.texture ); 30617 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel ); 30618 30619 } else if ( isRenderTarget3D ) { 30620 30621 const textureProperties = properties.get( renderTarget.texture ); 30622 const layer = activeCubeFace || 0; 30623 _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); 30624 30625 } 30626 30627 _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings 30628 30629 }; 30630 30631 this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { 30632 30633 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { 30634 30635 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); 30636 return; 30637 30638 } 30639 30640 let framebuffer = properties.get( renderTarget ).__webglFramebuffer; 30641 30642 if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { 30643 30644 framebuffer = framebuffer[ activeCubeFaceIndex ]; 30645 30646 } 30647 30648 if ( framebuffer ) { 30649 30650 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 30651 30652 try { 30653 30654 const texture = renderTarget.texture; 30655 const textureFormat = texture.format; 30656 const textureType = texture.type; 30657 30658 if ( ! capabilities.textureFormatReadable( textureFormat ) ) { 30659 30660 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); 30661 return; 30662 30663 } 30664 30665 if ( ! capabilities.textureTypeReadable( textureType ) ) { 30666 30667 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); 30668 return; 30669 30670 } 30671 30672 // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) 30673 30674 if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { 30675 30676 _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); 30677 30678 } 30679 30680 } finally { 30681 30682 // restore framebuffer of current render target if necessary 30683 30684 const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; 30685 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 30686 30687 } 30688 30689 } 30690 30691 }; 30692 30693 this.readRenderTargetPixelsAsync = async function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { 30694 30695 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { 30696 30697 throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); 30698 30699 } 30700 30701 let framebuffer = properties.get( renderTarget ).__webglFramebuffer;
30702 if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { 30703 30704 framebuffer = framebuffer[ activeCubeFaceIndex ]; 30705 30706 } 30707 30708 if ( framebuffer ) { 30709 30710 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 30711 30712 try { 30713 30714 const texture = renderTarget.texture; 30715 const textureFormat = texture.format; 30716 const textureType = texture.type; 30717 30718 if ( ! capabilities.textureFormatReadable( textureFormat ) ) { 30719 30720 throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.' ); 30721 30722 } 30723 30724 if ( ! capabilities.textureTypeReadable( textureType ) ) { 30725 30726 throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.' ); 30727 30728 } 30729 30730 // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) 30731 if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { 30732 30733 const glBuffer = _gl.createBuffer(); 30734 _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); 30735 _gl.bufferData( _gl.PIXEL_PACK_BUFFER, buffer.byteLength, _gl.STREAM_READ ); 30736 _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), 0 ); 30737 _gl.flush(); 30738 30739 // check if the commands have finished every 8 ms 30740 const sync = _gl.fenceSync( _gl.SYNC_GPU_COMMANDS_COMPLETE, 0 ); 30741 await probeAsync( _gl, sync, 4 ); 30742 30743 try { 30744 30745 _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); 30746 _gl.getBufferSubData( _gl.PIXEL_PACK_BUFFER, 0, buffer ); 30747 30748 } finally { 30749 30750 _gl.deleteBuffer( glBuffer ); 30751 _gl.deleteSync( sync ); 30752 30753 } 30754 30755 return buffer; 30756 30757 } 30758 30759 } finally { 30760 30761 // restore framebuffer of current render target if necessary 30762 30763 const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; 30764 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 30765 30766 } 30767 30768 } 30769 30770 }; 30771 30772 this.copyFramebufferToTexture = function ( texture, position = null, level = 0 ) { 30773 30774 // support previous signature with position first 30775 if ( texture.isTexture !== true ) { 30776 30777 // @deprecated, r165 30778 console.warn( 'WebGLRenderer: copyFramebufferToTexture function signature has changed.' ); 30779 30780 position = arguments[ 0 ] || null; 30781 texture = arguments[ 1 ]; 30782 30783 } 30784 30785 const levelScale = Math.pow( 2, - level ); 30786 const width = Math.floor( texture.image.width * levelScale ); 30787 const height = Math.floor( texture.image.height * levelScale ); 30788 30789 const x = position !== null ? position.x : 0; 30790 const y = position !== null ? position.y : 0; 30791 30792 textures.setTexture2D( texture, 0 ); 30793 30794 _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, x, y, width, height ); 30795 30796 state.unbindTexture(); 30797 30798 }; 30799 30800 this.copyTextureToTexture = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { 30801 30802 // support previous signature with dstPosition first 30803 if ( srcTexture.isTexture !== true ) { 30804 30805 // @deprecated, r165 30806 console.warn( 'WebGLRenderer: copyTextureToTexture function signature has changed.' ); 30807 30808 dstPosition = arguments[ 0 ] || null; 30809 srcTexture = arguments[ 1 ]; 30810 dstTexture = arguments[ 2 ]; 30811 level = arguments[ 3 ] || 0; 30812 srcRegion = null; 30813 30814 } 30815 30816 let width, height, minX, minY; 30817 let dstX, dstY; 30818 if ( srcRegion !== null ) { 30819 30820 width = srcRegion.max.x - srcRegion.min.x; 30821 height = srcRegion.max.y - srcRegion.min.y; 30822 minX = srcRegion.min.x; 30823 minY = srcRegion.min.y; 30824 30825 } else { 30826 30827 width = srcTexture.image.width; 30828 height = srcTexture.image.height; 30829 minX = 0; 30830 minY = 0; 30831 30832 } 30833 30834 if ( dstPosition !== null ) { 30835 30836 dstX = dstPosition.x; 30837 dstY = dstPosition.y; 30838 30839 } else { 30840 30841 dstX = 0; 30842 dstY = 0; 30843 30844 } 30845 30846 const glFormat = utils.convert( dstTexture.format ); 30847 const glType = utils.convert( dstTexture.type ); 30848 30849 textures.setTexture2D( dstTexture, 0 ); 30850 30851 // As another texture upload may have changed pixelStorei 30852 // parameters, make sure they are correct for the dstTexture 30853 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); 30854 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); 30855 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); 30856 30857 const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); 30858 const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); 30859 const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); 30860 const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); 30861 const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); 30862 30863 const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image; 30864 30865 _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); 30866 _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); 30867 _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX ); 30868 _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY ); 30869 30870 if ( srcTexture.isDataTexture ) { 30871 30872 _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data ); 30873 30874 } else { 30875 30876 if ( srcTexture.isCompressedTexture ) { 30877 30878 _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data ); 30879 30880 } else { 30881 30882 _gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, glFormat, glType, image ); 30883 30884 } 30885 30886 } 30887 30888 _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); 30889 _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); 30890 _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); 30891 _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); 30892 _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); 30893 30894 // Generate mipmaps only when copying level 0 30895 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); 30896 30897 state.unbindTexture(); 30898 30899 }; 30900 30901 this.copyTextureToTexture3D = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { 30902 30903 // support previous signature with source box first 30904 if ( srcTexture.isTexture !== true ) { 30905 30906 // @deprecated, r165 30907 console.warn( 'WebGLRenderer: copyTextureToTexture3D function signature has changed.' ); 30908 30909 srcRegion = arguments[ 0 ] || null; 30910 dstPosition = arguments[ 1 ] || null; 30911 srcTexture = arguments[ 2 ]; 30912 dstTexture = arguments[ 3 ]; 30913 level = arguments[ 4 ] || 0; 30914 30915 } 30916 30917 let width, height, depth, minX, minY, minZ; 30918 let dstX, dstY, dstZ; 30919 const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image; 30920 if ( srcRegion !== null ) { 30921 30922 width = srcRegion.max.x - srcRegion.min.x; 30923 height = srcRegion.max.y - srcRegion.min.y; 30924 depth = srcRegion.max.z - srcRegion.min.z;
vendor: 4,292 bytes, lines 30925-31099
30925 minX = srcRegion.min.x; 30926 minY = srcRegion.min.y; 30927 minZ = srcRegion.min.z; 30928 30929 } else { 30930 30931 width = image.width; 30932 height = image.height; 30933 depth = image.depth; 30934 minX = 0; 30935 minY = 0; 30936 minZ = 0; 30937 30938 } 30939 30940 if ( dstPosition !== null ) { 30941 30942 dstX = dstPosition.x; 30943 dstY = dstPosition.y; 30944 dstZ = dstPosition.z; 30945 30946 } else { 30947 30948 dstX = 0; 30949 dstY = 0; 30950 dstZ = 0; 30951 30952 } 30953 30954 const glFormat = utils.convert( dstTexture.format ); 30955 const glType = utils.convert( dstTexture.type ); 30956 let glTarget; 30957 30958 if ( dstTexture.isData3DTexture ) { 30959 30960 textures.setTexture3D( dstTexture, 0 ); 30961 glTarget = _gl.TEXTURE_3D; 30962 30963 } else if ( dstTexture.isDataArrayTexture || dstTexture.isCompressedArrayTexture ) { 30964 30965 textures.setTexture2DArray( dstTexture, 0 ); 30966 glTarget = _gl.TEXTURE_2D_ARRAY; 30967 30968 } else { 30969 30970 console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); 30971 return; 30972 30973 } 30974 30975 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); 30976 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); 30977 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); 30978 30979 const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); 30980 const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); 30981 const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); 30982 const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); 30983 const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES ); 30984 30985 _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width ); 30986 _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height ); 30987 _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX ); 30988 _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY ); 30989 _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ ); 30990 30991 if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { 30992 30993 _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data ); 30994 30995 } else { 30996 30997 if ( dstTexture.isCompressedArrayTexture ) { 30998 30999 _gl.compressedTexSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, image.data ); 31000 31001 } else { 31002 31003 _gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image ); 31004 31005 } 31006 31007 } 31008 31009 _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); 31010 _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); 31011 _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); 31012 _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); 31013 _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); 31014 31015 // Generate mipmaps only when copying level 0 31016 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); 31017 31018 state.unbindTexture(); 31019 31020 }; 31021 31022 this.initRenderTarget = function ( target ) { 31023 31024 if ( properties.get( target ).__webglFramebuffer === undefined ) { 31025 31026 textures.setupRenderTarget( target ); 31027 31028 } 31029 31030 }; 31031 31032 this.initTexture = function ( texture ) { 31033 31034 if ( texture.isCubeTexture ) { 31035 31036 textures.setTextureCube( texture, 0 ); 31037 31038 } else if ( texture.isData3DTexture ) { 31039 31040 textures.setTexture3D( texture, 0 ); 31041 31042 } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { 31043 31044 textures.setTexture2DArray( texture, 0 ); 31045 31046 } else { 31047 31048 textures.setTexture2D( texture, 0 ); 31049 31050 } 31051 31052 state.unbindTexture(); 31053 31054 }; 31055 31056 this.resetState = function () { 31057 31058 _currentActiveCubeFace = 0; 31059 _currentActiveMipmapLevel = 0; 31060 _currentRenderTarget = null; 31061 31062 state.reset(); 31063 bindingStates.reset(); 31064 31065 }; 31066 31067 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { 31068 31069 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); 31070 31071 } 31072 31073 } 31074 31075 get coordinateSystem() { 31076 31077 return WebGLCoordinateSystem; 31078 31079 } 31080 31081 get outputColorSpace() { 31082 31083 return this._outputColorSpace; 31084 31085 } 31086 31087 set outputColorSpace( colorSpace ) { 31088 31089 this._outputColorSpace = colorSpace; 31090 31091 const gl = this.getContext(); 31092 gl.drawingBufferColorSpace = colorSpace === DisplayP3ColorSpace ? 'display-p3' : 'srgb'; 31093 gl.unpackColorSpace = ColorManagement.workingColorSpace === LinearDisplayP3ColorSpace ? 'display-p3' : 'srgb'; 31094 31095 } 31096 31097} 31098 31099class FogExp2 {
vendor: 11,981 bytes, lines 31100-31786
31100 31101 constructor( color, density = 0.00025 ) { 31102 31103 this.isFogExp2 = true; 31104 31105 this.name = ''; 31106 31107 this.color = new Color( color ); 31108 this.density = density; 31109 31110 } 31111 31112 clone() { 31113 31114 return new FogExp2( this.color, this.density ); 31115 31116 } 31117 31118 toJSON( /* meta */ ) { 31119 31120 return { 31121 type: 'FogExp2', 31122 name: this.name, 31123 color: this.color.getHex(), 31124 density: this.density 31125 }; 31126 31127 } 31128 31129} 31130 31131class Fog { 31132 31133 constructor( color, near = 1, far = 1000 ) { 31134 31135 this.isFog = true; 31136 31137 this.name = ''; 31138 31139 this.color = new Color( color ); 31140 31141 this.near = near; 31142 this.far = far; 31143 31144 } 31145 31146 clone() { 31147 31148 return new Fog( this.color, this.near, this.far ); 31149 31150 } 31151 31152 toJSON( /* meta */ ) { 31153 31154 return { 31155 type: 'Fog', 31156 name: this.name, 31157 color: this.color.getHex(), 31158 near: this.near, 31159 far: this.far 31160 }; 31161 31162 } 31163 31164} 31165 31166class Scene extends Object3D { 31167 31168 constructor() { 31169 31170 super(); 31171 31172 this.isScene = true; 31173 31174 this.type = 'Scene'; 31175 31176 this.background = null; 31177 this.environment = null; 31178 this.fog = null; 31179 31180 this.backgroundBlurriness = 0; 31181 this.backgroundIntensity = 1; 31182 this.backgroundRotation = new Euler(); 31183 31184 this.environmentIntensity = 1; 31185 this.environmentRotation = new Euler(); 31186 31187 this.overrideMaterial = null; 31188 31189 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { 31190 31191 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); 31192 31193 } 31194 31195 } 31196 31197 copy( source, recursive ) { 31198 31199 super.copy( source, recursive ); 31200 31201 if ( source.background !== null ) this.background = source.background.clone(); 31202 if ( source.environment !== null ) this.environment = source.environment.clone(); 31203 if ( source.fog !== null ) this.fog = source.fog.clone(); 31204 31205 this.backgroundBlurriness = source.backgroundBlurriness; 31206 this.backgroundIntensity = source.backgroundIntensity; 31207 this.backgroundRotation.copy( source.backgroundRotation ); 31208 31209 this.environmentIntensity = source.environmentIntensity; 31210 this.environmentRotation.copy( source.environmentRotation ); 31211 31212 if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone(); 31213 31214 this.matrixAutoUpdate = source.matrixAutoUpdate; 31215 31216 return this; 31217 31218 } 31219 31220 toJSON( meta ) { 31221 31222 const data = super.toJSON( meta ); 31223 31224 if ( this.fog !== null ) data.object.fog = this.fog.toJSON(); 31225 31226 if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness; 31227 if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity; 31228 data.object.backgroundRotation = this.backgroundRotation.toArray(); 31229 31230 if ( this.environmentIntensity !== 1 ) data.object.environmentIntensity = this.environmentIntensity; 31231 data.object.environmentRotation = this.environmentRotation.toArray(); 31232 31233 return data; 31234 31235 } 31236 31237} 31238 31239class InterleavedBuffer { 31240 31241 constructor( array, stride ) { 31242 31243 this.isInterleavedBuffer = true; 31244 31245 this.array = array; 31246 this.stride = stride; 31247 this.count = array !== undefined ? array.length / stride : 0; 31248 31249 this.usage = StaticDrawUsage; 31250 this._updateRange = { offset: 0, count: - 1 }; 31251 this.updateRanges = []; 31252 31253 this.version = 0; 31254 31255 this.uuid = generateUUID(); 31256 31257 } 31258 31259 onUploadCallback() {} 31260 31261 set needsUpdate( value ) { 31262 31263 if ( value === true ) this.version ++; 31264 31265 } 31266 31267 get updateRange() { 31268 31269 warnOnce( 'THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 31270 return this._updateRange; 31271 31272 } 31273 31274 setUsage( value ) { 31275 31276 this.usage = value; 31277 31278 return this; 31279 31280 } 31281 31282 addUpdateRange( start, count ) { 31283 31284 this.updateRanges.push( { start, count } ); 31285 31286 } 31287 31288 clearUpdateRanges() { 31289 31290 this.updateRanges.length = 0; 31291 31292 } 31293 31294 copy( source ) { 31295 31296 this.array = new source.array.constructor( source.array ); 31297 this.count = source.count; 31298 this.stride = source.stride; 31299 this.usage = source.usage; 31300 31301 return this; 31302 31303 } 31304 31305 copyAt( index1, attribute, index2 ) { 31306 31307 index1 *= this.stride; 31308 index2 *= attribute.stride; 31309 31310 for ( let i = 0, l = this.stride; i < l; i ++ ) { 31311 31312 this.array[ index1 + i ] = attribute.array[ index2 + i ]; 31313 31314 } 31315 31316 return this; 31317 31318 } 31319 31320 set( value, offset = 0 ) { 31321 31322 this.array.set( value, offset ); 31323 31324 return this; 31325 31326 } 31327 31328 clone( data ) { 31329 31330 if ( data.arrayBuffers === undefined ) { 31331 31332 data.arrayBuffers = {}; 31333 31334 } 31335 31336 if ( this.array.buffer._uuid === undefined ) { 31337 31338 this.array.buffer._uuid = generateUUID(); 31339 31340 } 31341 31342 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { 31343 31344 data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer; 31345 31346 } 31347 31348 const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] ); 31349 31350 const ib = new this.constructor( array, this.stride ); 31351 ib.setUsage( this.usage ); 31352 31353 return ib; 31354 31355 } 31356 31357 onUpload( callback ) { 31358 31359 this.onUploadCallback = callback; 31360 31361 return this; 31362 31363 } 31364 31365 toJSON( data ) { 31366 31367 if ( data.arrayBuffers === undefined ) { 31368 31369 data.arrayBuffers = {}; 31370 31371 } 31372 31373 // generate UUID for array buffer if necessary 31374 31375 if ( this.array.buffer._uuid === undefined ) { 31376 31377 this.array.buffer._uuid = generateUUID(); 31378 31379 } 31380 31381 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { 31382 31383 data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) ); 31384 31385 } 31386 31387 // 31388 31389 return { 31390 uuid: this.uuid, 31391 buffer: this.array.buffer._uuid, 31392 type: this.array.constructor.name, 31393 stride: this.stride 31394 }; 31395 31396 } 31397 31398} 31399 31400const _vector$6 = /*@__PURE__*/ new Vector3(); 31401 31402class InterleavedBufferAttribute { 31403 31404 constructor( interleavedBuffer, itemSize, offset, normalized = false ) { 31405 31406 this.isInterleavedBufferAttribute = true; 31407 31408 this.name = ''; 31409 31410 this.data = interleavedBuffer; 31411 this.itemSize = itemSize; 31412 this.offset = offset; 31413 31414 this.normalized = normalized; 31415 31416 } 31417 31418 get count() { 31419 31420 return this.data.count; 31421 31422 } 31423 31424 get array() { 31425 31426 return this.data.array; 31427 31428 } 31429 31430 set needsUpdate( value ) { 31431 31432 this.data.needsUpdate = value; 31433 31434 } 31435 31436 applyMatrix4( m ) { 31437 31438 for ( let i = 0, l = this.data.count; i < l; i ++ ) { 31439 31440 _vector$6.fromBufferAttribute( this, i ); 31441 31442 _vector$6.applyMatrix4( m ); 31443 31444 this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); 31445 31446 } 31447 31448 return this; 31449 31450 } 31451 31452 applyNormalMatrix( m ) { 31453 31454 for ( let i = 0, l = this.count; i < l; i ++ ) { 31455 31456 _vector$6.fromBufferAttribute( this, i ); 31457 31458 _vector$6.applyNormalMatrix( m ); 31459 31460 this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); 31461 31462 } 31463 31464 return this; 31465 31466 } 31467 31468 transformDirection( m ) { 31469 31470 for ( let i = 0, l = this.count; i < l; i ++ ) { 31471 31472 _vector$6.fromBufferAttribute( this, i ); 31473 31474 _vector$6.transformDirection( m ); 31475 31476 this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); 31477 31478 } 31479 31480 return this; 31481 31482 } 31483 31484 getComponent( index, component ) { 31485 31486 let value = this.array[ index * this.data.stride + this.offset + component ]; 31487 31488 if ( this.normalized ) value = denormalize( value, this.array ); 31489 31490 return value; 31491 31492 } 31493 31494 setComponent( index, component, value ) { 31495 31496 if ( this.normalized ) value = normalize( value, this.array ); 31497 31498 this.data.array[ index * this.data.stride + this.offset + component ] = value; 31499 31500 return this; 31501 31502 } 31503 31504 setX( index, x ) { 31505 31506 if ( this.normalized ) x = normalize( x, this.array ); 31507 31508 this.data.array[ index * this.data.stride + this.offset ] = x; 31509 31510 return this; 31511 31512 } 31513 31514 setY( index, y ) { 31515 31516 if ( this.normalized ) y = normalize( y, this.array ); 31517 31518 this.data.array[ index * this.data.stride + this.offset + 1 ] = y; 31519 31520 return this; 31521 31522 } 31523 31524 setZ( index, z ) { 31525 31526 if ( this.normalized ) z = normalize( z, this.array ); 31527 31528 this.data.array[ index * this.data.stride + this.offset + 2 ] = z; 31529 31530 return this; 31531 31532 } 31533 31534 setW( index, w ) { 31535 31536 if ( this.normalized ) w = normalize( w, this.array ); 31537 31538 this.data.array[ index * this.data.stride + this.offset + 3 ] = w; 31539 31540 return this; 31541 31542 } 31543 31544 getX( index ) { 31545 31546 let x = this.data.array[ index * this.data.stride + this.offset ]; 31547 31548 if ( this.normalized ) x = denormalize( x, this.array ); 31549 31550 return x; 31551 31552 } 31553 31554 getY( index ) { 31555 31556 let y = this.data.array[ index * this.data.stride + this.offset + 1 ]; 31557 31558 if ( this.normalized ) y = denormalize( y, this.array ); 31559 31560 return y; 31561 31562 } 31563 31564 getZ( index ) { 31565 31566 let z = this.data.array[ index * this.data.stride + this.offset + 2 ]; 31567 31568 if ( this.normalized ) z = denormalize( z, this.array ); 31569 31570 return z; 31571 31572 } 31573 31574 getW( index ) { 31575 31576 let w = this.data.array[ index * this.data.stride + this.offset + 3 ]; 31577 31578 if ( this.normalized ) w = denormalize( w, this.array ); 31579 31580 return w; 31581 31582 } 31583 31584 setXY( index, x, y ) { 31585 31586 index = index * this.data.stride + this.offset; 31587 31588 if ( this.normalized ) { 31589 31590 x = normalize( x, this.array ); 31591 y = normalize( y, this.array ); 31592 31593 } 31594 31595 this.data.array[ index + 0 ] = x; 31596 this.data.array[ index + 1 ] = y; 31597 31598 return this; 31599 31600 } 31601 31602 setXYZ( index, x, y, z ) { 31603 31604 index = index * this.data.stride + this.offset; 31605 31606 if ( this.normalized ) { 31607 31608 x = normalize( x, this.array ); 31609 y = normalize( y, this.array ); 31610 z = normalize( z, this.array ); 31611 31612 } 31613 31614 this.data.array[ index + 0 ] = x; 31615 this.data.array[ index + 1 ] = y; 31616 this.data.array[ index + 2 ] = z; 31617 31618 return this; 31619 31620 } 31621 31622 setXYZW( index, x, y, z, w ) { 31623 31624 index = index * this.data.stride + this.offset; 31625 31626 if ( this.normalized ) { 31627 31628 x = normalize( x, this.array ); 31629 y = normalize( y, this.array ); 31630 z = normalize( z, this.array ); 31631 w = normalize( w, this.array ); 31632 31633 } 31634 31635 this.data.array[ index + 0 ] = x; 31636 this.data.array[ index + 1 ] = y; 31637 this.data.array[ index + 2 ] = z; 31638 this.data.array[ index + 3 ] = w; 31639 31640 return this; 31641 31642 } 31643 31644 clone( data ) { 31645 31646 if ( data === undefined ) { 31647 31648 console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' ); 31649 31650 const array = []; 31651 31652 for ( let i = 0; i < this.count; i ++ ) { 31653 31654 const index = i * this.data.stride + this.offset; 31655 31656 for ( let j = 0; j < this.itemSize; j ++ ) { 31657 31658 array.push( this.data.array[ index + j ] ); 31659 31660 } 31661 31662 } 31663 31664 return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized ); 31665 31666 } else { 31667 31668 if ( data.interleavedBuffers === undefined ) { 31669 31670 data.interleavedBuffers = {}; 31671 31672 } 31673 31674 if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { 31675 31676 data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data ); 31677 31678 } 31679 31680 return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized ); 31681 31682 } 31683 31684 } 31685 31686 toJSON( data ) { 31687 31688 if ( data === undefined ) { 31689 31690 console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' ); 31691 31692 const array = []; 31693 31694 for ( let i = 0; i < this.count; i ++ ) { 31695 31696 const index = i * this.data.stride + this.offset; 31697 31698 for ( let j = 0; j < this.itemSize; j ++ ) { 31699 31700 array.push( this.data.array[ index + j ] ); 31701 31702 } 31703 31704 } 31705 31706 // de-interleave data and save it as an ordinary buffer attribute for now 31707 31708 return { 31709 itemSize: this.itemSize, 31710 type: this.array.constructor.name, 31711 array: array, 31712 normalized: this.normalized 31713 }; 31714 31715 } else { 31716 31717 // save as true interleaved attribute 31718 31719 if ( data.interleavedBuffers === undefined ) { 31720 31721 data.interleavedBuffers = {}; 31722 31723 } 31724 31725 if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { 31726 31727 data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data ); 31728 31729 } 31730 31731 return { 31732 isInterleavedBufferAttribute: true, 31733 itemSize: this.itemSize, 31734 data: this.data.uuid, 31735 offset: this.offset, 31736 normalized: this.normalized 31737 }; 31738 31739 } 31740 31741 } 31742 31743} 31744 31745class SpriteMaterial extends Material { 31746 31747 constructor( parameters ) { 31748 31749 super(); 31750 31751 this.isSpriteMaterial = true; 31752 31753 this.type = 'SpriteMaterial'; 31754 31755 this.color = new Color( 0xffffff ); 31756 31757 this.map = null; 31758 31759 this.alphaMap = null; 31760 31761 this.rotation = 0; 31762 31763 this.sizeAttenuation = true; 31764 31765 this.transparent = true; 31766 31767 this.fog = true; 31768 31769 this.setValues( parameters ); 31770 31771 } 31772 31773 copy( source ) { 31774 31775 super.copy( source ); 31776 31777 this.color.copy( source.color ); 31778 31779 this.map = source.map; 31780 31781 this.alphaMap = source.alphaMap; 31782 31783 this.rotation = source.rotation; 31784 31785 this.sizeAttenuation = source.sizeAttenuation; 31786
vendor: 6,736 bytes, lines 31787-32123
31787 this.fog = source.fog; 31788 31789 return this; 31790 31791 } 31792 31793} 31794 31795let _geometry; 31796 31797const _intersectPoint = /*@__PURE__*/ new Vector3(); 31798const _worldScale = /*@__PURE__*/ new Vector3(); 31799const _mvPosition = /*@__PURE__*/ new Vector3(); 31800 31801const _alignedPosition = /*@__PURE__*/ new Vector2(); 31802const _rotatedPosition = /*@__PURE__*/ new Vector2(); 31803const _viewWorldMatrix = /*@__PURE__*/ new Matrix4(); 31804 31805const _vA = /*@__PURE__*/ new Vector3(); 31806const _vB = /*@__PURE__*/ new Vector3(); 31807const _vC = /*@__PURE__*/ new Vector3(); 31808 31809const _uvA = /*@__PURE__*/ new Vector2(); 31810const _uvB = /*@__PURE__*/ new Vector2(); 31811const _uvC = /*@__PURE__*/ new Vector2(); 31812 31813class Sprite extends Object3D { 31814 31815 constructor( material = new SpriteMaterial() ) { 31816 31817 super(); 31818 31819 this.isSprite = true; 31820 31821 this.type = 'Sprite'; 31822 31823 if ( _geometry === undefined ) { 31824 31825 _geometry = new BufferGeometry(); 31826 31827 const float32Array = new Float32Array( [ 31828 - 0.5, - 0.5, 0, 0, 0, 31829 0.5, - 0.5, 0, 1, 0, 31830 0.5, 0.5, 0, 1, 1, 31831 - 0.5, 0.5, 0, 0, 1 31832 ] ); 31833 31834 const interleavedBuffer = new InterleavedBuffer( float32Array, 5 ); 31835 31836 _geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] ); 31837 _geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) ); 31838 _geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) ); 31839 31840 } 31841 31842 this.geometry = _geometry; 31843 this.material = material; 31844 31845 this.center = new Vector2( 0.5, 0.5 ); 31846 31847 } 31848 31849 raycast( raycaster, intersects ) { 31850 31851 if ( raycaster.camera === null ) { 31852 31853 console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' ); 31854 31855 } 31856 31857 _worldScale.setFromMatrixScale( this.matrixWorld ); 31858 31859 _viewWorldMatrix.copy( raycaster.camera.matrixWorld ); 31860 this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld ); 31861 31862 _mvPosition.setFromMatrixPosition( this.modelViewMatrix ); 31863 31864 if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) { 31865 31866 _worldScale.multiplyScalar( - _mvPosition.z ); 31867 31868 } 31869 31870 const rotation = this.material.rotation; 31871 let sin, cos; 31872 31873 if ( rotation !== 0 ) { 31874 31875 cos = Math.cos( rotation ); 31876 sin = Math.sin( rotation ); 31877 31878 } 31879 31880 const center = this.center; 31881 31882 transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 31883 transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 31884 transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 31885 31886 _uvA.set( 0, 0 ); 31887 _uvB.set( 1, 0 ); 31888 _uvC.set( 1, 1 ); 31889 31890 // check first triangle 31891 let intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC, false, _intersectPoint ); 31892 31893 if ( intersect === null ) { 31894 31895 // check second triangle 31896 transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 31897 _uvB.set( 0, 1 ); 31898 31899 intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB, false, _intersectPoint ); 31900 if ( intersect === null ) { 31901 31902 return; 31903 31904 } 31905 31906 } 31907 31908 const distance = raycaster.ray.origin.distanceTo( _intersectPoint ); 31909 31910 if ( distance < raycaster.near || distance > raycaster.far ) return; 31911 31912 intersects.push( { 31913 31914 distance: distance, 31915 point: _intersectPoint.clone(), 31916 uv: Triangle.getInterpolation( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), 31917 face: null, 31918 object: this 31919 31920 } ); 31921 31922 } 31923 31924 copy( source, recursive ) { 31925 31926 super.copy( source, recursive ); 31927 31928 if ( source.center !== undefined ) this.center.copy( source.center ); 31929 31930 this.material = source.material; 31931 31932 return this; 31933 31934 } 31935 31936} 31937 31938function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) { 31939 31940 // compute position in camera space 31941 _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale ); 31942 31943 // to check if rotation is not zero 31944 if ( sin !== undefined ) { 31945 31946 _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y ); 31947 _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y ); 31948 31949 } else { 31950 31951 _rotatedPosition.copy( _alignedPosition ); 31952 31953 } 31954 31955 31956 vertexPosition.copy( mvPosition ); 31957 vertexPosition.x += _rotatedPosition.x; 31958 vertexPosition.y += _rotatedPosition.y; 31959 31960 // transform to world space 31961 vertexPosition.applyMatrix4( _viewWorldMatrix ); 31962 31963} 31964 31965const _v1$2 = /*@__PURE__*/ new Vector3(); 31966const _v2$1 = /*@__PURE__*/ new Vector3(); 31967 31968class LOD extends Object3D { 31969 31970 constructor() { 31971 31972 super(); 31973 31974 this._currentLevel = 0; 31975 31976 this.type = 'LOD'; 31977 31978 Object.defineProperties( this, { 31979 levels: { 31980 enumerable: true, 31981 value: [] 31982 }, 31983 isLOD: { 31984 value: true, 31985 } 31986 } ); 31987 31988 this.autoUpdate = true; 31989 31990 } 31991 31992 copy( source ) { 31993 31994 super.copy( source, false ); 31995 31996 const levels = source.levels; 31997 31998 for ( let i = 0, l = levels.length; i < l; i ++ ) { 31999 32000 const level = levels[ i ]; 32001 32002 this.addLevel( level.object.clone(), level.distance, level.hysteresis ); 32003 32004 } 32005 32006 this.autoUpdate = source.autoUpdate; 32007 32008 return this; 32009 32010 } 32011 32012 addLevel( object, distance = 0, hysteresis = 0 ) { 32013 32014 distance = Math.abs( distance ); 32015 32016 const levels = this.levels; 32017 32018 let l; 32019 32020 for ( l = 0; l < levels.length; l ++ ) { 32021 32022 if ( distance < levels[ l ].distance ) { 32023 32024 break; 32025 32026 } 32027 32028 } 32029 32030 levels.splice( l, 0, { distance: distance, hysteresis: hysteresis, object: object } ); 32031 32032 this.add( object ); 32033 32034 return this; 32035 32036 } 32037 32038 getCurrentLevel() { 32039 32040 return this._currentLevel; 32041 32042 } 32043 32044 32045 32046 getObjectForDistance( distance ) { 32047 32048 const levels = this.levels; 32049 32050 if ( levels.length > 0 ) { 32051 32052 let i, l; 32053 32054 for ( i = 1, l = levels.length; i < l; i ++ ) { 32055 32056 let levelDistance = levels[ i ].distance; 32057 32058 if ( levels[ i ].object.visible ) { 32059 32060 levelDistance -= levelDistance * levels[ i ].hysteresis; 32061 32062 } 32063 32064 if ( distance < levelDistance ) { 32065 32066 break; 32067 32068 } 32069 32070 } 32071 32072 return levels[ i - 1 ].object; 32073 32074 } 32075 32076 return null; 32077 32078 } 32079 32080 raycast( raycaster, intersects ) { 32081 32082 const levels = this.levels; 32083 32084 if ( levels.length > 0 ) { 32085 32086 _v1$2.setFromMatrixPosition( this.matrixWorld ); 32087 32088 const distance = raycaster.ray.origin.distanceTo( _v1$2 ); 32089 32090 this.getObjectForDistance( distance ).raycast( raycaster, intersects ); 32091 32092 } 32093 32094 } 32095 32096 update( camera ) { 32097 32098 const levels = this.levels; 32099 32100 if ( levels.length > 1 ) { 32101 32102 _v1$2.setFromMatrixPosition( camera.matrixWorld ); 32103 _v2$1.setFromMatrixPosition( this.matrixWorld ); 32104 32105 const distance = _v1$2.distanceTo( _v2$1 ) / camera.zoom; 32106 32107 levels[ 0 ].object.visible = true; 32108 32109 let i, l; 32110 32111 for ( i = 1, l = levels.length; i < l; i ++ ) { 32112 32113 let levelDistance = levels[ i ].distance; 32114 32115 if ( levels[ i ].object.visible ) { 32116 32117 levelDistance -= levelDistance * levels[ i ].hysteresis; 32118 32119 } 32120 32121 if ( distance >= levelDistance ) { 32122 32123 levels[ i - 1 ].object.visible = false;
vendor: 4,383 bytes, lines 32124-32357
32124 levels[ i ].object.visible = true; 32125 32126 } else { 32127 32128 break; 32129 32130 } 32131 32132 } 32133 32134 this._currentLevel = i - 1; 32135 32136 for ( ; i < l; i ++ ) { 32137 32138 levels[ i ].object.visible = false; 32139 32140 } 32141 32142 } 32143 32144 } 32145 32146 toJSON( meta ) { 32147 32148 const data = super.toJSON( meta ); 32149 32150 if ( this.autoUpdate === false ) data.object.autoUpdate = false; 32151 32152 data.object.levels = []; 32153 32154 const levels = this.levels; 32155 32156 for ( let i = 0, l = levels.length; i < l; i ++ ) { 32157 32158 const level = levels[ i ]; 32159 32160 data.object.levels.push( { 32161 object: level.object.uuid, 32162 distance: level.distance, 32163 hysteresis: level.hysteresis 32164 } ); 32165 32166 } 32167 32168 return data; 32169 32170 } 32171 32172} 32173 32174const _basePosition = /*@__PURE__*/ new Vector3(); 32175 32176const _skinIndex = /*@__PURE__*/ new Vector4(); 32177const _skinWeight = /*@__PURE__*/ new Vector4(); 32178 32179const _vector3 = /*@__PURE__*/ new Vector3(); 32180const _matrix4 = /*@__PURE__*/ new Matrix4(); 32181const _vertex = /*@__PURE__*/ new Vector3(); 32182 32183const _sphere$4 = /*@__PURE__*/ new Sphere(); 32184const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); 32185const _ray$2 = /*@__PURE__*/ new Ray(); 32186 32187class SkinnedMesh extends Mesh { 32188 32189 constructor( geometry, material ) { 32190 32191 super( geometry, material ); 32192 32193 this.isSkinnedMesh = true; 32194 32195 this.type = 'SkinnedMesh'; 32196 32197 this.bindMode = AttachedBindMode; 32198 this.bindMatrix = new Matrix4(); 32199 this.bindMatrixInverse = new Matrix4(); 32200 32201 this.boundingBox = null; 32202 this.boundingSphere = null; 32203 32204 } 32205 32206 computeBoundingBox() { 32207 32208 const geometry = this.geometry; 32209 32210 if ( this.boundingBox === null ) { 32211 32212 this.boundingBox = new Box3(); 32213 32214 } 32215 32216 this.boundingBox.makeEmpty(); 32217 32218 const positionAttribute = geometry.getAttribute( 'position' ); 32219 32220 for ( let i = 0; i < positionAttribute.count; i ++ ) { 32221 32222 this.getVertexPosition( i, _vertex ); 32223 this.boundingBox.expandByPoint( _vertex ); 32224 32225 } 32226 32227 } 32228 32229 computeBoundingSphere() { 32230 32231 const geometry = this.geometry; 32232 32233 if ( this.boundingSphere === null ) { 32234 32235 this.boundingSphere = new Sphere(); 32236 32237 } 32238 32239 this.boundingSphere.makeEmpty(); 32240 32241 const positionAttribute = geometry.getAttribute( 'position' ); 32242 32243 for ( let i = 0; i < positionAttribute.count; i ++ ) { 32244 32245 this.getVertexPosition( i, _vertex ); 32246 this.boundingSphere.expandByPoint( _vertex ); 32247 32248 } 32249 32250 } 32251 32252 copy( source, recursive ) { 32253 32254 super.copy( source, recursive ); 32255 32256 this.bindMode = source.bindMode; 32257 this.bindMatrix.copy( source.bindMatrix ); 32258 this.bindMatrixInverse.copy( source.bindMatrixInverse ); 32259 32260 this.skeleton = source.skeleton; 32261 32262 if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); 32263 if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); 32264 32265 return this; 32266 32267 } 32268 32269 raycast( raycaster, intersects ) { 32270 32271 const material = this.material; 32272 const matrixWorld = this.matrixWorld; 32273 32274 if ( material === undefined ) return; 32275 32276 // test with bounding sphere in world space 32277 32278 if ( this.boundingSphere === null ) this.computeBoundingSphere(); 32279 32280 _sphere$4.copy( this.boundingSphere ); 32281 _sphere$4.applyMatrix4( matrixWorld ); 32282 32283 if ( raycaster.ray.intersectsSphere( _sphere$4 ) === false ) return; 32284 32285 // convert ray to local space of skinned mesh 32286 32287 _inverseMatrix$2.copy( matrixWorld ).invert(); 32288 _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); 32289 32290 // test with bounding box in local space 32291 32292 if ( this.boundingBox !== null ) { 32293 32294 if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return; 32295 32296 } 32297 32298 // test for intersections with geometry 32299 32300 this._computeIntersections( raycaster, intersects, _ray$2 ); 32301 32302 } 32303 32304 getVertexPosition( index, target ) { 32305 32306 super.getVertexPosition( index, target ); 32307 32308 this.applyBoneTransform( index, target ); 32309 32310 return target; 32311 32312 } 32313 32314 bind( skeleton, bindMatrix ) { 32315 32316 this.skeleton = skeleton; 32317 32318 if ( bindMatrix === undefined ) { 32319 32320 this.updateMatrixWorld( true ); 32321 32322 this.skeleton.calculateInverses(); 32323 32324 bindMatrix = this.matrixWorld; 32325 32326 } 32327 32328 this.bindMatrix.copy( bindMatrix ); 32329 this.bindMatrixInverse.copy( bindMatrix ).invert(); 32330 32331 } 32332 32333 pose() { 32334 32335 this.skeleton.pose(); 32336 32337 } 32338 32339 normalizeSkinWeights() { 32340 32341 const vector = new Vector4(); 32342 32343 const skinWeight = this.geometry.attributes.skinWeight; 32344 32345 for ( let i = 0, l = skinWeight.count; i < l; i ++ ) { 32346 32347 vector.fromBufferAttribute( skinWeight, i ); 32348 32349 const scale = 1.0 / vector.manhattanLength(); 32350 32351 if ( scale !== Infinity ) { 32352 32353 vector.multiplyScalar( scale ); 32354 32355 } else { 32356 32357 vector.set( 1, 0, 0, 0 );
vendor: 12,910 bytes, lines 32357-33029
32357 // do something reasonable 32358 32359 } 32360 32361 skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w ); 32362 32363 } 32364 32365 } 32366 32367 updateMatrixWorld( force ) { 32368 32369 super.updateMatrixWorld( force ); 32370 32371 if ( this.bindMode === AttachedBindMode ) { 32372 32373 this.bindMatrixInverse.copy( this.matrixWorld ).invert(); 32374 32375 } else if ( this.bindMode === DetachedBindMode ) { 32376 32377 this.bindMatrixInverse.copy( this.bindMatrix ).invert(); 32378 32379 } else { 32380 32381 console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); 32382 32383 } 32384 32385 } 32386 32387 applyBoneTransform( index, vector ) { 32388 32389 const skeleton = this.skeleton; 32390 const geometry = this.geometry; 32391 32392 _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); 32393 _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); 32394 32395 _basePosition.copy( vector ).applyMatrix4( this.bindMatrix ); 32396 32397 vector.set( 0, 0, 0 ); 32398 32399 for ( let i = 0; i < 4; i ++ ) { 32400 32401 const weight = _skinWeight.getComponent( i ); 32402 32403 if ( weight !== 0 ) { 32404 32405 const boneIndex = _skinIndex.getComponent( i ); 32406 32407 _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); 32408 32409 vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); 32410 32411 } 32412 32413 } 32414 32415 return vector.applyMatrix4( this.bindMatrixInverse ); 32416 32417 } 32418 32419} 32420 32421class Bone extends Object3D { 32422 32423 constructor() { 32424 32425 super(); 32426 32427 this.isBone = true; 32428 32429 this.type = 'Bone'; 32430 32431 } 32432 32433} 32434 32435class DataTexture extends Texture { 32436 32437 constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { 32438 32439 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); 32440 32441 this.isDataTexture = true; 32442 32443 this.image = { data: data, width: width, height: height }; 32444 32445 this.generateMipmaps = false; 32446 this.flipY = false; 32447 this.unpackAlignment = 1; 32448 32449 } 32450 32451} 32452 32453const _offsetMatrix = /*@__PURE__*/ new Matrix4(); 32454const _identityMatrix$1 = /*@__PURE__*/ new Matrix4(); 32455 32456class Skeleton { 32457 32458 constructor( bones = [], boneInverses = [] ) { 32459 32460 this.uuid = generateUUID(); 32461 32462 this.bones = bones.slice( 0 ); 32463 this.boneInverses = boneInverses; 32464 this.boneMatrices = null; 32465 32466 this.boneTexture = null; 32467 32468 this.init(); 32469 32470 } 32471 32472 init() { 32473 32474 const bones = this.bones; 32475 const boneInverses = this.boneInverses; 32476 32477 this.boneMatrices = new Float32Array( bones.length * 16 ); 32478 32479 // calculate inverse bone matrices if necessary 32480 32481 if ( boneInverses.length === 0 ) { 32482 32483 this.calculateInverses(); 32484 32485 } else { 32486 32487 // handle special case 32488 32489 if ( bones.length !== boneInverses.length ) { 32490 32491 console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' ); 32492 32493 this.boneInverses = []; 32494 32495 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32496 32497 this.boneInverses.push( new Matrix4() ); 32498 32499 } 32500 32501 } 32502 32503 } 32504 32505 } 32506 32507 calculateInverses() { 32508 32509 this.boneInverses.length = 0; 32510 32511 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32512 32513 const inverse = new Matrix4(); 32514 32515 if ( this.bones[ i ] ) { 32516 32517 inverse.copy( this.bones[ i ].matrixWorld ).invert(); 32518 32519 } 32520 32521 this.boneInverses.push( inverse ); 32522 32523 } 32524 32525 } 32526 32527 pose() { 32528 32529 // recover the bind-time world matrices 32530 32531 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32532 32533 const bone = this.bones[ i ]; 32534 32535 if ( bone ) { 32536 32537 bone.matrixWorld.copy( this.boneInverses[ i ] ).invert(); 32538 32539 } 32540 32541 } 32542 32543 // compute the local matrices, positions, rotations and scales 32544 32545 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32546 32547 const bone = this.bones[ i ]; 32548 32549 if ( bone ) { 32550 32551 if ( bone.parent && bone.parent.isBone ) { 32552 32553 bone.matrix.copy( bone.parent.matrixWorld ).invert(); 32554 bone.matrix.multiply( bone.matrixWorld ); 32555 32556 } else { 32557 32558 bone.matrix.copy( bone.matrixWorld ); 32559 32560 } 32561 32562 bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); 32563 32564 } 32565 32566 } 32567 32568 } 32569 32570 update() { 32571 32572 const bones = this.bones; 32573 const boneInverses = this.boneInverses; 32574 const boneMatrices = this.boneMatrices; 32575 const boneTexture = this.boneTexture; 32576 32577 // flatten bone matrices to array 32578 32579 for ( let i = 0, il = bones.length; i < il; i ++ ) { 32580 32581 // compute the offset between the current and the original transform 32582 32583 const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix$1; 32584 32585 _offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); 32586 _offsetMatrix.toArray( boneMatrices, i * 16 ); 32587 32588 } 32589 32590 if ( boneTexture !== null ) { 32591 32592 boneTexture.needsUpdate = true; 32593 32594 } 32595 32596 } 32597 32598 clone() { 32599 32600 return new Skeleton( this.bones, this.boneInverses ); 32601 32602 } 32603 32604 computeBoneTexture() { 32605 32606 // layout (1 matrix = 4 pixels) 32607 // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) 32608 // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) 32609 // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) 32610 // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) 32611 // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) 32612 32613 let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix 32614 size = Math.ceil( size / 4 ) * 4; 32615 size = Math.max( size, 4 ); 32616 32617 const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel 32618 boneMatrices.set( this.boneMatrices ); // copy current values 32619 32620 const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); 32621 boneTexture.needsUpdate = true; 32622 32623 this.boneMatrices = boneMatrices; 32624 this.boneTexture = boneTexture; 32625 32626 return this; 32627 32628 } 32629 32630 getBoneByName( name ) { 32631 32632 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32633 32634 const bone = this.bones[ i ]; 32635 32636 if ( bone.name === name ) { 32637 32638 return bone; 32639 32640 } 32641 32642 } 32643 32644 return undefined; 32645 32646 } 32647 32648 dispose( ) { 32649 32650 if ( this.boneTexture !== null ) { 32651 32652 this.boneTexture.dispose(); 32653 32654 this.boneTexture = null; 32655 32656 } 32657 32658 } 32659 32660 fromJSON( json, bones ) { 32661 32662 this.uuid = json.uuid; 32663 32664 for ( let i = 0, l = json.bones.length; i < l; i ++ ) { 32665 32666 const uuid = json.bones[ i ]; 32667 let bone = bones[ uuid ]; 32668 32669 if ( bone === undefined ) { 32670 32671 console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid ); 32672 bone = new Bone(); 32673 32674 } 32675 32676 this.bones.push( bone ); 32677 this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) ); 32678 32679 } 32680 32681 this.init(); 32682 32683 return this; 32684 32685 } 32686 32687 toJSON() { 32688 32689 const data = { 32690 metadata: { 32691 version: 4.6, 32692 type: 'Skeleton', 32693 generator: 'Skeleton.toJSON' 32694 }, 32695 bones: [], 32696 boneInverses: [] 32697 }; 32698 32699 data.uuid = this.uuid; 32700 32701 const bones = this.bones; 32702 const boneInverses = this.boneInverses; 32703 32704 for ( let i = 0, l = bones.length; i < l; i ++ ) { 32705 32706 const bone = bones[ i ]; 32707 data.bones.push( bone.uuid ); 32708 32709 const boneInverse = boneInverses[ i ]; 32710 data.boneInverses.push( boneInverse.toArray() ); 32711 32712 } 32713 32714 return data; 32715 32716 } 32717 32718} 32719 32720class InstancedBufferAttribute extends BufferAttribute { 32721 32722 constructor( array, itemSize, normalized, meshPerAttribute = 1 ) { 32723 32724 super( array, itemSize, normalized ); 32725 32726 this.isInstancedBufferAttribute = true; 32727 32728 this.meshPerAttribute = meshPerAttribute; 32729 32730 } 32731 32732 copy( source ) { 32733 32734 super.copy( source ); 32735 32736 this.meshPerAttribute = source.meshPerAttribute; 32737 32738 return this; 32739 32740 } 32741 32742 toJSON() { 32743 32744 const data = super.toJSON(); 32745 32746 data.meshPerAttribute = this.meshPerAttribute; 32747 32748 data.isInstancedBufferAttribute = true; 32749 32750 return data; 32751 32752 } 32753 32754} 32755 32756const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4(); 32757const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4(); 32758 32759const _instanceIntersects = []; 32760 32761const _box3 = /*@__PURE__*/ new Box3(); 32762const _identity = /*@__PURE__*/ new Matrix4(); 32763const _mesh$1 = /*@__PURE__*/ new Mesh(); 32764const _sphere$3 = /*@__PURE__*/ new Sphere(); 32765 32766class InstancedMesh extends Mesh { 32767 32768 constructor( geometry, material, count ) { 32769 32770 super( geometry, material ); 32771 32772 this.isInstancedMesh = true; 32773 32774 this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 ); 32775 this.instanceColor = null; 32776 this.morphTexture = null; 32777 32778 this.count = count; 32779 32780 this.boundingBox = null; 32781 this.boundingSphere = null; 32782 32783 for ( let i = 0; i < count; i ++ ) { 32784 32785 this.setMatrixAt( i, _identity ); 32786 32787 } 32788 32789 } 32790 32791 computeBoundingBox() { 32792 32793 const geometry = this.geometry; 32794 const count = this.count; 32795 32796 if ( this.boundingBox === null ) { 32797 32798 this.boundingBox = new Box3(); 32799 32800 } 32801 32802 if ( geometry.boundingBox === null ) { 32803 32804 geometry.computeBoundingBox(); 32805 32806 } 32807 32808 this.boundingBox.makeEmpty(); 32809 32810 for ( let i = 0; i < count; i ++ ) { 32811 32812 this.getMatrixAt( i, _instanceLocalMatrix ); 32813 32814 _box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix ); 32815 32816 this.boundingBox.union( _box3 ); 32817 32818 } 32819 32820 } 32821 32822 computeBoundingSphere() { 32823 32824 const geometry = this.geometry; 32825 const count = this.count; 32826 32827 if ( this.boundingSphere === null ) { 32828 32829 this.boundingSphere = new Sphere(); 32830 32831 } 32832 32833 if ( geometry.boundingSphere === null ) { 32834 32835 geometry.computeBoundingSphere(); 32836 32837 } 32838 32839 this.boundingSphere.makeEmpty(); 32840 32841 for ( let i = 0; i < count; i ++ ) { 32842 32843 this.getMatrixAt( i, _instanceLocalMatrix ); 32844 32845 _sphere$3.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix ); 32846 32847 this.boundingSphere.union( _sphere$3 ); 32848 32849 } 32850 32851 } 32852 32853 copy( source, recursive ) { 32854 32855 super.copy( source, recursive ); 32856 32857 this.instanceMatrix.copy( source.instanceMatrix ); 32858 32859 if ( source.morphTexture !== null ) this.morphTexture = source.morphTexture.clone(); 32860 if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone(); 32861 32862 this.count = source.count; 32863 32864 if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); 32865 if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); 32866 32867 return this; 32868 32869 } 32870 32871 getColorAt( index, color ) { 32872 32873 color.fromArray( this.instanceColor.array, index * 3 ); 32874 32875 } 32876 32877 getMatrixAt( index, matrix ) { 32878 32879 matrix.fromArray( this.instanceMatrix.array, index * 16 ); 32880 32881 } 32882 32883 getMorphAt( index, object ) { 32884 32885 const objectInfluences = object.morphTargetInfluences; 32886 32887 const array = this.morphTexture.source.data.data; 32888 32889 const len = objectInfluences.length + 1; // All influences + the baseInfluenceSum 32890 32891 const dataIndex = index * len + 1; // Skip the baseInfluenceSum at the beginning 32892 32893 for ( let i = 0; i < objectInfluences.length; i ++ ) { 32894 32895 objectInfluences[ i ] = array[ dataIndex + i ]; 32896 32897 } 32898 32899 } 32900 32901 raycast( raycaster, intersects ) { 32902 32903 const matrixWorld = this.matrixWorld; 32904 const raycastTimes = this.count; 32905 32906 _mesh$1.geometry = this.geometry; 32907 _mesh$1.material = this.material; 32908 32909 if ( _mesh$1.material === undefined ) return; 32910 32911 // test with bounding sphere first 32912 32913 if ( this.boundingSphere === null ) this.computeBoundingSphere(); 32914 32915 _sphere$3.copy( this.boundingSphere ); 32916 _sphere$3.applyMatrix4( matrixWorld ); 32917 32918 if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return; 32919 32920 // now test each instance 32921 32922 for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) { 32923 32924 // calculate the world matrix for each instance 32925 32926 this.getMatrixAt( instanceId, _instanceLocalMatrix ); 32927 32928 _instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix ); 32929 32930 // the mesh represents this single instance 32931 32932 _mesh$1.matrixWorld = _instanceWorldMatrix; 32933 32934 _mesh$1.raycast( raycaster, _instanceIntersects ); 32935 32936 // process the result of raycast 32937 32938 for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) { 32939 32940 const intersect = _instanceIntersects[ i ]; 32941 intersect.instanceId = instanceId; 32942 intersect.object = this; 32943 intersects.push( intersect ); 32944 32945 } 32946 32947 _instanceIntersects.length = 0; 32948 32949 } 32950 32951 } 32952 32953 setColorAt( index, color ) { 32954 32955 if ( this.instanceColor === null ) { 32956 32957 this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ), 3 ); 32958 32959 } 32960 32961 color.toArray( this.instanceColor.array, index * 3 ); 32962 32963 } 32964 32965 setMatrixAt( index, matrix ) { 32966 32967 matrix.toArray( this.instanceMatrix.array, index * 16 ); 32968 32969 } 32970 32971 setMorphAt( index, object ) { 32972 32973 const objectInfluences = object.morphTargetInfluences; 32974 32975 const len = objectInfluences.length + 1; // morphBaseInfluence + all influences 32976 32977 if ( this.morphTexture === null ) { 32978 32979 this.morphTexture = new DataTexture( new Float32Array( len * this.count ), len, this.count, RedFormat, FloatType ); 32980 32981 } 32982 32983 const array = this.morphTexture.source.data.data; 32984 32985 let morphInfluencesSum = 0; 32986 32987 for ( let i = 0; i < objectInfluences.length; i ++ ) { 32988 32989 morphInfluencesSum += objectInfluences[ i ]; 32990 32991 } 32992 32993 const morphBaseInfluence = this.geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; 32994 32995 const dataIndex = len * index; 32996 32997 array[ dataIndex ] = morphBaseInfluence; 32998 32999 array.set( objectInfluences, dataIndex + 1 ); 33000 33001 } 33002 33003 updateMorphTargets() { 33004 33005 } 33006 33007 dispose() { 33008 33009 this.dispatchEvent( { type: 'dispose' } ); 33010 33011 if ( this.morphTexture !== null ) { 33012 33013 this.morphTexture.dispose(); 33014 this.morphTexture = null; 33015 33016 } 33017 33018 return this; 33019 33020 } 33021 33022} 33023 33024function sortOpaque( a, b ) { 33025 33026 return a.z - b.z; 33027 33028} 33029
vendor: 4,321 bytes, lines 33030-33204
33030function sortTransparent( a, b ) { 33031 33032 return b.z - a.z; 33033 33034} 33035 33036class MultiDrawRenderList { 33037 33038 constructor() { 33039 33040 this.index = 0; 33041 this.pool = []; 33042 this.list = []; 33043 33044 } 33045 33046 push( drawRange, z ) { 33047 33048 const pool = this.pool; 33049 const list = this.list; 33050 if ( this.index >= pool.length ) { 33051 33052 pool.push( { 33053 33054 start: - 1, 33055 count: - 1, 33056 z: - 1, 33057 33058 } ); 33059 33060 } 33061 33062 const item = pool[ this.index ]; 33063 list.push( item ); 33064 this.index ++; 33065 33066 item.start = drawRange.start; 33067 item.count = drawRange.count; 33068 item.z = z; 33069 33070 } 33071 33072 reset() { 33073 33074 this.list.length = 0; 33075 this.index = 0; 33076 33077 } 33078 33079} 33080 33081const ID_ATTR_NAME = 'batchId'; 33082const _matrix$1 = /*@__PURE__*/ new Matrix4(); 33083const _invMatrixWorld = /*@__PURE__*/ new Matrix4(); 33084const _identityMatrix = /*@__PURE__*/ new Matrix4(); 33085const _whiteColor = /*@__PURE__*/ new Color( 1, 1, 1 ); 33086const _projScreenMatrix$2 = /*@__PURE__*/ new Matrix4(); 33087const _frustum = /*@__PURE__*/ new Frustum(); 33088const _box$1 = /*@__PURE__*/ new Box3(); 33089const _sphere$2 = /*@__PURE__*/ new Sphere(); 33090const _vector$5 = /*@__PURE__*/ new Vector3(); 33091const _forward = /*@__PURE__*/ new Vector3(); 33092const _temp = /*@__PURE__*/ new Vector3(); 33093const _renderList = /*@__PURE__*/ new MultiDrawRenderList(); 33094const _mesh = /*@__PURE__*/ new Mesh(); 33095const _batchIntersects = []; 33096 33097// @TODO: SkinnedMesh support? 33098// @TODO: geometry.groups support? 33099// @TODO: geometry.drawRange support? 33100// @TODO: geometry.morphAttributes support? 33101// @TODO: Support uniform parameter per geometry 33102// @TODO: Add an "optimize" function to pack geometry and remove data gaps 33103 33104// copies data from attribute "src" into "target" starting at "targetOffset" 33105function copyAttributeData( src, target, targetOffset = 0 ) { 33106 33107 const itemSize = target.itemSize; 33108 if ( src.isInterleavedBufferAttribute || src.array.constructor !== target.array.constructor ) { 33109 33110 // use the component getters and setters if the array data cannot 33111 // be copied directly 33112 const vertexCount = src.count; 33113 for ( let i = 0; i < vertexCount; i ++ ) { 33114 33115 for ( let c = 0; c < itemSize; c ++ ) { 33116 33117 target.setComponent( i + targetOffset, c, src.getComponent( i, c ) ); 33118 33119 } 33120 33121 } 33122 33123 } else { 33124 33125 // faster copy approach using typed array set function 33126 target.array.set( src.array, targetOffset * itemSize ); 33127 33128 } 33129 33130 target.needsUpdate = true; 33131 33132} 33133 33134class BatchedMesh extends Mesh { 33135 33136 get maxGeometryCount() { 33137 33138 return this._maxGeometryCount; 33139 33140 } 33141 33142 constructor( maxGeometryCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material ) { 33143 33144 super( new BufferGeometry(), material ); 33145 33146 this.isBatchedMesh = true; 33147 this.perObjectFrustumCulled = true; 33148 this.sortObjects = true; 33149 this.boundingBox = null; 33150 this.boundingSphere = null; 33151 this.customSort = null; 33152 33153 this._drawRanges = []; 33154 this._reservedRanges = []; 33155 33156 this._visibility = []; 33157 this._active = []; 33158 this._bounds = []; 33159 33160 this._maxGeometryCount = maxGeometryCount; 33161 this._maxVertexCount = maxVertexCount; 33162 this._maxIndexCount = maxIndexCount; 33163 33164 this._geometryInitialized = false; 33165 this._geometryCount = 0; 33166 this._multiDrawCounts = new Int32Array( maxGeometryCount ); 33167 this._multiDrawStarts = new Int32Array( maxGeometryCount ); 33168 this._multiDrawCount = 0; 33169 this._multiDrawInstances = null; 33170 this._visibilityChanged = true; 33171 33172 // Local matrix per geometry by using data texture 33173 this._matricesTexture = null; 33174 33175 this._initMatricesTexture(); 33176 33177 // Local color per geometry by using data texture 33178 this._colorsTexture = null; 33179 33180 } 33181 33182 _initMatricesTexture() { 33183 33184 // layout (1 matrix = 4 pixels) 33185 // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) 33186 // with 8x8 pixel texture max 16 matrices * 4 pixels = (8 * 8) 33187 // 16x16 pixel texture max 64 matrices * 4 pixels = (16 * 16) 33188 // 32x32 pixel texture max 256 matrices * 4 pixels = (32 * 32) 33189 // 64x64 pixel texture max 1024 matrices * 4 pixels = (64 * 64) 33190 33191 let size = Math.sqrt( this._maxGeometryCount * 4 ); // 4 pixels needed for 1 matrix 33192 size = Math.ceil( size / 4 ) * 4; 33193 size = Math.max( size, 4 ); 33194 33195 const matricesArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel 33196 const matricesTexture = new DataTexture( matricesArray, size, size, RGBAFormat, FloatType ); 33197 33198 this._matricesTexture = matricesTexture; 33199 33200 } 33201 33202 _initColorsTexture() { 33203 33204 let size = Math.sqrt( this._maxGeometryCount );
33205 size = Math.ceil( size ); 33206 33207 // 4 floats per RGBA pixel initialized to white 33208 const colorsArray = new Float32Array( size * size * 4 ).fill( 1 ); 33209 const colorsTexture = new DataTexture( colorsArray, size, size, RGBAFormat, FloatType ); 33210 colorsTexture.colorSpace = ColorManagement.workingColorSpace; 33211 33212 this._colorsTexture = colorsTexture; 33213 33214 } 33215 33216 _initializeGeometry( reference ) { 33217 33218 const geometry = this.geometry; 33219 const maxVertexCount = this._maxVertexCount; 33220 const maxGeometryCount = this._maxGeometryCount; 33221 const maxIndexCount = this._maxIndexCount; 33222 if ( this._geometryInitialized === false ) { 33223 33224 for ( const attributeName in reference.attributes ) { 33225 33226 const srcAttribute = reference.getAttribute( attributeName ); 33227 const { array, itemSize, normalized } = srcAttribute; 33228 33229 const dstArray = new array.constructor( maxVertexCount * itemSize ); 33230 const dstAttribute = new BufferAttribute( dstArray, itemSize, normalized ); 33231 33232 geometry.setAttribute( attributeName, dstAttribute ); 33233 33234 } 33235 33236 if ( reference.getIndex() !== null ) { 33237 33238 const indexArray = maxVertexCount > 65536 33239 ? new Uint32Array( maxIndexCount ) 33240 : new Uint16Array( maxIndexCount ); 33241 33242 geometry.setIndex( new BufferAttribute( indexArray, 1 ) ); 33243 33244 } 33245 33246 const idArray = maxGeometryCount > 65536 33247 ? new Uint32Array( maxVertexCount ) 33248 : new Uint16Array( maxVertexCount ); 33249 geometry.setAttribute( ID_ATTR_NAME, new BufferAttribute( idArray, 1 ) ); 33250 33251 this._geometryInitialized = true; 33252 33253 } 33254 33255 } 33256 33257 // Make sure the geometry is compatible with the existing combined geometry attributes 33258 _validateGeometry( geometry ) { 33259 33260 // check that the geometry doesn't have a version of our reserved id attribute 33261 if ( geometry.getAttribute( ID_ATTR_NAME ) ) { 33262 33263 throw new Error( `BatchedMesh: Geometry cannot use attribute "${ ID_ATTR_NAME }"` ); 33264 33265 } 33266 33267 // check to ensure the geometries are using consistent attributes and indices 33268 const batchGeometry = this.geometry; 33269 if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) { 33270 33271 throw new Error( 'BatchedMesh: All geometries must consistently have "index".' ); 33272 33273 } 33274 33275 for ( const attributeName in batchGeometry.attributes ) { 33276 33277 if ( attributeName === ID_ATTR_NAME ) { 33278 33279 continue; 33280 33281 } 33282 33283 if ( ! geometry.hasAttribute( attributeName ) ) { 33284 33285 throw new Error( `BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` ); 33286 33287 } 33288 33289 const srcAttribute = geometry.getAttribute( attributeName ); 33290 const dstAttribute = batchGeometry.getAttribute( attributeName ); 33291 if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) { 33292 33293 throw new Error( 'BatchedMesh: All attributes must have a consistent itemSize and normalized value.' ); 33294 33295 } 33296 33297 } 33298 33299 } 33300 33301 setCustomSort( func ) { 33302 33303 this.customSort = func; 33304 return this; 33305 33306 } 33307 33308 computeBoundingBox() { 33309 33310 if ( this.boundingBox === null ) { 33311 33312 this.boundingBox = new Box3(); 33313 33314 } 33315 33316 const geometryCount = this._geometryCount; 33317 const boundingBox = this.boundingBox; 33318 const active = this._active; 33319 33320 boundingBox.makeEmpty(); 33321 for ( let i = 0; i < geometryCount; i ++ ) { 33322 33323 if ( active[ i ] === false ) continue; 33324 33325 this.getMatrixAt( i, _matrix$1 ); 33326 this.getBoundingBoxAt( i, _box$1 ).applyMatrix4( _matrix$1 ); 33327 boundingBox.union( _box$1 ); 33328 33329 } 33330 33331 } 33332 33333 computeBoundingSphere() { 33334 33335 if ( this.boundingSphere === null ) { 33336 33337 this.boundingSphere = new Sphere(); 33338 33339 } 33340 33341 const geometryCount = this._geometryCount; 33342 const boundingSphere = this.boundingSphere; 33343 const active = this._active; 33344 33345 boundingSphere.makeEmpty(); 33346 for ( let i = 0; i < geometryCount; i ++ ) { 33347 33348 if ( active[ i ] === false ) continue; 33349 33350 this.getMatrixAt( i, _matrix$1 ); 33351 this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix$1 ); 33352 boundingSphere.union( _sphere$2 ); 33353 33354 } 33355 33356 } 33357 33358 addGeometry( geometry, vertexCount = - 1, indexCount = - 1 ) { 33359 33360 this._initializeGeometry( geometry ); 33361 33362 this._validateGeometry( geometry ); 33363 33364 // ensure we're not over geometry 33365 if ( this._geometryCount >= this._maxGeometryCount ) { 33366 33367 throw new Error( 'BatchedMesh: Maximum geometry count reached.' ); 33368 33369 } 33370 33371 // get the necessary range fo the geometry 33372 const reservedRange = { 33373 vertexStart: - 1, 33374 vertexCount: - 1, 33375 indexStart: - 1, 33376 indexCount: - 1, 33377 }; 33378 33379 let lastRange = null; 33380 const reservedRanges = this._reservedRanges; 33381 const drawRanges = this._drawRanges; 33382 const bounds = this._bounds; 33383 if ( this._geometryCount !== 0 ) { 33384 33385 lastRange = reservedRanges[ reservedRanges.length - 1 ]; 33386 33387 } 33388 33389 if ( vertexCount === - 1 ) { 33390 33391 reservedRange.vertexCount = geometry.getAttribute( 'position' ).count; 33392 33393 } else { 33394 33395 reservedRange.vertexCount = vertexCount; 33396 33397 } 33398 33399 if ( lastRange === null ) { 33400 33401 reservedRange.vertexStart = 0; 33402 33403 } else { 33404 33405 reservedRange.vertexStart = lastRange.vertexStart + lastRange.vertexCount; 33406 33407 } 33408 33409 const index = geometry.getIndex(); 33410 const hasIndex = index !== null; 33411 if ( hasIndex ) { 33412 33413 if ( indexCount === - 1 ) { 33414 33415 reservedRange.indexCount = index.count; 33416 33417 } else { 33418 33419 reservedRange.indexCount = indexCount; 33420 33421 } 33422 33423 if ( lastRange === null ) { 33424 33425 reservedRange.indexStart = 0; 33426 33427 } else { 33428 33429 reservedRange.indexStart = lastRange.indexStart + lastRange.indexCount; 33430 33431 } 33432 33433 } 33434 33435 if ( 33436 reservedRange.indexStart !== - 1 && 33437 reservedRange.indexStart + reservedRange.indexCount > this._maxIndexCount || 33438 reservedRange.vertexStart + reservedRange.vertexCount > this._maxVertexCount 33439 ) { 33440 33441 throw new Error( 'BatchedMesh: Reserved space request exceeds the maximum buffer size.' ); 33442 33443 } 33444 33445 const visibility = this._visibility; 33446 const active = this._active; 33447 const matricesTexture = this._matricesTexture; 33448 const matricesArray = this._matricesTexture.image.data; 33449 const colorsTexture = this._colorsTexture; 33450 33451 // push new visibility states 33452 visibility.push( true ); 33453 active.push( true ); 33454 33455 // update id 33456 const geometryId = this._geometryCount; 33457 this._geometryCount ++; 33458 33459 // initialize matrix information 33460 _identityMatrix.toArray( matricesArray, geometryId * 16 ); 33461 matricesTexture.needsUpdate = true; 33462 33463 // initialize the color to white 33464 if ( colorsTexture !== null ) { 33465 33466 _whiteColor.toArray( colorsTexture.image.data, geometryId * 4 ); 33467 colorsTexture.needsUpdate = true; 33468 33469 } 33470 33471 // add the reserved range and draw range objects 33472 reservedRanges.push( reservedRange ); 33473 drawRanges.push( { 33474 start: hasIndex ? reservedRange.indexStart : reservedRange.vertexStart, 33475 count: - 1 33476 } ); 33477 bounds.push( { 33478 boxInitialized: false, 33479 box: new Box3(), 33480 33481 sphereInitialized: false, 33482 sphere: new Sphere() 33483 } ); 33484 33485 // set the id for the geometry 33486 const idAttribute = this.geometry.getAttribute( ID_ATTR_NAME ); 33487 for ( let i = 0; i < reservedRange.vertexCount; i ++ ) { 33488 33489 idAttribute.setX( reservedRange.vertexStart + i, geometryId ); 33490 33491 } 33492 33493 idAttribute.needsUpdate = true; 33494 33495 // update the geometry 33496 this.setGeometryAt( geometryId, geometry ); 33497 33498 return geometryId; 33499 33500 } 33501 33502 setGeometryAt( id, geometry ) { 33503 33504 if ( id >= this._geometryCount ) { 33505 33506 throw new Error( 'BatchedMesh: Maximum geometry count reached.' ); 33507 33508 } 33509
33510 this._validateGeometry( geometry ); 33511 33512 const batchGeometry = this.geometry; 33513 const hasIndex = batchGeometry.getIndex() !== null; 33514 const dstIndex = batchGeometry.getIndex(); 33515 const srcIndex = geometry.getIndex(); 33516 const reservedRange = this._reservedRanges[ id ]; 33517 if ( 33518 hasIndex && 33519 srcIndex.count > reservedRange.indexCount || 33520 geometry.attributes.position.count > reservedRange.vertexCount 33521 ) { 33522 33523 throw new Error( 'BatchedMesh: Reserved space not large enough for provided geometry.' ); 33524 33525 } 33526 33527 // copy geometry over 33528 const vertexStart = reservedRange.vertexStart; 33529 const vertexCount = reservedRange.vertexCount; 33530 for ( const attributeName in batchGeometry.attributes ) { 33531 33532 if ( attributeName === ID_ATTR_NAME ) { 33533 33534 continue; 33535 33536 } 33537 33538 // copy attribute data 33539 const srcAttribute = geometry.getAttribute( attributeName ); 33540 const dstAttribute = batchGeometry.getAttribute( attributeName ); 33541 copyAttributeData( srcAttribute, dstAttribute, vertexStart ); 33542 33543 // fill the rest in with zeroes 33544 const itemSize = srcAttribute.itemSize; 33545 for ( let i = srcAttribute.count, l = vertexCount; i < l; i ++ ) { 33546 33547 const index = vertexStart + i; 33548 for ( let c = 0; c < itemSize; c ++ ) { 33549 33550 dstAttribute.setComponent( index, c, 0 ); 33551 33552 } 33553 33554 } 33555 33556 dstAttribute.needsUpdate = true; 33557 dstAttribute.addUpdateRange( vertexStart * itemSize, vertexCount * itemSize ); 33558 33559 } 33560 33561 // copy index 33562 if ( hasIndex ) { 33563 33564 const indexStart = reservedRange.indexStart; 33565 33566 // copy index data over 33567 for ( let i = 0; i < srcIndex.count; i ++ ) { 33568 33569 dstIndex.setX( indexStart + i, vertexStart + srcIndex.getX( i ) ); 33570 33571 } 33572 33573 // fill the rest in with zeroes 33574 for ( let i = srcIndex.count, l = reservedRange.indexCount; i < l; i ++ ) { 33575 33576 dstIndex.setX( indexStart + i, vertexStart ); 33577 33578 } 33579 33580 dstIndex.needsUpdate = true; 33581 dstIndex.addUpdateRange( indexStart, reservedRange.indexCount ); 33582 33583 } 33584 33585 // store the bounding boxes 33586 const bound = this._bounds[ id ]; 33587 if ( geometry.boundingBox !== null ) { 33588 33589 bound.box.copy( geometry.boundingBox ); 33590 bound.boxInitialized = true; 33591 33592 } else { 33593 33594 bound.boxInitialized = false; 33595 33596 } 33597 33598 if ( geometry.boundingSphere !== null ) { 33599 33600 bound.sphere.copy( geometry.boundingSphere ); 33601 bound.sphereInitialized = true; 33602 33603 } else { 33604 33605 bound.sphereInitialized = false; 33606 33607 } 33608 33609 // set drawRange count 33610 const drawRange = this._drawRanges[ id ]; 33611 const posAttr = geometry.getAttribute( 'position' ); 33612 drawRange.count = hasIndex ? srcIndex.count : posAttr.count; 33613 this._visibilityChanged = true; 33614 33615 return id; 33616 33617 } 33618 33619 deleteGeometry( geometryId ) { 33620 33621 // Note: User needs to call optimize() afterward to pack the data. 33622 33623 const active = this._active; 33624 if ( geometryId >= active.length || active[ geometryId ] === false ) { 33625 33626 return this; 33627 33628 } 33629 33630 active[ geometryId ] = false; 33631 this._visibilityChanged = true; 33632 33633 return this; 33634 33635 } 33636 33637 getInstanceCountAt( id ) { 33638 33639 if ( this._multiDrawInstances === null ) return null; 33640 33641 return this._multiDrawInstances[ id ]; 33642 33643 } 33644 33645 setInstanceCountAt( id, instanceCount ) { 33646 33647 if ( this._multiDrawInstances === null ) { 33648 33649 this._multiDrawInstances = new Int32Array( this._maxGeometryCount ).fill( 1 ); 33650 33651 } 33652 33653 this._multiDrawInstances[ id ] = instanceCount; 33654 33655 return id; 33656 33657 } 33658 33659 // get bounding box and compute it if it doesn't exist 33660 getBoundingBoxAt( id, target ) { 33661 33662 const active = this._active; 33663 if ( active[ id ] === false ) { 33664 33665 return null; 33666 33667 } 33668 33669 // compute bounding box 33670 const bound = this._bounds[ id ]; 33671 const box = bound.box; 33672 const geometry = this.geometry; 33673 if ( bound.boxInitialized === false ) { 33674 33675 box.makeEmpty(); 33676 33677 const index = geometry.index; 33678 const position = geometry.attributes.position; 33679 const drawRange = this._drawRanges[ id ]; 33680 for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) { 33681 33682 let iv = i; 33683 if ( index ) { 33684 33685 iv = index.getX( iv ); 33686 33687 } 33688 33689 box.expandByPoint( _vector$5.fromBufferAttribute( position, iv ) ); 33690 33691 } 33692 33693 bound.boxInitialized = true; 33694 33695 } 33696 33697 target.copy( box ); 33698 return target; 33699 33700 } 33701 33702 // get bounding sphere and compute it if it doesn't exist 33703 getBoundingSphereAt( id, target ) { 33704 33705 const active = this._active; 33706 if ( active[ id ] === false ) { 33707 33708 return null; 33709 33710 } 33711 33712 // compute bounding sphere 33713 const bound = this._bounds[ id ]; 33714 const sphere = bound.sphere; 33715 const geometry = this.geometry; 33716 if ( bound.sphereInitialized === false ) { 33717 33718 sphere.makeEmpty(); 33719 33720 this.getBoundingBoxAt( id, _box$1 ); 33721 _box$1.getCenter( sphere.center ); 33722 33723 const index = geometry.index; 33724 const position = geometry.attributes.position; 33725 const drawRange = this._drawRanges[ id ]; 33726 33727 let maxRadiusSq = 0; 33728 for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) { 33729 33730 let iv = i; 33731 if ( index ) { 33732 33733 iv = index.getX( iv ); 33734 33735 } 33736 33737 _vector$5.fromBufferAttribute( position, iv ); 33738 maxRadiusSq = Math.max( maxRadiusSq, sphere.center.distanceToSquared( _vector$5 ) ); 33739 33740 } 33741 33742 sphere.radius = Math.sqrt( maxRadiusSq ); 33743 bound.sphereInitialized = true; 33744 33745 } 33746 33747 target.copy( sphere ); 33748 return target; 33749 33750 } 33751
33752 setMatrixAt( geometryId, matrix ) { 33753 33754 // @TODO: Map geometryId to index of the arrays because 33755 // optimize() can make geometryId mismatch the index 33756 33757 const active = this._active; 33758 const matricesTexture = this._matricesTexture; 33759 const matricesArray = this._matricesTexture.image.data; 33760 const geometryCount = this._geometryCount; 33761 if ( geometryId >= geometryCount || active[ geometryId ] === false ) { 33762 33763 return this; 33764 33765 } 33766 33767 matrix.toArray( matricesArray, geometryId * 16 ); 33768 matricesTexture.needsUpdate = true; 33769 33770 return this; 33771 33772 } 33773 33774 getMatrixAt( geometryId, matrix ) { 33775 33776 const active = this._active; 33777 const matricesArray = this._matricesTexture.image.data; 33778 const geometryCount = this._geometryCount; 33779 if ( geometryId >= geometryCount || active[ geometryId ] === false ) { 33780 33781 return null; 33782 33783 } 33784 33785 return matrix.fromArray( matricesArray, geometryId * 16 ); 33786 33787 } 33788 33789 setColorAt( geometryId, color ) { 33790 33791 if ( this._colorsTexture === null ) { 33792 33793 this._initColorsTexture(); 33794 33795 } 33796 33797 // @TODO: Map geometryId to index of the arrays because 33798 // optimize() can make geometryId mismatch the index 33799 33800 const active = this._active; 33801 const colorsTexture = this._colorsTexture; 33802 const colorsArray = this._colorsTexture.image.data; 33803 const geometryCount = this._geometryCount; 33804 if ( geometryId >= geometryCount || active[ geometryId ] === false ) { 33805 33806 return this; 33807 33808 } 33809 33810 color.toArray( colorsArray, geometryId * 4 ); 33811 colorsTexture.needsUpdate = true; 33812 33813 return this; 33814 33815 } 33816 33817 getColorAt( geometryId, color ) { 33818 33819 const active = this._active; 33820 const colorsArray = this._colorsTexture.image.data; 33821 const geometryCount = this._geometryCount; 33822 if ( geometryId >= geometryCount || active[ geometryId ] === false ) { 33823 33824 return null; 33825 33826 } 33827 33828 return color.fromArray( colorsArray, geometryId * 4 ); 33829 33830 } 33831 33832 setVisibleAt( geometryId, value ) { 33833 33834 const visibility = this._visibility; 33835 const active = this._active; 33836 const geometryCount = this._geometryCount; 33837 33838 // if the geometry is out of range, not active, or visibility state 33839 // does not change then return early 33840 if ( 33841 geometryId >= geometryCount || 33842 active[ geometryId ] === false || 33843 visibility[ geometryId ] === value 33844 ) { 33845 33846 return this; 33847 33848 } 33849 33850 visibility[ geometryId ] = value; 33851 this._visibilityChanged = true; 33852 33853 return this; 33854 33855 } 33856 33857 getVisibleAt( geometryId ) { 33858 33859 const visibility = this._visibility; 33860 const active = this._active; 33861 const geometryCount = this._geometryCount; 33862 33863 // return early if the geometry is out of range or not active 33864 if ( geometryId >= geometryCount || active[ geometryId ] === false ) { 33865 33866 return false; 33867 33868 } 33869 33870 return visibility[ geometryId ]; 33871 33872 } 33873 33874 raycast( raycaster, intersects ) { 33875 33876 const visibility = this._visibility; 33877 const active = this._active; 33878 const drawRanges = this._drawRanges; 33879 const geometryCount = this._geometryCount; 33880 const matrixWorld = this.matrixWorld; 33881 const batchGeometry = this.geometry; 33882 33883 // iterate over each geometry 33884 _mesh.material = this.material; 33885 _mesh.geometry.index = batchGeometry.index; 33886 _mesh.geometry.attributes = batchGeometry.attributes; 33887 if ( _mesh.geometry.boundingBox === null ) { 33888 33889 _mesh.geometry.boundingBox = new Box3(); 33890 33891 } 33892 33893 if ( _mesh.geometry.boundingSphere === null ) { 33894 33895 _mesh.geometry.boundingSphere = new Sphere(); 33896 33897 } 33898 33899 for ( let i = 0; i < geometryCount; i ++ ) { 33900 33901 if ( ! visibility[ i ] || ! active[ i ] ) { 33902 33903 continue; 33904 33905 } 33906 33907 const drawRange = drawRanges[ i ]; 33908 _mesh.geometry.setDrawRange( drawRange.start, drawRange.count ); 33909 33910 // ge the intersects 33911 this.getMatrixAt( i, _mesh.matrixWorld ).premultiply( matrixWorld ); 33912 this.getBoundingBoxAt( i, _mesh.geometry.boundingBox ); 33913 this.getBoundingSphereAt( i, _mesh.geometry.boundingSphere ); 33914 _mesh.raycast( raycaster, _batchIntersects ); 33915 33916 // add batch id to the intersects 33917 for ( let j = 0, l = _batchIntersects.length; j < l; j ++ ) { 33918 33919 const intersect = _batchIntersects[ j ]; 33920 intersect.object = this; 33921 intersect.batchId = i; 33922 intersects.push( intersect ); 33923 33924 } 33925 33926 _batchIntersects.length = 0; 33927 33928 } 33929 33930 _mesh.material = null; 33931 _mesh.geometry.index = null; 33932 _mesh.geometry.attributes = {}; 33933 _mesh.geometry.setDrawRange( 0, Infinity ); 33934 33935 } 33936 33937 copy( source ) { 33938 33939 super.copy( source ); 33940 33941 this.geometry = source.geometry.clone(); 33942 this.perObjectFrustumCulled = source.perObjectFrustumCulled; 33943 this.sortObjects = source.sortObjects; 33944 this.boundingBox = source.boundingBox !== null ? source.boundingBox.clone() : null; 33945 this.boundingSphere = source.boundingSphere !== null ? source.boundingSphere.clone() : null; 33946 33947 this._drawRanges = source._drawRanges.map( range => ( { ...range } ) ); 33948 this._reservedRanges = source._reservedRanges.map( range => ( { ...range } ) ); 33949 33950 this._visibility = source._visibility.slice(); 33951 this._active = source._active.slice(); 33952 this._bounds = source._bounds.map( bound => ( {
33953 boxInitialized: bound.boxInitialized, 33954 box: bound.box.clone(), 33955 33956 sphereInitialized: bound.sphereInitialized, 33957 sphere: bound.sphere.clone() 33958 } ) ); 33959 33960 this._maxGeometryCount = source._maxGeometryCount; 33961 this._maxVertexCount = source._maxVertexCount; 33962 this._maxIndexCount = source._maxIndexCount; 33963 33964 this._geometryInitialized = source._geometryInitialized; 33965 this._geometryCount = source._geometryCount; 33966 this._multiDrawCounts = source._multiDrawCounts.slice(); 33967 this._multiDrawStarts = source._multiDrawStarts.slice(); 33968 33969 this._matricesTexture = source._matricesTexture.clone(); 33970 this._matricesTexture.image.data = this._matricesTexture.image.slice(); 33971 33972 if ( this._colorsTexture !== null ) { 33973 33974 this._colorsTexture = source._colorsTexture.clone(); 33975 this._colorsTexture.image.data = this._colorsTexture.image.slice(); 33976 33977 } 33978 33979 return this; 33980 33981 } 33982 33983 dispose() { 33984 33985 // Assuming the geometry is not shared with other meshes 33986 this.geometry.dispose(); 33987 33988 this._matricesTexture.dispose(); 33989 this._matricesTexture = null; 33990 33991 if ( this._colorsTexture !== null ) { 33992 33993 this._colorsTexture.dispose(); 33994 this._colorsTexture = null; 33995 33996 } 33997 33998 return this; 33999 34000 } 34001 34002 onBeforeRender( renderer, scene, camera, geometry, material/*, _group*/ ) { 34003 34004 // if visibility has not changed and frustum culling and object sorting is not required 34005 // then skip iterating over all items 34006 if ( ! this._visibilityChanged && ! this.perObjectFrustumCulled && ! this.sortObjects ) { 34007 34008 return; 34009 34010 } 34011 34012 // the indexed version of the multi draw function requires specifying the start 34013 // offset in bytes. 34014 const index = geometry.getIndex(); 34015 const bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT; 34016 34017 const active = this._active; 34018 const visibility = this._visibility; 34019 const multiDrawStarts = this._multiDrawStarts; 34020 const multiDrawCounts = this._multiDrawCounts; 34021 const drawRanges = this._drawRanges; 34022 const perObjectFrustumCulled = this.perObjectFrustumCulled; 34023 34024 // prepare the frustum in the local frame 34025 if ( perObjectFrustumCulled ) { 34026 34027 _projScreenMatrix$2 34028 .multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ) 34029 .multiply( this.matrixWorld ); 34030 _frustum.setFromProjectionMatrix( 34031 _projScreenMatrix$2, 34032 renderer.coordinateSystem 34033 ); 34034 34035 } 34036 34037 let count = 0; 34038 if ( this.sortObjects ) { 34039 34040 // get the camera position in the local frame 34041 _invMatrixWorld.copy( this.matrixWorld ).invert(); 34042 _vector$5.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4( _invMatrixWorld ); 34043 _forward.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ).transformDirection( _invMatrixWorld ); 34044 34045 for ( let i = 0, l = visibility.length; i < l; i ++ ) { 34046 34047 if ( visibility[ i ] && active[ i ] ) { 34048 34049 // get the bounds in world space 34050 this.getMatrixAt( i, _matrix$1 ); 34051 this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix$1 ); 34052 34053 // determine whether the batched geometry is within the frustum 34054 let culled = false; 34055 if ( perObjectFrustumCulled ) { 34056 34057 culled = ! _frustum.intersectsSphere( _sphere$2 ); 34058 34059 } 34060 34061 if ( ! culled ) { 34062 34063 // get the distance from camera used for sorting 34064 const z = _temp.subVectors( _sphere$2.center, _vector$5 ).dot( _forward ); 34065 _renderList.push( drawRanges[ i ], z ); 34066 34067 } 34068 34069 } 34070 34071 } 34072 34073 // Sort the draw ranges and prep for rendering 34074 const list = _renderList.list; 34075 const customSort = this.customSort; 34076 if ( customSort === null ) { 34077 34078 list.sort( material.transparent ? sortTransparent : sortOpaque ); 34079 34080 } else { 34081 34082 customSort.call( this, list, camera ); 34083 34084 } 34085 34086 for ( let i = 0, l = list.length; i < l; i ++ ) { 34087 34088 const item = list[ i ]; 34089 multiDrawStarts[ count ] = item.start * bytesPerElement; 34090 multiDrawCounts[ count ] = item.count; 34091 count ++; 34092 34093 } 34094 34095 _renderList.reset(); 34096 34097 } else { 34098 34099 for ( let i = 0, l = visibility.length; i < l; i ++ ) { 34100 34101 if ( visibility[ i ] && active[ i ] ) { 34102 34103 // determine whether the batched geometry is within the frustum 34104 let culled = false; 34105 if ( perObjectFrustumCulled ) { 34106 34107 // get the bounds in world space 34108 this.getMatrixAt( i, _matrix$1 ); 34109 this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix$1 ); 34110 culled = ! _frustum.intersectsSphere( _sphere$2 ); 34111 34112 } 34113 34114 if ( ! culled ) { 34115 34116 const range = drawRanges[ i ]; 34117 multiDrawStarts[ count ] = range.start * bytesPerElement; 34118 multiDrawCounts[ count ] = range.count; 34119 count ++; 34120 34121 } 34122 34123 } 34124 34125 } 34126 34127 } 34128 34129 this._multiDrawCount = count; 34130 this._visibilityChanged = false;
vendor: 19,160 bytes, lines 34131-35077
34131 34132 } 34133 34134 onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial/* , group */ ) { 34135 34136 this.onBeforeRender( renderer, null, shadowCamera, geometry, depthMaterial ); 34137 34138 } 34139 34140} 34141 34142class LineBasicMaterial extends Material { 34143 34144 constructor( parameters ) { 34145 34146 super(); 34147 34148 this.isLineBasicMaterial = true; 34149 34150 this.type = 'LineBasicMaterial'; 34151 34152 this.color = new Color( 0xffffff ); 34153 34154 this.map = null; 34155 34156 this.linewidth = 1; 34157 this.linecap = 'round'; 34158 this.linejoin = 'round'; 34159 34160 this.fog = true; 34161 34162 this.setValues( parameters ); 34163 34164 } 34165 34166 34167 copy( source ) { 34168 34169 super.copy( source ); 34170 34171 this.color.copy( source.color ); 34172 34173 this.map = source.map; 34174 34175 this.linewidth = source.linewidth; 34176 this.linecap = source.linecap; 34177 this.linejoin = source.linejoin; 34178 34179 this.fog = source.fog; 34180 34181 return this; 34182 34183 } 34184 34185} 34186 34187const _vStart = /*@__PURE__*/ new Vector3(); 34188const _vEnd = /*@__PURE__*/ new Vector3(); 34189 34190const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4(); 34191const _ray$1 = /*@__PURE__*/ new Ray(); 34192const _sphere$1 = /*@__PURE__*/ new Sphere(); 34193 34194const _intersectPointOnRay = /*@__PURE__*/ new Vector3(); 34195const _intersectPointOnSegment = /*@__PURE__*/ new Vector3(); 34196 34197class Line extends Object3D { 34198 34199 constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) { 34200 34201 super(); 34202 34203 this.isLine = true; 34204 34205 this.type = 'Line'; 34206 34207 this.geometry = geometry; 34208 this.material = material; 34209 34210 this.updateMorphTargets(); 34211 34212 } 34213 34214 copy( source, recursive ) { 34215 34216 super.copy( source, recursive ); 34217 34218 this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; 34219 this.geometry = source.geometry; 34220 34221 return this; 34222 34223 } 34224 34225 computeLineDistances() { 34226 34227 const geometry = this.geometry; 34228 34229 // we assume non-indexed geometry 34230 34231 if ( geometry.index === null ) { 34232 34233 const positionAttribute = geometry.attributes.position; 34234 const lineDistances = [ 0 ]; 34235 34236 for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) { 34237 34238 _vStart.fromBufferAttribute( positionAttribute, i - 1 ); 34239 _vEnd.fromBufferAttribute( positionAttribute, i ); 34240 34241 lineDistances[ i ] = lineDistances[ i - 1 ]; 34242 lineDistances[ i ] += _vStart.distanceTo( _vEnd ); 34243 34244 } 34245 34246 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); 34247 34248 } else { 34249 34250 console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); 34251 34252 } 34253 34254 return this; 34255 34256 } 34257 34258 raycast( raycaster, intersects ) { 34259 34260 const geometry = this.geometry; 34261 const matrixWorld = this.matrixWorld; 34262 const threshold = raycaster.params.Line.threshold; 34263 const drawRange = geometry.drawRange; 34264 34265 // Checking boundingSphere distance to ray 34266 34267 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 34268 34269 _sphere$1.copy( geometry.boundingSphere ); 34270 _sphere$1.applyMatrix4( matrixWorld ); 34271 _sphere$1.radius += threshold; 34272 34273 if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return; 34274 34275 // 34276 34277 _inverseMatrix$1.copy( matrixWorld ).invert(); 34278 _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 ); 34279 34280 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); 34281 const localThresholdSq = localThreshold * localThreshold; 34282 34283 const step = this.isLineSegments ? 2 : 1; 34284 34285 const index = geometry.index; 34286 const attributes = geometry.attributes; 34287 const positionAttribute = attributes.position; 34288 34289 if ( index !== null ) { 34290 34291 const start = Math.max( 0, drawRange.start ); 34292 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); 34293 34294 for ( let i = start, l = end - 1; i < l; i += step ) { 34295 34296 const a = index.getX( i ); 34297 const b = index.getX( i + 1 ); 34298 34299 const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b ); 34300 34301 if ( intersect ) { 34302 34303 intersects.push( intersect ); 34304 34305 } 34306 34307 } 34308 34309 if ( this.isLineLoop ) { 34310 34311 const a = index.getX( end - 1 ); 34312 const b = index.getX( start ); 34313 34314 const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b ); 34315 34316 if ( intersect ) { 34317 34318 intersects.push( intersect ); 34319 34320 } 34321 34322 } 34323 34324 } else { 34325 34326 const start = Math.max( 0, drawRange.start ); 34327 const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); 34328 34329 for ( let i = start, l = end - 1; i < l; i += step ) { 34330 34331 const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, i, i + 1 ); 34332 34333 if ( intersect ) { 34334 34335 intersects.push( intersect ); 34336 34337 } 34338 34339 } 34340 34341 if ( this.isLineLoop ) { 34342 34343 const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, end - 1, start ); 34344 34345 if ( intersect ) { 34346 34347 intersects.push( intersect ); 34348 34349 } 34350 34351 } 34352 34353 } 34354 34355 } 34356 34357 updateMorphTargets() { 34358 34359 const geometry = this.geometry; 34360 34361 const morphAttributes = geometry.morphAttributes; 34362 const keys = Object.keys( morphAttributes ); 34363 34364 if ( keys.length > 0 ) { 34365 34366 const morphAttribute = morphAttributes[ keys[ 0 ] ]; 34367 34368 if ( morphAttribute !== undefined ) { 34369 34370 this.morphTargetInfluences = []; 34371 this.morphTargetDictionary = {}; 34372 34373 for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 34374 34375 const name = morphAttribute[ m ].name || String( m ); 34376 34377 this.morphTargetInfluences.push( 0 ); 34378 this.morphTargetDictionary[ name ] = m; 34379 34380 } 34381 34382 } 34383 34384 } 34385 34386 } 34387 34388} 34389 34390function checkIntersection( object, raycaster, ray, thresholdSq, a, b ) { 34391 34392 const positionAttribute = object.geometry.attributes.position; 34393 34394 _vStart.fromBufferAttribute( positionAttribute, a ); 34395 _vEnd.fromBufferAttribute( positionAttribute, b ); 34396 34397 const distSq = ray.distanceSqToSegment( _vStart, _vEnd, _intersectPointOnRay, _intersectPointOnSegment ); 34398 34399 if ( distSq > thresholdSq ) return; 34400 34401 _intersectPointOnRay.applyMatrix4( object.matrixWorld ); // Move back to world space for distance calculation 34402 34403 const distance = raycaster.ray.origin.distanceTo( _intersectPointOnRay ); 34404 34405 if ( distance < raycaster.near || distance > raycaster.far ) return; 34406 34407 return { 34408 34409 distance: distance, 34410 // What do we want? intersection point on the ray or on the segment?? 34411 // point: raycaster.ray.at( distance ), 34412 point: _intersectPointOnSegment.clone().applyMatrix4( object.matrixWorld ), 34413 index: a, 34414 face: null, 34415 faceIndex: null, 34416 object: object 34417 34418 }; 34419 34420} 34421 34422const _start = /*@__PURE__*/ new Vector3(); 34423const _end = /*@__PURE__*/ new Vector3(); 34424 34425class LineSegments extends Line { 34426 34427 constructor( geometry, material ) { 34428 34429 super( geometry, material ); 34430 34431 this.isLineSegments = true; 34432 34433 this.type = 'LineSegments'; 34434 34435 } 34436 34437 computeLineDistances() { 34438 34439 const geometry = this.geometry; 34440 34441 // we assume non-indexed geometry 34442 34443 if ( geometry.index === null ) { 34444 34445 const positionAttribute = geometry.attributes.position; 34446 const lineDistances = []; 34447 34448 for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) { 34449 34450 _start.fromBufferAttribute( positionAttribute, i ); 34451 _end.fromBufferAttribute( positionAttribute, i + 1 ); 34452 34453 lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ]; 34454 lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end ); 34455 34456 } 34457 34458 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); 34459 34460 } else { 34461 34462 console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); 34463 34464 } 34465 34466 return this; 34467 34468 } 34469 34470} 34471 34472class LineLoop extends Line { 34473 34474 constructor( geometry, material ) { 34475 34476 super( geometry, material ); 34477 34478 this.isLineLoop = true; 34479 34480 this.type = 'LineLoop'; 34481 34482 } 34483 34484} 34485 34486class PointsMaterial extends Material { 34487 34488 constructor( parameters ) { 34489 34490 super(); 34491 34492 this.isPointsMaterial = true; 34493 34494 this.type = 'PointsMaterial'; 34495 34496 this.color = new Color( 0xffffff ); 34497 34498 this.map = null; 34499 34500 this.alphaMap = null; 34501 34502 this.size = 1; 34503 this.sizeAttenuation = true; 34504 34505 this.fog = true; 34506 34507 this.setValues( parameters ); 34508 34509 } 34510 34511 copy( source ) { 34512 34513 super.copy( source ); 34514 34515 this.color.copy( source.color ); 34516 34517 this.map = source.map; 34518 34519 this.alphaMap = source.alphaMap; 34520 34521 this.size = source.size; 34522 this.sizeAttenuation = source.sizeAttenuation; 34523 34524 this.fog = source.fog; 34525 34526 return this; 34527 34528 } 34529 34530} 34531 34532const _inverseMatrix = /*@__PURE__*/ new Matrix4(); 34533const _ray = /*@__PURE__*/ new Ray(); 34534const _sphere = /*@__PURE__*/ new Sphere(); 34535const _position$2 = /*@__PURE__*/ new Vector3(); 34536 34537class Points extends Object3D { 34538 34539 constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) { 34540 34541 super(); 34542 34543 this.isPoints = true; 34544 34545 this.type = 'Points'; 34546 34547 this.geometry = geometry; 34548 this.material = material; 34549 34550 this.updateMorphTargets(); 34551 34552 } 34553 34554 copy( source, recursive ) { 34555 34556 super.copy( source, recursive ); 34557 34558 this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; 34559 this.geometry = source.geometry; 34560 34561 return this; 34562 34563 } 34564 34565 raycast( raycaster, intersects ) { 34566 34567 const geometry = this.geometry; 34568 const matrixWorld = this.matrixWorld; 34569 const threshold = raycaster.params.Points.threshold; 34570 const drawRange = geometry.drawRange; 34571 34572 // Checking boundingSphere distance to ray 34573 34574 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 34575 34576 _sphere.copy( geometry.boundingSphere ); 34577 _sphere.applyMatrix4( matrixWorld ); 34578 _sphere.radius += threshold; 34579 34580 if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return; 34581 34582 // 34583 34584 _inverseMatrix.copy( matrixWorld ).invert(); 34585 _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix ); 34586 34587 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); 34588 const localThresholdSq = localThreshold * localThreshold; 34589 34590 const index = geometry.index; 34591 const attributes = geometry.attributes; 34592 const positionAttribute = attributes.position; 34593 34594 if ( index !== null ) { 34595 34596 const start = Math.max( 0, drawRange.start ); 34597 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); 34598 34599 for ( let i = start, il = end; i < il; i ++ ) { 34600 34601 const a = index.getX( i ); 34602 34603 _position$2.fromBufferAttribute( positionAttribute, a ); 34604 34605 testPoint( _position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this ); 34606 34607 } 34608 34609 } else { 34610 34611 const start = Math.max( 0, drawRange.start ); 34612 const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); 34613 34614 for ( let i = start, l = end; i < l; i ++ ) { 34615 34616 _position$2.fromBufferAttribute( positionAttribute, i ); 34617 34618 testPoint( _position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this ); 34619 34620 } 34621 34622 } 34623 34624 } 34625 34626 updateMorphTargets() { 34627 34628 const geometry = this.geometry; 34629 34630 const morphAttributes = geometry.morphAttributes; 34631 const keys = Object.keys( morphAttributes ); 34632 34633 if ( keys.length > 0 ) { 34634 34635 const morphAttribute = morphAttributes[ keys[ 0 ] ]; 34636 34637 if ( morphAttribute !== undefined ) { 34638 34639 this.morphTargetInfluences = []; 34640 this.morphTargetDictionary = {}; 34641 34642 for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 34643 34644 const name = morphAttribute[ m ].name || String( m ); 34645 34646 this.morphTargetInfluences.push( 0 ); 34647 this.morphTargetDictionary[ name ] = m; 34648 34649 } 34650 34651 } 34652 34653 } 34654 34655 } 34656 34657} 34658 34659function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) { 34660 34661 const rayPointDistanceSq = _ray.distanceSqToPoint( point ); 34662 34663 if ( rayPointDistanceSq < localThresholdSq ) { 34664 34665 const intersectPoint = new Vector3(); 34666 34667 _ray.closestPointToPoint( point, intersectPoint ); 34668 intersectPoint.applyMatrix4( matrixWorld ); 34669 34670 const distance = raycaster.ray.origin.distanceTo( intersectPoint ); 34671 34672 if ( distance < raycaster.near || distance > raycaster.far ) return; 34673 34674 intersects.push( { 34675 34676 distance: distance, 34677 distanceToRay: Math.sqrt( rayPointDistanceSq ), 34678 point: intersectPoint, 34679 index: index, 34680 face: null, 34681 object: object 34682 34683 } ); 34684 34685 } 34686 34687} 34688 34689class VideoTexture extends Texture { 34690 34691 constructor( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { 34692 34693 super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 34694 34695 this.isVideoTexture = true; 34696 34697 this.minFilter = minFilter !== undefined ? minFilter : LinearFilter; 34698 this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; 34699 34700 this.generateMipmaps = false; 34701 34702 const scope = this; 34703 34704 function updateVideo() { 34705 34706 scope.needsUpdate = true; 34707 video.requestVideoFrameCallback( updateVideo ); 34708 34709 } 34710 34711 if ( 'requestVideoFrameCallback' in video ) { 34712 34713 video.requestVideoFrameCallback( updateVideo ); 34714 34715 } 34716 34717 } 34718 34719 clone() { 34720 34721 return new this.constructor( this.image ).copy( this ); 34722 34723 } 34724 34725 update() { 34726 34727 const video = this.image; 34728 const hasVideoFrameCallback = 'requestVideoFrameCallback' in video; 34729 34730 if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) { 34731 34732 this.needsUpdate = true; 34733 34734 } 34735 34736 } 34737 34738} 34739 34740class FramebufferTexture extends Texture { 34741 34742 constructor( width, height ) { 34743 34744 super( { width, height } ); 34745 34746 this.isFramebufferTexture = true; 34747 34748 this.magFilter = NearestFilter; 34749 this.minFilter = NearestFilter; 34750 34751 this.generateMipmaps = false; 34752 34753 this.needsUpdate = true; 34754 34755 } 34756 34757} 34758 34759class CompressedTexture extends Texture { 34760 34761 constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) { 34762 34763 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); 34764 34765 this.isCompressedTexture = true; 34766 34767 this.image = { width: width, height: height }; 34768 this.mipmaps = mipmaps; 34769 34770 // no flipping for cube textures 34771 // (also flipping doesn't work for compressed textures ) 34772 34773 this.flipY = false; 34774 34775 // can't generate mipmaps for compressed textures 34776 // mips must be embedded in DDS files 34777 34778 this.generateMipmaps = false; 34779 34780 } 34781 34782} 34783 34784class CompressedArrayTexture extends CompressedTexture { 34785 34786 constructor( mipmaps, width, height, depth, format, type ) { 34787 34788 super( mipmaps, width, height, format, type ); 34789 34790 this.isCompressedArrayTexture = true; 34791 this.image.depth = depth; 34792 this.wrapR = ClampToEdgeWrapping; 34793 34794 this.layerUpdates = new Set(); 34795 34796 } 34797 34798 addLayerUpdates( layerIndex ) { 34799 34800 this.layerUpdates.add( layerIndex ); 34801 34802 } 34803 34804 clearLayerUpdates() { 34805 34806 this.layerUpdates.clear(); 34807 34808 } 34809 34810} 34811 34812class CompressedCubeTexture extends CompressedTexture { 34813 34814 constructor( images, format, type ) { 34815 34816 super( undefined, images[ 0 ].width, images[ 0 ].height, format, type, CubeReflectionMapping ); 34817 34818 this.isCompressedCubeTexture = true; 34819 this.isCubeTexture = true; 34820 34821 this.image = images; 34822 34823 } 34824 34825} 34826 34827class CanvasTexture extends Texture { 34828 34829 constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { 34830 34831 super( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 34832 34833 this.isCanvasTexture = true; 34834 34835 this.needsUpdate = true; 34836 34837 } 34838 34839} 34840 34841/** 34842 * Extensible curve object. 34843 * 34844 * Some common of curve methods: 34845 * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget ) 34846 * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget ) 34847 * .getPoints(), .getSpacedPoints() 34848 * .getLength() 34849 * .updateArcLengths() 34850 * 34851 * This following curves inherit from THREE.Curve: 34852 * 34853 * -- 2D curves -- 34854 * THREE.ArcCurve 34855 * THREE.CubicBezierCurve 34856 * THREE.EllipseCurve 34857 * THREE.LineCurve 34858 * THREE.QuadraticBezierCurve 34859 * THREE.SplineCurve 34860 * 34861 * -- 3D curves -- 34862 * THREE.CatmullRomCurve3 34863 * THREE.CubicBezierCurve3 34864 * THREE.LineCurve3 34865 * THREE.QuadraticBezierCurve3 34866 * 34867 * A series of curves can be represented as a THREE.CurvePath. 34868 * 34869 **/ 34870 34871class Curve { 34872 34873 constructor() { 34874 34875 this.type = 'Curve'; 34876 34877 this.arcLengthDivisions = 200; 34878 34879 } 34880 34881 // Virtual base class method to overwrite and implement in subclasses 34882 // - t [0 .. 1] 34883 34884 getPoint( /* t, optionalTarget */ ) { 34885 34886 console.warn( 'THREE.Curve: .getPoint() not implemented.' ); 34887 return null; 34888 34889 } 34890 34891 // Get point at relative position in curve according to arc length 34892 // - u [0 .. 1] 34893 34894 getPointAt( u, optionalTarget ) { 34895 34896 const t = this.getUtoTmapping( u ); 34897 return this.getPoint( t, optionalTarget ); 34898 34899 } 34900 34901 // Get sequence of points using getPoint( t ) 34902 34903 getPoints( divisions = 5 ) { 34904 34905 const points = []; 34906 34907 for ( let d = 0; d <= divisions; d ++ ) { 34908 34909 points.push( this.getPoint( d / divisions ) ); 34910 34911 } 34912 34913 return points; 34914 34915 } 34916 34917 // Get sequence of points using getPointAt( u ) 34918 34919 getSpacedPoints( divisions = 5 ) { 34920 34921 const points = []; 34922 34923 for ( let d = 0; d <= divisions; d ++ ) { 34924 34925 points.push( this.getPointAt( d / divisions ) ); 34926 34927 } 34928 34929 return points; 34930 34931 } 34932 34933 // Get total curve arc length 34934 34935 getLength() { 34936 34937 const lengths = this.getLengths(); 34938 return lengths[ lengths.length - 1 ]; 34939 34940 } 34941 34942 // Get list of cumulative segment lengths 34943 34944 getLengths( divisions = this.arcLengthDivisions ) { 34945 34946 if ( this.cacheArcLengths && 34947 ( this.cacheArcLengths.length === divisions + 1 ) && 34948 ! this.needsUpdate ) { 34949 34950 return this.cacheArcLengths; 34951 34952 } 34953 34954 this.needsUpdate = false; 34955 34956 const cache = []; 34957 let current, last = this.getPoint( 0 ); 34958 let sum = 0; 34959 34960 cache.push( 0 ); 34961 34962 for ( let p = 1; p <= divisions; p ++ ) { 34963 34964 current = this.getPoint( p / divisions ); 34965 sum += current.distanceTo( last ); 34966 cache.push( sum ); 34967 last = current; 34968 34969 } 34970 34971 this.cacheArcLengths = cache; 34972 34973 return cache; // { sums: cache, sum: sum }; Sum is in the last element. 34974 34975 } 34976 34977 updateArcLengths() { 34978 34979 this.needsUpdate = true; 34980 this.getLengths(); 34981 34982 } 34983 34984 // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant 34985 34986 getUtoTmapping( u, distance ) { 34987 34988 const arcLengths = this.getLengths(); 34989 34990 let i = 0; 34991 const il = arcLengths.length; 34992 34993 let targetArcLength; // The targeted u distance value to get 34994 34995 if ( distance ) { 34996 34997 targetArcLength = distance; 34998 34999 } else { 35000 35001 targetArcLength = u * arcLengths[ il - 1 ]; 35002 35003 } 35004 35005 // binary search for the index with largest value smaller than target u distance 35006 35007 let low = 0, high = il - 1, comparison; 35008 35009 while ( low <= high ) { 35010 35011 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 35012 35013 comparison = arcLengths[ i ] - targetArcLength; 35014 35015 if ( comparison < 0 ) { 35016 35017 low = i + 1; 35018 35019 } else if ( comparison > 0 ) { 35020 35021 high = i - 1; 35022 35023 } else { 35024 35025 high = i; 35026 break; 35027 35028 // DONE 35029 35030 } 35031 35032 } 35033 35034 i = high; 35035 35036 if ( arcLengths[ i ] === targetArcLength ) { 35037 35038 return i / ( il - 1 ); 35039 35040 } 35041 35042 // we could get finer grain at lengths, or use simple interpolation between two points 35043 35044 const lengthBefore = arcLengths[ i ]; 35045 const lengthAfter = arcLengths[ i + 1 ]; 35046 35047 const segmentLength = lengthAfter - lengthBefore; 35048 35049 // determine where we are between the 'before' and 'after' points 35050 35051 const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; 35052 35053 // add that fractional amount to t 35054 35055 const t = ( i + segmentFraction ) / ( il - 1 ); 35056 35057 return t; 35058 35059 } 35060 35061 // Returns a unit vector tangent at t 35062 // In case any sub curve does not implement its tangent derivation, 35063 // 2 points a small delta apart will be used to find its gradient 35064 // which seems to give a reasonable approximation 35065 35066 getTangent( t, optionalTarget ) { 35067 35068 const delta = 0.0001; 35069 let t1 = t - delta; 35070 let t2 = t + delta; 35071 35072 // Capping in case of danger 35073 35074 if ( t1 < 0 ) t1 = 0; 35075 if ( t2 > 1 ) t2 = 1; 35076 35077 const pt1 = this.getPoint( t1 );
vendor: 5,109 bytes, lines 35078-35346
35078 const pt2 = this.getPoint( t2 ); 35079 35080 const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() ); 35081 35082 tangent.copy( pt2 ).sub( pt1 ).normalize(); 35083 35084 return tangent; 35085 35086 } 35087 35088 getTangentAt( u, optionalTarget ) { 35089 35090 const t = this.getUtoTmapping( u ); 35091 return this.getTangent( t, optionalTarget ); 35092 35093 } 35094 35095 computeFrenetFrames( segments, closed ) { 35096 35097 // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf 35098 35099 const normal = new Vector3(); 35100 35101 const tangents = []; 35102 const normals = []; 35103 const binormals = []; 35104 35105 const vec = new Vector3(); 35106 const mat = new Matrix4(); 35107 35108 // compute the tangent vectors for each segment on the curve 35109 35110 for ( let i = 0; i <= segments; i ++ ) { 35111 35112 const u = i / segments; 35113 35114 tangents[ i ] = this.getTangentAt( u, new Vector3() ); 35115 35116 } 35117 35118 // select an initial normal vector perpendicular to the first tangent vector, 35119 // and in the direction of the minimum tangent xyz component 35120 35121 normals[ 0 ] = new Vector3(); 35122 binormals[ 0 ] = new Vector3(); 35123 let min = Number.MAX_VALUE; 35124 const tx = Math.abs( tangents[ 0 ].x ); 35125 const ty = Math.abs( tangents[ 0 ].y ); 35126 const tz = Math.abs( tangents[ 0 ].z ); 35127 35128 if ( tx <= min ) { 35129 35130 min = tx; 35131 normal.set( 1, 0, 0 ); 35132 35133 } 35134 35135 if ( ty <= min ) { 35136 35137 min = ty; 35138 normal.set( 0, 1, 0 ); 35139 35140 } 35141 35142 if ( tz <= min ) { 35143 35144 normal.set( 0, 0, 1 ); 35145 35146 } 35147 35148 vec.crossVectors( tangents[ 0 ], normal ).normalize(); 35149 35150 normals[ 0 ].crossVectors( tangents[ 0 ], vec ); 35151 binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ); 35152 35153 35154 // compute the slowly-varying normal and binormal vectors for each segment on the curve 35155 35156 for ( let i = 1; i <= segments; i ++ ) { 35157 35158 normals[ i ] = normals[ i - 1 ].clone(); 35159 35160 binormals[ i ] = binormals[ i - 1 ].clone(); 35161 35162 vec.crossVectors( tangents[ i - 1 ], tangents[ i ] ); 35163 35164 if ( vec.length() > Number.EPSILON ) { 35165 35166 vec.normalize(); 35167 35168 const theta = Math.acos( clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors 35169 35170 normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) ); 35171 35172 } 35173 35174 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); 35175 35176 } 35177 35178 // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same 35179 35180 if ( closed === true ) { 35181 35182 let theta = Math.acos( clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) ); 35183 theta /= segments; 35184 35185 if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) { 35186 35187 theta = - theta; 35188 35189 } 35190 35191 for ( let i = 1; i <= segments; i ++ ) { 35192 35193 // twist a little... 35194 normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) ); 35195 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); 35196 35197 } 35198 35199 } 35200 35201 return { 35202 tangents: tangents, 35203 normals: normals, 35204 binormals: binormals 35205 }; 35206 35207 } 35208 35209 clone() { 35210 35211 return new this.constructor().copy( this ); 35212 35213 } 35214 35215 copy( source ) { 35216 35217 this.arcLengthDivisions = source.arcLengthDivisions; 35218 35219 return this; 35220 35221 } 35222 35223 toJSON() { 35224 35225 const data = { 35226 metadata: { 35227 version: 4.6, 35228 type: 'Curve', 35229 generator: 'Curve.toJSON' 35230 } 35231 }; 35232 35233 data.arcLengthDivisions = this.arcLengthDivisions; 35234 data.type = this.type; 35235 35236 return data; 35237 35238 } 35239 35240 fromJSON( json ) { 35241 35242 this.arcLengthDivisions = json.arcLengthDivisions; 35243 35244 return this; 35245 35246 } 35247 35248} 35249 35250class EllipseCurve extends Curve { 35251 35252 constructor( aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0 ) { 35253 35254 super(); 35255 35256 this.isEllipseCurve = true; 35257 35258 this.type = 'EllipseCurve'; 35259 35260 this.aX = aX; 35261 this.aY = aY; 35262 35263 this.xRadius = xRadius; 35264 this.yRadius = yRadius; 35265 35266 this.aStartAngle = aStartAngle; 35267 this.aEndAngle = aEndAngle; 35268 35269 this.aClockwise = aClockwise; 35270 35271 this.aRotation = aRotation; 35272 35273 } 35274 35275 getPoint( t, optionalTarget = new Vector2() ) { 35276 35277 const point = optionalTarget; 35278 35279 const twoPi = Math.PI * 2; 35280 let deltaAngle = this.aEndAngle - this.aStartAngle; 35281 const samePoints = Math.abs( deltaAngle ) < Number.EPSILON; 35282 35283 // ensures that deltaAngle is 0 .. 2 PI 35284 while ( deltaAngle < 0 ) deltaAngle += twoPi; 35285 while ( deltaAngle > twoPi ) deltaAngle -= twoPi; 35286 35287 if ( deltaAngle < Number.EPSILON ) { 35288 35289 if ( samePoints ) { 35290 35291 deltaAngle = 0; 35292 35293 } else { 35294 35295 deltaAngle = twoPi; 35296 35297 } 35298 35299 } 35300 35301 if ( this.aClockwise === true && ! samePoints ) { 35302 35303 if ( deltaAngle === twoPi ) { 35304 35305 deltaAngle = - twoPi; 35306 35307 } else { 35308 35309 deltaAngle = deltaAngle - twoPi; 35310 35311 } 35312 35313 } 35314 35315 const angle = this.aStartAngle + t * deltaAngle; 35316 let x = this.aX + this.xRadius * Math.cos( angle ); 35317 let y = this.aY + this.yRadius * Math.sin( angle ); 35318 35319 if ( this.aRotation !== 0 ) { 35320 35321 const cos = Math.cos( this.aRotation ); 35322 const sin = Math.sin( this.aRotation ); 35323 35324 const tx = x - this.aX; 35325 const ty = y - this.aY; 35326 35327 // Rotate the point about the center of the ellipse. 35328 x = tx * cos - ty * sin + this.aX; 35329 y = tx * sin + ty * cos + this.aY; 35330 35331 } 35332 35333 return point.set( x, y ); 35334 35335 } 35336 35337 copy( source ) { 35338 35339 super.copy( source ); 35340 35341 this.aX = source.aX; 35342 this.aY = source.aY; 35343 35344 this.xRadius = source.xRadius; 35345 this.yRadius = source.yRadius; 35346
vendor: 29,619 bytes, lines 35347-37029
35347 this.aStartAngle = source.aStartAngle; 35348 this.aEndAngle = source.aEndAngle; 35349 35350 this.aClockwise = source.aClockwise; 35351 35352 this.aRotation = source.aRotation; 35353 35354 return this; 35355 35356 } 35357 35358 toJSON() { 35359 35360 const data = super.toJSON(); 35361 35362 data.aX = this.aX; 35363 data.aY = this.aY; 35364 35365 data.xRadius = this.xRadius; 35366 data.yRadius = this.yRadius; 35367 35368 data.aStartAngle = this.aStartAngle; 35369 data.aEndAngle = this.aEndAngle; 35370 35371 data.aClockwise = this.aClockwise; 35372 35373 data.aRotation = this.aRotation; 35374 35375 return data; 35376 35377 } 35378 35379 fromJSON( json ) { 35380 35381 super.fromJSON( json ); 35382 35383 this.aX = json.aX; 35384 this.aY = json.aY; 35385 35386 this.xRadius = json.xRadius; 35387 this.yRadius = json.yRadius; 35388 35389 this.aStartAngle = json.aStartAngle; 35390 this.aEndAngle = json.aEndAngle; 35391 35392 this.aClockwise = json.aClockwise; 35393 35394 this.aRotation = json.aRotation; 35395 35396 return this; 35397 35398 } 35399 35400} 35401 35402class ArcCurve extends EllipseCurve { 35403 35404 constructor( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 35405 35406 super( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); 35407 35408 this.isArcCurve = true; 35409 35410 this.type = 'ArcCurve'; 35411 35412 } 35413 35414} 35415 35416/** 35417 * Centripetal CatmullRom Curve - which is useful for avoiding 35418 * cusps and self-intersections in non-uniform catmull rom curves. 35419 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf 35420 * 35421 * curve.type accepts centripetal(default), chordal and catmullrom 35422 * curve.tension is used for catmullrom which defaults to 0.5 35423 */ 35424 35425 35426/* 35427Based on an optimized c++ solution in 35428 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/ 35429 - http://ideone.com/NoEbVM 35430 35431This CubicPoly class could be used for reusing some variables and calculations, 35432but for three.js curve use, it could be possible inlined and flatten into a single function call 35433which can be placed in CurveUtils. 35434*/ 35435 35436function CubicPoly() { 35437 35438 let c0 = 0, c1 = 0, c2 = 0, c3 = 0; 35439 35440 /* 35441 * Compute coefficients for a cubic polynomial 35442 * p(s) = c0 + c1*s + c2*s^2 + c3*s^3 35443 * such that 35444 * p(0) = x0, p(1) = x1 35445 * and 35446 * p'(0) = t0, p'(1) = t1. 35447 */ 35448 function init( x0, x1, t0, t1 ) { 35449 35450 c0 = x0; 35451 c1 = t0; 35452 c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1; 35453 c3 = 2 * x0 - 2 * x1 + t0 + t1; 35454 35455 } 35456 35457 return { 35458 35459 initCatmullRom: function ( x0, x1, x2, x3, tension ) { 35460 35461 init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) ); 35462 35463 }, 35464 35465 initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) { 35466 35467 // compute tangents when parameterized in [t1,t2] 35468 let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1; 35469 let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2; 35470 35471 // rescale tangents for parametrization in [0,1] 35472 t1 *= dt1; 35473 t2 *= dt1; 35474 35475 init( x1, x2, t1, t2 ); 35476 35477 }, 35478 35479 calc: function ( t ) { 35480 35481 const t2 = t * t; 35482 const t3 = t2 * t; 35483 return c0 + c1 * t + c2 * t2 + c3 * t3; 35484 35485 } 35486 35487 }; 35488 35489} 35490 35491// 35492 35493const tmp = /*@__PURE__*/ new Vector3(); 35494const px = /*@__PURE__*/ new CubicPoly(); 35495const py = /*@__PURE__*/ new CubicPoly(); 35496const pz = /*@__PURE__*/ new CubicPoly(); 35497 35498class CatmullRomCurve3 extends Curve { 35499 35500 constructor( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) { 35501 35502 super(); 35503 35504 this.isCatmullRomCurve3 = true; 35505 35506 this.type = 'CatmullRomCurve3'; 35507 35508 this.points = points; 35509 this.closed = closed; 35510 this.curveType = curveType; 35511 this.tension = tension; 35512 35513 } 35514 35515 getPoint( t, optionalTarget = new Vector3() ) { 35516 35517 const point = optionalTarget; 35518 35519 const points = this.points; 35520 const l = points.length; 35521 35522 const p = ( l - ( this.closed ? 0 : 1 ) ) * t; 35523 let intPoint = Math.floor( p ); 35524 let weight = p - intPoint; 35525 35526 if ( this.closed ) { 35527 35528 intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l; 35529 35530 } else if ( weight === 0 && intPoint === l - 1 ) { 35531 35532 intPoint = l - 2; 35533 weight = 1; 35534 35535 } 35536 35537 let p0, p3; // 4 points (p1 & p2 defined below) 35538 35539 if ( this.closed || intPoint > 0 ) { 35540 35541 p0 = points[ ( intPoint - 1 ) % l ]; 35542 35543 } else { 35544 35545 // extrapolate first point 35546 tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] ); 35547 p0 = tmp; 35548 35549 } 35550 35551 const p1 = points[ intPoint % l ]; 35552 const p2 = points[ ( intPoint + 1 ) % l ]; 35553 35554 if ( this.closed || intPoint + 2 < l ) { 35555 35556 p3 = points[ ( intPoint + 2 ) % l ]; 35557 35558 } else { 35559 35560 // extrapolate last point 35561 tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] ); 35562 p3 = tmp; 35563 35564 } 35565 35566 if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) { 35567 35568 // init Centripetal / Chordal Catmull-Rom 35569 const pow = this.curveType === 'chordal' ? 0.5 : 0.25; 35570 let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow ); 35571 let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow ); 35572 let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow ); 35573 35574 // safety check for repeated points 35575 if ( dt1 < 1e-4 ) dt1 = 1.0; 35576 if ( dt0 < 1e-4 ) dt0 = dt1; 35577 if ( dt2 < 1e-4 ) dt2 = dt1; 35578 35579 px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 ); 35580 py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 ); 35581 pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 ); 35582 35583 } else if ( this.curveType === 'catmullrom' ) { 35584 35585 px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension ); 35586 py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension ); 35587 pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension ); 35588 35589 } 35590 35591 point.set( 35592 px.calc( weight ), 35593 py.calc( weight ), 35594 pz.calc( weight ) 35595 ); 35596 35597 return point; 35598 35599 } 35600 35601 copy( source ) { 35602 35603 super.copy( source ); 35604 35605 this.points = []; 35606 35607 for ( let i = 0, l = source.points.length; i < l; i ++ ) { 35608 35609 const point = source.points[ i ]; 35610 35611 this.points.push( point.clone() ); 35612 35613 } 35614 35615 this.closed = source.closed; 35616 this.curveType = source.curveType; 35617 this.tension = source.tension; 35618 35619 return this; 35620 35621 } 35622 35623 toJSON() { 35624 35625 const data = super.toJSON(); 35626 35627 data.points = []; 35628 35629 for ( let i = 0, l = this.points.length; i < l; i ++ ) { 35630 35631 const point = this.points[ i ]; 35632 data.points.push( point.toArray() ); 35633 35634 } 35635 35636 data.closed = this.closed; 35637 data.curveType = this.curveType; 35638 data.tension = this.tension; 35639 35640 return data; 35641 35642 } 35643 35644 fromJSON( json ) { 35645 35646 super.fromJSON( json ); 35647 35648 this.points = []; 35649 35650 for ( let i = 0, l = json.points.length; i < l; i ++ ) { 35651 35652 const point = json.points[ i ]; 35653 this.points.push( new Vector3().fromArray( point ) ); 35654 35655 } 35656 35657 this.closed = json.closed; 35658 this.curveType = json.curveType; 35659 this.tension = json.tension; 35660 35661 return this; 35662 35663 } 35664 35665} 35666 35667/** 35668 * Bezier Curves formulas obtained from 35669 * https://en.wikipedia.org/wiki/B%C3%A9zier_curve 35670 */ 35671 35672function CatmullRom( t, p0, p1, p2, p3 ) { 35673 35674 const v0 = ( p2 - p0 ) * 0.5; 35675 const v1 = ( p3 - p1 ) * 0.5; 35676 const t2 = t * t; 35677 const t3 = t * t2; 35678 return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1; 35679 35680} 35681 35682// 35683 35684function QuadraticBezierP0( t, p ) { 35685 35686 const k = 1 - t; 35687 return k * k * p; 35688 35689} 35690 35691function QuadraticBezierP1( t, p ) { 35692 35693 return 2 * ( 1 - t ) * t * p; 35694 35695} 35696 35697function QuadraticBezierP2( t, p ) { 35698 35699 return t * t * p; 35700 35701} 35702 35703function QuadraticBezier( t, p0, p1, p2 ) { 35704 35705 return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) + 35706 QuadraticBezierP2( t, p2 ); 35707 35708} 35709 35710// 35711 35712function CubicBezierP0( t, p ) { 35713 35714 const k = 1 - t; 35715 return k * k * k * p; 35716 35717} 35718 35719function CubicBezierP1( t, p ) { 35720 35721 const k = 1 - t; 35722 return 3 * k * k * t * p; 35723 35724} 35725 35726function CubicBezierP2( t, p ) { 35727 35728 return 3 * ( 1 - t ) * t * t * p; 35729 35730} 35731 35732function CubicBezierP3( t, p ) { 35733 35734 return t * t * t * p; 35735 35736} 35737 35738function CubicBezier( t, p0, p1, p2, p3 ) { 35739 35740 return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) + 35741 CubicBezierP3( t, p3 ); 35742 35743} 35744 35745class CubicBezierCurve extends Curve { 35746 35747 constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) { 35748 35749 super(); 35750 35751 this.isCubicBezierCurve = true; 35752 35753 this.type = 'CubicBezierCurve'; 35754 35755 this.v0 = v0; 35756 this.v1 = v1; 35757 this.v2 = v2; 35758 this.v3 = v3; 35759 35760 } 35761 35762 getPoint( t, optionalTarget = new Vector2() ) { 35763 35764 const point = optionalTarget; 35765 35766 const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; 35767 35768 point.set( 35769 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), 35770 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ) 35771 ); 35772 35773 return point; 35774 35775 } 35776 35777 copy( source ) { 35778 35779 super.copy( source ); 35780 35781 this.v0.copy( source.v0 ); 35782 this.v1.copy( source.v1 ); 35783 this.v2.copy( source.v2 ); 35784 this.v3.copy( source.v3 ); 35785 35786 return this; 35787 35788 } 35789 35790 toJSON() { 35791 35792 const data = super.toJSON(); 35793 35794 data.v0 = this.v0.toArray(); 35795 data.v1 = this.v1.toArray(); 35796 data.v2 = this.v2.toArray(); 35797 data.v3 = this.v3.toArray(); 35798 35799 return data; 35800 35801 } 35802 35803 fromJSON( json ) { 35804 35805 super.fromJSON( json ); 35806 35807 this.v0.fromArray( json.v0 ); 35808 this.v1.fromArray( json.v1 ); 35809 this.v2.fromArray( json.v2 ); 35810 this.v3.fromArray( json.v3 ); 35811 35812 return this; 35813 35814 } 35815 35816} 35817 35818class CubicBezierCurve3 extends Curve { 35819 35820 constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) { 35821 35822 super(); 35823 35824 this.isCubicBezierCurve3 = true; 35825 35826 this.type = 'CubicBezierCurve3'; 35827 35828 this.v0 = v0; 35829 this.v1 = v1; 35830 this.v2 = v2; 35831 this.v3 = v3; 35832 35833 } 35834 35835 getPoint( t, optionalTarget = new Vector3() ) { 35836 35837 const point = optionalTarget; 35838 35839 const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; 35840 35841 point.set( 35842 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), 35843 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ), 35844 CubicBezier( t, v0.z, v1.z, v2.z, v3.z ) 35845 ); 35846 35847 return point; 35848 35849 } 35850 35851 copy( source ) { 35852 35853 super.copy( source ); 35854 35855 this.v0.copy( source.v0 ); 35856 this.v1.copy( source.v1 ); 35857 this.v2.copy( source.v2 ); 35858 this.v3.copy( source.v3 ); 35859 35860 return this; 35861 35862 } 35863 35864 toJSON() { 35865 35866 const data = super.toJSON(); 35867 35868 data.v0 = this.v0.toArray(); 35869 data.v1 = this.v1.toArray(); 35870 data.v2 = this.v2.toArray(); 35871 data.v3 = this.v3.toArray(); 35872 35873 return data; 35874 35875 } 35876 35877 fromJSON( json ) { 35878 35879 super.fromJSON( json ); 35880 35881 this.v0.fromArray( json.v0 ); 35882 this.v1.fromArray( json.v1 ); 35883 this.v2.fromArray( json.v2 ); 35884 this.v3.fromArray( json.v3 ); 35885 35886 return this; 35887 35888 } 35889 35890} 35891 35892class LineCurve extends Curve { 35893 35894 constructor( v1 = new Vector2(), v2 = new Vector2() ) { 35895 35896 super(); 35897 35898 this.isLineCurve = true; 35899 35900 this.type = 'LineCurve'; 35901 35902 this.v1 = v1; 35903 this.v2 = v2; 35904 35905 } 35906 35907 getPoint( t, optionalTarget = new Vector2() ) { 35908 35909 const point = optionalTarget; 35910 35911 if ( t === 1 ) { 35912 35913 point.copy( this.v2 ); 35914 35915 } else { 35916 35917 point.copy( this.v2 ).sub( this.v1 ); 35918 point.multiplyScalar( t ).add( this.v1 ); 35919 35920 } 35921 35922 return point; 35923 35924 } 35925 35926 // Line curve is linear, so we can overwrite default getPointAt 35927 getPointAt( u, optionalTarget ) { 35928 35929 return this.getPoint( u, optionalTarget ); 35930 35931 } 35932 35933 getTangent( t, optionalTarget = new Vector2() ) { 35934 35935 return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); 35936 35937 } 35938 35939 getTangentAt( u, optionalTarget ) { 35940 35941 return this.getTangent( u, optionalTarget ); 35942 35943 } 35944 35945 copy( source ) { 35946 35947 super.copy( source ); 35948 35949 this.v1.copy( source.v1 ); 35950 this.v2.copy( source.v2 ); 35951 35952 return this; 35953 35954 } 35955 35956 toJSON() { 35957 35958 const data = super.toJSON(); 35959 35960 data.v1 = this.v1.toArray(); 35961 data.v2 = this.v2.toArray(); 35962 35963 return data; 35964 35965 } 35966 35967 fromJSON( json ) { 35968 35969 super.fromJSON( json ); 35970 35971 this.v1.fromArray( json.v1 ); 35972 this.v2.fromArray( json.v2 ); 35973 35974 return this; 35975 35976 } 35977 35978} 35979 35980class LineCurve3 extends Curve { 35981 35982 constructor( v1 = new Vector3(), v2 = new Vector3() ) { 35983 35984 super(); 35985 35986 this.isLineCurve3 = true; 35987 35988 this.type = 'LineCurve3'; 35989 35990 this.v1 = v1; 35991 this.v2 = v2; 35992 35993 } 35994 35995 getPoint( t, optionalTarget = new Vector3() ) { 35996 35997 const point = optionalTarget; 35998 35999 if ( t === 1 ) { 36000 36001 point.copy( this.v2 ); 36002 36003 } else { 36004 36005 point.copy( this.v2 ).sub( this.v1 ); 36006 point.multiplyScalar( t ).add( this.v1 ); 36007 36008 } 36009 36010 return point; 36011 36012 } 36013 36014 // Line curve is linear, so we can overwrite default getPointAt 36015 getPointAt( u, optionalTarget ) { 36016 36017 return this.getPoint( u, optionalTarget ); 36018 36019 } 36020 36021 getTangent( t, optionalTarget = new Vector3() ) { 36022 36023 return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); 36024 36025 } 36026 36027 getTangentAt( u, optionalTarget ) { 36028 36029 return this.getTangent( u, optionalTarget ); 36030 36031 } 36032 36033 copy( source ) { 36034 36035 super.copy( source ); 36036 36037 this.v1.copy( source.v1 ); 36038 this.v2.copy( source.v2 ); 36039 36040 return this; 36041 36042 } 36043 36044 toJSON() { 36045 36046 const data = super.toJSON(); 36047 36048 data.v1 = this.v1.toArray(); 36049 data.v2 = this.v2.toArray(); 36050 36051 return data; 36052 36053 } 36054 36055 fromJSON( json ) { 36056 36057 super.fromJSON( json ); 36058 36059 this.v1.fromArray( json.v1 ); 36060 this.v2.fromArray( json.v2 ); 36061 36062 return this; 36063 36064 } 36065 36066} 36067 36068class QuadraticBezierCurve extends Curve { 36069 36070 constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) { 36071 36072 super(); 36073 36074 this.isQuadraticBezierCurve = true; 36075 36076 this.type = 'QuadraticBezierCurve'; 36077 36078 this.v0 = v0; 36079 this.v1 = v1; 36080 this.v2 = v2; 36081 36082 } 36083 36084 getPoint( t, optionalTarget = new Vector2() ) { 36085 36086 const point = optionalTarget; 36087 36088 const v0 = this.v0, v1 = this.v1, v2 = this.v2; 36089 36090 point.set( 36091 QuadraticBezier( t, v0.x, v1.x, v2.x ), 36092 QuadraticBezier( t, v0.y, v1.y, v2.y ) 36093 ); 36094 36095 return point; 36096 36097 } 36098 36099 copy( source ) { 36100 36101 super.copy( source ); 36102 36103 this.v0.copy( source.v0 ); 36104 this.v1.copy( source.v1 ); 36105 this.v2.copy( source.v2 ); 36106 36107 return this; 36108 36109 } 36110 36111 toJSON() { 36112 36113 const data = super.toJSON(); 36114 36115 data.v0 = this.v0.toArray(); 36116 data.v1 = this.v1.toArray(); 36117 data.v2 = this.v2.toArray(); 36118 36119 return data; 36120 36121 } 36122 36123 fromJSON( json ) { 36124 36125 super.fromJSON( json ); 36126 36127 this.v0.fromArray( json.v0 ); 36128 this.v1.fromArray( json.v1 ); 36129 this.v2.fromArray( json.v2 ); 36130 36131 return this; 36132 36133 } 36134 36135} 36136 36137class QuadraticBezierCurve3 extends Curve { 36138 36139 constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) { 36140 36141 super(); 36142 36143 this.isQuadraticBezierCurve3 = true; 36144 36145 this.type = 'QuadraticBezierCurve3'; 36146 36147 this.v0 = v0; 36148 this.v1 = v1; 36149 this.v2 = v2; 36150 36151 } 36152 36153 getPoint( t, optionalTarget = new Vector3() ) { 36154 36155 const point = optionalTarget; 36156 36157 const v0 = this.v0, v1 = this.v1, v2 = this.v2; 36158 36159 point.set( 36160 QuadraticBezier( t, v0.x, v1.x, v2.x ), 36161 QuadraticBezier( t, v0.y, v1.y, v2.y ), 36162 QuadraticBezier( t, v0.z, v1.z, v2.z ) 36163 ); 36164 36165 return point; 36166 36167 } 36168 36169 copy( source ) { 36170 36171 super.copy( source ); 36172 36173 this.v0.copy( source.v0 ); 36174 this.v1.copy( source.v1 ); 36175 this.v2.copy( source.v2 ); 36176 36177 return this; 36178 36179 } 36180 36181 toJSON() { 36182 36183 const data = super.toJSON(); 36184 36185 data.v0 = this.v0.toArray(); 36186 data.v1 = this.v1.toArray(); 36187 data.v2 = this.v2.toArray(); 36188 36189 return data; 36190 36191 } 36192 36193 fromJSON( json ) { 36194 36195 super.fromJSON( json ); 36196 36197 this.v0.fromArray( json.v0 ); 36198 this.v1.fromArray( json.v1 ); 36199 this.v2.fromArray( json.v2 ); 36200 36201 return this; 36202 36203 } 36204 36205} 36206 36207class SplineCurve extends Curve { 36208 36209 constructor( points = [] ) { 36210 36211 super(); 36212 36213 this.isSplineCurve = true; 36214 36215 this.type = 'SplineCurve'; 36216 36217 this.points = points; 36218 36219 } 36220 36221 getPoint( t, optionalTarget = new Vector2() ) { 36222 36223 const point = optionalTarget; 36224 36225 const points = this.points; 36226 const p = ( points.length - 1 ) * t; 36227 36228 const intPoint = Math.floor( p ); 36229 const weight = p - intPoint; 36230 36231 const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ]; 36232 const p1 = points[ intPoint ]; 36233 const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ]; 36234 const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ]; 36235 36236 point.set( 36237 CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ), 36238 CatmullRom( weight, p0.y, p1.y, p2.y, p3.y ) 36239 ); 36240 36241 return point; 36242 36243 } 36244 36245 copy( source ) { 36246 36247 super.copy( source ); 36248 36249 this.points = []; 36250 36251 for ( let i = 0, l = source.points.length; i < l; i ++ ) { 36252 36253 const point = source.points[ i ]; 36254 36255 this.points.push( point.clone() ); 36256 36257 } 36258 36259 return this; 36260 36261 } 36262 36263 toJSON() { 36264 36265 const data = super.toJSON(); 36266 36267 data.points = []; 36268 36269 for ( let i = 0, l = this.points.length; i < l; i ++ ) { 36270 36271 const point = this.points[ i ]; 36272 data.points.push( point.toArray() ); 36273 36274 } 36275 36276 return data; 36277 36278 } 36279 36280 fromJSON( json ) { 36281 36282 super.fromJSON( json ); 36283 36284 this.points = []; 36285 36286 for ( let i = 0, l = json.points.length; i < l; i ++ ) { 36287 36288 const point = json.points[ i ]; 36289 this.points.push( new Vector2().fromArray( point ) ); 36290 36291 } 36292 36293 return this; 36294 36295 } 36296 36297} 36298 36299var Curves = /*#__PURE__*/Object.freeze({ 36300 __proto__: null, 36301 ArcCurve: ArcCurve, 36302 CatmullRomCurve3: CatmullRomCurve3, 36303 CubicBezierCurve: CubicBezierCurve, 36304 CubicBezierCurve3: CubicBezierCurve3, 36305 EllipseCurve: EllipseCurve, 36306 LineCurve: LineCurve, 36307 LineCurve3: LineCurve3, 36308 QuadraticBezierCurve: QuadraticBezierCurve, 36309 QuadraticBezierCurve3: QuadraticBezierCurve3, 36310 SplineCurve: SplineCurve 36311}); 36312 36313/************************************************************** 36314 * Curved Path - a curve path is simply a array of connected 36315 * curves, but retains the api of a curve 36316 **************************************************************/ 36317 36318class CurvePath extends Curve { 36319 36320 constructor() { 36321 36322 super(); 36323 36324 this.type = 'CurvePath'; 36325 36326 this.curves = []; 36327 this.autoClose = false; // Automatically closes the path 36328 36329 } 36330 36331 add( curve ) { 36332 36333 this.curves.push( curve ); 36334 36335 } 36336 36337 closePath() { 36338 36339 // Add a line curve if start and end of lines are not connected 36340 const startPoint = this.curves[ 0 ].getPoint( 0 ); 36341 const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 ); 36342 36343 if ( ! startPoint.equals( endPoint ) ) { 36344 36345 const lineType = ( startPoint.isVector2 === true ) ? 'LineCurve' : 'LineCurve3'; 36346 this.curves.push( new Curves[ lineType ]( endPoint, startPoint ) ); 36347 36348 } 36349 36350 return this; 36351 36352 } 36353 36354 // To get accurate point with reference to 36355 // entire path distance at time t, 36356 // following has to be done: 36357 36358 // 1. Length of each sub path have to be known 36359 // 2. Locate and identify type of curve 36360 // 3. Get t for the curve 36361 // 4. Return curve.getPointAt(t') 36362 36363 getPoint( t, optionalTarget ) { 36364 36365 const d = t * this.getLength(); 36366 const curveLengths = this.getCurveLengths(); 36367 let i = 0; 36368 36369 // To think about boundaries points. 36370 36371 while ( i < curveLengths.length ) { 36372 36373 if ( curveLengths[ i ] >= d ) { 36374 36375 const diff = curveLengths[ i ] - d; 36376 const curve = this.curves[ i ]; 36377 36378 const segmentLength = curve.getLength(); 36379 const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength; 36380 36381 return curve.getPointAt( u, optionalTarget ); 36382 36383 } 36384 36385 i ++; 36386 36387 } 36388 36389 return null; 36390 36391 // loop where sum != 0, sum > d , sum+1 <d 36392 36393 } 36394 36395 // We cannot use the default THREE.Curve getPoint() with getLength() because in 36396 // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath 36397 // getPoint() depends on getLength 36398 36399 getLength() { 36400 36401 const lens = this.getCurveLengths(); 36402 return lens[ lens.length - 1 ]; 36403 36404 } 36405 36406 // cacheLengths must be recalculated. 36407 updateArcLengths() { 36408 36409 this.needsUpdate = true; 36410 this.cacheLengths = null; 36411 this.getCurveLengths(); 36412 36413 } 36414 36415 // Compute lengths and cache them 36416 // We cannot overwrite getLengths() because UtoT mapping uses it. 36417 36418 getCurveLengths() { 36419 36420 // We use cache values if curves and cache array are same length 36421 36422 if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) { 36423 36424 return this.cacheLengths; 36425 36426 } 36427 36428 // Get length of sub-curve 36429 // Push sums into cached array 36430 36431 const lengths = []; 36432 let sums = 0; 36433 36434 for ( let i = 0, l = this.curves.length; i < l; i ++ ) { 36435 36436 sums += this.curves[ i ].getLength(); 36437 lengths.push( sums ); 36438 36439 } 36440 36441 this.cacheLengths = lengths; 36442 36443 return lengths; 36444 36445 } 36446 36447 getSpacedPoints( divisions = 40 ) { 36448 36449 const points = []; 36450 36451 for ( let i = 0; i <= divisions; i ++ ) { 36452 36453 points.push( this.getPoint( i / divisions ) ); 36454 36455 } 36456 36457 if ( this.autoClose ) { 36458 36459 points.push( points[ 0 ] ); 36460 36461 } 36462 36463 return points; 36464 36465 } 36466 36467 getPoints( divisions = 12 ) { 36468 36469 const points = []; 36470 let last; 36471 36472 for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) { 36473 36474 const curve = curves[ i ]; 36475 const resolution = curve.isEllipseCurve ? divisions * 2 36476 : ( curve.isLineCurve || curve.isLineCurve3 ) ? 1 36477 : curve.isSplineCurve ? divisions * curve.points.length 36478 : divisions; 36479 36480 const pts = curve.getPoints( resolution ); 36481 36482 for ( let j = 0; j < pts.length; j ++ ) { 36483 36484 const point = pts[ j ]; 36485 36486 if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates 36487 36488 points.push( point ); 36489 last = point; 36490 36491 } 36492 36493 } 36494 36495 if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) { 36496 36497 points.push( points[ 0 ] ); 36498 36499 } 36500 36501 return points; 36502 36503 } 36504 36505 copy( source ) { 36506 36507 super.copy( source ); 36508 36509 this.curves = []; 36510 36511 for ( let i = 0, l = source.curves.length; i < l; i ++ ) { 36512 36513 const curve = source.curves[ i ]; 36514 36515 this.curves.push( curve.clone() ); 36516 36517 } 36518 36519 this.autoClose = source.autoClose; 36520 36521 return this; 36522 36523 } 36524 36525 toJSON() { 36526 36527 const data = super.toJSON(); 36528 36529 data.autoClose = this.autoClose; 36530 data.curves = []; 36531 36532 for ( let i = 0, l = this.curves.length; i < l; i ++ ) { 36533 36534 const curve = this.curves[ i ]; 36535 data.curves.push( curve.toJSON() ); 36536 36537 } 36538 36539 return data; 36540 36541 } 36542 36543 fromJSON( json ) { 36544 36545 super.fromJSON( json ); 36546 36547 this.autoClose = json.autoClose; 36548 this.curves = []; 36549 36550 for ( let i = 0, l = json.curves.length; i < l; i ++ ) { 36551 36552 const curve = json.curves[ i ]; 36553 this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) ); 36554 36555 } 36556 36557 return this; 36558 36559 } 36560 36561} 36562 36563class Path extends CurvePath { 36564 36565 constructor( points ) { 36566 36567 super(); 36568 36569 this.type = 'Path'; 36570 36571 this.currentPoint = new Vector2(); 36572 36573 if ( points ) { 36574 36575 this.setFromPoints( points ); 36576 36577 } 36578 36579 } 36580 36581 setFromPoints( points ) { 36582 36583 this.moveTo( points[ 0 ].x, points[ 0 ].y ); 36584 36585 for ( let i = 1, l = points.length; i < l; i ++ ) { 36586 36587 this.lineTo( points[ i ].x, points[ i ].y ); 36588 36589 } 36590 36591 return this; 36592 36593 } 36594 36595 moveTo( x, y ) { 36596 36597 this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying? 36598 36599 return this; 36600 36601 } 36602 36603 lineTo( x, y ) { 36604 36605 const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) ); 36606 this.curves.push( curve ); 36607 36608 this.currentPoint.set( x, y ); 36609 36610 return this; 36611 36612 } 36613 36614 quadraticCurveTo( aCPx, aCPy, aX, aY ) { 36615 36616 const curve = new QuadraticBezierCurve( 36617 this.currentPoint.clone(), 36618 new Vector2( aCPx, aCPy ), 36619 new Vector2( aX, aY ) 36620 ); 36621 36622 this.curves.push( curve ); 36623 36624 this.currentPoint.set( aX, aY ); 36625 36626 return this; 36627 36628 } 36629 36630 bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { 36631 36632 const curve = new CubicBezierCurve( 36633 this.currentPoint.clone(), 36634 new Vector2( aCP1x, aCP1y ), 36635 new Vector2( aCP2x, aCP2y ), 36636 new Vector2( aX, aY ) 36637 ); 36638 36639 this.curves.push( curve ); 36640 36641 this.currentPoint.set( aX, aY ); 36642 36643 return this; 36644 36645 } 36646 36647 splineThru( pts /*Array of Vector*/ ) { 36648 36649 const npts = [ this.currentPoint.clone() ].concat( pts ); 36650 36651 const curve = new SplineCurve( npts ); 36652 this.curves.push( curve ); 36653 36654 this.currentPoint.copy( pts[ pts.length - 1 ] ); 36655 36656 return this; 36657 36658 } 36659 36660 arc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 36661 36662 const x0 = this.currentPoint.x; 36663 const y0 = this.currentPoint.y; 36664 36665 this.absarc( aX + x0, aY + y0, aRadius, 36666 aStartAngle, aEndAngle, aClockwise ); 36667 36668 return this; 36669 36670 } 36671 36672 absarc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 36673 36674 this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); 36675 36676 return this; 36677 36678 } 36679 36680 ellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { 36681 36682 const x0 = this.currentPoint.x; 36683 const y0 = this.currentPoint.y; 36684 36685 this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); 36686 36687 return this; 36688 36689 } 36690 36691 absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { 36692 36693 const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); 36694 36695 if ( this.curves.length > 0 ) { 36696 36697 // if a previous curve is present, attempt to join 36698 const firstPoint = curve.getPoint( 0 ); 36699 36700 if ( ! firstPoint.equals( this.currentPoint ) ) { 36701 36702 this.lineTo( firstPoint.x, firstPoint.y ); 36703 36704 } 36705 36706 } 36707 36708 this.curves.push( curve ); 36709 36710 const lastPoint = curve.getPoint( 1 ); 36711 this.currentPoint.copy( lastPoint ); 36712 36713 return this; 36714 36715 } 36716 36717 copy( source ) { 36718 36719 super.copy( source ); 36720 36721 this.currentPoint.copy( source.currentPoint ); 36722 36723 return this; 36724 36725 } 36726 36727 toJSON() { 36728 36729 const data = super.toJSON(); 36730 36731 data.currentPoint = this.currentPoint.toArray(); 36732 36733 return data; 36734 36735 } 36736 36737 fromJSON( json ) { 36738 36739 super.fromJSON( json ); 36740 36741 this.currentPoint.fromArray( json.currentPoint ); 36742 36743 return this; 36744 36745 } 36746 36747} 36748 36749class LatheGeometry extends BufferGeometry { 36750 36751 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 ) { 36752 36753 super(); 36754 36755 this.type = 'LatheGeometry'; 36756 36757 this.parameters = { 36758 points: points, 36759 segments: segments, 36760 phiStart: phiStart, 36761 phiLength: phiLength 36762 }; 36763 36764 segments = Math.floor( segments ); 36765 36766 // clamp phiLength so it's in range of [ 0, 2PI ] 36767 36768 phiLength = clamp( phiLength, 0, Math.PI * 2 ); 36769 36770 // buffers 36771 36772 const indices = []; 36773 const vertices = []; 36774 const uvs = []; 36775 const initNormals = []; 36776 const normals = []; 36777 36778 // helper variables 36779 36780 const inverseSegments = 1.0 / segments; 36781 const vertex = new Vector3(); 36782 const uv = new Vector2(); 36783 const normal = new Vector3(); 36784 const curNormal = new Vector3(); 36785 const prevNormal = new Vector3(); 36786 let dx = 0; 36787 let dy = 0; 36788 36789 // pre-compute normals for initial "meridian" 36790 36791 for ( let j = 0; j <= ( points.length - 1 ); j ++ ) { 36792 36793 switch ( j ) { 36794 36795 case 0: // special handling for 1st vertex on path 36796 36797 dx = points[ j + 1 ].x - points[ j ].x; 36798 dy = points[ j + 1 ].y - points[ j ].y; 36799 36800 normal.x = dy * 1.0; 36801 normal.y = - dx; 36802 normal.z = dy * 0.0; 36803 36804 prevNormal.copy( normal ); 36805 36806 normal.normalize(); 36807 36808 initNormals.push( normal.x, normal.y, normal.z ); 36809 36810 break; 36811 36812 case ( points.length - 1 ): // special handling for last Vertex on path 36813 36814 initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z ); 36815 36816 break; 36817 36818 default: // default handling for all vertices in between 36819 36820 dx = points[ j + 1 ].x - points[ j ].x; 36821 dy = points[ j + 1 ].y - points[ j ].y; 36822 36823 normal.x = dy * 1.0; 36824 normal.y = - dx; 36825 normal.z = dy * 0.0; 36826 36827 curNormal.copy( normal ); 36828 36829 normal.x += prevNormal.x; 36830 normal.y += prevNormal.y; 36831 normal.z += prevNormal.z; 36832 36833 normal.normalize(); 36834 36835 initNormals.push( normal.x, normal.y, normal.z ); 36836 36837 prevNormal.copy( curNormal ); 36838 36839 } 36840 36841 } 36842 36843 // generate vertices, uvs and normals 36844 36845 for ( let i = 0; i <= segments; i ++ ) { 36846 36847 const phi = phiStart + i * inverseSegments * phiLength; 36848 36849 const sin = Math.sin( phi ); 36850 const cos = Math.cos( phi ); 36851 36852 for ( let j = 0; j <= ( points.length - 1 ); j ++ ) { 36853 36854 // vertex 36855 36856 vertex.x = points[ j ].x * sin; 36857 vertex.y = points[ j ].y; 36858 vertex.z = points[ j ].x * cos; 36859 36860 vertices.push( vertex.x, vertex.y, vertex.z ); 36861 36862 // uv 36863 36864 uv.x = i / segments; 36865 uv.y = j / ( points.length - 1 ); 36866 36867 uvs.push( uv.x, uv.y ); 36868 36869 // normal 36870 36871 const x = initNormals[ 3 * j + 0 ] * sin; 36872 const y = initNormals[ 3 * j + 1 ]; 36873 const z = initNormals[ 3 * j + 0 ] * cos; 36874 36875 normals.push( x, y, z ); 36876 36877 } 36878 36879 } 36880 36881 // indices 36882 36883 for ( let i = 0; i < segments; i ++ ) { 36884 36885 for ( let j = 0; j < ( points.length - 1 ); j ++ ) { 36886 36887 const base = j + i * points.length; 36888 36889 const a = base; 36890 const b = base + points.length; 36891 const c = base + points.length + 1; 36892 const d = base + 1; 36893 36894 // faces 36895 36896 indices.push( a, b, d ); 36897 indices.push( c, d, b ); 36898 36899 } 36900 36901 } 36902 36903 // build geometry 36904 36905 this.setIndex( indices ); 36906 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 36907 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 36908 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 36909 36910 } 36911 36912 copy( source ) { 36913 36914 super.copy( source ); 36915 36916 this.parameters = Object.assign( {}, source.parameters ); 36917 36918 return this; 36919 36920 } 36921 36922 static fromJSON( data ) { 36923 36924 return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength ); 36925 36926 } 36927 36928} 36929 36930class CapsuleGeometry extends LatheGeometry { 36931 36932 constructor( radius = 1, length = 1, capSegments = 4, radialSegments = 8 ) { 36933 36934 const path = new Path(); 36935 path.absarc( 0, - length / 2, radius, Math.PI * 1.5, 0 ); 36936 path.absarc( 0, length / 2, radius, 0, Math.PI * 0.5 ); 36937 36938 super( path.getPoints( capSegments ), radialSegments ); 36939 36940 this.type = 'CapsuleGeometry'; 36941 36942 this.parameters = { 36943 radius: radius, 36944 length: length, 36945 capSegments: capSegments, 36946 radialSegments: radialSegments, 36947 }; 36948 36949 } 36950 36951 static fromJSON( data ) { 36952 36953 return new CapsuleGeometry( data.radius, data.length, data.capSegments, data.radialSegments ); 36954 36955 } 36956 36957} 36958 36959class CircleGeometry extends BufferGeometry { 36960 36961 constructor( radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2 ) { 36962 36963 super(); 36964 36965 this.type = 'CircleGeometry'; 36966 36967 this.parameters = { 36968 radius: radius, 36969 segments: segments, 36970 thetaStart: thetaStart, 36971 thetaLength: thetaLength 36972 }; 36973 36974 segments = Math.max( 3, segments ); 36975 36976 // buffers 36977 36978 const indices = []; 36979 const vertices = []; 36980 const normals = []; 36981 const uvs = []; 36982 36983 // helper variables 36984 36985 const vertex = new Vector3(); 36986 const uv = new Vector2(); 36987 36988 // center point 36989 36990 vertices.push( 0, 0, 0 ); 36991 normals.push( 0, 0, 1 ); 36992 uvs.push( 0.5, 0.5 ); 36993 36994 for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) { 36995 36996 const segment = thetaStart + s / segments * thetaLength; 36997 36998 // vertex 36999 37000 vertex.x = radius * Math.cos( segment ); 37001 vertex.y = radius * Math.sin( segment ); 37002 37003 vertices.push( vertex.x, vertex.y, vertex.z ); 37004 37005 // normal 37006 37007 normals.push( 0, 0, 1 ); 37008 37009 // uvs 37010 37011 uv.x = ( vertices[ i ] / radius + 1 ) / 2; 37012 uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2; 37013 37014 uvs.push( uv.x, uv.y ); 37015 37016 } 37017 37018 // indices 37019 37020 for ( let i = 1; i <= segments; i ++ ) { 37021 37022 indices.push( i, i + 1, 0 ); 37023 37024 } 37025 37026 // build geometry 37027 37028 this.setIndex( indices ); 37029 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,756 bytes, lines 37030-37255
37030 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 37031 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 37032 37033 } 37034 37035 copy( source ) { 37036 37037 super.copy( source ); 37038 37039 this.parameters = Object.assign( {}, source.parameters ); 37040 37041 return this; 37042 37043 } 37044 37045 static fromJSON( data ) { 37046 37047 return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength ); 37048 37049 } 37050 37051} 37052 37053class CylinderGeometry extends BufferGeometry { 37054 37055 constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { 37056 37057 super(); 37058 37059 this.type = 'CylinderGeometry'; 37060 37061 this.parameters = { 37062 radiusTop: radiusTop, 37063 radiusBottom: radiusBottom, 37064 height: height, 37065 radialSegments: radialSegments, 37066 heightSegments: heightSegments, 37067 openEnded: openEnded, 37068 thetaStart: thetaStart, 37069 thetaLength: thetaLength 37070 }; 37071 37072 const scope = this; 37073 37074 radialSegments = Math.floor( radialSegments ); 37075 heightSegments = Math.floor( heightSegments ); 37076 37077 // buffers 37078 37079 const indices = []; 37080 const vertices = []; 37081 const normals = []; 37082 const uvs = []; 37083 37084 // helper variables 37085 37086 let index = 0; 37087 const indexArray = []; 37088 const halfHeight = height / 2; 37089 let groupStart = 0; 37090 37091 // generate geometry 37092 37093 generateTorso(); 37094 37095 if ( openEnded === false ) { 37096 37097 if ( radiusTop > 0 ) generateCap( true ); 37098 if ( radiusBottom > 0 ) generateCap( false ); 37099 37100 } 37101 37102 // build geometry 37103 37104 this.setIndex( indices ); 37105 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 37106 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 37107 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 37108 37109 function generateTorso() { 37110 37111 const normal = new Vector3(); 37112 const vertex = new Vector3(); 37113 37114 let groupCount = 0; 37115 37116 // this will be used to calculate the normal 37117 const slope = ( radiusBottom - radiusTop ) / height; 37118 37119 // generate vertices, normals and uvs 37120 37121 for ( let y = 0; y <= heightSegments; y ++ ) { 37122 37123 const indexRow = []; 37124 37125 const v = y / heightSegments; 37126 37127 // calculate the radius of the current row 37128 37129 const radius = v * ( radiusBottom - radiusTop ) + radiusTop; 37130 37131 for ( let x = 0; x <= radialSegments; x ++ ) { 37132 37133 const u = x / radialSegments; 37134 37135 const theta = u * thetaLength + thetaStart; 37136 37137 const sinTheta = Math.sin( theta ); 37138 const cosTheta = Math.cos( theta ); 37139 37140 // vertex 37141 37142 vertex.x = radius * sinTheta; 37143 vertex.y = - v * height + halfHeight; 37144 vertex.z = radius * cosTheta; 37145 vertices.push( vertex.x, vertex.y, vertex.z ); 37146 37147 // normal 37148 37149 normal.set( sinTheta, slope, cosTheta ).normalize(); 37150 normals.push( normal.x, normal.y, normal.z ); 37151 37152 // uv 37153 37154 uvs.push( u, 1 - v ); 37155 37156 // save index of vertex in respective row 37157 37158 indexRow.push( index ++ ); 37159 37160 } 37161 37162 // now save vertices of the row in our index array 37163 37164 indexArray.push( indexRow ); 37165 37166 } 37167 37168 // generate indices 37169 37170 for ( let x = 0; x < radialSegments; x ++ ) { 37171 37172 for ( let y = 0; y < heightSegments; y ++ ) { 37173 37174 // we use the index array to access the correct indices 37175 37176 const a = indexArray[ y ][ x ]; 37177 const b = indexArray[ y + 1 ][ x ]; 37178 const c = indexArray[ y + 1 ][ x + 1 ]; 37179 const d = indexArray[ y ][ x + 1 ]; 37180 37181 // faces 37182 37183 indices.push( a, b, d ); 37184 indices.push( b, c, d ); 37185 37186 // update group counter 37187 37188 groupCount += 6; 37189 37190 } 37191 37192 } 37193 37194 // add a group to the geometry. this will ensure multi material support 37195 37196 scope.addGroup( groupStart, groupCount, 0 ); 37197 37198 // calculate new start value for groups 37199 37200 groupStart += groupCount; 37201 37202 } 37203 37204 function generateCap( top ) { 37205 37206 // save the index of the first center vertex 37207 const centerIndexStart = index; 37208 37209 const uv = new Vector2(); 37210 const vertex = new Vector3(); 37211 37212 let groupCount = 0; 37213 37214 const radius = ( top === true ) ? radiusTop : radiusBottom; 37215 const sign = ( top === true ) ? 1 : - 1; 37216 37217 // first we generate the center vertex data of the cap. 37218 // because the geometry needs one set of uvs per face, 37219 // we must generate a center vertex per face/segment 37220 37221 for ( let x = 1; x <= radialSegments; x ++ ) { 37222 37223 // vertex 37224 37225 vertices.push( 0, halfHeight * sign, 0 ); 37226 37227 // normal 37228 37229 normals.push( 0, sign, 0 ); 37230 37231 // uv 37232 37233 uvs.push( 0.5, 0.5 ); 37234 37235 // increase index 37236 37237 index ++; 37238 37239 } 37240 37241 // save the index of the last center vertex 37242 const centerIndexEnd = index; 37243 37244 // now we generate the surrounding vertices, normals and uvs 37245 37246 for ( let x = 0; x <= radialSegments; x ++ ) { 37247 37248 const u = x / radialSegments; 37249 const theta = u * thetaLength + thetaStart; 37250 37251 const cosTheta = Math.cos( theta ); 37252 const sinTheta = Math.sin( theta ); 37253 37254 // vertex 37255
vendor: 16,069 bytes, lines 37256-38034
37256 vertex.x = radius * sinTheta; 37257 vertex.y = halfHeight * sign; 37258 vertex.z = radius * cosTheta; 37259 vertices.push( vertex.x, vertex.y, vertex.z ); 37260 37261 // normal 37262 37263 normals.push( 0, sign, 0 ); 37264 37265 // uv 37266 37267 uv.x = ( cosTheta * 0.5 ) + 0.5; 37268 uv.y = ( sinTheta * 0.5 * sign ) + 0.5; 37269 uvs.push( uv.x, uv.y ); 37270 37271 // increase index 37272 37273 index ++; 37274 37275 } 37276 37277 // generate indices 37278 37279 for ( let x = 0; x < radialSegments; x ++ ) { 37280 37281 const c = centerIndexStart + x; 37282 const i = centerIndexEnd + x; 37283 37284 if ( top === true ) { 37285 37286 // face top 37287 37288 indices.push( i, i + 1, c ); 37289 37290 } else { 37291 37292 // face bottom 37293 37294 indices.push( i + 1, i, c ); 37295 37296 } 37297 37298 groupCount += 3; 37299 37300 } 37301 37302 // add a group to the geometry. this will ensure multi material support 37303 37304 scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); 37305 37306 // calculate new start value for groups 37307 37308 groupStart += groupCount; 37309 37310 } 37311 37312 } 37313 37314 copy( source ) { 37315 37316 super.copy( source ); 37317 37318 this.parameters = Object.assign( {}, source.parameters ); 37319 37320 return this; 37321 37322 } 37323 37324 static fromJSON( data ) { 37325 37326 return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); 37327 37328 } 37329 37330} 37331 37332class ConeGeometry extends CylinderGeometry { 37333 37334 constructor( radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { 37335 37336 super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); 37337 37338 this.type = 'ConeGeometry'; 37339 37340 this.parameters = { 37341 radius: radius, 37342 height: height, 37343 radialSegments: radialSegments, 37344 heightSegments: heightSegments, 37345 openEnded: openEnded, 37346 thetaStart: thetaStart, 37347 thetaLength: thetaLength 37348 }; 37349 37350 } 37351 37352 static fromJSON( data ) { 37353 37354 return new ConeGeometry( data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); 37355 37356 } 37357 37358} 37359 37360class PolyhedronGeometry extends BufferGeometry { 37361 37362 constructor( vertices = [], indices = [], radius = 1, detail = 0 ) { 37363 37364 super(); 37365 37366 this.type = 'PolyhedronGeometry'; 37367 37368 this.parameters = { 37369 vertices: vertices, 37370 indices: indices, 37371 radius: radius, 37372 detail: detail 37373 }; 37374 37375 // default buffer data 37376 37377 const vertexBuffer = []; 37378 const uvBuffer = []; 37379 37380 // the subdivision creates the vertex buffer data 37381 37382 subdivide( detail ); 37383 37384 // all vertices should lie on a conceptual sphere with a given radius 37385 37386 applyRadius( radius ); 37387 37388 // finally, create the uv data 37389 37390 generateUVs(); 37391 37392 // build non-indexed geometry 37393 37394 this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) ); 37395 this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) ); 37396 this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) ); 37397 37398 if ( detail === 0 ) { 37399 37400 this.computeVertexNormals(); // flat normals 37401 37402 } else { 37403 37404 this.normalizeNormals(); // smooth normals 37405 37406 } 37407 37408 // helper functions 37409 37410 function subdivide( detail ) { 37411 37412 const a = new Vector3(); 37413 const b = new Vector3(); 37414 const c = new Vector3(); 37415 37416 // iterate over all faces and apply a subdivision with the given detail value 37417 37418 for ( let i = 0; i < indices.length; i += 3 ) { 37419 37420 // get the vertices of the face 37421 37422 getVertexByIndex( indices[ i + 0 ], a ); 37423 getVertexByIndex( indices[ i + 1 ], b ); 37424 getVertexByIndex( indices[ i + 2 ], c ); 37425 37426 // perform subdivision 37427 37428 subdivideFace( a, b, c, detail ); 37429 37430 } 37431 37432 } 37433 37434 function subdivideFace( a, b, c, detail ) { 37435 37436 const cols = detail + 1; 37437 37438 // we use this multidimensional array as a data structure for creating the subdivision 37439 37440 const v = []; 37441 37442 // construct all of the vertices for this subdivision 37443 37444 for ( let i = 0; i <= cols; i ++ ) { 37445 37446 v[ i ] = []; 37447 37448 const aj = a.clone().lerp( c, i / cols ); 37449 const bj = b.clone().lerp( c, i / cols ); 37450 37451 const rows = cols - i; 37452 37453 for ( let j = 0; j <= rows; j ++ ) { 37454 37455 if ( j === 0 && i === cols ) { 37456 37457 v[ i ][ j ] = aj; 37458 37459 } else { 37460 37461 v[ i ][ j ] = aj.clone().lerp( bj, j / rows ); 37462 37463 } 37464 37465 } 37466 37467 } 37468 37469 // construct all of the faces 37470 37471 for ( let i = 0; i < cols; i ++ ) { 37472 37473 for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) { 37474 37475 const k = Math.floor( j / 2 ); 37476 37477 if ( j % 2 === 0 ) { 37478 37479 pushVertex( v[ i ][ k + 1 ] ); 37480 pushVertex( v[ i + 1 ][ k ] ); 37481 pushVertex( v[ i ][ k ] ); 37482 37483 } else { 37484 37485 pushVertex( v[ i ][ k + 1 ] ); 37486 pushVertex( v[ i + 1 ][ k + 1 ] ); 37487 pushVertex( v[ i + 1 ][ k ] ); 37488 37489 } 37490 37491 } 37492 37493 } 37494 37495 } 37496 37497 function applyRadius( radius ) { 37498 37499 const vertex = new Vector3(); 37500 37501 // iterate over the entire buffer and apply the radius to each vertex 37502 37503 for ( let i = 0; i < vertexBuffer.length; i += 3 ) { 37504 37505 vertex.x = vertexBuffer[ i + 0 ]; 37506 vertex.y = vertexBuffer[ i + 1 ]; 37507 vertex.z = vertexBuffer[ i + 2 ]; 37508 37509 vertex.normalize().multiplyScalar( radius ); 37510 37511 vertexBuffer[ i + 0 ] = vertex.x; 37512 vertexBuffer[ i + 1 ] = vertex.y; 37513 vertexBuffer[ i + 2 ] = vertex.z; 37514 37515 } 37516 37517 } 37518 37519 function generateUVs() { 37520 37521 const vertex = new Vector3(); 37522 37523 for ( let i = 0; i < vertexBuffer.length; i += 3 ) { 37524 37525 vertex.x = vertexBuffer[ i + 0 ]; 37526 vertex.y = vertexBuffer[ i + 1 ]; 37527 vertex.z = vertexBuffer[ i + 2 ]; 37528 37529 const u = azimuth( vertex ) / 2 / Math.PI + 0.5; 37530 const v = inclination( vertex ) / Math.PI + 0.5; 37531 uvBuffer.push( u, 1 - v ); 37532 37533 } 37534 37535 correctUVs(); 37536 37537 correctSeam(); 37538 37539 } 37540 37541 function correctSeam() { 37542 37543 // handle case when face straddles the seam, see #3269 37544 37545 for ( let i = 0; i < uvBuffer.length; i += 6 ) { 37546 37547 // uv data of a single face 37548 37549 const x0 = uvBuffer[ i + 0 ]; 37550 const x1 = uvBuffer[ i + 2 ]; 37551 const x2 = uvBuffer[ i + 4 ]; 37552 37553 const max = Math.max( x0, x1, x2 ); 37554 const min = Math.min( x0, x1, x2 ); 37555 37556 // 0.9 is somewhat arbitrary 37557 37558 if ( max > 0.9 && min < 0.1 ) { 37559 37560 if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1; 37561 if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1; 37562 if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1; 37563 37564 } 37565 37566 } 37567 37568 } 37569 37570 function pushVertex( vertex ) { 37571 37572 vertexBuffer.push( vertex.x, vertex.y, vertex.z ); 37573 37574 } 37575 37576 function getVertexByIndex( index, vertex ) { 37577 37578 const stride = index * 3; 37579 37580 vertex.x = vertices[ stride + 0 ]; 37581 vertex.y = vertices[ stride + 1 ]; 37582 vertex.z = vertices[ stride + 2 ]; 37583 37584 } 37585 37586 function correctUVs() { 37587 37588 const a = new Vector3(); 37589 const b = new Vector3(); 37590 const c = new Vector3(); 37591 37592 const centroid = new Vector3(); 37593 37594 const uvA = new Vector2(); 37595 const uvB = new Vector2(); 37596 const uvC = new Vector2(); 37597 37598 for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) { 37599 37600 a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] ); 37601 b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] ); 37602 c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] ); 37603 37604 uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] ); 37605 uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] ); 37606 uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] ); 37607 37608 centroid.copy( a ).add( b ).add( c ).divideScalar( 3 ); 37609 37610 const azi = azimuth( centroid ); 37611 37612 correctUV( uvA, j + 0, a, azi ); 37613 correctUV( uvB, j + 2, b, azi ); 37614 correctUV( uvC, j + 4, c, azi ); 37615 37616 } 37617 37618 } 37619 37620 function correctUV( uv, stride, vector, azimuth ) { 37621 37622 if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) { 37623 37624 uvBuffer[ stride ] = uv.x - 1; 37625 37626 } 37627 37628 if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) { 37629 37630 uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5; 37631 37632 } 37633 37634 } 37635 37636 // Angle around the Y axis, counter-clockwise when looking from above. 37637 37638 function azimuth( vector ) { 37639 37640 return Math.atan2( vector.z, - vector.x ); 37641 37642 } 37643 37644 37645 // Angle above the XZ plane. 37646 37647 function inclination( vector ) { 37648 37649 return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) ); 37650 37651 } 37652 37653 } 37654 37655 copy( source ) { 37656 37657 super.copy( source ); 37658 37659 this.parameters = Object.assign( {}, source.parameters ); 37660 37661 return this; 37662 37663 } 37664 37665 static fromJSON( data ) { 37666 37667 return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details ); 37668 37669 } 37670 37671} 37672 37673class DodecahedronGeometry extends PolyhedronGeometry { 37674 37675 constructor( radius = 1, detail = 0 ) { 37676 37677 const t = ( 1 + Math.sqrt( 5 ) ) / 2; 37678 const r = 1 / t; 37679 37680 const vertices = [ 37681 37682 // (±1, ±1, ±1) 37683 - 1, - 1, - 1, - 1, - 1, 1, 37684 - 1, 1, - 1, - 1, 1, 1, 37685 1, - 1, - 1, 1, - 1, 1, 37686 1, 1, - 1, 1, 1, 1, 37687 37688 // (0, ±1/Ï, ±Ï) 37689 0, - r, - t, 0, - r, t, 37690 0, r, - t, 0, r, t, 37691 37692 // (±1/Ï, ±Ï, 0) 37693 - r, - t, 0, - r, t, 0, 37694 r, - t, 0, r, t, 0, 37695 37696 // (±Ï, 0, ±1/Ï) 37697 - t, 0, - r, t, 0, - r, 37698 - t, 0, r, t, 0, r 37699 ]; 37700 37701 const indices = [ 37702 3, 11, 7, 3, 7, 15, 3, 15, 13, 37703 7, 19, 17, 7, 17, 6, 7, 6, 15, 37704 17, 4, 8, 17, 8, 10, 17, 10, 6, 37705 8, 0, 16, 8, 16, 2, 8, 2, 10, 37706 0, 12, 1, 0, 1, 18, 0, 18, 16, 37707 6, 10, 2, 6, 2, 13, 6, 13, 15, 37708 2, 16, 18, 2, 18, 3, 2, 3, 13, 37709 18, 1, 9, 18, 9, 11, 18, 11, 3, 37710 4, 14, 12, 4, 12, 0, 4, 0, 8, 37711 11, 9, 5, 11, 5, 19, 11, 19, 7, 37712 19, 5, 14, 19, 14, 4, 19, 4, 17, 37713 1, 12, 14, 1, 14, 5, 1, 5, 9 37714 ]; 37715 37716 super( vertices, indices, radius, detail ); 37717 37718 this.type = 'DodecahedronGeometry'; 37719 37720 this.parameters = { 37721 radius: radius, 37722 detail: detail 37723 }; 37724 37725 } 37726 37727 static fromJSON( data ) { 37728 37729 return new DodecahedronGeometry( data.radius, data.detail ); 37730 37731 } 37732 37733} 37734 37735const _v0 = /*@__PURE__*/ new Vector3(); 37736const _v1$1 = /*@__PURE__*/ new Vector3(); 37737const _normal = /*@__PURE__*/ new Vector3(); 37738const _triangle = /*@__PURE__*/ new Triangle(); 37739 37740class EdgesGeometry extends BufferGeometry { 37741 37742 constructor( geometry = null, thresholdAngle = 1 ) { 37743 37744 super(); 37745 37746 this.type = 'EdgesGeometry'; 37747 37748 this.parameters = { 37749 geometry: geometry, 37750 thresholdAngle: thresholdAngle 37751 }; 37752 37753 if ( geometry !== null ) { 37754 37755 const precisionPoints = 4; 37756 const precision = Math.pow( 10, precisionPoints ); 37757 const thresholdDot = Math.cos( DEG2RAD * thresholdAngle ); 37758 37759 const indexAttr = geometry.getIndex(); 37760 const positionAttr = geometry.getAttribute( 'position' ); 37761 const indexCount = indexAttr ? indexAttr.count : positionAttr.count; 37762 37763 const indexArr = [ 0, 0, 0 ]; 37764 const vertKeys = [ 'a', 'b', 'c' ]; 37765 const hashes = new Array( 3 ); 37766 37767 const edgeData = {}; 37768 const vertices = []; 37769 for ( let i = 0; i < indexCount; i += 3 ) { 37770 37771 if ( indexAttr ) { 37772 37773 indexArr[ 0 ] = indexAttr.getX( i ); 37774 indexArr[ 1 ] = indexAttr.getX( i + 1 ); 37775 indexArr[ 2 ] = indexAttr.getX( i + 2 ); 37776 37777 } else { 37778 37779 indexArr[ 0 ] = i; 37780 indexArr[ 1 ] = i + 1; 37781 indexArr[ 2 ] = i + 2; 37782 37783 } 37784 37785 const { a, b, c } = _triangle; 37786 a.fromBufferAttribute( positionAttr, indexArr[ 0 ] ); 37787 b.fromBufferAttribute( positionAttr, indexArr[ 1 ] ); 37788 c.fromBufferAttribute( positionAttr, indexArr[ 2 ] ); 37789 _triangle.getNormal( _normal ); 37790 37791 // create hashes for the edge from the vertices 37792 hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`; 37793 hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`; 37794 hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`; 37795 37796 // skip degenerate triangles 37797 if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) { 37798 37799 continue; 37800 37801 } 37802 37803 // iterate over every edge 37804 for ( let j = 0; j < 3; j ++ ) { 37805 37806 // get the first and next vertex making up the edge 37807 const jNext = ( j + 1 ) % 3; 37808 const vecHash0 = hashes[ j ]; 37809 const vecHash1 = hashes[ jNext ]; 37810 const v0 = _triangle[ vertKeys[ j ] ]; 37811 const v1 = _triangle[ vertKeys[ jNext ] ]; 37812 37813 const hash = `${ vecHash0 }_${ vecHash1 }`; 37814 const reverseHash = `${ vecHash1 }_${ vecHash0 }`; 37815 37816 if ( reverseHash in edgeData && edgeData[ reverseHash ] ) { 37817 37818 // if we found a sibling edge add it into the vertex array if 37819 // it meets the angle threshold and delete the edge from the map. 37820 if ( _normal.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) { 37821 37822 vertices.push( v0.x, v0.y, v0.z ); 37823 vertices.push( v1.x, v1.y, v1.z ); 37824 37825 } 37826 37827 edgeData[ reverseHash ] = null; 37828 37829 } else if ( ! ( hash in edgeData ) ) { 37830 37831 // if we've already got an edge here then skip adding a new one 37832 edgeData[ hash ] = { 37833 37834 index0: indexArr[ j ], 37835 index1: indexArr[ jNext ], 37836 normal: _normal.clone(), 37837 37838 }; 37839 37840 } 37841 37842 } 37843 37844 } 37845 37846 // iterate over all remaining, unmatched edges and add them to the vertex array 37847 for ( const key in edgeData ) { 37848 37849 if ( edgeData[ key ] ) { 37850 37851 const { index0, index1 } = edgeData[ key ]; 37852 _v0.fromBufferAttribute( positionAttr, index0 ); 37853 _v1$1.fromBufferAttribute( positionAttr, index1 ); 37854 37855 vertices.push( _v0.x, _v0.y, _v0.z ); 37856 vertices.push( _v1$1.x, _v1$1.y, _v1$1.z ); 37857 37858 } 37859 37860 } 37861 37862 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 37863 37864 } 37865 37866 } 37867 37868 copy( source ) { 37869 37870 super.copy( source ); 37871 37872 this.parameters = Object.assign( {}, source.parameters ); 37873 37874 return this; 37875 37876 } 37877 37878} 37879 37880class Shape extends Path { 37881 37882 constructor( points ) { 37883 37884 super( points ); 37885 37886 this.uuid = generateUUID(); 37887 37888 this.type = 'Shape'; 37889 37890 this.holes = []; 37891 37892 } 37893 37894 getPointsHoles( divisions ) { 37895 37896 const holesPts = []; 37897 37898 for ( let i = 0, l = this.holes.length; i < l; i ++ ) { 37899 37900 holesPts[ i ] = this.holes[ i ].getPoints( divisions ); 37901 37902 } 37903 37904 return holesPts; 37905 37906 } 37907 37908 // get points of shape and holes (keypoints based on segments parameter) 37909 37910 extractPoints( divisions ) { 37911 37912 return { 37913 37914 shape: this.getPoints( divisions ), 37915 holes: this.getPointsHoles( divisions ) 37916 37917 }; 37918 37919 } 37920 37921 copy( source ) { 37922 37923 super.copy( source ); 37924 37925 this.holes = []; 37926 37927 for ( let i = 0, l = source.holes.length; i < l; i ++ ) { 37928 37929 const hole = source.holes[ i ]; 37930 37931 this.holes.push( hole.clone() ); 37932 37933 } 37934 37935 return this; 37936 37937 } 37938 37939 toJSON() { 37940 37941 const data = super.toJSON(); 37942 37943 data.uuid = this.uuid; 37944 data.holes = []; 37945 37946 for ( let i = 0, l = this.holes.length; i < l; i ++ ) { 37947 37948 const hole = this.holes[ i ]; 37949 data.holes.push( hole.toJSON() ); 37950 37951 } 37952 37953 return data; 37954 37955 } 37956 37957 fromJSON( json ) { 37958 37959 super.fromJSON( json ); 37960 37961 this.uuid = json.uuid; 37962 this.holes = []; 37963 37964 for ( let i = 0, l = json.holes.length; i < l; i ++ ) { 37965 37966 const hole = json.holes[ i ]; 37967 this.holes.push( new Path().fromJSON( hole ) ); 37968 37969 } 37970 37971 return this; 37972 37973 } 37974 37975} 37976 37977/** 37978 * Port from https://github.com/mapbox/earcut (v2.2.4) 37979 */ 37980 37981const Earcut = { 37982 37983 triangulate: function ( data, holeIndices, dim = 2 ) { 37984 37985 const hasHoles = holeIndices && holeIndices.length; 37986 const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length; 37987 let outerNode = linkedList( data, 0, outerLen, dim, true ); 37988 const triangles = []; 37989 37990 if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles; 37991 37992 let minX, minY, maxX, maxY, x, y, invSize; 37993 37994 if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim ); 37995 37996 // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox 37997 if ( data.length > 80 * dim ) { 37998 37999 minX = maxX = data[ 0 ]; 38000 minY = maxY = data[ 1 ]; 38001 38002 for ( let i = dim; i < outerLen; i += dim ) { 38003 38004 x = data[ i ]; 38005 y = data[ i + 1 ]; 38006 if ( x < minX ) minX = x; 38007 if ( y < minY ) minY = y; 38008 if ( x > maxX ) maxX = x; 38009 if ( y > maxY ) maxY = y; 38010 38011 } 38012 38013 // minX, minY and invSize are later used to transform coords into integers for z-order calculation 38014 invSize = Math.max( maxX - minX, maxY - minY ); 38015 invSize = invSize !== 0 ? 32767 / invSize : 0; 38016 38017 } 38018 38019 earcutLinked( outerNode, triangles, dim, minX, minY, invSize, 0 ); 38020 38021 return triangles; 38022 38023 } 38024 38025}; 38026 38027// create a circular doubly linked list from polygon points in the specified winding order 38028function linkedList( data, start, end, dim, clockwise ) { 38029 38030 let i, last; 38031 38032 if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) { 38033 38034 for ( i = start; i < end;
vendor: 10,405 bytes, lines 38034-38507
38034 i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); 38035 38036 } else { 38037 38038 for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); 38039 38040 } 38041 38042 if ( last && equals( last, last.next ) ) { 38043 38044 removeNode( last ); 38045 last = last.next; 38046 38047 } 38048 38049 return last; 38050 38051} 38052 38053// eliminate colinear or duplicate points 38054function filterPoints( start, end ) { 38055 38056 if ( ! start ) return start; 38057 if ( ! end ) end = start; 38058 38059 let p = start, 38060 again; 38061 do { 38062 38063 again = false; 38064 38065 if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) { 38066 38067 removeNode( p ); 38068 p = end = p.prev; 38069 if ( p === p.next ) break; 38070 again = true; 38071 38072 } else { 38073 38074 p = p.next; 38075 38076 } 38077 38078 } while ( again || p !== end ); 38079 38080 return end; 38081 38082} 38083 38084// main ear slicing loop which triangulates a polygon (given as a linked list) 38085function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) { 38086 38087 if ( ! ear ) return; 38088 38089 // interlink polygon nodes in z-order 38090 if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize ); 38091 38092 let stop = ear, 38093 prev, next; 38094 38095 // iterate through ears, slicing them one by one 38096 while ( ear.prev !== ear.next ) { 38097 38098 prev = ear.prev; 38099 next = ear.next; 38100 38101 if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) { 38102 38103 // cut off the triangle 38104 triangles.push( prev.i / dim | 0 ); 38105 triangles.push( ear.i / dim | 0 ); 38106 triangles.push( next.i / dim | 0 ); 38107 38108 removeNode( ear ); 38109 38110 // skipping the next vertex leads to less sliver triangles 38111 ear = next.next; 38112 stop = next.next; 38113 38114 continue; 38115 38116 } 38117 38118 ear = next; 38119 38120 // if we looped through the whole remaining polygon and can't find any more ears 38121 if ( ear === stop ) { 38122 38123 // try filtering points and slicing again 38124 if ( ! pass ) { 38125 38126 earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 ); 38127 38128 // if this didn't work, try curing all small self-intersections locally 38129 38130 } else if ( pass === 1 ) { 38131 38132 ear = cureLocalIntersections( filterPoints( ear ), triangles, dim ); 38133 earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 ); 38134 38135 // as a last resort, try splitting the remaining polygon into two 38136 38137 } else if ( pass === 2 ) { 38138 38139 splitEarcut( ear, triangles, dim, minX, minY, invSize ); 38140 38141 } 38142 38143 break; 38144 38145 } 38146 38147 } 38148 38149} 38150 38151// check whether a polygon node forms a valid ear with adjacent nodes 38152function isEar( ear ) { 38153 38154 const a = ear.prev, 38155 b = ear, 38156 c = ear.next; 38157 38158 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear 38159 38160 // now make sure we don't have other points inside the potential ear 38161 const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; 38162 38163 // triangle bbox; min & max are calculated like this for speed 38164 const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ), 38165 y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ), 38166 x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ), 38167 y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy ); 38168 38169 let p = c.next; 38170 while ( p !== a ) { 38171 38172 if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && 38173 pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && 38174 area( p.prev, p, p.next ) >= 0 ) return false; 38175 p = p.next; 38176 38177 } 38178 38179 return true; 38180 38181} 38182 38183function isEarHashed( ear, minX, minY, invSize ) { 38184 38185 const a = ear.prev, 38186 b = ear, 38187 c = ear.next; 38188 38189 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear 38190 38191 const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; 38192 38193 // triangle bbox; min & max are calculated like this for speed 38194 const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ), 38195 y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ), 38196 x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ), 38197 y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy ); 38198 38199 // z-order range for the current triangle bbox; 38200 const minZ = zOrder( x0, y0, minX, minY, invSize ), 38201 maxZ = zOrder( x1, y1, minX, minY, invSize ); 38202 38203 let p = ear.prevZ, 38204 n = ear.nextZ; 38205 38206 // look for points inside the triangle in both directions 38207 while ( p && p.z >= minZ && n && n.z <= maxZ ) { 38208 38209 if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && 38210 pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false; 38211 p = p.prevZ; 38212 38213 if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && 38214 pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false; 38215 n = n.nextZ; 38216 38217 } 38218 38219 // look for remaining points in decreasing z-order 38220 while ( p && p.z >= minZ ) { 38221 38222 if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && 38223 pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false; 38224 p = p.prevZ; 38225 38226 } 38227 38228 // look for remaining points in increasing z-order 38229 while ( n && n.z <= maxZ ) { 38230 38231 if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && 38232 pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false; 38233 n = n.nextZ; 38234 38235 } 38236 38237 return true; 38238 38239} 38240 38241// go through all polygon nodes and cure small local self-intersections 38242function cureLocalIntersections( start, triangles, dim ) { 38243 38244 let p = start; 38245 do { 38246 38247 const a = p.prev, 38248 b = p.next.next; 38249 38250 if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) { 38251 38252 triangles.push( a.i / dim | 0 ); 38253 triangles.push( p.i / dim | 0 ); 38254 triangles.push( b.i / dim | 0 ); 38255 38256 // remove two nodes involved 38257 removeNode( p ); 38258 removeNode( p.next ); 38259 38260 p = start = b; 38261 38262 } 38263 38264 p = p.next; 38265 38266 } while ( p !== start ); 38267 38268 return filterPoints( p ); 38269 38270} 38271 38272// try splitting polygon into two and triangulate them independently 38273function splitEarcut( start, triangles, dim, minX, minY, invSize ) { 38274 38275 // look for a valid diagonal that divides the polygon into two 38276 let a = start; 38277 do { 38278 38279 let b = a.next.next; 38280 while ( b !== a.prev ) { 38281 38282 if ( a.i !== b.i && isValidDiagonal( a, b ) ) { 38283 38284 // split the polygon in two by the diagonal 38285 let c = splitPolygon( a, b ); 38286 38287 // filter colinear points around the cuts 38288 a = filterPoints( a, a.next ); 38289 c = filterPoints( c, c.next ); 38290 38291 // run earcut on each half 38292 earcutLinked( a, triangles, dim, minX, minY, invSize, 0 ); 38293 earcutLinked( c, triangles, dim, minX, minY, invSize, 0 ); 38294 return; 38295 38296 } 38297 38298 b = b.next; 38299 38300 } 38301 38302 a = a.next; 38303 38304 } while ( a !== start ); 38305 38306} 38307 38308// link every hole into the outer loop, producing a single-ring polygon without holes 38309function eliminateHoles( data, holeIndices, outerNode, dim ) { 38310 38311 const queue = []; 38312 let i, len, start, end, list; 38313 38314 for ( i = 0, len = holeIndices.length; i < len; i ++ ) { 38315 38316 start = holeIndices[ i ] * dim; 38317 end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length; 38318 list = linkedList( data, start, end, dim, false ); 38319 if ( list === list.next ) list.steiner = true; 38320 queue.push( getLeftmost( list ) ); 38321 38322 } 38323 38324 queue.sort( compareX ); 38325 38326 // process holes from left to right 38327 for ( i = 0; i < queue.length; i ++ ) { 38328 38329 outerNode = eliminateHole( queue[ i ], outerNode ); 38330 38331 } 38332 38333 return outerNode; 38334 38335} 38336 38337function compareX( a, b ) { 38338 38339 return a.x - b.x; 38340 38341} 38342 38343// find a bridge between vertices that connects hole with an outer ring and link it 38344function eliminateHole( hole, outerNode ) { 38345 38346 const bridge = findHoleBridge( hole, outerNode ); 38347 if ( ! bridge ) { 38348 38349 return outerNode; 38350 38351 } 38352 38353 const bridgeReverse = splitPolygon( bridge, hole ); 38354 38355 // filter collinear points around the cuts 38356 filterPoints( bridgeReverse, bridgeReverse.next ); 38357 return filterPoints( bridge, bridge.next ); 38358 38359} 38360 38361// David Eberly's algorithm for finding a bridge between hole and outer polygon 38362function findHoleBridge( hole, outerNode ) { 38363 38364 let p = outerNode, 38365 qx = - Infinity, 38366 m; 38367 38368 const hx = hole.x, hy = hole.y; 38369 38370 // find a segment intersected by a ray from the hole's leftmost point to the left; 38371 // segment's endpoint with lesser x will be potential connection point 38372 do { 38373 38374 if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) { 38375 38376 const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y ); 38377 if ( x <= hx && x > qx ) { 38378 38379 qx = x; 38380 m = p.x < p.next.x ? p : p.next; 38381 if ( x === hx ) return m; // hole touches outer segment; pick leftmost endpoint 38382 38383 } 38384 38385 } 38386 38387 p = p.next; 38388 38389 } while ( p !== outerNode ); 38390 38391 if ( ! m ) return null; 38392 38393 // look for points inside the triangle of hole point, segment intersection and endpoint; 38394 // if there are no points found, we have a valid connection; 38395 // otherwise choose the point of the minimum angle with the ray as connection point 38396 38397 const stop = m, 38398 mx = m.x, 38399 my = m.y; 38400 let tanMin = Infinity, tan; 38401 38402 p = m; 38403 38404 do { 38405 38406 if ( hx >= p.x && p.x >= mx && hx !== p.x && 38407 pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) { 38408 38409 tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential 38410 38411 if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) { 38412 38413 m = p; 38414 tanMin = tan; 38415 38416 } 38417 38418 } 38419 38420 p = p.next; 38421 38422 } while ( p !== stop ); 38423 38424 return m; 38425 38426} 38427 38428// whether sector in vertex m contains sector in vertex p in the same coordinates 38429function sectorContainsSector( m, p ) { 38430 38431 return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0; 38432 38433} 38434 38435// interlink polygon nodes in z-order 38436function indexCurve( start, minX, minY, invSize ) { 38437 38438 let p = start; 38439 do { 38440 38441 if ( p.z === 0 ) p.z = zOrder( p.x, p.y, minX, minY, invSize ); 38442 p.prevZ = p.prev; 38443 p.nextZ = p.next; 38444 p = p.next; 38445 38446 } while ( p !== start ); 38447 38448 p.prevZ.nextZ = null; 38449 p.prevZ = null; 38450 38451 sortLinked( p ); 38452 38453} 38454 38455// Simon Tatham's linked list merge sort algorithm 38456// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html 38457function sortLinked( list ) { 38458 38459 let i, p, q, e, tail, numMerges, pSize, qSize, 38460 inSize = 1; 38461 38462 do { 38463 38464 p = list; 38465 list = null; 38466 tail = null; 38467 numMerges = 0; 38468 38469 while ( p ) { 38470 38471 numMerges ++; 38472 q = p; 38473 pSize = 0; 38474 for ( i = 0; i < inSize; i ++ ) { 38475 38476 pSize ++; 38477 q = q.nextZ; 38478 if ( ! q ) break; 38479 38480 } 38481 38482 qSize = inSize; 38483 38484 while ( pSize > 0 || ( qSize > 0 && q ) ) { 38485 38486 if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) { 38487 38488 e = p; 38489 p = p.nextZ; 38490 pSize --; 38491 38492 } else { 38493 38494 e = q; 38495 q = q.nextZ; 38496 qSize --; 38497 38498 } 38499 38500 if ( tail ) tail.nextZ = e; 38501 else list = e; 38502 38503 e.prevZ = tail; 38504 tail = e; 38505 38506 } 38507
vendor: 9,707 bytes, lines 38508-38935
38508 p = q; 38509 38510 } 38511 38512 tail.nextZ = null; 38513 inSize *= 2; 38514 38515 } while ( numMerges > 1 ); 38516 38517 return list; 38518 38519} 38520 38521// z-order of a point given coords and inverse of the longer side of data bbox 38522function zOrder( x, y, minX, minY, invSize ) { 38523 38524 // coords are transformed into non-negative 15-bit integer range 38525 x = ( x - minX ) * invSize | 0; 38526 y = ( y - minY ) * invSize | 0; 38527 38528 x = ( x | ( x << 8 ) ) & 0x00FF00FF; 38529 x = ( x | ( x << 4 ) ) & 0x0F0F0F0F; 38530 x = ( x | ( x << 2 ) ) & 0x33333333; 38531 x = ( x | ( x << 1 ) ) & 0x55555555; 38532 38533 y = ( y | ( y << 8 ) ) & 0x00FF00FF; 38534 y = ( y | ( y << 4 ) ) & 0x0F0F0F0F; 38535 y = ( y | ( y << 2 ) ) & 0x33333333; 38536 y = ( y | ( y << 1 ) ) & 0x55555555; 38537 38538 return x | ( y << 1 ); 38539 38540} 38541 38542// find the leftmost node of a polygon ring 38543function getLeftmost( start ) { 38544 38545 let p = start, 38546 leftmost = start; 38547 do { 38548 38549 if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p; 38550 p = p.next; 38551 38552 } while ( p !== start ); 38553 38554 return leftmost; 38555 38556} 38557 38558// check if a point lies within a convex triangle 38559function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) { 38560 38561 return ( cx - px ) * ( ay - py ) >= ( ax - px ) * ( cy - py ) && 38562 ( ax - px ) * ( by - py ) >= ( bx - px ) * ( ay - py ) && 38563 ( bx - px ) * ( cy - py ) >= ( cx - px ) * ( by - py ); 38564 38565} 38566 38567// check if a diagonal between two polygon nodes is valid (lies in polygon interior) 38568function isValidDiagonal( a, b ) { 38569 38570 return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges 38571 ( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible 38572 ( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors 38573 equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case 38574 38575} 38576 38577// signed area of a triangle 38578function area( p, q, r ) { 38579 38580 return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y ); 38581 38582} 38583 38584// check if two points are equal 38585function equals( p1, p2 ) { 38586 38587 return p1.x === p2.x && p1.y === p2.y; 38588 38589} 38590 38591// check if two segments intersect 38592function intersects( p1, q1, p2, q2 ) { 38593 38594 const o1 = sign( area( p1, q1, p2 ) ); 38595 const o2 = sign( area( p1, q1, q2 ) ); 38596 const o3 = sign( area( p2, q2, p1 ) ); 38597 const o4 = sign( area( p2, q2, q1 ) ); 38598 38599 if ( o1 !== o2 && o3 !== o4 ) return true; // general case 38600 38601 if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1 38602 if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1 38603 if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2 38604 if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2 38605 38606 return false; 38607 38608} 38609 38610// for collinear points p, q, r, check if point q lies on segment pr 38611function onSegment( p, q, r ) { 38612 38613 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 ); 38614 38615} 38616 38617function sign( num ) { 38618 38619 return num > 0 ? 1 : num < 0 ? - 1 : 0; 38620 38621} 38622 38623// check if a polygon diagonal intersects any polygon segments 38624function intersectsPolygon( a, b ) { 38625 38626 let p = a; 38627 do { 38628 38629 if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && 38630 intersects( p, p.next, a, b ) ) return true; 38631 p = p.next; 38632 38633 } while ( p !== a ); 38634 38635 return false; 38636 38637} 38638 38639// check if a polygon diagonal is locally inside the polygon 38640function locallyInside( a, b ) { 38641 38642 return area( a.prev, a, a.next ) < 0 ? 38643 area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 : 38644 area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0; 38645 38646} 38647 38648// check if the middle point of a polygon diagonal is inside the polygon 38649function middleInside( a, b ) { 38650 38651 let p = a, 38652 inside = false; 38653 const px = ( a.x + b.x ) / 2, 38654 py = ( a.y + b.y ) / 2; 38655 do { 38656 38657 if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y && 38658 ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) 38659 inside = ! inside; 38660 p = p.next; 38661 38662 } while ( p !== a ); 38663 38664 return inside; 38665 38666} 38667 38668// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; 38669// if one belongs to the outer ring and another to a hole, it merges it into a single ring 38670function splitPolygon( a, b ) { 38671 38672 const a2 = new Node( a.i, a.x, a.y ), 38673 b2 = new Node( b.i, b.x, b.y ), 38674 an = a.next, 38675 bp = b.prev; 38676 38677 a.next = b; 38678 b.prev = a; 38679 38680 a2.next = an; 38681 an.prev = a2; 38682 38683 b2.next = a2; 38684 a2.prev = b2; 38685 38686 bp.next = b2; 38687 b2.prev = bp; 38688 38689 return b2; 38690 38691} 38692 38693// create a node and optionally link it with previous one (in a circular doubly linked list) 38694function insertNode( i, x, y, last ) { 38695 38696 const p = new Node( i, x, y ); 38697 38698 if ( ! last ) { 38699 38700 p.prev = p; 38701 p.next = p; 38702 38703 } else { 38704 38705 p.next = last.next; 38706 p.prev = last; 38707 last.next.prev = p; 38708 last.next = p; 38709 38710 } 38711 38712 return p; 38713 38714} 38715 38716function removeNode( p ) { 38717 38718 p.next.prev = p.prev; 38719 p.prev.next = p.next; 38720 38721 if ( p.prevZ ) p.prevZ.nextZ = p.nextZ; 38722 if ( p.nextZ ) p.nextZ.prevZ = p.prevZ; 38723 38724} 38725 38726function Node( i, x, y ) { 38727 38728 // vertex index in coordinates array 38729 this.i = i; 38730 38731 // vertex coordinates 38732 this.x = x; 38733 this.y = y; 38734 38735 // previous and next vertex nodes in a polygon ring 38736 this.prev = null; 38737 this.next = null; 38738 38739 // z-order curve value 38740 this.z = 0; 38741 38742 // previous and next nodes in z-order 38743 this.prevZ = null; 38744 this.nextZ = null; 38745 38746 // indicates whether this is a steiner point 38747 this.steiner = false; 38748 38749} 38750 38751function signedArea( data, start, end, dim ) { 38752 38753 let sum = 0; 38754 for ( let i = start, j = end - dim; i < end; i += dim ) { 38755 38756 sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] ); 38757 j = i; 38758 38759 } 38760 38761 return sum; 38762 38763} 38764 38765class ShapeUtils { 38766 38767 // calculate area of the contour polygon 38768 38769 static area( contour ) { 38770 38771 const n = contour.length; 38772 let a = 0.0; 38773 38774 for ( let p = n - 1, q = 0; q < n; p = q ++ ) { 38775 38776 a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y; 38777 38778 } 38779 38780 return a * 0.5; 38781 38782 } 38783 38784 static isClockWise( pts ) { 38785 38786 return ShapeUtils.area( pts ) < 0; 38787 38788 } 38789 38790 static triangulateShape( contour, holes ) { 38791 38792 const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ] 38793 const holeIndices = []; // array of hole indices 38794 const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ] 38795 38796 removeDupEndPts( contour ); 38797 addContour( vertices, contour ); 38798 38799 // 38800 38801 let holeIndex = contour.length; 38802 38803 holes.forEach( removeDupEndPts ); 38804 38805 for ( let i = 0; i < holes.length; i ++ ) { 38806 38807 holeIndices.push( holeIndex ); 38808 holeIndex += holes[ i ].length; 38809 addContour( vertices, holes[ i ] ); 38810 38811 } 38812 38813 // 38814 38815 const triangles = Earcut.triangulate( vertices, holeIndices ); 38816 38817 // 38818 38819 for ( let i = 0; i < triangles.length; i += 3 ) { 38820 38821 faces.push( triangles.slice( i, i + 3 ) ); 38822 38823 } 38824 38825 return faces; 38826 38827 } 38828 38829} 38830 38831function removeDupEndPts( points ) { 38832 38833 const l = points.length; 38834 38835 if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) { 38836 38837 points.pop(); 38838 38839 } 38840 38841} 38842 38843function addContour( vertices, contour ) { 38844 38845 for ( let i = 0; i < contour.length; i ++ ) { 38846 38847 vertices.push( contour[ i ].x ); 38848 vertices.push( contour[ i ].y ); 38849 38850 } 38851 38852} 38853 38854/** 38855 * Creates extruded geometry from a path shape. 38856 * 38857 * parameters = { 38858 * 38859 * curveSegments: <int>, // number of points on the curves 38860 * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too 38861 * depth: <float>, // Depth to extrude the shape 38862 * 38863 * bevelEnabled: <bool>, // turn on bevel 38864 * bevelThickness: <float>, // how deep into the original shape bevel goes 38865 * bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel 38866 * bevelOffset: <float>, // how far from shape outline does bevel start 38867 * bevelSegments: <int>, // number of bevel layers 38868 * 38869 * extrudePath: <THREE.Curve> // curve to extrude shape along 38870 * 38871 * UVGenerator: <Object> // object that provides UV generator functions 38872 * 38873 * } 38874 */ 38875 38876 38877class ExtrudeGeometry extends BufferGeometry { 38878 38879 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 = {} ) { 38880 38881 super(); 38882 38883 this.type = 'ExtrudeGeometry'; 38884 38885 this.parameters = { 38886 shapes: shapes, 38887 options: options 38888 }; 38889 38890 shapes = Array.isArray( shapes ) ? shapes : [ shapes ]; 38891 38892 const scope = this; 38893 38894 const verticesArray = []; 38895 const uvArray = []; 38896 38897 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 38898 38899 const shape = shapes[ i ]; 38900 addShape( shape ); 38901 38902 } 38903 38904 // build geometry 38905 38906 this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) ); 38907 this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) ); 38908 38909 this.computeVertexNormals(); 38910 38911 // functions 38912 38913 function addShape( shape ) { 38914 38915 const placeholder = []; 38916 38917 // options 38918 38919 const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12; 38920 const steps = options.steps !== undefined ? options.steps : 1; 38921 const depth = options.depth !== undefined ? options.depth : 1; 38922 38923 let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; 38924 let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2; 38925 let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1; 38926 let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0; 38927 let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3; 38928 38929 const extrudePath = options.extrudePath; 38930 38931 const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator; 38932 38933 // 38934 38935 let extrudePts, extrudeByPath = false;
vendor: 2,791 bytes, lines 38936-39049
38936 let splineTube, binormal, normal, position2; 38937 38938 if ( extrudePath ) { 38939 38940 extrudePts = extrudePath.getSpacedPoints( steps ); 38941 38942 extrudeByPath = true; 38943 bevelEnabled = false; // bevels not supported for path extrusion 38944 38945 // SETUP TNB variables 38946 38947 // TODO1 - have a .isClosed in spline? 38948 38949 splineTube = extrudePath.computeFrenetFrames( steps, false ); 38950 38951 // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length); 38952 38953 binormal = new Vector3(); 38954 normal = new Vector3(); 38955 position2 = new Vector3(); 38956 38957 } 38958 38959 // Safeguards if bevels are not enabled 38960 38961 if ( ! bevelEnabled ) { 38962 38963 bevelSegments = 0; 38964 bevelThickness = 0; 38965 bevelSize = 0; 38966 bevelOffset = 0; 38967 38968 } 38969 38970 // Variables initialization 38971 38972 const shapePoints = shape.extractPoints( curveSegments ); 38973 38974 let vertices = shapePoints.shape; 38975 const holes = shapePoints.holes; 38976 38977 const reverse = ! ShapeUtils.isClockWise( vertices ); 38978 38979 if ( reverse ) { 38980 38981 vertices = vertices.reverse(); 38982 38983 // Maybe we should also check if holes are in the opposite direction, just to be safe ... 38984 38985 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 38986 38987 const ahole = holes[ h ]; 38988 38989 if ( ShapeUtils.isClockWise( ahole ) ) { 38990 38991 holes[ h ] = ahole.reverse(); 38992 38993 } 38994 38995 } 38996 38997 } 38998 38999 39000 const faces = ShapeUtils.triangulateShape( vertices, holes ); 39001 39002 /* Vertices */ 39003 39004 const contour = vertices; // vertices has all points but contour has only points of circumference 39005 39006 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 39007 39008 const ahole = holes[ h ]; 39009 39010 vertices = vertices.concat( ahole ); 39011 39012 } 39013 39014 39015 function scalePt2( pt, vec, size ) { 39016 39017 if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' ); 39018 39019 return pt.clone().addScaledVector( vec, size ); 39020 39021 } 39022 39023 const vlen = vertices.length, flen = faces.length; 39024 39025 39026 // Find directions for point movement 39027 39028 39029 function getBevelVec( inPt, inPrev, inNext ) { 39030 39031 // computes for inPt the corresponding point inPt' on a new contour 39032 // shifted by 1 unit (length of normalized vector) to the left 39033 // if we walk along contour clockwise, this new contour is outside the old one 39034 // 39035 // inPt' is the intersection of the two lines parallel to the two 39036 // adjacent edges of inPt at a distance of 1 unit on the left side. 39037 39038 let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt 39039 39040 // good reading for geometry algorithms (here: line-line intersection) 39041 // http://geomalgorithms.com/a05-_intersect-1.html 39042 39043 const v_prev_x = inPt.x - inPrev.x, 39044 v_prev_y = inPt.y - inPrev.y; 39045 const v_next_x = inNext.x - inPt.x, 39046 v_next_y = inNext.y - inPt.y; 39047 39048 const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y ); 39049
vendor: 17,452 bytes, lines 39050-39901
39050 // check for collinear edges 39051 const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x ); 39052 39053 if ( Math.abs( collinear0 ) > Number.EPSILON ) { 39054 39055 // not collinear 39056 39057 // length of vectors for normalizing 39058 39059 const v_prev_len = Math.sqrt( v_prev_lensq ); 39060 const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y ); 39061 39062 // shift adjacent points by unit vectors to the left 39063 39064 const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len ); 39065 const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len ); 39066 39067 const ptNextShift_x = ( inNext.x - v_next_y / v_next_len ); 39068 const ptNextShift_y = ( inNext.y + v_next_x / v_next_len ); 39069 39070 // scaling factor for v_prev to intersection point 39071 39072 const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y - 39073 ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) / 39074 ( v_prev_x * v_next_y - v_prev_y * v_next_x ); 39075 39076 // vector from inPt to intersection point 39077 39078 v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x ); 39079 v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y ); 39080 39081 // Don't normalize!, otherwise sharp corners become ugly 39082 // but prevent crazy spikes 39083 const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y ); 39084 if ( v_trans_lensq <= 2 ) { 39085 39086 return new Vector2( v_trans_x, v_trans_y ); 39087 39088 } else { 39089 39090 shrink_by = Math.sqrt( v_trans_lensq / 2 ); 39091 39092 } 39093 39094 } else { 39095 39096 // handle special case of collinear edges 39097 39098 let direction_eq = false; // assumes: opposite 39099 39100 if ( v_prev_x > Number.EPSILON ) { 39101 39102 if ( v_next_x > Number.EPSILON ) { 39103 39104 direction_eq = true; 39105 39106 } 39107 39108 } else { 39109 39110 if ( v_prev_x < - Number.EPSILON ) { 39111 39112 if ( v_next_x < - Number.EPSILON ) { 39113 39114 direction_eq = true; 39115 39116 } 39117 39118 } else { 39119 39120 if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) { 39121 39122 direction_eq = true; 39123 39124 } 39125 39126 } 39127 39128 } 39129 39130 if ( direction_eq ) { 39131 39132 // console.log("Warning: lines are a straight sequence"); 39133 v_trans_x = - v_prev_y; 39134 v_trans_y = v_prev_x; 39135 shrink_by = Math.sqrt( v_prev_lensq ); 39136 39137 } else { 39138 39139 // console.log("Warning: lines are a straight spike"); 39140 v_trans_x = v_prev_x; 39141 v_trans_y = v_prev_y; 39142 shrink_by = Math.sqrt( v_prev_lensq / 2 ); 39143 39144 } 39145 39146 } 39147 39148 return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by ); 39149 39150 } 39151 39152 39153 const contourMovements = []; 39154 39155 for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { 39156 39157 if ( j === il ) j = 0; 39158 if ( k === il ) k = 0; 39159 39160 // (j)---(i)---(k) 39161 // console.log('i,j,k', i, j , k) 39162 39163 contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); 39164 39165 } 39166 39167 const holesMovements = []; 39168 let oneHoleMovements, verticesMovements = contourMovements.concat(); 39169 39170 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 39171 39172 const ahole = holes[ h ]; 39173 39174 oneHoleMovements = []; 39175 39176 for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { 39177 39178 if ( j === il ) j = 0; 39179 if ( k === il ) k = 0; 39180 39181 // (j)---(i)---(k) 39182 oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] ); 39183 39184 } 39185 39186 holesMovements.push( oneHoleMovements ); 39187 verticesMovements = verticesMovements.concat( oneHoleMovements ); 39188 39189 } 39190 39191 39192 // Loop bevelSegments, 1 for the front, 1 for the back 39193 39194 for ( let b = 0; b < bevelSegments; b ++ ) { 39195 39196 //for ( b = bevelSegments; b > 0; b -- ) { 39197 39198 const t = b / bevelSegments; 39199 const z = bevelThickness * Math.cos( t * Math.PI / 2 ); 39200 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset; 39201 39202 // contract shape 39203 39204 for ( let i = 0, il = contour.length; i < il; i ++ ) { 39205 39206 const vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); 39207 39208 v( vert.x, vert.y, - z ); 39209 39210 } 39211 39212 // expand holes 39213 39214 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 39215 39216 const ahole = holes[ h ]; 39217 oneHoleMovements = holesMovements[ h ]; 39218 39219 for ( let i = 0, il = ahole.length; i < il; i ++ ) { 39220 39221 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); 39222 39223 v( vert.x, vert.y, - z ); 39224 39225 } 39226 39227 } 39228 39229 } 39230 39231 const bs = bevelSize + bevelOffset; 39232 39233 // Back facing vertices 39234 39235 for ( let i = 0; i < vlen; i ++ ) { 39236 39237 const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; 39238 39239 if ( ! extrudeByPath ) { 39240 39241 v( vert.x, vert.y, 0 ); 39242 39243 } else { 39244 39245 // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x ); 39246 39247 normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x ); 39248 binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y ); 39249 39250 position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal ); 39251 39252 v( position2.x, position2.y, position2.z ); 39253 39254 } 39255 39256 } 39257 39258 // Add stepped vertices... 39259 // Including front facing vertices 39260 39261 for ( let s = 1; s <= steps; s ++ ) { 39262 39263 for ( let i = 0; i < vlen; i ++ ) { 39264 39265 const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; 39266 39267 if ( ! extrudeByPath ) { 39268 39269 v( vert.x, vert.y, depth / steps * s ); 39270 39271 } else { 39272 39273 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x ); 39274 39275 normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x ); 39276 binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y ); 39277 39278 position2.copy( extrudePts[ s ] ).add( normal ).add( binormal ); 39279 39280 v( position2.x, position2.y, position2.z ); 39281 39282 } 39283 39284 } 39285 39286 } 39287 39288 39289 // Add bevel segments planes 39290 39291 //for ( b = 1; b <= bevelSegments; b ++ ) { 39292 for ( let b = bevelSegments - 1; b >= 0; b -- ) { 39293 39294 const t = b / bevelSegments; 39295 const z = bevelThickness * Math.cos( t * Math.PI / 2 ); 39296 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset; 39297 39298 // contract shape 39299 39300 for ( let i = 0, il = contour.length; i < il; i ++ ) { 39301 39302 const vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); 39303 v( vert.x, vert.y, depth + z ); 39304 39305 } 39306 39307 // expand holes 39308 39309 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 39310 39311 const ahole = holes[ h ]; 39312 oneHoleMovements = holesMovements[ h ]; 39313 39314 for ( let i = 0, il = ahole.length; i < il; i ++ ) { 39315 39316 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); 39317 39318 if ( ! extrudeByPath ) { 39319 39320 v( vert.x, vert.y, depth + z ); 39321 39322 } else { 39323 39324 v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z ); 39325 39326 } 39327 39328 } 39329 39330 } 39331 39332 } 39333 39334 /* Faces */ 39335 39336 // Top and bottom faces 39337 39338 buildLidFaces(); 39339 39340 // Sides faces 39341 39342 buildSideFaces(); 39343 39344 39345 ///// Internal functions 39346 39347 function buildLidFaces() { 39348 39349 const start = verticesArray.length / 3; 39350 39351 if ( bevelEnabled ) { 39352 39353 let layer = 0; // steps + 1 39354 let offset = vlen * layer; 39355 39356 // Bottom faces 39357 39358 for ( let i = 0; i < flen; i ++ ) { 39359 39360 const face = faces[ i ]; 39361 f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset ); 39362 39363 } 39364 39365 layer = steps + bevelSegments * 2; 39366 offset = vlen * layer; 39367 39368 // Top faces 39369 39370 for ( let i = 0; i < flen; i ++ ) { 39371 39372 const face = faces[ i ]; 39373 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset ); 39374 39375 } 39376 39377 } else { 39378 39379 // Bottom faces 39380 39381 for ( let i = 0; i < flen; i ++ ) { 39382 39383 const face = faces[ i ]; 39384 f3( face[ 2 ], face[ 1 ], face[ 0 ] ); 39385 39386 } 39387 39388 // Top faces 39389 39390 for ( let i = 0; i < flen; i ++ ) { 39391 39392 const face = faces[ i ]; 39393 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps ); 39394 39395 } 39396 39397 } 39398 39399 scope.addGroup( start, verticesArray.length / 3 - start, 0 ); 39400 39401 } 39402 39403 // Create faces for the z-sides of the shape 39404 39405 function buildSideFaces() { 39406 39407 const start = verticesArray.length / 3; 39408 let layeroffset = 0; 39409 sidewalls( contour, layeroffset ); 39410 layeroffset += contour.length; 39411 39412 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 39413 39414 const ahole = holes[ h ]; 39415 sidewalls( ahole, layeroffset ); 39416 39417 //, true 39418 layeroffset += ahole.length; 39419 39420 } 39421 39422 39423 scope.addGroup( start, verticesArray.length / 3 - start, 1 ); 39424 39425 39426 } 39427 39428 function sidewalls( contour, layeroffset ) { 39429 39430 let i = contour.length; 39431 39432 while ( -- i >= 0 ) { 39433 39434 const j = i; 39435 let k = i - 1; 39436 if ( k < 0 ) k = contour.length - 1; 39437 39438 //console.log('b', i,j, i-1, k,vertices.length); 39439 39440 for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) { 39441 39442 const slen1 = vlen * s; 39443 const slen2 = vlen * ( s + 1 ); 39444 39445 const a = layeroffset + j + slen1, 39446 b = layeroffset + k + slen1, 39447 c = layeroffset + k + slen2, 39448 d = layeroffset + j + slen2; 39449 39450 f4( a, b, c, d ); 39451 39452 } 39453 39454 } 39455 39456 } 39457 39458 function v( x, y, z ) { 39459 39460 placeholder.push( x ); 39461 placeholder.push( y ); 39462 placeholder.push( z ); 39463 39464 } 39465 39466 39467 function f3( a, b, c ) { 39468 39469 addVertex( a ); 39470 addVertex( b ); 39471 addVertex( c ); 39472 39473 const nextIndex = verticesArray.length / 3; 39474 const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); 39475 39476 addUV( uvs[ 0 ] ); 39477 addUV( uvs[ 1 ] ); 39478 addUV( uvs[ 2 ] ); 39479 39480 } 39481 39482 function f4( a, b, c, d ) { 39483 39484 addVertex( a ); 39485 addVertex( b ); 39486 addVertex( d ); 39487 39488 addVertex( b ); 39489 addVertex( c ); 39490 addVertex( d ); 39491 39492 39493 const nextIndex = verticesArray.length / 3; 39494 const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); 39495 39496 addUV( uvs[ 0 ] ); 39497 addUV( uvs[ 1 ] ); 39498 addUV( uvs[ 3 ] ); 39499 39500 addUV( uvs[ 1 ] ); 39501 addUV( uvs[ 2 ] ); 39502 addUV( uvs[ 3 ] ); 39503 39504 } 39505 39506 function addVertex( index ) { 39507 39508 verticesArray.push( placeholder[ index * 3 + 0 ] ); 39509 verticesArray.push( placeholder[ index * 3 + 1 ] ); 39510 verticesArray.push( placeholder[ index * 3 + 2 ] ); 39511 39512 } 39513 39514 39515 function addUV( vector2 ) { 39516 39517 uvArray.push( vector2.x ); 39518 uvArray.push( vector2.y ); 39519 39520 } 39521 39522 } 39523 39524 } 39525 39526 copy( source ) { 39527 39528 super.copy( source ); 39529 39530 this.parameters = Object.assign( {}, source.parameters ); 39531 39532 return this; 39533 39534 } 39535 39536 toJSON() { 39537 39538 const data = super.toJSON(); 39539 39540 const shapes = this.parameters.shapes; 39541 const options = this.parameters.options; 39542 39543 return toJSON$1( shapes, options, data ); 39544 39545 } 39546 39547 static fromJSON( data, shapes ) { 39548 39549 const geometryShapes = []; 39550 39551 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) { 39552 39553 const shape = shapes[ data.shapes[ j ] ]; 39554 39555 geometryShapes.push( shape ); 39556 39557 } 39558 39559 const extrudePath = data.options.extrudePath; 39560 39561 if ( extrudePath !== undefined ) { 39562 39563 data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath ); 39564 39565 } 39566 39567 return new ExtrudeGeometry( geometryShapes, data.options ); 39568 39569 } 39570 39571} 39572 39573const WorldUVGenerator = { 39574 39575 generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) { 39576 39577 const a_x = vertices[ indexA * 3 ]; 39578 const a_y = vertices[ indexA * 3 + 1 ]; 39579 const b_x = vertices[ indexB * 3 ]; 39580 const b_y = vertices[ indexB * 3 + 1 ]; 39581 const c_x = vertices[ indexC * 3 ]; 39582 const c_y = vertices[ indexC * 3 + 1 ]; 39583 39584 return [ 39585 new Vector2( a_x, a_y ), 39586 new Vector2( b_x, b_y ), 39587 new Vector2( c_x, c_y ) 39588 ]; 39589 39590 }, 39591 39592 generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) { 39593 39594 const a_x = vertices[ indexA * 3 ]; 39595 const a_y = vertices[ indexA * 3 + 1 ]; 39596 const a_z = vertices[ indexA * 3 + 2 ]; 39597 const b_x = vertices[ indexB * 3 ]; 39598 const b_y = vertices[ indexB * 3 + 1 ]; 39599 const b_z = vertices[ indexB * 3 + 2 ]; 39600 const c_x = vertices[ indexC * 3 ]; 39601 const c_y = vertices[ indexC * 3 + 1 ]; 39602 const c_z = vertices[ indexC * 3 + 2 ]; 39603 const d_x = vertices[ indexD * 3 ]; 39604 const d_y = vertices[ indexD * 3 + 1 ]; 39605 const d_z = vertices[ indexD * 3 + 2 ]; 39606 39607 if ( Math.abs( a_y - b_y ) < Math.abs( a_x - b_x ) ) { 39608 39609 return [ 39610 new Vector2( a_x, 1 - a_z ), 39611 new Vector2( b_x, 1 - b_z ), 39612 new Vector2( c_x, 1 - c_z ), 39613 new Vector2( d_x, 1 - d_z ) 39614 ]; 39615 39616 } else { 39617 39618 return [ 39619 new Vector2( a_y, 1 - a_z ), 39620 new Vector2( b_y, 1 - b_z ), 39621 new Vector2( c_y, 1 - c_z ), 39622 new Vector2( d_y, 1 - d_z ) 39623 ]; 39624 39625 } 39626 39627 } 39628 39629}; 39630 39631function toJSON$1( shapes, options, data ) { 39632 39633 data.shapes = []; 39634 39635 if ( Array.isArray( shapes ) ) { 39636 39637 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 39638 39639 const shape = shapes[ i ]; 39640 39641 data.shapes.push( shape.uuid ); 39642 39643 } 39644 39645 } else { 39646 39647 data.shapes.push( shapes.uuid ); 39648 39649 } 39650 39651 data.options = Object.assign( {}, options ); 39652 39653 if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON(); 39654 39655 return data; 39656 39657} 39658 39659class IcosahedronGeometry extends PolyhedronGeometry { 39660 39661 constructor( radius = 1, detail = 0 ) { 39662 39663 const t = ( 1 + Math.sqrt( 5 ) ) / 2; 39664 39665 const vertices = [ 39666 - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0, 39667 0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 39668 t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1 39669 ]; 39670 39671 const indices = [ 39672 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 39673 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, 39674 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 39675 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1 39676 ]; 39677 39678 super( vertices, indices, radius, detail ); 39679 39680 this.type = 'IcosahedronGeometry'; 39681 39682 this.parameters = { 39683 radius: radius, 39684 detail: detail 39685 }; 39686 39687 } 39688 39689 static fromJSON( data ) { 39690 39691 return new IcosahedronGeometry( data.radius, data.detail ); 39692 39693 } 39694 39695} 39696 39697class OctahedronGeometry extends PolyhedronGeometry { 39698 39699 constructor( radius = 1, detail = 0 ) { 39700 39701 const vertices = [ 39702 1, 0, 0, - 1, 0, 0, 0, 1, 0, 39703 0, - 1, 0, 0, 0, 1, 0, 0, - 1 39704 ]; 39705 39706 const indices = [ 39707 0, 2, 4, 0, 4, 3, 0, 3, 5, 39708 0, 5, 2, 1, 2, 5, 1, 5, 3, 39709 1, 3, 4, 1, 4, 2 39710 ]; 39711 39712 super( vertices, indices, radius, detail ); 39713 39714 this.type = 'OctahedronGeometry'; 39715 39716 this.parameters = { 39717 radius: radius, 39718 detail: detail 39719 }; 39720 39721 } 39722 39723 static fromJSON( data ) { 39724 39725 return new OctahedronGeometry( data.radius, data.detail ); 39726 39727 } 39728 39729} 39730 39731class RingGeometry extends BufferGeometry { 39732 39733 constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) { 39734 39735 super(); 39736 39737 this.type = 'RingGeometry'; 39738 39739 this.parameters = { 39740 innerRadius: innerRadius, 39741 outerRadius: outerRadius, 39742 thetaSegments: thetaSegments, 39743 phiSegments: phiSegments, 39744 thetaStart: thetaStart, 39745 thetaLength: thetaLength 39746 }; 39747 39748 thetaSegments = Math.max( 3, thetaSegments ); 39749 phiSegments = Math.max( 1, phiSegments ); 39750 39751 // buffers 39752 39753 const indices = []; 39754 const vertices = []; 39755 const normals = []; 39756 const uvs = []; 39757 39758 // some helper variables 39759 39760 let radius = innerRadius; 39761 const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments ); 39762 const vertex = new Vector3(); 39763 const uv = new Vector2(); 39764 39765 // generate vertices, normals and uvs 39766 39767 for ( let j = 0; j <= phiSegments; j ++ ) { 39768 39769 for ( let i = 0; i <= thetaSegments; i ++ ) { 39770 39771 // values are generate from the inside of the ring to the outside 39772 39773 const segment = thetaStart + i / thetaSegments * thetaLength; 39774 39775 // vertex 39776 39777 vertex.x = radius * Math.cos( segment ); 39778 vertex.y = radius * Math.sin( segment ); 39779 39780 vertices.push( vertex.x, vertex.y, vertex.z ); 39781 39782 // normal 39783 39784 normals.push( 0, 0, 1 ); 39785 39786 // uv 39787 39788 uv.x = ( vertex.x / outerRadius + 1 ) / 2; 39789 uv.y = ( vertex.y / outerRadius + 1 ) / 2; 39790 39791 uvs.push( uv.x, uv.y ); 39792 39793 } 39794 39795 // increase the radius for next row of vertices 39796 39797 radius += radiusStep; 39798 39799 } 39800 39801 // indices 39802 39803 for ( let j = 0; j < phiSegments; j ++ ) { 39804 39805 const thetaSegmentLevel = j * ( thetaSegments + 1 ); 39806 39807 for ( let i = 0; i < thetaSegments; i ++ ) { 39808 39809 const segment = i + thetaSegmentLevel; 39810 39811 const a = segment; 39812 const b = segment + thetaSegments + 1; 39813 const c = segment + thetaSegments + 2; 39814 const d = segment + 1; 39815 39816 // faces 39817 39818 indices.push( a, b, d ); 39819 indices.push( b, c, d ); 39820 39821 } 39822 39823 } 39824 39825 // build geometry 39826 39827 this.setIndex( indices ); 39828 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 39829 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 39830 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 39831 39832 } 39833 39834 copy( source ) { 39835 39836 super.copy( source ); 39837 39838 this.parameters = Object.assign( {}, source.parameters ); 39839 39840 return this; 39841 39842 } 39843 39844 static fromJSON( data ) { 39845 39846 return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength ); 39847 39848 } 39849 39850} 39851 39852class ShapeGeometry extends BufferGeometry { 39853 39854 constructor( shapes = new Shape( [ new Vector2( 0, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), curveSegments = 12 ) { 39855 39856 super(); 39857 39858 this.type = 'ShapeGeometry'; 39859 39860 this.parameters = { 39861 shapes: shapes, 39862 curveSegments: curveSegments 39863 }; 39864 39865 // buffers 39866 39867 const indices = []; 39868 const vertices = []; 39869 const normals = []; 39870 const uvs = []; 39871 39872 // helper variables 39873 39874 let groupStart = 0; 39875 let groupCount = 0; 39876 39877 // allow single and array values for "shapes" parameter 39878 39879 if ( Array.isArray( shapes ) === false ) { 39880 39881 addShape( shapes ); 39882 39883 } else { 39884 39885 for ( let i = 0; i < shapes.length; i ++ ) { 39886 39887 addShape( shapes[ i ] ); 39888 39889 this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support 39890 39891 groupStart += groupCount; 39892 groupCount = 0; 39893 39894 } 39895 39896 } 39897 39898 // build geometry 39899 39900 this.setIndex( indices ); 39901 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,878 bytes, lines 39902-40148
39902 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 39903 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 39904 39905 39906 // helper functions 39907 39908 function addShape( shape ) { 39909 39910 const indexOffset = vertices.length / 3; 39911 const points = shape.extractPoints( curveSegments ); 39912 39913 let shapeVertices = points.shape; 39914 const shapeHoles = points.holes; 39915 39916 // check direction of vertices 39917 39918 if ( ShapeUtils.isClockWise( shapeVertices ) === false ) { 39919 39920 shapeVertices = shapeVertices.reverse(); 39921 39922 } 39923 39924 for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) { 39925 39926 const shapeHole = shapeHoles[ i ]; 39927 39928 if ( ShapeUtils.isClockWise( shapeHole ) === true ) { 39929 39930 shapeHoles[ i ] = shapeHole.reverse(); 39931 39932 } 39933 39934 } 39935 39936 const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles ); 39937 39938 // join vertices of inner and outer paths to a single array 39939 39940 for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) { 39941 39942 const shapeHole = shapeHoles[ i ]; 39943 shapeVertices = shapeVertices.concat( shapeHole ); 39944 39945 } 39946 39947 // vertices, normals, uvs 39948 39949 for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) { 39950 39951 const vertex = shapeVertices[ i ]; 39952 39953 vertices.push( vertex.x, vertex.y, 0 ); 39954 normals.push( 0, 0, 1 ); 39955 uvs.push( vertex.x, vertex.y ); // world uvs 39956 39957 } 39958 39959 // indices 39960 39961 for ( let i = 0, l = faces.length; i < l; i ++ ) { 39962 39963 const face = faces[ i ]; 39964 39965 const a = face[ 0 ] + indexOffset; 39966 const b = face[ 1 ] + indexOffset; 39967 const c = face[ 2 ] + indexOffset; 39968 39969 indices.push( a, b, c ); 39970 groupCount += 3; 39971 39972 } 39973 39974 } 39975 39976 } 39977 39978 copy( source ) { 39979 39980 super.copy( source ); 39981 39982 this.parameters = Object.assign( {}, source.parameters ); 39983 39984 return this; 39985 39986 } 39987 39988 toJSON() { 39989 39990 const data = super.toJSON(); 39991 39992 const shapes = this.parameters.shapes; 39993 39994 return toJSON( shapes, data ); 39995 39996 } 39997 39998 static fromJSON( data, shapes ) { 39999 40000 const geometryShapes = []; 40001 40002 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) { 40003 40004 const shape = shapes[ data.shapes[ j ] ]; 40005 40006 geometryShapes.push( shape ); 40007 40008 } 40009 40010 return new ShapeGeometry( geometryShapes, data.curveSegments ); 40011 40012 } 40013 40014} 40015 40016function toJSON( shapes, data ) { 40017 40018 data.shapes = []; 40019 40020 if ( Array.isArray( shapes ) ) { 40021 40022 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 40023 40024 const shape = shapes[ i ]; 40025 40026 data.shapes.push( shape.uuid ); 40027 40028 } 40029 40030 } else { 40031 40032 data.shapes.push( shapes.uuid ); 40033 40034 } 40035 40036 return data; 40037 40038} 40039 40040class SphereGeometry extends BufferGeometry { 40041 40042 constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) { 40043 40044 super(); 40045 40046 this.type = 'SphereGeometry'; 40047 40048 this.parameters = { 40049 radius: radius, 40050 widthSegments: widthSegments, 40051 heightSegments: heightSegments, 40052 phiStart: phiStart, 40053 phiLength: phiLength, 40054 thetaStart: thetaStart, 40055 thetaLength: thetaLength 40056 }; 40057 40058 widthSegments = Math.max( 3, Math.floor( widthSegments ) ); 40059 heightSegments = Math.max( 2, Math.floor( heightSegments ) ); 40060 40061 const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI ); 40062 40063 let index = 0; 40064 const grid = []; 40065 40066 const vertex = new Vector3(); 40067 const normal = new Vector3(); 40068 40069 // buffers 40070 40071 const indices = []; 40072 const vertices = []; 40073 const normals = []; 40074 const uvs = []; 40075 40076 // generate vertices, normals and uvs 40077 40078 for ( let iy = 0; iy <= heightSegments; iy ++ ) { 40079 40080 const verticesRow = []; 40081 40082 const v = iy / heightSegments; 40083 40084 // special case for the poles 40085 40086 let uOffset = 0; 40087 40088 if ( iy === 0 && thetaStart === 0 ) { 40089 40090 uOffset = 0.5 / widthSegments; 40091 40092 } else if ( iy === heightSegments && thetaEnd === Math.PI ) { 40093 40094 uOffset = - 0.5 / widthSegments; 40095 40096 } 40097 40098 for ( let ix = 0; ix <= widthSegments; ix ++ ) { 40099 40100 const u = ix / widthSegments; 40101 40102 // vertex 40103 40104 vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); 40105 vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); 40106 vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); 40107 40108 vertices.push( vertex.x, vertex.y, vertex.z ); 40109 40110 // normal 40111 40112 normal.copy( vertex ).normalize(); 40113 normals.push( normal.x, normal.y, normal.z ); 40114 40115 // uv 40116 40117 uvs.push( u + uOffset, 1 - v ); 40118 40119 verticesRow.push( index ++ ); 40120 40121 } 40122 40123 grid.push( verticesRow ); 40124 40125 } 40126 40127 // indices 40128 40129 for ( let iy = 0; iy < heightSegments; iy ++ ) { 40130 40131 for ( let ix = 0; ix < widthSegments; ix ++ ) { 40132 40133 const a = grid[ iy ][ ix + 1 ]; 40134 const b = grid[ iy ][ ix ]; 40135 const c = grid[ iy + 1 ][ ix ]; 40136 const d = grid[ iy + 1 ][ ix + 1 ]; 40137 40138 if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d ); 40139 if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d ); 40140 40141 } 40142 40143 } 40144 40145 // build geometry 40146 40147 this.setIndex( indices ); 40148 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 6,566 bytes, lines 40149-40441
40149 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 40150 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 40151 40152 } 40153 40154 copy( source ) { 40155 40156 super.copy( source ); 40157 40158 this.parameters = Object.assign( {}, source.parameters ); 40159 40160 return this; 40161 40162 } 40163 40164 static fromJSON( data ) { 40165 40166 return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); 40167 40168 } 40169 40170} 40171 40172class TetrahedronGeometry extends PolyhedronGeometry { 40173 40174 constructor( radius = 1, detail = 0 ) { 40175 40176 const vertices = [ 40177 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1 40178 ]; 40179 40180 const indices = [ 40181 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 40182 ]; 40183 40184 super( vertices, indices, radius, detail ); 40185 40186 this.type = 'TetrahedronGeometry'; 40187 40188 this.parameters = { 40189 radius: radius, 40190 detail: detail 40191 }; 40192 40193 } 40194 40195 static fromJSON( data ) { 40196 40197 return new TetrahedronGeometry( data.radius, data.detail ); 40198 40199 } 40200 40201} 40202 40203class TorusGeometry extends BufferGeometry { 40204 40205 constructor( radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2 ) { 40206 40207 super(); 40208 40209 this.type = 'TorusGeometry'; 40210 40211 this.parameters = { 40212 radius: radius, 40213 tube: tube, 40214 radialSegments: radialSegments, 40215 tubularSegments: tubularSegments, 40216 arc: arc 40217 }; 40218 40219 radialSegments = Math.floor( radialSegments ); 40220 tubularSegments = Math.floor( tubularSegments ); 40221 40222 // buffers 40223 40224 const indices = []; 40225 const vertices = []; 40226 const normals = []; 40227 const uvs = []; 40228 40229 // helper variables 40230 40231 const center = new Vector3(); 40232 const vertex = new Vector3(); 40233 const normal = new Vector3(); 40234 40235 // generate vertices, normals and uvs 40236 40237 for ( let j = 0; j <= radialSegments; j ++ ) { 40238 40239 for ( let i = 0; i <= tubularSegments; i ++ ) { 40240 40241 const u = i / tubularSegments * arc; 40242 const v = j / radialSegments * Math.PI * 2; 40243 40244 // vertex 40245 40246 vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u ); 40247 vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u ); 40248 vertex.z = tube * Math.sin( v ); 40249 40250 vertices.push( vertex.x, vertex.y, vertex.z ); 40251 40252 // normal 40253 40254 center.x = radius * Math.cos( u ); 40255 center.y = radius * Math.sin( u ); 40256 normal.subVectors( vertex, center ).normalize(); 40257 40258 normals.push( normal.x, normal.y, normal.z ); 40259 40260 // uv 40261 40262 uvs.push( i / tubularSegments ); 40263 uvs.push( j / radialSegments ); 40264 40265 } 40266 40267 } 40268 40269 // generate indices 40270 40271 for ( let j = 1; j <= radialSegments; j ++ ) { 40272 40273 for ( let i = 1; i <= tubularSegments; i ++ ) { 40274 40275 // indices 40276 40277 const a = ( tubularSegments + 1 ) * j + i - 1; 40278 const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1; 40279 const c = ( tubularSegments + 1 ) * ( j - 1 ) + i; 40280 const d = ( tubularSegments + 1 ) * j + i; 40281 40282 // faces 40283 40284 indices.push( a, b, d ); 40285 indices.push( b, c, d ); 40286 40287 } 40288 40289 } 40290 40291 // build geometry 40292 40293 this.setIndex( indices ); 40294 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 40295 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 40296 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 40297 40298 } 40299 40300 copy( source ) { 40301 40302 super.copy( source ); 40303 40304 this.parameters = Object.assign( {}, source.parameters ); 40305 40306 return this; 40307 40308 } 40309 40310 static fromJSON( data ) { 40311 40312 return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc ); 40313 40314 } 40315 40316} 40317 40318class TorusKnotGeometry extends BufferGeometry { 40319 40320 constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) { 40321 40322 super(); 40323 40324 this.type = 'TorusKnotGeometry'; 40325 40326 this.parameters = { 40327 radius: radius, 40328 tube: tube, 40329 tubularSegments: tubularSegments, 40330 radialSegments: radialSegments, 40331 p: p, 40332 q: q 40333 }; 40334 40335 tubularSegments = Math.floor( tubularSegments ); 40336 radialSegments = Math.floor( radialSegments ); 40337 40338 // buffers 40339 40340 const indices = []; 40341 const vertices = []; 40342 const normals = []; 40343 const uvs = []; 40344 40345 // helper variables 40346 40347 const vertex = new Vector3(); 40348 const normal = new Vector3(); 40349 40350 const P1 = new Vector3(); 40351 const P2 = new Vector3(); 40352 40353 const B = new Vector3(); 40354 const T = new Vector3(); 40355 const N = new Vector3(); 40356 40357 // generate vertices, normals and uvs 40358 40359 for ( let i = 0; i <= tubularSegments; ++ i ) { 40360 40361 // the radian "u" is used to calculate the position on the torus curve of the current tubular segment 40362 40363 const u = i / tubularSegments * p * Math.PI * 2; 40364 40365 // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead. 40366 // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions 40367 40368 calculatePositionOnCurve( u, p, q, radius, P1 ); 40369 calculatePositionOnCurve( u + 0.01, p, q, radius, P2 ); 40370 40371 // calculate orthonormal basis 40372 40373 T.subVectors( P2, P1 ); 40374 N.addVectors( P2, P1 ); 40375 B.crossVectors( T, N ); 40376 N.crossVectors( B, T ); 40377 40378 // normalize B, N. T can be ignored, we don't use it 40379 40380 B.normalize(); 40381 N.normalize(); 40382 40383 for ( let j = 0; j <= radialSegments; ++ j ) { 40384 40385 // now calculate the vertices. they are nothing more than an extrusion of the torus curve. 40386 // because we extrude a shape in the xy-plane, there is no need to calculate a z-value. 40387 40388 const v = j / radialSegments * Math.PI * 2; 40389 const cx = - tube * Math.cos( v ); 40390 const cy = tube * Math.sin( v ); 40391 40392 // now calculate the final vertex position. 40393 // first we orient the extrusion with our basis vectors, then we add it to the current position on the curve 40394 40395 vertex.x = P1.x + ( cx * N.x + cy * B.x ); 40396 vertex.y = P1.y + ( cx * N.y + cy * B.y ); 40397 vertex.z = P1.z + ( cx * N.z + cy * B.z ); 40398 40399 vertices.push( vertex.x, vertex.y, vertex.z ); 40400 40401 // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal) 40402 40403 normal.subVectors( vertex, P1 ).normalize(); 40404 40405 normals.push( normal.x, normal.y, normal.z ); 40406 40407 // uv 40408 40409 uvs.push( i / tubularSegments ); 40410 uvs.push( j / radialSegments ); 40411 40412 } 40413 40414 } 40415 40416 // generate indices 40417 40418 for ( let j = 1; j <= tubularSegments; j ++ ) { 40419 40420 for ( let i = 1; i <= radialSegments; i ++ ) { 40421 40422 // indices 40423 40424 const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); 40425 const b = ( radialSegments + 1 ) * j + ( i - 1 ); 40426 const c = ( radialSegments + 1 ) * j + i; 40427 const d = ( radialSegments + 1 ) * ( j - 1 ) + i; 40428 40429 // faces 40430 40431 indices.push( a, b, d ); 40432 indices.push( b, c, d ); 40433 40434 } 40435 40436 } 40437 40438 // build geometry 40439 40440 this.setIndex( indices ); 40441 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 7,450 bytes, lines 40442-40800
40442 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 40443 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 40444 40445 // this function calculates the current position on the torus curve 40446 40447 function calculatePositionOnCurve( u, p, q, radius, position ) { 40448 40449 const cu = Math.cos( u ); 40450 const su = Math.sin( u ); 40451 const quOverP = q / p * u; 40452 const cs = Math.cos( quOverP ); 40453 40454 position.x = radius * ( 2 + cs ) * 0.5 * cu; 40455 position.y = radius * ( 2 + cs ) * su * 0.5; 40456 position.z = radius * Math.sin( quOverP ) * 0.5; 40457 40458 } 40459 40460 } 40461 40462 copy( source ) { 40463 40464 super.copy( source ); 40465 40466 this.parameters = Object.assign( {}, source.parameters ); 40467 40468 return this; 40469 40470 } 40471 40472 static fromJSON( data ) { 40473 40474 return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q ); 40475 40476 } 40477 40478} 40479 40480class TubeGeometry extends BufferGeometry { 40481 40482 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 ) { 40483 40484 super(); 40485 40486 this.type = 'TubeGeometry'; 40487 40488 this.parameters = { 40489 path: path, 40490 tubularSegments: tubularSegments, 40491 radius: radius, 40492 radialSegments: radialSegments, 40493 closed: closed 40494 }; 40495 40496 const frames = path.computeFrenetFrames( tubularSegments, closed ); 40497 40498 // expose internals 40499 40500 this.tangents = frames.tangents; 40501 this.normals = frames.normals; 40502 this.binormals = frames.binormals; 40503 40504 // helper variables 40505 40506 const vertex = new Vector3(); 40507 const normal = new Vector3(); 40508 const uv = new Vector2(); 40509 let P = new Vector3(); 40510 40511 // buffer 40512 40513 const vertices = []; 40514 const normals = []; 40515 const uvs = []; 40516 const indices = []; 40517 40518 // create buffer data 40519 40520 generateBufferData(); 40521 40522 // build geometry 40523 40524 this.setIndex( indices ); 40525 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 40526 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 40527 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 40528 40529 // functions 40530 40531 function generateBufferData() { 40532 40533 for ( let i = 0; i < tubularSegments; i ++ ) { 40534 40535 generateSegment( i ); 40536 40537 } 40538 40539 // if the geometry is not closed, generate the last row of vertices and normals 40540 // at the regular position on the given path 40541 // 40542 // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ) 40543 40544 generateSegment( ( closed === false ) ? tubularSegments : 0 ); 40545 40546 // uvs are generated in a separate function. 40547 // this makes it easy compute correct values for closed geometries 40548 40549 generateUVs(); 40550 40551 // finally create faces 40552 40553 generateIndices(); 40554 40555 } 40556 40557 function generateSegment( i ) { 40558 40559 // we use getPointAt to sample evenly distributed points from the given path 40560 40561 P = path.getPointAt( i / tubularSegments, P ); 40562 40563 // retrieve corresponding normal and binormal 40564 40565 const N = frames.normals[ i ]; 40566 const B = frames.binormals[ i ]; 40567 40568 // generate normals and vertices for the current segment 40569 40570 for ( let j = 0; j <= radialSegments; j ++ ) { 40571 40572 const v = j / radialSegments * Math.PI * 2; 40573 40574 const sin = Math.sin( v ); 40575 const cos = - Math.cos( v ); 40576 40577 // normal 40578 40579 normal.x = ( cos * N.x + sin * B.x ); 40580 normal.y = ( cos * N.y + sin * B.y ); 40581 normal.z = ( cos * N.z + sin * B.z ); 40582 normal.normalize(); 40583 40584 normals.push( normal.x, normal.y, normal.z ); 40585 40586 // vertex 40587 40588 vertex.x = P.x + radius * normal.x; 40589 vertex.y = P.y + radius * normal.y; 40590 vertex.z = P.z + radius * normal.z; 40591 40592 vertices.push( vertex.x, vertex.y, vertex.z ); 40593 40594 } 40595 40596 } 40597 40598 function generateIndices() { 40599 40600 for ( let j = 1; j <= tubularSegments; j ++ ) { 40601 40602 for ( let i = 1; i <= radialSegments; i ++ ) { 40603 40604 const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); 40605 const b = ( radialSegments + 1 ) * j + ( i - 1 ); 40606 const c = ( radialSegments + 1 ) * j + i; 40607 const d = ( radialSegments + 1 ) * ( j - 1 ) + i; 40608 40609 // faces 40610 40611 indices.push( a, b, d ); 40612 indices.push( b, c, d ); 40613 40614 } 40615 40616 } 40617 40618 } 40619 40620 function generateUVs() { 40621 40622 for ( let i = 0; i <= tubularSegments; i ++ ) { 40623 40624 for ( let j = 0; j <= radialSegments; j ++ ) { 40625 40626 uv.x = i / tubularSegments; 40627 uv.y = j / radialSegments; 40628 40629 uvs.push( uv.x, uv.y ); 40630 40631 } 40632 40633 } 40634 40635 } 40636 40637 } 40638 40639 copy( source ) { 40640 40641 super.copy( source ); 40642 40643 this.parameters = Object.assign( {}, source.parameters ); 40644 40645 return this; 40646 40647 } 40648 40649 toJSON() { 40650 40651 const data = super.toJSON(); 40652 40653 data.path = this.parameters.path.toJSON(); 40654 40655 return data; 40656 40657 } 40658 40659 static fromJSON( data ) { 40660 40661 // This only works for built-in curves (e.g. CatmullRomCurve3). 40662 // User defined curves or instances of CurvePath will not be deserialized. 40663 return new TubeGeometry( 40664 new Curves[ data.path.type ]().fromJSON( data.path ), 40665 data.tubularSegments, 40666 data.radius, 40667 data.radialSegments, 40668 data.closed 40669 ); 40670 40671 } 40672 40673} 40674 40675class WireframeGeometry extends BufferGeometry { 40676 40677 constructor( geometry = null ) { 40678 40679 super(); 40680 40681 this.type = 'WireframeGeometry'; 40682 40683 this.parameters = { 40684 geometry: geometry 40685 }; 40686 40687 if ( geometry !== null ) { 40688 40689 // buffer 40690 40691 const vertices = []; 40692 const edges = new Set(); 40693 40694 // helper variables 40695 40696 const start = new Vector3(); 40697 const end = new Vector3(); 40698 40699 if ( geometry.index !== null ) { 40700 40701 // indexed BufferGeometry 40702 40703 const position = geometry.attributes.position; 40704 const indices = geometry.index; 40705 let groups = geometry.groups; 40706 40707 if ( groups.length === 0 ) { 40708 40709 groups = [ { start: 0, count: indices.count, materialIndex: 0 } ]; 40710 40711 } 40712 40713 // create a data structure that contains all edges without duplicates 40714 40715 for ( let o = 0, ol = groups.length; o < ol; ++ o ) { 40716 40717 const group = groups[ o ]; 40718 40719 const groupStart = group.start; 40720 const groupCount = group.count; 40721 40722 for ( let i = groupStart, l = ( groupStart + groupCount ); i < l; i += 3 ) { 40723 40724 for ( let j = 0; j < 3; j ++ ) { 40725 40726 const index1 = indices.getX( i + j ); 40727 const index2 = indices.getX( i + ( j + 1 ) % 3 ); 40728 40729 start.fromBufferAttribute( position, index1 ); 40730 end.fromBufferAttribute( position, index2 ); 40731 40732 if ( isUniqueEdge( start, end, edges ) === true ) { 40733 40734 vertices.push( start.x, start.y, start.z ); 40735 vertices.push( end.x, end.y, end.z ); 40736 40737 } 40738 40739 } 40740 40741 } 40742 40743 } 40744 40745 } else { 40746 40747 // non-indexed BufferGeometry 40748 40749 const position = geometry.attributes.position; 40750 40751 for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) { 40752 40753 for ( let j = 0; j < 3; j ++ ) { 40754 40755 // three edges per triangle, an edge is represented as (index1, index2) 40756 // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0) 40757 40758 const index1 = 3 * i + j; 40759 const index2 = 3 * i + ( ( j + 1 ) % 3 ); 40760 40761 start.fromBufferAttribute( position, index1 ); 40762 end.fromBufferAttribute( position, index2 ); 40763 40764 if ( isUniqueEdge( start, end, edges ) === true ) { 40765 40766 vertices.push( start.x, start.y, start.z ); 40767 vertices.push( end.x, end.y, end.z ); 40768 40769 } 40770 40771 } 40772 40773 } 40774 40775 } 40776 40777 // build geometry 40778 40779 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 40780 40781 } 40782 40783 } 40784 40785 copy( source ) { 40786 40787 super.copy( source ); 40788 40789 this.parameters = Object.assign( {}, source.parameters ); 40790 40791 return this; 40792 40793 } 40794 40795} 40796 40797function isUniqueEdge( start, end, edges ) { 40798 40799 const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`; 40800 const hash2 = `${end.x}
40800,${end.y},${end.z}-${start.x},${start.y},${start.z}`; // coincident edge 40801 40802 if ( edges.has( hash1 ) === true || edges.has( hash2 ) === true ) { 40803 40804 return false; 40805 40806 } else { 40807 40808 edges.add( hash1 ); 40809 edges.add( hash2 ); 40810 return true; 40811 40812 } 40813 40814} 40815 40816var Geometries = /*#__PURE__*/Object.freeze({ 40817 __proto__: null, 40818 BoxGeometry: BoxGeometry, 40819 CapsuleGeometry: CapsuleGeometry, 40820 CircleGeometry: CircleGeometry, 40821 ConeGeometry: ConeGeometry, 40822 CylinderGeometry: CylinderGeometry, 40823 DodecahedronGeometry: DodecahedronGeometry, 40824 EdgesGeometry: EdgesGeometry, 40825 ExtrudeGeometry: ExtrudeGeometry, 40826 IcosahedronGeometry: IcosahedronGeometry, 40827 LatheGeometry: LatheGeometry, 40828 OctahedronGeometry: OctahedronGeometry, 40829 PlaneGeometry: PlaneGeometry, 40830 PolyhedronGeometry: PolyhedronGeometry, 40831 RingGeometry: RingGeometry, 40832 ShapeGeometry: ShapeGeometry, 40833 SphereGeometry: SphereGeometry, 40834 TetrahedronGeometry: TetrahedronGeometry, 40835 TorusGeometry: TorusGeometry, 40836 TorusKnotGeometry: TorusKnotGeometry, 40837 TubeGeometry: TubeGeometry, 40838 WireframeGeometry: WireframeGeometry 40839}); 40840 40841class ShadowMaterial extends Material { 40842 40843 constructor( parameters ) { 40844 40845 super(); 40846 40847 this.isShadowMaterial = true; 40848 40849 this.type = 'ShadowMaterial'; 40850 40851 this.color = new Color( 0x000000 ); 40852 this.transparent = true; 40853 40854 this.fog = true; 40855 40856 this.setValues( parameters ); 40857 40858 } 40859 40860 copy( source ) { 40861 40862 super.copy( source ); 40863 40864 this.color.copy( source.color ); 40865 40866 this.fog = source.fog; 40867 40868 return this; 40869 40870 } 40871 40872} 40873 40874class RawShaderMaterial extends ShaderMaterial { 40875 40876 constructor( parameters ) { 40877 40878 super( parameters ); 40879 40880 this.isRawShaderMaterial = true; 40881 40882 this.type = 'RawShaderMaterial'; 40883 40884 } 40885 40886} 40887 40888class MeshStandardMaterial extends Material { 40889 40890 constructor( parameters ) { 40891 40892 super(); 40893 40894 this.isMeshStandardMaterial = true; 40895 40896 this.defines = { 'STANDARD': '' }; 40897 40898 this.type = 'MeshStandardMaterial'; 40899 40900 this.color = new Color( 0xffffff ); // diffuse 40901 this.roughness = 1.0; 40902 this.metalness = 0.0; 40903 40904 this.map = null; 40905 40906 this.lightMap = null; 40907 this.lightMapIntensity = 1.0; 40908 40909 this.aoMap = null; 40910 this.aoMapIntensity = 1.0; 40911 40912 this.emissive = new Color( 0x000000 ); 40913 this.emissiveIntensity = 1.0; 40914 this.emissiveMap = null; 40915 40916 this.bumpMap = null; 40917 this.bumpScale = 1; 40918 40919 this.normalMap = null; 40920 this.normalMapType = TangentSpaceNormalMap; 40921 this.normalScale = new Vector2( 1, 1 ); 40922 40923 this.displacementMap = null; 40924 this.displacementScale = 1; 40925 this.displacementBias = 0; 40926 40927 this.roughnessMap = null; 40928 40929 this.metalnessMap = null; 40930 40931 this.alphaMap = null; 40932 40933 this.envMap = null; 40934 this.envMapRotation = new Euler(); 40935 this.envMapIntensity = 1.0; 40936 40937 this.wireframe = false; 40938 this.wireframeLinewidth = 1; 40939 this.wireframeLinecap = 'round'; 40940 this.wireframeLinejoin = 'round'; 40941 40942 this.flatShading = false; 40943 40944 this.fog = true; 40945 40946 this.setValues( parameters ); 40947 40948 } 40949 40950 copy( source ) { 40951 40952 super.copy( source ); 40953 40954 this.defines = { 'STANDARD': '' }; 40955 40956 this.color.copy( source.color ); 40957 this.roughness = source.roughness; 40958 this.metalness = source.metalness; 40959 40960 this.map = source.map; 40961 40962 this.lightMap = source.lightMap; 40963 this.lightMapIntensity = source.lightMapIntensity; 40964 40965 this.aoMap = source.aoMap; 40966 this.aoMapIntensity = source.aoMapIntensity; 40967 40968 this.emissive.copy( source.emissive ); 40969 this.emissiveMap = source.emissiveMap; 40970 this.emissiveIntensity = source.emissiveIntensity; 40971 40972 this.bumpMap = source.bumpMap; 40973 this.bumpScale = source.bumpScale; 40974 40975 this.normalMap = source.normalMap; 40976 this.normalMapType = source.normalMapType; 40977 this.normalScale.copy( source.normalScale ); 40978 40979 this.displacementMap = source.displacementMap; 40980 this.displacementScale = source.displacementScale; 40981 this.displacementBias = source.displacementBias; 40982 40983 this.roughnessMap = source.roughnessMap; 40984 40985 this.metalnessMap = source.metalnessMap; 40986 40987 this.alphaMap = source.alphaMap; 40988 40989 this.envMap = source.envMap; 40990 this.envMapRotation.copy( source.envMapRotation ); 40991 this.envMapIntensity = source.envMapIntensity; 40992 40993 this.wireframe = source.wireframe; 40994 this.wireframeLinewidth = source.wireframeLinewidth; 40995 this.wireframeLinecap = source.wireframeLinecap; 40996 this.wireframeLinejoin = source.wireframeLinejoin; 40997
vendor: 5,396 bytes, lines 40998-41293
40998 this.flatShading = source.flatShading; 40999 41000 this.fog = source.fog; 41001 41002 return this; 41003 41004 } 41005 41006} 41007 41008class MeshPhysicalMaterial extends MeshStandardMaterial { 41009 41010 constructor( parameters ) { 41011 41012 super(); 41013 41014 this.isMeshPhysicalMaterial = true; 41015 41016 this.defines = { 41017 41018 'STANDARD': '', 41019 'PHYSICAL': '' 41020 41021 }; 41022 41023 this.type = 'MeshPhysicalMaterial'; 41024 41025 this.anisotropyRotation = 0; 41026 this.anisotropyMap = null; 41027 41028 this.clearcoatMap = null; 41029 this.clearcoatRoughness = 0.0; 41030 this.clearcoatRoughnessMap = null; 41031 this.clearcoatNormalScale = new Vector2( 1, 1 ); 41032 this.clearcoatNormalMap = null; 41033 41034 this.ior = 1.5; 41035 41036 Object.defineProperty( this, 'reflectivity', { 41037 get: function () { 41038 41039 return ( clamp( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) ); 41040 41041 }, 41042 set: function ( reflectivity ) { 41043 41044 this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity ); 41045 41046 } 41047 } ); 41048 41049 this.iridescenceMap = null; 41050 this.iridescenceIOR = 1.3; 41051 this.iridescenceThicknessRange = [ 100, 400 ]; 41052 this.iridescenceThicknessMap = null; 41053 41054 this.sheenColor = new Color( 0x000000 ); 41055 this.sheenColorMap = null; 41056 this.sheenRoughness = 1.0; 41057 this.sheenRoughnessMap = null; 41058 41059 this.transmissionMap = null; 41060 41061 this.thickness = 0; 41062 this.thicknessMap = null; 41063 this.attenuationDistance = Infinity; 41064 this.attenuationColor = new Color( 1, 1, 1 ); 41065 41066 this.specularIntensity = 1.0; 41067 this.specularIntensityMap = null; 41068 this.specularColor = new Color( 1, 1, 1 ); 41069 this.specularColorMap = null; 41070 41071 this._anisotropy = 0; 41072 this._clearcoat = 0; 41073 this._dispersion = 0; 41074 this._iridescence = 0; 41075 this._sheen = 0.0; 41076 this._transmission = 0; 41077 41078 this.setValues( parameters ); 41079 41080 } 41081 41082 get anisotropy() { 41083 41084 return this._anisotropy; 41085 41086 } 41087 41088 set anisotropy( value ) { 41089 41090 if ( this._anisotropy > 0 !== value > 0 ) { 41091 41092 this.version ++; 41093 41094 } 41095 41096 this._anisotropy = value; 41097 41098 } 41099 41100 get clearcoat() { 41101 41102 return this._clearcoat; 41103 41104 } 41105 41106 set clearcoat( value ) { 41107 41108 if ( this._clearcoat > 0 !== value > 0 ) { 41109 41110 this.version ++; 41111 41112 } 41113 41114 this._clearcoat = value; 41115 41116 } 41117 41118 get iridescence() { 41119 41120 return this._iridescence; 41121 41122 } 41123 41124 set iridescence( value ) { 41125 41126 if ( this._iridescence > 0 !== value > 0 ) { 41127 41128 this.version ++; 41129 41130 } 41131 41132 this._iridescence = value; 41133 41134 } 41135 41136 get dispersion() { 41137 41138 return this._dispersion; 41139 41140 } 41141 41142 set dispersion( value ) { 41143 41144 if ( this._dispersion > 0 !== value > 0 ) { 41145 41146 this.version ++; 41147 41148 } 41149 41150 this._dispersion = value; 41151 41152 } 41153 41154 get sheen() { 41155 41156 return this._sheen; 41157 41158 } 41159 41160 set sheen( value ) { 41161 41162 if ( this._sheen > 0 !== value > 0 ) { 41163 41164 this.version ++; 41165 41166 } 41167 41168 this._sheen = value; 41169 41170 } 41171 41172 get transmission() { 41173 41174 return this._transmission; 41175 41176 } 41177 41178 set transmission( value ) { 41179 41180 if ( this._transmission > 0 !== value > 0 ) { 41181 41182 this.version ++; 41183 41184 } 41185 41186 this._transmission = value; 41187 41188 } 41189 41190 copy( source ) { 41191 41192 super.copy( source ); 41193 41194 this.defines = { 41195 41196 'STANDARD': '', 41197 'PHYSICAL': '' 41198 41199 }; 41200 41201 this.anisotropy = source.anisotropy; 41202 this.anisotropyRotation = source.anisotropyRotation; 41203 this.anisotropyMap = source.anisotropyMap; 41204 41205 this.clearcoat = source.clearcoat; 41206 this.clearcoatMap = source.clearcoatMap; 41207 this.clearcoatRoughness = source.clearcoatRoughness; 41208 this.clearcoatRoughnessMap = source.clearcoatRoughnessMap; 41209 this.clearcoatNormalMap = source.clearcoatNormalMap; 41210 this.clearcoatNormalScale.copy( source.clearcoatNormalScale ); 41211 41212 this.dispersion = source.dispersion; 41213 this.ior = source.ior; 41214 41215 this.iridescence = source.iridescence; 41216 this.iridescenceMap = source.iridescenceMap; 41217 this.iridescenceIOR = source.iridescenceIOR; 41218 this.iridescenceThicknessRange = [ ...source.iridescenceThicknessRange ]; 41219 this.iridescenceThicknessMap = source.iridescenceThicknessMap; 41220 41221 this.sheen = source.sheen; 41222 this.sheenColor.copy( source.sheenColor ); 41223 this.sheenColorMap = source.sheenColorMap; 41224 this.sheenRoughness = source.sheenRoughness; 41225 this.sheenRoughnessMap = source.sheenRoughnessMap; 41226 41227 this.transmission = source.transmission; 41228 this.transmissionMap = source.transmissionMap; 41229 41230 this.thickness = source.thickness; 41231 this.thicknessMap = source.thicknessMap; 41232 this.attenuationDistance = source.attenuationDistance; 41233 this.attenuationColor.copy( source.attenuationColor ); 41234 41235 this.specularIntensity = source.specularIntensity; 41236 this.specularIntensityMap = source.specularIntensityMap; 41237 this.specularColor.copy( source.specularColor ); 41238 this.specularColorMap = source.specularColorMap; 41239 41240 return this; 41241 41242 } 41243 41244} 41245 41246class MeshPhongMaterial extends Material { 41247 41248 constructor( parameters ) { 41249 41250 super(); 41251 41252 this.isMeshPhongMaterial = true; 41253 41254 this.type = 'MeshPhongMaterial'; 41255 41256 this.color = new Color( 0xffffff ); // diffuse 41257 this.specular = new Color( 0x111111 ); 41258 this.shininess = 30; 41259 41260 this.map = null; 41261 41262 this.lightMap = null; 41263 this.lightMapIntensity = 1.0; 41264 41265 this.aoMap = null; 41266 this.aoMapIntensity = 1.0; 41267 41268 this.emissive = new Color( 0x000000 ); 41269 this.emissiveIntensity = 1.0; 41270 this.emissiveMap = null; 41271 41272 this.bumpMap = null; 41273 this.bumpScale = 1; 41274 41275 this.normalMap = null; 41276 this.normalMapType = TangentSpaceNormalMap; 41277 this.normalScale = new Vector2( 1, 1 ); 41278 41279 this.displacementMap = null; 41280 this.displacementScale = 1; 41281 this.displacementBias = 0; 41282 41283 this.specularMap = null; 41284 41285 this.alphaMap = null; 41286 41287 this.envMap = null; 41288 this.envMapRotation = new Euler(); 41289 this.combine = MultiplyOperation; 41290 this.reflectivity = 1; 41291 this.refractionRatio = 0.98; 41292 41293 this.wireframe = false;
41294 this.wireframeLinewidth = 1; 41295 this.wireframeLinecap = 'round'; 41296 this.wireframeLinejoin = 'round'; 41297 41298 this.flatShading = false; 41299 41300 this.fog = true; 41301 41302 this.setValues( parameters ); 41303 41304 } 41305 41306 copy( source ) { 41307 41308 super.copy( source ); 41309 41310 this.color.copy( source.color ); 41311 this.specular.copy( source.specular ); 41312 this.shininess = source.shininess; 41313 41314 this.map = source.map; 41315 41316 this.lightMap = source.lightMap; 41317 this.lightMapIntensity = source.lightMapIntensity; 41318 41319 this.aoMap = source.aoMap; 41320 this.aoMapIntensity = source.aoMapIntensity; 41321 41322 this.emissive.copy( source.emissive ); 41323 this.emissiveMap = source.emissiveMap; 41324 this.emissiveIntensity = source.emissiveIntensity; 41325 41326 this.bumpMap = source.bumpMap; 41327 this.bumpScale = source.bumpScale; 41328 41329 this.normalMap = source.normalMap; 41330 this.normalMapType = source.normalMapType; 41331 this.normalScale.copy( source.normalScale ); 41332 41333 this.displacementMap = source.displacementMap; 41334 this.displacementScale = source.displacementScale; 41335 this.displacementBias = source.displacementBias; 41336 41337 this.specularMap = source.specularMap; 41338 41339 this.alphaMap = source.alphaMap; 41340 41341 this.envMap = source.envMap; 41342 this.envMapRotation.copy( source.envMapRotation ); 41343 this.combine = source.combine; 41344 this.reflectivity = source.reflectivity; 41345 this.refractionRatio = source.refractionRatio; 41346 41347 this.wireframe = source.wireframe; 41348 this.wireframeLinewidth = source.wireframeLinewidth; 41349 this.wireframeLinecap = source.wireframeLinecap; 41350 this.wireframeLinejoin = source.wireframeLinejoin; 41351 41352 this.flatShading = source.flatShading; 41353 41354 this.fog = source.fog; 41355 41356 return this; 41357 41358 } 41359 41360} 41361 41362class MeshToonMaterial extends Material { 41363 41364 constructor( parameters ) { 41365 41366 super(); 41367 41368 this.isMeshToonMaterial = true; 41369 41370 this.defines = { 'TOON': '' }; 41371 41372 this.type = 'MeshToonMaterial'; 41373 41374 this.color = new Color( 0xffffff ); 41375 41376 this.map = null; 41377 this.gradientMap = null; 41378 41379 this.lightMap = null; 41380 this.lightMapIntensity = 1.0; 41381 41382 this.aoMap = null; 41383 this.aoMapIntensity = 1.0; 41384 41385 this.emissive = new Color( 0x000000 ); 41386 this.emissiveIntensity = 1.0; 41387 this.emissiveMap = null; 41388 41389 this.bumpMap = null; 41390 this.bumpScale = 1; 41391 41392 this.normalMap = null; 41393 this.normalMapType = TangentSpaceNormalMap; 41394 this.normalScale = new Vector2( 1, 1 ); 41395 41396 this.displacementMap = null; 41397 this.displacementScale = 1; 41398 this.displacementBias = 0; 41399 41400 this.alphaMap = null; 41401 41402 this.wireframe = false; 41403 this.wireframeLinewidth = 1; 41404 this.wireframeLinecap = 'round'; 41405 this.wireframeLinejoin = 'round'; 41406 41407 this.fog = true; 41408 41409 this.setValues( parameters ); 41410 41411 } 41412 41413 copy( source ) { 41414 41415 super.copy( source ); 41416 41417 this.color.copy( source.color ); 41418 41419 this.map = source.map; 41420 this.gradientMap = source.gradientMap; 41421 41422 this.lightMap = source.lightMap; 41423 this.lightMapIntensity = source.lightMapIntensity; 41424 41425 this.aoMap = source.aoMap; 41426 this.aoMapIntensity = source.aoMapIntensity; 41427 41428 this.emissive.copy( source.emissive ); 41429 this.emissiveMap = source.emissiveMap; 41430 this.emissiveIntensity = source.emissiveIntensity; 41431 41432 this.bumpMap = source.bumpMap; 41433 this.bumpScale = source.bumpScale; 41434 41435 this.normalMap = source.normalMap; 41436 this.normalMapType = source.normalMapType; 41437 this.normalScale.copy( source.normalScale ); 41438 41439 this.displacementMap = source.displacementMap; 41440 this.displacementScale = source.displacementScale; 41441 this.displacementBias = source.displacementBias; 41442 41443 this.alphaMap = source.alphaMap; 41444 41445 this.wireframe = source.wireframe; 41446 this.wireframeLinewidth = source.wireframeLinewidth; 41447 this.wireframeLinecap = source.wireframeLinecap; 41448 this.wireframeLinejoin = source.wireframeLinejoin; 41449 41450 this.fog = source.fog; 41451 41452 return this; 41453 41454 } 41455 41456} 41457 41458class MeshNormalMaterial extends Material { 41459 41460 constructor( parameters ) { 41461 41462 super(); 41463 41464 this.isMeshNormalMaterial = true; 41465 41466 this.type = 'MeshNormalMaterial'; 41467 41468 this.bumpMap = null; 41469 this.bumpScale = 1; 41470 41471 this.normalMap = null; 41472 this.normalMapType = TangentSpaceNormalMap; 41473 this.normalScale = new Vector2( 1, 1 ); 41474 41475 this.displacementMap = null; 41476 this.displacementScale = 1; 41477 this.displacementBias = 0; 41478 41479 this.wireframe = false; 41480 this.wireframeLinewidth = 1; 41481 41482 this.flatShading = false;
vendor: 20,656 bytes, lines 41483-42523
41483 41484 this.setValues( parameters ); 41485 41486 } 41487 41488 copy( source ) { 41489 41490 super.copy( source ); 41491 41492 this.bumpMap = source.bumpMap; 41493 this.bumpScale = source.bumpScale; 41494 41495 this.normalMap = source.normalMap; 41496 this.normalMapType = source.normalMapType; 41497 this.normalScale.copy( source.normalScale ); 41498 41499 this.displacementMap = source.displacementMap; 41500 this.displacementScale = source.displacementScale; 41501 this.displacementBias = source.displacementBias; 41502 41503 this.wireframe = source.wireframe; 41504 this.wireframeLinewidth = source.wireframeLinewidth; 41505 41506 this.flatShading = source.flatShading; 41507 41508 return this; 41509 41510 } 41511 41512} 41513 41514class MeshLambertMaterial extends Material { 41515 41516 constructor( parameters ) { 41517 41518 super(); 41519 41520 this.isMeshLambertMaterial = true; 41521 41522 this.type = 'MeshLambertMaterial'; 41523 41524 this.color = new Color( 0xffffff ); // diffuse 41525 41526 this.map = null; 41527 41528 this.lightMap = null; 41529 this.lightMapIntensity = 1.0; 41530 41531 this.aoMap = null; 41532 this.aoMapIntensity = 1.0; 41533 41534 this.emissive = new Color( 0x000000 ); 41535 this.emissiveIntensity = 1.0; 41536 this.emissiveMap = null; 41537 41538 this.bumpMap = null; 41539 this.bumpScale = 1; 41540 41541 this.normalMap = null; 41542 this.normalMapType = TangentSpaceNormalMap; 41543 this.normalScale = new Vector2( 1, 1 ); 41544 41545 this.displacementMap = null; 41546 this.displacementScale = 1; 41547 this.displacementBias = 0; 41548 41549 this.specularMap = null; 41550 41551 this.alphaMap = null; 41552 41553 this.envMap = null; 41554 this.envMapRotation = new Euler(); 41555 this.combine = MultiplyOperation; 41556 this.reflectivity = 1; 41557 this.refractionRatio = 0.98; 41558 41559 this.wireframe = false; 41560 this.wireframeLinewidth = 1; 41561 this.wireframeLinecap = 'round'; 41562 this.wireframeLinejoin = 'round'; 41563 41564 this.flatShading = false; 41565 41566 this.fog = true; 41567 41568 this.setValues( parameters ); 41569 41570 } 41571 41572 copy( source ) { 41573 41574 super.copy( source ); 41575 41576 this.color.copy( source.color ); 41577 41578 this.map = source.map; 41579 41580 this.lightMap = source.lightMap; 41581 this.lightMapIntensity = source.lightMapIntensity; 41582 41583 this.aoMap = source.aoMap; 41584 this.aoMapIntensity = source.aoMapIntensity; 41585 41586 this.emissive.copy( source.emissive ); 41587 this.emissiveMap = source.emissiveMap; 41588 this.emissiveIntensity = source.emissiveIntensity; 41589 41590 this.bumpMap = source.bumpMap; 41591 this.bumpScale = source.bumpScale; 41592 41593 this.normalMap = source.normalMap; 41594 this.normalMapType = source.normalMapType; 41595 this.normalScale.copy( source.normalScale ); 41596 41597 this.displacementMap = source.displacementMap; 41598 this.displacementScale = source.displacementScale; 41599 this.displacementBias = source.displacementBias; 41600 41601 this.specularMap = source.specularMap; 41602 41603 this.alphaMap = source.alphaMap; 41604 41605 this.envMap = source.envMap; 41606 this.envMapRotation.copy( source.envMapRotation ); 41607 this.combine = source.combine; 41608 this.reflectivity = source.reflectivity; 41609 this.refractionRatio = source.refractionRatio; 41610 41611 this.wireframe = source.wireframe; 41612 this.wireframeLinewidth = source.wireframeLinewidth; 41613 this.wireframeLinecap = source.wireframeLinecap; 41614 this.wireframeLinejoin = source.wireframeLinejoin; 41615 41616 this.flatShading = source.flatShading; 41617 41618 this.fog = source.fog; 41619 41620 return this; 41621 41622 } 41623 41624} 41625 41626class MeshMatcapMaterial extends Material { 41627 41628 constructor( parameters ) { 41629 41630 super(); 41631 41632 this.isMeshMatcapMaterial = true; 41633 41634 this.defines = { 'MATCAP': '' }; 41635 41636 this.type = 'MeshMatcapMaterial'; 41637 41638 this.color = new Color( 0xffffff ); // diffuse 41639 41640 this.matcap = null; 41641 41642 this.map = null; 41643 41644 this.bumpMap = null; 41645 this.bumpScale = 1; 41646 41647 this.normalMap = null; 41648 this.normalMapType = TangentSpaceNormalMap; 41649 this.normalScale = new Vector2( 1, 1 ); 41650 41651 this.displacementMap = null; 41652 this.displacementScale = 1; 41653 this.displacementBias = 0; 41654 41655 this.alphaMap = null; 41656 41657 this.flatShading = false; 41658 41659 this.fog = true; 41660 41661 this.setValues( parameters ); 41662 41663 } 41664 41665 41666 copy( source ) { 41667 41668 super.copy( source ); 41669 41670 this.defines = { 'MATCAP': '' }; 41671 41672 this.color.copy( source.color ); 41673 41674 this.matcap = source.matcap; 41675 41676 this.map = source.map; 41677 41678 this.bumpMap = source.bumpMap; 41679 this.bumpScale = source.bumpScale; 41680 41681 this.normalMap = source.normalMap; 41682 this.normalMapType = source.normalMapType; 41683 this.normalScale.copy( source.normalScale ); 41684 41685 this.displacementMap = source.displacementMap; 41686 this.displacementScale = source.displacementScale; 41687 this.displacementBias = source.displacementBias; 41688 41689 this.alphaMap = source.alphaMap; 41690 41691 this.flatShading = source.flatShading; 41692 41693 this.fog = source.fog; 41694 41695 return this; 41696 41697 } 41698 41699} 41700 41701class LineDashedMaterial extends LineBasicMaterial { 41702 41703 constructor( parameters ) { 41704 41705 super(); 41706 41707 this.isLineDashedMaterial = true; 41708 41709 this.type = 'LineDashedMaterial'; 41710 41711 this.scale = 1; 41712 this.dashSize = 3; 41713 this.gapSize = 1; 41714 41715 this.setValues( parameters ); 41716 41717 } 41718 41719 copy( source ) { 41720 41721 super.copy( source ); 41722 41723 this.scale = source.scale; 41724 this.dashSize = source.dashSize; 41725 this.gapSize = source.gapSize; 41726 41727 return this; 41728 41729 } 41730 41731} 41732 41733// converts an array to a specific type 41734function convertArray( array, type, forceClone ) { 41735 41736 if ( ! array || // let 'undefined' and 'null' pass 41737 ! forceClone && array.constructor === type ) return array; 41738 41739 if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { 41740 41741 return new type( array ); // create typed array 41742 41743 } 41744 41745 return Array.prototype.slice.call( array ); // create Array 41746 41747} 41748 41749function isTypedArray( object ) { 41750 41751 return ArrayBuffer.isView( object ) && 41752 ! ( object instanceof DataView ); 41753 41754} 41755 41756// returns an array by which times and values can be sorted 41757function getKeyframeOrder( times ) { 41758 41759 function compareTime( i, j ) { 41760 41761 return times[ i ] - times[ j ]; 41762 41763 } 41764 41765 const n = times.length; 41766 const result = new Array( n ); 41767 for ( let i = 0; i !== n; ++ i ) result[ i ] = i; 41768 41769 result.sort( compareTime ); 41770 41771 return result; 41772 41773} 41774 41775// uses the array previously returned by 'getKeyframeOrder' to sort data 41776function sortedArray( values, stride, order ) { 41777 41778 const nValues = values.length; 41779 const result = new values.constructor( nValues ); 41780 41781 for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { 41782 41783 const srcOffset = order[ i ] * stride; 41784 41785 for ( let j = 0; j !== stride; ++ j ) { 41786 41787 result[ dstOffset ++ ] = values[ srcOffset + j ]; 41788 41789 } 41790 41791 } 41792 41793 return result; 41794 41795} 41796 41797// function for parsing AOS keyframe formats 41798function flattenJSON( jsonKeys, times, values, valuePropertyName ) { 41799 41800 let i = 1, key = jsonKeys[ 0 ]; 41801 41802 while ( key !== undefined && key[ valuePropertyName ] === undefined ) { 41803 41804 key = jsonKeys[ i ++ ]; 41805 41806 } 41807 41808 if ( key === undefined ) return; // no data 41809 41810 let value = key[ valuePropertyName ]; 41811 if ( value === undefined ) return; // no data 41812 41813 if ( Array.isArray( value ) ) { 41814 41815 do { 41816 41817 value = key[ valuePropertyName ]; 41818 41819 if ( value !== undefined ) { 41820 41821 times.push( key.time ); 41822 values.push.apply( values, value ); // push all elements 41823 41824 } 41825 41826 key = jsonKeys[ i ++ ]; 41827 41828 } while ( key !== undefined ); 41829 41830 } else if ( value.toArray !== undefined ) { 41831 41832 // ...assume THREE.Math-ish 41833 41834 do { 41835 41836 value = key[ valuePropertyName ]; 41837 41838 if ( value !== undefined ) { 41839 41840 times.push( key.time ); 41841 value.toArray( values, values.length ); 41842 41843 } 41844 41845 key = jsonKeys[ i ++ ]; 41846 41847 } while ( key !== undefined ); 41848 41849 } else { 41850 41851 // otherwise push as-is 41852 41853 do { 41854 41855 value = key[ valuePropertyName ]; 41856 41857 if ( value !== undefined ) { 41858 41859 times.push( key.time ); 41860 values.push( value ); 41861 41862 } 41863 41864 key = jsonKeys[ i ++ ]; 41865 41866 } while ( key !== undefined ); 41867 41868 } 41869 41870} 41871 41872function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) { 41873 41874 const clip = sourceClip.clone(); 41875 41876 clip.name = name; 41877 41878 const tracks = []; 41879 41880 for ( let i = 0; i < clip.tracks.length; ++ i ) { 41881 41882 const track = clip.tracks[ i ]; 41883 const valueSize = track.getValueSize(); 41884 41885 const times = []; 41886 const values = []; 41887 41888 for ( let j = 0; j < track.times.length; ++ j ) { 41889 41890 const frame = track.times[ j ] * fps; 41891 41892 if ( frame < startFrame || frame >= endFrame ) continue; 41893 41894 times.push( track.times[ j ] ); 41895 41896 for ( let k = 0; k < valueSize; ++ k ) { 41897 41898 values.push( track.values[ j * valueSize + k ] ); 41899 41900 } 41901 41902 } 41903 41904 if ( times.length === 0 ) continue; 41905 41906 track.times = convertArray( times, track.times.constructor ); 41907 track.values = convertArray( values, track.values.constructor ); 41908 41909 tracks.push( track ); 41910 41911 } 41912 41913 clip.tracks = tracks; 41914 41915 // find minimum .times value across all tracks in the trimmed clip 41916 41917 let minStartTime = Infinity; 41918 41919 for ( let i = 0; i < clip.tracks.length; ++ i ) { 41920 41921 if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) { 41922 41923 minStartTime = clip.tracks[ i ].times[ 0 ]; 41924 41925 } 41926 41927 } 41928 41929 // shift all tracks such that clip begins at t=0 41930 41931 for ( let i = 0; i < clip.tracks.length; ++ i ) { 41932 41933 clip.tracks[ i ].shift( - 1 * minStartTime ); 41934 41935 } 41936 41937 clip.resetDuration(); 41938 41939 return clip; 41940 41941} 41942 41943function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) { 41944 41945 if ( fps <= 0 ) fps = 30; 41946 41947 const numTracks = referenceClip.tracks.length; 41948 const referenceTime = referenceFrame / fps; 41949 41950 // Make each track's values relative to the values at the reference frame 41951 for ( let i = 0; i < numTracks; ++ i ) { 41952 41953 const referenceTrack = referenceClip.tracks[ i ]; 41954 const referenceTrackType = referenceTrack.ValueTypeName; 41955 41956 // Skip this track if it's non-numeric 41957 if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue; 41958 41959 // Find the track in the target clip whose name and type matches the reference track 41960 const targetTrack = targetClip.tracks.find( function ( track ) { 41961 41962 return track.name === referenceTrack.name 41963 && track.ValueTypeName === referenceTrackType; 41964 41965 } ); 41966 41967 if ( targetTrack === undefined ) continue; 41968 41969 let referenceOffset = 0; 41970 const referenceValueSize = referenceTrack.getValueSize(); 41971 41972 if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { 41973 41974 referenceOffset = referenceValueSize / 3; 41975 41976 } 41977 41978 let targetOffset = 0; 41979 const targetValueSize = targetTrack.getValueSize(); 41980 41981 if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { 41982 41983 targetOffset = targetValueSize / 3; 41984 41985 } 41986 41987 const lastIndex = referenceTrack.times.length - 1; 41988 let referenceValue; 41989 41990 // Find the value to subtract out of the track 41991 if ( referenceTime <= referenceTrack.times[ 0 ] ) { 41992 41993 // Reference frame is earlier than the first keyframe, so just use the first keyframe 41994 const startIndex = referenceOffset; 41995 const endIndex = referenceValueSize - referenceOffset; 41996 referenceValue = referenceTrack.values.slice( startIndex, endIndex ); 41997 41998 } else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) { 41999 42000 // Reference frame is after the last keyframe, so just use the last keyframe 42001 const startIndex = lastIndex * referenceValueSize + referenceOffset; 42002 const endIndex = startIndex + referenceValueSize - referenceOffset; 42003 referenceValue = referenceTrack.values.slice( startIndex, endIndex ); 42004 42005 } else { 42006 42007 // Interpolate to the reference value 42008 const interpolant = referenceTrack.createInterpolant(); 42009 const startIndex = referenceOffset; 42010 const endIndex = referenceValueSize - referenceOffset; 42011 interpolant.evaluate( referenceTime ); 42012 referenceValue = interpolant.resultBuffer.slice( startIndex, endIndex ); 42013 42014 } 42015 42016 // Conjugate the quaternion 42017 if ( referenceTrackType === 'quaternion' ) { 42018 42019 const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate(); 42020 referenceQuat.toArray( referenceValue ); 42021 42022 } 42023 42024 // Subtract the reference value from all of the track values 42025 42026 const numTimes = targetTrack.times.length; 42027 for ( let j = 0; j < numTimes; ++ j ) { 42028 42029 const valueStart = j * targetValueSize + targetOffset; 42030 42031 if ( referenceTrackType === 'quaternion' ) { 42032 42033 // Multiply the conjugate for quaternion track types 42034 Quaternion.multiplyQuaternionsFlat( 42035 targetTrack.values, 42036 valueStart, 42037 referenceValue, 42038 0, 42039 targetTrack.values, 42040 valueStart 42041 ); 42042 42043 } else { 42044 42045 const valueEnd = targetValueSize - targetOffset * 2; 42046 42047 // Subtract each value for all other numeric track types 42048 for ( let k = 0; k < valueEnd; ++ k ) { 42049 42050 targetTrack.values[ valueStart + k ] -= referenceValue[ k ]; 42051 42052 } 42053 42054 } 42055 42056 } 42057 42058 } 42059 42060 targetClip.blendMode = AdditiveAnimationBlendMode; 42061 42062 return targetClip; 42063 42064} 42065 42066const AnimationUtils = { 42067 convertArray: convertArray, 42068 isTypedArray: isTypedArray, 42069 getKeyframeOrder: getKeyframeOrder, 42070 sortedArray: sortedArray, 42071 flattenJSON: flattenJSON, 42072 subclip: subclip, 42073 makeClipAdditive: makeClipAdditive 42074}; 42075 42076/** 42077 * Abstract base class of interpolants over parametric samples. 42078 * 42079 * The parameter domain is one dimensional, typically the time or a path 42080 * along a curve defined by the data. 42081 * 42082 * The sample values can have any dimensionality and derived classes may 42083 * apply special interpretations to the data. 42084 * 42085 * This class provides the interval seek in a Template Method, deferring 42086 * the actual interpolation to derived classes. 42087 * 42088 * Time complexity is O(1) for linear access crossing at most two points 42089 * and O(log N) for random access, where N is the number of positions. 42090 * 42091 * References: 42092 * 42093 * http://www.oodesign.com/template-method-pattern.html 42094 * 42095 */ 42096 42097class Interpolant { 42098 42099 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 42100 42101 this.parameterPositions = parameterPositions; 42102 this._cachedIndex = 0; 42103 42104 this.resultBuffer = resultBuffer !== undefined ? 42105 resultBuffer : new sampleValues.constructor( sampleSize ); 42106 this.sampleValues = sampleValues; 42107 this.valueSize = sampleSize; 42108 42109 this.settings = null; 42110 this.DefaultSettings_ = {}; 42111 42112 } 42113 42114 evaluate( t ) { 42115 42116 const pp = this.parameterPositions; 42117 let i1 = this._cachedIndex, 42118 t1 = pp[ i1 ], 42119 t0 = pp[ i1 - 1 ]; 42120 42121 validate_interval: { 42122 42123 seek: { 42124 42125 let right; 42126 42127 linear_scan: { 42128 42129 //- See http://jsperf.com/comparison-to-undefined/3 42130 //- slower code: 42131 //- 42132 //- if ( t >= t1 || t1 === undefined ) { 42133 forward_scan: if ( ! ( t < t1 ) ) { 42134 42135 for ( let giveUpAt = i1 + 2; ; ) { 42136 42137 if ( t1 === undefined ) { 42138 42139 if ( t < t0 ) break forward_scan; 42140 42141 // after end 42142 42143 i1 = pp.length; 42144 this._cachedIndex = i1; 42145 return this.copySampleValue_( i1 - 1 ); 42146 42147 } 42148 42149 if ( i1 === giveUpAt ) break; // this loop 42150 42151 t0 = t1; 42152 t1 = pp[ ++ i1 ]; 42153 42154 if ( t < t1 ) { 42155 42156 // we have arrived at the sought interval 42157 break seek; 42158 42159 } 42160 42161 } 42162 42163 // prepare binary search on the right side of the index 42164 right = pp.length; 42165 break linear_scan; 42166 42167 } 42168 42169 //- slower code: 42170 //- if ( t < t0 || t0 === undefined ) { 42171 if ( ! ( t >= t0 ) ) { 42172 42173 // looping? 42174 42175 const t1global = pp[ 1 ]; 42176 42177 if ( t < t1global ) { 42178 42179 i1 = 2; // + 1, using the scan for the details 42180 t0 = t1global; 42181 42182 } 42183 42184 // linear reverse scan 42185 42186 for ( let giveUpAt = i1 - 2; ; ) { 42187 42188 if ( t0 === undefined ) { 42189 42190 // before start 42191 42192 this._cachedIndex = 0; 42193 return this.copySampleValue_( 0 ); 42194 42195 } 42196 42197 if ( i1 === giveUpAt ) break; // this loop 42198 42199 t1 = t0; 42200 t0 = pp[ -- i1 - 1 ]; 42201 42202 if ( t >= t0 ) { 42203 42204 // we have arrived at the sought interval 42205 break seek; 42206 42207 } 42208 42209 } 42210 42211 // prepare binary search on the left side of the index 42212 right = i1; 42213 i1 = 0; 42214 break linear_scan; 42215 42216 } 42217 42218 // the interval is valid 42219 42220 break validate_interval; 42221 42222 } // linear scan 42223 42224 // binary search 42225 42226 while ( i1 < right ) { 42227 42228 const mid = ( i1 + right ) >>> 1; 42229 42230 if ( t < pp[ mid ] ) { 42231 42232 right = mid; 42233 42234 } else { 42235 42236 i1 = mid + 1; 42237 42238 } 42239 42240 } 42241 42242 t1 = pp[ i1 ]; 42243 t0 = pp[ i1 - 1 ]; 42244 42245 // check boundary cases, again 42246 42247 if ( t0 === undefined ) { 42248 42249 this._cachedIndex = 0; 42250 return this.copySampleValue_( 0 ); 42251 42252 } 42253 42254 if ( t1 === undefined ) { 42255 42256 i1 = pp.length; 42257 this._cachedIndex = i1; 42258 return this.copySampleValue_( i1 - 1 ); 42259 42260 } 42261 42262 } // seek 42263 42264 this._cachedIndex = i1; 42265 42266 this.intervalChanged_( i1, t0, t1 ); 42267 42268 } // validate_interval 42269 42270 return this.interpolate_( i1, t0, t, t1 ); 42271 42272 } 42273 42274 getSettings_() { 42275 42276 return this.settings || this.DefaultSettings_; 42277 42278 } 42279 42280 copySampleValue_( index ) { 42281 42282 // copies a sample value to the result buffer 42283 42284 const result = this.resultBuffer, 42285 values = this.sampleValues, 42286 stride = this.valueSize, 42287 offset = index * stride; 42288 42289 for ( let i = 0; i !== stride; ++ i ) { 42290 42291 result[ i ] = values[ offset + i ]; 42292 42293 } 42294 42295 return result; 42296 42297 } 42298 42299 // Template methods for derived classes: 42300 42301 interpolate_( /* i1, t0, t, t1 */ ) { 42302 42303 throw new Error( 'call to abstract method' ); 42304 // implementations shall return this.resultBuffer 42305 42306 } 42307 42308 intervalChanged_( /* i1, t0, t1 */ ) { 42309 42310 // empty 42311 42312 } 42313 42314} 42315 42316/** 42317 * Fast and simple cubic spline interpolant. 42318 * 42319 * It was derived from a Hermitian construction setting the first derivative 42320 * at each sample position to the linear slope between neighboring positions 42321 * over their parameter interval. 42322 */ 42323 42324class CubicInterpolant extends Interpolant { 42325 42326 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 42327 42328 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 42329 42330 this._weightPrev = - 0; 42331 this._offsetPrev = - 0; 42332 this._weightNext = - 0; 42333 this._offsetNext = - 0; 42334 42335 this.DefaultSettings_ = { 42336 42337 endingStart: ZeroCurvatureEnding, 42338 endingEnd: ZeroCurvatureEnding 42339 42340 }; 42341 42342 } 42343 42344 intervalChanged_( i1, t0, t1 ) { 42345 42346 const pp = this.parameterPositions; 42347 let iPrev = i1 - 2, 42348 iNext = i1 + 1, 42349 42350 tPrev = pp[ iPrev ], 42351 tNext = pp[ iNext ]; 42352 42353 if ( tPrev === undefined ) { 42354 42355 switch ( this.getSettings_().endingStart ) { 42356 42357 case ZeroSlopeEnding: 42358 42359 // f'(t0) = 0 42360 iPrev = i1; 42361 tPrev = 2 * t0 - t1; 42362 42363 break; 42364 42365 case WrapAroundEnding: 42366 42367 // use the other end of the curve 42368 iPrev = pp.length - 2; 42369 tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; 42370 42371 break; 42372 42373 default: // ZeroCurvatureEnding 42374 42375 // f''(t0) = 0 a.k.a. Natural Spline 42376 iPrev = i1; 42377 tPrev = t1; 42378 42379 } 42380 42381 } 42382 42383 if ( tNext === undefined ) { 42384 42385 switch ( this.getSettings_().endingEnd ) { 42386 42387 case ZeroSlopeEnding: 42388 42389 // f'(tN) = 0 42390 iNext = i1; 42391 tNext = 2 * t1 - t0; 42392 42393 break; 42394 42395 case WrapAroundEnding: 42396 42397 // use the other end of the curve 42398 iNext = 1; 42399 tNext = t1 + pp[ 1 ] - pp[ 0 ]; 42400 42401 break; 42402 42403 default: // ZeroCurvatureEnding 42404 42405 // f''(tN) = 0, a.k.a. Natural Spline 42406 iNext = i1 - 1; 42407 tNext = t0; 42408 42409 } 42410 42411 } 42412 42413 const halfDt = ( t1 - t0 ) * 0.5, 42414 stride = this.valueSize; 42415 42416 this._weightPrev = halfDt / ( t0 - tPrev ); 42417 this._weightNext = halfDt / ( tNext - t1 ); 42418 this._offsetPrev = iPrev * stride; 42419 this._offsetNext = iNext * stride; 42420 42421 } 42422 42423 interpolate_( i1, t0, t, t1 ) { 42424 42425 const result = this.resultBuffer, 42426 values = this.sampleValues, 42427 stride = this.valueSize, 42428 42429 o1 = i1 * stride, o0 = o1 - stride, 42430 oP = this._offsetPrev, oN = this._offsetNext, 42431 wP = this._weightPrev, wN = this._weightNext, 42432 42433 p = ( t - t0 ) / ( t1 - t0 ), 42434 pp = p * p, 42435 ppp = pp * p; 42436 42437 // evaluate polynomials 42438 42439 const sP = - wP * ppp + 2 * wP * pp - wP * p; 42440 const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1; 42441 const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p; 42442 const sN = wN * ppp - wN * pp; 42443 42444 // combine data linearly 42445 42446 for ( let i = 0; i !== stride; ++ i ) { 42447 42448 result[ i ] = 42449 sP * values[ oP + i ] + 42450 s0 * values[ o0 + i ] + 42451 s1 * values[ o1 + i ] + 42452 sN * values[ oN + i ]; 42453 42454 } 42455 42456 return result; 42457 42458 } 42459 42460} 42461 42462class LinearInterpolant extends Interpolant { 42463 42464 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 42465 42466 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 42467 42468 } 42469 42470 interpolate_( i1, t0, t, t1 ) { 42471 42472 const result = this.resultBuffer, 42473 values = this.sampleValues, 42474 stride = this.valueSize, 42475 42476 offset1 = i1 * stride, 42477 offset0 = offset1 - stride, 42478 42479 weight1 = ( t - t0 ) / ( t1 - t0 ), 42480 weight0 = 1 - weight1; 42481 42482 for ( let i = 0; i !== stride; ++ i ) { 42483 42484 result[ i ] = 42485 values[ offset0 + i ] * weight0 + 42486 values[ offset1 + i ] * weight1; 42487 42488 } 42489 42490 return result; 42491 42492 } 42493 42494} 42495 42496/** 42497 * 42498 * Interpolant that evaluates to the sample value at the position preceding 42499 * the parameter. 42500 */ 42501 42502class DiscreteInterpolant extends Interpolant { 42503 42504 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 42505 42506 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 42507 42508 } 42509 42510 interpolate_( i1 /*, t0, t, t1 */ ) { 42511 42512 return this.copySampleValue_( i1 - 1 ); 42513 42514 } 42515 42516} 42517 42518class KeyframeTrack { 42519 42520 constructor( name, times, values, interpolation ) { 42521 42522 if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); 42523 if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + n
vendor: 22,519 bytes, lines 42523-43731
42523ame ); 42524 42525 this.name = name; 42526 42527 this.times = convertArray( times, this.TimeBufferType ); 42528 this.values = convertArray( values, this.ValueBufferType ); 42529 42530 this.setInterpolation( interpolation || this.DefaultInterpolation ); 42531 42532 } 42533 42534 // Serialization (in static context, because of constructor invocation 42535 // and automatic invocation of .toJSON): 42536 42537 static toJSON( track ) { 42538 42539 const trackType = track.constructor; 42540 42541 let json; 42542 42543 // derived classes can define a static toJSON method 42544 if ( trackType.toJSON !== this.toJSON ) { 42545 42546 json = trackType.toJSON( track ); 42547 42548 } else { 42549 42550 // by default, we assume the data can be serialized as-is 42551 json = { 42552 42553 'name': track.name, 42554 'times': convertArray( track.times, Array ), 42555 'values': convertArray( track.values, Array ) 42556 42557 }; 42558 42559 const interpolation = track.getInterpolation(); 42560 42561 if ( interpolation !== track.DefaultInterpolation ) { 42562 42563 json.interpolation = interpolation; 42564 42565 } 42566 42567 } 42568 42569 json.type = track.ValueTypeName; // mandatory 42570 42571 return json; 42572 42573 } 42574 42575 InterpolantFactoryMethodDiscrete( result ) { 42576 42577 return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); 42578 42579 } 42580 42581 InterpolantFactoryMethodLinear( result ) { 42582 42583 return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); 42584 42585 } 42586 42587 InterpolantFactoryMethodSmooth( result ) { 42588 42589 return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); 42590 42591 } 42592 42593 setInterpolation( interpolation ) { 42594 42595 let factoryMethod; 42596 42597 switch ( interpolation ) { 42598 42599 case InterpolateDiscrete: 42600 42601 factoryMethod = this.InterpolantFactoryMethodDiscrete; 42602 42603 break; 42604 42605 case InterpolateLinear: 42606 42607 factoryMethod = this.InterpolantFactoryMethodLinear; 42608 42609 break; 42610 42611 case InterpolateSmooth: 42612 42613 factoryMethod = this.InterpolantFactoryMethodSmooth; 42614 42615 break; 42616 42617 } 42618 42619 if ( factoryMethod === undefined ) { 42620 42621 const message = 'unsupported interpolation for ' + 42622 this.ValueTypeName + ' keyframe track named ' + this.name; 42623 42624 if ( this.createInterpolant === undefined ) { 42625 42626 // fall back to default, unless the default itself is messed up 42627 if ( interpolation !== this.DefaultInterpolation ) { 42628 42629 this.setInterpolation( this.DefaultInterpolation ); 42630 42631 } else { 42632 42633 throw new Error( message ); // fatal, in this case 42634 42635 } 42636 42637 } 42638 42639 console.warn( 'THREE.KeyframeTrack:', message ); 42640 return this; 42641 42642 } 42643 42644 this.createInterpolant = factoryMethod; 42645 42646 return this; 42647 42648 } 42649 42650 getInterpolation() { 42651 42652 switch ( this.createInterpolant ) { 42653 42654 case this.InterpolantFactoryMethodDiscrete: 42655 42656 return InterpolateDiscrete; 42657 42658 case this.InterpolantFactoryMethodLinear: 42659 42660 return InterpolateLinear; 42661 42662 case this.InterpolantFactoryMethodSmooth: 42663 42664 return InterpolateSmooth; 42665 42666 } 42667 42668 } 42669 42670 getValueSize() { 42671 42672 return this.values.length / this.times.length; 42673 42674 } 42675 42676 // move all keyframes either forwards or backwards in time 42677 shift( timeOffset ) { 42678 42679 if ( timeOffset !== 0.0 ) { 42680 42681 const times = this.times; 42682 42683 for ( let i = 0, n = times.length; i !== n; ++ i ) { 42684 42685 times[ i ] += timeOffset; 42686 42687 } 42688 42689 } 42690 42691 return this; 42692 42693 } 42694 42695 // scale all keyframe times by a factor (useful for frame <-> seconds conversions) 42696 scale( timeScale ) { 42697 42698 if ( timeScale !== 1.0 ) { 42699 42700 const times = this.times; 42701 42702 for ( let i = 0, n = times.length; i !== n; ++ i ) { 42703 42704 times[ i ] *= timeScale; 42705 42706 } 42707 42708 } 42709 42710 return this; 42711 42712 } 42713 42714 // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. 42715 // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values 42716 trim( startTime, endTime ) { 42717 42718 const times = this.times, 42719 nKeys = times.length; 42720 42721 let from = 0, 42722 to = nKeys - 1; 42723 42724 while ( from !== nKeys && times[ from ] < startTime ) { 42725 42726 ++ from; 42727 42728 } 42729 42730 while ( to !== - 1 && times[ to ] > endTime ) { 42731 42732 -- to; 42733 42734 } 42735 42736 ++ to; // inclusive -> exclusive bound 42737 42738 if ( from !== 0 || to !== nKeys ) { 42739 42740 // empty tracks are forbidden, so keep at least one keyframe 42741 if ( from >= to ) { 42742 42743 to = Math.max( to, 1 ); 42744 from = to - 1; 42745 42746 } 42747 42748 const stride = this.getValueSize(); 42749 this.times = times.slice( from, to ); 42750 this.values = this.values.slice( from * stride, to * stride ); 42751 42752 } 42753 42754 return this; 42755 42756 } 42757 42758 // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable 42759 validate() { 42760 42761 let valid = true; 42762 42763 const valueSize = this.getValueSize(); 42764 if ( valueSize - Math.floor( valueSize ) !== 0 ) { 42765 42766 console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); 42767 valid = false; 42768 42769 } 42770 42771 const times = this.times, 42772 values = this.values, 42773 42774 nKeys = times.length; 42775 42776 if ( nKeys === 0 ) { 42777 42778 console.error( 'THREE.KeyframeTrack: Track is empty.', this ); 42779 valid = false; 42780 42781 } 42782 42783 let prevTime = null; 42784 42785 for ( let i = 0; i !== nKeys; i ++ ) { 42786 42787 const currTime = times[ i ]; 42788 42789 if ( typeof currTime === 'number' && isNaN( currTime ) ) { 42790 42791 console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); 42792 valid = false; 42793 break; 42794 42795 } 42796 42797 if ( prevTime !== null && prevTime > currTime ) { 42798 42799 console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); 42800 valid = false; 42801 break; 42802 42803 } 42804 42805 prevTime = currTime; 42806 42807 } 42808 42809 if ( values !== undefined ) { 42810 42811 if ( isTypedArray( values ) ) { 42812 42813 for ( let i = 0, n = values.length; i !== n; ++ i ) { 42814 42815 const value = values[ i ]; 42816 42817 if ( isNaN( value ) ) { 42818 42819 console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); 42820 valid = false; 42821 break; 42822 42823 } 42824 42825 } 42826 42827 } 42828 42829 } 42830 42831 return valid; 42832 42833 } 42834 42835 // removes equivalent sequential keys as common in morph target sequences 42836 // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) 42837 optimize() { 42838 42839 // times or values may be shared with other tracks, so overwriting is unsafe 42840 const times = this.times.slice(), 42841 values = this.values.slice(), 42842 stride = this.getValueSize(), 42843 42844 smoothInterpolation = this.getInterpolation() === InterpolateSmooth, 42845 42846 lastIndex = times.length - 1; 42847 42848 let writeIndex = 1; 42849 42850 for ( let i = 1; i < lastIndex; ++ i ) { 42851 42852 let keep = false; 42853 42854 const time = times[ i ]; 42855 const timeNext = times[ i + 1 ]; 42856 42857 // remove adjacent keyframes scheduled at the same time 42858 42859 if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) { 42860 42861 if ( ! smoothInterpolation ) { 42862 42863 // remove unnecessary keyframes same as their neighbors 42864 42865 const offset = i * stride, 42866 offsetP = offset - stride, 42867 offsetN = offset + stride; 42868 42869 for ( let j = 0; j !== stride; ++ j ) { 42870 42871 const value = values[ offset + j ]; 42872 42873 if ( value !== values[ offsetP + j ] || 42874 value !== values[ offsetN + j ] ) { 42875 42876 keep = true; 42877 break; 42878 42879 } 42880 42881 } 42882 42883 } else { 42884 42885 keep = true; 42886 42887 } 42888 42889 } 42890 42891 // in-place compaction 42892 42893 if ( keep ) { 42894 42895 if ( i !== writeIndex ) { 42896 42897 times[ writeIndex ] = times[ i ]; 42898 42899 const readOffset = i * stride, 42900 writeOffset = writeIndex * stride; 42901 42902 for ( let j = 0; j !== stride; ++ j ) { 42903 42904 values[ writeOffset + j ] = values[ readOffset + j ]; 42905 42906 } 42907 42908 } 42909 42910 ++ writeIndex; 42911 42912 } 42913 42914 } 42915 42916 // flush last keyframe (compaction looks ahead) 42917 42918 if ( lastIndex > 0 ) { 42919 42920 times[ writeIndex ] = times[ lastIndex ]; 42921 42922 for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { 42923 42924 values[ writeOffset + j ] = values[ readOffset + j ]; 42925 42926 } 42927 42928 ++ writeIndex; 42929 42930 } 42931 42932 if ( writeIndex !== times.length ) { 42933 42934 this.times = times.slice( 0, writeIndex ); 42935 this.values = values.slice( 0, writeIndex * stride ); 42936 42937 } else { 42938 42939 this.times = times; 42940 this.values = values; 42941 42942 } 42943 42944 return this; 42945 42946 } 42947 42948 clone() { 42949 42950 const times = this.times.slice(); 42951 const values = this.values.slice(); 42952 42953 const TypedKeyframeTrack = this.constructor; 42954 const track = new TypedKeyframeTrack( this.name, times, values ); 42955 42956 // Interpolant argument to constructor is not saved, so copy the factory method directly. 42957 track.createInterpolant = this.createInterpolant; 42958 42959 return track; 42960 42961 } 42962 42963} 42964 42965KeyframeTrack.prototype.TimeBufferType = Float32Array; 42966KeyframeTrack.prototype.ValueBufferType = Float32Array; 42967KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; 42968 42969/** 42970 * A Track of Boolean keyframe values. 42971 */ 42972class BooleanKeyframeTrack extends KeyframeTrack { 42973 42974 // No interpolation parameter because only InterpolateDiscrete is valid. 42975 constructor( name, times, values ) { 42976 42977 super( name, times, values ); 42978 42979 } 42980 42981} 42982 42983BooleanKeyframeTrack.prototype.ValueTypeName = 'bool'; 42984BooleanKeyframeTrack.prototype.ValueBufferType = Array; 42985BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; 42986BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; 42987BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; 42988 42989/** 42990 * A Track of keyframe values that represent color. 42991 */ 42992class ColorKeyframeTrack extends KeyframeTrack {} 42993 42994ColorKeyframeTrack.prototype.ValueTypeName = 'color'; 42995 42996/** 42997 * A Track of numeric keyframe values. 42998 */ 42999class NumberKeyframeTrack extends KeyframeTrack {} 43000 43001NumberKeyframeTrack.prototype.ValueTypeName = 'number'; 43002 43003/** 43004 * Spherical linear unit quaternion interpolant. 43005 */ 43006 43007class QuaternionLinearInterpolant extends Interpolant { 43008 43009 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 43010 43011 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 43012 43013 } 43014 43015 interpolate_( i1, t0, t, t1 ) { 43016 43017 const result = this.resultBuffer, 43018 values = this.sampleValues, 43019 stride = this.valueSize, 43020 43021 alpha = ( t - t0 ) / ( t1 - t0 ); 43022 43023 let offset = i1 * stride; 43024 43025 for ( let end = offset + stride; offset !== end; offset += 4 ) { 43026 43027 Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); 43028 43029 } 43030 43031 return result; 43032 43033 } 43034 43035} 43036 43037/** 43038 * A Track of quaternion keyframe values. 43039 */ 43040class QuaternionKeyframeTrack extends KeyframeTrack { 43041 43042 InterpolantFactoryMethodLinear( result ) { 43043 43044 return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); 43045 43046 } 43047 43048} 43049 43050QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion'; 43051// ValueBufferType is inherited 43052// DefaultInterpolation is inherited; 43053QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; 43054 43055/** 43056 * A Track that interpolates Strings 43057 */ 43058class StringKeyframeTrack extends KeyframeTrack { 43059 43060 // No interpolation parameter because only InterpolateDiscrete is valid. 43061 constructor( name, times, values ) { 43062 43063 super( name, times, values ); 43064 43065 } 43066 43067} 43068 43069StringKeyframeTrack.prototype.ValueTypeName = 'string'; 43070StringKeyframeTrack.prototype.ValueBufferType = Array; 43071StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; 43072StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; 43073StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; 43074 43075/** 43076 * A Track of vectored keyframe values. 43077 */ 43078class VectorKeyframeTrack extends KeyframeTrack {} 43079 43080VectorKeyframeTrack.prototype.ValueTypeName = 'vector'; 43081 43082class AnimationClip { 43083 43084 constructor( name = '', duration = - 1, tracks = [], blendMode = NormalAnimationBlendMode ) { 43085 43086 this.name = name; 43087 this.tracks = tracks; 43088 this.duration = duration; 43089 this.blendMode = blendMode; 43090 43091 this.uuid = generateUUID(); 43092 43093 // this means it should figure out its duration by scanning the tracks 43094 if ( this.duration < 0 ) { 43095 43096 this.resetDuration(); 43097 43098 } 43099 43100 } 43101 43102 43103 static parse( json ) { 43104 43105 const tracks = [], 43106 jsonTracks = json.tracks, 43107 frameTime = 1.0 / ( json.fps || 1.0 ); 43108 43109 for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) { 43110 43111 tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) ); 43112 43113 } 43114 43115 const clip = new this( json.name, json.duration, tracks, json.blendMode ); 43116 clip.uuid = json.uuid; 43117 43118 return clip; 43119 43120 } 43121 43122 static toJSON( clip ) { 43123 43124 const tracks = [], 43125 clipTracks = clip.tracks; 43126 43127 const json = { 43128 43129 'name': clip.name, 43130 'duration': clip.duration, 43131 'tracks': tracks, 43132 'uuid': clip.uuid, 43133 'blendMode': clip.blendMode 43134 43135 }; 43136 43137 for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) { 43138 43139 tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); 43140 43141 } 43142 43143 return json; 43144 43145 } 43146 43147 static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) { 43148 43149 const numMorphTargets = morphTargetSequence.length; 43150 const tracks = []; 43151 43152 for ( let i = 0; i < numMorphTargets; i ++ ) { 43153 43154 let times = []; 43155 let values = []; 43156 43157 times.push( 43158 ( i + numMorphTargets - 1 ) % numMorphTargets, 43159 i, 43160 ( i + 1 ) % numMorphTargets ); 43161 43162 values.push( 0, 1, 0 ); 43163 43164 const order = getKeyframeOrder( times ); 43165 times = sortedArray( times, 1, order ); 43166 values = sortedArray( values, 1, order ); 43167 43168 // if there is a key at the first frame, duplicate it as the 43169 // last frame as well for perfect loop. 43170 if ( ! noLoop && times[ 0 ] === 0 ) { 43171 43172 times.push( numMorphTargets ); 43173 values.push( values[ 0 ] ); 43174 43175 } 43176 43177 tracks.push( 43178 new NumberKeyframeTrack( 43179 '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', 43180 times, values 43181 ).scale( 1.0 / fps ) ); 43182 43183 } 43184 43185 return new this( name, - 1, tracks ); 43186 43187 } 43188 43189 static findByName( objectOrClipArray, name ) { 43190 43191 let clipArray = objectOrClipArray; 43192 43193 if ( ! Array.isArray( objectOrClipArray ) ) { 43194 43195 const o = objectOrClipArray; 43196 clipArray = o.geometry && o.geometry.animations || o.animations; 43197 43198 } 43199 43200 for ( let i = 0; i < clipArray.length; i ++ ) { 43201 43202 if ( clipArray[ i ].name === name ) { 43203 43204 return clipArray[ i ]; 43205 43206 } 43207 43208 } 43209 43210 return null; 43211 43212 } 43213 43214 static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) { 43215 43216 const animationToMorphTargets = {}; 43217 43218 // tested with https://regex101.com/ on trick sequences 43219 // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 43220 const pattern = /^([\w-]*?)([\d]+)$/; 43221 43222 // sort morph target names into animation groups based 43223 // patterns like Walk_001, Walk_002, Run_001, Run_002 43224 for ( let i = 0, il = morphTargets.length; i < il; i ++ ) { 43225 43226 const morphTarget = morphTargets[ i ]; 43227 const parts = morphTarget.name.match( pattern ); 43228 43229 if ( parts && parts.length > 1 ) { 43230 43231 const name = parts[ 1 ]; 43232 43233 let animationMorphTargets = animationToMorphTargets[ name ]; 43234 43235 if ( ! animationMorphTargets ) { 43236 43237 animationToMorphTargets[ name ] = animationMorphTargets = []; 43238 43239 } 43240 43241 animationMorphTargets.push( morphTarget ); 43242 43243 } 43244 43245 } 43246 43247 const clips = []; 43248 43249 for ( const name in animationToMorphTargets ) { 43250 43251 clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); 43252 43253 } 43254 43255 return clips; 43256 43257 } 43258 43259 // parse the animation.hierarchy format 43260 static parseAnimation( animation, bones ) { 43261 43262 if ( ! animation ) { 43263 43264 console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); 43265 return null; 43266 43267 } 43268 43269 const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { 43270 43271 // only return track if there are actually keys. 43272 if ( animationKeys.length !== 0 ) { 43273 43274 const times = []; 43275 const values = []; 43276 43277 flattenJSON( animationKeys, times, values, propertyName ); 43278 43279 // empty keys are filtered out, so check again 43280 if ( times.length !== 0 ) { 43281 43282 destTracks.push( new trackType( trackName, times, values ) ); 43283 43284 } 43285 43286 } 43287 43288 }; 43289 43290 const tracks = []; 43291 43292 const clipName = animation.name || 'default'; 43293 const fps = animation.fps || 30; 43294 const blendMode = animation.blendMode; 43295 43296 // automatic length determination in AnimationClip. 43297 let duration = animation.length || - 1; 43298 43299 const hierarchyTracks = animation.hierarchy || []; 43300 43301 for ( let h = 0; h < hierarchyTracks.length; h ++ ) { 43302 43303 const animationKeys = hierarchyTracks[ h ].keys; 43304 43305 // skip empty tracks 43306 if ( ! animationKeys || animationKeys.length === 0 ) continue; 43307 43308 // process morph targets 43309 if ( animationKeys[ 0 ].morphTargets ) { 43310 43311 // figure out all morph targets used in this track 43312 const morphTargetNames = {}; 43313 43314 let k; 43315 43316 for ( k = 0; k < animationKeys.length; k ++ ) { 43317 43318 if ( animationKeys[ k ].morphTargets ) { 43319 43320 for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { 43321 43322 morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; 43323 43324 } 43325 43326 } 43327 43328 } 43329 43330 // create a track for each morph target with all zero 43331 // morphTargetInfluences except for the keys in which 43332 // the morphTarget is named. 43333 for ( const morphTargetName in morphTargetNames ) { 43334 43335 const times = []; 43336 const values = []; 43337 43338 for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { 43339 43340 const animationKey = animationKeys[ k ]; 43341 43342 times.push( animationKey.time ); 43343 values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); 43344 43345 } 43346 43347 tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); 43348 43349 } 43350 43351 duration = morphTargetNames.length * fps; 43352 43353 } else { 43354 43355 // ...assume skeletal animation 43356 43357 const boneName = '.bones[' + bones[ h ].name + ']'; 43358 43359 addNonemptyTrack( 43360 VectorKeyframeTrack, boneName + '.position', 43361 animationKeys, 'pos', tracks ); 43362 43363 addNonemptyTrack( 43364 QuaternionKeyframeTrack, boneName + '.quaternion', 43365 animationKeys, 'rot', tracks ); 43366 43367 addNonemptyTrack( 43368 VectorKeyframeTrack, boneName + '.scale', 43369 animationKeys, 'scl', tracks ); 43370 43371 } 43372 43373 } 43374 43375 if ( tracks.length === 0 ) { 43376 43377 return null; 43378 43379 } 43380 43381 const clip = new this( clipName, duration, tracks, blendMode ); 43382 43383 return clip; 43384 43385 } 43386 43387 resetDuration() { 43388 43389 const tracks = this.tracks; 43390 let duration = 0; 43391 43392 for ( let i = 0, n = tracks.length; i !== n; ++ i ) { 43393 43394 const track = this.tracks[ i ]; 43395 43396 duration = Math.max( duration, track.times[ track.times.length - 1 ] ); 43397 43398 } 43399 43400 this.duration = duration; 43401 43402 return this; 43403 43404 } 43405 43406 trim() { 43407 43408 for ( let i = 0; i < this.tracks.length; i ++ ) { 43409 43410 this.tracks[ i ].trim( 0, this.duration ); 43411 43412 } 43413 43414 return this; 43415 43416 } 43417 43418 validate() { 43419 43420 let valid = true; 43421 43422 for ( let i = 0; i < this.tracks.length; i ++ ) { 43423 43424 valid = valid && this.tracks[ i ].validate(); 43425 43426 } 43427 43428 return valid; 43429 43430 } 43431 43432 optimize() { 43433 43434 for ( let i = 0; i < this.tracks.length; i ++ ) { 43435 43436 this.tracks[ i ].optimize(); 43437 43438 } 43439 43440 return this; 43441 43442 } 43443 43444 clone() { 43445 43446 const tracks = []; 43447 43448 for ( let i = 0; i < this.tracks.length; i ++ ) { 43449 43450 tracks.push( this.tracks[ i ].clone() ); 43451 43452 } 43453 43454 return new this.constructor( this.name, this.duration, tracks, this.blendMode ); 43455 43456 } 43457 43458 toJSON() { 43459 43460 return this.constructor.toJSON( this ); 43461 43462 } 43463 43464} 43465 43466function getTrackTypeForValueTypeName( typeName ) { 43467 43468 switch ( typeName.toLowerCase() ) { 43469 43470 case 'scalar': 43471 case 'double': 43472 case 'float': 43473 case 'number': 43474 case 'integer': 43475 43476 return NumberKeyframeTrack; 43477 43478 case 'vector': 43479 case 'vector2': 43480 case 'vector3': 43481 case 'vector4': 43482 43483 return VectorKeyframeTrack; 43484 43485 case 'color': 43486 43487 return ColorKeyframeTrack; 43488 43489 case 'quaternion': 43490 43491 return QuaternionKeyframeTrack; 43492 43493 case 'bool': 43494 case 'boolean': 43495 43496 return BooleanKeyframeTrack; 43497 43498 case 'string': 43499 43500 return StringKeyframeTrack; 43501 43502 } 43503 43504 throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); 43505 43506} 43507 43508function parseKeyframeTrack( json ) { 43509 43510 if ( json.type === undefined ) { 43511 43512 throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); 43513 43514 } 43515 43516 const trackType = getTrackTypeForValueTypeName( json.type ); 43517 43518 if ( json.times === undefined ) { 43519 43520 const times = [], values = []; 43521 43522 flattenJSON( json.keys, times, values, 'value' ); 43523 43524 json.times = times; 43525 json.values = values; 43526 43527 } 43528 43529 // derived classes can define a static parse method 43530 if ( trackType.parse !== undefined ) { 43531 43532 return trackType.parse( json ); 43533 43534 } else { 43535 43536 // by default, we assume a constructor compatible with the base 43537 return new trackType( json.name, json.times, json.values, json.interpolation ); 43538 43539 } 43540 43541} 43542 43543const Cache = { 43544 43545 enabled: false, 43546 43547 files: {}, 43548 43549 add: function ( key, file ) { 43550 43551 if ( this.enabled === false ) return; 43552 43553 // console.log( 'THREE.Cache', 'Adding key:', key ); 43554 43555 this.files[ key ] = file; 43556 43557 }, 43558 43559 get: function ( key ) { 43560 43561 if ( this.enabled === false ) return; 43562 43563 // console.log( 'THREE.Cache', 'Checking key:', key ); 43564 43565 return this.files[ key ]; 43566 43567 }, 43568 43569 remove: function ( key ) { 43570 43571 delete this.files[ key ]; 43572 43573 }, 43574 43575 clear: function () { 43576 43577 this.files = {}; 43578 43579 } 43580 43581}; 43582 43583class LoadingManager { 43584 43585 constructor( onLoad, onProgress, onError ) { 43586 43587 const scope = this; 43588 43589 let isLoading = false; 43590 let itemsLoaded = 0; 43591 let itemsTotal = 0; 43592 let urlModifier = undefined; 43593 const handlers = []; 43594 43595 // Refer to #5689 for the reason why we don't set .onStart 43596 // in the constructor 43597 43598 this.onStart = undefined; 43599 this.onLoad = onLoad; 43600 this.onProgress = onProgress; 43601 this.onError = onError; 43602 43603 this.itemStart = function ( url ) { 43604 43605 itemsTotal ++; 43606 43607 if ( isLoading === false ) { 43608 43609 if ( scope.onStart !== undefined ) { 43610 43611 scope.onStart( url, itemsLoaded, itemsTotal ); 43612 43613 } 43614 43615 } 43616 43617 isLoading = true; 43618 43619 }; 43620 43621 this.itemEnd = function ( url ) { 43622 43623 itemsLoaded ++; 43624 43625 if ( scope.onProgress !== undefined ) { 43626 43627 scope.onProgress( url, itemsLoaded, itemsTotal ); 43628 43629 } 43630 43631 if ( itemsLoaded === itemsTotal ) { 43632 43633 isLoading = false; 43634 43635 if ( scope.onLoad !== undefined ) { 43636 43637 scope.onLoad(); 43638 43639 } 43640 43641 } 43642 43643 }; 43644 43645 this.itemError = function ( url ) { 43646 43647 if ( scope.onError !== undefined ) { 43648 43649 scope.onError( url ); 43650 43651 } 43652 43653 }; 43654 43655 this.resolveURL = function ( url ) { 43656 43657 if ( urlModifier ) { 43658 43659 return urlModifier( url ); 43660 43661 } 43662 43663 return url; 43664 43665 }; 43666 43667 this.setURLModifier = function ( transform ) { 43668 43669 urlModifier = transform; 43670 43671 return this; 43672 43673 }; 43674 43675 this.addHandler = function ( regex, loader ) { 43676 43677 handlers.push( regex, loader ); 43678 43679 return this; 43680 43681 }; 43682 43683 this.removeHandler = function ( regex ) { 43684 43685 const index = handlers.indexOf( regex ); 43686 43687 if ( index !== - 1 ) { 43688 43689 handlers.splice( index, 2 ); 43690 43691 } 43692 43693 return this; 43694 43695 }; 43696 43697 this.getHandler = function ( file ) { 43698 43699 for ( let i = 0, l = handlers.length; i < l; i += 2 ) { 43700 43701 const regex = handlers[ i ]; 43702 const loader = handlers[ i + 1 ]; 43703 43704 if ( regex.global ) regex.lastIndex = 0; // see #17920 43705 43706 if ( regex.test( file ) ) { 43707 43708 return loader; 43709 43710 } 43711 43712 } 43713 43714 return null; 43715 43716 }; 43717 43718 } 43719 43720} 43721 43722const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager(); 43723 43724class Loader { 43725 43726 constructor( manager ) { 43727 43728 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 43729 43730 this.crossOrigin = 'anonymous'; 43731 this.withCredentials = false;
vendor: 12,944 bytes, lines 43732-44461
43732 this.path = ''; 43733 this.resourcePath = ''; 43734 this.requestHeader = {}; 43735 43736 } 43737 43738 load( /* url, onLoad, onProgress, onError */ ) {} 43739 43740 loadAsync( url, onProgress ) { 43741 43742 const scope = this; 43743 43744 return new Promise( function ( resolve, reject ) { 43745 43746 scope.load( url, resolve, onProgress, reject ); 43747 43748 } ); 43749 43750 } 43751 43752 parse( /* data */ ) {} 43753 43754 setCrossOrigin( crossOrigin ) { 43755 43756 this.crossOrigin = crossOrigin; 43757 return this; 43758 43759 } 43760 43761 setWithCredentials( value ) { 43762 43763 this.withCredentials = value; 43764 return this; 43765 43766 } 43767 43768 setPath( path ) { 43769 43770 this.path = path; 43771 return this; 43772 43773 } 43774 43775 setResourcePath( resourcePath ) { 43776 43777 this.resourcePath = resourcePath; 43778 return this; 43779 43780 } 43781 43782 setRequestHeader( requestHeader ) { 43783 43784 this.requestHeader = requestHeader; 43785 return this; 43786 43787 } 43788 43789} 43790 43791Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT'; 43792 43793const loading = {}; 43794 43795class HttpError extends Error { 43796 43797 constructor( message, response ) { 43798 43799 super( message ); 43800 this.response = response; 43801 43802 } 43803 43804} 43805 43806class FileLoader extends Loader { 43807 43808 constructor( manager ) { 43809 43810 super( manager ); 43811 43812 } 43813 43814 load( url, onLoad, onProgress, onError ) { 43815 43816 if ( url === undefined ) url = ''; 43817 43818 if ( this.path !== undefined ) url = this.path + url; 43819 43820 url = this.manager.resolveURL( url ); 43821 43822 const cached = Cache.get( url ); 43823 43824 if ( cached !== undefined ) { 43825 43826 this.manager.itemStart( url ); 43827 43828 setTimeout( () => { 43829 43830 if ( onLoad ) onLoad( cached ); 43831 43832 this.manager.itemEnd( url ); 43833 43834 }, 0 ); 43835 43836 return cached; 43837 43838 } 43839 43840 // Check if request is duplicate 43841 43842 if ( loading[ url ] !== undefined ) { 43843 43844 loading[ url ].push( { 43845 43846 onLoad: onLoad, 43847 onProgress: onProgress, 43848 onError: onError 43849 43850 } ); 43851 43852 return; 43853 43854 } 43855 43856 // Initialise array for duplicate requests 43857 loading[ url ] = []; 43858 43859 loading[ url ].push( { 43860 onLoad: onLoad, 43861 onProgress: onProgress, 43862 onError: onError, 43863 } ); 43864 43865 // create request 43866 const req = new Request( url, { 43867 headers: new Headers( this.requestHeader ), 43868 credentials: this.withCredentials ? 'include' : 'same-origin', 43869 // An abort controller could be added within a future PR 43870 } ); 43871 43872 // record states ( avoid data race ) 43873 const mimeType = this.mimeType; 43874 const responseType = this.responseType; 43875 43876 // start the fetch 43877 fetch( req ) 43878 .then( response => { 43879 43880 if ( response.status === 200 || response.status === 0 ) { 43881 43882 // Some browsers return HTTP Status 0 when using non-http protocol 43883 // e.g. 'file://' or 'data://'. Handle as success. 43884 43885 if ( response.status === 0 ) { 43886 43887 console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); 43888 43889 } 43890 43891 // Workaround: Checking if response.body === undefined for Alipay browser #23548 43892 43893 if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) { 43894 43895 return response; 43896 43897 } 43898 43899 const callbacks = loading[ url ]; 43900 const reader = response.body.getReader(); 43901 43902 // Nginx needs X-File-Size check 43903 // https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content 43904 const contentLength = response.headers.get( 'X-File-Size' ) || response.headers.get( 'Content-Length' ); 43905 const total = contentLength ? parseInt( contentLength ) : 0; 43906 const lengthComputable = total !== 0; 43907 let loaded = 0; 43908 43909 // periodically read data into the new stream tracking while download progress 43910 const stream = new ReadableStream( { 43911 start( controller ) { 43912 43913 readData(); 43914 43915 function readData() { 43916 43917 reader.read().then( ( { done, value } ) => { 43918 43919 if ( done ) { 43920 43921 controller.close(); 43922 43923 } else { 43924 43925 loaded += value.byteLength; 43926 43927 const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } ); 43928 for ( let i = 0, il = callbacks.length; i < il; i ++ ) { 43929 43930 const callback = callbacks[ i ]; 43931 if ( callback.onProgress ) callback.onProgress( event ); 43932 43933 } 43934 43935 controller.enqueue( value ); 43936 readData(); 43937 43938 } 43939 43940 }, ( e ) => { 43941 43942 controller.error( e ); 43943 43944 } ); 43945 43946 } 43947 43948 } 43949 43950 } ); 43951 43952 return new Response( stream ); 43953 43954 } else { 43955 43956 throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response ); 43957 43958 } 43959 43960 } ) 43961 .then( response => { 43962 43963 switch ( responseType ) { 43964 43965 case 'arraybuffer': 43966 43967 return response.arrayBuffer(); 43968 43969 case 'blob': 43970 43971 return response.blob(); 43972 43973 case 'document': 43974 43975 return response.text() 43976 .then( text => { 43977 43978 const parser = new DOMParser(); 43979 return parser.parseFromString( text, mimeType ); 43980 43981 } ); 43982 43983 case 'json': 43984 43985 return response.json(); 43986 43987 default: 43988 43989 if ( mimeType === undefined ) { 43990 43991 return response.text(); 43992 43993 } else { 43994 43995 // sniff encoding 43996 const re = /charset="?([^;"\s]*)"?/i; 43997 const exec = re.exec( mimeType ); 43998 const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined; 43999 const decoder = new TextDecoder( label ); 44000 return response.arrayBuffer().then( ab => decoder.decode( ab ) ); 44001 44002 } 44003 44004 } 44005 44006 } ) 44007 .then( data => { 44008 44009 // Add to cache only on HTTP success, so that we do not cache 44010 // error response bodies as proper responses to requests. 44011 Cache.add( url, data ); 44012 44013 const callbacks = loading[ url ]; 44014 delete loading[ url ]; 44015 44016 for ( let i = 0, il = callbacks.length; i < il; i ++ ) { 44017 44018 const callback = callbacks[ i ]; 44019 if ( callback.onLoad ) callback.onLoad( data ); 44020 44021 } 44022 44023 } ) 44024 .catch( err => { 44025 44026 // Abort errors and other errors are handled the same 44027 44028 const callbacks = loading[ url ]; 44029 44030 if ( callbacks === undefined ) { 44031 44032 // When onLoad was called and url was deleted in `loading` 44033 this.manager.itemError( url ); 44034 throw err; 44035 44036 } 44037 44038 delete loading[ url ]; 44039 44040 for ( let i = 0, il = callbacks.length; i < il; i ++ ) { 44041 44042 const callback = callbacks[ i ]; 44043 if ( callback.onError ) callback.onError( err ); 44044 44045 } 44046 44047 this.manager.itemError( url ); 44048 44049 } ) 44050 .finally( () => { 44051 44052 this.manager.itemEnd( url ); 44053 44054 } ); 44055 44056 this.manager.itemStart( url ); 44057 44058 } 44059 44060 setResponseType( value ) { 44061 44062 this.responseType = value; 44063 return this; 44064 44065 } 44066 44067 setMimeType( value ) { 44068 44069 this.mimeType = value; 44070 return this; 44071 44072 } 44073 44074} 44075 44076class AnimationLoader extends Loader { 44077 44078 constructor( manager ) { 44079 44080 super( manager ); 44081 44082 } 44083 44084 load( url, onLoad, onProgress, onError ) { 44085 44086 const scope = this; 44087 44088 const loader = new FileLoader( this.manager ); 44089 loader.setPath( this.path ); 44090 loader.setRequestHeader( this.requestHeader ); 44091 loader.setWithCredentials( this.withCredentials ); 44092 loader.load( url, function ( text ) { 44093 44094 try { 44095 44096 onLoad( scope.parse( JSON.parse( text ) ) ); 44097 44098 } catch ( e ) { 44099 44100 if ( onError ) { 44101 44102 onError( e ); 44103 44104 } else { 44105 44106 console.error( e ); 44107 44108 } 44109 44110 scope.manager.itemError( url ); 44111 44112 } 44113 44114 }, onProgress, onError ); 44115 44116 } 44117 44118 parse( json ) { 44119 44120 const animations = []; 44121 44122 for ( let i = 0; i < json.length; i ++ ) { 44123 44124 const clip = AnimationClip.parse( json[ i ] ); 44125 44126 animations.push( clip ); 44127 44128 } 44129 44130 return animations; 44131 44132 } 44133 44134} 44135 44136/** 44137 * Abstract Base class to block based textures loader (dds, pvr, ...) 44138 * 44139 * Sub classes have to implement the parse() method which will be used in load(). 44140 */ 44141 44142class CompressedTextureLoader extends Loader { 44143 44144 constructor( manager ) { 44145 44146 super( manager ); 44147 44148 } 44149 44150 load( url, onLoad, onProgress, onError ) { 44151 44152 const scope = this; 44153 44154 const images = []; 44155 44156 const texture = new CompressedTexture(); 44157 44158 const loader = new FileLoader( this.manager ); 44159 loader.setPath( this.path ); 44160 loader.setResponseType( 'arraybuffer' ); 44161 loader.setRequestHeader( this.requestHeader ); 44162 loader.setWithCredentials( scope.withCredentials ); 44163 44164 let loaded = 0; 44165 44166 function loadTexture( i ) { 44167 44168 loader.load( url[ i ], function ( buffer ) { 44169 44170 const texDatas = scope.parse( buffer, true ); 44171 44172 images[ i ] = { 44173 width: texDatas.width, 44174 height: texDatas.height, 44175 format: texDatas.format, 44176 mipmaps: texDatas.mipmaps 44177 }; 44178 44179 loaded += 1; 44180 44181 if ( loaded === 6 ) { 44182 44183 if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter; 44184 44185 texture.image = images; 44186 texture.format = texDatas.format; 44187 texture.needsUpdate = true; 44188 44189 if ( onLoad ) onLoad( texture ); 44190 44191 } 44192 44193 }, onProgress, onError ); 44194 44195 } 44196 44197 if ( Array.isArray( url ) ) { 44198 44199 for ( let i = 0, il = url.length; i < il; ++ i ) { 44200 44201 loadTexture( i ); 44202 44203 } 44204 44205 } else { 44206 44207 // compressed cubemap texture stored in a single DDS file 44208 44209 loader.load( url, function ( buffer ) { 44210 44211 const texDatas = scope.parse( buffer, true ); 44212 44213 if ( texDatas.isCubemap ) { 44214 44215 const faces = texDatas.mipmaps.length / texDatas.mipmapCount; 44216 44217 for ( let f = 0; f < faces; f ++ ) { 44218 44219 images[ f ] = { mipmaps: [] }; 44220 44221 for ( let i = 0; i < texDatas.mipmapCount; i ++ ) { 44222 44223 images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] ); 44224 images[ f ].format = texDatas.format; 44225 images[ f ].width = texDatas.width; 44226 images[ f ].height = texDatas.height; 44227 44228 } 44229 44230 } 44231 44232 texture.image = images; 44233 44234 } else { 44235 44236 texture.image.width = texDatas.width; 44237 texture.image.height = texDatas.height; 44238 texture.mipmaps = texDatas.mipmaps; 44239 44240 } 44241 44242 if ( texDatas.mipmapCount === 1 ) { 44243 44244 texture.minFilter = LinearFilter; 44245 44246 } 44247 44248 texture.format = texDatas.format; 44249 texture.needsUpdate = true; 44250 44251 if ( onLoad ) onLoad( texture ); 44252 44253 }, onProgress, onError ); 44254 44255 } 44256 44257 return texture; 44258 44259 } 44260 44261} 44262 44263class ImageLoader extends Loader { 44264 44265 constructor( manager ) { 44266 44267 super( manager ); 44268 44269 } 44270 44271 load( url, onLoad, onProgress, onError ) { 44272 44273 if ( this.path !== undefined ) url = this.path + url; 44274 44275 url = this.manager.resolveURL( url ); 44276 44277 const scope = this; 44278 44279 const cached = Cache.get( url ); 44280 44281 if ( cached !== undefined ) { 44282 44283 scope.manager.itemStart( url ); 44284 44285 setTimeout( function () { 44286 44287 if ( onLoad ) onLoad( cached ); 44288 44289 scope.manager.itemEnd( url ); 44290 44291 }, 0 ); 44292 44293 return cached; 44294 44295 } 44296 44297 const image = createElementNS( 'img' ); 44298 44299 function onImageLoad() { 44300 44301 removeEventListeners(); 44302 44303 Cache.add( url, this ); 44304 44305 if ( onLoad ) onLoad( this ); 44306 44307 scope.manager.itemEnd( url ); 44308 44309 } 44310 44311 function onImageError( event ) { 44312 44313 removeEventListeners(); 44314 44315 if ( onError ) onError( event ); 44316 44317 scope.manager.itemError( url ); 44318 scope.manager.itemEnd( url ); 44319 44320 } 44321 44322 function removeEventListeners() { 44323 44324 image.removeEventListener( 'load', onImageLoad, false ); 44325 image.removeEventListener( 'error', onImageError, false ); 44326 44327 } 44328 44329 image.addEventListener( 'load', onImageLoad, false ); 44330 image.addEventListener( 'error', onImageError, false ); 44331 44332 if ( url.slice( 0, 5 ) !== 'data:' ) { 44333 44334 if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; 44335 44336 } 44337 44338 scope.manager.itemStart( url ); 44339 44340 image.src = url; 44341 44342 return image; 44343 44344 } 44345 44346} 44347 44348class CubeTextureLoader extends Loader { 44349 44350 constructor( manager ) { 44351 44352 super( manager ); 44353 44354 } 44355 44356 load( urls, onLoad, onProgress, onError ) { 44357 44358 const texture = new CubeTexture(); 44359 texture.colorSpace = SRGBColorSpace; 44360 44361 const loader = new ImageLoader( this.manager ); 44362 loader.setCrossOrigin( this.crossOrigin ); 44363 loader.setPath( this.path ); 44364 44365 let loaded = 0; 44366 44367 function loadTexture( i ) { 44368 44369 loader.load( urls[ i ], function ( image ) { 44370 44371 texture.images[ i ] = image; 44372 44373 loaded ++; 44374 44375 if ( loaded === 6 ) { 44376 44377 texture.needsUpdate = true; 44378 44379 if ( onLoad ) onLoad( texture ); 44380 44381 } 44382 44383 }, undefined, onError ); 44384 44385 } 44386 44387 for ( let i = 0; i < urls.length; ++ i ) { 44388 44389 loadTexture( i ); 44390 44391 } 44392 44393 return texture; 44394 44395 } 44396 44397} 44398 44399/** 44400 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) 44401 * 44402 * Sub classes have to implement the parse() method which will be used in load(). 44403 */ 44404 44405class DataTextureLoader extends Loader { 44406 44407 constructor( manager ) { 44408 44409 super( manager ); 44410 44411 } 44412 44413 load( url, onLoad, onProgress, onError ) { 44414 44415 const scope = this; 44416 44417 const texture = new DataTexture(); 44418 44419 const loader = new FileLoader( this.manager ); 44420 loader.setResponseType( 'arraybuffer' ); 44421 loader.setRequestHeader( this.requestHeader ); 44422 loader.setPath( this.path ); 44423 loader.setWithCredentials( scope.withCredentials ); 44424 loader.load( url, function ( buffer ) { 44425 44426 let texData; 44427 44428 try { 44429 44430 texData = scope.parse( buffer ); 44431 44432 } catch ( error ) { 44433 44434 if ( onError !== undefined ) { 44435 44436 onError( error ); 44437 44438 } else { 44439 44440 console.error( error ); 44441 return; 44442 44443 } 44444 44445 } 44446 44447 if ( texData.image !== undefined ) { 44448 44449 texture.image = texData.image; 44450 44451 } else if ( texData.data !== undefined ) { 44452 44453 texture.image.width = texData.width; 44454 texture.image.height = texData.height; 44455 texture.image.data = texData.data; 44456 44457 } 44458 44459 texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping; 44460 texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping; 44461
vendor: 4,953 bytes, lines 44462-44748
44462 texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter; 44463 texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter; 44464 44465 texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; 44466 44467 if ( texData.colorSpace !== undefined ) { 44468 44469 texture.colorSpace = texData.colorSpace; 44470 44471 } 44472 44473 if ( texData.flipY !== undefined ) { 44474 44475 texture.flipY = texData.flipY; 44476 44477 } 44478 44479 if ( texData.format !== undefined ) { 44480 44481 texture.format = texData.format; 44482 44483 } 44484 44485 if ( texData.type !== undefined ) { 44486 44487 texture.type = texData.type; 44488 44489 } 44490 44491 if ( texData.mipmaps !== undefined ) { 44492 44493 texture.mipmaps = texData.mipmaps; 44494 texture.minFilter = LinearMipmapLinearFilter; // presumably... 44495 44496 } 44497 44498 if ( texData.mipmapCount === 1 ) { 44499 44500 texture.minFilter = LinearFilter; 44501 44502 } 44503 44504 if ( texData.generateMipmaps !== undefined ) { 44505 44506 texture.generateMipmaps = texData.generateMipmaps; 44507 44508 } 44509 44510 texture.needsUpdate = true; 44511 44512 if ( onLoad ) onLoad( texture, texData ); 44513 44514 }, onProgress, onError ); 44515 44516 44517 return texture; 44518 44519 } 44520 44521} 44522 44523class TextureLoader extends Loader { 44524 44525 constructor( manager ) { 44526 44527 super( manager ); 44528 44529 } 44530 44531 load( url, onLoad, onProgress, onError ) { 44532 44533 const texture = new Texture(); 44534 44535 const loader = new ImageLoader( this.manager ); 44536 loader.setCrossOrigin( this.crossOrigin ); 44537 loader.setPath( this.path ); 44538 44539 loader.load( url, function ( image ) { 44540 44541 texture.image = image; 44542 texture.needsUpdate = true; 44543 44544 if ( onLoad !== undefined ) { 44545 44546 onLoad( texture ); 44547 44548 } 44549 44550 }, onProgress, onError ); 44551 44552 return texture; 44553 44554 } 44555 44556} 44557 44558class Light extends Object3D { 44559 44560 constructor( color, intensity = 1 ) { 44561 44562 super(); 44563 44564 this.isLight = true; 44565 44566 this.type = 'Light'; 44567 44568 this.color = new Color( color ); 44569 this.intensity = intensity; 44570 44571 } 44572 44573 dispose() { 44574 44575 // Empty here in base class; some subclasses override. 44576 44577 } 44578 44579 copy( source, recursive ) { 44580 44581 super.copy( source, recursive ); 44582 44583 this.color.copy( source.color ); 44584 this.intensity = source.intensity; 44585 44586 return this; 44587 44588 } 44589 44590 toJSON( meta ) { 44591 44592 const data = super.toJSON( meta ); 44593 44594 data.object.color = this.color.getHex(); 44595 data.object.intensity = this.intensity; 44596 44597 if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); 44598 44599 if ( this.distance !== undefined ) data.object.distance = this.distance; 44600 if ( this.angle !== undefined ) data.object.angle = this.angle; 44601 if ( this.decay !== undefined ) data.object.decay = this.decay; 44602 if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; 44603 44604 if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); 44605 44606 return data; 44607 44608 } 44609 44610} 44611 44612class HemisphereLight extends Light { 44613 44614 constructor( skyColor, groundColor, intensity ) { 44615 44616 super( skyColor, intensity ); 44617 44618 this.isHemisphereLight = true; 44619 44620 this.type = 'HemisphereLight'; 44621 44622 this.position.copy( Object3D.DEFAULT_UP ); 44623 this.updateMatrix(); 44624 44625 this.groundColor = new Color( groundColor ); 44626 44627 } 44628 44629 copy( source, recursive ) { 44630 44631 super.copy( source, recursive ); 44632 44633 this.groundColor.copy( source.groundColor ); 44634 44635 return this; 44636 44637 } 44638 44639} 44640 44641const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4(); 44642const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3(); 44643const _lookTarget$1 = /*@__PURE__*/ new Vector3(); 44644 44645class LightShadow { 44646 44647 constructor( camera ) { 44648 44649 this.camera = camera; 44650 44651 this.bias = 0; 44652 this.normalBias = 0; 44653 this.radius = 1; 44654 this.blurSamples = 8; 44655 44656 this.mapSize = new Vector2( 512, 512 ); 44657 44658 this.map = null; 44659 this.mapPass = null; 44660 this.matrix = new Matrix4(); 44661 44662 this.autoUpdate = true; 44663 this.needsUpdate = false; 44664 44665 this._frustum = new Frustum(); 44666 this._frameExtents = new Vector2( 1, 1 ); 44667 44668 this._viewportCount = 1; 44669 44670 this._viewports = [ 44671 44672 new Vector4( 0, 0, 1, 1 ) 44673 44674 ]; 44675 44676 } 44677 44678 getViewportCount() { 44679 44680 return this._viewportCount; 44681 44682 } 44683 44684 getFrustum() { 44685 44686 return this._frustum; 44687 44688 } 44689 44690 updateMatrices( light ) { 44691 44692 const shadowCamera = this.camera; 44693 const shadowMatrix = this.matrix; 44694 44695 _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld ); 44696 shadowCamera.position.copy( _lightPositionWorld$1 ); 44697 44698 _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld ); 44699 shadowCamera.lookAt( _lookTarget$1 ); 44700 shadowCamera.updateMatrixWorld(); 44701 44702 _projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); 44703 this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 ); 44704 44705 shadowMatrix.set( 44706 0.5, 0.0, 0.0, 0.5, 44707 0.0, 0.5, 0.0, 0.5, 44708 0.0, 0.0, 0.5, 0.5, 44709 0.0, 0.0, 0.0, 1.0 44710 ); 44711 44712 shadowMatrix.multiply( _projScreenMatrix$1 ); 44713 44714 } 44715 44716 getViewport( viewportIndex ) { 44717 44718 return this._viewports[ viewportIndex ]; 44719 44720 } 44721 44722 getFrameExtents() { 44723 44724 return this._frameExtents; 44725 44726 } 44727 44728 dispose() { 44729 44730 if ( this.map ) { 44731 44732 this.map.dispose(); 44733 44734 } 44735 44736 if ( this.mapPass ) { 44737 44738 this.mapPass.dispose(); 44739 44740 } 44741 44742 } 44743 44744 copy( source ) { 44745 44746 this.camera = source.camera.clone(); 44747 44748 this.bias = source.bias;
vendor: 5,709 bytes, lines 44749-45036
44749 this.radius = source.radius; 44750 44751 this.mapSize.copy( source.mapSize ); 44752 44753 return this; 44754 44755 } 44756 44757 clone() { 44758 44759 return new this.constructor().copy( this ); 44760 44761 } 44762 44763 toJSON() { 44764 44765 const object = {}; 44766 44767 if ( this.bias !== 0 ) object.bias = this.bias; 44768 if ( this.normalBias !== 0 ) object.normalBias = this.normalBias; 44769 if ( this.radius !== 1 ) object.radius = this.radius; 44770 if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray(); 44771 44772 object.camera = this.camera.toJSON( false ).object; 44773 delete object.camera.matrix; 44774 44775 return object; 44776 44777 } 44778 44779} 44780 44781class SpotLightShadow extends LightShadow { 44782 44783 constructor() { 44784 44785 super( new PerspectiveCamera( 50, 1, 0.5, 500 ) ); 44786 44787 this.isSpotLightShadow = true; 44788 44789 this.focus = 1; 44790 44791 } 44792 44793 updateMatrices( light ) { 44794 44795 const camera = this.camera; 44796 44797 const fov = RAD2DEG * 2 * light.angle * this.focus; 44798 const aspect = this.mapSize.width / this.mapSize.height; 44799 const far = light.distance || camera.far; 44800 44801 if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { 44802 44803 camera.fov = fov; 44804 camera.aspect = aspect; 44805 camera.far = far; 44806 camera.updateProjectionMatrix(); 44807 44808 } 44809 44810 super.updateMatrices( light ); 44811 44812 } 44813 44814 copy( source ) { 44815 44816 super.copy( source ); 44817 44818 this.focus = source.focus; 44819 44820 return this; 44821 44822 } 44823 44824} 44825 44826class SpotLight extends Light { 44827 44828 constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) { 44829 44830 super( color, intensity ); 44831 44832 this.isSpotLight = true; 44833 44834 this.type = 'SpotLight'; 44835 44836 this.position.copy( Object3D.DEFAULT_UP ); 44837 this.updateMatrix(); 44838 44839 this.target = new Object3D(); 44840 44841 this.distance = distance; 44842 this.angle = angle; 44843 this.penumbra = penumbra; 44844 this.decay = decay; 44845 44846 this.map = null; 44847 44848 this.shadow = new SpotLightShadow(); 44849 44850 } 44851 44852 get power() { 44853 44854 // compute the light's luminous power (in lumens) from its intensity (in candela) 44855 // by convention for a spotlight, luminous power (lm) = Ï * luminous intensity (cd) 44856 return this.intensity * Math.PI; 44857 44858 } 44859 44860 set power( power ) { 44861 44862 // set the light's intensity (in candela) from the desired luminous power (in lumens) 44863 this.intensity = power / Math.PI; 44864 44865 } 44866 44867 dispose() { 44868 44869 this.shadow.dispose(); 44870 44871 } 44872 44873 copy( source, recursive ) { 44874 44875 super.copy( source, recursive ); 44876 44877 this.distance = source.distance; 44878 this.angle = source.angle; 44879 this.penumbra = source.penumbra; 44880 this.decay = source.decay; 44881 44882 this.target = source.target.clone(); 44883 44884 this.shadow = source.shadow.clone(); 44885 44886 return this; 44887 44888 } 44889 44890} 44891 44892const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); 44893const _lightPositionWorld = /*@__PURE__*/ new Vector3(); 44894const _lookTarget = /*@__PURE__*/ new Vector3(); 44895 44896class PointLightShadow extends LightShadow { 44897 44898 constructor() { 44899 44900 super( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); 44901 44902 this.isPointLightShadow = true; 44903 44904 this._frameExtents = new Vector2( 4, 2 ); 44905 44906 this._viewportCount = 6; 44907 44908 this._viewports = [ 44909 // These viewports map a cube-map onto a 2D texture with the 44910 // following orientation: 44911 // 44912 // xzXZ 44913 // y Y 44914 // 44915 // X - Positive x direction 44916 // x - Negative x direction 44917 // Y - Positive y direction 44918 // y - Negative y direction 44919 // Z - Positive z direction 44920 // z - Negative z direction 44921 44922 // positive X 44923 new Vector4( 2, 1, 1, 1 ), 44924 // negative X 44925 new Vector4( 0, 1, 1, 1 ), 44926 // positive Z 44927 new Vector4( 3, 1, 1, 1 ), 44928 // negative Z 44929 new Vector4( 1, 1, 1, 1 ), 44930 // positive Y 44931 new Vector4( 3, 0, 1, 1 ), 44932 // negative Y 44933 new Vector4( 1, 0, 1, 1 ) 44934 ]; 44935 44936 this._cubeDirections = [ 44937 new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), 44938 new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) 44939 ]; 44940 44941 this._cubeUps = [ 44942 new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), 44943 new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) 44944 ]; 44945 44946 } 44947 44948 updateMatrices( light, viewportIndex = 0 ) { 44949 44950 const camera = this.camera; 44951 const shadowMatrix = this.matrix; 44952 44953 const far = light.distance || camera.far; 44954 44955 if ( far !== camera.far ) { 44956 44957 camera.far = far; 44958 camera.updateProjectionMatrix(); 44959 44960 } 44961 44962 _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); 44963 camera.position.copy( _lightPositionWorld ); 44964 44965 _lookTarget.copy( camera.position ); 44966 _lookTarget.add( this._cubeDirections[ viewportIndex ] ); 44967 camera.up.copy( this._cubeUps[ viewportIndex ] ); 44968 camera.lookAt( _lookTarget ); 44969 camera.updateMatrixWorld(); 44970 44971 shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); 44972 44973 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); 44974 this._frustum.setFromProjectionMatrix( _projScreenMatrix ); 44975 44976 } 44977 44978} 44979 44980class PointLight extends Light { 44981 44982 constructor( color, intensity, distance = 0, decay = 2 ) { 44983 44984 super( color, intensity ); 44985 44986 this.isPointLight = true; 44987 44988 this.type = 'PointLight'; 44989 44990 this.distance = distance; 44991 this.decay = decay; 44992 44993 this.shadow = new PointLightShadow(); 44994 44995 } 44996 44997 get power() { 44998 44999 // compute the light's luminous power (in lumens) from its intensity (in candela) 45000 // for an isotropic light source, luminous power (lm) = 4 Ï luminous intensity (cd) 45001 return this.intensity * 4 * Math.PI; 45002 45003 } 45004 45005 set power( power ) { 45006 45007 // set the light's intensity (in candela) from the desired luminous power (in lumens) 45008 this.intensity = power / ( 4 * Math.PI ); 45009 45010 } 45011 45012 dispose() { 45013 45014 this.shadow.dispose(); 45015 45016 } 45017 45018 copy( source, recursive ) { 45019 45020 super.copy( source, recursive ); 45021 45022 this.distance = source.distance; 45023 this.decay = source.decay; 45024 45025 this.shadow = source.shadow.clone(); 45026 45027 return this; 45028 45029 } 45030 45031} 45032 45033class DirectionalLightShadow extends LightShadow { 45034 45035 constructor() { 45036
vendor: 4,273 bytes, lines 45037-45258
45037 super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); 45038 45039 this.isDirectionalLightShadow = true; 45040 45041 } 45042 45043} 45044 45045class DirectionalLight extends Light { 45046 45047 constructor( color, intensity ) { 45048 45049 super( color, intensity ); 45050 45051 this.isDirectionalLight = true; 45052 45053 this.type = 'DirectionalLight'; 45054 45055 this.position.copy( Object3D.DEFAULT_UP ); 45056 this.updateMatrix(); 45057 45058 this.target = new Object3D(); 45059 45060 this.shadow = new DirectionalLightShadow(); 45061 45062 } 45063 45064 dispose() { 45065 45066 this.shadow.dispose(); 45067 45068 } 45069 45070 copy( source ) { 45071 45072 super.copy( source ); 45073 45074 this.target = source.target.clone(); 45075 this.shadow = source.shadow.clone(); 45076 45077 return this; 45078 45079 } 45080 45081} 45082 45083class AmbientLight extends Light { 45084 45085 constructor( color, intensity ) { 45086 45087 super( color, intensity ); 45088 45089 this.isAmbientLight = true; 45090 45091 this.type = 'AmbientLight'; 45092 45093 } 45094 45095} 45096 45097class RectAreaLight extends Light { 45098 45099 constructor( color, intensity, width = 10, height = 10 ) { 45100 45101 super( color, intensity ); 45102 45103 this.isRectAreaLight = true; 45104 45105 this.type = 'RectAreaLight'; 45106 45107 this.width = width; 45108 this.height = height; 45109 45110 } 45111 45112 get power() { 45113 45114 // compute the light's luminous power (in lumens) from its intensity (in nits) 45115 return this.intensity * this.width * this.height * Math.PI; 45116 45117 } 45118 45119 set power( power ) { 45120 45121 // set the light's intensity (in nits) from the desired luminous power (in lumens) 45122 this.intensity = power / ( this.width * this.height * Math.PI ); 45123 45124 } 45125 45126 copy( source ) { 45127 45128 super.copy( source ); 45129 45130 this.width = source.width; 45131 this.height = source.height; 45132 45133 return this; 45134 45135 } 45136 45137 toJSON( meta ) { 45138 45139 const data = super.toJSON( meta ); 45140 45141 data.object.width = this.width; 45142 data.object.height = this.height; 45143 45144 return data; 45145 45146 } 45147 45148} 45149 45150/** 45151 * Primary reference: 45152 * https://graphics.stanford.edu/papers/envmap/envmap.pdf 45153 * 45154 * Secondary reference: 45155 * https://www.ppsloan.org/publications/StupidSH36.pdf 45156 */ 45157 45158// 3-band SH defined by 9 coefficients 45159 45160class SphericalHarmonics3 { 45161 45162 constructor() { 45163 45164 this.isSphericalHarmonics3 = true; 45165 45166 this.coefficients = []; 45167 45168 for ( let i = 0; i < 9; i ++ ) { 45169 45170 this.coefficients.push( new Vector3() ); 45171 45172 } 45173 45174 } 45175 45176 set( coefficients ) { 45177 45178 for ( let i = 0; i < 9; i ++ ) { 45179 45180 this.coefficients[ i ].copy( coefficients[ i ] ); 45181 45182 } 45183 45184 return this; 45185 45186 } 45187 45188 zero() { 45189 45190 for ( let i = 0; i < 9; i ++ ) { 45191 45192 this.coefficients[ i ].set( 0, 0, 0 ); 45193 45194 } 45195 45196 return this; 45197 45198 } 45199 45200 // get the radiance in the direction of the normal 45201 // target is a Vector3 45202 getAt( normal, target ) { 45203 45204 // normal is assumed to be unit length 45205 45206 const x = normal.x, y = normal.y, z = normal.z; 45207 45208 const coeff = this.coefficients; 45209 45210 // band 0 45211 target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 ); 45212 45213 // band 1 45214 target.addScaledVector( coeff[ 1 ], 0.488603 * y ); 45215 target.addScaledVector( coeff[ 2 ], 0.488603 * z ); 45216 target.addScaledVector( coeff[ 3 ], 0.488603 * x ); 45217 45218 // band 2 45219 target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) ); 45220 target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) ); 45221 target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) ); 45222 target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) ); 45223 target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) ); 45224 45225 return target; 45226 45227 } 45228 45229 // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal 45230 // target is a Vector3 45231 // https://graphics.stanford.edu/papers/envmap/envmap.pdf 45232 getIrradianceAt( normal, target ) { 45233 45234 // normal is assumed to be unit length 45235 45236 const x = normal.x, y = normal.y, z = normal.z; 45237 45238 const coeff = this.coefficients; 45239 45240 // band 0 45241 target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // Ï * 0.282095 45242 45243 // band 1 45244 target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * Ï / 3 ) * 0.488603 45245 target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z ); 45246 target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x ); 45247 45248 // band 2 45249 target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( Ï / 4 ) * 1.092548 45250 target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z ); 45251 target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( Ï / 4 ) * 0.315392 * 3 45252 target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z ); 45253 target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( Ï / 4 ) * 0.546274 45254 45255 return target; 45256 45257 } 45258
vendor: 40,043 bytes, lines 45259-46905
45259 add( sh ) { 45260 45261 for ( let i = 0; i < 9; i ++ ) { 45262 45263 this.coefficients[ i ].add( sh.coefficients[ i ] ); 45264 45265 } 45266 45267 return this; 45268 45269 } 45270 45271 addScaledSH( sh, s ) { 45272 45273 for ( let i = 0; i < 9; i ++ ) { 45274 45275 this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s ); 45276 45277 } 45278 45279 return this; 45280 45281 } 45282 45283 scale( s ) { 45284 45285 for ( let i = 0; i < 9; i ++ ) { 45286 45287 this.coefficients[ i ].multiplyScalar( s ); 45288 45289 } 45290 45291 return this; 45292 45293 } 45294 45295 lerp( sh, alpha ) { 45296 45297 for ( let i = 0; i < 9; i ++ ) { 45298 45299 this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha ); 45300 45301 } 45302 45303 return this; 45304 45305 } 45306 45307 equals( sh ) { 45308 45309 for ( let i = 0; i < 9; i ++ ) { 45310 45311 if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) { 45312 45313 return false; 45314 45315 } 45316 45317 } 45318 45319 return true; 45320 45321 } 45322 45323 copy( sh ) { 45324 45325 return this.set( sh.coefficients ); 45326 45327 } 45328 45329 clone() { 45330 45331 return new this.constructor().copy( this ); 45332 45333 } 45334 45335 fromArray( array, offset = 0 ) { 45336 45337 const coefficients = this.coefficients; 45338 45339 for ( let i = 0; i < 9; i ++ ) { 45340 45341 coefficients[ i ].fromArray( array, offset + ( i * 3 ) ); 45342 45343 } 45344 45345 return this; 45346 45347 } 45348 45349 toArray( array = [], offset = 0 ) { 45350 45351 const coefficients = this.coefficients; 45352 45353 for ( let i = 0; i < 9; i ++ ) { 45354 45355 coefficients[ i ].toArray( array, offset + ( i * 3 ) ); 45356 45357 } 45358 45359 return array; 45360 45361 } 45362 45363 // evaluate the basis functions 45364 // shBasis is an Array[ 9 ] 45365 static getBasisAt( normal, shBasis ) { 45366 45367 // normal is assumed to be unit length 45368 45369 const x = normal.x, y = normal.y, z = normal.z; 45370 45371 // band 0 45372 shBasis[ 0 ] = 0.282095; 45373 45374 // band 1 45375 shBasis[ 1 ] = 0.488603 * y; 45376 shBasis[ 2 ] = 0.488603 * z; 45377 shBasis[ 3 ] = 0.488603 * x; 45378 45379 // band 2 45380 shBasis[ 4 ] = 1.092548 * x * y; 45381 shBasis[ 5 ] = 1.092548 * y * z; 45382 shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 ); 45383 shBasis[ 7 ] = 1.092548 * x * z; 45384 shBasis[ 8 ] = 0.546274 * ( x * x - y * y ); 45385 45386 } 45387 45388} 45389 45390class LightProbe extends Light { 45391 45392 constructor( sh = new SphericalHarmonics3(), intensity = 1 ) { 45393 45394 super( undefined, intensity ); 45395 45396 this.isLightProbe = true; 45397 45398 this.sh = sh; 45399 45400 } 45401 45402 copy( source ) { 45403 45404 super.copy( source ); 45405 45406 this.sh.copy( source.sh ); 45407 45408 return this; 45409 45410 } 45411 45412 fromJSON( json ) { 45413 45414 this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON(); 45415 this.sh.fromArray( json.sh ); 45416 45417 return this; 45418 45419 } 45420 45421 toJSON( meta ) { 45422 45423 const data = super.toJSON( meta ); 45424 45425 data.object.sh = this.sh.toArray(); 45426 45427 return data; 45428 45429 } 45430 45431} 45432 45433class MaterialLoader extends Loader { 45434 45435 constructor( manager ) { 45436 45437 super( manager ); 45438 this.textures = {}; 45439 45440 } 45441 45442 load( url, onLoad, onProgress, onError ) { 45443 45444 const scope = this; 45445 45446 const loader = new FileLoader( scope.manager ); 45447 loader.setPath( scope.path ); 45448 loader.setRequestHeader( scope.requestHeader ); 45449 loader.setWithCredentials( scope.withCredentials ); 45450 loader.load( url, function ( text ) { 45451 45452 try { 45453 45454 onLoad( scope.parse( JSON.parse( text ) ) ); 45455 45456 } catch ( e ) { 45457 45458 if ( onError ) { 45459 45460 onError( e ); 45461 45462 } else { 45463 45464 console.error( e ); 45465 45466 } 45467 45468 scope.manager.itemError( url ); 45469 45470 } 45471 45472 }, onProgress, onError ); 45473 45474 } 45475 45476 parse( json ) { 45477 45478 const textures = this.textures; 45479 45480 function getTexture( name ) { 45481 45482 if ( textures[ name ] === undefined ) { 45483 45484 console.warn( 'THREE.MaterialLoader: Undefined texture', name ); 45485 45486 } 45487 45488 return textures[ name ]; 45489 45490 } 45491 45492 const material = MaterialLoader.createMaterialFromType( json.type ); 45493 45494 if ( json.uuid !== undefined ) material.uuid = json.uuid; 45495 if ( json.name !== undefined ) material.name = json.name; 45496 if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color ); 45497 if ( json.roughness !== undefined ) material.roughness = json.roughness; 45498 if ( json.metalness !== undefined ) material.metalness = json.metalness; 45499 if ( json.sheen !== undefined ) material.sheen = json.sheen; 45500 if ( json.sheenColor !== undefined ) material.sheenColor = new Color().setHex( json.sheenColor ); 45501 if ( json.sheenRoughness !== undefined ) material.sheenRoughness = json.sheenRoughness; 45502 if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive ); 45503 if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular ); 45504 if ( json.specularIntensity !== undefined ) material.specularIntensity = json.specularIntensity; 45505 if ( json.specularColor !== undefined && material.specularColor !== undefined ) material.specularColor.setHex( json.specularColor ); 45506 if ( json.shininess !== undefined ) material.shininess = json.shininess; 45507 if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat; 45508 if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness; 45509 if ( json.dispersion !== undefined ) material.dispersion = json.dispersion; 45510 if ( json.iridescence !== undefined ) material.iridescence = json.iridescence; 45511 if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR; 45512 if ( json.iridescenceThicknessRange !== undefined ) material.iridescenceThicknessRange = json.iridescenceThicknessRange; 45513 if ( json.transmission !== undefined ) material.transmission = json.transmission; 45514 if ( json.thickness !== undefined ) material.thickness = json.thickness; 45515 if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance; 45516 if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor ); 45517 if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy; 45518 if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation; 45519 if ( json.fog !== undefined ) material.fog = json.fog; 45520 if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; 45521 if ( json.blending !== undefined ) material.blending = json.blending; 45522 if ( json.combine !== undefined ) material.combine = json.combine; 45523 if ( json.side !== undefined ) material.side = json.side; 45524 if ( json.shadowSide !== undefined ) material.shadowSide = json.shadowSide; 45525 if ( json.opacity !== undefined ) material.opacity = json.opacity; 45526 if ( json.transparent !== undefined ) material.transparent = json.transparent; 45527 if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest; 45528 if ( json.alphaHash !== undefined ) material.alphaHash = json.alphaHash; 45529 if ( json.depthFunc !== undefined ) material.depthFunc = json.depthFunc; 45530 if ( json.depthTest !== undefined ) material.depthTest = json.depthTest; 45531 if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite; 45532 if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite; 45533 if ( json.blendSrc !== undefined ) material.blendSrc = json.blendSrc; 45534 if ( json.blendDst !== undefined ) material.blendDst = json.blendDst; 45535 if ( json.blendEquation !== undefined ) material.blendEquation = json.blendEquation; 45536 if ( json.blendSrcAlpha !== undefined ) material.blendSrcAlpha = json.blendSrcAlpha; 45537 if ( json.blendDstAlpha !== undefined ) material.blendDstAlpha = json.blendDstAlpha; 45538 if ( json.blendEquationAlpha !== undefined ) material.blendEquationAlpha = json.blendEquationAlpha; 45539 if ( json.blendColor !== undefined && material.blendColor !== undefined ) material.blendColor.setHex( json.blendColor ); 45540 if ( json.blendAlpha !== undefined ) material.blendAlpha = json.blendAlpha; 45541 if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask; 45542 if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc; 45543 if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef; 45544 if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask; 45545 if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail; 45546 if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail; 45547 if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass; 45548 if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite; 45549 45550 if ( json.wireframe !== undefined ) material.wireframe = json.wireframe; 45551 if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth; 45552 if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap; 45553 if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin; 45554 45555 if ( json.rotation !== undefined ) material.rotation = json.rotation; 45556 45557 if ( json.linewidth !== undefined ) material.linewidth = json.linewidth; 45558 if ( json.dashSize !== undefined ) material.dashSize = json.dashSize; 45559 if ( json.gapSize !== undefined ) material.gapSize = json.gapSize; 45560 if ( json.scale !== undefined ) material.scale = json.scale; 45561 45562 if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset; 45563 if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor; 45564 if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits; 45565 45566 if ( json.dithering !== undefined ) material.dithering = json.dithering; 45567 45568 if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage; 45569 if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha; 45570 if ( json.forceSinglePass !== undefined ) material.forceSinglePass = json.forceSinglePass; 45571 45572 if ( json.visible !== undefined ) material.visible = json.visible; 45573 45574 if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped; 45575 45576 if ( json.userData !== undefined ) material.userData = json.userData; 45577 45578 if ( json.vertexColors !== undefined ) { 45579 45580 if ( typeof json.vertexColors === 'number' ) { 45581 45582 material.vertexColors = ( json.vertexColors > 0 ) ? true : false; 45583 45584 } else { 45585 45586 material.vertexColors = json.vertexColors; 45587 45588 } 45589 45590 } 45591 45592 // Shader Material 45593 45594 if ( json.uniforms !== undefined ) { 45595 45596 for ( const name in json.uniforms ) { 45597 45598 const uniform = json.uniforms[ name ]; 45599 45600 material.uniforms[ name ] = {}; 45601 45602 switch ( uniform.type ) { 45603 45604 case 't': 45605 material.uniforms[ name ].value = getTexture( uniform.value ); 45606 break; 45607 45608 case 'c': 45609 material.uniforms[ name ].value = new Color().setHex( uniform.value ); 45610 break; 45611 45612 case 'v2': 45613 material.uniforms[ name ].value = new Vector2().fromArray( uniform.value ); 45614 break; 45615 45616 case 'v3': 45617 material.uniforms[ name ].value = new Vector3().fromArray( uniform.value ); 45618 break; 45619 45620 case 'v4': 45621 material.uniforms[ name ].value = new Vector4().fromArray( uniform.value ); 45622 break; 45623 45624 case 'm3': 45625 material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value ); 45626 break; 45627 45628 case 'm4': 45629 material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value ); 45630 break; 45631 45632 default: 45633 material.uniforms[ name ].value = uniform.value; 45634 45635 } 45636 45637 } 45638 45639 } 45640 45641 if ( json.defines !== undefined ) material.defines = json.defines; 45642 if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader; 45643 if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; 45644 if ( json.glslVersion !== undefined ) material.glslVersion = json.glslVersion; 45645 45646 if ( json.extensions !== undefined ) { 45647 45648 for ( const key in json.extensions ) { 45649 45650 material.extensions[ key ] = json.extensions[ key ]; 45651 45652 } 45653 45654 } 45655 45656 if ( json.lights !== undefined ) material.lights = json.lights; 45657 if ( json.clipping !== undefined ) material.clipping = json.clipping; 45658 45659 // for PointsMaterial 45660 45661 if ( json.size !== undefined ) material.size = json.size; 45662 if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation; 45663 45664 // maps 45665 45666 if ( json.map !== undefined ) material.map = getTexture( json.map ); 45667 if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap ); 45668 45669 if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap ); 45670 45671 if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap ); 45672 if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale; 45673 45674 if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap ); 45675 if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType; 45676 if ( json.normalScale !== undefined ) { 45677 45678 let normalScale = json.normalScale; 45679 45680 if ( Array.isArray( normalScale ) === false ) { 45681 45682 // Blender exporter used to export a scalar. See #7459 45683 45684 normalScale = [ normalScale, normalScale ]; 45685 45686 } 45687 45688 material.normalScale = new Vector2().fromArray( normalScale ); 45689 45690 } 45691 45692 if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap ); 45693 if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale; 45694 if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias; 45695 45696 if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap ); 45697 if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap ); 45698 45699 if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap ); 45700 if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity; 45701 45702 if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap ); 45703 if ( json.specularIntensityMap !== undefined ) material.specularIntensityMap = getTexture( json.specularIntensityMap ); 45704 if ( json.specularColorMap !== undefined ) material.specularColorMap = getTexture( json.specularColorMap ); 45705 45706 if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap ); 45707 if ( json.envMapRotation !== undefined ) material.envMapRotation.fromArray( json.envMapRotation ); 45708 if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity; 45709 45710 if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity; 45711 if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio; 45712 45713 if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap ); 45714 if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity; 45715 45716 if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap ); 45717 if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity; 45718 45719 if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap ); 45720 45721 if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap ); 45722 if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap ); 45723 if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap ); 45724 if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale ); 45725 45726 if ( json.iridescenceMap !== undefined ) material.iridescenceMap = getTexture( json.iridescenceMap ); 45727 if ( json.iridescenceThicknessMap !== undefined ) material.iridescenceThicknessMap = getTexture( json.iridescenceThicknessMap ); 45728 45729 if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap ); 45730 if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap ); 45731 45732 if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap ); 45733 45734 if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap ); 45735 if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap ); 45736 45737 return material; 45738 45739 } 45740 45741 setTextures( value ) { 45742 45743 this.textures = value; 45744 return this; 45745 45746 } 45747 45748 static createMaterialFromType( type ) { 45749 45750 const materialLib = { 45751 ShadowMaterial, 45752 SpriteMaterial, 45753 RawShaderMaterial, 45754 ShaderMaterial, 45755 PointsMaterial, 45756 MeshPhysicalMaterial, 45757 MeshStandardMaterial, 45758 MeshPhongMaterial, 45759 MeshToonMaterial, 45760 MeshNormalMaterial, 45761 MeshLambertMaterial, 45762 MeshDepthMaterial, 45763 MeshDistanceMaterial, 45764 MeshBasicMaterial, 45765 MeshMatcapMaterial, 45766 LineDashedMaterial, 45767 LineBasicMaterial, 45768 Material 45769 }; 45770 45771 return new materialLib[ type ](); 45772 45773 } 45774 45775} 45776 45777class LoaderUtils { 45778 45779 static decodeText( array ) { // @deprecated, r165 45780 45781 console.warn( 'THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead.' ); 45782 45783 if ( typeof TextDecoder !== 'undefined' ) { 45784 45785 return new TextDecoder().decode( array ); 45786 45787 } 45788 45789 // Avoid the String.fromCharCode.apply(null, array) shortcut, which 45790 // throws a "maximum call stack size exceeded" error for large arrays. 45791 45792 let s = ''; 45793 45794 for ( let i = 0, il = array.length; i < il; i ++ ) { 45795 45796 // Implicitly assumes little-endian. 45797 s += String.fromCharCode( array[ i ] ); 45798 45799 } 45800 45801 try { 45802 45803 // merges multi-byte utf-8 characters. 45804 45805 return decodeURIComponent( escape( s ) ); 45806 45807 } catch ( e ) { // see #16358 45808 45809 return s; 45810 45811 } 45812 45813 } 45814 45815 static extractUrlBase( url ) { 45816 45817 const index = url.lastIndexOf( '/' ); 45818 45819 if ( index === - 1 ) return './'; 45820 45821 return url.slice( 0, index + 1 ); 45822 45823 } 45824 45825 static resolveURL( url, path ) { 45826 45827 // Invalid URL 45828 if ( typeof url !== 'string' || url === '' ) return ''; 45829 45830 // Host Relative URL 45831 if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) { 45832 45833 path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' ); 45834 45835 } 45836 45837 // Absolute URL http://,https://,// 45838 if ( /^(https?:)?\/\//i.test( url ) ) return url; 45839 45840 // Data URI 45841 if ( /^data:.*,.*$/i.test( url ) ) return url; 45842 45843 // Blob URL 45844 if ( /^blob:.*$/i.test( url ) ) return url; 45845 45846 // Relative URL 45847 return path + url; 45848 45849 } 45850 45851} 45852 45853class InstancedBufferGeometry extends BufferGeometry { 45854 45855 constructor() { 45856 45857 super(); 45858 45859 this.isInstancedBufferGeometry = true; 45860 45861 this.type = 'InstancedBufferGeometry'; 45862 this.instanceCount = Infinity; 45863 45864 } 45865 45866 copy( source ) { 45867 45868 super.copy( source ); 45869 45870 this.instanceCount = source.instanceCount; 45871 45872 return this; 45873 45874 } 45875 45876 toJSON() { 45877 45878 const data = super.toJSON(); 45879 45880 data.instanceCount = this.instanceCount; 45881 45882 data.isInstancedBufferGeometry = true; 45883 45884 return data; 45885 45886 } 45887 45888} 45889 45890class BufferGeometryLoader extends Loader { 45891 45892 constructor( manager ) { 45893 45894 super( manager ); 45895 45896 } 45897 45898 load( url, onLoad, onProgress, onError ) { 45899 45900 const scope = this; 45901 45902 const loader = new FileLoader( scope.manager ); 45903 loader.setPath( scope.path ); 45904 loader.setRequestHeader( scope.requestHeader ); 45905 loader.setWithCredentials( scope.withCredentials ); 45906 loader.load( url, function ( text ) { 45907 45908 try { 45909 45910 onLoad( scope.parse( JSON.parse( text ) ) ); 45911 45912 } catch ( e ) { 45913 45914 if ( onError ) { 45915 45916 onError( e ); 45917 45918 } else { 45919 45920 console.error( e ); 45921 45922 } 45923 45924 scope.manager.itemError( url ); 45925 45926 } 45927 45928 }, onProgress, onError ); 45929 45930 } 45931 45932 parse( json ) { 45933 45934 const interleavedBufferMap = {}; 45935 const arrayBufferMap = {}; 45936 45937 function getInterleavedBuffer( json, uuid ) { 45938 45939 if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ]; 45940 45941 const interleavedBuffers = json.interleavedBuffers; 45942 const interleavedBuffer = interleavedBuffers[ uuid ]; 45943 45944 const buffer = getArrayBuffer( json, interleavedBuffer.buffer ); 45945 45946 const array = getTypedArray( interleavedBuffer.type, buffer ); 45947 const ib = new InterleavedBuffer( array, interleavedBuffer.stride ); 45948 ib.uuid = interleavedBuffer.uuid; 45949 45950 interleavedBufferMap[ uuid ] = ib; 45951 45952 return ib; 45953 45954 } 45955 45956 function getArrayBuffer( json, uuid ) { 45957 45958 if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ]; 45959 45960 const arrayBuffers = json.arrayBuffers; 45961 const arrayBuffer = arrayBuffers[ uuid ]; 45962 45963 const ab = new Uint32Array( arrayBuffer ).buffer; 45964 45965 arrayBufferMap[ uuid ] = ab; 45966 45967 return ab; 45968 45969 } 45970 45971 const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry(); 45972 45973 const index = json.data.index; 45974 45975 if ( index !== undefined ) { 45976 45977 const typedArray = getTypedArray( index.type, index.array ); 45978 geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); 45979 45980 } 45981 45982 const attributes = json.data.attributes; 45983 45984 for ( const key in attributes ) { 45985 45986 const attribute = attributes[ key ]; 45987 let bufferAttribute; 45988 45989 if ( attribute.isInterleavedBufferAttribute ) { 45990 45991 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); 45992 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); 45993 45994 } else { 45995 45996 const typedArray = getTypedArray( attribute.type, attribute.array ); 45997 const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute; 45998 bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized ); 45999 46000 } 46001 46002 if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; 46003 if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage ); 46004 46005 geometry.setAttribute( key, bufferAttribute ); 46006 46007 } 46008 46009 const morphAttributes = json.data.morphAttributes; 46010 46011 if ( morphAttributes ) { 46012 46013 for ( const key in morphAttributes ) { 46014 46015 const attributeArray = morphAttributes[ key ]; 46016 46017 const array = []; 46018 46019 for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { 46020 46021 const attribute = attributeArray[ i ]; 46022 let bufferAttribute; 46023 46024 if ( attribute.isInterleavedBufferAttribute ) { 46025 46026 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); 46027 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); 46028 46029 } else { 46030 46031 const typedArray = getTypedArray( attribute.type, attribute.array ); 46032 bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ); 46033 46034 } 46035 46036 if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; 46037 array.push( bufferAttribute ); 46038 46039 } 46040 46041 geometry.morphAttributes[ key ] = array; 46042 46043 } 46044 46045 } 46046 46047 const morphTargetsRelative = json.data.morphTargetsRelative; 46048 46049 if ( morphTargetsRelative ) { 46050 46051 geometry.morphTargetsRelative = true; 46052 46053 } 46054 46055 const groups = json.data.groups || json.data.drawcalls || json.data.offsets; 46056 46057 if ( groups !== undefined ) { 46058 46059 for ( let i = 0, n = groups.length; i !== n; ++ i ) { 46060 46061 const group = groups[ i ]; 46062 46063 geometry.addGroup( group.start, group.count, group.materialIndex ); 46064 46065 } 46066 46067 } 46068 46069 const boundingSphere = json.data.boundingSphere; 46070 46071 if ( boundingSphere !== undefined ) { 46072 46073 const center = new Vector3(); 46074 46075 if ( boundingSphere.center !== undefined ) { 46076 46077 center.fromArray( boundingSphere.center ); 46078 46079 } 46080 46081 geometry.boundingSphere = new Sphere( center, boundingSphere.radius ); 46082 46083 } 46084 46085 if ( json.name ) geometry.name = json.name; 46086 if ( json.userData ) geometry.userData = json.userData; 46087 46088 return geometry; 46089 46090 } 46091 46092} 46093 46094class ObjectLoader extends Loader { 46095 46096 constructor( manager ) { 46097 46098 super( manager ); 46099 46100 } 46101 46102 load( url, onLoad, onProgress, onError ) { 46103 46104 const scope = this; 46105 46106 const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; 46107 this.resourcePath = this.resourcePath || path; 46108 46109 const loader = new FileLoader( this.manager ); 46110 loader.setPath( this.path ); 46111 loader.setRequestHeader( this.requestHeader ); 46112 loader.setWithCredentials( this.withCredentials ); 46113 loader.load( url, function ( text ) { 46114 46115 let json = null; 46116 46117 try { 46118 46119 json = JSON.parse( text ); 46120 46121 } catch ( error ) { 46122 46123 if ( onError !== undefined ) onError( error ); 46124 46125 console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); 46126 46127 return; 46128 46129 } 46130 46131 const metadata = json.metadata; 46132 46133 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { 46134 46135 if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) ); 46136 46137 console.error( 'THREE.ObjectLoader: Can\'t load ' + url ); 46138 return; 46139 46140 } 46141 46142 scope.parse( json, onLoad ); 46143 46144 }, onProgress, onError ); 46145 46146 } 46147 46148 async loadAsync( url, onProgress ) { 46149 46150 const scope = this; 46151 46152 const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; 46153 this.resourcePath = this.resourcePath || path; 46154 46155 const loader = new FileLoader( this.manager ); 46156 loader.setPath( this.path ); 46157 loader.setRequestHeader( this.requestHeader ); 46158 loader.setWithCredentials( this.withCredentials ); 46159 46160 const text = await loader.loadAsync( url, onProgress ); 46161 46162 const json = JSON.parse( text ); 46163 46164 const metadata = json.metadata; 46165 46166 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { 46167 46168 throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url ); 46169 46170 } 46171 46172 return await scope.parseAsync( json ); 46173 46174 } 46175 46176 parse( json, onLoad ) { 46177 46178 const animations = this.parseAnimations( json.animations ); 46179 const shapes = this.parseShapes( json.shapes ); 46180 const geometries = this.parseGeometries( json.geometries, shapes ); 46181 46182 const images = this.parseImages( json.images, function () { 46183 46184 if ( onLoad !== undefined ) onLoad( object ); 46185 46186 } ); 46187 46188 const textures = this.parseTextures( json.textures, images ); 46189 const materials = this.parseMaterials( json.materials, textures ); 46190 46191 const object = this.parseObject( json.object, geometries, materials, textures, animations ); 46192 const skeletons = this.parseSkeletons( json.skeletons, object ); 46193 46194 this.bindSkeletons( object, skeletons ); 46195 46196 // 46197 46198 if ( onLoad !== undefined ) { 46199 46200 let hasImages = false; 46201 46202 for ( const uuid in images ) { 46203 46204 if ( images[ uuid ].data instanceof HTMLImageElement ) { 46205 46206 hasImages = true; 46207 break; 46208 46209 } 46210 46211 } 46212 46213 if ( hasImages === false ) onLoad( object ); 46214 46215 } 46216 46217 return object; 46218 46219 } 46220 46221 async parseAsync( json ) { 46222 46223 const animations = this.parseAnimations( json.animations ); 46224 const shapes = this.parseShapes( json.shapes ); 46225 const geometries = this.parseGeometries( json.geometries, shapes ); 46226 46227 const images = await this.parseImagesAsync( json.images ); 46228 46229 const textures = this.parseTextures( json.textures, images ); 46230 const materials = this.parseMaterials( json.materials, textures ); 46231 46232 const object = this.parseObject( json.object, geometries, materials, textures, animations ); 46233 const skeletons = this.parseSkeletons( json.skeletons, object ); 46234 46235 this.bindSkeletons( object, skeletons ); 46236 46237 return object; 46238 46239 } 46240 46241 parseShapes( json ) { 46242 46243 const shapes = {}; 46244 46245 if ( json !== undefined ) { 46246 46247 for ( let i = 0, l = json.length; i < l; i ++ ) { 46248 46249 const shape = new Shape().fromJSON( json[ i ] ); 46250 46251 shapes[ shape.uuid ] = shape; 46252 46253 } 46254 46255 } 46256 46257 return shapes; 46258 46259 } 46260 46261 parseSkeletons( json, object ) { 46262 46263 const skeletons = {}; 46264 const bones = {}; 46265 46266 // generate bone lookup table 46267 46268 object.traverse( function ( child ) { 46269 46270 if ( child.isBone ) bones[ child.uuid ] = child; 46271 46272 } ); 46273 46274 // create skeletons 46275 46276 if ( json !== undefined ) { 46277 46278 for ( let i = 0, l = json.length; i < l; i ++ ) { 46279 46280 const skeleton = new Skeleton().fromJSON( json[ i ], bones ); 46281 46282 skeletons[ skeleton.uuid ] = skeleton; 46283 46284 } 46285 46286 } 46287 46288 return skeletons; 46289 46290 } 46291 46292 parseGeometries( json, shapes ) { 46293 46294 const geometries = {}; 46295 46296 if ( json !== undefined ) { 46297 46298 const bufferGeometryLoader = new BufferGeometryLoader(); 46299 46300 for ( let i = 0, l = json.length; i < l; i ++ ) { 46301 46302 let geometry; 46303 const data = json[ i ]; 46304 46305 switch ( data.type ) { 46306 46307 case 'BufferGeometry': 46308 case 'InstancedBufferGeometry': 46309 46310 geometry = bufferGeometryLoader.parse( data ); 46311 break; 46312 46313 default: 46314 46315 if ( data.type in Geometries ) { 46316 46317 geometry = Geometries[ data.type ].fromJSON( data, shapes ); 46318 46319 } else { 46320 46321 console.warn( `THREE.ObjectLoader: Unsupported geometry type "${ data.type }"` ); 46322 46323 } 46324 46325 } 46326 46327 geometry.uuid = data.uuid; 46328 46329 if ( data.name !== undefined ) geometry.name = data.name; 46330 if ( data.userData !== undefined ) geometry.userData = data.userData; 46331 46332 geometries[ data.uuid ] = geometry; 46333 46334 } 46335 46336 } 46337 46338 return geometries; 46339 46340 } 46341 46342 parseMaterials( json, textures ) { 46343 46344 const cache = {}; // MultiMaterial 46345 const materials = {}; 46346 46347 if ( json !== undefined ) { 46348 46349 const loader = new MaterialLoader(); 46350 loader.setTextures( textures ); 46351 46352 for ( let i = 0, l = json.length; i < l; i ++ ) { 46353 46354 const data = json[ i ]; 46355 46356 if ( cache[ data.uuid ] === undefined ) { 46357 46358 cache[ data.uuid ] = loader.parse( data ); 46359 46360 } 46361 46362 materials[ data.uuid ] = cache[ data.uuid ]; 46363 46364 } 46365 46366 } 46367 46368 return materials; 46369 46370 } 46371 46372 parseAnimations( json ) { 46373 46374 const animations = {}; 46375 46376 if ( json !== undefined ) { 46377 46378 for ( let i = 0; i < json.length; i ++ ) { 46379 46380 const data = json[ i ]; 46381 46382 const clip = AnimationClip.parse( data ); 46383 46384 animations[ clip.uuid ] = clip; 46385 46386 } 46387 46388 } 46389 46390 return animations; 46391 46392 } 46393 46394 parseImages( json, onLoad ) { 46395 46396 const scope = this; 46397 const images = {}; 46398 46399 let loader; 46400 46401 function loadImage( url ) { 46402 46403 scope.manager.itemStart( url ); 46404 46405 return loader.load( url, function () { 46406 46407 scope.manager.itemEnd( url ); 46408 46409 }, undefined, function () { 46410 46411 scope.manager.itemError( url ); 46412 scope.manager.itemEnd( url ); 46413 46414 } ); 46415 46416 } 46417 46418 function deserializeImage( image ) { 46419 46420 if ( typeof image === 'string' ) { 46421 46422 const url = image; 46423 46424 const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; 46425 46426 return loadImage( path ); 46427 46428 } else { 46429 46430 if ( image.data ) { 46431 46432 return { 46433 data: getTypedArray( image.type, image.data ), 46434 width: image.width, 46435 height: image.height 46436 }; 46437 46438 } else { 46439 46440 return null; 46441 46442 } 46443 46444 } 46445 46446 } 46447 46448 if ( json !== undefined && json.length > 0 ) { 46449 46450 const manager = new LoadingManager( onLoad ); 46451 46452 loader = new ImageLoader( manager ); 46453 loader.setCrossOrigin( this.crossOrigin ); 46454 46455 for ( let i = 0, il = json.length; i < il; i ++ ) { 46456 46457 const image = json[ i ]; 46458 const url = image.url; 46459 46460 if ( Array.isArray( url ) ) { 46461 46462 // load array of images e.g CubeTexture 46463 46464 const imageArray = []; 46465 46466 for ( let j = 0, jl = url.length; j < jl; j ++ ) { 46467 46468 const currentUrl = url[ j ]; 46469 46470 const deserializedImage = deserializeImage( currentUrl ); 46471 46472 if ( deserializedImage !== null ) { 46473 46474 if ( deserializedImage instanceof HTMLImageElement ) { 46475 46476 imageArray.push( deserializedImage ); 46477 46478 } else { 46479 46480 // special case: handle array of data textures for cube textures 46481 46482 imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); 46483 46484 } 46485 46486 } 46487 46488 } 46489 46490 images[ image.uuid ] = new Source( imageArray ); 46491 46492 } else { 46493 46494 // load single image 46495 46496 const deserializedImage = deserializeImage( image.url ); 46497 images[ image.uuid ] = new Source( deserializedImage ); 46498 46499 46500 } 46501 46502 } 46503 46504 } 46505 46506 return images; 46507 46508 } 46509 46510 async parseImagesAsync( json ) { 46511 46512 const scope = this; 46513 const images = {}; 46514 46515 let loader; 46516 46517 async function deserializeImage( image ) { 46518 46519 if ( typeof image === 'string' ) { 46520 46521 const url = image; 46522 46523 const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; 46524 46525 return await loader.loadAsync( path ); 46526 46527 } else { 46528 46529 if ( image.data ) { 46530 46531 return { 46532 data: getTypedArray( image.type, image.data ), 46533 width: image.width, 46534 height: image.height 46535 }; 46536 46537 } else { 46538 46539 return null; 46540 46541 } 46542 46543 } 46544 46545 } 46546 46547 if ( json !== undefined && json.length > 0 ) { 46548 46549 loader = new ImageLoader( this.manager ); 46550 loader.setCrossOrigin( this.crossOrigin ); 46551 46552 for ( let i = 0, il = json.length; i < il; i ++ ) { 46553 46554 const image = json[ i ]; 46555 const url = image.url; 46556 46557 if ( Array.isArray( url ) ) { 46558 46559 // load array of images e.g CubeTexture 46560 46561 const imageArray = []; 46562 46563 for ( let j = 0, jl = url.length; j < jl; j ++ ) { 46564 46565 const currentUrl = url[ j ]; 46566 46567 const deserializedImage = await deserializeImage( currentUrl ); 46568 46569 if ( deserializedImage !== null ) { 46570 46571 if ( deserializedImage instanceof HTMLImageElement ) { 46572 46573 imageArray.push( deserializedImage ); 46574 46575 } else { 46576 46577 // special case: handle array of data textures for cube textures 46578 46579 imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); 46580 46581 } 46582 46583 } 46584 46585 } 46586 46587 images[ image.uuid ] = new Source( imageArray ); 46588 46589 } else { 46590 46591 // load single image 46592 46593 const deserializedImage = await deserializeImage( image.url ); 46594 images[ image.uuid ] = new Source( deserializedImage ); 46595 46596 } 46597 46598 } 46599 46600 } 46601 46602 return images; 46603 46604 } 46605 46606 parseTextures( json, images ) { 46607 46608 function parseConstant( value, type ) { 46609 46610 if ( typeof value === 'number' ) return value; 46611 46612 console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); 46613 46614 return type[ value ]; 46615 46616 } 46617 46618 const textures = {}; 46619 46620 if ( json !== undefined ) { 46621 46622 for ( let i = 0, l = json.length; i < l; i ++ ) { 46623 46624 const data = json[ i ]; 46625 46626 if ( data.image === undefined ) { 46627 46628 console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); 46629 46630 } 46631 46632 if ( images[ data.image ] === undefined ) { 46633 46634 console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); 46635 46636 } 46637 46638 const source = images[ data.image ]; 46639 const image = source.data; 46640 46641 let texture; 46642 46643 if ( Array.isArray( image ) ) { 46644 46645 texture = new CubeTexture(); 46646 46647 if ( image.length === 6 ) texture.needsUpdate = true; 46648 46649 } else { 46650 46651 if ( image && image.data ) { 46652 46653 texture = new DataTexture(); 46654 46655 } else { 46656 46657 texture = new Texture(); 46658 46659 } 46660 46661 if ( image ) texture.needsUpdate = true; // textures can have undefined image data 46662 46663 } 46664 46665 texture.source = source; 46666 46667 texture.uuid = data.uuid; 46668 46669 if ( data.name !== undefined ) texture.name = data.name; 46670 46671 if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); 46672 if ( data.channel !== undefined ) texture.channel = data.channel; 46673 46674 if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); 46675 if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); 46676 if ( data.center !== undefined ) texture.center.fromArray( data.center ); 46677 if ( data.rotation !== undefined ) texture.rotation = data.rotation; 46678 46679 if ( data.wrap !== undefined ) { 46680 46681 texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); 46682 texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); 46683 46684 } 46685 46686 if ( data.format !== undefined ) texture.format = data.format; 46687 if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat; 46688 if ( data.type !== undefined ) texture.type = data.type; 46689 if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace; 46690 46691 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); 46692 if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); 46693 if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy; 46694 46695 if ( data.flipY !== undefined ) texture.flipY = data.flipY; 46696 46697 if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps; 46698 if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha; 46699 if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment; 46700 if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction; 46701 46702 if ( data.userData !== undefined ) texture.userData = data.userData; 46703 46704 textures[ data.uuid ] = texture; 46705 46706 } 46707 46708 } 46709 46710 return textures; 46711 46712 } 46713 46714 parseObject( data, geometries, materials, textures, animations ) { 46715 46716 let object; 46717 46718 function getGeometry( name ) { 46719 46720 if ( geometries[ name ] === undefined ) { 46721 46722 console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); 46723 46724 } 46725 46726 return geometries[ name ]; 46727 46728 } 46729 46730 function getMaterial( name ) { 46731 46732 if ( name === undefined ) return undefined; 46733 46734 if ( Array.isArray( name ) ) { 46735 46736 const array = []; 46737 46738 for ( let i = 0, l = name.length; i < l; i ++ ) { 46739 46740 const uuid = name[ i ]; 46741 46742 if ( materials[ uuid ] === undefined ) { 46743 46744 console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); 46745 46746 } 46747 46748 array.push( materials[ uuid ] ); 46749 46750 } 46751 46752 return array; 46753 46754 } 46755 46756 if ( materials[ name ] === undefined ) { 46757 46758 console.warn( 'THREE.ObjectLoader: Undefined material', name ); 46759 46760 } 46761 46762 return materials[ name ]; 46763 46764 } 46765 46766 function getTexture( uuid ) { 46767 46768 if ( textures[ uuid ] === undefined ) { 46769 46770 console.warn( 'THREE.ObjectLoader: Undefined texture', uuid ); 46771 46772 } 46773 46774 return textures[ uuid ]; 46775 46776 } 46777 46778 let geometry, material; 46779 46780 switch ( data.type ) { 46781 46782 case 'Scene': 46783 46784 object = new Scene(); 46785 46786 if ( data.background !== undefined ) { 46787 46788 if ( Number.isInteger( data.background ) ) { 46789 46790 object.background = new Color( data.background ); 46791 46792 } else { 46793 46794 object.background = getTexture( data.background ); 46795 46796 } 46797 46798 } 46799 46800 if ( data.environment !== undefined ) { 46801 46802 object.environment = getTexture( data.environment ); 46803 46804 } 46805 46806 if ( data.fog !== undefined ) { 46807 46808 if ( data.fog.type === 'Fog' ) { 46809 46810 object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); 46811 46812 } else if ( data.fog.type === 'FogExp2' ) { 46813 46814 object.fog = new FogExp2( data.fog.color, data.fog.density ); 46815 46816 } 46817 46818 if ( data.fog.name !== '' ) { 46819 46820 object.fog.name = data.fog.name; 46821 46822 } 46823 46824 } 46825 46826 if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness; 46827 if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity; 46828 if ( data.backgroundRotation !== undefined ) object.backgroundRotation.fromArray( data.backgroundRotation ); 46829 46830 if ( data.environmentIntensity !== undefined ) object.environmentIntensity = data.environmentIntensity; 46831 if ( data.environmentRotation !== undefined ) object.environmentRotation.fromArray( data.environmentRotation ); 46832 46833 break; 46834 46835 case 'PerspectiveCamera': 46836 46837 object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); 46838 46839 if ( data.focus !== undefined ) object.focus = data.focus; 46840 if ( data.zoom !== undefined ) object.zoom = data.zoom; 46841 if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge; 46842 if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset; 46843 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); 46844 46845 break; 46846 46847 case 'OrthographicCamera': 46848 46849 object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); 46850 46851 if ( data.zoom !== undefined ) object.zoom = data.zoom; 46852 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); 46853 46854 break; 46855 46856 case 'AmbientLight': 46857 46858 object = new AmbientLight( data.color, data.intensity ); 46859 46860 break; 46861 46862 case 'DirectionalLight': 46863 46864 object = new DirectionalLight( data.color, data.intensity ); 46865 46866 break; 46867 46868 case 'PointLight': 46869 46870 object = new PointLight( data.color, data.intensity, data.distance, data.decay ); 46871 46872 break; 46873 46874 case 'RectAreaLight': 46875 46876 object = new RectAreaLight( data.color, data.intensity, data.width, data.height ); 46877 46878 break; 46879 46880 case 'SpotLight': 46881 46882 object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay ); 46883 46884 break; 46885 46886 case 'HemisphereLight': 46887 46888 object = new HemisphereLight( data.color, data.groundColor, data.intensity ); 46889 46890 break; 46891 46892 case 'LightProbe': 46893 46894 object = new LightProbe().fromJSON( data ); 46895 46896 break; 46897 46898 case 'SkinnedMesh': 46899 46900 geometry = getGeometry( data.geometry ); 46901 material = getMaterial( data.material ); 46902 46903 object = new SkinnedMesh( geometry, material ); 46904 46905 if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
vendor: 17,558 bytes, lines 46906-47737
46906 if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix ); 46907 if ( data.skeleton !== undefined ) object.skeleton = data.skeleton; 46908 46909 break; 46910 46911 case 'Mesh': 46912 46913 geometry = getGeometry( data.geometry ); 46914 material = getMaterial( data.material ); 46915 46916 object = new Mesh( geometry, material ); 46917 46918 break; 46919 46920 case 'InstancedMesh': 46921 46922 geometry = getGeometry( data.geometry ); 46923 material = getMaterial( data.material ); 46924 const count = data.count; 46925 const instanceMatrix = data.instanceMatrix; 46926 const instanceColor = data.instanceColor; 46927 46928 object = new InstancedMesh( geometry, material, count ); 46929 object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 ); 46930 if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize ); 46931 46932 break; 46933 46934 case 'BatchedMesh': 46935 46936 geometry = getGeometry( data.geometry ); 46937 material = getMaterial( data.material ); 46938 46939 object = new BatchedMesh( data.maxGeometryCount, data.maxVertexCount, data.maxIndexCount, material ); 46940 object.geometry = geometry; 46941 object.perObjectFrustumCulled = data.perObjectFrustumCulled; 46942 object.sortObjects = data.sortObjects; 46943 46944 object._drawRanges = data.drawRanges; 46945 object._reservedRanges = data.reservedRanges; 46946 46947 object._visibility = data.visibility; 46948 object._active = data.active; 46949 object._bounds = data.bounds.map( bound => { 46950 46951 const box = new Box3(); 46952 box.min.fromArray( bound.boxMin ); 46953 box.max.fromArray( bound.boxMax ); 46954 46955 const sphere = new Sphere(); 46956 sphere.radius = bound.sphereRadius; 46957 sphere.center.fromArray( bound.sphereCenter ); 46958 46959 return { 46960 boxInitialized: bound.boxInitialized, 46961 box: box, 46962 46963 sphereInitialized: bound.sphereInitialized, 46964 sphere: sphere 46965 }; 46966 46967 } ); 46968 46969 object._maxGeometryCount = data.maxGeometryCount; 46970 object._maxVertexCount = data.maxVertexCount; 46971 object._maxIndexCount = data.maxIndexCount; 46972 46973 object._geometryInitialized = data.geometryInitialized; 46974 object._geometryCount = data.geometryCount; 46975 46976 object._matricesTexture = getTexture( data.matricesTexture.uuid ); 46977 if ( data.colorsTexture !== undefined ) object._colorsTexture = getTexture( data.colorsTexture.uuid ); 46978 46979 break; 46980 46981 case 'LOD': 46982 46983 object = new LOD(); 46984 46985 break; 46986 46987 case 'Line': 46988 46989 object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) ); 46990 46991 break; 46992 46993 case 'LineLoop': 46994 46995 object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); 46996 46997 break; 46998 46999 case 'LineSegments': 47000 47001 object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); 47002 47003 break; 47004 47005 case 'PointCloud': 47006 case 'Points': 47007 47008 object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) ); 47009 47010 break; 47011 47012 case 'Sprite': 47013 47014 object = new Sprite( getMaterial( data.material ) ); 47015 47016 break; 47017 47018 case 'Group': 47019 47020 object = new Group(); 47021 47022 break; 47023 47024 case 'Bone': 47025 47026 object = new Bone(); 47027 47028 break; 47029 47030 default: 47031 47032 object = new Object3D(); 47033 47034 } 47035 47036 object.uuid = data.uuid; 47037 47038 if ( data.name !== undefined ) object.name = data.name; 47039 47040 if ( data.matrix !== undefined ) { 47041 47042 object.matrix.fromArray( data.matrix ); 47043 47044 if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate; 47045 if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale ); 47046 47047 } else { 47048 47049 if ( data.position !== undefined ) object.position.fromArray( data.position ); 47050 if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation ); 47051 if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion ); 47052 if ( data.scale !== undefined ) object.scale.fromArray( data.scale ); 47053 47054 } 47055 47056 if ( data.up !== undefined ) object.up.fromArray( data.up ); 47057 47058 if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; 47059 if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; 47060 47061 if ( data.shadow ) { 47062 47063 if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias; 47064 if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias; 47065 if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius; 47066 if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize ); 47067 if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera ); 47068 47069 } 47070 47071 if ( data.visible !== undefined ) object.visible = data.visible; 47072 if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled; 47073 if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder; 47074 if ( data.userData !== undefined ) object.userData = data.userData; 47075 if ( data.layers !== undefined ) object.layers.mask = data.layers; 47076 47077 if ( data.children !== undefined ) { 47078 47079 const children = data.children; 47080 47081 for ( let i = 0; i < children.length; i ++ ) { 47082 47083 object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) ); 47084 47085 } 47086 47087 } 47088 47089 if ( data.animations !== undefined ) { 47090 47091 const objectAnimations = data.animations; 47092 47093 for ( let i = 0; i < objectAnimations.length; i ++ ) { 47094 47095 const uuid = objectAnimations[ i ]; 47096 47097 object.animations.push( animations[ uuid ] ); 47098 47099 } 47100 47101 } 47102 47103 if ( data.type === 'LOD' ) { 47104 47105 if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate; 47106 47107 const levels = data.levels; 47108 47109 for ( let l = 0; l < levels.length; l ++ ) { 47110 47111 const level = levels[ l ]; 47112 const child = object.getObjectByProperty( 'uuid', level.object ); 47113 47114 if ( child !== undefined ) { 47115 47116 object.addLevel( child, level.distance, level.hysteresis ); 47117 47118 } 47119 47120 } 47121 47122 } 47123 47124 return object; 47125 47126 } 47127 47128 bindSkeletons( object, skeletons ) { 47129 47130 if ( Object.keys( skeletons ).length === 0 ) return; 47131 47132 object.traverse( function ( child ) { 47133 47134 if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) { 47135 47136 const skeleton = skeletons[ child.skeleton ]; 47137 47138 if ( skeleton === undefined ) { 47139 47140 console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton ); 47141 47142 } else { 47143 47144 child.bind( skeleton, child.bindMatrix ); 47145 47146 } 47147 47148 } 47149 47150 } ); 47151 47152 } 47153 47154} 47155 47156const TEXTURE_MAPPING = { 47157 UVMapping: UVMapping, 47158 CubeReflectionMapping: CubeReflectionMapping, 47159 CubeRefractionMapping: CubeRefractionMapping, 47160 EquirectangularReflectionMapping: EquirectangularReflectionMapping, 47161 EquirectangularRefractionMapping: EquirectangularRefractionMapping, 47162 CubeUVReflectionMapping: CubeUVReflectionMapping 47163}; 47164 47165const TEXTURE_WRAPPING = { 47166 RepeatWrapping: RepeatWrapping, 47167 ClampToEdgeWrapping: ClampToEdgeWrapping, 47168 MirroredRepeatWrapping: MirroredRepeatWrapping 47169}; 47170 47171const TEXTURE_FILTER = { 47172 NearestFilter: NearestFilter, 47173 NearestMipmapNearestFilter: NearestMipmapNearestFilter, 47174 NearestMipmapLinearFilter: NearestMipmapLinearFilter, 47175 LinearFilter: LinearFilter, 47176 LinearMipmapNearestFilter: LinearMipmapNearestFilter, 47177 LinearMipmapLinearFilter: LinearMipmapLinearFilter 47178}; 47179 47180class ImageBitmapLoader extends Loader { 47181 47182 constructor( manager ) { 47183 47184 super( manager ); 47185 47186 this.isImageBitmapLoader = true; 47187 47188 if ( typeof createImageBitmap === 'undefined' ) { 47189 47190 console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' ); 47191 47192 } 47193 47194 if ( typeof fetch === 'undefined' ) { 47195 47196 console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' ); 47197 47198 } 47199 47200 this.options = { premultiplyAlpha: 'none' }; 47201 47202 } 47203 47204 setOptions( options ) { 47205 47206 this.options = options; 47207 47208 return this; 47209 47210 } 47211 47212 load( url, onLoad, onProgress, onError ) { 47213 47214 if ( url === undefined ) url = ''; 47215 47216 if ( this.path !== undefined ) url = this.path + url; 47217 47218 url = this.manager.resolveURL( url ); 47219 47220 const scope = this; 47221 47222 const cached = Cache.get( url ); 47223 47224 if ( cached !== undefined ) { 47225 47226 scope.manager.itemStart( url ); 47227 47228 // If cached is a promise, wait for it to resolve 47229 if ( cached.then ) { 47230 47231 cached.then( imageBitmap => { 47232 47233 if ( onLoad ) onLoad( imageBitmap ); 47234 47235 scope.manager.itemEnd( url ); 47236 47237 } ).catch( e => { 47238 47239 if ( onError ) onError( e ); 47240 47241 } ); 47242 return; 47243 47244 } 47245 47246 // If cached is not a promise (i.e., it's already an imageBitmap) 47247 setTimeout( function () { 47248 47249 if ( onLoad ) onLoad( cached ); 47250 47251 scope.manager.itemEnd( url ); 47252 47253 }, 0 ); 47254 47255 return cached; 47256 47257 } 47258 47259 const fetchOptions = {}; 47260 fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include'; 47261 fetchOptions.headers = this.requestHeader; 47262 47263 const promise = fetch( url, fetchOptions ).then( function ( res ) { 47264 47265 return res.blob(); 47266 47267 } ).then( function ( blob ) { 47268 47269 return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) ); 47270 47271 } ).then( function ( imageBitmap ) { 47272 47273 Cache.add( url, imageBitmap ); 47274 47275 if ( onLoad ) onLoad( imageBitmap ); 47276 47277 scope.manager.itemEnd( url ); 47278 47279 return imageBitmap; 47280 47281 } ).catch( function ( e ) { 47282 47283 if ( onError ) onError( e ); 47284 47285 Cache.remove( url ); 47286 47287 scope.manager.itemError( url ); 47288 scope.manager.itemEnd( url ); 47289 47290 } ); 47291 47292 Cache.add( url, promise ); 47293 scope.manager.itemStart( url ); 47294 47295 } 47296 47297} 47298 47299let _context; 47300 47301class AudioContext { 47302 47303 static getContext() { 47304 47305 if ( _context === undefined ) { 47306 47307 _context = new ( window.AudioContext || window.webkitAudioContext )(); 47308 47309 } 47310 47311 return _context; 47312 47313 } 47314 47315 static setContext( value ) { 47316 47317 _context = value; 47318 47319 } 47320 47321} 47322 47323class AudioLoader extends Loader { 47324 47325 constructor( manager ) { 47326 47327 super( manager ); 47328 47329 } 47330 47331 load( url, onLoad, onProgress, onError ) { 47332 47333 const scope = this; 47334 47335 const loader = new FileLoader( this.manager ); 47336 loader.setResponseType( 'arraybuffer' ); 47337 loader.setPath( this.path ); 47338 loader.setRequestHeader( this.requestHeader ); 47339 loader.setWithCredentials( this.withCredentials ); 47340 loader.load( url, function ( buffer ) { 47341 47342 try { 47343 47344 // Create a copy of the buffer. The `decodeAudioData` method 47345 // detaches the buffer when complete, preventing reuse. 47346 const bufferCopy = buffer.slice( 0 ); 47347 47348 const context = AudioContext.getContext(); 47349 context.decodeAudioData( bufferCopy, function ( audioBuffer ) { 47350 47351 onLoad( audioBuffer ); 47352 47353 } ).catch( handleError ); 47354 47355 } catch ( e ) { 47356 47357 handleError( e ); 47358 47359 } 47360 47361 }, onProgress, onError ); 47362 47363 function handleError( e ) { 47364 47365 if ( onError ) { 47366 47367 onError( e ); 47368 47369 } else { 47370 47371 console.error( e ); 47372 47373 } 47374 47375 scope.manager.itemError( url ); 47376 47377 } 47378 47379 } 47380 47381} 47382 47383const _eyeRight = /*@__PURE__*/ new Matrix4(); 47384const _eyeLeft = /*@__PURE__*/ new Matrix4(); 47385const _projectionMatrix = /*@__PURE__*/ new Matrix4(); 47386 47387class StereoCamera { 47388 47389 constructor() { 47390 47391 this.type = 'StereoCamera'; 47392 47393 this.aspect = 1; 47394 47395 this.eyeSep = 0.064; 47396 47397 this.cameraL = new PerspectiveCamera(); 47398 this.cameraL.layers.enable( 1 ); 47399 this.cameraL.matrixAutoUpdate = false; 47400 47401 this.cameraR = new PerspectiveCamera(); 47402 this.cameraR.layers.enable( 2 ); 47403 this.cameraR.matrixAutoUpdate = false; 47404 47405 this._cache = { 47406 focus: null, 47407 fov: null, 47408 aspect: null, 47409 near: null, 47410 far: null, 47411 zoom: null, 47412 eyeSep: null 47413 }; 47414 47415 } 47416 47417 update( camera ) { 47418 47419 const cache = this._cache; 47420 47421 const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov || 47422 cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near || 47423 cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep; 47424 47425 if ( needsUpdate ) { 47426 47427 cache.focus = camera.focus; 47428 cache.fov = camera.fov; 47429 cache.aspect = camera.aspect * this.aspect; 47430 cache.near = camera.near; 47431 cache.far = camera.far; 47432 cache.zoom = camera.zoom; 47433 cache.eyeSep = this.eyeSep; 47434 47435 // Off-axis stereoscopic effect based on 47436 // http://paulbourke.net/stereographics/stereorender/ 47437 47438 _projectionMatrix.copy( camera.projectionMatrix ); 47439 const eyeSepHalf = cache.eyeSep / 2; 47440 const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus; 47441 const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom; 47442 let xmin, xmax; 47443 47444 // translate xOffset 47445 47446 _eyeLeft.elements[ 12 ] = - eyeSepHalf; 47447 _eyeRight.elements[ 12 ] = eyeSepHalf; 47448 47449 // for left eye 47450 47451 xmin = - ymax * cache.aspect + eyeSepOnProjection; 47452 xmax = ymax * cache.aspect + eyeSepOnProjection; 47453 47454 _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); 47455 _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); 47456 47457 this.cameraL.projectionMatrix.copy( _projectionMatrix ); 47458 47459 // for right eye 47460 47461 xmin = - ymax * cache.aspect - eyeSepOnProjection; 47462 xmax = ymax * cache.aspect - eyeSepOnProjection; 47463 47464 _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); 47465 _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); 47466 47467 this.cameraR.projectionMatrix.copy( _projectionMatrix ); 47468 47469 } 47470 47471 this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft ); 47472 this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight ); 47473 47474 } 47475 47476} 47477 47478class Clock { 47479 47480 constructor( autoStart = true ) { 47481 47482 this.autoStart = autoStart; 47483 47484 this.startTime = 0; 47485 this.oldTime = 0; 47486 this.elapsedTime = 0; 47487 47488 this.running = false; 47489 47490 } 47491 47492 start() { 47493 47494 this.startTime = now(); 47495 47496 this.oldTime = this.startTime; 47497 this.elapsedTime = 0; 47498 this.running = true; 47499 47500 } 47501 47502 stop() { 47503 47504 this.getElapsedTime(); 47505 this.running = false; 47506 this.autoStart = false; 47507 47508 } 47509 47510 getElapsedTime() { 47511 47512 this.getDelta(); 47513 return this.elapsedTime; 47514 47515 } 47516 47517 getDelta() { 47518 47519 let diff = 0; 47520 47521 if ( this.autoStart && ! this.running ) { 47522 47523 this.start(); 47524 return 0; 47525 47526 } 47527 47528 if ( this.running ) { 47529 47530 const newTime = now(); 47531 47532 diff = ( newTime - this.oldTime ) / 1000; 47533 this.oldTime = newTime; 47534 47535 this.elapsedTime += diff; 47536 47537 } 47538 47539 return diff; 47540 47541 } 47542 47543} 47544 47545function now() { 47546 47547 return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732 47548 47549} 47550 47551const _position$1 = /*@__PURE__*/ new Vector3(); 47552const _quaternion$1 = /*@__PURE__*/ new Quaternion(); 47553const _scale$1 = /*@__PURE__*/ new Vector3(); 47554const _orientation$1 = /*@__PURE__*/ new Vector3(); 47555 47556class AudioListener extends Object3D { 47557 47558 constructor() { 47559 47560 super(); 47561 47562 this.type = 'AudioListener'; 47563 47564 this.context = AudioContext.getContext(); 47565 47566 this.gain = this.context.createGain(); 47567 this.gain.connect( this.context.destination ); 47568 47569 this.filter = null; 47570 47571 this.timeDelta = 0; 47572 47573 // private 47574 47575 this._clock = new Clock(); 47576 47577 } 47578 47579 getInput() { 47580 47581 return this.gain; 47582 47583 } 47584 47585 removeFilter() { 47586 47587 if ( this.filter !== null ) { 47588 47589 this.gain.disconnect( this.filter ); 47590 this.filter.disconnect( this.context.destination ); 47591 this.gain.connect( this.context.destination ); 47592 this.filter = null; 47593 47594 } 47595 47596 return this; 47597 47598 } 47599 47600 getFilter() { 47601 47602 return this.filter; 47603 47604 } 47605 47606 setFilter( value ) { 47607 47608 if ( this.filter !== null ) { 47609 47610 this.gain.disconnect( this.filter ); 47611 this.filter.disconnect( this.context.destination ); 47612 47613 } else { 47614 47615 this.gain.disconnect( this.context.destination ); 47616 47617 } 47618 47619 this.filter = value; 47620 this.gain.connect( this.filter ); 47621 this.filter.connect( this.context.destination ); 47622 47623 return this; 47624 47625 } 47626 47627 getMasterVolume() { 47628 47629 return this.gain.gain.value; 47630 47631 } 47632 47633 setMasterVolume( value ) { 47634 47635 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); 47636 47637 return this; 47638 47639 } 47640 47641 updateMatrixWorld( force ) { 47642 47643 super.updateMatrixWorld( force ); 47644 47645 const listener = this.context.listener; 47646 const up = this.up; 47647 47648 this.timeDelta = this._clock.getDelta(); 47649 47650 this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 ); 47651 47652 _orientation$1.set( 0, 0, - 1 ).applyQuaternion( _quaternion$1 ); 47653 47654 if ( listener.positionX ) { 47655 47656 // code path for Chrome (see #14393) 47657 47658 const endTime = this.context.currentTime + this.timeDelta; 47659 47660 listener.positionX.linearRampToValueAtTime( _position$1.x, endTime ); 47661 listener.positionY.linearRampToValueAtTime( _position$1.y, endTime ); 47662 listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime ); 47663 listener.forwardX.linearRampToValueAtTime( _orientation$1.x, endTime ); 47664 listener.forwardY.linearRampToValueAtTime( _orientation$1.y, endTime ); 47665 listener.forwardZ.linearRampToValueAtTime( _orientation$1.z, endTime ); 47666 listener.upX.linearRampToValueAtTime( up.x, endTime ); 47667 listener.upY.linearRampToValueAtTime( up.y, endTime ); 47668 listener.upZ.linearRampToValueAtTime( up.z, endTime ); 47669 47670 } else { 47671 47672 listener.setPosition( _position$1.x, _position$1.y, _position$1.z ); 47673 listener.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z ); 47674 47675 } 47676 47677 } 47678 47679} 47680 47681class Audio extends Object3D { 47682 47683 constructor( listener ) { 47684 47685 super(); 47686 47687 this.type = 'Audio'; 47688 47689 this.listener = listener; 47690 this.context = listener.context; 47691 47692 this.gain = this.context.createGain(); 47693 this.gain.connect( listener.getInput() ); 47694 47695 this.autoplay = false; 47696 47697 this.buffer = null; 47698 this.detune = 0; 47699 this.loop = false; 47700 this.loopStart = 0; 47701 this.loopEnd = 0; 47702 this.offset = 0; 47703 this.duration = undefined; 47704 this.playbackRate = 1; 47705 this.isPlaying = false; 47706 this.hasPlaybackControl = true; 47707 this.source = null; 47708 this.sourceType = 'empty'; 47709 47710 this._startedAt = 0; 47711 this._progress = 0; 47712 this._connected = false; 47713 47714 this.filters = []; 47715 47716 } 47717 47718 getOutput() { 47719 47720 return this.gain; 47721 47722 } 47723 47724 setNodeSource( audioNode ) { 47725 47726 this.hasPlaybackControl = false; 47727 this.sourceType = 'audioNode'; 47728 this.source = audioNode; 47729 this.connect(); 47730 47731 return this; 47732 47733 } 47734 47735 setMediaElementSource( mediaElement ) { 47736 47737 this.hasPlaybackControl = false;
vendor: 8,682 bytes, lines 47738-48281
47738 this.sourceType = 'mediaNode'; 47739 this.source = this.context.createMediaElementSource( mediaElement ); 47740 this.connect(); 47741 47742 return this; 47743 47744 } 47745 47746 setMediaStreamSource( mediaStream ) { 47747 47748 this.hasPlaybackControl = false; 47749 this.sourceType = 'mediaStreamNode'; 47750 this.source = this.context.createMediaStreamSource( mediaStream ); 47751 this.connect(); 47752 47753 return this; 47754 47755 } 47756 47757 setBuffer( audioBuffer ) { 47758 47759 this.buffer = audioBuffer; 47760 this.sourceType = 'buffer'; 47761 47762 if ( this.autoplay ) this.play(); 47763 47764 return this; 47765 47766 } 47767 47768 play( delay = 0 ) { 47769 47770 if ( this.isPlaying === true ) { 47771 47772 console.warn( 'THREE.Audio: Audio is already playing.' ); 47773 return; 47774 47775 } 47776 47777 if ( this.hasPlaybackControl === false ) { 47778 47779 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47780 return; 47781 47782 } 47783 47784 this._startedAt = this.context.currentTime + delay; 47785 47786 const source = this.context.createBufferSource(); 47787 source.buffer = this.buffer; 47788 source.loop = this.loop; 47789 source.loopStart = this.loopStart; 47790 source.loopEnd = this.loopEnd; 47791 source.onended = this.onEnded.bind( this ); 47792 source.start( this._startedAt, this._progress + this.offset, this.duration ); 47793 47794 this.isPlaying = true; 47795 47796 this.source = source; 47797 47798 this.setDetune( this.detune ); 47799 this.setPlaybackRate( this.playbackRate ); 47800 47801 return this.connect(); 47802 47803 } 47804 47805 pause() { 47806 47807 if ( this.hasPlaybackControl === false ) { 47808 47809 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47810 return; 47811 47812 } 47813 47814 if ( this.isPlaying === true ) { 47815 47816 // update current progress 47817 47818 this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate; 47819 47820 if ( this.loop === true ) { 47821 47822 // ensure _progress does not exceed duration with looped audios 47823 47824 this._progress = this._progress % ( this.duration || this.buffer.duration ); 47825 47826 } 47827 47828 this.source.stop(); 47829 this.source.onended = null; 47830 47831 this.isPlaying = false; 47832 47833 } 47834 47835 return this; 47836 47837 } 47838 47839 stop() { 47840 47841 if ( this.hasPlaybackControl === false ) { 47842 47843 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47844 return; 47845 47846 } 47847 47848 this._progress = 0; 47849 47850 if ( this.source !== null ) { 47851 47852 this.source.stop(); 47853 this.source.onended = null; 47854 47855 } 47856 47857 this.isPlaying = false; 47858 47859 return this; 47860 47861 } 47862 47863 connect() { 47864 47865 if ( this.filters.length > 0 ) { 47866 47867 this.source.connect( this.filters[ 0 ] ); 47868 47869 for ( let i = 1, l = this.filters.length; i < l; i ++ ) { 47870 47871 this.filters[ i - 1 ].connect( this.filters[ i ] ); 47872 47873 } 47874 47875 this.filters[ this.filters.length - 1 ].connect( this.getOutput() ); 47876 47877 } else { 47878 47879 this.source.connect( this.getOutput() ); 47880 47881 } 47882 47883 this._connected = true; 47884 47885 return this; 47886 47887 } 47888 47889 disconnect() { 47890 47891 if ( this._connected === false ) { 47892 47893 return; 47894 47895 } 47896 47897 if ( this.filters.length > 0 ) { 47898 47899 this.source.disconnect( this.filters[ 0 ] ); 47900 47901 for ( let i = 1, l = this.filters.length; i < l; i ++ ) { 47902 47903 this.filters[ i - 1 ].disconnect( this.filters[ i ] ); 47904 47905 } 47906 47907 this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() ); 47908 47909 } else { 47910 47911 this.source.disconnect( this.getOutput() ); 47912 47913 } 47914 47915 this._connected = false; 47916 47917 return this; 47918 47919 } 47920 47921 getFilters() { 47922 47923 return this.filters; 47924 47925 } 47926 47927 setFilters( value ) { 47928 47929 if ( ! value ) value = []; 47930 47931 if ( this._connected === true ) { 47932 47933 this.disconnect(); 47934 this.filters = value.slice(); 47935 this.connect(); 47936 47937 } else { 47938 47939 this.filters = value.slice(); 47940 47941 } 47942 47943 return this; 47944 47945 } 47946 47947 setDetune( value ) { 47948 47949 this.detune = value; 47950 47951 if ( this.isPlaying === true && this.source.detune !== undefined ) { 47952 47953 this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 ); 47954 47955 } 47956 47957 return this; 47958 47959 } 47960 47961 getDetune() { 47962 47963 return this.detune; 47964 47965 } 47966 47967 getFilter() { 47968 47969 return this.getFilters()[ 0 ]; 47970 47971 } 47972 47973 setFilter( filter ) { 47974 47975 return this.setFilters( filter ? [ filter ] : [] ); 47976 47977 } 47978 47979 setPlaybackRate( value ) { 47980 47981 if ( this.hasPlaybackControl === false ) { 47982 47983 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47984 return; 47985 47986 } 47987 47988 this.playbackRate = value; 47989 47990 if ( this.isPlaying === true ) { 47991 47992 this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 ); 47993 47994 } 47995 47996 return this; 47997 47998 } 47999 48000 getPlaybackRate() { 48001 48002 return this.playbackRate; 48003 48004 } 48005 48006 onEnded() { 48007 48008 this.isPlaying = false; 48009 48010 } 48011 48012 getLoop() { 48013 48014 if ( this.hasPlaybackControl === false ) { 48015 48016 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 48017 return false; 48018 48019 } 48020 48021 return this.loop; 48022 48023 } 48024 48025 setLoop( value ) { 48026 48027 if ( this.hasPlaybackControl === false ) { 48028 48029 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 48030 return; 48031 48032 } 48033 48034 this.loop = value; 48035 48036 if ( this.isPlaying === true ) { 48037 48038 this.source.loop = this.loop; 48039 48040 } 48041 48042 return this; 48043 48044 } 48045 48046 setLoopStart( value ) { 48047 48048 this.loopStart = value; 48049 48050 return this; 48051 48052 } 48053 48054 setLoopEnd( value ) { 48055 48056 this.loopEnd = value; 48057 48058 return this; 48059 48060 } 48061 48062 getVolume() { 48063 48064 return this.gain.gain.value; 48065 48066 } 48067 48068 setVolume( value ) { 48069 48070 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); 48071 48072 return this; 48073 48074 } 48075 48076} 48077 48078const _position = /*@__PURE__*/ new Vector3(); 48079const _quaternion = /*@__PURE__*/ new Quaternion(); 48080const _scale = /*@__PURE__*/ new Vector3(); 48081const _orientation = /*@__PURE__*/ new Vector3(); 48082 48083class PositionalAudio extends Audio { 48084 48085 constructor( listener ) { 48086 48087 super( listener ); 48088 48089 this.panner = this.context.createPanner(); 48090 this.panner.panningModel = 'HRTF'; 48091 this.panner.connect( this.gain ); 48092 48093 } 48094 48095 connect() { 48096 48097 super.connect(); 48098 48099 this.panner.connect( this.gain ); 48100 48101 } 48102 48103 disconnect() { 48104 48105 super.disconnect(); 48106 48107 this.panner.disconnect( this.gain ); 48108 48109 } 48110 48111 getOutput() { 48112 48113 return this.panner; 48114 48115 } 48116 48117 getRefDistance() { 48118 48119 return this.panner.refDistance; 48120 48121 } 48122 48123 setRefDistance( value ) { 48124 48125 this.panner.refDistance = value; 48126 48127 return this; 48128 48129 } 48130 48131 getRolloffFactor() { 48132 48133 return this.panner.rolloffFactor; 48134 48135 } 48136 48137 setRolloffFactor( value ) { 48138 48139 this.panner.rolloffFactor = value; 48140 48141 return this; 48142 48143 } 48144 48145 getDistanceModel() { 48146 48147 return this.panner.distanceModel; 48148 48149 } 48150 48151 setDistanceModel( value ) { 48152 48153 this.panner.distanceModel = value; 48154 48155 return this; 48156 48157 } 48158 48159 getMaxDistance() { 48160 48161 return this.panner.maxDistance; 48162 48163 } 48164 48165 setMaxDistance( value ) { 48166 48167 this.panner.maxDistance = value; 48168 48169 return this; 48170 48171 } 48172 48173 setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) { 48174 48175 this.panner.coneInnerAngle = coneInnerAngle; 48176 this.panner.coneOuterAngle = coneOuterAngle; 48177 this.panner.coneOuterGain = coneOuterGain; 48178 48179 return this; 48180 48181 } 48182 48183 updateMatrixWorld( force ) { 48184 48185 super.updateMatrixWorld( force ); 48186 48187 if ( this.hasPlaybackControl === true && this.isPlaying === false ) return; 48188 48189 this.matrixWorld.decompose( _position, _quaternion, _scale ); 48190 48191 _orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion ); 48192 48193 const panner = this.panner; 48194 48195 if ( panner.positionX ) { 48196 48197 // code path for Chrome and Firefox (see #14393) 48198 48199 const endTime = this.context.currentTime + this.listener.timeDelta; 48200 48201 panner.positionX.linearRampToValueAtTime( _position.x, endTime ); 48202 panner.positionY.linearRampToValueAtTime( _position.y, endTime ); 48203 panner.positionZ.linearRampToValueAtTime( _position.z, endTime ); 48204 panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime ); 48205 panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime ); 48206 panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime ); 48207 48208 } else { 48209 48210 panner.setPosition( _position.x, _position.y, _position.z ); 48211 panner.setOrientation( _orientation.x, _orientation.y, _orientation.z ); 48212 48213 } 48214 48215 } 48216 48217} 48218 48219class AudioAnalyser { 48220 48221 constructor( audio, fftSize = 2048 ) { 48222 48223 this.analyser = audio.context.createAnalyser(); 48224 this.analyser.fftSize = fftSize; 48225 48226 this.data = new Uint8Array( this.analyser.frequencyBinCount ); 48227 48228 audio.getOutput().connect( this.analyser ); 48229 48230 } 48231 48232 48233 getFrequencyData() { 48234 48235 this.analyser.getByteFrequencyData( this.data ); 48236 48237 return this.data; 48238 48239 } 48240 48241 getAverageFrequency() { 48242 48243 let value = 0; 48244 const data = this.getFrequencyData(); 48245 48246 for ( let i = 0; i < data.length; i ++ ) { 48247 48248 value += data[ i ]; 48249 48250 } 48251 48252 return value / data.length; 48253 48254 } 48255 48256} 48257 48258class PropertyMixer { 48259 48260 constructor( binding, typeName, valueSize ) { 48261 48262 this.binding = binding; 48263 this.valueSize = valueSize; 48264 48265 let mixFunction, 48266 mixFunctionAdditive, 48267 setIdentity; 48268 48269 // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ] 48270 // 48271 // interpolators can use .buffer as their .result 48272 // the data then goes to 'incoming' 48273 // 48274 // 'accu0' and 'accu1' are used frame-interleaved for 48275 // the cumulative result and are compared to detect 48276 // changes 48277 // 48278 // 'orig' stores the original state of the property 48279 // 48280 // 'add' is used for additive cumulative results 48281 //
vendor: 13,778 bytes, lines 48282-48912
48282 // 'work' is optional and is only present for quaternion types. It is used 48283 // to store intermediate quaternion multiplication results 48284 48285 switch ( typeName ) { 48286 48287 case 'quaternion': 48288 mixFunction = this._slerp; 48289 mixFunctionAdditive = this._slerpAdditive; 48290 setIdentity = this._setAdditiveIdentityQuaternion; 48291 48292 this.buffer = new Float64Array( valueSize * 6 ); 48293 this._workIndex = 5; 48294 break; 48295 48296 case 'string': 48297 case 'bool': 48298 mixFunction = this._select; 48299 48300 // Use the regular mix function and for additive on these types, 48301 // additive is not relevant for non-numeric types 48302 mixFunctionAdditive = this._select; 48303 48304 setIdentity = this._setAdditiveIdentityOther; 48305 48306 this.buffer = new Array( valueSize * 5 ); 48307 break; 48308 48309 default: 48310 mixFunction = this._lerp; 48311 mixFunctionAdditive = this._lerpAdditive; 48312 setIdentity = this._setAdditiveIdentityNumeric; 48313 48314 this.buffer = new Float64Array( valueSize * 5 ); 48315 48316 } 48317 48318 this._mixBufferRegion = mixFunction; 48319 this._mixBufferRegionAdditive = mixFunctionAdditive; 48320 this._setIdentity = setIdentity; 48321 this._origIndex = 3; 48322 this._addIndex = 4; 48323 48324 this.cumulativeWeight = 0; 48325 this.cumulativeWeightAdditive = 0; 48326 48327 this.useCount = 0; 48328 this.referenceCount = 0; 48329 48330 } 48331 48332 // accumulate data in the 'incoming' region into 'accu<i>' 48333 accumulate( accuIndex, weight ) { 48334 48335 // note: happily accumulating nothing when weight = 0, the caller knows 48336 // the weight and shouldn't have made the call in the first place 48337 48338 const buffer = this.buffer, 48339 stride = this.valueSize, 48340 offset = accuIndex * stride + stride; 48341 48342 let currentWeight = this.cumulativeWeight; 48343 48344 if ( currentWeight === 0 ) { 48345 48346 // accuN := incoming * weight 48347 48348 for ( let i = 0; i !== stride; ++ i ) { 48349 48350 buffer[ offset + i ] = buffer[ i ]; 48351 48352 } 48353 48354 currentWeight = weight; 48355 48356 } else { 48357 48358 // accuN := accuN + incoming * weight 48359 48360 currentWeight += weight; 48361 const mix = weight / currentWeight; 48362 this._mixBufferRegion( buffer, offset, 0, mix, stride ); 48363 48364 } 48365 48366 this.cumulativeWeight = currentWeight; 48367 48368 } 48369 48370 // accumulate data in the 'incoming' region into 'add' 48371 accumulateAdditive( weight ) { 48372 48373 const buffer = this.buffer, 48374 stride = this.valueSize, 48375 offset = stride * this._addIndex; 48376 48377 if ( this.cumulativeWeightAdditive === 0 ) { 48378 48379 // add = identity 48380 48381 this._setIdentity(); 48382 48383 } 48384 48385 // add := add + incoming * weight 48386 48387 this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride ); 48388 this.cumulativeWeightAdditive += weight; 48389 48390 } 48391 48392 // apply the state of 'accu<i>' to the binding when accus differ 48393 apply( accuIndex ) { 48394 48395 const stride = this.valueSize, 48396 buffer = this.buffer, 48397 offset = accuIndex * stride + stride, 48398 48399 weight = this.cumulativeWeight, 48400 weightAdditive = this.cumulativeWeightAdditive, 48401 48402 binding = this.binding; 48403 48404 this.cumulativeWeight = 0; 48405 this.cumulativeWeightAdditive = 0; 48406 48407 if ( weight < 1 ) { 48408 48409 // accuN := accuN + original * ( 1 - cumulativeWeight ) 48410 48411 const originalValueOffset = stride * this._origIndex; 48412 48413 this._mixBufferRegion( 48414 buffer, offset, originalValueOffset, 1 - weight, stride ); 48415 48416 } 48417 48418 if ( weightAdditive > 0 ) { 48419 48420 // accuN := accuN + additive accuN 48421 48422 this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride ); 48423 48424 } 48425 48426 for ( let i = stride, e = stride + stride; i !== e; ++ i ) { 48427 48428 if ( buffer[ i ] !== buffer[ i + stride ] ) { 48429 48430 // value has changed -> update scene graph 48431 48432 binding.setValue( buffer, offset ); 48433 break; 48434 48435 } 48436 48437 } 48438 48439 } 48440 48441 // remember the state of the bound property and copy it to both accus 48442 saveOriginalState() { 48443 48444 const binding = this.binding; 48445 48446 const buffer = this.buffer, 48447 stride = this.valueSize, 48448 48449 originalValueOffset = stride * this._origIndex; 48450 48451 binding.getValue( buffer, originalValueOffset ); 48452 48453 // accu[0..1] := orig -- initially detect changes against the original 48454 for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) { 48455 48456 buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ]; 48457 48458 } 48459 48460 // Add to identity for additive 48461 this._setIdentity(); 48462 48463 this.cumulativeWeight = 0; 48464 this.cumulativeWeightAdditive = 0; 48465 48466 } 48467 48468 // apply the state previously taken via 'saveOriginalState' to the binding 48469 restoreOriginalState() { 48470 48471 const originalValueOffset = this.valueSize * 3; 48472 this.binding.setValue( this.buffer, originalValueOffset ); 48473 48474 } 48475 48476 _setAdditiveIdentityNumeric() { 48477 48478 const startIndex = this._addIndex * this.valueSize; 48479 const endIndex = startIndex + this.valueSize; 48480 48481 for ( let i = startIndex; i < endIndex; i ++ ) { 48482 48483 this.buffer[ i ] = 0; 48484 48485 } 48486 48487 } 48488 48489 _setAdditiveIdentityQuaternion() { 48490 48491 this._setAdditiveIdentityNumeric(); 48492 this.buffer[ this._addIndex * this.valueSize + 3 ] = 1; 48493 48494 } 48495 48496 _setAdditiveIdentityOther() { 48497 48498 const startIndex = this._origIndex * this.valueSize; 48499 const targetIndex = this._addIndex * this.valueSize; 48500 48501 for ( let i = 0; i < this.valueSize; i ++ ) { 48502 48503 this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ]; 48504 48505 } 48506 48507 } 48508 48509 48510 // mix functions 48511 48512 _select( buffer, dstOffset, srcOffset, t, stride ) { 48513 48514 if ( t >= 0.5 ) { 48515 48516 for ( let i = 0; i !== stride; ++ i ) { 48517 48518 buffer[ dstOffset + i ] = buffer[ srcOffset + i ]; 48519 48520 } 48521 48522 } 48523 48524 } 48525 48526 _slerp( buffer, dstOffset, srcOffset, t ) { 48527 48528 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t ); 48529 48530 } 48531 48532 _slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { 48533 48534 const workOffset = this._workIndex * stride; 48535 48536 // Store result in intermediate buffer offset 48537 Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset ); 48538 48539 // Slerp to the intermediate result 48540 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t ); 48541 48542 } 48543 48544 _lerp( buffer, dstOffset, srcOffset, t, stride ) { 48545 48546 const s = 1 - t; 48547 48548 for ( let i = 0; i !== stride; ++ i ) { 48549 48550 const j = dstOffset + i; 48551 48552 buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t; 48553 48554 } 48555 48556 } 48557 48558 _lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { 48559 48560 for ( let i = 0; i !== stride; ++ i ) { 48561 48562 const j = dstOffset + i; 48563 48564 buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t; 48565 48566 } 48567 48568 } 48569 48570} 48571 48572// Characters [].:/ are reserved for track binding syntax. 48573const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/'; 48574const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' ); 48575 48576// Attempts to allow node names from any language. ES5's `\w` regexp matches 48577// only latin characters, and the unicode \p{L} is not yet supported. So 48578// instead, we exclude reserved characters and match everything else. 48579const _wordChar = '[^' + _RESERVED_CHARS_RE + ']'; 48580const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']'; 48581 48582// Parent directories, delimited by '/' or ':'. Currently unused, but must 48583// be matched to parse the rest of the track name. 48584const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar ); 48585 48586// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'. 48587const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot ); 48588 48589// Object on target node, and accessor. May not contain reserved 48590// characters. Accessor may contain any character except closing bracket. 48591const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar ); 48592 48593// Property and accessor. May not contain reserved characters. Accessor may 48594// contain any non-bracket characters. 48595const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar ); 48596 48597const _trackRe = new RegExp( '' 48598 + '^' 48599 + _directoryRe 48600 + _nodeRe 48601 + _objectRe 48602 + _propertyRe 48603 + '$' 48604); 48605 48606const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ]; 48607 48608class Composite { 48609 48610 constructor( targetGroup, path, optionalParsedPath ) { 48611 48612 const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); 48613 48614 this._targetGroup = targetGroup; 48615 this._bindings = targetGroup.subscribe_( path, parsedPath ); 48616 48617 } 48618 48619 getValue( array, offset ) { 48620 48621 this.bind(); // bind all binding 48622 48623 const firstValidIndex = this._targetGroup.nCachedObjects_, 48624 binding = this._bindings[ firstValidIndex ]; 48625 48626 // and only call .getValue on the first 48627 if ( binding !== undefined ) binding.getValue( array, offset ); 48628 48629 } 48630 48631 setValue( array, offset ) { 48632 48633 const bindings = this._bindings; 48634 48635 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { 48636 48637 bindings[ i ].setValue( array, offset ); 48638 48639 } 48640 48641 } 48642 48643 bind() { 48644 48645 const bindings = this._bindings; 48646 48647 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { 48648 48649 bindings[ i ].bind(); 48650 48651 } 48652 48653 } 48654 48655 unbind() { 48656 48657 const bindings = this._bindings; 48658 48659 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { 48660 48661 bindings[ i ].unbind(); 48662 48663 } 48664 48665 } 48666 48667} 48668 48669// Note: This class uses a State pattern on a per-method basis: 48670// 'bind' sets 'this.getValue' / 'setValue' and shadows the 48671// prototype version of these methods with one that represents 48672// the bound state. When the property is not found, the methods 48673// become no-ops. 48674class PropertyBinding { 48675 48676 constructor( rootNode, path, parsedPath ) { 48677 48678 this.path = path; 48679 this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); 48680 48681 this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ); 48682 48683 this.rootNode = rootNode; 48684 48685 // initial state of these methods that calls 'bind' 48686 this.getValue = this._getValue_unbound; 48687 this.setValue = this._setValue_unbound; 48688 48689 } 48690 48691 48692 static create( root, path, parsedPath ) { 48693 48694 if ( ! ( root && root.isAnimationObjectGroup ) ) { 48695 48696 return new PropertyBinding( root, path, parsedPath ); 48697 48698 } else { 48699 48700 return new PropertyBinding.Composite( root, path, parsedPath ); 48701 48702 } 48703 48704 } 48705 48706 /** 48707 * Replaces spaces with underscores and removes unsupported characters from 48708 * node names, to ensure compatibility with parseTrackName(). 48709 * 48710 * @param {string} name Node name to be sanitized. 48711 * @return {string} 48712 */ 48713 static sanitizeNodeName( name ) { 48714 48715 return name.replace( /\s/g, '_' ).replace( _reservedRe, '' ); 48716 48717 } 48718 48719 static parseTrackName( trackName ) { 48720 48721 const matches = _trackRe.exec( trackName ); 48722 48723 if ( matches === null ) { 48724 48725 throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName ); 48726 48727 } 48728 48729 const results = { 48730 // directoryName: matches[ 1 ], // (tschw) currently unused 48731 nodeName: matches[ 2 ], 48732 objectName: matches[ 3 ], 48733 objectIndex: matches[ 4 ], 48734 propertyName: matches[ 5 ], // required 48735 propertyIndex: matches[ 6 ] 48736 }; 48737 48738 const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' ); 48739 48740 if ( lastDot !== undefined && lastDot !== - 1 ) { 48741 48742 const objectName = results.nodeName.substring( lastDot + 1 ); 48743 48744 // Object names must be checked against an allowlist. Otherwise, there 48745 // is no way to parse 'foo.bar.baz': 'baz' must be a property, but 48746 // 'bar' could be the objectName, or part of a nodeName (which can 48747 // include '.' characters). 48748 if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) { 48749 48750 results.nodeName = results.nodeName.substring( 0, lastDot ); 48751 results.objectName = objectName; 48752 48753 } 48754 48755 } 48756 48757 if ( results.propertyName === null || results.propertyName.length === 0 ) { 48758 48759 throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName ); 48760 48761 } 48762 48763 return results; 48764 48765 } 48766 48767 static findNode( root, nodeName ) { 48768 48769 if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { 48770 48771 return root; 48772 48773 } 48774 48775 // search into skeleton bones. 48776 if ( root.skeleton ) { 48777 48778 const bone = root.skeleton.getBoneByName( nodeName ); 48779 48780 if ( bone !== undefined ) { 48781 48782 return bone; 48783 48784 } 48785 48786 } 48787 48788 // search into node subtree. 48789 if ( root.children ) { 48790 48791 const searchNodeSubtree = function ( children ) { 48792 48793 for ( let i = 0; i < children.length; i ++ ) { 48794 48795 const childNode = children[ i ]; 48796 48797 if ( childNode.name === nodeName || childNode.uuid === nodeName ) { 48798 48799 return childNode; 48800 48801 } 48802 48803 const result = searchNodeSubtree( childNode.children ); 48804 48805 if ( result ) return result; 48806 48807 } 48808 48809 return null; 48810 48811 }; 48812 48813 const subTreeNode = searchNodeSubtree( root.children ); 48814 48815 if ( subTreeNode ) { 48816 48817 return subTreeNode; 48818 48819 } 48820 48821 } 48822 48823 return null; 48824 48825 } 48826 48827 // these are used to "bind" a nonexistent property 48828 _getValue_unavailable() {} 48829 _setValue_unavailable() {} 48830 48831 // Getters 48832 48833 _getValue_direct( buffer, offset ) { 48834 48835 buffer[ offset ] = this.targetObject[ this.propertyName ]; 48836 48837 } 48838 48839 _getValue_array( buffer, offset ) { 48840 48841 const source = this.resolvedProperty; 48842 48843 for ( let i = 0, n = source.length; i !== n; ++ i ) { 48844 48845 buffer[ offset ++ ] = source[ i ]; 48846 48847 } 48848 48849 } 48850 48851 _getValue_arrayElement( buffer, offset ) { 48852 48853 buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; 48854 48855 } 48856 48857 _getValue_toArray( buffer, offset ) { 48858 48859 this.resolvedProperty.toArray( buffer, offset ); 48860 48861 } 48862 48863 // Direct 48864 48865 _setValue_direct( buffer, offset ) { 48866 48867 this.targetObject[ this.propertyName ] = buffer[ offset ]; 48868 48869 } 48870 48871 _setValue_direct_setNeedsUpdate( buffer, offset ) { 48872 48873 this.targetObject[ this.propertyName ] = buffer[ offset ]; 48874 this.targetObject.needsUpdate = true; 48875 48876 } 48877 48878 _setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { 48879 48880 this.targetObject[ this.propertyName ] = buffer[ offset ]; 48881 this.targetObject.matrixWorldNeedsUpdate = true; 48882 48883 } 48884 48885 // EntireArray 48886 48887 _setValue_array( buffer, offset ) { 48888 48889 const dest = this.resolvedProperty; 48890 48891 for ( let i = 0, n = dest.length; i !== n; ++ i ) { 48892 48893 dest[ i ] = buffer[ offset ++ ]; 48894 48895 } 48896 48897 } 48898 48899 _setValue_array_setNeedsUpdate( buffer, offset ) { 48900 48901 const dest = this.resolvedProperty; 48902 48903 for ( let i = 0, n = dest.length; i !== n; ++ i ) { 48904 48905 dest[ i ] = buffer[ offset ++ ]; 48906 48907 } 48908 48909 this.targetObject.needsUpdate = true; 48910 48911 } 48912
vendor: 8,185 bytes, lines 48913-49268
48913 _setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { 48914 48915 const dest = this.resolvedProperty; 48916 48917 for ( let i = 0, n = dest.length; i !== n; ++ i ) { 48918 48919 dest[ i ] = buffer[ offset ++ ]; 48920 48921 } 48922 48923 this.targetObject.matrixWorldNeedsUpdate = true; 48924 48925 } 48926 48927 // ArrayElement 48928 48929 _setValue_arrayElement( buffer, offset ) { 48930 48931 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 48932 48933 } 48934 48935 _setValue_arrayElement_setNeedsUpdate( buffer, offset ) { 48936 48937 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 48938 this.targetObject.needsUpdate = true; 48939 48940 } 48941 48942 _setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { 48943 48944 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 48945 this.targetObject.matrixWorldNeedsUpdate = true; 48946 48947 } 48948 48949 // HasToFromArray 48950 48951 _setValue_fromArray( buffer, offset ) { 48952 48953 this.resolvedProperty.fromArray( buffer, offset ); 48954 48955 } 48956 48957 _setValue_fromArray_setNeedsUpdate( buffer, offset ) { 48958 48959 this.resolvedProperty.fromArray( buffer, offset ); 48960 this.targetObject.needsUpdate = true; 48961 48962 } 48963 48964 _setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { 48965 48966 this.resolvedProperty.fromArray( buffer, offset ); 48967 this.targetObject.matrixWorldNeedsUpdate = true; 48968 48969 } 48970 48971 _getValue_unbound( targetArray, offset ) { 48972 48973 this.bind(); 48974 this.getValue( targetArray, offset ); 48975 48976 } 48977 48978 _setValue_unbound( sourceArray, offset ) { 48979 48980 this.bind(); 48981 this.setValue( sourceArray, offset ); 48982 48983 } 48984 48985 // create getter / setter pair for a property in the scene graph 48986 bind() { 48987 48988 let targetObject = this.node; 48989 const parsedPath = this.parsedPath; 48990 48991 const objectName = parsedPath.objectName; 48992 const propertyName = parsedPath.propertyName; 48993 let propertyIndex = parsedPath.propertyIndex; 48994 48995 if ( ! targetObject ) { 48996 48997 targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ); 48998 48999 this.node = targetObject; 49000 49001 } 49002 49003 // set fail state so we can just 'return' on error 49004 this.getValue = this._getValue_unavailable; 49005 this.setValue = this._setValue_unavailable; 49006 49007 // ensure there is a value node 49008 if ( ! targetObject ) { 49009 49010 console.warn( 'THREE.PropertyBinding: No target node found for track: ' + this.path + '.' ); 49011 return; 49012 49013 } 49014 49015 if ( objectName ) { 49016 49017 let objectIndex = parsedPath.objectIndex; 49018 49019 // special cases were we need to reach deeper into the hierarchy to get the face materials.... 49020 switch ( objectName ) { 49021 49022 case 'materials': 49023 49024 if ( ! targetObject.material ) { 49025 49026 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); 49027 return; 49028 49029 } 49030 49031 if ( ! targetObject.material.materials ) { 49032 49033 console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this ); 49034 return; 49035 49036 } 49037 49038 targetObject = targetObject.material.materials; 49039 49040 break; 49041 49042 case 'bones': 49043 49044 if ( ! targetObject.skeleton ) { 49045 49046 console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this ); 49047 return; 49048 49049 } 49050 49051 // potential future optimization: skip this if propertyIndex is already an integer 49052 // and convert the integer string to a true integer. 49053 49054 targetObject = targetObject.skeleton.bones; 49055 49056 // support resolving morphTarget names into indices. 49057 for ( let i = 0; i < targetObject.length; i ++ ) { 49058 49059 if ( targetObject[ i ].name === objectIndex ) { 49060 49061 objectIndex = i; 49062 break; 49063 49064 } 49065 49066 } 49067 49068 break; 49069 49070 case 'map': 49071 49072 if ( 'map' in targetObject ) { 49073 49074 targetObject = targetObject.map; 49075 break; 49076 49077 } 49078 49079 if ( ! targetObject.material ) { 49080 49081 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); 49082 return; 49083 49084 } 49085 49086 if ( ! targetObject.material.map ) { 49087 49088 console.error( 'THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.', this ); 49089 return; 49090 49091 } 49092 49093 targetObject = targetObject.material.map; 49094 break; 49095 49096 default: 49097 49098 if ( targetObject[ objectName ] === undefined ) { 49099 49100 console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this ); 49101 return; 49102 49103 } 49104 49105 targetObject = targetObject[ objectName ]; 49106 49107 } 49108 49109 49110 if ( objectIndex !== undefined ) { 49111 49112 if ( targetObject[ objectIndex ] === undefined ) { 49113 49114 console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject ); 49115 return; 49116 49117 } 49118 49119 targetObject = targetObject[ objectIndex ]; 49120 49121 } 49122 49123 } 49124 49125 // resolve property 49126 const nodeProperty = targetObject[ propertyName ]; 49127 49128 if ( nodeProperty === undefined ) { 49129 49130 const nodeName = parsedPath.nodeName; 49131 49132 console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName + 49133 '.' + propertyName + ' but it wasn\'t found.', targetObject ); 49134 return; 49135 49136 } 49137 49138 // determine versioning scheme 49139 let versioning = this.Versioning.None; 49140 49141 this.targetObject = targetObject; 49142 49143 if ( targetObject.needsUpdate !== undefined ) { // material 49144 49145 versioning = this.Versioning.NeedsUpdate; 49146 49147 } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform 49148 49149 versioning = this.Versioning.MatrixWorldNeedsUpdate; 49150 49151 } 49152 49153 // determine how the property gets bound 49154 let bindingType = this.BindingType.Direct; 49155 49156 if ( propertyIndex !== undefined ) { 49157 49158 // access a sub element of the property array (only primitives are supported right now) 49159 49160 if ( propertyName === 'morphTargetInfluences' ) { 49161 49162 // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer. 49163 49164 // support resolving morphTarget names into indices. 49165 if ( ! targetObject.geometry ) { 49166 49167 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this ); 49168 return; 49169 49170 } 49171 49172 if ( ! targetObject.geometry.morphAttributes ) { 49173 49174 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this ); 49175 return; 49176 49177 } 49178 49179 if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) { 49180 49181 propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ]; 49182 49183 } 49184 49185 } 49186 49187 bindingType = this.BindingType.ArrayElement; 49188 49189 this.resolvedProperty = nodeProperty; 49190 this.propertyIndex = propertyIndex; 49191 49192 } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) { 49193 49194 // must use copy for Object3D.Euler/Quaternion 49195 49196 bindingType = this.BindingType.HasFromToArray; 49197 49198 this.resolvedProperty = nodeProperty; 49199 49200 } else if ( Array.isArray( nodeProperty ) ) { 49201 49202 bindingType = this.BindingType.EntireArray; 49203 49204 this.resolvedProperty = nodeProperty; 49205 49206 } else { 49207 49208 this.propertyName = propertyName; 49209 49210 } 49211 49212 // select getter / setter 49213 this.getValue = this.GetterByBindingType[ bindingType ]; 49214 this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; 49215 49216 } 49217 49218 unbind() { 49219 49220 this.node = null; 49221 49222 // back to the prototype version of getValue / setValue 49223 // note: avoiding to mutate the shape of 'this' via 'delete' 49224 this.getValue = this._getValue_unbound; 49225 this.setValue = this._setValue_unbound; 49226 49227 } 49228 49229} 49230 49231PropertyBinding.Composite = Composite; 49232 49233PropertyBinding.prototype.BindingType = { 49234 Direct: 0, 49235 EntireArray: 1, 49236 ArrayElement: 2, 49237 HasFromToArray: 3 49238}; 49239 49240PropertyBinding.prototype.Versioning = { 49241 None: 0, 49242 NeedsUpdate: 1, 49243 MatrixWorldNeedsUpdate: 2 49244}; 49245 49246PropertyBinding.prototype.GetterByBindingType = [ 49247 49248 PropertyBinding.prototype._getValue_direct, 49249 PropertyBinding.prototype._getValue_array, 49250 PropertyBinding.prototype._getValue_arrayElement, 49251 PropertyBinding.prototype._getValue_toArray, 49252 49253]; 49254 49255PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [ 49256 49257 [ 49258 // Direct 49259 PropertyBinding.prototype._setValue_direct, 49260 PropertyBinding.prototype._setValue_direct_setNeedsUpdate, 49261 PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate, 49262 49263 ], [ 49264 49265 // EntireArray 49266 49267 PropertyBinding.prototype._setValue_array, 49268 PropertyBinding.prototype._setValue_array_setNeedsUpdate,
vendor: 4,282 bytes, lines 49269-49449
49269 PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate, 49270 49271 ], [ 49272 49273 // ArrayElement 49274 PropertyBinding.prototype._setValue_arrayElement, 49275 PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate, 49276 PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate, 49277 49278 ], [ 49279 49280 // HasToFromArray 49281 PropertyBinding.prototype._setValue_fromArray, 49282 PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate, 49283 PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate, 49284 49285 ] 49286 49287]; 49288 49289/** 49290 * 49291 * A group of objects that receives a shared animation state. 49292 * 49293 * Usage: 49294 * 49295 * - Add objects you would otherwise pass as 'root' to the 49296 * constructor or the .clipAction method of AnimationMixer. 49297 * 49298 * - Instead pass this object as 'root'. 49299 * 49300 * - You can also add and remove objects later when the mixer 49301 * is running. 49302 * 49303 * Note: 49304 * 49305 * Objects of this class appear as one object to the mixer, 49306 * so cache control of the individual objects must be done 49307 * on the group. 49308 * 49309 * Limitation: 49310 * 49311 * - The animated properties must be compatible among the 49312 * all objects in the group. 49313 * 49314 * - A single property can either be controlled through a 49315 * target group or directly, but not both. 49316 */ 49317 49318class AnimationObjectGroup { 49319 49320 constructor() { 49321 49322 this.isAnimationObjectGroup = true; 49323 49324 this.uuid = generateUUID(); 49325 49326 // cached objects followed by the active ones 49327 this._objects = Array.prototype.slice.call( arguments ); 49328 49329 this.nCachedObjects_ = 0; // threshold 49330 // note: read by PropertyBinding.Composite 49331 49332 const indices = {}; 49333 this._indicesByUUID = indices; // for bookkeeping 49334 49335 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 49336 49337 indices[ arguments[ i ].uuid ] = i; 49338 49339 } 49340 49341 this._paths = []; // inside: string 49342 this._parsedPaths = []; // inside: { we don't care, here } 49343 this._bindings = []; // inside: Array< PropertyBinding > 49344 this._bindingsIndicesByPath = {}; // inside: indices in these arrays 49345 49346 const scope = this; 49347 49348 this.stats = { 49349 49350 objects: { 49351 get total() { 49352 49353 return scope._objects.length; 49354 49355 }, 49356 get inUse() { 49357 49358 return this.total - scope.nCachedObjects_; 49359 49360 } 49361 }, 49362 get bindingsPerObject() { 49363 49364 return scope._bindings.length; 49365 49366 } 49367 49368 }; 49369 49370 } 49371 49372 add() { 49373 49374 const objects = this._objects, 49375 indicesByUUID = this._indicesByUUID, 49376 paths = this._paths, 49377 parsedPaths = this._parsedPaths, 49378 bindings = this._bindings, 49379 nBindings = bindings.length; 49380 49381 let knownObject = undefined, 49382 nObjects = objects.length, 49383 nCachedObjects = this.nCachedObjects_; 49384 49385 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 49386 49387 const object = arguments[ i ], 49388 uuid = object.uuid; 49389 let index = indicesByUUID[ uuid ]; 49390 49391 if ( index === undefined ) { 49392 49393 // unknown object -> add it to the ACTIVE region 49394 49395 index = nObjects ++; 49396 indicesByUUID[ uuid ] = index; 49397 objects.push( object ); 49398 49399 // accounting is done, now do the same for all bindings 49400 49401 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 49402 49403 bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); 49404 49405 } 49406 49407 } else if ( index < nCachedObjects ) { 49408 49409 knownObject = objects[ index ]; 49410 49411 // move existing object to the ACTIVE region 49412 49413 const firstActiveIndex = -- nCachedObjects, 49414 lastCachedObject = objects[ firstActiveIndex ]; 49415 49416 indicesByUUID[ lastCachedObject.uuid ] = index; 49417 objects[ index ] = lastCachedObject; 49418 49419 indicesByUUID[ uuid ] = firstActiveIndex; 49420 objects[ firstActiveIndex ] = object; 49421 49422 // accounting is done, now do the same for all bindings 49423 49424 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 49425 49426 const bindingsForPath = bindings[ j ], 49427 lastCached = bindingsForPath[ firstActiveIndex ]; 49428 49429 let binding = bindingsForPath[ index ]; 49430 49431 bindingsForPath[ index ] = lastCached; 49432 49433 if ( binding === undefined ) { 49434 49435 // since we do not bother to create new bindings 49436 // for objects that are cached, the binding may 49437 // or may not exist 49438 49439 binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); 49440 49441 } 49442 49443 bindingsForPath[ firstActiveIndex ] = binding; 49444 49445 } 49446 49447 } else if ( objects[ index ] !== knownObject ) { 49448 49449 console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
vendor: 4,120 bytes, lines 49450-49616
49450 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); 49451 49452 } // else the object is already where we want it to be 49453 49454 } // for arguments 49455 49456 this.nCachedObjects_ = nCachedObjects; 49457 49458 } 49459 49460 remove() { 49461 49462 const objects = this._objects, 49463 indicesByUUID = this._indicesByUUID, 49464 bindings = this._bindings, 49465 nBindings = bindings.length; 49466 49467 let nCachedObjects = this.nCachedObjects_; 49468 49469 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 49470 49471 const object = arguments[ i ], 49472 uuid = object.uuid, 49473 index = indicesByUUID[ uuid ]; 49474 49475 if ( index !== undefined && index >= nCachedObjects ) { 49476 49477 // move existing object into the CACHED region 49478 49479 const lastCachedIndex = nCachedObjects ++, 49480 firstActiveObject = objects[ lastCachedIndex ]; 49481 49482 indicesByUUID[ firstActiveObject.uuid ] = index; 49483 objects[ index ] = firstActiveObject; 49484 49485 indicesByUUID[ uuid ] = lastCachedIndex; 49486 objects[ lastCachedIndex ] = object; 49487 49488 // accounting is done, now do the same for all bindings 49489 49490 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 49491 49492 const bindingsForPath = bindings[ j ], 49493 firstActive = bindingsForPath[ lastCachedIndex ], 49494 binding = bindingsForPath[ index ]; 49495 49496 bindingsForPath[ index ] = firstActive; 49497 bindingsForPath[ lastCachedIndex ] = binding; 49498 49499 } 49500 49501 } 49502 49503 } // for arguments 49504 49505 this.nCachedObjects_ = nCachedObjects; 49506 49507 } 49508 49509 // remove & forget 49510 uncache() { 49511 49512 const objects = this._objects, 49513 indicesByUUID = this._indicesByUUID, 49514 bindings = this._bindings, 49515 nBindings = bindings.length; 49516 49517 let nCachedObjects = this.nCachedObjects_, 49518 nObjects = objects.length; 49519 49520 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 49521 49522 const object = arguments[ i ], 49523 uuid = object.uuid, 49524 index = indicesByUUID[ uuid ]; 49525 49526 if ( index !== undefined ) { 49527 49528 delete indicesByUUID[ uuid ]; 49529 49530 if ( index < nCachedObjects ) { 49531 49532 // object is cached, shrink the CACHED region 49533 49534 const firstActiveIndex = -- nCachedObjects, 49535 lastCachedObject = objects[ firstActiveIndex ], 49536 lastIndex = -- nObjects, 49537 lastObject = objects[ lastIndex ]; 49538 49539 // last cached object takes this object's place 49540 indicesByUUID[ lastCachedObject.uuid ] = index; 49541 objects[ index ] = lastCachedObject; 49542 49543 // last object goes to the activated slot and pop 49544 indicesByUUID[ lastObject.uuid ] = firstActiveIndex; 49545 objects[ firstActiveIndex ] = lastObject; 49546 objects.pop(); 49547 49548 // accounting is done, now do the same for all bindings 49549 49550 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 49551 49552 const bindingsForPath = bindings[ j ], 49553 lastCached = bindingsForPath[ firstActiveIndex ], 49554 last = bindingsForPath[ lastIndex ]; 49555 49556 bindingsForPath[ index ] = lastCached; 49557 bindingsForPath[ firstActiveIndex ] = last; 49558 bindingsForPath.pop(); 49559 49560 } 49561 49562 } else { 49563 49564 // object is active, just swap with the last and pop 49565 49566 const lastIndex = -- nObjects, 49567 lastObject = objects[ lastIndex ]; 49568 49569 if ( lastIndex > 0 ) { 49570 49571 indicesByUUID[ lastObject.uuid ] = index; 49572 49573 } 49574 49575 objects[ index ] = lastObject; 49576 objects.pop(); 49577 49578 // accounting is done, now do the same for all bindings 49579 49580 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 49581 49582 const bindingsForPath = bindings[ j ]; 49583 49584 bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; 49585 bindingsForPath.pop(); 49586 49587 } 49588 49589 } // cached or active 49590 49591 } // if object is known 49592 49593 } // for arguments 49594 49595 this.nCachedObjects_ = nCachedObjects; 49596 49597 } 49598 49599 // Internal interface used by befriended PropertyBinding.Composite: 49600 49601 subscribe_( path, parsedPath ) { 49602 49603 // returns an array of bindings for the given path that is changed 49604 // according to the contained objects in the group 49605 49606 const indicesByPath = this._bindingsIndicesByPath; 49607 let index = indicesByPath[ path ]; 49608 const bindings = this._bindings; 49609 49610 if ( index !== undefined ) return bindings[ index ]; 49611 49612 const paths = this._paths, 49613 parsedPaths = this._parsedPaths, 49614 objects = this._objects, 49615 nObjects = objects.length, 49616 nCachedObjects = this.nCachedObjects_,
vendor: 7,613 bytes, lines 49617-50010
49617 bindingsForPath = new Array( nObjects ); 49618 49619 index = bindings.length; 49620 49621 indicesByPath[ path ] = index; 49622 49623 paths.push( path ); 49624 parsedPaths.push( parsedPath ); 49625 bindings.push( bindingsForPath ); 49626 49627 for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) { 49628 49629 const object = objects[ i ]; 49630 bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); 49631 49632 } 49633 49634 return bindingsForPath; 49635 49636 } 49637 49638 unsubscribe_( path ) { 49639 49640 // tells the group to forget about a property path and no longer 49641 // update the array previously obtained with 'subscribe_' 49642 49643 const indicesByPath = this._bindingsIndicesByPath, 49644 index = indicesByPath[ path ]; 49645 49646 if ( index !== undefined ) { 49647 49648 const paths = this._paths, 49649 parsedPaths = this._parsedPaths, 49650 bindings = this._bindings, 49651 lastBindingsIndex = bindings.length - 1, 49652 lastBindings = bindings[ lastBindingsIndex ], 49653 lastBindingsPath = path[ lastBindingsIndex ]; 49654 49655 indicesByPath[ lastBindingsPath ] = index; 49656 49657 bindings[ index ] = lastBindings; 49658 bindings.pop(); 49659 49660 parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; 49661 parsedPaths.pop(); 49662 49663 paths[ index ] = paths[ lastBindingsIndex ]; 49664 paths.pop(); 49665 49666 } 49667 49668 } 49669 49670} 49671 49672class AnimationAction { 49673 49674 constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) { 49675 49676 this._mixer = mixer; 49677 this._clip = clip; 49678 this._localRoot = localRoot; 49679 this.blendMode = blendMode; 49680 49681 const tracks = clip.tracks, 49682 nTracks = tracks.length, 49683 interpolants = new Array( nTracks ); 49684 49685 const interpolantSettings = { 49686 endingStart: ZeroCurvatureEnding, 49687 endingEnd: ZeroCurvatureEnding 49688 }; 49689 49690 for ( let i = 0; i !== nTracks; ++ i ) { 49691 49692 const interpolant = tracks[ i ].createInterpolant( null ); 49693 interpolants[ i ] = interpolant; 49694 interpolant.settings = interpolantSettings; 49695 49696 } 49697 49698 this._interpolantSettings = interpolantSettings; 49699 49700 this._interpolants = interpolants; // bound by the mixer 49701 49702 // inside: PropertyMixer (managed by the mixer) 49703 this._propertyBindings = new Array( nTracks ); 49704 49705 this._cacheIndex = null; // for the memory manager 49706 this._byClipCacheIndex = null; // for the memory manager 49707 49708 this._timeScaleInterpolant = null; 49709 this._weightInterpolant = null; 49710 49711 this.loop = LoopRepeat; 49712 this._loopCount = - 1; 49713 49714 // global mixer time when the action is to be started 49715 // it's set back to 'null' upon start of the action 49716 this._startTime = null; 49717 49718 // scaled local time of the action 49719 // gets clamped or wrapped to 0..clip.duration according to loop 49720 this.time = 0; 49721 49722 this.timeScale = 1; 49723 this._effectiveTimeScale = 1; 49724 49725 this.weight = 1; 49726 this._effectiveWeight = 1; 49727 49728 this.repetitions = Infinity; // no. of repetitions when looping 49729 49730 this.paused = false; // true -> zero effective time scale 49731 this.enabled = true; // false -> zero effective weight 49732 49733 this.clampWhenFinished = false;// keep feeding the last frame? 49734 49735 this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate 49736 this.zeroSlopeAtEnd = true;// clips for start, loop and end 49737 49738 } 49739 49740 // State & Scheduling 49741 49742 play() { 49743 49744 this._mixer._activateAction( this ); 49745 49746 return this; 49747 49748 } 49749 49750 stop() { 49751 49752 this._mixer._deactivateAction( this ); 49753 49754 return this.reset(); 49755 49756 } 49757 49758 reset() { 49759 49760 this.paused = false; 49761 this.enabled = true; 49762 49763 this.time = 0; // restart clip 49764 this._loopCount = - 1;// forget previous loops 49765 this._startTime = null;// forget scheduling 49766 49767 return this.stopFading().stopWarping(); 49768 49769 } 49770 49771 isRunning() { 49772 49773 return this.enabled && ! this.paused && this.timeScale !== 0 && 49774 this._startTime === null && this._mixer._isActiveAction( this ); 49775 49776 } 49777 49778 // return true when play has been called 49779 isScheduled() { 49780 49781 return this._mixer._isActiveAction( this ); 49782 49783 } 49784 49785 startAt( time ) { 49786 49787 this._startTime = time; 49788 49789 return this; 49790 49791 } 49792 49793 setLoop( mode, repetitions ) { 49794 49795 this.loop = mode; 49796 this.repetitions = repetitions; 49797 49798 return this; 49799 49800 } 49801 49802 // Weight 49803 49804 // set the weight stopping any scheduled fading 49805 // although .enabled = false yields an effective weight of zero, this 49806 // method does *not* change .enabled, because it would be confusing 49807 setEffectiveWeight( weight ) { 49808 49809 this.weight = weight; 49810 49811 // note: same logic as when updated at runtime 49812 this._effectiveWeight = this.enabled ? weight : 0; 49813 49814 return this.stopFading(); 49815 49816 } 49817 49818 // return the weight considering fading and .enabled 49819 getEffectiveWeight() { 49820 49821 return this._effectiveWeight; 49822 49823 } 49824 49825 fadeIn( duration ) { 49826 49827 return this._scheduleFading( duration, 0, 1 ); 49828 49829 } 49830 49831 fadeOut( duration ) { 49832 49833 return this._scheduleFading( duration, 1, 0 ); 49834 49835 } 49836 49837 crossFadeFrom( fadeOutAction, duration, warp ) { 49838 49839 fadeOutAction.fadeOut( duration ); 49840 this.fadeIn( duration ); 49841 49842 if ( warp ) { 49843 49844 const fadeInDuration = this._clip.duration, 49845 fadeOutDuration = fadeOutAction._clip.duration, 49846 49847 startEndRatio = fadeOutDuration / fadeInDuration, 49848 endStartRatio = fadeInDuration / fadeOutDuration; 49849 49850 fadeOutAction.warp( 1.0, startEndRatio, duration ); 49851 this.warp( endStartRatio, 1.0, duration ); 49852 49853 } 49854 49855 return this; 49856 49857 } 49858 49859 crossFadeTo( fadeInAction, duration, warp ) { 49860 49861 return fadeInAction.crossFadeFrom( this, duration, warp ); 49862 49863 } 49864 49865 stopFading() { 49866 49867 const weightInterpolant = this._weightInterpolant; 49868 49869 if ( weightInterpolant !== null ) { 49870 49871 this._weightInterpolant = null; 49872 this._mixer._takeBackControlInterpolant( weightInterpolant ); 49873 49874 } 49875 49876 return this; 49877 49878 } 49879 49880 // Time Scale Control 49881 49882 // set the time scale stopping any scheduled warping 49883 // although .paused = true yields an effective time scale of zero, this 49884 // method does *not* change .paused, because it would be confusing 49885 setEffectiveTimeScale( timeScale ) { 49886 49887 this.timeScale = timeScale; 49888 this._effectiveTimeScale = this.paused ? 0 : timeScale; 49889 49890 return this.stopWarping(); 49891 49892 } 49893 49894 // return the time scale considering warping and .paused 49895 getEffectiveTimeScale() { 49896 49897 return this._effectiveTimeScale; 49898 49899 } 49900 49901 setDuration( duration ) { 49902 49903 this.timeScale = this._clip.duration / duration; 49904 49905 return this.stopWarping(); 49906 49907 } 49908 49909 syncWith( action ) { 49910 49911 this.time = action.time; 49912 this.timeScale = action.timeScale; 49913 49914 return this.stopWarping(); 49915 49916 } 49917 49918 halt( duration ) { 49919 49920 return this.warp( this._effectiveTimeScale, 0, duration ); 49921 49922 } 49923 49924 warp( startTimeScale, endTimeScale, duration ) { 49925 49926 const mixer = this._mixer, 49927 now = mixer.time, 49928 timeScale = this.timeScale; 49929 49930 let interpolant = this._timeScaleInterpolant; 49931 49932 if ( interpolant === null ) { 49933 49934 interpolant = mixer._lendControlInterpolant(); 49935 this._timeScaleInterpolant = interpolant; 49936 49937 } 49938 49939 const times = interpolant.parameterPositions, 49940 values = interpolant.sampleValues; 49941 49942 times[ 0 ] = now; 49943 times[ 1 ] = now + duration; 49944 49945 values[ 0 ] = startTimeScale / timeScale; 49946 values[ 1 ] = endTimeScale / timeScale; 49947 49948 return this; 49949 49950 } 49951 49952 stopWarping() { 49953 49954 const timeScaleInterpolant = this._timeScaleInterpolant; 49955 49956 if ( timeScaleInterpolant !== null ) { 49957 49958 this._timeScaleInterpolant = null; 49959 this._mixer._takeBackControlInterpolant( timeScaleInterpolant ); 49960 49961 } 49962 49963 return this; 49964 49965 } 49966 49967 // Object Accessors 49968 49969 getMixer() { 49970 49971 return this._mixer; 49972 49973 } 49974 49975 getClip() { 49976 49977 return this._clip; 49978 49979 } 49980 49981 getRoot() { 49982 49983 return this._localRoot || this._mixer._root; 49984 49985 } 49986 49987 // Interna 49988 49989 _update( time, deltaTime, timeDirection, accuIndex ) { 49990 49991 // called by the mixer 49992 49993 if ( ! this.enabled ) { 49994 49995 // call ._updateWeight() to update ._effectiveWeight 49996 49997 this._updateWeight( time ); 49998 return; 49999 50000 } 50001 50002 const startTime = this._startTime; 50003 50004 if ( startTime !== null ) { 50005 50006 // check for scheduled start of action 50007 50008 const timeRunning = ( time - startTime ) * timeDirection; 50009 if ( timeRunning < 0 || timeDirection === 0 ) { 50010
vendor: 6,044 bytes, lines 50011-50369
50011 deltaTime = 0; 50012 50013 } else { 50014 50015 50016 this._startTime = null; // unschedule 50017 deltaTime = timeDirection * timeRunning; 50018 50019 } 50020 50021 } 50022 50023 // apply time scale and advance time 50024 50025 deltaTime *= this._updateTimeScale( time ); 50026 const clipTime = this._updateTime( deltaTime ); 50027 50028 // note: _updateTime may disable the action resulting in 50029 // an effective weight of 0 50030 50031 const weight = this._updateWeight( time ); 50032 50033 if ( weight > 0 ) { 50034 50035 const interpolants = this._interpolants; 50036 const propertyMixers = this._propertyBindings; 50037 50038 switch ( this.blendMode ) { 50039 50040 case AdditiveAnimationBlendMode: 50041 50042 for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { 50043 50044 interpolants[ j ].evaluate( clipTime ); 50045 propertyMixers[ j ].accumulateAdditive( weight ); 50046 50047 } 50048 50049 break; 50050 50051 case NormalAnimationBlendMode: 50052 default: 50053 50054 for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { 50055 50056 interpolants[ j ].evaluate( clipTime ); 50057 propertyMixers[ j ].accumulate( accuIndex, weight ); 50058 50059 } 50060 50061 } 50062 50063 } 50064 50065 } 50066 50067 _updateWeight( time ) { 50068 50069 let weight = 0; 50070 50071 if ( this.enabled ) { 50072 50073 weight = this.weight; 50074 const interpolant = this._weightInterpolant; 50075 50076 if ( interpolant !== null ) { 50077 50078 const interpolantValue = interpolant.evaluate( time )[ 0 ]; 50079 50080 weight *= interpolantValue; 50081 50082 if ( time > interpolant.parameterPositions[ 1 ] ) { 50083 50084 this.stopFading(); 50085 50086 if ( interpolantValue === 0 ) { 50087 50088 // faded out, disable 50089 this.enabled = false; 50090 50091 } 50092 50093 } 50094 50095 } 50096 50097 } 50098 50099 this._effectiveWeight = weight; 50100 return weight; 50101 50102 } 50103 50104 _updateTimeScale( time ) { 50105 50106 let timeScale = 0; 50107 50108 if ( ! this.paused ) { 50109 50110 timeScale = this.timeScale; 50111 50112 const interpolant = this._timeScaleInterpolant; 50113 50114 if ( interpolant !== null ) { 50115 50116 const interpolantValue = interpolant.evaluate( time )[ 0 ]; 50117 50118 timeScale *= interpolantValue; 50119 50120 if ( time > interpolant.parameterPositions[ 1 ] ) { 50121 50122 this.stopWarping(); 50123 50124 if ( timeScale === 0 ) { 50125 50126 // motion has halted, pause 50127 this.paused = true; 50128 50129 } else { 50130 50131 // warp done - apply final time scale 50132 this.timeScale = timeScale; 50133 50134 } 50135 50136 } 50137 50138 } 50139 50140 } 50141 50142 this._effectiveTimeScale = timeScale; 50143 return timeScale; 50144 50145 } 50146 50147 _updateTime( deltaTime ) { 50148 50149 const duration = this._clip.duration; 50150 const loop = this.loop; 50151 50152 let time = this.time + deltaTime; 50153 let loopCount = this._loopCount; 50154 50155 const pingPong = ( loop === LoopPingPong ); 50156 50157 if ( deltaTime === 0 ) { 50158 50159 if ( loopCount === - 1 ) return time; 50160 50161 return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time; 50162 50163 } 50164 50165 if ( loop === LoopOnce ) { 50166 50167 if ( loopCount === - 1 ) { 50168 50169 // just started 50170 50171 this._loopCount = 0; 50172 this._setEndings( true, true, false ); 50173 50174 } 50175 50176 handle_stop: { 50177 50178 if ( time >= duration ) { 50179 50180 time = duration; 50181 50182 } else if ( time < 0 ) { 50183 50184 time = 0; 50185 50186 } else { 50187 50188 this.time = time; 50189 50190 break handle_stop; 50191 50192 } 50193 50194 if ( this.clampWhenFinished ) this.paused = true; 50195 else this.enabled = false; 50196 50197 this.time = time; 50198 50199 this._mixer.dispatchEvent( { 50200 type: 'finished', action: this, 50201 direction: deltaTime < 0 ? - 1 : 1 50202 } ); 50203 50204 } 50205 50206 } else { // repetitive Repeat or PingPong 50207 50208 if ( loopCount === - 1 ) { 50209 50210 // just started 50211 50212 if ( deltaTime >= 0 ) { 50213 50214 loopCount = 0; 50215 50216 this._setEndings( true, this.repetitions === 0, pingPong ); 50217 50218 } else { 50219 50220 // when looping in reverse direction, the initial 50221 // transition through zero counts as a repetition, 50222 // so leave loopCount at -1 50223 50224 this._setEndings( this.repetitions === 0, true, pingPong ); 50225 50226 } 50227 50228 } 50229 50230 if ( time >= duration || time < 0 ) { 50231 50232 // wrap around 50233 50234 const loopDelta = Math.floor( time / duration ); // signed 50235 time -= duration * loopDelta; 50236 50237 loopCount += Math.abs( loopDelta ); 50238 50239 const pending = this.repetitions - loopCount; 50240 50241 if ( pending <= 0 ) { 50242 50243 // have to stop (switch state, clamp time, fire event) 50244 50245 if ( this.clampWhenFinished ) this.paused = true; 50246 else this.enabled = false; 50247 50248 time = deltaTime > 0 ? duration : 0; 50249 50250 this.time = time; 50251 50252 this._mixer.dispatchEvent( { 50253 type: 'finished', action: this, 50254 direction: deltaTime > 0 ? 1 : - 1 50255 } ); 50256 50257 } else { 50258 50259 // keep running 50260 50261 if ( pending === 1 ) { 50262 50263 // entering the last round 50264 50265 const atStart = deltaTime < 0; 50266 this._setEndings( atStart, ! atStart, pingPong ); 50267 50268 } else { 50269 50270 this._setEndings( false, false, pingPong ); 50271 50272 } 50273 50274 this._loopCount = loopCount; 50275 50276 this.time = time; 50277 50278 this._mixer.dispatchEvent( { 50279 type: 'loop', action: this, loopDelta: loopDelta 50280 } ); 50281 50282 } 50283 50284 } else { 50285 50286 this.time = time; 50287 50288 } 50289 50290 if ( pingPong && ( loopCount & 1 ) === 1 ) { 50291 50292 // invert time for the "pong round" 50293 50294 return duration - time; 50295 50296 } 50297 50298 } 50299 50300 return time; 50301 50302 } 50303 50304 _setEndings( atStart, atEnd, pingPong ) { 50305 50306 const settings = this._interpolantSettings; 50307 50308 if ( pingPong ) { 50309 50310 settings.endingStart = ZeroSlopeEnding; 50311 settings.endingEnd = ZeroSlopeEnding; 50312 50313 } else { 50314 50315 // assuming for LoopOnce atStart == atEnd == true 50316 50317 if ( atStart ) { 50318 50319 settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding; 50320 50321 } else { 50322 50323 settings.endingStart = WrapAroundEnding; 50324 50325 } 50326 50327 if ( atEnd ) { 50328 50329 settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding; 50330 50331 } else { 50332 50333 settings.endingEnd = WrapAroundEnding; 50334 50335 } 50336 50337 } 50338 50339 } 50340 50341 _scheduleFading( duration, weightNow, weightThen ) { 50342 50343 const mixer = this._mixer, now = mixer.time; 50344 let interpolant = this._weightInterpolant; 50345 50346 if ( interpolant === null ) { 50347 50348 interpolant = mixer._lendControlInterpolant(); 50349 this._weightInterpolant = interpolant; 50350 50351 } 50352 50353 const times = interpolant.parameterPositions, 50354 values = interpolant.sampleValues; 50355 50356 times[ 0 ] = now; 50357 values[ 0 ] = weightNow; 50358 times[ 1 ] = now + duration; 50359 values[ 1 ] = weightThen; 50360 50361 return this; 50362 50363 } 50364 50365} 50366 50367const _controlInterpolantsResultBuffer = new Float32Array( 1 ); 50368 50369
vendor: 13,381 bytes, lines 50370-51010
50370class AnimationMixer extends EventDispatcher { 50371 50372 constructor( root ) { 50373 50374 super(); 50375 50376 this._root = root; 50377 this._initMemoryManager(); 50378 this._accuIndex = 0; 50379 this.time = 0; 50380 this.timeScale = 1.0; 50381 50382 } 50383 50384 _bindAction( action, prototypeAction ) { 50385 50386 const root = action._localRoot || this._root, 50387 tracks = action._clip.tracks, 50388 nTracks = tracks.length, 50389 bindings = action._propertyBindings, 50390 interpolants = action._interpolants, 50391 rootUuid = root.uuid, 50392 bindingsByRoot = this._bindingsByRootAndName; 50393 50394 let bindingsByName = bindingsByRoot[ rootUuid ]; 50395 50396 if ( bindingsByName === undefined ) { 50397 50398 bindingsByName = {}; 50399 bindingsByRoot[ rootUuid ] = bindingsByName; 50400 50401 } 50402 50403 for ( let i = 0; i !== nTracks; ++ i ) { 50404 50405 const track = tracks[ i ], 50406 trackName = track.name; 50407 50408 let binding = bindingsByName[ trackName ]; 50409 50410 if ( binding !== undefined ) { 50411 50412 ++ binding.referenceCount; 50413 bindings[ i ] = binding; 50414 50415 } else { 50416 50417 binding = bindings[ i ]; 50418 50419 if ( binding !== undefined ) { 50420 50421 // existing binding, make sure the cache knows 50422 50423 if ( binding._cacheIndex === null ) { 50424 50425 ++ binding.referenceCount; 50426 this._addInactiveBinding( binding, rootUuid, trackName ); 50427 50428 } 50429 50430 continue; 50431 50432 } 50433 50434 const path = prototypeAction && prototypeAction. 50435 _propertyBindings[ i ].binding.parsedPath; 50436 50437 binding = new PropertyMixer( 50438 PropertyBinding.create( root, trackName, path ), 50439 track.ValueTypeName, track.getValueSize() ); 50440 50441 ++ binding.referenceCount; 50442 this._addInactiveBinding( binding, rootUuid, trackName ); 50443 50444 bindings[ i ] = binding; 50445 50446 } 50447 50448 interpolants[ i ].resultBuffer = binding.buffer; 50449 50450 } 50451 50452 } 50453 50454 _activateAction( action ) { 50455 50456 if ( ! this._isActiveAction( action ) ) { 50457 50458 if ( action._cacheIndex === null ) { 50459 50460 // this action has been forgotten by the cache, but the user 50461 // appears to be still using it -> rebind 50462 50463 const rootUuid = ( action._localRoot || this._root ).uuid, 50464 clipUuid = action._clip.uuid, 50465 actionsForClip = this._actionsByClip[ clipUuid ]; 50466 50467 this._bindAction( action, 50468 actionsForClip && actionsForClip.knownActions[ 0 ] ); 50469 50470 this._addInactiveAction( action, clipUuid, rootUuid ); 50471 50472 } 50473 50474 const bindings = action._propertyBindings; 50475 50476 // increment reference counts / sort out state 50477 for ( let i = 0, n = bindings.length; i !== n; ++ i ) { 50478 50479 const binding = bindings[ i ]; 50480 50481 if ( binding.useCount ++ === 0 ) { 50482 50483 this._lendBinding( binding ); 50484 binding.saveOriginalState(); 50485 50486 } 50487 50488 } 50489 50490 this._lendAction( action ); 50491 50492 } 50493 50494 } 50495 50496 _deactivateAction( action ) { 50497 50498 if ( this._isActiveAction( action ) ) { 50499 50500 const bindings = action._propertyBindings; 50501 50502 // decrement reference counts / sort out state 50503 for ( let i = 0, n = bindings.length; i !== n; ++ i ) { 50504 50505 const binding = bindings[ i ]; 50506 50507 if ( -- binding.useCount === 0 ) { 50508 50509 binding.restoreOriginalState(); 50510 this._takeBackBinding( binding ); 50511 50512 } 50513 50514 } 50515 50516 this._takeBackAction( action ); 50517 50518 } 50519 50520 } 50521 50522 // Memory manager 50523 50524 _initMemoryManager() { 50525 50526 this._actions = []; // 'nActiveActions' followed by inactive ones 50527 this._nActiveActions = 0; 50528 50529 this._actionsByClip = {}; 50530 // inside: 50531 // { 50532 // knownActions: Array< AnimationAction > - used as prototypes 50533 // actionByRoot: AnimationAction - lookup 50534 // } 50535 50536 50537 this._bindings = []; // 'nActiveBindings' followed by inactive ones 50538 this._nActiveBindings = 0; 50539 50540 this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer > 50541 50542 50543 this._controlInterpolants = []; // same game as above 50544 this._nActiveControlInterpolants = 0; 50545 50546 const scope = this; 50547 50548 this.stats = { 50549 50550 actions: { 50551 get total() { 50552 50553 return scope._actions.length; 50554 50555 }, 50556 get inUse() { 50557 50558 return scope._nActiveActions; 50559 50560 } 50561 }, 50562 bindings: { 50563 get total() { 50564 50565 return scope._bindings.length; 50566 50567 }, 50568 get inUse() { 50569 50570 return scope._nActiveBindings; 50571 50572 } 50573 }, 50574 controlInterpolants: { 50575 get total() { 50576 50577 return scope._controlInterpolants.length; 50578 50579 }, 50580 get inUse() { 50581 50582 return scope._nActiveControlInterpolants; 50583 50584 } 50585 } 50586 50587 }; 50588 50589 } 50590 50591 // Memory management for AnimationAction objects 50592 50593 _isActiveAction( action ) { 50594 50595 const index = action._cacheIndex; 50596 return index !== null && index < this._nActiveActions; 50597 50598 } 50599 50600 _addInactiveAction( action, clipUuid, rootUuid ) { 50601 50602 const actions = this._actions, 50603 actionsByClip = this._actionsByClip; 50604 50605 let actionsForClip = actionsByClip[ clipUuid ]; 50606 50607 if ( actionsForClip === undefined ) { 50608 50609 actionsForClip = { 50610 50611 knownActions: [ action ], 50612 actionByRoot: {} 50613 50614 }; 50615 50616 action._byClipCacheIndex = 0; 50617 50618 actionsByClip[ clipUuid ] = actionsForClip; 50619 50620 } else { 50621 50622 const knownActions = actionsForClip.knownActions; 50623 50624 action._byClipCacheIndex = knownActions.length; 50625 knownActions.push( action ); 50626 50627 } 50628 50629 action._cacheIndex = actions.length; 50630 actions.push( action ); 50631 50632 actionsForClip.actionByRoot[ rootUuid ] = action; 50633 50634 } 50635 50636 _removeInactiveAction( action ) { 50637 50638 const actions = this._actions, 50639 lastInactiveAction = actions[ actions.length - 1 ], 50640 cacheIndex = action._cacheIndex; 50641 50642 lastInactiveAction._cacheIndex = cacheIndex; 50643 actions[ cacheIndex ] = lastInactiveAction; 50644 actions.pop(); 50645 50646 action._cacheIndex = null; 50647 50648 50649 const clipUuid = action._clip.uuid, 50650 actionsByClip = this._actionsByClip, 50651 actionsForClip = actionsByClip[ clipUuid ], 50652 knownActionsForClip = actionsForClip.knownActions, 50653 50654 lastKnownAction = 50655 knownActionsForClip[ knownActionsForClip.length - 1 ], 50656 50657 byClipCacheIndex = action._byClipCacheIndex; 50658 50659 lastKnownAction._byClipCacheIndex = byClipCacheIndex; 50660 knownActionsForClip[ byClipCacheIndex ] = lastKnownAction; 50661 knownActionsForClip.pop(); 50662 50663 action._byClipCacheIndex = null; 50664 50665 50666 const actionByRoot = actionsForClip.actionByRoot, 50667 rootUuid = ( action._localRoot || this._root ).uuid; 50668 50669 delete actionByRoot[ rootUuid ]; 50670 50671 if ( knownActionsForClip.length === 0 ) { 50672 50673 delete actionsByClip[ clipUuid ]; 50674 50675 } 50676 50677 this._removeInactiveBindingsForAction( action ); 50678 50679 } 50680 50681 _removeInactiveBindingsForAction( action ) { 50682 50683 const bindings = action._propertyBindings; 50684 50685 for ( let i = 0, n = bindings.length; i !== n; ++ i ) { 50686 50687 const binding = bindings[ i ]; 50688 50689 if ( -- binding.referenceCount === 0 ) { 50690 50691 this._removeInactiveBinding( binding ); 50692 50693 } 50694 50695 } 50696 50697 } 50698 50699 _lendAction( action ) { 50700 50701 // [ active actions | inactive actions ] 50702 // [ active actions >| inactive actions ] 50703 // s a 50704 // <-swap-> 50705 // a s 50706 50707 const actions = this._actions, 50708 prevIndex = action._cacheIndex, 50709 50710 lastActiveIndex = this._nActiveActions ++, 50711 50712 firstInactiveAction = actions[ lastActiveIndex ]; 50713 50714 action._cacheIndex = lastActiveIndex; 50715 actions[ lastActiveIndex ] = action; 50716 50717 firstInactiveAction._cacheIndex = prevIndex; 50718 actions[ prevIndex ] = firstInactiveAction; 50719 50720 } 50721 50722 _takeBackAction( action ) { 50723 50724 // [ active actions | inactive actions ] 50725 // [ active actions |< inactive actions ] 50726 // a s 50727 // <-swap-> 50728 // s a 50729 50730 const actions = this._actions, 50731 prevIndex = action._cacheIndex, 50732 50733 firstInactiveIndex = -- this._nActiveActions, 50734 50735 lastActiveAction = actions[ firstInactiveIndex ]; 50736 50737 action._cacheIndex = firstInactiveIndex; 50738 actions[ firstInactiveIndex ] = action; 50739 50740 lastActiveAction._cacheIndex = prevIndex; 50741 actions[ prevIndex ] = lastActiveAction; 50742 50743 } 50744 50745 // Memory management for PropertyMixer objects 50746 50747 _addInactiveBinding( binding, rootUuid, trackName ) { 50748 50749 const bindingsByRoot = this._bindingsByRootAndName, 50750 bindings = this._bindings; 50751 50752 let bindingByName = bindingsByRoot[ rootUuid ]; 50753 50754 if ( bindingByName === undefined ) { 50755 50756 bindingByName = {}; 50757 bindingsByRoot[ rootUuid ] = bindingByName; 50758 50759 } 50760 50761 bindingByName[ trackName ] = binding; 50762 50763 binding._cacheIndex = bindings.length; 50764 bindings.push( binding ); 50765 50766 } 50767 50768 _removeInactiveBinding( binding ) { 50769 50770 const bindings = this._bindings, 50771 propBinding = binding.binding, 50772 rootUuid = propBinding.rootNode.uuid, 50773 trackName = propBinding.path, 50774 bindingsByRoot = this._bindingsByRootAndName, 50775 bindingByName = bindingsByRoot[ rootUuid ], 50776 50777 lastInactiveBinding = bindings[ bindings.length - 1 ], 50778 cacheIndex = binding._cacheIndex; 50779 50780 lastInactiveBinding._cacheIndex = cacheIndex; 50781 bindings[ cacheIndex ] = lastInactiveBinding; 50782 bindings.pop(); 50783 50784 delete bindingByName[ trackName ]; 50785 50786 if ( Object.keys( bindingByName ).length === 0 ) { 50787 50788 delete bindingsByRoot[ rootUuid ]; 50789 50790 } 50791 50792 } 50793 50794 _lendBinding( binding ) { 50795 50796 const bindings = this._bindings, 50797 prevIndex = binding._cacheIndex, 50798 50799 lastActiveIndex = this._nActiveBindings ++, 50800 50801 firstInactiveBinding = bindings[ lastActiveIndex ]; 50802 50803 binding._cacheIndex = lastActiveIndex; 50804 bindings[ lastActiveIndex ] = binding; 50805 50806 firstInactiveBinding._cacheIndex = prevIndex; 50807 bindings[ prevIndex ] = firstInactiveBinding; 50808 50809 } 50810 50811 _takeBackBinding( binding ) { 50812 50813 const bindings = this._bindings, 50814 prevIndex = binding._cacheIndex, 50815 50816 firstInactiveIndex = -- this._nActiveBindings, 50817 50818 lastActiveBinding = bindings[ firstInactiveIndex ]; 50819 50820 binding._cacheIndex = firstInactiveIndex; 50821 bindings[ firstInactiveIndex ] = binding; 50822 50823 lastActiveBinding._cacheIndex = prevIndex; 50824 bindings[ prevIndex ] = lastActiveBinding; 50825 50826 } 50827 50828 50829 // Memory management of Interpolants for weight and time scale 50830 50831 _lendControlInterpolant() { 50832 50833 const interpolants = this._controlInterpolants, 50834 lastActiveIndex = this._nActiveControlInterpolants ++; 50835 50836 let interpolant = interpolants[ lastActiveIndex ]; 50837 50838 if ( interpolant === undefined ) { 50839 50840 interpolant = new LinearInterpolant( 50841 new Float32Array( 2 ), new Float32Array( 2 ), 50842 1, _controlInterpolantsResultBuffer ); 50843 50844 interpolant.__cacheIndex = lastActiveIndex; 50845 interpolants[ lastActiveIndex ] = interpolant; 50846 50847 } 50848 50849 return interpolant; 50850 50851 } 50852 50853 _takeBackControlInterpolant( interpolant ) { 50854 50855 const interpolants = this._controlInterpolants, 50856 prevIndex = interpolant.__cacheIndex, 50857 50858 firstInactiveIndex = -- this._nActiveControlInterpolants, 50859 50860 lastActiveInterpolant = interpolants[ firstInactiveIndex ]; 50861 50862 interpolant.__cacheIndex = firstInactiveIndex; 50863 interpolants[ firstInactiveIndex ] = interpolant; 50864 50865 lastActiveInterpolant.__cacheIndex = prevIndex; 50866 interpolants[ prevIndex ] = lastActiveInterpolant; 50867 50868 } 50869 50870 // return an action for a clip optionally using a custom root target 50871 // object (this method allocates a lot of dynamic memory in case a 50872 // previously unknown clip/root combination is specified) 50873 clipAction( clip, optionalRoot, blendMode ) { 50874 50875 const root = optionalRoot || this._root, 50876 rootUuid = root.uuid; 50877 50878 let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip; 50879 50880 const clipUuid = clipObject !== null ? clipObject.uuid : clip; 50881 50882 const actionsForClip = this._actionsByClip[ clipUuid ]; 50883 let prototypeAction = null; 50884 50885 if ( blendMode === undefined ) { 50886 50887 if ( clipObject !== null ) { 50888 50889 blendMode = clipObject.blendMode; 50890 50891 } else { 50892 50893 blendMode = NormalAnimationBlendMode; 50894 50895 } 50896 50897 } 50898 50899 if ( actionsForClip !== undefined ) { 50900 50901 const existingAction = actionsForClip.actionByRoot[ rootUuid ]; 50902 50903 if ( existingAction !== undefined && existingAction.blendMode === blendMode ) { 50904 50905 return existingAction; 50906 50907 } 50908 50909 // we know the clip, so we don't have to parse all 50910 // the bindings again but can just copy 50911 prototypeAction = actionsForClip.knownActions[ 0 ]; 50912 50913 // also, take the clip from the prototype action 50914 if ( clipObject === null ) 50915 clipObject = prototypeAction._clip; 50916 50917 } 50918 50919 // clip must be known when specified via string 50920 if ( clipObject === null ) return null; 50921 50922 // allocate all resources required to run it 50923 const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode ); 50924 50925 this._bindAction( newAction, prototypeAction ); 50926 50927 // and make the action known to the memory manager 50928 this._addInactiveAction( newAction, clipUuid, rootUuid ); 50929 50930 return newAction; 50931 50932 } 50933 50934 // get an existing action 50935 existingAction( clip, optionalRoot ) { 50936 50937 const root = optionalRoot || this._root, 50938 rootUuid = root.uuid, 50939 50940 clipObject = typeof clip === 'string' ? 50941 AnimationClip.findByName( root, clip ) : clip, 50942 50943 clipUuid = clipObject ? clipObject.uuid : clip, 50944 50945 actionsForClip = this._actionsByClip[ clipUuid ]; 50946 50947 if ( actionsForClip !== undefined ) { 50948 50949 return actionsForClip.actionByRoot[ rootUuid ] || null; 50950 50951 } 50952 50953 return null; 50954 50955 } 50956 50957 // deactivates all previously scheduled actions 50958 stopAllAction() { 50959 50960 const actions = this._actions, 50961 nActions = this._nActiveActions; 50962 50963 for ( let i = nActions - 1; i >= 0; -- i ) { 50964 50965 actions[ i ].stop(); 50966 50967 } 50968 50969 return this; 50970 50971 } 50972 50973 // advance the time and update apply the animation 50974 update( deltaTime ) { 50975 50976 deltaTime *= this.timeScale; 50977 50978 const actions = this._actions, 50979 nActions = this._nActiveActions, 50980 50981 time = this.time += deltaTime, 50982 timeDirection = Math.sign( deltaTime ), 50983 50984 accuIndex = this._accuIndex ^= 1; 50985 50986 // run active actions 50987 50988 for ( let i = 0; i !== nActions; ++ i ) { 50989 50990 const action = actions[ i ]; 50991 50992 action._update( time, deltaTime, timeDirection, accuIndex ); 50993 50994 } 50995 50996 // update scene graph 50997 50998 const bindings = this._bindings, 50999 nBindings = this._nActiveBindings; 51000 51001 for ( let i = 0; i !== nBindings; ++ i ) { 51002 51003 bindings[ i ].apply( accuIndex ); 51004 51005 } 51006 51007 return this; 51008 51009 } 51010
vendor: 2,763 bytes, lines 51011-51144
51011 // Allows you to seek to a specific time in an animation. 51012 setTime( timeInSeconds ) { 51013 51014 this.time = 0; // Zero out time attribute for AnimationMixer object; 51015 for ( let i = 0; i < this._actions.length; i ++ ) { 51016 51017 this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects. 51018 51019 } 51020 51021 return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object. 51022 51023 } 51024 51025 // return this mixer's root target object 51026 getRoot() { 51027 51028 return this._root; 51029 51030 } 51031 51032 // free all resources specific to a particular clip 51033 uncacheClip( clip ) { 51034 51035 const actions = this._actions, 51036 clipUuid = clip.uuid, 51037 actionsByClip = this._actionsByClip, 51038 actionsForClip = actionsByClip[ clipUuid ]; 51039 51040 if ( actionsForClip !== undefined ) { 51041 51042 // note: just calling _removeInactiveAction would mess up the 51043 // iteration state and also require updating the state we can 51044 // just throw away 51045 51046 const actionsToRemove = actionsForClip.knownActions; 51047 51048 for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) { 51049 51050 const action = actionsToRemove[ i ]; 51051 51052 this._deactivateAction( action ); 51053 51054 const cacheIndex = action._cacheIndex, 51055 lastInactiveAction = actions[ actions.length - 1 ]; 51056 51057 action._cacheIndex = null; 51058 action._byClipCacheIndex = null; 51059 51060 lastInactiveAction._cacheIndex = cacheIndex; 51061 actions[ cacheIndex ] = lastInactiveAction; 51062 actions.pop(); 51063 51064 this._removeInactiveBindingsForAction( action ); 51065 51066 } 51067 51068 delete actionsByClip[ clipUuid ]; 51069 51070 } 51071 51072 } 51073 51074 // free all resources specific to a particular root target object 51075 uncacheRoot( root ) { 51076 51077 const rootUuid = root.uuid, 51078 actionsByClip = this._actionsByClip; 51079 51080 for ( const clipUuid in actionsByClip ) { 51081 51082 const actionByRoot = actionsByClip[ clipUuid ].actionByRoot, 51083 action = actionByRoot[ rootUuid ]; 51084 51085 if ( action !== undefined ) { 51086 51087 this._deactivateAction( action ); 51088 this._removeInactiveAction( action ); 51089 51090 } 51091 51092 } 51093 51094 const bindingsByRoot = this._bindingsByRootAndName, 51095 bindingByName = bindingsByRoot[ rootUuid ]; 51096 51097 if ( bindingByName !== undefined ) { 51098 51099 for ( const trackName in bindingByName ) { 51100 51101 const binding = bindingByName[ trackName ]; 51102 binding.restoreOriginalState(); 51103 this._removeInactiveBinding( binding ); 51104 51105 } 51106 51107 } 51108 51109 } 51110 51111 // remove a targeted clip from the cache 51112 uncacheAction( clip, optionalRoot ) { 51113 51114 const action = this.existingAction( clip, optionalRoot ); 51115 51116 if ( action !== null ) { 51117 51118 this._deactivateAction( action ); 51119 this._removeInactiveAction( action ); 51120 51121 } 51122 51123 } 51124 51125} 51126 51127class Uniform { 51128 51129 constructor( value ) { 51130 51131 this.value = value; 51132 51133 } 51134 51135 clone() { 51136 51137 return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() ); 51138 51139 } 51140 51141} 51142 51143let _id = 0; 51144
vendor: 4,828 bytes, lines 51145-51446
51145class UniformsGroup extends EventDispatcher { 51146 51147 constructor() { 51148 51149 super(); 51150 51151 this.isUniformsGroup = true; 51152 51153 Object.defineProperty( this, 'id', { value: _id ++ } ); 51154 51155 this.name = ''; 51156 51157 this.usage = StaticDrawUsage; 51158 this.uniforms = []; 51159 51160 } 51161 51162 add( uniform ) { 51163 51164 this.uniforms.push( uniform ); 51165 51166 return this; 51167 51168 } 51169 51170 remove( uniform ) { 51171 51172 const index = this.uniforms.indexOf( uniform ); 51173 51174 if ( index !== - 1 ) this.uniforms.splice( index, 1 ); 51175 51176 return this; 51177 51178 } 51179 51180 setName( name ) { 51181 51182 this.name = name; 51183 51184 return this; 51185 51186 } 51187 51188 setUsage( value ) { 51189 51190 this.usage = value; 51191 51192 return this; 51193 51194 } 51195 51196 dispose() { 51197 51198 this.dispatchEvent( { type: 'dispose' } ); 51199 51200 return this; 51201 51202 } 51203 51204 copy( source ) { 51205 51206 this.name = source.name; 51207 this.usage = source.usage; 51208 51209 const uniformsSource = source.uniforms; 51210 51211 this.uniforms.length = 0; 51212 51213 for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) { 51214 51215 const uniforms = Array.isArray( uniformsSource[ i ] ) ? uniformsSource[ i ] : [ uniformsSource[ i ] ]; 51216 51217 for ( let j = 0; j < uniforms.length; j ++ ) { 51218 51219 this.uniforms.push( uniforms[ j ].clone() ); 51220 51221 } 51222 51223 } 51224 51225 return this; 51226 51227 } 51228 51229 clone() { 51230 51231 return new this.constructor().copy( this ); 51232 51233 } 51234 51235} 51236 51237class InstancedInterleavedBuffer extends InterleavedBuffer { 51238 51239 constructor( array, stride, meshPerAttribute = 1 ) { 51240 51241 super( array, stride ); 51242 51243 this.isInstancedInterleavedBuffer = true; 51244 51245 this.meshPerAttribute = meshPerAttribute; 51246 51247 } 51248 51249 copy( source ) { 51250 51251 super.copy( source ); 51252 51253 this.meshPerAttribute = source.meshPerAttribute; 51254 51255 return this; 51256 51257 } 51258 51259 clone( data ) { 51260 51261 const ib = super.clone( data ); 51262 51263 ib.meshPerAttribute = this.meshPerAttribute; 51264 51265 return ib; 51266 51267 } 51268 51269 toJSON( data ) { 51270 51271 const json = super.toJSON( data ); 51272 51273 json.isInstancedInterleavedBuffer = true; 51274 json.meshPerAttribute = this.meshPerAttribute; 51275 51276 return json; 51277 51278 } 51279 51280} 51281 51282class GLBufferAttribute { 51283 51284 constructor( buffer, type, itemSize, elementSize, count ) { 51285 51286 this.isGLBufferAttribute = true; 51287 51288 this.name = ''; 51289 51290 this.buffer = buffer; 51291 this.type = type; 51292 this.itemSize = itemSize; 51293 this.elementSize = elementSize; 51294 this.count = count; 51295 51296 this.version = 0; 51297 51298 } 51299 51300 set needsUpdate( value ) { 51301 51302 if ( value === true ) this.version ++; 51303 51304 } 51305 51306 setBuffer( buffer ) { 51307 51308 this.buffer = buffer; 51309 51310 return this; 51311 51312 } 51313 51314 setType( type, elementSize ) { 51315 51316 this.type = type; 51317 this.elementSize = elementSize; 51318 51319 return this; 51320 51321 } 51322 51323 setItemSize( itemSize ) { 51324 51325 this.itemSize = itemSize; 51326 51327 return this; 51328 51329 } 51330 51331 setCount( count ) { 51332 51333 this.count = count; 51334 51335 return this; 51336 51337 } 51338 51339} 51340 51341const _matrix = /*@__PURE__*/ new Matrix4(); 51342 51343class Raycaster { 51344 51345 constructor( origin, direction, near = 0, far = Infinity ) { 51346 51347 this.ray = new Ray( origin, direction ); 51348 // direction is assumed to be normalized (for accurate distance calculations) 51349 51350 this.near = near; 51351 this.far = far; 51352 this.camera = null; 51353 this.layers = new Layers(); 51354 51355 this.params = { 51356 Mesh: {}, 51357 Line: { threshold: 1 }, 51358 LOD: {}, 51359 Points: { threshold: 1 }, 51360 Sprite: {} 51361 }; 51362 51363 } 51364 51365 set( origin, direction ) { 51366 51367 // direction is assumed to be normalized (for accurate distance calculations) 51368 51369 this.ray.set( origin, direction ); 51370 51371 } 51372 51373 setFromCamera( coords, camera ) { 51374 51375 if ( camera.isPerspectiveCamera ) { 51376 51377 this.ray.origin.setFromMatrixPosition( camera.matrixWorld ); 51378 this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize(); 51379 this.camera = camera; 51380 51381 } else if ( camera.isOrthographicCamera ) { 51382 51383 this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera 51384 this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); 51385 this.camera = camera; 51386 51387 } else { 51388 51389 console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type ); 51390 51391 } 51392 51393 } 51394 51395 setFromXRController( controller ) { 51396 51397 _matrix.identity().extractRotation( controller.matrixWorld ); 51398 51399 this.ray.origin.setFromMatrixPosition( controller.matrixWorld ); 51400 this.ray.direction.set( 0, 0, - 1 ).applyMatrix4( _matrix ); 51401 51402 return this; 51403 51404 } 51405 51406 intersectObject( object, recursive = true, intersects = [] ) { 51407 51408 intersect( object, this, intersects, recursive ); 51409 51410 intersects.sort( ascSort ); 51411 51412 return intersects; 51413 51414 } 51415 51416 intersectObjects( objects, recursive = true, intersects = [] ) { 51417 51418 for ( let i = 0, l = objects.length; i < l; i ++ ) { 51419 51420 intersect( objects[ i ], this, intersects, recursive ); 51421 51422 } 51423 51424 intersects.sort( ascSort ); 51425 51426 return intersects; 51427 51428 } 51429 51430} 51431 51432function ascSort( a, b ) { 51433 51434 return a.distance - b.distance; 51435 51436} 51437 51438function intersect( object, raycaster, intersects, recursive ) { 51439 51440 let propagate = true; 51441 51442 if ( object.layers.test( raycaster.layers ) ) { 51443 51444 const result = object.raycast( raycaster, intersects ); 51445 51446 if ( result === false ) propagate = false;
vendor: 21,614 bytes, lines 51447-52624
51447 51448 } 51449 51450 if ( propagate === true && recursive === true ) { 51451 51452 const children = object.children; 51453 51454 for ( let i = 0, l = children.length; i < l; i ++ ) { 51455 51456 intersect( children[ i ], raycaster, intersects, true ); 51457 51458 } 51459 51460 } 51461 51462} 51463 51464/** 51465 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system 51466 * 51467 * phi (the polar angle) is measured from the positive y-axis. The positive y-axis is up. 51468 * theta (the azimuthal angle) is measured from the positive z-axis. 51469 */ 51470class Spherical { 51471 51472 constructor( radius = 1, phi = 0, theta = 0 ) { 51473 51474 this.radius = radius; 51475 this.phi = phi; // polar angle 51476 this.theta = theta; // azimuthal angle 51477 51478 return this; 51479 51480 } 51481 51482 set( radius, phi, theta ) { 51483 51484 this.radius = radius; 51485 this.phi = phi; 51486 this.theta = theta; 51487 51488 return this; 51489 51490 } 51491 51492 copy( other ) { 51493 51494 this.radius = other.radius; 51495 this.phi = other.phi; 51496 this.theta = other.theta; 51497 51498 return this; 51499 51500 } 51501 51502 // restrict phi to be between EPS and PI-EPS 51503 makeSafe() { 51504 51505 const EPS = 0.000001; 51506 this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) ); 51507 51508 return this; 51509 51510 } 51511 51512 setFromVector3( v ) { 51513 51514 return this.setFromCartesianCoords( v.x, v.y, v.z ); 51515 51516 } 51517 51518 setFromCartesianCoords( x, y, z ) { 51519 51520 this.radius = Math.sqrt( x * x + y * y + z * z ); 51521 51522 if ( this.radius === 0 ) { 51523 51524 this.theta = 0; 51525 this.phi = 0; 51526 51527 } else { 51528 51529 this.theta = Math.atan2( x, z ); 51530 this.phi = Math.acos( clamp( y / this.radius, - 1, 1 ) ); 51531 51532 } 51533 51534 return this; 51535 51536 } 51537 51538 clone() { 51539 51540 return new this.constructor().copy( this ); 51541 51542 } 51543 51544} 51545 51546/** 51547 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system 51548 */ 51549 51550class Cylindrical { 51551 51552 constructor( radius = 1, theta = 0, y = 0 ) { 51553 51554 this.radius = radius; // distance from the origin to a point in the x-z plane 51555 this.theta = theta; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis 51556 this.y = y; // height above the x-z plane 51557 51558 return this; 51559 51560 } 51561 51562 set( radius, theta, y ) { 51563 51564 this.radius = radius; 51565 this.theta = theta; 51566 this.y = y; 51567 51568 return this; 51569 51570 } 51571 51572 copy( other ) { 51573 51574 this.radius = other.radius; 51575 this.theta = other.theta; 51576 this.y = other.y; 51577 51578 return this; 51579 51580 } 51581 51582 setFromVector3( v ) { 51583 51584 return this.setFromCartesianCoords( v.x, v.y, v.z ); 51585 51586 } 51587 51588 setFromCartesianCoords( x, y, z ) { 51589 51590 this.radius = Math.sqrt( x * x + z * z ); 51591 this.theta = Math.atan2( x, z ); 51592 this.y = y; 51593 51594 return this; 51595 51596 } 51597 51598 clone() { 51599 51600 return new this.constructor().copy( this ); 51601 51602 } 51603 51604} 51605 51606const _vector$4 = /*@__PURE__*/ new Vector2(); 51607 51608class Box2 { 51609 51610 constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) { 51611 51612 this.isBox2 = true; 51613 51614 this.min = min; 51615 this.max = max; 51616 51617 } 51618 51619 set( min, max ) { 51620 51621 this.min.copy( min ); 51622 this.max.copy( max ); 51623 51624 return this; 51625 51626 } 51627 51628 setFromPoints( points ) { 51629 51630 this.makeEmpty(); 51631 51632 for ( let i = 0, il = points.length; i < il; i ++ ) { 51633 51634 this.expandByPoint( points[ i ] ); 51635 51636 } 51637 51638 return this; 51639 51640 } 51641 51642 setFromCenterAndSize( center, size ) { 51643 51644 const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 ); 51645 this.min.copy( center ).sub( halfSize ); 51646 this.max.copy( center ).add( halfSize ); 51647 51648 return this; 51649 51650 } 51651 51652 clone() { 51653 51654 return new this.constructor().copy( this ); 51655 51656 } 51657 51658 copy( box ) { 51659 51660 this.min.copy( box.min ); 51661 this.max.copy( box.max ); 51662 51663 return this; 51664 51665 } 51666 51667 makeEmpty() { 51668 51669 this.min.x = this.min.y = + Infinity; 51670 this.max.x = this.max.y = - Infinity; 51671 51672 return this; 51673 51674 } 51675 51676 isEmpty() { 51677 51678 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes 51679 51680 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); 51681 51682 } 51683 51684 getCenter( target ) { 51685 51686 return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); 51687 51688 } 51689 51690 getSize( target ) { 51691 51692 return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min ); 51693 51694 } 51695 51696 expandByPoint( point ) { 51697 51698 this.min.min( point ); 51699 this.max.max( point ); 51700 51701 return this; 51702 51703 } 51704 51705 expandByVector( vector ) { 51706 51707 this.min.sub( vector ); 51708 this.max.add( vector ); 51709 51710 return this; 51711 51712 } 51713 51714 expandByScalar( scalar ) { 51715 51716 this.min.addScalar( - scalar ); 51717 this.max.addScalar( scalar ); 51718 51719 return this; 51720 51721 } 51722 51723 containsPoint( point ) { 51724 51725 return point.x < this.min.x || point.x > this.max.x || 51726 point.y < this.min.y || point.y > this.max.y ? false : true; 51727 51728 } 51729 51730 containsBox( box ) { 51731 51732 return this.min.x <= box.min.x && box.max.x <= this.max.x && 51733 this.min.y <= box.min.y && box.max.y <= this.max.y; 51734 51735 } 51736 51737 getParameter( point, target ) { 51738 51739 // This can potentially have a divide by zero if the box 51740 // has a size dimension of 0. 51741 51742 return target.set( 51743 ( point.x - this.min.x ) / ( this.max.x - this.min.x ), 51744 ( point.y - this.min.y ) / ( this.max.y - this.min.y ) 51745 ); 51746 51747 } 51748 51749 intersectsBox( box ) { 51750 51751 // using 4 splitting planes to rule out intersections 51752 51753 return box.max.x < this.min.x || box.min.x > this.max.x || 51754 box.max.y < this.min.y || box.min.y > this.max.y ? false : true; 51755 51756 } 51757 51758 clampPoint( point, target ) { 51759 51760 return target.copy( point ).clamp( this.min, this.max ); 51761 51762 } 51763 51764 distanceToPoint( point ) { 51765 51766 return this.clampPoint( point, _vector$4 ).distanceTo( point ); 51767 51768 } 51769 51770 intersect( box ) { 51771 51772 this.min.max( box.min ); 51773 this.max.min( box.max ); 51774 51775 if ( this.isEmpty() ) this.makeEmpty(); 51776 51777 return this; 51778 51779 } 51780 51781 union( box ) { 51782 51783 this.min.min( box.min ); 51784 this.max.max( box.max ); 51785 51786 return this; 51787 51788 } 51789 51790 translate( offset ) { 51791 51792 this.min.add( offset ); 51793 this.max.add( offset ); 51794 51795 return this; 51796 51797 } 51798 51799 equals( box ) { 51800 51801 return box.min.equals( this.min ) && box.max.equals( this.max ); 51802 51803 } 51804 51805} 51806 51807const _startP = /*@__PURE__*/ new Vector3(); 51808const _startEnd = /*@__PURE__*/ new Vector3(); 51809 51810class Line3 { 51811 51812 constructor( start = new Vector3(), end = new Vector3() ) { 51813 51814 this.start = start; 51815 this.end = end; 51816 51817 } 51818 51819 set( start, end ) { 51820 51821 this.start.copy( start ); 51822 this.end.copy( end ); 51823 51824 return this; 51825 51826 } 51827 51828 copy( line ) { 51829 51830 this.start.copy( line.start ); 51831 this.end.copy( line.end ); 51832 51833 return this; 51834 51835 } 51836 51837 getCenter( target ) { 51838 51839 return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); 51840 51841 } 51842 51843 delta( target ) { 51844 51845 return target.subVectors( this.end, this.start ); 51846 51847 } 51848 51849 distanceSq() { 51850 51851 return this.start.distanceToSquared( this.end ); 51852 51853 } 51854 51855 distance() { 51856 51857 return this.start.distanceTo( this.end ); 51858 51859 } 51860 51861 at( t, target ) { 51862 51863 return this.delta( target ).multiplyScalar( t ).add( this.start ); 51864 51865 } 51866 51867 closestPointToPointParameter( point, clampToLine ) { 51868 51869 _startP.subVectors( point, this.start ); 51870 _startEnd.subVectors( this.end, this.start ); 51871 51872 const startEnd2 = _startEnd.dot( _startEnd ); 51873 const startEnd_startP = _startEnd.dot( _startP ); 51874 51875 let t = startEnd_startP / startEnd2; 51876 51877 if ( clampToLine ) { 51878 51879 t = clamp( t, 0, 1 ); 51880 51881 } 51882 51883 return t; 51884 51885 } 51886 51887 closestPointToPoint( point, clampToLine, target ) { 51888 51889 const t = this.closestPointToPointParameter( point, clampToLine ); 51890 51891 return this.delta( target ).multiplyScalar( t ).add( this.start ); 51892 51893 } 51894 51895 applyMatrix4( matrix ) { 51896 51897 this.start.applyMatrix4( matrix ); 51898 this.end.applyMatrix4( matrix ); 51899 51900 return this; 51901 51902 } 51903 51904 equals( line ) { 51905 51906 return line.start.equals( this.start ) && line.end.equals( this.end ); 51907 51908 } 51909 51910 clone() { 51911 51912 return new this.constructor().copy( this ); 51913 51914 } 51915 51916} 51917 51918const _vector$3 = /*@__PURE__*/ new Vector3(); 51919 51920class SpotLightHelper extends Object3D { 51921 51922 constructor( light, color ) { 51923 51924 super(); 51925 51926 this.light = light; 51927 51928 this.matrixAutoUpdate = false; 51929 51930 this.color = color; 51931 51932 this.type = 'SpotLightHelper'; 51933 51934 const geometry = new BufferGeometry(); 51935 51936 const positions = [ 51937 0, 0, 0, 0, 0, 1, 51938 0, 0, 0, 1, 0, 1, 51939 0, 0, 0, - 1, 0, 1, 51940 0, 0, 0, 0, 1, 1, 51941 0, 0, 0, 0, - 1, 1 51942 ]; 51943 51944 for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) { 51945 51946 const p1 = ( i / l ) * Math.PI * 2; 51947 const p2 = ( j / l ) * Math.PI * 2; 51948 51949 positions.push( 51950 Math.cos( p1 ), Math.sin( p1 ), 1, 51951 Math.cos( p2 ), Math.sin( p2 ), 1 51952 ); 51953 51954 } 51955 51956 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 51957 51958 const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); 51959 51960 this.cone = new LineSegments( geometry, material ); 51961 this.add( this.cone ); 51962 51963 this.update(); 51964 51965 } 51966 51967 dispose() { 51968 51969 this.cone.geometry.dispose(); 51970 this.cone.material.dispose(); 51971 51972 } 51973 51974 update() { 51975 51976 this.light.updateWorldMatrix( true, false ); 51977 this.light.target.updateWorldMatrix( true, false ); 51978 51979 // update the local matrix based on the parent and light target transforms 51980 if ( this.parent ) { 51981 51982 this.parent.updateWorldMatrix( true ); 51983 51984 this.matrix 51985 .copy( this.parent.matrixWorld ) 51986 .invert() 51987 .multiply( this.light.matrixWorld ); 51988 51989 } else { 51990 51991 this.matrix.copy( this.light.matrixWorld ); 51992 51993 } 51994 51995 this.matrixWorld.copy( this.light.matrixWorld ); 51996 51997 const coneLength = this.light.distance ? this.light.distance : 1000; 51998 const coneWidth = coneLength * Math.tan( this.light.angle ); 51999 52000 this.cone.scale.set( coneWidth, coneWidth, coneLength ); 52001 52002 _vector$3.setFromMatrixPosition( this.light.target.matrixWorld ); 52003 52004 this.cone.lookAt( _vector$3 ); 52005 52006 if ( this.color !== undefined ) { 52007 52008 this.cone.material.color.set( this.color ); 52009 52010 } else { 52011 52012 this.cone.material.color.copy( this.light.color ); 52013 52014 } 52015 52016 } 52017 52018} 52019 52020const _vector$2 = /*@__PURE__*/ new Vector3(); 52021const _boneMatrix = /*@__PURE__*/ new Matrix4(); 52022const _matrixWorldInv = /*@__PURE__*/ new Matrix4(); 52023 52024 52025class SkeletonHelper extends LineSegments { 52026 52027 constructor( object ) { 52028 52029 const bones = getBoneList( object ); 52030 52031 const geometry = new BufferGeometry(); 52032 52033 const vertices = []; 52034 const colors = []; 52035 52036 const color1 = new Color( 0, 0, 1 ); 52037 const color2 = new Color( 0, 1, 0 ); 52038 52039 for ( let i = 0; i < bones.length; i ++ ) { 52040 52041 const bone = bones[ i ]; 52042 52043 if ( bone.parent && bone.parent.isBone ) { 52044 52045 vertices.push( 0, 0, 0 ); 52046 vertices.push( 0, 0, 0 ); 52047 colors.push( color1.r, color1.g, color1.b ); 52048 colors.push( color2.r, color2.g, color2.b ); 52049 52050 } 52051 52052 } 52053 52054 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 52055 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 52056 52057 const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } ); 52058 52059 super( geometry, material ); 52060 52061 this.isSkeletonHelper = true; 52062 52063 this.type = 'SkeletonHelper'; 52064 52065 this.root = object; 52066 this.bones = bones; 52067 52068 this.matrix = object.matrixWorld; 52069 this.matrixAutoUpdate = false; 52070 52071 } 52072 52073 updateMatrixWorld( force ) { 52074 52075 const bones = this.bones; 52076 52077 const geometry = this.geometry; 52078 const position = geometry.getAttribute( 'position' ); 52079 52080 _matrixWorldInv.copy( this.root.matrixWorld ).invert(); 52081 52082 for ( let i = 0, j = 0; i < bones.length; i ++ ) { 52083 52084 const bone = bones[ i ]; 52085 52086 if ( bone.parent && bone.parent.isBone ) { 52087 52088 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld ); 52089 _vector$2.setFromMatrixPosition( _boneMatrix ); 52090 position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z ); 52091 52092 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld ); 52093 _vector$2.setFromMatrixPosition( _boneMatrix ); 52094 position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z ); 52095 52096 j += 2; 52097 52098 } 52099 52100 } 52101 52102 geometry.getAttribute( 'position' ).needsUpdate = true; 52103 52104 super.updateMatrixWorld( force ); 52105 52106 } 52107 52108 dispose() { 52109 52110 this.geometry.dispose(); 52111 this.material.dispose(); 52112 52113 } 52114 52115} 52116 52117 52118function getBoneList( object ) { 52119 52120 const boneList = []; 52121 52122 if ( object.isBone === true ) { 52123 52124 boneList.push( object ); 52125 52126 } 52127 52128 for ( let i = 0; i < object.children.length; i ++ ) { 52129 52130 boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); 52131 52132 } 52133 52134 return boneList; 52135 52136} 52137 52138class PointLightHelper extends Mesh { 52139 52140 constructor( light, sphereSize, color ) { 52141 52142 const geometry = new SphereGeometry( sphereSize, 4, 2 ); 52143 const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); 52144 52145 super( geometry, material ); 52146 52147 this.light = light; 52148 52149 this.color = color; 52150 52151 this.type = 'PointLightHelper'; 52152 52153 this.matrix = this.light.matrixWorld; 52154 this.matrixAutoUpdate = false; 52155 52156 this.update(); 52157 52158 52159 /* 52160 // TODO: delete this comment? 52161 const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); 52162 const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); 52163 52164 this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); 52165 this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); 52166 52167 const d = light.distance; 52168 52169 if ( d === 0.0 ) { 52170 52171 this.lightDistance.visible = false; 52172 52173 } else { 52174 52175 this.lightDistance.scale.set( d, d, d ); 52176 52177 } 52178 52179 this.add( this.lightDistance ); 52180 */ 52181 52182 } 52183 52184 dispose() { 52185 52186 this.geometry.dispose(); 52187 this.material.dispose(); 52188 52189 } 52190 52191 update() { 52192 52193 this.light.updateWorldMatrix( true, false ); 52194 52195 if ( this.color !== undefined ) { 52196 52197 this.material.color.set( this.color ); 52198 52199 } else { 52200 52201 this.material.color.copy( this.light.color ); 52202 52203 } 52204 52205 /* 52206 const d = this.light.distance; 52207 52208 if ( d === 0.0 ) { 52209 52210 this.lightDistance.visible = false; 52211 52212 } else { 52213 52214 this.lightDistance.visible = true; 52215 this.lightDistance.scale.set( d, d, d ); 52216 52217 } 52218 */ 52219 52220 } 52221 52222} 52223 52224const _vector$1 = /*@__PURE__*/ new Vector3(); 52225const _color1 = /*@__PURE__*/ new Color(); 52226const _color2 = /*@__PURE__*/ new Color(); 52227 52228class HemisphereLightHelper extends Object3D { 52229 52230 constructor( light, size, color ) { 52231 52232 super(); 52233 52234 this.light = light; 52235 52236 this.matrix = light.matrixWorld; 52237 this.matrixAutoUpdate = false; 52238 52239 this.color = color; 52240 52241 this.type = 'HemisphereLightHelper'; 52242 52243 const geometry = new OctahedronGeometry( size ); 52244 geometry.rotateY( Math.PI * 0.5 ); 52245 52246 this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); 52247 if ( this.color === undefined ) this.material.vertexColors = true; 52248 52249 const position = geometry.getAttribute( 'position' ); 52250 const colors = new Float32Array( position.count * 3 ); 52251 52252 geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) ); 52253 52254 this.add( new Mesh( geometry, this.material ) ); 52255 52256 this.update(); 52257 52258 } 52259 52260 dispose() { 52261 52262 this.children[ 0 ].geometry.dispose(); 52263 this.children[ 0 ].material.dispose(); 52264 52265 } 52266 52267 update() { 52268 52269 const mesh = this.children[ 0 ]; 52270 52271 if ( this.color !== undefined ) { 52272 52273 this.material.color.set( this.color ); 52274 52275 } else { 52276 52277 const colors = mesh.geometry.getAttribute( 'color' ); 52278 52279 _color1.copy( this.light.color ); 52280 _color2.copy( this.light.groundColor ); 52281 52282 for ( let i = 0, l = colors.count; i < l; i ++ ) { 52283 52284 const color = ( i < ( l / 2 ) ) ? _color1 : _color2; 52285 52286 colors.setXYZ( i, color.r, color.g, color.b ); 52287 52288 } 52289 52290 colors.needsUpdate = true; 52291 52292 } 52293 52294 this.light.updateWorldMatrix( true, false ); 52295 52296 mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() ); 52297 52298 } 52299 52300} 52301 52302class GridHelper extends LineSegments { 52303 52304 constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) { 52305 52306 color1 = new Color( color1 ); 52307 color2 = new Color( color2 ); 52308 52309 const center = divisions / 2; 52310 const step = size / divisions; 52311 const halfSize = size / 2; 52312 52313 const vertices = [], colors = []; 52314 52315 for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) { 52316 52317 vertices.push( - halfSize, 0, k, halfSize, 0, k ); 52318 vertices.push( k, 0, - halfSize, k, 0, halfSize ); 52319 52320 const color = i === center ? color1 : color2; 52321 52322 color.toArray( colors, j ); j += 3; 52323 color.toArray( colors, j ); j += 3; 52324 color.toArray( colors, j ); j += 3; 52325 color.toArray( colors, j ); j += 3; 52326 52327 } 52328 52329 const geometry = new BufferGeometry(); 52330 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 52331 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 52332 52333 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); 52334 52335 super( geometry, material ); 52336 52337 this.type = 'GridHelper'; 52338 52339 } 52340 52341 dispose() { 52342 52343 this.geometry.dispose(); 52344 this.material.dispose(); 52345 52346 } 52347 52348} 52349 52350class PolarGridHelper extends LineSegments { 52351 52352 constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) { 52353 52354 color1 = new Color( color1 ); 52355 color2 = new Color( color2 ); 52356 52357 const vertices = []; 52358 const colors = []; 52359 52360 // create the sectors 52361 52362 if ( sectors > 1 ) { 52363 52364 for ( let i = 0; i < sectors; i ++ ) { 52365 52366 const v = ( i / sectors ) * ( Math.PI * 2 ); 52367 52368 const x = Math.sin( v ) * radius; 52369 const z = Math.cos( v ) * radius; 52370 52371 vertices.push( 0, 0, 0 ); 52372 vertices.push( x, 0, z ); 52373 52374 const color = ( i & 1 ) ? color1 : color2; 52375 52376 colors.push( color.r, color.g, color.b ); 52377 colors.push( color.r, color.g, color.b ); 52378 52379 } 52380 52381 } 52382 52383 // create the rings 52384 52385 for ( let i = 0; i < rings; i ++ ) { 52386 52387 const color = ( i & 1 ) ? color1 : color2; 52388 52389 const r = radius - ( radius / rings * i ); 52390 52391 for ( let j = 0; j < divisions; j ++ ) { 52392 52393 // first vertex 52394 52395 let v = ( j / divisions ) * ( Math.PI * 2 ); 52396 52397 let x = Math.sin( v ) * r; 52398 let z = Math.cos( v ) * r; 52399 52400 vertices.push( x, 0, z ); 52401 colors.push( color.r, color.g, color.b ); 52402 52403 // second vertex 52404 52405 v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 ); 52406 52407 x = Math.sin( v ) * r; 52408 z = Math.cos( v ) * r; 52409 52410 vertices.push( x, 0, z ); 52411 colors.push( color.r, color.g, color.b ); 52412 52413 } 52414 52415 } 52416 52417 const geometry = new BufferGeometry(); 52418 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 52419 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 52420 52421 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); 52422 52423 super( geometry, material ); 52424 52425 this.type = 'PolarGridHelper'; 52426 52427 } 52428 52429 dispose() { 52430 52431 this.geometry.dispose(); 52432 this.material.dispose(); 52433 52434 } 52435 52436} 52437 52438const _v1 = /*@__PURE__*/ new Vector3(); 52439const _v2 = /*@__PURE__*/ new Vector3(); 52440const _v3 = /*@__PURE__*/ new Vector3(); 52441 52442class DirectionalLightHelper extends Object3D { 52443 52444 constructor( light, size, color ) { 52445 52446 super(); 52447 52448 this.light = light; 52449 52450 this.matrix = light.matrixWorld; 52451 this.matrixAutoUpdate = false; 52452 52453 this.color = color; 52454 52455 this.type = 'DirectionalLightHelper'; 52456 52457 if ( size === undefined ) size = 1; 52458 52459 let geometry = new BufferGeometry(); 52460 geometry.setAttribute( 'position', new Float32BufferAttribute( [ 52461 - size, size, 0, 52462 size, size, 0, 52463 size, - size, 0, 52464 - size, - size, 0, 52465 - size, size, 0 52466 ], 3 ) ); 52467 52468 const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); 52469 52470 this.lightPlane = new Line( geometry, material ); 52471 this.add( this.lightPlane ); 52472 52473 geometry = new BufferGeometry(); 52474 geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); 52475 52476 this.targetLine = new Line( geometry, material ); 52477 this.add( this.targetLine ); 52478 52479 this.update(); 52480 52481 } 52482 52483 dispose() { 52484 52485 this.lightPlane.geometry.dispose(); 52486 this.lightPlane.material.dispose(); 52487 this.targetLine.geometry.dispose(); 52488 this.targetLine.material.dispose(); 52489 52490 } 52491 52492 update() { 52493 52494 this.light.updateWorldMatrix( true, false ); 52495 this.light.target.updateWorldMatrix( true, false ); 52496 52497 _v1.setFromMatrixPosition( this.light.matrixWorld ); 52498 _v2.setFromMatrixPosition( this.light.target.matrixWorld ); 52499 _v3.subVectors( _v2, _v1 ); 52500 52501 this.lightPlane.lookAt( _v2 ); 52502 52503 if ( this.color !== undefined ) { 52504 52505 this.lightPlane.material.color.set( this.color ); 52506 this.targetLine.material.color.set( this.color ); 52507 52508 } else { 52509 52510 this.lightPlane.material.color.copy( this.light.color ); 52511 this.targetLine.material.color.copy( this.light.color ); 52512 52513 } 52514 52515 this.targetLine.lookAt( _v2 ); 52516 this.targetLine.scale.z = _v3.length(); 52517 52518 } 52519 52520} 52521 52522const _vector = /*@__PURE__*/ new Vector3(); 52523const _camera = /*@__PURE__*/ new Camera(); 52524 52525/** 52526 * - shows frustum, line of sight and up of the camera 52527 * - suitable for fast updates 52528 * - based on frustum visualization in lightgl.js shadowmap example 52529 * https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html 52530 */ 52531 52532class CameraHelper extends LineSegments { 52533 52534 constructor( camera ) { 52535 52536 const geometry = new BufferGeometry(); 52537 const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } ); 52538 52539 const vertices = []; 52540 const colors = []; 52541 52542 const pointMap = {}; 52543 52544 // near 52545 52546 addLine( 'n1', 'n2' ); 52547 addLine( 'n2', 'n4' ); 52548 addLine( 'n4', 'n3' ); 52549 addLine( 'n3', 'n1' ); 52550 52551 // far 52552 52553 addLine( 'f1', 'f2' ); 52554 addLine( 'f2', 'f4' ); 52555 addLine( 'f4', 'f3' ); 52556 addLine( 'f3', 'f1' ); 52557 52558 // sides 52559 52560 addLine( 'n1', 'f1' ); 52561 addLine( 'n2', 'f2' ); 52562 addLine( 'n3', 'f3' ); 52563 addLine( 'n4', 'f4' ); 52564 52565 // cone 52566 52567 addLine( 'p', 'n1' ); 52568 addLine( 'p', 'n2' ); 52569 addLine( 'p', 'n3' ); 52570 addLine( 'p', 'n4' ); 52571 52572 // up 52573 52574 addLine( 'u1', 'u2' ); 52575 addLine( 'u2', 'u3' ); 52576 addLine( 'u3', 'u1' ); 52577 52578 // target 52579 52580 addLine( 'c', 't' ); 52581 addLine( 'p', 'c' ); 52582 52583 // cross 52584 52585 addLine( 'cn1', 'cn2' ); 52586 addLine( 'cn3', 'cn4' ); 52587 52588 addLine( 'cf1', 'cf2' ); 52589 addLine( 'cf3', 'cf4' ); 52590 52591 function addLine( a, b ) { 52592 52593 addPoint( a ); 52594 addPoint( b ); 52595 52596 } 52597 52598 function addPoint( id ) { 52599 52600 vertices.push( 0, 0, 0 ); 52601 colors.push( 0, 0, 0 ); 52602 52603 if ( pointMap[ id ] === undefined ) { 52604 52605 pointMap[ id ] = []; 52606 52607 } 52608 52609 pointMap[ id ].push( ( vertices.length / 3 ) - 1 ); 52610 52611 } 52612 52613 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 52614 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 52615 52616 super( geometry, material ); 52617 52618 this.type = 'CameraHelper'; 52619 52620 this.camera = camera; 52621 if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix(); 52622 52623 this.matrix = camera.matrixWorld; 52624 this.matrixAutoUpdate = false;
52625 52626 this.pointMap = pointMap; 52627 52628 this.update(); 52629 52630 // colors 52631 52632 const colorFrustum = new Color( 0xffaa00 ); 52633 const colorCone = new Color( 0xff0000 ); 52634 const colorUp = new Color( 0x00aaff ); 52635 const colorTarget = new Color( 0xffffff ); 52636 const colorCross = new Color( 0x333333 ); 52637 52638 this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross ); 52639 52640 } 52641 52642 setColors( frustum, cone, up, target, cross ) { 52643 52644 const geometry = this.geometry; 52645 52646 const colorAttribute = geometry.getAttribute( 'color' ); 52647 52648 // near 52649 52650 colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2 52651 colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4 52652 colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3 52653 colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1 52654 52655 // far 52656 52657 colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2 52658 colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4 52659 colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3 52660 colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1 52661 52662 // sides 52663 52664 colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1 52665 colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2 52666 colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3 52667 colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4 52668 52669 // cone 52670 52671 colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1 52672 colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2 52673 colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3 52674 colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4 52675 52676 // up 52677 52678 colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2 52679 colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3 52680 colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1 52681 52682 // target 52683 52684 colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t 52685 colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c 52686 52687 // cross 52688 52689 colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2 52690 colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4 52691 52692 colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2 52693 colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4 52694 52695 colorAttribute.needsUpdate = true; 52696 52697 } 52698 52699 update() { 52700 52701 const geometry = this.geometry; 52702 const pointMap = this.pointMap; 52703 52704 const w = 1, h = 1; 52705 52706 // we need just camera projection matrix inverse 52707 // world matrix must be identity 52708 52709 _camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse ); 52710 52711 // center / target 52712 52713 setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 ); 52714 setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 ); 52715 52716 // near 52717 52718 setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 ); 52719 setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 ); 52720 setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 ); 52721 setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 ); 52722 52723 // far 52724 52725 setPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 ); 52726 setPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 ); 52727 setPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 ); 52728 setPoint( 'f4', pointMap, geometry, _camera, w, h, 1 ); 52729 52730 // up 52731 52732 setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 ); 52733 setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 ); 52734 setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 ); 52735 52736 // cross 52737 52738 setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 ); 52739 setPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 ); 52740 setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 ); 52741 setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 ); 52742 52743 setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 ); 52744 setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 ); 52745 setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 ); 52746 setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 ); 52747 52748 geometry.getAttribute( 'position' ).needsUpdate = true; 52749 52750 } 52751 52752 dispose() { 52753 52754 this.geometry.dispose(); 52755 this.material.dispose(); 52756 52757 } 52758 52759} 52760 52761 52762function setPoint( point, pointMap, geometry, camera, x, y, z ) { 52763 52764 _vector.set( x, y, z ).unproject( camera ); 52765 52766 const points = pointMap[ point ]; 52767 52768 if ( points !== undefined ) { 52769 52770 const position = geometry.getAttribute( 'position' ); 52771 52772 for ( let i = 0, l = points.length; i < l; i ++ ) { 52773 52774 position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z ); 52775 52776 } 52777 52778 } 52779 52780} 52781 52782const _box = /*@__PURE__*/ new Box3(); 52783 52784class BoxHelper extends LineSegments { 52785 52786 constructor( object, color = 0xffff00 ) { 52787 52788 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 ] ); 52789 const positions = new Float32Array( 8 * 3 ); 52790 52791 const geometry = new BufferGeometry(); 52792 geometry.setIndex( new BufferAttribute( indices, 1 ) ); 52793 geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) ); 52794 52795 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 52796 52797 this.object = object; 52798 this.type = 'BoxHelper'; 52799 52800 this.matrixAutoUpdate = false;
vendor: 4,705 bytes, lines 52801-53017
52801 52802 this.update(); 52803 52804 } 52805 52806 update( object ) { 52807 52808 if ( object !== undefined ) { 52809 52810 console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' ); 52811 52812 } 52813 52814 if ( this.object !== undefined ) { 52815 52816 _box.setFromObject( this.object ); 52817 52818 } 52819 52820 if ( _box.isEmpty() ) return; 52821 52822 const min = _box.min; 52823 const max = _box.max; 52824 52825 /* 52826 5____4 52827 1/___0/| 52828 | 6__|_7 52829 2/___3/ 52830 52831 0: max.x, max.y, max.z 52832 1: min.x, max.y, max.z 52833 2: min.x, min.y, max.z 52834 3: max.x, min.y, max.z 52835 4: max.x, max.y, min.z 52836 5: min.x, max.y, min.z 52837 6: min.x, min.y, min.z 52838 7: max.x, min.y, min.z 52839 */ 52840 52841 const position = this.geometry.attributes.position; 52842 const array = position.array; 52843 52844 array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z; 52845 array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z; 52846 array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z; 52847 array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z; 52848 array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z; 52849 array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z; 52850 array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z; 52851 array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z; 52852 52853 position.needsUpdate = true; 52854 52855 this.geometry.computeBoundingSphere(); 52856 52857 } 52858 52859 setFromObject( object ) { 52860 52861 this.object = object; 52862 this.update(); 52863 52864 return this; 52865 52866 } 52867 52868 copy( source, recursive ) { 52869 52870 super.copy( source, recursive ); 52871 52872 this.object = source.object; 52873 52874 return this; 52875 52876 } 52877 52878 dispose() { 52879 52880 this.geometry.dispose(); 52881 this.material.dispose(); 52882 52883 } 52884 52885} 52886 52887class Box3Helper extends LineSegments { 52888 52889 constructor( box, color = 0xffff00 ) { 52890 52891 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 ] ); 52892 52893 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 ]; 52894 52895 const geometry = new BufferGeometry(); 52896 52897 geometry.setIndex( new BufferAttribute( indices, 1 ) ); 52898 52899 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 52900 52901 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 52902 52903 this.box = box; 52904 52905 this.type = 'Box3Helper'; 52906 52907 this.geometry.computeBoundingSphere(); 52908 52909 } 52910 52911 updateMatrixWorld( force ) { 52912 52913 const box = this.box; 52914 52915 if ( box.isEmpty() ) return; 52916 52917 box.getCenter( this.position ); 52918 52919 box.getSize( this.scale ); 52920 52921 this.scale.multiplyScalar( 0.5 ); 52922 52923 super.updateMatrixWorld( force ); 52924 52925 } 52926 52927 dispose() { 52928 52929 this.geometry.dispose(); 52930 this.material.dispose(); 52931 52932 } 52933 52934} 52935 52936class PlaneHelper extends Line { 52937 52938 constructor( plane, size = 1, hex = 0xffff00 ) { 52939 52940 const color = hex; 52941 52942 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 ]; 52943 52944 const geometry = new BufferGeometry(); 52945 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 52946 geometry.computeBoundingSphere(); 52947 52948 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 52949 52950 this.type = 'PlaneHelper'; 52951 52952 this.plane = plane; 52953 52954 this.size = size; 52955 52956 const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ]; 52957 52958 const geometry2 = new BufferGeometry(); 52959 geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); 52960 geometry2.computeBoundingSphere(); 52961 52962 this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) ); 52963 52964 } 52965 52966 updateMatrixWorld( force ) { 52967 52968 this.position.set( 0, 0, 0 ); 52969 52970 this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 ); 52971 52972 this.lookAt( this.plane.normal ); 52973 52974 this.translateZ( - this.plane.constant ); 52975 52976 super.updateMatrixWorld( force ); 52977 52978 } 52979 52980 dispose() { 52981 52982 this.geometry.dispose(); 52983 this.material.dispose(); 52984 this.children[ 0 ].geometry.dispose(); 52985 this.children[ 0 ].material.dispose(); 52986 52987 } 52988 52989} 52990 52991const _axis = /*@__PURE__*/ new Vector3(); 52992let _lineGeometry, _coneGeometry; 52993 52994class ArrowHelper extends Object3D { 52995 52996 // dir is assumed to be normalized 52997 52998 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 ) { 52999 53000 super(); 53001 53002 this.type = 'ArrowHelper'; 53003 53004 if ( _lineGeometry === undefined ) { 53005 53006 _lineGeometry = new BufferGeometry(); 53007 _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); 53008 53009 _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 ); 53010 _coneGeometry.translate( 0, - 0.5, 0 ); 53011 53012 } 53013 53014 this.position.copy( origin ); 53015 53016 this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 53017 this.line.matrixAutoUpdate = false;
vendor: 3,957 bytes, lines 53018-53237
53018 this.add( this.line ); 53019 53020 this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) ); 53021 this.cone.matrixAutoUpdate = false; 53022 this.add( this.cone ); 53023 53024 this.setDirection( dir ); 53025 this.setLength( length, headLength, headWidth ); 53026 53027 } 53028 53029 setDirection( dir ) { 53030 53031 // dir is assumed to be normalized 53032 53033 if ( dir.y > 0.99999 ) { 53034 53035 this.quaternion.set( 0, 0, 0, 1 ); 53036 53037 } else if ( dir.y < - 0.99999 ) { 53038 53039 this.quaternion.set( 1, 0, 0, 0 ); 53040 53041 } else { 53042 53043 _axis.set( dir.z, 0, - dir.x ).normalize(); 53044 53045 const radians = Math.acos( dir.y ); 53046 53047 this.quaternion.setFromAxisAngle( _axis, radians ); 53048 53049 } 53050 53051 } 53052 53053 setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) { 53054 53055 this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458 53056 this.line.updateMatrix(); 53057 53058 this.cone.scale.set( headWidth, headLength, headWidth ); 53059 this.cone.position.y = length; 53060 this.cone.updateMatrix(); 53061 53062 } 53063 53064 setColor( color ) { 53065 53066 this.line.material.color.set( color ); 53067 this.cone.material.color.set( color ); 53068 53069 } 53070 53071 copy( source ) { 53072 53073 super.copy( source, false ); 53074 53075 this.line.copy( source.line ); 53076 this.cone.copy( source.cone ); 53077 53078 return this; 53079 53080 } 53081 53082 dispose() { 53083 53084 this.line.geometry.dispose(); 53085 this.line.material.dispose(); 53086 this.cone.geometry.dispose(); 53087 this.cone.material.dispose(); 53088 53089 } 53090 53091} 53092 53093class AxesHelper extends LineSegments { 53094 53095 constructor( size = 1 ) { 53096 53097 const vertices = [ 53098 0, 0, 0, size, 0, 0, 53099 0, 0, 0, 0, size, 0, 53100 0, 0, 0, 0, 0, size 53101 ]; 53102 53103 const colors = [ 53104 1, 0, 0, 1, 0.6, 0, 53105 0, 1, 0, 0.6, 1, 0, 53106 0, 0, 1, 0, 0.6, 1 53107 ]; 53108 53109 const geometry = new BufferGeometry(); 53110 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 53111 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 53112 53113 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); 53114 53115 super( geometry, material ); 53116 53117 this.type = 'AxesHelper'; 53118 53119 } 53120 53121 setColors( xAxisColor, yAxisColor, zAxisColor ) { 53122 53123 const color = new Color(); 53124 const array = this.geometry.attributes.color.array; 53125 53126 color.set( xAxisColor ); 53127 color.toArray( array, 0 ); 53128 color.toArray( array, 3 ); 53129 53130 color.set( yAxisColor ); 53131 color.toArray( array, 6 ); 53132 color.toArray( array, 9 ); 53133 53134 color.set( zAxisColor ); 53135 color.toArray( array, 12 ); 53136 color.toArray( array, 15 ); 53137 53138 this.geometry.attributes.color.needsUpdate = true; 53139 53140 return this; 53141 53142 } 53143 53144 dispose() { 53145 53146 this.geometry.dispose(); 53147 this.material.dispose(); 53148 53149 } 53150 53151} 53152 53153class ShapePath { 53154 53155 constructor() { 53156 53157 this.type = 'ShapePath'; 53158 53159 this.color = new Color(); 53160 53161 this.subPaths = []; 53162 this.currentPath = null; 53163 53164 } 53165 53166 moveTo( x, y ) { 53167 53168 this.currentPath = new Path(); 53169 this.subPaths.push( this.currentPath ); 53170 this.currentPath.moveTo( x, y ); 53171 53172 return this; 53173 53174 } 53175 53176 lineTo( x, y ) { 53177 53178 this.currentPath.lineTo( x, y ); 53179 53180 return this; 53181 53182 } 53183 53184 quadraticCurveTo( aCPx, aCPy, aX, aY ) { 53185 53186 this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY ); 53187 53188 return this; 53189 53190 } 53191 53192 bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { 53193 53194 this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ); 53195 53196 return this; 53197 53198 } 53199 53200 splineThru( pts ) { 53201 53202 this.currentPath.splineThru( pts ); 53203 53204 return this; 53205 53206 } 53207 53208 toShapes( isCCW ) { 53209 53210 function toShapesNoHoles( inSubpaths ) { 53211 53212 const shapes = []; 53213 53214 for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) { 53215 53216 const tmpPath = inSubpaths[ i ]; 53217 53218 const tmpShape = new Shape(); 53219 tmpShape.curves = tmpPath.curves; 53220 53221 shapes.push( tmpShape ); 53222 53223 } 53224 53225 return shapes; 53226 53227 } 53228 53229 function isPointInsidePolygon( inPt, inPolygon ) { 53230 53231 const polyLen = inPolygon.length; 53232 53233 // inPt on polygon contour => immediate success or 53234 // toggling of inside/outside at every single! intersection point of an edge 53235 // with the horizontal line through inPt, left of inPt 53236 // not counting lowerY endpoints of edges and whole edges on that line 53237 let inside = false;
53238 for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { 53239 53240 let edgeLowPt = inPolygon[ p ]; 53241 let edgeHighPt = inPolygon[ q ]; 53242 53243 let edgeDx = edgeHighPt.x - edgeLowPt.x; 53244 let edgeDy = edgeHighPt.y - edgeLowPt.y; 53245 53246 if ( Math.abs( edgeDy ) > Number.EPSILON ) { 53247 53248 // not parallel 53249 if ( edgeDy < 0 ) { 53250 53251 edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx; 53252 edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy; 53253 53254 } 53255 53256 if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue; 53257 53258 if ( inPt.y === edgeLowPt.y ) { 53259 53260 if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ? 53261 // continue; // no intersection or edgeLowPt => doesn't count !!! 53262 53263 } else { 53264 53265 const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y ); 53266 if ( perpEdge === 0 ) return true; // inPt is on contour ? 53267 if ( perpEdge < 0 ) continue; 53268 inside = ! inside; // true intersection left of inPt 53269 53270 } 53271 53272 } else { 53273 53274 // parallel or collinear 53275 if ( inPt.y !== edgeLowPt.y ) continue; // parallel 53276 // edge lies on the same horizontal line as inPt 53277 if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || 53278 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour ! 53279 // continue; 53280 53281 } 53282 53283 } 53284 53285 return inside; 53286 53287 } 53288 53289 const isClockWise = ShapeUtils.isClockWise; 53290 53291 const subPaths = this.subPaths; 53292 if ( subPaths.length === 0 ) return []; 53293 53294 let solid, tmpPath, tmpShape; 53295 const shapes = []; 53296 53297 if ( subPaths.length === 1 ) { 53298 53299 tmpPath = subPaths[ 0 ]; 53300 tmpShape = new Shape(); 53301 tmpShape.curves = tmpPath.curves; 53302 shapes.push( tmpShape ); 53303 return shapes; 53304 53305 } 53306 53307 let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); 53308 holesFirst = isCCW ? ! holesFirst : holesFirst; 53309 53310 // console.log("Holes first", holesFirst); 53311 53312 const betterShapeHoles = []; 53313 const newShapes = []; 53314 let newShapeHoles = []; 53315 let mainIdx = 0; 53316 let tmpPoints; 53317 53318 newShapes[ mainIdx ] = undefined; 53319 newShapeHoles[ mainIdx ] = []; 53320 53321 for ( let i = 0, l = subPaths.length; i < l; i ++ ) { 53322 53323 tmpPath = subPaths[ i ]; 53324 tmpPoints = tmpPath.getPoints(); 53325 solid = isClockWise( tmpPoints ); 53326 solid = isCCW ? ! solid : solid; 53327 53328 if ( solid ) { 53329 53330 if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++; 53331 53332 newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints }; 53333 newShapes[ mainIdx ].s.curves = tmpPath.curves; 53334 53335 if ( holesFirst ) mainIdx ++; 53336 newShapeHoles[ mainIdx ] = []; 53337 53338 //console.log('cw', i); 53339 53340 } else { 53341 53342 newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); 53343 53344 //console.log('ccw', i); 53345 53346 } 53347 53348 } 53349 53350 // only Holes? -> probably all Shapes with wrong orientation 53351 if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths ); 53352 53353 53354 if ( newShapes.length > 1 ) { 53355 53356 let ambiguous = false; 53357 let toChange = 0; 53358 53359 for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { 53360 53361 betterShapeHoles[ sIdx ] = []; 53362 53363 } 53364 53365 for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { 53366 53367 const sho = newShapeHoles[ sIdx ]; 53368 53369 for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) { 53370 53371 const ho = sho[ hIdx ]; 53372 let hole_unassigned = true; 53373 53374 for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) { 53375 53376 if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) { 53377 53378 if ( sIdx !== s2Idx ) toChange ++; 53379 53380 if ( hole_unassigned ) { 53381 53382 hole_unassigned = false; 53383 betterShapeHoles[ s2Idx ].push( ho ); 53384 53385 } else { 53386 53387 ambiguous = true; 53388 53389 } 53390 53391 } 53392 53393 } 53394 53395 if ( hole_unassigned ) { 53396 53397 betterShapeHoles[ sIdx ].push( ho ); 53398 53399 } 53400 53401 } 53402 53403 } 53404 53405 if ( toChange > 0 && ambiguous === false ) { 53406 53407 newShapeHoles = betterShapeHoles; 53408 53409 } 53410 53411 } 53412 53413 let tmpHoles; 53414 53415 for ( let i = 0, il = newShapes.length; i < il; i ++ ) { 53416 53417 tmpShape = newShapes[ i ].s; 53418 shapes.push( tmpShape ); 53419 tmpHoles = newShapeHoles[ i ]; 53420 53421 for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) { 53422 53423 tmpShape.holes.push( tmpHoles[ j ].h ); 53424 53425 } 53426 53427 } 53428 53429 //console.log("shape", shapes); 53430 53431 return shapes; 53432 53433 } 53434 53435} 53436 53437class WebGLMultipleRenderTargets extends WebGLRenderTarget { // @deprecated, r162 53438 53439 constructor( width = 1, height = 1, count = 1, options = {} ) { 53440 53441 console.warn( 'THREE.WebGLMultipleRenderTargets has been deprecated and will be removed in r172. Use THREE.WebGLRenderTarget and set the "count" parameter to enable MRT.' ); 53442 53443 super( width, height, { ...options, count } ); 53444
53445 this.isWebGLMultipleRenderTargets = true; 53446 53447 } 53448 53449 get texture() { 53450 53451 return this.textures; 53452 53453 } 53454 53455} 53456 53457if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { 53458 53459 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: { 53460 revision: REVISION, 53461 } } ) ); 53462 53463} 53464 53465if ( typeof window !== 'undefined' ) { 53466 53467 if ( window.__THREE__ ) { 53468 53469 console.warn( 'WARNING: Multiple instances of Three.js being imported.' ); 53470 53471 } else { 53472 53473 window.__THREE__ = REVISION; 53474 53475 } 53476 53477} 53478 53479export { 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
53479phicCamera, 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.