1/** 2 * @license 3 * Copyright 2010-2023 Three.js Authors 4 * SPDX-License-Identifier: MIT 5 */ 6const REVISION = '160'; 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 TwoPassDoubleSide = 2; // r149 22const NoBlending = 0; 23const NormalBlending = 1; 24const AdditiveBlending = 2; 25const SubtractiveBlending = 3; 26const MultiplyBlending = 4; 27const CustomBlending = 5; 28const AddEquation = 100; 29const SubtractEquation = 101; 30const ReverseSubtractEquation = 102; 31const MinEquation = 103; 32const MaxEquation = 104; 33const ZeroFactor = 200; 34const OneFactor = 201; 35const SrcColorFactor = 202; 36const OneMinusSrcColorFactor = 203; 37const SrcAlphaFactor = 204; 38const OneMinusSrcAlphaFactor = 205; 39const DstAlphaFactor = 206; 40const OneMinusDstAlphaFactor = 207; 41const DstColorFactor = 208; 42const OneMinusDstColorFactor = 209; 43const SrcAlphaSaturateFactor = 210; 44const ConstantColorFactor = 211; 45const OneMinusConstantColorFactor = 212; 46const ConstantAlphaFactor = 213; 47const OneMinusConstantAlphaFactor = 214; 48const NeverDepth = 0; 49const AlwaysDepth = 1; 50const LessDepth = 2; 51const LessEqualDepth = 3; 52const EqualDepth = 4; 53const GreaterEqualDepth = 5; 54const GreaterDepth = 6; 55const NotEqualDepth = 7; 56const MultiplyOperation = 0; 57const MixOperation = 1; 58const AddOperation = 2; 59const NoToneMapping = 0; 60const LinearToneMapping = 1; 61const ReinhardToneMapping = 2; 62const CineonToneMapping = 3; 63const ACESFilmicToneMapping = 4; 64const CustomToneMapping = 5; 65const AgXToneMapping = 6; 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 AlphaFormat = 1021; 100const RGBAFormat = 1023; 101const LuminanceFormat = 1024; 102const LuminanceAlphaFormat = 1025; 103const DepthFormat = 1026; 104const DepthStencilFormat = 1027; 105const RedFormat = 1028; 106const RedIntegerFormat = 1029; 107const RGFormat = 1030; 108const RGIntegerFormat = 1031; 109const RGBAIntegerFormat = 1033; 110 111const RGB_S3TC_DXT1_Format = 33776; 112const RGBA_S3TC_DXT1_Format = 33777; 113const RGBA_S3TC_DXT3_Format = 33778; 114const RGBA_S3TC_DXT5_Format = 33779; 115const RGB_PVRTC_4BPPV1_Format = 35840; 116const RGB_PVRTC_2BPPV1_Format = 35841; 117const RGBA_PVRTC_4BPPV1_Format = 35842; 118const RGBA_PVRTC_2BPPV1_Format = 35843; 119const RGB_ETC1_Format = 36196; 120const RGB_ETC2_Format = 37492; 121const RGBA_ETC2_EAC_Format = 37496; 122const RGBA_ASTC_4x4_Format = 37808; 123const RGBA_ASTC_5x4_Format = 37809; 124const RGBA_ASTC_5x5_Format = 37810; 125const RGBA_ASTC_6x5_Format = 37811; 126const RGBA_ASTC_6x6_Format = 37812; 127const RGBA_ASTC_8x5_Format = 37813; 128const RGBA_ASTC_8x6_Format = 37814; 129const RGBA_ASTC_8x8_Format = 37815; 130const RGBA_ASTC_10x5_Format = 37816; 131const RGBA_ASTC_10x6_Format = 37817; 132const RGBA_ASTC_10x8_Format = 37818; 133const RGBA_ASTC_10x10_Format = 37819; 134const RGBA_ASTC_12x10_Format = 37820; 135const RGBA_ASTC_12x12_Format = 37821; 136const RGBA_BPTC_Format = 36492; 137const RGB_BPTC_SIGNED_Format = 36494; 138const RGB_BPTC_UNSIGNED_Format = 36495; 139const RED_RGTC1_Format = 36283;
vendor: 8,389 bytes, lines 140-434
140const SIGNED_RED_RGTC1_Format = 36284; 141const RED_GREEN_RGTC2_Format = 36285; 142const SIGNED_RED_GREEN_RGTC2_Format = 36286; 143const LoopOnce = 2200; 144const LoopRepeat = 2201; 145const LoopPingPong = 2202; 146const InterpolateDiscrete = 2300; 147const InterpolateLinear = 2301; 148const InterpolateSmooth = 2302; 149const ZeroCurvatureEnding = 2400; 150const ZeroSlopeEnding = 2401; 151const WrapAroundEnding = 2402; 152const NormalAnimationBlendMode = 2500; 153const AdditiveAnimationBlendMode = 2501; 154const TrianglesDrawMode = 0; 155const TriangleStripDrawMode = 1; 156const TriangleFanDrawMode = 2; 157/** @deprecated Use LinearSRGBColorSpace or NoColorSpace in three.js r152+. */ 158const LinearEncoding = 3000; 159/** @deprecated Use SRGBColorSpace in three.js r152+. */ 160const sRGBEncoding = 3001; 161const BasicDepthPacking = 3200; 162const RGBADepthPacking = 3201; 163const TangentSpaceNormalMap = 0; 164const ObjectSpaceNormalMap = 1; 165 166// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available. 167const NoColorSpace = ''; 168const SRGBColorSpace = 'srgb'; 169const LinearSRGBColorSpace = 'srgb-linear'; 170const DisplayP3ColorSpace = 'display-p3'; 171const LinearDisplayP3ColorSpace = 'display-p3-linear'; 172 173const LinearTransfer = 'linear'; 174const SRGBTransfer = 'srgb'; 175 176const Rec709Primaries = 'rec709'; 177const P3Primaries = 'p3'; 178 179const ZeroStencilOp = 0; 180const KeepStencilOp = 7680; 181const ReplaceStencilOp = 7681; 182const IncrementStencilOp = 7682; 183const DecrementStencilOp = 7683; 184const IncrementWrapStencilOp = 34055; 185const DecrementWrapStencilOp = 34056; 186const InvertStencilOp = 5386; 187 188const NeverStencilFunc = 512; 189const LessStencilFunc = 513; 190const EqualStencilFunc = 514; 191const LessEqualStencilFunc = 515; 192const GreaterStencilFunc = 516; 193const NotEqualStencilFunc = 517; 194const GreaterEqualStencilFunc = 518; 195const AlwaysStencilFunc = 519; 196 197const NeverCompare = 512; 198const LessCompare = 513; 199const EqualCompare = 514; 200const LessEqualCompare = 515; 201const GreaterCompare = 516; 202const NotEqualCompare = 517; 203const GreaterEqualCompare = 518; 204const AlwaysCompare = 519; 205 206const StaticDrawUsage = 35044; 207const DynamicDrawUsage = 35048; 208const StreamDrawUsage = 35040; 209const StaticReadUsage = 35045; 210const DynamicReadUsage = 35049; 211const StreamReadUsage = 35041; 212const StaticCopyUsage = 35046; 213const DynamicCopyUsage = 35050; 214const StreamCopyUsage = 35042; 215 216const GLSL1 = '100'; 217const GLSL3 = '300 es'; 218 219const _SRGBAFormat = 1035; // fallback for WebGL 1 220 221const WebGLCoordinateSystem = 2000; 222const WebGPUCoordinateSystem = 2001; 223 224/** 225 * https://github.com/mrdoob/eventdispatcher.js/ 226 */ 227 228class EventDispatcher { 229 230 addEventListener( type, listener ) { 231 232 if ( this._listeners === undefined ) this._listeners = {}; 233 234 const listeners = this._listeners; 235 236 if ( listeners[ type ] === undefined ) { 237 238 listeners[ type ] = []; 239 240 } 241 242 if ( listeners[ type ].indexOf( listener ) === - 1 ) { 243 244 listeners[ type ].push( listener ); 245 246 } 247 248 } 249 250 hasEventListener( type, listener ) { 251 252 if ( this._listeners === undefined ) return false; 253 254 const listeners = this._listeners; 255 256 return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1; 257 258 } 259 260 removeEventListener( type, listener ) { 261 262 if ( this._listeners === undefined ) return; 263 264 const listeners = this._listeners; 265 const listenerArray = listeners[ type ]; 266 267 if ( listenerArray !== undefined ) { 268 269 const index = listenerArray.indexOf( listener ); 270 271 if ( index !== - 1 ) { 272 273 listenerArray.splice( index, 1 ); 274 275 } 276 277 } 278 279 } 280 281 dispatchEvent( event ) { 282 283 if ( this._listeners === undefined ) return; 284 285 const listeners = this._listeners; 286 const listenerArray = listeners[ event.type ]; 287 288 if ( listenerArray !== undefined ) { 289 290 event.target = this; 291 292 // Make a copy, in case listeners are removed while iterating. 293 const array = listenerArray.slice( 0 ); 294 295 for ( let i = 0, l = array.length; i < l; i ++ ) { 296 297 array[ i ].call( this, event ); 298 299 } 300 301 event.target = null; 302 303 } 304 305 } 306 307} 308 309const _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' ]; 310 311let _seed = 1234567; 312 313 314const DEG2RAD = Math.PI / 180; 315const RAD2DEG = 180 / Math.PI; 316 317// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 318function generateUUID() { 319 320 const d0 = Math.random() * 0xffffffff | 0; 321 const d1 = Math.random() * 0xffffffff | 0; 322 const d2 = Math.random() * 0xffffffff | 0; 323 const d3 = Math.random() * 0xffffffff | 0; 324 const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' + 325 _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' + 326 _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] + 327 _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ]; 328 329 // .toLowerCase() here flattens concatenated strings to save heap memory space. 330 return uuid.toLowerCase(); 331 332} 333 334function clamp( value, min, max ) { 335 336 return Math.max( min, Math.min( max, value ) ); 337 338} 339 340// compute euclidean modulo of m % n 341// https://en.wikipedia.org/wiki/Modulo_operation 342function euclideanModulo( n, m ) { 343 344 return ( ( n % m ) + m ) % m; 345 346} 347 348// Linear mapping from range <a1, a2> to range <b1, b2> 349function mapLinear( x, a1, a2, b1, b2 ) { 350 351 return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); 352 353} 354 355// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/ 356function inverseLerp( x, y, value ) { 357 358 if ( x !== y ) { 359 360 return ( value - x ) / ( y - x ); 361 362 } else { 363 364 return 0; 365 366 } 367 368} 369 370// https://en.wikipedia.org/wiki/Linear_interpolation 371function lerp( x, y, t ) { 372 373 return ( 1 - t ) * x + t * y; 374 375} 376 377// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ 378function damp( x, y, lambda, dt ) { 379 380 return lerp( x, y, 1 - Math.exp( - lambda * dt ) ); 381 382} 383 384// https://www.desmos.com/calculator/vcsjnyz7x4 385function pingpong( x, length = 1 ) { 386 387 return length - Math.abs( euclideanModulo( x, length * 2 ) - length ); 388 389} 390 391// http://en.wikipedia.org/wiki/Smoothstep 392function smoothstep( x, min, max ) { 393 394 if ( x <= min ) return 0; 395 if ( x >= max ) return 1; 396 397 x = ( x - min ) / ( max - min ); 398 399 return x * x * ( 3 - 2 * x ); 400 401} 402 403function smootherstep( x, min, max ) { 404 405 if ( x <= min ) return 0; 406 if ( x >= max ) return 1; 407 408 x = ( x - min ) / ( max - min ); 409 410 return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); 411 412} 413 414// Random integer from <low, high> interval 415function randInt( low, high ) { 416 417 return low + Math.floor( Math.random() * ( high - low + 1 ) ); 418 419} 420 421// Random float from <low, high> interval 422function randFloat( low, high ) { 423 424 return low + Math.random() * ( high - low ); 425 426} 427 428// Random float from <-range/2, range/2> interval 429function randFloatSpread( range ) { 430 431 return range * ( 0.5 - Math.random() ); 432 433} 434
vendor: 7,916 bytes, lines 435-1010
435// Deterministic pseudo-random float in the interval [ 0, 1 ] 436function seededRandom( s ) { 437 438 if ( s !== undefined ) _seed = s; 439 440 // Mulberry32 generator 441 442 let t = _seed += 0x6D2B79F5; 443 444 t = Math.imul( t ^ t >>> 15, t | 1 ); 445 446 t ^= t + Math.imul( t ^ t >>> 7, t | 61 ); 447 448 return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296; 449 450} 451 452function degToRad( degrees ) { 453 454 return degrees * DEG2RAD; 455 456} 457 458function radToDeg( radians ) { 459 460 return radians * RAD2DEG; 461 462} 463 464function isPowerOfTwo( value ) { 465 466 return ( value & ( value - 1 ) ) === 0 && value !== 0; 467 468} 469 470function ceilPowerOfTwo( value ) { 471 472 return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); 473 474} 475 476function floorPowerOfTwo( value ) { 477 478 return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); 479 480} 481 482function setQuaternionFromProperEuler( q, a, b, c, order ) { 483 484 // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles 485 486 // rotations are applied to the axes in the order specified by 'order' 487 // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c' 488 // angles are in radians 489 490 const cos = Math.cos; 491 const sin = Math.sin; 492 493 const c2 = cos( b / 2 ); 494 const s2 = sin( b / 2 ); 495 496 const c13 = cos( ( a + c ) / 2 ); 497 const s13 = sin( ( a + c ) / 2 ); 498 499 const c1_3 = cos( ( a - c ) / 2 ); 500 const s1_3 = sin( ( a - c ) / 2 ); 501 502 const c3_1 = cos( ( c - a ) / 2 ); 503 const s3_1 = sin( ( c - a ) / 2 ); 504 505 switch ( order ) { 506 507 case 'XYX': 508 q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 ); 509 break; 510 511 case 'YZY': 512 q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 ); 513 break; 514 515 case 'ZXZ': 516 q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 ); 517 break; 518 519 case 'XZX': 520 q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 ); 521 break; 522 523 case 'YXY': 524 q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 ); 525 break; 526 527 case 'ZYZ': 528 q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 ); 529 break; 530 531 default: 532 console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order ); 533 534 } 535 536} 537 538function denormalize( value, array ) { 539 540 switch ( array.constructor ) { 541 542 case Float32Array: 543 544 return value; 545 546 case Uint32Array: 547 548 return value / 4294967295.0; 549 550 case Uint16Array: 551 552 return value / 65535.0; 553 554 case Uint8Array: 555 556 return value / 255.0; 557 558 case Int32Array: 559 560 return Math.max( value / 2147483647.0, - 1.0 ); 561 562 case Int16Array: 563 564 return Math.max( value / 32767.0, - 1.0 ); 565 566 case Int8Array: 567 568 return Math.max( value / 127.0, - 1.0 ); 569 570 default: 571 572 throw new Error( 'Invalid component type.' ); 573 574 } 575 576} 577 578function normalize( value, array ) { 579 580 switch ( array.constructor ) { 581 582 case Float32Array: 583 584 return value; 585 586 case Uint32Array: 587 588 return Math.round( value * 4294967295.0 ); 589 590 case Uint16Array: 591 592 return Math.round( value * 65535.0 ); 593 594 case Uint8Array: 595 596 return Math.round( value * 255.0 ); 597 598 case Int32Array: 599 600 return Math.round( value * 2147483647.0 ); 601 602 case Int16Array: 603 604 return Math.round( value * 32767.0 ); 605 606 case Int8Array: 607 608 return Math.round( value * 127.0 ); 609 610 default: 611 612 throw new Error( 'Invalid component type.' ); 613 614 } 615 616} 617 618const MathUtils = { 619 DEG2RAD: DEG2RAD, 620 RAD2DEG: RAD2DEG, 621 generateUUID: generateUUID, 622 clamp: clamp, 623 euclideanModulo: euclideanModulo, 624 mapLinear: mapLinear, 625 inverseLerp: inverseLerp, 626 lerp: lerp, 627 damp: damp, 628 pingpong: pingpong, 629 smoothstep: smoothstep, 630 smootherstep: smootherstep, 631 randInt: randInt, 632 randFloat: randFloat, 633 randFloatSpread: randFloatSpread, 634 seededRandom: seededRandom, 635 degToRad: degToRad, 636 radToDeg: radToDeg, 637 isPowerOfTwo: isPowerOfTwo, 638 ceilPowerOfTwo: ceilPowerOfTwo, 639 floorPowerOfTwo: floorPowerOfTwo, 640 setQuaternionFromProperEuler: setQuaternionFromProperEuler, 641 normalize: normalize, 642 denormalize: denormalize 643}; 644 645class Vector2 { 646 647 constructor( x = 0, y = 0 ) { 648 649 Vector2.prototype.isVector2 = true; 650 651 this.x = x; 652 this.y = y; 653 654 } 655 656 get width() { 657 658 return this.x; 659 660 } 661 662 set width( value ) { 663 664 this.x = value; 665 666 } 667 668 get height() { 669 670 return this.y; 671 672 } 673 674 set height( value ) { 675 676 this.y = value; 677 678 } 679 680 set( x, y ) { 681 682 this.x = x; 683 this.y = y; 684 685 return this; 686 687 } 688 689 setScalar( scalar ) { 690 691 this.x = scalar; 692 this.y = scalar; 693 694 return this; 695 696 } 697 698 setX( x ) { 699 700 this.x = x; 701 702 return this; 703 704 } 705 706 setY( y ) { 707 708 this.y = y; 709 710 return this; 711 712 } 713 714 setComponent( index, value ) { 715 716 switch ( index ) { 717 718 case 0: this.x = value; break; 719 case 1: this.y = value; break; 720 default: throw new Error( 'index is out of range: ' + index ); 721 722 } 723 724 return this; 725 726 } 727 728 getComponent( index ) { 729 730 switch ( index ) { 731 732 case 0: return this.x; 733 case 1: return this.y; 734 default: throw new Error( 'index is out of range: ' + index ); 735 736 } 737 738 } 739 740 clone() { 741 742 return new this.constructor( this.x, this.y ); 743 744 } 745 746 copy( v ) { 747 748 this.x = v.x; 749 this.y = v.y; 750 751 return this; 752 753 } 754 755 add( v ) { 756 757 this.x += v.x; 758 this.y += v.y; 759 760 return this; 761 762 } 763 764 addScalar( s ) { 765 766 this.x += s; 767 this.y += s; 768 769 return this; 770 771 } 772 773 addVectors( a, b ) { 774 775 this.x = a.x + b.x; 776 this.y = a.y + b.y; 777 778 return this; 779 780 } 781 782 addScaledVector( v, s ) { 783 784 this.x += v.x * s; 785 this.y += v.y * s; 786 787 return this; 788 789 } 790 791 sub( v ) { 792 793 this.x -= v.x; 794 this.y -= v.y; 795 796 return this; 797 798 } 799 800 subScalar( s ) { 801 802 this.x -= s; 803 this.y -= s; 804 805 return this; 806 807 } 808 809 subVectors( a, b ) { 810 811 this.x = a.x - b.x; 812 this.y = a.y - b.y; 813 814 return this; 815 816 } 817 818 multiply( v ) { 819 820 this.x *= v.x; 821 this.y *= v.y; 822 823 return this; 824 825 } 826 827 multiplyScalar( scalar ) { 828 829 this.x *= scalar; 830 this.y *= scalar; 831 832 return this; 833 834 } 835 836 divide( v ) { 837 838 this.x /= v.x; 839 this.y /= v.y; 840 841 return this; 842 843 } 844 845 divideScalar( scalar ) { 846 847 return this.multiplyScalar( 1 / scalar ); 848 849 } 850 851 applyMatrix3( m ) { 852 853 const x = this.x, y = this.y; 854 const e = m.elements; 855 856 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ]; 857 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ]; 858 859 return this; 860 861 } 862 863 min( v ) { 864 865 this.x = Math.min( this.x, v.x ); 866 this.y = Math.min( this.y, v.y ); 867 868 return this; 869 870 } 871 872 max( v ) { 873 874 this.x = Math.max( this.x, v.x ); 875 this.y = Math.max( this.y, v.y ); 876 877 return this; 878 879 } 880 881 clamp( min, max ) { 882 883 // assumes min < max, componentwise 884 885 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 886 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 887 888 return this; 889 890 } 891 892 clampScalar( minVal, maxVal ) { 893 894 this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); 895 this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); 896 897 return this; 898 899 } 900 901 clampLength( min, max ) { 902 903 const length = this.length(); 904 905 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 906 907 } 908 909 floor() { 910 911 this.x = Math.floor( this.x ); 912 this.y = Math.floor( this.y ); 913 914 return this; 915 916 } 917 918 ceil() { 919 920 this.x = Math.ceil( this.x ); 921 this.y = Math.ceil( this.y ); 922 923 return this; 924 925 } 926 927 round() { 928 929 this.x = Math.round( this.x ); 930 this.y = Math.round( this.y ); 931 932 return this; 933 934 } 935 936 roundToZero() { 937 938 this.x = Math.trunc( this.x ); 939 this.y = Math.trunc( this.y ); 940 941 return this; 942 943 } 944 945 negate() { 946 947 this.x = - this.x; 948 this.y = - this.y; 949 950 return this; 951 952 } 953 954 dot( v ) { 955 956 return this.x * v.x + this.y * v.y; 957 958 } 959 960 cross( v ) { 961 962 return this.x * v.y - this.y * v.x; 963 964 } 965 966 lengthSq() { 967 968 return this.x * this.x + this.y * this.y; 969 970 } 971 972 length() { 973 974 return Math.sqrt( this.x * this.x + this.y * this.y ); 975 976 } 977 978 manhattanLength() { 979 980 return Math.abs( this.x ) + Math.abs( this.y ); 981 982 } 983 984 normalize() { 985 986 return this.divideScalar( this.length() || 1 ); 987 988 } 989 990 angle() { 991 992 // computes the angle in radians with respect to the positive x-axis 993 994 const angle = Math.atan2( - this.y, - this.x ) + Math.PI; 995 996 return angle; 997 998 } 999 1000 angleTo( v ) { 1001 1002 const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); 1003 1004 if ( denominator === 0 ) return Math.PI / 2; 1005 1006 const theta = this.dot( v ) / denominator; 1007 1008 // clamp, to handle numerical problems 1009 1010 return Math.acos( clamp( theta, -
vendor: 7,768 bytes, lines 1010-1522
10101, 1 ) ); 1011 1012 } 1013 1014 distanceTo( v ) { 1015 1016 return Math.sqrt( this.distanceToSquared( v ) ); 1017 1018 } 1019 1020 distanceToSquared( v ) { 1021 1022 const dx = this.x - v.x, dy = this.y - v.y; 1023 return dx * dx + dy * dy; 1024 1025 } 1026 1027 manhattanDistanceTo( v ) { 1028 1029 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ); 1030 1031 } 1032 1033 setLength( length ) { 1034 1035 return this.normalize().multiplyScalar( length ); 1036 1037 } 1038 1039 lerp( v, alpha ) { 1040 1041 this.x += ( v.x - this.x ) * alpha; 1042 this.y += ( v.y - this.y ) * alpha; 1043 1044 return this; 1045 1046 } 1047 1048 lerpVectors( v1, v2, alpha ) { 1049 1050 this.x = v1.x + ( v2.x - v1.x ) * alpha; 1051 this.y = v1.y + ( v2.y - v1.y ) * alpha; 1052 1053 return this; 1054 1055 } 1056 1057 equals( v ) { 1058 1059 return ( ( v.x === this.x ) && ( v.y === this.y ) ); 1060 1061 } 1062 1063 fromArray( array, offset = 0 ) { 1064 1065 this.x = array[ offset ]; 1066 this.y = array[ offset + 1 ]; 1067 1068 return this; 1069 1070 } 1071 1072 toArray( array = [], offset = 0 ) { 1073 1074 array[ offset ] = this.x; 1075 array[ offset + 1 ] = this.y; 1076 1077 return array; 1078 1079 } 1080 1081 fromBufferAttribute( attribute, index ) { 1082 1083 this.x = attribute.getX( index ); 1084 this.y = attribute.getY( index ); 1085 1086 return this; 1087 1088 } 1089 1090 rotateAround( center, angle ) { 1091 1092 const c = Math.cos( angle ), s = Math.sin( angle ); 1093 1094 const x = this.x - center.x; 1095 const y = this.y - center.y; 1096 1097 this.x = x * c - y * s + center.x; 1098 this.y = x * s + y * c + center.y; 1099 1100 return this; 1101 1102 } 1103 1104 random() { 1105 1106 this.x = Math.random(); 1107 this.y = Math.random(); 1108 1109 return this; 1110 1111 } 1112 1113 *[ Symbol.iterator ]() { 1114 1115 yield this.x; 1116 yield this.y; 1117 1118 } 1119 1120} 1121 1122class Matrix3 { 1123 1124 constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { 1125 1126 Matrix3.prototype.isMatrix3 = true; 1127 1128 this.elements = [ 1129 1130 1, 0, 0, 1131 0, 1, 0, 1132 0, 0, 1 1133 1134 ]; 1135 1136 if ( n11 !== undefined ) { 1137 1138 this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ); 1139 1140 } 1141 1142 } 1143 1144 set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { 1145 1146 const te = this.elements; 1147 1148 te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31; 1149 te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32; 1150 te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33; 1151 1152 return this; 1153 1154 } 1155 1156 identity() { 1157 1158 this.set( 1159 1160 1, 0, 0, 1161 0, 1, 0, 1162 0, 0, 1 1163 1164 ); 1165 1166 return this; 1167 1168 } 1169 1170 copy( m ) { 1171 1172 const te = this.elements; 1173 const me = m.elements; 1174 1175 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; 1176 te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; 1177 te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ]; 1178 1179 return this; 1180 1181 } 1182 1183 extractBasis( xAxis, yAxis, zAxis ) { 1184 1185 xAxis.setFromMatrix3Column( this, 0 ); 1186 yAxis.setFromMatrix3Column( this, 1 ); 1187 zAxis.setFromMatrix3Column( this, 2 ); 1188 1189 return this; 1190 1191 } 1192 1193 setFromMatrix4( m ) { 1194 1195 const me = m.elements; 1196 1197 this.set( 1198 1199 me[ 0 ], me[ 4 ], me[ 8 ], 1200 me[ 1 ], me[ 5 ], me[ 9 ], 1201 me[ 2 ], me[ 6 ], me[ 10 ] 1202 1203 ); 1204 1205 return this; 1206 1207 } 1208 1209 multiply( m ) { 1210 1211 return this.multiplyMatrices( this, m ); 1212 1213 } 1214 1215 premultiply( m ) { 1216 1217 return this.multiplyMatrices( m, this ); 1218 1219 } 1220 1221 multiplyMatrices( a, b ) { 1222 1223 const ae = a.elements; 1224 const be = b.elements; 1225 const te = this.elements; 1226 1227 const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ]; 1228 const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ]; 1229 const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ]; 1230 1231 const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ]; 1232 const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ]; 1233 const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ]; 1234 1235 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; 1236 te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; 1237 te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; 1238 1239 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; 1240 te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; 1241 te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; 1242 1243 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31; 1244 te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32; 1245 te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33; 1246 1247 return this; 1248 1249 } 1250 1251 multiplyScalar( s ) { 1252 1253 const te = this.elements; 1254 1255 te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s; 1256 te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s; 1257 te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s; 1258 1259 return this; 1260 1261 } 1262 1263 determinant() { 1264 1265 const te = this.elements; 1266 1267 const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], 1268 d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], 1269 g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; 1270 1271 return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; 1272 1273 } 1274 1275 invert() { 1276 1277 const te = this.elements, 1278 1279 n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], 1280 n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ], 1281 n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ], 1282 1283 t11 = n33 * n22 - n32 * n23, 1284 t12 = n32 * n13 - n33 * n12, 1285 t13 = n23 * n12 - n22 * n13, 1286 1287 det = n11 * t11 + n21 * t12 + n31 * t13; 1288 1289 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); 1290 1291 const detInv = 1 / det; 1292 1293 te[ 0 ] = t11 * detInv; 1294 te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; 1295 te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; 1296 1297 te[ 3 ] = t12 * detInv; 1298 te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; 1299 te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; 1300 1301 te[ 6 ] = t13 * detInv; 1302 te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; 1303 te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; 1304 1305 return this; 1306 1307 } 1308 1309 transpose() { 1310 1311 let tmp; 1312 const m = this.elements; 1313 1314 tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp; 1315 tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp; 1316 tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp; 1317 1318 return this; 1319 1320 } 1321 1322 getNormalMatrix( matrix4 ) { 1323 1324 return this.setFromMatrix4( matrix4 ).invert().transpose(); 1325 1326 } 1327 1328 transposeIntoArray( r ) { 1329 1330 const m = this.elements; 1331 1332 r[ 0 ] = m[ 0 ]; 1333 r[ 1 ] = m[ 3 ]; 1334 r[ 2 ] = m[ 6 ]; 1335 r[ 3 ] = m[ 1 ]; 1336 r[ 4 ] = m[ 4 ]; 1337 r[ 5 ] = m[ 7 ]; 1338 r[ 6 ] = m[ 2 ]; 1339 r[ 7 ] = m[ 5 ]; 1340 r[ 8 ] = m[ 8 ]; 1341 1342 return this; 1343 1344 } 1345 1346 setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) { 1347 1348 const c = Math.cos( rotation ); 1349 const s = Math.sin( rotation ); 1350 1351 this.set( 1352 sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, 1353 - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, 1354 0, 0, 1 1355 ); 1356 1357 return this; 1358 1359 } 1360 1361 // 1362 1363 scale( sx, sy ) { 1364 1365 this.premultiply( _m3.makeScale( sx, sy ) ); 1366 1367 return this; 1368 1369 } 1370 1371 rotate( theta ) { 1372 1373 this.premultiply( _m3.makeRotation( - theta ) ); 1374 1375 return this; 1376 1377 } 1378 1379 translate( tx, ty ) { 1380 1381 this.premultiply( _m3.makeTranslation( tx, ty ) ); 1382 1383 return this; 1384 1385 } 1386 1387 // for 2D Transforms 1388 1389 makeTranslation( x, y ) { 1390 1391 if ( x.isVector2 ) { 1392 1393 this.set( 1394 1395 1, 0, x.x, 1396 0, 1, x.y, 1397 0, 0, 1 1398 1399 ); 1400 1401 } else { 1402 1403 this.set( 1404 1405 1, 0, x, 1406 0, 1, y, 1407 0, 0, 1 1408 1409 ); 1410 1411 } 1412 1413 return this; 1414 1415 } 1416 1417 makeRotation( theta ) { 1418 1419 // counterclockwise 1420 1421 const c = Math.cos( theta ); 1422 const s = Math.sin( theta ); 1423 1424 this.set( 1425 1426 c, - s, 0, 1427 s, c, 0, 1428 0, 0, 1 1429 1430 ); 1431 1432 return this; 1433 1434 } 1435 1436 makeScale( x, y ) { 1437 1438 this.set( 1439 1440 x, 0, 0, 1441 0, y, 0, 1442 0, 0, 1 1443 1444 ); 1445 1446 return this; 1447 1448 } 1449 1450 // 1451 1452 equals( matrix ) { 1453 1454 const te = this.elements; 1455 const me = matrix.elements; 1456 1457 for ( let i = 0; i < 9; i ++ ) { 1458 1459 if ( te[ i ] !== me[ i ] ) return false; 1460 1461 } 1462 1463 return true; 1464 1465 } 1466 1467 fromArray( array, offset = 0 ) { 1468 1469 for ( let i = 0; i < 9; i ++ ) { 1470 1471 this.elements[ i ] = array[ i + offset ]; 1472 1473 } 1474 1475 return this; 1476 1477 } 1478 1479 toArray( array = [], offset = 0 ) { 1480 1481 const te = this.elements; 1482 1483 array[ offset ] = te[ 0 ]; 1484 array[ offset + 1 ] = te[ 1 ]; 1485 array[ offset + 2 ] = te[ 2 ]; 1486 1487 array[ offset + 3 ] = te[ 3 ]; 1488 array[ offset + 4 ] = te[ 4 ]; 1489 array[ offset + 5 ] = te[ 5 ]; 1490 1491 array[ offset + 6 ] = te[ 6 ]; 1492 array[ offset + 7 ] = te[ 7 ]; 1493 array[ offset + 8 ] = te[ 8 ]; 1494 1495 return array; 1496 1497 } 1498 1499 clone() { 1500 1501 return new this.constructor().fromArray( this.elements ); 1502 1503 } 1504 1505} 1506 1507const _m3 = /*@__PURE__*/ new Matrix3(); 1508 1509function arrayNeedsUint32( array ) { 1510 1511 // assumes larger values usually on last 1512 1513 for ( let i = array.length - 1; i >= 0; -- i ) { 1514 1515 if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 1516 1517 } 1518 1519 return false; 1520 1521} 1522
vendor: 8,505 bytes, lines 1523-1953
1523const TYPED_ARRAYS = { 1524 Int8Array: Int8Array, 1525 Uint8Array: Uint8Array, 1526 Uint8ClampedArray: Uint8ClampedArray, 1527 Int16Array: Int16Array, 1528 Uint16Array: Uint16Array, 1529 Int32Array: Int32Array, 1530 Uint32Array: Uint32Array, 1531 Float32Array: Float32Array, 1532 Float64Array: Float64Array 1533}; 1534 1535function getTypedArray( type, buffer ) { 1536 1537 return new TYPED_ARRAYS[ type ]( buffer ); 1538 1539} 1540 1541function createElementNS( name ) { 1542 1543 return document.createElementNS( 'http://www.w3.org/1999/xhtml', name ); 1544 1545} 1546 1547function createCanvasElement() { 1548 1549 const canvas = createElementNS( 'canvas' ); 1550 canvas.style.display = 'block'; 1551 return canvas; 1552 1553} 1554 1555const _cache = {}; 1556 1557function warnOnce( message ) { 1558 1559 if ( message in _cache ) return; 1560 1561 _cache[ message ] = true; 1562 1563 console.warn( message ); 1564 1565} 1566 1567/** 1568 * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping 1569 * or clipping. Based on W3C specifications for sRGB and Display P3, 1570 * and ICC specifications for the D50 connection space. Values in/out 1571 * are _linear_ sRGB and _linear_ Display P3. 1572 * 1573 * Note that both sRGB and Display P3 use the sRGB transfer functions. 1574 * 1575 * Reference: 1576 * - http://www.russellcottrell.com/photo/matrixCalculator.htm 1577 */ 1578 1579const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().set( 1580 0.8224621, 0.177538, 0.0, 1581 0.0331941, 0.9668058, 0.0, 1582 0.0170827, 0.0723974, 0.9105199, 1583); 1584 1585const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().set( 1586 1.2249401, - 0.2249404, 0.0, 1587 - 0.0420569, 1.0420571, 0.0, 1588 - 0.0196376, - 0.0786361, 1.0982735 1589); 1590 1591/** 1592 * Defines supported color spaces by transfer function and primaries, 1593 * and provides conversions to/from the Linear-sRGB reference space. 1594 */ 1595const COLOR_SPACES = { 1596 [ LinearSRGBColorSpace ]: { 1597 transfer: LinearTransfer, 1598 primaries: Rec709Primaries, 1599 toReference: ( color ) => color, 1600 fromReference: ( color ) => color, 1601 }, 1602 [ SRGBColorSpace ]: { 1603 transfer: SRGBTransfer, 1604 primaries: Rec709Primaries, 1605 toReference: ( color ) => color.convertSRGBToLinear(), 1606 fromReference: ( color ) => color.convertLinearToSRGB(), 1607 }, 1608 [ LinearDisplayP3ColorSpace ]: { 1609 transfer: LinearTransfer, 1610 primaries: P3Primaries, 1611 toReference: ( color ) => color.applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), 1612 fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ), 1613 }, 1614 [ DisplayP3ColorSpace ]: { 1615 transfer: SRGBTransfer, 1616 primaries: P3Primaries, 1617 toReference: ( color ) => color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), 1618 fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(), 1619 }, 1620}; 1621 1622const SUPPORTED_WORKING_COLOR_SPACES = new Set( [ LinearSRGBColorSpace, LinearDisplayP3ColorSpace ] ); 1623 1624const ColorManagement = { 1625 1626 enabled: true, 1627 1628 _workingColorSpace: LinearSRGBColorSpace, 1629 1630 get workingColorSpace() { 1631 1632 return this._workingColorSpace; 1633 1634 }, 1635 1636 set workingColorSpace( colorSpace ) { 1637 1638 if ( ! SUPPORTED_WORKING_COLOR_SPACES.has( colorSpace ) ) { 1639 1640 throw new Error( `Unsupported working color space, "${ colorSpace }".` ); 1641 1642 } 1643 1644 this._workingColorSpace = colorSpace; 1645 1646 }, 1647 1648 convert: function ( color, sourceColorSpace, targetColorSpace ) { 1649 1650 if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { 1651 1652 return color; 1653 1654 } 1655 1656 const sourceToReference = COLOR_SPACES[ sourceColorSpace ].toReference; 1657 const targetFromReference = COLOR_SPACES[ targetColorSpace ].fromReference; 1658 1659 return targetFromReference( sourceToReference( color ) ); 1660 1661 }, 1662 1663 fromWorkingColorSpace: function ( color, targetColorSpace ) { 1664 1665 return this.convert( color, this._workingColorSpace, targetColorSpace ); 1666 1667 }, 1668 1669 toWorkingColorSpace: function ( color, sourceColorSpace ) { 1670 1671 return this.convert( color, sourceColorSpace, this._workingColorSpace ); 1672 1673 }, 1674 1675 getPrimaries: function ( colorSpace ) { 1676 1677 return COLOR_SPACES[ colorSpace ].primaries; 1678 1679 }, 1680 1681 getTransfer: function ( colorSpace ) { 1682 1683 if ( colorSpace === NoColorSpace ) return LinearTransfer; 1684 1685 return COLOR_SPACES[ colorSpace ].transfer; 1686 1687 }, 1688 1689}; 1690 1691 1692function SRGBToLinear( c ) { 1693 1694 return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 ); 1695 1696} 1697 1698function LinearToSRGB( c ) { 1699 1700 return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055; 1701 1702} 1703 1704let _canvas; 1705 1706class ImageUtils { 1707 1708 static getDataURL( image ) { 1709 1710 if ( /^data:/i.test( image.src ) ) { 1711 1712 return image.src; 1713 1714 } 1715 1716 if ( typeof HTMLCanvasElement === 'undefined' ) { 1717 1718 return image.src; 1719 1720 } 1721 1722 let canvas; 1723 1724 if ( image instanceof HTMLCanvasElement ) { 1725 1726 canvas = image; 1727 1728 } else { 1729 1730 if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); 1731 1732 _canvas.width = image.width; 1733 _canvas.height = image.height; 1734 1735 const context = _canvas.getContext( '2d' ); 1736 1737 if ( image instanceof ImageData ) { 1738 1739 context.putImageData( image, 0, 0 ); 1740 1741 } else { 1742 1743 context.drawImage( image, 0, 0, image.width, image.height ); 1744 1745 } 1746 1747 canvas = _canvas; 1748 1749 } 1750 1751 if ( canvas.width > 2048 || canvas.height > 2048 ) { 1752 1753 console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); 1754 1755 return canvas.toDataURL( 'image/jpeg', 0.6 ); 1756 1757 } else { 1758 1759 return canvas.toDataURL( 'image/png' ); 1760 1761 } 1762 1763 } 1764 1765 static sRGBToLinear( image ) { 1766 1767 if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || 1768 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || 1769 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { 1770 1771 const canvas = createElementNS( 'canvas' ); 1772 1773 canvas.width = image.width; 1774 canvas.height = image.height; 1775 1776 const context = canvas.getContext( '2d' ); 1777 context.drawImage( image, 0, 0, image.width, image.height ); 1778 1779 const imageData = context.getImageData( 0, 0, image.width, image.height ); 1780 const data = imageData.data; 1781 1782 for ( let i = 0; i < data.length; i ++ ) { 1783 1784 data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; 1785 1786 } 1787 1788 context.putImageData( imageData, 0, 0 ); 1789 1790 return canvas; 1791 1792 } else if ( image.data ) { 1793 1794 const data = image.data.slice( 0 ); 1795 1796 for ( let i = 0; i < data.length; i ++ ) { 1797 1798 if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { 1799 1800 data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); 1801 1802 } else { 1803 1804 // assuming float 1805 1806 data[ i ] = SRGBToLinear( data[ i ] ); 1807 1808 } 1809 1810 } 1811 1812 return { 1813 data: data, 1814 width: image.width, 1815 height: image.height 1816 }; 1817 1818 } else { 1819 1820 console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); 1821 return image; 1822 1823 } 1824 1825 } 1826 1827} 1828 1829let _sourceId = 0; 1830 1831class Source { 1832 1833 constructor( data = null ) { 1834 1835 this.isSource = true; 1836 1837 Object.defineProperty( this, 'id', { value: _sourceId ++ } ); 1838 1839 this.uuid = generateUUID(); 1840 1841 this.data = data; 1842 1843 this.version = 0; 1844 1845 } 1846 1847 set needsUpdate( value ) { 1848 1849 if ( value === true ) this.version ++; 1850 1851 } 1852 1853 toJSON( meta ) { 1854 1855 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 1856 1857 if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { 1858 1859 return meta.images[ this.uuid ]; 1860 1861 } 1862 1863 const output = { 1864 uuid: this.uuid, 1865 url: '' 1866 }; 1867 1868 const data = this.data; 1869 1870 if ( data !== null ) { 1871 1872 let url; 1873 1874 if ( Array.isArray( data ) ) { 1875 1876 // cube texture 1877 1878 url = []; 1879 1880 for ( let i = 0, l = data.length; i < l; i ++ ) { 1881 1882 if ( data[ i ].isDataTexture ) { 1883 1884 url.push( serializeImage( data[ i ].image ) ); 1885 1886 } else { 1887 1888 url.push( serializeImage( data[ i ] ) ); 1889 1890 } 1891 1892 } 1893 1894 } else { 1895 1896 // texture 1897 1898 url = serializeImage( data ); 1899 1900 } 1901 1902 output.url = url; 1903 1904 } 1905 1906 if ( ! isRootObject ) { 1907 1908 meta.images[ this.uuid ] = output; 1909 1910 } 1911 1912 return output; 1913 1914 } 1915 1916} 1917 1918function serializeImage( image ) { 1919 1920 if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || 1921 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || 1922 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { 1923 1924 // default images 1925 1926 return ImageUtils.getDataURL( image ); 1927 1928 } else { 1929 1930 if ( image.data ) { 1931 1932 // images of DataTexture 1933 1934 return { 1935 data: Array.from( image.data ), 1936 width: image.width, 1937 height: image.height, 1938 type: image.data.constructor.name 1939 }; 1940 1941 } else { 1942 1943 console.warn( 'THREE.Texture: Unable to serialize Texture.' ); 1944 return {}; 1945 1946 } 1947 1948 } 1949 1950} 1951 1952let _textureId = 0; 1953
vendor: 6,087 bytes, lines 1954-2258
1954class Texture extends EventDispatcher { 1955 1956 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 ) { 1957 1958 super(); 1959 1960 this.isTexture = true; 1961 1962 Object.defineProperty( this, 'id', { value: _textureId ++ } ); 1963 1964 this.uuid = generateUUID(); 1965 1966 this.name = ''; 1967 1968 this.source = new Source( image ); 1969 this.mipmaps = []; 1970 1971 this.mapping = mapping; 1972 this.channel = 0; 1973 1974 this.wrapS = wrapS; 1975 this.wrapT = wrapT; 1976 1977 this.magFilter = magFilter; 1978 this.minFilter = minFilter; 1979 1980 this.anisotropy = anisotropy; 1981 1982 this.format = format; 1983 this.internalFormat = null; 1984 this.type = type; 1985 1986 this.offset = new Vector2( 0, 0 ); 1987 this.repeat = new Vector2( 1, 1 ); 1988 this.center = new Vector2( 0, 0 ); 1989 this.rotation = 0; 1990 1991 this.matrixAutoUpdate = true; 1992 this.matrix = new Matrix3(); 1993 1994 this.generateMipmaps = true; 1995 this.premultiplyAlpha = false; 1996 this.flipY = true; 1997 this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) 1998 1999 if ( typeof colorSpace === 'string' ) { 2000 2001 this.colorSpace = colorSpace; 2002 2003 } else { // @deprecated, r152 2004 2005 warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); 2006 this.colorSpace = colorSpace === sRGBEncoding ? SRGBColorSpace : NoColorSpace; 2007 2008 } 2009 2010 2011 this.userData = {}; 2012 2013 this.version = 0; 2014 this.onUpdate = null; 2015 2016 this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not 2017 this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) 2018 2019 } 2020 2021 get image() { 2022 2023 return this.source.data; 2024 2025 } 2026 2027 set image( value = null ) { 2028 2029 this.source.data = value; 2030 2031 } 2032 2033 updateMatrix() { 2034 2035 this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); 2036 2037 } 2038 2039 clone() { 2040 2041 return new this.constructor().copy( this ); 2042 2043 } 2044 2045 copy( source ) { 2046 2047 this.name = source.name; 2048 2049 this.source = source.source; 2050 this.mipmaps = source.mipmaps.slice( 0 ); 2051 2052 this.mapping = source.mapping; 2053 this.channel = source.channel; 2054 2055 this.wrapS = source.wrapS; 2056 this.wrapT = source.wrapT; 2057 2058 this.magFilter = source.magFilter; 2059 this.minFilter = source.minFilter; 2060 2061 this.anisotropy = source.anisotropy; 2062 2063 this.format = source.format; 2064 this.internalFormat = source.internalFormat; 2065 this.type = source.type; 2066 2067 this.offset.copy( source.offset ); 2068 this.repeat.copy( source.repeat ); 2069 this.center.copy( source.center ); 2070 this.rotation = source.rotation; 2071 2072 this.matrixAutoUpdate = source.matrixAutoUpdate; 2073 this.matrix.copy( source.matrix ); 2074 2075 this.generateMipmaps = source.generateMipmaps; 2076 this.premultiplyAlpha = source.premultiplyAlpha; 2077 this.flipY = source.flipY; 2078 this.unpackAlignment = source.unpackAlignment; 2079 this.colorSpace = source.colorSpace; 2080 2081 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 2082 2083 this.needsUpdate = true; 2084 2085 return this; 2086 2087 } 2088 2089 toJSON( meta ) { 2090 2091 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 2092 2093 if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { 2094 2095 return meta.textures[ this.uuid ]; 2096 2097 } 2098 2099 const output = { 2100 2101 metadata: { 2102 version: 4.6, 2103 type: 'Texture', 2104 generator: 'Texture.toJSON' 2105 }, 2106 2107 uuid: this.uuid, 2108 name: this.name, 2109 2110 image: this.source.toJSON( meta ).uuid, 2111 2112 mapping: this.mapping, 2113 channel: this.channel, 2114 2115 repeat: [ this.repeat.x, this.repeat.y ], 2116 offset: [ this.offset.x, this.offset.y ], 2117 center: [ this.center.x, this.center.y ], 2118 rotation: this.rotation, 2119 2120 wrap: [ this.wrapS, this.wrapT ], 2121 2122 format: this.format, 2123 internalFormat: this.internalFormat, 2124 type: this.type, 2125 colorSpace: this.colorSpace, 2126 2127 minFilter: this.minFilter, 2128 magFilter: this.magFilter, 2129 anisotropy: this.anisotropy, 2130 2131 flipY: this.flipY, 2132 2133 generateMipmaps: this.generateMipmaps, 2134 premultiplyAlpha: this.premultiplyAlpha, 2135 unpackAlignment: this.unpackAlignment 2136 2137 }; 2138 2139 if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; 2140 2141 if ( ! isRootObject ) { 2142 2143 meta.textures[ this.uuid ] = output; 2144 2145 } 2146 2147 return output; 2148 2149 } 2150 2151 dispose() { 2152 2153 this.dispatchEvent( { type: 'dispose' } ); 2154 2155 } 2156 2157 transformUv( uv ) { 2158 2159 if ( this.mapping !== UVMapping ) return uv; 2160 2161 uv.applyMatrix3( this.matrix ); 2162 2163 if ( uv.x < 0 || uv.x > 1 ) { 2164 2165 switch ( this.wrapS ) { 2166 2167 case RepeatWrapping: 2168 2169 uv.x = uv.x - Math.floor( uv.x ); 2170 break; 2171 2172 case ClampToEdgeWrapping: 2173 2174 uv.x = uv.x < 0 ? 0 : 1; 2175 break; 2176 2177 case MirroredRepeatWrapping: 2178 2179 if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { 2180 2181 uv.x = Math.ceil( uv.x ) - uv.x; 2182 2183 } else { 2184 2185 uv.x = uv.x - Math.floor( uv.x ); 2186 2187 } 2188 2189 break; 2190 2191 } 2192 2193 } 2194 2195 if ( uv.y < 0 || uv.y > 1 ) { 2196 2197 switch ( this.wrapT ) { 2198 2199 case RepeatWrapping: 2200 2201 uv.y = uv.y - Math.floor( uv.y ); 2202 break; 2203 2204 case ClampToEdgeWrapping: 2205 2206 uv.y = uv.y < 0 ? 0 : 1; 2207 break; 2208 2209 case MirroredRepeatWrapping: 2210 2211 if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { 2212 2213 uv.y = Math.ceil( uv.y ) - uv.y; 2214 2215 } else { 2216 2217 uv.y = uv.y - Math.floor( uv.y ); 2218 2219 } 2220 2221 break; 2222 2223 } 2224 2225 } 2226 2227 if ( this.flipY ) { 2228 2229 uv.y = 1 - uv.y; 2230 2231 } 2232 2233 return uv; 2234 2235 } 2236 2237 set needsUpdate( value ) { 2238 2239 if ( value === true ) { 2240 2241 this.version ++; 2242 this.source.needsUpdate = true; 2243 2244 } 2245 2246 } 2247 2248 get encoding() { // @deprecated, r152 2249 2250 warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); 2251 return this.colorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding; 2252 2253 } 2254 2255 set encoding( encoding ) { // @deprecated, r152 2256 2257 warnOnce( 'THREE.Texture: Property .encoding has been replaced by .colorSpace.' ); 2258 this.colorSpace = encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
vendor: 10,756 bytes, lines 2258-2935
2258 2259 2260 } 2261 2262} 2263 2264Texture.DEFAULT_IMAGE = null; 2265Texture.DEFAULT_MAPPING = UVMapping; 2266Texture.DEFAULT_ANISOTROPY = 1; 2267 2268class Vector4 { 2269 2270 constructor( x = 0, y = 0, z = 0, w = 1 ) { 2271 2272 Vector4.prototype.isVector4 = true; 2273 2274 this.x = x; 2275 this.y = y; 2276 this.z = z; 2277 this.w = w; 2278 2279 } 2280 2281 get width() { 2282 2283 return this.z; 2284 2285 } 2286 2287 set width( value ) { 2288 2289 this.z = value; 2290 2291 } 2292 2293 get height() { 2294 2295 return this.w; 2296 2297 } 2298 2299 set height( value ) { 2300 2301 this.w = value; 2302 2303 } 2304 2305 set( x, y, z, w ) { 2306 2307 this.x = x; 2308 this.y = y; 2309 this.z = z; 2310 this.w = w; 2311 2312 return this; 2313 2314 } 2315 2316 setScalar( scalar ) { 2317 2318 this.x = scalar; 2319 this.y = scalar; 2320 this.z = scalar; 2321 this.w = scalar; 2322 2323 return this; 2324 2325 } 2326 2327 setX( x ) { 2328 2329 this.x = x; 2330 2331 return this; 2332 2333 } 2334 2335 setY( y ) { 2336 2337 this.y = y; 2338 2339 return this; 2340 2341 } 2342 2343 setZ( z ) { 2344 2345 this.z = z; 2346 2347 return this; 2348 2349 } 2350 2351 setW( w ) { 2352 2353 this.w = w; 2354 2355 return this; 2356 2357 } 2358 2359 setComponent( index, value ) { 2360 2361 switch ( index ) { 2362 2363 case 0: this.x = value; break; 2364 case 1: this.y = value; break; 2365 case 2: this.z = value; break; 2366 case 3: this.w = value; break; 2367 default: throw new Error( 'index is out of range: ' + index ); 2368 2369 } 2370 2371 return this; 2372 2373 } 2374 2375 getComponent( index ) { 2376 2377 switch ( index ) { 2378 2379 case 0: return this.x; 2380 case 1: return this.y; 2381 case 2: return this.z; 2382 case 3: return this.w; 2383 default: throw new Error( 'index is out of range: ' + index ); 2384 2385 } 2386 2387 } 2388 2389 clone() { 2390 2391 return new this.constructor( this.x, this.y, this.z, this.w ); 2392 2393 } 2394 2395 copy( v ) { 2396 2397 this.x = v.x; 2398 this.y = v.y; 2399 this.z = v.z; 2400 this.w = ( v.w !== undefined ) ? v.w : 1; 2401 2402 return this; 2403 2404 } 2405 2406 add( v ) { 2407 2408 this.x += v.x; 2409 this.y += v.y; 2410 this.z += v.z; 2411 this.w += v.w; 2412 2413 return this; 2414 2415 } 2416 2417 addScalar( s ) { 2418 2419 this.x += s; 2420 this.y += s; 2421 this.z += s; 2422 this.w += s; 2423 2424 return this; 2425 2426 } 2427 2428 addVectors( a, b ) { 2429 2430 this.x = a.x + b.x; 2431 this.y = a.y + b.y; 2432 this.z = a.z + b.z; 2433 this.w = a.w + b.w; 2434 2435 return this; 2436 2437 } 2438 2439 addScaledVector( v, s ) { 2440 2441 this.x += v.x * s; 2442 this.y += v.y * s; 2443 this.z += v.z * s; 2444 this.w += v.w * s; 2445 2446 return this; 2447 2448 } 2449 2450 sub( v ) { 2451 2452 this.x -= v.x; 2453 this.y -= v.y; 2454 this.z -= v.z; 2455 this.w -= v.w; 2456 2457 return this; 2458 2459 } 2460 2461 subScalar( s ) { 2462 2463 this.x -= s; 2464 this.y -= s; 2465 this.z -= s; 2466 this.w -= s; 2467 2468 return this; 2469 2470 } 2471 2472 subVectors( a, b ) { 2473 2474 this.x = a.x - b.x; 2475 this.y = a.y - b.y; 2476 this.z = a.z - b.z; 2477 this.w = a.w - b.w; 2478 2479 return this; 2480 2481 } 2482 2483 multiply( v ) { 2484 2485 this.x *= v.x; 2486 this.y *= v.y; 2487 this.z *= v.z; 2488 this.w *= v.w; 2489 2490 return this; 2491 2492 } 2493 2494 multiplyScalar( scalar ) { 2495 2496 this.x *= scalar; 2497 this.y *= scalar; 2498 this.z *= scalar; 2499 this.w *= scalar; 2500 2501 return this; 2502 2503 } 2504 2505 applyMatrix4( m ) { 2506 2507 const x = this.x, y = this.y, z = this.z, w = this.w; 2508 const e = m.elements; 2509 2510 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; 2511 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; 2512 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; 2513 this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; 2514 2515 return this; 2516 2517 } 2518 2519 divideScalar( scalar ) { 2520 2521 return this.multiplyScalar( 1 / scalar ); 2522 2523 } 2524 2525 setAxisAngleFromQuaternion( q ) { 2526 2527 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm 2528 2529 // q is assumed to be normalized 2530 2531 this.w = 2 * Math.acos( q.w ); 2532 2533 const s = Math.sqrt( 1 - q.w * q.w ); 2534 2535 if ( s < 0.0001 ) { 2536 2537 this.x = 1; 2538 this.y = 0; 2539 this.z = 0; 2540 2541 } else { 2542 2543 this.x = q.x / s; 2544 this.y = q.y / s; 2545 this.z = q.z / s; 2546 2547 } 2548 2549 return this; 2550 2551 } 2552 2553 setAxisAngleFromRotationMatrix( m ) { 2554 2555 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm 2556 2557 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 2558 2559 let angle, x, y, z; // variables for result 2560 const epsilon = 0.01, // margin to allow for rounding errors 2561 epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees 2562 2563 te = m.elements, 2564 2565 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], 2566 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], 2567 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; 2568 2569 if ( ( Math.abs( m12 - m21 ) < epsilon ) && 2570 ( Math.abs( m13 - m31 ) < epsilon ) && 2571 ( Math.abs( m23 - m32 ) < epsilon ) ) { 2572 2573 // singularity found 2574 // first check for identity matrix which must have +1 for all terms 2575 // in leading diagonal and zero in other terms 2576 2577 if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && 2578 ( Math.abs( m13 + m31 ) < epsilon2 ) && 2579 ( Math.abs( m23 + m32 ) < epsilon2 ) && 2580 ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { 2581 2582 // this singularity is identity matrix so angle = 0 2583 2584 this.set( 1, 0, 0, 0 ); 2585 2586 return this; // zero angle, arbitrary axis 2587 2588 } 2589 2590 // otherwise this singularity is angle = 180 2591 2592 angle = Math.PI; 2593 2594 const xx = ( m11 + 1 ) / 2; 2595 const yy = ( m22 + 1 ) / 2; 2596 const zz = ( m33 + 1 ) / 2; 2597 const xy = ( m12 + m21 ) / 4; 2598 const xz = ( m13 + m31 ) / 4; 2599 const yz = ( m23 + m32 ) / 4; 2600 2601 if ( ( xx > yy ) && ( xx > zz ) ) { 2602 2603 // m11 is the largest diagonal term 2604 2605 if ( xx < epsilon ) { 2606 2607 x = 0; 2608 y = 0.707106781; 2609 z = 0.707106781; 2610 2611 } else { 2612 2613 x = Math.sqrt( xx ); 2614 y = xy / x; 2615 z = xz / x; 2616 2617 } 2618 2619 } else if ( yy > zz ) { 2620 2621 // m22 is the largest diagonal term 2622 2623 if ( yy < epsilon ) { 2624 2625 x = 0.707106781; 2626 y = 0; 2627 z = 0.707106781; 2628 2629 } else { 2630 2631 y = Math.sqrt( yy ); 2632 x = xy / y; 2633 z = yz / y; 2634 2635 } 2636 2637 } else { 2638 2639 // m33 is the largest diagonal term so base result on this 2640 2641 if ( zz < epsilon ) { 2642 2643 x = 0.707106781; 2644 y = 0.707106781; 2645 z = 0; 2646 2647 } else { 2648 2649 z = Math.sqrt( zz ); 2650 x = xz / z; 2651 y = yz / z; 2652 2653 } 2654 2655 } 2656 2657 this.set( x, y, z, angle ); 2658 2659 return this; // return 180 deg rotation 2660 2661 } 2662 2663 // as we have reached here there are no singularities so we can handle normally 2664 2665 let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + 2666 ( m13 - m31 ) * ( m13 - m31 ) + 2667 ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize 2668 2669 if ( Math.abs( s ) < 0.001 ) s = 1; 2670 2671 // prevent divide by zero, should not happen if matrix is orthogonal and should be 2672 // caught by singularity test above, but I've left it in just in case 2673 2674 this.x = ( m32 - m23 ) / s; 2675 this.y = ( m13 - m31 ) / s; 2676 this.z = ( m21 - m12 ) / s; 2677 this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); 2678 2679 return this; 2680 2681 } 2682 2683 min( v ) { 2684 2685 this.x = Math.min( this.x, v.x ); 2686 this.y = Math.min( this.y, v.y ); 2687 this.z = Math.min( this.z, v.z ); 2688 this.w = Math.min( this.w, v.w ); 2689 2690 return this; 2691 2692 } 2693 2694 max( v ) { 2695 2696 this.x = Math.max( this.x, v.x ); 2697 this.y = Math.max( this.y, v.y ); 2698 this.z = Math.max( this.z, v.z ); 2699 this.w = Math.max( this.w, v.w ); 2700 2701 return this; 2702 2703 } 2704 2705 clamp( min, max ) { 2706 2707 // assumes min < max, componentwise 2708 2709 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 2710 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 2711 this.z = Math.max( min.z, Math.min( max.z, this.z ) ); 2712 this.w = Math.max( min.w, Math.min( max.w, this.w ) ); 2713 2714 return this; 2715 2716 } 2717 2718 clampScalar( minVal, maxVal ) { 2719 2720 this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); 2721 this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); 2722 this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); 2723 this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); 2724 2725 return this; 2726 2727 } 2728 2729 clampLength( min, max ) { 2730 2731 const length = this.length(); 2732 2733 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 2734 2735 } 2736 2737 floor() { 2738 2739 this.x = Math.floor( this.x ); 2740 this.y = Math.floor( this.y ); 2741 this.z = Math.floor( this.z ); 2742 this.w = Math.floor( this.w ); 2743 2744 return this; 2745 2746 } 2747 2748 ceil() { 2749 2750 this.x = Math.ceil( this.x ); 2751 this.y = Math.ceil( this.y ); 2752 this.z = Math.ceil( this.z ); 2753 this.w = Math.ceil( this.w ); 2754 2755 return this; 2756 2757 } 2758 2759 round() { 2760 2761 this.x = Math.round( this.x ); 2762 this.y = Math.round( this.y ); 2763 this.z = Math.round( this.z ); 2764 this.w = Math.round( this.w ); 2765 2766 return this; 2767 2768 } 2769 2770 roundToZero() { 2771 2772 this.x = Math.trunc( this.x ); 2773 this.y = Math.trunc( this.y ); 2774 this.z = Math.trunc( this.z ); 2775 this.w = Math.trunc( this.w ); 2776 2777 return this; 2778 2779 } 2780 2781 negate() { 2782 2783 this.x = - this.x; 2784 this.y = - this.y; 2785 this.z = - this.z; 2786 this.w = - this.w; 2787 2788 return this; 2789 2790 } 2791 2792 dot( v ) { 2793 2794 return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; 2795 2796 } 2797 2798 lengthSq() { 2799 2800 return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; 2801 2802 } 2803 2804 length() { 2805 2806 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); 2807 2808 } 2809 2810 manhattanLength() { 2811 2812 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); 2813 2814 } 2815 2816 normalize() { 2817 2818 return this.divideScalar( this.length() || 1 ); 2819 2820 } 2821 2822 setLength( length ) { 2823 2824 return this.normalize().multiplyScalar( length ); 2825 2826 } 2827 2828 lerp( v, alpha ) { 2829 2830 this.x += ( v.x - this.x ) * alpha; 2831 this.y += ( v.y - this.y ) * alpha; 2832 this.z += ( v.z - this.z ) * alpha; 2833 this.w += ( v.w - this.w ) * alpha; 2834 2835 return this; 2836 2837 } 2838 2839 lerpVectors( v1, v2, alpha ) { 2840 2841 this.x = v1.x + ( v2.x - v1.x ) * alpha; 2842 this.y = v1.y + ( v2.y - v1.y ) * alpha; 2843 this.z = v1.z + ( v2.z - v1.z ) * alpha; 2844 this.w = v1.w + ( v2.w - v1.w ) * alpha; 2845 2846 return this; 2847 2848 } 2849 2850 equals( v ) { 2851 2852 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); 2853 2854 } 2855 2856 fromArray( array, offset = 0 ) { 2857 2858 this.x = array[ offset ]; 2859 this.y = array[ offset + 1 ]; 2860 this.z = array[ offset + 2 ]; 2861 this.w = array[ offset + 3 ]; 2862 2863 return this; 2864 2865 } 2866 2867 toArray( array = [], offset = 0 ) { 2868 2869 array[ offset ] = this.x; 2870 array[ offset + 1 ] = this.y; 2871 array[ offset + 2 ] = this.z; 2872 array[ offset + 3 ] = this.w; 2873 2874 return array; 2875 2876 } 2877 2878 fromBufferAttribute( attribute, index ) { 2879 2880 this.x = attribute.getX( index ); 2881 this.y = attribute.getY( index ); 2882 this.z = attribute.getZ( index ); 2883 this.w = attribute.getW( index ); 2884 2885 return this; 2886 2887 } 2888 2889 random() { 2890 2891 this.x = Math.random(); 2892 this.y = Math.random(); 2893 this.z = Math.random(); 2894 this.w = Math.random(); 2895 2896 return this; 2897 2898 } 2899 2900 *[ Symbol.iterator ]() { 2901 2902 yield this.x; 2903 yield this.y; 2904 yield this.z; 2905 yield this.w; 2906 2907 } 2908 2909} 2910 2911/* 2912 In options, we can specify: 2913 * Texture parameters for an auto-generated target texture 2914 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers 2915*/ 2916class RenderTarget extends EventDispatcher { 2917 2918 constructor( width = 1, height = 1, options = {} ) { 2919 2920 super(); 2921 2922 this.isRenderTarget = true; 2923 2924 this.width = width; 2925 this.height = height; 2926 this.depth = 1; 2927 2928 this.scissor = new Vector4( 0, 0, width, height ); 2929 this.scissorTest = false; 2930 2931 this.viewport = new Vector4( 0, 0, width, height ); 2932 2933 const image = { width: width, height: height, depth: 1 }; 2934 2935
2935if ( options.encoding !== undefined ) { 2936 2937 // @deprecated, r152 2938 warnOnce( 'THREE.WebGLRenderTarget: option.encoding has been replaced by option.colorSpace.' ); 2939 options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; 2940 2941 } 2942 2943 options = Object.assign( { 2944 generateMipmaps: false, 2945 internalFormat: null, 2946 minFilter: LinearFilter, 2947 depthBuffer: true, 2948 stencilBuffer: false, 2949 depthTexture: null, 2950 samples: 0 2951 }, options ); 2952 2953 this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); 2954 this.texture.isRenderTargetTexture = true; 2955 2956 this.texture.flipY = false; 2957 this.texture.generateMipmaps = options.generateMipmaps; 2958 this.texture.internalFormat = options.internalFormat; 2959 2960 this.depthBuffer = options.depthBuffer; 2961 this.stencilBuffer = options.stencilBuffer; 2962 2963 this.depthTexture = options.depthTexture; 2964 2965 this.samples = options.samples; 2966 2967 } 2968 2969 setSize( width, height, depth = 1 ) { 2970 2971 if ( this.width !== width || this.height !== height || this.depth !== depth ) { 2972 2973 this.width = width; 2974 this.height = height; 2975 this.depth = depth; 2976 2977 this.texture.image.width = width; 2978 this.texture.image.height = height; 2979 this.texture.image.depth = depth; 2980 2981 this.dispose(); 2982 2983 } 2984 2985 this.viewport.set( 0, 0, width, height ); 2986 this.scissor.set( 0, 0, width, height ); 2987 2988 } 2989 2990 clone() { 2991 2992 return new this.constructor().copy( this ); 2993 2994 } 2995 2996 copy( source ) { 2997 2998 this.width = source.width; 2999 this.height = source.height; 3000 this.depth = source.depth; 3001 3002 this.scissor.copy( source.scissor ); 3003 this.scissorTest = source.scissorTest; 3004 3005 this.viewport.copy( source.viewport ); 3006 3007 this.texture = source.texture.clone(); 3008 this.texture.isRenderTargetTexture = true; 3009 3010 // ensure image object is not shared, see #20328 3011 3012 const image = Object.assign( {}, source.texture.image ); 3013 this.texture.source = new Source( image ); 3014 3015 this.depthBuffer = source.depthBuffer; 3016 this.stencilBuffer = source.stencilBuffer; 3017 3018 if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); 3019 3020 this.samples = source.samples; 3021 3022 return this; 3023 3024 } 3025 3026 dispose() { 3027 3028 this.dispatchEvent( { type: 'dispose' } ); 3029 3030 } 3031 3032} 3033 3034class WebGLRenderTarget extends RenderTarget { 3035 3036 constructor( width = 1, height = 1, options = {} ) { 3037 3038 super( width, height, options ); 3039
vendor: 24,564 bytes, lines 3040-4475
3040 this.isWebGLRenderTarget = true; 3041 3042 } 3043 3044} 3045 3046class DataArrayTexture extends Texture { 3047 3048 constructor( data = null, width = 1, height = 1, depth = 1 ) { 3049 3050 super( null ); 3051 3052 this.isDataArrayTexture = true; 3053 3054 this.image = { data, width, height, depth }; 3055 3056 this.magFilter = NearestFilter; 3057 this.minFilter = NearestFilter; 3058 3059 this.wrapR = ClampToEdgeWrapping; 3060 3061 this.generateMipmaps = false; 3062 this.flipY = false; 3063 this.unpackAlignment = 1; 3064 3065 } 3066 3067} 3068 3069class WebGLArrayRenderTarget extends WebGLRenderTarget { 3070 3071 constructor( width = 1, height = 1, depth = 1, options = {} ) { 3072 3073 super( width, height, options ); 3074 3075 this.isWebGLArrayRenderTarget = true; 3076 3077 this.depth = depth; 3078 3079 this.texture = new DataArrayTexture( null, width, height, depth ); 3080 3081 this.texture.isRenderTargetTexture = true; 3082 3083 } 3084 3085} 3086 3087class Data3DTexture extends Texture { 3088 3089 constructor( data = null, width = 1, height = 1, depth = 1 ) { 3090 3091 // We're going to add .setXXX() methods for setting properties later. 3092 // Users can still set in DataTexture3D directly. 3093 // 3094 // const texture = new THREE.DataTexture3D( data, width, height, depth ); 3095 // texture.anisotropy = 16; 3096 // 3097 // See #14839 3098 3099 super( null ); 3100 3101 this.isData3DTexture = true; 3102 3103 this.image = { data, width, height, depth }; 3104 3105 this.magFilter = NearestFilter; 3106 this.minFilter = NearestFilter; 3107 3108 this.wrapR = ClampToEdgeWrapping; 3109 3110 this.generateMipmaps = false; 3111 this.flipY = false; 3112 this.unpackAlignment = 1; 3113 3114 } 3115 3116} 3117 3118class WebGL3DRenderTarget extends WebGLRenderTarget { 3119 3120 constructor( width = 1, height = 1, depth = 1, options = {} ) { 3121 3122 super( width, height, options ); 3123 3124 this.isWebGL3DRenderTarget = true; 3125 3126 this.depth = depth; 3127 3128 this.texture = new Data3DTexture( null, width, height, depth ); 3129 3130 this.texture.isRenderTargetTexture = true; 3131 3132 } 3133 3134} 3135 3136class WebGLMultipleRenderTargets extends WebGLRenderTarget { 3137 3138 constructor( width = 1, height = 1, count = 1, options = {} ) { 3139 3140 super( width, height, options ); 3141 3142 this.isWebGLMultipleRenderTargets = true; 3143 3144 const texture = this.texture; 3145 3146 this.texture = []; 3147 3148 for ( let i = 0; i < count; i ++ ) { 3149 3150 this.texture[ i ] = texture.clone(); 3151 this.texture[ i ].isRenderTargetTexture = true; 3152 3153 } 3154 3155 } 3156 3157 setSize( width, height, depth = 1 ) { 3158 3159 if ( this.width !== width || this.height !== height || this.depth !== depth ) { 3160 3161 this.width = width; 3162 this.height = height; 3163 this.depth = depth; 3164 3165 for ( let i = 0, il = this.texture.length; i < il; i ++ ) { 3166 3167 this.texture[ i ].image.width = width; 3168 this.texture[ i ].image.height = height; 3169 this.texture[ i ].image.depth = depth; 3170 3171 } 3172 3173 this.dispose(); 3174 3175 } 3176 3177 this.viewport.set( 0, 0, width, height ); 3178 this.scissor.set( 0, 0, width, height ); 3179 3180 } 3181 3182 copy( source ) { 3183 3184 this.dispose(); 3185 3186 this.width = source.width; 3187 this.height = source.height; 3188 this.depth = source.depth; 3189 3190 this.scissor.copy( source.scissor ); 3191 this.scissorTest = source.scissorTest; 3192 3193 this.viewport.copy( source.viewport ); 3194 3195 this.depthBuffer = source.depthBuffer; 3196 this.stencilBuffer = source.stencilBuffer; 3197 3198 if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); 3199 3200 this.texture.length = 0; 3201 3202 for ( let i = 0, il = source.texture.length; i < il; i ++ ) { 3203 3204 this.texture[ i ] = source.texture[ i ].clone(); 3205 this.texture[ i ].isRenderTargetTexture = true; 3206 3207 } 3208 3209 return this; 3210 3211 } 3212 3213} 3214 3215class Quaternion { 3216 3217 constructor( x = 0, y = 0, z = 0, w = 1 ) { 3218 3219 this.isQuaternion = true; 3220 3221 this._x = x; 3222 this._y = y; 3223 this._z = z; 3224 this._w = w; 3225 3226 } 3227 3228 static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { 3229 3230 // fuzz-free, array-based Quaternion SLERP operation 3231 3232 let x0 = src0[ srcOffset0 + 0 ], 3233 y0 = src0[ srcOffset0 + 1 ], 3234 z0 = src0[ srcOffset0 + 2 ], 3235 w0 = src0[ srcOffset0 + 3 ]; 3236 3237 const x1 = src1[ srcOffset1 + 0 ], 3238 y1 = src1[ srcOffset1 + 1 ], 3239 z1 = src1[ srcOffset1 + 2 ], 3240 w1 = src1[ srcOffset1 + 3 ]; 3241 3242 if ( t === 0 ) { 3243 3244 dst[ dstOffset + 0 ] = x0; 3245 dst[ dstOffset + 1 ] = y0; 3246 dst[ dstOffset + 2 ] = z0; 3247 dst[ dstOffset + 3 ] = w0; 3248 return; 3249 3250 } 3251 3252 if ( t === 1 ) { 3253 3254 dst[ dstOffset + 0 ] = x1; 3255 dst[ dstOffset + 1 ] = y1; 3256 dst[ dstOffset + 2 ] = z1; 3257 dst[ dstOffset + 3 ] = w1; 3258 return; 3259 3260 } 3261 3262 if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { 3263 3264 let s = 1 - t; 3265 const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, 3266 dir = ( cos >= 0 ? 1 : - 1 ), 3267 sqrSin = 1 - cos * cos; 3268 3269 // Skip the Slerp for tiny steps to avoid numeric problems: 3270 if ( sqrSin > Number.EPSILON ) { 3271 3272 const sin = Math.sqrt( sqrSin ), 3273 len = Math.atan2( sin, cos * dir ); 3274 3275 s = Math.sin( s * len ) / sin; 3276 t = Math.sin( t * len ) / sin; 3277 3278 } 3279 3280 const tDir = t * dir; 3281 3282 x0 = x0 * s + x1 * tDir; 3283 y0 = y0 * s + y1 * tDir; 3284 z0 = z0 * s + z1 * tDir; 3285 w0 = w0 * s + w1 * tDir; 3286 3287 // Normalize in case we just did a lerp: 3288 if ( s === 1 - t ) { 3289 3290 const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); 3291 3292 x0 *= f; 3293 y0 *= f; 3294 z0 *= f; 3295 w0 *= f; 3296 3297 } 3298 3299 } 3300 3301 dst[ dstOffset ] = x0; 3302 dst[ dstOffset + 1 ] = y0; 3303 dst[ dstOffset + 2 ] = z0; 3304 dst[ dstOffset + 3 ] = w0; 3305 3306 } 3307 3308 static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { 3309 3310 const x0 = src0[ srcOffset0 ]; 3311 const y0 = src0[ srcOffset0 + 1 ]; 3312 const z0 = src0[ srcOffset0 + 2 ]; 3313 const w0 = src0[ srcOffset0 + 3 ]; 3314 3315 const x1 = src1[ srcOffset1 ]; 3316 const y1 = src1[ srcOffset1 + 1 ]; 3317 const z1 = src1[ srcOffset1 + 2 ]; 3318 const w1 = src1[ srcOffset1 + 3 ]; 3319 3320 dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; 3321 dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; 3322 dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; 3323 dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; 3324 3325 return dst; 3326 3327 } 3328 3329 get x() { 3330 3331 return this._x; 3332 3333 } 3334 3335 set x( value ) { 3336 3337 this._x = value; 3338 this._onChangeCallback(); 3339 3340 } 3341 3342 get y() { 3343 3344 return this._y; 3345 3346 } 3347 3348 set y( value ) { 3349 3350 this._y = value; 3351 this._onChangeCallback(); 3352 3353 } 3354 3355 get z() { 3356 3357 return this._z; 3358 3359 } 3360 3361 set z( value ) { 3362 3363 this._z = value; 3364 this._onChangeCallback(); 3365 3366 } 3367 3368 get w() { 3369 3370 return this._w; 3371 3372 } 3373 3374 set w( value ) { 3375 3376 this._w = value; 3377 this._onChangeCallback(); 3378 3379 } 3380 3381 set( x, y, z, w ) { 3382 3383 this._x = x; 3384 this._y = y; 3385 this._z = z; 3386 this._w = w; 3387 3388 this._onChangeCallback(); 3389 3390 return this; 3391 3392 } 3393 3394 clone() { 3395 3396 return new this.constructor( this._x, this._y, this._z, this._w ); 3397 3398 } 3399 3400 copy( quaternion ) { 3401 3402 this._x = quaternion.x; 3403 this._y = quaternion.y; 3404 this._z = quaternion.z; 3405 this._w = quaternion.w; 3406 3407 this._onChangeCallback(); 3408 3409 return this; 3410 3411 } 3412 3413 setFromEuler( euler, update = true ) { 3414 3415 const x = euler._x, y = euler._y, z = euler._z, order = euler._order; 3416 3417 // http://www.mathworks.com/matlabcentral/fileexchange/ 3418 // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ 3419 // content/SpinCalc.m 3420 3421 const cos = Math.cos; 3422 const sin = Math.sin; 3423 3424 const c1 = cos( x / 2 ); 3425 const c2 = cos( y / 2 ); 3426 const c3 = cos( z / 2 ); 3427 3428 const s1 = sin( x / 2 ); 3429 const s2 = sin( y / 2 ); 3430 const s3 = sin( z / 2 ); 3431 3432 switch ( order ) { 3433 3434 case 'XYZ': 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 'YXZ': 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 'ZXY': 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 case 'ZYX': 3456 this._x = s1 * c2 * c3 - c1 * s2 * s3; 3457 this._y = c1 * s2 * c3 + s1 * c2 * s3; 3458 this._z = c1 * c2 * s3 - s1 * s2 * c3; 3459 this._w = c1 * c2 * c3 + s1 * s2 * s3; 3460 break; 3461 3462 case 'YZX': 3463 this._x = s1 * c2 * c3 + c1 * s2 * s3; 3464 this._y = c1 * s2 * c3 + s1 * c2 * s3; 3465 this._z = c1 * c2 * s3 - s1 * s2 * c3; 3466 this._w = c1 * c2 * c3 - s1 * s2 * s3; 3467 break; 3468 3469 case 'XZY': 3470 this._x = s1 * c2 * c3 - c1 * s2 * s3; 3471 this._y = c1 * s2 * c3 - s1 * c2 * s3; 3472 this._z = c1 * c2 * s3 + s1 * s2 * c3; 3473 this._w = c1 * c2 * c3 + s1 * s2 * s3; 3474 break; 3475 3476 default: 3477 console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); 3478 3479 } 3480 3481 if ( update === true ) this._onChangeCallback(); 3482 3483 return this; 3484 3485 } 3486 3487 setFromAxisAngle( axis, angle ) { 3488 3489 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm 3490 3491 // assumes axis is normalized 3492 3493 const halfAngle = angle / 2, s = Math.sin( halfAngle ); 3494 3495 this._x = axis.x * s; 3496 this._y = axis.y * s; 3497 this._z = axis.z * s; 3498 this._w = Math.cos( halfAngle ); 3499 3500 this._onChangeCallback(); 3501 3502 return this; 3503 3504 } 3505 3506 setFromRotationMatrix( m ) { 3507 3508 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm 3509 3510 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 3511 3512 const te = m.elements, 3513 3514 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], 3515 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], 3516 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], 3517 3518 trace = m11 + m22 + m33; 3519 3520 if ( trace > 0 ) { 3521 3522 const s = 0.5 / Math.sqrt( trace + 1.0 ); 3523 3524 this._w = 0.25 / s; 3525 this._x = ( m32 - m23 ) * s; 3526 this._y = ( m13 - m31 ) * s; 3527 this._z = ( m21 - m12 ) * s; 3528 3529 } else if ( m11 > m22 && m11 > m33 ) { 3530 3531 const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); 3532 3533 this._w = ( m32 - m23 ) / s; 3534 this._x = 0.25 * s; 3535 this._y = ( m12 + m21 ) / s; 3536 this._z = ( m13 + m31 ) / s; 3537 3538 } else if ( m22 > m33 ) { 3539 3540 const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); 3541 3542 this._w = ( m13 - m31 ) / s; 3543 this._x = ( m12 + m21 ) / s; 3544 this._y = 0.25 * s; 3545 this._z = ( m23 + m32 ) / s; 3546 3547 } else { 3548 3549 const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); 3550 3551 this._w = ( m21 - m12 ) / s; 3552 this._x = ( m13 + m31 ) / s; 3553 this._y = ( m23 + m32 ) / s; 3554 this._z = 0.25 * s; 3555 3556 } 3557 3558 this._onChangeCallback(); 3559 3560 return this; 3561 3562 } 3563 3564 setFromUnitVectors( vFrom, vTo ) { 3565 3566 // assumes direction vectors vFrom and vTo are normalized 3567 3568 let r = vFrom.dot( vTo ) + 1; 3569 3570 if ( r < Number.EPSILON ) { 3571 3572 // vFrom and vTo point in opposite directions 3573 3574 r = 0; 3575 3576 if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { 3577 3578 this._x = - vFrom.y; 3579 this._y = vFrom.x; 3580 this._z = 0; 3581 this._w = r; 3582 3583 } else { 3584 3585 this._x = 0; 3586 this._y = - vFrom.z; 3587 this._z = vFrom.y; 3588 this._w = r; 3589 3590 } 3591 3592 } else { 3593 3594 // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 3595 3596 this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; 3597 this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; 3598 this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; 3599 this._w = r; 3600 3601 } 3602 3603 return this.normalize(); 3604 3605 } 3606 3607 angleTo( q ) { 3608 3609 return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) ); 3610 3611 } 3612 3613 rotateTowards( q, step ) { 3614 3615 const angle = this.angleTo( q ); 3616 3617 if ( angle === 0 ) return this; 3618 3619 const t = Math.min( 1, step / angle ); 3620 3621 this.slerp( q, t ); 3622 3623 return this; 3624 3625 } 3626 3627 identity() { 3628 3629 return this.set( 0, 0, 0, 1 ); 3630 3631 } 3632 3633 invert() { 3634 3635 // quaternion is assumed to have unit length 3636 3637 return this.conjugate(); 3638 3639 } 3640 3641 conjugate() { 3642 3643 this._x *= - 1; 3644 this._y *= - 1; 3645 this._z *= - 1; 3646 3647 this._onChangeCallback(); 3648 3649 return this; 3650 3651 } 3652 3653 dot( v ) { 3654 3655 return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; 3656 3657 } 3658 3659 lengthSq() { 3660 3661 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; 3662 3663 } 3664 3665 length() { 3666 3667 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); 3668 3669 } 3670 3671 normalize() { 3672 3673 let l = this.length(); 3674 3675 if ( l === 0 ) { 3676 3677 this._x = 0; 3678 this._y = 0; 3679 this._z = 0; 3680 this._w = 1; 3681 3682 } else { 3683 3684 l = 1 / l; 3685 3686 this._x = this._x * l; 3687 this._y = this._y * l; 3688 this._z = this._z * l; 3689 this._w = this._w * l; 3690 3691 } 3692 3693 this._onChangeCallback(); 3694 3695 return this; 3696 3697 } 3698 3699 multiply( q ) { 3700 3701 return this.multiplyQuaternions( this, q ); 3702 3703 } 3704 3705 premultiply( q ) { 3706 3707 return this.multiplyQuaternions( q, this ); 3708 3709 } 3710 3711 multiplyQuaternions( a, b ) { 3712 3713 // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm 3714 3715 const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; 3716 const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; 3717 3718 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; 3719 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; 3720 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; 3721 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; 3722 3723 this._onChangeCallback(); 3724 3725 return this; 3726 3727 } 3728 3729 slerp( qb, t ) { 3730 3731 if ( t === 0 ) return this; 3732 if ( t === 1 ) return this.copy( qb ); 3733 3734 const x = this._x, y = this._y, z = this._z, w = this._w; 3735 3736 // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ 3737 3738 let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; 3739 3740 if ( cosHalfTheta < 0 ) { 3741 3742 this._w = - qb._w; 3743 this._x = - qb._x; 3744 this._y = - qb._y; 3745 this._z = - qb._z; 3746 3747 cosHalfTheta = - cosHalfTheta; 3748 3749 } else { 3750 3751 this.copy( qb ); 3752 3753 } 3754 3755 if ( cosHalfTheta >= 1.0 ) { 3756 3757 this._w = w; 3758 this._x = x; 3759 this._y = y; 3760 this._z = z; 3761 3762 return this; 3763 3764 } 3765 3766 const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; 3767 3768 if ( sqrSinHalfTheta <= Number.EPSILON ) { 3769 3770 const s = 1 - t; 3771 this._w = s * w + t * this._w; 3772 this._x = s * x + t * this._x; 3773 this._y = s * y + t * this._y; 3774 this._z = s * z + t * this._z; 3775 3776 this.normalize(); // normalize calls _onChangeCallback() 3777 3778 return this; 3779 3780 } 3781 3782 const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); 3783 const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); 3784 const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, 3785 ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; 3786 3787 this._w = ( w * ratioA + this._w * ratioB ); 3788 this._x = ( x * ratioA + this._x * ratioB ); 3789 this._y = ( y * ratioA + this._y * ratioB ); 3790 this._z = ( z * ratioA + this._z * ratioB ); 3791 3792 this._onChangeCallback(); 3793 3794 return this; 3795 3796 } 3797 3798 slerpQuaternions( qa, qb, t ) { 3799 3800 return this.copy( qa ).slerp( qb, t ); 3801 3802 } 3803 3804 random() { 3805 3806 // Derived from http://planning.cs.uiuc.edu/node198.html 3807 // Note, this source uses w, x, y, z ordering, 3808 // so we swap the order below. 3809 3810 const u1 = Math.random(); 3811 const sqrt1u1 = Math.sqrt( 1 - u1 ); 3812 const sqrtu1 = Math.sqrt( u1 ); 3813 3814 const u2 = 2 * Math.PI * Math.random(); 3815 3816 const u3 = 2 * Math.PI * Math.random(); 3817 3818 return this.set( 3819 sqrt1u1 * Math.cos( u2 ), 3820 sqrtu1 * Math.sin( u3 ), 3821 sqrtu1 * Math.cos( u3 ), 3822 sqrt1u1 * Math.sin( u2 ), 3823 ); 3824 3825 } 3826 3827 equals( quaternion ) { 3828 3829 return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); 3830 3831 } 3832 3833 fromArray( array, offset = 0 ) { 3834 3835 this._x = array[ offset ]; 3836 this._y = array[ offset + 1 ]; 3837 this._z = array[ offset + 2 ]; 3838 this._w = array[ offset + 3 ]; 3839 3840 this._onChangeCallback(); 3841 3842 return this; 3843 3844 } 3845 3846 toArray( array = [], offset = 0 ) { 3847 3848 array[ offset ] = this._x; 3849 array[ offset + 1 ] = this._y; 3850 array[ offset + 2 ] = this._z; 3851 array[ offset + 3 ] = this._w; 3852 3853 return array; 3854 3855 } 3856 3857 fromBufferAttribute( attribute, index ) { 3858 3859 this._x = attribute.getX( index ); 3860 this._y = attribute.getY( index ); 3861 this._z = attribute.getZ( index ); 3862 this._w = attribute.getW( index ); 3863 3864 this._onChangeCallback(); 3865 3866 return this; 3867 3868 } 3869 3870 toJSON() { 3871 3872 return this.toArray(); 3873 3874 } 3875 3876 _onChange( callback ) { 3877 3878 this._onChangeCallback = callback; 3879 3880 return this; 3881 3882 } 3883 3884 _onChangeCallback() {} 3885 3886 *[ Symbol.iterator ]() { 3887 3888 yield this._x; 3889 yield this._y; 3890 yield this._z; 3891 yield this._w; 3892 3893 } 3894 3895} 3896 3897class Vector3 { 3898 3899 constructor( x = 0, y = 0, z = 0 ) { 3900 3901 Vector3.prototype.isVector3 = true; 3902 3903 this.x = x; 3904 this.y = y; 3905 this.z = z; 3906 3907 } 3908 3909 set( x, y, z ) { 3910 3911 if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) 3912 3913 this.x = x; 3914 this.y = y; 3915 this.z = z; 3916 3917 return this; 3918 3919 } 3920 3921 setScalar( scalar ) { 3922 3923 this.x = scalar; 3924 this.y = scalar; 3925 this.z = scalar; 3926 3927 return this; 3928 3929 } 3930 3931 setX( x ) { 3932 3933 this.x = x; 3934 3935 return this; 3936 3937 } 3938 3939 setY( y ) { 3940 3941 this.y = y; 3942 3943 return this; 3944 3945 } 3946 3947 setZ( z ) { 3948 3949 this.z = z; 3950 3951 return this; 3952 3953 } 3954 3955 setComponent( index, value ) { 3956 3957 switch ( index ) { 3958 3959 case 0: this.x = value; break; 3960 case 1: this.y = value; break; 3961 case 2: this.z = value; break; 3962 default: throw new Error( 'index is out of range: ' + index ); 3963 3964 } 3965 3966 return this; 3967 3968 } 3969 3970 getComponent( index ) { 3971 3972 switch ( index ) { 3973 3974 case 0: return this.x; 3975 case 1: return this.y; 3976 case 2: return this.z; 3977 default: throw new Error( 'index is out of range: ' + index ); 3978 3979 } 3980 3981 } 3982 3983 clone() { 3984 3985 return new this.constructor( this.x, this.y, this.z ); 3986 3987 } 3988 3989 copy( v ) { 3990 3991 this.x = v.x; 3992 this.y = v.y; 3993 this.z = v.z; 3994 3995 return this; 3996 3997 } 3998 3999 add( v ) { 4000 4001 this.x += v.x; 4002 this.y += v.y; 4003 this.z += v.z; 4004 4005 return this; 4006 4007 } 4008 4009 addScalar( s ) { 4010 4011 this.x += s; 4012 this.y += s; 4013 this.z += s; 4014 4015 return this; 4016 4017 } 4018 4019 addVectors( a, b ) { 4020 4021 this.x = a.x + b.x; 4022 this.y = a.y + b.y; 4023 this.z = a.z + b.z; 4024 4025 return this; 4026 4027 } 4028 4029 addScaledVector( v, s ) { 4030 4031 this.x += v.x * s; 4032 this.y += v.y * s; 4033 this.z += v.z * s; 4034 4035 return this; 4036 4037 } 4038 4039 sub( v ) { 4040 4041 this.x -= v.x; 4042 this.y -= v.y; 4043 this.z -= v.z; 4044 4045 return this; 4046 4047 } 4048 4049 subScalar( s ) { 4050 4051 this.x -= s; 4052 this.y -= s; 4053 this.z -= s; 4054 4055 return this; 4056 4057 } 4058 4059 subVectors( a, b ) { 4060 4061 this.x = a.x - b.x; 4062 this.y = a.y - b.y; 4063 this.z = a.z - b.z; 4064 4065 return this; 4066 4067 } 4068 4069 multiply( v ) { 4070 4071 this.x *= v.x; 4072 this.y *= v.y; 4073 this.z *= v.z; 4074 4075 return this; 4076 4077 } 4078 4079 multiplyScalar( scalar ) { 4080 4081 this.x *= scalar; 4082 this.y *= scalar; 4083 this.z *= scalar; 4084 4085 return this; 4086 4087 } 4088 4089 multiplyVectors( a, b ) { 4090 4091 this.x = a.x * b.x; 4092 this.y = a.y * b.y; 4093 this.z = a.z * b.z; 4094 4095 return this; 4096 4097 } 4098 4099 applyEuler( euler ) { 4100 4101 return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); 4102 4103 } 4104 4105 applyAxisAngle( axis, angle ) { 4106 4107 return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); 4108 4109 } 4110 4111 applyMatrix3( m ) { 4112 4113 const x = this.x, y = this.y, z = this.z; 4114 const e = m.elements; 4115 4116 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; 4117 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; 4118 this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; 4119 4120 return this; 4121 4122 } 4123 4124 applyNormalMatrix( m ) { 4125 4126 return this.applyMatrix3( m ).normalize(); 4127 4128 } 4129 4130 applyMatrix4( m ) { 4131 4132 const x = this.x, y = this.y, z = this.z; 4133 const e = m.elements; 4134 4135 const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); 4136 4137 this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; 4138 this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; 4139 this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; 4140 4141 return this; 4142 4143 } 4144 4145 applyQuaternion( q ) { 4146 4147 // quaternion q is assumed to have unit length 4148 4149 const vx = this.x, vy = this.y, vz = this.z; 4150 const qx = q.x, qy = q.y, qz = q.z, qw = q.w; 4151 4152 // t = 2 * cross( q.xyz, v ); 4153 const tx = 2 * ( qy * vz - qz * vy ); 4154 const ty = 2 * ( qz * vx - qx * vz ); 4155 const tz = 2 * ( qx * vy - qy * vx ); 4156 4157 // v + q.w * t + cross( q.xyz, t ); 4158 this.x = vx + qw * tx + qy * tz - qz * ty; 4159 this.y = vy + qw * ty + qz * tx - qx * tz; 4160 this.z = vz + qw * tz + qx * ty - qy * tx; 4161 4162 return this; 4163 4164 } 4165 4166 project( camera ) { 4167 4168 return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); 4169 4170 } 4171 4172 unproject( camera ) { 4173 4174 return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); 4175 4176 } 4177 4178 transformDirection( m ) { 4179 4180 // input: THREE.Matrix4 affine matrix 4181 // vector interpreted as a direction 4182 4183 const x = this.x, y = this.y, z = this.z; 4184 const e = m.elements; 4185 4186 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; 4187 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; 4188 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; 4189 4190 return this.normalize(); 4191 4192 } 4193 4194 divide( v ) { 4195 4196 this.x /= v.x; 4197 this.y /= v.y; 4198 this.z /= v.z; 4199 4200 return this; 4201 4202 } 4203 4204 divideScalar( scalar ) { 4205 4206 return this.multiplyScalar( 1 / scalar ); 4207 4208 } 4209 4210 min( v ) { 4211 4212 this.x = Math.min( this.x, v.x ); 4213 this.y = Math.min( this.y, v.y ); 4214 this.z = Math.min( this.z, v.z ); 4215 4216 return this; 4217 4218 } 4219 4220 max( v ) { 4221 4222 this.x = Math.max( this.x, v.x ); 4223 this.y = Math.max( this.y, v.y ); 4224 this.z = Math.max( this.z, v.z ); 4225 4226 return this; 4227 4228 } 4229 4230 clamp( min, max ) { 4231 4232 // assumes min < max, componentwise 4233 4234 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 4235 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 4236 this.z = Math.max( min.z, Math.min( max.z, this.z ) ); 4237 4238 return this; 4239 4240 } 4241 4242 clampScalar( minVal, maxVal ) { 4243 4244 this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); 4245 this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); 4246 this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); 4247 4248 return this; 4249 4250 } 4251 4252 clampLength( min, max ) { 4253 4254 const length = this.length(); 4255 4256 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 4257 4258 } 4259 4260 floor() { 4261 4262 this.x = Math.floor( this.x ); 4263 this.y = Math.floor( this.y ); 4264 this.z = Math.floor( this.z ); 4265 4266 return this; 4267 4268 } 4269 4270 ceil() { 4271 4272 this.x = Math.ceil( this.x ); 4273 this.y = Math.ceil( this.y ); 4274 this.z = Math.ceil( this.z ); 4275 4276 return this; 4277 4278 } 4279 4280 round() { 4281 4282 this.x = Math.round( this.x ); 4283 this.y = Math.round( this.y ); 4284 this.z = Math.round( this.z ); 4285 4286 return this; 4287 4288 } 4289 4290 roundToZero() { 4291 4292 this.x = Math.trunc( this.x ); 4293 this.y = Math.trunc( this.y ); 4294 this.z = Math.trunc( this.z ); 4295 4296 return this; 4297 4298 } 4299 4300 negate() { 4301 4302 this.x = - this.x; 4303 this.y = - this.y; 4304 this.z = - this.z; 4305 4306 return this; 4307 4308 } 4309 4310 dot( v ) { 4311 4312 return this.x * v.x + this.y * v.y + this.z * v.z; 4313 4314 } 4315 4316 // TODO lengthSquared? 4317 4318 lengthSq() { 4319 4320 return this.x * this.x + this.y * this.y + this.z * this.z; 4321 4322 } 4323 4324 length() { 4325 4326 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); 4327 4328 } 4329 4330 manhattanLength() { 4331 4332 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); 4333 4334 } 4335 4336 normalize() { 4337 4338 return this.divideScalar( this.length() || 1 ); 4339 4340 } 4341 4342 setLength( length ) { 4343 4344 return this.normalize().multiplyScalar( length ); 4345 4346 } 4347 4348 lerp( v, alpha ) { 4349 4350 this.x += ( v.x - this.x ) * alpha; 4351 this.y += ( v.y - this.y ) * alpha; 4352 this.z += ( v.z - this.z ) * alpha; 4353 4354 return this; 4355 4356 } 4357 4358 lerpVectors( v1, v2, alpha ) { 4359 4360 this.x = v1.x + ( v2.x - v1.x ) * alpha; 4361 this.y = v1.y + ( v2.y - v1.y ) * alpha; 4362 this.z = v1.z + ( v2.z - v1.z ) * alpha; 4363 4364 return this; 4365 4366 } 4367 4368 cross( v ) { 4369 4370 return this.crossVectors( this, v ); 4371 4372 } 4373 4374 crossVectors( a, b ) { 4375 4376 const ax = a.x, ay = a.y, az = a.z; 4377 const bx = b.x, by = b.y, bz = b.z; 4378 4379 this.x = ay * bz - az * by; 4380 this.y = az * bx - ax * bz; 4381 this.z = ax * by - ay * bx; 4382 4383 return this; 4384 4385 } 4386 4387 projectOnVector( v ) { 4388 4389 const denominator = v.lengthSq(); 4390 4391 if ( denominator === 0 ) return this.set( 0, 0, 0 ); 4392 4393 const scalar = v.dot( this ) / denominator; 4394 4395 return this.copy( v ).multiplyScalar( scalar ); 4396 4397 } 4398 4399 projectOnPlane( planeNormal ) { 4400 4401 _vector$c.copy( this ).projectOnVector( planeNormal ); 4402 4403 return this.sub( _vector$c ); 4404 4405 } 4406 4407 reflect( normal ) { 4408 4409 // reflect incident vector off plane orthogonal to normal 4410 // normal is assumed to have unit length 4411 4412 return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); 4413 4414 } 4415 4416 angleTo( v ) { 4417 4418 const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); 4419 4420 if ( denominator === 0 ) return Math.PI / 2; 4421 4422 const theta = this.dot( v ) / denominator; 4423 4424 // clamp, to handle numerical problems 4425 4426 return Math.acos( clamp( theta, - 1, 1 ) ); 4427 4428 } 4429 4430 distanceTo( v ) { 4431 4432 return Math.sqrt( this.distanceToSquared( v ) ); 4433 4434 } 4435 4436 distanceToSquared( v ) { 4437 4438 const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; 4439 4440 return dx * dx + dy * dy + dz * dz; 4441 4442 } 4443 4444 manhattanDistanceTo( v ) { 4445 4446 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); 4447 4448 } 4449 4450 setFromSpherical( s ) { 4451 4452 return this.setFromSphericalCoords( s.radius, s.phi, s.theta ); 4453 4454 } 4455 4456 setFromSphericalCoords( radius, phi, theta ) { 4457 4458 const sinPhiRadius = Math.sin( phi ) * radius; 4459 4460 this.x = sinPhiRadius * Math.sin( theta ); 4461 this.y = Math.cos( phi ) * radius; 4462 this.z = sinPhiRadius * Math.cos( theta ); 4463 4464 return this; 4465 4466 } 4467 4468 setFromCylindrical( c ) { 4469 4470 return this.setFromCylindricalCoords( c.radius, c.theta, c.y ); 4471 4472 } 4473 4474 setFromCylindricalCoords( radius, theta, y ) { 4475
vendor: 1,851 bytes, lines 4476-4598
4476 this.x = radius * Math.sin( theta ); 4477 this.y = y; 4478 this.z = radius * Math.cos( theta ); 4479 4480 return this; 4481 4482 } 4483 4484 setFromMatrixPosition( m ) { 4485 4486 const e = m.elements; 4487 4488 this.x = e[ 12 ]; 4489 this.y = e[ 13 ]; 4490 this.z = e[ 14 ]; 4491 4492 return this; 4493 4494 } 4495 4496 setFromMatrixScale( m ) { 4497 4498 const sx = this.setFromMatrixColumn( m, 0 ).length(); 4499 const sy = this.setFromMatrixColumn( m, 1 ).length(); 4500 const sz = this.setFromMatrixColumn( m, 2 ).length(); 4501 4502 this.x = sx; 4503 this.y = sy; 4504 this.z = sz; 4505 4506 return this; 4507 4508 } 4509 4510 setFromMatrixColumn( m, index ) { 4511 4512 return this.fromArray( m.elements, index * 4 ); 4513 4514 } 4515 4516 setFromMatrix3Column( m, index ) { 4517 4518 return this.fromArray( m.elements, index * 3 ); 4519 4520 } 4521 4522 setFromEuler( e ) { 4523 4524 this.x = e._x; 4525 this.y = e._y; 4526 this.z = e._z; 4527 4528 return this; 4529 4530 } 4531 4532 setFromColor( c ) { 4533 4534 this.x = c.r; 4535 this.y = c.g; 4536 this.z = c.b; 4537 4538 return this; 4539 4540 } 4541 4542 equals( v ) { 4543 4544 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); 4545 4546 } 4547 4548 fromArray( array, offset = 0 ) { 4549 4550 this.x = array[ offset ]; 4551 this.y = array[ offset + 1 ]; 4552 this.z = array[ offset + 2 ]; 4553 4554 return this; 4555 4556 } 4557 4558 toArray( array = [], offset = 0 ) { 4559 4560 array[ offset ] = this.x; 4561 array[ offset + 1 ] = this.y; 4562 array[ offset + 2 ] = this.z; 4563 4564 return array; 4565 4566 } 4567 4568 fromBufferAttribute( attribute, index ) { 4569 4570 this.x = attribute.getX( index ); 4571 this.y = attribute.getY( index ); 4572 this.z = attribute.getZ( index ); 4573 4574 return this; 4575 4576 } 4577 4578 random() { 4579 4580 this.x = Math.random(); 4581 this.y = Math.random(); 4582 this.z = Math.random(); 4583 4584 return this; 4585 4586 } 4587 4588 randomDirection() { 4589 4590 // Derived from https://mathworld.wolfram.com/SpherePointPicking.html 4591 4592 const u = ( Math.random() - 0.5 ) * 2; 4593 const t = Math.random() * Math.PI * 2; 4594 const f = Math.sqrt( 1 - u ** 2 ); 4595 4596 this.x = f * Math.cos( t ); 4597 this.y = f * Math.sin( t ); 4598 this.z = u
vendor: 11,889 bytes, lines 4598-5154
4598; 4599 4600 return this; 4601 4602 } 4603 4604 *[ Symbol.iterator ]() { 4605 4606 yield this.x; 4607 yield this.y; 4608 yield this.z; 4609 4610 } 4611 4612} 4613 4614const _vector$c = /*@__PURE__*/ new Vector3(); 4615const _quaternion$4 = /*@__PURE__*/ new Quaternion(); 4616 4617class Box3 { 4618 4619 constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) { 4620 4621 this.isBox3 = true; 4622 4623 this.min = min; 4624 this.max = max; 4625 4626 } 4627 4628 set( min, max ) { 4629 4630 this.min.copy( min ); 4631 this.max.copy( max ); 4632 4633 return this; 4634 4635 } 4636 4637 setFromArray( array ) { 4638 4639 this.makeEmpty(); 4640 4641 for ( let i = 0, il = array.length; i < il; i += 3 ) { 4642 4643 this.expandByPoint( _vector$b.fromArray( array, i ) ); 4644 4645 } 4646 4647 return this; 4648 4649 } 4650 4651 setFromBufferAttribute( attribute ) { 4652 4653 this.makeEmpty(); 4654 4655 for ( let i = 0, il = attribute.count; i < il; i ++ ) { 4656 4657 this.expandByPoint( _vector$b.fromBufferAttribute( attribute, i ) ); 4658 4659 } 4660 4661 return this; 4662 4663 } 4664 4665 setFromPoints( points ) { 4666 4667 this.makeEmpty(); 4668 4669 for ( let i = 0, il = points.length; i < il; i ++ ) { 4670 4671 this.expandByPoint( points[ i ] ); 4672 4673 } 4674 4675 return this; 4676 4677 } 4678 4679 setFromCenterAndSize( center, size ) { 4680 4681 const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); 4682 4683 this.min.copy( center ).sub( halfSize ); 4684 this.max.copy( center ).add( halfSize ); 4685 4686 return this; 4687 4688 } 4689 4690 setFromObject( object, precise = false ) { 4691 4692 this.makeEmpty(); 4693 4694 return this.expandByObject( object, precise ); 4695 4696 } 4697 4698 clone() { 4699 4700 return new this.constructor().copy( this ); 4701 4702 } 4703 4704 copy( box ) { 4705 4706 this.min.copy( box.min ); 4707 this.max.copy( box.max ); 4708 4709 return this; 4710 4711 } 4712 4713 makeEmpty() { 4714 4715 this.min.x = this.min.y = this.min.z = + Infinity; 4716 this.max.x = this.max.y = this.max.z = - Infinity; 4717 4718 return this; 4719 4720 } 4721 4722 isEmpty() { 4723 4724 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes 4725 4726 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); 4727 4728 } 4729 4730 getCenter( target ) { 4731 4732 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); 4733 4734 } 4735 4736 getSize( target ) { 4737 4738 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min ); 4739 4740 } 4741 4742 expandByPoint( point ) { 4743 4744 this.min.min( point ); 4745 this.max.max( point ); 4746 4747 return this; 4748 4749 } 4750 4751 expandByVector( vector ) { 4752 4753 this.min.sub( vector ); 4754 this.max.add( vector ); 4755 4756 return this; 4757 4758 } 4759 4760 expandByScalar( scalar ) { 4761 4762 this.min.addScalar( - scalar ); 4763 this.max.addScalar( scalar ); 4764 4765 return this; 4766 4767 } 4768 4769 expandByObject( object, precise = false ) { 4770 4771 // Computes the world-axis-aligned bounding box of an object (including its children), 4772 // accounting for both the object's, and children's, world transforms 4773 4774 object.updateWorldMatrix( false, false ); 4775 4776 const geometry = object.geometry; 4777 4778 if ( geometry !== undefined ) { 4779 4780 const positionAttribute = geometry.getAttribute( 'position' ); 4781 4782 // precise AABB computation based on vertex data requires at least a position attribute. 4783 // instancing isn't supported so far and uses the normal (conservative) code path. 4784 4785 if ( precise === true && positionAttribute !== undefined && object.isInstancedMesh !== true ) { 4786 4787 for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) { 4788 4789 if ( object.isMesh === true ) { 4790 4791 object.getVertexPosition( i, _vector$b ); 4792 4793 } else { 4794 4795 _vector$b.fromBufferAttribute( positionAttribute, i ); 4796 4797 } 4798 4799 _vector$b.applyMatrix4( object.matrixWorld ); 4800 this.expandByPoint( _vector$b ); 4801 4802 } 4803 4804 } else { 4805 4806 if ( object.boundingBox !== undefined ) { 4807 4808 // object-level bounding box 4809 4810 if ( object.boundingBox === null ) { 4811 4812 object.computeBoundingBox(); 4813 4814 } 4815 4816 _box$4.copy( object.boundingBox ); 4817 4818 4819 } else { 4820 4821 // geometry-level bounding box 4822 4823 if ( geometry.boundingBox === null ) { 4824 4825 geometry.computeBoundingBox(); 4826 4827 } 4828 4829 _box$4.copy( geometry.boundingBox ); 4830 4831 } 4832 4833 _box$4.applyMatrix4( object.matrixWorld ); 4834 4835 this.union( _box$4 ); 4836 4837 } 4838 4839 } 4840 4841 const children = object.children; 4842 4843 for ( let i = 0, l = children.length; i < l; i ++ ) { 4844 4845 this.expandByObject( children[ i ], precise ); 4846 4847 } 4848 4849 return this; 4850 4851 } 4852 4853 containsPoint( point ) { 4854 4855 return point.x < this.min.x || point.x > this.max.x || 4856 point.y < this.min.y || point.y > this.max.y || 4857 point.z < this.min.z || point.z > this.max.z ? false : true; 4858 4859 } 4860 4861 containsBox( box ) { 4862 4863 return this.min.x <= box.min.x && box.max.x <= this.max.x && 4864 this.min.y <= box.min.y && box.max.y <= this.max.y && 4865 this.min.z <= box.min.z && box.max.z <= this.max.z; 4866 4867 } 4868 4869 getParameter( point, target ) { 4870 4871 // This can potentially have a divide by zero if the box 4872 // has a size dimension of 0. 4873 4874 return target.set( 4875 ( point.x - this.min.x ) / ( this.max.x - this.min.x ), 4876 ( point.y - this.min.y ) / ( this.max.y - this.min.y ), 4877 ( point.z - this.min.z ) / ( this.max.z - this.min.z ) 4878 ); 4879 4880 } 4881 4882 intersectsBox( box ) { 4883 4884 // using 6 splitting planes to rule out intersections. 4885 return box.max.x < this.min.x || box.min.x > this.max.x || 4886 box.max.y < this.min.y || box.min.y > this.max.y || 4887 box.max.z < this.min.z || box.min.z > this.max.z ? false : true; 4888 4889 } 4890 4891 intersectsSphere( sphere ) { 4892 4893 // Find the point on the AABB closest to the sphere center. 4894 this.clampPoint( sphere.center, _vector$b ); 4895 4896 // If that point is inside the sphere, the AABB and sphere intersect. 4897 return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); 4898 4899 } 4900 4901 intersectsPlane( plane ) { 4902 4903 // We compute the minimum and maximum dot product values. If those values 4904 // are on the same side (back or front) of the plane, then there is no intersection. 4905 4906 let min, max; 4907 4908 if ( plane.normal.x > 0 ) { 4909 4910 min = plane.normal.x * this.min.x; 4911 max = plane.normal.x * this.max.x; 4912 4913 } else { 4914 4915 min = plane.normal.x * this.max.x; 4916 max = plane.normal.x * this.min.x; 4917 4918 } 4919 4920 if ( plane.normal.y > 0 ) { 4921 4922 min += plane.normal.y * this.min.y; 4923 max += plane.normal.y * this.max.y; 4924 4925 } else { 4926 4927 min += plane.normal.y * this.max.y; 4928 max += plane.normal.y * this.min.y; 4929 4930 } 4931 4932 if ( plane.normal.z > 0 ) { 4933 4934 min += plane.normal.z * this.min.z; 4935 max += plane.normal.z * this.max.z; 4936 4937 } else { 4938 4939 min += plane.normal.z * this.max.z; 4940 max += plane.normal.z * this.min.z; 4941 4942 } 4943 4944 return ( min <= - plane.constant && max >= - plane.constant ); 4945 4946 } 4947 4948 intersectsTriangle( triangle ) { 4949 4950 if ( this.isEmpty() ) { 4951 4952 return false; 4953 4954 } 4955 4956 // compute box center and extents 4957 this.getCenter( _center ); 4958 _extents.subVectors( this.max, _center ); 4959 4960 // translate triangle to aabb origin 4961 _v0$2.subVectors( triangle.a, _center ); 4962 _v1$7.subVectors( triangle.b, _center ); 4963 _v2$4.subVectors( triangle.c, _center ); 4964 4965 // compute edge vectors for triangle 4966 _f0.subVectors( _v1$7, _v0$2 ); 4967 _f1.subVectors( _v2$4, _v1$7 ); 4968 _f2.subVectors( _v0$2, _v2$4 ); 4969 4970 // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb 4971 // 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 4972 // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned) 4973 let axes = [ 4974 0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y, 4975 _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x, 4976 - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0 4977 ]; 4978 if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) { 4979 4980 return false; 4981 4982 } 4983 4984 // test 3 face normals from the aabb 4985 axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; 4986 if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) { 4987 4988 return false; 4989 4990 } 4991 4992 // finally testing the face normal of the triangle 4993 // use already existing triangle edge vectors here 4994 _triangleNormal.crossVectors( _f0, _f1 ); 4995 axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ]; 4996 4997 return satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ); 4998 4999 } 5000 5001 clampPoint( point, target ) { 5002 5003 return target.copy( point ).clamp( this.min, this.max ); 5004 5005 } 5006 5007 distanceToPoint( point ) { 5008 5009 return this.clampPoint( point, _vector$b ).distanceTo( point ); 5010 5011 } 5012 5013 getBoundingSphere( target ) { 5014 5015 if ( this.isEmpty() ) { 5016 5017 target.makeEmpty(); 5018 5019 } else { 5020 5021 this.getCenter( target.center ); 5022 5023 target.radius = this.getSize( _vector$b ).length() * 0.5; 5024 5025 } 5026 5027 return target; 5028 5029 } 5030 5031 intersect( box ) { 5032 5033 this.min.max( box.min ); 5034 this.max.min( box.max ); 5035 5036 // 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. 5037 if ( this.isEmpty() ) this.makeEmpty(); 5038 5039 return this; 5040 5041 } 5042 5043 union( box ) { 5044 5045 this.min.min( box.min ); 5046 this.max.max( box.max ); 5047 5048 return this; 5049 5050 } 5051 5052 applyMatrix4( matrix ) { 5053 5054 // transform of empty box is an empty box. 5055 if ( this.isEmpty() ) return this; 5056 5057 // NOTE: I am using a binary pattern to specify all 2^3 combinations below 5058 _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 5059 _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 5060 _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 5061 _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 5062 _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 5063 _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 5064 _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 5065 _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 5066 5067 this.setFromPoints( _points ); 5068 5069 return this; 5070 5071 } 5072 5073 translate( offset ) { 5074 5075 this.min.add( offset ); 5076 this.max.add( offset ); 5077 5078 return this; 5079 5080 } 5081 5082 equals( box ) { 5083 5084 return box.min.equals( this.min ) && box.max.equals( this.max ); 5085 5086 } 5087 5088} 5089 5090const _points = [ 5091 /*@__PURE__*/ new Vector3(), 5092 /*@__PURE__*/ new Vector3(), 5093 /*@__PURE__*/ new Vector3(), 5094 /*@__PURE__*/ new Vector3(), 5095 /*@__PURE__*/ new Vector3(), 5096 /*@__PURE__*/ new Vector3(), 5097 /*@__PURE__*/ new Vector3(), 5098 /*@__PURE__*/ new Vector3() 5099]; 5100 5101const _vector$b = /*@__PURE__*/ new Vector3(); 5102 5103const _box$4 = /*@__PURE__*/ new Box3(); 5104 5105// triangle centered vertices 5106 5107const _v0$2 = /*@__PURE__*/ new Vector3(); 5108const _v1$7 = /*@__PURE__*/ new Vector3(); 5109const _v2$4 = /*@__PURE__*/ new Vector3(); 5110 5111// triangle edge vectors 5112 5113const _f0 = /*@__PURE__*/ new Vector3(); 5114const _f1 = /*@__PURE__*/ new Vector3(); 5115const _f2 = /*@__PURE__*/ new Vector3(); 5116 5117const _center = /*@__PURE__*/ new Vector3(); 5118const _extents = /*@__PURE__*/ new Vector3(); 5119const _triangleNormal = /*@__PURE__*/ new Vector3(); 5120const _testAxis = /*@__PURE__*/ new Vector3(); 5121 5122function satForAxes( axes, v0, v1, v2, extents ) { 5123 5124 for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) { 5125 5126 _testAxis.fromArray( axes, i ); 5127 // project the aabb onto the separating axis 5128 const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z ); 5129 // project all 3 vertices of the triangle onto the separating axis 5130 const p0 = v0.dot( _testAxis ); 5131 const p1 = v1.dot( _testAxis ); 5132 const p2 = v2.dot( _testAxis ); 5133 // actual test, basically see if either of the most extreme of the triangle points intersects r 5134 if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) { 5135 5136 // points of the projected triangle are outside the projected half-length of the aabb 5137 // the axis is separating and we can exit 5138 return false; 5139 5140 } 5141 5142 } 5143 5144 return true; 5145 5146} 5147 5148const _box$3 = /*@__PURE__*/ new Box3(); 5149const _v1$6 = /*@__PURE__*/ new Vector3(); 5150const _v2$3 = /*@__PURE__*/ new Vector3(); 5151 5152class Sphere { 5153 5154 constructor( center = new Vector3(), radius = -
vendor: 3,824 bytes, lines 5154-5400
5154 1 ) { 5155 5156 this.isSphere = true; 5157 5158 this.center = center; 5159 this.radius = radius; 5160 5161 } 5162 5163 set( center, radius ) { 5164 5165 this.center.copy( center ); 5166 this.radius = radius; 5167 5168 return this; 5169 5170 } 5171 5172 setFromPoints( points, optionalCenter ) { 5173 5174 const center = this.center; 5175 5176 if ( optionalCenter !== undefined ) { 5177 5178 center.copy( optionalCenter ); 5179 5180 } else { 5181 5182 _box$3.setFromPoints( points ).getCenter( center ); 5183 5184 } 5185 5186 let maxRadiusSq = 0; 5187 5188 for ( let i = 0, il = points.length; i < il; i ++ ) { 5189 5190 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); 5191 5192 } 5193 5194 this.radius = Math.sqrt( maxRadiusSq ); 5195 5196 return this; 5197 5198 } 5199 5200 copy( sphere ) { 5201 5202 this.center.copy( sphere.center ); 5203 this.radius = sphere.radius; 5204 5205 return this; 5206 5207 } 5208 5209 isEmpty() { 5210 5211 return ( this.radius < 0 ); 5212 5213 } 5214 5215 makeEmpty() { 5216 5217 this.center.set( 0, 0, 0 ); 5218 this.radius = - 1; 5219 5220 return this; 5221 5222 } 5223 5224 containsPoint( point ) { 5225 5226 return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); 5227 5228 } 5229 5230 distanceToPoint( point ) { 5231 5232 return ( point.distanceTo( this.center ) - this.radius ); 5233 5234 } 5235 5236 intersectsSphere( sphere ) { 5237 5238 const radiusSum = this.radius + sphere.radius; 5239 5240 return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); 5241 5242 } 5243 5244 intersectsBox( box ) { 5245 5246 return box.intersectsSphere( this ); 5247 5248 } 5249 5250 intersectsPlane( plane ) { 5251 5252 return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; 5253 5254 } 5255 5256 clampPoint( point, target ) { 5257 5258 const deltaLengthSq = this.center.distanceToSquared( point ); 5259 5260 target.copy( point ); 5261 5262 if ( deltaLengthSq > ( this.radius * this.radius ) ) { 5263 5264 target.sub( this.center ).normalize(); 5265 target.multiplyScalar( this.radius ).add( this.center ); 5266 5267 } 5268 5269 return target; 5270 5271 } 5272 5273 getBoundingBox( target ) { 5274 5275 if ( this.isEmpty() ) { 5276 5277 // Empty sphere produces empty bounding box 5278 target.makeEmpty(); 5279 return target; 5280 5281 } 5282 5283 target.set( this.center, this.center ); 5284 target.expandByScalar( this.radius ); 5285 5286 return target; 5287 5288 } 5289 5290 applyMatrix4( matrix ) { 5291 5292 this.center.applyMatrix4( matrix ); 5293 this.radius = this.radius * matrix.getMaxScaleOnAxis(); 5294 5295 return this; 5296 5297 } 5298 5299 translate( offset ) { 5300 5301 this.center.add( offset ); 5302 5303 return this; 5304 5305 } 5306 5307 expandByPoint( point ) { 5308 5309 if ( this.isEmpty() ) { 5310 5311 this.center.copy( point ); 5312 5313 this.radius = 0; 5314 5315 return this; 5316 5317 } 5318 5319 _v1$6.subVectors( point, this.center ); 5320 5321 const lengthSq = _v1$6.lengthSq(); 5322 5323 if ( lengthSq > ( this.radius * this.radius ) ) { 5324 5325 // calculate the minimal sphere 5326 5327 const length = Math.sqrt( lengthSq ); 5328 5329 const delta = ( length - this.radius ) * 0.5; 5330 5331 this.center.addScaledVector( _v1$6, delta / length ); 5332 5333 this.radius += delta; 5334 5335 } 5336 5337 return this; 5338 5339 } 5340 5341 union( sphere ) { 5342 5343 if ( sphere.isEmpty() ) { 5344 5345 return this; 5346 5347 } 5348 5349 if ( this.isEmpty() ) { 5350 5351 this.copy( sphere ); 5352 5353 return this; 5354 5355 } 5356 5357 if ( this.center.equals( sphere.center ) === true ) { 5358 5359 this.radius = Math.max( this.radius, sphere.radius ); 5360 5361 } else { 5362 5363 _v2$3.subVectors( sphere.center, this.center ).setLength( sphere.radius ); 5364 5365 this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) ); 5366 5367 this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) ); 5368 5369 } 5370 5371 return this; 5372 5373 } 5374 5375 equals( sphere ) { 5376 5377 return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); 5378 5379 } 5380 5381 clone() { 5382 5383 return new this.constructor().copy( this ); 5384 5385 } 5386 5387} 5388 5389const _vector$a = /*@__PURE__*/ new Vector3(); 5390const _segCenter = /*@__PURE__*/ new Vector3(); 5391const _segDir = /*@__PURE__*/ new Vector3(); 5392const _diff = /*@__PURE__*/ new Vector3(); 5393 5394const _edge1 = /*@__PURE__*/ new Vector3(); 5395const _edge2 = /*@__PURE__*/ new Vector3(); 5396const _normal$1 = /*@__PURE__*/ new Vector3(); 5397 5398class Ray { 5399 5400 constructor( origin = new Vector3(), direction = new Vector3( 0, 0, -
vendor: 8,510 bytes, lines 5400-5806
54001 ) ) { 5401 5402 this.origin = origin; 5403 this.direction = direction; 5404 5405 } 5406 5407 set( origin, direction ) { 5408 5409 this.origin.copy( origin ); 5410 this.direction.copy( direction ); 5411 5412 return this; 5413 5414 } 5415 5416 copy( ray ) { 5417 5418 this.origin.copy( ray.origin ); 5419 this.direction.copy( ray.direction ); 5420 5421 return this; 5422 5423 } 5424 5425 at( t, target ) { 5426 5427 return target.copy( this.origin ).addScaledVector( this.direction, t ); 5428 5429 } 5430 5431 lookAt( v ) { 5432 5433 this.direction.copy( v ).sub( this.origin ).normalize(); 5434 5435 return this; 5436 5437 } 5438 5439 recast( t ) { 5440 5441 this.origin.copy( this.at( t, _vector$a ) ); 5442 5443 return this; 5444 5445 } 5446 5447 closestPointToPoint( point, target ) { 5448 5449 target.subVectors( point, this.origin ); 5450 5451 const directionDistance = target.dot( this.direction ); 5452 5453 if ( directionDistance < 0 ) { 5454 5455 return target.copy( this.origin ); 5456 5457 } 5458 5459 return target.copy( this.origin ).addScaledVector( this.direction, directionDistance ); 5460 5461 } 5462 5463 distanceToPoint( point ) { 5464 5465 return Math.sqrt( this.distanceSqToPoint( point ) ); 5466 5467 } 5468 5469 distanceSqToPoint( point ) { 5470 5471 const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); 5472 5473 // point behind the ray 5474 5475 if ( directionDistance < 0 ) { 5476 5477 return this.origin.distanceToSquared( point ); 5478 5479 } 5480 5481 _vector$a.copy( this.origin ).addScaledVector( this.direction, directionDistance ); 5482 5483 return _vector$a.distanceToSquared( point ); 5484 5485 } 5486 5487 distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { 5488 5489 // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h 5490 // It returns the min distance between the ray and the segment 5491 // defined by v0 and v1 5492 // It can also set two optional targets : 5493 // - The closest point on the ray 5494 // - The closest point on the segment 5495 5496 _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); 5497 _segDir.copy( v1 ).sub( v0 ).normalize(); 5498 _diff.copy( this.origin ).sub( _segCenter ); 5499 5500 const segExtent = v0.distanceTo( v1 ) * 0.5; 5501 const a01 = - this.direction.dot( _segDir ); 5502 const b0 = _diff.dot( this.direction ); 5503 const b1 = - _diff.dot( _segDir ); 5504 const c = _diff.lengthSq(); 5505 const det = Math.abs( 1 - a01 * a01 ); 5506 let s0, s1, sqrDist, extDet; 5507 5508 if ( det > 0 ) { 5509 5510 // The ray and segment are not parallel. 5511 5512 s0 = a01 * b1 - b0; 5513 s1 = a01 * b0 - b1; 5514 extDet = segExtent * det; 5515 5516 if ( s0 >= 0 ) { 5517 5518 if ( s1 >= - extDet ) { 5519 5520 if ( s1 <= extDet ) { 5521 5522 // region 0 5523 // Minimum at interior points of ray and segment. 5524 5525 const invDet = 1 / det; 5526 s0 *= invDet; 5527 s1 *= invDet; 5528 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; 5529 5530 } else { 5531 5532 // region 1 5533 5534 s1 = segExtent; 5535 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 5536 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5537 5538 } 5539 5540 } else { 5541 5542 // region 5 5543 5544 s1 = - segExtent; 5545 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 5546 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5547 5548 } 5549 5550 } else { 5551 5552 if ( s1 <= - extDet ) { 5553 5554 // region 4 5555 5556 s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) ); 5557 s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); 5558 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5559 5560 } else if ( s1 <= extDet ) { 5561 5562 // region 3 5563 5564 s0 = 0; 5565 s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); 5566 sqrDist = s1 * ( s1 + 2 * b1 ) + c; 5567 5568 } else { 5569 5570 // region 2 5571 5572 s0 = Math.max( 0, - ( a01 * segExtent + b0 ) ); 5573 s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); 5574 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5575 5576 } 5577 5578 } 5579 5580 } else { 5581 5582 // Ray and segment are parallel. 5583 5584 s1 = ( a01 > 0 ) ? - segExtent : segExtent; 5585 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 5586 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 5587 5588 } 5589 5590 if ( optionalPointOnRay ) { 5591 5592 optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 ); 5593 5594 } 5595 5596 if ( optionalPointOnSegment ) { 5597 5598 optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 ); 5599 5600 } 5601 5602 return sqrDist; 5603 5604 } 5605 5606 intersectSphere( sphere, target ) { 5607 5608 _vector$a.subVectors( sphere.center, this.origin ); 5609 const tca = _vector$a.dot( this.direction ); 5610 const d2 = _vector$a.dot( _vector$a ) - tca * tca; 5611 const radius2 = sphere.radius * sphere.radius; 5612 5613 if ( d2 > radius2 ) return null; 5614 5615 const thc = Math.sqrt( radius2 - d2 ); 5616 5617 // t0 = first intersect point - entrance on front of sphere 5618 const t0 = tca - thc; 5619 5620 // t1 = second intersect point - exit point on back of sphere 5621 const t1 = tca + thc; 5622 5623 // test to see if t1 is behind the ray - if so, return null 5624 if ( t1 < 0 ) return null; 5625 5626 // test to see if t0 is behind the ray: 5627 // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, 5628 // in order to always return an intersect point that is in front of the ray. 5629 if ( t0 < 0 ) return this.at( t1, target ); 5630 5631 // else t0 is in front of the ray, so return the first collision point scaled by t0 5632 return this.at( t0, target ); 5633 5634 } 5635 5636 intersectsSphere( sphere ) { 5637 5638 return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius ); 5639 5640 } 5641 5642 distanceToPlane( plane ) { 5643 5644 const denominator = plane.normal.dot( this.direction ); 5645 5646 if ( denominator === 0 ) { 5647 5648 // line is coplanar, return origin 5649 if ( plane.distanceToPoint( this.origin ) === 0 ) { 5650 5651 return 0; 5652 5653 } 5654 5655 // Null is preferable to undefined since undefined means.... it is undefined 5656 5657 return null; 5658 5659 } 5660 5661 const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; 5662 5663 // Return if the ray never intersects the plane 5664 5665 return t >= 0 ? t : null; 5666 5667 } 5668 5669 intersectPlane( plane, target ) { 5670 5671 const t = this.distanceToPlane( plane ); 5672 5673 if ( t === null ) { 5674 5675 return null; 5676 5677 } 5678 5679 return this.at( t, target ); 5680 5681 } 5682 5683 intersectsPlane( plane ) { 5684 5685 // check if the ray lies on the plane first 5686 5687 const distToPoint = plane.distanceToPoint( this.origin ); 5688 5689 if ( distToPoint === 0 ) { 5690 5691 return true; 5692 5693 } 5694 5695 const denominator = plane.normal.dot( this.direction ); 5696 5697 if ( denominator * distToPoint < 0 ) { 5698 5699 return true; 5700 5701 } 5702 5703 // ray origin is behind the plane (and is pointing behind it) 5704 5705 return false; 5706 5707 } 5708 5709 intersectBox( box, target ) { 5710 5711 let tmin, tmax, tymin, tymax, tzmin, tzmax; 5712 5713 const invdirx = 1 / this.direction.x, 5714 invdiry = 1 / this.direction.y, 5715 invdirz = 1 / this.direction.z; 5716 5717 const origin = this.origin; 5718 5719 if ( invdirx >= 0 ) { 5720 5721 tmin = ( box.min.x - origin.x ) * invdirx; 5722 tmax = ( box.max.x - origin.x ) * invdirx; 5723 5724 } else { 5725 5726 tmin = ( box.max.x - origin.x ) * invdirx; 5727 tmax = ( box.min.x - origin.x ) * invdirx; 5728 5729 } 5730 5731 if ( invdiry >= 0 ) { 5732 5733 tymin = ( box.min.y - origin.y ) * invdiry; 5734 tymax = ( box.max.y - origin.y ) * invdiry; 5735 5736 } else { 5737 5738 tymin = ( box.max.y - origin.y ) * invdiry; 5739 tymax = ( box.min.y - origin.y ) * invdiry; 5740 5741 } 5742 5743 if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; 5744 5745 if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin; 5746 5747 if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax; 5748 5749 if ( invdirz >= 0 ) { 5750 5751 tzmin = ( box.min.z - origin.z ) * invdirz; 5752 tzmax = ( box.max.z - origin.z ) * invdirz; 5753 5754 } else { 5755 5756 tzmin = ( box.max.z - origin.z ) * invdirz; 5757 tzmax = ( box.min.z - origin.z ) * invdirz; 5758 5759 } 5760 5761 if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; 5762 5763 if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; 5764 5765 if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; 5766 5767 //return point closest to the ray (positive side) 5768 5769 if ( tmax < 0 ) return null; 5770 5771 return this.at( tmin >= 0 ? tmin : tmax, target ); 5772 5773 } 5774 5775 intersectsBox( box ) { 5776 5777 return this.intersectBox( box, _vector$a ) !== null; 5778 5779 } 5780 5781 intersectTriangle( a, b, c, backfaceCulling, target ) { 5782 5783 // Compute the offset origin, edges, and normal. 5784 5785 // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h 5786 5787 _edge1.subVectors( b, a ); 5788 _edge2.subVectors( c, a ); 5789 _normal$1.crossVectors( _edge1, _edge2 ); 5790 5791 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, 5792 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by 5793 // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) 5794 // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) 5795 // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) 5796 let DdN = this.direction.dot( _normal$1 ); 5797 let sign; 5798 5799 if ( DdN > 0 ) { 5800 5801 if ( backfaceCulling ) return null; 5802 sign = 1; 5803 5804 } else if ( DdN < 0 ) { 5805 5806 sign = -
5806
vendor: 16,979 bytes, lines 5806-6624
58061; 5807 DdN = - DdN; 5808 5809 } else { 5810 5811 return null; 5812 5813 } 5814 5815 _diff.subVectors( this.origin, a ); 5816 const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) ); 5817 5818 // b1 < 0, no intersection 5819 if ( DdQxE2 < 0 ) { 5820 5821 return null; 5822 5823 } 5824 5825 const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) ); 5826 5827 // b2 < 0, no intersection 5828 if ( DdE1xQ < 0 ) { 5829 5830 return null; 5831 5832 } 5833 5834 // b1+b2 > 1, no intersection 5835 if ( DdQxE2 + DdE1xQ > DdN ) { 5836 5837 return null; 5838 5839 } 5840 5841 // Line intersects triangle, check if ray does. 5842 const QdN = - sign * _diff.dot( _normal$1 ); 5843 5844 // t < 0, no intersection 5845 if ( QdN < 0 ) { 5846 5847 return null; 5848 5849 } 5850 5851 // Ray intersects triangle. 5852 return this.at( QdN / DdN, target ); 5853 5854 } 5855 5856 applyMatrix4( matrix4 ) { 5857 5858 this.origin.applyMatrix4( matrix4 ); 5859 this.direction.transformDirection( matrix4 ); 5860 5861 return this; 5862 5863 } 5864 5865 equals( ray ) { 5866 5867 return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); 5868 5869 } 5870 5871 clone() { 5872 5873 return new this.constructor().copy( this ); 5874 5875 } 5876 5877} 5878 5879class Matrix4 { 5880 5881 constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { 5882 5883 Matrix4.prototype.isMatrix4 = true; 5884 5885 this.elements = [ 5886 5887 1, 0, 0, 0, 5888 0, 1, 0, 0, 5889 0, 0, 1, 0, 5890 0, 0, 0, 1 5891 5892 ]; 5893 5894 if ( n11 !== undefined ) { 5895 5896 this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ); 5897 5898 } 5899 5900 } 5901 5902 set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { 5903 5904 const te = this.elements; 5905 5906 te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14; 5907 te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24; 5908 te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34; 5909 te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44; 5910 5911 return this; 5912 5913 } 5914 5915 identity() { 5916 5917 this.set( 5918 5919 1, 0, 0, 0, 5920 0, 1, 0, 0, 5921 0, 0, 1, 0, 5922 0, 0, 0, 1 5923 5924 ); 5925 5926 return this; 5927 5928 } 5929 5930 clone() { 5931 5932 return new Matrix4().fromArray( this.elements ); 5933 5934 } 5935 5936 copy( m ) { 5937 5938 const te = this.elements; 5939 const me = m.elements; 5940 5941 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ]; 5942 te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; 5943 te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ]; 5944 te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ]; 5945 5946 return this; 5947 5948 } 5949 5950 copyPosition( m ) { 5951 5952 const te = this.elements, me = m.elements; 5953 5954 te[ 12 ] = me[ 12 ]; 5955 te[ 13 ] = me[ 13 ]; 5956 te[ 14 ] = me[ 14 ]; 5957 5958 return this; 5959 5960 } 5961 5962 setFromMatrix3( m ) { 5963 5964 const me = m.elements; 5965 5966 this.set( 5967 5968 me[ 0 ], me[ 3 ], me[ 6 ], 0, 5969 me[ 1 ], me[ 4 ], me[ 7 ], 0, 5970 me[ 2 ], me[ 5 ], me[ 8 ], 0, 5971 0, 0, 0, 1 5972 5973 ); 5974 5975 return this; 5976 5977 } 5978 5979 extractBasis( xAxis, yAxis, zAxis ) { 5980 5981 xAxis.setFromMatrixColumn( this, 0 ); 5982 yAxis.setFromMatrixColumn( this, 1 ); 5983 zAxis.setFromMatrixColumn( this, 2 ); 5984 5985 return this; 5986 5987 } 5988 5989 makeBasis( xAxis, yAxis, zAxis ) { 5990 5991 this.set( 5992 xAxis.x, yAxis.x, zAxis.x, 0, 5993 xAxis.y, yAxis.y, zAxis.y, 0, 5994 xAxis.z, yAxis.z, zAxis.z, 0, 5995 0, 0, 0, 1 5996 ); 5997 5998 return this; 5999 6000 } 6001 6002 extractRotation( m ) { 6003 6004 // this method does not support reflection matrices 6005 6006 const te = this.elements; 6007 const me = m.elements; 6008 6009 const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length(); 6010 const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length(); 6011 const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length(); 6012 6013 te[ 0 ] = me[ 0 ] * scaleX; 6014 te[ 1 ] = me[ 1 ] * scaleX; 6015 te[ 2 ] = me[ 2 ] * scaleX; 6016 te[ 3 ] = 0; 6017 6018 te[ 4 ] = me[ 4 ] * scaleY; 6019 te[ 5 ] = me[ 5 ] * scaleY; 6020 te[ 6 ] = me[ 6 ] * scaleY; 6021 te[ 7 ] = 0; 6022 6023 te[ 8 ] = me[ 8 ] * scaleZ; 6024 te[ 9 ] = me[ 9 ] * scaleZ; 6025 te[ 10 ] = me[ 10 ] * scaleZ; 6026 te[ 11 ] = 0; 6027 6028 te[ 12 ] = 0; 6029 te[ 13 ] = 0; 6030 te[ 14 ] = 0; 6031 te[ 15 ] = 1; 6032 6033 return this; 6034 6035 } 6036 6037 makeRotationFromEuler( euler ) { 6038 6039 const te = this.elements; 6040 6041 const x = euler.x, y = euler.y, z = euler.z; 6042 const a = Math.cos( x ), b = Math.sin( x ); 6043 const c = Math.cos( y ), d = Math.sin( y ); 6044 const e = Math.cos( z ), f = Math.sin( z ); 6045 6046 if ( euler.order === 'XYZ' ) { 6047 6048 const ae = a * e, af = a * f, be = b * e, bf = b * f; 6049 6050 te[ 0 ] = c * e; 6051 te[ 4 ] = - c * f; 6052 te[ 8 ] = d; 6053 6054 te[ 1 ] = af + be * d; 6055 te[ 5 ] = ae - bf * d; 6056 te[ 9 ] = - b * c; 6057 6058 te[ 2 ] = bf - ae * d; 6059 te[ 6 ] = be + af * d; 6060 te[ 10 ] = a * c; 6061 6062 } else if ( euler.order === 'YXZ' ) { 6063 6064 const ce = c * e, cf = c * f, de = d * e, df = d * f; 6065 6066 te[ 0 ] = ce + df * b; 6067 te[ 4 ] = de * b - cf; 6068 te[ 8 ] = a * d; 6069 6070 te[ 1 ] = a * f; 6071 te[ 5 ] = a * e; 6072 te[ 9 ] = - b; 6073 6074 te[ 2 ] = cf * b - de; 6075 te[ 6 ] = df + ce * b; 6076 te[ 10 ] = a * c; 6077 6078 } else if ( euler.order === 'ZXY' ) { 6079 6080 const ce = c * e, cf = c * f, de = d * e, df = d * f; 6081 6082 te[ 0 ] = ce - df * b; 6083 te[ 4 ] = - a * f; 6084 te[ 8 ] = de + cf * b; 6085 6086 te[ 1 ] = cf + de * b; 6087 te[ 5 ] = a * e; 6088 te[ 9 ] = df - ce * b; 6089 6090 te[ 2 ] = - a * d; 6091 te[ 6 ] = b; 6092 te[ 10 ] = a * c; 6093 6094 } else if ( euler.order === 'ZYX' ) { 6095 6096 const ae = a * e, af = a * f, be = b * e, bf = b * f; 6097 6098 te[ 0 ] = c * e; 6099 te[ 4 ] = be * d - af; 6100 te[ 8 ] = ae * d + bf; 6101 6102 te[ 1 ] = c * f; 6103 te[ 5 ] = bf * d + ae; 6104 te[ 9 ] = af * d - be; 6105 6106 te[ 2 ] = - d; 6107 te[ 6 ] = b * c; 6108 te[ 10 ] = a * c; 6109 6110 } else if ( euler.order === 'YZX' ) { 6111 6112 const ac = a * c, ad = a * d, bc = b * c, bd = b * d; 6113 6114 te[ 0 ] = c * e; 6115 te[ 4 ] = bd - ac * f; 6116 te[ 8 ] = bc * f + ad; 6117 6118 te[ 1 ] = f; 6119 te[ 5 ] = a * e; 6120 te[ 9 ] = - b * e; 6121 6122 te[ 2 ] = - d * e; 6123 te[ 6 ] = ad * f + bc; 6124 te[ 10 ] = ac - bd * f; 6125 6126 } else if ( euler.order === 'XZY' ) { 6127 6128 const ac = a * c, ad = a * d, bc = b * c, bd = b * d; 6129 6130 te[ 0 ] = c * e; 6131 te[ 4 ] = - f; 6132 te[ 8 ] = d * e; 6133 6134 te[ 1 ] = ac * f + bd; 6135 te[ 5 ] = a * e; 6136 te[ 9 ] = ad * f - bc; 6137 6138 te[ 2 ] = bc * f - ad; 6139 te[ 6 ] = b * e; 6140 te[ 10 ] = bd * f + ac; 6141 6142 } 6143 6144 // bottom row 6145 te[ 3 ] = 0; 6146 te[ 7 ] = 0; 6147 te[ 11 ] = 0; 6148 6149 // last column 6150 te[ 12 ] = 0; 6151 te[ 13 ] = 0; 6152 te[ 14 ] = 0; 6153 te[ 15 ] = 1; 6154 6155 return this; 6156 6157 } 6158 6159 makeRotationFromQuaternion( q ) { 6160 6161 return this.compose( _zero, q, _one ); 6162 6163 } 6164 6165 lookAt( eye, target, up ) { 6166 6167 const te = this.elements; 6168 6169 _z.subVectors( eye, target ); 6170 6171 if ( _z.lengthSq() === 0 ) { 6172 6173 // eye and target are in the same position 6174 6175 _z.z = 1; 6176 6177 } 6178 6179 _z.normalize(); 6180 _x.crossVectors( up, _z ); 6181 6182 if ( _x.lengthSq() === 0 ) { 6183 6184 // up and z are parallel 6185 6186 if ( Math.abs( up.z ) === 1 ) { 6187 6188 _z.x += 0.0001; 6189 6190 } else { 6191 6192 _z.z += 0.0001; 6193 6194 } 6195 6196 _z.normalize(); 6197 _x.crossVectors( up, _z ); 6198 6199 } 6200 6201 _x.normalize(); 6202 _y.crossVectors( _z, _x ); 6203 6204 te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x; 6205 te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y; 6206 te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z; 6207 6208 return this; 6209 6210 } 6211 6212 multiply( m ) { 6213 6214 return this.multiplyMatrices( this, m ); 6215 6216 } 6217 6218 premultiply( m ) { 6219 6220 return this.multiplyMatrices( m, this ); 6221 6222 } 6223 6224 multiplyMatrices( a, b ) { 6225 6226 const ae = a.elements; 6227 const be = b.elements; 6228 const te = this.elements; 6229 6230 const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ]; 6231 const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ]; 6232 const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ]; 6233 const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ]; 6234 6235 const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ]; 6236 const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ]; 6237 const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ]; 6238 const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ]; 6239 6240 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; 6241 te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; 6242 te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; 6243 te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; 6244 6245 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; 6246 te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; 6247 te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; 6248 te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; 6249 6250 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; 6251 te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; 6252 te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; 6253 te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; 6254 6255 te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; 6256 te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; 6257 te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; 6258 te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; 6259 6260 return this; 6261 6262 } 6263 6264 multiplyScalar( s ) { 6265 6266 const te = this.elements; 6267 6268 te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s; 6269 te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s; 6270 te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s; 6271 te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s; 6272 6273 return this; 6274 6275 } 6276 6277 determinant() { 6278 6279 const te = this.elements; 6280 6281 const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ]; 6282 const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ]; 6283 const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ]; 6284 const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ]; 6285 6286 //TODO: make this more efficient 6287 //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) 6288 6289 return ( 6290 n41 * ( 6291 + n14 * n23 * n32 6292 - n13 * n24 * n32 6293 - n14 * n22 * n33 6294 + n12 * n24 * n33 6295 + n13 * n22 * n34 6296 - n12 * n23 * n34 6297 ) + 6298 n42 * ( 6299 + n11 * n23 * n34 6300 - n11 * n24 * n33 6301 + n14 * n21 * n33 6302 - n13 * n21 * n34 6303 + n13 * n24 * n31 6304 - n14 * n23 * n31 6305 ) + 6306 n43 * ( 6307 + n11 * n24 * n32 6308 - n11 * n22 * n34 6309 - n14 * n21 * n32 6310 + n12 * n21 * n34 6311 + n14 * n22 * n31 6312 - n12 * n24 * n31 6313 ) + 6314 n44 * ( 6315 - n13 * n22 * n31 6316 - n11 * n23 * n32 6317 + n11 * n22 * n33 6318 + n13 * n21 * n32 6319 - n12 * n21 * n33 6320 + n12 * n23 * n31 6321 ) 6322 6323 ); 6324 6325 } 6326 6327 transpose() { 6328 6329 const te = this.elements; 6330 let tmp; 6331 6332 tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp; 6333 tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp; 6334 tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp; 6335 6336 tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp; 6337 tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp; 6338 tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp; 6339 6340 return this; 6341 6342 } 6343 6344 setPosition( x, y, z ) { 6345 6346 const te = this.elements; 6347 6348 if ( x.isVector3 ) { 6349 6350 te[ 12 ] = x.x; 6351 te[ 13 ] = x.y; 6352 te[ 14 ] = x.z; 6353 6354 } else { 6355 6356 te[ 12 ] = x; 6357 te[ 13 ] = y; 6358 te[ 14 ] = z; 6359 6360 } 6361 6362 return this; 6363 6364 } 6365 6366 invert() { 6367 6368 // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm 6369 const te = this.elements, 6370 6371 n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ], 6372 n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ], 6373 n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ], 6374 n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ], 6375 6376 t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44, 6377 t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44, 6378 t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44, 6379 t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34; 6380 6381 const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; 6382 6383 if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); 6384 6385 const detInv = 1 / det; 6386 6387 te[ 0 ] = t11 * detInv; 6388 te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv; 6389 te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv; 6390 te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv; 6391 6392 te[ 4 ] = t12 * detInv; 6393 te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv; 6394 te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv; 6395 te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv; 6396 6397 te[ 8 ] = t13 * detInv; 6398 te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv; 6399 te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv; 6400 te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv; 6401 6402 te[ 12 ] = t14 * detInv; 6403 te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv; 6404 te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv; 6405 te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv; 6406 6407 return this; 6408 6409 } 6410 6411 scale( v ) { 6412 6413 const te = this.elements; 6414 const x = v.x, y = v.y, z = v.z; 6415 6416 te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; 6417 te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; 6418 te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; 6419 te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; 6420 6421 return this; 6422 6423 } 6424 6425 getMaxScaleOnAxis() { 6426 6427 const te = this.elements; 6428 6429 const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ]; 6430 const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ]; 6431 const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ]; 6432 6433 return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); 6434 6435 } 6436 6437 makeTranslation( x, y, z ) { 6438 6439 if ( x.isVector3 ) { 6440 6441 this.set( 6442 6443 1, 0, 0, x.x, 6444 0, 1, 0, x.y, 6445 0, 0, 1, x.z, 6446 0, 0, 0, 1 6447 6448 ); 6449 6450 } else { 6451 6452 this.set( 6453 6454 1, 0, 0, x, 6455 0, 1, 0, y, 6456 0, 0, 1, z, 6457 0, 0, 0, 1 6458 6459 ); 6460 6461 } 6462 6463 return this; 6464 6465 } 6466 6467 makeRotationX( theta ) { 6468 6469 const c = Math.cos( theta ), s = Math.sin( theta ); 6470 6471 this.set( 6472 6473 1, 0, 0, 0, 6474 0, c, - s, 0, 6475 0, s, c, 0, 6476 0, 0, 0, 1 6477 6478 ); 6479 6480 return this; 6481 6482 } 6483 6484 makeRotationY( theta ) { 6485 6486 const c = Math.cos( theta ), s = Math.sin( theta ); 6487 6488 this.set( 6489 6490 c, 0, s, 0, 6491 0, 1, 0, 0, 6492 - s, 0, c, 0, 6493 0, 0, 0, 1 6494 6495 ); 6496 6497 return this; 6498 6499 } 6500 6501 makeRotationZ( theta ) { 6502 6503 const c = Math.cos( theta ), s = Math.sin( theta ); 6504 6505 this.set( 6506 6507 c, - s, 0, 0, 6508 s, c, 0, 0, 6509 0, 0, 1, 0, 6510 0, 0, 0, 1 6511 6512 ); 6513 6514 return this; 6515 6516 } 6517 6518 makeRotationAxis( axis, angle ) { 6519 6520 // Based on http://www.gamedev.net/reference/articles/article1199.asp 6521 6522 const c = Math.cos( angle ); 6523 const s = Math.sin( angle ); 6524 const t = 1 - c; 6525 const x = axis.x, y = axis.y, z = axis.z; 6526 const tx = t * x, ty = t * y; 6527 6528 this.set( 6529 6530 tx * x + c, tx * y - s * z, tx * z + s * y, 0, 6531 tx * y + s * z, ty * y + c, ty * z - s * x, 0, 6532 tx * z - s * y, ty * z + s * x, t * z * z + c, 0, 6533 0, 0, 0, 1 6534 6535 ); 6536 6537 return this; 6538 6539 } 6540 6541 makeScale( x, y, z ) { 6542 6543 this.set( 6544 6545 x, 0, 0, 0, 6546 0, y, 0, 0, 6547 0, 0, z, 0, 6548 0, 0, 0, 1 6549 6550 ); 6551 6552 return this; 6553 6554 } 6555 6556 makeShear( xy, xz, yx, yz, zx, zy ) { 6557 6558 this.set( 6559 6560 1, yx, zx, 0, 6561 xy, 1, zy, 0, 6562 xz, yz, 1, 0, 6563 0, 0, 0, 1 6564 6565 ); 6566 6567 return this; 6568 6569 } 6570 6571 compose( position, quaternion, scale ) { 6572 6573 const te = this.elements; 6574 6575 const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w; 6576 const x2 = x + x, y2 = y + y, z2 = z + z; 6577 const xx = x * x2, xy = x * y2, xz = x * z2; 6578 const yy = y * y2, yz = y * z2, zz = z * z2; 6579 const wx = w * x2, wy = w * y2, wz = w * z2; 6580 6581 const sx = scale.x, sy = scale.y, sz = scale.z; 6582 6583 te[ 0 ] = ( 1 - ( yy + zz ) ) * sx; 6584 te[ 1 ] = ( xy + wz ) * sx; 6585 te[ 2 ] = ( xz - wy ) * sx; 6586 te[ 3 ] = 0; 6587 6588 te[ 4 ] = ( xy - wz ) * sy; 6589 te[ 5 ] = ( 1 - ( xx + zz ) ) * sy; 6590 te[ 6 ] = ( yz + wx ) * sy; 6591 te[ 7 ] = 0; 6592 6593 te[ 8 ] = ( xz + wy ) * sz; 6594 te[ 9 ] = ( yz - wx ) * sz; 6595 te[ 10 ] = ( 1 - ( xx + yy ) ) * sz; 6596 te[ 11 ] = 0; 6597 6598 te[ 12 ] = position.x; 6599 te[ 13 ] = position.y; 6600 te[ 14 ] = position.z; 6601 te[ 15 ] = 1; 6602 6603 return this; 6604 6605 } 6606 6607 decompose( position, quaternion, scale ) { 6608 6609 const te = this.elements; 6610 6611 let sx = _v1$5.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); 6612 const sy = _v1$5.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); 6613 const sz = _v1$5.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); 6614 6615 // if determine is negative, we need to invert one scale 6616 const det = this.determinant(); 6617 if ( det < 0 ) sx = - sx; 6618 6619 position.x = te[ 12 ]; 6620 position.y = te[ 13 ]; 6621 position.z = te[ 14 ]; 6622 6623 // scale the rotation part 6624 _m1$
vendor: 16,143 bytes, lines 6624-7569
66242.copy( this ); 6625 6626 const invSX = 1 / sx; 6627 const invSY = 1 / sy; 6628 const invSZ = 1 / sz; 6629 6630 _m1$2.elements[ 0 ] *= invSX; 6631 _m1$2.elements[ 1 ] *= invSX; 6632 _m1$2.elements[ 2 ] *= invSX; 6633 6634 _m1$2.elements[ 4 ] *= invSY; 6635 _m1$2.elements[ 5 ] *= invSY; 6636 _m1$2.elements[ 6 ] *= invSY; 6637 6638 _m1$2.elements[ 8 ] *= invSZ; 6639 _m1$2.elements[ 9 ] *= invSZ; 6640 _m1$2.elements[ 10 ] *= invSZ; 6641 6642 quaternion.setFromRotationMatrix( _m1$2 ); 6643 6644 scale.x = sx; 6645 scale.y = sy; 6646 scale.z = sz; 6647 6648 return this; 6649 6650 } 6651 6652 makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { 6653 6654 const te = this.elements; 6655 const x = 2 * near / ( right - left ); 6656 const y = 2 * near / ( top - bottom ); 6657 6658 const a = ( right + left ) / ( right - left ); 6659 const b = ( top + bottom ) / ( top - bottom ); 6660 6661 let c, d; 6662 6663 if ( coordinateSystem === WebGLCoordinateSystem ) { 6664 6665 c = - ( far + near ) / ( far - near ); 6666 d = ( - 2 * far * near ) / ( far - near ); 6667 6668 } else if ( coordinateSystem === WebGPUCoordinateSystem ) { 6669 6670 c = - far / ( far - near ); 6671 d = ( - far * near ) / ( far - near ); 6672 6673 } else { 6674 6675 throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem ); 6676 6677 } 6678 6679 te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; 6680 te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; 6681 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; 6682 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; 6683 6684 return this; 6685 6686 } 6687 6688 makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { 6689 6690 const te = this.elements; 6691 const w = 1.0 / ( right - left ); 6692 const h = 1.0 / ( top - bottom ); 6693 const p = 1.0 / ( far - near ); 6694 6695 const x = ( right + left ) * w; 6696 const y = ( top + bottom ) * h; 6697 6698 let z, zInv; 6699 6700 if ( coordinateSystem === WebGLCoordinateSystem ) { 6701 6702 z = ( far + near ) * p; 6703 zInv = - 2 * p; 6704 6705 } else if ( coordinateSystem === WebGPUCoordinateSystem ) { 6706 6707 z = near * p; 6708 zInv = - 1 * p; 6709 6710 } else { 6711 6712 throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem ); 6713 6714 } 6715 6716 te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; 6717 te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; 6718 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = zInv; te[ 14 ] = - z; 6719 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; 6720 6721 return this; 6722 6723 } 6724 6725 equals( matrix ) { 6726 6727 const te = this.elements; 6728 const me = matrix.elements; 6729 6730 for ( let i = 0; i < 16; i ++ ) { 6731 6732 if ( te[ i ] !== me[ i ] ) return false; 6733 6734 } 6735 6736 return true; 6737 6738 } 6739 6740 fromArray( array, offset = 0 ) { 6741 6742 for ( let i = 0; i < 16; i ++ ) { 6743 6744 this.elements[ i ] = array[ i + offset ]; 6745 6746 } 6747 6748 return this; 6749 6750 } 6751 6752 toArray( array = [], offset = 0 ) { 6753 6754 const te = this.elements; 6755 6756 array[ offset ] = te[ 0 ]; 6757 array[ offset + 1 ] = te[ 1 ]; 6758 array[ offset + 2 ] = te[ 2 ]; 6759 array[ offset + 3 ] = te[ 3 ]; 6760 6761 array[ offset + 4 ] = te[ 4 ]; 6762 array[ offset + 5 ] = te[ 5 ]; 6763 array[ offset + 6 ] = te[ 6 ]; 6764 array[ offset + 7 ] = te[ 7 ]; 6765 6766 array[ offset + 8 ] = te[ 8 ]; 6767 array[ offset + 9 ] = te[ 9 ]; 6768 array[ offset + 10 ] = te[ 10 ]; 6769 array[ offset + 11 ] = te[ 11 ]; 6770 6771 array[ offset + 12 ] = te[ 12 ]; 6772 array[ offset + 13 ] = te[ 13 ]; 6773 array[ offset + 14 ] = te[ 14 ]; 6774 array[ offset + 15 ] = te[ 15 ]; 6775 6776 return array; 6777 6778 } 6779 6780} 6781 6782const _v1$5 = /*@__PURE__*/ new Vector3(); 6783const _m1$2 = /*@__PURE__*/ new Matrix4(); 6784const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 ); 6785const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 ); 6786const _x = /*@__PURE__*/ new Vector3(); 6787const _y = /*@__PURE__*/ new Vector3(); 6788const _z = /*@__PURE__*/ new Vector3(); 6789 6790const _matrix$1 = /*@__PURE__*/ new Matrix4(); 6791const _quaternion$3 = /*@__PURE__*/ new Quaternion(); 6792 6793class Euler { 6794 6795 constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) { 6796 6797 this.isEuler = true; 6798 6799 this._x = x; 6800 this._y = y; 6801 this._z = z; 6802 this._order = order; 6803 6804 } 6805 6806 get x() { 6807 6808 return this._x; 6809 6810 } 6811 6812 set x( value ) { 6813 6814 this._x = value; 6815 this._onChangeCallback(); 6816 6817 } 6818 6819 get y() { 6820 6821 return this._y; 6822 6823 } 6824 6825 set y( value ) { 6826 6827 this._y = value; 6828 this._onChangeCallback(); 6829 6830 } 6831 6832 get z() { 6833 6834 return this._z; 6835 6836 } 6837 6838 set z( value ) { 6839 6840 this._z = value; 6841 this._onChangeCallback(); 6842 6843 } 6844 6845 get order() { 6846 6847 return this._order; 6848 6849 } 6850 6851 set order( value ) { 6852 6853 this._order = value; 6854 this._onChangeCallback(); 6855 6856 } 6857 6858 set( x, y, z, order = this._order ) { 6859 6860 this._x = x; 6861 this._y = y; 6862 this._z = z; 6863 this._order = order; 6864 6865 this._onChangeCallback(); 6866 6867 return this; 6868 6869 } 6870 6871 clone() { 6872 6873 return new this.constructor( this._x, this._y, this._z, this._order ); 6874 6875 } 6876 6877 copy( euler ) { 6878 6879 this._x = euler._x; 6880 this._y = euler._y; 6881 this._z = euler._z; 6882 this._order = euler._order; 6883 6884 this._onChangeCallback(); 6885 6886 return this; 6887 6888 } 6889 6890 setFromRotationMatrix( m, order = this._order, update = true ) { 6891 6892 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 6893 6894 const te = m.elements; 6895 const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ]; 6896 const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ]; 6897 const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; 6898 6899 switch ( order ) { 6900 6901 case 'XYZ': 6902 6903 this._y = Math.asin( clamp( m13, - 1, 1 ) ); 6904 6905 if ( Math.abs( m13 ) < 0.9999999 ) { 6906 6907 this._x = Math.atan2( - m23, m33 ); 6908 this._z = Math.atan2( - m12, m11 ); 6909 6910 } else { 6911 6912 this._x = Math.atan2( m32, m22 ); 6913 this._z = 0; 6914 6915 } 6916 6917 break; 6918 6919 case 'YXZ': 6920 6921 this._x = Math.asin( - clamp( m23, - 1, 1 ) ); 6922 6923 if ( Math.abs( m23 ) < 0.9999999 ) { 6924 6925 this._y = Math.atan2( m13, m33 ); 6926 this._z = Math.atan2( m21, m22 ); 6927 6928 } else { 6929 6930 this._y = Math.atan2( - m31, m11 ); 6931 this._z = 0; 6932 6933 } 6934 6935 break; 6936 6937 case 'ZXY': 6938 6939 this._x = Math.asin( clamp( m32, - 1, 1 ) ); 6940 6941 if ( Math.abs( m32 ) < 0.9999999 ) { 6942 6943 this._y = Math.atan2( - m31, m33 ); 6944 this._z = Math.atan2( - m12, m22 ); 6945 6946 } else { 6947 6948 this._y = 0; 6949 this._z = Math.atan2( m21, m11 ); 6950 6951 } 6952 6953 break; 6954 6955 case 'ZYX': 6956 6957 this._y = Math.asin( - clamp( m31, - 1, 1 ) ); 6958 6959 if ( Math.abs( m31 ) < 0.9999999 ) { 6960 6961 this._x = Math.atan2( m32, m33 ); 6962 this._z = Math.atan2( m21, m11 ); 6963 6964 } else { 6965 6966 this._x = 0; 6967 this._z = Math.atan2( - m12, m22 ); 6968 6969 } 6970 6971 break; 6972 6973 case 'YZX': 6974 6975 this._z = Math.asin( clamp( m21, - 1, 1 ) ); 6976 6977 if ( Math.abs( m21 ) < 0.9999999 ) { 6978 6979 this._x = Math.atan2( - m23, m22 ); 6980 this._y = Math.atan2( - m31, m11 ); 6981 6982 } else { 6983 6984 this._x = 0; 6985 this._y = Math.atan2( m13, m33 ); 6986 6987 } 6988 6989 break; 6990 6991 case 'XZY': 6992 6993 this._z = Math.asin( - clamp( m12, - 1, 1 ) ); 6994 6995 if ( Math.abs( m12 ) < 0.9999999 ) { 6996 6997 this._x = Math.atan2( m32, m22 ); 6998 this._y = Math.atan2( m13, m11 ); 6999 7000 } else { 7001 7002 this._x = Math.atan2( - m23, m33 ); 7003 this._y = 0; 7004 7005 } 7006 7007 break; 7008 7009 default: 7010 7011 console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order ); 7012 7013 } 7014 7015 this._order = order; 7016 7017 if ( update === true ) this._onChangeCallback(); 7018 7019 return this; 7020 7021 } 7022 7023 setFromQuaternion( q, order, update ) { 7024 7025 _matrix$1.makeRotationFromQuaternion( q ); 7026 7027 return this.setFromRotationMatrix( _matrix$1, order, update ); 7028 7029 } 7030 7031 setFromVector3( v, order = this._order ) { 7032 7033 return this.set( v.x, v.y, v.z, order ); 7034 7035 } 7036 7037 reorder( newOrder ) { 7038 7039 // WARNING: this discards revolution information -bhouston 7040 7041 _quaternion$3.setFromEuler( this ); 7042 7043 return this.setFromQuaternion( _quaternion$3, newOrder ); 7044 7045 } 7046 7047 equals( euler ) { 7048 7049 return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); 7050 7051 } 7052 7053 fromArray( array ) { 7054 7055 this._x = array[ 0 ]; 7056 this._y = array[ 1 ]; 7057 this._z = array[ 2 ]; 7058 if ( array[ 3 ] !== undefined ) this._order = array[ 3 ]; 7059 7060 this._onChangeCallback(); 7061 7062 return this; 7063 7064 } 7065 7066 toArray( array = [], offset = 0 ) { 7067 7068 array[ offset ] = this._x; 7069 array[ offset + 1 ] = this._y; 7070 array[ offset + 2 ] = this._z; 7071 array[ offset + 3 ] = this._order; 7072 7073 return array; 7074 7075 } 7076 7077 _onChange( callback ) { 7078 7079 this._onChangeCallback = callback; 7080 7081 return this; 7082 7083 } 7084 7085 _onChangeCallback() {} 7086 7087 *[ Symbol.iterator ]() { 7088 7089 yield this._x; 7090 yield this._y; 7091 yield this._z; 7092 yield this._order; 7093 7094 } 7095 7096} 7097 7098Euler.DEFAULT_ORDER = 'XYZ'; 7099 7100class Layers { 7101 7102 constructor() { 7103 7104 this.mask = 1 | 0; 7105 7106 } 7107 7108 set( channel ) { 7109 7110 this.mask = ( 1 << channel | 0 ) >>> 0; 7111 7112 } 7113 7114 enable( channel ) { 7115 7116 this.mask |= 1 << channel | 0; 7117 7118 } 7119 7120 enableAll() { 7121 7122 this.mask = 0xffffffff | 0; 7123 7124 } 7125 7126 toggle( channel ) { 7127 7128 this.mask ^= 1 << channel | 0; 7129 7130 } 7131 7132 disable( channel ) { 7133 7134 this.mask &= ~ ( 1 << channel | 0 ); 7135 7136 } 7137 7138 disableAll() { 7139 7140 this.mask = 0; 7141 7142 } 7143 7144 test( layers ) { 7145 7146 return ( this.mask & layers.mask ) !== 0; 7147 7148 } 7149 7150 isEnabled( channel ) { 7151 7152 return ( this.mask & ( 1 << channel | 0 ) ) !== 0; 7153 7154 } 7155 7156} 7157 7158let _object3DId = 0; 7159 7160const _v1$4 = /*@__PURE__*/ new Vector3(); 7161const _q1 = /*@__PURE__*/ new Quaternion(); 7162const _m1$1 = /*@__PURE__*/ new Matrix4(); 7163const _target = /*@__PURE__*/ new Vector3(); 7164 7165const _position$3 = /*@__PURE__*/ new Vector3(); 7166const _scale$2 = /*@__PURE__*/ new Vector3(); 7167const _quaternion$2 = /*@__PURE__*/ new Quaternion(); 7168 7169const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 ); 7170const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 ); 7171const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 ); 7172 7173const _addedEvent = { type: 'added' }; 7174const _removedEvent = { type: 'removed' }; 7175 7176class Object3D extends EventDispatcher { 7177 7178 constructor() { 7179 7180 super(); 7181 7182 this.isObject3D = true; 7183 7184 Object.defineProperty( this, 'id', { value: _object3DId ++ } ); 7185 7186 this.uuid = generateUUID(); 7187 7188 this.name = ''; 7189 this.type = 'Object3D'; 7190 7191 this.parent = null; 7192 this.children = []; 7193 7194 this.up = Object3D.DEFAULT_UP.clone(); 7195 7196 const position = new Vector3(); 7197 const rotation = new Euler(); 7198 const quaternion = new Quaternion(); 7199 const scale = new Vector3( 1, 1, 1 ); 7200 7201 function onRotationChange() { 7202 7203 quaternion.setFromEuler( rotation, false ); 7204 7205 } 7206 7207 function onQuaternionChange() { 7208 7209 rotation.setFromQuaternion( quaternion, undefined, false ); 7210 7211 } 7212 7213 rotation._onChange( onRotationChange ); 7214 quaternion._onChange( onQuaternionChange ); 7215 7216 Object.defineProperties( this, { 7217 position: { 7218 configurable: true, 7219 enumerable: true, 7220 value: position 7221 }, 7222 rotation: { 7223 configurable: true, 7224 enumerable: true, 7225 value: rotation 7226 }, 7227 quaternion: { 7228 configurable: true, 7229 enumerable: true, 7230 value: quaternion 7231 }, 7232 scale: { 7233 configurable: true, 7234 enumerable: true, 7235 value: scale 7236 }, 7237 modelViewMatrix: { 7238 value: new Matrix4() 7239 }, 7240 normalMatrix: { 7241 value: new Matrix3() 7242 } 7243 } ); 7244 7245 this.matrix = new Matrix4(); 7246 this.matrixWorld = new Matrix4(); 7247 7248 this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE; 7249 7250 this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer 7251 this.matrixWorldNeedsUpdate = false; 7252 7253 this.layers = new Layers(); 7254 this.visible = true; 7255 7256 this.castShadow = false; 7257 this.receiveShadow = false; 7258 7259 this.frustumCulled = true; 7260 this.renderOrder = 0; 7261 7262 this.animations = []; 7263 7264 this.userData = {}; 7265 7266 } 7267 7268 onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} 7269 7270 onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} 7271 7272 onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {} 7273 7274 onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {} 7275 7276 applyMatrix4( matrix ) { 7277 7278 if ( this.matrixAutoUpdate ) this.updateMatrix(); 7279 7280 this.matrix.premultiply( matrix ); 7281 7282 this.matrix.decompose( this.position, this.quaternion, this.scale ); 7283 7284 } 7285 7286 applyQuaternion( q ) { 7287 7288 this.quaternion.premultiply( q ); 7289 7290 return this; 7291 7292 } 7293 7294 setRotationFromAxisAngle( axis, angle ) { 7295 7296 // assumes axis is normalized 7297 7298 this.quaternion.setFromAxisAngle( axis, angle ); 7299 7300 } 7301 7302 setRotationFromEuler( euler ) { 7303 7304 this.quaternion.setFromEuler( euler, true ); 7305 7306 } 7307 7308 setRotationFromMatrix( m ) { 7309 7310 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 7311 7312 this.quaternion.setFromRotationMatrix( m ); 7313 7314 } 7315 7316 setRotationFromQuaternion( q ) { 7317 7318 // assumes q is normalized 7319 7320 this.quaternion.copy( q ); 7321 7322 } 7323 7324 rotateOnAxis( axis, angle ) { 7325 7326 // rotate object on axis in object space 7327 // axis is assumed to be normalized 7328 7329 _q1.setFromAxisAngle( axis, angle ); 7330 7331 this.quaternion.multiply( _q1 ); 7332 7333 return this; 7334 7335 } 7336 7337 rotateOnWorldAxis( axis, angle ) { 7338 7339 // rotate object on axis in world space 7340 // axis is assumed to be normalized 7341 // method assumes no rotated parent 7342 7343 _q1.setFromAxisAngle( axis, angle ); 7344 7345 this.quaternion.premultiply( _q1 ); 7346 7347 return this; 7348 7349 } 7350 7351 rotateX( angle ) { 7352 7353 return this.rotateOnAxis( _xAxis, angle ); 7354 7355 } 7356 7357 rotateY( angle ) { 7358 7359 return this.rotateOnAxis( _yAxis, angle ); 7360 7361 } 7362 7363 rotateZ( angle ) { 7364 7365 return this.rotateOnAxis( _zAxis, angle ); 7366 7367 } 7368 7369 translateOnAxis( axis, distance ) { 7370 7371 // translate object by distance along axis in object space 7372 // axis is assumed to be normalized 7373 7374 _v1$4.copy( axis ).applyQuaternion( this.quaternion ); 7375 7376 this.position.add( _v1$4.multiplyScalar( distance ) ); 7377 7378 return this; 7379 7380 } 7381 7382 translateX( distance ) { 7383 7384 return this.translateOnAxis( _xAxis, distance ); 7385 7386 } 7387 7388 translateY( distance ) { 7389 7390 return this.translateOnAxis( _yAxis, distance ); 7391 7392 } 7393 7394 translateZ( distance ) { 7395 7396 return this.translateOnAxis( _zAxis, distance ); 7397 7398 } 7399 7400 localToWorld( vector ) { 7401 7402 this.updateWorldMatrix( true, false ); 7403 7404 return vector.applyMatrix4( this.matrixWorld ); 7405 7406 } 7407 7408 worldToLocal( vector ) { 7409 7410 this.updateWorldMatrix( true, false ); 7411 7412 return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() ); 7413 7414 } 7415 7416 lookAt( x, y, z ) { 7417 7418 // This method does not support objects having non-uniformly-scaled parent(s) 7419 7420 if ( x.isVector3 ) { 7421 7422 _target.copy( x ); 7423 7424 } else { 7425 7426 _target.set( x, y, z ); 7427 7428 } 7429 7430 const parent = this.parent; 7431 7432 this.updateWorldMatrix( true, false ); 7433 7434 _position$3.setFromMatrixPosition( this.matrixWorld ); 7435 7436 if ( this.isCamera || this.isLight ) { 7437 7438 _m1$1.lookAt( _position$3, _target, this.up ); 7439 7440 } else { 7441 7442 _m1$1.lookAt( _target, _position$3, this.up ); 7443 7444 } 7445 7446 this.quaternion.setFromRotationMatrix( _m1$1 ); 7447 7448 if ( parent ) { 7449 7450 _m1$1.extractRotation( parent.matrixWorld ); 7451 _q1.setFromRotationMatrix( _m1$1 ); 7452 this.quaternion.premultiply( _q1.invert() ); 7453 7454 } 7455 7456 } 7457 7458 add( object ) { 7459 7460 if ( arguments.length > 1 ) { 7461 7462 for ( let i = 0; i < arguments.length; i ++ ) { 7463 7464 this.add( arguments[ i ] ); 7465 7466 } 7467 7468 return this; 7469 7470 } 7471 7472 if ( object === this ) { 7473 7474 console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object ); 7475 return this; 7476 7477 } 7478 7479 if ( object && object.isObject3D ) { 7480 7481 if ( object.parent !== null ) { 7482 7483 object.parent.remove( object ); 7484 7485 } 7486 7487 object.parent = this; 7488 this.children.push( object ); 7489 7490 object.dispatchEvent( _addedEvent ); 7491 7492 } else { 7493 7494 console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object ); 7495 7496 } 7497 7498 return this; 7499 7500 } 7501 7502 remove( object ) { 7503 7504 if ( arguments.length > 1 ) { 7505 7506 for ( let i = 0; i < arguments.length; i ++ ) { 7507 7508 this.remove( arguments[ i ] ); 7509 7510 } 7511 7512 return this; 7513 7514 } 7515 7516 const index = this.children.indexOf( object ); 7517 7518 if ( index !== - 1 ) { 7519 7520 object.parent = null; 7521 this.children.splice( index, 1 ); 7522 7523 object.dispatchEvent( _removedEvent ); 7524 7525 } 7526 7527 return this; 7528 7529 } 7530 7531 removeFromParent() { 7532 7533 const parent = this.parent; 7534 7535 if ( parent !== null ) { 7536 7537 parent.remove( this ); 7538 7539 } 7540 7541 return this; 7542 7543 } 7544 7545 clear() { 7546 7547 return this.remove( ... this.children ); 7548 7549 } 7550 7551 attach( object ) { 7552 7553 // adds object as a child of this, while maintaining the object's world transform 7554 7555 // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s) 7556 7557 this.updateWorldMatrix( true, false ); 7558 7559 _m1$1.copy( this.matrixWorld ).invert(); 7560 7561 if ( object.parent !== null ) { 7562 7563 object.parent.updateWorldMatrix( true, false ); 7564 7565 _m1$1.multiply( object.parent.matrixWorld ); 7566 7567 } 7568 7569 object.applyMatrix4( _m1$1
vendor: 11,708 bytes, lines 7569-8159
7569 ); 7570 7571 this.add( object ); 7572 7573 object.updateWorldMatrix( false, true ); 7574 7575 return this; 7576 7577 } 7578 7579 getObjectById( id ) { 7580 7581 return this.getObjectByProperty( 'id', id ); 7582 7583 } 7584 7585 getObjectByName( name ) { 7586 7587 return this.getObjectByProperty( 'name', name ); 7588 7589 } 7590 7591 getObjectByProperty( name, value ) { 7592 7593 if ( this[ name ] === value ) return this; 7594 7595 for ( let i = 0, l = this.children.length; i < l; i ++ ) { 7596 7597 const child = this.children[ i ]; 7598 const object = child.getObjectByProperty( name, value ); 7599 7600 if ( object !== undefined ) { 7601 7602 return object; 7603 7604 } 7605 7606 } 7607 7608 return undefined; 7609 7610 } 7611 7612 getObjectsByProperty( name, value, result = [] ) { 7613 7614 if ( this[ name ] === value ) result.push( this ); 7615 7616 const children = this.children; 7617 7618 for ( let i = 0, l = children.length; i < l; i ++ ) { 7619 7620 children[ i ].getObjectsByProperty( name, value, result ); 7621 7622 } 7623 7624 return result; 7625 7626 } 7627 7628 getWorldPosition( target ) { 7629 7630 this.updateWorldMatrix( true, false ); 7631 7632 return target.setFromMatrixPosition( this.matrixWorld ); 7633 7634 } 7635 7636 getWorldQuaternion( target ) { 7637 7638 this.updateWorldMatrix( true, false ); 7639 7640 this.matrixWorld.decompose( _position$3, target, _scale$2 ); 7641 7642 return target; 7643 7644 } 7645 7646 getWorldScale( target ) { 7647 7648 this.updateWorldMatrix( true, false ); 7649 7650 this.matrixWorld.decompose( _position$3, _quaternion$2, target ); 7651 7652 return target; 7653 7654 } 7655 7656 getWorldDirection( target ) { 7657 7658 this.updateWorldMatrix( true, false ); 7659 7660 const e = this.matrixWorld.elements; 7661 7662 return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize(); 7663 7664 } 7665 7666 raycast( /* raycaster, intersects */ ) {} 7667 7668 traverse( callback ) { 7669 7670 callback( this ); 7671 7672 const children = this.children; 7673 7674 for ( let i = 0, l = children.length; i < l; i ++ ) { 7675 7676 children[ i ].traverse( callback ); 7677 7678 } 7679 7680 } 7681 7682 traverseVisible( callback ) { 7683 7684 if ( this.visible === false ) return; 7685 7686 callback( this ); 7687 7688 const children = this.children; 7689 7690 for ( let i = 0, l = children.length; i < l; i ++ ) { 7691 7692 children[ i ].traverseVisible( callback ); 7693 7694 } 7695 7696 } 7697 7698 traverseAncestors( callback ) { 7699 7700 const parent = this.parent; 7701 7702 if ( parent !== null ) { 7703 7704 callback( parent ); 7705 7706 parent.traverseAncestors( callback ); 7707 7708 } 7709 7710 } 7711 7712 updateMatrix() { 7713 7714 this.matrix.compose( this.position, this.quaternion, this.scale ); 7715 7716 this.matrixWorldNeedsUpdate = true; 7717 7718 } 7719 7720 updateMatrixWorld( force ) { 7721 7722 if ( this.matrixAutoUpdate ) this.updateMatrix(); 7723 7724 if ( this.matrixWorldNeedsUpdate || force ) { 7725 7726 if ( this.parent === null ) { 7727 7728 this.matrixWorld.copy( this.matrix ); 7729 7730 } else { 7731 7732 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); 7733 7734 } 7735 7736 this.matrixWorldNeedsUpdate = false; 7737 7738 force = true; 7739 7740 } 7741 7742 // update children 7743 7744 const children = this.children; 7745 7746 for ( let i = 0, l = children.length; i < l; i ++ ) { 7747 7748 const child = children[ i ]; 7749 7750 if ( child.matrixWorldAutoUpdate === true || force === true ) { 7751 7752 child.updateMatrixWorld( force ); 7753 7754 } 7755 7756 } 7757 7758 } 7759 7760 updateWorldMatrix( updateParents, updateChildren ) { 7761 7762 const parent = this.parent; 7763 7764 if ( updateParents === true && parent !== null && parent.matrixWorldAutoUpdate === true ) { 7765 7766 parent.updateWorldMatrix( true, false ); 7767 7768 } 7769 7770 if ( this.matrixAutoUpdate ) this.updateMatrix(); 7771 7772 if ( this.parent === null ) { 7773 7774 this.matrixWorld.copy( this.matrix ); 7775 7776 } else { 7777 7778 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); 7779 7780 } 7781 7782 // update children 7783 7784 if ( updateChildren === true ) { 7785 7786 const children = this.children; 7787 7788 for ( let i = 0, l = children.length; i < l; i ++ ) { 7789 7790 const child = children[ i ]; 7791 7792 if ( child.matrixWorldAutoUpdate === true ) { 7793 7794 child.updateWorldMatrix( false, true ); 7795 7796 } 7797 7798 } 7799 7800 } 7801 7802 } 7803 7804 toJSON( meta ) { 7805 7806 // meta is a string when called from JSON.stringify 7807 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 7808 7809 const output = {}; 7810 7811 // meta is a hash used to collect geometries, materials. 7812 // not providing it implies that this is the root object 7813 // being serialized. 7814 if ( isRootObject ) { 7815 7816 // initialize meta obj 7817 meta = { 7818 geometries: {}, 7819 materials: {}, 7820 textures: {}, 7821 images: {}, 7822 shapes: {}, 7823 skeletons: {}, 7824 animations: {}, 7825 nodes: {} 7826 }; 7827 7828 output.metadata = { 7829 version: 4.6, 7830 type: 'Object', 7831 generator: 'Object3D.toJSON' 7832 }; 7833 7834 } 7835 7836 // standard Object3D serialization 7837 7838 const object = {}; 7839 7840 object.uuid = this.uuid; 7841 object.type = this.type; 7842 7843 if ( this.name !== '' ) object.name = this.name; 7844 if ( this.castShadow === true ) object.castShadow = true; 7845 if ( this.receiveShadow === true ) object.receiveShadow = true; 7846 if ( this.visible === false ) object.visible = false; 7847 if ( this.frustumCulled === false ) object.frustumCulled = false; 7848 if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder; 7849 if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData; 7850 7851 object.layers = this.layers.mask; 7852 object.matrix = this.matrix.toArray(); 7853 object.up = this.up.toArray(); 7854 7855 if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; 7856 7857 // object specific properties 7858 7859 if ( this.isInstancedMesh ) { 7860 7861 object.type = 'InstancedMesh'; 7862 object.count = this.count; 7863 object.instanceMatrix = this.instanceMatrix.toJSON(); 7864 if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON(); 7865 7866 } 7867 7868 if ( this.isBatchedMesh ) { 7869 7870 object.type = 'BatchedMesh'; 7871 object.perObjectFrustumCulled = this.perObjectFrustumCulled; 7872 object.sortObjects = this.sortObjects; 7873 7874 object.drawRanges = this._drawRanges; 7875 object.reservedRanges = this._reservedRanges; 7876 7877 object.visibility = this._visibility; 7878 object.active = this._active; 7879 object.bounds = this._bounds.map( bound => ( { 7880 boxInitialized: bound.boxInitialized, 7881 boxMin: bound.box.min.toArray(), 7882 boxMax: bound.box.max.toArray(), 7883 7884 sphereInitialized: bound.sphereInitialized, 7885 sphereRadius: bound.sphere.radius, 7886 sphereCenter: bound.sphere.center.toArray() 7887 } ) ); 7888 7889 object.maxGeometryCount = this._maxGeometryCount; 7890 object.maxVertexCount = this._maxVertexCount; 7891 object.maxIndexCount = this._maxIndexCount; 7892 7893 object.geometryInitialized = this._geometryInitialized; 7894 object.geometryCount = this._geometryCount; 7895 7896 object.matricesTexture = this._matricesTexture.toJSON( meta ); 7897 7898 if ( this.boundingSphere !== null ) { 7899 7900 object.boundingSphere = { 7901 center: object.boundingSphere.center.toArray(), 7902 radius: object.boundingSphere.radius 7903 }; 7904 7905 } 7906 7907 if ( this.boundingBox !== null ) { 7908 7909 object.boundingBox = { 7910 min: object.boundingBox.min.toArray(), 7911 max: object.boundingBox.max.toArray() 7912 }; 7913 7914 } 7915 7916 } 7917 7918 // 7919 7920 function serialize( library, element ) { 7921 7922 if ( library[ element.uuid ] === undefined ) { 7923 7924 library[ element.uuid ] = element.toJSON( meta ); 7925 7926 } 7927 7928 return element.uuid; 7929 7930 } 7931 7932 if ( this.isScene ) { 7933 7934 if ( this.background ) { 7935 7936 if ( this.background.isColor ) { 7937 7938 object.background = this.background.toJSON(); 7939 7940 } else if ( this.background.isTexture ) { 7941 7942 object.background = this.background.toJSON( meta ).uuid; 7943 7944 } 7945 7946 } 7947 7948 if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) { 7949 7950 object.environment = this.environment.toJSON( meta ).uuid; 7951 7952 } 7953 7954 } else if ( this.isMesh || this.isLine || this.isPoints ) { 7955 7956 object.geometry = serialize( meta.geometries, this.geometry ); 7957 7958 const parameters = this.geometry.parameters; 7959 7960 if ( parameters !== undefined && parameters.shapes !== undefined ) { 7961 7962 const shapes = parameters.shapes; 7963 7964 if ( Array.isArray( shapes ) ) { 7965 7966 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 7967 7968 const shape = shapes[ i ]; 7969 7970 serialize( meta.shapes, shape ); 7971 7972 } 7973 7974 } else { 7975 7976 serialize( meta.shapes, shapes ); 7977 7978 } 7979 7980 } 7981 7982 } 7983 7984 if ( this.isSkinnedMesh ) { 7985 7986 object.bindMode = this.bindMode; 7987 object.bindMatrix = this.bindMatrix.toArray(); 7988 7989 if ( this.skeleton !== undefined ) { 7990 7991 serialize( meta.skeletons, this.skeleton ); 7992 7993 object.skeleton = this.skeleton.uuid; 7994 7995 } 7996 7997 } 7998 7999 if ( this.material !== undefined ) { 8000 8001 if ( Array.isArray( this.material ) ) { 8002 8003 const uuids = []; 8004 8005 for ( let i = 0, l = this.material.length; i < l; i ++ ) { 8006 8007 uuids.push( serialize( meta.materials, this.material[ i ] ) ); 8008 8009 } 8010 8011 object.material = uuids; 8012 8013 } else { 8014 8015 object.material = serialize( meta.materials, this.material ); 8016 8017 } 8018 8019 } 8020 8021 // 8022 8023 if ( this.children.length > 0 ) { 8024 8025 object.children = []; 8026 8027 for ( let i = 0; i < this.children.length; i ++ ) { 8028 8029 object.children.push( this.children[ i ].toJSON( meta ).object ); 8030 8031 } 8032 8033 } 8034 8035 // 8036 8037 if ( this.animations.length > 0 ) { 8038 8039 object.animations = []; 8040 8041 for ( let i = 0; i < this.animations.length; i ++ ) { 8042 8043 const animation = this.animations[ i ]; 8044 8045 object.animations.push( serialize( meta.animations, animation ) ); 8046 8047 } 8048 8049 } 8050 8051 if ( isRootObject ) { 8052 8053 const geometries = extractFromCache( meta.geometries ); 8054 const materials = extractFromCache( meta.materials ); 8055 const textures = extractFromCache( meta.textures ); 8056 const images = extractFromCache( meta.images ); 8057 const shapes = extractFromCache( meta.shapes ); 8058 const skeletons = extractFromCache( meta.skeletons ); 8059 const animations = extractFromCache( meta.animations ); 8060 const nodes = extractFromCache( meta.nodes ); 8061 8062 if ( geometries.length > 0 ) output.geometries = geometries; 8063 if ( materials.length > 0 ) output.materials = materials; 8064 if ( textures.length > 0 ) output.textures = textures; 8065 if ( images.length > 0 ) output.images = images; 8066 if ( shapes.length > 0 ) output.shapes = shapes; 8067 if ( skeletons.length > 0 ) output.skeletons = skeletons; 8068 if ( animations.length > 0 ) output.animations = animations; 8069 if ( nodes.length > 0 ) output.nodes = nodes; 8070 8071 } 8072 8073 output.object = object; 8074 8075 return output; 8076 8077 // extract data from the cache hash 8078 // remove metadata on each item 8079 // and return as array 8080 function extractFromCache( cache ) { 8081 8082 const values = []; 8083 for ( const key in cache ) { 8084 8085 const data = cache[ key ]; 8086 delete data.metadata; 8087 values.push( data ); 8088 8089 } 8090 8091 return values; 8092 8093 } 8094 8095 } 8096 8097 clone( recursive ) { 8098 8099 return new this.constructor().copy( this, recursive ); 8100 8101 } 8102 8103 copy( source, recursive = true ) { 8104 8105 this.name = source.name; 8106 8107 this.up.copy( source.up ); 8108 8109 this.position.copy( source.position ); 8110 this.rotation.order = source.rotation.order; 8111 this.quaternion.copy( source.quaternion ); 8112 this.scale.copy( source.scale ); 8113 8114 this.matrix.copy( source.matrix ); 8115 this.matrixWorld.copy( source.matrixWorld ); 8116 8117 this.matrixAutoUpdate = source.matrixAutoUpdate; 8118 8119 this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate; 8120 this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; 8121 8122 this.layers.mask = source.layers.mask; 8123 this.visible = source.visible; 8124 8125 this.castShadow = source.castShadow; 8126 this.receiveShadow = source.receiveShadow; 8127 8128 this.frustumCulled = source.frustumCulled; 8129 this.renderOrder = source.renderOrder; 8130 8131 this.animations = source.animations.slice(); 8132 8133 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 8134 8135 if ( recursive === true ) { 8136 8137 for ( let i = 0; i < source.children.length; i ++ ) { 8138 8139 const child = source.children[ i ]; 8140 this.add( child.clone() ); 8141 8142 } 8143 8144 } 8145 8146 return this; 8147 8148 } 8149 8150} 8151 8152Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 ); 8153Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true; 8154Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true; 8155 8156const _v0$1 = /*@__PURE__*/ new Vector3(); 8157const _v1$3 = /*@__PURE__*/ new Vector3(); 8158const _v2$2 = /*@__PURE__*/ new Vector3(); 8159const _v3$
81591 = /*@__PURE__*/ new Vector3(); 8160 8161const _vab = /*@__PURE__*/ new Vector3(); 8162const _vac = /*@__PURE__*/ new Vector3(); 8163const _vbc = /*@__PURE__*/ new Vector3(); 8164const _vap = /*@__PURE__*/ new Vector3(); 8165const _vbp = /*@__PURE__*/ new Vector3(); 8166const _vcp = /*@__PURE__*/ new Vector3(); 8167 8168let warnedGetUV = false; 8169 8170class Triangle { 8171 8172 constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { 8173 8174 this.a = a; 8175 this.b = b; 8176 this.c = c; 8177 8178 } 8179 8180 static getNormal( a, b, c, target ) { 8181 8182 target.subVectors( c, b ); 8183 _v0$1.subVectors( a, b ); 8184 target.cross( _v0$1 ); 8185 8186 const targetLengthSq = target.lengthSq(); 8187 if ( targetLengthSq > 0 ) { 8188 8189 return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) ); 8190 8191 } 8192 8193 return target.set( 0, 0, 0 ); 8194 8195 } 8196 8197 // static/instance method to calculate barycentric coordinates 8198 // based on: http://www.blackpawn.com/texts/pointinpoly/default.html 8199 static getBarycoord( point, a, b, c, target ) { 8200 8201 _v0$1.subVectors( c, a ); 8202 _v1$3.subVectors( b, a ); 8203 _v2$2.subVectors( point, a ); 8204
vendor: 4,129 bytes, lines 8205-8412
8205 const dot00 = _v0$1.dot( _v0$1 ); 8206 const dot01 = _v0$1.dot( _v1$3 ); 8207 const dot02 = _v0$1.dot( _v2$2 ); 8208 const dot11 = _v1$3.dot( _v1$3 ); 8209 const dot12 = _v1$3.dot( _v2$2 ); 8210 8211 const denom = ( dot00 * dot11 - dot01 * dot01 ); 8212 8213 // collinear or singular triangle 8214 if ( denom === 0 ) { 8215 8216 target.set( 0, 0, 0 ); 8217 return null; 8218 8219 } 8220 8221 const invDenom = 1 / denom; 8222 const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; 8223 const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; 8224 8225 // barycentric coordinates must always sum to 1 8226 return target.set( 1 - u - v, v, u ); 8227 8228 } 8229 8230 static containsPoint( point, a, b, c ) { 8231 8232 // if the triangle is degenerate then we can't contain a point 8233 if ( this.getBarycoord( point, a, b, c, _v3$1 ) === null ) { 8234 8235 return false; 8236 8237 } 8238 8239 return ( _v3$1.x >= 0 ) && ( _v3$1.y >= 0 ) && ( ( _v3$1.x + _v3$1.y ) <= 1 ); 8240 8241 } 8242 8243 static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) { // @deprecated, r151 8244 8245 if ( warnedGetUV === false ) { 8246 8247 console.warn( 'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' ); 8248 8249 warnedGetUV = true; 8250 8251 } 8252 8253 return this.getInterpolation( point, p1, p2, p3, uv1, uv2, uv3, target ); 8254 8255 } 8256 8257 static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) { 8258 8259 if ( this.getBarycoord( point, p1, p2, p3, _v3$1 ) === null ) { 8260 8261 target.x = 0; 8262 target.y = 0; 8263 if ( 'z' in target ) target.z = 0; 8264 if ( 'w' in target ) target.w = 0; 8265 return null; 8266 8267 } 8268 8269 target.setScalar( 0 ); 8270 target.addScaledVector( v1, _v3$1.x ); 8271 target.addScaledVector( v2, _v3$1.y ); 8272 target.addScaledVector( v3, _v3$1.z ); 8273 8274 return target; 8275 8276 } 8277 8278 static isFrontFacing( a, b, c, direction ) { 8279 8280 _v0$1.subVectors( c, b ); 8281 _v1$3.subVectors( a, b ); 8282 8283 // strictly front facing 8284 return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false; 8285 8286 } 8287 8288 set( a, b, c ) { 8289 8290 this.a.copy( a ); 8291 this.b.copy( b ); 8292 this.c.copy( c ); 8293 8294 return this; 8295 8296 } 8297 8298 setFromPointsAndIndices( points, i0, i1, i2 ) { 8299 8300 this.a.copy( points[ i0 ] ); 8301 this.b.copy( points[ i1 ] ); 8302 this.c.copy( points[ i2 ] ); 8303 8304 return this; 8305 8306 } 8307 8308 setFromAttributeAndIndices( attribute, i0, i1, i2 ) { 8309 8310 this.a.fromBufferAttribute( attribute, i0 ); 8311 this.b.fromBufferAttribute( attribute, i1 ); 8312 this.c.fromBufferAttribute( attribute, i2 ); 8313 8314 return this; 8315 8316 } 8317 8318 clone() { 8319 8320 return new this.constructor().copy( this ); 8321 8322 } 8323 8324 copy( triangle ) { 8325 8326 this.a.copy( triangle.a ); 8327 this.b.copy( triangle.b ); 8328 this.c.copy( triangle.c ); 8329 8330 return this; 8331 8332 } 8333 8334 getArea() { 8335 8336 _v0$1.subVectors( this.c, this.b ); 8337 _v1$3.subVectors( this.a, this.b ); 8338 8339 return _v0$1.cross( _v1$3 ).length() * 0.5; 8340 8341 } 8342 8343 getMidpoint( target ) { 8344 8345 return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); 8346 8347 } 8348 8349 getNormal( target ) { 8350 8351 return Triangle.getNormal( this.a, this.b, this.c, target ); 8352 8353 } 8354 8355 getPlane( target ) { 8356 8357 return target.setFromCoplanarPoints( this.a, this.b, this.c ); 8358 8359 } 8360 8361 getBarycoord( point, target ) { 8362 8363 return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); 8364 8365 } 8366 8367 getUV( point, uv1, uv2, uv3, target ) { // @deprecated, r151 8368 8369 if ( warnedGetUV === false ) { 8370 8371 console.warn( 'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' ); 8372 8373 warnedGetUV = true; 8374 8375 } 8376 8377 return Triangle.getInterpolation( point, this.a, this.b, this.c, uv1, uv2, uv3, target ); 8378 8379 } 8380 8381 getInterpolation( point, v1, v2, v3, target ) { 8382 8383 return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target ); 8384 8385 } 8386 8387 containsPoint( point ) { 8388 8389 return Triangle.containsPoint( point, this.a, this.b, this.c ); 8390 8391 } 8392 8393 isFrontFacing( direction ) { 8394 8395 return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); 8396 8397 } 8398 8399 intersectsBox( box ) { 8400 8401 return box.intersectsTriangle( this ); 8402 8403 } 8404 8405 closestPointToPoint( p, target ) { 8406 8407 const a = this.a, b = this.b, c = this.c; 8408 let v, w; 8409 8410 // algorithm thanks to Real-Time Collision Detection by Christer Ericson, 8411 // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., 8412 // under the accompanying license; see chapter 5.1.5 for detailed explanation.
vendor: 26,125 bytes, lines 8413-9454
8413 // basically, we're distinguishing which of the voronoi regions of the triangle 8414 // the point lies in with the minimum amount of redundant computation. 8415 8416 _vab.subVectors( b, a ); 8417 _vac.subVectors( c, a ); 8418 _vap.subVectors( p, a ); 8419 const d1 = _vab.dot( _vap ); 8420 const d2 = _vac.dot( _vap ); 8421 if ( d1 <= 0 && d2 <= 0 ) { 8422 8423 // vertex region of A; barycentric coords (1, 0, 0) 8424 return target.copy( a ); 8425 8426 } 8427 8428 _vbp.subVectors( p, b ); 8429 const d3 = _vab.dot( _vbp ); 8430 const d4 = _vac.dot( _vbp ); 8431 if ( d3 >= 0 && d4 <= d3 ) { 8432 8433 // vertex region of B; barycentric coords (0, 1, 0) 8434 return target.copy( b ); 8435 8436 } 8437 8438 const vc = d1 * d4 - d3 * d2; 8439 if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { 8440 8441 v = d1 / ( d1 - d3 ); 8442 // edge region of AB; barycentric coords (1-v, v, 0) 8443 return target.copy( a ).addScaledVector( _vab, v ); 8444 8445 } 8446 8447 _vcp.subVectors( p, c ); 8448 const d5 = _vab.dot( _vcp ); 8449 const d6 = _vac.dot( _vcp ); 8450 if ( d6 >= 0 && d5 <= d6 ) { 8451 8452 // vertex region of C; barycentric coords (0, 0, 1) 8453 return target.copy( c ); 8454 8455 } 8456 8457 const vb = d5 * d2 - d1 * d6; 8458 if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { 8459 8460 w = d2 / ( d2 - d6 ); 8461 // edge region of AC; barycentric coords (1-w, 0, w) 8462 return target.copy( a ).addScaledVector( _vac, w ); 8463 8464 } 8465 8466 const va = d3 * d6 - d5 * d4; 8467 if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { 8468 8469 _vbc.subVectors( c, b ); 8470 w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); 8471 // edge region of BC; barycentric coords (0, 1-w, w) 8472 return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC 8473 8474 } 8475 8476 // face region 8477 const denom = 1 / ( va + vb + vc ); 8478 // u = va * denom 8479 v = vb * denom; 8480 w = vc * denom; 8481 8482 return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); 8483 8484 } 8485 8486 equals( triangle ) { 8487 8488 return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); 8489 8490 } 8491 8492} 8493 8494const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, 8495 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, 8496 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, 8497 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, 8498 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, 8499 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, 8500 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, 8501 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, 8502 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, 8503 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, 8504 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, 8505 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, 8506 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, 8507 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, 8508 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, 8509 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, 8510 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, 8511 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, 8512 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, 8513 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, 8514 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, 8515 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, 8516 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, 8517 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; 8518 8519const _hslA = { h: 0, s: 0, l: 0 }; 8520const _hslB = { h: 0, s: 0, l: 0 }; 8521 8522function hue2rgb( p, q, t ) { 8523 8524 if ( t < 0 ) t += 1; 8525 if ( t > 1 ) t -= 1; 8526 if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; 8527 if ( t < 1 / 2 ) return q; 8528 if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); 8529 return p; 8530 8531} 8532 8533class Color { 8534 8535 constructor( r, g, b ) { 8536 8537 this.isColor = true; 8538 8539 this.r = 1; 8540 this.g = 1; 8541 this.b = 1; 8542 8543 return this.set( r, g, b ); 8544 8545 } 8546 8547 set( r, g, b ) { 8548 8549 if ( g === undefined && b === undefined ) { 8550 8551 // r is THREE.Color, hex or string 8552 8553 const value = r; 8554 8555 if ( value && value.isColor ) { 8556 8557 this.copy( value ); 8558 8559 } else if ( typeof value === 'number' ) { 8560 8561 this.setHex( value ); 8562 8563 } else if ( typeof value === 'string' ) { 8564 8565 this.setStyle( value ); 8566 8567 } 8568 8569 } else { 8570 8571 this.setRGB( r, g, b ); 8572 8573 } 8574 8575 return this; 8576 8577 } 8578 8579 setScalar( scalar ) { 8580 8581 this.r = scalar; 8582 this.g = scalar; 8583 this.b = scalar; 8584 8585 return this; 8586 8587 } 8588 8589 setHex( hex, colorSpace = SRGBColorSpace ) { 8590 8591 hex = Math.floor( hex ); 8592 8593 this.r = ( hex >> 16 & 255 ) / 255; 8594 this.g = ( hex >> 8 & 255 ) / 255; 8595 this.b = ( hex & 255 ) / 255; 8596 8597 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8598 8599 return this; 8600 8601 } 8602 8603 setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { 8604 8605 this.r = r; 8606 this.g = g; 8607 this.b = b; 8608 8609 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8610 8611 return this; 8612 8613 } 8614 8615 setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { 8616 8617 // h,s,l ranges are in 0.0 - 1.0 8618 h = euclideanModulo( h, 1 ); 8619 s = clamp( s, 0, 1 ); 8620 l = clamp( l, 0, 1 ); 8621 8622 if ( s === 0 ) { 8623 8624 this.r = this.g = this.b = l; 8625 8626 } else { 8627 8628 const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); 8629 const q = ( 2 * l ) - p; 8630 8631 this.r = hue2rgb( q, p, h + 1 / 3 ); 8632 this.g = hue2rgb( q, p, h ); 8633 this.b = hue2rgb( q, p, h - 1 / 3 ); 8634 8635 } 8636 8637 ColorManagement.toWorkingColorSpace( this, colorSpace ); 8638 8639 return this; 8640 8641 } 8642 8643 setStyle( style, colorSpace = SRGBColorSpace ) { 8644 8645 function handleAlpha( string ) { 8646 8647 if ( string === undefined ) return; 8648 8649 if ( parseFloat( string ) < 1 ) { 8650 8651 console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); 8652 8653 } 8654 8655 } 8656 8657 8658 let m; 8659 8660 if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) { 8661 8662 // rgb / hsl 8663 8664 let color; 8665 const name = m[ 1 ]; 8666 const components = m[ 2 ]; 8667 8668 switch ( name ) { 8669 8670 case 'rgb': 8671 case 'rgba': 8672 8673 if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { 8674 8675 // rgb(255,0,0) rgba(255,0,0,0.5) 8676 8677 handleAlpha( color[ 4 ] ); 8678 8679 return this.setRGB( 8680 Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255, 8681 Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255, 8682 Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255, 8683 colorSpace 8684 ); 8685 8686 } 8687 8688 if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { 8689 8690 // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) 8691 8692 handleAlpha( color[ 4 ] ); 8693 8694 return this.setRGB( 8695 Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100, 8696 Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100, 8697 Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100, 8698 colorSpace 8699 ); 8700 8701 } 8702 8703 break; 8704 8705 case 'hsl': 8706 case 'hsla': 8707 8708 if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { 8709 8710 // hsl(120,50%,50%) hsla(120,50%,50%,0.5) 8711 8712 handleAlpha( color[ 4 ] ); 8713 8714 return this.setHSL( 8715 parseFloat( color[ 1 ] ) / 360, 8716 parseFloat( color[ 2 ] ) / 100, 8717 parseFloat( color[ 3 ] ) / 100, 8718 colorSpace 8719 ); 8720 8721 } 8722 8723 break; 8724 8725 default: 8726 8727 console.warn( 'THREE.Color: Unknown color model ' + style ); 8728 8729 } 8730 8731 } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { 8732 8733 // hex color 8734 8735 const hex = m[ 1 ]; 8736 const size = hex.length; 8737 8738 if ( size === 3 ) { 8739 8740 // #ff0 8741 return this.setRGB( 8742 parseInt( hex.charAt( 0 ), 16 ) / 15, 8743 parseInt( hex.charAt( 1 ), 16 ) / 15, 8744 parseInt( hex.charAt( 2 ), 16 ) / 15, 8745 colorSpace 8746 ); 8747 8748 } else if ( size === 6 ) { 8749 8750 // #ff0000 8751 return this.setHex( parseInt( hex, 16 ), colorSpace ); 8752 8753 } else { 8754 8755 console.warn( 'THREE.Color: Invalid hex color ' + style ); 8756 8757 } 8758 8759 } else if ( style && style.length > 0 ) { 8760 8761 return this.setColorName( style, colorSpace ); 8762 8763 } 8764 8765 return this; 8766 8767 } 8768 8769 setColorName( style, colorSpace = SRGBColorSpace ) { 8770 8771 // color keywords 8772 const hex = _colorKeywords[ style.toLowerCase() ]; 8773 8774 if ( hex !== undefined ) { 8775 8776 // red 8777 this.setHex( hex, colorSpace ); 8778 8779 } else { 8780 8781 // unknown color 8782 console.warn( 'THREE.Color: Unknown color ' + style ); 8783 8784 } 8785 8786 return this; 8787 8788 } 8789 8790 clone() { 8791 8792 return new this.constructor( this.r, this.g, this.b ); 8793 8794 } 8795 8796 copy( color ) { 8797 8798 this.r = color.r; 8799 this.g = color.g; 8800 this.b = color.b; 8801 8802 return this; 8803 8804 } 8805 8806 copySRGBToLinear( color ) { 8807 8808 this.r = SRGBToLinear( color.r ); 8809 this.g = SRGBToLinear( color.g ); 8810 this.b = SRGBToLinear( color.b ); 8811 8812 return this; 8813 8814 } 8815 8816 copyLinearToSRGB( color ) { 8817 8818 this.r = LinearToSRGB( color.r ); 8819 this.g = LinearToSRGB( color.g ); 8820 this.b = LinearToSRGB( color.b ); 8821 8822 return this; 8823 8824 } 8825 8826 convertSRGBToLinear() { 8827 8828 this.copySRGBToLinear( this ); 8829 8830 return this; 8831 8832 } 8833 8834 convertLinearToSRGB() { 8835 8836 this.copyLinearToSRGB( this ); 8837 8838 return this; 8839 8840 } 8841 8842 getHex( colorSpace = SRGBColorSpace ) { 8843 8844 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 8845 8846 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 ) ); 8847 8848 } 8849 8850 getHexString( colorSpace = SRGBColorSpace ) { 8851 8852 return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); 8853 8854 } 8855 8856 getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { 8857 8858 // h,s,l ranges are in 0.0 - 1.0 8859 8860 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 8861 8862 const r = _color.r, g = _color.g, b = _color.b; 8863 8864 const max = Math.max( r, g, b ); 8865 const min = Math.min( r, g, b ); 8866 8867 let hue, saturation; 8868 const lightness = ( min + max ) / 2.0; 8869 8870 if ( min === max ) { 8871 8872 hue = 0; 8873 saturation = 0; 8874 8875 } else { 8876 8877 const delta = max - min; 8878 8879 saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); 8880 8881 switch ( max ) { 8882 8883 case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; 8884 case g: hue = ( b - r ) / delta + 2; break; 8885 case b: hue = ( r - g ) / delta + 4; break; 8886 8887 } 8888 8889 hue /= 6; 8890 8891 } 8892 8893 target.h = hue; 8894 target.s = saturation; 8895 target.l = lightness; 8896 8897 return target; 8898 8899 } 8900 8901 getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { 8902 8903 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 8904 8905 target.r = _color.r; 8906 target.g = _color.g; 8907 target.b = _color.b; 8908 8909 return target; 8910 8911 } 8912 8913 getStyle( colorSpace = SRGBColorSpace ) { 8914 8915 ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); 8916 8917 const r = _color.r, g = _color.g, b = _color.b; 8918 8919 if ( colorSpace !== SRGBColorSpace ) { 8920 8921 // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). 8922 return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`; 8923 8924 } 8925 8926 return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`; 8927 8928 } 8929 8930 offsetHSL( h, s, l ) { 8931 8932 this.getHSL( _hslA ); 8933 8934 return this.setHSL( _hslA.h + h, _hslA.s + s, _hslA.l + l ); 8935 8936 } 8937 8938 add( color ) { 8939 8940 this.r += color.r; 8941 this.g += color.g; 8942 this.b += color.b; 8943 8944 return this; 8945 8946 } 8947 8948 addColors( color1, color2 ) { 8949 8950 this.r = color1.r + color2.r; 8951 this.g = color1.g + color2.g; 8952 this.b = color1.b + color2.b; 8953 8954 return this; 8955 8956 } 8957 8958 addScalar( s ) { 8959 8960 this.r += s; 8961 this.g += s; 8962 this.b += s; 8963 8964 return this; 8965 8966 } 8967 8968 sub( color ) { 8969 8970 this.r = Math.max( 0, this.r - color.r ); 8971 this.g = Math.max( 0, this.g - color.g ); 8972 this.b = Math.max( 0, this.b - color.b ); 8973 8974 return this; 8975 8976 } 8977 8978 multiply( color ) { 8979 8980 this.r *= color.r; 8981 this.g *= color.g; 8982 this.b *= color.b; 8983 8984 return this; 8985 8986 } 8987 8988 multiplyScalar( s ) { 8989 8990 this.r *= s; 8991 this.g *= s; 8992 this.b *= s; 8993 8994 return this; 8995 8996 } 8997 8998 lerp( color, alpha ) { 8999 9000 this.r += ( color.r - this.r ) * alpha; 9001 this.g += ( color.g - this.g ) * alpha; 9002 this.b += ( color.b - this.b ) * alpha; 9003 9004 return this; 9005 9006 } 9007 9008 lerpColors( color1, color2, alpha ) { 9009 9010 this.r = color1.r + ( color2.r - color1.r ) * alpha; 9011 this.g = color1.g + ( color2.g - color1.g ) * alpha; 9012 this.b = color1.b + ( color2.b - color1.b ) * alpha; 9013 9014 return this; 9015 9016 } 9017 9018 lerpHSL( color, alpha ) { 9019 9020 this.getHSL( _hslA ); 9021 color.getHSL( _hslB ); 9022 9023 const h = lerp( _hslA.h, _hslB.h, alpha ); 9024 const s = lerp( _hslA.s, _hslB.s, alpha ); 9025 const l = lerp( _hslA.l, _hslB.l, alpha ); 9026 9027 this.setHSL( h, s, l ); 9028 9029 return this; 9030 9031 } 9032 9033 setFromVector3( v ) { 9034 9035 this.r = v.x; 9036 this.g = v.y; 9037 this.b = v.z; 9038 9039 return this; 9040 9041 } 9042 9043 applyMatrix3( m ) { 9044 9045 const r = this.r, g = this.g, b = this.b; 9046 const e = m.elements; 9047 9048 this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b; 9049 this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b; 9050 this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b; 9051 9052 return this; 9053 9054 } 9055 9056 equals( c ) { 9057 9058 return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); 9059 9060 } 9061 9062 fromArray( array, offset = 0 ) { 9063 9064 this.r = array[ offset ]; 9065 this.g = array[ offset + 1 ]; 9066 this.b = array[ offset + 2 ]; 9067 9068 return this; 9069 9070 } 9071 9072 toArray( array = [], offset = 0 ) { 9073 9074 array[ offset ] = this.r; 9075 array[ offset + 1 ] = this.g; 9076 array[ offset + 2 ] = this.b; 9077 9078 return array; 9079 9080 } 9081 9082 fromBufferAttribute( attribute, index ) { 9083 9084 this.r = attribute.getX( index ); 9085 this.g = attribute.getY( index ); 9086 this.b = attribute.getZ( index ); 9087 9088 return this; 9089 9090 } 9091 9092 toJSON() { 9093 9094 return this.getHex(); 9095 9096 } 9097 9098 *[ Symbol.iterator ]() { 9099 9100 yield this.r; 9101 yield this.g; 9102 yield this.b; 9103 9104 } 9105 9106} 9107 9108const _color = /*@__PURE__*/ new Color(); 9109 9110Color.NAMES = _colorKeywords; 9111 9112let _materialId = 0; 9113 9114class Material extends EventDispatcher { 9115 9116 constructor() { 9117 9118 super(); 9119 9120 this.isMaterial = true; 9121 9122 Object.defineProperty( this, 'id', { value: _materialId ++ } ); 9123 9124 this.uuid = generateUUID(); 9125 9126 this.name = ''; 9127 this.type = 'Material'; 9128 9129 this.blending = NormalBlending; 9130 this.side = FrontSide; 9131 this.vertexColors = false; 9132 9133 this.opacity = 1; 9134 this.transparent = false; 9135 this.alphaHash = false; 9136 9137 this.blendSrc = SrcAlphaFactor; 9138 this.blendDst = OneMinusSrcAlphaFactor; 9139 this.blendEquation = AddEquation; 9140 this.blendSrcAlpha = null; 9141 this.blendDstAlpha = null; 9142 this.blendEquationAlpha = null; 9143 this.blendColor = new Color( 0, 0, 0 ); 9144 this.blendAlpha = 0; 9145 9146 this.depthFunc = LessEqualDepth; 9147 this.depthTest = true; 9148 this.depthWrite = true; 9149 9150 this.stencilWriteMask = 0xff; 9151 this.stencilFunc = AlwaysStencilFunc; 9152 this.stencilRef = 0; 9153 this.stencilFuncMask = 0xff; 9154 this.stencilFail = KeepStencilOp; 9155 this.stencilZFail = KeepStencilOp; 9156 this.stencilZPass = KeepStencilOp; 9157 this.stencilWrite = false; 9158 9159 this.clippingPlanes = null; 9160 this.clipIntersection = false; 9161 this.clipShadows = false; 9162 9163 this.shadowSide = null; 9164 9165 this.colorWrite = true; 9166 9167 this.precision = null; // override the renderer's default precision for this material 9168 9169 this.polygonOffset = false; 9170 this.polygonOffsetFactor = 0; 9171 this.polygonOffsetUnits = 0; 9172 9173 this.dithering = false; 9174 9175 this.alphaToCoverage = false; 9176 this.premultipliedAlpha = false; 9177 this.forceSinglePass = false; 9178 9179 this.visible = true; 9180 9181 this.toneMapped = true; 9182 9183 this.userData = {}; 9184 9185 this.version = 0; 9186 9187 this._alphaTest = 0; 9188 9189 } 9190 9191 get alphaTest() { 9192 9193 return this._alphaTest; 9194 9195 } 9196 9197 set alphaTest( value ) { 9198 9199 if ( this._alphaTest > 0 !== value > 0 ) { 9200 9201 this.version ++; 9202 9203 } 9204 9205 this._alphaTest = value; 9206 9207 } 9208 9209 onBuild( /* shaderobject, renderer */ ) {} 9210 9211 onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} 9212 9213 onBeforeCompile( /* shaderobject, renderer */ ) {} 9214 9215 customProgramCacheKey() { 9216 9217 return this.onBeforeCompile.toString(); 9218 9219 } 9220 9221 setValues( values ) { 9222 9223 if ( values === undefined ) return; 9224 9225 for ( const key in values ) { 9226 9227 const newValue = values[ key ]; 9228 9229 if ( newValue === undefined ) { 9230 9231 console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` ); 9232 continue; 9233 9234 } 9235 9236 const currentValue = this[ key ]; 9237 9238 if ( currentValue === undefined ) { 9239 9240 console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` ); 9241 continue; 9242 9243 } 9244 9245 if ( currentValue && currentValue.isColor ) { 9246 9247 currentValue.set( newValue ); 9248 9249 } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { 9250 9251 currentValue.copy( newValue ); 9252 9253 } else { 9254 9255 this[ key ] = newValue; 9256 9257 } 9258 9259 } 9260 9261 } 9262 9263 toJSON( meta ) { 9264 9265 const isRootObject = ( meta === undefined || typeof meta === 'string' ); 9266 9267 if ( isRootObject ) { 9268 9269 meta = { 9270 textures: {}, 9271 images: {} 9272 }; 9273 9274 } 9275 9276 const data = { 9277 metadata: { 9278 version: 4.6, 9279 type: 'Material', 9280 generator: 'Material.toJSON' 9281 } 9282 }; 9283 9284 // standard Material serialization 9285 data.uuid = this.uuid; 9286 data.type = this.type; 9287 9288 if ( this.name !== '' ) data.name = this.name; 9289 9290 if ( this.color && this.color.isColor ) data.color = this.color.getHex(); 9291 9292 if ( this.roughness !== undefined ) data.roughness = this.roughness; 9293 if ( this.metalness !== undefined ) data.metalness = this.metalness; 9294 9295 if ( this.sheen !== undefined ) data.sheen = this.sheen; 9296 if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); 9297 if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; 9298 if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); 9299 if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; 9300 9301 if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); 9302 if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; 9303 if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); 9304 if ( this.shininess !== undefined ) data.shininess = this.shininess; 9305 if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; 9306 if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; 9307 9308 if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { 9309 9310 data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; 9311 9312 } 9313 9314 if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { 9315 9316 data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; 9317 9318 } 9319 9320 if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { 9321 9322 data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; 9323 data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); 9324 9325 } 9326 9327 if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; 9328 if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; 9329 if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; 9330 9331 if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { 9332 9333 data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; 9334 9335 } 9336 9337 if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { 9338 9339 data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; 9340 9341 } 9342 9343 if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy; 9344 if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation; 9345 9346 if ( this.anisotropyMap && this.anisotropyMap.isTexture ) { 9347 9348 data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid; 9349 9350 } 9351 9352 if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; 9353 if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; 9354 if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; 9355 9356 if ( this.lightMap && this.lightMap.isTexture ) { 9357 9358 data.lightMap = this.lightMap.toJSON( meta ).uuid; 9359 data.lightMapIntensity = this.lightMapIntensity; 9360 9361 } 9362 9363 if ( this.aoMap && this.aoMap.isTexture ) { 9364 9365 data.aoMap = this.aoMap.toJSON( meta ).uuid; 9366 data.aoMapIntensity = this.aoMapIntensity; 9367 9368 } 9369 9370 if ( this.bumpMap && this.bumpMap.isTexture ) { 9371 9372 data.bumpMap = this.bumpMap.toJSON( meta ).uuid; 9373 data.bumpScale = this.bumpScale; 9374 9375 } 9376 9377 if ( this.normalMap && this.normalMap.isTexture ) { 9378 9379 data.normalMap = this.normalMap.toJSON( meta ).uuid; 9380 data.normalMapType = this.normalMapType; 9381 data.normalScale = this.normalScale.toArray(); 9382 9383 } 9384 9385 if ( this.displacementMap && this.displacementMap.isTexture ) { 9386 9387 data.displacementMap = this.displacementMap.toJSON( meta ).uuid; 9388 data.displacementScale = this.displacementScale; 9389 data.displacementBias = this.displacementBias; 9390 9391 } 9392 9393 if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; 9394 if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; 9395 9396 if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; 9397 if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; 9398 if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; 9399 if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; 9400 9401 if ( this.envMap && this.envMap.isTexture ) { 9402 9403 data.envMap = this.envMap.toJSON( meta ).uuid; 9404 9405 if ( this.combine !== undefined ) data.combine = this.combine; 9406 9407 } 9408 9409 if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; 9410 if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; 9411 if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; 9412 9413 if ( this.gradientMap && this.gradientMap.isTexture ) { 9414 9415 data.gradientMap = this.gradientMap.toJSON( meta ).uuid; 9416 9417 } 9418 9419 if ( this.transmission !== undefined ) data.transmission = this.transmission; 9420 if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; 9421 if ( this.thickness !== undefined ) data.thickness = this.thickness; 9422 if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; 9423 if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; 9424 if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); 9425 9426 if ( this.size !== undefined ) data.size = this.size; 9427 if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; 9428 if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; 9429 9430 if ( this.blending !== NormalBlending ) data.blending = this.blending; 9431 if ( this.side !== FrontSide ) data.side = this.side; 9432 if ( this.vertexColors === true ) data.vertexColors = true; 9433 9434 if ( this.opacity < 1 ) data.opacity = this.opacity; 9435 if ( this.transparent === true ) data.transparent = true; 9436 9437 if ( this.blendSrc !== SrcAlphaFactor ) data.blendSrc = this.blendSrc; 9438 if ( this.blendDst !== OneMinusSrcAlphaFactor ) data.blendDst = this.blendDst; 9439 if ( this.blendEquation !== AddEquation ) data.blendEquation = this.blendEquation; 9440 if ( this.blendSrcAlpha !== null ) data.blendSrcAlpha = this.blendSrcAlpha; 9441 if ( this.blendDstAlpha !== null ) data.blendDstAlpha = this.blendDstAlpha; 9442 if ( this.blendEquationAlpha !== null ) data.blendEquationAlpha = this.blendEquationAlpha; 9443 if ( this.blendColor && this.blendColor.isColor ) data.blendColor = this.blendColor.getHex(); 9444 if ( this.blendAlpha !== 0 ) data.blendAlpha = this.blendAlpha; 9445 9446 if ( this.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc; 9447 if ( this.depthTest === false ) data.depthTest = this.depthTest; 9448 if ( this.depthWrite === false ) data.depthWrite = this.depthWrite; 9449 if ( this.colorWrite === false ) data.colorWrite = this.colorWrite; 9450 9451 if ( this.stencilWriteMask !== 0xff ) data.stencilWriteMask = this.stencilWriteMask; 9452 if ( this.stencilFunc !== AlwaysStencilFunc ) data.stencilFunc = this.stencilFunc; 9453 if ( this.stencilRef !== 0 ) data.stencilRef = this.stencilRef; 9454 if ( this.stencilFuncMask !== 0xff ) data.stencilFuncMask = this.stencilFuncMask;
vendor: 5,379 bytes, lines 9455-9657
9455 if ( this.stencilFail !== KeepStencilOp ) data.stencilFail = this.stencilFail; 9456 if ( this.stencilZFail !== KeepStencilOp ) data.stencilZFail = this.stencilZFail; 9457 if ( this.stencilZPass !== KeepStencilOp ) data.stencilZPass = this.stencilZPass; 9458 if ( this.stencilWrite === true ) data.stencilWrite = this.stencilWrite; 9459 9460 // rotation (SpriteMaterial) 9461 if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; 9462 9463 if ( this.polygonOffset === true ) data.polygonOffset = true; 9464 if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; 9465 if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; 9466 9467 if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; 9468 if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; 9469 if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; 9470 if ( this.scale !== undefined ) data.scale = this.scale; 9471 9472 if ( this.dithering === true ) data.dithering = true; 9473 9474 if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; 9475 if ( this.alphaHash === true ) data.alphaHash = true; 9476 if ( this.alphaToCoverage === true ) data.alphaToCoverage = true; 9477 if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = true; 9478 if ( this.forceSinglePass === true ) data.forceSinglePass = true; 9479 9480 if ( this.wireframe === true ) data.wireframe = true; 9481 if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; 9482 if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; 9483 if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; 9484 9485 if ( this.flatShading === true ) data.flatShading = true; 9486 9487 if ( this.visible === false ) data.visible = false; 9488 9489 if ( this.toneMapped === false ) data.toneMapped = false; 9490 9491 if ( this.fog === false ) data.fog = false; 9492 9493 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; 9494 9495 // TODO: Copied from Object3D.toJSON 9496 9497 function extractFromCache( cache ) { 9498 9499 const values = []; 9500 9501 for ( const key in cache ) { 9502 9503 const data = cache[ key ]; 9504 delete data.metadata; 9505 values.push( data ); 9506 9507 } 9508 9509 return values; 9510 9511 } 9512 9513 if ( isRootObject ) { 9514 9515 const textures = extractFromCache( meta.textures ); 9516 const images = extractFromCache( meta.images ); 9517 9518 if ( textures.length > 0 ) data.textures = textures; 9519 if ( images.length > 0 ) data.images = images; 9520 9521 } 9522 9523 return data; 9524 9525 } 9526 9527 clone() { 9528 9529 return new this.constructor().copy( this ); 9530 9531 } 9532 9533 copy( source ) { 9534 9535 this.name = source.name; 9536 9537 this.blending = source.blending; 9538 this.side = source.side; 9539 this.vertexColors = source.vertexColors; 9540 9541 this.opacity = source.opacity; 9542 this.transparent = source.transparent; 9543 9544 this.blendSrc = source.blendSrc; 9545 this.blendDst = source.blendDst; 9546 this.blendEquation = source.blendEquation; 9547 this.blendSrcAlpha = source.blendSrcAlpha; 9548 this.blendDstAlpha = source.blendDstAlpha; 9549 this.blendEquationAlpha = source.blendEquationAlpha; 9550 this.blendColor.copy( source.blendColor ); 9551 this.blendAlpha = source.blendAlpha; 9552 9553 this.depthFunc = source.depthFunc; 9554 this.depthTest = source.depthTest; 9555 this.depthWrite = source.depthWrite; 9556 9557 this.stencilWriteMask = source.stencilWriteMask; 9558 this.stencilFunc = source.stencilFunc; 9559 this.stencilRef = source.stencilRef; 9560 this.stencilFuncMask = source.stencilFuncMask; 9561 this.stencilFail = source.stencilFail; 9562 this.stencilZFail = source.stencilZFail; 9563 this.stencilZPass = source.stencilZPass; 9564 this.stencilWrite = source.stencilWrite; 9565 9566 const srcPlanes = source.clippingPlanes; 9567 let dstPlanes = null; 9568 9569 if ( srcPlanes !== null ) { 9570 9571 const n = srcPlanes.length; 9572 dstPlanes = new Array( n ); 9573 9574 for ( let i = 0; i !== n; ++ i ) { 9575 9576 dstPlanes[ i ] = srcPlanes[ i ].clone(); 9577 9578 } 9579 9580 } 9581 9582 this.clippingPlanes = dstPlanes; 9583 this.clipIntersection = source.clipIntersection; 9584 this.clipShadows = source.clipShadows; 9585 9586 this.shadowSide = source.shadowSide; 9587 9588 this.colorWrite = source.colorWrite; 9589 9590 this.precision = source.precision; 9591 9592 this.polygonOffset = source.polygonOffset; 9593 this.polygonOffsetFactor = source.polygonOffsetFactor; 9594 this.polygonOffsetUnits = source.polygonOffsetUnits; 9595 9596 this.dithering = source.dithering; 9597 9598 this.alphaTest = source.alphaTest; 9599 this.alphaHash = source.alphaHash; 9600 this.alphaToCoverage = source.alphaToCoverage; 9601 this.premultipliedAlpha = source.premultipliedAlpha; 9602 this.forceSinglePass = source.forceSinglePass; 9603 9604 this.visible = source.visible; 9605 9606 this.toneMapped = source.toneMapped; 9607 9608 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 9609 9610 return this; 9611 9612 } 9613 9614 dispose() { 9615 9616 this.dispatchEvent( { type: 'dispose' } ); 9617 9618 } 9619 9620 set needsUpdate( value ) { 9621 9622 if ( value === true ) this.version ++; 9623 9624 } 9625 9626} 9627 9628class MeshBasicMaterial extends Material { 9629 9630 constructor( parameters ) { 9631 9632 super(); 9633 9634 this.isMeshBasicMaterial = true; 9635 9636 this.type = 'MeshBasicMaterial'; 9637 9638 this.color = new Color( 0xffffff ); // emissive 9639 9640 this.map = null; 9641 9642 this.lightMap = null; 9643 this.lightMapIntensity = 1.0; 9644 9645 this.aoMap = null; 9646 this.aoMapIntensity = 1.0; 9647 9648 this.specularMap = null; 9649 9650 this.alphaMap = null; 9651 9652 this.envMap = null; 9653 this.combine = MultiplyOperation; 9654 this.reflectivity = 1; 9655 this.refractionRatio = 0.98; 9656 9657 this.wireframe = false;
vendor: 5,583 bytes, lines 9658-9942
9658 this.wireframeLinewidth = 1; 9659 this.wireframeLinecap = 'round'; 9660 this.wireframeLinejoin = 'round'; 9661 9662 this.fog = true; 9663 9664 this.setValues( parameters ); 9665 9666 } 9667 9668 copy( source ) { 9669 9670 super.copy( source ); 9671 9672 this.color.copy( source.color ); 9673 9674 this.map = source.map; 9675 9676 this.lightMap = source.lightMap; 9677 this.lightMapIntensity = source.lightMapIntensity; 9678 9679 this.aoMap = source.aoMap; 9680 this.aoMapIntensity = source.aoMapIntensity; 9681 9682 this.specularMap = source.specularMap; 9683 9684 this.alphaMap = source.alphaMap; 9685 9686 this.envMap = source.envMap; 9687 this.combine = source.combine; 9688 this.reflectivity = source.reflectivity; 9689 this.refractionRatio = source.refractionRatio; 9690 9691 this.wireframe = source.wireframe; 9692 this.wireframeLinewidth = source.wireframeLinewidth; 9693 this.wireframeLinecap = source.wireframeLinecap; 9694 this.wireframeLinejoin = source.wireframeLinejoin; 9695 9696 this.fog = source.fog; 9697 9698 return this; 9699 9700 } 9701 9702} 9703 9704// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf 9705 9706const _tables = /*@__PURE__*/ _generateTables(); 9707 9708function _generateTables() { 9709 9710 // float32 to float16 helpers 9711 9712 const buffer = new ArrayBuffer( 4 ); 9713 const floatView = new Float32Array( buffer ); 9714 const uint32View = new Uint32Array( buffer ); 9715 9716 const baseTable = new Uint32Array( 512 ); 9717 const shiftTable = new Uint32Array( 512 ); 9718 9719 for ( let i = 0; i < 256; ++ i ) { 9720 9721 const e = i - 127; 9722 9723 // very small number (0, -0) 9724 9725 if ( e < - 27 ) { 9726 9727 baseTable[ i ] = 0x0000; 9728 baseTable[ i | 0x100 ] = 0x8000; 9729 shiftTable[ i ] = 24; 9730 shiftTable[ i | 0x100 ] = 24; 9731 9732 // small number (denorm) 9733 9734 } else if ( e < - 14 ) { 9735 9736 baseTable[ i ] = 0x0400 >> ( - e - 14 ); 9737 baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000; 9738 shiftTable[ i ] = - e - 1; 9739 shiftTable[ i | 0x100 ] = - e - 1; 9740 9741 // normal number 9742 9743 } else if ( e <= 15 ) { 9744 9745 baseTable[ i ] = ( e + 15 ) << 10; 9746 baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000; 9747 shiftTable[ i ] = 13; 9748 shiftTable[ i | 0x100 ] = 13; 9749 9750 // large number (Infinity, -Infinity) 9751 9752 } else if ( e < 128 ) { 9753 9754 baseTable[ i ] = 0x7c00; 9755 baseTable[ i | 0x100 ] = 0xfc00; 9756 shiftTable[ i ] = 24; 9757 shiftTable[ i | 0x100 ] = 24; 9758 9759 // stay (NaN, Infinity, -Infinity) 9760 9761 } else { 9762 9763 baseTable[ i ] = 0x7c00; 9764 baseTable[ i | 0x100 ] = 0xfc00; 9765 shiftTable[ i ] = 13; 9766 shiftTable[ i | 0x100 ] = 13; 9767 9768 } 9769 9770 } 9771 9772 // float16 to float32 helpers 9773 9774 const mantissaTable = new Uint32Array( 2048 ); 9775 const exponentTable = new Uint32Array( 64 ); 9776 const offsetTable = new Uint32Array( 64 ); 9777 9778 for ( let i = 1; i < 1024; ++ i ) { 9779 9780 let m = i << 13; // zero pad mantissa bits 9781 let e = 0; // zero exponent 9782 9783 // normalized 9784 while ( ( m & 0x00800000 ) === 0 ) { 9785 9786 m <<= 1; 9787 e -= 0x00800000; // decrement exponent 9788 9789 } 9790 9791 m &= ~ 0x00800000; // clear leading 1 bit 9792 e += 0x38800000; // adjust bias 9793 9794 mantissaTable[ i ] = m | e; 9795 9796 } 9797 9798 for ( let i = 1024; i < 2048; ++ i ) { 9799 9800 mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 ); 9801 9802 } 9803 9804 for ( let i = 1; i < 31; ++ i ) { 9805 9806 exponentTable[ i ] = i << 23; 9807 9808 } 9809 9810 exponentTable[ 31 ] = 0x47800000; 9811 exponentTable[ 32 ] = 0x80000000; 9812 9813 for ( let i = 33; i < 63; ++ i ) { 9814 9815 exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 ); 9816 9817 } 9818 9819 exponentTable[ 63 ] = 0xc7800000; 9820 9821 for ( let i = 1; i < 64; ++ i ) { 9822 9823 if ( i !== 32 ) { 9824 9825 offsetTable[ i ] = 1024; 9826 9827 } 9828 9829 } 9830 9831 return { 9832 floatView: floatView, 9833 uint32View: uint32View, 9834 baseTable: baseTable, 9835 shiftTable: shiftTable, 9836 mantissaTable: mantissaTable, 9837 exponentTable: exponentTable, 9838 offsetTable: offsetTable 9839 }; 9840 9841} 9842 9843// float32 to float16 9844 9845function toHalfFloat( val ) { 9846 9847 if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' ); 9848 9849 val = clamp( val, - 65504, 65504 ); 9850 9851 _tables.floatView[ 0 ] = val; 9852 const f = _tables.uint32View[ 0 ]; 9853 const e = ( f >> 23 ) & 0x1ff; 9854 return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] ); 9855 9856} 9857 9858// float16 to float32 9859 9860function fromHalfFloat( val ) { 9861 9862 const m = val >> 10; 9863 _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ]; 9864 return _tables.floatView[ 0 ]; 9865 9866} 9867 9868const DataUtils = { 9869 toHalfFloat: toHalfFloat, 9870 fromHalfFloat: fromHalfFloat, 9871}; 9872 9873const _vector$9 = /*@__PURE__*/ new Vector3(); 9874const _vector2$1 = /*@__PURE__*/ new Vector2(); 9875 9876class BufferAttribute { 9877 9878 constructor( array, itemSize, normalized = false ) { 9879 9880 if ( Array.isArray( array ) ) { 9881 9882 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); 9883 9884 } 9885 9886 this.isBufferAttribute = true; 9887 9888 this.name = ''; 9889 9890 this.array = array; 9891 this.itemSize = itemSize; 9892 this.count = array !== undefined ? array.length / itemSize : 0; 9893 this.normalized = normalized; 9894 9895 this.usage = StaticDrawUsage; 9896 this._updateRange = { offset: 0, count: - 1 }; 9897 this.updateRanges = []; 9898 this.gpuType = FloatType; 9899 9900 this.version = 0; 9901 9902 } 9903 9904 onUploadCallback() {} 9905 9906 set needsUpdate( value ) { 9907 9908 if ( value === true ) this.version ++; 9909 9910 } 9911 9912 get updateRange() { 9913 9914 console.warn( 'THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 9915 return this._updateRange; 9916 9917 } 9918 9919 setUsage( value ) { 9920 9921 this.usage = value; 9922 9923 return this; 9924 9925 } 9926 9927 addUpdateRange( start, count ) { 9928 9929 this.updateRanges.push( { start, count } ); 9930 9931 } 9932 9933 clearUpdateRanges() { 9934 9935 this.updateRanges.length = 0; 9936 9937 } 9938 9939 copy( source ) { 9940 9941 this.name = source.name; 9942 this.array = new source.array.constructor( source.array );
vendor: 9,245 bytes, lines 9943-10509
9943 this.itemSize = source.itemSize; 9944 this.count = source.count; 9945 this.normalized = source.normalized; 9946 9947 this.usage = source.usage; 9948 this.gpuType = source.gpuType; 9949 9950 return this; 9951 9952 } 9953 9954 copyAt( index1, attribute, index2 ) { 9955 9956 index1 *= this.itemSize; 9957 index2 *= attribute.itemSize; 9958 9959 for ( let i = 0, l = this.itemSize; i < l; i ++ ) { 9960 9961 this.array[ index1 + i ] = attribute.array[ index2 + i ]; 9962 9963 } 9964 9965 return this; 9966 9967 } 9968 9969 copyArray( array ) { 9970 9971 this.array.set( array ); 9972 9973 return this; 9974 9975 } 9976 9977 applyMatrix3( m ) { 9978 9979 if ( this.itemSize === 2 ) { 9980 9981 for ( let i = 0, l = this.count; i < l; i ++ ) { 9982 9983 _vector2$1.fromBufferAttribute( this, i ); 9984 _vector2$1.applyMatrix3( m ); 9985 9986 this.setXY( i, _vector2$1.x, _vector2$1.y ); 9987 9988 } 9989 9990 } else if ( this.itemSize === 3 ) { 9991 9992 for ( let i = 0, l = this.count; i < l; i ++ ) { 9993 9994 _vector$9.fromBufferAttribute( this, i ); 9995 _vector$9.applyMatrix3( m ); 9996 9997 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 9998 9999 } 10000 10001 } 10002 10003 return this; 10004 10005 } 10006 10007 applyMatrix4( m ) { 10008 10009 for ( let i = 0, l = this.count; i < l; i ++ ) { 10010 10011 _vector$9.fromBufferAttribute( this, i ); 10012 10013 _vector$9.applyMatrix4( m ); 10014 10015 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 10016 10017 } 10018 10019 return this; 10020 10021 } 10022 10023 applyNormalMatrix( m ) { 10024 10025 for ( let i = 0, l = this.count; i < l; i ++ ) { 10026 10027 _vector$9.fromBufferAttribute( this, i ); 10028 10029 _vector$9.applyNormalMatrix( m ); 10030 10031 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 10032 10033 } 10034 10035 return this; 10036 10037 } 10038 10039 transformDirection( m ) { 10040 10041 for ( let i = 0, l = this.count; i < l; i ++ ) { 10042 10043 _vector$9.fromBufferAttribute( this, i ); 10044 10045 _vector$9.transformDirection( m ); 10046 10047 this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); 10048 10049 } 10050 10051 return this; 10052 10053 } 10054 10055 set( value, offset = 0 ) { 10056 10057 // Matching BufferAttribute constructor, do not normalize the array. 10058 this.array.set( value, offset ); 10059 10060 return this; 10061 10062 } 10063 10064 getComponent( index, component ) { 10065 10066 let value = this.array[ index * this.itemSize + component ]; 10067 10068 if ( this.normalized ) value = denormalize( value, this.array ); 10069 10070 return value; 10071 10072 } 10073 10074 setComponent( index, component, value ) { 10075 10076 if ( this.normalized ) value = normalize( value, this.array ); 10077 10078 this.array[ index * this.itemSize + component ] = value; 10079 10080 return this; 10081 10082 } 10083 10084 getX( index ) { 10085 10086 let x = this.array[ index * this.itemSize ]; 10087 10088 if ( this.normalized ) x = denormalize( x, this.array ); 10089 10090 return x; 10091 10092 } 10093 10094 setX( index, x ) { 10095 10096 if ( this.normalized ) x = normalize( x, this.array ); 10097 10098 this.array[ index * this.itemSize ] = x; 10099 10100 return this; 10101 10102 } 10103 10104 getY( index ) { 10105 10106 let y = this.array[ index * this.itemSize + 1 ]; 10107 10108 if ( this.normalized ) y = denormalize( y, this.array ); 10109 10110 return y; 10111 10112 } 10113 10114 setY( index, y ) { 10115 10116 if ( this.normalized ) y = normalize( y, this.array ); 10117 10118 this.array[ index * this.itemSize + 1 ] = y; 10119 10120 return this; 10121 10122 } 10123 10124 getZ( index ) { 10125 10126 let z = this.array[ index * this.itemSize + 2 ]; 10127 10128 if ( this.normalized ) z = denormalize( z, this.array ); 10129 10130 return z; 10131 10132 } 10133 10134 setZ( index, z ) { 10135 10136 if ( this.normalized ) z = normalize( z, this.array ); 10137 10138 this.array[ index * this.itemSize + 2 ] = z; 10139 10140 return this; 10141 10142 } 10143 10144 getW( index ) { 10145 10146 let w = this.array[ index * this.itemSize + 3 ]; 10147 10148 if ( this.normalized ) w = denormalize( w, this.array ); 10149 10150 return w; 10151 10152 } 10153 10154 setW( index, w ) { 10155 10156 if ( this.normalized ) w = normalize( w, this.array ); 10157 10158 this.array[ index * this.itemSize + 3 ] = w; 10159 10160 return this; 10161 10162 } 10163 10164 setXY( index, x, y ) { 10165 10166 index *= this.itemSize; 10167 10168 if ( this.normalized ) { 10169 10170 x = normalize( x, this.array ); 10171 y = normalize( y, this.array ); 10172 10173 } 10174 10175 this.array[ index + 0 ] = x; 10176 this.array[ index + 1 ] = y; 10177 10178 return this; 10179 10180 } 10181 10182 setXYZ( index, x, y, z ) { 10183 10184 index *= this.itemSize; 10185 10186 if ( this.normalized ) { 10187 10188 x = normalize( x, this.array ); 10189 y = normalize( y, this.array ); 10190 z = normalize( z, this.array ); 10191 10192 } 10193 10194 this.array[ index + 0 ] = x; 10195 this.array[ index + 1 ] = y; 10196 this.array[ index + 2 ] = z; 10197 10198 return this; 10199 10200 } 10201 10202 setXYZW( index, x, y, z, w ) { 10203 10204 index *= this.itemSize; 10205 10206 if ( this.normalized ) { 10207 10208 x = normalize( x, this.array ); 10209 y = normalize( y, this.array ); 10210 z = normalize( z, this.array ); 10211 w = normalize( w, this.array ); 10212 10213 } 10214 10215 this.array[ index + 0 ] = x; 10216 this.array[ index + 1 ] = y; 10217 this.array[ index + 2 ] = z; 10218 this.array[ index + 3 ] = w; 10219 10220 return this; 10221 10222 } 10223 10224 onUpload( callback ) { 10225 10226 this.onUploadCallback = callback; 10227 10228 return this; 10229 10230 } 10231 10232 clone() { 10233 10234 return new this.constructor( this.array, this.itemSize ).copy( this ); 10235 10236 } 10237 10238 toJSON() { 10239 10240 const data = { 10241 itemSize: this.itemSize, 10242 type: this.array.constructor.name, 10243 array: Array.from( this.array ), 10244 normalized: this.normalized 10245 }; 10246 10247 if ( this.name !== '' ) data.name = this.name; 10248 if ( this.usage !== StaticDrawUsage ) data.usage = this.usage; 10249 10250 return data; 10251 10252 } 10253 10254} 10255 10256// 10257 10258class Int8BufferAttribute extends BufferAttribute { 10259 10260 constructor( array, itemSize, normalized ) { 10261 10262 super( new Int8Array( array ), itemSize, normalized ); 10263 10264 } 10265 10266} 10267 10268class Uint8BufferAttribute extends BufferAttribute { 10269 10270 constructor( array, itemSize, normalized ) { 10271 10272 super( new Uint8Array( array ), itemSize, normalized ); 10273 10274 } 10275 10276} 10277 10278class Uint8ClampedBufferAttribute extends BufferAttribute { 10279 10280 constructor( array, itemSize, normalized ) { 10281 10282 super( new Uint8ClampedArray( array ), itemSize, normalized ); 10283 10284 } 10285 10286} 10287 10288class Int16BufferAttribute extends BufferAttribute { 10289 10290 constructor( array, itemSize, normalized ) { 10291 10292 super( new Int16Array( array ), itemSize, normalized ); 10293 10294 } 10295 10296} 10297 10298class Uint16BufferAttribute extends BufferAttribute { 10299 10300 constructor( array, itemSize, normalized ) { 10301 10302 super( new Uint16Array( array ), itemSize, normalized ); 10303 10304 } 10305 10306} 10307 10308class Int32BufferAttribute extends BufferAttribute { 10309 10310 constructor( array, itemSize, normalized ) { 10311 10312 super( new Int32Array( array ), itemSize, normalized ); 10313 10314 } 10315 10316} 10317 10318class Uint32BufferAttribute extends BufferAttribute { 10319 10320 constructor( array, itemSize, normalized ) { 10321 10322 super( new Uint32Array( array ), itemSize, normalized ); 10323 10324 } 10325 10326} 10327 10328class Float16BufferAttribute extends BufferAttribute { 10329 10330 constructor( array, itemSize, normalized ) { 10331 10332 super( new Uint16Array( array ), itemSize, normalized ); 10333 10334 this.isFloat16BufferAttribute = true; 10335 10336 } 10337 10338 getX( index ) { 10339 10340 let x = fromHalfFloat( this.array[ index * this.itemSize ] ); 10341 10342 if ( this.normalized ) x = denormalize( x, this.array ); 10343 10344 return x; 10345 10346 } 10347 10348 setX( index, x ) { 10349 10350 if ( this.normalized ) x = normalize( x, this.array ); 10351 10352 this.array[ index * this.itemSize ] = toHalfFloat( x ); 10353 10354 return this; 10355 10356 } 10357 10358 getY( index ) { 10359 10360 let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] ); 10361 10362 if ( this.normalized ) y = denormalize( y, this.array ); 10363 10364 return y; 10365 10366 } 10367 10368 setY( index, y ) { 10369 10370 if ( this.normalized ) y = normalize( y, this.array ); 10371 10372 this.array[ index * this.itemSize + 1 ] = toHalfFloat( y ); 10373 10374 return this; 10375 10376 } 10377 10378 getZ( index ) { 10379 10380 let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] ); 10381 10382 if ( this.normalized ) z = denormalize( z, this.array ); 10383 10384 return z; 10385 10386 } 10387 10388 setZ( index, z ) { 10389 10390 if ( this.normalized ) z = normalize( z, this.array ); 10391 10392 this.array[ index * this.itemSize + 2 ] = toHalfFloat( z ); 10393 10394 return this; 10395 10396 } 10397 10398 getW( index ) { 10399 10400 let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] ); 10401 10402 if ( this.normalized ) w = denormalize( w, this.array ); 10403 10404 return w; 10405 10406 } 10407 10408 setW( index, w ) { 10409 10410 if ( this.normalized ) w = normalize( w, this.array ); 10411 10412 this.array[ index * this.itemSize + 3 ] = toHalfFloat( w ); 10413 10414 return this; 10415 10416 } 10417 10418 setXY( index, x, y ) { 10419 10420 index *= this.itemSize; 10421 10422 if ( this.normalized ) { 10423 10424 x = normalize( x, this.array ); 10425 y = normalize( y, this.array ); 10426 10427 } 10428 10429 this.array[ index + 0 ] = toHalfFloat( x ); 10430 this.array[ index + 1 ] = toHalfFloat( y ); 10431 10432 return this; 10433 10434 } 10435 10436 setXYZ( index, x, y, z ) { 10437 10438 index *= this.itemSize; 10439 10440 if ( this.normalized ) { 10441 10442 x = normalize( x, this.array ); 10443 y = normalize( y, this.array ); 10444 z = normalize( z, this.array ); 10445 10446 } 10447 10448 this.array[ index + 0 ] = toHalfFloat( x ); 10449 this.array[ index + 1 ] = toHalfFloat( y ); 10450 this.array[ index + 2 ] = toHalfFloat( z ); 10451 10452 return this; 10453 10454 } 10455 10456 setXYZW( index, x, y, z, w ) { 10457 10458 index *= this.itemSize; 10459 10460 if ( this.normalized ) { 10461 10462 x = normalize( x, this.array ); 10463 y = normalize( y, this.array ); 10464 z = normalize( z, this.array ); 10465 w = normalize( w, this.array ); 10466 10467 } 10468 10469 this.array[ index + 0 ] = toHalfFloat( x ); 10470 this.array[ index + 1 ] = toHalfFloat( y ); 10471 this.array[ index + 2 ] = toHalfFloat( z ); 10472 this.array[ index + 3 ] = toHalfFloat( w ); 10473 10474 return this; 10475 10476 } 10477 10478} 10479 10480 10481class Float32BufferAttribute extends BufferAttribute { 10482 10483 constructor( array, itemSize, normalized ) { 10484 10485 super( new Float32Array( array ), itemSize, normalized ); 10486 10487 } 10488 10489} 10490 10491class Float64BufferAttribute extends BufferAttribute { 10492 10493 constructor( array, itemSize, normalized ) { 10494 10495 super( new Float64Array( array ), itemSize, normalized ); 10496 10497 } 10498 10499} 10500 10501let _id$2 = 0; 10502 10503const _m1 = /*@__PURE__*/ new Matrix4(); 10504const _obj = /*@__PURE__*/ new Object3D(); 10505const _offset = /*@__PURE__*/ new Vector3(); 10506const _box$2 = /*@__PURE__*/ new Box3(); 10507const _boxMorphTargets = /*@__PURE__*/ new Box3(); 10508const _vector$8 = /*@__PURE__*/ new Vector3(); 10509
vendor: 5,687 bytes, lines 10510-10861
10510class BufferGeometry extends EventDispatcher { 10511 10512 constructor() { 10513 10514 super(); 10515 10516 this.isBufferGeometry = true; 10517 10518 Object.defineProperty( this, 'id', { value: _id$2 ++ } ); 10519 10520 this.uuid = generateUUID(); 10521 10522 this.name = ''; 10523 this.type = 'BufferGeometry'; 10524 10525 this.index = null; 10526 this.attributes = {}; 10527 10528 this.morphAttributes = {}; 10529 this.morphTargetsRelative = false; 10530 10531 this.groups = []; 10532 10533 this.boundingBox = null; 10534 this.boundingSphere = null; 10535 10536 this.drawRange = { start: 0, count: Infinity }; 10537 10538 this.userData = {}; 10539 10540 } 10541 10542 getIndex() { 10543 10544 return this.index; 10545 10546 } 10547 10548 setIndex( index ) { 10549 10550 if ( Array.isArray( index ) ) { 10551 10552 this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); 10553 10554 } else { 10555 10556 this.index = index; 10557 10558 } 10559 10560 return this; 10561 10562 } 10563 10564 getAttribute( name ) { 10565 10566 return this.attributes[ name ]; 10567 10568 } 10569 10570 setAttribute( name, attribute ) { 10571 10572 this.attributes[ name ] = attribute; 10573 10574 return this; 10575 10576 } 10577 10578 deleteAttribute( name ) { 10579 10580 delete this.attributes[ name ]; 10581 10582 return this; 10583 10584 } 10585 10586 hasAttribute( name ) { 10587 10588 return this.attributes[ name ] !== undefined; 10589 10590 } 10591 10592 addGroup( start, count, materialIndex = 0 ) { 10593 10594 this.groups.push( { 10595 10596 start: start, 10597 count: count, 10598 materialIndex: materialIndex 10599 10600 } ); 10601 10602 } 10603 10604 clearGroups() { 10605 10606 this.groups = []; 10607 10608 } 10609 10610 setDrawRange( start, count ) { 10611 10612 this.drawRange.start = start; 10613 this.drawRange.count = count; 10614 10615 } 10616 10617 applyMatrix4( matrix ) { 10618 10619 const position = this.attributes.position; 10620 10621 if ( position !== undefined ) { 10622 10623 position.applyMatrix4( matrix ); 10624 10625 position.needsUpdate = true; 10626 10627 } 10628 10629 const normal = this.attributes.normal; 10630 10631 if ( normal !== undefined ) { 10632 10633 const normalMatrix = new Matrix3().getNormalMatrix( matrix ); 10634 10635 normal.applyNormalMatrix( normalMatrix ); 10636 10637 normal.needsUpdate = true; 10638 10639 } 10640 10641 const tangent = this.attributes.tangent; 10642 10643 if ( tangent !== undefined ) { 10644 10645 tangent.transformDirection( matrix ); 10646 10647 tangent.needsUpdate = true; 10648 10649 } 10650 10651 if ( this.boundingBox !== null ) { 10652 10653 this.computeBoundingBox(); 10654 10655 } 10656 10657 if ( this.boundingSphere !== null ) { 10658 10659 this.computeBoundingSphere(); 10660 10661 } 10662 10663 return this; 10664 10665 } 10666 10667 applyQuaternion( q ) { 10668 10669 _m1.makeRotationFromQuaternion( q ); 10670 10671 this.applyMatrix4( _m1 ); 10672 10673 return this; 10674 10675 } 10676 10677 rotateX( angle ) { 10678 10679 // rotate geometry around world x-axis 10680 10681 _m1.makeRotationX( angle ); 10682 10683 this.applyMatrix4( _m1 ); 10684 10685 return this; 10686 10687 } 10688 10689 rotateY( angle ) { 10690 10691 // rotate geometry around world y-axis 10692 10693 _m1.makeRotationY( angle ); 10694 10695 this.applyMatrix4( _m1 ); 10696 10697 return this; 10698 10699 } 10700 10701 rotateZ( angle ) { 10702 10703 // rotate geometry around world z-axis 10704 10705 _m1.makeRotationZ( angle ); 10706 10707 this.applyMatrix4( _m1 ); 10708 10709 return this; 10710 10711 } 10712 10713 translate( x, y, z ) { 10714 10715 // translate geometry 10716 10717 _m1.makeTranslation( x, y, z ); 10718 10719 this.applyMatrix4( _m1 ); 10720 10721 return this; 10722 10723 } 10724 10725 scale( x, y, z ) { 10726 10727 // scale geometry 10728 10729 _m1.makeScale( x, y, z ); 10730 10731 this.applyMatrix4( _m1 ); 10732 10733 return this; 10734 10735 } 10736 10737 lookAt( vector ) { 10738 10739 _obj.lookAt( vector ); 10740 10741 _obj.updateMatrix(); 10742 10743 this.applyMatrix4( _obj.matrix ); 10744 10745 return this; 10746 10747 } 10748 10749 center() { 10750 10751 this.computeBoundingBox(); 10752 10753 this.boundingBox.getCenter( _offset ).negate(); 10754 10755 this.translate( _offset.x, _offset.y, _offset.z ); 10756 10757 return this; 10758 10759 } 10760 10761 setFromPoints( points ) { 10762 10763 const position = []; 10764 10765 for ( let i = 0, l = points.length; i < l; i ++ ) { 10766 10767 const point = points[ i ]; 10768 position.push( point.x, point.y, point.z || 0 ); 10769 10770 } 10771 10772 this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); 10773 10774 return this; 10775 10776 } 10777 10778 computeBoundingBox() { 10779 10780 if ( this.boundingBox === null ) { 10781 10782 this.boundingBox = new Box3(); 10783 10784 } 10785 10786 const position = this.attributes.position; 10787 const morphAttributesPosition = this.morphAttributes.position; 10788 10789 if ( position && position.isGLBufferAttribute ) { 10790 10791 console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this ); 10792 10793 this.boundingBox.set( 10794 new Vector3( - Infinity, - Infinity, - Infinity ), 10795 new Vector3( + Infinity, + Infinity, + Infinity ) 10796 ); 10797 10798 return; 10799 10800 } 10801 10802 if ( position !== undefined ) { 10803 10804 this.boundingBox.setFromBufferAttribute( position ); 10805 10806 // process morph attributes if present 10807 10808 if ( morphAttributesPosition ) { 10809 10810 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { 10811 10812 const morphAttribute = morphAttributesPosition[ i ]; 10813 _box$2.setFromBufferAttribute( morphAttribute ); 10814 10815 if ( this.morphTargetsRelative ) { 10816 10817 _vector$8.addVectors( this.boundingBox.min, _box$2.min ); 10818 this.boundingBox.expandByPoint( _vector$8 ); 10819 10820 _vector$8.addVectors( this.boundingBox.max, _box$2.max ); 10821 this.boundingBox.expandByPoint( _vector$8 ); 10822 10823 } else { 10824 10825 this.boundingBox.expandByPoint( _box$2.min ); 10826 this.boundingBox.expandByPoint( _box$2.max ); 10827 10828 } 10829 10830 } 10831 10832 } 10833 10834 } else { 10835 10836 this.boundingBox.makeEmpty(); 10837 10838 } 10839 10840 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { 10841 10842 console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); 10843 10844 } 10845 10846 } 10847 10848 computeBoundingSphere() { 10849 10850 if ( this.boundingSphere === null ) { 10851 10852 this.boundingSphere = new Sphere(); 10853 10854 } 10855 10856 const position = this.attributes.position; 10857 const morphAttributesPosition = this.morphAttributes.position; 10858 10859 if ( position && position.isGLBufferAttribute ) { 10860 10861 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "fal
vendor: 5,692 bytes, lines 10861-11117
10861se".', this ); 10862 10863 this.boundingSphere.set( new Vector3(), Infinity ); 10864 10865 return; 10866 10867 } 10868 10869 if ( position ) { 10870 10871 // first, find the center of the bounding sphere 10872 10873 const center = this.boundingSphere.center; 10874 10875 _box$2.setFromBufferAttribute( position ); 10876 10877 // process morph attributes if present 10878 10879 if ( morphAttributesPosition ) { 10880 10881 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { 10882 10883 const morphAttribute = morphAttributesPosition[ i ]; 10884 _boxMorphTargets.setFromBufferAttribute( morphAttribute ); 10885 10886 if ( this.morphTargetsRelative ) { 10887 10888 _vector$8.addVectors( _box$2.min, _boxMorphTargets.min ); 10889 _box$2.expandByPoint( _vector$8 ); 10890 10891 _vector$8.addVectors( _box$2.max, _boxMorphTargets.max ); 10892 _box$2.expandByPoint( _vector$8 ); 10893 10894 } else { 10895 10896 _box$2.expandByPoint( _boxMorphTargets.min ); 10897 _box$2.expandByPoint( _boxMorphTargets.max ); 10898 10899 } 10900 10901 } 10902 10903 } 10904 10905 _box$2.getCenter( center ); 10906 10907 // second, try to find a boundingSphere with a radius smaller than the 10908 // boundingSphere of the boundingBox: sqrt(3) smaller in the best case 10909 10910 let maxRadiusSq = 0; 10911 10912 for ( let i = 0, il = position.count; i < il; i ++ ) { 10913 10914 _vector$8.fromBufferAttribute( position, i ); 10915 10916 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); 10917 10918 } 10919 10920 // process morph attributes if present 10921 10922 if ( morphAttributesPosition ) { 10923 10924 for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { 10925 10926 const morphAttribute = morphAttributesPosition[ i ]; 10927 const morphTargetsRelative = this.morphTargetsRelative; 10928 10929 for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) { 10930 10931 _vector$8.fromBufferAttribute( morphAttribute, j ); 10932 10933 if ( morphTargetsRelative ) { 10934 10935 _offset.fromBufferAttribute( position, j ); 10936 _vector$8.add( _offset ); 10937 10938 } 10939 10940 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); 10941 10942 } 10943 10944 } 10945 10946 } 10947 10948 this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); 10949 10950 if ( isNaN( this.boundingSphere.radius ) ) { 10951 10952 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); 10953 10954 } 10955 10956 } 10957 10958 } 10959 10960 computeTangents() { 10961 10962 const index = this.index; 10963 const attributes = this.attributes; 10964 10965 // based on http://www.terathon.com/code/tangent.html 10966 // (per vertex tangents) 10967 10968 if ( index === null || 10969 attributes.position === undefined || 10970 attributes.normal === undefined || 10971 attributes.uv === undefined ) { 10972 10973 console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' ); 10974 return; 10975 10976 } 10977 10978 const indices = index.array; 10979 const positions = attributes.position.array; 10980 const normals = attributes.normal.array; 10981 const uvs = attributes.uv.array; 10982 10983 const nVertices = positions.length / 3; 10984 10985 if ( this.hasAttribute( 'tangent' ) === false ) { 10986 10987 this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) ); 10988 10989 } 10990 10991 const tangents = this.getAttribute( 'tangent' ).array; 10992 10993 const tan1 = [], tan2 = []; 10994 10995 for ( let i = 0; i < nVertices; i ++ ) { 10996 10997 tan1[ i ] = new Vector3(); 10998 tan2[ i ] = new Vector3(); 10999 11000 } 11001 11002 const vA = new Vector3(), 11003 vB = new Vector3(), 11004 vC = new Vector3(), 11005 11006 uvA = new Vector2(), 11007 uvB = new Vector2(), 11008 uvC = new Vector2(), 11009 11010 sdir = new Vector3(), 11011 tdir = new Vector3(); 11012 11013 function handleTriangle( a, b, c ) { 11014 11015 vA.fromArray( positions, a * 3 ); 11016 vB.fromArray( positions, b * 3 ); 11017 vC.fromArray( positions, c * 3 ); 11018 11019 uvA.fromArray( uvs, a * 2 ); 11020 uvB.fromArray( uvs, b * 2 ); 11021 uvC.fromArray( uvs, c * 2 ); 11022 11023 vB.sub( vA ); 11024 vC.sub( vA ); 11025 11026 uvB.sub( uvA ); 11027 uvC.sub( uvA ); 11028 11029 const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y ); 11030 11031 // silently ignore degenerate uv triangles having coincident or colinear vertices 11032 11033 if ( ! isFinite( r ) ) return; 11034 11035 sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r ); 11036 tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r ); 11037 11038 tan1[ a ].add( sdir ); 11039 tan1[ b ].add( sdir ); 11040 tan1[ c ].add( sdir ); 11041 11042 tan2[ a ].add( tdir ); 11043 tan2[ b ].add( tdir ); 11044 tan2[ c ].add( tdir ); 11045 11046 } 11047 11048 let groups = this.groups; 11049 11050 if ( groups.length === 0 ) { 11051 11052 groups = [ { 11053 start: 0, 11054 count: indices.length 11055 } ]; 11056 11057 } 11058 11059 for ( let i = 0, il = groups.length; i < il; ++ i ) { 11060 11061 const group = groups[ i ]; 11062 11063 const start = group.start; 11064 const count = group.count; 11065 11066 for ( let j = start, jl = start + count; j < jl; j += 3 ) { 11067 11068 handleTriangle( 11069 indices[ j + 0 ], 11070 indices[ j + 1 ], 11071 indices[ j + 2 ] 11072 ); 11073 11074 } 11075 11076 } 11077 11078 const tmp = new Vector3(), tmp2 = new Vector3(); 11079 const n = new Vector3(), n2 = new Vector3(); 11080 11081 function handleVertex( v ) { 11082 11083 n.fromArray( normals, v * 3 ); 11084 n2.copy( n ); 11085 11086 const t = tan1[ v ]; 11087 11088 // Gram-Schmidt orthogonalize 11089 11090 tmp.copy( t ); 11091 tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize(); 11092 11093 // Calculate handedness 11094 11095 tmp2.crossVectors( n2, t ); 11096 const test = tmp2.dot( tan2[ v ] ); 11097 const w = ( test < 0.0 ) ? - 1.0 : 1.0; 11098 11099 tangents[ v * 4 ] = tmp.x; 11100 tangents[ v * 4 + 1 ] = tmp.y; 11101 tangents[ v * 4 + 2 ] = tmp.z; 11102 tangents[ v * 4 + 3 ] = w; 11103 11104 } 11105 11106 for ( let i = 0, il = groups.length; i < il; ++ i ) { 11107 11108 const group = groups[ i ]; 11109 11110 const start = group.start; 11111 const count = group.count; 11112 11113 for ( let j = start, jl = start + count; j < jl; j += 3 ) { 11114 11115 handleVertex( indices[ j + 0 ] ); 11116 handleVertex( indices[ j + 1 ] ); 11117 handleVertex( indices[ j + 2 ]
vendor: 18,013 bytes, lines 11117-11945
11117 ); 11118 11119 } 11120 11121 } 11122 11123 } 11124 11125 computeVertexNormals() { 11126 11127 const index = this.index; 11128 const positionAttribute = this.getAttribute( 'position' ); 11129 11130 if ( positionAttribute !== undefined ) { 11131 11132 let normalAttribute = this.getAttribute( 'normal' ); 11133 11134 if ( normalAttribute === undefined ) { 11135 11136 normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 ); 11137 this.setAttribute( 'normal', normalAttribute ); 11138 11139 } else { 11140 11141 // reset existing normals to zero 11142 11143 for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) { 11144 11145 normalAttribute.setXYZ( i, 0, 0, 0 ); 11146 11147 } 11148 11149 } 11150 11151 const pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); 11152 const nA = new Vector3(), nB = new Vector3(), nC = new Vector3(); 11153 const cb = new Vector3(), ab = new Vector3(); 11154 11155 // indexed elements 11156 11157 if ( index ) { 11158 11159 for ( let i = 0, il = index.count; i < il; i += 3 ) { 11160 11161 const vA = index.getX( i + 0 ); 11162 const vB = index.getX( i + 1 ); 11163 const vC = index.getX( i + 2 ); 11164 11165 pA.fromBufferAttribute( positionAttribute, vA ); 11166 pB.fromBufferAttribute( positionAttribute, vB ); 11167 pC.fromBufferAttribute( positionAttribute, vC ); 11168 11169 cb.subVectors( pC, pB ); 11170 ab.subVectors( pA, pB ); 11171 cb.cross( ab ); 11172 11173 nA.fromBufferAttribute( normalAttribute, vA ); 11174 nB.fromBufferAttribute( normalAttribute, vB ); 11175 nC.fromBufferAttribute( normalAttribute, vC ); 11176 11177 nA.add( cb ); 11178 nB.add( cb ); 11179 nC.add( cb ); 11180 11181 normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z ); 11182 normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z ); 11183 normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z ); 11184 11185 } 11186 11187 } else { 11188 11189 // non-indexed elements (unconnected triangle soup) 11190 11191 for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) { 11192 11193 pA.fromBufferAttribute( positionAttribute, i + 0 ); 11194 pB.fromBufferAttribute( positionAttribute, i + 1 ); 11195 pC.fromBufferAttribute( positionAttribute, i + 2 ); 11196 11197 cb.subVectors( pC, pB ); 11198 ab.subVectors( pA, pB ); 11199 cb.cross( ab ); 11200 11201 normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z ); 11202 normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z ); 11203 normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z ); 11204 11205 } 11206 11207 } 11208 11209 this.normalizeNormals(); 11210 11211 normalAttribute.needsUpdate = true; 11212 11213 } 11214 11215 } 11216 11217 normalizeNormals() { 11218 11219 const normals = this.attributes.normal; 11220 11221 for ( let i = 0, il = normals.count; i < il; i ++ ) { 11222 11223 _vector$8.fromBufferAttribute( normals, i ); 11224 11225 _vector$8.normalize(); 11226 11227 normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); 11228 11229 } 11230 11231 } 11232 11233 toNonIndexed() { 11234 11235 function convertBufferAttribute( attribute, indices ) { 11236 11237 const array = attribute.array; 11238 const itemSize = attribute.itemSize; 11239 const normalized = attribute.normalized; 11240 11241 const array2 = new array.constructor( indices.length * itemSize ); 11242 11243 let index = 0, index2 = 0; 11244 11245 for ( let i = 0, l = indices.length; i < l; i ++ ) { 11246 11247 if ( attribute.isInterleavedBufferAttribute ) { 11248 11249 index = indices[ i ] * attribute.data.stride + attribute.offset; 11250 11251 } else { 11252 11253 index = indices[ i ] * itemSize; 11254 11255 } 11256 11257 for ( let j = 0; j < itemSize; j ++ ) { 11258 11259 array2[ index2 ++ ] = array[ index ++ ]; 11260 11261 } 11262 11263 } 11264 11265 return new BufferAttribute( array2, itemSize, normalized ); 11266 11267 } 11268 11269 // 11270 11271 if ( this.index === null ) { 11272 11273 console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' ); 11274 return this; 11275 11276 } 11277 11278 const geometry2 = new BufferGeometry(); 11279 11280 const indices = this.index.array; 11281 const attributes = this.attributes; 11282 11283 // attributes 11284 11285 for ( const name in attributes ) { 11286 11287 const attribute = attributes[ name ]; 11288 11289 const newAttribute = convertBufferAttribute( attribute, indices ); 11290 11291 geometry2.setAttribute( name, newAttribute ); 11292 11293 } 11294 11295 // morph attributes 11296 11297 const morphAttributes = this.morphAttributes; 11298 11299 for ( const name in morphAttributes ) { 11300 11301 const morphArray = []; 11302 const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes 11303 11304 for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) { 11305 11306 const attribute = morphAttribute[ i ]; 11307 11308 const newAttribute = convertBufferAttribute( attribute, indices ); 11309 11310 morphArray.push( newAttribute ); 11311 11312 } 11313 11314 geometry2.morphAttributes[ name ] = morphArray; 11315 11316 } 11317 11318 geometry2.morphTargetsRelative = this.morphTargetsRelative; 11319 11320 // groups 11321 11322 const groups = this.groups; 11323 11324 for ( let i = 0, l = groups.length; i < l; i ++ ) { 11325 11326 const group = groups[ i ]; 11327 geometry2.addGroup( group.start, group.count, group.materialIndex ); 11328 11329 } 11330 11331 return geometry2; 11332 11333 } 11334 11335 toJSON() { 11336 11337 const data = { 11338 metadata: { 11339 version: 4.6, 11340 type: 'BufferGeometry', 11341 generator: 'BufferGeometry.toJSON' 11342 } 11343 }; 11344 11345 // standard BufferGeometry serialization 11346 11347 data.uuid = this.uuid; 11348 data.type = this.type; 11349 if ( this.name !== '' ) data.name = this.name; 11350 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; 11351 11352 if ( this.parameters !== undefined ) { 11353 11354 const parameters = this.parameters; 11355 11356 for ( const key in parameters ) { 11357 11358 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; 11359 11360 } 11361 11362 return data; 11363 11364 } 11365 11366 // for simplicity the code assumes attributes are not shared across geometries, see #15811 11367 11368 data.data = { attributes: {} }; 11369 11370 const index = this.index; 11371 11372 if ( index !== null ) { 11373 11374 data.data.index = { 11375 type: index.array.constructor.name, 11376 array: Array.prototype.slice.call( index.array ) 11377 }; 11378 11379 } 11380 11381 const attributes = this.attributes; 11382 11383 for ( const key in attributes ) { 11384 11385 const attribute = attributes[ key ]; 11386 11387 data.data.attributes[ key ] = attribute.toJSON( data.data ); 11388 11389 } 11390 11391 const morphAttributes = {}; 11392 let hasMorphAttributes = false; 11393 11394 for ( const key in this.morphAttributes ) { 11395 11396 const attributeArray = this.morphAttributes[ key ]; 11397 11398 const array = []; 11399 11400 for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { 11401 11402 const attribute = attributeArray[ i ]; 11403 11404 array.push( attribute.toJSON( data.data ) ); 11405 11406 } 11407 11408 if ( array.length > 0 ) { 11409 11410 morphAttributes[ key ] = array; 11411 11412 hasMorphAttributes = true; 11413 11414 } 11415 11416 } 11417 11418 if ( hasMorphAttributes ) { 11419 11420 data.data.morphAttributes = morphAttributes; 11421 data.data.morphTargetsRelative = this.morphTargetsRelative; 11422 11423 } 11424 11425 const groups = this.groups; 11426 11427 if ( groups.length > 0 ) { 11428 11429 data.data.groups = JSON.parse( JSON.stringify( groups ) ); 11430 11431 } 11432 11433 const boundingSphere = this.boundingSphere; 11434 11435 if ( boundingSphere !== null ) { 11436 11437 data.data.boundingSphere = { 11438 center: boundingSphere.center.toArray(), 11439 radius: boundingSphere.radius 11440 }; 11441 11442 } 11443 11444 return data; 11445 11446 } 11447 11448 clone() { 11449 11450 return new this.constructor().copy( this ); 11451 11452 } 11453 11454 copy( source ) { 11455 11456 // reset 11457 11458 this.index = null; 11459 this.attributes = {}; 11460 this.morphAttributes = {}; 11461 this.groups = []; 11462 this.boundingBox = null; 11463 this.boundingSphere = null; 11464 11465 // used for storing cloned, shared data 11466 11467 const data = {}; 11468 11469 // name 11470 11471 this.name = source.name; 11472 11473 // index 11474 11475 const index = source.index; 11476 11477 if ( index !== null ) { 11478 11479 this.setIndex( index.clone( data ) ); 11480 11481 } 11482 11483 // attributes 11484 11485 const attributes = source.attributes; 11486 11487 for ( const name in attributes ) { 11488 11489 const attribute = attributes[ name ]; 11490 this.setAttribute( name, attribute.clone( data ) ); 11491 11492 } 11493 11494 // morph attributes 11495 11496 const morphAttributes = source.morphAttributes; 11497 11498 for ( const name in morphAttributes ) { 11499 11500 const array = []; 11501 const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes 11502 11503 for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) { 11504 11505 array.push( morphAttribute[ i ].clone( data ) ); 11506 11507 } 11508 11509 this.morphAttributes[ name ] = array; 11510 11511 } 11512 11513 this.morphTargetsRelative = source.morphTargetsRelative; 11514 11515 // groups 11516 11517 const groups = source.groups; 11518 11519 for ( let i = 0, l = groups.length; i < l; i ++ ) { 11520 11521 const group = groups[ i ]; 11522 this.addGroup( group.start, group.count, group.materialIndex ); 11523 11524 } 11525 11526 // bounding box 11527 11528 const boundingBox = source.boundingBox; 11529 11530 if ( boundingBox !== null ) { 11531 11532 this.boundingBox = boundingBox.clone(); 11533 11534 } 11535 11536 // bounding sphere 11537 11538 const boundingSphere = source.boundingSphere; 11539 11540 if ( boundingSphere !== null ) { 11541 11542 this.boundingSphere = boundingSphere.clone(); 11543 11544 } 11545 11546 // draw range 11547 11548 this.drawRange.start = source.drawRange.start; 11549 this.drawRange.count = source.drawRange.count; 11550 11551 // user data 11552 11553 this.userData = source.userData; 11554 11555 return this; 11556 11557 } 11558 11559 dispose() { 11560 11561 this.dispatchEvent( { type: 'dispose' } ); 11562 11563 } 11564 11565} 11566 11567const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4(); 11568const _ray$3 = /*@__PURE__*/ new Ray(); 11569const _sphere$6 = /*@__PURE__*/ new Sphere(); 11570const _sphereHitAt = /*@__PURE__*/ new Vector3(); 11571 11572const _vA$1 = /*@__PURE__*/ new Vector3(); 11573const _vB$1 = /*@__PURE__*/ new Vector3(); 11574const _vC$1 = /*@__PURE__*/ new Vector3(); 11575 11576const _tempA = /*@__PURE__*/ new Vector3(); 11577const _morphA = /*@__PURE__*/ new Vector3(); 11578 11579const _uvA$1 = /*@__PURE__*/ new Vector2(); 11580const _uvB$1 = /*@__PURE__*/ new Vector2(); 11581const _uvC$1 = /*@__PURE__*/ new Vector2(); 11582 11583const _normalA = /*@__PURE__*/ new Vector3(); 11584const _normalB = /*@__PURE__*/ new Vector3(); 11585const _normalC = /*@__PURE__*/ new Vector3(); 11586 11587const _intersectionPoint = /*@__PURE__*/ new Vector3(); 11588const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); 11589 11590class Mesh extends Object3D { 11591 11592 constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) { 11593 11594 super(); 11595 11596 this.isMesh = true; 11597 11598 this.type = 'Mesh'; 11599 11600 this.geometry = geometry; 11601 this.material = material; 11602 11603 this.updateMorphTargets(); 11604 11605 } 11606 11607 copy( source, recursive ) { 11608 11609 super.copy( source, recursive ); 11610 11611 if ( source.morphTargetInfluences !== undefined ) { 11612 11613 this.morphTargetInfluences = source.morphTargetInfluences.slice(); 11614 11615 } 11616 11617 if ( source.morphTargetDictionary !== undefined ) { 11618 11619 this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); 11620 11621 } 11622 11623 this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; 11624 this.geometry = source.geometry; 11625 11626 return this; 11627 11628 } 11629 11630 updateMorphTargets() { 11631 11632 const geometry = this.geometry; 11633 11634 const morphAttributes = geometry.morphAttributes; 11635 const keys = Object.keys( morphAttributes ); 11636 11637 if ( keys.length > 0 ) { 11638 11639 const morphAttribute = morphAttributes[ keys[ 0 ] ]; 11640 11641 if ( morphAttribute !== undefined ) { 11642 11643 this.morphTargetInfluences = []; 11644 this.morphTargetDictionary = {}; 11645 11646 for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 11647 11648 const name = morphAttribute[ m ].name || String( m ); 11649 11650 this.morphTargetInfluences.push( 0 ); 11651 this.morphTargetDictionary[ name ] = m; 11652 11653 } 11654 11655 } 11656 11657 } 11658 11659 } 11660 11661 getVertexPosition( index, target ) { 11662 11663 const geometry = this.geometry; 11664 const position = geometry.attributes.position; 11665 const morphPosition = geometry.morphAttributes.position; 11666 const morphTargetsRelative = geometry.morphTargetsRelative; 11667 11668 target.fromBufferAttribute( position, index ); 11669 11670 const morphInfluences = this.morphTargetInfluences; 11671 11672 if ( morphPosition && morphInfluences ) { 11673 11674 _morphA.set( 0, 0, 0 ); 11675 11676 for ( let i = 0, il = morphPosition.length; i < il; i ++ ) { 11677 11678 const influence = morphInfluences[ i ]; 11679 const morphAttribute = morphPosition[ i ]; 11680 11681 if ( influence === 0 ) continue; 11682 11683 _tempA.fromBufferAttribute( morphAttribute, index ); 11684 11685 if ( morphTargetsRelative ) { 11686 11687 _morphA.addScaledVector( _tempA, influence ); 11688 11689 } else { 11690 11691 _morphA.addScaledVector( _tempA.sub( target ), influence ); 11692 11693 } 11694 11695 } 11696 11697 target.add( _morphA ); 11698 11699 } 11700 11701 return target; 11702 11703 } 11704 11705 raycast( raycaster, intersects ) { 11706 11707 const geometry = this.geometry; 11708 const material = this.material; 11709 const matrixWorld = this.matrixWorld; 11710 11711 if ( material === undefined ) return; 11712 11713 // test with bounding sphere in world space 11714 11715 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 11716 11717 _sphere$6.copy( geometry.boundingSphere ); 11718 _sphere$6.applyMatrix4( matrixWorld ); 11719 11720 // check distance from ray origin to bounding sphere 11721 11722 _ray$3.copy( raycaster.ray ).recast( raycaster.near ); 11723 11724 if ( _sphere$6.containsPoint( _ray$3.origin ) === false ) { 11725 11726 if ( _ray$3.intersectSphere( _sphere$6, _sphereHitAt ) === null ) return; 11727 11728 if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return; 11729 11730 } 11731 11732 // convert ray to local space of mesh 11733 11734 _inverseMatrix$3.copy( matrixWorld ).invert(); 11735 _ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 ); 11736 11737 // test with bounding box in local space 11738 11739 if ( geometry.boundingBox !== null ) { 11740 11741 if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return; 11742 11743 } 11744 11745 // test for intersections with geometry 11746 11747 this._computeIntersections( raycaster, intersects, _ray$3 ); 11748 11749 } 11750 11751 _computeIntersections( raycaster, intersects, rayLocalSpace ) { 11752 11753 let intersection; 11754 11755 const geometry = this.geometry; 11756 const material = this.material; 11757 11758 const index = geometry.index; 11759 const position = geometry.attributes.position; 11760 const uv = geometry.attributes.uv; 11761 const uv1 = geometry.attributes.uv1; 11762 const normal = geometry.attributes.normal; 11763 const groups = geometry.groups; 11764 const drawRange = geometry.drawRange; 11765 11766 if ( index !== null ) { 11767 11768 // indexed buffer geometry 11769 11770 if ( Array.isArray( material ) ) { 11771 11772 for ( let i = 0, il = groups.length; i < il; i ++ ) { 11773 11774 const group = groups[ i ]; 11775 const groupMaterial = material[ group.materialIndex ]; 11776 11777 const start = Math.max( group.start, drawRange.start ); 11778 const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); 11779 11780 for ( let j = start, jl = end; j < jl; j += 3 ) { 11781 11782 const a = index.getX( j ); 11783 const b = index.getX( j + 1 ); 11784 const c = index.getX( j + 2 ); 11785 11786 intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); 11787 11788 if ( intersection ) { 11789 11790 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics 11791 intersection.face.materialIndex = group.materialIndex; 11792 intersects.push( intersection ); 11793 11794 } 11795 11796 } 11797 11798 } 11799 11800 } else { 11801 11802 const start = Math.max( 0, drawRange.start ); 11803 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); 11804 11805 for ( let i = start, il = end; i < il; i += 3 ) { 11806 11807 const a = index.getX( i ); 11808 const b = index.getX( i + 1 ); 11809 const c = index.getX( i + 2 ); 11810 11811 intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); 11812 11813 if ( intersection ) { 11814 11815 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics 11816 intersects.push( intersection ); 11817 11818 } 11819 11820 } 11821 11822 } 11823 11824 } else if ( position !== undefined ) { 11825 11826 // non-indexed buffer geometry 11827 11828 if ( Array.isArray( material ) ) { 11829 11830 for ( let i = 0, il = groups.length; i < il; i ++ ) { 11831 11832 const group = groups[ i ]; 11833 const groupMaterial = material[ group.materialIndex ]; 11834 11835 const start = Math.max( group.start, drawRange.start ); 11836 const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); 11837 11838 for ( let j = start, jl = end; j < jl; j += 3 ) { 11839 11840 const a = j; 11841 const b = j + 1; 11842 const c = j + 2; 11843 11844 intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); 11845 11846 if ( intersection ) { 11847 11848 intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics 11849 intersection.face.materialIndex = group.materialIndex; 11850 intersects.push( intersection ); 11851 11852 } 11853 11854 } 11855 11856 } 11857 11858 } else { 11859 11860 const start = Math.max( 0, drawRange.start ); 11861 const end = Math.min( position.count, ( drawRange.start + drawRange.count ) ); 11862 11863 for ( let i = start, il = end; i < il; i += 3 ) { 11864 11865 const a = i; 11866 const b = i + 1; 11867 const c = i + 2; 11868 11869 intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); 11870 11871 if ( intersection ) { 11872 11873 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics 11874 intersects.push( intersection ); 11875 11876 } 11877 11878 } 11879 11880 } 11881 11882 } 11883 11884 } 11885 11886} 11887 11888function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) { 11889 11890 let intersect; 11891 11892 if ( material.side === BackSide ) { 11893 11894 intersect = ray.intersectTriangle( pC, pB, pA, true, point ); 11895 11896 } else { 11897 11898 intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point ); 11899 11900 } 11901 11902 if ( intersect === null ) return null; 11903 11904 _intersectionPointWorld.copy( point ); 11905 _intersectionPointWorld.applyMatrix4( object.matrixWorld ); 11906 11907 const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld ); 11908 11909 if ( distance < raycaster.near || distance > raycaster.far ) return null; 11910 11911 return { 11912 distance: distance, 11913 point: _intersectionPointWorld.clone(), 11914 object: object 11915 }; 11916 11917} 11918 11919function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) { 11920 11921 object.getVertexPosition( a, _vA$1 ); 11922 object.getVertexPosition( b, _vB$1 ); 11923 object.getVertexPosition( c, _vC$1 ); 11924 11925 const intersection = checkIntersection( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint ); 11926 11927 if ( intersection ) { 11928 11929 if ( uv ) { 11930 11931 _uvA$1.fromBufferAttribute( uv, a ); 11932 _uvB$1.fromBufferAttribute( uv, b ); 11933 _uvC$1.fromBufferAttribute( uv, c ); 11934 11935 intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); 11936 11937 } 11938 11939 if ( uv1 ) { 11940 11941 _uvA$1.fromBufferAttribute( uv1, a ); 11942 _uvB$1.fromBufferAttribute( uv1, b ); 11943 _uvC$1.fromBufferAttribute( uv1, c ); 11944 11945 intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() );
11946 intersection.uv2 = intersection.uv1; // @deprecated, r152 11947 11948 } 11949 11950 if ( normal ) { 11951 11952 _normalA.fromBufferAttribute( normal, a ); 11953 _normalB.fromBufferAttribute( normal, b ); 11954 _normalC.fromBufferAttribute( normal, c ); 11955
vendor: 11,895 bytes, lines 11956-12544
11956 intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() ); 11957 11958 if ( intersection.normal.dot( ray.direction ) > 0 ) { 11959 11960 intersection.normal.multiplyScalar( - 1 ); 11961 11962 } 11963 11964 } 11965 11966 const face = { 11967 a: a, 11968 b: b, 11969 c: c, 11970 normal: new Vector3(), 11971 materialIndex: 0 11972 }; 11973 11974 Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal ); 11975 11976 intersection.face = face; 11977 11978 } 11979 11980 return intersection; 11981 11982} 11983 11984class BoxGeometry extends BufferGeometry { 11985 11986 constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) { 11987 11988 super(); 11989 11990 this.type = 'BoxGeometry'; 11991 11992 this.parameters = { 11993 width: width, 11994 height: height, 11995 depth: depth, 11996 widthSegments: widthSegments, 11997 heightSegments: heightSegments, 11998 depthSegments: depthSegments 11999 }; 12000 12001 const scope = this; 12002 12003 // segments 12004 12005 widthSegments = Math.floor( widthSegments ); 12006 heightSegments = Math.floor( heightSegments ); 12007 depthSegments = Math.floor( depthSegments ); 12008 12009 // buffers 12010 12011 const indices = []; 12012 const vertices = []; 12013 const normals = []; 12014 const uvs = []; 12015 12016 // helper variables 12017 12018 let numberOfVertices = 0; 12019 let groupStart = 0; 12020 12021 // build each side of the box geometry 12022 12023 buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px 12024 buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx 12025 buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py 12026 buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny 12027 buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz 12028 buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz 12029 12030 // build geometry 12031 12032 this.setIndex( indices ); 12033 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 12034 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 12035 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 12036 12037 function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { 12038 12039 const segmentWidth = width / gridX; 12040 const segmentHeight = height / gridY; 12041 12042 const widthHalf = width / 2; 12043 const heightHalf = height / 2; 12044 const depthHalf = depth / 2; 12045 12046 const gridX1 = gridX + 1; 12047 const gridY1 = gridY + 1; 12048 12049 let vertexCounter = 0; 12050 let groupCount = 0; 12051 12052 const vector = new Vector3(); 12053 12054 // generate vertices, normals and uvs 12055 12056 for ( let iy = 0; iy < gridY1; iy ++ ) { 12057 12058 const y = iy * segmentHeight - heightHalf; 12059 12060 for ( let ix = 0; ix < gridX1; ix ++ ) { 12061 12062 const x = ix * segmentWidth - widthHalf; 12063 12064 // set values to correct vector component 12065 12066 vector[ u ] = x * udir; 12067 vector[ v ] = y * vdir; 12068 vector[ w ] = depthHalf; 12069 12070 // now apply vector to vertex buffer 12071 12072 vertices.push( vector.x, vector.y, vector.z ); 12073 12074 // set values to correct vector component 12075 12076 vector[ u ] = 0; 12077 vector[ v ] = 0; 12078 vector[ w ] = depth > 0 ? 1 : - 1; 12079 12080 // now apply vector to normal buffer 12081 12082 normals.push( vector.x, vector.y, vector.z ); 12083 12084 // uvs 12085 12086 uvs.push( ix / gridX ); 12087 uvs.push( 1 - ( iy / gridY ) ); 12088 12089 // counters 12090 12091 vertexCounter += 1; 12092 12093 } 12094 12095 } 12096 12097 // indices 12098 12099 // 1. you need three indices to draw a single face 12100 // 2. a single segment consists of two faces 12101 // 3. so we need to generate six (2*3) indices per segment 12102 12103 for ( let iy = 0; iy < gridY; iy ++ ) { 12104 12105 for ( let ix = 0; ix < gridX; ix ++ ) { 12106 12107 const a = numberOfVertices + ix + gridX1 * iy; 12108 const b = numberOfVertices + ix + gridX1 * ( iy + 1 ); 12109 const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); 12110 const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; 12111 12112 // faces 12113 12114 indices.push( a, b, d ); 12115 indices.push( b, c, d ); 12116 12117 // increase counter 12118 12119 groupCount += 6; 12120 12121 } 12122 12123 } 12124 12125 // add a group to the geometry. this will ensure multi material support 12126 12127 scope.addGroup( groupStart, groupCount, materialIndex ); 12128 12129 // calculate new start value for groups 12130 12131 groupStart += groupCount; 12132 12133 // update total number of vertices 12134 12135 numberOfVertices += vertexCounter; 12136 12137 } 12138 12139 } 12140 12141 copy( source ) { 12142 12143 super.copy( source ); 12144 12145 this.parameters = Object.assign( {}, source.parameters ); 12146 12147 return this; 12148 12149 } 12150 12151 static fromJSON( data ) { 12152 12153 return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); 12154 12155 } 12156 12157} 12158 12159/** 12160 * Uniform Utilities 12161 */ 12162 12163function cloneUniforms( src ) { 12164 12165 const dst = {}; 12166 12167 for ( const u in src ) { 12168 12169 dst[ u ] = {}; 12170 12171 for ( const p in src[ u ] ) { 12172 12173 const property = src[ u ][ p ]; 12174 12175 if ( property && ( property.isColor || 12176 property.isMatrix3 || property.isMatrix4 || 12177 property.isVector2 || property.isVector3 || property.isVector4 || 12178 property.isTexture || property.isQuaternion ) ) { 12179 12180 if ( property.isRenderTargetTexture ) { 12181 12182 console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); 12183 dst[ u ][ p ] = null; 12184 12185 } else { 12186 12187 dst[ u ][ p ] = property.clone(); 12188 12189 } 12190 12191 } else if ( Array.isArray( property ) ) { 12192 12193 dst[ u ][ p ] = property.slice(); 12194 12195 } else { 12196 12197 dst[ u ][ p ] = property; 12198 12199 } 12200 12201 } 12202 12203 } 12204 12205 return dst; 12206 12207} 12208 12209function mergeUniforms( uniforms ) { 12210 12211 const merged = {}; 12212 12213 for ( let u = 0; u < uniforms.length; u ++ ) { 12214 12215 const tmp = cloneUniforms( uniforms[ u ] ); 12216 12217 for ( const p in tmp ) { 12218 12219 merged[ p ] = tmp[ p ]; 12220 12221 } 12222 12223 } 12224 12225 return merged; 12226 12227} 12228 12229function cloneUniformsGroups( src ) { 12230 12231 const dst = []; 12232 12233 for ( let u = 0; u < src.length; u ++ ) { 12234 12235 dst.push( src[ u ].clone() ); 12236 12237 } 12238 12239 return dst; 12240 12241} 12242 12243function getUnlitUniformColorSpace( renderer ) { 12244 12245 if ( renderer.getRenderTarget() === null ) { 12246 12247 // https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398 12248 return renderer.outputColorSpace; 12249 12250 } 12251 12252 return ColorManagement.workingColorSpace; 12253 12254} 12255 12256// Legacy 12257 12258const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms }; 12259 12260var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"; 12261 12262var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}"; 12263 12264class ShaderMaterial extends Material { 12265 12266 constructor( parameters ) { 12267 12268 super(); 12269 12270 this.isShaderMaterial = true; 12271 12272 this.type = 'ShaderMaterial'; 12273 12274 this.defines = {}; 12275 this.uniforms = {}; 12276 this.uniformsGroups = []; 12277 12278 this.vertexShader = default_vertex; 12279 this.fragmentShader = default_fragment; 12280 12281 this.linewidth = 1; 12282 12283 this.wireframe = false; 12284 this.wireframeLinewidth = 1; 12285 12286 this.fog = false; // set to use scene fog 12287 this.lights = false; // set to use scene lights 12288 this.clipping = false; // set to use user-defined clipping planes 12289 12290 this.forceSinglePass = true; 12291 12292 this.extensions = { 12293 derivatives: false, // set to use derivatives 12294 fragDepth: false, // set to use fragment depth values 12295 drawBuffers: false, // set to use draw buffers 12296 shaderTextureLOD: false, // set to use shader texture LOD 12297 clipCullDistance: false // set to use vertex shader clipping 12298 }; 12299 12300 // When rendered geometry doesn't include these attributes but the material does, 12301 // use these default values in WebGL. This avoids errors when buffer data is missing. 12302 this.defaultAttributeValues = { 12303 'color': [ 1, 1, 1 ], 12304 'uv': [ 0, 0 ], 12305 'uv1': [ 0, 0 ] 12306 }; 12307 12308 this.index0AttributeName = undefined; 12309 this.uniformsNeedUpdate = false; 12310 12311 this.glslVersion = null; 12312 12313 if ( parameters !== undefined ) { 12314 12315 this.setValues( parameters ); 12316 12317 } 12318 12319 } 12320 12321 copy( source ) { 12322 12323 super.copy( source ); 12324 12325 this.fragmentShader = source.fragmentShader; 12326 this.vertexShader = source.vertexShader; 12327 12328 this.uniforms = cloneUniforms( source.uniforms ); 12329 this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups ); 12330 12331 this.defines = Object.assign( {}, source.defines ); 12332 12333 this.wireframe = source.wireframe; 12334 this.wireframeLinewidth = source.wireframeLinewidth; 12335 12336 this.fog = source.fog; 12337 this.lights = source.lights; 12338 this.clipping = source.clipping; 12339 12340 this.extensions = Object.assign( {}, source.extensions ); 12341 12342 this.glslVersion = source.glslVersion; 12343 12344 return this; 12345 12346 } 12347 12348 toJSON( meta ) { 12349 12350 const data = super.toJSON( meta ); 12351 12352 data.glslVersion = this.glslVersion; 12353 data.uniforms = {}; 12354 12355 for ( const name in this.uniforms ) { 12356 12357 const uniform = this.uniforms[ name ]; 12358 const value = uniform.value; 12359 12360 if ( value && value.isTexture ) { 12361 12362 data.uniforms[ name ] = { 12363 type: 't', 12364 value: value.toJSON( meta ).uuid 12365 }; 12366 12367 } else if ( value && value.isColor ) { 12368 12369 data.uniforms[ name ] = { 12370 type: 'c', 12371 value: value.getHex() 12372 }; 12373 12374 } else if ( value && value.isVector2 ) { 12375 12376 data.uniforms[ name ] = { 12377 type: 'v2', 12378 value: value.toArray() 12379 }; 12380 12381 } else if ( value && value.isVector3 ) { 12382 12383 data.uniforms[ name ] = { 12384 type: 'v3', 12385 value: value.toArray() 12386 }; 12387 12388 } else if ( value && value.isVector4 ) { 12389 12390 data.uniforms[ name ] = { 12391 type: 'v4', 12392 value: value.toArray() 12393 }; 12394 12395 } else if ( value && value.isMatrix3 ) { 12396 12397 data.uniforms[ name ] = { 12398 type: 'm3', 12399 value: value.toArray() 12400 }; 12401 12402 } else if ( value && value.isMatrix4 ) { 12403 12404 data.uniforms[ name ] = { 12405 type: 'm4', 12406 value: value.toArray() 12407 }; 12408 12409 } else { 12410 12411 data.uniforms[ name ] = { 12412 value: value 12413 }; 12414 12415 // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far 12416 12417 } 12418 12419 } 12420 12421 if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines; 12422 12423 data.vertexShader = this.vertexShader; 12424 data.fragmentShader = this.fragmentShader; 12425 12426 data.lights = this.lights; 12427 data.clipping = this.clipping; 12428 12429 const extensions = {}; 12430 12431 for ( const key in this.extensions ) { 12432 12433 if ( this.extensions[ key ] === true ) extensions[ key ] = true; 12434 12435 } 12436 12437 if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions; 12438 12439 return data; 12440 12441 } 12442 12443} 12444 12445class Camera extends Object3D { 12446 12447 constructor() { 12448 12449 super(); 12450 12451 this.isCamera = true; 12452 12453 this.type = 'Camera'; 12454 12455 this.matrixWorldInverse = new Matrix4(); 12456 12457 this.projectionMatrix = new Matrix4(); 12458 this.projectionMatrixInverse = new Matrix4(); 12459 12460 this.coordinateSystem = WebGLCoordinateSystem; 12461 12462 } 12463 12464 copy( source, recursive ) { 12465 12466 super.copy( source, recursive ); 12467 12468 this.matrixWorldInverse.copy( source.matrixWorldInverse ); 12469 12470 this.projectionMatrix.copy( source.projectionMatrix ); 12471 this.projectionMatrixInverse.copy( source.projectionMatrixInverse ); 12472 12473 this.coordinateSystem = source.coordinateSystem; 12474 12475 return this; 12476 12477 } 12478 12479 getWorldDirection( target ) { 12480 12481 return super.getWorldDirection( target ).negate(); 12482 12483 } 12484 12485 updateMatrixWorld( force ) { 12486 12487 super.updateMatrixWorld( force ); 12488 12489 this.matrixWorldInverse.copy( this.matrixWorld ).invert(); 12490 12491 } 12492 12493 updateWorldMatrix( updateParents, updateChildren ) { 12494 12495 super.updateWorldMatrix( updateParents, updateChildren ); 12496 12497 this.matrixWorldInverse.copy( this.matrixWorld ).invert(); 12498 12499 } 12500 12501 clone() { 12502 12503 return new this.constructor().copy( this ); 12504 12505 } 12506 12507} 12508 12509class PerspectiveCamera extends Camera { 12510 12511 constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) { 12512 12513 super(); 12514 12515 this.isPerspectiveCamera = true; 12516 12517 this.type = 'PerspectiveCamera'; 12518 12519 this.fov = fov; 12520 this.zoom = 1; 12521 12522 this.near = near; 12523 this.far = far; 12524 this.focus = 10; 12525 12526 this.aspect = aspect; 12527 this.view = null; 12528 12529 this.filmGauge = 35; // width of the film (default in millimeters) 12530 this.filmOffset = 0; // horizontal film offset (same unit as gauge) 12531 12532 this.updateProjectionMatrix(); 12533 12534 } 12535 12536 copy( source, recursive ) { 12537 12538 super.copy( source, recursive ); 12539 12540 this.fov = source.fov; 12541 this.zoom = source.zoom; 12542 12543 this.near = source.near; 12544 this.far = source.far;
vendor: 3,387 bytes, lines 12545-12690
12545 this.focus = source.focus; 12546 12547 this.aspect = source.aspect; 12548 this.view = source.view === null ? null : Object.assign( {}, source.view ); 12549 12550 this.filmGauge = source.filmGauge; 12551 this.filmOffset = source.filmOffset; 12552 12553 return this; 12554 12555 } 12556 12557 /** 12558 * Sets the FOV by focal length in respect to the current .filmGauge. 12559 * 12560 * The default film gauge is 35, so that the focal length can be specified for 12561 * a 35mm (full frame) camera. 12562 * 12563 * Values for focal length and film gauge must have the same unit. 12564 */ 12565 setFocalLength( focalLength ) { 12566 12567 /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */ 12568 const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; 12569 12570 this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope ); 12571 this.updateProjectionMatrix(); 12572 12573 } 12574 12575 /** 12576 * Calculates the focal length from the current .fov and .filmGauge. 12577 */ 12578 getFocalLength() { 12579 12580 const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov ); 12581 12582 return 0.5 * this.getFilmHeight() / vExtentSlope; 12583 12584 } 12585 12586 getEffectiveFOV() { 12587 12588 return RAD2DEG * 2 * Math.atan( 12589 Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom ); 12590 12591 } 12592 12593 getFilmWidth() { 12594 12595 // film not completely covered in portrait format (aspect < 1) 12596 return this.filmGauge * Math.min( this.aspect, 1 ); 12597 12598 } 12599 12600 getFilmHeight() { 12601 12602 // film not completely covered in landscape format (aspect > 1) 12603 return this.filmGauge / Math.max( this.aspect, 1 ); 12604 12605 } 12606 12607 /** 12608 * Sets an offset in a larger frustum. This is useful for multi-window or 12609 * multi-monitor/multi-machine setups. 12610 * 12611 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and 12612 * the monitors are in grid like this 12613 * 12614 * +---+---+---+ 12615 * | A | B | C | 12616 * +---+---+---+ 12617 * | D | E | F | 12618 * +---+---+---+ 12619 * 12620 * then for each monitor you would call it like this 12621 * 12622 * const w = 1920; 12623 * const h = 1080; 12624 * const fullWidth = w * 3; 12625 * const fullHeight = h * 2; 12626 * 12627 * --A-- 12628 * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); 12629 * --B-- 12630 * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); 12631 * --C-- 12632 * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); 12633 * --D-- 12634 * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); 12635 * --E-- 12636 * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); 12637 * --F-- 12638 * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); 12639 * 12640 * Note there is no reason monitors have to be the same size or in a grid. 12641 */ 12642 setViewOffset( fullWidth, fullHeight, x, y, width, height ) { 12643 12644 this.aspect = fullWidth / fullHeight; 12645 12646 if ( this.view === null ) { 12647 12648 this.view = { 12649 enabled: true, 12650 fullWidth: 1, 12651 fullHeight: 1, 12652 offsetX: 0, 12653 offsetY: 0, 12654 width: 1, 12655 height: 1 12656 }; 12657 12658 } 12659 12660 this.view.enabled = true; 12661 this.view.fullWidth = fullWidth; 12662 this.view.fullHeight = fullHeight; 12663 this.view.offsetX = x; 12664 this.view.offsetY = y; 12665 this.view.width = width; 12666 this.view.height = height; 12667 12668 this.updateProjectionMatrix(); 12669 12670 } 12671 12672 clearViewOffset() { 12673 12674 if ( this.view !== null ) { 12675 12676 this.view.enabled = false; 12677 12678 } 12679 12680 this.updateProjectionMatrix(); 12681 12682 } 12683 12684 updateProjectionMatrix() { 12685 12686 const near = this.near; 12687 let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom; 12688 let height = 2 * top; 12689 let width = this.aspect * height; 12690 let left = - 0.5 * width;
vendor: 25,579 bytes, lines 12691-13840
12691 const view = this.view; 12692 12693 if ( this.view !== null && this.view.enabled ) { 12694 12695 const fullWidth = view.fullWidth, 12696 fullHeight = view.fullHeight; 12697 12698 left += view.offsetX * width / fullWidth; 12699 top -= view.offsetY * height / fullHeight; 12700 width *= view.width / fullWidth; 12701 height *= view.height / fullHeight; 12702 12703 } 12704 12705 const skew = this.filmOffset; 12706 if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); 12707 12708 this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem ); 12709 12710 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); 12711 12712 } 12713 12714 toJSON( meta ) { 12715 12716 const data = super.toJSON( meta ); 12717 12718 data.object.fov = this.fov; 12719 data.object.zoom = this.zoom; 12720 12721 data.object.near = this.near; 12722 data.object.far = this.far; 12723 data.object.focus = this.focus; 12724 12725 data.object.aspect = this.aspect; 12726 12727 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); 12728 12729 data.object.filmGauge = this.filmGauge; 12730 data.object.filmOffset = this.filmOffset; 12731 12732 return data; 12733 12734 } 12735 12736} 12737 12738const fov = - 90; // negative fov is not an error 12739const aspect = 1; 12740 12741class CubeCamera extends Object3D { 12742 12743 constructor( near, far, renderTarget ) { 12744 12745 super(); 12746 12747 this.type = 'CubeCamera'; 12748 12749 this.renderTarget = renderTarget; 12750 this.coordinateSystem = null; 12751 this.activeMipmapLevel = 0; 12752 12753 const cameraPX = new PerspectiveCamera( fov, aspect, near, far ); 12754 cameraPX.layers = this.layers; 12755 this.add( cameraPX ); 12756 12757 const cameraNX = new PerspectiveCamera( fov, aspect, near, far ); 12758 cameraNX.layers = this.layers; 12759 this.add( cameraNX ); 12760 12761 const cameraPY = new PerspectiveCamera( fov, aspect, near, far ); 12762 cameraPY.layers = this.layers; 12763 this.add( cameraPY ); 12764 12765 const cameraNY = new PerspectiveCamera( fov, aspect, near, far ); 12766 cameraNY.layers = this.layers; 12767 this.add( cameraNY ); 12768 12769 const cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); 12770 cameraPZ.layers = this.layers; 12771 this.add( cameraPZ ); 12772 12773 const cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); 12774 cameraNZ.layers = this.layers; 12775 this.add( cameraNZ ); 12776 12777 } 12778 12779 updateCoordinateSystem() { 12780 12781 const coordinateSystem = this.coordinateSystem; 12782 12783 const cameras = this.children.concat(); 12784 12785 const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras; 12786 12787 for ( const camera of cameras ) this.remove( camera ); 12788 12789 if ( coordinateSystem === WebGLCoordinateSystem ) { 12790 12791 cameraPX.up.set( 0, 1, 0 ); 12792 cameraPX.lookAt( 1, 0, 0 ); 12793 12794 cameraNX.up.set( 0, 1, 0 ); 12795 cameraNX.lookAt( - 1, 0, 0 ); 12796 12797 cameraPY.up.set( 0, 0, - 1 ); 12798 cameraPY.lookAt( 0, 1, 0 ); 12799 12800 cameraNY.up.set( 0, 0, 1 ); 12801 cameraNY.lookAt( 0, - 1, 0 ); 12802 12803 cameraPZ.up.set( 0, 1, 0 ); 12804 cameraPZ.lookAt( 0, 0, 1 ); 12805 12806 cameraNZ.up.set( 0, 1, 0 ); 12807 cameraNZ.lookAt( 0, 0, - 1 ); 12808 12809 } else if ( coordinateSystem === WebGPUCoordinateSystem ) { 12810 12811 cameraPX.up.set( 0, - 1, 0 ); 12812 cameraPX.lookAt( - 1, 0, 0 ); 12813 12814 cameraNX.up.set( 0, - 1, 0 ); 12815 cameraNX.lookAt( 1, 0, 0 ); 12816 12817 cameraPY.up.set( 0, 0, 1 ); 12818 cameraPY.lookAt( 0, 1, 0 ); 12819 12820 cameraNY.up.set( 0, 0, - 1 ); 12821 cameraNY.lookAt( 0, - 1, 0 ); 12822 12823 cameraPZ.up.set( 0, - 1, 0 ); 12824 cameraPZ.lookAt( 0, 0, 1 ); 12825 12826 cameraNZ.up.set( 0, - 1, 0 ); 12827 cameraNZ.lookAt( 0, 0, - 1 ); 12828 12829 } else { 12830 12831 throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem ); 12832 12833 } 12834 12835 for ( const camera of cameras ) { 12836 12837 this.add( camera ); 12838 12839 camera.updateMatrixWorld(); 12840 12841 } 12842 12843 } 12844 12845 update( renderer, scene ) { 12846 12847 if ( this.parent === null ) this.updateMatrixWorld(); 12848 12849 const { renderTarget, activeMipmapLevel } = this; 12850 12851 if ( this.coordinateSystem !== renderer.coordinateSystem ) { 12852 12853 this.coordinateSystem = renderer.coordinateSystem; 12854 12855 this.updateCoordinateSystem(); 12856 12857 } 12858 12859 const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children; 12860 12861 const currentRenderTarget = renderer.getRenderTarget(); 12862 const currentActiveCubeFace = renderer.getActiveCubeFace(); 12863 const currentActiveMipmapLevel = renderer.getActiveMipmapLevel(); 12864 12865 const currentXrEnabled = renderer.xr.enabled; 12866 12867 renderer.xr.enabled = false; 12868 12869 const generateMipmaps = renderTarget.texture.generateMipmaps; 12870 12871 renderTarget.texture.generateMipmaps = false; 12872 12873 renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel ); 12874 renderer.render( scene, cameraPX ); 12875 12876 renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel ); 12877 renderer.render( scene, cameraNX ); 12878 12879 renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel ); 12880 renderer.render( scene, cameraPY ); 12881 12882 renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel ); 12883 renderer.render( scene, cameraNY ); 12884 12885 renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel ); 12886 renderer.render( scene, cameraPZ ); 12887 12888 // mipmaps are generated during the last call of render() 12889 // at this point, all sides of the cube render target are defined 12890 12891 renderTarget.texture.generateMipmaps = generateMipmaps; 12892 12893 renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel ); 12894 renderer.render( scene, cameraNZ ); 12895 12896 renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel ); 12897 12898 renderer.xr.enabled = currentXrEnabled; 12899 12900 renderTarget.texture.needsPMREMUpdate = true; 12901 12902 } 12903 12904} 12905 12906class CubeTexture extends Texture { 12907 12908 constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { 12909 12910 images = images !== undefined ? images : []; 12911 mapping = mapping !== undefined ? mapping : CubeReflectionMapping; 12912 12913 super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); 12914 12915 this.isCubeTexture = true; 12916 12917 this.flipY = false; 12918 12919 } 12920 12921 get images() { 12922 12923 return this.image; 12924 12925 } 12926 12927 set images( value ) { 12928 12929 this.image = value; 12930 12931 } 12932 12933} 12934 12935class WebGLCubeRenderTarget extends WebGLRenderTarget { 12936 12937 constructor( size = 1, options = {} ) { 12938 12939 super( size, size, options ); 12940 12941 this.isWebGLCubeRenderTarget = true; 12942 12943 const image = { width: size, height: size, depth: 1 }; 12944 const images = [ image, image, image, image, image, image ]; 12945 12946 if ( options.encoding !== undefined ) { 12947 12948 // @deprecated, r152 12949 warnOnce( 'THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace.' ); 12950 options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace; 12951 12952 } 12953 12954 this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); 12955 12956 // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) 12957 // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, 12958 // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly. 12959 12960 // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped 12961 // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture 12962 // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures). 12963 12964 this.texture.isRenderTargetTexture = true; 12965 12966 this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; 12967 this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; 12968 12969 } 12970 12971 fromEquirectangularTexture( renderer, texture ) { 12972 12973 this.texture.type = texture.type; 12974 this.texture.colorSpace = texture.colorSpace; 12975 12976 this.texture.generateMipmaps = texture.generateMipmaps; 12977 this.texture.minFilter = texture.minFilter; 12978 this.texture.magFilter = texture.magFilter; 12979 12980 const shader = { 12981 12982 uniforms: { 12983 tEquirect: { value: null }, 12984 }, 12985 12986 vertexShader: /* glsl */` 12987 12988 varying vec3 vWorldDirection; 12989 12990 vec3 transformDirection( in vec3 dir, in mat4 matrix ) { 12991 12992 return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); 12993 12994 } 12995 12996 void main() { 12997 12998 vWorldDirection = transformDirection( position, modelMatrix ); 12999 13000 #include <begin_vertex> 13001 #include <project_vertex> 13002 13003 } 13004 `, 13005 13006 fragmentShader: /* glsl */` 13007 13008 uniform sampler2D tEquirect; 13009 13010 varying vec3 vWorldDirection; 13011 13012 #include <common> 13013 13014 void main() { 13015 13016 vec3 direction = normalize( vWorldDirection ); 13017 13018 vec2 sampleUV = equirectUv( direction ); 13019 13020 gl_FragColor = texture2D( tEquirect, sampleUV ); 13021 13022 } 13023 ` 13024 }; 13025 13026 const geometry = new BoxGeometry( 5, 5, 5 ); 13027 13028 const material = new ShaderMaterial( { 13029 13030 name: 'CubemapFromEquirect', 13031 13032 uniforms: cloneUniforms( shader.uniforms ), 13033 vertexShader: shader.vertexShader, 13034 fragmentShader: shader.fragmentShader, 13035 side: BackSide, 13036 blending: NoBlending 13037 13038 } ); 13039 13040 material.uniforms.tEquirect.value = texture; 13041 13042 const mesh = new Mesh( geometry, material ); 13043 13044 const currentMinFilter = texture.minFilter; 13045 13046 // Avoid blurred poles 13047 if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter; 13048 13049 const camera = new CubeCamera( 1, 10, this ); 13050 camera.update( renderer, mesh ); 13051 13052 texture.minFilter = currentMinFilter; 13053 13054 mesh.geometry.dispose(); 13055 mesh.material.dispose(); 13056 13057 return this; 13058 13059 } 13060 13061 clear( renderer, color, depth, stencil ) { 13062 13063 const currentRenderTarget = renderer.getRenderTarget(); 13064 13065 for ( let i = 0; i < 6; i ++ ) { 13066 13067 renderer.setRenderTarget( this, i ); 13068 13069 renderer.clear( color, depth, stencil ); 13070 13071 } 13072 13073 renderer.setRenderTarget( currentRenderTarget ); 13074 13075 } 13076 13077} 13078 13079const _vector1 = /*@__PURE__*/ new Vector3(); 13080const _vector2 = /*@__PURE__*/ new Vector3(); 13081const _normalMatrix = /*@__PURE__*/ new Matrix3(); 13082 13083class Plane { 13084 13085 constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) { 13086 13087 this.isPlane = true; 13088 13089 // normal is assumed to be normalized 13090 13091 this.normal = normal; 13092 this.constant = constant; 13093 13094 } 13095 13096 set( normal, constant ) { 13097 13098 this.normal.copy( normal ); 13099 this.constant = constant; 13100 13101 return this; 13102 13103 } 13104 13105 setComponents( x, y, z, w ) { 13106 13107 this.normal.set( x, y, z ); 13108 this.constant = w; 13109 13110 return this; 13111 13112 } 13113 13114 setFromNormalAndCoplanarPoint( normal, point ) { 13115 13116 this.normal.copy( normal ); 13117 this.constant = - point.dot( this.normal ); 13118 13119 return this; 13120 13121 } 13122 13123 setFromCoplanarPoints( a, b, c ) { 13124 13125 const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize(); 13126 13127 // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? 13128 13129 this.setFromNormalAndCoplanarPoint( normal, a ); 13130 13131 return this; 13132 13133 } 13134 13135 copy( plane ) { 13136 13137 this.normal.copy( plane.normal ); 13138 this.constant = plane.constant; 13139 13140 return this; 13141 13142 } 13143 13144 normalize() { 13145 13146 // Note: will lead to a divide by zero if the plane is invalid. 13147 13148 const inverseNormalLength = 1.0 / this.normal.length(); 13149 this.normal.multiplyScalar( inverseNormalLength ); 13150 this.constant *= inverseNormalLength; 13151 13152 return this; 13153 13154 } 13155 13156 negate() { 13157 13158 this.constant *= - 1; 13159 this.normal.negate(); 13160 13161 return this; 13162 13163 } 13164 13165 distanceToPoint( point ) { 13166 13167 return this.normal.dot( point ) + this.constant; 13168 13169 } 13170 13171 distanceToSphere( sphere ) { 13172 13173 return this.distanceToPoint( sphere.center ) - sphere.radius; 13174 13175 } 13176 13177 projectPoint( point, target ) { 13178 13179 return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) ); 13180 13181 } 13182 13183 intersectLine( line, target ) { 13184 13185 const direction = line.delta( _vector1 ); 13186 13187 const denominator = this.normal.dot( direction ); 13188 13189 if ( denominator === 0 ) { 13190 13191 // line is coplanar, return origin 13192 if ( this.distanceToPoint( line.start ) === 0 ) { 13193 13194 return target.copy( line.start ); 13195 13196 } 13197 13198 // Unsure if this is the correct method to handle this case. 13199 return null; 13200 13201 } 13202 13203 const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; 13204 13205 if ( t < 0 || t > 1 ) { 13206 13207 return null; 13208 13209 } 13210 13211 return target.copy( line.start ).addScaledVector( direction, t ); 13212 13213 } 13214 13215 intersectsLine( line ) { 13216 13217 // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. 13218 13219 const startSign = this.distanceToPoint( line.start ); 13220 const endSign = this.distanceToPoint( line.end ); 13221 13222 return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); 13223 13224 } 13225 13226 intersectsBox( box ) { 13227 13228 return box.intersectsPlane( this ); 13229 13230 } 13231 13232 intersectsSphere( sphere ) { 13233 13234 return sphere.intersectsPlane( this ); 13235 13236 } 13237 13238 coplanarPoint( target ) { 13239 13240 return target.copy( this.normal ).multiplyScalar( - this.constant ); 13241 13242 } 13243 13244 applyMatrix4( matrix, optionalNormalMatrix ) { 13245 13246 const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix ); 13247 13248 const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix ); 13249 13250 const normal = this.normal.applyMatrix3( normalMatrix ).normalize(); 13251 13252 this.constant = - referencePoint.dot( normal ); 13253 13254 return this; 13255 13256 } 13257 13258 translate( offset ) { 13259 13260 this.constant -= offset.dot( this.normal ); 13261 13262 return this; 13263 13264 } 13265 13266 equals( plane ) { 13267 13268 return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); 13269 13270 } 13271 13272 clone() { 13273 13274 return new this.constructor().copy( this ); 13275 13276 } 13277 13278} 13279 13280const _sphere$5 = /*@__PURE__*/ new Sphere(); 13281const _vector$7 = /*@__PURE__*/ new Vector3(); 13282 13283class Frustum { 13284 13285 constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) { 13286 13287 this.planes = [ p0, p1, p2, p3, p4, p5 ]; 13288 13289 } 13290 13291 set( p0, p1, p2, p3, p4, p5 ) { 13292 13293 const planes = this.planes; 13294 13295 planes[ 0 ].copy( p0 ); 13296 planes[ 1 ].copy( p1 ); 13297 planes[ 2 ].copy( p2 ); 13298 planes[ 3 ].copy( p3 ); 13299 planes[ 4 ].copy( p4 ); 13300 planes[ 5 ].copy( p5 ); 13301 13302 return this; 13303 13304 } 13305 13306 copy( frustum ) { 13307 13308 const planes = this.planes; 13309 13310 for ( let i = 0; i < 6; i ++ ) { 13311 13312 planes[ i ].copy( frustum.planes[ i ] ); 13313 13314 } 13315 13316 return this; 13317 13318 } 13319 13320 setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem ) { 13321 13322 const planes = this.planes; 13323 const me = m.elements; 13324 const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ]; 13325 const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ]; 13326 const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ]; 13327 const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ]; 13328 13329 planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize(); 13330 planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize(); 13331 planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize(); 13332 planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize(); 13333 planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize(); 13334 13335 if ( coordinateSystem === WebGLCoordinateSystem ) { 13336 13337 planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); 13338 13339 } else if ( coordinateSystem === WebGPUCoordinateSystem ) { 13340 13341 planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize(); 13342 13343 } else { 13344 13345 throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem ); 13346 13347 } 13348 13349 return this; 13350 13351 } 13352 13353 intersectsObject( object ) { 13354 13355 if ( object.boundingSphere !== undefined ) { 13356 13357 if ( object.boundingSphere === null ) object.computeBoundingSphere(); 13358 13359 _sphere$5.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld ); 13360 13361 } else { 13362 13363 const geometry = object.geometry; 13364 13365 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 13366 13367 _sphere$5.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); 13368 13369 } 13370 13371 return this.intersectsSphere( _sphere$5 ); 13372 13373 } 13374 13375 intersectsSprite( sprite ) { 13376 13377 _sphere$5.center.set( 0, 0, 0 ); 13378 _sphere$5.radius = 0.7071067811865476; 13379 _sphere$5.applyMatrix4( sprite.matrixWorld ); 13380 13381 return this.intersectsSphere( _sphere$5 ); 13382 13383 } 13384 13385 intersectsSphere( sphere ) { 13386 13387 const planes = this.planes; 13388 const center = sphere.center; 13389 const negRadius = - sphere.radius; 13390 13391 for ( let i = 0; i < 6; i ++ ) { 13392 13393 const distance = planes[ i ].distanceToPoint( center ); 13394 13395 if ( distance < negRadius ) { 13396 13397 return false; 13398 13399 } 13400 13401 } 13402 13403 return true; 13404 13405 } 13406 13407 intersectsBox( box ) { 13408 13409 const planes = this.planes; 13410 13411 for ( let i = 0; i < 6; i ++ ) { 13412 13413 const plane = planes[ i ]; 13414 13415 // corner at max distance 13416 13417 _vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x; 13418 _vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y; 13419 _vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z; 13420 13421 if ( plane.distanceToPoint( _vector$7 ) < 0 ) { 13422 13423 return false; 13424 13425 } 13426 13427 } 13428 13429 return true; 13430 13431 } 13432 13433 containsPoint( point ) { 13434 13435 const planes = this.planes; 13436 13437 for ( let i = 0; i < 6; i ++ ) { 13438 13439 if ( planes[ i ].distanceToPoint( point ) < 0 ) { 13440 13441 return false; 13442 13443 } 13444 13445 } 13446 13447 return true; 13448 13449 } 13450 13451 clone() { 13452 13453 return new this.constructor().copy( this ); 13454 13455 } 13456 13457} 13458 13459function WebGLAnimation() { 13460 13461 let context = null; 13462 let isAnimating = false; 13463 let animationLoop = null; 13464 let requestId = null; 13465 13466 function onAnimationFrame( time, frame ) { 13467 13468 animationLoop( time, frame ); 13469 13470 requestId = context.requestAnimationFrame( onAnimationFrame ); 13471 13472 } 13473 13474 return { 13475 13476 start: function () { 13477 13478 if ( isAnimating === true ) return; 13479 if ( animationLoop === null ) return; 13480 13481 requestId = context.requestAnimationFrame( onAnimationFrame ); 13482 13483 isAnimating = true; 13484 13485 }, 13486 13487 stop: function () { 13488 13489 context.cancelAnimationFrame( requestId ); 13490 13491 isAnimating = false; 13492 13493 }, 13494 13495 setAnimationLoop: function ( callback ) { 13496 13497 animationLoop = callback; 13498 13499 }, 13500 13501 setContext: function ( value ) { 13502 13503 context = value; 13504 13505 } 13506 13507 }; 13508 13509} 13510 13511function WebGLAttributes( gl, capabilities ) { 13512 13513 const isWebGL2 = capabilities.isWebGL2; 13514 13515 const buffers = new WeakMap(); 13516 13517 function createBuffer( attribute, bufferType ) { 13518 13519 const array = attribute.array; 13520 const usage = attribute.usage; 13521 const size = array.byteLength; 13522 13523 const buffer = gl.createBuffer(); 13524 13525 gl.bindBuffer( bufferType, buffer ); 13526 gl.bufferData( bufferType, array, usage ); 13527 13528 attribute.onUploadCallback(); 13529 13530 let type; 13531 13532 if ( array instanceof Float32Array ) { 13533 13534 type = gl.FLOAT; 13535 13536 } else if ( array instanceof Uint16Array ) { 13537 13538 if ( attribute.isFloat16BufferAttribute ) { 13539 13540 if ( isWebGL2 ) { 13541 13542 type = gl.HALF_FLOAT; 13543 13544 } else { 13545 13546 throw new Error( 'THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.' ); 13547 13548 } 13549 13550 } else { 13551 13552 type = gl.UNSIGNED_SHORT; 13553 13554 } 13555 13556 } else if ( array instanceof Int16Array ) { 13557 13558 type = gl.SHORT; 13559 13560 } else if ( array instanceof Uint32Array ) { 13561 13562 type = gl.UNSIGNED_INT; 13563 13564 } else if ( array instanceof Int32Array ) { 13565 13566 type = gl.INT; 13567 13568 } else if ( array instanceof Int8Array ) { 13569 13570 type = gl.BYTE; 13571 13572 } else if ( array instanceof Uint8Array ) { 13573 13574 type = gl.UNSIGNED_BYTE; 13575 13576 } else if ( array instanceof Uint8ClampedArray ) { 13577 13578 type = gl.UNSIGNED_BYTE; 13579 13580 } else { 13581 13582 throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array ); 13583 13584 } 13585 13586 return { 13587 buffer: buffer, 13588 type: type, 13589 bytesPerElement: array.BYTES_PER_ELEMENT, 13590 version: attribute.version, 13591 size: size 13592 }; 13593 13594 } 13595 13596 function updateBuffer( buffer, attribute, bufferType ) { 13597 13598 const array = attribute.array; 13599 const updateRange = attribute._updateRange; // deprecated 13600 const updateRanges = attribute.updateRanges; 13601 13602 gl.bindBuffer( bufferType, buffer ); 13603 13604 if ( updateRange.count === - 1 && updateRanges.length === 0 ) { 13605 13606 // Not using update ranges 13607 gl.bufferSubData( bufferType, 0, array ); 13608 13609 } 13610 13611 if ( updateRanges.length !== 0 ) { 13612 13613 for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { 13614 13615 const range = updateRanges[ i ]; 13616 if ( isWebGL2 ) { 13617 13618 gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, 13619 array, range.start, range.count ); 13620 13621 } else { 13622 13623 gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, 13624 array.subarray( range.start, range.start + range.count ) ); 13625 13626 } 13627 13628 } 13629 13630 attribute.clearUpdateRanges(); 13631 13632 } 13633 13634 // deprecated 13635 if ( updateRange.count !== - 1 ) { 13636 13637 if ( isWebGL2 ) { 13638 13639 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, 13640 array, updateRange.offset, updateRange.count ); 13641 13642 } else { 13643 13644 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, 13645 array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) ); 13646 13647 } 13648 13649 updateRange.count = - 1; // reset range 13650 13651 } 13652 13653 attribute.onUploadCallback(); 13654 13655 } 13656 13657 // 13658 13659 function get( attribute ) { 13660 13661 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 13662 13663 return buffers.get( attribute ); 13664 13665 } 13666 13667 function remove( attribute ) { 13668 13669 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 13670 13671 const data = buffers.get( attribute ); 13672 13673 if ( data ) { 13674 13675 gl.deleteBuffer( data.buffer ); 13676 13677 buffers.delete( attribute ); 13678 13679 } 13680 13681 } 13682 13683 function update( attribute, bufferType ) { 13684 13685 if ( attribute.isGLBufferAttribute ) { 13686 13687 const cached = buffers.get( attribute ); 13688 13689 if ( ! cached || cached.version < attribute.version ) { 13690 13691 buffers.set( attribute, { 13692 buffer: attribute.buffer, 13693 type: attribute.type, 13694 bytesPerElement: attribute.elementSize, 13695 version: attribute.version 13696 } ); 13697 13698 } 13699 13700 return; 13701 13702 } 13703 13704 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 13705 13706 const data = buffers.get( attribute ); 13707 13708 if ( data === undefined ) { 13709 13710 buffers.set( attribute, createBuffer( attribute, bufferType ) ); 13711 13712 } else if ( data.version < attribute.version ) { 13713 13714 if ( data.size !== attribute.array.byteLength ) { 13715 13716 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.' ); 13717 13718 } 13719 13720 updateBuffer( data.buffer, attribute, bufferType ); 13721 13722 data.version = attribute.version; 13723 13724 } 13725 13726 } 13727 13728 return { 13729 13730 get: get, 13731 remove: remove, 13732 update: update 13733 13734 }; 13735 13736} 13737 13738class PlaneGeometry extends BufferGeometry { 13739 13740 constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) { 13741 13742 super(); 13743 13744 this.type = 'PlaneGeometry'; 13745 13746 this.parameters = { 13747 width: width, 13748 height: height, 13749 widthSegments: widthSegments, 13750 heightSegments: heightSegments 13751 }; 13752 13753 const width_half = width / 2; 13754 const height_half = height / 2; 13755 13756 const gridX = Math.floor( widthSegments ); 13757 const gridY = Math.floor( heightSegments ); 13758 13759 const gridX1 = gridX + 1; 13760 const gridY1 = gridY + 1; 13761 13762 const segment_width = width / gridX; 13763 const segment_height = height / gridY; 13764 13765 // 13766 13767 const indices = []; 13768 const vertices = []; 13769 const normals = []; 13770 const uvs = []; 13771 13772 for ( let iy = 0; iy < gridY1; iy ++ ) { 13773 13774 const y = iy * segment_height - height_half; 13775 13776 for ( let ix = 0; ix < gridX1; ix ++ ) { 13777 13778 const x = ix * segment_width - width_half; 13779 13780 vertices.push( x, - y, 0 ); 13781 13782 normals.push( 0, 0, 1 ); 13783 13784 uvs.push( ix / gridX ); 13785 uvs.push( 1 - ( iy / gridY ) ); 13786 13787 } 13788 13789 } 13790 13791 for ( let iy = 0; iy < gridY; iy ++ ) { 13792 13793 for ( let ix = 0; ix < gridX; ix ++ ) { 13794 13795 const a = ix + gridX1 * iy; 13796 const b = ix + gridX1 * ( iy + 1 ); 13797 const c = ( ix + 1 ) + gridX1 * ( iy + 1 ); 13798 const d = ( ix + 1 ) + gridX1 * iy; 13799 13800 indices.push( a, b, d ); 13801 indices.push( b, c, d ); 13802 13803 } 13804 13805 } 13806 13807 this.setIndex( indices ); 13808 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 13809 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 13810 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 13811 13812 } 13813 13814 copy( source ) { 13815 13816 super.copy( source ); 13817 13818 this.parameters = Object.assign( {}, source.parameters ); 13819 13820 return this; 13821 13822 } 13823 13824 static fromJSON( data ) { 13825 13826 return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments ); 13827 13828 } 13829 13830} 13831 13832var alphahash_fragment = "#ifdef USE_ALPHAHASH\n\tif ( diffuseColor.a < getAlphaHashThreshold( vPosition ) ) discard;\n#endif"; 13833 13834var 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"; 13835 13836var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif"; 13837 13838var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif"; 13839 13840var alphatest_fragment = "#ifdef USE_ALPHATEST\n\tif ( diffuseColor.a < alphaTest ) discard;
vendor: 6,502 bytes, lines 13840-13862
13840\n#endif"; 13841 13842var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif"; 13843 13844var 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"; 13845 13846var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; 13847 13848var 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"; 13849 13850var batching_vertex = "#ifdef USE_BATCHING\n\tmat4 batchingMatrix = getBatchingMatrix( batchId );\n#endif"; 13851 13852var begin_vertex = "vec3 transformed = vec3( position );\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif"; 13853 13854var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif"; 13855 13856var 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"; 13857 13858var 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"; 13859 13860var 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"; 13861 13862var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#
13862pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif"; 13863 13864var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif"; 13865 13866var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif"; 13867 13868var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif"; 13869 13870var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif"; 13871 13872var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif"; 13873 13874var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif"; 13875 13876var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif"; 13877 13878var 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"; 13879 13880var 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"; 13881 13882var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );
13882\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"; 13883 13884var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif"; 13885 13886var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif"; 13887 13888var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif"; 13889 13890var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif"; 13891 13892var colorspace_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );"; 13893 13894var 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}"; 13895 13896var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif"; 13897 13898var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap
vendor: 9,428 bytes, lines 13898-13926
13898;\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"; 13899 13900var 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"; 13901 13902var 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"; 13903 13904var envmap_vertex = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif"; 13905 13906var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif"; 13907 13908var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif"; 13909 13910var 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"; 13911 13912var 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"; 13913 13914var 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}"; 13915 13916var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif"; 13917 13918var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; 13919 13920var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;"; 13921 13922var 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"; 13923 13924var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif"; 13925 13926var 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,
13926worldNormal, 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,
vendor: 32,390 bytes, lines 13926-13966
13926 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"; 13927 13928var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;"; 13929 13930var 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"; 13931 13932var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;"; 13933 13934var 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"; 13935 13936var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif"; 13937 13938var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}"; 13939 13940var 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"; 13941 13942var 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"; 13943 13944var 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"; 13945 13946var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; 13947 13948var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif"; 13949 13950var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif"; 13951 13952var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif"; 13953 13954var 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"; 13955 13956var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif"; 13957 13958var 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"; 13959 13960var 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"; 13961 13962var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif"; 13963 13964var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; 13965 13966var morph
13966color_vertex = "#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif"; 13967 13968var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif"; 13969 13970var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];
vendor: 27,395 bytes, lines 13970-14032
13970\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif"; 13971 13972var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif"; 13973 13974var 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;"; 13975 13976var 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"; 13977 13978var 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"; 13979 13980var 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"; 13981 13982var 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"; 13983 13984var 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"; 13985 13986var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif"; 13987 13988var 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"; 13989 13990var 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"; 13991 13992var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif"; 13993 13994var 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 );"; 13995 13996var 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}"; 13997 13998var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif"; 13999 14000var 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;"; 14001 14002var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif"; 14003 14004var 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"; 14005 14006var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif"; 14007 14008var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; 14009 14010var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif"; 14011 14012var 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"; 14013 14014var 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"; 14015 14016var 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}"; 14017 14018var 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"; 14019 14020var 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"; 14021 14022var 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"; 14023 14024var 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"; 14025 14026var 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"; 14027 14028var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; 14029 14030var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif"; 14031 14032var 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
14032= LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor *= toneMappingExposure;\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\treturn color;\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }"; 14033 14034var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif"; 14035 14036var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );
vendor: 8,994 bytes, lines 14036-14052
14036\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"; 14037 14038var 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"; 14039 14040var 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"; 14041 14042var 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;\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"; 14043 14044var 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"; 14045 14046const 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}"; 14047 14048const 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}"; 14049 14050const 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}"; 14051 14052const 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
14052flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n}"; 14053 14054const 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}"; 14055 14056const 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}"; 14057 14058const 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#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}"; 14059 14060const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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}"; 14061 14062const 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#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}"; 14063 14064const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\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}"; 14065 14066const 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}"; 14067 14068const 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}"; 14069 14070const 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 <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}"; 14071 14072const 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\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <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}"; 14073 14074const 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 <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}"; 14075 14076const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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}"; 14077 14078const 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 <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}"; 14079 14080const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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}"; 14081 14082const 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 <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}"; 14083 14084const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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;
14084\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}"; 14085 14086const 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 <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}"; 14087 14088const 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\t#include <clipping_planes_fragment>\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}"; 14089 14090const 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 <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}"; 14091 14092const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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}"; 14093 14094const 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 <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}"; 14095 14096const 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;
14096\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <iridescence_fragment>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_physical_pars_fragment>\n#include <transmission_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_pars_fragment>\n#include <iridescence_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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;
14096\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}"; 14097 14098const 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 <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}"; 14099 14100const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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}"; 14101 14102const 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 <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}"; 14103 14104const 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\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\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}"; 14105 14106const 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 <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}"; 14107 14108const 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}"; 14109 14110const 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}"; 14111 14112const 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\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\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}"; 14113 14114const ShaderChunk = { 14115 alphahash_fragment: alphahash_fragment, 14116 alphahash_pars_fragment: alphahash_pars_fragment, 14117 alphamap_fragment: alphamap_fragment, 14118 alphamap_pars_fragment: alphamap_pars_fragment, 14119 alphatest_fragment: alphatest_fragment, 14120 alphatest_pars_fragment: alphatest_pars_fragment, 14121 aomap_fragment: aomap_fragment, 14122 aomap_pars_fragment: aomap_pars_fragment, 14123 batching_pars_vertex: batching_pars_vertex, 14124 batching_vertex: batching_vertex, 14125 begin_vertex: begin_vertex, 14126 beginnormal_vertex: beginnormal_vertex, 14127 bsdfs: bsdfs, 14128 iridescence_fragment: iridescence_fragment, 14129 bumpmap_pars_fragment: bumpmap_pars_fragment, 14130 clipping_planes_fragment: clipping_planes_fragment, 14131 clipping_planes_pars_fragment: clipping_planes_pars_fragment, 14132 clipping_planes_pars_vertex: clipping_planes_pars_vertex, 14133 clipping_planes_vertex: clipping_planes_vertex, 14134 color_fragment: color_fragment, 14135 color_pars_fragment: color_pars_fragment, 14136 color_pars_vertex: color_pars_vertex, 14137 color_vertex: color_vertex, 14138 common: common, 14139 cube_uv_reflection_fragment: cube_uv_reflection_fragment, 14140 defaultnormal_vertex: defaultnormal_vertex, 14141 displacementmap_pars_vertex: displacementmap_pars_vertex, 14142 displacementmap_vertex: displacementmap_vertex, 14143 emissivemap_fragment: emissivemap_fragment, 14144 emissivemap_pars_fragment: emissivemap_pars_fragment, 14145 colorspace_fragment: colorspace_fragment, 14146 colorspace_pars_fragment: colorspace_pars_fragment, 14147 envmap_fragment: envmap_fragment, 14148 envmap_common_pars_fragment: envmap_common_pars_fragment, 14149 envmap_pars_fragment: envmap_pars_fragment, 14150 envmap_pars_vertex: envmap_pars_vertex, 14151 envmap_physical_pars_fragment: envmap_physical_pars_fragment, 14152 envmap_vertex: envmap_vertex, 14153 fog_vertex: fog_vertex, 14154 fog_pars_vertex: fog_pars_vertex, 14155 fog_fragment: fog_fragment, 14156 fog_pars_fragment: fog_pars_fragment, 14157 gradientmap_pars_fragment: gradientmap_pars_fragment, 14158 lightmap_fragment: lightmap_fragment, 14159 lightmap_pars_fragment: lightmap_pars_fragment, 14160 lights_lambert_fragment: lights_lambert_fragment, 14161 lights_lambert_pars_fragment: lights_lambert_pars_fragment, 14162 lights_pars_begin: lights_pars_begin, 14163 lights_toon_fragment: lights_toon_fragment, 14164 lights_toon_pars_fragment: lights_toon_pars_fragment, 14165 lights_phong_fragment: lights_phong_fragment, 14166 lights_phong_pars_fragment: lights_phong_pars_fragment, 14167 lights_physical_fragment: lights_physical_fragment, 14168 lights_physical_pars_fragment: lights_physical_pars_fragment, 14169 lights_fragment_begin: lights_fragment_begin, 14170 lights_fragment_maps: lights_fragment_maps, 14171 lights_fragment_end: lights_fragment_end, 14172 logdepthbuf_fragment: logdepthbuf_fragment, 14173 logdepthbuf_pars_fragment: logdepthbuf_pars_fragment, 14174 logdepthbuf_pars_vertex: logdepthbuf_pars_vertex, 14175 logdepthbuf_vertex: logdepthbuf_vertex, 14176 map_fragment: map_fragment, 14177 map_pars_fragment: map_pars_fragment, 14178 map_particle_fragment: map_particle_fragment, 14179 map_particle_pars_fragment: map_particle_pars_fragment, 14180 metalnessmap_fragment: metalnessmap_fragment, 14181 metalnessmap_pars_fragment: metalnessmap_pars_fragment, 14182 morphcolor_vertex: morphcolor_vertex, 14183 morphnormal_vertex: morphnormal_vertex, 14184 morphtarget_pars_vertex: morphtarget_pars_vertex, 14185 morphtarget_vertex: morphtarget_vertex, 14186 normal_fragment_begin: normal_fragment_begin, 14187 normal_fragment_maps: normal_fragment_maps, 14188 normal_pars_fragment: normal_pars_fragment, 14189 normal_pars_vertex: normal_pars_vertex, 14190 normal_vertex: normal_vertex, 14191 normalmap_pars_fragment: normalmap_pars_fragment, 14192 clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin, 14193 clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps, 14194 clearcoat_pars_fragment: clearcoat_pars_fragment, 14195 iridescence_pars_fragment: iridescence_pars_fragment, 14196 opaque_fragment: opaque_fragment, 14197 packing: packing, 14198 premultiplied_alpha_fragment: premultiplied_alpha_fragment, 14199 project_vertex: project_vertex, 14200 dithering_fragment: dithering_fragment, 14201 dithering_pars_fragment: dithering_pars_fragment, 14202 roughnessmap_fragment: roughnessmap_fragment, 14203 roughnessmap_pars_fragment: roughnessmap_pars_fragment, 14204 shadowmap_pars_fragment: shadowmap_pars_fragment, 14205 shadowmap_pars_vertex: shadowmap_pars_vertex, 14206 shadowmap_vertex: shadowmap_vertex, 14207 shadowmask_pars_fragment: shadowmask_pars_fragment, 14208 skinbase_vertex: skinbase_vertex, 14209 skinning_pars_vertex: skinning_pars_vertex, 14210 skinning_vertex: skinning_vertex, 14211 skinnormal_vertex: skinnormal_vertex, 14212 specularmap_fragment: specularmap_fragment, 14213 specularmap_pars_fragment: specularmap_pars_fragment, 14214 tonemapping_fragment: tonemapping_fragment, 14215 tonemapping_pars_fragment: tonemapping_pars_fragment, 14216 transmission_fragment: transmission_fragment, 14217 transmission_pars_fragment: transmission_pars_fragment, 14218 uv_pars_fragment: uv_pars_fragment, 14219 uv_pars_vertex: uv_pars_vertex, 14220 uv_vertex: uv_vertex, 14221 worldpos_vertex: worldpos_vertex, 14222 14223 background_vert: vertex$h, 14224 background_frag: fragment$h, 14225 backgroundCube_vert: vertex$g, 14226 backgroundCube_frag: fragment$g, 14227 cube_vert: vertex$f, 14228 cube_frag: fragment$f, 14229 depth_vert: vertex$e, 14230 depth_frag: fragment$e, 14231 distanceRGBA_vert: vertex$d, 14232 distanceRGBA_frag: fragment$d, 14233 equirect_vert: vertex$c, 14234 equirect_frag: fragment$c, 14235 linedashed_vert: vertex$b, 14236 linedashed_frag: fragment$b, 14237 meshbasic_vert: vertex$a, 14238 meshbasic_frag: fragment$a, 14239 meshlambert_vert: vertex$9, 14240 meshlambert_frag: fragment$9, 14241 meshmatcap_vert: vertex$8, 14242 meshmatcap_frag: fragment$8, 14243 meshnormal_vert: vertex$7, 14244 meshnormal_frag: fragment$7, 14245 meshphong_vert: vertex$6, 14246 meshphong_frag: fragment$6, 14247 meshphysical_vert: vertex$5, 14248 meshphysical_frag: fragment$5, 14249 meshtoon_vert: vertex$4, 14250 meshtoon_frag: fragment$4, 14251 points_vert: vertex$3, 14252 points_frag: fragment$3, 14253 shadow_vert: vertex$2, 14254 shadow_frag: fragment$2, 14255 sprite_vert: vertex$1, 14256 sprite_frag: fragment$1 14257}; 14258 14259/** 14260 * Uniforms library for shared webgl shaders 14261 */ 14262 14263const UniformsLib = { 14264 14265 common: { 14266 14267 diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, 14268 opacity: { value: 1.0 }, 14269 14270 map: { value: null }, 14271 mapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14272 14273 alphaMap: { value: null }, 14274 alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14275 14276 alphaTest: { value: 0 } 14277 14278 }, 14279 14280 specularmap: { 14281 14282 specularMap: { value: null }, 14283 specularMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14284 14285 }, 14286 14287 envmap: { 14288 14289 envMap: { value: null }, 14290 flipEnvMap: { value: -
vendor: 8,194 bytes, lines 14290-14708
142901 }, 14291 reflectivity: { value: 1.0 }, // basic, lambert, phong 14292 ior: { value: 1.5 }, // physical 14293 refractionRatio: { value: 0.98 }, // basic, lambert, phong 14294 14295 }, 14296 14297 aomap: { 14298 14299 aoMap: { value: null }, 14300 aoMapIntensity: { value: 1 }, 14301 aoMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14302 14303 }, 14304 14305 lightmap: { 14306 14307 lightMap: { value: null }, 14308 lightMapIntensity: { value: 1 }, 14309 lightMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14310 14311 }, 14312 14313 bumpmap: { 14314 14315 bumpMap: { value: null }, 14316 bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14317 bumpScale: { value: 1 } 14318 14319 }, 14320 14321 normalmap: { 14322 14323 normalMap: { value: null }, 14324 normalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14325 normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) } 14326 14327 }, 14328 14329 displacementmap: { 14330 14331 displacementMap: { value: null }, 14332 displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14333 displacementScale: { value: 1 }, 14334 displacementBias: { value: 0 } 14335 14336 }, 14337 14338 emissivemap: { 14339 14340 emissiveMap: { value: null }, 14341 emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14342 14343 }, 14344 14345 metalnessmap: { 14346 14347 metalnessMap: { value: null }, 14348 metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14349 14350 }, 14351 14352 roughnessmap: { 14353 14354 roughnessMap: { value: null }, 14355 roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() } 14356 14357 }, 14358 14359 gradientmap: { 14360 14361 gradientMap: { value: null } 14362 14363 }, 14364 14365 fog: { 14366 14367 fogDensity: { value: 0.00025 }, 14368 fogNear: { value: 1 }, 14369 fogFar: { value: 2000 }, 14370 fogColor: { value: /*@__PURE__*/ new Color( 0xffffff ) } 14371 14372 }, 14373 14374 lights: { 14375 14376 ambientLightColor: { value: [] }, 14377 14378 lightProbe: { value: [] }, 14379 14380 directionalLights: { value: [], properties: { 14381 direction: {}, 14382 color: {} 14383 } }, 14384 14385 directionalLightShadows: { value: [], properties: { 14386 shadowBias: {}, 14387 shadowNormalBias: {}, 14388 shadowRadius: {}, 14389 shadowMapSize: {} 14390 } }, 14391 14392 directionalShadowMap: { value: [] }, 14393 directionalShadowMatrix: { value: [] }, 14394 14395 spotLights: { value: [], properties: { 14396 color: {}, 14397 position: {}, 14398 direction: {}, 14399 distance: {}, 14400 coneCos: {}, 14401 penumbraCos: {}, 14402 decay: {} 14403 } }, 14404 14405 spotLightShadows: { value: [], properties: { 14406 shadowBias: {}, 14407 shadowNormalBias: {}, 14408 shadowRadius: {}, 14409 shadowMapSize: {} 14410 } }, 14411 14412 spotLightMap: { value: [] }, 14413 spotShadowMap: { value: [] }, 14414 spotLightMatrix: { value: [] }, 14415 14416 pointLights: { value: [], properties: { 14417 color: {}, 14418 position: {}, 14419 decay: {}, 14420 distance: {} 14421 } }, 14422 14423 pointLightShadows: { value: [], properties: { 14424 shadowBias: {}, 14425 shadowNormalBias: {}, 14426 shadowRadius: {}, 14427 shadowMapSize: {}, 14428 shadowCameraNear: {}, 14429 shadowCameraFar: {} 14430 } }, 14431 14432 pointShadowMap: { value: [] }, 14433 pointShadowMatrix: { value: [] }, 14434 14435 hemisphereLights: { value: [], properties: { 14436 direction: {}, 14437 skyColor: {}, 14438 groundColor: {} 14439 } }, 14440 14441 // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src 14442 rectAreaLights: { value: [], properties: { 14443 color: {}, 14444 position: {}, 14445 width: {}, 14446 height: {} 14447 } }, 14448 14449 ltc_1: { value: null }, 14450 ltc_2: { value: null } 14451 14452 }, 14453 14454 points: { 14455 14456 diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, 14457 opacity: { value: 1.0 }, 14458 size: { value: 1.0 }, 14459 scale: { value: 1.0 }, 14460 map: { value: null }, 14461 alphaMap: { value: null }, 14462 alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14463 alphaTest: { value: 0 }, 14464 uvTransform: { value: /*@__PURE__*/ new Matrix3() } 14465 14466 }, 14467 14468 sprite: { 14469 14470 diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) }, 14471 opacity: { value: 1.0 }, 14472 center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) }, 14473 rotation: { value: 0.0 }, 14474 map: { value: null }, 14475 mapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14476 alphaMap: { value: null }, 14477 alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14478 alphaTest: { value: 0 } 14479 14480 } 14481 14482}; 14483 14484const ShaderLib = { 14485 14486 basic: { 14487 14488 uniforms: /*@__PURE__*/ mergeUniforms( [ 14489 UniformsLib.common, 14490 UniformsLib.specularmap, 14491 UniformsLib.envmap, 14492 UniformsLib.aomap, 14493 UniformsLib.lightmap, 14494 UniformsLib.fog 14495 ] ), 14496 14497 vertexShader: ShaderChunk.meshbasic_vert, 14498 fragmentShader: ShaderChunk.meshbasic_frag 14499 14500 }, 14501 14502 lambert: { 14503 14504 uniforms: /*@__PURE__*/ mergeUniforms( [ 14505 UniformsLib.common, 14506 UniformsLib.specularmap, 14507 UniformsLib.envmap, 14508 UniformsLib.aomap, 14509 UniformsLib.lightmap, 14510 UniformsLib.emissivemap, 14511 UniformsLib.bumpmap, 14512 UniformsLib.normalmap, 14513 UniformsLib.displacementmap, 14514 UniformsLib.fog, 14515 UniformsLib.lights, 14516 { 14517 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) } 14518 } 14519 ] ), 14520 14521 vertexShader: ShaderChunk.meshlambert_vert, 14522 fragmentShader: ShaderChunk.meshlambert_frag 14523 14524 }, 14525 14526 phong: { 14527 14528 uniforms: /*@__PURE__*/ mergeUniforms( [ 14529 UniformsLib.common, 14530 UniformsLib.specularmap, 14531 UniformsLib.envmap, 14532 UniformsLib.aomap, 14533 UniformsLib.lightmap, 14534 UniformsLib.emissivemap, 14535 UniformsLib.bumpmap, 14536 UniformsLib.normalmap, 14537 UniformsLib.displacementmap, 14538 UniformsLib.fog, 14539 UniformsLib.lights, 14540 { 14541 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 14542 specular: { value: /*@__PURE__*/ new Color( 0x111111 ) }, 14543 shininess: { value: 30 } 14544 } 14545 ] ), 14546 14547 vertexShader: ShaderChunk.meshphong_vert, 14548 fragmentShader: ShaderChunk.meshphong_frag 14549 14550 }, 14551 14552 standard: { 14553 14554 uniforms: /*@__PURE__*/ mergeUniforms( [ 14555 UniformsLib.common, 14556 UniformsLib.envmap, 14557 UniformsLib.aomap, 14558 UniformsLib.lightmap, 14559 UniformsLib.emissivemap, 14560 UniformsLib.bumpmap, 14561 UniformsLib.normalmap, 14562 UniformsLib.displacementmap, 14563 UniformsLib.roughnessmap, 14564 UniformsLib.metalnessmap, 14565 UniformsLib.fog, 14566 UniformsLib.lights, 14567 { 14568 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 14569 roughness: { value: 1.0 }, 14570 metalness: { value: 0.0 }, 14571 envMapIntensity: { value: 1 } // temporary 14572 } 14573 ] ), 14574 14575 vertexShader: ShaderChunk.meshphysical_vert, 14576 fragmentShader: ShaderChunk.meshphysical_frag 14577 14578 }, 14579 14580 toon: { 14581 14582 uniforms: /*@__PURE__*/ mergeUniforms( [ 14583 UniformsLib.common, 14584 UniformsLib.aomap, 14585 UniformsLib.lightmap, 14586 UniformsLib.emissivemap, 14587 UniformsLib.bumpmap, 14588 UniformsLib.normalmap, 14589 UniformsLib.displacementmap, 14590 UniformsLib.gradientmap, 14591 UniformsLib.fog, 14592 UniformsLib.lights, 14593 { 14594 emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) } 14595 } 14596 ] ), 14597 14598 vertexShader: ShaderChunk.meshtoon_vert, 14599 fragmentShader: ShaderChunk.meshtoon_frag 14600 14601 }, 14602 14603 matcap: { 14604 14605 uniforms: /*@__PURE__*/ mergeUniforms( [ 14606 UniformsLib.common, 14607 UniformsLib.bumpmap, 14608 UniformsLib.normalmap, 14609 UniformsLib.displacementmap, 14610 UniformsLib.fog, 14611 { 14612 matcap: { value: null } 14613 } 14614 ] ), 14615 14616 vertexShader: ShaderChunk.meshmatcap_vert, 14617 fragmentShader: ShaderChunk.meshmatcap_frag 14618 14619 }, 14620 14621 points: { 14622 14623 uniforms: /*@__PURE__*/ mergeUniforms( [ 14624 UniformsLib.points, 14625 UniformsLib.fog 14626 ] ), 14627 14628 vertexShader: ShaderChunk.points_vert, 14629 fragmentShader: ShaderChunk.points_frag 14630 14631 }, 14632 14633 dashed: { 14634 14635 uniforms: /*@__PURE__*/ mergeUniforms( [ 14636 UniformsLib.common, 14637 UniformsLib.fog, 14638 { 14639 scale: { value: 1 }, 14640 dashSize: { value: 1 }, 14641 totalSize: { value: 2 } 14642 } 14643 ] ), 14644 14645 vertexShader: ShaderChunk.linedashed_vert, 14646 fragmentShader: ShaderChunk.linedashed_frag 14647 14648 }, 14649 14650 depth: { 14651 14652 uniforms: /*@__PURE__*/ mergeUniforms( [ 14653 UniformsLib.common, 14654 UniformsLib.displacementmap 14655 ] ), 14656 14657 vertexShader: ShaderChunk.depth_vert, 14658 fragmentShader: ShaderChunk.depth_frag 14659 14660 }, 14661 14662 normal: { 14663 14664 uniforms: /*@__PURE__*/ mergeUniforms( [ 14665 UniformsLib.common, 14666 UniformsLib.bumpmap, 14667 UniformsLib.normalmap, 14668 UniformsLib.displacementmap, 14669 { 14670 opacity: { value: 1.0 } 14671 } 14672 ] ), 14673 14674 vertexShader: ShaderChunk.meshnormal_vert, 14675 fragmentShader: ShaderChunk.meshnormal_frag 14676 14677 }, 14678 14679 sprite: { 14680 14681 uniforms: /*@__PURE__*/ mergeUniforms( [ 14682 UniformsLib.sprite, 14683 UniformsLib.fog 14684 ] ), 14685 14686 vertexShader: ShaderChunk.sprite_vert, 14687 fragmentShader: ShaderChunk.sprite_frag 14688 14689 }, 14690 14691 background: { 14692 14693 uniforms: { 14694 uvTransform: { value: /*@__PURE__*/ new Matrix3() }, 14695 t2D: { value: null }, 14696 backgroundIntensity: { value: 1 } 14697 }, 14698 14699 vertexShader: ShaderChunk.background_vert, 14700 fragmentShader: ShaderChunk.background_frag 14701 14702 }, 14703 14704 backgroundCube: { 14705 14706 uniforms: { 14707 envMap: { value: null }, 14708 flipEnvMap: { value: -
vendor: 3,607 bytes, lines 14708-14834
14708 1 }, 14709 backgroundBlurriness: { value: 0 }, 14710 backgroundIntensity: { value: 1 } 14711 }, 14712 14713 vertexShader: ShaderChunk.backgroundCube_vert, 14714 fragmentShader: ShaderChunk.backgroundCube_frag 14715 14716 }, 14717 14718 cube: { 14719 14720 uniforms: { 14721 tCube: { value: null }, 14722 tFlip: { value: - 1 }, 14723 opacity: { value: 1.0 } 14724 }, 14725 14726 vertexShader: ShaderChunk.cube_vert, 14727 fragmentShader: ShaderChunk.cube_frag 14728 14729 }, 14730 14731 equirect: { 14732 14733 uniforms: { 14734 tEquirect: { value: null }, 14735 }, 14736 14737 vertexShader: ShaderChunk.equirect_vert, 14738 fragmentShader: ShaderChunk.equirect_frag 14739 14740 }, 14741 14742 distanceRGBA: { 14743 14744 uniforms: /*@__PURE__*/ mergeUniforms( [ 14745 UniformsLib.common, 14746 UniformsLib.displacementmap, 14747 { 14748 referencePosition: { value: /*@__PURE__*/ new Vector3() }, 14749 nearDistance: { value: 1 }, 14750 farDistance: { value: 1000 } 14751 } 14752 ] ), 14753 14754 vertexShader: ShaderChunk.distanceRGBA_vert, 14755 fragmentShader: ShaderChunk.distanceRGBA_frag 14756 14757 }, 14758 14759 shadow: { 14760 14761 uniforms: /*@__PURE__*/ mergeUniforms( [ 14762 UniformsLib.lights, 14763 UniformsLib.fog, 14764 { 14765 color: { value: /*@__PURE__*/ new Color( 0x00000 ) }, 14766 opacity: { value: 1.0 } 14767 }, 14768 ] ), 14769 14770 vertexShader: ShaderChunk.shadow_vert, 14771 fragmentShader: ShaderChunk.shadow_frag 14772 14773 } 14774 14775}; 14776 14777ShaderLib.physical = { 14778 14779 uniforms: /*@__PURE__*/ mergeUniforms( [ 14780 ShaderLib.standard.uniforms, 14781 { 14782 clearcoat: { value: 0 }, 14783 clearcoatMap: { value: null }, 14784 clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14785 clearcoatNormalMap: { value: null }, 14786 clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14787 clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }, 14788 clearcoatRoughness: { value: 0 }, 14789 clearcoatRoughnessMap: { value: null }, 14790 clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14791 iridescence: { value: 0 }, 14792 iridescenceMap: { value: null }, 14793 iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14794 iridescenceIOR: { value: 1.3 }, 14795 iridescenceThicknessMinimum: { value: 100 }, 14796 iridescenceThicknessMaximum: { value: 400 }, 14797 iridescenceThicknessMap: { value: null }, 14798 iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14799 sheen: { value: 0 }, 14800 sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 14801 sheenColorMap: { value: null }, 14802 sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14803 sheenRoughness: { value: 1 }, 14804 sheenRoughnessMap: { value: null }, 14805 sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14806 transmission: { value: 0 }, 14807 transmissionMap: { value: null }, 14808 transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14809 transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() }, 14810 transmissionSamplerMap: { value: null }, 14811 thickness: { value: 0 }, 14812 thicknessMap: { value: null }, 14813 thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14814 attenuationDistance: { value: 0 }, 14815 attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) }, 14816 specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) }, 14817 specularColorMap: { value: null }, 14818 specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14819 specularIntensity: { value: 1 }, 14820 specularIntensityMap: { value: null }, 14821 specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14822 anisotropyVector: { value: /*@__PURE__*/ new Vector2() }, 14823 anisotropyMap: { value: null }, 14824 anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() }, 14825 } 14826 ] ), 14827 14828 vertexShader: ShaderChunk.meshphysical_vert, 14829 fragmentShader: ShaderChunk.meshphysical_frag 14830 14831}; 14832 14833const _rgb = { r: 0, b: 0, g: 0 }; 14834
vendor: 2,765 bytes, lines 14835-14933
14835function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) { 14836 14837 const clearColor = new Color( 0x000000 ); 14838 let clearAlpha = alpha === true ? 0 : 1; 14839 14840 let planeMesh; 14841 let boxMesh; 14842 14843 let currentBackground = null; 14844 let currentBackgroundVersion = 0; 14845 let currentTonemapping = null; 14846 14847 function render( renderList, scene ) { 14848 14849 let forceClear = false; 14850 let background = scene.isScene === true ? scene.background : null; 14851 14852 if ( background && background.isTexture ) { 14853 14854 const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background 14855 background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background ); 14856 14857 } 14858 14859 if ( background === null ) { 14860 14861 setClear( clearColor, clearAlpha ); 14862 14863 } else if ( background && background.isColor ) { 14864 14865 setClear( background, 1 ); 14866 forceClear = true; 14867 14868 } 14869 14870 const environmentBlendMode = renderer.xr.getEnvironmentBlendMode(); 14871 14872 if ( environmentBlendMode === 'additive' ) { 14873 14874 state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha ); 14875 14876 } else if ( environmentBlendMode === 'alpha-blend' ) { 14877 14878 state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha ); 14879 14880 } 14881 14882 if ( renderer.autoClear || forceClear ) { 14883 14884 renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); 14885 14886 } 14887 14888 if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) { 14889 14890 if ( boxMesh === undefined ) { 14891 14892 boxMesh = new Mesh( 14893 new BoxGeometry( 1, 1, 1 ), 14894 new ShaderMaterial( { 14895 name: 'BackgroundCubeMaterial', 14896 uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ), 14897 vertexShader: ShaderLib.backgroundCube.vertexShader, 14898 fragmentShader: ShaderLib.backgroundCube.fragmentShader, 14899 side: BackSide, 14900 depthTest: false, 14901 depthWrite: false, 14902 fog: false 14903 } ) 14904 ); 14905 14906 boxMesh.geometry.deleteAttribute( 'normal' ); 14907 boxMesh.geometry.deleteAttribute( 'uv' ); 14908 14909 boxMesh.onBeforeRender = function ( renderer, scene, camera ) { 14910 14911 this.matrixWorld.copyPosition( camera.matrixWorld ); 14912 14913 }; 14914 14915 // add "envMap" material property so the renderer can evaluate it like for built-in materials 14916 Object.defineProperty( boxMesh.material, 'envMap', { 14917 14918 get: function () { 14919 14920 return this.uniforms.envMap.value; 14921 14922 } 14923 14924 } ); 14925 14926 objects.update( boxMesh ); 14927 14928 } 14929 14930 boxMesh.material.uniforms.envMap.value = background; 14931 boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1; 14932 boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness; 14933 boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity
vendor: 25,376 bytes, lines 14933-16100
14933; 14934 boxMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer; 14935 14936 if ( currentBackground !== background || 14937 currentBackgroundVersion !== background.version || 14938 currentTonemapping !== renderer.toneMapping ) { 14939 14940 boxMesh.material.needsUpdate = true; 14941 14942 currentBackground = background; 14943 currentBackgroundVersion = background.version; 14944 currentTonemapping = renderer.toneMapping; 14945 14946 } 14947 14948 boxMesh.layers.enableAll(); 14949 14950 // push to the pre-sorted opaque render list 14951 renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null ); 14952 14953 } else if ( background && background.isTexture ) { 14954 14955 if ( planeMesh === undefined ) { 14956 14957 planeMesh = new Mesh( 14958 new PlaneGeometry( 2, 2 ), 14959 new ShaderMaterial( { 14960 name: 'BackgroundMaterial', 14961 uniforms: cloneUniforms( ShaderLib.background.uniforms ), 14962 vertexShader: ShaderLib.background.vertexShader, 14963 fragmentShader: ShaderLib.background.fragmentShader, 14964 side: FrontSide, 14965 depthTest: false, 14966 depthWrite: false, 14967 fog: false 14968 } ) 14969 ); 14970 14971 planeMesh.geometry.deleteAttribute( 'normal' ); 14972 14973 // add "map" material property so the renderer can evaluate it like for built-in materials 14974 Object.defineProperty( planeMesh.material, 'map', { 14975 14976 get: function () { 14977 14978 return this.uniforms.t2D.value; 14979 14980 } 14981 14982 } ); 14983 14984 objects.update( planeMesh ); 14985 14986 } 14987 14988 planeMesh.material.uniforms.t2D.value = background; 14989 planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity; 14990 planeMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer; 14991 14992 if ( background.matrixAutoUpdate === true ) { 14993 14994 background.updateMatrix(); 14995 14996 } 14997 14998 planeMesh.material.uniforms.uvTransform.value.copy( background.matrix ); 14999 15000 if ( currentBackground !== background || 15001 currentBackgroundVersion !== background.version || 15002 currentTonemapping !== renderer.toneMapping ) { 15003 15004 planeMesh.material.needsUpdate = true; 15005 15006 currentBackground = background; 15007 currentBackgroundVersion = background.version; 15008 currentTonemapping = renderer.toneMapping; 15009 15010 } 15011 15012 planeMesh.layers.enableAll(); 15013 15014 // push to the pre-sorted opaque render list 15015 renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null ); 15016 15017 } 15018 15019 } 15020 15021 function setClear( color, alpha ) { 15022 15023 color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) ); 15024 15025 state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha ); 15026 15027 } 15028 15029 return { 15030 15031 getClearColor: function () { 15032 15033 return clearColor; 15034 15035 }, 15036 setClearColor: function ( color, alpha = 1 ) { 15037 15038 clearColor.set( color ); 15039 clearAlpha = alpha; 15040 setClear( clearColor, clearAlpha ); 15041 15042 }, 15043 getClearAlpha: function () { 15044 15045 return clearAlpha; 15046 15047 }, 15048 setClearAlpha: function ( alpha ) { 15049 15050 clearAlpha = alpha; 15051 setClear( clearColor, clearAlpha ); 15052 15053 }, 15054 render: render 15055 15056 }; 15057 15058} 15059 15060function WebGLBindingStates( gl, extensions, attributes, capabilities ) { 15061 15062 const maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); 15063 15064 const extension = capabilities.isWebGL2 ? null : extensions.get( 'OES_vertex_array_object' ); 15065 const vaoAvailable = capabilities.isWebGL2 || extension !== null; 15066 15067 const bindingStates = {}; 15068 15069 const defaultState = createBindingState( null ); 15070 let currentState = defaultState; 15071 let forceUpdate = false; 15072 15073 function setup( object, material, program, geometry, index ) { 15074 15075 let updateBuffers = false; 15076 15077 if ( vaoAvailable ) { 15078 15079 const state = getBindingState( geometry, program, material ); 15080 15081 if ( currentState !== state ) { 15082 15083 currentState = state; 15084 bindVertexArrayObject( currentState.object ); 15085 15086 } 15087 15088 updateBuffers = needsUpdate( object, geometry, program, index ); 15089 15090 if ( updateBuffers ) saveCache( object, geometry, program, index ); 15091 15092 } else { 15093 15094 const wireframe = ( material.wireframe === true ); 15095 15096 if ( currentState.geometry !== geometry.id || 15097 currentState.program !== program.id || 15098 currentState.wireframe !== wireframe ) { 15099 15100 currentState.geometry = geometry.id; 15101 currentState.program = program.id; 15102 currentState.wireframe = wireframe; 15103 15104 updateBuffers = true; 15105 15106 } 15107 15108 } 15109 15110 if ( index !== null ) { 15111 15112 attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); 15113 15114 } 15115 15116 if ( updateBuffers || forceUpdate ) { 15117 15118 forceUpdate = false; 15119 15120 setupVertexAttributes( object, material, program, geometry ); 15121 15122 if ( index !== null ) { 15123 15124 gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer ); 15125 15126 } 15127 15128 } 15129 15130 } 15131 15132 function createVertexArrayObject() { 15133 15134 if ( capabilities.isWebGL2 ) return gl.createVertexArray(); 15135 15136 return extension.createVertexArrayOES(); 15137 15138 } 15139 15140 function bindVertexArrayObject( vao ) { 15141 15142 if ( capabilities.isWebGL2 ) return gl.bindVertexArray( vao ); 15143 15144 return extension.bindVertexArrayOES( vao ); 15145 15146 } 15147 15148 function deleteVertexArrayObject( vao ) { 15149 15150 if ( capabilities.isWebGL2 ) return gl.deleteVertexArray( vao ); 15151 15152 return extension.deleteVertexArrayOES( vao ); 15153 15154 } 15155 15156 function getBindingState( geometry, program, material ) { 15157 15158 const wireframe = ( material.wireframe === true ); 15159 15160 let programMap = bindingStates[ geometry.id ]; 15161 15162 if ( programMap === undefined ) { 15163 15164 programMap = {}; 15165 bindingStates[ geometry.id ] = programMap; 15166 15167 } 15168 15169 let stateMap = programMap[ program.id ]; 15170 15171 if ( stateMap === undefined ) { 15172 15173 stateMap = {}; 15174 programMap[ program.id ] = stateMap; 15175 15176 } 15177 15178 let state = stateMap[ wireframe ]; 15179 15180 if ( state === undefined ) { 15181 15182 state = createBindingState( createVertexArrayObject() ); 15183 stateMap[ wireframe ] = state; 15184 15185 } 15186 15187 return state; 15188 15189 } 15190 15191 function createBindingState( vao ) { 15192 15193 const newAttributes = []; 15194 const enabledAttributes = []; 15195 const attributeDivisors = []; 15196 15197 for ( let i = 0; i < maxVertexAttributes; i ++ ) { 15198 15199 newAttributes[ i ] = 0; 15200 enabledAttributes[ i ] = 0; 15201 attributeDivisors[ i ] = 0; 15202 15203 } 15204 15205 return { 15206 15207 // for backward compatibility on non-VAO support browser 15208 geometry: null, 15209 program: null, 15210 wireframe: false, 15211 15212 newAttributes: newAttributes, 15213 enabledAttributes: enabledAttributes, 15214 attributeDivisors: attributeDivisors, 15215 object: vao, 15216 attributes: {}, 15217 index: null 15218 15219 }; 15220 15221 } 15222 15223 function needsUpdate( object, geometry, program, index ) { 15224 15225 const cachedAttributes = currentState.attributes; 15226 const geometryAttributes = geometry.attributes; 15227 15228 let attributesNum = 0; 15229 15230 const programAttributes = program.getAttributes(); 15231 15232 for ( const name in programAttributes ) { 15233 15234 const programAttribute = programAttributes[ name ]; 15235 15236 if ( programAttribute.location >= 0 ) { 15237 15238 const cachedAttribute = cachedAttributes[ name ]; 15239 let geometryAttribute = geometryAttributes[ name ]; 15240 15241 if ( geometryAttribute === undefined ) { 15242 15243 if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; 15244 if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; 15245 15246 } 15247 15248 if ( cachedAttribute === undefined ) return true; 15249 15250 if ( cachedAttribute.attribute !== geometryAttribute ) return true; 15251 15252 if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data ) return true; 15253 15254 attributesNum ++; 15255 15256 } 15257 15258 } 15259 15260 if ( currentState.attributesNum !== attributesNum ) return true; 15261 15262 if ( currentState.index !== index ) return true; 15263 15264 return false; 15265 15266 } 15267 15268 function saveCache( object, geometry, program, index ) { 15269 15270 const cache = {}; 15271 const attributes = geometry.attributes; 15272 let attributesNum = 0; 15273 15274 const programAttributes = program.getAttributes(); 15275 15276 for ( const name in programAttributes ) { 15277 15278 const programAttribute = programAttributes[ name ]; 15279 15280 if ( programAttribute.location >= 0 ) { 15281 15282 let attribute = attributes[ name ]; 15283 15284 if ( attribute === undefined ) { 15285 15286 if ( name === 'instanceMatrix' && object.instanceMatrix ) attribute = object.instanceMatrix; 15287 if ( name === 'instanceColor' && object.instanceColor ) attribute = object.instanceColor; 15288 15289 } 15290 15291 const data = {}; 15292 data.attribute = attribute; 15293 15294 if ( attribute && attribute.data ) { 15295 15296 data.data = attribute.data; 15297 15298 } 15299 15300 cache[ name ] = data; 15301 15302 attributesNum ++; 15303 15304 } 15305 15306 } 15307 15308 currentState.attributes = cache; 15309 currentState.attributesNum = attributesNum; 15310 15311 currentState.index = index; 15312 15313 } 15314 15315 function initAttributes() { 15316 15317 const newAttributes = currentState.newAttributes; 15318 15319 for ( let i = 0, il = newAttributes.length; i < il; i ++ ) { 15320 15321 newAttributes[ i ] = 0; 15322 15323 } 15324 15325 } 15326 15327 function enableAttribute( attribute ) { 15328 15329 enableAttributeAndDivisor( attribute, 0 ); 15330 15331 } 15332 15333 function enableAttributeAndDivisor( attribute, meshPerAttribute ) { 15334 15335 const newAttributes = currentState.newAttributes; 15336 const enabledAttributes = currentState.enabledAttributes; 15337 const attributeDivisors = currentState.attributeDivisors; 15338 15339 newAttributes[ attribute ] = 1; 15340 15341 if ( enabledAttributes[ attribute ] === 0 ) { 15342 15343 gl.enableVertexAttribArray( attribute ); 15344 enabledAttributes[ attribute ] = 1; 15345 15346 } 15347 15348 if ( attributeDivisors[ attribute ] !== meshPerAttribute ) { 15349 15350 const extension = capabilities.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' ); 15351 15352 extension[ capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute ); 15353 attributeDivisors[ attribute ] = meshPerAttribute; 15354 15355 } 15356 15357 } 15358 15359 function disableUnusedAttributes() { 15360 15361 const newAttributes = currentState.newAttributes; 15362 const enabledAttributes = currentState.enabledAttributes; 15363 15364 for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) { 15365 15366 if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { 15367 15368 gl.disableVertexAttribArray( i ); 15369 enabledAttributes[ i ] = 0; 15370 15371 } 15372 15373 } 15374 15375 } 15376 15377 function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) { 15378 15379 if ( integer === true ) { 15380 15381 gl.vertexAttribIPointer( index, size, type, stride, offset ); 15382 15383 } else { 15384 15385 gl.vertexAttribPointer( index, size, type, normalized, stride, offset ); 15386 15387 } 15388 15389 } 15390 15391 function setupVertexAttributes( object, material, program, geometry ) { 15392 15393 if ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) { 15394 15395 if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) return; 15396 15397 } 15398 15399 initAttributes(); 15400 15401 const geometryAttributes = geometry.attributes; 15402 15403 const programAttributes = program.getAttributes(); 15404 15405 const materialDefaultAttributeValues = material.defaultAttributeValues; 15406 15407 for ( const name in programAttributes ) { 15408 15409 const programAttribute = programAttributes[ name ]; 15410 15411 if ( programAttribute.location >= 0 ) { 15412 15413 let geometryAttribute = geometryAttributes[ name ]; 15414 15415 if ( geometryAttribute === undefined ) { 15416 15417 if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; 15418 if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; 15419 15420 } 15421 15422 if ( geometryAttribute !== undefined ) { 15423 15424 const normalized = geometryAttribute.normalized; 15425 const size = geometryAttribute.itemSize; 15426 15427 const attribute = attributes.get( geometryAttribute ); 15428 15429 // TODO Attribute may not be available on context restore 15430 15431 if ( attribute === undefined ) continue; 15432 15433 const buffer = attribute.buffer; 15434 const type = attribute.type; 15435 const bytesPerElement = attribute.bytesPerElement; 15436 15437 // check for integer attributes (WebGL 2 only) 15438 15439 const integer = ( capabilities.isWebGL2 === true && ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType ) ); 15440 15441 if ( geometryAttribute.isInterleavedBufferAttribute ) { 15442 15443 const data = geometryAttribute.data; 15444 const stride = data.stride; 15445 const offset = geometryAttribute.offset; 15446 15447 if ( data.isInstancedInterleavedBuffer ) { 15448 15449 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15450 15451 enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute ); 15452 15453 } 15454 15455 if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { 15456 15457 geometry._maxInstanceCount = data.meshPerAttribute * data.count; 15458 15459 } 15460 15461 } else { 15462 15463 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15464 15465 enableAttribute( programAttribute.location + i ); 15466 15467 } 15468 15469 } 15470 15471 gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); 15472 15473 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15474 15475 vertexAttribPointer( 15476 programAttribute.location + i, 15477 size / programAttribute.locationSize, 15478 type, 15479 normalized, 15480 stride * bytesPerElement, 15481 ( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement, 15482 integer 15483 ); 15484 15485 } 15486 15487 } else { 15488 15489 if ( geometryAttribute.isInstancedBufferAttribute ) { 15490 15491 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15492 15493 enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute ); 15494 15495 } 15496 15497 if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) { 15498 15499 geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; 15500 15501 } 15502 15503 } else { 15504 15505 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15506 15507 enableAttribute( programAttribute.location + i ); 15508 15509 } 15510 15511 } 15512 15513 gl.bindBuffer( gl.ARRAY_BUFFER, buffer ); 15514 15515 for ( let i = 0; i < programAttribute.locationSize; i ++ ) { 15516 15517 vertexAttribPointer( 15518 programAttribute.location + i, 15519 size / programAttribute.locationSize, 15520 type, 15521 normalized, 15522 size * bytesPerElement, 15523 ( size / programAttribute.locationSize ) * i * bytesPerElement, 15524 integer 15525 ); 15526 15527 } 15528 15529 } 15530 15531 } else if ( materialDefaultAttributeValues !== undefined ) { 15532 15533 const value = materialDefaultAttributeValues[ name ]; 15534 15535 if ( value !== undefined ) { 15536 15537 switch ( value.length ) { 15538 15539 case 2: 15540 gl.vertexAttrib2fv( programAttribute.location, value ); 15541 break; 15542 15543 case 3: 15544 gl.vertexAttrib3fv( programAttribute.location, value ); 15545 break; 15546 15547 case 4: 15548 gl.vertexAttrib4fv( programAttribute.location, value ); 15549 break; 15550 15551 default: 15552 gl.vertexAttrib1fv( programAttribute.location, value ); 15553 15554 } 15555 15556 } 15557 15558 } 15559 15560 } 15561 15562 } 15563 15564 disableUnusedAttributes(); 15565 15566 } 15567 15568 function dispose() { 15569 15570 reset(); 15571 15572 for ( const geometryId in bindingStates ) { 15573 15574 const programMap = bindingStates[ geometryId ]; 15575 15576 for ( const programId in programMap ) { 15577 15578 const stateMap = programMap[ programId ]; 15579 15580 for ( const wireframe in stateMap ) { 15581 15582 deleteVertexArrayObject( stateMap[ wireframe ].object ); 15583 15584 delete stateMap[ wireframe ]; 15585 15586 } 15587 15588 delete programMap[ programId ]; 15589 15590 } 15591 15592 delete bindingStates[ geometryId ]; 15593 15594 } 15595 15596 } 15597 15598 function releaseStatesOfGeometry( geometry ) { 15599 15600 if ( bindingStates[ geometry.id ] === undefined ) return; 15601 15602 const programMap = bindingStates[ geometry.id ]; 15603 15604 for ( const programId in programMap ) { 15605 15606 const stateMap = programMap[ programId ]; 15607 15608 for ( const wireframe in stateMap ) { 15609 15610 deleteVertexArrayObject( stateMap[ wireframe ].object ); 15611 15612 delete stateMap[ wireframe ]; 15613 15614 } 15615 15616 delete programMap[ programId ]; 15617 15618 } 15619 15620 delete bindingStates[ geometry.id ]; 15621 15622 } 15623 15624 function releaseStatesOfProgram( program ) { 15625 15626 for ( const geometryId in bindingStates ) { 15627 15628 const programMap = bindingStates[ geometryId ]; 15629 15630 if ( programMap[ program.id ] === undefined ) continue; 15631 15632 const stateMap = programMap[ program.id ]; 15633 15634 for ( const wireframe in stateMap ) { 15635 15636 deleteVertexArrayObject( stateMap[ wireframe ].object ); 15637 15638 delete stateMap[ wireframe ]; 15639 15640 } 15641 15642 delete programMap[ program.id ]; 15643 15644 } 15645 15646 } 15647 15648 function reset() { 15649 15650 resetDefaultState(); 15651 forceUpdate = true; 15652 15653 if ( currentState === defaultState ) return; 15654 15655 currentState = defaultState; 15656 bindVertexArrayObject( currentState.object ); 15657 15658 } 15659 15660 // for backward-compatibility 15661 15662 function resetDefaultState() { 15663 15664 defaultState.geometry = null; 15665 defaultState.program = null; 15666 defaultState.wireframe = false; 15667 15668 } 15669 15670 return { 15671 15672 setup: setup, 15673 reset: reset, 15674 resetDefaultState: resetDefaultState, 15675 dispose: dispose, 15676 releaseStatesOfGeometry: releaseStatesOfGeometry, 15677 releaseStatesOfProgram: releaseStatesOfProgram, 15678 15679 initAttributes: initAttributes, 15680 enableAttribute: enableAttribute, 15681 disableUnusedAttributes: disableUnusedAttributes 15682 15683 }; 15684 15685} 15686 15687function WebGLBufferRenderer( gl, extensions, info, capabilities ) { 15688 15689 const isWebGL2 = capabilities.isWebGL2; 15690 15691 let mode; 15692 15693 function setMode( value ) { 15694 15695 mode = value; 15696 15697 } 15698 15699 function render( start, count ) { 15700 15701 gl.drawArrays( mode, start, count ); 15702 15703 info.update( count, mode, 1 ); 15704 15705 } 15706 15707 function renderInstances( start, count, primcount ) { 15708 15709 if ( primcount === 0 ) return; 15710 15711 let extension, methodName; 15712 15713 if ( isWebGL2 ) { 15714 15715 extension = gl; 15716 methodName = 'drawArraysInstanced'; 15717 15718 } else { 15719 15720 extension = extensions.get( 'ANGLE_instanced_arrays' ); 15721 methodName = 'drawArraysInstancedANGLE'; 15722 15723 if ( extension === null ) { 15724 15725 console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); 15726 return; 15727 15728 } 15729 15730 } 15731 15732 extension[ methodName ]( mode, start, count, primcount ); 15733 15734 info.update( count, mode, primcount ); 15735 15736 } 15737 15738 function renderMultiDraw( starts, counts, drawCount ) { 15739 15740 if ( drawCount === 0 ) return; 15741 15742 const extension = extensions.get( 'WEBGL_multi_draw' ); 15743 if ( extension === null ) { 15744 15745 for ( let i = 0; i < drawCount; i ++ ) { 15746 15747 this.render( starts[ i ], counts[ i ] ); 15748 15749 } 15750 15751 } else { 15752 15753 extension.multiDrawArraysWEBGL( mode, starts, 0, counts, 0, drawCount ); 15754 15755 let elementCount = 0; 15756 for ( let i = 0; i < drawCount; i ++ ) { 15757 15758 elementCount += counts[ i ]; 15759 15760 } 15761 15762 info.update( elementCount, mode, 1 ); 15763 15764 } 15765 15766 } 15767 15768 // 15769 15770 this.setMode = setMode; 15771 this.render = render; 15772 this.renderInstances = renderInstances; 15773 this.renderMultiDraw = renderMultiDraw; 15774 15775} 15776 15777function WebGLCapabilities( gl, extensions, parameters ) { 15778 15779 let maxAnisotropy; 15780 15781 function getMaxAnisotropy() { 15782 15783 if ( maxAnisotropy !== undefined ) return maxAnisotropy; 15784 15785 if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { 15786 15787 const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); 15788 15789 maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); 15790 15791 } else { 15792 15793 maxAnisotropy = 0; 15794 15795 } 15796 15797 return maxAnisotropy; 15798 15799 } 15800 15801 function getMaxPrecision( precision ) { 15802 15803 if ( precision === 'highp' ) { 15804 15805 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 && 15806 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) { 15807 15808 return 'highp'; 15809 15810 } 15811 15812 precision = 'mediump'; 15813 15814 } 15815 15816 if ( precision === 'mediump' ) { 15817 15818 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 && 15819 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) { 15820 15821 return 'mediump'; 15822 15823 } 15824 15825 } 15826 15827 return 'lowp'; 15828 15829 } 15830 15831 const isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl.constructor.name === 'WebGL2RenderingContext'; 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 drawBuffers = isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ); 15844 15845 const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; 15846 15847 const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); 15848 const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); 15849 const maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE ); 15850 const maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE ); 15851 15852 const maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); 15853 const maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS ); 15854 const maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS ); 15855 const maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS ); 15856 15857 const vertexTextures = maxVertexTextures > 0; 15858 const floatFragmentTextures = isWebGL2 || extensions.has( 'OES_texture_float' ); 15859 const floatVertexTextures = vertexTextures && floatFragmentTextures; 15860 15861 const maxSamples = isWebGL2 ? gl.getParameter( gl.MAX_SAMPLES ) : 0; 15862 15863 return { 15864 15865 isWebGL2: isWebGL2, 15866 15867 drawBuffers: drawBuffers, 15868 15869 getMaxAnisotropy: getMaxAnisotropy, 15870 getMaxPrecision: getMaxPrecision, 15871 15872 precision: precision, 15873 logarithmicDepthBuffer: logarithmicDepthBuffer, 15874 15875 maxTextures: maxTextures, 15876 maxVertexTextures: maxVertexTextures, 15877 maxTextureSize: maxTextureSize, 15878 maxCubemapSize: maxCubemapSize, 15879 15880 maxAttributes: maxAttributes, 15881 maxVertexUniforms: maxVertexUniforms, 15882 maxVaryings: maxVaryings, 15883 maxFragmentUniforms: maxFragmentUniforms, 15884 15885 vertexTextures: vertexTextures, 15886 floatFragmentTextures: floatFragmentTextures, 15887 floatVertexTextures: floatVertexTextures, 15888 15889 maxSamples: maxSamples 15890 15891 }; 15892 15893} 15894 15895function WebGLClipping( properties ) { 15896 15897 const scope = this; 15898 15899 let globalState = null, 15900 numGlobalPlanes = 0, 15901 localClippingEnabled = false, 15902 renderingShadows = false; 15903 15904 const plane = new Plane(), 15905 viewNormalMatrix = new Matrix3(), 15906 15907 uniform = { value: null, needsUpdate: false }; 15908 15909 this.uniform = uniform; 15910 this.numPlanes = 0; 15911 this.numIntersection = 0; 15912 15913 this.init = function ( planes, enableLocalClipping ) { 15914 15915 const enabled = 15916 planes.length !== 0 || 15917 enableLocalClipping || 15918 // enable state of previous frame - the clipping code has to 15919 // run another frame in order to reset the state: 15920 numGlobalPlanes !== 0 || 15921 localClippingEnabled; 15922 15923 localClippingEnabled = enableLocalClipping; 15924 15925 numGlobalPlanes = planes.length; 15926 15927 return enabled; 15928 15929 }; 15930 15931 this.beginShadows = function () { 15932 15933 renderingShadows = true; 15934 projectPlanes( null ); 15935 15936 }; 15937 15938 this.endShadows = function () { 15939 15940 renderingShadows = false; 15941 15942 }; 15943 15944 this.setGlobalState = function ( planes, camera ) { 15945 15946 globalState = projectPlanes( planes, camera, 0 ); 15947 15948 }; 15949 15950 this.setState = function ( material, camera, useCache ) { 15951 15952 const planes = material.clippingPlanes, 15953 clipIntersection = material.clipIntersection, 15954 clipShadows = material.clipShadows; 15955 15956 const materialProperties = properties.get( material ); 15957 15958 if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) { 15959 15960 // there's no local clipping 15961 15962 if ( renderingShadows ) { 15963 15964 // there's no global clipping 15965 15966 projectPlanes( null ); 15967 15968 } else { 15969 15970 resetGlobalState(); 15971 15972 } 15973 15974 } else { 15975 15976 const nGlobal = renderingShadows ? 0 : numGlobalPlanes, 15977 lGlobal = nGlobal * 4; 15978 15979 let dstArray = materialProperties.clippingState || null; 15980 15981 uniform.value = dstArray; // ensure unique state 15982 15983 dstArray = projectPlanes( planes, camera, lGlobal, useCache ); 15984 15985 for ( let i = 0; i !== lGlobal; ++ i ) { 15986 15987 dstArray[ i ] = globalState[ i ]; 15988 15989 } 15990 15991 materialProperties.clippingState = dstArray; 15992 this.numIntersection = clipIntersection ? this.numPlanes : 0; 15993 this.numPlanes += nGlobal; 15994 15995 } 15996 15997 15998 }; 15999 16000 function resetGlobalState() { 16001 16002 if ( uniform.value !== globalState ) { 16003 16004 uniform.value = globalState; 16005 uniform.needsUpdate = numGlobalPlanes > 0; 16006 16007 } 16008 16009 scope.numPlanes = numGlobalPlanes; 16010 scope.numIntersection = 0; 16011 16012 } 16013 16014 function projectPlanes( planes, camera, dstOffset, skipTransform ) { 16015 16016 const nPlanes = planes !== null ? planes.length : 0; 16017 let dstArray = null; 16018 16019 if ( nPlanes !== 0 ) { 16020 16021 dstArray = uniform.value; 16022 16023 if ( skipTransform !== true || dstArray === null ) { 16024 16025 const flatSize = dstOffset + nPlanes * 4, 16026 viewMatrix = camera.matrixWorldInverse; 16027 16028 viewNormalMatrix.getNormalMatrix( viewMatrix ); 16029 16030 if ( dstArray === null || dstArray.length < flatSize ) { 16031 16032 dstArray = new Float32Array( flatSize ); 16033 16034 } 16035 16036 for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) { 16037 16038 plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix ); 16039 16040 plane.normal.toArray( dstArray, i4 ); 16041 dstArray[ i4 + 3 ] = plane.constant; 16042 16043 } 16044 16045 } 16046 16047 uniform.value = dstArray; 16048 uniform.needsUpdate = true; 16049 16050 } 16051 16052 scope.numPlanes = nPlanes; 16053 scope.numIntersection = 0; 16054 16055 return dstArray; 16056 16057 } 16058 16059} 16060 16061function WebGLCubeMaps( renderer ) { 16062 16063 let cubemaps = new WeakMap(); 16064 16065 function mapTextureMapping( texture, mapping ) { 16066 16067 if ( mapping === EquirectangularReflectionMapping ) { 16068 16069 texture.mapping = CubeReflectionMapping; 16070 16071 } else if ( mapping === EquirectangularRefractionMapping ) { 16072 16073 texture.mapping = CubeRefractionMapping; 16074 16075 } 16076 16077 return texture; 16078 16079 } 16080 16081 function get( texture ) { 16082 16083 if ( texture && texture.isTexture ) { 16084 16085 const mapping = texture.mapping; 16086 16087 if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) { 16088 16089 if ( cubemaps.has( texture ) ) { 16090 16091 const cubemap = cubemaps.get( texture ).texture; 16092 return mapTextureMapping( cubemap, texture.mapping ); 16093 16094 } else { 16095 16096 const image = texture.image; 16097 16098 if ( image && image.height > 0 ) { 16099 16100 const renderTarget = new WebGLCubeRenderTarget( image.height
vendor: 20,344 bytes, lines 16100-16931
16100/ 2 ); 16101 renderTarget.fromEquirectangularTexture( renderer, texture ); 16102 cubemaps.set( texture, renderTarget ); 16103 16104 texture.addEventListener( 'dispose', onTextureDispose ); 16105 16106 return mapTextureMapping( renderTarget.texture, texture.mapping ); 16107 16108 } else { 16109 16110 // image not yet ready. try the conversion next frame 16111 16112 return null; 16113 16114 } 16115 16116 } 16117 16118 } 16119 16120 } 16121 16122 return texture; 16123 16124 } 16125 16126 function onTextureDispose( event ) { 16127 16128 const texture = event.target; 16129 16130 texture.removeEventListener( 'dispose', onTextureDispose ); 16131 16132 const cubemap = cubemaps.get( texture ); 16133 16134 if ( cubemap !== undefined ) { 16135 16136 cubemaps.delete( texture ); 16137 cubemap.dispose(); 16138 16139 } 16140 16141 } 16142 16143 function dispose() { 16144 16145 cubemaps = new WeakMap(); 16146 16147 } 16148 16149 return { 16150 get: get, 16151 dispose: dispose 16152 }; 16153 16154} 16155 16156class OrthographicCamera extends Camera { 16157 16158 constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) { 16159 16160 super(); 16161 16162 this.isOrthographicCamera = true; 16163 16164 this.type = 'OrthographicCamera'; 16165 16166 this.zoom = 1; 16167 this.view = null; 16168 16169 this.left = left; 16170 this.right = right; 16171 this.top = top; 16172 this.bottom = bottom; 16173 16174 this.near = near; 16175 this.far = far; 16176 16177 this.updateProjectionMatrix(); 16178 16179 } 16180 16181 copy( source, recursive ) { 16182 16183 super.copy( source, recursive ); 16184 16185 this.left = source.left; 16186 this.right = source.right; 16187 this.top = source.top; 16188 this.bottom = source.bottom; 16189 this.near = source.near; 16190 this.far = source.far; 16191 16192 this.zoom = source.zoom; 16193 this.view = source.view === null ? null : Object.assign( {}, source.view ); 16194 16195 return this; 16196 16197 } 16198 16199 setViewOffset( fullWidth, fullHeight, x, y, width, height ) { 16200 16201 if ( this.view === null ) { 16202 16203 this.view = { 16204 enabled: true, 16205 fullWidth: 1, 16206 fullHeight: 1, 16207 offsetX: 0, 16208 offsetY: 0, 16209 width: 1, 16210 height: 1 16211 }; 16212 16213 } 16214 16215 this.view.enabled = true; 16216 this.view.fullWidth = fullWidth; 16217 this.view.fullHeight = fullHeight; 16218 this.view.offsetX = x; 16219 this.view.offsetY = y; 16220 this.view.width = width; 16221 this.view.height = height; 16222 16223 this.updateProjectionMatrix(); 16224 16225 } 16226 16227 clearViewOffset() { 16228 16229 if ( this.view !== null ) { 16230 16231 this.view.enabled = false; 16232 16233 } 16234 16235 this.updateProjectionMatrix(); 16236 16237 } 16238 16239 updateProjectionMatrix() { 16240 16241 const dx = ( this.right - this.left ) / ( 2 * this.zoom ); 16242 const dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); 16243 const cx = ( this.right + this.left ) / 2; 16244 const cy = ( this.top + this.bottom ) / 2; 16245 16246 let left = cx - dx; 16247 let right = cx + dx; 16248 let top = cy + dy; 16249 let bottom = cy - dy; 16250 16251 if ( this.view !== null && this.view.enabled ) { 16252 16253 const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom; 16254 const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom; 16255 16256 left += scaleW * this.view.offsetX; 16257 right = left + scaleW * this.view.width; 16258 top -= scaleH * this.view.offsetY; 16259 bottom = top - scaleH * this.view.height; 16260 16261 } 16262 16263 this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem ); 16264 16265 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); 16266 16267 } 16268 16269 toJSON( meta ) { 16270 16271 const data = super.toJSON( meta ); 16272 16273 data.object.zoom = this.zoom; 16274 data.object.left = this.left; 16275 data.object.right = this.right; 16276 data.object.top = this.top; 16277 data.object.bottom = this.bottom; 16278 data.object.near = this.near; 16279 data.object.far = this.far; 16280 16281 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); 16282 16283 return data; 16284 16285 } 16286 16287} 16288 16289const LOD_MIN = 4; 16290 16291// The standard deviations (radians) associated with the extra mips. These are 16292// chosen to approximate a Trowbridge-Reitz distribution function times the 16293// geometric shadowing function. These sigma values squared must match the 16294// variance #defines in cube_uv_reflection_fragment.glsl.js. 16295const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ]; 16296 16297// The maximum length of the blur for loop. Smaller sigmas will use fewer 16298// samples and exit early, but not recompile the shader. 16299const MAX_SAMPLES = 20; 16300 16301const _flatCamera = /*@__PURE__*/ new OrthographicCamera(); 16302const _clearColor = /*@__PURE__*/ new Color(); 16303let _oldTarget = null; 16304let _oldActiveCubeFace = 0; 16305let _oldActiveMipmapLevel = 0; 16306 16307// Golden Ratio 16308const PHI = ( 1 + Math.sqrt( 5 ) ) / 2; 16309const INV_PHI = 1 / PHI; 16310 16311// Vertices of a dodecahedron (except the opposites, which represent the 16312// same axis), used as axis directions evenly spread on a sphere. 16313const _axisDirections = [ 16314 /*@__PURE__*/ new Vector3( 1, 1, 1 ), 16315 /*@__PURE__*/ new Vector3( - 1, 1, 1 ), 16316 /*@__PURE__*/ new Vector3( 1, 1, - 1 ), 16317 /*@__PURE__*/ new Vector3( - 1, 1, - 1 ), 16318 /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), 16319 /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), 16320 /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), 16321 /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), 16322 /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), 16323 /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ) ]; 16324 16325/** 16326 * This class generates a Prefiltered, Mipmapped Radiance Environment Map 16327 * (PMREM) from a cubeMap environment texture. This allows different levels of 16328 * blur to be quickly accessed based on material roughness. It is packed into a 16329 * special CubeUV format that allows us to perform custom interpolation so that 16330 * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap 16331 * chain, it only goes down to the LOD_MIN level (above), and then creates extra 16332 * even more filtered 'mips' at the same LOD_MIN resolution, associated with 16333 * higher roughness levels. In this way we maintain resolution to smoothly 16334 * interpolate diffuse lighting while limiting sampling computation. 16335 * 16336 * Paper: Fast, Accurate Image-Based Lighting 16337 * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view 16338*/ 16339 16340class PMREMGenerator { 16341 16342 constructor( renderer ) { 16343 16344 this._renderer = renderer; 16345 this._pingPongRenderTarget = null; 16346 16347 this._lodMax = 0; 16348 this._cubeSize = 0; 16349 this._lodPlanes = []; 16350 this._sizeLods = []; 16351 this._sigmas = []; 16352 16353 this._blurMaterial = null; 16354 this._cubemapMaterial = null; 16355 this._equirectMaterial = null; 16356 16357 this._compileMaterial( this._blurMaterial ); 16358 16359 } 16360 16361 /** 16362 * Generates a PMREM from a supplied Scene, which can be faster than using an 16363 * image if networking bandwidth is low. Optional sigma specifies a blur radius 16364 * in radians to be applied to the scene before PMREM generation. Optional near 16365 * and far planes ensure the scene is rendered in its entirety (the cubeCamera 16366 * is placed at the origin). 16367 */ 16368 fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { 16369 16370 _oldTarget = this._renderer.getRenderTarget(); 16371 _oldActiveCubeFace = this._renderer.getActiveCubeFace(); 16372 _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); 16373 16374 this._setSize( 256 ); 16375 16376 const cubeUVRenderTarget = this._allocateTargets(); 16377 cubeUVRenderTarget.depthBuffer = true; 16378 16379 this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); 16380 16381 if ( sigma > 0 ) { 16382 16383 this._blur( cubeUVRenderTarget, 0, 0, sigma ); 16384 16385 } 16386 16387 this._applyPMREM( cubeUVRenderTarget ); 16388 this._cleanup( cubeUVRenderTarget ); 16389 16390 return cubeUVRenderTarget; 16391 16392 } 16393 16394 /** 16395 * Generates a PMREM from an equirectangular texture, which can be either LDR 16396 * or HDR. The ideal input image size is 1k (1024 x 512), 16397 * as this matches best with the 256 x 256 cubemap output. 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 */ 16410 fromCubemap( cubemap, renderTarget = null ) { 16411 16412 return this._fromTexture( cubemap, renderTarget ); 16413 16414 } 16415 16416 /** 16417 * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during 16418 * your texture's network fetch for increased concurrency. 16419 */ 16420 compileCubemapShader() { 16421 16422 if ( this._cubemapMaterial === null ) { 16423 16424 this._cubemapMaterial = _getCubemapMaterial(); 16425 this._compileMaterial( this._cubemapMaterial ); 16426 16427 } 16428 16429 } 16430 16431 /** 16432 * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during 16433 * your texture's network fetch for increased concurrency. 16434 */ 16435 compileEquirectangularShader() { 16436 16437 if ( this._equirectMaterial === null ) { 16438 16439 this._equirectMaterial = _getEquirectMaterial(); 16440 this._compileMaterial( this._equirectMaterial ); 16441 16442 } 16443 16444 } 16445 16446 /** 16447 * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class, 16448 * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on 16449 * one of them will cause any others to also become unusable. 16450 */ 16451 dispose() { 16452 16453 this._dispose(); 16454 16455 if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose(); 16456 if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose(); 16457 16458 } 16459 16460 // private interface 16461 16462 _setSize( cubeSize ) { 16463 16464 this._lodMax = Math.floor( Math.log2( cubeSize ) ); 16465 this._cubeSize = Math.pow( 2, this._lodMax ); 16466 16467 } 16468 16469 _dispose() { 16470 16471 if ( this._blurMaterial !== null ) this._blurMaterial.dispose(); 16472 16473 if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose(); 16474 16475 for ( let i = 0; i < this._lodPlanes.length; i ++ ) { 16476 16477 this._lodPlanes[ i ].dispose(); 16478 16479 } 16480 16481 } 16482 16483 _cleanup( outputTarget ) { 16484 16485 this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel ); 16486 outputTarget.scissorTest = false; 16487 _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height ); 16488 16489 } 16490 16491 _fromTexture( texture, renderTarget ) { 16492 16493 if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) { 16494 16495 this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) ); 16496 16497 } else { // Equirectangular 16498 16499 this._setSize( texture.image.width / 4 ); 16500 16501 } 16502 16503 _oldTarget = this._renderer.getRenderTarget(); 16504 _oldActiveCubeFace = this._renderer.getActiveCubeFace(); 16505 _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); 16506 16507 const cubeUVRenderTarget = renderTarget || this._allocateTargets(); 16508 this._textureToCubeUV( texture, cubeUVRenderTarget ); 16509 this._applyPMREM( cubeUVRenderTarget ); 16510 this._cleanup( cubeUVRenderTarget ); 16511 16512 return cubeUVRenderTarget; 16513 16514 } 16515 16516 _allocateTargets() { 16517 16518 const width = 3 * Math.max( this._cubeSize, 16 * 7 ); 16519 const height = 4 * this._cubeSize; 16520 16521 const params = { 16522 magFilter: LinearFilter, 16523 minFilter: LinearFilter, 16524 generateMipmaps: false, 16525 type: HalfFloatType, 16526 format: RGBAFormat, 16527 colorSpace: LinearSRGBColorSpace, 16528 depthBuffer: false 16529 }; 16530 16531 const cubeUVRenderTarget = _createRenderTarget( width, height, params ); 16532 16533 if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) { 16534 16535 if ( this._pingPongRenderTarget !== null ) { 16536 16537 this._dispose(); 16538 16539 } 16540 16541 this._pingPongRenderTarget = _createRenderTarget( width, height, params ); 16542 16543 const { _lodMax } = this; 16544 ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) ); 16545 16546 this._blurMaterial = _getBlurShader( _lodMax, width, height ); 16547 16548 } 16549 16550 return cubeUVRenderTarget; 16551 16552 } 16553 16554 _compileMaterial( material ) { 16555 16556 const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material ); 16557 this._renderer.compile( tmpMesh, _flatCamera ); 16558 16559 } 16560 16561 _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) { 16562 16563 const fov = 90; 16564 const aspect = 1; 16565 const cubeCamera = new PerspectiveCamera( fov, aspect, near, far ); 16566 const upSign = [ 1, - 1, 1, 1, 1, 1 ]; 16567 const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ]; 16568 const renderer = this._renderer; 16569 16570 const originalAutoClear = renderer.autoClear; 16571 const toneMapping = renderer.toneMapping; 16572 renderer.getClearColor( _clearColor ); 16573 16574 renderer.toneMapping = NoToneMapping; 16575 renderer.autoClear = false; 16576 16577 const backgroundMaterial = new MeshBasicMaterial( { 16578 name: 'PMREM.Background', 16579 side: BackSide, 16580 depthWrite: false, 16581 depthTest: false, 16582 } ); 16583 16584 const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial ); 16585 16586 let useSolidColor = false; 16587 const background = scene.background; 16588 16589 if ( background ) { 16590 16591 if ( background.isColor ) { 16592 16593 backgroundMaterial.color.copy( background ); 16594 scene.background = null; 16595 useSolidColor = true; 16596 16597 } 16598 16599 } else { 16600 16601 backgroundMaterial.color.copy( _clearColor ); 16602 useSolidColor = true; 16603 16604 } 16605 16606 for ( let i = 0; i < 6; i ++ ) { 16607 16608 const col = i % 3; 16609 16610 if ( col === 0 ) { 16611 16612 cubeCamera.up.set( 0, upSign[ i ], 0 ); 16613 cubeCamera.lookAt( forwardSign[ i ], 0, 0 ); 16614 16615 } else if ( col === 1 ) { 16616 16617 cubeCamera.up.set( 0, 0, upSign[ i ] ); 16618 cubeCamera.lookAt( 0, forwardSign[ i ], 0 ); 16619 16620 } else { 16621 16622 cubeCamera.up.set( 0, upSign[ i ], 0 ); 16623 cubeCamera.lookAt( 0, 0, forwardSign[ i ] ); 16624 16625 } 16626 16627 const size = this._cubeSize; 16628 16629 _setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size ); 16630 16631 renderer.setRenderTarget( cubeUVRenderTarget ); 16632 16633 if ( useSolidColor ) { 16634 16635 renderer.render( backgroundBox, cubeCamera ); 16636 16637 } 16638 16639 renderer.render( scene, cubeCamera ); 16640 16641 } 16642 16643 backgroundBox.geometry.dispose(); 16644 backgroundBox.material.dispose(); 16645 16646 renderer.toneMapping = toneMapping; 16647 renderer.autoClear = originalAutoClear; 16648 scene.background = background; 16649 16650 } 16651 16652 _textureToCubeUV( texture, cubeUVRenderTarget ) { 16653 16654 const renderer = this._renderer; 16655 16656 const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ); 16657 16658 if ( isCubeTexture ) { 16659 16660 if ( this._cubemapMaterial === null ) { 16661 16662 this._cubemapMaterial = _getCubemapMaterial(); 16663 16664 } 16665 16666 this._cubemapMaterial.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? - 1 : 1; 16667 16668 } else { 16669 16670 if ( this._equirectMaterial === null ) { 16671 16672 this._equirectMaterial = _getEquirectMaterial(); 16673 16674 } 16675 16676 } 16677 16678 const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; 16679 const mesh = new Mesh( this._lodPlanes[ 0 ], material ); 16680 16681 const uniforms = material.uniforms; 16682 16683 uniforms[ 'envMap' ].value = texture; 16684 16685 const size = this._cubeSize; 16686 16687 _setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size ); 16688 16689 renderer.setRenderTarget( cubeUVRenderTarget ); 16690 renderer.render( mesh, _flatCamera ); 16691 16692 } 16693 16694 _applyPMREM( cubeUVRenderTarget ) { 16695 16696 const renderer = this._renderer; 16697 const autoClear = renderer.autoClear; 16698 renderer.autoClear = false; 16699 16700 for ( let i = 1; i < this._lodPlanes.length; i ++ ) { 16701 16702 const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); 16703 16704 const poleAxis = _axisDirections[ ( i - 1 ) % _axisDirections.length ]; 16705 16706 this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); 16707 16708 } 16709 16710 renderer.autoClear = autoClear; 16711 16712 } 16713 16714 /** 16715 * This is a two-pass Gaussian blur for a cubemap. Normally this is done 16716 * vertically and horizontally, but this breaks down on a cube. Here we apply 16717 * the blur latitudinally (around the poles), and then longitudinally (towards 16718 * the poles) to approximate the orthogonally-separable blur. It is least 16719 * accurate at the poles, but still does a decent job. 16720 */ 16721 _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) { 16722 16723 const pingPongRenderTarget = this._pingPongRenderTarget; 16724 16725 this._halfBlur( 16726 cubeUVRenderTarget, 16727 pingPongRenderTarget, 16728 lodIn, 16729 lodOut, 16730 sigma, 16731 'latitudinal', 16732 poleAxis ); 16733 16734 this._halfBlur( 16735 pingPongRenderTarget, 16736 cubeUVRenderTarget, 16737 lodOut, 16738 lodOut, 16739 sigma, 16740 'longitudinal', 16741 poleAxis ); 16742 16743 } 16744 16745 _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) { 16746 16747 const renderer = this._renderer; 16748 const blurMaterial = this._blurMaterial; 16749 16750 if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { 16751 16752 console.error( 16753 'blur direction must be either latitudinal or longitudinal!' ); 16754 16755 } 16756 16757 // Number of standard deviations at which to cut off the discrete approximation. 16758 const STANDARD_DEVIATIONS = 3; 16759 16760 const blurMesh = new Mesh( this._lodPlanes[ lodOut ], blurMaterial ); 16761 const blurUniforms = blurMaterial.uniforms; 16762 16763 const pixels = this._sizeLods[ lodIn ] - 1; 16764 const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 ); 16765 const sigmaPixels = sigmaRadians / radiansPerPixel; 16766 const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES; 16767 16768 if ( samples > MAX_SAMPLES ) { 16769 16770 console.warn( `sigmaRadians, ${ 16771 sigmaRadians}, is too large and will clip, as it requested ${ 16772 samples} samples when the maximum is set to ${MAX_SAMPLES}` ); 16773 16774 } 16775 16776 const weights = []; 16777 let sum = 0; 16778 16779 for ( let i = 0; i < MAX_SAMPLES; ++ i ) { 16780 16781 const x = i / sigmaPixels; 16782 const weight = Math.exp( - x * x / 2 ); 16783 weights.push( weight ); 16784 16785 if ( i === 0 ) { 16786 16787 sum += weight; 16788 16789 } else if ( i < samples ) { 16790 16791 sum += 2 * weight; 16792 16793 } 16794 16795 } 16796 16797 for ( let i = 0; i < weights.length; i ++ ) { 16798 16799 weights[ i ] = weights[ i ] / sum; 16800 16801 } 16802 16803 blurUniforms[ 'envMap' ].value = targetIn.texture; 16804 blurUniforms[ 'samples' ].value = samples; 16805 blurUniforms[ 'weights' ].value = weights; 16806 blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal'; 16807 16808 if ( poleAxis ) { 16809 16810 blurUniforms[ 'poleAxis' ].value = poleAxis; 16811 16812 } 16813 16814 const { _lodMax } = this; 16815 blurUniforms[ 'dTheta' ].value = radiansPerPixel; 16816 blurUniforms[ 'mipInt' ].value = _lodMax - lodIn; 16817 16818 const outputSize = this._sizeLods[ lodOut ]; 16819 const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); 16820 const y = 4 * ( this._cubeSize - outputSize ); 16821 16822 _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize ); 16823 renderer.setRenderTarget( targetOut ); 16824 renderer.render( blurMesh, _flatCamera ); 16825 16826 } 16827 16828} 16829 16830 16831 16832function _createPlanes( lodMax ) { 16833 16834 const lodPlanes = []; 16835 const sizeLods = []; 16836 const sigmas = []; 16837 16838 let lod = lodMax; 16839 16840 const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length; 16841 16842 for ( let i = 0; i < totalLods; i ++ ) { 16843 16844 const sizeLod = Math.pow( 2, lod ); 16845 sizeLods.push( sizeLod ); 16846 let sigma = 1.0 / sizeLod; 16847 16848 if ( i > lodMax - LOD_MIN ) { 16849 16850 sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ]; 16851 16852 } else if ( i === 0 ) { 16853 16854 sigma = 0; 16855 16856 } 16857 16858 sigmas.push( sigma ); 16859 16860 const texelSize = 1.0 / ( sizeLod - 2 ); 16861 const min = - texelSize; 16862 const max = 1 + texelSize; 16863 const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ]; 16864 16865 const cubeFaces = 6; 16866 const vertices = 6; 16867 const positionSize = 3; 16868 const uvSize = 2; 16869 const faceIndexSize = 1; 16870 16871 const position = new Float32Array( positionSize * vertices * cubeFaces ); 16872 const uv = new Float32Array( uvSize * vertices * cubeFaces ); 16873 const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces ); 16874 16875 for ( let face = 0; face < cubeFaces; face ++ ) { 16876 16877 const x = ( face % 3 ) * 2 / 3 - 1; 16878 const y = face > 2 ? 0 : - 1; 16879 const coordinates = [ 16880 x, y, 0, 16881 x + 2 / 3, y, 0, 16882 x + 2 / 3, y + 1, 0, 16883 x, y, 0, 16884 x + 2 / 3, y + 1, 0, 16885 x, y + 1, 0 16886 ]; 16887 position.set( coordinates, positionSize * vertices * face ); 16888 uv.set( uv1, uvSize * vertices * face ); 16889 const fill = [ face, face, face, face, face, face ]; 16890 faceIndex.set( fill, faceIndexSize * vertices * face ); 16891 16892 } 16893 16894 const planes = new BufferGeometry(); 16895 planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) ); 16896 planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) ); 16897 planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) ); 16898 lodPlanes.push( planes ); 16899 16900 if ( lod > LOD_MIN ) { 16901 16902 lod --; 16903 16904 } 16905 16906 } 16907 16908 return { lodPlanes, sizeLods, sigmas }; 16909 16910} 16911 16912function _createRenderTarget( width, height, params ) { 16913 16914 const cubeUVRenderTarget = new WebGLRenderTarget( width, height, params ); 16915 cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping; 16916 cubeUVRenderTarget.texture.name = 'PMREM.cubeUv'; 16917 cubeUVRenderTarget.scissorTest = true; 16918 return cubeUVRenderTarget; 16919 16920} 16921 16922function _setViewport( target, x, y, width, height ) { 16923 16924 target.viewport.set( x, y, width, height ); 16925 target.scissor.set( x, y, width, height ); 16926 16927} 16928 16929function _getBlurShader( lodMax, width, height ) { 16930 16931 const weights = new Float32Array( MAX_SAMPLES );
vendor: 2,857 bytes, lines 16932-17077
16932 const poleAxis = new Vector3( 0, 1, 0 ); 16933 const shaderMaterial = new ShaderMaterial( { 16934 16935 name: 'SphericalGaussianBlur', 16936 16937 defines: { 16938 'n': MAX_SAMPLES, 16939 'CUBEUV_TEXEL_WIDTH': 1.0 / width, 16940 'CUBEUV_TEXEL_HEIGHT': 1.0 / height, 16941 'CUBEUV_MAX_MIP': `${lodMax}.0`, 16942 }, 16943 16944 uniforms: { 16945 'envMap': { value: null }, 16946 'samples': { value: 1 }, 16947 'weights': { value: weights }, 16948 'latitudinal': { value: false }, 16949 'dTheta': { value: 0 }, 16950 'mipInt': { value: 0 }, 16951 'poleAxis': { value: poleAxis } 16952 }, 16953 16954 vertexShader: _getCommonVertexShader(), 16955 16956 fragmentShader: /* glsl */` 16957 16958 precision mediump float; 16959 precision mediump int; 16960 16961 varying vec3 vOutputDirection; 16962 16963 uniform sampler2D envMap; 16964 uniform int samples; 16965 uniform float weights[ n ]; 16966 uniform bool latitudinal; 16967 uniform float dTheta; 16968 uniform float mipInt; 16969 uniform vec3 poleAxis; 16970 16971 #define ENVMAP_TYPE_CUBE_UV 16972 #include <cube_uv_reflection_fragment> 16973 16974 vec3 getSample( float theta, vec3 axis ) { 16975 16976 float cosTheta = cos( theta ); 16977 // Rodrigues' axis-angle rotation 16978 vec3 sampleDirection = vOutputDirection * cosTheta 16979 + cross( axis, vOutputDirection ) * sin( theta ) 16980 + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta ); 16981 16982 return bilinearCubeUV( envMap, sampleDirection, mipInt ); 16983 16984 } 16985 16986 void main() { 16987 16988 vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection ); 16989 16990 if ( all( equal( axis, vec3( 0.0 ) ) ) ) { 16991 16992 axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x ); 16993 16994 } 16995 16996 axis = normalize( axis ); 16997 16998 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 ); 16999 gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis ); 17000 17001 for ( int i = 1; i < n; i++ ) { 17002 17003 if ( i >= samples ) { 17004 17005 break; 17006 17007 } 17008 17009 float theta = dTheta * float( i ); 17010 gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis ); 17011 gl_FragColor.rgb += weights[ i ] * getSample( theta, axis ); 17012 17013 } 17014 17015 } 17016 `, 17017 17018 blending: NoBlending, 17019 depthTest: false, 17020 depthWrite: false 17021 17022 } ); 17023 17024 return shaderMaterial; 17025 17026} 17027 17028function _getEquirectMaterial() { 17029 17030 return new ShaderMaterial( { 17031 17032 name: 'EquirectangularToCubeUV', 17033 17034 uniforms: { 17035 'envMap': { value: null } 17036 }, 17037 17038 vertexShader: _getCommonVertexShader(), 17039 17040 fragmentShader: /* glsl */` 17041 17042 precision mediump float; 17043 precision mediump int; 17044 17045 varying vec3 vOutputDirection; 17046 17047 uniform sampler2D envMap; 17048 17049 #include <common> 17050 17051 void main() { 17052 17053 vec3 outputDirection = normalize( vOutputDirection ); 17054 vec2 uv = equirectUv( outputDirection ); 17055 17056 gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 ); 17057 17058 } 17059 `, 17060 17061 blending: NoBlending, 17062 depthTest: false, 17063 depthWrite: false 17064 17065 } ); 17066 17067} 17068 17069function _getCubemapMaterial() { 17070 17071 return new ShaderMaterial( { 17072 17073 name: 'CubemapToCubeUV', 17074 17075 uniforms: { 17076 'envMap': { value: null }, 17077 'flipEnvMap': { value: -
vendor: 16,828 bytes, lines 17077-17915
170771 } 17078 }, 17079 17080 vertexShader: _getCommonVertexShader(), 17081 17082 fragmentShader: /* glsl */` 17083 17084 precision mediump float; 17085 precision mediump int; 17086 17087 uniform float flipEnvMap; 17088 17089 varying vec3 vOutputDirection; 17090 17091 uniform samplerCube envMap; 17092 17093 void main() { 17094 17095 gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ); 17096 17097 } 17098 `, 17099 17100 blending: NoBlending, 17101 depthTest: false, 17102 depthWrite: false 17103 17104 } ); 17105 17106} 17107 17108function _getCommonVertexShader() { 17109 17110 return /* glsl */` 17111 17112 precision mediump float; 17113 precision mediump int; 17114 17115 attribute float faceIndex; 17116 17117 varying vec3 vOutputDirection; 17118 17119 // RH coordinate system; PMREM face-indexing convention 17120 vec3 getDirection( vec2 uv, float face ) { 17121 17122 uv = 2.0 * uv - 1.0; 17123 17124 vec3 direction = vec3( uv, 1.0 ); 17125 17126 if ( face == 0.0 ) { 17127 17128 direction = direction.zyx; // ( 1, v, u ) pos x 17129 17130 } else if ( face == 1.0 ) { 17131 17132 direction = direction.xzy; 17133 direction.xz *= -1.0; // ( -u, 1, -v ) pos y 17134 17135 } else if ( face == 2.0 ) { 17136 17137 direction.x *= -1.0; // ( -u, v, 1 ) pos z 17138 17139 } else if ( face == 3.0 ) { 17140 17141 direction = direction.zyx; 17142 direction.xz *= -1.0; // ( -1, v, -u ) neg x 17143 17144 } else if ( face == 4.0 ) { 17145 17146 direction = direction.xzy; 17147 direction.xy *= -1.0; // ( -u, -1, v ) neg y 17148 17149 } else if ( face == 5.0 ) { 17150 17151 direction.z *= -1.0; // ( u, v, -1 ) neg z 17152 17153 } 17154 17155 return direction; 17156 17157 } 17158 17159 void main() { 17160 17161 vOutputDirection = getDirection( uv, faceIndex ); 17162 gl_Position = vec4( position, 1.0 ); 17163 17164 } 17165 `; 17166 17167} 17168 17169function WebGLCubeUVMaps( renderer ) { 17170 17171 let cubeUVmaps = new WeakMap(); 17172 17173 let pmremGenerator = null; 17174 17175 function get( texture ) { 17176 17177 if ( texture && texture.isTexture ) { 17178 17179 const mapping = texture.mapping; 17180 17181 const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ); 17182 const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); 17183 17184 // equirect/cube map to cubeUV conversion 17185 17186 if ( isEquirectMap || isCubeMap ) { 17187 17188 if ( texture.isRenderTargetTexture && texture.needsPMREMUpdate === true ) { 17189 17190 texture.needsPMREMUpdate = false; 17191 17192 let renderTarget = cubeUVmaps.get( texture ); 17193 17194 if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); 17195 17196 renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget ); 17197 cubeUVmaps.set( texture, renderTarget ); 17198 17199 return renderTarget.texture; 17200 17201 } else { 17202 17203 if ( cubeUVmaps.has( texture ) ) { 17204 17205 return cubeUVmaps.get( texture ).texture; 17206 17207 } else { 17208 17209 const image = texture.image; 17210 17211 if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) { 17212 17213 if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer ); 17214 17215 const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture ); 17216 cubeUVmaps.set( texture, renderTarget ); 17217 17218 texture.addEventListener( 'dispose', onTextureDispose ); 17219 17220 return renderTarget.texture; 17221 17222 } else { 17223 17224 // image not yet ready. try the conversion next frame 17225 17226 return null; 17227 17228 } 17229 17230 } 17231 17232 } 17233 17234 } 17235 17236 } 17237 17238 return texture; 17239 17240 } 17241 17242 function isCubeTextureComplete( image ) { 17243 17244 let count = 0; 17245 const length = 6; 17246 17247 for ( let i = 0; i < length; i ++ ) { 17248 17249 if ( image[ i ] !== undefined ) count ++; 17250 17251 } 17252 17253 return count === length; 17254 17255 17256 } 17257 17258 function onTextureDispose( event ) { 17259 17260 const texture = event.target; 17261 17262 texture.removeEventListener( 'dispose', onTextureDispose ); 17263 17264 const cubemapUV = cubeUVmaps.get( texture ); 17265 17266 if ( cubemapUV !== undefined ) { 17267 17268 cubeUVmaps.delete( texture ); 17269 cubemapUV.dispose(); 17270 17271 } 17272 17273 } 17274 17275 function dispose() { 17276 17277 cubeUVmaps = new WeakMap(); 17278 17279 if ( pmremGenerator !== null ) { 17280 17281 pmremGenerator.dispose(); 17282 pmremGenerator = null; 17283 17284 } 17285 17286 } 17287 17288 return { 17289 get: get, 17290 dispose: dispose 17291 }; 17292 17293} 17294 17295function WebGLExtensions( gl ) { 17296 17297 const extensions = {}; 17298 17299 function getExtension( name ) { 17300 17301 if ( extensions[ name ] !== undefined ) { 17302 17303 return extensions[ name ]; 17304 17305 } 17306 17307 let extension; 17308 17309 switch ( name ) { 17310 17311 case 'WEBGL_depth_texture': 17312 extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' ); 17313 break; 17314 17315 case 'EXT_texture_filter_anisotropic': 17316 extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' ); 17317 break; 17318 17319 case 'WEBGL_compressed_texture_s3tc': 17320 extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' ); 17321 break; 17322 17323 case 'WEBGL_compressed_texture_pvrtc': 17324 extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' ); 17325 break; 17326 17327 default: 17328 extension = gl.getExtension( name ); 17329 17330 } 17331 17332 extensions[ name ] = extension; 17333 17334 return extension; 17335 17336 } 17337 17338 return { 17339 17340 has: function ( name ) { 17341 17342 return getExtension( name ) !== null; 17343 17344 }, 17345 17346 init: function ( capabilities ) { 17347 17348 if ( capabilities.isWebGL2 ) { 17349 17350 getExtension( 'EXT_color_buffer_float' ); 17351 getExtension( 'WEBGL_clip_cull_distance' ); 17352 17353 } else { 17354 17355 getExtension( 'WEBGL_depth_texture' ); 17356 getExtension( 'OES_texture_float' ); 17357 getExtension( 'OES_texture_half_float' ); 17358 getExtension( 'OES_texture_half_float_linear' ); 17359 getExtension( 'OES_standard_derivatives' ); 17360 getExtension( 'OES_element_index_uint' ); 17361 getExtension( 'OES_vertex_array_object' ); 17362 getExtension( 'ANGLE_instanced_arrays' ); 17363 17364 } 17365 17366 getExtension( 'OES_texture_float_linear' ); 17367 getExtension( 'EXT_color_buffer_half_float' ); 17368 getExtension( 'WEBGL_multisampled_render_to_texture' ); 17369 17370 }, 17371 17372 get: function ( name ) { 17373 17374 const extension = getExtension( name ); 17375 17376 if ( extension === null ) { 17377 17378 console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); 17379 17380 } 17381 17382 return extension; 17383 17384 } 17385 17386 }; 17387 17388} 17389 17390function WebGLGeometries( gl, attributes, info, bindingStates ) { 17391 17392 const geometries = {}; 17393 const wireframeAttributes = new WeakMap(); 17394 17395 function onGeometryDispose( event ) { 17396 17397 const geometry = event.target; 17398 17399 if ( geometry.index !== null ) { 17400 17401 attributes.remove( geometry.index ); 17402 17403 } 17404 17405 for ( const name in geometry.attributes ) { 17406 17407 attributes.remove( geometry.attributes[ name ] ); 17408 17409 } 17410 17411 for ( const name in geometry.morphAttributes ) { 17412 17413 const array = geometry.morphAttributes[ name ]; 17414 17415 for ( let i = 0, l = array.length; i < l; i ++ ) { 17416 17417 attributes.remove( array[ i ] ); 17418 17419 } 17420 17421 } 17422 17423 geometry.removeEventListener( 'dispose', onGeometryDispose ); 17424 17425 delete geometries[ geometry.id ]; 17426 17427 const attribute = wireframeAttributes.get( geometry ); 17428 17429 if ( attribute ) { 17430 17431 attributes.remove( attribute ); 17432 wireframeAttributes.delete( geometry ); 17433 17434 } 17435 17436 bindingStates.releaseStatesOfGeometry( geometry ); 17437 17438 if ( geometry.isInstancedBufferGeometry === true ) { 17439 17440 delete geometry._maxInstanceCount; 17441 17442 } 17443 17444 // 17445 17446 info.memory.geometries --; 17447 17448 } 17449 17450 function get( object, geometry ) { 17451 17452 if ( geometries[ geometry.id ] === true ) return geometry; 17453 17454 geometry.addEventListener( 'dispose', onGeometryDispose ); 17455 17456 geometries[ geometry.id ] = true; 17457 17458 info.memory.geometries ++; 17459 17460 return geometry; 17461 17462 } 17463 17464 function update( geometry ) { 17465 17466 const geometryAttributes = geometry.attributes; 17467 17468 // Updating index buffer in VAO now. See WebGLBindingStates. 17469 17470 for ( const name in geometryAttributes ) { 17471 17472 attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER ); 17473 17474 } 17475 17476 // morph targets 17477 17478 const morphAttributes = geometry.morphAttributes; 17479 17480 for ( const name in morphAttributes ) { 17481 17482 const array = morphAttributes[ name ]; 17483 17484 for ( let i = 0, l = array.length; i < l; i ++ ) { 17485 17486 attributes.update( array[ i ], gl.ARRAY_BUFFER ); 17487 17488 } 17489 17490 } 17491 17492 } 17493 17494 function updateWireframeAttribute( geometry ) { 17495 17496 const indices = []; 17497 17498 const geometryIndex = geometry.index; 17499 const geometryPosition = geometry.attributes.position; 17500 let version = 0; 17501 17502 if ( geometryIndex !== null ) { 17503 17504 const array = geometryIndex.array; 17505 version = geometryIndex.version; 17506 17507 for ( let i = 0, l = array.length; i < l; i += 3 ) { 17508 17509 const a = array[ i + 0 ]; 17510 const b = array[ i + 1 ]; 17511 const c = array[ i + 2 ]; 17512 17513 indices.push( a, b, b, c, c, a ); 17514 17515 } 17516 17517 } else if ( geometryPosition !== undefined ) { 17518 17519 const array = geometryPosition.array; 17520 version = geometryPosition.version; 17521 17522 for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { 17523 17524 const a = i + 0; 17525 const b = i + 1; 17526 const c = i + 2; 17527 17528 indices.push( a, b, b, c, c, a ); 17529 17530 } 17531 17532 } else { 17533 17534 return; 17535 17536 } 17537 17538 const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); 17539 attribute.version = version; 17540 17541 // Updating index buffer in VAO now. See WebGLBindingStates 17542 17543 // 17544 17545 const previousAttribute = wireframeAttributes.get( geometry ); 17546 17547 if ( previousAttribute ) attributes.remove( previousAttribute ); 17548 17549 // 17550 17551 wireframeAttributes.set( geometry, attribute ); 17552 17553 } 17554 17555 function getWireframeAttribute( geometry ) { 17556 17557 const currentAttribute = wireframeAttributes.get( geometry ); 17558 17559 if ( currentAttribute ) { 17560 17561 const geometryIndex = geometry.index; 17562 17563 if ( geometryIndex !== null ) { 17564 17565 // if the attribute is obsolete, create a new one 17566 17567 if ( currentAttribute.version < geometryIndex.version ) { 17568 17569 updateWireframeAttribute( geometry ); 17570 17571 } 17572 17573 } 17574 17575 } else { 17576 17577 updateWireframeAttribute( geometry ); 17578 17579 } 17580 17581 return wireframeAttributes.get( geometry ); 17582 17583 } 17584 17585 return { 17586 17587 get: get, 17588 update: update, 17589 17590 getWireframeAttribute: getWireframeAttribute 17591 17592 }; 17593 17594} 17595 17596function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) { 17597 17598 const isWebGL2 = capabilities.isWebGL2; 17599 17600 let mode; 17601 17602 function setMode( value ) { 17603 17604 mode = value; 17605 17606 } 17607 17608 let type, bytesPerElement; 17609 17610 function setIndex( value ) { 17611 17612 type = value.type; 17613 bytesPerElement = value.bytesPerElement; 17614 17615 } 17616 17617 function render( start, count ) { 17618 17619 gl.drawElements( mode, count, type, start * bytesPerElement ); 17620 17621 info.update( count, mode, 1 ); 17622 17623 } 17624 17625 function renderInstances( start, count, primcount ) { 17626 17627 if ( primcount === 0 ) return; 17628 17629 let extension, methodName; 17630 17631 if ( isWebGL2 ) { 17632 17633 extension = gl; 17634 methodName = 'drawElementsInstanced'; 17635 17636 } else { 17637 17638 extension = extensions.get( 'ANGLE_instanced_arrays' ); 17639 methodName = 'drawElementsInstancedANGLE'; 17640 17641 if ( extension === null ) { 17642 17643 console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); 17644 return; 17645 17646 } 17647 17648 } 17649 17650 extension[ methodName ]( mode, count, type, start * bytesPerElement, primcount ); 17651 17652 info.update( count, mode, primcount ); 17653 17654 } 17655 17656 function renderMultiDraw( starts, counts, drawCount ) { 17657 17658 if ( drawCount === 0 ) return; 17659 17660 const extension = extensions.get( 'WEBGL_multi_draw' ); 17661 if ( extension === null ) { 17662 17663 for ( let i = 0; i < drawCount; i ++ ) { 17664 17665 this.render( starts[ i ] / bytesPerElement, counts[ i ] ); 17666 17667 } 17668 17669 } else { 17670 17671 extension.multiDrawElementsWEBGL( mode, counts, 0, type, starts, 0, drawCount ); 17672 17673 let elementCount = 0; 17674 for ( let i = 0; i < drawCount; i ++ ) { 17675 17676 elementCount += counts[ i ]; 17677 17678 } 17679 17680 info.update( elementCount, mode, 1 ); 17681 17682 } 17683 17684 } 17685 17686 // 17687 17688 this.setMode = setMode; 17689 this.setIndex = setIndex; 17690 this.render = render; 17691 this.renderInstances = renderInstances; 17692 this.renderMultiDraw = renderMultiDraw; 17693 17694} 17695 17696function WebGLInfo( gl ) { 17697 17698 const memory = { 17699 geometries: 0, 17700 textures: 0 17701 }; 17702 17703 const render = { 17704 frame: 0, 17705 calls: 0, 17706 triangles: 0, 17707 points: 0, 17708 lines: 0 17709 }; 17710 17711 function update( count, mode, instanceCount ) { 17712 17713 render.calls ++; 17714 17715 switch ( mode ) { 17716 17717 case gl.TRIANGLES: 17718 render.triangles += instanceCount * ( count / 3 ); 17719 break; 17720 17721 case gl.LINES: 17722 render.lines += instanceCount * ( count / 2 ); 17723 break; 17724 17725 case gl.LINE_STRIP: 17726 render.lines += instanceCount * ( count - 1 ); 17727 break; 17728 17729 case gl.LINE_LOOP: 17730 render.lines += instanceCount * count; 17731 break; 17732 17733 case gl.POINTS: 17734 render.points += instanceCount * count; 17735 break; 17736 17737 default: 17738 console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode ); 17739 break; 17740 17741 } 17742 17743 } 17744 17745 function reset() { 17746 17747 render.calls = 0; 17748 render.triangles = 0; 17749 render.points = 0; 17750 render.lines = 0; 17751 17752 } 17753 17754 return { 17755 memory: memory, 17756 render: render, 17757 programs: null, 17758 autoReset: true, 17759 reset: reset, 17760 update: update 17761 }; 17762 17763} 17764 17765function numericalSort( a, b ) { 17766 17767 return a[ 0 ] - b[ 0 ]; 17768 17769} 17770 17771function absNumericalSort( a, b ) { 17772 17773 return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] ); 17774 17775} 17776 17777function WebGLMorphtargets( gl, capabilities, textures ) { 17778 17779 const influencesList = {}; 17780 const morphInfluences = new Float32Array( 8 ); 17781 const morphTextures = new WeakMap(); 17782 const morph = new Vector4(); 17783 17784 const workInfluences = []; 17785 17786 for ( let i = 0; i < 8; i ++ ) { 17787 17788 workInfluences[ i ] = [ i, 0 ]; 17789 17790 } 17791 17792 function update( object, geometry, program ) { 17793 17794 const objectInfluences = object.morphTargetInfluences; 17795 17796 if ( capabilities.isWebGL2 === true ) { 17797 17798 // instead of using attributes, the WebGL 2 code path encodes morph targets 17799 // into an array of data textures. Each layer represents a single morph target. 17800 17801 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; 17802 const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; 17803 17804 let entry = morphTextures.get( geometry ); 17805 17806 if ( entry === undefined || entry.count !== morphTargetsCount ) { 17807 17808 if ( entry !== undefined ) entry.texture.dispose(); 17809 17810 const hasMorphPosition = geometry.morphAttributes.position !== undefined; 17811 const hasMorphNormals = geometry.morphAttributes.normal !== undefined; 17812 const hasMorphColors = geometry.morphAttributes.color !== undefined; 17813 17814 const morphTargets = geometry.morphAttributes.position || []; 17815 const morphNormals = geometry.morphAttributes.normal || []; 17816 const morphColors = geometry.morphAttributes.color || []; 17817 17818 let vertexDataCount = 0; 17819 17820 if ( hasMorphPosition === true ) vertexDataCount = 1; 17821 if ( hasMorphNormals === true ) vertexDataCount = 2; 17822 if ( hasMorphColors === true ) vertexDataCount = 3; 17823 17824 let width = geometry.attributes.position.count * vertexDataCount; 17825 let height = 1; 17826 17827 if ( width > capabilities.maxTextureSize ) { 17828 17829 height = Math.ceil( width / capabilities.maxTextureSize ); 17830 width = capabilities.maxTextureSize; 17831 17832 } 17833 17834 const buffer = new Float32Array( width * height * 4 * morphTargetsCount ); 17835 17836 const texture = new DataArrayTexture( buffer, width, height, morphTargetsCount ); 17837 texture.type = FloatType; 17838 texture.needsUpdate = true; 17839 17840 // fill buffer 17841 17842 const vertexDataStride = vertexDataCount * 4; 17843 17844 for ( let i = 0; i < morphTargetsCount; i ++ ) { 17845 17846 const morphTarget = morphTargets[ i ]; 17847 const morphNormal = morphNormals[ i ]; 17848 const morphColor = morphColors[ i ]; 17849 17850 const offset = width * height * 4 * i; 17851 17852 for ( let j = 0; j < morphTarget.count; j ++ ) { 17853 17854 const stride = j * vertexDataStride; 17855 17856 if ( hasMorphPosition === true ) { 17857 17858 morph.fromBufferAttribute( morphTarget, j ); 17859 17860 buffer[ offset + stride + 0 ] = morph.x; 17861 buffer[ offset + stride + 1 ] = morph.y; 17862 buffer[ offset + stride + 2 ] = morph.z; 17863 buffer[ offset + stride + 3 ] = 0; 17864 17865 } 17866 17867 if ( hasMorphNormals === true ) { 17868 17869 morph.fromBufferAttribute( morphNormal, j ); 17870 17871 buffer[ offset + stride + 4 ] = morph.x; 17872 buffer[ offset + stride + 5 ] = morph.y; 17873 buffer[ offset + stride + 6 ] = morph.z; 17874 buffer[ offset + stride + 7 ] = 0; 17875 17876 } 17877 17878 if ( hasMorphColors === true ) { 17879 17880 morph.fromBufferAttribute( morphColor, j ); 17881 17882 buffer[ offset + stride + 8 ] = morph.x; 17883 buffer[ offset + stride + 9 ] = morph.y; 17884 buffer[ offset + stride + 10 ] = morph.z; 17885 buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? morph.w : 1; 17886 17887 } 17888 17889 } 17890 17891 } 17892 17893 entry = { 17894 count: morphTargetsCount, 17895 texture: texture, 17896 size: new Vector2( width, height ) 17897 }; 17898 17899 morphTextures.set( geometry, entry ); 17900 17901 function disposeTexture() { 17902 17903 texture.dispose(); 17904 17905 morphTextures.delete( geometry ); 17906 17907 geometry.removeEventListener( 'dispose', disposeTexture ); 17908 17909 } 17910 17911 geometry.addEventListener( 'dispose', disposeTexture ); 17912 17913 } 17914 17915 //
17916 17917 let morphInfluencesSum = 0; 17918 17919 for ( let i = 0; i < objectInfluences.length; i ++ ) { 17920 17921 morphInfluencesSum += objectInfluences[ i ]; 17922 17923 } 17924 17925 const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; 17926 17927 program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence ); 17928 program.getUniforms().setValue( gl, 'morphTargetInfluences', objectInfluences ); 17929 17930 program.getUniforms().setValue( gl, 'morphTargetsTexture', entry.texture, textures ); 17931 program.getUniforms().setValue( gl, 'morphTargetsTextureSize', entry.size );
vendor: 29,081 bytes, lines 17932-19482
17932 17933 17934 } else { 17935 17936 // When object doesn't have morph target influences defined, we treat it as a 0-length array 17937 // This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences 17938 17939 const length = objectInfluences === undefined ? 0 : objectInfluences.length; 17940 17941 let influences = influencesList[ geometry.id ]; 17942 17943 if ( influences === undefined || influences.length !== length ) { 17944 17945 // initialise list 17946 17947 influences = []; 17948 17949 for ( let i = 0; i < length; i ++ ) { 17950 17951 influences[ i ] = [ i, 0 ]; 17952 17953 } 17954 17955 influencesList[ geometry.id ] = influences; 17956 17957 } 17958 17959 // Collect influences 17960 17961 for ( let i = 0; i < length; i ++ ) { 17962 17963 const influence = influences[ i ]; 17964 17965 influence[ 0 ] = i; 17966 influence[ 1 ] = objectInfluences[ i ]; 17967 17968 } 17969 17970 influences.sort( absNumericalSort ); 17971 17972 for ( let i = 0; i < 8; i ++ ) { 17973 17974 if ( i < length && influences[ i ][ 1 ] ) { 17975 17976 workInfluences[ i ][ 0 ] = influences[ i ][ 0 ]; 17977 workInfluences[ i ][ 1 ] = influences[ i ][ 1 ]; 17978 17979 } else { 17980 17981 workInfluences[ i ][ 0 ] = Number.MAX_SAFE_INTEGER; 17982 workInfluences[ i ][ 1 ] = 0; 17983 17984 } 17985 17986 } 17987 17988 workInfluences.sort( numericalSort ); 17989 17990 const morphTargets = geometry.morphAttributes.position; 17991 const morphNormals = geometry.morphAttributes.normal; 17992 17993 let morphInfluencesSum = 0; 17994 17995 for ( let i = 0; i < 8; i ++ ) { 17996 17997 const influence = workInfluences[ i ]; 17998 const index = influence[ 0 ]; 17999 const value = influence[ 1 ]; 18000 18001 if ( index !== Number.MAX_SAFE_INTEGER && value ) { 18002 18003 if ( morphTargets && geometry.getAttribute( 'morphTarget' + i ) !== morphTargets[ index ] ) { 18004 18005 geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] ); 18006 18007 } 18008 18009 if ( morphNormals && geometry.getAttribute( 'morphNormal' + i ) !== morphNormals[ index ] ) { 18010 18011 geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] ); 18012 18013 } 18014 18015 morphInfluences[ i ] = value; 18016 morphInfluencesSum += value; 18017 18018 } else { 18019 18020 if ( morphTargets && geometry.hasAttribute( 'morphTarget' + i ) === true ) { 18021 18022 geometry.deleteAttribute( 'morphTarget' + i ); 18023 18024 } 18025 18026 if ( morphNormals && geometry.hasAttribute( 'morphNormal' + i ) === true ) { 18027 18028 geometry.deleteAttribute( 'morphNormal' + i ); 18029 18030 } 18031 18032 morphInfluences[ i ] = 0; 18033 18034 } 18035 18036 } 18037 18038 // GLSL shader uses formula baseinfluence * base + sum(target * influence) 18039 // This allows us to switch between absolute morphs and relative morphs without changing shader code 18040 // When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence) 18041 const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; 18042 18043 program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence ); 18044 program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences ); 18045 18046 } 18047 18048 } 18049 18050 return { 18051 18052 update: update 18053 18054 }; 18055 18056} 18057 18058function WebGLObjects( gl, geometries, attributes, info ) { 18059 18060 let updateMap = new WeakMap(); 18061 18062 function update( object ) { 18063 18064 const frame = info.render.frame; 18065 18066 const geometry = object.geometry; 18067 const buffergeometry = geometries.get( object, geometry ); 18068 18069 // Update once per frame 18070 18071 if ( updateMap.get( buffergeometry ) !== frame ) { 18072 18073 geometries.update( buffergeometry ); 18074 18075 updateMap.set( buffergeometry, frame ); 18076 18077 } 18078 18079 if ( object.isInstancedMesh ) { 18080 18081 if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) { 18082 18083 object.addEventListener( 'dispose', onInstancedMeshDispose ); 18084 18085 } 18086 18087 if ( updateMap.get( object ) !== frame ) { 18088 18089 attributes.update( object.instanceMatrix, gl.ARRAY_BUFFER ); 18090 18091 if ( object.instanceColor !== null ) { 18092 18093 attributes.update( object.instanceColor, gl.ARRAY_BUFFER ); 18094 18095 } 18096 18097 updateMap.set( object, frame ); 18098 18099 } 18100 18101 } 18102 18103 if ( object.isSkinnedMesh ) { 18104 18105 const skeleton = object.skeleton; 18106 18107 if ( updateMap.get( skeleton ) !== frame ) { 18108 18109 skeleton.update(); 18110 18111 updateMap.set( skeleton, frame ); 18112 18113 } 18114 18115 } 18116 18117 return buffergeometry; 18118 18119 } 18120 18121 function dispose() { 18122 18123 updateMap = new WeakMap(); 18124 18125 } 18126 18127 function onInstancedMeshDispose( event ) { 18128 18129 const instancedMesh = event.target; 18130 18131 instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose ); 18132 18133 attributes.remove( instancedMesh.instanceMatrix ); 18134 18135 if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor ); 18136 18137 } 18138 18139 return { 18140 18141 update: update, 18142 dispose: dispose 18143 18144 }; 18145 18146} 18147 18148class DepthTexture extends Texture { 18149 18150 constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) { 18151 18152 format = format !== undefined ? format : DepthFormat; 18153 18154 if ( format !== DepthFormat && format !== DepthStencilFormat ) { 18155 18156 throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); 18157 18158 } 18159 18160 if ( type === undefined && format === DepthFormat ) type = UnsignedIntType; 18161 if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type; 18162 18163 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 18164 18165 this.isDepthTexture = true; 18166 18167 this.image = { width: width, height: height }; 18168 18169 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; 18170 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; 18171 18172 this.flipY = false; 18173 this.generateMipmaps = false; 18174 18175 this.compareFunction = null; 18176 18177 } 18178 18179 18180 copy( source ) { 18181 18182 super.copy( source ); 18183 18184 this.compareFunction = source.compareFunction; 18185 18186 return this; 18187 18188 } 18189 18190 toJSON( meta ) { 18191 18192 const data = super.toJSON( meta ); 18193 18194 if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction; 18195 18196 return data; 18197 18198 } 18199 18200} 18201 18202/** 18203 * Uniforms of a program. 18204 * Those form a tree structure with a special top-level container for the root, 18205 * which you get by calling 'new WebGLUniforms( gl, program )'. 18206 * 18207 * 18208 * Properties of inner nodes including the top-level container: 18209 * 18210 * .seq - array of nested uniforms 18211 * .map - nested uniforms by name 18212 * 18213 * 18214 * Methods of all nodes except the top-level container: 18215 * 18216 * .setValue( gl, value, [textures] ) 18217 * 18218 * uploads a uniform value(s) 18219 * the 'textures' parameter is needed for sampler uniforms 18220 * 18221 * 18222 * Static methods of the top-level container (textures factorizations): 18223 * 18224 * .upload( gl, seq, values, textures ) 18225 * 18226 * sets uniforms in 'seq' to 'values[id].value' 18227 * 18228 * .seqWithValue( seq, values ) : filteredSeq 18229 * 18230 * filters 'seq' entries with corresponding entry in values 18231 * 18232 * 18233 * Methods of the top-level container (textures factorizations): 18234 * 18235 * .setValue( gl, name, value, textures ) 18236 * 18237 * sets uniform with name 'name' to 'value' 18238 * 18239 * .setOptional( gl, obj, prop ) 18240 * 18241 * like .set for an optional property of the object 18242 * 18243 */ 18244 18245 18246const emptyTexture = /*@__PURE__*/ new Texture(); 18247 18248const emptyShadowTexture = /*@__PURE__*/ new DepthTexture( 1, 1 ); 18249emptyShadowTexture.compareFunction = LessEqualCompare; 18250 18251const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture(); 18252const empty3dTexture = /*@__PURE__*/ new Data3DTexture(); 18253const emptyCubeTexture = /*@__PURE__*/ new CubeTexture(); 18254 18255// --- Utilities --- 18256 18257// Array Caches (provide typed arrays for temporary by size) 18258 18259const arrayCacheF32 = []; 18260const arrayCacheI32 = []; 18261 18262// Float32Array caches used for uploading Matrix uniforms 18263 18264const mat4array = new Float32Array( 16 ); 18265const mat3array = new Float32Array( 9 ); 18266const mat2array = new Float32Array( 4 ); 18267 18268// Flattening for arrays of vectors and matrices 18269 18270function flatten( array, nBlocks, blockSize ) { 18271 18272 const firstElem = array[ 0 ]; 18273 18274 if ( firstElem <= 0 || firstElem > 0 ) return array; 18275 // unoptimized: ! isNaN( firstElem ) 18276 // see http://jacksondunstan.com/articles/983 18277 18278 const n = nBlocks * blockSize; 18279 let r = arrayCacheF32[ n ]; 18280 18281 if ( r === undefined ) { 18282 18283 r = new Float32Array( n ); 18284 arrayCacheF32[ n ] = r; 18285 18286 } 18287 18288 if ( nBlocks !== 0 ) { 18289 18290 firstElem.toArray( r, 0 ); 18291 18292 for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) { 18293 18294 offset += blockSize; 18295 array[ i ].toArray( r, offset ); 18296 18297 } 18298 18299 } 18300 18301 return r; 18302 18303} 18304 18305function arraysEqual( a, b ) { 18306 18307 if ( a.length !== b.length ) return false; 18308 18309 for ( let i = 0, l = a.length; i < l; i ++ ) { 18310 18311 if ( a[ i ] !== b[ i ] ) return false; 18312 18313 } 18314 18315 return true; 18316 18317} 18318 18319function copyArray( a, b ) { 18320 18321 for ( let i = 0, l = b.length; i < l; i ++ ) { 18322 18323 a[ i ] = b[ i ]; 18324 18325 } 18326 18327} 18328 18329// Texture unit allocation 18330 18331function allocTexUnits( textures, n ) { 18332 18333 let r = arrayCacheI32[ n ]; 18334 18335 if ( r === undefined ) { 18336 18337 r = new Int32Array( n ); 18338 arrayCacheI32[ n ] = r; 18339 18340 } 18341 18342 for ( let i = 0; i !== n; ++ i ) { 18343 18344 r[ i ] = textures.allocateTextureUnit(); 18345 18346 } 18347 18348 return r; 18349 18350} 18351 18352// --- Setters --- 18353 18354// Note: Defining these methods externally, because they come in a bunch 18355// and this way their names minify. 18356 18357// Single scalar 18358 18359function setValueV1f( gl, v ) { 18360 18361 const cache = this.cache; 18362 18363 if ( cache[ 0 ] === v ) return; 18364 18365 gl.uniform1f( this.addr, v ); 18366 18367 cache[ 0 ] = v; 18368 18369} 18370 18371// Single float vector (from flat array or THREE.VectorN) 18372 18373function setValueV2f( gl, v ) { 18374 18375 const cache = this.cache; 18376 18377 if ( v.x !== undefined ) { 18378 18379 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 18380 18381 gl.uniform2f( this.addr, v.x, v.y ); 18382 18383 cache[ 0 ] = v.x; 18384 cache[ 1 ] = v.y; 18385 18386 } 18387 18388 } else { 18389 18390 if ( arraysEqual( cache, v ) ) return; 18391 18392 gl.uniform2fv( this.addr, v ); 18393 18394 copyArray( cache, v ); 18395 18396 } 18397 18398} 18399 18400function setValueV3f( gl, v ) { 18401 18402 const cache = this.cache; 18403 18404 if ( v.x !== undefined ) { 18405 18406 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 18407 18408 gl.uniform3f( this.addr, v.x, v.y, v.z ); 18409 18410 cache[ 0 ] = v.x; 18411 cache[ 1 ] = v.y; 18412 cache[ 2 ] = v.z; 18413 18414 } 18415 18416 } else if ( v.r !== undefined ) { 18417 18418 if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) { 18419 18420 gl.uniform3f( this.addr, v.r, v.g, v.b ); 18421 18422 cache[ 0 ] = v.r; 18423 cache[ 1 ] = v.g; 18424 cache[ 2 ] = v.b; 18425 18426 } 18427 18428 } else { 18429 18430 if ( arraysEqual( cache, v ) ) return; 18431 18432 gl.uniform3fv( this.addr, v ); 18433 18434 copyArray( cache, v ); 18435 18436 } 18437 18438} 18439 18440function setValueV4f( gl, v ) { 18441 18442 const cache = this.cache; 18443 18444 if ( v.x !== undefined ) { 18445 18446 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 18447 18448 gl.uniform4f( this.addr, v.x, v.y, v.z, v.w ); 18449 18450 cache[ 0 ] = v.x; 18451 cache[ 1 ] = v.y; 18452 cache[ 2 ] = v.z; 18453 cache[ 3 ] = v.w; 18454 18455 } 18456 18457 } else { 18458 18459 if ( arraysEqual( cache, v ) ) return; 18460 18461 gl.uniform4fv( this.addr, v ); 18462 18463 copyArray( cache, v ); 18464 18465 } 18466 18467} 18468 18469// Single matrix (from flat array or THREE.MatrixN) 18470 18471function setValueM2( gl, v ) { 18472 18473 const cache = this.cache; 18474 const elements = v.elements; 18475 18476 if ( elements === undefined ) { 18477 18478 if ( arraysEqual( cache, v ) ) return; 18479 18480 gl.uniformMatrix2fv( this.addr, false, v ); 18481 18482 copyArray( cache, v ); 18483 18484 } else { 18485 18486 if ( arraysEqual( cache, elements ) ) return; 18487 18488 mat2array.set( elements ); 18489 18490 gl.uniformMatrix2fv( this.addr, false, mat2array ); 18491 18492 copyArray( cache, elements ); 18493 18494 } 18495 18496} 18497 18498function setValueM3( gl, v ) { 18499 18500 const cache = this.cache; 18501 const elements = v.elements; 18502 18503 if ( elements === undefined ) { 18504 18505 if ( arraysEqual( cache, v ) ) return; 18506 18507 gl.uniformMatrix3fv( this.addr, false, v ); 18508 18509 copyArray( cache, v ); 18510 18511 } else { 18512 18513 if ( arraysEqual( cache, elements ) ) return; 18514 18515 mat3array.set( elements ); 18516 18517 gl.uniformMatrix3fv( this.addr, false, mat3array ); 18518 18519 copyArray( cache, elements ); 18520 18521 } 18522 18523} 18524 18525function setValueM4( gl, v ) { 18526 18527 const cache = this.cache; 18528 const elements = v.elements; 18529 18530 if ( elements === undefined ) { 18531 18532 if ( arraysEqual( cache, v ) ) return; 18533 18534 gl.uniformMatrix4fv( this.addr, false, v ); 18535 18536 copyArray( cache, v ); 18537 18538 } else { 18539 18540 if ( arraysEqual( cache, elements ) ) return; 18541 18542 mat4array.set( elements ); 18543 18544 gl.uniformMatrix4fv( this.addr, false, mat4array ); 18545 18546 copyArray( cache, elements ); 18547 18548 } 18549 18550} 18551 18552// Single integer / boolean 18553 18554function setValueV1i( gl, v ) { 18555 18556 const cache = this.cache; 18557 18558 if ( cache[ 0 ] === v ) return; 18559 18560 gl.uniform1i( this.addr, v ); 18561 18562 cache[ 0 ] = v; 18563 18564} 18565 18566// Single integer / boolean vector (from flat array or THREE.VectorN) 18567 18568function setValueV2i( gl, v ) { 18569 18570 const cache = this.cache; 18571 18572 if ( v.x !== undefined ) { 18573 18574 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 18575 18576 gl.uniform2i( this.addr, v.x, v.y ); 18577 18578 cache[ 0 ] = v.x; 18579 cache[ 1 ] = v.y; 18580 18581 } 18582 18583 } else { 18584 18585 if ( arraysEqual( cache, v ) ) return; 18586 18587 gl.uniform2iv( this.addr, v ); 18588 18589 copyArray( cache, v ); 18590 18591 } 18592 18593} 18594 18595function setValueV3i( gl, v ) { 18596 18597 const cache = this.cache; 18598 18599 if ( v.x !== undefined ) { 18600 18601 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 18602 18603 gl.uniform3i( this.addr, v.x, v.y, v.z ); 18604 18605 cache[ 0 ] = v.x; 18606 cache[ 1 ] = v.y; 18607 cache[ 2 ] = v.z; 18608 18609 } 18610 18611 } else { 18612 18613 if ( arraysEqual( cache, v ) ) return; 18614 18615 gl.uniform3iv( this.addr, v ); 18616 18617 copyArray( cache, v ); 18618 18619 } 18620 18621} 18622 18623function setValueV4i( gl, v ) { 18624 18625 const cache = this.cache; 18626 18627 if ( v.x !== undefined ) { 18628 18629 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 18630 18631 gl.uniform4i( this.addr, v.x, v.y, v.z, v.w ); 18632 18633 cache[ 0 ] = v.x; 18634 cache[ 1 ] = v.y; 18635 cache[ 2 ] = v.z; 18636 cache[ 3 ] = v.w; 18637 18638 } 18639 18640 } else { 18641 18642 if ( arraysEqual( cache, v ) ) return; 18643 18644 gl.uniform4iv( this.addr, v ); 18645 18646 copyArray( cache, v ); 18647 18648 } 18649 18650} 18651 18652// Single unsigned integer 18653 18654function setValueV1ui( gl, v ) { 18655 18656 const cache = this.cache; 18657 18658 if ( cache[ 0 ] === v ) return; 18659 18660 gl.uniform1ui( this.addr, v ); 18661 18662 cache[ 0 ] = v; 18663 18664} 18665 18666// Single unsigned integer vector (from flat array or THREE.VectorN) 18667 18668function setValueV2ui( gl, v ) { 18669 18670 const cache = this.cache; 18671 18672 if ( v.x !== undefined ) { 18673 18674 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 18675 18676 gl.uniform2ui( this.addr, v.x, v.y ); 18677 18678 cache[ 0 ] = v.x; 18679 cache[ 1 ] = v.y; 18680 18681 } 18682 18683 } else { 18684 18685 if ( arraysEqual( cache, v ) ) return; 18686 18687 gl.uniform2uiv( this.addr, v ); 18688 18689 copyArray( cache, v ); 18690 18691 } 18692 18693} 18694 18695function setValueV3ui( gl, v ) { 18696 18697 const cache = this.cache; 18698 18699 if ( v.x !== undefined ) { 18700 18701 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 18702 18703 gl.uniform3ui( this.addr, v.x, v.y, v.z ); 18704 18705 cache[ 0 ] = v.x; 18706 cache[ 1 ] = v.y; 18707 cache[ 2 ] = v.z; 18708 18709 } 18710 18711 } else { 18712 18713 if ( arraysEqual( cache, v ) ) return; 18714 18715 gl.uniform3uiv( this.addr, v ); 18716 18717 copyArray( cache, v ); 18718 18719 } 18720 18721} 18722 18723function setValueV4ui( gl, v ) { 18724 18725 const cache = this.cache; 18726 18727 if ( v.x !== undefined ) { 18728 18729 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 18730 18731 gl.uniform4ui( this.addr, v.x, v.y, v.z, v.w ); 18732 18733 cache[ 0 ] = v.x; 18734 cache[ 1 ] = v.y; 18735 cache[ 2 ] = v.z; 18736 cache[ 3 ] = v.w; 18737 18738 } 18739 18740 } else { 18741 18742 if ( arraysEqual( cache, v ) ) return; 18743 18744 gl.uniform4uiv( this.addr, v ); 18745 18746 copyArray( cache, v ); 18747 18748 } 18749 18750} 18751 18752 18753// Single texture (2D / Cube) 18754 18755function setValueT1( gl, v, textures ) { 18756 18757 const cache = this.cache; 18758 const unit = textures.allocateTextureUnit(); 18759 18760 if ( cache[ 0 ] !== unit ) { 18761 18762 gl.uniform1i( this.addr, unit ); 18763 cache[ 0 ] = unit; 18764 18765 } 18766 18767 const emptyTexture2D = ( this.type === gl.SAMPLER_2D_SHADOW ) ? emptyShadowTexture : emptyTexture; 18768 18769 textures.setTexture2D( v || emptyTexture2D, unit ); 18770 18771} 18772 18773function setValueT3D1( gl, v, textures ) { 18774 18775 const cache = this.cache; 18776 const unit = textures.allocateTextureUnit(); 18777 18778 if ( cache[ 0 ] !== unit ) { 18779 18780 gl.uniform1i( this.addr, unit ); 18781 cache[ 0 ] = unit; 18782 18783 } 18784 18785 textures.setTexture3D( v || empty3dTexture, unit ); 18786 18787} 18788 18789function setValueT6( gl, v, textures ) { 18790 18791 const cache = this.cache; 18792 const unit = textures.allocateTextureUnit(); 18793 18794 if ( cache[ 0 ] !== unit ) { 18795 18796 gl.uniform1i( this.addr, unit ); 18797 cache[ 0 ] = unit; 18798 18799 } 18800 18801 textures.setTextureCube( v || emptyCubeTexture, unit ); 18802 18803} 18804 18805function setValueT2DArray1( gl, v, textures ) { 18806 18807 const cache = this.cache; 18808 const unit = textures.allocateTextureUnit(); 18809 18810 if ( cache[ 0 ] !== unit ) { 18811 18812 gl.uniform1i( this.addr, unit ); 18813 cache[ 0 ] = unit; 18814 18815 } 18816 18817 textures.setTexture2DArray( v || emptyArrayTexture, unit ); 18818 18819} 18820 18821// Helper to pick the right setter for the singular case 18822 18823function getSingularSetter( type ) { 18824 18825 switch ( type ) { 18826 18827 case 0x1406: return setValueV1f; // FLOAT 18828 case 0x8b50: return setValueV2f; // _VEC2 18829 case 0x8b51: return setValueV3f; // _VEC3 18830 case 0x8b52: return setValueV4f; // _VEC4 18831 18832 case 0x8b5a: return setValueM2; // _MAT2 18833 case 0x8b5b: return setValueM3; // _MAT3 18834 case 0x8b5c: return setValueM4; // _MAT4 18835 18836 case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL 18837 case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2 18838 case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3 18839 case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4 18840 18841 case 0x1405: return setValueV1ui; // UINT 18842 case 0x8dc6: return setValueV2ui; // _VEC2 18843 case 0x8dc7: return setValueV3ui; // _VEC3 18844 case 0x8dc8: return setValueV4ui; // _VEC4 18845 18846 case 0x8b5e: // SAMPLER_2D 18847 case 0x8d66: // SAMPLER_EXTERNAL_OES 18848 case 0x8dca: // INT_SAMPLER_2D 18849 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D 18850 case 0x8b62: // SAMPLER_2D_SHADOW 18851 return setValueT1; 18852 18853 case 0x8b5f: // SAMPLER_3D 18854 case 0x8dcb: // INT_SAMPLER_3D 18855 case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D 18856 return setValueT3D1; 18857 18858 case 0x8b60: // SAMPLER_CUBE 18859 case 0x8dcc: // INT_SAMPLER_CUBE 18860 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE 18861 case 0x8dc5: // SAMPLER_CUBE_SHADOW 18862 return setValueT6; 18863 18864 case 0x8dc1: // SAMPLER_2D_ARRAY 18865 case 0x8dcf: // INT_SAMPLER_2D_ARRAY 18866 case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY 18867 case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW 18868 return setValueT2DArray1; 18869 18870 } 18871 18872} 18873 18874 18875// Array of scalars 18876 18877function setValueV1fArray( gl, v ) { 18878 18879 gl.uniform1fv( this.addr, v ); 18880 18881} 18882 18883// Array of vectors (from flat array or array of THREE.VectorN) 18884 18885function setValueV2fArray( gl, v ) { 18886 18887 const data = flatten( v, this.size, 2 ); 18888 18889 gl.uniform2fv( this.addr, data ); 18890 18891} 18892 18893function setValueV3fArray( gl, v ) { 18894 18895 const data = flatten( v, this.size, 3 ); 18896 18897 gl.uniform3fv( this.addr, data ); 18898 18899} 18900 18901function setValueV4fArray( gl, v ) { 18902 18903 const data = flatten( v, this.size, 4 ); 18904 18905 gl.uniform4fv( this.addr, data ); 18906 18907} 18908 18909// Array of matrices (from flat array or array of THREE.MatrixN) 18910 18911function setValueM2Array( gl, v ) { 18912 18913 const data = flatten( v, this.size, 4 ); 18914 18915 gl.uniformMatrix2fv( this.addr, false, data ); 18916 18917} 18918 18919function setValueM3Array( gl, v ) { 18920 18921 const data = flatten( v, this.size, 9 ); 18922 18923 gl.uniformMatrix3fv( this.addr, false, data ); 18924 18925} 18926 18927function setValueM4Array( gl, v ) { 18928 18929 const data = flatten( v, this.size, 16 ); 18930 18931 gl.uniformMatrix4fv( this.addr, false, data ); 18932 18933} 18934 18935// Array of integer / boolean 18936 18937function setValueV1iArray( gl, v ) { 18938 18939 gl.uniform1iv( this.addr, v ); 18940 18941} 18942 18943// Array of integer / boolean vectors (from flat array) 18944 18945function setValueV2iArray( gl, v ) { 18946 18947 gl.uniform2iv( this.addr, v ); 18948 18949} 18950 18951function setValueV3iArray( gl, v ) { 18952 18953 gl.uniform3iv( this.addr, v ); 18954 18955} 18956 18957function setValueV4iArray( gl, v ) { 18958 18959 gl.uniform4iv( this.addr, v ); 18960 18961} 18962 18963// Array of unsigned integer 18964 18965function setValueV1uiArray( gl, v ) { 18966 18967 gl.uniform1uiv( this.addr, v ); 18968 18969} 18970 18971// Array of unsigned integer vectors (from flat array) 18972 18973function setValueV2uiArray( gl, v ) { 18974 18975 gl.uniform2uiv( this.addr, v ); 18976 18977} 18978 18979function setValueV3uiArray( gl, v ) { 18980 18981 gl.uniform3uiv( this.addr, v ); 18982 18983} 18984 18985function setValueV4uiArray( gl, v ) { 18986 18987 gl.uniform4uiv( this.addr, v ); 18988 18989} 18990 18991 18992// Array of textures (2D / 3D / Cube / 2DArray) 18993 18994function setValueT1Array( gl, v, textures ) { 18995 18996 const cache = this.cache; 18997 18998 const n = v.length; 18999 19000 const units = allocTexUnits( textures, n ); 19001 19002 if ( ! arraysEqual( cache, units ) ) { 19003 19004 gl.uniform1iv( this.addr, units ); 19005 19006 copyArray( cache, units ); 19007 19008 } 19009 19010 for ( let i = 0; i !== n; ++ i ) { 19011 19012 textures.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); 19013 19014 } 19015 19016} 19017 19018function setValueT3DArray( gl, v, textures ) { 19019 19020 const cache = this.cache; 19021 19022 const n = v.length; 19023 19024 const units = allocTexUnits( textures, n ); 19025 19026 if ( ! arraysEqual( cache, units ) ) { 19027 19028 gl.uniform1iv( this.addr, units ); 19029 19030 copyArray( cache, units ); 19031 19032 } 19033 19034 for ( let i = 0; i !== n; ++ i ) { 19035 19036 textures.setTexture3D( v[ i ] || empty3dTexture, units[ i ] ); 19037 19038 } 19039 19040} 19041 19042function setValueT6Array( gl, v, textures ) { 19043 19044 const cache = this.cache; 19045 19046 const n = v.length; 19047 19048 const units = allocTexUnits( textures, n ); 19049 19050 if ( ! arraysEqual( cache, units ) ) { 19051 19052 gl.uniform1iv( this.addr, units ); 19053 19054 copyArray( cache, units ); 19055 19056 } 19057 19058 for ( let i = 0; i !== n; ++ i ) { 19059 19060 textures.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] ); 19061 19062 } 19063 19064} 19065 19066function setValueT2DArrayArray( gl, v, textures ) { 19067 19068 const cache = this.cache; 19069 19070 const n = v.length; 19071 19072 const units = allocTexUnits( textures, n ); 19073 19074 if ( ! arraysEqual( cache, units ) ) { 19075 19076 gl.uniform1iv( this.addr, units ); 19077 19078 copyArray( cache, units ); 19079 19080 } 19081 19082 for ( let i = 0; i !== n; ++ i ) { 19083 19084 textures.setTexture2DArray( v[ i ] || emptyArrayTexture, units[ i ] ); 19085 19086 } 19087 19088} 19089 19090 19091// Helper to pick the right setter for a pure (bottom-level) array 19092 19093function getPureArraySetter( type ) { 19094 19095 switch ( type ) { 19096 19097 case 0x1406: return setValueV1fArray; // FLOAT 19098 case 0x8b50: return setValueV2fArray; // _VEC2 19099 case 0x8b51: return setValueV3fArray; // _VEC3 19100 case 0x8b52: return setValueV4fArray; // _VEC4 19101 19102 case 0x8b5a: return setValueM2Array; // _MAT2 19103 case 0x8b5b: return setValueM3Array; // _MAT3 19104 case 0x8b5c: return setValueM4Array; // _MAT4 19105 19106 case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL 19107 case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2 19108 case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3 19109 case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4 19110 19111 case 0x1405: return setValueV1uiArray; // UINT 19112 case 0x8dc6: return setValueV2uiArray; // _VEC2 19113 case 0x8dc7: return setValueV3uiArray; // _VEC3 19114 case 0x8dc8: return setValueV4uiArray; // _VEC4 19115 19116 case 0x8b5e: // SAMPLER_2D 19117 case 0x8d66: // SAMPLER_EXTERNAL_OES 19118 case 0x8dca: // INT_SAMPLER_2D 19119 case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D 19120 case 0x8b62: // SAMPLER_2D_SHADOW 19121 return setValueT1Array; 19122 19123 case 0x8b5f: // SAMPLER_3D 19124 case 0x8dcb: // INT_SAMPLER_3D 19125 case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D 19126 return setValueT3DArray; 19127 19128 case 0x8b60: // SAMPLER_CUBE 19129 case 0x8dcc: // INT_SAMPLER_CUBE 19130 case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE 19131 case 0x8dc5: // SAMPLER_CUBE_SHADOW 19132 return setValueT6Array; 19133 19134 case 0x8dc1: // SAMPLER_2D_ARRAY 19135 case 0x8dcf: // INT_SAMPLER_2D_ARRAY 19136 case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY 19137 case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW 19138 return setValueT2DArrayArray; 19139 19140 } 19141 19142} 19143 19144// --- Uniform Classes --- 19145 19146class SingleUniform { 19147 19148 constructor( id, activeInfo, addr ) { 19149 19150 this.id = id; 19151 this.addr = addr; 19152 this.cache = []; 19153 this.type = activeInfo.type; 19154 this.setValue = getSingularSetter( activeInfo.type ); 19155 19156 // this.path = activeInfo.name; // DEBUG 19157 19158 } 19159 19160} 19161 19162class PureArrayUniform { 19163 19164 constructor( id, activeInfo, addr ) { 19165 19166 this.id = id; 19167 this.addr = addr; 19168 this.cache = []; 19169 this.type = activeInfo.type; 19170 this.size = activeInfo.size; 19171 this.setValue = getPureArraySetter( activeInfo.type ); 19172 19173 // this.path = activeInfo.name; // DEBUG 19174 19175 } 19176 19177} 19178 19179class StructuredUniform { 19180 19181 constructor( id ) { 19182 19183 this.id = id; 19184 19185 this.seq = []; 19186 this.map = {}; 19187 19188 } 19189 19190 setValue( gl, value, textures ) { 19191 19192 const seq = this.seq; 19193 19194 for ( let i = 0, n = seq.length; i !== n; ++ i ) { 19195 19196 const u = seq[ i ]; 19197 u.setValue( gl, value[ u.id ], textures ); 19198 19199 } 19200 19201 } 19202 19203} 19204 19205// --- Top-level --- 19206 19207// Parser - builds up the property tree from the path strings 19208 19209const RePathPart = /(\w+)(\])?(\[|\.)?/g; 19210 19211// extracts 19212// - the identifier (member name or array index) 19213// - followed by an optional right bracket (found when array index) 19214// - followed by an optional left bracket or dot (type of subscript) 19215// 19216// Note: These portions can be read in a non-overlapping fashion and 19217// allow straightforward parsing of the hierarchy that WebGL encodes 19218// in the uniform names. 19219 19220function addUniform( container, uniformObject ) { 19221 19222 container.seq.push( uniformObject ); 19223 container.map[ uniformObject.id ] = uniformObject; 19224 19225} 19226 19227function parseUniform( activeInfo, addr, container ) { 19228 19229 const path = activeInfo.name, 19230 pathLength = path.length; 19231 19232 // reset RegExp object, because of the early exit of a previous run 19233 RePathPart.lastIndex = 0; 19234 19235 while ( true ) { 19236 19237 const match = RePathPart.exec( path ), 19238 matchEnd = RePathPart.lastIndex; 19239 19240 let id = match[ 1 ]; 19241 const idIsIndex = match[ 2 ] === ']', 19242 subscript = match[ 3 ]; 19243 19244 if ( idIsIndex ) id = id | 0; // convert to integer 19245 19246 if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) { 19247 19248 // bare name or "pure" bottom-level array "[0]" suffix 19249 19250 addUniform( container, subscript === undefined ? 19251 new SingleUniform( id, activeInfo, addr ) : 19252 new PureArrayUniform( id, activeInfo, addr ) ); 19253 19254 break; 19255 19256 } else { 19257 19258 // step into inner node / create it in case it doesn't exist 19259 19260 const map = container.map; 19261 let next = map[ id ]; 19262 19263 if ( next === undefined ) { 19264 19265 next = new StructuredUniform( id ); 19266 addUniform( container, next ); 19267 19268 } 19269 19270 container = next; 19271 19272 } 19273 19274 } 19275 19276} 19277 19278// Root Container 19279 19280class WebGLUniforms { 19281 19282 constructor( gl, program ) { 19283 19284 this.seq = []; 19285 this.map = {}; 19286 19287 const n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS ); 19288 19289 for ( let i = 0; i < n; ++ i ) { 19290 19291 const info = gl.getActiveUniform( program, i ), 19292 addr = gl.getUniformLocation( program, info.name ); 19293 19294 parseUniform( info, addr, this ); 19295 19296 } 19297 19298 } 19299 19300 setValue( gl, name, value, textures ) { 19301 19302 const u = this.map[ name ]; 19303 19304 if ( u !== undefined ) u.setValue( gl, value, textures ); 19305 19306 } 19307 19308 setOptional( gl, object, name ) { 19309 19310 const v = object[ name ]; 19311 19312 if ( v !== undefined ) this.setValue( gl, name, v ); 19313 19314 } 19315 19316 static upload( gl, seq, values, textures ) { 19317 19318 for ( let i = 0, n = seq.length; i !== n; ++ i ) { 19319 19320 const u = seq[ i ], 19321 v = values[ u.id ]; 19322 19323 if ( v.needsUpdate !== false ) { 19324 19325 // note: always updating when .needsUpdate is undefined 19326 u.setValue( gl, v.value, textures ); 19327 19328 } 19329 19330 } 19331 19332 } 19333 19334 static seqWithValue( seq, values ) { 19335 19336 const r = []; 19337 19338 for ( let i = 0, n = seq.length; i !== n; ++ i ) { 19339 19340 const u = seq[ i ]; 19341 if ( u.id in values ) r.push( u ); 19342 19343 } 19344 19345 return r; 19346 19347 } 19348 19349} 19350 19351function WebGLShader( gl, type, string ) { 19352 19353 const shader = gl.createShader( type ); 19354 19355 gl.shaderSource( shader, string ); 19356 gl.compileShader( shader ); 19357 19358 return shader; 19359 19360} 19361 19362// From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/ 19363const COMPLETION_STATUS_KHR = 0x91B1; 19364 19365let programIdCount = 0; 19366 19367function handleSource( string, errorLine ) { 19368 19369 const lines = string.split( '\n' ); 19370 const lines2 = []; 19371 19372 const from = Math.max( errorLine - 6, 0 ); 19373 const to = Math.min( errorLine + 6, lines.length ); 19374 19375 for ( let i = from; i < to; i ++ ) { 19376 19377 const line = i + 1; 19378 lines2.push( `${line === errorLine ? '>' : ' '} ${line}: ${lines[ i ]}` ); 19379 19380 } 19381 19382 return lines2.join( '\n' ); 19383 19384} 19385 19386function getEncodingComponents( colorSpace ) { 19387 19388 const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); 19389 const encodingPrimaries = ColorManagement.getPrimaries( colorSpace ); 19390 19391 let gamutMapping; 19392 19393 if ( workingPrimaries === encodingPrimaries ) { 19394 19395 gamutMapping = ''; 19396 19397 } else if ( workingPrimaries === P3Primaries && encodingPrimaries === Rec709Primaries ) { 19398 19399 gamutMapping = 'LinearDisplayP3ToLinearSRGB'; 19400 19401 } else if ( workingPrimaries === Rec709Primaries && encodingPrimaries === P3Primaries ) { 19402 19403 gamutMapping = 'LinearSRGBToLinearDisplayP3'; 19404 19405 } 19406 19407 switch ( colorSpace ) { 19408 19409 case LinearSRGBColorSpace: 19410 case LinearDisplayP3ColorSpace: 19411 return [ gamutMapping, 'LinearTransferOETF' ]; 19412 19413 case SRGBColorSpace: 19414 case DisplayP3ColorSpace: 19415 return [ gamutMapping, 'sRGBTransferOETF' ]; 19416 19417 default: 19418 console.warn( 'THREE.WebGLProgram: Unsupported color space:', colorSpace ); 19419 return [ gamutMapping, 'LinearTransferOETF' ]; 19420 19421 } 19422 19423} 19424 19425function getShaderErrors( gl, shader, type ) { 19426 19427 const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS ); 19428 const errors = gl.getShaderInfoLog( shader ).trim(); 19429 19430 if ( status && errors === '' ) return ''; 19431 19432 const errorMatches = /ERROR: 0:(\d+)/.exec( errors ); 19433 if ( errorMatches ) { 19434 19435 // --enable-privileged-webgl-extension 19436 // console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); 19437 19438 const errorLine = parseInt( errorMatches[ 1 ] ); 19439 return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine ); 19440 19441 } else { 19442 19443 return errors; 19444 19445 } 19446 19447} 19448 19449function getTexelEncodingFunction( functionName, colorSpace ) { 19450 19451 const components = getEncodingComponents( colorSpace ); 19452 return `vec4 ${functionName}( vec4 value ) { return ${components[ 0 ]}( ${components[ 1 ]}( value ) ); }`; 19453 19454} 19455 19456function getToneMappingFunction( functionName, toneMapping ) { 19457 19458 let toneMappingName; 19459 19460 switch ( toneMapping ) { 19461 19462 case LinearToneMapping: 19463 toneMappingName = 'Linear'; 19464 break; 19465 19466 case ReinhardToneMapping: 19467 toneMappingName = 'Reinhard'; 19468 break; 19469 19470 case CineonToneMapping: 19471 toneMappingName = 'OptimizedCineon'; 19472 break; 19473 19474 case ACESFilmicToneMapping: 19475 toneMappingName = 'ACESFilmic'; 19476 break; 19477 19478 case AgXToneMapping: 19479 toneMappingName = 'AgX'; 19480 break; 19481 19482 case
vendor: 17,767 bytes, lines 19482-20098
19482CustomToneMapping: 19483 toneMappingName = 'Custom'; 19484 break; 19485 19486 default: 19487 console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping ); 19488 toneMappingName = 'Linear'; 19489 19490 } 19491 19492 return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }'; 19493 19494} 19495 19496function generateExtensions( parameters ) { 19497 19498 const chunks = [ 19499 ( parameters.extensionDerivatives || !! parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.normalMapTangentSpace || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '', 19500 ( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '', 19501 ( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '', 19502 ( parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : '' 19503 ]; 19504 19505 return chunks.filter( filterEmptyLine ).join( '\n' ); 19506 19507} 19508 19509function generateVertexExtensions( parameters ) { 19510 19511 const chunks = [ 19512 parameters.extensionClipCullDistance ? '#extension GL_ANGLE_clip_cull_distance : require' : '' 19513 ]; 19514 19515 return chunks.filter( filterEmptyLine ).join( '\n' ); 19516 19517} 19518 19519function generateDefines( defines ) { 19520 19521 const chunks = []; 19522 19523 for ( const name in defines ) { 19524 19525 const value = defines[ name ]; 19526 19527 if ( value === false ) continue; 19528 19529 chunks.push( '#define ' + name + ' ' + value ); 19530 19531 } 19532 19533 return chunks.join( '\n' ); 19534 19535} 19536 19537function fetchAttributeLocations( gl, program ) { 19538 19539 const attributes = {}; 19540 19541 const n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES ); 19542 19543 for ( let i = 0; i < n; i ++ ) { 19544 19545 const info = gl.getActiveAttrib( program, i ); 19546 const name = info.name; 19547 19548 let locationSize = 1; 19549 if ( info.type === gl.FLOAT_MAT2 ) locationSize = 2; 19550 if ( info.type === gl.FLOAT_MAT3 ) locationSize = 3; 19551 if ( info.type === gl.FLOAT_MAT4 ) locationSize = 4; 19552 19553 // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); 19554 19555 attributes[ name ] = { 19556 type: info.type, 19557 location: gl.getAttribLocation( program, name ), 19558 locationSize: locationSize 19559 }; 19560 19561 } 19562 19563 return attributes; 19564 19565} 19566 19567function filterEmptyLine( string ) { 19568 19569 return string !== ''; 19570 19571} 19572 19573function replaceLightNums( string, parameters ) { 19574 19575 const numSpotLightCoords = parameters.numSpotLightShadows + parameters.numSpotLightMaps - parameters.numSpotLightShadowsWithMaps; 19576 19577 return string 19578 .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights ) 19579 .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights ) 19580 .replace( /NUM_SPOT_LIGHT_MAPS/g, parameters.numSpotLightMaps ) 19581 .replace( /NUM_SPOT_LIGHT_COORDS/g, numSpotLightCoords ) 19582 .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights ) 19583 .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights ) 19584 .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights ) 19585 .replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows ) 19586 .replace( /NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g, parameters.numSpotLightShadowsWithMaps ) 19587 .replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows ) 19588 .replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows ); 19589 19590} 19591 19592function replaceClippingPlaneNums( string, parameters ) { 19593 19594 return string 19595 .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes ) 19596 .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) ); 19597 19598} 19599 19600// Resolve Includes 19601 19602const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm; 19603 19604function resolveIncludes( string ) { 19605 19606 return string.replace( includePattern, includeReplacer ); 19607 19608} 19609 19610const shaderChunkMap = new Map( [ 19611 [ 'encodings_fragment', 'colorspace_fragment' ], // @deprecated, r154 19612 [ 'encodings_pars_fragment', 'colorspace_pars_fragment' ], // @deprecated, r154 19613 [ 'output_fragment', 'opaque_fragment' ], // @deprecated, r154 19614] ); 19615 19616function includeReplacer( match, include ) { 19617 19618 let string = ShaderChunk[ include ]; 19619 19620 if ( string === undefined ) { 19621 19622 const newInclude = shaderChunkMap.get( include ); 19623 19624 if ( newInclude !== undefined ) { 19625 19626 string = ShaderChunk[ newInclude ]; 19627 console.warn( 'THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude ); 19628 19629 } else { 19630 19631 throw new Error( 'Can not resolve #include <' + include + '>' ); 19632 19633 } 19634 19635 } 19636 19637 return resolveIncludes( string ); 19638 19639} 19640 19641// Unroll Loops 19642 19643const 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; 19644 19645function unrollLoops( string ) { 19646 19647 return string.replace( unrollLoopPattern, loopReplacer ); 19648 19649} 19650 19651function loopReplacer( match, start, end, snippet ) { 19652 19653 let string = ''; 19654 19655 for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) { 19656 19657 string += snippet 19658 .replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' ) 19659 .replace( /UNROLLED_LOOP_INDEX/g, i ); 19660 19661 } 19662 19663 return string; 19664 19665} 19666 19667// 19668 19669function generatePrecision( parameters ) { 19670 19671 let precisionstring = 'precision ' + parameters.precision + ' float;\nprecision ' + parameters.precision + ' int;'; 19672 19673 if ( parameters.precision === 'highp' ) { 19674 19675 precisionstring += '\n#define HIGH_PRECISION'; 19676 19677 } else if ( parameters.precision === 'mediump' ) { 19678 19679 precisionstring += '\n#define MEDIUM_PRECISION'; 19680 19681 } else if ( parameters.precision === 'lowp' ) { 19682 19683 precisionstring += '\n#define LOW_PRECISION'; 19684 19685 } 19686 19687 return precisionstring; 19688 19689} 19690 19691function generateShadowMapTypeDefine( parameters ) { 19692 19693 let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; 19694 19695 if ( parameters.shadowMapType === PCFShadowMap ) { 19696 19697 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; 19698 19699 } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { 19700 19701 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; 19702 19703 } else if ( parameters.shadowMapType === VSMShadowMap ) { 19704 19705 shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM'; 19706 19707 } 19708 19709 return shadowMapTypeDefine; 19710 19711} 19712 19713function generateEnvMapTypeDefine( parameters ) { 19714 19715 let envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; 19716 19717 if ( parameters.envMap ) { 19718 19719 switch ( parameters.envMapMode ) { 19720 19721 case CubeReflectionMapping: 19722 case CubeRefractionMapping: 19723 envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; 19724 break; 19725 19726 case CubeUVReflectionMapping: 19727 envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; 19728 break; 19729 19730 } 19731 19732 } 19733 19734 return envMapTypeDefine; 19735 19736} 19737 19738function generateEnvMapModeDefine( parameters ) { 19739 19740 let envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; 19741 19742 if ( parameters.envMap ) { 19743 19744 switch ( parameters.envMapMode ) { 19745 19746 case CubeRefractionMapping: 19747 19748 envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; 19749 break; 19750 19751 } 19752 19753 } 19754 19755 return envMapModeDefine; 19756 19757} 19758 19759function generateEnvMapBlendingDefine( parameters ) { 19760 19761 let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE'; 19762 19763 if ( parameters.envMap ) { 19764 19765 switch ( parameters.combine ) { 19766 19767 case MultiplyOperation: 19768 envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; 19769 break; 19770 19771 case MixOperation: 19772 envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; 19773 break; 19774 19775 case AddOperation: 19776 envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; 19777 break; 19778 19779 } 19780 19781 } 19782 19783 return envMapBlendingDefine; 19784 19785} 19786 19787function generateCubeUVSize( parameters ) { 19788 19789 const imageHeight = parameters.envMapCubeUVHeight; 19790 19791 if ( imageHeight === null ) return null; 19792 19793 const maxMip = Math.log2( imageHeight ) - 2; 19794 19795 const texelHeight = 1.0 / imageHeight; 19796 19797 const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) ); 19798 19799 return { texelWidth, texelHeight, maxMip }; 19800 19801} 19802 19803function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { 19804 19805 // TODO Send this event to Three.js DevTools 19806 // console.log( 'WebGLProgram', cacheKey ); 19807 19808 const gl = renderer.getContext(); 19809 19810 const defines = parameters.defines; 19811 19812 let vertexShader = parameters.vertexShader; 19813 let fragmentShader = parameters.fragmentShader; 19814 19815 const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters ); 19816 const envMapTypeDefine = generateEnvMapTypeDefine( parameters ); 19817 const envMapModeDefine = generateEnvMapModeDefine( parameters ); 19818 const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters ); 19819 const envMapCubeUVSize = generateCubeUVSize( parameters ); 19820 19821 const customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters ); 19822 19823 const customVertexExtensions = generateVertexExtensions( parameters ); 19824 19825 const customDefines = generateDefines( defines ); 19826 19827 const program = gl.createProgram(); 19828 19829 let prefixVertex, prefixFragment; 19830 let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : ''; 19831 19832 if ( parameters.isRawShaderMaterial ) { 19833 19834 prefixVertex = [ 19835 19836 '#define SHADER_TYPE ' + parameters.shaderType, 19837 '#define SHADER_NAME ' + parameters.shaderName, 19838 19839 customDefines 19840 19841 ].filter( filterEmptyLine ).join( '\n' ); 19842 19843 if ( prefixVertex.length > 0 ) { 19844 19845 prefixVertex += '\n'; 19846 19847 } 19848 19849 prefixFragment = [ 19850 19851 customExtensions, 19852 19853 '#define SHADER_TYPE ' + parameters.shaderType, 19854 '#define SHADER_NAME ' + parameters.shaderName, 19855 19856 customDefines 19857 19858 ].filter( filterEmptyLine ).join( '\n' ); 19859 19860 if ( prefixFragment.length > 0 ) { 19861 19862 prefixFragment += '\n'; 19863 19864 } 19865 19866 } else { 19867 19868 prefixVertex = [ 19869 19870 generatePrecision( parameters ), 19871 19872 '#define SHADER_TYPE ' + parameters.shaderType, 19873 '#define SHADER_NAME ' + parameters.shaderName, 19874 19875 customDefines, 19876 19877 parameters.extensionClipCullDistance ? '#define USE_CLIP_DISTANCE' : '', 19878 parameters.batching ? '#define USE_BATCHING' : '', 19879 parameters.instancing ? '#define USE_INSTANCING' : '', 19880 parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '', 19881 19882 parameters.useFog && parameters.fog ? '#define USE_FOG' : '', 19883 parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '', 19884 19885 parameters.map ? '#define USE_MAP' : '', 19886 parameters.envMap ? '#define USE_ENVMAP' : '', 19887 parameters.envMap ? '#define ' + envMapModeDefine : '', 19888 parameters.lightMap ? '#define USE_LIGHTMAP' : '', 19889 parameters.aoMap ? '#define USE_AOMAP' : '', 19890 parameters.bumpMap ? '#define USE_BUMPMAP' : '', 19891 parameters.normalMap ? '#define USE_NORMALMAP' : '', 19892 parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', 19893 parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', 19894 parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '', 19895 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', 19896 19897 parameters.anisotropy ? '#define USE_ANISOTROPY' : '', 19898 parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', 19899 19900 parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', 19901 parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', 19902 parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', 19903 19904 parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', 19905 parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', 19906 19907 parameters.specularMap ? '#define USE_SPECULARMAP' : '', 19908 parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', 19909 parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', 19910 19911 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', 19912 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', 19913 parameters.alphaMap ? '#define USE_ALPHAMAP' : '', 19914 parameters.alphaHash ? '#define USE_ALPHAHASH' : '', 19915 19916 parameters.transmission ? '#define USE_TRANSMISSION' : '', 19917 parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', 19918 parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', 19919 19920 parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', 19921 parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', 19922 19923 // 19924 19925 parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '', 19926 parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '', 19927 parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '', 19928 parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '', 19929 parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '', 19930 parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '', 19931 parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '', 19932 parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '', 19933 19934 parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '', 19935 parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '', 19936 19937 parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '', 19938 19939 parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '', 19940 parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '', 19941 parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '', 19942 19943 parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '', 19944 parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '', 19945 19946 parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '', 19947 parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '', 19948 19949 parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '', 19950 parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '', 19951 parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '', 19952 19953 parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '', 19954 parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '', 19955 19956 // 19957 19958 parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', 19959 parameters.vertexColors ? '#define USE_COLOR' : '', 19960 parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', 19961 parameters.vertexUv1s ? '#define USE_UV1' : '', 19962 parameters.vertexUv2s ? '#define USE_UV2' : '', 19963 parameters.vertexUv3s ? '#define USE_UV3' : '', 19964 19965 parameters.pointsUvs ? '#define USE_POINTS_UV' : '', 19966 19967 parameters.flatShading ? '#define FLAT_SHADED' : '', 19968 19969 parameters.skinning ? '#define USE_SKINNING' : '', 19970 19971 parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', 19972 parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', 19973 ( parameters.morphColors && parameters.isWebGL2 ) ? '#define USE_MORPHCOLORS' : '', 19974 ( parameters.morphTargetsCount > 0 && parameters.isWebGL2 ) ? '#define MORPHTARGETS_TEXTURE' : '', 19975 ( parameters.morphTargetsCount > 0 && parameters.isWebGL2 ) ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '', 19976 ( parameters.morphTargetsCount > 0 && parameters.isWebGL2 ) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '', 19977 parameters.doubleSided ? '#define DOUBLE_SIDED' : '', 19978 parameters.flipSided ? '#define FLIP_SIDED' : '', 19979 19980 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', 19981 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', 19982 19983 parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', 19984 19985 parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', 19986 19987 parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', 19988 19989 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', 19990 ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '', 19991 19992 'uniform mat4 modelMatrix;', 19993 'uniform mat4 modelViewMatrix;', 19994 'uniform mat4 projectionMatrix;', 19995 'uniform mat4 viewMatrix;', 19996 'uniform mat3 normalMatrix;', 19997 'uniform vec3 cameraPosition;', 19998 'uniform bool isOrthographic;', 19999 20000 '#ifdef USE_INSTANCING', 20001 20002 ' attribute mat4 instanceMatrix;', 20003 20004 '#endif', 20005 20006 '#ifdef USE_INSTANCING_COLOR', 20007 20008 ' attribute vec3 instanceColor;', 20009 20010 '#endif', 20011 20012 'attribute vec3 position;', 20013 'attribute vec3 normal;', 20014 'attribute vec2 uv;', 20015 20016 '#ifdef USE_UV1', 20017 20018 ' attribute vec2 uv1;', 20019 20020 '#endif', 20021 20022 '#ifdef USE_UV2', 20023 20024 ' attribute vec2 uv2;', 20025 20026 '#endif', 20027 20028 '#ifdef USE_UV3', 20029 20030 ' attribute vec2 uv3;', 20031 20032 '#endif', 20033 20034 '#ifdef USE_TANGENT', 20035 20036 ' attribute vec4 tangent;', 20037 20038 '#endif', 20039 20040 '#if defined( USE_COLOR_ALPHA )', 20041 20042 ' attribute vec4 color;', 20043 20044 '#elif defined( USE_COLOR )', 20045 20046 ' attribute vec3 color;', 20047 20048 '#endif', 20049 20050 '#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )', 20051 20052 ' attribute vec3 morphTarget0;', 20053 ' attribute vec3 morphTarget1;', 20054 ' attribute vec3 morphTarget2;', 20055 ' attribute vec3 morphTarget3;', 20056 20057 ' #ifdef USE_MORPHNORMALS', 20058 20059 ' attribute vec3 morphNormal0;', 20060 ' attribute vec3 morphNormal1;', 20061 ' attribute vec3 morphNormal2;', 20062 ' attribute vec3 morphNormal3;', 20063 20064 ' #else', 20065 20066 ' attribute vec3 morphTarget4;', 20067 ' attribute vec3 morphTarget5;', 20068 ' attribute vec3 morphTarget6;', 20069 ' attribute vec3 morphTarget7;', 20070 20071 ' #endif', 20072 20073 '#endif', 20074 20075 '#ifdef USE_SKINNING', 20076 20077 ' attribute vec4 skinIndex;', 20078 ' attribute vec4 skinWeight;', 20079 20080 '#endif', 20081 20082 '\n' 20083 20084 ].filter( filterEmptyLine ).join( '\n' ); 20085 20086 prefixFragment = [ 20087 20088 customExtensions, 20089 20090 generatePrecision( parameters ), 20091 20092 '#define SHADER_TYPE ' + parameters.shaderType, 20093 '#define SHADER_NAME ' + parameters.shaderName, 20094 20095 customDefines, 20096 20097 parameters.useFog && parameters.fog ? '#define USE_FOG' : '', 20098 parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '',
vendor: 8,229 bytes, lines 20099-20301
20099 20100 parameters.map ? '#define USE_MAP' : '', 20101 parameters.matcap ? '#define USE_MATCAP' : '', 20102 parameters.envMap ? '#define USE_ENVMAP' : '', 20103 parameters.envMap ? '#define ' + envMapTypeDefine : '', 20104 parameters.envMap ? '#define ' + envMapModeDefine : '', 20105 parameters.envMap ? '#define ' + envMapBlendingDefine : '', 20106 envMapCubeUVSize ? '#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth : '', 20107 envMapCubeUVSize ? '#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight : '', 20108 envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '', 20109 parameters.lightMap ? '#define USE_LIGHTMAP' : '', 20110 parameters.aoMap ? '#define USE_AOMAP' : '', 20111 parameters.bumpMap ? '#define USE_BUMPMAP' : '', 20112 parameters.normalMap ? '#define USE_NORMALMAP' : '', 20113 parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '', 20114 parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '', 20115 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', 20116 20117 parameters.anisotropy ? '#define USE_ANISOTROPY' : '', 20118 parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '', 20119 20120 parameters.clearcoat ? '#define USE_CLEARCOAT' : '', 20121 parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '', 20122 parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '', 20123 parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '', 20124 20125 parameters.iridescence ? '#define USE_IRIDESCENCE' : '', 20126 parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', 20127 parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '', 20128 20129 parameters.specularMap ? '#define USE_SPECULARMAP' : '', 20130 parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '', 20131 parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '', 20132 20133 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', 20134 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', 20135 20136 parameters.alphaMap ? '#define USE_ALPHAMAP' : '', 20137 parameters.alphaTest ? '#define USE_ALPHATEST' : '', 20138 parameters.alphaHash ? '#define USE_ALPHAHASH' : '', 20139 20140 parameters.sheen ? '#define USE_SHEEN' : '', 20141 parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '', 20142 parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '', 20143 20144 parameters.transmission ? '#define USE_TRANSMISSION' : '', 20145 parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', 20146 parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', 20147 20148 parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', 20149 parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', 20150 parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', 20151 parameters.vertexUv1s ? '#define USE_UV1' : '', 20152 parameters.vertexUv2s ? '#define USE_UV2' : '', 20153 parameters.vertexUv3s ? '#define USE_UV3' : '', 20154 20155 parameters.pointsUvs ? '#define USE_POINTS_UV' : '', 20156 20157 parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', 20158 20159 parameters.flatShading ? '#define FLAT_SHADED' : '', 20160 20161 parameters.doubleSided ? '#define DOUBLE_SIDED' : '', 20162 parameters.flipSided ? '#define FLIP_SIDED' : '', 20163 20164 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', 20165 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', 20166 20167 parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', 20168 20169 parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', 20170 20171 parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '', 20172 20173 parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', 20174 20175 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', 20176 ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '', 20177 20178 'uniform mat4 viewMatrix;', 20179 'uniform vec3 cameraPosition;', 20180 'uniform bool isOrthographic;', 20181 20182 ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '', 20183 ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below 20184 ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '', 20185 20186 parameters.dithering ? '#define DITHERING' : '', 20187 parameters.opaque ? '#define OPAQUE' : '', 20188 20189 ShaderChunk[ 'colorspace_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below 20190 getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputColorSpace ), 20191 20192 parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', 20193 20194 '\n' 20195 20196 ].filter( filterEmptyLine ).join( '\n' ); 20197 20198 } 20199 20200 vertexShader = resolveIncludes( vertexShader ); 20201 vertexShader = replaceLightNums( vertexShader, parameters ); 20202 vertexShader = replaceClippingPlaneNums( vertexShader, parameters ); 20203 20204 fragmentShader = resolveIncludes( fragmentShader ); 20205 fragmentShader = replaceLightNums( fragmentShader, parameters ); 20206 fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters ); 20207 20208 vertexShader = unrollLoops( vertexShader ); 20209 fragmentShader = unrollLoops( fragmentShader ); 20210 20211 if ( parameters.isWebGL2 && parameters.isRawShaderMaterial !== true ) { 20212 20213 // GLSL 3.0 conversion for built-in materials and ShaderMaterial 20214 20215 versionString = '#version 300 es\n'; 20216 20217 prefixVertex = [ 20218 customVertexExtensions, 20219 'precision mediump sampler2DArray;', 20220 '#define attribute in', 20221 '#define varying out', 20222 '#define texture2D texture' 20223 ].join( '\n' ) + '\n' + prefixVertex; 20224 20225 prefixFragment = [ 20226 'precision mediump sampler2DArray;', 20227 '#define varying in', 20228 ( parameters.glslVersion === GLSL3 ) ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;', 20229 ( parameters.glslVersion === GLSL3 ) ? '' : '#define gl_FragColor pc_fragColor', 20230 '#define gl_FragDepthEXT gl_FragDepth', 20231 '#define texture2D texture', 20232 '#define textureCube texture', 20233 '#define texture2DProj textureProj', 20234 '#define texture2DLodEXT textureLod', 20235 '#define texture2DProjLodEXT textureProjLod', 20236 '#define textureCubeLodEXT textureLod', 20237 '#define texture2DGradEXT textureGrad', 20238 '#define texture2DProjGradEXT textureProjGrad', 20239 '#define textureCubeGradEXT textureGrad' 20240 ].join( '\n' ) + '\n' + prefixFragment; 20241 20242 } 20243 20244 const vertexGlsl = versionString + prefixVertex + vertexShader; 20245 const fragmentGlsl = versionString + prefixFragment + fragmentShader; 20246 20247 // console.log( '*VERTEX*', vertexGlsl ); 20248 // console.log( '*FRAGMENT*', fragmentGlsl ); 20249 20250 const glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); 20251 const glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); 20252 20253 gl.attachShader( program, glVertexShader ); 20254 gl.attachShader( program, glFragmentShader ); 20255 20256 // Force a particular attribute to index 0. 20257 20258 if ( parameters.index0AttributeName !== undefined ) { 20259 20260 gl.bindAttribLocation( program, 0, parameters.index0AttributeName ); 20261 20262 } else if ( parameters.morphTargets === true ) { 20263 20264 // programs with morphTargets displace position out of attribute 0 20265 gl.bindAttribLocation( program, 0, 'position' ); 20266 20267 } 20268 20269 gl.linkProgram( program ); 20270 20271 function onFirstUse( self ) { 20272 20273 // check for link errors 20274 if ( renderer.debug.checkShaderErrors ) { 20275 20276 const programLog = gl.getProgramInfoLog( program ).trim(); 20277 const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim(); 20278 const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim(); 20279 20280 let runnable = true; 20281 let haveDiagnostics = true; 20282 20283 if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { 20284 20285 runnable = false; 20286 20287 if ( typeof renderer.debug.onShaderError === 'function' ) { 20288 20289 renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader ); 20290 20291 } else { 20292 20293 // default error reporting 20294 20295 const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' ); 20296 const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' ); 20297 20298 console.error( 20299 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + 20300 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' + 20301 '
vendor: 24,726 bytes, lines 20301-21198
20301Program Info Log: ' + programLog + '\n' + 20302 vertexErrors + '\n' + 20303 fragmentErrors 20304 ); 20305 20306 } 20307 20308 } else if ( programLog !== '' ) { 20309 20310 console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog ); 20311 20312 } else if ( vertexLog === '' || fragmentLog === '' ) { 20313 20314 haveDiagnostics = false; 20315 20316 } 20317 20318 if ( haveDiagnostics ) { 20319 20320 self.diagnostics = { 20321 20322 runnable: runnable, 20323 20324 programLog: programLog, 20325 20326 vertexShader: { 20327 20328 log: vertexLog, 20329 prefix: prefixVertex 20330 20331 }, 20332 20333 fragmentShader: { 20334 20335 log: fragmentLog, 20336 prefix: prefixFragment 20337 20338 } 20339 20340 }; 20341 20342 } 20343 20344 } 20345 20346 // Clean up 20347 20348 // Crashes in iOS9 and iOS10. #18402 20349 // gl.detachShader( program, glVertexShader ); 20350 // gl.detachShader( program, glFragmentShader ); 20351 20352 gl.deleteShader( glVertexShader ); 20353 gl.deleteShader( glFragmentShader ); 20354 20355 cachedUniforms = new WebGLUniforms( gl, program ); 20356 cachedAttributes = fetchAttributeLocations( gl, program ); 20357 20358 } 20359 20360 // set up caching for uniform locations 20361 20362 let cachedUniforms; 20363 20364 this.getUniforms = function () { 20365 20366 if ( cachedUniforms === undefined ) { 20367 20368 // Populates cachedUniforms and cachedAttributes 20369 onFirstUse( this ); 20370 20371 } 20372 20373 return cachedUniforms; 20374 20375 }; 20376 20377 // set up caching for attribute locations 20378 20379 let cachedAttributes; 20380 20381 this.getAttributes = function () { 20382 20383 if ( cachedAttributes === undefined ) { 20384 20385 // Populates cachedAttributes and cachedUniforms 20386 onFirstUse( this ); 20387 20388 } 20389 20390 return cachedAttributes; 20391 20392 }; 20393 20394 // indicate when the program is ready to be used. if the KHR_parallel_shader_compile extension isn't supported, 20395 // flag the program as ready immediately. It may cause a stall when it's first used. 20396 20397 let programReady = ( parameters.rendererExtensionParallelShaderCompile === false ); 20398 20399 this.isReady = function () { 20400 20401 if ( programReady === false ) { 20402 20403 programReady = gl.getProgramParameter( program, COMPLETION_STATUS_KHR ); 20404 20405 } 20406 20407 return programReady; 20408 20409 }; 20410 20411 // free resource 20412 20413 this.destroy = function () { 20414 20415 bindingStates.releaseStatesOfProgram( this ); 20416 20417 gl.deleteProgram( program ); 20418 this.program = undefined; 20419 20420 }; 20421 20422 // 20423 20424 this.type = parameters.shaderType; 20425 this.name = parameters.shaderName; 20426 this.id = programIdCount ++; 20427 this.cacheKey = cacheKey; 20428 this.usedTimes = 1; 20429 this.program = program; 20430 this.vertexShader = glVertexShader; 20431 this.fragmentShader = glFragmentShader; 20432 20433 return this; 20434 20435} 20436 20437let _id$1 = 0; 20438 20439class WebGLShaderCache { 20440 20441 constructor() { 20442 20443 this.shaderCache = new Map(); 20444 this.materialCache = new Map(); 20445 20446 } 20447 20448 update( material ) { 20449 20450 const vertexShader = material.vertexShader; 20451 const fragmentShader = material.fragmentShader; 20452 20453 const vertexShaderStage = this._getShaderStage( vertexShader ); 20454 const fragmentShaderStage = this._getShaderStage( fragmentShader ); 20455 20456 const materialShaders = this._getShaderCacheForMaterial( material ); 20457 20458 if ( materialShaders.has( vertexShaderStage ) === false ) { 20459 20460 materialShaders.add( vertexShaderStage ); 20461 vertexShaderStage.usedTimes ++; 20462 20463 } 20464 20465 if ( materialShaders.has( fragmentShaderStage ) === false ) { 20466 20467 materialShaders.add( fragmentShaderStage ); 20468 fragmentShaderStage.usedTimes ++; 20469 20470 } 20471 20472 return this; 20473 20474 } 20475 20476 remove( material ) { 20477 20478 const materialShaders = this.materialCache.get( material ); 20479 20480 for ( const shaderStage of materialShaders ) { 20481 20482 shaderStage.usedTimes --; 20483 20484 if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage.code ); 20485 20486 } 20487 20488 this.materialCache.delete( material ); 20489 20490 return this; 20491 20492 } 20493 20494 getVertexShaderID( material ) { 20495 20496 return this._getShaderStage( material.vertexShader ).id; 20497 20498 } 20499 20500 getFragmentShaderID( material ) { 20501 20502 return this._getShaderStage( material.fragmentShader ).id; 20503 20504 } 20505 20506 dispose() { 20507 20508 this.shaderCache.clear(); 20509 this.materialCache.clear(); 20510 20511 } 20512 20513 _getShaderCacheForMaterial( material ) { 20514 20515 const cache = this.materialCache; 20516 let set = cache.get( material ); 20517 20518 if ( set === undefined ) { 20519 20520 set = new Set(); 20521 cache.set( material, set ); 20522 20523 } 20524 20525 return set; 20526 20527 } 20528 20529 _getShaderStage( code ) { 20530 20531 const cache = this.shaderCache; 20532 let stage = cache.get( code ); 20533 20534 if ( stage === undefined ) { 20535 20536 stage = new WebGLShaderStage( code ); 20537 cache.set( code, stage ); 20538 20539 } 20540 20541 return stage; 20542 20543 } 20544 20545} 20546 20547class WebGLShaderStage { 20548 20549 constructor( code ) { 20550 20551 this.id = _id$1 ++; 20552 20553 this.code = code; 20554 this.usedTimes = 0; 20555 20556 } 20557 20558} 20559 20560function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) { 20561 20562 const _programLayers = new Layers(); 20563 const _customShaders = new WebGLShaderCache(); 20564 const programs = []; 20565 20566 const IS_WEBGL2 = capabilities.isWebGL2; 20567 const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; 20568 const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures; 20569 20570 let precision = capabilities.precision; 20571 20572 const shaderIDs = { 20573 MeshDepthMaterial: 'depth', 20574 MeshDistanceMaterial: 'distanceRGBA', 20575 MeshNormalMaterial: 'normal', 20576 MeshBasicMaterial: 'basic', 20577 MeshLambertMaterial: 'lambert', 20578 MeshPhongMaterial: 'phong', 20579 MeshToonMaterial: 'toon', 20580 MeshStandardMaterial: 'physical', 20581 MeshPhysicalMaterial: 'physical', 20582 MeshMatcapMaterial: 'matcap', 20583 LineBasicMaterial: 'basic', 20584 LineDashedMaterial: 'dashed', 20585 PointsMaterial: 'points', 20586 ShadowMaterial: 'shadow', 20587 SpriteMaterial: 'sprite' 20588 }; 20589 20590 function getChannel( value ) { 20591 20592 if ( value === 0 ) return 'uv'; 20593 20594 return `uv${ value }`; 20595 20596 } 20597 20598 function getParameters( material, lights, shadows, scene, object ) { 20599 20600 const fog = scene.fog; 20601 const geometry = object.geometry; 20602 const environment = material.isMeshStandardMaterial ? scene.environment : null; 20603 20604 const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); 20605 const envMapCubeUVHeight = ( !! envMap ) && ( envMap.mapping === CubeUVReflectionMapping ) ? envMap.image.height : null; 20606 20607 const shaderID = shaderIDs[ material.type ]; 20608 20609 // heuristics to create shader parameters according to lights in the scene 20610 // (not to blow over maxLights budget) 20611 20612 if ( material.precision !== null ) { 20613 20614 precision = capabilities.getMaxPrecision( material.precision ); 20615 20616 if ( precision !== material.precision ) { 20617 20618 console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); 20619 20620 } 20621 20622 } 20623 20624 // 20625 20626 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; 20627 const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; 20628 20629 let morphTextureStride = 0; 20630 20631 if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 1; 20632 if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 2; 20633 if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 3; 20634 20635 // 20636 20637 let vertexShader, fragmentShader; 20638 let customVertexShaderID, customFragmentShaderID; 20639 20640 if ( shaderID ) { 20641 20642 const shader = ShaderLib[ shaderID ]; 20643 20644 vertexShader = shader.vertexShader; 20645 fragmentShader = shader.fragmentShader; 20646 20647 } else { 20648 20649 vertexShader = material.vertexShader; 20650 fragmentShader = material.fragmentShader; 20651 20652 _customShaders.update( material ); 20653 20654 customVertexShaderID = _customShaders.getVertexShaderID( material ); 20655 customFragmentShaderID = _customShaders.getFragmentShaderID( material ); 20656 20657 } 20658 20659 const currentRenderTarget = renderer.getRenderTarget(); 20660 20661 const IS_INSTANCEDMESH = object.isInstancedMesh === true; 20662 const IS_BATCHEDMESH = object.isBatchedMesh === true; 20663 20664 const HAS_MAP = !! material.map; 20665 const HAS_MATCAP = !! material.matcap; 20666 const HAS_ENVMAP = !! envMap; 20667 const HAS_AOMAP = !! material.aoMap; 20668 const HAS_LIGHTMAP = !! material.lightMap; 20669 const HAS_BUMPMAP = !! material.bumpMap; 20670 const HAS_NORMALMAP = !! material.normalMap; 20671 const HAS_DISPLACEMENTMAP = !! material.displacementMap; 20672 const HAS_EMISSIVEMAP = !! material.emissiveMap; 20673 20674 const HAS_METALNESSMAP = !! material.metalnessMap; 20675 const HAS_ROUGHNESSMAP = !! material.roughnessMap; 20676 20677 const HAS_ANISOTROPY = material.anisotropy > 0; 20678 const HAS_CLEARCOAT = material.clearcoat > 0; 20679 const HAS_IRIDESCENCE = material.iridescence > 0; 20680 const HAS_SHEEN = material.sheen > 0; 20681 const HAS_TRANSMISSION = material.transmission > 0; 20682 20683 const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap; 20684 20685 const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap; 20686 const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap; 20687 const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap; 20688 20689 const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap; 20690 const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap; 20691 20692 const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap; 20693 const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap; 20694 20695 const HAS_SPECULARMAP = !! material.specularMap; 20696 const HAS_SPECULAR_COLORMAP = !! material.specularColorMap; 20697 const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap; 20698 20699 const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap; 20700 const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap; 20701 20702 const HAS_GRADIENTMAP = !! material.gradientMap; 20703 20704 const HAS_ALPHAMAP = !! material.alphaMap; 20705 20706 const HAS_ALPHATEST = material.alphaTest > 0; 20707 20708 const HAS_ALPHAHASH = !! material.alphaHash; 20709 20710 const HAS_EXTENSIONS = !! material.extensions; 20711 20712 const HAS_ATTRIBUTE_UV1 = !! geometry.attributes.uv1; 20713 const HAS_ATTRIBUTE_UV2 = !! geometry.attributes.uv2; 20714 const HAS_ATTRIBUTE_UV3 = !! geometry.attributes.uv3; 20715 20716 let toneMapping = NoToneMapping; 20717 20718 if ( material.toneMapped ) { 20719 20720 if ( currentRenderTarget === null || currentRenderTarget.isXRRenderTarget === true ) { 20721 20722 toneMapping = renderer.toneMapping; 20723 20724 } 20725 20726 } 20727 20728 const parameters = { 20729 20730 isWebGL2: IS_WEBGL2, 20731 20732 shaderID: shaderID, 20733 shaderType: material.type, 20734 shaderName: material.name, 20735 20736 vertexShader: vertexShader, 20737 fragmentShader: fragmentShader, 20738 defines: material.defines, 20739 20740 customVertexShaderID: customVertexShaderID, 20741 customFragmentShaderID: customFragmentShaderID, 20742 20743 isRawShaderMaterial: material.isRawShaderMaterial === true, 20744 glslVersion: material.glslVersion, 20745 20746 precision: precision, 20747 20748 batching: IS_BATCHEDMESH, 20749 instancing: IS_INSTANCEDMESH, 20750 instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null, 20751 20752 supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES, 20753 outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ), 20754 20755 map: HAS_MAP, 20756 matcap: HAS_MATCAP, 20757 envMap: HAS_ENVMAP, 20758 envMapMode: HAS_ENVMAP && envMap.mapping, 20759 envMapCubeUVHeight: envMapCubeUVHeight, 20760 aoMap: HAS_AOMAP, 20761 lightMap: HAS_LIGHTMAP, 20762 bumpMap: HAS_BUMPMAP, 20763 normalMap: HAS_NORMALMAP, 20764 displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP, 20765 emissiveMap: HAS_EMISSIVEMAP, 20766 20767 normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap, 20768 normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap, 20769 20770 metalnessMap: HAS_METALNESSMAP, 20771 roughnessMap: HAS_ROUGHNESSMAP, 20772 20773 anisotropy: HAS_ANISOTROPY, 20774 anisotropyMap: HAS_ANISOTROPYMAP, 20775 20776 clearcoat: HAS_CLEARCOAT, 20777 clearcoatMap: HAS_CLEARCOATMAP, 20778 clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP, 20779 clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP, 20780 20781 iridescence: HAS_IRIDESCENCE, 20782 iridescenceMap: HAS_IRIDESCENCEMAP, 20783 iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP, 20784 20785 sheen: HAS_SHEEN, 20786 sheenColorMap: HAS_SHEEN_COLORMAP, 20787 sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP, 20788 20789 specularMap: HAS_SPECULARMAP, 20790 specularColorMap: HAS_SPECULAR_COLORMAP, 20791 specularIntensityMap: HAS_SPECULAR_INTENSITYMAP, 20792 20793 transmission: HAS_TRANSMISSION, 20794 transmissionMap: HAS_TRANSMISSIONMAP, 20795 thicknessMap: HAS_THICKNESSMAP, 20796 20797 gradientMap: HAS_GRADIENTMAP, 20798 20799 opaque: material.transparent === false && material.blending === NormalBlending, 20800 20801 alphaMap: HAS_ALPHAMAP, 20802 alphaTest: HAS_ALPHATEST, 20803 alphaHash: HAS_ALPHAHASH, 20804 20805 combine: material.combine, 20806 20807 // 20808 20809 mapUv: HAS_MAP && getChannel( material.map.channel ), 20810 aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ), 20811 lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ), 20812 bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ), 20813 normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ), 20814 displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ), 20815 emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ), 20816 20817 metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ), 20818 roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ), 20819 20820 anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ), 20821 20822 clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ), 20823 clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ), 20824 clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ), 20825 20826 iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ), 20827 iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ), 20828 20829 sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ), 20830 sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ), 20831 20832 specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ), 20833 specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ), 20834 specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ), 20835 20836 transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ), 20837 thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ), 20838 20839 alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ), 20840 20841 // 20842 20843 vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ), 20844 vertexColors: material.vertexColors, 20845 vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4, 20846 vertexUv1s: HAS_ATTRIBUTE_UV1, 20847 vertexUv2s: HAS_ATTRIBUTE_UV2, 20848 vertexUv3s: HAS_ATTRIBUTE_UV3, 20849 20850 pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ), 20851 20852 fog: !! fog, 20853 useFog: material.fog === true, 20854 fogExp2: ( fog && fog.isFogExp2 ), 20855 20856 flatShading: material.flatShading === true, 20857 20858 sizeAttenuation: material.sizeAttenuation === true, 20859 logarithmicDepthBuffer: logarithmicDepthBuffer, 20860 20861 skinning: object.isSkinnedMesh === true, 20862 20863 morphTargets: geometry.morphAttributes.position !== undefined, 20864 morphNormals: geometry.morphAttributes.normal !== undefined, 20865 morphColors: geometry.morphAttributes.color !== undefined, 20866 morphTargetsCount: morphTargetsCount, 20867 morphTextureStride: morphTextureStride, 20868 20869 numDirLights: lights.directional.length, 20870 numPointLights: lights.point.length, 20871 numSpotLights: lights.spot.length, 20872 numSpotLightMaps: lights.spotLightMap.length, 20873 numRectAreaLights: lights.rectArea.length, 20874 numHemiLights: lights.hemi.length, 20875 20876 numDirLightShadows: lights.directionalShadowMap.length, 20877 numPointLightShadows: lights.pointShadowMap.length, 20878 numSpotLightShadows: lights.spotShadowMap.length, 20879 numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps, 20880 20881 numLightProbes: lights.numLightProbes, 20882 20883 numClippingPlanes: clipping.numPlanes, 20884 numClipIntersection: clipping.numIntersection, 20885 20886 dithering: material.dithering, 20887 20888 shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0, 20889 shadowMapType: renderer.shadowMap.type, 20890 20891 toneMapping: toneMapping, 20892 useLegacyLights: renderer._useLegacyLights, 20893 20894 decodeVideoTexture: HAS_MAP && ( material.map.isVideoTexture === true ) && ( ColorManagement.getTransfer( material.map.colorSpace ) === SRGBTransfer ), 20895 20896 premultipliedAlpha: material.premultipliedAlpha, 20897 20898 doubleSided: material.side === DoubleSide, 20899 flipSided: material.side === BackSide, 20900 20901 useDepthPacking: material.depthPacking >= 0, 20902 depthPacking: material.depthPacking || 0, 20903 20904 index0AttributeName: material.index0AttributeName, 20905 20906 extensionDerivatives: HAS_EXTENSIONS && material.extensions.derivatives === true, 20907 extensionFragDepth: HAS_EXTENSIONS && material.extensions.fragDepth === true, 20908 extensionDrawBuffers: HAS_EXTENSIONS && material.extensions.drawBuffers === true, 20909 extensionShaderTextureLOD: HAS_EXTENSIONS && material.extensions.shaderTextureLOD === true, 20910 extensionClipCullDistance: HAS_EXTENSIONS && material.extensions.clipCullDistance && extensions.has( 'WEBGL_clip_cull_distance' ), 20911 20912 rendererExtensionFragDepth: IS_WEBGL2 || extensions.has( 'EXT_frag_depth' ), 20913 rendererExtensionDrawBuffers: IS_WEBGL2 || extensions.has( 'WEBGL_draw_buffers' ), 20914 rendererExtensionShaderTextureLod: IS_WEBGL2 || extensions.has( 'EXT_shader_texture_lod' ), 20915 rendererExtensionParallelShaderCompile: extensions.has( 'KHR_parallel_shader_compile' ), 20916 20917 customProgramCacheKey: material.customProgramCacheKey() 20918 20919 }; 20920 20921 return parameters; 20922 20923 } 20924 20925 function getProgramCacheKey( parameters ) { 20926 20927 const array = []; 20928 20929 if ( parameters.shaderID ) { 20930 20931 array.push( parameters.shaderID ); 20932 20933 } else { 20934 20935 array.push( parameters.customVertexShaderID ); 20936 array.push( parameters.customFragmentShaderID ); 20937 20938 } 20939 20940 if ( parameters.defines !== undefined ) { 20941 20942 for ( const name in parameters.defines ) { 20943 20944 array.push( name ); 20945 array.push( parameters.defines[ name ] ); 20946 20947 } 20948 20949 } 20950 20951 if ( parameters.isRawShaderMaterial === false ) { 20952 20953 getProgramCacheKeyParameters( array, parameters ); 20954 getProgramCacheKeyBooleans( array, parameters ); 20955 array.push( renderer.outputColorSpace ); 20956 20957 } 20958 20959 array.push( parameters.customProgramCacheKey ); 20960 20961 return array.join(); 20962 20963 } 20964 20965 function getProgramCacheKeyParameters( array, parameters ) { 20966 20967 array.push( parameters.precision ); 20968 array.push( parameters.outputColorSpace ); 20969 array.push( parameters.envMapMode ); 20970 array.push( parameters.envMapCubeUVHeight ); 20971 array.push( parameters.mapUv ); 20972 array.push( parameters.alphaMapUv ); 20973 array.push( parameters.lightMapUv ); 20974 array.push( parameters.aoMapUv ); 20975 array.push( parameters.bumpMapUv ); 20976 array.push( parameters.normalMapUv ); 20977 array.push( parameters.displacementMapUv ); 20978 array.push( parameters.emissiveMapUv ); 20979 array.push( parameters.metalnessMapUv ); 20980 array.push( parameters.roughnessMapUv ); 20981 array.push( parameters.anisotropyMapUv ); 20982 array.push( parameters.clearcoatMapUv ); 20983 array.push( parameters.clearcoatNormalMapUv ); 20984 array.push( parameters.clearcoatRoughnessMapUv ); 20985 array.push( parameters.iridescenceMapUv ); 20986 array.push( parameters.iridescenceThicknessMapUv ); 20987 array.push( parameters.sheenColorMapUv ); 20988 array.push( parameters.sheenRoughnessMapUv ); 20989 array.push( parameters.specularMapUv ); 20990 array.push( parameters.specularColorMapUv ); 20991 array.push( parameters.specularIntensityMapUv ); 20992 array.push( parameters.transmissionMapUv ); 20993 array.push( parameters.thicknessMapUv ); 20994 array.push( parameters.combine ); 20995 array.push( parameters.fogExp2 ); 20996 array.push( parameters.sizeAttenuation ); 20997 array.push( parameters.morphTargetsCount ); 20998 array.push( parameters.morphAttributeCount ); 20999 array.push( parameters.numDirLights ); 21000 array.push( parameters.numPointLights ); 21001 array.push( parameters.numSpotLights ); 21002 array.push( parameters.numSpotLightMaps ); 21003 array.push( parameters.numHemiLights ); 21004 array.push( parameters.numRectAreaLights ); 21005 array.push( parameters.numDirLightShadows ); 21006 array.push( parameters.numPointLightShadows ); 21007 array.push( parameters.numSpotLightShadows ); 21008 array.push( parameters.numSpotLightShadowsWithMaps ); 21009 array.push( parameters.numLightProbes ); 21010 array.push( parameters.shadowMapType ); 21011 array.push( parameters.toneMapping ); 21012 array.push( parameters.numClippingPlanes ); 21013 array.push( parameters.numClipIntersection ); 21014 array.push( parameters.depthPacking ); 21015 21016 } 21017 21018 function getProgramCacheKeyBooleans( array, parameters ) { 21019 21020 _programLayers.disableAll(); 21021 21022 if ( parameters.isWebGL2 ) 21023 _programLayers.enable( 0 ); 21024 if ( parameters.supportsVertexTextures ) 21025 _programLayers.enable( 1 ); 21026 if ( parameters.instancing ) 21027 _programLayers.enable( 2 ); 21028 if ( parameters.instancingColor ) 21029 _programLayers.enable( 3 ); 21030 if ( parameters.matcap ) 21031 _programLayers.enable( 4 ); 21032 if ( parameters.envMap ) 21033 _programLayers.enable( 5 ); 21034 if ( parameters.normalMapObjectSpace ) 21035 _programLayers.enable( 6 ); 21036 if ( parameters.normalMapTangentSpace ) 21037 _programLayers.enable( 7 ); 21038 if ( parameters.clearcoat ) 21039 _programLayers.enable( 8 ); 21040 if ( parameters.iridescence ) 21041 _programLayers.enable( 9 ); 21042 if ( parameters.alphaTest ) 21043 _programLayers.enable( 10 ); 21044 if ( parameters.vertexColors ) 21045 _programLayers.enable( 11 ); 21046 if ( parameters.vertexAlphas ) 21047 _programLayers.enable( 12 ); 21048 if ( parameters.vertexUv1s ) 21049 _programLayers.enable( 13 ); 21050 if ( parameters.vertexUv2s ) 21051 _programLayers.enable( 14 ); 21052 if ( parameters.vertexUv3s ) 21053 _programLayers.enable( 15 ); 21054 if ( parameters.vertexTangents ) 21055 _programLayers.enable( 16 ); 21056 if ( parameters.anisotropy ) 21057 _programLayers.enable( 17 ); 21058 if ( parameters.alphaHash ) 21059 _programLayers.enable( 18 ); 21060 if ( parameters.batching ) 21061 _programLayers.enable( 19 ); 21062 21063 array.push( _programLayers.mask ); 21064 _programLayers.disableAll(); 21065 21066 if ( parameters.fog ) 21067 _programLayers.enable( 0 ); 21068 if ( parameters.useFog ) 21069 _programLayers.enable( 1 ); 21070 if ( parameters.flatShading ) 21071 _programLayers.enable( 2 ); 21072 if ( parameters.logarithmicDepthBuffer ) 21073 _programLayers.enable( 3 ); 21074 if ( parameters.skinning ) 21075 _programLayers.enable( 4 ); 21076 if ( parameters.morphTargets ) 21077 _programLayers.enable( 5 ); 21078 if ( parameters.morphNormals ) 21079 _programLayers.enable( 6 ); 21080 if ( parameters.morphColors ) 21081 _programLayers.enable( 7 ); 21082 if ( parameters.premultipliedAlpha ) 21083 _programLayers.enable( 8 ); 21084 if ( parameters.shadowMapEnabled ) 21085 _programLayers.enable( 9 ); 21086 if ( parameters.useLegacyLights ) 21087 _programLayers.enable( 10 ); 21088 if ( parameters.doubleSided ) 21089 _programLayers.enable( 11 ); 21090 if ( parameters.flipSided ) 21091 _programLayers.enable( 12 ); 21092 if ( parameters.useDepthPacking ) 21093 _programLayers.enable( 13 ); 21094 if ( parameters.dithering ) 21095 _programLayers.enable( 14 ); 21096 if ( parameters.transmission ) 21097 _programLayers.enable( 15 ); 21098 if ( parameters.sheen ) 21099 _programLayers.enable( 16 ); 21100 if ( parameters.opaque ) 21101 _programLayers.enable( 17 ); 21102 if ( parameters.pointsUvs ) 21103 _programLayers.enable( 18 ); 21104 if ( parameters.decodeVideoTexture ) 21105 _programLayers.enable( 19 ); 21106 21107 array.push( _programLayers.mask ); 21108 21109 } 21110 21111 function getUniforms( material ) { 21112 21113 const shaderID = shaderIDs[ material.type ]; 21114 let uniforms; 21115 21116 if ( shaderID ) { 21117 21118 const shader = ShaderLib[ shaderID ]; 21119 uniforms = UniformsUtils.clone( shader.uniforms ); 21120 21121 } else { 21122 21123 uniforms = material.uniforms; 21124 21125 } 21126 21127 return uniforms; 21128 21129 } 21130 21131 function acquireProgram( parameters, cacheKey ) { 21132 21133 let program; 21134 21135 // Check if code has been already compiled 21136 for ( let p = 0, pl = programs.length; p < pl; p ++ ) { 21137 21138 const preexistingProgram = programs[ p ]; 21139 21140 if ( preexistingProgram.cacheKey === cacheKey ) { 21141 21142 program = preexistingProgram; 21143 ++ program.usedTimes; 21144 21145 break; 21146 21147 } 21148 21149 } 21150 21151 if ( program === undefined ) { 21152 21153 program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates ); 21154 programs.push( program ); 21155 21156 } 21157 21158 return program; 21159 21160 } 21161 21162 function releaseProgram( program ) { 21163 21164 if ( -- program.usedTimes === 0 ) { 21165 21166 // Remove from unordered set 21167 const i = programs.indexOf( program ); 21168 programs[ i ] = programs[ programs.length - 1 ]; 21169 programs.pop(); 21170 21171 // Free WebGL resources 21172 program.destroy(); 21173 21174 } 21175 21176 } 21177 21178 function releaseShaderCache( material ) { 21179 21180 _customShaders.remove( material ); 21181 21182 } 21183 21184 function dispose() { 21185 21186 _customShaders.dispose(); 21187 21188 } 21189 21190 return { 21191 getParameters: getParameters, 21192 getProgramCacheKey: getProgramCacheKey, 21193 getUniforms: getUniforms, 21194 acquireProgram: acquireProgram, 21195 releaseProgram: releaseProgram, 21196 releaseShaderCache: releaseShaderCache, 21197 // Exposed for resource monitoring & error feedback via renderer.info: 21198 programs: programs,
vendor: 4,538 bytes, lines 21199-21480
21199 dispose: dispose 21200 }; 21201 21202} 21203 21204function WebGLProperties() { 21205 21206 let properties = new WeakMap(); 21207 21208 function get( object ) { 21209 21210 let map = properties.get( object ); 21211 21212 if ( map === undefined ) { 21213 21214 map = {}; 21215 properties.set( object, map ); 21216 21217 } 21218 21219 return map; 21220 21221 } 21222 21223 function remove( object ) { 21224 21225 properties.delete( object ); 21226 21227 } 21228 21229 function update( object, key, value ) { 21230 21231 properties.get( object )[ key ] = value; 21232 21233 } 21234 21235 function dispose() { 21236 21237 properties = new WeakMap(); 21238 21239 } 21240 21241 return { 21242 get: get, 21243 remove: remove, 21244 update: update, 21245 dispose: dispose 21246 }; 21247 21248} 21249 21250function painterSortStable( a, b ) { 21251 21252 if ( a.groupOrder !== b.groupOrder ) { 21253 21254 return a.groupOrder - b.groupOrder; 21255 21256 } else if ( a.renderOrder !== b.renderOrder ) { 21257 21258 return a.renderOrder - b.renderOrder; 21259 21260 } else if ( a.material.id !== b.material.id ) { 21261 21262 return a.material.id - b.material.id; 21263 21264 } else if ( a.z !== b.z ) { 21265 21266 return a.z - b.z; 21267 21268 } else { 21269 21270 return a.id - b.id; 21271 21272 } 21273 21274} 21275 21276function reversePainterSortStable( a, b ) { 21277 21278 if ( a.groupOrder !== b.groupOrder ) { 21279 21280 return a.groupOrder - b.groupOrder; 21281 21282 } else if ( a.renderOrder !== b.renderOrder ) { 21283 21284 return a.renderOrder - b.renderOrder; 21285 21286 } else if ( a.z !== b.z ) { 21287 21288 return b.z - a.z; 21289 21290 } else { 21291 21292 return a.id - b.id; 21293 21294 } 21295 21296} 21297 21298 21299function WebGLRenderList() { 21300 21301 const renderItems = []; 21302 let renderItemsIndex = 0; 21303 21304 const opaque = []; 21305 const transmissive = []; 21306 const transparent = []; 21307 21308 function init() { 21309 21310 renderItemsIndex = 0; 21311 21312 opaque.length = 0; 21313 transmissive.length = 0; 21314 transparent.length = 0; 21315 21316 } 21317 21318 function getNextRenderItem( object, geometry, material, groupOrder, z, group ) { 21319 21320 let renderItem = renderItems[ renderItemsIndex ]; 21321 21322 if ( renderItem === undefined ) { 21323 21324 renderItem = { 21325 id: object.id, 21326 object: object, 21327 geometry: geometry, 21328 material: material, 21329 groupOrder: groupOrder, 21330 renderOrder: object.renderOrder, 21331 z: z, 21332 group: group 21333 }; 21334 21335 renderItems[ renderItemsIndex ] = renderItem; 21336 21337 } else { 21338 21339 renderItem.id = object.id; 21340 renderItem.object = object; 21341 renderItem.geometry = geometry; 21342 renderItem.material = material; 21343 renderItem.groupOrder = groupOrder; 21344 renderItem.renderOrder = object.renderOrder; 21345 renderItem.z = z; 21346 renderItem.group = group; 21347 21348 } 21349 21350 renderItemsIndex ++; 21351 21352 return renderItem; 21353 21354 } 21355 21356 function push( object, geometry, material, groupOrder, z, group ) { 21357 21358 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); 21359 21360 if ( material.transmission > 0.0 ) { 21361 21362 transmissive.push( renderItem ); 21363 21364 } else if ( material.transparent === true ) { 21365 21366 transparent.push( renderItem ); 21367 21368 } else { 21369 21370 opaque.push( renderItem ); 21371 21372 } 21373 21374 } 21375 21376 function unshift( object, geometry, material, groupOrder, z, group ) { 21377 21378 const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group ); 21379 21380 if ( material.transmission > 0.0 ) { 21381 21382 transmissive.unshift( renderItem ); 21383 21384 } else if ( material.transparent === true ) { 21385 21386 transparent.unshift( renderItem ); 21387 21388 } else { 21389 21390 opaque.unshift( renderItem ); 21391 21392 } 21393 21394 } 21395 21396 function sort( customOpaqueSort, customTransparentSort ) { 21397 21398 if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable ); 21399 if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable ); 21400 if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable ); 21401 21402 } 21403 21404 function finish() { 21405 21406 // Clear references from inactive renderItems in the list 21407 21408 for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) { 21409 21410 const renderItem = renderItems[ i ]; 21411 21412 if ( renderItem.id === null ) break; 21413 21414 renderItem.id = null; 21415 renderItem.object = null; 21416 renderItem.geometry = null; 21417 renderItem.material = null; 21418 renderItem.group = null; 21419 21420 } 21421 21422 } 21423 21424 return { 21425 21426 opaque: opaque, 21427 transmissive: transmissive, 21428 transparent: transparent, 21429 21430 init: init, 21431 push: push, 21432 unshift: unshift, 21433 finish: finish, 21434 21435 sort: sort 21436 }; 21437 21438} 21439 21440function WebGLRenderLists() { 21441 21442 let lists = new WeakMap(); 21443 21444 function get( scene, renderCallDepth ) { 21445 21446 const listArray = lists.get( scene ); 21447 let list; 21448 21449 if ( listArray === undefined ) { 21450 21451 list = new WebGLRenderList(); 21452 lists.set( scene, [ list ] ); 21453 21454 } else { 21455 21456 if ( renderCallDepth >= listArray.length ) { 21457 21458 list = new WebGLRenderList(); 21459 listArray.push( list ); 21460 21461 } else { 21462 21463 list = listArray[ renderCallDepth ]; 21464 21465 } 21466 21467 } 21468 21469 return list; 21470 21471 } 21472 21473 function dispose() { 21474 21475 lists = new WeakMap(); 21476 21477 } 21478 21479 return { 21480 get: get,
vendor: 2,723 bytes, lines 21481-21654
21481 dispose: dispose 21482 }; 21483 21484} 21485 21486function UniformsCache() { 21487 21488 const lights = {}; 21489 21490 return { 21491 21492 get: function ( light ) { 21493 21494 if ( lights[ light.id ] !== undefined ) { 21495 21496 return lights[ light.id ]; 21497 21498 } 21499 21500 let uniforms; 21501 21502 switch ( light.type ) { 21503 21504 case 'DirectionalLight': 21505 uniforms = { 21506 direction: new Vector3(), 21507 color: new Color() 21508 }; 21509 break; 21510 21511 case 'SpotLight': 21512 uniforms = { 21513 position: new Vector3(), 21514 direction: new Vector3(), 21515 color: new Color(), 21516 distance: 0, 21517 coneCos: 0, 21518 penumbraCos: 0, 21519 decay: 0 21520 }; 21521 break; 21522 21523 case 'PointLight': 21524 uniforms = { 21525 position: new Vector3(), 21526 color: new Color(), 21527 distance: 0, 21528 decay: 0 21529 }; 21530 break; 21531 21532 case 'HemisphereLight': 21533 uniforms = { 21534 direction: new Vector3(), 21535 skyColor: new Color(), 21536 groundColor: new Color() 21537 }; 21538 break; 21539 21540 case 'RectAreaLight': 21541 uniforms = { 21542 color: new Color(), 21543 position: new Vector3(), 21544 halfWidth: new Vector3(), 21545 halfHeight: new Vector3() 21546 }; 21547 break; 21548 21549 } 21550 21551 lights[ light.id ] = uniforms; 21552 21553 return uniforms; 21554 21555 } 21556 21557 }; 21558 21559} 21560 21561function ShadowUniformsCache() { 21562 21563 const lights = {}; 21564 21565 return { 21566 21567 get: function ( light ) { 21568 21569 if ( lights[ light.id ] !== undefined ) { 21570 21571 return lights[ light.id ]; 21572 21573 } 21574 21575 let uniforms; 21576 21577 switch ( light.type ) { 21578 21579 case 'DirectionalLight': 21580 uniforms = { 21581 shadowBias: 0, 21582 shadowNormalBias: 0, 21583 shadowRadius: 1, 21584 shadowMapSize: new Vector2() 21585 }; 21586 break; 21587 21588 case 'SpotLight': 21589 uniforms = { 21590 shadowBias: 0, 21591 shadowNormalBias: 0, 21592 shadowRadius: 1, 21593 shadowMapSize: new Vector2() 21594 }; 21595 break; 21596 21597 case 'PointLight': 21598 uniforms = { 21599 shadowBias: 0, 21600 shadowNormalBias: 0, 21601 shadowRadius: 1, 21602 shadowMapSize: new Vector2(), 21603 shadowCameraNear: 1, 21604 shadowCameraFar: 1000 21605 }; 21606 break; 21607 21608 // TODO (abelnation): set RectAreaLight shadow uniforms 21609 21610 } 21611 21612 lights[ light.id ] = uniforms; 21613 21614 return uniforms; 21615 21616 } 21617 21618 }; 21619 21620} 21621 21622 21623 21624let nextVersion = 0; 21625 21626function shadowCastingAndTexturingLightsFirst( lightA, lightB ) { 21627 21628 return ( lightB.castShadow ? 2 : 0 ) - ( lightA.castShadow ? 2 : 0 ) + ( lightB.map ? 1 : 0 ) - ( lightA.map ? 1 : 0 ); 21629 21630} 21631 21632function WebGLLights( extensions, capabilities ) { 21633 21634 const cache = new UniformsCache(); 21635 21636 const shadowCache = ShadowUniformsCache(); 21637 21638 const state = { 21639 21640 version: 0, 21641 21642 hash: { 21643 directionalLength: - 1, 21644 pointLength: - 1, 21645 spotLength: - 1, 21646 rectAreaLength: - 1, 21647 hemiLength: - 1, 21648 21649 numDirectionalShadows: - 1, 21650 numPointShadows: - 1, 21651 numSpotShadows: - 1, 21652 numSpotMaps: - 1, 21653 21654 numLightProbes: -
vendor: 16,167 bytes, lines 21654-22305
216541 21655 }, 21656 21657 ambient: [ 0, 0, 0 ], 21658 probe: [], 21659 directional: [], 21660 directionalShadow: [], 21661 directionalShadowMap: [], 21662 directionalShadowMatrix: [], 21663 spot: [], 21664 spotLightMap: [], 21665 spotShadow: [], 21666 spotShadowMap: [], 21667 spotLightMatrix: [], 21668 rectArea: [], 21669 rectAreaLTC1: null, 21670 rectAreaLTC2: null, 21671 point: [], 21672 pointShadow: [], 21673 pointShadowMap: [], 21674 pointShadowMatrix: [], 21675 hemi: [], 21676 numSpotLightShadowsWithMaps: 0, 21677 numLightProbes: 0 21678 21679 }; 21680 21681 for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() ); 21682 21683 const vector3 = new Vector3(); 21684 const matrix4 = new Matrix4(); 21685 const matrix42 = new Matrix4(); 21686 21687 function setup( lights, useLegacyLights ) { 21688 21689 let r = 0, g = 0, b = 0; 21690 21691 for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 ); 21692 21693 let directionalLength = 0; 21694 let pointLength = 0; 21695 let spotLength = 0; 21696 let rectAreaLength = 0; 21697 let hemiLength = 0; 21698 21699 let numDirectionalShadows = 0; 21700 let numPointShadows = 0; 21701 let numSpotShadows = 0; 21702 let numSpotMaps = 0; 21703 let numSpotShadowsWithMaps = 0; 21704 21705 let numLightProbes = 0; 21706 21707 // ordering : [shadow casting + map texturing, map texturing, shadow casting, none ] 21708 lights.sort( shadowCastingAndTexturingLightsFirst ); 21709 21710 // artist-friendly light intensity scaling factor 21711 const scaleFactor = ( useLegacyLights === true ) ? Math.PI : 1; 21712 21713 for ( let i = 0, l = lights.length; i < l; i ++ ) { 21714 21715 const light = lights[ i ]; 21716 21717 const color = light.color; 21718 const intensity = light.intensity; 21719 const distance = light.distance; 21720 21721 const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; 21722 21723 if ( light.isAmbientLight ) { 21724 21725 r += color.r * intensity * scaleFactor; 21726 g += color.g * intensity * scaleFactor; 21727 b += color.b * intensity * scaleFactor; 21728 21729 } else if ( light.isLightProbe ) { 21730 21731 for ( let j = 0; j < 9; j ++ ) { 21732 21733 state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity ); 21734 21735 } 21736 21737 numLightProbes ++; 21738 21739 } else if ( light.isDirectionalLight ) { 21740 21741 const uniforms = cache.get( light ); 21742 21743 uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor ); 21744 21745 if ( light.castShadow ) { 21746 21747 const shadow = light.shadow; 21748 21749 const shadowUniforms = shadowCache.get( light ); 21750 21751 shadowUniforms.shadowBias = shadow.bias; 21752 shadowUniforms.shadowNormalBias = shadow.normalBias; 21753 shadowUniforms.shadowRadius = shadow.radius; 21754 shadowUniforms.shadowMapSize = shadow.mapSize; 21755 21756 state.directionalShadow[ directionalLength ] = shadowUniforms; 21757 state.directionalShadowMap[ directionalLength ] = shadowMap; 21758 state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; 21759 21760 numDirectionalShadows ++; 21761 21762 } 21763 21764 state.directional[ directionalLength ] = uniforms; 21765 21766 directionalLength ++; 21767 21768 } else if ( light.isSpotLight ) { 21769 21770 const uniforms = cache.get( light ); 21771 21772 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 21773 21774 uniforms.color.copy( color ).multiplyScalar( intensity * scaleFactor ); 21775 uniforms.distance = distance; 21776 21777 uniforms.coneCos = Math.cos( light.angle ); 21778 uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); 21779 uniforms.decay = light.decay; 21780 21781 state.spot[ spotLength ] = uniforms; 21782 21783 const shadow = light.shadow; 21784 21785 if ( light.map ) { 21786 21787 state.spotLightMap[ numSpotMaps ] = light.map; 21788 numSpotMaps ++; 21789 21790 // make sure the lightMatrix is up to date 21791 // TODO : do it if required only 21792 shadow.updateMatrices( light ); 21793 21794 if ( light.castShadow ) numSpotShadowsWithMaps ++; 21795 21796 } 21797 21798 state.spotLightMatrix[ spotLength ] = shadow.matrix; 21799 21800 if ( light.castShadow ) { 21801 21802 const shadowUniforms = shadowCache.get( light ); 21803 21804 shadowUniforms.shadowBias = shadow.bias; 21805 shadowUniforms.shadowNormalBias = shadow.normalBias; 21806 shadowUniforms.shadowRadius = shadow.radius; 21807 shadowUniforms.shadowMapSize = shadow.mapSize; 21808 21809 state.spotShadow[ spotLength ] = shadowUniforms; 21810 state.spotShadowMap[ spotLength ] = shadowMap; 21811 21812 numSpotShadows ++; 21813 21814 } 21815 21816 spotLength ++; 21817 21818 } else if ( light.isRectAreaLight ) { 21819 21820 const uniforms = cache.get( light ); 21821 21822 uniforms.color.copy( color ).multiplyScalar( intensity ); 21823 21824 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); 21825 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); 21826 21827 state.rectArea[ rectAreaLength ] = uniforms; 21828 21829 rectAreaLength ++; 21830 21831 } else if ( light.isPointLight ) { 21832 21833 const uniforms = cache.get( light ); 21834 21835 uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor ); 21836 uniforms.distance = light.distance; 21837 uniforms.decay = light.decay; 21838 21839 if ( light.castShadow ) { 21840 21841 const shadow = light.shadow; 21842 21843 const shadowUniforms = shadowCache.get( light ); 21844 21845 shadowUniforms.shadowBias = shadow.bias; 21846 shadowUniforms.shadowNormalBias = shadow.normalBias; 21847 shadowUniforms.shadowRadius = shadow.radius; 21848 shadowUniforms.shadowMapSize = shadow.mapSize; 21849 shadowUniforms.shadowCameraNear = shadow.camera.near; 21850 shadowUniforms.shadowCameraFar = shadow.camera.far; 21851 21852 state.pointShadow[ pointLength ] = shadowUniforms; 21853 state.pointShadowMap[ pointLength ] = shadowMap; 21854 state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; 21855 21856 numPointShadows ++; 21857 21858 } 21859 21860 state.point[ pointLength ] = uniforms; 21861 21862 pointLength ++; 21863 21864 } else if ( light.isHemisphereLight ) { 21865 21866 const uniforms = cache.get( light ); 21867 21868 uniforms.skyColor.copy( light.color ).multiplyScalar( intensity * scaleFactor ); 21869 uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity * scaleFactor ); 21870 21871 state.hemi[ hemiLength ] = uniforms; 21872 21873 hemiLength ++; 21874 21875 } 21876 21877 } 21878 21879 if ( rectAreaLength > 0 ) { 21880 21881 if ( capabilities.isWebGL2 ) { 21882 21883 // WebGL 2 21884 21885 if ( extensions.has( 'OES_texture_float_linear' ) === true ) { 21886 21887 state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1; 21888 state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2; 21889 21890 } else { 21891 21892 state.rectAreaLTC1 = UniformsLib.LTC_HALF_1; 21893 state.rectAreaLTC2 = UniformsLib.LTC_HALF_2; 21894 21895 } 21896 21897 } else { 21898 21899 // WebGL 1 21900 21901 if ( extensions.has( 'OES_texture_float_linear' ) === true ) { 21902 21903 state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1; 21904 state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2; 21905 21906 } else if ( extensions.has( 'OES_texture_half_float_linear' ) === true ) { 21907 21908 state.rectAreaLTC1 = UniformsLib.LTC_HALF_1; 21909 state.rectAreaLTC2 = UniformsLib.LTC_HALF_2; 21910 21911 } else { 21912 21913 console.error( 'THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.' ); 21914 21915 } 21916 21917 } 21918 21919 } 21920 21921 state.ambient[ 0 ] = r; 21922 state.ambient[ 1 ] = g; 21923 state.ambient[ 2 ] = b; 21924 21925 const hash = state.hash; 21926 21927 if ( hash.directionalLength !== directionalLength || 21928 hash.pointLength !== pointLength || 21929 hash.spotLength !== spotLength || 21930 hash.rectAreaLength !== rectAreaLength || 21931 hash.hemiLength !== hemiLength || 21932 hash.numDirectionalShadows !== numDirectionalShadows || 21933 hash.numPointShadows !== numPointShadows || 21934 hash.numSpotShadows !== numSpotShadows || 21935 hash.numSpotMaps !== numSpotMaps || 21936 hash.numLightProbes !== numLightProbes ) { 21937 21938 state.directional.length = directionalLength; 21939 state.spot.length = spotLength; 21940 state.rectArea.length = rectAreaLength; 21941 state.point.length = pointLength; 21942 state.hemi.length = hemiLength; 21943 21944 state.directionalShadow.length = numDirectionalShadows; 21945 state.directionalShadowMap.length = numDirectionalShadows; 21946 state.pointShadow.length = numPointShadows; 21947 state.pointShadowMap.length = numPointShadows; 21948 state.spotShadow.length = numSpotShadows; 21949 state.spotShadowMap.length = numSpotShadows; 21950 state.directionalShadowMatrix.length = numDirectionalShadows; 21951 state.pointShadowMatrix.length = numPointShadows; 21952 state.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps; 21953 state.spotLightMap.length = numSpotMaps; 21954 state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps; 21955 state.numLightProbes = numLightProbes; 21956 21957 hash.directionalLength = directionalLength; 21958 hash.pointLength = pointLength; 21959 hash.spotLength = spotLength; 21960 hash.rectAreaLength = rectAreaLength; 21961 hash.hemiLength = hemiLength; 21962 21963 hash.numDirectionalShadows = numDirectionalShadows; 21964 hash.numPointShadows = numPointShadows; 21965 hash.numSpotShadows = numSpotShadows; 21966 hash.numSpotMaps = numSpotMaps; 21967 21968 hash.numLightProbes = numLightProbes; 21969 21970 state.version = nextVersion ++; 21971 21972 } 21973 21974 } 21975 21976 function setupView( lights, camera ) { 21977 21978 let directionalLength = 0; 21979 let pointLength = 0; 21980 let spotLength = 0; 21981 let rectAreaLength = 0; 21982 let hemiLength = 0; 21983 21984 const viewMatrix = camera.matrixWorldInverse; 21985 21986 for ( let i = 0, l = lights.length; i < l; i ++ ) { 21987 21988 const light = lights[ i ]; 21989 21990 if ( light.isDirectionalLight ) { 21991 21992 const uniforms = state.directional[ directionalLength ]; 21993 21994 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 21995 vector3.setFromMatrixPosition( light.target.matrixWorld ); 21996 uniforms.direction.sub( vector3 ); 21997 uniforms.direction.transformDirection( viewMatrix ); 21998 21999 directionalLength ++; 22000 22001 } else if ( light.isSpotLight ) { 22002 22003 const uniforms = state.spot[ spotLength ]; 22004 22005 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 22006 uniforms.position.applyMatrix4( viewMatrix ); 22007 22008 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 22009 vector3.setFromMatrixPosition( light.target.matrixWorld ); 22010 uniforms.direction.sub( vector3 ); 22011 uniforms.direction.transformDirection( viewMatrix ); 22012 22013 spotLength ++; 22014 22015 } else if ( light.isRectAreaLight ) { 22016 22017 const uniforms = state.rectArea[ rectAreaLength ]; 22018 22019 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 22020 uniforms.position.applyMatrix4( viewMatrix ); 22021 22022 // extract local rotation of light to derive width/height half vectors 22023 matrix42.identity(); 22024 matrix4.copy( light.matrixWorld ); 22025 matrix4.premultiply( viewMatrix ); 22026 matrix42.extractRotation( matrix4 ); 22027 22028 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); 22029 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); 22030 22031 uniforms.halfWidth.applyMatrix4( matrix42 ); 22032 uniforms.halfHeight.applyMatrix4( matrix42 ); 22033 22034 rectAreaLength ++; 22035 22036 } else if ( light.isPointLight ) { 22037 22038 const uniforms = state.point[ pointLength ]; 22039 22040 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 22041 uniforms.position.applyMatrix4( viewMatrix ); 22042 22043 pointLength ++; 22044 22045 } else if ( light.isHemisphereLight ) { 22046 22047 const uniforms = state.hemi[ hemiLength ]; 22048 22049 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 22050 uniforms.direction.transformDirection( viewMatrix ); 22051 22052 hemiLength ++; 22053 22054 } 22055 22056 } 22057 22058 } 22059 22060 return { 22061 setup: setup, 22062 setupView: setupView, 22063 state: state 22064 }; 22065 22066} 22067 22068function WebGLRenderState( extensions, capabilities ) { 22069 22070 const lights = new WebGLLights( extensions, capabilities ); 22071 22072 const lightsArray = []; 22073 const shadowsArray = []; 22074 22075 function init() { 22076 22077 lightsArray.length = 0; 22078 shadowsArray.length = 0; 22079 22080 } 22081 22082 function pushLight( light ) { 22083 22084 lightsArray.push( light ); 22085 22086 } 22087 22088 function pushShadow( shadowLight ) { 22089 22090 shadowsArray.push( shadowLight ); 22091 22092 } 22093 22094 function setupLights( useLegacyLights ) { 22095 22096 lights.setup( lightsArray, useLegacyLights ); 22097 22098 } 22099 22100 function setupLightsView( camera ) { 22101 22102 lights.setupView( lightsArray, camera ); 22103 22104 } 22105 22106 const state = { 22107 lightsArray: lightsArray, 22108 shadowsArray: shadowsArray, 22109 22110 lights: lights 22111 }; 22112 22113 return { 22114 init: init, 22115 state: state, 22116 setupLights: setupLights, 22117 setupLightsView: setupLightsView, 22118 22119 pushLight: pushLight, 22120 pushShadow: pushShadow 22121 }; 22122 22123} 22124 22125function WebGLRenderStates( extensions, capabilities ) { 22126 22127 let renderStates = new WeakMap(); 22128 22129 function get( scene, renderCallDepth = 0 ) { 22130 22131 const renderStateArray = renderStates.get( scene ); 22132 let renderState; 22133 22134 if ( renderStateArray === undefined ) { 22135 22136 renderState = new WebGLRenderState( extensions, capabilities ); 22137 renderStates.set( scene, [ renderState ] ); 22138 22139 } else { 22140 22141 if ( renderCallDepth >= renderStateArray.length ) { 22142 22143 renderState = new WebGLRenderState( extensions, capabilities ); 22144 renderStateArray.push( renderState ); 22145 22146 } else { 22147 22148 renderState = renderStateArray[ renderCallDepth ]; 22149 22150 } 22151 22152 } 22153 22154 return renderState; 22155 22156 } 22157 22158 function dispose() { 22159 22160 renderStates = new WeakMap(); 22161 22162 } 22163 22164 return { 22165 get: get, 22166 dispose: dispose 22167 }; 22168 22169} 22170 22171class MeshDepthMaterial extends Material { 22172 22173 constructor( parameters ) { 22174 22175 super(); 22176 22177 this.isMeshDepthMaterial = true; 22178 22179 this.type = 'MeshDepthMaterial'; 22180 22181 this.depthPacking = BasicDepthPacking; 22182 22183 this.map = null; 22184 22185 this.alphaMap = null; 22186 22187 this.displacementMap = null; 22188 this.displacementScale = 1; 22189 this.displacementBias = 0; 22190 22191 this.wireframe = false; 22192 this.wireframeLinewidth = 1; 22193 22194 this.setValues( parameters ); 22195 22196 } 22197 22198 copy( source ) { 22199 22200 super.copy( source ); 22201 22202 this.depthPacking = source.depthPacking; 22203 22204 this.map = source.map; 22205 22206 this.alphaMap = source.alphaMap; 22207 22208 this.displacementMap = source.displacementMap; 22209 this.displacementScale = source.displacementScale; 22210 this.displacementBias = source.displacementBias; 22211 22212 this.wireframe = source.wireframe; 22213 this.wireframeLinewidth = source.wireframeLinewidth; 22214 22215 return this; 22216 22217 } 22218 22219} 22220 22221class MeshDistanceMaterial extends Material { 22222 22223 constructor( parameters ) { 22224 22225 super(); 22226 22227 this.isMeshDistanceMaterial = true; 22228 22229 this.type = 'MeshDistanceMaterial'; 22230 22231 this.map = null; 22232 22233 this.alphaMap = null; 22234 22235 this.displacementMap = null; 22236 this.displacementScale = 1; 22237 this.displacementBias = 0; 22238 22239 this.setValues( parameters ); 22240 22241 } 22242 22243 copy( source ) { 22244 22245 super.copy( source ); 22246 22247 this.map = source.map; 22248 22249 this.alphaMap = source.alphaMap; 22250 22251 this.displacementMap = source.displacementMap; 22252 this.displacementScale = source.displacementScale; 22253 this.displacementBias = source.displacementBias; 22254 22255 return this; 22256 22257 } 22258 22259} 22260 22261const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}"; 22262 22263const 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}"; 22264 22265function WebGLShadowMap( _renderer, _objects, _capabilities ) { 22266 22267 let _frustum = new Frustum(); 22268 22269 const _shadowMapSize = new Vector2(), 22270 _viewportSize = new Vector2(), 22271 22272 _viewport = new Vector4(), 22273 22274 _depthMaterial = new MeshDepthMaterial( { depthPacking: RGBADepthPacking } ), 22275 _distanceMaterial = new MeshDistanceMaterial(), 22276 22277 _materialCache = {}, 22278 22279 _maxTextureSize = _capabilities.maxTextureSize; 22280 22281 const shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide }; 22282 22283 const shadowMaterialVertical = new ShaderMaterial( { 22284 defines: { 22285 VSM_SAMPLES: 8 22286 }, 22287 uniforms: { 22288 shadow_pass: { value: null }, 22289 resolution: { value: new Vector2() }, 22290 radius: { value: 4.0 } 22291 }, 22292 22293 vertexShader: vertex, 22294 fragmentShader: fragment 22295 22296 } ); 22297 22298 const shadowMaterialHorizontal = shadowMaterialVertical.clone(); 22299 shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1; 22300 22301 const fullScreenTri = new BufferGeometry(); 22302 fullScreenTri.setAttribute( 22303 'position', 22304 new BufferAttribute( 22305 new Float32Array( [ -
22305 1, - 1, 0.5, 3, - 1, 0.5, -
vendor: 10,677 bytes, lines 22305-22728
223051, 3, 0.5 ] ), 22306 3 22307 ) 22308 ); 22309 22310 const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical ); 22311 22312 const scope = this; 22313 22314 this.enabled = false; 22315 22316 this.autoUpdate = true; 22317 this.needsUpdate = false; 22318 22319 this.type = PCFShadowMap; 22320 let _previousType = this.type; 22321 22322 this.render = function ( lights, scene, camera ) { 22323 22324 if ( scope.enabled === false ) return; 22325 if ( scope.autoUpdate === false && scope.needsUpdate === false ) return; 22326 22327 if ( lights.length === 0 ) return; 22328 22329 const currentRenderTarget = _renderer.getRenderTarget(); 22330 const activeCubeFace = _renderer.getActiveCubeFace(); 22331 const activeMipmapLevel = _renderer.getActiveMipmapLevel(); 22332 22333 const _state = _renderer.state; 22334 22335 // Set GL state for depth map. 22336 _state.setBlending( NoBlending ); 22337 _state.buffers.color.setClear( 1, 1, 1, 1 ); 22338 _state.buffers.depth.setTest( true ); 22339 _state.setScissorTest( false ); 22340 22341 // check for shadow map type changes 22342 22343 const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap ); 22344 const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap ); 22345 22346 // render depth map 22347 22348 for ( let i = 0, il = lights.length; i < il; i ++ ) { 22349 22350 const light = lights[ i ]; 22351 const shadow = light.shadow; 22352 22353 if ( shadow === undefined ) { 22354 22355 console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); 22356 continue; 22357 22358 } 22359 22360 if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue; 22361 22362 _shadowMapSize.copy( shadow.mapSize ); 22363 22364 const shadowFrameExtents = shadow.getFrameExtents(); 22365 22366 _shadowMapSize.multiply( shadowFrameExtents ); 22367 22368 _viewportSize.copy( shadow.mapSize ); 22369 22370 if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) { 22371 22372 if ( _shadowMapSize.x > _maxTextureSize ) { 22373 22374 _viewportSize.x = Math.floor( _maxTextureSize / shadowFrameExtents.x ); 22375 _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x; 22376 shadow.mapSize.x = _viewportSize.x; 22377 22378 } 22379 22380 if ( _shadowMapSize.y > _maxTextureSize ) { 22381 22382 _viewportSize.y = Math.floor( _maxTextureSize / shadowFrameExtents.y ); 22383 _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y; 22384 shadow.mapSize.y = _viewportSize.y; 22385 22386 } 22387 22388 } 22389 22390 if ( shadow.map === null || toVSM === true || fromVSM === true ) { 22391 22392 const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {}; 22393 22394 if ( shadow.map !== null ) { 22395 22396 shadow.map.dispose(); 22397 22398 } 22399 22400 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); 22401 shadow.map.texture.name = light.name + '.shadowMap'; 22402 22403 shadow.camera.updateProjectionMatrix(); 22404 22405 } 22406 22407 _renderer.setRenderTarget( shadow.map ); 22408 _renderer.clear(); 22409 22410 const viewportCount = shadow.getViewportCount(); 22411 22412 for ( let vp = 0; vp < viewportCount; vp ++ ) { 22413 22414 const viewport = shadow.getViewport( vp ); 22415 22416 _viewport.set( 22417 _viewportSize.x * viewport.x, 22418 _viewportSize.y * viewport.y, 22419 _viewportSize.x * viewport.z, 22420 _viewportSize.y * viewport.w 22421 ); 22422 22423 _state.viewport( _viewport ); 22424 22425 shadow.updateMatrices( light, vp ); 22426 22427 _frustum = shadow.getFrustum(); 22428 22429 renderObject( scene, camera, shadow.camera, light, this.type ); 22430 22431 } 22432 22433 // do blur pass for VSM 22434 22435 if ( shadow.isPointLightShadow !== true && this.type === VSMShadowMap ) { 22436 22437 VSMPass( shadow, camera ); 22438 22439 } 22440 22441 shadow.needsUpdate = false; 22442 22443 } 22444 22445 _previousType = this.type; 22446 22447 scope.needsUpdate = false; 22448 22449 _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); 22450 22451 }; 22452 22453 function VSMPass( shadow, camera ) { 22454 22455 const geometry = _objects.update( fullScreenMesh ); 22456 22457 if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) { 22458 22459 shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples; 22460 shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples; 22461 22462 shadowMaterialVertical.needsUpdate = true; 22463 shadowMaterialHorizontal.needsUpdate = true; 22464 22465 } 22466 22467 if ( shadow.mapPass === null ) { 22468 22469 shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y ); 22470 22471 } 22472 22473 // vertical pass 22474 22475 shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture; 22476 shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize; 22477 shadowMaterialVertical.uniforms.radius.value = shadow.radius; 22478 _renderer.setRenderTarget( shadow.mapPass ); 22479 _renderer.clear(); 22480 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null ); 22481 22482 // horizontal pass 22483 22484 shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture; 22485 shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize; 22486 shadowMaterialHorizontal.uniforms.radius.value = shadow.radius; 22487 _renderer.setRenderTarget( shadow.map ); 22488 _renderer.clear(); 22489 _renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null ); 22490 22491 } 22492 22493 function getDepthMaterial( object, material, light, type ) { 22494 22495 let result = null; 22496 22497 const customMaterial = ( light.isPointLight === true ) ? object.customDistanceMaterial : object.customDepthMaterial; 22498 22499 if ( customMaterial !== undefined ) { 22500 22501 result = customMaterial; 22502 22503 } else { 22504 22505 result = ( light.isPointLight === true ) ? _distanceMaterial : _depthMaterial; 22506 22507 if ( ( _renderer.localClippingEnabled && material.clipShadows === true && Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) || 22508 ( material.displacementMap && material.displacementScale !== 0 ) || 22509 ( material.alphaMap && material.alphaTest > 0 ) || 22510 ( material.map && material.alphaTest > 0 ) ) { 22511 22512 // in this case we need a unique material instance reflecting the 22513 // appropriate state 22514 22515 const keyA = result.uuid, keyB = material.uuid; 22516 22517 let materialsForVariant = _materialCache[ keyA ]; 22518 22519 if ( materialsForVariant === undefined ) { 22520 22521 materialsForVariant = {}; 22522 _materialCache[ keyA ] = materialsForVariant; 22523 22524 } 22525 22526 let cachedMaterial = materialsForVariant[ keyB ]; 22527 22528 if ( cachedMaterial === undefined ) { 22529 22530 cachedMaterial = result.clone(); 22531 materialsForVariant[ keyB ] = cachedMaterial; 22532 material.addEventListener( 'dispose', onMaterialDispose ); 22533 22534 } 22535 22536 result = cachedMaterial; 22537 22538 } 22539 22540 } 22541 22542 result.visible = material.visible; 22543 result.wireframe = material.wireframe; 22544 22545 if ( type === VSMShadowMap ) { 22546 22547 result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side; 22548 22549 } else { 22550 22551 result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ]; 22552 22553 } 22554 22555 result.alphaMap = material.alphaMap; 22556 result.alphaTest = material.alphaTest; 22557 result.map = material.map; 22558 22559 result.clipShadows = material.clipShadows; 22560 result.clippingPlanes = material.clippingPlanes; 22561 result.clipIntersection = material.clipIntersection; 22562 22563 result.displacementMap = material.displacementMap; 22564 result.displacementScale = material.displacementScale; 22565 result.displacementBias = material.displacementBias; 22566 22567 result.wireframeLinewidth = material.wireframeLinewidth; 22568 result.linewidth = material.linewidth; 22569 22570 if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) { 22571 22572 const materialProperties = _renderer.properties.get( result ); 22573 materialProperties.light = light; 22574 22575 } 22576 22577 return result; 22578 22579 } 22580 22581 function renderObject( object, camera, shadowCamera, light, type ) { 22582 22583 if ( object.visible === false ) return; 22584 22585 const visible = object.layers.test( camera.layers ); 22586 22587 if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { 22588 22589 if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { 22590 22591 object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); 22592 22593 const geometry = _objects.update( object ); 22594 const material = object.material; 22595 22596 if ( Array.isArray( material ) ) { 22597 22598 const groups = geometry.groups; 22599 22600 for ( let k = 0, kl = groups.length; k < kl; k ++ ) { 22601 22602 const group = groups[ k ]; 22603 const groupMaterial = material[ group.materialIndex ]; 22604 22605 if ( groupMaterial && groupMaterial.visible ) { 22606 22607 const depthMaterial = getDepthMaterial( object, groupMaterial, light, type ); 22608 22609 object.onBeforeShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); 22610 22611 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); 22612 22613 object.onAfterShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); 22614 22615 } 22616 22617 } 22618 22619 } else if ( material.visible ) { 22620 22621 const depthMaterial = getDepthMaterial( object, material, light, type ); 22622 22623 object.onBeforeShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); 22624 22625 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); 22626 22627 object.onAfterShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); 22628 22629 } 22630 22631 } 22632 22633 } 22634 22635 const children = object.children; 22636 22637 for ( let i = 0, l = children.length; i < l; i ++ ) { 22638 22639 renderObject( children[ i ], camera, shadowCamera, light, type ); 22640 22641 } 22642 22643 } 22644 22645 function onMaterialDispose( event ) { 22646 22647 const material = event.target; 22648 22649 material.removeEventListener( 'dispose', onMaterialDispose ); 22650 22651 // make sure to remove the unique distance/depth materials used for shadow map rendering 22652 22653 for ( const id in _materialCache ) { 22654 22655 const cache = _materialCache[ id ]; 22656 22657 const uuid = event.target.uuid; 22658 22659 if ( uuid in cache ) { 22660 22661 const shadowMaterial = cache[ uuid ]; 22662 shadowMaterial.dispose(); 22663 delete cache[ uuid ]; 22664 22665 } 22666 22667 } 22668 22669 } 22670 22671} 22672 22673function WebGLState( gl, extensions, capabilities ) { 22674 22675 const isWebGL2 = capabilities.isWebGL2; 22676 22677 function ColorBuffer() { 22678 22679 let locked = false; 22680 22681 const color = new Vector4(); 22682 let currentColorMask = null; 22683 const currentColorClear = new Vector4( 0, 0, 0, 0 ); 22684 22685 return { 22686 22687 setMask: function ( colorMask ) { 22688 22689 if ( currentColorMask !== colorMask && ! locked ) { 22690 22691 gl.colorMask( colorMask, colorMask, colorMask, colorMask ); 22692 currentColorMask = colorMask; 22693 22694 } 22695 22696 }, 22697 22698 setLocked: function ( lock ) { 22699 22700 locked = lock; 22701 22702 }, 22703 22704 setClear: function ( r, g, b, a, premultipliedAlpha ) { 22705 22706 if ( premultipliedAlpha === true ) { 22707 22708 r *= a; g *= a; b *= a; 22709 22710 } 22711 22712 color.set( r, g, b, a ); 22713 22714 if ( currentColorClear.equals( color ) === false ) { 22715 22716 gl.clearColor( r, g, b, a ); 22717 currentColorClear.copy( color ); 22718 22719 } 22720 22721 }, 22722 22723 reset: function () { 22724 22725 locked = false; 22726 22727 currentColorMask = null; 22728 currentColorClear.set( -
22728
vendor: 4,959 bytes, lines 22728-23015
227281, 0, 0, 0 ); // set to invalid state 22729 22730 } 22731 22732 }; 22733 22734 } 22735 22736 function DepthBuffer() { 22737 22738 let locked = false; 22739 22740 let currentDepthMask = null; 22741 let currentDepthFunc = null; 22742 let currentDepthClear = null; 22743 22744 return { 22745 22746 setTest: function ( depthTest ) { 22747 22748 if ( depthTest ) { 22749 22750 enable( gl.DEPTH_TEST ); 22751 22752 } else { 22753 22754 disable( gl.DEPTH_TEST ); 22755 22756 } 22757 22758 }, 22759 22760 setMask: function ( depthMask ) { 22761 22762 if ( currentDepthMask !== depthMask && ! locked ) { 22763 22764 gl.depthMask( depthMask ); 22765 currentDepthMask = depthMask; 22766 22767 } 22768 22769 }, 22770 22771 setFunc: function ( depthFunc ) { 22772 22773 if ( currentDepthFunc !== depthFunc ) { 22774 22775 switch ( depthFunc ) { 22776 22777 case NeverDepth: 22778 22779 gl.depthFunc( gl.NEVER ); 22780 break; 22781 22782 case AlwaysDepth: 22783 22784 gl.depthFunc( gl.ALWAYS ); 22785 break; 22786 22787 case LessDepth: 22788 22789 gl.depthFunc( gl.LESS ); 22790 break; 22791 22792 case LessEqualDepth: 22793 22794 gl.depthFunc( gl.LEQUAL ); 22795 break; 22796 22797 case EqualDepth: 22798 22799 gl.depthFunc( gl.EQUAL ); 22800 break; 22801 22802 case GreaterEqualDepth: 22803 22804 gl.depthFunc( gl.GEQUAL ); 22805 break; 22806 22807 case GreaterDepth: 22808 22809 gl.depthFunc( gl.GREATER ); 22810 break; 22811 22812 case NotEqualDepth: 22813 22814 gl.depthFunc( gl.NOTEQUAL ); 22815 break; 22816 22817 default: 22818 22819 gl.depthFunc( gl.LEQUAL ); 22820 22821 } 22822 22823 currentDepthFunc = depthFunc; 22824 22825 } 22826 22827 }, 22828 22829 setLocked: function ( lock ) { 22830 22831 locked = lock; 22832 22833 }, 22834 22835 setClear: function ( depth ) { 22836 22837 if ( currentDepthClear !== depth ) { 22838 22839 gl.clearDepth( depth ); 22840 currentDepthClear = depth; 22841 22842 } 22843 22844 }, 22845 22846 reset: function () { 22847 22848 locked = false; 22849 22850 currentDepthMask = null; 22851 currentDepthFunc = null; 22852 currentDepthClear = null; 22853 22854 } 22855 22856 }; 22857 22858 } 22859 22860 function StencilBuffer() { 22861 22862 let locked = false; 22863 22864 let currentStencilMask = null; 22865 let currentStencilFunc = null; 22866 let currentStencilRef = null; 22867 let currentStencilFuncMask = null; 22868 let currentStencilFail = null; 22869 let currentStencilZFail = null; 22870 let currentStencilZPass = null; 22871 let currentStencilClear = null; 22872 22873 return { 22874 22875 setTest: function ( stencilTest ) { 22876 22877 if ( ! locked ) { 22878 22879 if ( stencilTest ) { 22880 22881 enable( gl.STENCIL_TEST ); 22882 22883 } else { 22884 22885 disable( gl.STENCIL_TEST ); 22886 22887 } 22888 22889 } 22890 22891 }, 22892 22893 setMask: function ( stencilMask ) { 22894 22895 if ( currentStencilMask !== stencilMask && ! locked ) { 22896 22897 gl.stencilMask( stencilMask ); 22898 currentStencilMask = stencilMask; 22899 22900 } 22901 22902 }, 22903 22904 setFunc: function ( stencilFunc, stencilRef, stencilMask ) { 22905 22906 if ( currentStencilFunc !== stencilFunc || 22907 currentStencilRef !== stencilRef || 22908 currentStencilFuncMask !== stencilMask ) { 22909 22910 gl.stencilFunc( stencilFunc, stencilRef, stencilMask ); 22911 22912 currentStencilFunc = stencilFunc; 22913 currentStencilRef = stencilRef; 22914 currentStencilFuncMask = stencilMask; 22915 22916 } 22917 22918 }, 22919 22920 setOp: function ( stencilFail, stencilZFail, stencilZPass ) { 22921 22922 if ( currentStencilFail !== stencilFail || 22923 currentStencilZFail !== stencilZFail || 22924 currentStencilZPass !== stencilZPass ) { 22925 22926 gl.stencilOp( stencilFail, stencilZFail, stencilZPass ); 22927 22928 currentStencilFail = stencilFail; 22929 currentStencilZFail = stencilZFail; 22930 currentStencilZPass = stencilZPass; 22931 22932 } 22933 22934 }, 22935 22936 setLocked: function ( lock ) { 22937 22938 locked = lock; 22939 22940 }, 22941 22942 setClear: function ( stencil ) { 22943 22944 if ( currentStencilClear !== stencil ) { 22945 22946 gl.clearStencil( stencil ); 22947 currentStencilClear = stencil; 22948 22949 } 22950 22951 }, 22952 22953 reset: function () { 22954 22955 locked = false; 22956 22957 currentStencilMask = null; 22958 currentStencilFunc = null; 22959 currentStencilRef = null; 22960 currentStencilFuncMask = null; 22961 currentStencilFail = null; 22962 currentStencilZFail = null; 22963 currentStencilZPass = null; 22964 currentStencilClear = null; 22965 22966 } 22967 22968 }; 22969 22970 } 22971 22972 // 22973 22974 const colorBuffer = new ColorBuffer(); 22975 const depthBuffer = new DepthBuffer(); 22976 const stencilBuffer = new StencilBuffer(); 22977 22978 const uboBindings = new WeakMap(); 22979 const uboProgramMap = new WeakMap(); 22980 22981 let enabledCapabilities = {}; 22982 22983 let currentBoundFramebuffers = {}; 22984 let currentDrawbuffers = new WeakMap(); 22985 let defaultDrawbuffers = []; 22986 22987 let currentProgram = null; 22988 22989 let currentBlendingEnabled = false; 22990 let currentBlending = null; 22991 let currentBlendEquation = null; 22992 let currentBlendSrc = null; 22993 let currentBlendDst = null; 22994 let currentBlendEquationAlpha = null; 22995 let currentBlendSrcAlpha = null; 22996 let currentBlendDstAlpha = null; 22997 let currentBlendColor = new Color( 0, 0, 0 ); 22998 let currentBlendAlpha = 0; 22999 let currentPremultipledAlpha = false; 23000 23001 let currentFlipSided = null; 23002 let currentCullFace = null; 23003 23004 let currentLineWidth = null; 23005 23006 let currentPolygonOffsetFactor = null; 23007 let currentPolygonOffsetUnits = null; 23008 23009 const maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); 23010 23011 let lineWidthAvailable = false; 23012 let version = 0; 23013 const glVersion = gl.getParameter( gl.VERSION ); 23014 23015 if ( glVersion.indexOf( 'WebGL' ) !== -
vendor: 4,090 bytes, lines 23015-23214
23015 1 ) { 23016 23017 version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] ); 23018 lineWidthAvailable = ( version >= 1.0 ); 23019 23020 } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) { 23021 23022 version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] ); 23023 lineWidthAvailable = ( version >= 2.0 ); 23024 23025 } 23026 23027 let currentTextureSlot = null; 23028 let currentBoundTextures = {}; 23029 23030 const scissorParam = gl.getParameter( gl.SCISSOR_BOX ); 23031 const viewportParam = gl.getParameter( gl.VIEWPORT ); 23032 23033 const currentScissor = new Vector4().fromArray( scissorParam ); 23034 const currentViewport = new Vector4().fromArray( viewportParam ); 23035 23036 function createTexture( type, target, count, dimensions ) { 23037 23038 const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. 23039 const texture = gl.createTexture(); 23040 23041 gl.bindTexture( type, texture ); 23042 gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); 23043 gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); 23044 23045 for ( let i = 0; i < count; i ++ ) { 23046 23047 if ( isWebGL2 && ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) ) { 23048 23049 gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); 23050 23051 } else { 23052 23053 gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); 23054 23055 } 23056 23057 } 23058 23059 return texture; 23060 23061 } 23062 23063 const emptyTextures = {}; 23064 emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 ); 23065 emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 ); 23066 23067 if ( isWebGL2 ) { 23068 23069 emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 ); 23070 emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 ); 23071 23072 } 23073 23074 // init 23075 23076 colorBuffer.setClear( 0, 0, 0, 1 ); 23077 depthBuffer.setClear( 1 ); 23078 stencilBuffer.setClear( 0 ); 23079 23080 enable( gl.DEPTH_TEST ); 23081 depthBuffer.setFunc( LessEqualDepth ); 23082 23083 setFlipSided( false ); 23084 setCullFace( CullFaceBack ); 23085 enable( gl.CULL_FACE ); 23086 23087 setBlending( NoBlending ); 23088 23089 // 23090 23091 function enable( id ) { 23092 23093 if ( enabledCapabilities[ id ] !== true ) { 23094 23095 gl.enable( id ); 23096 enabledCapabilities[ id ] = true; 23097 23098 } 23099 23100 } 23101 23102 function disable( id ) { 23103 23104 if ( enabledCapabilities[ id ] !== false ) { 23105 23106 gl.disable( id ); 23107 enabledCapabilities[ id ] = false; 23108 23109 } 23110 23111 } 23112 23113 function bindFramebuffer( target, framebuffer ) { 23114 23115 if ( currentBoundFramebuffers[ target ] !== framebuffer ) { 23116 23117 gl.bindFramebuffer( target, framebuffer ); 23118 23119 currentBoundFramebuffers[ target ] = framebuffer; 23120 23121 if ( isWebGL2 ) { 23122 23123 // gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER 23124 23125 if ( target === gl.DRAW_FRAMEBUFFER ) { 23126 23127 currentBoundFramebuffers[ gl.FRAMEBUFFER ] = framebuffer; 23128 23129 } 23130 23131 if ( target === gl.FRAMEBUFFER ) { 23132 23133 currentBoundFramebuffers[ gl.DRAW_FRAMEBUFFER ] = framebuffer; 23134 23135 } 23136 23137 } 23138 23139 return true; 23140 23141 } 23142 23143 return false; 23144 23145 } 23146 23147 function drawBuffers( renderTarget, framebuffer ) { 23148 23149 let drawBuffers = defaultDrawbuffers; 23150 23151 let needsUpdate = false; 23152 23153 if ( renderTarget ) { 23154 23155 drawBuffers = currentDrawbuffers.get( framebuffer ); 23156 23157 if ( drawBuffers === undefined ) { 23158 23159 drawBuffers = []; 23160 currentDrawbuffers.set( framebuffer, drawBuffers ); 23161 23162 } 23163 23164 if ( renderTarget.isWebGLMultipleRenderTargets ) { 23165 23166 const textures = renderTarget.texture; 23167 23168 if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) { 23169 23170 for ( let i = 0, il = textures.length; i < il; i ++ ) { 23171 23172 drawBuffers[ i ] = gl.COLOR_ATTACHMENT0 + i; 23173 23174 } 23175 23176 drawBuffers.length = textures.length; 23177 23178 needsUpdate = true; 23179 23180 } 23181 23182 } else { 23183 23184 if ( drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) { 23185 23186 drawBuffers[ 0 ] = gl.COLOR_ATTACHMENT0; 23187 23188 needsUpdate = true; 23189 23190 } 23191 23192 } 23193 23194 } else { 23195 23196 if ( drawBuffers[ 0 ] !== gl.BACK ) { 23197 23198 drawBuffers[ 0 ] = gl.BACK; 23199 23200 needsUpdate = true; 23201 23202 } 23203 23204 } 23205 23206 if ( needsUpdate ) { 23207 23208 if ( capabilities.isWebGL2 ) { 23209 23210 gl.drawBuffers( drawBuffers ); 23211 23212 } else { 23213 23214 extensions.get( 'WEBGL_draw_buffers' ).drawBuffersWEBGL( drawBuffers
vendor: 15,740 bytes, lines 23214-24002
23214 ); 23215 23216 } 23217 23218 } 23219 23220 23221 } 23222 23223 function useProgram( program ) { 23224 23225 if ( currentProgram !== program ) { 23226 23227 gl.useProgram( program ); 23228 23229 currentProgram = program; 23230 23231 return true; 23232 23233 } 23234 23235 return false; 23236 23237 } 23238 23239 const equationToGL = { 23240 [ AddEquation ]: gl.FUNC_ADD, 23241 [ SubtractEquation ]: gl.FUNC_SUBTRACT, 23242 [ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT 23243 }; 23244 23245 if ( isWebGL2 ) { 23246 23247 equationToGL[ MinEquation ] = gl.MIN; 23248 equationToGL[ MaxEquation ] = gl.MAX; 23249 23250 } else { 23251 23252 const extension = extensions.get( 'EXT_blend_minmax' ); 23253 23254 if ( extension !== null ) { 23255 23256 equationToGL[ MinEquation ] = extension.MIN_EXT; 23257 equationToGL[ MaxEquation ] = extension.MAX_EXT; 23258 23259 } 23260 23261 } 23262 23263 const factorToGL = { 23264 [ ZeroFactor ]: gl.ZERO, 23265 [ OneFactor ]: gl.ONE, 23266 [ SrcColorFactor ]: gl.SRC_COLOR, 23267 [ SrcAlphaFactor ]: gl.SRC_ALPHA, 23268 [ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE, 23269 [ DstColorFactor ]: gl.DST_COLOR, 23270 [ DstAlphaFactor ]: gl.DST_ALPHA, 23271 [ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR, 23272 [ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA, 23273 [ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR, 23274 [ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA, 23275 [ ConstantColorFactor ]: gl.CONSTANT_COLOR, 23276 [ OneMinusConstantColorFactor ]: gl.ONE_MINUS_CONSTANT_COLOR, 23277 [ ConstantAlphaFactor ]: gl.CONSTANT_ALPHA, 23278 [ OneMinusConstantAlphaFactor ]: gl.ONE_MINUS_CONSTANT_ALPHA 23279 }; 23280 23281 function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, blendColor, blendAlpha, premultipliedAlpha ) { 23282 23283 if ( blending === NoBlending ) { 23284 23285 if ( currentBlendingEnabled === true ) { 23286 23287 disable( gl.BLEND ); 23288 currentBlendingEnabled = false; 23289 23290 } 23291 23292 return; 23293 23294 } 23295 23296 if ( currentBlendingEnabled === false ) { 23297 23298 enable( gl.BLEND ); 23299 currentBlendingEnabled = true; 23300 23301 } 23302 23303 if ( blending !== CustomBlending ) { 23304 23305 if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { 23306 23307 if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) { 23308 23309 gl.blendEquation( gl.FUNC_ADD ); 23310 23311 currentBlendEquation = AddEquation; 23312 currentBlendEquationAlpha = AddEquation; 23313 23314 } 23315 23316 if ( premultipliedAlpha ) { 23317 23318 switch ( blending ) { 23319 23320 case NormalBlending: 23321 gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); 23322 break; 23323 23324 case AdditiveBlending: 23325 gl.blendFunc( gl.ONE, gl.ONE ); 23326 break; 23327 23328 case SubtractiveBlending: 23329 gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); 23330 break; 23331 23332 case MultiplyBlending: 23333 gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); 23334 break; 23335 23336 default: 23337 console.error( 'THREE.WebGLState: Invalid blending: ', blending ); 23338 break; 23339 23340 } 23341 23342 } else { 23343 23344 switch ( blending ) { 23345 23346 case NormalBlending: 23347 gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); 23348 break; 23349 23350 case AdditiveBlending: 23351 gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); 23352 break; 23353 23354 case SubtractiveBlending: 23355 gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); 23356 break; 23357 23358 case MultiplyBlending: 23359 gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); 23360 break; 23361 23362 default: 23363 console.error( 'THREE.WebGLState: Invalid blending: ', blending ); 23364 break; 23365 23366 } 23367 23368 } 23369 23370 currentBlendSrc = null; 23371 currentBlendDst = null; 23372 currentBlendSrcAlpha = null; 23373 currentBlendDstAlpha = null; 23374 currentBlendColor.set( 0, 0, 0 ); 23375 currentBlendAlpha = 0; 23376 23377 currentBlending = blending; 23378 currentPremultipledAlpha = premultipliedAlpha; 23379 23380 } 23381 23382 return; 23383 23384 } 23385 23386 // custom blending 23387 23388 blendEquationAlpha = blendEquationAlpha || blendEquation; 23389 blendSrcAlpha = blendSrcAlpha || blendSrc; 23390 blendDstAlpha = blendDstAlpha || blendDst; 23391 23392 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { 23393 23394 gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] ); 23395 23396 currentBlendEquation = blendEquation; 23397 currentBlendEquationAlpha = blendEquationAlpha; 23398 23399 } 23400 23401 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { 23402 23403 gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] ); 23404 23405 currentBlendSrc = blendSrc; 23406 currentBlendDst = blendDst; 23407 currentBlendSrcAlpha = blendSrcAlpha; 23408 currentBlendDstAlpha = blendDstAlpha; 23409 23410 } 23411 23412 if ( blendColor.equals( currentBlendColor ) === false || blendAlpha !== currentBlendAlpha ) { 23413 23414 gl.blendColor( blendColor.r, blendColor.g, blendColor.b, blendAlpha ); 23415 23416 currentBlendColor.copy( blendColor ); 23417 currentBlendAlpha = blendAlpha; 23418 23419 } 23420 23421 currentBlending = blending; 23422 currentPremultipledAlpha = false; 23423 23424 } 23425 23426 function setMaterial( material, frontFaceCW ) { 23427 23428 material.side === DoubleSide 23429 ? disable( gl.CULL_FACE ) 23430 : enable( gl.CULL_FACE ); 23431 23432 let flipSided = ( material.side === BackSide ); 23433 if ( frontFaceCW ) flipSided = ! flipSided; 23434 23435 setFlipSided( flipSided ); 23436 23437 ( material.blending === NormalBlending && material.transparent === false ) 23438 ? setBlending( NoBlending ) 23439 : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.blendColor, material.blendAlpha, material.premultipliedAlpha ); 23440 23441 depthBuffer.setFunc( material.depthFunc ); 23442 depthBuffer.setTest( material.depthTest ); 23443 depthBuffer.setMask( material.depthWrite ); 23444 colorBuffer.setMask( material.colorWrite ); 23445 23446 const stencilWrite = material.stencilWrite; 23447 stencilBuffer.setTest( stencilWrite ); 23448 if ( stencilWrite ) { 23449 23450 stencilBuffer.setMask( material.stencilWriteMask ); 23451 stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask ); 23452 stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass ); 23453 23454 } 23455 23456 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); 23457 23458 material.alphaToCoverage === true 23459 ? enable( gl.SAMPLE_ALPHA_TO_COVERAGE ) 23460 : disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); 23461 23462 } 23463 23464 // 23465 23466 function setFlipSided( flipSided ) { 23467 23468 if ( currentFlipSided !== flipSided ) { 23469 23470 if ( flipSided ) { 23471 23472 gl.frontFace( gl.CW ); 23473 23474 } else { 23475 23476 gl.frontFace( gl.CCW ); 23477 23478 } 23479 23480 currentFlipSided = flipSided; 23481 23482 } 23483 23484 } 23485 23486 function setCullFace( cullFace ) { 23487 23488 if ( cullFace !== CullFaceNone ) { 23489 23490 enable( gl.CULL_FACE ); 23491 23492 if ( cullFace !== currentCullFace ) { 23493 23494 if ( cullFace === CullFaceBack ) { 23495 23496 gl.cullFace( gl.BACK ); 23497 23498 } else if ( cullFace === CullFaceFront ) { 23499 23500 gl.cullFace( gl.FRONT ); 23501 23502 } else { 23503 23504 gl.cullFace( gl.FRONT_AND_BACK ); 23505 23506 } 23507 23508 } 23509 23510 } else { 23511 23512 disable( gl.CULL_FACE ); 23513 23514 } 23515 23516 currentCullFace = cullFace; 23517 23518 } 23519 23520 function setLineWidth( width ) { 23521 23522 if ( width !== currentLineWidth ) { 23523 23524 if ( lineWidthAvailable ) gl.lineWidth( width ); 23525 23526 currentLineWidth = width; 23527 23528 } 23529 23530 } 23531 23532 function setPolygonOffset( polygonOffset, factor, units ) { 23533 23534 if ( polygonOffset ) { 23535 23536 enable( gl.POLYGON_OFFSET_FILL ); 23537 23538 if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { 23539 23540 gl.polygonOffset( factor, units ); 23541 23542 currentPolygonOffsetFactor = factor; 23543 currentPolygonOffsetUnits = units; 23544 23545 } 23546 23547 } else { 23548 23549 disable( gl.POLYGON_OFFSET_FILL ); 23550 23551 } 23552 23553 } 23554 23555 function setScissorTest( scissorTest ) { 23556 23557 if ( scissorTest ) { 23558 23559 enable( gl.SCISSOR_TEST ); 23560 23561 } else { 23562 23563 disable( gl.SCISSOR_TEST ); 23564 23565 } 23566 23567 } 23568 23569 // texture 23570 23571 function activeTexture( webglSlot ) { 23572 23573 if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1; 23574 23575 if ( currentTextureSlot !== webglSlot ) { 23576 23577 gl.activeTexture( webglSlot ); 23578 currentTextureSlot = webglSlot; 23579 23580 } 23581 23582 } 23583 23584 function bindTexture( webglType, webglTexture, webglSlot ) { 23585 23586 if ( webglSlot === undefined ) { 23587 23588 if ( currentTextureSlot === null ) { 23589 23590 webglSlot = gl.TEXTURE0 + maxTextures - 1; 23591 23592 } else { 23593 23594 webglSlot = currentTextureSlot; 23595 23596 } 23597 23598 } 23599 23600 let boundTexture = currentBoundTextures[ webglSlot ]; 23601 23602 if ( boundTexture === undefined ) { 23603 23604 boundTexture = { type: undefined, texture: undefined }; 23605 currentBoundTextures[ webglSlot ] = boundTexture; 23606 23607 } 23608 23609 if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { 23610 23611 if ( currentTextureSlot !== webglSlot ) { 23612 23613 gl.activeTexture( webglSlot ); 23614 currentTextureSlot = webglSlot; 23615 23616 } 23617 23618 gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] ); 23619 23620 boundTexture.type = webglType; 23621 boundTexture.texture = webglTexture; 23622 23623 } 23624 23625 } 23626 23627 function unbindTexture() { 23628 23629 const boundTexture = currentBoundTextures[ currentTextureSlot ]; 23630 23631 if ( boundTexture !== undefined && boundTexture.type !== undefined ) { 23632 23633 gl.bindTexture( boundTexture.type, null ); 23634 23635 boundTexture.type = undefined; 23636 boundTexture.texture = undefined; 23637 23638 } 23639 23640 } 23641 23642 function compressedTexImage2D() { 23643 23644 try { 23645 23646 gl.compressedTexImage2D.apply( gl, arguments ); 23647 23648 } catch ( error ) { 23649 23650 console.error( 'THREE.WebGLState:', error ); 23651 23652 } 23653 23654 } 23655 23656 function compressedTexImage3D() { 23657 23658 try { 23659 23660 gl.compressedTexImage3D.apply( gl, arguments ); 23661 23662 } catch ( error ) { 23663 23664 console.error( 'THREE.WebGLState:', error ); 23665 23666 } 23667 23668 } 23669 23670 function texSubImage2D() { 23671 23672 try { 23673 23674 gl.texSubImage2D.apply( gl, arguments ); 23675 23676 } catch ( error ) { 23677 23678 console.error( 'THREE.WebGLState:', error ); 23679 23680 } 23681 23682 } 23683 23684 function texSubImage3D() { 23685 23686 try { 23687 23688 gl.texSubImage3D.apply( gl, arguments ); 23689 23690 } catch ( error ) { 23691 23692 console.error( 'THREE.WebGLState:', error ); 23693 23694 } 23695 23696 } 23697 23698 function compressedTexSubImage2D() { 23699 23700 try { 23701 23702 gl.compressedTexSubImage2D.apply( gl, arguments ); 23703 23704 } catch ( error ) { 23705 23706 console.error( 'THREE.WebGLState:', error ); 23707 23708 } 23709 23710 } 23711 23712 function compressedTexSubImage3D() { 23713 23714 try { 23715 23716 gl.compressedTexSubImage3D.apply( gl, arguments ); 23717 23718 } catch ( error ) { 23719 23720 console.error( 'THREE.WebGLState:', error ); 23721 23722 } 23723 23724 } 23725 23726 function texStorage2D() { 23727 23728 try { 23729 23730 gl.texStorage2D.apply( gl, arguments ); 23731 23732 } catch ( error ) { 23733 23734 console.error( 'THREE.WebGLState:', error ); 23735 23736 } 23737 23738 } 23739 23740 function texStorage3D() { 23741 23742 try { 23743 23744 gl.texStorage3D.apply( gl, arguments ); 23745 23746 } catch ( error ) { 23747 23748 console.error( 'THREE.WebGLState:', error ); 23749 23750 } 23751 23752 } 23753 23754 function texImage2D() { 23755 23756 try { 23757 23758 gl.texImage2D.apply( gl, arguments ); 23759 23760 } catch ( error ) { 23761 23762 console.error( 'THREE.WebGLState:', error ); 23763 23764 } 23765 23766 } 23767 23768 function texImage3D() { 23769 23770 try { 23771 23772 gl.texImage3D.apply( gl, arguments ); 23773 23774 } catch ( error ) { 23775 23776 console.error( 'THREE.WebGLState:', error ); 23777 23778 } 23779 23780 } 23781 23782 // 23783 23784 function scissor( scissor ) { 23785 23786 if ( currentScissor.equals( scissor ) === false ) { 23787 23788 gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w ); 23789 currentScissor.copy( scissor ); 23790 23791 } 23792 23793 } 23794 23795 function viewport( viewport ) { 23796 23797 if ( currentViewport.equals( viewport ) === false ) { 23798 23799 gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w ); 23800 currentViewport.copy( viewport ); 23801 23802 } 23803 23804 } 23805 23806 function updateUBOMapping( uniformsGroup, program ) { 23807 23808 let mapping = uboProgramMap.get( program ); 23809 23810 if ( mapping === undefined ) { 23811 23812 mapping = new WeakMap(); 23813 23814 uboProgramMap.set( program, mapping ); 23815 23816 } 23817 23818 let blockIndex = mapping.get( uniformsGroup ); 23819 23820 if ( blockIndex === undefined ) { 23821 23822 blockIndex = gl.getUniformBlockIndex( program, uniformsGroup.name ); 23823 23824 mapping.set( uniformsGroup, blockIndex ); 23825 23826 } 23827 23828 } 23829 23830 function uniformBlockBinding( uniformsGroup, program ) { 23831 23832 const mapping = uboProgramMap.get( program ); 23833 const blockIndex = mapping.get( uniformsGroup ); 23834 23835 if ( uboBindings.get( program ) !== blockIndex ) { 23836 23837 // bind shader specific block index to global block point 23838 gl.uniformBlockBinding( program, blockIndex, uniformsGroup.__bindingPointIndex ); 23839 23840 uboBindings.set( program, blockIndex ); 23841 23842 } 23843 23844 } 23845 23846 // 23847 23848 function reset() { 23849 23850 // reset state 23851 23852 gl.disable( gl.BLEND ); 23853 gl.disable( gl.CULL_FACE ); 23854 gl.disable( gl.DEPTH_TEST ); 23855 gl.disable( gl.POLYGON_OFFSET_FILL ); 23856 gl.disable( gl.SCISSOR_TEST ); 23857 gl.disable( gl.STENCIL_TEST ); 23858 gl.disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); 23859 23860 gl.blendEquation( gl.FUNC_ADD ); 23861 gl.blendFunc( gl.ONE, gl.ZERO ); 23862 gl.blendFuncSeparate( gl.ONE, gl.ZERO, gl.ONE, gl.ZERO ); 23863 gl.blendColor( 0, 0, 0, 0 ); 23864 23865 gl.colorMask( true, true, true, true ); 23866 gl.clearColor( 0, 0, 0, 0 ); 23867 23868 gl.depthMask( true ); 23869 gl.depthFunc( gl.LESS ); 23870 gl.clearDepth( 1 ); 23871 23872 gl.stencilMask( 0xffffffff ); 23873 gl.stencilFunc( gl.ALWAYS, 0, 0xffffffff ); 23874 gl.stencilOp( gl.KEEP, gl.KEEP, gl.KEEP ); 23875 gl.clearStencil( 0 ); 23876 23877 gl.cullFace( gl.BACK ); 23878 gl.frontFace( gl.CCW ); 23879 23880 gl.polygonOffset( 0, 0 ); 23881 23882 gl.activeTexture( gl.TEXTURE0 ); 23883 23884 gl.bindFramebuffer( gl.FRAMEBUFFER, null ); 23885 23886 if ( isWebGL2 === true ) { 23887 23888 gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null ); 23889 gl.bindFramebuffer( gl.READ_FRAMEBUFFER, null ); 23890 23891 } 23892 23893 gl.useProgram( null ); 23894 23895 gl.lineWidth( 1 ); 23896 23897 gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height ); 23898 gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height ); 23899 23900 // reset internals 23901 23902 enabledCapabilities = {}; 23903 23904 currentTextureSlot = null; 23905 currentBoundTextures = {}; 23906 23907 currentBoundFramebuffers = {}; 23908 currentDrawbuffers = new WeakMap(); 23909 defaultDrawbuffers = []; 23910 23911 currentProgram = null; 23912 23913 currentBlendingEnabled = false; 23914 currentBlending = null; 23915 currentBlendEquation = null; 23916 currentBlendSrc = null; 23917 currentBlendDst = null; 23918 currentBlendEquationAlpha = null; 23919 currentBlendSrcAlpha = null; 23920 currentBlendDstAlpha = null; 23921 currentBlendColor = new Color( 0, 0, 0 ); 23922 currentBlendAlpha = 0; 23923 currentPremultipledAlpha = false; 23924 23925 currentFlipSided = null; 23926 currentCullFace = null; 23927 23928 currentLineWidth = null; 23929 23930 currentPolygonOffsetFactor = null; 23931 currentPolygonOffsetUnits = null; 23932 23933 currentScissor.set( 0, 0, gl.canvas.width, gl.canvas.height ); 23934 currentViewport.set( 0, 0, gl.canvas.width, gl.canvas.height ); 23935 23936 colorBuffer.reset(); 23937 depthBuffer.reset(); 23938 stencilBuffer.reset(); 23939 23940 } 23941 23942 return { 23943 23944 buffers: { 23945 color: colorBuffer, 23946 depth: depthBuffer, 23947 stencil: stencilBuffer 23948 }, 23949 23950 enable: enable, 23951 disable: disable, 23952 23953 bindFramebuffer: bindFramebuffer, 23954 drawBuffers: drawBuffers, 23955 23956 useProgram: useProgram, 23957 23958 setBlending: setBlending, 23959 setMaterial: setMaterial, 23960 23961 setFlipSided: setFlipSided, 23962 setCullFace: setCullFace, 23963 23964 setLineWidth: setLineWidth, 23965 setPolygonOffset: setPolygonOffset, 23966 23967 setScissorTest: setScissorTest, 23968 23969 activeTexture: activeTexture, 23970 bindTexture: bindTexture, 23971 unbindTexture: unbindTexture, 23972 compressedTexImage2D: compressedTexImage2D, 23973 compressedTexImage3D: compressedTexImage3D, 23974 texImage2D: texImage2D, 23975 texImage3D: texImage3D, 23976 23977 updateUBOMapping: updateUBOMapping, 23978 uniformBlockBinding: uniformBlockBinding, 23979 23980 texStorage2D: texStorage2D, 23981 texStorage3D: texStorage3D, 23982 texSubImage2D: texSubImage2D, 23983 texSubImage3D: texSubImage3D, 23984 compressedTexSubImage2D: compressedTexSubImage2D, 23985 compressedTexSubImage3D: compressedTexSubImage3D, 23986 23987 scissor: scissor, 23988 viewport: viewport, 23989 23990 reset: reset 23991 23992 }; 23993 23994} 23995 23996function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) { 23997 23998 const isWebGL2 = capabilities.isWebGL2; 23999 const multisampledRTTExt = extensions.has( 'WEBGL_multisampled_render_to_texture' ) ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : null; 24000 const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test( navigator.userAgent ); 24001 24002 const _
vendor: 58,712 bytes, lines 24002-26075
24002videoTextures = new WeakMap(); 24003 let _canvas; 24004 24005 const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source 24006 24007 // cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas, 24008 // also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")! 24009 // Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d). 24010 24011 let useOffscreenCanvas = false; 24012 24013 try { 24014 24015 useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined' 24016 // eslint-disable-next-line compat/compat 24017 && ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null; 24018 24019 } catch ( err ) { 24020 24021 // Ignore any errors 24022 24023 } 24024 24025 function createCanvas( width, height ) { 24026 24027 // Use OffscreenCanvas when available. Specially needed in web workers 24028 24029 return useOffscreenCanvas ? 24030 // eslint-disable-next-line compat/compat 24031 new OffscreenCanvas( width, height ) : createElementNS( 'canvas' ); 24032 24033 } 24034 24035 function resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) { 24036 24037 let scale = 1; 24038 24039 // handle case if texture exceeds max size 24040 24041 if ( image.width > maxSize || image.height > maxSize ) { 24042 24043 scale = maxSize / Math.max( image.width, image.height ); 24044 24045 } 24046 24047 // only perform resize if necessary 24048 24049 if ( scale < 1 || needsPowerOfTwo === true ) { 24050 24051 // only perform resize for certain image types 24052 24053 if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || 24054 ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || 24055 ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { 24056 24057 const floor = needsPowerOfTwo ? floorPowerOfTwo : Math.floor; 24058 24059 const width = floor( scale * image.width ); 24060 const height = floor( scale * image.height ); 24061 24062 if ( _canvas === undefined ) _canvas = createCanvas( width, height ); 24063 24064 // cube textures can't reuse the same canvas 24065 24066 const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas; 24067 24068 canvas.width = width; 24069 canvas.height = height; 24070 24071 const context = canvas.getContext( '2d' ); 24072 context.drawImage( image, 0, 0, width, height ); 24073 24074 console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' ); 24075 24076 return canvas; 24077 24078 } else { 24079 24080 if ( 'data' in image ) { 24081 24082 console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' ); 24083 24084 } 24085 24086 return image; 24087 24088 } 24089 24090 } 24091 24092 return image; 24093 24094 } 24095 24096 function isPowerOfTwo$1( image ) { 24097 24098 return isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ); 24099 24100 } 24101 24102 function textureNeedsPowerOfTwo( texture ) { 24103 24104 if ( isWebGL2 ) return false; 24105 24106 return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) || 24107 ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ); 24108 24109 } 24110 24111 function textureNeedsGenerateMipmaps( texture, supportsMips ) { 24112 24113 return texture.generateMipmaps && supportsMips && 24114 texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; 24115 24116 } 24117 24118 function generateMipmap( target ) { 24119 24120 _gl.generateMipmap( target ); 24121 24122 } 24123 24124 function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { 24125 24126 if ( isWebGL2 === false ) return glFormat; 24127 24128 if ( internalFormatName !== null ) { 24129 24130 if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ]; 24131 24132 console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' ); 24133 24134 } 24135 24136 let internalFormat = glFormat; 24137 24138 if ( glFormat === _gl.RED ) { 24139 24140 if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F; 24141 if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F; 24142 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8; 24143 24144 } 24145 24146 if ( glFormat === _gl.RED_INTEGER ) { 24147 24148 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8UI; 24149 if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.R16UI; 24150 if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.R32UI; 24151 if ( glType === _gl.BYTE ) internalFormat = _gl.R8I; 24152 if ( glType === _gl.SHORT ) internalFormat = _gl.R16I; 24153 if ( glType === _gl.INT ) internalFormat = _gl.R32I; 24154 24155 } 24156 24157 if ( glFormat === _gl.RG ) { 24158 24159 if ( glType === _gl.FLOAT ) internalFormat = _gl.RG32F; 24160 if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RG16F; 24161 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8; 24162 24163 } 24164 24165 if ( glFormat === _gl.RGBA ) { 24166 24167 const transfer = forceLinearTransfer ? LinearTransfer : ColorManagement.getTransfer( colorSpace ); 24168 24169 if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; 24170 if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; 24171 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; 24172 if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4; 24173 if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1; 24174 24175 } 24176 24177 if ( internalFormat === _gl.R16F || internalFormat === _gl.R32F || 24178 internalFormat === _gl.RG16F || internalFormat === _gl.RG32F || 24179 internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) { 24180 24181 extensions.get( 'EXT_color_buffer_float' ); 24182 24183 } 24184 24185 return internalFormat; 24186 24187 } 24188 24189 function getMipLevels( texture, image, supportsMips ) { 24190 24191 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) === true || ( texture.isFramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) ) { 24192 24193 return Math.log2( Math.max( image.width, image.height ) ) + 1; 24194 24195 } else if ( texture.mipmaps !== undefined && texture.mipmaps.length > 0 ) { 24196 24197 // user-defined mipmaps 24198 24199 return texture.mipmaps.length; 24200 24201 } else if ( texture.isCompressedTexture && Array.isArray( texture.image ) ) { 24202 24203 return image.mipmaps.length; 24204 24205 } else { 24206 24207 // texture without mipmaps (only base level) 24208 24209 return 1; 24210 24211 } 24212 24213 } 24214 24215 // Fallback filters for non-power-of-2 textures 24216 24217 function filterFallback( f ) { 24218 24219 if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) { 24220 24221 return _gl.NEAREST; 24222 24223 } 24224 24225 return _gl.LINEAR; 24226 24227 } 24228 24229 // 24230 24231 function onTextureDispose( event ) { 24232 24233 const texture = event.target; 24234 24235 texture.removeEventListener( 'dispose', onTextureDispose ); 24236 24237 deallocateTexture( texture ); 24238 24239 if ( texture.isVideoTexture ) { 24240 24241 _videoTextures.delete( texture ); 24242 24243 } 24244 24245 } 24246 24247 function onRenderTargetDispose( event ) { 24248 24249 const renderTarget = event.target; 24250 24251 renderTarget.removeEventListener( 'dispose', onRenderTargetDispose ); 24252 24253 deallocateRenderTarget( renderTarget ); 24254 24255 } 24256 24257 // 24258 24259 function deallocateTexture( texture ) { 24260 24261 const textureProperties = properties.get( texture ); 24262 24263 if ( textureProperties.__webglInit === undefined ) return; 24264 24265 // check if it's necessary to remove the WebGLTexture object 24266 24267 const source = texture.source; 24268 const webglTextures = _sources.get( source ); 24269 24270 if ( webglTextures ) { 24271 24272 const webglTexture = webglTextures[ textureProperties.__cacheKey ]; 24273 webglTexture.usedTimes --; 24274 24275 // the WebGLTexture object is not used anymore, remove it 24276 24277 if ( webglTexture.usedTimes === 0 ) { 24278 24279 deleteTexture( texture ); 24280 24281 } 24282 24283 // remove the weak map entry if no WebGLTexture uses the source anymore 24284 24285 if ( Object.keys( webglTextures ).length === 0 ) { 24286 24287 _sources.delete( source ); 24288 24289 } 24290 24291 } 24292 24293 properties.remove( texture ); 24294 24295 } 24296 24297 function deleteTexture( texture ) { 24298 24299 const textureProperties = properties.get( texture ); 24300 _gl.deleteTexture( textureProperties.__webglTexture ); 24301 24302 const source = texture.source; 24303 const webglTextures = _sources.get( source ); 24304 delete webglTextures[ textureProperties.__cacheKey ]; 24305 24306 info.memory.textures --; 24307 24308 } 24309 24310 function deallocateRenderTarget( renderTarget ) { 24311 24312 const texture = renderTarget.texture; 24313 24314 const renderTargetProperties = properties.get( renderTarget ); 24315 const textureProperties = properties.get( texture ); 24316 24317 if ( textureProperties.__webglTexture !== undefined ) { 24318 24319 _gl.deleteTexture( textureProperties.__webglTexture ); 24320 24321 info.memory.textures --; 24322 24323 } 24324 24325 if ( renderTarget.depthTexture ) { 24326 24327 renderTarget.depthTexture.dispose(); 24328 24329 } 24330 24331 if ( renderTarget.isWebGLCubeRenderTarget ) { 24332 24333 for ( let i = 0; i < 6; i ++ ) { 24334 24335 if ( Array.isArray( renderTargetProperties.__webglFramebuffer[ i ] ) ) { 24336 24337 for ( let level = 0; level < renderTargetProperties.__webglFramebuffer[ i ].length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ][ level ] ); 24338 24339 } else { 24340 24341 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] ); 24342 24343 } 24344 24345 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); 24346 24347 } 24348 24349 } else { 24350 24351 if ( Array.isArray( renderTargetProperties.__webglFramebuffer ) ) { 24352 24353 for ( let level = 0; level < renderTargetProperties.__webglFramebuffer.length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ level ] ); 24354 24355 } else { 24356 24357 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer ); 24358 24359 } 24360 24361 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); 24362 if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer ); 24363 24364 if ( renderTargetProperties.__webglColorRenderbuffer ) { 24365 24366 for ( let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i ++ ) { 24367 24368 if ( renderTargetProperties.__webglColorRenderbuffer[ i ] ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer[ i ] ); 24369 24370 } 24371 24372 } 24373 24374 if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer ); 24375 24376 } 24377 24378 if ( renderTarget.isWebGLMultipleRenderTargets ) { 24379 24380 for ( let i = 0, il = texture.length; i < il; i ++ ) { 24381 24382 const attachmentProperties = properties.get( texture[ i ] ); 24383 24384 if ( attachmentProperties.__webglTexture ) { 24385 24386 _gl.deleteTexture( attachmentProperties.__webglTexture ); 24387 24388 info.memory.textures --; 24389 24390 } 24391 24392 properties.remove( texture[ i ] ); 24393 24394 } 24395 24396 } 24397 24398 properties.remove( texture ); 24399 properties.remove( renderTarget ); 24400 24401 } 24402 24403 // 24404 24405 let textureUnits = 0; 24406 24407 function resetTextureUnits() { 24408 24409 textureUnits = 0; 24410 24411 } 24412 24413 function allocateTextureUnit() { 24414 24415 const textureUnit = textureUnits; 24416 24417 if ( textureUnit >= capabilities.maxTextures ) { 24418 24419 console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); 24420 24421 } 24422 24423 textureUnits += 1; 24424 24425 return textureUnit; 24426 24427 } 24428 24429 function getTextureCacheKey( texture ) { 24430 24431 const array = []; 24432 24433 array.push( texture.wrapS ); 24434 array.push( texture.wrapT ); 24435 array.push( texture.wrapR || 0 ); 24436 array.push( texture.magFilter ); 24437 array.push( texture.minFilter ); 24438 array.push( texture.anisotropy ); 24439 array.push( texture.internalFormat ); 24440 array.push( texture.format ); 24441 array.push( texture.type ); 24442 array.push( texture.generateMipmaps ); 24443 array.push( texture.premultiplyAlpha ); 24444 array.push( texture.flipY ); 24445 array.push( texture.unpackAlignment ); 24446 array.push( texture.colorSpace ); 24447 24448 return array.join(); 24449 24450 } 24451 24452 // 24453 24454 function setTexture2D( texture, slot ) { 24455 24456 const textureProperties = properties.get( texture ); 24457 24458 if ( texture.isVideoTexture ) updateVideoTexture( texture ); 24459 24460 if ( texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version ) { 24461 24462 const image = texture.image; 24463 24464 if ( image === null ) { 24465 24466 console.warn( 'THREE.WebGLRenderer: Texture marked for update but no image data found.' ); 24467 24468 } else if ( image.complete === false ) { 24469 24470 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' ); 24471 24472 } else { 24473 24474 uploadTexture( textureProperties, texture, slot ); 24475 return; 24476 24477 } 24478 24479 } 24480 24481 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24482 24483 } 24484 24485 function setTexture2DArray( texture, slot ) { 24486 24487 const textureProperties = properties.get( texture ); 24488 24489 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 24490 24491 uploadTexture( textureProperties, texture, slot ); 24492 return; 24493 24494 } 24495 24496 state.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24497 24498 } 24499 24500 function setTexture3D( texture, slot ) { 24501 24502 const textureProperties = properties.get( texture ); 24503 24504 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 24505 24506 uploadTexture( textureProperties, texture, slot ); 24507 return; 24508 24509 } 24510 24511 state.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24512 24513 } 24514 24515 function setTextureCube( texture, slot ) { 24516 24517 const textureProperties = properties.get( texture ); 24518 24519 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 24520 24521 uploadCubeTexture( textureProperties, texture, slot ); 24522 return; 24523 24524 } 24525 24526 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24527 24528 } 24529 24530 const wrappingToGL = { 24531 [ RepeatWrapping ]: _gl.REPEAT, 24532 [ ClampToEdgeWrapping ]: _gl.CLAMP_TO_EDGE, 24533 [ MirroredRepeatWrapping ]: _gl.MIRRORED_REPEAT 24534 }; 24535 24536 const filterToGL = { 24537 [ NearestFilter ]: _gl.NEAREST, 24538 [ NearestMipmapNearestFilter ]: _gl.NEAREST_MIPMAP_NEAREST, 24539 [ NearestMipmapLinearFilter ]: _gl.NEAREST_MIPMAP_LINEAR, 24540 24541 [ LinearFilter ]: _gl.LINEAR, 24542 [ LinearMipmapNearestFilter ]: _gl.LINEAR_MIPMAP_NEAREST, 24543 [ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR 24544 }; 24545 24546 const compareToGL = { 24547 [ NeverCompare ]: _gl.NEVER, 24548 [ AlwaysCompare ]: _gl.ALWAYS, 24549 [ LessCompare ]: _gl.LESS, 24550 [ LessEqualCompare ]: _gl.LEQUAL, 24551 [ EqualCompare ]: _gl.EQUAL, 24552 [ GreaterEqualCompare ]: _gl.GEQUAL, 24553 [ GreaterCompare ]: _gl.GREATER, 24554 [ NotEqualCompare ]: _gl.NOTEQUAL 24555 }; 24556 24557 function setTextureParameters( textureType, texture, supportsMips ) { 24558 24559 if ( supportsMips ) { 24560 24561 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] ); 24562 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] ); 24563 24564 if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) { 24565 24566 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[ texture.wrapR ] ); 24567 24568 } 24569 24570 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] ); 24571 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[ texture.minFilter ] ); 24572 24573 } else { 24574 24575 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE ); 24576 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE ); 24577 24578 if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) { 24579 24580 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, _gl.CLAMP_TO_EDGE ); 24581 24582 } 24583 24584 if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) { 24585 24586 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' ); 24587 24588 } 24589 24590 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) ); 24591 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) ); 24592 24593 if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) { 24594 24595 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' ); 24596 24597 } 24598 24599 } 24600 24601 if ( texture.compareFunction ) { 24602 24603 _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE ); 24604 _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] ); 24605 24606 } 24607 24608 if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { 24609 24610 const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); 24611 24612 if ( texture.magFilter === NearestFilter ) return; 24613 if ( texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter ) return; 24614 if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false ) return; // verify extension for WebGL 1 and WebGL 2 24615 if ( isWebGL2 === false && ( texture.type === HalfFloatType && extensions.has( 'OES_texture_half_float_linear' ) === false ) ) return; // verify extension for WebGL 1 only 24616 24617 if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) { 24618 24619 _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) ); 24620 properties.get( texture ).__currentAnisotropy = texture.anisotropy; 24621 24622 } 24623 24624 } 24625 24626 } 24627 24628 function initTexture( textureProperties, texture ) { 24629 24630 let forceUpload = false; 24631 24632 if ( textureProperties.__webglInit === undefined ) { 24633 24634 textureProperties.__webglInit = true; 24635 24636 texture.addEventListener( 'dispose', onTextureDispose ); 24637 24638 } 24639 24640 // create Source <-> WebGLTextures mapping if necessary 24641 24642 const source = texture.source; 24643 let webglTextures = _sources.get( source ); 24644 24645 if ( webglTextures === undefined ) { 24646 24647 webglTextures = {}; 24648 _sources.set( source, webglTextures ); 24649 24650 } 24651 24652 // check if there is already a WebGLTexture object for the given texture parameters 24653 24654 const textureCacheKey = getTextureCacheKey( texture ); 24655 24656 if ( textureCacheKey !== textureProperties.__cacheKey ) { 24657 24658 // if not, create a new instance of WebGLTexture 24659 24660 if ( webglTextures[ textureCacheKey ] === undefined ) { 24661 24662 // create new entry 24663 24664 webglTextures[ textureCacheKey ] = { 24665 texture: _gl.createTexture(), 24666 usedTimes: 0 24667 }; 24668 24669 info.memory.textures ++; 24670 24671 // when a new instance of WebGLTexture was created, a texture upload is required 24672 // even if the image contents are identical 24673 24674 forceUpload = true; 24675 24676 } 24677 24678 webglTextures[ textureCacheKey ].usedTimes ++; 24679 24680 // every time the texture cache key changes, it's necessary to check if an instance of 24681 // WebGLTexture can be deleted in order to avoid a memory leak. 24682 24683 const webglTexture = webglTextures[ textureProperties.__cacheKey ]; 24684 24685 if ( webglTexture !== undefined ) { 24686 24687 webglTextures[ textureProperties.__cacheKey ].usedTimes --; 24688 24689 if ( webglTexture.usedTimes === 0 ) { 24690 24691 deleteTexture( texture ); 24692 24693 } 24694 24695 } 24696 24697 // store references to cache key and WebGLTexture object 24698 24699 textureProperties.__cacheKey = textureCacheKey; 24700 textureProperties.__webglTexture = webglTextures[ textureCacheKey ].texture; 24701 24702 } 24703 24704 return forceUpload; 24705 24706 } 24707 24708 function uploadTexture( textureProperties, texture, slot ) { 24709 24710 let textureType = _gl.TEXTURE_2D; 24711 24712 if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = _gl.TEXTURE_2D_ARRAY; 24713 if ( texture.isData3DTexture ) textureType = _gl.TEXTURE_3D; 24714 24715 const forceUpload = initTexture( textureProperties, texture ); 24716 const source = texture.source; 24717 24718 state.bindTexture( textureType, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 24719 24720 const sourceProperties = properties.get( source ); 24721 24722 if ( source.version !== sourceProperties.__version || forceUpload === true ) { 24723 24724 state.activeTexture( _gl.TEXTURE0 + slot ); 24725 24726 const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); 24727 const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); 24728 const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; 24729 24730 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); 24731 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); 24732 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); 24733 _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion ); 24734 24735 const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo$1( texture.image ) === false; 24736 let image = resizeImage( texture.image, needsPowerOfTwo, false, capabilities.maxTextureSize ); 24737 image = verifyColorSpace( texture, image ); 24738 24739 const supportsMips = isPowerOfTwo$1( image ) || isWebGL2, 24740 glFormat = utils.convert( texture.format, texture.colorSpace ); 24741 24742 let glType = utils.convert( texture.type ), 24743 glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture ); 24744 24745 setTextureParameters( textureType, texture, supportsMips ); 24746 24747 let mipmap; 24748 const mipmaps = texture.mipmaps; 24749 24750 const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true && glInternalFormat !== RGB_ETC1_Format ); 24751 const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); 24752 const levels = getMipLevels( texture, image, supportsMips ); 24753 24754 if ( texture.isDepthTexture ) { 24755 24756 // populate depth texture with dummy data 24757 24758 glInternalFormat = _gl.DEPTH_COMPONENT; 24759 24760 if ( isWebGL2 ) { 24761 24762 if ( texture.type === FloatType ) { 24763 24764 glInternalFormat = _gl.DEPTH_COMPONENT32F; 24765 24766 } else if ( texture.type === UnsignedIntType ) { 24767 24768 glInternalFormat = _gl.DEPTH_COMPONENT24; 24769 24770 } else if ( texture.type === UnsignedInt248Type ) { 24771 24772 glInternalFormat = _gl.DEPTH24_STENCIL8; 24773 24774 } else { 24775 24776 glInternalFormat = _gl.DEPTH_COMPONENT16; // WebGL2 requires sized internalformat for glTexImage2D 24777 24778 } 24779 24780 } else { 24781 24782 if ( texture.type === FloatType ) { 24783 24784 console.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' ); 24785 24786 } 24787 24788 } 24789 24790 // validation checks for WebGL 1 24791 24792 if ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) { 24793 24794 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are 24795 // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT 24796 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) 24797 if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) { 24798 24799 console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' ); 24800 24801 texture.type = UnsignedIntType; 24802 glType = utils.convert( texture.type ); 24803 24804 } 24805 24806 } 24807 24808 if ( texture.format === DepthStencilFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) { 24809 24810 // Depth stencil textures need the DEPTH_STENCIL internal format 24811 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) 24812 glInternalFormat = _gl.DEPTH_STENCIL; 24813 24814 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are 24815 // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL. 24816 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) 24817 if ( texture.type !== UnsignedInt248Type ) { 24818 24819 console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' ); 24820 24821 texture.type = UnsignedInt248Type; 24822 glType = utils.convert( texture.type ); 24823 24824 } 24825 24826 } 24827 24828 // 24829 24830 if ( allocateMemory ) { 24831 24832 if ( useTexStorage ) { 24833 24834 state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height ); 24835 24836 } else { 24837 24838 state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ); 24839 24840 } 24841 24842 } 24843 24844 } else if ( texture.isDataTexture ) { 24845 24846 // use manually created mipmaps if available 24847 // if there are no manual mipmaps 24848 // set 0 level mipmap and then use GL to generate other mipmap levels 24849 24850 if ( mipmaps.length > 0 && supportsMips ) { 24851 24852 if ( useTexStorage && allocateMemory ) { 24853 24854 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); 24855 24856 } 24857 24858 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 24859 24860 mipmap = mipmaps[ i ]; 24861 24862 if ( useTexStorage ) { 24863 24864 state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); 24865 24866 } else { 24867 24868 state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 24869 24870 } 24871 24872 } 24873 24874 texture.generateMipmaps = false; 24875 24876 } else { 24877 24878 if ( useTexStorage ) { 24879 24880 if ( allocateMemory ) { 24881 24882 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); 24883 24884 } 24885 24886 state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data ); 24887 24888 } else { 24889 24890 state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data ); 24891 24892 } 24893 24894 } 24895 24896 } else if ( texture.isCompressedTexture ) { 24897 24898 if ( texture.isCompressedArrayTexture ) { 24899 24900 if ( useTexStorage && allocateMemory ) { 24901 24902 state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth ); 24903 24904 } 24905 24906 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 24907 24908 mipmap = mipmaps[ i ]; 24909 24910 if ( texture.format !== RGBAFormat ) { 24911 24912 if ( glFormat !== null ) { 24913 24914 if ( useTexStorage ) { 24915 24916 state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); 24917 24918 } else { 24919 24920 state.compressedTexImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 ); 24921 24922 } 24923 24924 } else { 24925 24926 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); 24927 24928 } 24929 24930 } else { 24931 24932 if ( useTexStorage ) { 24933 24934 state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data ); 24935 24936 } else { 24937 24938 state.texImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data ); 24939 24940 } 24941 24942 } 24943 24944 } 24945 24946 } else { 24947 24948 if ( useTexStorage && allocateMemory ) { 24949 24950 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); 24951 24952 } 24953 24954 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 24955 24956 mipmap = mipmaps[ i ]; 24957 24958 if ( texture.format !== RGBAFormat ) { 24959 24960 if ( glFormat !== null ) { 24961 24962 if ( useTexStorage ) { 24963 24964 state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); 24965 24966 } else { 24967 24968 state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); 24969 24970 } 24971 24972 } else { 24973 24974 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); 24975 24976 } 24977 24978 } else { 24979 24980 if ( useTexStorage ) { 24981 24982 state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); 24983 24984 } else { 24985 24986 state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 24987 24988 } 24989 24990 } 24991 24992 } 24993 24994 } 24995 24996 } else if ( texture.isDataArrayTexture ) { 24997 24998 if ( useTexStorage ) { 24999 25000 if ( allocateMemory ) { 25001 25002 state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth ); 25003 25004 } 25005 25006 state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); 25007 25008 } else { 25009 25010 state.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); 25011 25012 } 25013 25014 } else if ( texture.isData3DTexture ) { 25015 25016 if ( useTexStorage ) { 25017 25018 if ( allocateMemory ) { 25019 25020 state.texStorage3D( _gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth ); 25021 25022 } 25023 25024 state.texSubImage3D( _gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); 25025 25026 } else { 25027 25028 state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data ); 25029 25030 } 25031 25032 } else if ( texture.isFramebufferTexture ) { 25033 25034 if ( allocateMemory ) { 25035 25036 if ( useTexStorage ) { 25037 25038 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); 25039 25040 } else { 25041 25042 let width = image.width, height = image.height; 25043 25044 for ( let i = 0; i < levels; i ++ ) { 25045 25046 state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, width, height, 0, glFormat, glType, null ); 25047 25048 width >>= 1; 25049 height >>= 1; 25050 25051 } 25052 25053 } 25054 25055 } 25056 25057 } else { 25058 25059 // regular Texture (image, video, canvas) 25060 25061 // use manually created mipmaps if available 25062 // if there are no manual mipmaps 25063 // set 0 level mipmap and then use GL to generate other mipmap levels 25064 25065 if ( mipmaps.length > 0 && supportsMips ) { 25066 25067 if ( useTexStorage && allocateMemory ) { 25068 25069 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height ); 25070 25071 } 25072 25073 for ( let i = 0, il = mipmaps.length; i < il; i ++ ) { 25074 25075 mipmap = mipmaps[ i ]; 25076 25077 if ( useTexStorage ) { 25078 25079 state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap ); 25080 25081 } else { 25082 25083 state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap ); 25084 25085 } 25086 25087 } 25088 25089 texture.generateMipmaps = false; 25090 25091 } else { 25092 25093 if ( useTexStorage ) { 25094 25095 if ( allocateMemory ) { 25096 25097 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); 25098 25099 } 25100 25101 state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image ); 25102 25103 } else { 25104 25105 state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image ); 25106 25107 } 25108 25109 } 25110 25111 } 25112 25113 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { 25114 25115 generateMipmap( textureType ); 25116 25117 } 25118 25119 sourceProperties.__version = source.version; 25120 25121 if ( texture.onUpdate ) texture.onUpdate( texture ); 25122 25123 } 25124 25125 textureProperties.__version = texture.version; 25126 25127 } 25128 25129 function uploadCubeTexture( textureProperties, texture, slot ) { 25130 25131 if ( texture.image.length !== 6 ) return; 25132 25133 const forceUpload = initTexture( textureProperties, texture ); 25134 const source = texture.source; 25135 25136 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot ); 25137 25138 const sourceProperties = properties.get( source ); 25139 25140 if ( source.version !== sourceProperties.__version || forceUpload === true ) { 25141 25142 state.activeTexture( _gl.TEXTURE0 + slot ); 25143 25144 const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace ); 25145 const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace ); 25146 const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL; 25147 25148 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); 25149 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); 25150 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); 25151 _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion ); 25152 25153 const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ); 25154 const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); 25155 25156 const cubeImage = []; 25157 25158 for ( let i = 0; i < 6; i ++ ) { 25159 25160 if ( ! isCompressed && ! isDataTexture ) { 25161 25162 cubeImage[ i ] = resizeImage( texture.image[ i ], false, true, capabilities.maxCubemapSize ); 25163 25164 } else { 25165 25166 cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ]; 25167 25168 } 25169 25170 cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] ); 25171 25172 } 25173 25174 const image = cubeImage[ 0 ], 25175 supportsMips = isPowerOfTwo$1( image ) || isWebGL2, 25176 glFormat = utils.convert( texture.format, texture.colorSpace ), 25177 glType = utils.convert( texture.type ), 25178 glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); 25179 25180 const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true ); 25181 const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); 25182 let levels = getMipLevels( texture, image, supportsMips ); 25183 25184 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, supportsMips ); 25185 25186 let mipmaps; 25187 25188 if ( isCompressed ) { 25189 25190 if ( useTexStorage && allocateMemory ) { 25191 25192 state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height ); 25193 25194 } 25195 25196 for ( let i = 0; i < 6; i ++ ) { 25197 25198 mipmaps = cubeImage[ i ].mipmaps; 25199 25200 for ( let j = 0; j < mipmaps.length; j ++ ) { 25201 25202 const mipmap = mipmaps[ j ]; 25203 25204 if ( texture.format !== RGBAFormat ) { 25205 25206 if ( glFormat !== null ) { 25207 25208 if ( useTexStorage ) { 25209 25210 state.compressedTexSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); 25211 25212 } else { 25213 25214 state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data ); 25215 25216 } 25217 25218 } else { 25219 25220 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); 25221 25222 } 25223 25224 } else { 25225 25226 if ( useTexStorage ) { 25227 25228 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); 25229 25230 } else { 25231 25232 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 25233 25234 } 25235 25236 } 25237 25238 } 25239 25240 } 25241 25242 } else { 25243 25244 mipmaps = texture.mipmaps; 25245 25246 if ( useTexStorage && allocateMemory ) { 25247 25248 // TODO: Uniformly handle mipmap definitions 25249 // Normal textures and compressed cube textures define base level + mips with their mipmap array 25250 // Uncompressed cube textures use their mipmap array only for mips (no base level) 25251 25252 if ( mipmaps.length > 0 ) levels ++; 25253 25254 state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, cubeImage[ 0 ].width, cubeImage[ 0 ].height ); 25255 25256 } 25257 25258 for ( let i = 0; i < 6; i ++ ) { 25259 25260 if ( isDataTexture ) { 25261 25262 if ( useTexStorage ) { 25263 25264 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data ); 25265 25266 } else { 25267 25268 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); 25269 25270 } 25271 25272 for ( let j = 0; j < mipmaps.length; j ++ ) { 25273 25274 const mipmap = mipmaps[ j ]; 25275 const mipmapImage = mipmap.image[ i ].image; 25276 25277 if ( useTexStorage ) { 25278 25279 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data ); 25280 25281 } else { 25282 25283 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data ); 25284 25285 } 25286 25287 } 25288 25289 } else { 25290 25291 if ( useTexStorage ) { 25292 25293 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] ); 25294 25295 } else { 25296 25297 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] ); 25298 25299 } 25300 25301 for ( let j = 0; j < mipmaps.length; j ++ ) { 25302 25303 const mipmap = mipmaps[ j ]; 25304 25305 if ( useTexStorage ) { 25306 25307 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] ); 25308 25309 } else { 25310 25311 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] ); 25312 25313 } 25314 25315 } 25316 25317 } 25318 25319 } 25320 25321 } 25322 25323 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { 25324 25325 // We assume images for cube map have the same size. 25326 generateMipmap( _gl.TEXTURE_CUBE_MAP ); 25327 25328 } 25329 25330 sourceProperties.__version = source.version; 25331 25332 if ( texture.onUpdate ) texture.onUpdate( texture ); 25333 25334 } 25335 25336 textureProperties.__version = texture.version; 25337 25338 } 25339 25340 // Render targets 25341 25342 // Setup storage for target texture and bind it to correct framebuffer 25343 function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget, level ) { 25344 25345 const glFormat = utils.convert( texture.format, texture.colorSpace ); 25346 const glType = utils.convert( texture.type ); 25347 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); 25348 const renderTargetProperties = properties.get( renderTarget ); 25349 25350 if ( ! renderTargetProperties.__hasExternalTextures ) { 25351 25352 const width = Math.max( 1, renderTarget.width >> level ); 25353 const height = Math.max( 1, renderTarget.height >> level ); 25354 25355 if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) { 25356 25357 state.texImage3D( textureTarget, level, glInternalFormat, width, height, renderTarget.depth, 0, glFormat, glType, null ); 25358 25359 } else { 25360 25361 state.texImage2D( textureTarget, level, glInternalFormat, width, height, 0, glFormat, glType, null ); 25362 25363 } 25364 25365 } 25366 25367 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 25368 25369 if ( useMultisampledRTT( renderTarget ) ) { 25370 25371 multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) ); 25372 25373 } else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) { // see #24753 25374 25375 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, level ); 25376 25377 } 25378 25379 state.bindFramebuffer( _gl.FRAMEBUFFER, null ); 25380 25381 } 25382 25383 25384 // Setup storage for internal depth/stencil buffers and bind to correct framebuffer 25385 function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) { 25386 25387 _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); 25388 25389 if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) { 25390 25391 let glInternalFormat = ( isWebGL2 === true ) ? _gl.DEPTH_COMPONENT24 : _gl.DEPTH_COMPONENT16; 25392 25393 if ( isMultisample || useMultisampledRTT( renderTarget ) ) { 25394 25395 const depthTexture = renderTarget.depthTexture; 25396 25397 if ( depthTexture && depthTexture.isDepthTexture ) { 25398 25399 if ( depthTexture.type === FloatType ) { 25400 25401 glInternalFormat = _gl.DEPTH_COMPONENT32F; 25402 25403 } else if ( depthTexture.type === UnsignedIntType ) { 25404 25405 glInternalFormat = _gl.DEPTH_COMPONENT24; 25406 25407 } 25408 25409 } 25410 25411 const samples = getRenderTargetSamples( renderTarget ); 25412 25413 if ( useMultisampledRTT( renderTarget ) ) { 25414 25415 multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25416 25417 } else { 25418 25419 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25420 25421 } 25422 25423 } else { 25424 25425 _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); 25426 25427 } 25428 25429 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); 25430 25431 } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) { 25432 25433 const samples = getRenderTargetSamples( renderTarget ); 25434 25435 if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { 25436 25437 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height ); 25438 25439 } else if ( useMultisampledRTT( renderTarget ) ) { 25440 25441 multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height ); 25442 25443 } else { 25444 25445 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height ); 25446 25447 } 25448 25449 25450 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); 25451 25452 } else { 25453 25454 const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [ renderTarget.texture ]; 25455 25456 for ( let i = 0; i < textures.length; i ++ ) { 25457 25458 const texture = textures[ i ]; 25459 25460 const glFormat = utils.convert( texture.format, texture.colorSpace ); 25461 const glType = utils.convert( texture.type ); 25462 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace ); 25463 const samples = getRenderTargetSamples( renderTarget ); 25464 25465 if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) { 25466 25467 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25468 25469 } else if ( useMultisampledRTT( renderTarget ) ) { 25470 25471 multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25472 25473 } else { 25474 25475 _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height ); 25476 25477 } 25478 25479 } 25480 25481 } 25482 25483 _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); 25484 25485 } 25486 25487 // Setup resources for a Depth Texture for a FBO (needs an extension) 25488 function setupDepthTexture( framebuffer, renderTarget ) { 25489 25490 const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget ); 25491 if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); 25492 25493 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 25494 25495 if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { 25496 25497 throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); 25498 25499 } 25500 25501 // upload an empty depth texture with framebuffer size 25502 if ( ! properties.get( renderTarget.depthTexture ).__webglTexture || 25503 renderTarget.depthTexture.image.width !== renderTarget.width || 25504 renderTarget.depthTexture.image.height !== renderTarget.height ) { 25505 25506 renderTarget.depthTexture.image.width = renderTarget.width; 25507 renderTarget.depthTexture.image.height = renderTarget.height; 25508 renderTarget.depthTexture.needsUpdate = true; 25509 25510 } 25511 25512 setTexture2D( renderTarget.depthTexture, 0 ); 25513 25514 const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; 25515 const samples = getRenderTargetSamples( renderTarget ); 25516 25517 if ( renderTarget.depthTexture.format === DepthFormat ) { 25518 25519 if ( useMultisampledRTT( renderTarget ) ) { 25520 25521 multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); 25522 25523 } else { 25524 25525 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); 25526 25527 } 25528 25529 } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { 25530 25531 if ( useMultisampledRTT( renderTarget ) ) { 25532 25533 multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples ); 25534 25535 } else { 25536 25537 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); 25538 25539 } 25540 25541 } else { 25542 25543 throw new Error( 'Unknown depthTexture format' ); 25544 25545 } 25546 25547 } 25548 25549 // Setup GL resources for a non-texture depth buffer 25550 function setupDepthRenderbuffer( renderTarget ) { 25551 25552 const renderTargetProperties = properties.get( renderTarget ); 25553 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); 25554 25555 if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) { 25556 25557 if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); 25558 25559 setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); 25560 25561 } else { 25562 25563 if ( isCube ) { 25564 25565 renderTargetProperties.__webglDepthbuffer = []; 25566 25567 for ( let i = 0; i < 6; i ++ ) { 25568 25569 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); 25570 renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); 25571 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false ); 25572 25573 } 25574 25575 } else { 25576 25577 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 25578 renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); 25579 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false ); 25580 25581 } 25582 25583 } 25584 25585 state.bindFramebuffer( _gl.FRAMEBUFFER, null ); 25586 25587 } 25588 25589 // rebind framebuffer with external textures 25590 function rebindTextures( renderTarget, colorTexture, depthTexture ) { 25591 25592 const renderTargetProperties = properties.get( renderTarget ); 25593 25594 if ( colorTexture !== undefined ) { 25595 25596 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, 0 ); 25597 25598 } 25599 25600 if ( depthTexture !== undefined ) { 25601 25602 setupDepthRenderbuffer( renderTarget ); 25603 25604 } 25605 25606 } 25607 25608 // Set up GL resources for the render target 25609 function setupRenderTarget( renderTarget ) { 25610 25611 const texture = renderTarget.texture; 25612 25613 const renderTargetProperties = properties.get( renderTarget ); 25614 const textureProperties = properties.get( texture ); 25615 25616 renderTarget.addEventListener( 'dispose', onRenderTargetDispose ); 25617 25618 if ( renderTarget.isWebGLMultipleRenderTargets !== true ) { 25619 25620 if ( textureProperties.__webglTexture === undefined ) { 25621 25622 textureProperties.__webglTexture = _gl.createTexture(); 25623 25624 } 25625 25626 textureProperties.__version = texture.version; 25627 info.memory.textures ++; 25628 25629 } 25630 25631 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true ); 25632 const isMultipleRenderTargets = ( renderTarget.isWebGLMultipleRenderTargets === true ); 25633 const supportsMips = isPowerOfTwo$1( renderTarget ) || isWebGL2; 25634 25635 // Setup framebuffer 25636 25637 if ( isCube ) { 25638 25639 renderTargetProperties.__webglFramebuffer = []; 25640 25641 for ( let i = 0; i < 6; i ++ ) { 25642 25643 if ( isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0 ) { 25644 25645 renderTargetProperties.__webglFramebuffer[ i ] = []; 25646 25647 for ( let level = 0; level < texture.mipmaps.length; level ++ ) { 25648 25649 renderTargetProperties.__webglFramebuffer[ i ][ level ] = _gl.createFramebuffer(); 25650 25651 } 25652 25653 } else { 25654 25655 renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer(); 25656 25657 } 25658 25659 } 25660 25661 } else { 25662 25663 if ( isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0 ) { 25664 25665 renderTargetProperties.__webglFramebuffer = []; 25666 25667 for ( let level = 0; level < texture.mipmaps.length; level ++ ) { 25668 25669 renderTargetProperties.__webglFramebuffer[ level ] = _gl.createFramebuffer(); 25670 25671 } 25672 25673 } else { 25674 25675 renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); 25676 25677 } 25678 25679 if ( isMultipleRenderTargets ) { 25680 25681 if ( capabilities.drawBuffers ) { 25682 25683 const textures = renderTarget.texture; 25684 25685 for ( let i = 0, il = textures.length; i < il; i ++ ) { 25686 25687 const attachmentProperties = properties.get( textures[ i ] ); 25688 25689 if ( attachmentProperties.__webglTexture === undefined ) { 25690 25691 attachmentProperties.__webglTexture = _gl.createTexture(); 25692 25693 info.memory.textures ++; 25694 25695 } 25696 25697 } 25698 25699 } else { 25700 25701 console.warn( 'THREE.WebGLRenderer: WebGLMultipleRenderTargets can only be used with WebGL2 or WEBGL_draw_buffers extension.' ); 25702 25703 } 25704 25705 } 25706 25707 if ( ( isWebGL2 && renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) { 25708 25709 const textures = isMultipleRenderTargets ? texture : [ texture ]; 25710 25711 renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer(); 25712 renderTargetProperties.__webglColorRenderbuffer = []; 25713 25714 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25715 25716 for ( let i = 0; i < textures.length; i ++ ) { 25717 25718 const texture = textures[ i ]; 25719 renderTargetProperties.__webglColorRenderbuffer[ i ] = _gl.createRenderbuffer(); 25720 25721 _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 25722 25723 const glFormat = utils.convert( texture.format, texture.colorSpace ); 25724 const glType = utils.convert( texture.type ); 25725 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true ); 25726 const samples = getRenderTargetSamples( renderTarget ); 25727 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); 25728 25729 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 25730 25731 } 25732 25733 _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); 25734 25735 if ( renderTarget.depthBuffer ) { 25736 25737 renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer(); 25738 setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true ); 25739 25740 } 25741 25742 state.bindFramebuffer( _gl.FRAMEBUFFER, null ); 25743 25744 } 25745 25746 } 25747 25748 // Setup color buffer 25749 25750 if ( isCube ) { 25751 25752 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); 25753 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, supportsMips ); 25754 25755 for ( let i = 0; i < 6; i ++ ) { 25756 25757 if ( isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0 ) { 25758 25759 for ( let level = 0; level < texture.mipmaps.length; level ++ ) { 25760 25761 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ][ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level ); 25762 25763 } 25764 25765 } else { 25766 25767 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0 ); 25768 25769 } 25770 25771 } 25772 25773 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { 25774 25775 generateMipmap( _gl.TEXTURE_CUBE_MAP ); 25776 25777 } 25778 25779 state.unbindTexture(); 25780 25781 } else if ( isMultipleRenderTargets ) { 25782 25783 const textures = renderTarget.texture; 25784 25785 for ( let i = 0, il = textures.length; i < il; i ++ ) { 25786 25787 const attachment = textures[ i ]; 25788 const attachmentProperties = properties.get( attachment ); 25789 25790 state.bindTexture( _gl.TEXTURE_2D, attachmentProperties.__webglTexture ); 25791 setTextureParameters( _gl.TEXTURE_2D, attachment, supportsMips ); 25792 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, 0 ); 25793 25794 if ( textureNeedsGenerateMipmaps( attachment, supportsMips ) ) { 25795 25796 generateMipmap( _gl.TEXTURE_2D ); 25797 25798 } 25799 25800 } 25801 25802 state.unbindTexture(); 25803 25804 } else { 25805 25806 let glTextureType = _gl.TEXTURE_2D; 25807 25808 if ( renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) { 25809 25810 if ( isWebGL2 ) { 25811 25812 glTextureType = renderTarget.isWebGL3DRenderTarget ? _gl.TEXTURE_3D : _gl.TEXTURE_2D_ARRAY; 25813 25814 } else { 25815 25816 console.error( 'THREE.WebGLTextures: THREE.Data3DTexture and THREE.DataArrayTexture only supported with WebGL2.' ); 25817 25818 } 25819 25820 } 25821 25822 state.bindTexture( glTextureType, textureProperties.__webglTexture ); 25823 setTextureParameters( glTextureType, texture, supportsMips ); 25824 25825 if ( isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0 ) { 25826 25827 for ( let level = 0; level < texture.mipmaps.length; level ++ ) { 25828 25829 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, level ); 25830 25831 } 25832 25833 } else { 25834 25835 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, 0 ); 25836 25837 } 25838 25839 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { 25840 25841 generateMipmap( glTextureType ); 25842 25843 } 25844 25845 state.unbindTexture(); 25846 25847 } 25848 25849 // Setup depth and stencil buffers 25850 25851 if ( renderTarget.depthBuffer ) { 25852 25853 setupDepthRenderbuffer( renderTarget ); 25854 25855 } 25856 25857 } 25858 25859 function updateRenderTargetMipmap( renderTarget ) { 25860 25861 const supportsMips = isPowerOfTwo$1( renderTarget ) || isWebGL2; 25862 25863 const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [ renderTarget.texture ]; 25864 25865 for ( let i = 0, il = textures.length; i < il; i ++ ) { 25866 25867 const texture = textures[ i ]; 25868 25869 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) { 25870 25871 const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; 25872 const webglTexture = properties.get( texture ).__webglTexture; 25873 25874 state.bindTexture( target, webglTexture ); 25875 generateMipmap( target ); 25876 state.unbindTexture(); 25877 25878 } 25879 25880 } 25881 25882 } 25883 25884 function updateMultisampleRenderTarget( renderTarget ) { 25885 25886 if ( ( isWebGL2 && renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) { 25887 25888 const textures = renderTarget.isWebGLMultipleRenderTargets ? renderTarget.texture : [ renderTarget.texture ]; 25889 const width = renderTarget.width; 25890 const height = renderTarget.height; 25891 let mask = _gl.COLOR_BUFFER_BIT; 25892 const invalidationArray = []; 25893 const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; 25894 const renderTargetProperties = properties.get( renderTarget ); 25895 const isMultipleRenderTargets = ( renderTarget.isWebGLMultipleRenderTargets === true ); 25896 25897 // If MRT we need to remove FBO attachments 25898 if ( isMultipleRenderTargets ) { 25899 25900 for ( let i = 0; i < textures.length; i ++ ) { 25901 25902 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25903 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null ); 25904 25905 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 25906 _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0 ); 25907 25908 } 25909 25910 } 25911 25912 state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25913 state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 25914 25915 for ( let i = 0; i < textures.length; i ++ ) { 25916 25917 invalidationArray.push( _gl.COLOR_ATTACHMENT0 + i ); 25918 25919 if ( renderTarget.depthBuffer ) { 25920 25921 invalidationArray.push( depthStyle ); 25922 25923 } 25924 25925 const ignoreDepthValues = ( renderTargetProperties.__ignoreDepthValues !== undefined ) ? renderTargetProperties.__ignoreDepthValues : false; 25926 25927 if ( ignoreDepthValues === false ) { 25928 25929 if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT; 25930 if ( renderTarget.stencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT; 25931 25932 } 25933 25934 if ( isMultipleRenderTargets ) { 25935 25936 _gl.framebufferRenderbuffer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 25937 25938 } 25939 25940 if ( ignoreDepthValues === true ) { 25941 25942 _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, [ depthStyle ] ); 25943 _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] ); 25944 25945 } 25946 25947 if ( isMultipleRenderTargets ) { 25948 25949 const webglTexture = properties.get( textures[ i ] ).__webglTexture; 25950 _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0 ); 25951 25952 } 25953 25954 _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST ); 25955 25956 if ( supportsInvalidateFramebuffer ) { 25957 25958 _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArray ); 25959 25960 } 25961 25962 25963 } 25964 25965 state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null ); 25966 state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null ); 25967 25968 // If MRT since pre-blit we removed the FBO we need to reconstruct the attachments 25969 if ( isMultipleRenderTargets ) { 25970 25971 for ( let i = 0; i < textures.length; i ++ ) { 25972 25973 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25974 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); 25975 25976 const webglTexture = properties.get( textures[ i ] ).__webglTexture; 25977 25978 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 25979 _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, webglTexture, 0 ); 25980 25981 } 25982 25983 } 25984 25985 state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); 25986 25987 } 25988 25989 } 25990 25991 function getRenderTargetSamples( renderTarget ) { 25992 25993 return Math.min( capabilities.maxSamples, renderTarget.samples ); 25994 25995 } 25996 25997 function useMultisampledRTT( renderTarget ) { 25998 25999 const renderTargetProperties = properties.get( renderTarget ); 26000 26001 return isWebGL2 && renderTarget.samples > 0 && extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true && renderTargetProperties.__useRenderToTexture !== false; 26002 26003 } 26004 26005 function updateVideoTexture( texture ) { 26006 26007 const frame = info.render.frame; 26008 26009 // Check the last frame we updated the VideoTexture 26010 26011 if ( _videoTextures.get( texture ) !== frame ) { 26012 26013 _videoTextures.set( texture, frame ); 26014 texture.update(); 26015 26016 } 26017 26018 } 26019 26020 function verifyColorSpace( texture, image ) { 26021 26022 const colorSpace = texture.colorSpace; 26023 const format = texture.format; 26024 const type = texture.type; 26025 26026 if ( texture.isCompressedTexture === true || texture.isVideoTexture === true || texture.format === _SRGBAFormat ) return image; 26027 26028 if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) { 26029 26030 // sRGB 26031 26032 if ( ColorManagement.getTransfer( colorSpace ) === SRGBTransfer ) { 26033 26034 if ( isWebGL2 === false ) { 26035 26036 // in WebGL 1, try to use EXT_sRGB extension and unsized formats 26037 26038 if ( extensions.has( 'EXT_sRGB' ) === true && format === RGBAFormat ) { 26039 26040 texture.format = _SRGBAFormat; 26041 26042 // it's not possible to generate mips in WebGL 1 with this extension 26043 26044 texture.minFilter = LinearFilter; 26045 texture.generateMipmaps = false; 26046 26047 } else { 26048 26049 // slow fallback (CPU decode) 26050 26051 image = ImageUtils.sRGBToLinear( image ); 26052 26053 } 26054 26055 } else { 26056 26057 // in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format 26058 26059 if ( format !== RGBAFormat || type !== UnsignedByteType ) { 26060 26061 console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' ); 26062 26063 } 26064 26065 } 26066 26067 } else { 26068 26069 console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace ); 26070 26071 } 26072 26073 } 26074 26075 return image
vendor: 16,386 bytes, lines 26075-26742
26075; 26076 26077 } 26078 26079 // 26080 26081 this.allocateTextureUnit = allocateTextureUnit; 26082 this.resetTextureUnits = resetTextureUnits; 26083 26084 this.setTexture2D = setTexture2D; 26085 this.setTexture2DArray = setTexture2DArray; 26086 this.setTexture3D = setTexture3D; 26087 this.setTextureCube = setTextureCube; 26088 this.rebindTextures = rebindTextures; 26089 this.setupRenderTarget = setupRenderTarget; 26090 this.updateRenderTargetMipmap = updateRenderTargetMipmap; 26091 this.updateMultisampleRenderTarget = updateMultisampleRenderTarget; 26092 this.setupDepthRenderbuffer = setupDepthRenderbuffer; 26093 this.setupFrameBufferTexture = setupFrameBufferTexture; 26094 this.useMultisampledRTT = useMultisampledRTT; 26095 26096} 26097 26098function WebGLUtils( gl, extensions, capabilities ) { 26099 26100 const isWebGL2 = capabilities.isWebGL2; 26101 26102 function convert( p, colorSpace = NoColorSpace ) { 26103 26104 let extension; 26105 26106 const transfer = ColorManagement.getTransfer( colorSpace ); 26107 26108 if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; 26109 if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; 26110 if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; 26111 26112 if ( p === ByteType ) return gl.BYTE; 26113 if ( p === ShortType ) return gl.SHORT; 26114 if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; 26115 if ( p === IntType ) return gl.INT; 26116 if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; 26117 if ( p === FloatType ) return gl.FLOAT; 26118 26119 if ( p === HalfFloatType ) { 26120 26121 if ( isWebGL2 ) return gl.HALF_FLOAT; 26122 26123 extension = extensions.get( 'OES_texture_half_float' ); 26124 26125 if ( extension !== null ) { 26126 26127 return extension.HALF_FLOAT_OES; 26128 26129 } else { 26130 26131 return null; 26132 26133 } 26134 26135 } 26136 26137 if ( p === AlphaFormat ) return gl.ALPHA; 26138 if ( p === RGBAFormat ) return gl.RGBA; 26139 if ( p === LuminanceFormat ) return gl.LUMINANCE; 26140 if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; 26141 if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; 26142 if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; 26143 26144 // WebGL 1 sRGB fallback 26145 26146 if ( p === _SRGBAFormat ) { 26147 26148 extension = extensions.get( 'EXT_sRGB' ); 26149 26150 if ( extension !== null ) { 26151 26152 return extension.SRGB_ALPHA_EXT; 26153 26154 } else { 26155 26156 return null; 26157 26158 } 26159 26160 } 26161 26162 // WebGL2 formats. 26163 26164 if ( p === RedFormat ) return gl.RED; 26165 if ( p === RedIntegerFormat ) return gl.RED_INTEGER; 26166 if ( p === RGFormat ) return gl.RG; 26167 if ( p === RGIntegerFormat ) return gl.RG_INTEGER; 26168 if ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER; 26169 26170 // S3TC 26171 26172 if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { 26173 26174 if ( transfer === SRGBTransfer ) { 26175 26176 extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); 26177 26178 if ( extension !== null ) { 26179 26180 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT; 26181 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; 26182 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; 26183 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; 26184 26185 } else { 26186 26187 return null; 26188 26189 } 26190 26191 } else { 26192 26193 extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); 26194 26195 if ( extension !== null ) { 26196 26197 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; 26198 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; 26199 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; 26200 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; 26201 26202 } else { 26203 26204 return null; 26205 26206 } 26207 26208 } 26209 26210 } 26211 26212 // PVRTC 26213 26214 if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { 26215 26216 extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); 26217 26218 if ( extension !== null ) { 26219 26220 if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; 26221 if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; 26222 if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; 26223 if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; 26224 26225 } else { 26226 26227 return null; 26228 26229 } 26230 26231 } 26232 26233 // ETC1 26234 26235 if ( p === RGB_ETC1_Format ) { 26236 26237 extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); 26238 26239 if ( extension !== null ) { 26240 26241 return extension.COMPRESSED_RGB_ETC1_WEBGL; 26242 26243 } else { 26244 26245 return null; 26246 26247 } 26248 26249 } 26250 26251 // ETC2 26252 26253 if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { 26254 26255 extension = extensions.get( 'WEBGL_compressed_texture_etc' ); 26256 26257 if ( extension !== null ) { 26258 26259 if ( p === RGB_ETC2_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; 26260 if ( p === RGBA_ETC2_EAC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; 26261 26262 } else { 26263 26264 return null; 26265 26266 } 26267 26268 } 26269 26270 // ASTC 26271 26272 if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format || 26273 p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format || 26274 p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format || 26275 p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format || 26276 p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) { 26277 26278 extension = extensions.get( 'WEBGL_compressed_texture_astc' ); 26279 26280 if ( extension !== null ) { 26281 26282 if ( p === RGBA_ASTC_4x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; 26283 if ( p === RGBA_ASTC_5x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; 26284 if ( p === RGBA_ASTC_5x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; 26285 if ( p === RGBA_ASTC_6x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; 26286 if ( p === RGBA_ASTC_6x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; 26287 if ( p === RGBA_ASTC_8x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; 26288 if ( p === RGBA_ASTC_8x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; 26289 if ( p === RGBA_ASTC_8x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; 26290 if ( p === RGBA_ASTC_10x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; 26291 if ( p === RGBA_ASTC_10x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; 26292 if ( p === RGBA_ASTC_10x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; 26293 if ( p === RGBA_ASTC_10x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; 26294 if ( p === RGBA_ASTC_12x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; 26295 if ( p === RGBA_ASTC_12x12_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; 26296 26297 } else { 26298 26299 return null; 26300 26301 } 26302 26303 } 26304 26305 // BPTC 26306 26307 if ( p === RGBA_BPTC_Format || p === RGB_BPTC_SIGNED_Format || p === RGB_BPTC_UNSIGNED_Format ) { 26308 26309 extension = extensions.get( 'EXT_texture_compression_bptc' ); 26310 26311 if ( extension !== null ) { 26312 26313 if ( p === RGBA_BPTC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; 26314 if ( p === RGB_BPTC_SIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT; 26315 if ( p === RGB_BPTC_UNSIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT; 26316 26317 } else { 26318 26319 return null; 26320 26321 } 26322 26323 } 26324 26325 // RGTC 26326 26327 if ( p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format ) { 26328 26329 extension = extensions.get( 'EXT_texture_compression_rgtc' ); 26330 26331 if ( extension !== null ) { 26332 26333 if ( p === RGBA_BPTC_Format ) return extension.COMPRESSED_RED_RGTC1_EXT; 26334 if ( p === SIGNED_RED_RGTC1_Format ) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT; 26335 if ( p === RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT; 26336 if ( p === SIGNED_RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT; 26337 26338 } else { 26339 26340 return null; 26341 26342 } 26343 26344 } 26345 26346 // 26347 26348 if ( p === UnsignedInt248Type ) { 26349 26350 if ( isWebGL2 ) return gl.UNSIGNED_INT_24_8; 26351 26352 extension = extensions.get( 'WEBGL_depth_texture' ); 26353 26354 if ( extension !== null ) { 26355 26356 return extension.UNSIGNED_INT_24_8_WEBGL; 26357 26358 } else { 26359 26360 return null; 26361 26362 } 26363 26364 } 26365 26366 // if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats) 26367 26368 return ( gl[ p ] !== undefined ) ? gl[ p ] : null; 26369 26370 } 26371 26372 return { convert: convert }; 26373 26374} 26375 26376class ArrayCamera extends PerspectiveCamera { 26377 26378 constructor( array = [] ) { 26379 26380 super(); 26381 26382 this.isArrayCamera = true; 26383 26384 this.cameras = array; 26385 26386 } 26387 26388} 26389 26390class Group extends Object3D { 26391 26392 constructor() { 26393 26394 super(); 26395 26396 this.isGroup = true; 26397 26398 this.type = 'Group'; 26399 26400 } 26401 26402} 26403 26404const _moveEvent = { type: 'move' }; 26405 26406class WebXRController { 26407 26408 constructor() { 26409 26410 this._targetRay = null; 26411 this._grip = null; 26412 this._hand = null; 26413 26414 } 26415 26416 getHandSpace() { 26417 26418 if ( this._hand === null ) { 26419 26420 this._hand = new Group(); 26421 this._hand.matrixAutoUpdate = false; 26422 this._hand.visible = false; 26423 26424 this._hand.joints = {}; 26425 this._hand.inputState = { pinching: false }; 26426 26427 } 26428 26429 return this._hand; 26430 26431 } 26432 26433 getTargetRaySpace() { 26434 26435 if ( this._targetRay === null ) { 26436 26437 this._targetRay = new Group(); 26438 this._targetRay.matrixAutoUpdate = false; 26439 this._targetRay.visible = false; 26440 this._targetRay.hasLinearVelocity = false; 26441 this._targetRay.linearVelocity = new Vector3(); 26442 this._targetRay.hasAngularVelocity = false; 26443 this._targetRay.angularVelocity = new Vector3(); 26444 26445 } 26446 26447 return this._targetRay; 26448 26449 } 26450 26451 getGripSpace() { 26452 26453 if ( this._grip === null ) { 26454 26455 this._grip = new Group(); 26456 this._grip.matrixAutoUpdate = false; 26457 this._grip.visible = false; 26458 this._grip.hasLinearVelocity = false; 26459 this._grip.linearVelocity = new Vector3(); 26460 this._grip.hasAngularVelocity = false; 26461 this._grip.angularVelocity = new Vector3(); 26462 26463 } 26464 26465 return this._grip; 26466 26467 } 26468 26469 dispatchEvent( event ) { 26470 26471 if ( this._targetRay !== null ) { 26472 26473 this._targetRay.dispatchEvent( event ); 26474 26475 } 26476 26477 if ( this._grip !== null ) { 26478 26479 this._grip.dispatchEvent( event ); 26480 26481 } 26482 26483 if ( this._hand !== null ) { 26484 26485 this._hand.dispatchEvent( event ); 26486 26487 } 26488 26489 return this; 26490 26491 } 26492 26493 connect( inputSource ) { 26494 26495 if ( inputSource && inputSource.hand ) { 26496 26497 const hand = this._hand; 26498 26499 if ( hand ) { 26500 26501 for ( const inputjoint of inputSource.hand.values() ) { 26502 26503 // Initialize hand with joints when connected 26504 this._getHandJoint( hand, inputjoint ); 26505 26506 } 26507 26508 } 26509 26510 } 26511 26512 this.dispatchEvent( { type: 'connected', data: inputSource } ); 26513 26514 return this; 26515 26516 } 26517 26518 disconnect( inputSource ) { 26519 26520 this.dispatchEvent( { type: 'disconnected', data: inputSource } ); 26521 26522 if ( this._targetRay !== null ) { 26523 26524 this._targetRay.visible = false; 26525 26526 } 26527 26528 if ( this._grip !== null ) { 26529 26530 this._grip.visible = false; 26531 26532 } 26533 26534 if ( this._hand !== null ) { 26535 26536 this._hand.visible = false; 26537 26538 } 26539 26540 return this; 26541 26542 } 26543 26544 update( inputSource, frame, referenceSpace ) { 26545 26546 let inputPose = null; 26547 let gripPose = null; 26548 let handPose = null; 26549 26550 const targetRay = this._targetRay; 26551 const grip = this._grip; 26552 const hand = this._hand; 26553 26554 if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) { 26555 26556 if ( hand && inputSource.hand ) { 26557 26558 handPose = true; 26559 26560 for ( const inputjoint of inputSource.hand.values() ) { 26561 26562 // Update the joints groups with the XRJoint poses 26563 const jointPose = frame.getJointPose( inputjoint, referenceSpace ); 26564 26565 // The transform of this joint will be updated with the joint pose on each frame 26566 const joint = this._getHandJoint( hand, inputjoint ); 26567 26568 if ( jointPose !== null ) { 26569 26570 joint.matrix.fromArray( jointPose.transform.matrix ); 26571 joint.matrix.decompose( joint.position, joint.rotation, joint.scale ); 26572 joint.matrixWorldNeedsUpdate = true; 26573 joint.jointRadius = jointPose.radius; 26574 26575 } 26576 26577 joint.visible = jointPose !== null; 26578 26579 } 26580 26581 // Custom events 26582 26583 // Check pinchz 26584 const indexTip = hand.joints[ 'index-finger-tip' ]; 26585 const thumbTip = hand.joints[ 'thumb-tip' ]; 26586 const distance = indexTip.position.distanceTo( thumbTip.position ); 26587 26588 const distanceToPinch = 0.02; 26589 const threshold = 0.005; 26590 26591 if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) { 26592 26593 hand.inputState.pinching = false; 26594 this.dispatchEvent( { 26595 type: 'pinchend', 26596 handedness: inputSource.handedness, 26597 target: this 26598 } ); 26599 26600 } else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) { 26601 26602 hand.inputState.pinching = true; 26603 this.dispatchEvent( { 26604 type: 'pinchstart', 26605 handedness: inputSource.handedness, 26606 target: this 26607 } ); 26608 26609 } 26610 26611 } else { 26612 26613 if ( grip !== null && inputSource.gripSpace ) { 26614 26615 gripPose = frame.getPose( inputSource.gripSpace, referenceSpace ); 26616 26617 if ( gripPose !== null ) { 26618 26619 grip.matrix.fromArray( gripPose.transform.matrix ); 26620 grip.matrix.decompose( grip.position, grip.rotation, grip.scale ); 26621 grip.matrixWorldNeedsUpdate = true; 26622 26623 if ( gripPose.linearVelocity ) { 26624 26625 grip.hasLinearVelocity = true; 26626 grip.linearVelocity.copy( gripPose.linearVelocity ); 26627 26628 } else { 26629 26630 grip.hasLinearVelocity = false; 26631 26632 } 26633 26634 if ( gripPose.angularVelocity ) { 26635 26636 grip.hasAngularVelocity = true; 26637 grip.angularVelocity.copy( gripPose.angularVelocity ); 26638 26639 } else { 26640 26641 grip.hasAngularVelocity = false; 26642 26643 } 26644 26645 } 26646 26647 } 26648 26649 } 26650 26651 if ( targetRay !== null ) { 26652 26653 inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace ); 26654 26655 // Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it 26656 if ( inputPose === null && gripPose !== null ) { 26657 26658 inputPose = gripPose; 26659 26660 } 26661 26662 if ( inputPose !== null ) { 26663 26664 targetRay.matrix.fromArray( inputPose.transform.matrix ); 26665 targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale ); 26666 targetRay.matrixWorldNeedsUpdate = true; 26667 26668 if ( inputPose.linearVelocity ) { 26669 26670 targetRay.hasLinearVelocity = true; 26671 targetRay.linearVelocity.copy( inputPose.linearVelocity ); 26672 26673 } else { 26674 26675 targetRay.hasLinearVelocity = false; 26676 26677 } 26678 26679 if ( inputPose.angularVelocity ) { 26680 26681 targetRay.hasAngularVelocity = true; 26682 targetRay.angularVelocity.copy( inputPose.angularVelocity ); 26683 26684 } else { 26685 26686 targetRay.hasAngularVelocity = false; 26687 26688 } 26689 26690 this.dispatchEvent( _moveEvent ); 26691 26692 } 26693 26694 } 26695 26696 26697 } 26698 26699 if ( targetRay !== null ) { 26700 26701 targetRay.visible = ( inputPose !== null ); 26702 26703 } 26704 26705 if ( grip !== null ) { 26706 26707 grip.visible = ( gripPose !== null ); 26708 26709 } 26710 26711 if ( hand !== null ) { 26712 26713 hand.visible = ( handPose !== null ); 26714 26715 } 26716 26717 return this; 26718 26719 } 26720 26721 // private method 26722 26723 _getHandJoint( hand, inputjoint ) { 26724 26725 if ( hand.joints[ inputjoint.jointName ] === undefined ) { 26726 26727 const joint = new Group(); 26728 joint.matrixAutoUpdate = false; 26729 joint.visible = false; 26730 hand.joints[ inputjoint.jointName ] = joint; 26731 26732 hand.add( joint ); 26733 26734 } 26735 26736 return hand.joints[ inputjoint.jointName ]; 26737 26738 } 26739 26740} 26741 26742c
vendor: 41,656 bytes, lines 26742-28561
26742lass WebXRManager extends EventDispatcher { 26743 26744 constructor( renderer, gl ) { 26745 26746 super(); 26747 26748 const scope = this; 26749 26750 let session = null; 26751 26752 let framebufferScaleFactor = 1.0; 26753 26754 let referenceSpace = null; 26755 let referenceSpaceType = 'local-floor'; 26756 // Set default foveation to maximum. 26757 let foveation = 1.0; 26758 let customReferenceSpace = null; 26759 26760 let pose = null; 26761 let glBinding = null; 26762 let glProjLayer = null; 26763 let glBaseLayer = null; 26764 let xrFrame = null; 26765 const attributes = gl.getContextAttributes(); 26766 let initialRenderTarget = null; 26767 let newRenderTarget = null; 26768 26769 const controllers = []; 26770 const controllerInputSources = []; 26771 26772 const currentSize = new Vector2(); 26773 let currentPixelRatio = null; 26774 26775 // 26776 26777 const cameraL = new PerspectiveCamera(); 26778 cameraL.layers.enable( 1 ); 26779 cameraL.viewport = new Vector4(); 26780 26781 const cameraR = new PerspectiveCamera(); 26782 cameraR.layers.enable( 2 ); 26783 cameraR.viewport = new Vector4(); 26784 26785 const cameras = [ cameraL, cameraR ]; 26786 26787 const cameraXR = new ArrayCamera(); 26788 cameraXR.layers.enable( 1 ); 26789 cameraXR.layers.enable( 2 ); 26790 26791 let _currentDepthNear = null; 26792 let _currentDepthFar = null; 26793 26794 // 26795 26796 this.cameraAutoUpdate = true; 26797 this.enabled = false; 26798 26799 this.isPresenting = false; 26800 26801 this.getController = function ( index ) { 26802 26803 let controller = controllers[ index ]; 26804 26805 if ( controller === undefined ) { 26806 26807 controller = new WebXRController(); 26808 controllers[ index ] = controller; 26809 26810 } 26811 26812 return controller.getTargetRaySpace(); 26813 26814 }; 26815 26816 this.getControllerGrip = function ( index ) { 26817 26818 let controller = controllers[ index ]; 26819 26820 if ( controller === undefined ) { 26821 26822 controller = new WebXRController(); 26823 controllers[ index ] = controller; 26824 26825 } 26826 26827 return controller.getGripSpace(); 26828 26829 }; 26830 26831 this.getHand = function ( index ) { 26832 26833 let controller = controllers[ index ]; 26834 26835 if ( controller === undefined ) { 26836 26837 controller = new WebXRController(); 26838 controllers[ index ] = controller; 26839 26840 } 26841 26842 return controller.getHandSpace(); 26843 26844 }; 26845 26846 // 26847 26848 function onSessionEvent( event ) { 26849 26850 const controllerIndex = controllerInputSources.indexOf( event.inputSource ); 26851 26852 if ( controllerIndex === - 1 ) { 26853 26854 return; 26855 26856 } 26857 26858 const controller = controllers[ controllerIndex ]; 26859 26860 if ( controller !== undefined ) { 26861 26862 controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace ); 26863 controller.dispatchEvent( { type: event.type, data: event.inputSource } ); 26864 26865 } 26866 26867 } 26868 26869 function onSessionEnd() { 26870 26871 session.removeEventListener( 'select', onSessionEvent ); 26872 session.removeEventListener( 'selectstart', onSessionEvent ); 26873 session.removeEventListener( 'selectend', onSessionEvent ); 26874 session.removeEventListener( 'squeeze', onSessionEvent ); 26875 session.removeEventListener( 'squeezestart', onSessionEvent ); 26876 session.removeEventListener( 'squeezeend', onSessionEvent ); 26877 session.removeEventListener( 'end', onSessionEnd ); 26878 session.removeEventListener( 'inputsourceschange', onInputSourcesChange ); 26879 26880 for ( let i = 0; i < controllers.length; i ++ ) { 26881 26882 const inputSource = controllerInputSources[ i ]; 26883 26884 if ( inputSource === null ) continue; 26885 26886 controllerInputSources[ i ] = null; 26887 26888 controllers[ i ].disconnect( inputSource ); 26889 26890 } 26891 26892 _currentDepthNear = null; 26893 _currentDepthFar = null; 26894 26895 // restore framebuffer/rendering state 26896 26897 renderer.setRenderTarget( initialRenderTarget ); 26898 26899 glBaseLayer = null; 26900 glProjLayer = null; 26901 glBinding = null; 26902 session = null; 26903 newRenderTarget = null; 26904 26905 // 26906 26907 animation.stop(); 26908 26909 scope.isPresenting = false; 26910 26911 renderer.setPixelRatio( currentPixelRatio ); 26912 renderer.setSize( currentSize.width, currentSize.height, false ); 26913 26914 scope.dispatchEvent( { type: 'sessionend' } ); 26915 26916 } 26917 26918 this.setFramebufferScaleFactor = function ( value ) { 26919 26920 framebufferScaleFactor = value; 26921 26922 if ( scope.isPresenting === true ) { 26923 26924 console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' ); 26925 26926 } 26927 26928 }; 26929 26930 this.setReferenceSpaceType = function ( value ) { 26931 26932 referenceSpaceType = value; 26933 26934 if ( scope.isPresenting === true ) { 26935 26936 console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' ); 26937 26938 } 26939 26940 }; 26941 26942 this.getReferenceSpace = function () { 26943 26944 return customReferenceSpace || referenceSpace; 26945 26946 }; 26947 26948 this.setReferenceSpace = function ( space ) { 26949 26950 customReferenceSpace = space; 26951 26952 }; 26953 26954 this.getBaseLayer = function () { 26955 26956 return glProjLayer !== null ? glProjLayer : glBaseLayer; 26957 26958 }; 26959 26960 this.getBinding = function () { 26961 26962 return glBinding; 26963 26964 }; 26965 26966 this.getFrame = function () { 26967 26968 return xrFrame; 26969 26970 }; 26971 26972 this.getSession = function () { 26973 26974 return session; 26975 26976 }; 26977 26978 this.setSession = async function ( value ) { 26979 26980 session = value; 26981 26982 if ( session !== null ) { 26983 26984 initialRenderTarget = renderer.getRenderTarget(); 26985 26986 session.addEventListener( 'select', onSessionEvent ); 26987 session.addEventListener( 'selectstart', onSessionEvent ); 26988 session.addEventListener( 'selectend', onSessionEvent ); 26989 session.addEventListener( 'squeeze', onSessionEvent ); 26990 session.addEventListener( 'squeezestart', onSessionEvent ); 26991 session.addEventListener( 'squeezeend', onSessionEvent ); 26992 session.addEventListener( 'end', onSessionEnd ); 26993 session.addEventListener( 'inputsourceschange', onInputSourcesChange ); 26994 26995 if ( attributes.xrCompatible !== true ) { 26996 26997 await gl.makeXRCompatible(); 26998 26999 } 27000 27001 currentPixelRatio = renderer.getPixelRatio(); 27002 renderer.getSize( currentSize ); 27003 27004 if ( ( session.renderState.layers === undefined ) || ( renderer.capabilities.isWebGL2 === false ) ) { 27005 27006 const layerInit = { 27007 antialias: ( session.renderState.layers === undefined ) ? attributes.antialias : true, 27008 alpha: true, 27009 depth: attributes.depth, 27010 stencil: attributes.stencil, 27011 framebufferScaleFactor: framebufferScaleFactor 27012 }; 27013 27014 glBaseLayer = new XRWebGLLayer( session, gl, layerInit ); 27015 27016 session.updateRenderState( { baseLayer: glBaseLayer } ); 27017 27018 renderer.setPixelRatio( 1 ); 27019 renderer.setSize( glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, false ); 27020 27021 newRenderTarget = new WebGLRenderTarget( 27022 glBaseLayer.framebufferWidth, 27023 glBaseLayer.framebufferHeight, 27024 { 27025 format: RGBAFormat, 27026 type: UnsignedByteType, 27027 colorSpace: renderer.outputColorSpace, 27028 stencilBuffer: attributes.stencil 27029 } 27030 ); 27031 27032 } else { 27033 27034 let depthFormat = null; 27035 let depthType = null; 27036 let glDepthFormat = null; 27037 27038 if ( attributes.depth ) { 27039 27040 glDepthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24; 27041 depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat; 27042 depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType; 27043 27044 } 27045 27046 const projectionlayerInit = { 27047 colorFormat: gl.RGBA8, 27048 depthFormat: glDepthFormat, 27049 scaleFactor: framebufferScaleFactor 27050 }; 27051 27052 glBinding = new XRWebGLBinding( session, gl ); 27053 27054 glProjLayer = glBinding.createProjectionLayer( projectionlayerInit ); 27055 27056 session.updateRenderState( { layers: [ glProjLayer ] } ); 27057 27058 renderer.setPixelRatio( 1 ); 27059 renderer.setSize( glProjLayer.textureWidth, glProjLayer.textureHeight, false ); 27060 27061 newRenderTarget = new WebGLRenderTarget( 27062 glProjLayer.textureWidth, 27063 glProjLayer.textureHeight, 27064 { 27065 format: RGBAFormat, 27066 type: UnsignedByteType, 27067 depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ), 27068 stencilBuffer: attributes.stencil, 27069 colorSpace: renderer.outputColorSpace, 27070 samples: attributes.antialias ? 4 : 0 27071 } ); 27072 27073 const renderTargetProperties = renderer.properties.get( newRenderTarget ); 27074 renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues; 27075 27076 } 27077 27078 newRenderTarget.isXRRenderTarget = true; // TODO Remove this when possible, see #23278 27079 27080 this.setFoveation( foveation ); 27081 27082 customReferenceSpace = null; 27083 referenceSpace = await session.requestReferenceSpace( referenceSpaceType ); 27084 27085 animation.setContext( session ); 27086 animation.start(); 27087 27088 scope.isPresenting = true; 27089 27090 scope.dispatchEvent( { type: 'sessionstart' } ); 27091 27092 } 27093 27094 }; 27095 27096 this.getEnvironmentBlendMode = function () { 27097 27098 if ( session !== null ) { 27099 27100 return session.environmentBlendMode; 27101 27102 } 27103 27104 }; 27105 27106 function onInputSourcesChange( event ) { 27107 27108 // Notify disconnected 27109 27110 for ( let i = 0; i < event.removed.length; i ++ ) { 27111 27112 const inputSource = event.removed[ i ]; 27113 const index = controllerInputSources.indexOf( inputSource ); 27114 27115 if ( index >= 0 ) { 27116 27117 controllerInputSources[ index ] = null; 27118 controllers[ index ].disconnect( inputSource ); 27119 27120 } 27121 27122 } 27123 27124 // Notify connected 27125 27126 for ( let i = 0; i < event.added.length; i ++ ) { 27127 27128 const inputSource = event.added[ i ]; 27129 27130 let controllerIndex = controllerInputSources.indexOf( inputSource ); 27131 27132 if ( controllerIndex === - 1 ) { 27133 27134 // Assign input source a controller that currently has no input source 27135 27136 for ( let i = 0; i < controllers.length; i ++ ) { 27137 27138 if ( i >= controllerInputSources.length ) { 27139 27140 controllerInputSources.push( inputSource ); 27141 controllerIndex = i; 27142 break; 27143 27144 } else if ( controllerInputSources[ i ] === null ) { 27145 27146 controllerInputSources[ i ] = inputSource; 27147 controllerIndex = i; 27148 break; 27149 27150 } 27151 27152 } 27153 27154 // If all controllers do currently receive input we ignore new ones 27155 27156 if ( controllerIndex === - 1 ) break; 27157 27158 } 27159 27160 const controller = controllers[ controllerIndex ]; 27161 27162 if ( controller ) { 27163 27164 controller.connect( inputSource ); 27165 27166 } 27167 27168 } 27169 27170 } 27171 27172 // 27173 27174 const cameraLPos = new Vector3(); 27175 const cameraRPos = new Vector3(); 27176 27177 /** 27178 * Assumes 2 cameras that are parallel and share an X-axis, and that 27179 * the cameras' projection and world matrices have already been set. 27180 * And that near and far planes are identical for both cameras. 27181 * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 27182 */ 27183 function setProjectionFromUnion( camera, cameraL, cameraR ) { 27184 27185 cameraLPos.setFromMatrixPosition( cameraL.matrixWorld ); 27186 cameraRPos.setFromMatrixPosition( cameraR.matrixWorld ); 27187 27188 const ipd = cameraLPos.distanceTo( cameraRPos ); 27189 27190 const projL = cameraL.projectionMatrix.elements; 27191 const projR = cameraR.projectionMatrix.elements; 27192 27193 // VR systems will have identical far and near planes, and 27194 // most likely identical top and bottom frustum extents. 27195 // Use the left camera for these values. 27196 const near = projL[ 14 ] / ( projL[ 10 ] - 1 ); 27197 const far = projL[ 14 ] / ( projL[ 10 ] + 1 ); 27198 const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ]; 27199 const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ]; 27200 27201 const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ]; 27202 const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ]; 27203 const left = near * leftFov; 27204 const right = near * rightFov; 27205 27206 // Calculate the new camera's position offset from the 27207 // left camera. xOffset should be roughly half `ipd`. 27208 const zOffset = ipd / ( - leftFov + rightFov ); 27209 const xOffset = zOffset * - leftFov; 27210 27211 // TODO: Better way to apply this offset? 27212 cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale ); 27213 camera.translateX( xOffset ); 27214 camera.translateZ( zOffset ); 27215 camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale ); 27216 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); 27217 27218 // Find the union of the frustum values of the cameras and scale 27219 // the values so that the near plane's position does not change in world space, 27220 // although must now be relative to the new union camera. 27221 const near2 = near + zOffset; 27222 const far2 = far + zOffset; 27223 const left2 = left - xOffset; 27224 const right2 = right + ( ipd - xOffset ); 27225 const top2 = topFov * far / far2 * near2; 27226 const bottom2 = bottomFov * far / far2 * near2; 27227 27228 camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); 27229 camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); 27230 27231 } 27232 27233 function updateCamera( camera, parent ) { 27234 27235 if ( parent === null ) { 27236 27237 camera.matrixWorld.copy( camera.matrix ); 27238 27239 } else { 27240 27241 camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix ); 27242 27243 } 27244 27245 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert(); 27246 27247 } 27248 27249 this.updateCamera = function ( camera ) { 27250 27251 if ( session === null ) return; 27252 27253 cameraXR.near = cameraR.near = cameraL.near = camera.near; 27254 cameraXR.far = cameraR.far = cameraL.far = camera.far; 27255 27256 if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) { 27257 27258 // Note that the new renderState won't apply until the next frame. See #18320 27259 27260 session.updateRenderState( { 27261 depthNear: cameraXR.near, 27262 depthFar: cameraXR.far 27263 } ); 27264 27265 _currentDepthNear = cameraXR.near; 27266 _currentDepthFar = cameraXR.far; 27267 27268 } 27269 27270 const parent = camera.parent; 27271 const cameras = cameraXR.cameras; 27272 27273 updateCamera( cameraXR, parent ); 27274 27275 for ( let i = 0; i < cameras.length; i ++ ) { 27276 27277 updateCamera( cameras[ i ], parent ); 27278 27279 } 27280 27281 // update projection matrix for proper view frustum culling 27282 27283 if ( cameras.length === 2 ) { 27284 27285 setProjectionFromUnion( cameraXR, cameraL, cameraR ); 27286 27287 } else { 27288 27289 // assume single camera setup (AR) 27290 27291 cameraXR.projectionMatrix.copy( cameraL.projectionMatrix ); 27292 27293 } 27294 27295 // update user camera and its children 27296 27297 updateUserCamera( camera, cameraXR, parent ); 27298 27299 }; 27300 27301 function updateUserCamera( camera, cameraXR, parent ) { 27302 27303 if ( parent === null ) { 27304 27305 camera.matrix.copy( cameraXR.matrixWorld ); 27306 27307 } else { 27308 27309 camera.matrix.copy( parent.matrixWorld ); 27310 camera.matrix.invert(); 27311 camera.matrix.multiply( cameraXR.matrixWorld ); 27312 27313 } 27314 27315 camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); 27316 camera.updateMatrixWorld( true ); 27317 27318 camera.projectionMatrix.copy( cameraXR.projectionMatrix ); 27319 camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse ); 27320 27321 if ( camera.isPerspectiveCamera ) { 27322 27323 camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] ); 27324 camera.zoom = 1; 27325 27326 } 27327 27328 } 27329 27330 this.getCamera = function () { 27331 27332 return cameraXR; 27333 27334 }; 27335 27336 this.getFoveation = function () { 27337 27338 if ( glProjLayer === null && glBaseLayer === null ) { 27339 27340 return undefined; 27341 27342 } 27343 27344 return foveation; 27345 27346 }; 27347 27348 this.setFoveation = function ( value ) { 27349 27350 // 0 = no foveation = full resolution 27351 // 1 = maximum foveation = the edges render at lower resolution 27352 27353 foveation = value; 27354 27355 if ( glProjLayer !== null ) { 27356 27357 glProjLayer.fixedFoveation = value; 27358 27359 } 27360 27361 if ( glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined ) { 27362 27363 glBaseLayer.fixedFoveation = value; 27364 27365 } 27366 27367 }; 27368 27369 // Animation Loop 27370 27371 let onAnimationFrameCallback = null; 27372 27373 function onAnimationFrame( time, frame ) { 27374 27375 pose = frame.getViewerPose( customReferenceSpace || referenceSpace ); 27376 xrFrame = frame; 27377 27378 if ( pose !== null ) { 27379 27380 const views = pose.views; 27381 27382 if ( glBaseLayer !== null ) { 27383 27384 renderer.setRenderTargetFramebuffer( newRenderTarget, glBaseLayer.framebuffer ); 27385 renderer.setRenderTarget( newRenderTarget ); 27386 27387 } 27388 27389 let cameraXRNeedsUpdate = false; 27390 27391 // check if it's necessary to rebuild cameraXR's camera list 27392 27393 if ( views.length !== cameraXR.cameras.length ) { 27394 27395 cameraXR.cameras.length = 0; 27396 cameraXRNeedsUpdate = true; 27397 27398 } 27399 27400 for ( let i = 0; i < views.length; i ++ ) { 27401 27402 const view = views[ i ]; 27403 27404 let viewport = null; 27405 27406 if ( glBaseLayer !== null ) { 27407 27408 viewport = glBaseLayer.getViewport( view ); 27409 27410 } else { 27411 27412 const glSubImage = glBinding.getViewSubImage( glProjLayer, view ); 27413 viewport = glSubImage.viewport; 27414 27415 // For side-by-side projection, we only produce a single texture for both eyes. 27416 if ( i === 0 ) { 27417 27418 renderer.setRenderTargetTextures( 27419 newRenderTarget, 27420 glSubImage.colorTexture, 27421 glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture ); 27422 27423 renderer.setRenderTarget( newRenderTarget ); 27424 27425 } 27426 27427 } 27428 27429 let camera = cameras[ i ]; 27430 27431 if ( camera === undefined ) { 27432 27433 camera = new PerspectiveCamera(); 27434 camera.layers.enable( i ); 27435 camera.viewport = new Vector4(); 27436 cameras[ i ] = camera; 27437 27438 } 27439 27440 camera.matrix.fromArray( view.transform.matrix ); 27441 camera.matrix.decompose( camera.position, camera.quaternion, camera.scale ); 27442 camera.projectionMatrix.fromArray( view.projectionMatrix ); 27443 camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert(); 27444 camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); 27445 27446 if ( i === 0 ) { 27447 27448 cameraXR.matrix.copy( camera.matrix ); 27449 cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale ); 27450 27451 } 27452 27453 if ( cameraXRNeedsUpdate === true ) { 27454 27455 cameraXR.cameras.push( camera ); 27456 27457 } 27458 27459 } 27460 27461 } 27462 27463 // 27464 27465 for ( let i = 0; i < controllers.length; i ++ ) { 27466 27467 const inputSource = controllerInputSources[ i ]; 27468 const controller = controllers[ i ]; 27469 27470 if ( inputSource !== null && controller !== undefined ) { 27471 27472 controller.update( inputSource, frame, customReferenceSpace || referenceSpace ); 27473 27474 } 27475 27476 } 27477 27478 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame ); 27479 27480 if ( frame.detectedPlanes ) { 27481 27482 scope.dispatchEvent( { type: 'planesdetected', data: frame } ); 27483 27484 } 27485 27486 xrFrame = null; 27487 27488 } 27489 27490 const animation = new WebGLAnimation(); 27491 27492 animation.setAnimationLoop( onAnimationFrame ); 27493 27494 this.setAnimationLoop = function ( callback ) { 27495 27496 onAnimationFrameCallback = callback; 27497 27498 }; 27499 27500 this.dispose = function () {}; 27501 27502 } 27503 27504} 27505 27506function WebGLMaterials( renderer, properties ) { 27507 27508 function refreshTransformUniform( map, uniform ) { 27509 27510 if ( map.matrixAutoUpdate === true ) { 27511 27512 map.updateMatrix(); 27513 27514 } 27515 27516 uniform.value.copy( map.matrix ); 27517 27518 } 27519 27520 function refreshFogUniforms( uniforms, fog ) { 27521 27522 fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) ); 27523 27524 if ( fog.isFog ) { 27525 27526 uniforms.fogNear.value = fog.near; 27527 uniforms.fogFar.value = fog.far; 27528 27529 } else if ( fog.isFogExp2 ) { 27530 27531 uniforms.fogDensity.value = fog.density; 27532 27533 } 27534 27535 } 27536 27537 function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) { 27538 27539 if ( material.isMeshBasicMaterial ) { 27540 27541 refreshUniformsCommon( uniforms, material ); 27542 27543 } else if ( material.isMeshLambertMaterial ) { 27544 27545 refreshUniformsCommon( uniforms, material ); 27546 27547 } else if ( material.isMeshToonMaterial ) { 27548 27549 refreshUniformsCommon( uniforms, material ); 27550 refreshUniformsToon( uniforms, material ); 27551 27552 } else if ( material.isMeshPhongMaterial ) { 27553 27554 refreshUniformsCommon( uniforms, material ); 27555 refreshUniformsPhong( uniforms, material ); 27556 27557 } else if ( material.isMeshStandardMaterial ) { 27558 27559 refreshUniformsCommon( uniforms, material ); 27560 refreshUniformsStandard( uniforms, material ); 27561 27562 if ( material.isMeshPhysicalMaterial ) { 27563 27564 refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ); 27565 27566 } 27567 27568 } else if ( material.isMeshMatcapMaterial ) { 27569 27570 refreshUniformsCommon( uniforms, material ); 27571 refreshUniformsMatcap( uniforms, material ); 27572 27573 } else if ( material.isMeshDepthMaterial ) { 27574 27575 refreshUniformsCommon( uniforms, material ); 27576 27577 } else if ( material.isMeshDistanceMaterial ) { 27578 27579 refreshUniformsCommon( uniforms, material ); 27580 refreshUniformsDistance( uniforms, material ); 27581 27582 } else if ( material.isMeshNormalMaterial ) { 27583 27584 refreshUniformsCommon( uniforms, material ); 27585 27586 } else if ( material.isLineBasicMaterial ) { 27587 27588 refreshUniformsLine( uniforms, material ); 27589 27590 if ( material.isLineDashedMaterial ) { 27591 27592 refreshUniformsDash( uniforms, material ); 27593 27594 } 27595 27596 } else if ( material.isPointsMaterial ) { 27597 27598 refreshUniformsPoints( uniforms, material, pixelRatio, height ); 27599 27600 } else if ( material.isSpriteMaterial ) { 27601 27602 refreshUniformsSprites( uniforms, material ); 27603 27604 } else if ( material.isShadowMaterial ) { 27605 27606 uniforms.color.value.copy( material.color ); 27607 uniforms.opacity.value = material.opacity; 27608 27609 } else if ( material.isShaderMaterial ) { 27610 27611 material.uniformsNeedUpdate = false; // #15581 27612 27613 } 27614 27615 } 27616 27617 function refreshUniformsCommon( uniforms, material ) { 27618 27619 uniforms.opacity.value = material.opacity; 27620 27621 if ( material.color ) { 27622 27623 uniforms.diffuse.value.copy( material.color ); 27624 27625 } 27626 27627 if ( material.emissive ) { 27628 27629 uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity ); 27630 27631 } 27632 27633 if ( material.map ) { 27634 27635 uniforms.map.value = material.map; 27636 27637 refreshTransformUniform( material.map, uniforms.mapTransform ); 27638 27639 } 27640 27641 if ( material.alphaMap ) { 27642 27643 uniforms.alphaMap.value = material.alphaMap; 27644 27645 refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); 27646 27647 } 27648 27649 if ( material.bumpMap ) { 27650 27651 uniforms.bumpMap.value = material.bumpMap; 27652 27653 refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform ); 27654 27655 uniforms.bumpScale.value = material.bumpScale; 27656 27657 if ( material.side === BackSide ) { 27658 27659 uniforms.bumpScale.value *= - 1; 27660 27661 } 27662 27663 } 27664 27665 if ( material.normalMap ) { 27666 27667 uniforms.normalMap.value = material.normalMap; 27668 27669 refreshTransformUniform( material.normalMap, uniforms.normalMapTransform ); 27670 27671 uniforms.normalScale.value.copy( material.normalScale ); 27672 27673 if ( material.side === BackSide ) { 27674 27675 uniforms.normalScale.value.negate(); 27676 27677 } 27678 27679 } 27680 27681 if ( material.displacementMap ) { 27682 27683 uniforms.displacementMap.value = material.displacementMap; 27684 27685 refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform ); 27686 27687 uniforms.displacementScale.value = material.displacementScale; 27688 uniforms.displacementBias.value = material.displacementBias; 27689 27690 } 27691 27692 if ( material.emissiveMap ) { 27693 27694 uniforms.emissiveMap.value = material.emissiveMap; 27695 27696 refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform ); 27697 27698 } 27699 27700 if ( material.specularMap ) { 27701 27702 uniforms.specularMap.value = material.specularMap; 27703 27704 refreshTransformUniform( material.specularMap, uniforms.specularMapTransform ); 27705 27706 } 27707 27708 if ( material.alphaTest > 0 ) { 27709 27710 uniforms.alphaTest.value = material.alphaTest; 27711 27712 } 27713 27714 const envMap = properties.get( material ).envMap; 27715 27716 if ( envMap ) { 27717 27718 uniforms.envMap.value = envMap; 27719 27720 uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; 27721 27722 uniforms.reflectivity.value = material.reflectivity; 27723 uniforms.ior.value = material.ior; 27724 uniforms.refractionRatio.value = material.refractionRatio; 27725 27726 } 27727 27728 if ( material.lightMap ) { 27729 27730 uniforms.lightMap.value = material.lightMap; 27731 27732 // artist-friendly light intensity scaling factor 27733 const scaleFactor = ( renderer._useLegacyLights === true ) ? Math.PI : 1; 27734 27735 uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor; 27736 27737 refreshTransformUniform( material.lightMap, uniforms.lightMapTransform ); 27738 27739 } 27740 27741 if ( material.aoMap ) { 27742 27743 uniforms.aoMap.value = material.aoMap; 27744 uniforms.aoMapIntensity.value = material.aoMapIntensity; 27745 27746 refreshTransformUniform( material.aoMap, uniforms.aoMapTransform ); 27747 27748 } 27749 27750 } 27751 27752 function refreshUniformsLine( uniforms, material ) { 27753 27754 uniforms.diffuse.value.copy( material.color ); 27755 uniforms.opacity.value = material.opacity; 27756 27757 if ( material.map ) { 27758 27759 uniforms.map.value = material.map; 27760 27761 refreshTransformUniform( material.map, uniforms.mapTransform ); 27762 27763 } 27764 27765 } 27766 27767 function refreshUniformsDash( uniforms, material ) { 27768 27769 uniforms.dashSize.value = material.dashSize; 27770 uniforms.totalSize.value = material.dashSize + material.gapSize; 27771 uniforms.scale.value = material.scale; 27772 27773 } 27774 27775 function refreshUniformsPoints( uniforms, material, pixelRatio, height ) { 27776 27777 uniforms.diffuse.value.copy( material.color ); 27778 uniforms.opacity.value = material.opacity; 27779 uniforms.size.value = material.size * pixelRatio; 27780 uniforms.scale.value = height * 0.5; 27781 27782 if ( material.map ) { 27783 27784 uniforms.map.value = material.map; 27785 27786 refreshTransformUniform( material.map, uniforms.uvTransform ); 27787 27788 } 27789 27790 if ( material.alphaMap ) { 27791 27792 uniforms.alphaMap.value = material.alphaMap; 27793 27794 refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); 27795 27796 } 27797 27798 if ( material.alphaTest > 0 ) { 27799 27800 uniforms.alphaTest.value = material.alphaTest; 27801 27802 } 27803 27804 } 27805 27806 function refreshUniformsSprites( uniforms, material ) { 27807 27808 uniforms.diffuse.value.copy( material.color ); 27809 uniforms.opacity.value = material.opacity; 27810 uniforms.rotation.value = material.rotation; 27811 27812 if ( material.map ) { 27813 27814 uniforms.map.value = material.map; 27815 27816 refreshTransformUniform( material.map, uniforms.mapTransform ); 27817 27818 } 27819 27820 if ( material.alphaMap ) { 27821 27822 uniforms.alphaMap.value = material.alphaMap; 27823 27824 refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform ); 27825 27826 } 27827 27828 if ( material.alphaTest > 0 ) { 27829 27830 uniforms.alphaTest.value = material.alphaTest; 27831 27832 } 27833 27834 } 27835 27836 function refreshUniformsPhong( uniforms, material ) { 27837 27838 uniforms.specular.value.copy( material.specular ); 27839 uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 ) 27840 27841 } 27842 27843 function refreshUniformsToon( uniforms, material ) { 27844 27845 if ( material.gradientMap ) { 27846 27847 uniforms.gradientMap.value = material.gradientMap; 27848 27849 } 27850 27851 } 27852 27853 function refreshUniformsStandard( uniforms, material ) { 27854 27855 uniforms.metalness.value = material.metalness; 27856 27857 if ( material.metalnessMap ) { 27858 27859 uniforms.metalnessMap.value = material.metalnessMap; 27860 27861 refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform ); 27862 27863 } 27864 27865 uniforms.roughness.value = material.roughness; 27866 27867 if ( material.roughnessMap ) { 27868 27869 uniforms.roughnessMap.value = material.roughnessMap; 27870 27871 refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform ); 27872 27873 } 27874 27875 const envMap = properties.get( material ).envMap; 27876 27877 if ( envMap ) { 27878 27879 //uniforms.envMap.value = material.envMap; // part of uniforms common 27880 uniforms.envMapIntensity.value = material.envMapIntensity; 27881 27882 } 27883 27884 } 27885 27886 function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) { 27887 27888 uniforms.ior.value = material.ior; // also part of uniforms common 27889 27890 if ( material.sheen > 0 ) { 27891 27892 uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen ); 27893 27894 uniforms.sheenRoughness.value = material.sheenRoughness; 27895 27896 if ( material.sheenColorMap ) { 27897 27898 uniforms.sheenColorMap.value = material.sheenColorMap; 27899 27900 refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform ); 27901 27902 } 27903 27904 if ( material.sheenRoughnessMap ) { 27905 27906 uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap; 27907 27908 refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform ); 27909 27910 } 27911 27912 } 27913 27914 if ( material.clearcoat > 0 ) { 27915 27916 uniforms.clearcoat.value = material.clearcoat; 27917 uniforms.clearcoatRoughness.value = material.clearcoatRoughness; 27918 27919 if ( material.clearcoatMap ) { 27920 27921 uniforms.clearcoatMap.value = material.clearcoatMap; 27922 27923 refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform ); 27924 27925 } 27926 27927 if ( material.clearcoatRoughnessMap ) { 27928 27929 uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap; 27930 27931 refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform ); 27932 27933 } 27934 27935 if ( material.clearcoatNormalMap ) { 27936 27937 uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap; 27938 27939 refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform ); 27940 27941 uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale ); 27942 27943 if ( material.side === BackSide ) { 27944 27945 uniforms.clearcoatNormalScale.value.negate(); 27946 27947 } 27948 27949 } 27950 27951 } 27952 27953 if ( material.iridescence > 0 ) { 27954 27955 uniforms.iridescence.value = material.iridescence; 27956 uniforms.iridescenceIOR.value = material.iridescenceIOR; 27957 uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[ 0 ]; 27958 uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[ 1 ]; 27959 27960 if ( material.iridescenceMap ) { 27961 27962 uniforms.iridescenceMap.value = material.iridescenceMap; 27963 27964 refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform ); 27965 27966 } 27967 27968 if ( material.iridescenceThicknessMap ) { 27969 27970 uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap; 27971 27972 refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform ); 27973 27974 } 27975 27976 } 27977 27978 if ( material.transmission > 0 ) { 27979 27980 uniforms.transmission.value = material.transmission; 27981 uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture; 27982 uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height ); 27983 27984 if ( material.transmissionMap ) { 27985 27986 uniforms.transmissionMap.value = material.transmissionMap; 27987 27988 refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform ); 27989 27990 } 27991 27992 uniforms.thickness.value = material.thickness; 27993 27994 if ( material.thicknessMap ) { 27995 27996 uniforms.thicknessMap.value = material.thicknessMap; 27997 27998 refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform ); 27999 28000 } 28001 28002 uniforms.attenuationDistance.value = material.attenuationDistance; 28003 uniforms.attenuationColor.value.copy( material.attenuationColor ); 28004 28005 } 28006 28007 if ( material.anisotropy > 0 ) { 28008 28009 uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); 28010 28011 if ( material.anisotropyMap ) { 28012 28013 uniforms.anisotropyMap.value = material.anisotropyMap; 28014 28015 refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform ); 28016 28017 } 28018 28019 } 28020 28021 uniforms.specularIntensity.value = material.specularIntensity; 28022 uniforms.specularColor.value.copy( material.specularColor ); 28023 28024 if ( material.specularColorMap ) { 28025 28026 uniforms.specularColorMap.value = material.specularColorMap; 28027 28028 refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform ); 28029 28030 } 28031 28032 if ( material.specularIntensityMap ) { 28033 28034 uniforms.specularIntensityMap.value = material.specularIntensityMap; 28035 28036 refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform ); 28037 28038 } 28039 28040 } 28041 28042 function refreshUniformsMatcap( uniforms, material ) { 28043 28044 if ( material.matcap ) { 28045 28046 uniforms.matcap.value = material.matcap; 28047 28048 } 28049 28050 } 28051 28052 function refreshUniformsDistance( uniforms, material ) { 28053 28054 const light = properties.get( material ).light; 28055 28056 uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld ); 28057 uniforms.nearDistance.value = light.shadow.camera.near; 28058 uniforms.farDistance.value = light.shadow.camera.far; 28059 28060 } 28061 28062 return { 28063 refreshFogUniforms: refreshFogUniforms, 28064 refreshMaterialUniforms: refreshMaterialUniforms 28065 }; 28066 28067} 28068 28069function WebGLUniformsGroups( gl, info, capabilities, state ) { 28070 28071 let buffers = {}; 28072 let updateList = {}; 28073 let allocatedBindingPoints = []; 28074 28075 const maxBindingPoints = ( capabilities.isWebGL2 ) ? gl.getParameter( gl.MAX_UNIFORM_BUFFER_BINDINGS ) : 0; // binding points are global whereas block indices are per shader program 28076 28077 function bind( uniformsGroup, program ) { 28078 28079 const webglProgram = program.program; 28080 state.uniformBlockBinding( uniformsGroup, webglProgram ); 28081 28082 } 28083 28084 function update( uniformsGroup, program ) { 28085 28086 let buffer = buffers[ uniformsGroup.id ]; 28087 28088 if ( buffer === undefined ) { 28089 28090 prepareUniformsGroup( uniformsGroup ); 28091 28092 buffer = createBuffer( uniformsGroup ); 28093 buffers[ uniformsGroup.id ] = buffer; 28094 28095 uniformsGroup.addEventListener( 'dispose', onUniformsGroupsDispose ); 28096 28097 } 28098 28099 // ensure to update the binding points/block indices mapping for this program 28100 28101 const webglProgram = program.program; 28102 state.updateUBOMapping( uniformsGroup, webglProgram ); 28103 28104 // update UBO once per frame 28105 28106 const frame = info.render.frame; 28107 28108 if ( updateList[ uniformsGroup.id ] !== frame ) { 28109 28110 updateBufferData( uniformsGroup ); 28111 28112 updateList[ uniformsGroup.id ] = frame; 28113 28114 } 28115 28116 } 28117 28118 function createBuffer( uniformsGroup ) { 28119 28120 // the setup of an UBO is independent of a particular shader program but global 28121 28122 const bindingPointIndex = allocateBindingPointIndex(); 28123 uniformsGroup.__bindingPointIndex = bindingPointIndex; 28124 28125 const buffer = gl.createBuffer(); 28126 const size = uniformsGroup.__size; 28127 const usage = uniformsGroup.usage; 28128 28129 gl.bindBuffer( gl.UNIFORM_BUFFER, buffer ); 28130 gl.bufferData( gl.UNIFORM_BUFFER, size, usage ); 28131 gl.bindBuffer( gl.UNIFORM_BUFFER, null ); 28132 gl.bindBufferBase( gl.UNIFORM_BUFFER, bindingPointIndex, buffer ); 28133 28134 return buffer; 28135 28136 } 28137 28138 function allocateBindingPointIndex() { 28139 28140 for ( let i = 0; i < maxBindingPoints; i ++ ) { 28141 28142 if ( allocatedBindingPoints.indexOf( i ) === - 1 ) { 28143 28144 allocatedBindingPoints.push( i ); 28145 return i; 28146 28147 } 28148 28149 } 28150 28151 console.error( 'THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' ); 28152 28153 return 0; 28154 28155 } 28156 28157 function updateBufferData( uniformsGroup ) { 28158 28159 const buffer = buffers[ uniformsGroup.id ]; 28160 const uniforms = uniformsGroup.uniforms; 28161 const cache = uniformsGroup.__cache; 28162 28163 gl.bindBuffer( gl.UNIFORM_BUFFER, buffer ); 28164 28165 for ( let i = 0, il = uniforms.length; i < il; i ++ ) { 28166 28167 const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ]; 28168 28169 for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) { 28170 28171 const uniform = uniformArray[ j ]; 28172 28173 if ( hasUniformChanged( uniform, i, j, cache ) === true ) { 28174 28175 const offset = uniform.__offset; 28176 28177 const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; 28178 28179 let arrayOffset = 0; 28180 28181 for ( let k = 0; k < values.length; k ++ ) { 28182 28183 const value = values[ k ]; 28184 28185 const info = getUniformSize( value ); 28186 28187 // TODO add integer and struct support 28188 if ( typeof value === 'number' || typeof value === 'boolean' ) { 28189 28190 uniform.__data[ 0 ] = value; 28191 gl.bufferSubData( gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data ); 28192 28193 } else if ( value.isMatrix3 ) { 28194 28195 // manually converting 3x3 to 3x4 28196 28197 uniform.__data[ 0 ] = value.elements[ 0 ]; 28198 uniform.__data[ 1 ] = value.elements[ 1 ]; 28199 uniform.__data[ 2 ] = value.elements[ 2 ]; 28200 uniform.__data[ 3 ] = 0; 28201 uniform.__data[ 4 ] = value.elements[ 3 ]; 28202 uniform.__data[ 5 ] = value.elements[ 4 ]; 28203 uniform.__data[ 6 ] = value.elements[ 5 ]; 28204 uniform.__data[ 7 ] = 0; 28205 uniform.__data[ 8 ] = value.elements[ 6 ]; 28206 uniform.__data[ 9 ] = value.elements[ 7 ]; 28207 uniform.__data[ 10 ] = value.elements[ 8 ]; 28208 uniform.__data[ 11 ] = 0; 28209 28210 } else { 28211 28212 value.toArray( uniform.__data, arrayOffset ); 28213 28214 arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT; 28215 28216 } 28217 28218 } 28219 28220 gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data ); 28221 28222 } 28223 28224 } 28225 28226 } 28227 28228 gl.bindBuffer( gl.UNIFORM_BUFFER, null ); 28229 28230 } 28231 28232 function hasUniformChanged( uniform, index, indexArray, cache ) { 28233 28234 const value = uniform.value; 28235 const indexString = index + '_' + indexArray; 28236 28237 if ( cache[ indexString ] === undefined ) { 28238 28239 // cache entry does not exist so far 28240 28241 if ( typeof value === 'number' || typeof value === 'boolean' ) { 28242 28243 cache[ indexString ] = value; 28244 28245 } else { 28246 28247 cache[ indexString ] = value.clone(); 28248 28249 } 28250 28251 return true; 28252 28253 } else { 28254 28255 const cachedObject = cache[ indexString ]; 28256 28257 // compare current value with cached entry 28258 28259 if ( typeof value === 'number' || typeof value === 'boolean' ) { 28260 28261 if ( cachedObject !== value ) { 28262 28263 cache[ indexString ] = value; 28264 return true; 28265 28266 } 28267 28268 } else { 28269 28270 if ( cachedObject.equals( value ) === false ) { 28271 28272 cachedObject.copy( value ); 28273 return true; 28274 28275 } 28276 28277 } 28278 28279 } 28280 28281 return false; 28282 28283 } 28284 28285 function prepareUniformsGroup( uniformsGroup ) { 28286 28287 // determine total buffer size according to the STD140 layout 28288 // Hint: STD140 is the only supported layout in WebGL 2 28289 28290 const uniforms = uniformsGroup.uniforms; 28291 28292 let offset = 0; // global buffer offset in bytes 28293 const chunkSize = 16; // size of a chunk in bytes 28294 28295 for ( let i = 0, l = uniforms.length; i < l; i ++ ) { 28296 28297 const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ]; 28298 28299 for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) { 28300 28301 const uniform = uniformArray[ j ]; 28302 28303 const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ]; 28304 28305 for ( let k = 0, kl = values.length; k < kl; k ++ ) { 28306 28307 const value = values[ k ]; 28308 28309 const info = getUniformSize( value ); 28310 28311 // Calculate the chunk offset 28312 const chunkOffsetUniform = offset % chunkSize; 28313 28314 // Check for chunk overflow 28315 if ( chunkOffsetUniform !== 0 && ( chunkSize - chunkOffsetUniform ) < info.boundary ) { 28316 28317 // Add padding and adjust offset 28318 offset += ( chunkSize - chunkOffsetUniform ); 28319 28320 } 28321 28322 // the following two properties will be used for partial buffer updates 28323 28324 uniform.__data = new Float32Array( info.storage / Float32Array.BYTES_PER_ELEMENT ); 28325 uniform.__offset = offset; 28326 28327 28328 // Update the global offset 28329 offset += info.storage; 28330 28331 28332 } 28333 28334 } 28335 28336 } 28337 28338 // ensure correct final padding 28339 28340 const chunkOffset = offset % chunkSize; 28341 28342 if ( chunkOffset > 0 ) offset += ( chunkSize - chunkOffset ); 28343 28344 // 28345 28346 uniformsGroup.__size = offset; 28347 uniformsGroup.__cache = {}; 28348 28349 return this; 28350 28351 } 28352 28353 function getUniformSize( value ) { 28354 28355 const info = { 28356 boundary: 0, // bytes 28357 storage: 0 // bytes 28358 }; 28359 28360 // determine sizes according to STD140 28361 28362 if ( typeof value === 'number' || typeof value === 'boolean' ) { 28363 28364 // float/int/bool 28365 28366 info.boundary = 4; 28367 info.storage = 4; 28368 28369 } else if ( value.isVector2 ) { 28370 28371 // vec2 28372 28373 info.boundary = 8; 28374 info.storage = 8; 28375 28376 } else if ( value.isVector3 || value.isColor ) { 28377 28378 // vec3 28379 28380 info.boundary = 16; 28381 info.storage = 12; // evil: vec3 must start on a 16-byte boundary but it only consumes 12 bytes 28382 28383 } else if ( value.isVector4 ) { 28384 28385 // vec4 28386 28387 info.boundary = 16; 28388 info.storage = 16; 28389 28390 } else if ( value.isMatrix3 ) { 28391 28392 // mat3 (in STD140 a 3x3 matrix is represented as 3x4) 28393 28394 info.boundary = 48; 28395 info.storage = 48; 28396 28397 } else if ( value.isMatrix4 ) { 28398 28399 // mat4 28400 28401 info.boundary = 64; 28402 info.storage = 64; 28403 28404 } else if ( value.isTexture ) { 28405 28406 console.warn( 'THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.' ); 28407 28408 } else { 28409 28410 console.warn( 'THREE.WebGLRenderer: Unsupported uniform value type.', value ); 28411 28412 } 28413 28414 return info; 28415 28416 } 28417 28418 function onUniformsGroupsDispose( event ) { 28419 28420 const uniformsGroup = event.target; 28421 28422 uniformsGroup.removeEventListener( 'dispose', onUniformsGroupsDispose ); 28423 28424 const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex ); 28425 allocatedBindingPoints.splice( index, 1 ); 28426 28427 gl.deleteBuffer( buffers[ uniformsGroup.id ] ); 28428 28429 delete buffers[ uniformsGroup.id ]; 28430 delete updateList[ uniformsGroup.id ]; 28431 28432 } 28433 28434 function dispose() { 28435 28436 for ( const id in buffers ) { 28437 28438 gl.deleteBuffer( buffers[ id ] ); 28439 28440 } 28441 28442 allocatedBindingPoints = []; 28443 buffers = {}; 28444 updateList = {}; 28445 28446 } 28447 28448 return { 28449 28450 bind: bind, 28451 update: update, 28452 28453 dispose: dispose 28454 28455 }; 28456 28457} 28458 28459class WebGLRenderer { 28460 28461 constructor( parameters = {} ) { 28462 28463 const { 28464 canvas = createCanvasElement(), 28465 context = null, 28466 depth = true, 28467 stencil = true, 28468 alpha = false, 28469 antialias = false, 28470 premultipliedAlpha = true, 28471 preserveDrawingBuffer = false, 28472 powerPreference = 'default', 28473 failIfMajorPerformanceCaveat = false, 28474 } = parameters; 28475 28476 this.isWebGLRenderer = true; 28477 28478 let _alpha; 28479 28480 if ( context !== null ) { 28481 28482 _alpha = context.getContextAttributes().alpha; 28483 28484 } else { 28485 28486 _alpha = alpha; 28487 28488 } 28489 28490 const uintClearColor = new Uint32Array( 4 ); 28491 const intClearColor = new Int32Array( 4 ); 28492 28493 let currentRenderList = null; 28494 let currentRenderState = null; 28495 28496 // render() can be called from within a callback triggered by another render. 28497 // We track this so that the nested render call gets its list and state isolated from the parent render call. 28498 28499 const renderListStack = []; 28500 const renderStateStack = []; 28501 28502 // public properties 28503 28504 this.domElement = canvas; 28505 28506 // Debug configuration container 28507 this.debug = { 28508 28509 /** 28510 * Enables error checking and reporting when shader programs are being compiled 28511 * @type {boolean} 28512 */ 28513 checkShaderErrors: true, 28514 /** 28515 * Callback for custom error reporting. 28516 * @type {?Function} 28517 */ 28518 onShaderError: null 28519 }; 28520 28521 // clearing 28522 28523 this.autoClear = true; 28524 this.autoClearColor = true; 28525 this.autoClearDepth = true; 28526 this.autoClearStencil = true; 28527 28528 // scene graph 28529 28530 this.sortObjects = true; 28531 28532 // user-defined clipping 28533 28534 this.clippingPlanes = []; 28535 this.localClippingEnabled = false; 28536 28537 // physically based shading 28538 28539 this._outputColorSpace = SRGBColorSpace; 28540 28541 // physical lights 28542 28543 this._useLegacyLights = false; 28544 28545 // tone mapping 28546 28547 this.toneMapping = NoToneMapping; 28548 this.toneMappingExposure = 1.0; 28549 28550 // internal properties 28551 28552 const _this = this; 28553 28554 let _isContextLost = false; 28555 28556 // internal state cache 28557 28558 let _currentActiveCubeFace = 0; 28559 let _currentActiveMipmapLevel = 0; 28560 let _currentRenderTarget = null; 28561 let _currentMaterialId = -
vendor: 7,816 bytes, lines 28561-28887
285611; 28562 28563 let _currentCamera = null; 28564 28565 const _currentViewport = new Vector4(); 28566 const _currentScissor = new Vector4(); 28567 let _currentScissorTest = null; 28568 28569 const _currentClearColor = new Color( 0x000000 ); 28570 let _currentClearAlpha = 0; 28571 28572 // 28573 28574 let _width = canvas.width; 28575 let _height = canvas.height; 28576 28577 let _pixelRatio = 1; 28578 let _opaqueSort = null; 28579 let _transparentSort = null; 28580 28581 const _viewport = new Vector4( 0, 0, _width, _height ); 28582 const _scissor = new Vector4( 0, 0, _width, _height ); 28583 let _scissorTest = false; 28584 28585 // frustum 28586 28587 const _frustum = new Frustum(); 28588 28589 // clipping 28590 28591 let _clippingEnabled = false; 28592 let _localClippingEnabled = false; 28593 28594 // transmission 28595 28596 let _transmissionRenderTarget = null; 28597 28598 // camera matrices cache 28599 28600 const _projScreenMatrix = new Matrix4(); 28601 28602 const _vector2 = new Vector2(); 28603 const _vector3 = new Vector3(); 28604 28605 const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true }; 28606 28607 function getTargetPixelRatio() { 28608 28609 return _currentRenderTarget === null ? _pixelRatio : 1; 28610 28611 } 28612 28613 // initialize 28614 28615 let _gl = context; 28616 28617 function getContext( contextNames, contextAttributes ) { 28618 28619 for ( let i = 0; i < contextNames.length; i ++ ) { 28620 28621 const contextName = contextNames[ i ]; 28622 const context = canvas.getContext( contextName, contextAttributes ); 28623 if ( context !== null ) return context; 28624 28625 } 28626 28627 return null; 28628 28629 } 28630 28631 try { 28632 28633 const contextAttributes = { 28634 alpha: true, 28635 depth, 28636 stencil, 28637 antialias, 28638 premultipliedAlpha, 28639 preserveDrawingBuffer, 28640 powerPreference, 28641 failIfMajorPerformanceCaveat, 28642 }; 28643 28644 // OffscreenCanvas does not have setAttribute, see #22811 28645 if ( 'setAttribute' in canvas ) canvas.setAttribute( 'data-engine', `three.js r${REVISION}` ); 28646 28647 // event listeners must be registered before WebGL context is created, see #12753 28648 canvas.addEventListener( 'webglcontextlost', onContextLost, false ); 28649 canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); 28650 canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false ); 28651 28652 if ( _gl === null ) { 28653 28654 const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ]; 28655 28656 if ( _this.isWebGL1Renderer === true ) { 28657 28658 contextNames.shift(); 28659 28660 } 28661 28662 _gl = getContext( contextNames, contextAttributes ); 28663 28664 if ( _gl === null ) { 28665 28666 if ( getContext( contextNames ) ) { 28667 28668 throw new Error( 'Error creating WebGL context with your selected attributes.' ); 28669 28670 } else { 28671 28672 throw new Error( 'Error creating WebGL context.' ); 28673 28674 } 28675 28676 } 28677 28678 } 28679 28680 if ( typeof WebGLRenderingContext !== 'undefined' && _gl instanceof WebGLRenderingContext ) { // @deprecated, r153 28681 28682 console.warn( 'THREE.WebGLRenderer: WebGL 1 support was deprecated in r153 and will be removed in r163.' ); 28683 28684 } 28685 28686 // Some experimental-webgl implementations do not have getShaderPrecisionFormat 28687 28688 if ( _gl.getShaderPrecisionFormat === undefined ) { 28689 28690 _gl.getShaderPrecisionFormat = function () { 28691 28692 return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; 28693 28694 }; 28695 28696 } 28697 28698 } catch ( error ) { 28699 28700 console.error( 'THREE.WebGLRenderer: ' + error.message ); 28701 throw error; 28702 28703 } 28704 28705 let extensions, capabilities, state, info; 28706 let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects; 28707 let programCache, materials, renderLists, renderStates, clipping, shadowMap; 28708 28709 let background, morphtargets, bufferRenderer, indexedBufferRenderer; 28710 28711 let utils, bindingStates, uniformsGroups; 28712 28713 function initGLContext() { 28714 28715 extensions = new WebGLExtensions( _gl ); 28716 28717 capabilities = new WebGLCapabilities( _gl, extensions, parameters ); 28718 28719 extensions.init( capabilities ); 28720 28721 utils = new WebGLUtils( _gl, extensions, capabilities ); 28722 28723 state = new WebGLState( _gl, extensions, capabilities ); 28724 28725 info = new WebGLInfo( _gl ); 28726 properties = new WebGLProperties(); 28727 textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); 28728 cubemaps = new WebGLCubeMaps( _this ); 28729 cubeuvmaps = new WebGLCubeUVMaps( _this ); 28730 attributes = new WebGLAttributes( _gl, capabilities ); 28731 bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities ); 28732 geometries = new WebGLGeometries( _gl, attributes, info, bindingStates ); 28733 objects = new WebGLObjects( _gl, geometries, attributes, info ); 28734 morphtargets = new WebGLMorphtargets( _gl, capabilities, textures ); 28735 clipping = new WebGLClipping( properties ); 28736 programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ); 28737 materials = new WebGLMaterials( _this, properties ); 28738 renderLists = new WebGLRenderLists(); 28739 renderStates = new WebGLRenderStates( extensions, capabilities ); 28740 background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha ); 28741 shadowMap = new WebGLShadowMap( _this, objects, capabilities ); 28742 uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state ); 28743 28744 bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities ); 28745 indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities ); 28746 28747 info.programs = programCache.programs; 28748 28749 _this.capabilities = capabilities; 28750 _this.extensions = extensions; 28751 _this.properties = properties; 28752 _this.renderLists = renderLists; 28753 _this.shadowMap = shadowMap; 28754 _this.state = state; 28755 _this.info = info; 28756 28757 } 28758 28759 initGLContext(); 28760 28761 // xr 28762 28763 const xr = new WebXRManager( _this, _gl ); 28764 28765 this.xr = xr; 28766 28767 // API 28768 28769 this.getContext = function () { 28770 28771 return _gl; 28772 28773 }; 28774 28775 this.getContextAttributes = function () { 28776 28777 return _gl.getContextAttributes(); 28778 28779 }; 28780 28781 this.forceContextLoss = function () { 28782 28783 const extension = extensions.get( 'WEBGL_lose_context' ); 28784 if ( extension ) extension.loseContext(); 28785 28786 }; 28787 28788 this.forceContextRestore = function () { 28789 28790 const extension = extensions.get( 'WEBGL_lose_context' ); 28791 if ( extension ) extension.restoreContext(); 28792 28793 }; 28794 28795 this.getPixelRatio = function () { 28796 28797 return _pixelRatio; 28798 28799 }; 28800 28801 this.setPixelRatio = function ( value ) { 28802 28803 if ( value === undefined ) return; 28804 28805 _pixelRatio = value; 28806 28807 this.setSize( _width, _height, false ); 28808 28809 }; 28810 28811 this.getSize = function ( target ) { 28812 28813 return target.set( _width, _height ); 28814 28815 }; 28816 28817 this.setSize = function ( width, height, updateStyle = true ) { 28818 28819 if ( xr.isPresenting ) { 28820 28821 console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); 28822 return; 28823 28824 } 28825 28826 _width = width; 28827 _height = height; 28828 28829 canvas.width = Math.floor( width * _pixelRatio ); 28830 canvas.height = Math.floor( height * _pixelRatio ); 28831 28832 if ( updateStyle === true ) { 28833 28834 canvas.style.width = width + 'px'; 28835 canvas.style.height = height + 'px'; 28836 28837 } 28838 28839 this.setViewport( 0, 0, width, height ); 28840 28841 }; 28842 28843 this.getDrawingBufferSize = function ( target ) { 28844 28845 return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor(); 28846 28847 }; 28848 28849 this.setDrawingBufferSize = function ( width, height, pixelRatio ) { 28850 28851 _width = width; 28852 _height = height; 28853 28854 _pixelRatio = pixelRatio; 28855 28856 canvas.width = Math.floor( width * pixelRatio ); 28857 canvas.height = Math.floor( height * pixelRatio ); 28858 28859 this.setViewport( 0, 0, width, height ); 28860 28861 }; 28862 28863 this.getCurrentViewport = function ( target ) { 28864 28865 return target.copy( _currentViewport ); 28866 28867 }; 28868 28869 this.getViewport = function ( target ) { 28870 28871 return target.copy( _viewport ); 28872 28873 }; 28874 28875 this.setViewport = function ( x, y, width, height ) { 28876 28877 if ( x.isVector4 ) { 28878 28879 _viewport.set( x.x, x.y, x.z, x.w ); 28880 28881 } else { 28882 28883 _viewport.set( x, y, width, height ); 28884 28885 } 28886 28887 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).
28887floor() ); 28888 28889 }; 28890 28891 this.getScissor = function ( target ) { 28892 28893 return target.copy( _scissor ); 28894 28895 }; 28896 28897 this.setScissor = function ( x, y, width, height ) { 28898 28899 if ( x.isVector4 ) { 28900 28901 _scissor.set( x.x, x.y, x.z, x.w ); 28902 28903 } else { 28904 28905 _scissor.set( x, y, width, height ); 28906 28907 } 28908 28909 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor
vendor: 14,801 bytes, lines 28909-29605
28909() ); 28910 28911 }; 28912 28913 this.getScissorTest = function () { 28914 28915 return _scissorTest; 28916 28917 }; 28918 28919 this.setScissorTest = function ( boolean ) { 28920 28921 state.setScissorTest( _scissorTest = boolean ); 28922 28923 }; 28924 28925 this.setOpaqueSort = function ( method ) { 28926 28927 _opaqueSort = method; 28928 28929 }; 28930 28931 this.setTransparentSort = function ( method ) { 28932 28933 _transparentSort = method; 28934 28935 }; 28936 28937 // Clearing 28938 28939 this.getClearColor = function ( target ) { 28940 28941 return target.copy( background.getClearColor() ); 28942 28943 }; 28944 28945 this.setClearColor = function () { 28946 28947 background.setClearColor.apply( background, arguments ); 28948 28949 }; 28950 28951 this.getClearAlpha = function () { 28952 28953 return background.getClearAlpha(); 28954 28955 }; 28956 28957 this.setClearAlpha = function () { 28958 28959 background.setClearAlpha.apply( background, arguments ); 28960 28961 }; 28962 28963 this.clear = function ( color = true, depth = true, stencil = true ) { 28964 28965 let bits = 0; 28966 28967 if ( color ) { 28968 28969 // check if we're trying to clear an integer target 28970 let isIntegerFormat = false; 28971 if ( _currentRenderTarget !== null ) { 28972 28973 const targetFormat = _currentRenderTarget.texture.format; 28974 isIntegerFormat = targetFormat === RGBAIntegerFormat || 28975 targetFormat === RGIntegerFormat || 28976 targetFormat === RedIntegerFormat; 28977 28978 } 28979 28980 // use the appropriate clear functions to clear the target if it's a signed 28981 // or unsigned integer target 28982 if ( isIntegerFormat ) { 28983 28984 const targetType = _currentRenderTarget.texture.type; 28985 const isUnsignedType = targetType === UnsignedByteType || 28986 targetType === UnsignedIntType || 28987 targetType === UnsignedShortType || 28988 targetType === UnsignedInt248Type || 28989 targetType === UnsignedShort4444Type || 28990 targetType === UnsignedShort5551Type; 28991 28992 const clearColor = background.getClearColor(); 28993 const a = background.getClearAlpha(); 28994 const r = clearColor.r; 28995 const g = clearColor.g; 28996 const b = clearColor.b; 28997 28998 if ( isUnsignedType ) { 28999 29000 uintClearColor[ 0 ] = r; 29001 uintClearColor[ 1 ] = g; 29002 uintClearColor[ 2 ] = b; 29003 uintClearColor[ 3 ] = a; 29004 _gl.clearBufferuiv( _gl.COLOR, 0, uintClearColor ); 29005 29006 } else { 29007 29008 intClearColor[ 0 ] = r; 29009 intClearColor[ 1 ] = g; 29010 intClearColor[ 2 ] = b; 29011 intClearColor[ 3 ] = a; 29012 _gl.clearBufferiv( _gl.COLOR, 0, intClearColor ); 29013 29014 } 29015 29016 } else { 29017 29018 bits |= _gl.COLOR_BUFFER_BIT; 29019 29020 } 29021 29022 } 29023 29024 if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; 29025 if ( stencil ) { 29026 29027 bits |= _gl.STENCIL_BUFFER_BIT; 29028 this.state.buffers.stencil.setMask( 0xffffffff ); 29029 29030 } 29031 29032 _gl.clear( bits ); 29033 29034 }; 29035 29036 this.clearColor = function () { 29037 29038 this.clear( true, false, false ); 29039 29040 }; 29041 29042 this.clearDepth = function () { 29043 29044 this.clear( false, true, false ); 29045 29046 }; 29047 29048 this.clearStencil = function () { 29049 29050 this.clear( false, false, true ); 29051 29052 }; 29053 29054 // 29055 29056 this.dispose = function () { 29057 29058 canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); 29059 canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); 29060 canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false ); 29061 29062 renderLists.dispose(); 29063 renderStates.dispose(); 29064 properties.dispose(); 29065 cubemaps.dispose(); 29066 cubeuvmaps.dispose(); 29067 objects.dispose(); 29068 bindingStates.dispose(); 29069 uniformsGroups.dispose(); 29070 programCache.dispose(); 29071 29072 xr.dispose(); 29073 29074 xr.removeEventListener( 'sessionstart', onXRSessionStart ); 29075 xr.removeEventListener( 'sessionend', onXRSessionEnd ); 29076 29077 if ( _transmissionRenderTarget ) { 29078 29079 _transmissionRenderTarget.dispose(); 29080 _transmissionRenderTarget = null; 29081 29082 } 29083 29084 animation.stop(); 29085 29086 }; 29087 29088 // Events 29089 29090 function onContextLost( event ) { 29091 29092 event.preventDefault(); 29093 29094 console.log( 'THREE.WebGLRenderer: Context Lost.' ); 29095 29096 _isContextLost = true; 29097 29098 } 29099 29100 function onContextRestore( /* event */ ) { 29101 29102 console.log( 'THREE.WebGLRenderer: Context Restored.' ); 29103 29104 _isContextLost = false; 29105 29106 const infoAutoReset = info.autoReset; 29107 const shadowMapEnabled = shadowMap.enabled; 29108 const shadowMapAutoUpdate = shadowMap.autoUpdate; 29109 const shadowMapNeedsUpdate = shadowMap.needsUpdate; 29110 const shadowMapType = shadowMap.type; 29111 29112 initGLContext(); 29113 29114 info.autoReset = infoAutoReset; 29115 shadowMap.enabled = shadowMapEnabled; 29116 shadowMap.autoUpdate = shadowMapAutoUpdate; 29117 shadowMap.needsUpdate = shadowMapNeedsUpdate; 29118 shadowMap.type = shadowMapType; 29119 29120 } 29121 29122 function onContextCreationError( event ) { 29123 29124 console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage ); 29125 29126 } 29127 29128 function onMaterialDispose( event ) { 29129 29130 const material = event.target; 29131 29132 material.removeEventListener( 'dispose', onMaterialDispose ); 29133 29134 deallocateMaterial( material ); 29135 29136 } 29137 29138 // Buffer deallocation 29139 29140 function deallocateMaterial( material ) { 29141 29142 releaseMaterialProgramReferences( material ); 29143 29144 properties.remove( material ); 29145 29146 } 29147 29148 29149 function releaseMaterialProgramReferences( material ) { 29150 29151 const programs = properties.get( material ).programs; 29152 29153 if ( programs !== undefined ) { 29154 29155 programs.forEach( function ( program ) { 29156 29157 programCache.releaseProgram( program ); 29158 29159 } ); 29160 29161 if ( material.isShaderMaterial ) { 29162 29163 programCache.releaseShaderCache( material ); 29164 29165 } 29166 29167 } 29168 29169 } 29170 29171 // Buffer rendering 29172 29173 this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) { 29174 29175 if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null) 29176 29177 const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); 29178 29179 const program = setProgram( camera, scene, geometry, material, object ); 29180 29181 state.setMaterial( material, frontFaceCW ); 29182 29183 // 29184 29185 let index = geometry.index; 29186 let rangeFactor = 1; 29187 29188 if ( material.wireframe === true ) { 29189 29190 index = geometries.getWireframeAttribute( geometry ); 29191 29192 if ( index === undefined ) return; 29193 29194 rangeFactor = 2; 29195 29196 } 29197 29198 // 29199 29200 const drawRange = geometry.drawRange; 29201 const position = geometry.attributes.position; 29202 29203 let drawStart = drawRange.start * rangeFactor; 29204 let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor; 29205 29206 if ( group !== null ) { 29207 29208 drawStart = Math.max( drawStart, group.start * rangeFactor ); 29209 drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor ); 29210 29211 } 29212 29213 if ( index !== null ) { 29214 29215 drawStart = Math.max( drawStart, 0 ); 29216 drawEnd = Math.min( drawEnd, index.count ); 29217 29218 } else if ( position !== undefined && position !== null ) { 29219 29220 drawStart = Math.max( drawStart, 0 ); 29221 drawEnd = Math.min( drawEnd, position.count ); 29222 29223 } 29224 29225 const drawCount = drawEnd - drawStart; 29226 29227 if ( drawCount < 0 || drawCount === Infinity ) return; 29228 29229 // 29230 29231 bindingStates.setup( object, material, program, geometry, index ); 29232 29233 let attribute; 29234 let renderer = bufferRenderer; 29235 29236 if ( index !== null ) { 29237 29238 attribute = attributes.get( index ); 29239 29240 renderer = indexedBufferRenderer; 29241 renderer.setIndex( attribute ); 29242 29243 } 29244 29245 // 29246 29247 if ( object.isMesh ) { 29248 29249 if ( material.wireframe === true ) { 29250 29251 state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); 29252 renderer.setMode( _gl.LINES ); 29253 29254 } else { 29255 29256 renderer.setMode( _gl.TRIANGLES ); 29257 29258 } 29259 29260 } else if ( object.isLine ) { 29261 29262 let lineWidth = material.linewidth; 29263 29264 if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material 29265 29266 state.setLineWidth( lineWidth * getTargetPixelRatio() ); 29267 29268 if ( object.isLineSegments ) { 29269 29270 renderer.setMode( _gl.LINES ); 29271 29272 } else if ( object.isLineLoop ) { 29273 29274 renderer.setMode( _gl.LINE_LOOP ); 29275 29276 } else { 29277 29278 renderer.setMode( _gl.LINE_STRIP ); 29279 29280 } 29281 29282 } else if ( object.isPoints ) { 29283 29284 renderer.setMode( _gl.POINTS ); 29285 29286 } else if ( object.isSprite ) { 29287 29288 renderer.setMode( _gl.TRIANGLES ); 29289 29290 } 29291 29292 if ( object.isBatchedMesh ) { 29293 29294 renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount ); 29295 29296 } else if ( object.isInstancedMesh ) { 29297 29298 renderer.renderInstances( drawStart, drawCount, object.count ); 29299 29300 } else if ( geometry.isInstancedBufferGeometry ) { 29301 29302 const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity; 29303 const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount ); 29304 29305 renderer.renderInstances( drawStart, drawCount, instanceCount ); 29306 29307 } else { 29308 29309 renderer.render( drawStart, drawCount ); 29310 29311 } 29312 29313 }; 29314 29315 // Compile 29316 29317 function prepareMaterial( material, scene, object ) { 29318 29319 if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { 29320 29321 material.side = BackSide; 29322 material.needsUpdate = true; 29323 getProgram( material, scene, object ); 29324 29325 material.side = FrontSide; 29326 material.needsUpdate = true; 29327 getProgram( material, scene, object ); 29328 29329 material.side = DoubleSide; 29330 29331 } else { 29332 29333 getProgram( material, scene, object ); 29334 29335 } 29336 29337 } 29338 29339 this.compile = function ( scene, camera, targetScene = null ) { 29340 29341 if ( targetScene === null ) targetScene = scene; 29342 29343 currentRenderState = renderStates.get( targetScene ); 29344 currentRenderState.init(); 29345 29346 renderStateStack.push( currentRenderState ); 29347 29348 // gather lights from both the target scene and the new object that will be added to the scene. 29349 29350 targetScene.traverseVisible( function ( object ) { 29351 29352 if ( object.isLight && object.layers.test( camera.layers ) ) { 29353 29354 currentRenderState.pushLight( object ); 29355 29356 if ( object.castShadow ) { 29357 29358 currentRenderState.pushShadow( object ); 29359 29360 } 29361 29362 } 29363 29364 } ); 29365 29366 if ( scene !== targetScene ) { 29367 29368 scene.traverseVisible( function ( object ) { 29369 29370 if ( object.isLight && object.layers.test( camera.layers ) ) { 29371 29372 currentRenderState.pushLight( object ); 29373 29374 if ( object.castShadow ) { 29375 29376 currentRenderState.pushShadow( object ); 29377 29378 } 29379 29380 } 29381 29382 } ); 29383 29384 } 29385 29386 currentRenderState.setupLights( _this._useLegacyLights ); 29387 29388 // Only initialize materials in the new scene, not the targetScene. 29389 29390 const materials = new Set(); 29391 29392 scene.traverse( function ( object ) { 29393 29394 const material = object.material; 29395 29396 if ( material ) { 29397 29398 if ( Array.isArray( material ) ) { 29399 29400 for ( let i = 0; i < material.length; i ++ ) { 29401 29402 const material2 = material[ i ]; 29403 29404 prepareMaterial( material2, targetScene, object ); 29405 materials.add( material2 ); 29406 29407 } 29408 29409 } else { 29410 29411 prepareMaterial( material, targetScene, object ); 29412 materials.add( material ); 29413 29414 } 29415 29416 } 29417 29418 } ); 29419 29420 renderStateStack.pop(); 29421 currentRenderState = null; 29422 29423 return materials; 29424 29425 }; 29426 29427 // compileAsync 29428 29429 this.compileAsync = function ( scene, camera, targetScene = null ) { 29430 29431 const materials = this.compile( scene, camera, targetScene ); 29432 29433 // Wait for all the materials in the new object to indicate that they're 29434 // ready to be used before resolving the promise. 29435 29436 return new Promise( ( resolve ) => { 29437 29438 function checkMaterialsReady() { 29439 29440 materials.forEach( function ( material ) { 29441 29442 const materialProperties = properties.get( material ); 29443 const program = materialProperties.currentProgram; 29444 29445 if ( program.isReady() ) { 29446 29447 // remove any programs that report they're ready to use from the list 29448 materials.delete( material ); 29449 29450 } 29451 29452 } ); 29453 29454 // once the list of compiling materials is empty, call the callback 29455 29456 if ( materials.size === 0 ) { 29457 29458 resolve( scene ); 29459 return; 29460 29461 } 29462 29463 // if some materials are still not ready, wait a bit and check again 29464 29465 setTimeout( checkMaterialsReady, 10 ); 29466 29467 } 29468 29469 if ( extensions.get( 'KHR_parallel_shader_compile' ) !== null ) { 29470 29471 // If we can check the compilation status of the materials without 29472 // blocking then do so right away. 29473 29474 checkMaterialsReady(); 29475 29476 } else { 29477 29478 // Otherwise start by waiting a bit to give the materials we just 29479 // initialized a chance to finish. 29480 29481 setTimeout( checkMaterialsReady, 10 ); 29482 29483 } 29484 29485 } ); 29486 29487 }; 29488 29489 // Animation Loop 29490 29491 let onAnimationFrameCallback = null; 29492 29493 function onAnimationFrame( time ) { 29494 29495 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time ); 29496 29497 } 29498 29499 function onXRSessionStart() { 29500 29501 animation.stop(); 29502 29503 } 29504 29505 function onXRSessionEnd() { 29506 29507 animation.start(); 29508 29509 } 29510 29511 const animation = new WebGLAnimation(); 29512 animation.setAnimationLoop( onAnimationFrame ); 29513 29514 if ( typeof self !== 'undefined' ) animation.setContext( self ); 29515 29516 this.setAnimationLoop = function ( callback ) { 29517 29518 onAnimationFrameCallback = callback; 29519 xr.setAnimationLoop( callback ); 29520 29521 ( callback === null ) ? animation.stop() : animation.start(); 29522 29523 }; 29524 29525 xr.addEventListener( 'sessionstart', onXRSessionStart ); 29526 xr.addEventListener( 'sessionend', onXRSessionEnd ); 29527 29528 // Rendering 29529 29530 this.render = function ( scene, camera ) { 29531 29532 if ( camera !== undefined && camera.isCamera !== true ) { 29533 29534 console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); 29535 return; 29536 29537 } 29538 29539 if ( _isContextLost === true ) return; 29540 29541 // update scene graph 29542 29543 if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); 29544 29545 // update camera matrices and frustum 29546 29547 if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); 29548 29549 if ( xr.enabled === true && xr.isPresenting === true ) { 29550 29551 if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera ); 29552 29553 camera = xr.getCamera(); // use XR camera for rendering 29554 29555 } 29556 29557 // 29558 if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget ); 29559 29560 currentRenderState = renderStates.get( scene, renderStateStack.length ); 29561 currentRenderState.init(); 29562 29563 renderStateStack.push( currentRenderState ); 29564 29565 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); 29566 _frustum.setFromProjectionMatrix( _projScreenMatrix ); 29567 29568 _localClippingEnabled = this.localClippingEnabled; 29569 _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled ); 29570 29571 currentRenderList = renderLists.get( scene, renderListStack.length ); 29572 currentRenderList.init(); 29573 29574 renderListStack.push( currentRenderList ); 29575 29576 projectObject( scene, camera, 0, _this.sortObjects ); 29577 29578 currentRenderList.finish(); 29579 29580 if ( _this.sortObjects === true ) { 29581 29582 currentRenderList.sort( _opaqueSort, _transparentSort ); 29583 29584 } 29585 29586 // 29587 29588 this.info.render.frame ++; 29589 29590 if ( _clippingEnabled === true ) clipping.beginShadows(); 29591 29592 const shadowsArray = currentRenderState.state.shadowsArray; 29593 29594 shadowMap.render( shadowsArray, scene, camera ); 29595 29596 if ( _clippingEnabled === true ) clipping.endShadows(); 29597 29598 // 29599 29600 if ( this.info.autoReset === true ) this.info.reset(); 29601 29602 29603 // 29604 29605
29605background.render( currentRenderList, scene ); 29606 29607 // render scene 29608 29609 currentRenderState.setupLights( _this._useLegacyLights ); 29610 29611 if ( camera.isArrayCamera ) { 29612 29613 const cameras = camera.cameras; 29614 29615 for ( let i = 0, l = cameras.length; i < l; i ++ ) { 29616 29617 const camera2 = cameras[ i ]; 29618 29619 renderScene( currentRenderList, scene, camera2, camera2.viewport ); 29620 29621 } 29622 29623 } else { 29624 29625 renderScene( currentRenderList, scene, camera ); 29626 29627 } 29628 29629 // 29630 29631 if ( _currentRenderTarget !== null ) { 29632 29633 // resolve multisample renderbuffers to a single-sample texture if necessary 29634 29635 textures.updateMultisampleRenderTarget( _currentRenderTarget ); 29636 29637 // Generate mipmap if we're using any kind of mipmap filtering 29638 29639 textures.updateRenderTargetMipmap( _currentRenderTarget ); 29640 29641 } 29642 29643 // 29644 29645 if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera ); 29646 29647 // _gl.finish(); 29648 29649 bindingStates.resetDefaultState(); 29650 _currentMaterialId = -
vendor: 9,575 bytes, lines 29650-30005
296501; 29651 _currentCamera = null; 29652 29653 renderStateStack.pop(); 29654 29655 if ( renderStateStack.length > 0 ) { 29656 29657 currentRenderState = renderStateStack[ renderStateStack.length - 1 ]; 29658 29659 } else { 29660 29661 currentRenderState = null; 29662 29663 } 29664 29665 renderListStack.pop(); 29666 29667 if ( renderListStack.length > 0 ) { 29668 29669 currentRenderList = renderListStack[ renderListStack.length - 1 ]; 29670 29671 } else { 29672 29673 currentRenderList = null; 29674 29675 } 29676 29677 }; 29678 29679 function projectObject( object, camera, groupOrder, sortObjects ) { 29680 29681 if ( object.visible === false ) return; 29682 29683 const visible = object.layers.test( camera.layers ); 29684 29685 if ( visible ) { 29686 29687 if ( object.isGroup ) { 29688 29689 groupOrder = object.renderOrder; 29690 29691 } else if ( object.isLOD ) { 29692 29693 if ( object.autoUpdate === true ) object.update( camera ); 29694 29695 } else if ( object.isLight ) { 29696 29697 currentRenderState.pushLight( object ); 29698 29699 if ( object.castShadow ) { 29700 29701 currentRenderState.pushShadow( object ); 29702 29703 } 29704 29705 } else if ( object.isSprite ) { 29706 29707 if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { 29708 29709 if ( sortObjects ) { 29710 29711 _vector3.setFromMatrixPosition( object.matrixWorld ) 29712 .applyMatrix4( _projScreenMatrix ); 29713 29714 } 29715 29716 const geometry = objects.update( object ); 29717 const material = object.material; 29718 29719 if ( material.visible ) { 29720 29721 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); 29722 29723 } 29724 29725 } 29726 29727 } else if ( object.isMesh || object.isLine || object.isPoints ) { 29728 29729 if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { 29730 29731 const geometry = objects.update( object ); 29732 const material = object.material; 29733 29734 if ( sortObjects ) { 29735 29736 if ( object.boundingSphere !== undefined ) { 29737 29738 if ( object.boundingSphere === null ) object.computeBoundingSphere(); 29739 _vector3.copy( object.boundingSphere.center ); 29740 29741 } else { 29742 29743 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 29744 _vector3.copy( geometry.boundingSphere.center ); 29745 29746 } 29747 29748 _vector3 29749 .applyMatrix4( object.matrixWorld ) 29750 .applyMatrix4( _projScreenMatrix ); 29751 29752 } 29753 29754 if ( Array.isArray( material ) ) { 29755 29756 const groups = geometry.groups; 29757 29758 for ( let i = 0, l = groups.length; i < l; i ++ ) { 29759 29760 const group = groups[ i ]; 29761 const groupMaterial = material[ group.materialIndex ]; 29762 29763 if ( groupMaterial && groupMaterial.visible ) { 29764 29765 currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); 29766 29767 } 29768 29769 } 29770 29771 } else if ( material.visible ) { 29772 29773 currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null ); 29774 29775 } 29776 29777 } 29778 29779 } 29780 29781 } 29782 29783 const children = object.children; 29784 29785 for ( let i = 0, l = children.length; i < l; i ++ ) { 29786 29787 projectObject( children[ i ], camera, groupOrder, sortObjects ); 29788 29789 } 29790 29791 } 29792 29793 function renderScene( currentRenderList, scene, camera, viewport ) { 29794 29795 const opaqueObjects = currentRenderList.opaque; 29796 const transmissiveObjects = currentRenderList.transmissive; 29797 const transparentObjects = currentRenderList.transparent; 29798 29799 currentRenderState.setupLightsView( camera ); 29800 29801 if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera ); 29802 29803 if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ); 29804 29805 if ( viewport ) state.viewport( _currentViewport.copy( viewport ) ); 29806 29807 if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); 29808 if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera ); 29809 if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera ); 29810 29811 // Ensure depth buffer writing is enabled so it can be cleared on next render 29812 29813 state.buffers.depth.setTest( true ); 29814 state.buffers.depth.setMask( true ); 29815 state.buffers.color.setMask( true ); 29816 29817 state.setPolygonOffset( false ); 29818 29819 } 29820 29821 function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) { 29822 29823 const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; 29824 29825 if ( overrideMaterial !== null ) { 29826 29827 return; 29828 29829 } 29830 29831 const isWebGL2 = capabilities.isWebGL2; 29832 29833 if ( _transmissionRenderTarget === null ) { 29834 29835 _transmissionRenderTarget = new WebGLRenderTarget( 1, 1, { 29836 generateMipmaps: true, 29837 type: extensions.has( 'EXT_color_buffer_half_float' ) ? HalfFloatType : UnsignedByteType, 29838 minFilter: LinearMipmapLinearFilter, 29839 samples: ( isWebGL2 ) ? 4 : 0 29840 } ); 29841 29842 // debug 29843 29844 /* 29845 const geometry = new PlaneGeometry(); 29846 const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } ); 29847 29848 const mesh = new Mesh( geometry, material ); 29849 scene.add( mesh ); 29850 */ 29851 29852 } 29853 29854 _this.getDrawingBufferSize( _vector2 ); 29855 29856 if ( isWebGL2 ) { 29857 29858 _transmissionRenderTarget.setSize( _vector2.x, _vector2.y ); 29859 29860 } else { 29861 29862 _transmissionRenderTarget.setSize( floorPowerOfTwo( _vector2.x ), floorPowerOfTwo( _vector2.y ) ); 29863 29864 } 29865 29866 // 29867 29868 const currentRenderTarget = _this.getRenderTarget(); 29869 _this.setRenderTarget( _transmissionRenderTarget ); 29870 29871 _this.getClearColor( _currentClearColor ); 29872 _currentClearAlpha = _this.getClearAlpha(); 29873 if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 ); 29874 29875 _this.clear(); 29876 29877 // Turn off the features which can affect the frag color for opaque objects pass. 29878 // Otherwise they are applied twice in opaque objects pass and transmission objects pass. 29879 const currentToneMapping = _this.toneMapping; 29880 _this.toneMapping = NoToneMapping; 29881 29882 renderObjects( opaqueObjects, scene, camera ); 29883 29884 textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); 29885 textures.updateRenderTargetMipmap( _transmissionRenderTarget ); 29886 29887 let renderTargetNeedsUpdate = false; 29888 29889 for ( let i = 0, l = transmissiveObjects.length; i < l; i ++ ) { 29890 29891 const renderItem = transmissiveObjects[ i ]; 29892 29893 const object = renderItem.object; 29894 const geometry = renderItem.geometry; 29895 const material = renderItem.material; 29896 const group = renderItem.group; 29897 29898 if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) { 29899 29900 const currentSide = material.side; 29901 29902 material.side = BackSide; 29903 material.needsUpdate = true; 29904 29905 renderObject( object, scene, camera, geometry, material, group ); 29906 29907 material.side = currentSide; 29908 material.needsUpdate = true; 29909 29910 renderTargetNeedsUpdate = true; 29911 29912 } 29913 29914 } 29915 29916 if ( renderTargetNeedsUpdate === true ) { 29917 29918 textures.updateMultisampleRenderTarget( _transmissionRenderTarget ); 29919 textures.updateRenderTargetMipmap( _transmissionRenderTarget ); 29920 29921 } 29922 29923 _this.setRenderTarget( currentRenderTarget ); 29924 29925 _this.setClearColor( _currentClearColor, _currentClearAlpha ); 29926 29927 _this.toneMapping = currentToneMapping; 29928 29929 } 29930 29931 function renderObjects( renderList, scene, camera ) { 29932 29933 const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null; 29934 29935 for ( let i = 0, l = renderList.length; i < l; i ++ ) { 29936 29937 const renderItem = renderList[ i ]; 29938 29939 const object = renderItem.object; 29940 const geometry = renderItem.geometry; 29941 const material = overrideMaterial === null ? renderItem.material : overrideMaterial; 29942 const group = renderItem.group; 29943 29944 if ( object.layers.test( camera.layers ) ) { 29945 29946 renderObject( object, scene, camera, geometry, material, group ); 29947 29948 } 29949 29950 } 29951 29952 } 29953 29954 function renderObject( object, scene, camera, geometry, material, group ) { 29955 29956 object.onBeforeRender( _this, scene, camera, geometry, material, group ); 29957 29958 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); 29959 object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); 29960 29961 material.onBeforeRender( _this, scene, camera, geometry, object, group ); 29962 29963 if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { 29964 29965 material.side = BackSide; 29966 material.needsUpdate = true; 29967 _this.renderBufferDirect( camera, scene, geometry, material, object, group ); 29968 29969 material.side = FrontSide; 29970 material.needsUpdate = true; 29971 _this.renderBufferDirect( camera, scene, geometry, material, object, group ); 29972 29973 material.side = DoubleSide; 29974 29975 } else { 29976 29977 _this.renderBufferDirect( camera, scene, geometry, material, object, group ); 29978 29979 } 29980 29981 object.onAfterRender( _this, scene, camera, geometry, material, group ); 29982 29983 } 29984 29985 function getProgram( material, scene, object ) { 29986 29987 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... 29988 29989 const materialProperties = properties.get( material ); 29990 29991 const lights = currentRenderState.state.lights; 29992 const shadowsArray = currentRenderState.state.shadowsArray; 29993 29994 const lightsStateVersion = lights.state.version; 29995 29996 const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object ); 29997 const programCacheKey = programCache.getProgramCacheKey( parameters ); 29998 29999 let programs = materialProperties.programs; 30000 30001 // always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change 30002 30003 materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null; 30004 materialProperties.fog = scene.fog; 30005 materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment );
vendor: 30,854 bytes, lines 30006-31002
30006 30007 if ( programs === undefined ) { 30008 30009 // new material 30010 30011 material.addEventListener( 'dispose', onMaterialDispose ); 30012 30013 programs = new Map(); 30014 materialProperties.programs = programs; 30015 30016 } 30017 30018 let program = programs.get( programCacheKey ); 30019 30020 if ( program !== undefined ) { 30021 30022 // early out if program and light state is identical 30023 30024 if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) { 30025 30026 updateCommonMaterialProperties( material, parameters ); 30027 30028 return program; 30029 30030 } 30031 30032 } else { 30033 30034 parameters.uniforms = programCache.getUniforms( material ); 30035 30036 material.onBuild( object, parameters, _this ); 30037 30038 material.onBeforeCompile( parameters, _this ); 30039 30040 program = programCache.acquireProgram( parameters, programCacheKey ); 30041 programs.set( programCacheKey, program ); 30042 30043 materialProperties.uniforms = parameters.uniforms; 30044 30045 } 30046 30047 const uniforms = materialProperties.uniforms; 30048 30049 if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) { 30050 30051 uniforms.clippingPlanes = clipping.uniform; 30052 30053 } 30054 30055 updateCommonMaterialProperties( material, parameters ); 30056 30057 // store the light setup it was created for 30058 30059 materialProperties.needsLights = materialNeedsLights( material ); 30060 materialProperties.lightsStateVersion = lightsStateVersion; 30061 30062 if ( materialProperties.needsLights ) { 30063 30064 // wire up the material to this renderer's lighting state 30065 30066 uniforms.ambientLightColor.value = lights.state.ambient; 30067 uniforms.lightProbe.value = lights.state.probe; 30068 uniforms.directionalLights.value = lights.state.directional; 30069 uniforms.directionalLightShadows.value = lights.state.directionalShadow; 30070 uniforms.spotLights.value = lights.state.spot; 30071 uniforms.spotLightShadows.value = lights.state.spotShadow; 30072 uniforms.rectAreaLights.value = lights.state.rectArea; 30073 uniforms.ltc_1.value = lights.state.rectAreaLTC1; 30074 uniforms.ltc_2.value = lights.state.rectAreaLTC2; 30075 uniforms.pointLights.value = lights.state.point; 30076 uniforms.pointLightShadows.value = lights.state.pointShadow; 30077 uniforms.hemisphereLights.value = lights.state.hemi; 30078 30079 uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; 30080 uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; 30081 uniforms.spotShadowMap.value = lights.state.spotShadowMap; 30082 uniforms.spotLightMatrix.value = lights.state.spotLightMatrix; 30083 uniforms.spotLightMap.value = lights.state.spotLightMap; 30084 uniforms.pointShadowMap.value = lights.state.pointShadowMap; 30085 uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; 30086 // TODO (abelnation): add area lights shadow info to uniforms 30087 30088 } 30089 30090 materialProperties.currentProgram = program; 30091 materialProperties.uniformsList = null; 30092 30093 return program; 30094 30095 } 30096 30097 function getUniformList( materialProperties ) { 30098 30099 if ( materialProperties.uniformsList === null ) { 30100 30101 const progUniforms = materialProperties.currentProgram.getUniforms(); 30102 materialProperties.uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, materialProperties.uniforms ); 30103 30104 } 30105 30106 return materialProperties.uniformsList; 30107 30108 } 30109 30110 function updateCommonMaterialProperties( material, parameters ) { 30111 30112 const materialProperties = properties.get( material ); 30113 30114 materialProperties.outputColorSpace = parameters.outputColorSpace; 30115 materialProperties.batching = parameters.batching; 30116 materialProperties.instancing = parameters.instancing; 30117 materialProperties.instancingColor = parameters.instancingColor; 30118 materialProperties.skinning = parameters.skinning; 30119 materialProperties.morphTargets = parameters.morphTargets; 30120 materialProperties.morphNormals = parameters.morphNormals; 30121 materialProperties.morphColors = parameters.morphColors; 30122 materialProperties.morphTargetsCount = parameters.morphTargetsCount; 30123 materialProperties.numClippingPlanes = parameters.numClippingPlanes; 30124 materialProperties.numIntersection = parameters.numClipIntersection; 30125 materialProperties.vertexAlphas = parameters.vertexAlphas; 30126 materialProperties.vertexTangents = parameters.vertexTangents; 30127 materialProperties.toneMapping = parameters.toneMapping; 30128 30129 } 30130 30131 function setProgram( camera, scene, geometry, material, object ) { 30132 30133 if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ... 30134 30135 textures.resetTextureUnits(); 30136 30137 const fog = scene.fog; 30138 const environment = material.isMeshStandardMaterial ? scene.environment : null; 30139 const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ); 30140 const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment ); 30141 const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4; 30142 const vertexTangents = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 ); 30143 const morphTargets = !! geometry.morphAttributes.position; 30144 const morphNormals = !! geometry.morphAttributes.normal; 30145 const morphColors = !! geometry.morphAttributes.color; 30146 30147 let toneMapping = NoToneMapping; 30148 30149 if ( material.toneMapped ) { 30150 30151 if ( _currentRenderTarget === null || _currentRenderTarget.isXRRenderTarget === true ) { 30152 30153 toneMapping = _this.toneMapping; 30154 30155 } 30156 30157 } 30158 30159 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; 30160 const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; 30161 30162 const materialProperties = properties.get( material ); 30163 const lights = currentRenderState.state.lights; 30164 30165 if ( _clippingEnabled === true ) { 30166 30167 if ( _localClippingEnabled === true || camera !== _currentCamera ) { 30168 30169 const useCache = 30170 camera === _currentCamera && 30171 material.id === _currentMaterialId; 30172 30173 // we might want to call this function with some ClippingGroup 30174 // object instead of the material, once it becomes feasible 30175 // (#8465, #8379) 30176 clipping.setState( material, camera, useCache ); 30177 30178 } 30179 30180 } 30181 30182 // 30183 30184 let needsProgramChange = false; 30185 30186 if ( material.version === materialProperties.__version ) { 30187 30188 if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) { 30189 30190 needsProgramChange = true; 30191 30192 } else if ( materialProperties.outputColorSpace !== colorSpace ) { 30193 30194 needsProgramChange = true; 30195 30196 } else if ( object.isBatchedMesh && materialProperties.batching === false ) { 30197 30198 needsProgramChange = true; 30199 30200 } else if ( ! object.isBatchedMesh && materialProperties.batching === true ) { 30201 30202 needsProgramChange = true; 30203 30204 } else if ( object.isInstancedMesh && materialProperties.instancing === false ) { 30205 30206 needsProgramChange = true; 30207 30208 } else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) { 30209 30210 needsProgramChange = true; 30211 30212 } else if ( object.isSkinnedMesh && materialProperties.skinning === false ) { 30213 30214 needsProgramChange = true; 30215 30216 } else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) { 30217 30218 needsProgramChange = true; 30219 30220 } else if ( object.isInstancedMesh && materialProperties.instancingColor === true && object.instanceColor === null ) { 30221 30222 needsProgramChange = true; 30223 30224 } else if ( object.isInstancedMesh && materialProperties.instancingColor === false && object.instanceColor !== null ) { 30225 30226 needsProgramChange = true; 30227 30228 } else if ( materialProperties.envMap !== envMap ) { 30229 30230 needsProgramChange = true; 30231 30232 } else if ( material.fog === true && materialProperties.fog !== fog ) { 30233 30234 needsProgramChange = true; 30235 30236 } else if ( materialProperties.numClippingPlanes !== undefined && 30237 ( materialProperties.numClippingPlanes !== clipping.numPlanes || 30238 materialProperties.numIntersection !== clipping.numIntersection ) ) { 30239 30240 needsProgramChange = true; 30241 30242 } else if ( materialProperties.vertexAlphas !== vertexAlphas ) { 30243 30244 needsProgramChange = true; 30245 30246 } else if ( materialProperties.vertexTangents !== vertexTangents ) { 30247 30248 needsProgramChange = true; 30249 30250 } else if ( materialProperties.morphTargets !== morphTargets ) { 30251 30252 needsProgramChange = true; 30253 30254 } else if ( materialProperties.morphNormals !== morphNormals ) { 30255 30256 needsProgramChange = true; 30257 30258 } else if ( materialProperties.morphColors !== morphColors ) { 30259 30260 needsProgramChange = true; 30261 30262 } else if ( materialProperties.toneMapping !== toneMapping ) { 30263 30264 needsProgramChange = true; 30265 30266 } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) { 30267 30268 needsProgramChange = true; 30269 30270 } 30271 30272 } else { 30273 30274 needsProgramChange = true; 30275 materialProperties.__version = material.version; 30276 30277 } 30278 30279 // 30280 30281 let program = materialProperties.currentProgram; 30282 30283 if ( needsProgramChange === true ) { 30284 30285 program = getProgram( material, scene, object ); 30286 30287 } 30288 30289 let refreshProgram = false; 30290 let refreshMaterial = false; 30291 let refreshLights = false; 30292 30293 const p_uniforms = program.getUniforms(), 30294 m_uniforms = materialProperties.uniforms; 30295 30296 if ( state.useProgram( program.program ) ) { 30297 30298 refreshProgram = true; 30299 refreshMaterial = true; 30300 refreshLights = true; 30301 30302 } 30303 30304 if ( material.id !== _currentMaterialId ) { 30305 30306 _currentMaterialId = material.id; 30307 30308 refreshMaterial = true; 30309 30310 } 30311 30312 if ( refreshProgram || _currentCamera !== camera ) { 30313 30314 // common camera uniforms 30315 30316 p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); 30317 p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); 30318 30319 const uCamPos = p_uniforms.map.cameraPosition; 30320 30321 if ( uCamPos !== undefined ) { 30322 30323 uCamPos.setValue( _gl, _vector3.setFromMatrixPosition( camera.matrixWorld ) ); 30324 30325 } 30326 30327 if ( capabilities.logarithmicDepthBuffer ) { 30328 30329 p_uniforms.setValue( _gl, 'logDepthBufFC', 30330 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); 30331 30332 } 30333 30334 // consider moving isOrthographic to UniformLib and WebGLMaterials, see https://github.com/mrdoob/three.js/pull/26467#issuecomment-1645185067 30335 30336 if ( material.isMeshPhongMaterial || 30337 material.isMeshToonMaterial || 30338 material.isMeshLambertMaterial || 30339 material.isMeshBasicMaterial || 30340 material.isMeshStandardMaterial || 30341 material.isShaderMaterial ) { 30342 30343 p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true ); 30344 30345 } 30346 30347 if ( _currentCamera !== camera ) { 30348 30349 _currentCamera = camera; 30350 30351 // lighting uniforms depend on the camera so enforce an update 30352 // now, in case this material supports lights - or later, when 30353 // the next material that does gets activated: 30354 30355 refreshMaterial = true; // set to true on material change 30356 refreshLights = true; // remains set until update done 30357 30358 } 30359 30360 } 30361 30362 // skinning and morph target uniforms must be set even if material didn't change 30363 // auto-setting of texture unit for bone and morph texture must go before other textures 30364 // otherwise textures used for skinning and morphing can take over texture units reserved for other material textures 30365 30366 if ( object.isSkinnedMesh ) { 30367 30368 p_uniforms.setOptional( _gl, object, 'bindMatrix' ); 30369 p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); 30370 30371 const skeleton = object.skeleton; 30372 30373 if ( skeleton ) { 30374 30375 if ( capabilities.floatVertexTextures ) { 30376 30377 if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture(); 30378 30379 p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures ); 30380 30381 } else { 30382 30383 console.warn( 'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' ); 30384 30385 } 30386 30387 } 30388 30389 } 30390 30391 if ( object.isBatchedMesh ) { 30392 30393 p_uniforms.setOptional( _gl, object, 'batchingTexture' ); 30394 p_uniforms.setValue( _gl, 'batchingTexture', object._matricesTexture, textures ); 30395 30396 } 30397 30398 const morphAttributes = geometry.morphAttributes; 30399 30400 if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined && capabilities.isWebGL2 === true ) ) { 30401 30402 morphtargets.update( object, geometry, program ); 30403 30404 } 30405 30406 if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) { 30407 30408 materialProperties.receiveShadow = object.receiveShadow; 30409 p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow ); 30410 30411 } 30412 30413 // https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512 30414 30415 if ( material.isMeshGouraudMaterial && material.envMap !== null ) { 30416 30417 m_uniforms.envMap.value = envMap; 30418 30419 m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1; 30420 30421 } 30422 30423 if ( refreshMaterial ) { 30424 30425 p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); 30426 30427 if ( materialProperties.needsLights ) { 30428 30429 // the current material requires lighting info 30430 30431 // note: all lighting uniforms are always set correctly 30432 // they simply reference the renderer's state for their 30433 // values 30434 // 30435 // use the current material's .needsUpdate flags to set 30436 // the GL state when required 30437 30438 markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); 30439 30440 } 30441 30442 // refresh uniforms common to several materials 30443 30444 if ( fog && material.fog === true ) { 30445 30446 materials.refreshFogUniforms( m_uniforms, fog ); 30447 30448 } 30449 30450 materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget ); 30451 30452 WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures ); 30453 30454 } 30455 30456 if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { 30457 30458 WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures ); 30459 material.uniformsNeedUpdate = false; 30460 30461 } 30462 30463 if ( material.isSpriteMaterial ) { 30464 30465 p_uniforms.setValue( _gl, 'center', object.center ); 30466 30467 } 30468 30469 // common matrices 30470 30471 p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); 30472 p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); 30473 p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); 30474 30475 // UBOs 30476 30477 if ( material.isShaderMaterial || material.isRawShaderMaterial ) { 30478 30479 const groups = material.uniformsGroups; 30480 30481 for ( let i = 0, l = groups.length; i < l; i ++ ) { 30482 30483 if ( capabilities.isWebGL2 ) { 30484 30485 const group = groups[ i ]; 30486 30487 uniformsGroups.update( group, program ); 30488 uniformsGroups.bind( group, program ); 30489 30490 } else { 30491 30492 console.warn( 'THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.' ); 30493 30494 } 30495 30496 } 30497 30498 } 30499 30500 return program; 30501 30502 } 30503 30504 // If uniforms are marked as clean, they don't need to be loaded to the GPU. 30505 30506 function markUniformsLightsNeedsUpdate( uniforms, value ) { 30507 30508 uniforms.ambientLightColor.needsUpdate = value; 30509 uniforms.lightProbe.needsUpdate = value; 30510 30511 uniforms.directionalLights.needsUpdate = value; 30512 uniforms.directionalLightShadows.needsUpdate = value; 30513 uniforms.pointLights.needsUpdate = value; 30514 uniforms.pointLightShadows.needsUpdate = value; 30515 uniforms.spotLights.needsUpdate = value; 30516 uniforms.spotLightShadows.needsUpdate = value; 30517 uniforms.rectAreaLights.needsUpdate = value; 30518 uniforms.hemisphereLights.needsUpdate = value; 30519 30520 } 30521 30522 function materialNeedsLights( material ) { 30523 30524 return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || 30525 material.isMeshStandardMaterial || material.isShadowMaterial || 30526 ( material.isShaderMaterial && material.lights === true ); 30527 30528 } 30529 30530 this.getActiveCubeFace = function () { 30531 30532 return _currentActiveCubeFace; 30533 30534 }; 30535 30536 this.getActiveMipmapLevel = function () { 30537 30538 return _currentActiveMipmapLevel; 30539 30540 }; 30541 30542 this.getRenderTarget = function () { 30543 30544 return _currentRenderTarget; 30545 30546 }; 30547 30548 this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) { 30549 30550 properties.get( renderTarget.texture ).__webglTexture = colorTexture; 30551 properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture; 30552 30553 const renderTargetProperties = properties.get( renderTarget ); 30554 renderTargetProperties.__hasExternalTextures = true; 30555 30556 if ( renderTargetProperties.__hasExternalTextures ) { 30557 30558 renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined; 30559 30560 if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) { 30561 30562 // The multisample_render_to_texture extension doesn't work properly if there 30563 // are midframe flushes and an external depth buffer. Disable use of the extension. 30564 if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) { 30565 30566 console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' ); 30567 renderTargetProperties.__useRenderToTexture = false; 30568 30569 } 30570 30571 } 30572 30573 } 30574 30575 }; 30576 30577 this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) { 30578 30579 const renderTargetProperties = properties.get( renderTarget ); 30580 renderTargetProperties.__webglFramebuffer = defaultFramebuffer; 30581 renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined; 30582 30583 }; 30584 30585 this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { 30586 30587 _currentRenderTarget = renderTarget; 30588 _currentActiveCubeFace = activeCubeFace; 30589 _currentActiveMipmapLevel = activeMipmapLevel; 30590 30591 let useDefaultFramebuffer = true; 30592 let framebuffer = null; 30593 let isCube = false; 30594 let isRenderTarget3D = false; 30595 30596 if ( renderTarget ) { 30597 30598 const renderTargetProperties = properties.get( renderTarget ); 30599 30600 if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) { 30601 30602 // We need to make sure to rebind the framebuffer. 30603 state.bindFramebuffer( _gl.FRAMEBUFFER, null ); 30604 useDefaultFramebuffer = false; 30605 30606 } else if ( renderTargetProperties.__webglFramebuffer === undefined ) { 30607 30608 textures.setupRenderTarget( renderTarget ); 30609 30610 } else if ( renderTargetProperties.__hasExternalTextures ) { 30611 30612 // Color and depth texture must be rebound in order for the swapchain to update. 30613 textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture ); 30614 30615 } 30616 30617 const texture = renderTarget.texture; 30618 30619 if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { 30620 30621 isRenderTarget3D = true; 30622 30623 } 30624 30625 const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; 30626 30627 if ( renderTarget.isWebGLCubeRenderTarget ) { 30628 30629 if ( Array.isArray( __webglFramebuffer[ activeCubeFace ] ) ) { 30630 30631 framebuffer = __webglFramebuffer[ activeCubeFace ][ activeMipmapLevel ]; 30632 30633 } else { 30634 30635 framebuffer = __webglFramebuffer[ activeCubeFace ]; 30636 30637 } 30638 30639 isCube = true; 30640 30641 } else if ( ( capabilities.isWebGL2 && renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) { 30642 30643 framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer; 30644 30645 } else { 30646 30647 if ( Array.isArray( __webglFramebuffer ) ) { 30648 30649 framebuffer = __webglFramebuffer[ activeMipmapLevel ]; 30650 30651 } else { 30652 30653 framebuffer = __webglFramebuffer; 30654 30655 } 30656 30657 } 30658 30659 _currentViewport.copy( renderTarget.viewport ); 30660 _currentScissor.copy( renderTarget.scissor ); 30661 _currentScissorTest = renderTarget.scissorTest; 30662 30663 } else { 30664 30665 _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor(); 30666 _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor(); 30667 _currentScissorTest = _scissorTest; 30668 30669 } 30670 30671 const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 30672 30673 if ( framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer ) { 30674 30675 state.drawBuffers( renderTarget, framebuffer ); 30676 30677 } 30678 30679 state.viewport( _currentViewport ); 30680 state.scissor( _currentScissor ); 30681 state.setScissorTest( _currentScissorTest ); 30682 30683 if ( isCube ) { 30684 30685 const textureProperties = properties.get( renderTarget.texture ); 30686 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel ); 30687 30688 } else if ( isRenderTarget3D ) { 30689 30690 const textureProperties = properties.get( renderTarget.texture ); 30691 const layer = activeCubeFace || 0; 30692 _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer ); 30693 30694 } 30695 30696 _currentMaterialId = - 1; // reset current material to ensure correct uniform bindings 30697 30698 }; 30699 30700 this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) { 30701 30702 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { 30703 30704 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); 30705 return; 30706 30707 } 30708 30709 let framebuffer = properties.get( renderTarget ).__webglFramebuffer; 30710 30711 if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) { 30712 30713 framebuffer = framebuffer[ activeCubeFaceIndex ]; 30714 30715 } 30716 30717 if ( framebuffer ) { 30718 30719 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 30720 30721 try { 30722 30723 const texture = renderTarget.texture; 30724 const textureFormat = texture.format; 30725 const textureType = texture.type; 30726 30727 if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { 30728 30729 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); 30730 return; 30731 30732 } 30733 30734 const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) ); 30735 30736 if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) 30737 ! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox 30738 ! halfFloatSupportedByExt ) { 30739 30740 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); 30741 return; 30742 30743 } 30744 30745 // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) 30746 30747 if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { 30748 30749 _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); 30750 30751 } 30752 30753 } finally { 30754 30755 // restore framebuffer of current render target if necessary 30756 30757 const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; 30758 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 30759 30760 } 30761 30762 } 30763 30764 }; 30765 30766 this.copyFramebufferToTexture = function ( position, texture, level = 0 ) { 30767 30768 const levelScale = Math.pow( 2, - level ); 30769 const width = Math.floor( texture.image.width * levelScale ); 30770 const height = Math.floor( texture.image.height * levelScale ); 30771 30772 textures.setTexture2D( texture, 0 ); 30773 30774 _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, position.x, position.y, width, height ); 30775 30776 state.unbindTexture(); 30777 30778 }; 30779 30780 this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) { 30781 30782 const width = srcTexture.image.width; 30783 const height = srcTexture.image.height; 30784 const glFormat = utils.convert( dstTexture.format ); 30785 const glType = utils.convert( dstTexture.type ); 30786 30787 textures.setTexture2D( dstTexture, 0 ); 30788 30789 // As another texture upload may have changed pixelStorei 30790 // parameters, make sure they are correct for the dstTexture 30791 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); 30792 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); 30793 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); 30794 30795 if ( srcTexture.isDataTexture ) { 30796 30797 _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data ); 30798 30799 } else { 30800 30801 if ( srcTexture.isCompressedTexture ) { 30802 30803 _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data ); 30804 30805 } else { 30806 30807 _gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image ); 30808 30809 } 30810 30811 } 30812 30813 // Generate mipmaps only when copying level 0 30814 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D ); 30815 30816 state.unbindTexture(); 30817 30818 }; 30819 30820 this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) { 30821 30822 if ( _this.isWebGL1Renderer ) { 30823 30824 console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' ); 30825 return; 30826 30827 } 30828 30829 const width = sourceBox.max.x - sourceBox.min.x + 1; 30830 const height = sourceBox.max.y - sourceBox.min.y + 1; 30831 const depth = sourceBox.max.z - sourceBox.min.z + 1; 30832 const glFormat = utils.convert( dstTexture.format ); 30833 const glType = utils.convert( dstTexture.type ); 30834 let glTarget; 30835 30836 if ( dstTexture.isData3DTexture ) { 30837 30838 textures.setTexture3D( dstTexture, 0 ); 30839 glTarget = _gl.TEXTURE_3D; 30840 30841 } else if ( dstTexture.isDataArrayTexture || dstTexture.isCompressedArrayTexture ) { 30842 30843 textures.setTexture2DArray( dstTexture, 0 ); 30844 glTarget = _gl.TEXTURE_2D_ARRAY; 30845 30846 } else { 30847 30848 console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' ); 30849 return; 30850 30851 } 30852 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 unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH ); 30858 const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT ); 30859 const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS ); 30860 const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS ); 30861 const unpackSkipImages = _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, sourceBox.min.x ); 30868 _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y ); 30869 _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z ); 30870 30871 if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) { 30872 30873 _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data ); 30874 30875 } else { 30876 30877 if ( srcTexture.isCompressedArrayTexture ) { 30878 30879 console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' ); 30880 _gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data ); 30881 30882 } else { 30883 30884 _gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image ); 30885 30886 } 30887 30888 } 30889 30890 _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen ); 30891 _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight ); 30892 _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels ); 30893 _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows ); 30894 _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages ); 30895 30896 // Generate mipmaps only when copying level 0 30897 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget ); 30898 30899 state.unbindTexture(); 30900 30901 }; 30902 30903 this.initTexture = function ( texture ) { 30904 30905 if ( texture.isCubeTexture ) { 30906 30907 textures.setTextureCube( texture, 0 ); 30908 30909 } else if ( texture.isData3DTexture ) { 30910 30911 textures.setTexture3D( texture, 0 ); 30912 30913 } else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { 30914 30915 textures.setTexture2DArray( texture, 0 ); 30916 30917 } else { 30918 30919 textures.setTexture2D( texture, 0 ); 30920 30921 } 30922 30923 state.unbindTexture(); 30924 30925 }; 30926 30927 this.resetState = function () { 30928 30929 _currentActiveCubeFace = 0; 30930 _currentActiveMipmapLevel = 0; 30931 _currentRenderTarget = null; 30932 30933 state.reset(); 30934 bindingStates.reset(); 30935 30936 }; 30937 30938 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { 30939 30940 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); 30941 30942 } 30943 30944 } 30945 30946 get coordinateSystem() { 30947 30948 return WebGLCoordinateSystem; 30949 30950 } 30951 30952 get outputColorSpace() { 30953 30954 return this._outputColorSpace; 30955 30956 } 30957 30958 set outputColorSpace( colorSpace ) { 30959 30960 this._outputColorSpace = colorSpace; 30961 30962 const gl = this.getContext(); 30963 gl.drawingBufferColorSpace = colorSpace === DisplayP3ColorSpace ? 'display-p3' : 'srgb'; 30964 gl.unpackColorSpace = ColorManagement.workingColorSpace === LinearDisplayP3ColorSpace ? 'display-p3' : 'srgb'; 30965 30966 } 30967 30968 get outputEncoding() { // @deprecated, r152 30969 30970 console.warn( 'THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.' ); 30971 return this.outputColorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding; 30972 30973 } 30974 30975 set outputEncoding( encoding ) { // @deprecated, r152 30976 30977 console.warn( 'THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.' ); 30978 this.outputColorSpace = encoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace; 30979 30980 } 30981 30982 get useLegacyLights() { // @deprecated, r155 30983 30984 console.warn( 'THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733.' ); 30985 return this._useLegacyLights; 30986 30987 } 30988 30989 set useLegacyLights( value ) { // @deprecated, r155 30990 30991 console.warn( 'THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733.' ); 30992 this._useLegacyLights = value; 30993 30994 } 30995 30996} 30997 30998class WebGL1Renderer extends WebGLRenderer {} 30999 31000WebGL1Renderer.prototype.isWebGL1Renderer = true; 31001 31002class FogExp2 {
vendor: 11,018 bytes, lines 31003-31656
31003 31004 constructor( color, density = 0.00025 ) { 31005 31006 this.isFogExp2 = true; 31007 31008 this.name = ''; 31009 31010 this.color = new Color( color ); 31011 this.density = density; 31012 31013 } 31014 31015 clone() { 31016 31017 return new FogExp2( this.color, this.density ); 31018 31019 } 31020 31021 toJSON( /* meta */ ) { 31022 31023 return { 31024 type: 'FogExp2', 31025 name: this.name, 31026 color: this.color.getHex(), 31027 density: this.density 31028 }; 31029 31030 } 31031 31032} 31033 31034class Fog { 31035 31036 constructor( color, near = 1, far = 1000 ) { 31037 31038 this.isFog = true; 31039 31040 this.name = ''; 31041 31042 this.color = new Color( color ); 31043 31044 this.near = near; 31045 this.far = far; 31046 31047 } 31048 31049 clone() { 31050 31051 return new Fog( this.color, this.near, this.far ); 31052 31053 } 31054 31055 toJSON( /* meta */ ) { 31056 31057 return { 31058 type: 'Fog', 31059 name: this.name, 31060 color: this.color.getHex(), 31061 near: this.near, 31062 far: this.far 31063 }; 31064 31065 } 31066 31067} 31068 31069class Scene extends Object3D { 31070 31071 constructor() { 31072 31073 super(); 31074 31075 this.isScene = true; 31076 31077 this.type = 'Scene'; 31078 31079 this.background = null; 31080 this.environment = null; 31081 this.fog = null; 31082 31083 this.backgroundBlurriness = 0; 31084 this.backgroundIntensity = 1; 31085 31086 this.overrideMaterial = null; 31087 31088 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { 31089 31090 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); 31091 31092 } 31093 31094 } 31095 31096 copy( source, recursive ) { 31097 31098 super.copy( source, recursive ); 31099 31100 if ( source.background !== null ) this.background = source.background.clone(); 31101 if ( source.environment !== null ) this.environment = source.environment.clone(); 31102 if ( source.fog !== null ) this.fog = source.fog.clone(); 31103 31104 this.backgroundBlurriness = source.backgroundBlurriness; 31105 this.backgroundIntensity = source.backgroundIntensity; 31106 31107 if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone(); 31108 31109 this.matrixAutoUpdate = source.matrixAutoUpdate; 31110 31111 return this; 31112 31113 } 31114 31115 toJSON( meta ) { 31116 31117 const data = super.toJSON( meta ); 31118 31119 if ( this.fog !== null ) data.object.fog = this.fog.toJSON(); 31120 if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness; 31121 if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity; 31122 31123 return data; 31124 31125 } 31126 31127} 31128 31129class InterleavedBuffer { 31130 31131 constructor( array, stride ) { 31132 31133 this.isInterleavedBuffer = true; 31134 31135 this.array = array; 31136 this.stride = stride; 31137 this.count = array !== undefined ? array.length / stride : 0; 31138 31139 this.usage = StaticDrawUsage; 31140 this._updateRange = { offset: 0, count: - 1 }; 31141 this.updateRanges = []; 31142 31143 this.version = 0; 31144 31145 this.uuid = generateUUID(); 31146 31147 } 31148 31149 onUploadCallback() {} 31150 31151 set needsUpdate( value ) { 31152 31153 if ( value === true ) this.version ++; 31154 31155 } 31156 31157 get updateRange() { 31158 31159 console.warn( 'THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 31160 return this._updateRange; 31161 31162 } 31163 31164 setUsage( value ) { 31165 31166 this.usage = value; 31167 31168 return this; 31169 31170 } 31171 31172 addUpdateRange( start, count ) { 31173 31174 this.updateRanges.push( { start, count } ); 31175 31176 } 31177 31178 clearUpdateRanges() { 31179 31180 this.updateRanges.length = 0; 31181 31182 } 31183 31184 copy( source ) { 31185 31186 this.array = new source.array.constructor( source.array ); 31187 this.count = source.count; 31188 this.stride = source.stride; 31189 this.usage = source.usage; 31190 31191 return this; 31192 31193 } 31194 31195 copyAt( index1, attribute, index2 ) { 31196 31197 index1 *= this.stride; 31198 index2 *= attribute.stride; 31199 31200 for ( let i = 0, l = this.stride; i < l; i ++ ) { 31201 31202 this.array[ index1 + i ] = attribute.array[ index2 + i ]; 31203 31204 } 31205 31206 return this; 31207 31208 } 31209 31210 set( value, offset = 0 ) { 31211 31212 this.array.set( value, offset ); 31213 31214 return this; 31215 31216 } 31217 31218 clone( data ) { 31219 31220 if ( data.arrayBuffers === undefined ) { 31221 31222 data.arrayBuffers = {}; 31223 31224 } 31225 31226 if ( this.array.buffer._uuid === undefined ) { 31227 31228 this.array.buffer._uuid = generateUUID(); 31229 31230 } 31231 31232 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { 31233 31234 data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer; 31235 31236 } 31237 31238 const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] ); 31239 31240 const ib = new this.constructor( array, this.stride ); 31241 ib.setUsage( this.usage ); 31242 31243 return ib; 31244 31245 } 31246 31247 onUpload( callback ) { 31248 31249 this.onUploadCallback = callback; 31250 31251 return this; 31252 31253 } 31254 31255 toJSON( data ) { 31256 31257 if ( data.arrayBuffers === undefined ) { 31258 31259 data.arrayBuffers = {}; 31260 31261 } 31262 31263 // generate UUID for array buffer if necessary 31264 31265 if ( this.array.buffer._uuid === undefined ) { 31266 31267 this.array.buffer._uuid = generateUUID(); 31268 31269 } 31270 31271 if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { 31272 31273 data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) ); 31274 31275 } 31276 31277 // 31278 31279 return { 31280 uuid: this.uuid, 31281 buffer: this.array.buffer._uuid, 31282 type: this.array.constructor.name, 31283 stride: this.stride 31284 }; 31285 31286 } 31287 31288} 31289 31290const _vector$6 = /*@__PURE__*/ new Vector3(); 31291 31292class InterleavedBufferAttribute { 31293 31294 constructor( interleavedBuffer, itemSize, offset, normalized = false ) { 31295 31296 this.isInterleavedBufferAttribute = true; 31297 31298 this.name = ''; 31299 31300 this.data = interleavedBuffer; 31301 this.itemSize = itemSize; 31302 this.offset = offset; 31303 31304 this.normalized = normalized; 31305 31306 } 31307 31308 get count() { 31309 31310 return this.data.count; 31311 31312 } 31313 31314 get array() { 31315 31316 return this.data.array; 31317 31318 } 31319 31320 set needsUpdate( value ) { 31321 31322 this.data.needsUpdate = value; 31323 31324 } 31325 31326 applyMatrix4( m ) { 31327 31328 for ( let i = 0, l = this.data.count; i < l; i ++ ) { 31329 31330 _vector$6.fromBufferAttribute( this, i ); 31331 31332 _vector$6.applyMatrix4( m ); 31333 31334 this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); 31335 31336 } 31337 31338 return this; 31339 31340 } 31341 31342 applyNormalMatrix( m ) { 31343 31344 for ( let i = 0, l = this.count; i < l; i ++ ) { 31345 31346 _vector$6.fromBufferAttribute( this, i ); 31347 31348 _vector$6.applyNormalMatrix( m ); 31349 31350 this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); 31351 31352 } 31353 31354 return this; 31355 31356 } 31357 31358 transformDirection( m ) { 31359 31360 for ( let i = 0, l = this.count; i < l; i ++ ) { 31361 31362 _vector$6.fromBufferAttribute( this, i ); 31363 31364 _vector$6.transformDirection( m ); 31365 31366 this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z ); 31367 31368 } 31369 31370 return this; 31371 31372 } 31373 31374 setX( index, x ) { 31375 31376 if ( this.normalized ) x = normalize( x, this.array ); 31377 31378 this.data.array[ index * this.data.stride + this.offset ] = x; 31379 31380 return this; 31381 31382 } 31383 31384 setY( index, y ) { 31385 31386 if ( this.normalized ) y = normalize( y, this.array ); 31387 31388 this.data.array[ index * this.data.stride + this.offset + 1 ] = y; 31389 31390 return this; 31391 31392 } 31393 31394 setZ( index, z ) { 31395 31396 if ( this.normalized ) z = normalize( z, this.array ); 31397 31398 this.data.array[ index * this.data.stride + this.offset + 2 ] = z; 31399 31400 return this; 31401 31402 } 31403 31404 setW( index, w ) { 31405 31406 if ( this.normalized ) w = normalize( w, this.array ); 31407 31408 this.data.array[ index * this.data.stride + this.offset + 3 ] = w; 31409 31410 return this; 31411 31412 } 31413 31414 getX( index ) { 31415 31416 let x = this.data.array[ index * this.data.stride + this.offset ]; 31417 31418 if ( this.normalized ) x = denormalize( x, this.array ); 31419 31420 return x; 31421 31422 } 31423 31424 getY( index ) { 31425 31426 let y = this.data.array[ index * this.data.stride + this.offset + 1 ]; 31427 31428 if ( this.normalized ) y = denormalize( y, this.array ); 31429 31430 return y; 31431 31432 } 31433 31434 getZ( index ) { 31435 31436 let z = this.data.array[ index * this.data.stride + this.offset + 2 ]; 31437 31438 if ( this.normalized ) z = denormalize( z, this.array ); 31439 31440 return z; 31441 31442 } 31443 31444 getW( index ) { 31445 31446 let w = this.data.array[ index * this.data.stride + this.offset + 3 ]; 31447 31448 if ( this.normalized ) w = denormalize( w, this.array ); 31449 31450 return w; 31451 31452 } 31453 31454 setXY( index, x, y ) { 31455 31456 index = index * this.data.stride + this.offset; 31457 31458 if ( this.normalized ) { 31459 31460 x = normalize( x, this.array ); 31461 y = normalize( y, this.array ); 31462 31463 } 31464 31465 this.data.array[ index + 0 ] = x; 31466 this.data.array[ index + 1 ] = y; 31467 31468 return this; 31469 31470 } 31471 31472 setXYZ( index, x, y, z ) { 31473 31474 index = index * this.data.stride + this.offset; 31475 31476 if ( this.normalized ) { 31477 31478 x = normalize( x, this.array ); 31479 y = normalize( y, this.array ); 31480 z = normalize( z, this.array ); 31481 31482 } 31483 31484 this.data.array[ index + 0 ] = x; 31485 this.data.array[ index + 1 ] = y; 31486 this.data.array[ index + 2 ] = z; 31487 31488 return this; 31489 31490 } 31491 31492 setXYZW( index, x, y, z, w ) { 31493 31494 index = index * this.data.stride + this.offset; 31495 31496 if ( this.normalized ) { 31497 31498 x = normalize( x, this.array ); 31499 y = normalize( y, this.array ); 31500 z = normalize( z, this.array ); 31501 w = normalize( w, this.array ); 31502 31503 } 31504 31505 this.data.array[ index + 0 ] = x; 31506 this.data.array[ index + 1 ] = y; 31507 this.data.array[ index + 2 ] = z; 31508 this.data.array[ index + 3 ] = w; 31509 31510 return this; 31511 31512 } 31513 31514 clone( data ) { 31515 31516 if ( data === undefined ) { 31517 31518 console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' ); 31519 31520 const array = []; 31521 31522 for ( let i = 0; i < this.count; i ++ ) { 31523 31524 const index = i * this.data.stride + this.offset; 31525 31526 for ( let j = 0; j < this.itemSize; j ++ ) { 31527 31528 array.push( this.data.array[ index + j ] ); 31529 31530 } 31531 31532 } 31533 31534 return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized ); 31535 31536 } else { 31537 31538 if ( data.interleavedBuffers === undefined ) { 31539 31540 data.interleavedBuffers = {}; 31541 31542 } 31543 31544 if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { 31545 31546 data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data ); 31547 31548 } 31549 31550 return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized ); 31551 31552 } 31553 31554 } 31555 31556 toJSON( data ) { 31557 31558 if ( data === undefined ) { 31559 31560 console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' ); 31561 31562 const array = []; 31563 31564 for ( let i = 0; i < this.count; i ++ ) { 31565 31566 const index = i * this.data.stride + this.offset; 31567 31568 for ( let j = 0; j < this.itemSize; j ++ ) { 31569 31570 array.push( this.data.array[ index + j ] ); 31571 31572 } 31573 31574 } 31575 31576 // de-interleave data and save it as an ordinary buffer attribute for now 31577 31578 return { 31579 itemSize: this.itemSize, 31580 type: this.array.constructor.name, 31581 array: array, 31582 normalized: this.normalized 31583 }; 31584 31585 } else { 31586 31587 // save as true interleaved attribute 31588 31589 if ( data.interleavedBuffers === undefined ) { 31590 31591 data.interleavedBuffers = {}; 31592 31593 } 31594 31595 if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { 31596 31597 data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data ); 31598 31599 } 31600 31601 return { 31602 isInterleavedBufferAttribute: true, 31603 itemSize: this.itemSize, 31604 data: this.data.uuid, 31605 offset: this.offset, 31606 normalized: this.normalized 31607 }; 31608 31609 } 31610 31611 } 31612 31613} 31614 31615class SpriteMaterial extends Material { 31616 31617 constructor( parameters ) { 31618 31619 super(); 31620 31621 this.isSpriteMaterial = true; 31622 31623 this.type = 'SpriteMaterial'; 31624 31625 this.color = new Color( 0xffffff ); 31626 31627 this.map = null; 31628 31629 this.alphaMap = null; 31630 31631 this.rotation = 0; 31632 31633 this.sizeAttenuation = true; 31634 31635 this.transparent = true; 31636 31637 this.fog = true; 31638 31639 this.setValues( parameters ); 31640 31641 } 31642 31643 copy( source ) { 31644 31645 super.copy( source ); 31646 31647 this.color.copy( source.color ); 31648 31649 this.map = source.map; 31650 31651 this.alphaMap = source.alphaMap; 31652 31653 this.rotation = source.rotation; 31654 31655 this.sizeAttenuation = source.sizeAttenuation; 31656
vendor: 6,736 bytes, lines 31657-31993
31657 this.fog = source.fog; 31658 31659 return this; 31660 31661 } 31662 31663} 31664 31665let _geometry; 31666 31667const _intersectPoint = /*@__PURE__*/ new Vector3(); 31668const _worldScale = /*@__PURE__*/ new Vector3(); 31669const _mvPosition = /*@__PURE__*/ new Vector3(); 31670 31671const _alignedPosition = /*@__PURE__*/ new Vector2(); 31672const _rotatedPosition = /*@__PURE__*/ new Vector2(); 31673const _viewWorldMatrix = /*@__PURE__*/ new Matrix4(); 31674 31675const _vA = /*@__PURE__*/ new Vector3(); 31676const _vB = /*@__PURE__*/ new Vector3(); 31677const _vC = /*@__PURE__*/ new Vector3(); 31678 31679const _uvA = /*@__PURE__*/ new Vector2(); 31680const _uvB = /*@__PURE__*/ new Vector2(); 31681const _uvC = /*@__PURE__*/ new Vector2(); 31682 31683class Sprite extends Object3D { 31684 31685 constructor( material = new SpriteMaterial() ) { 31686 31687 super(); 31688 31689 this.isSprite = true; 31690 31691 this.type = 'Sprite'; 31692 31693 if ( _geometry === undefined ) { 31694 31695 _geometry = new BufferGeometry(); 31696 31697 const float32Array = new Float32Array( [ 31698 - 0.5, - 0.5, 0, 0, 0, 31699 0.5, - 0.5, 0, 1, 0, 31700 0.5, 0.5, 0, 1, 1, 31701 - 0.5, 0.5, 0, 0, 1 31702 ] ); 31703 31704 const interleavedBuffer = new InterleavedBuffer( float32Array, 5 ); 31705 31706 _geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] ); 31707 _geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) ); 31708 _geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) ); 31709 31710 } 31711 31712 this.geometry = _geometry; 31713 this.material = material; 31714 31715 this.center = new Vector2( 0.5, 0.5 ); 31716 31717 } 31718 31719 raycast( raycaster, intersects ) { 31720 31721 if ( raycaster.camera === null ) { 31722 31723 console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' ); 31724 31725 } 31726 31727 _worldScale.setFromMatrixScale( this.matrixWorld ); 31728 31729 _viewWorldMatrix.copy( raycaster.camera.matrixWorld ); 31730 this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld ); 31731 31732 _mvPosition.setFromMatrixPosition( this.modelViewMatrix ); 31733 31734 if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) { 31735 31736 _worldScale.multiplyScalar( - _mvPosition.z ); 31737 31738 } 31739 31740 const rotation = this.material.rotation; 31741 let sin, cos; 31742 31743 if ( rotation !== 0 ) { 31744 31745 cos = Math.cos( rotation ); 31746 sin = Math.sin( rotation ); 31747 31748 } 31749 31750 const center = this.center; 31751 31752 transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 31753 transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 31754 transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 31755 31756 _uvA.set( 0, 0 ); 31757 _uvB.set( 1, 0 ); 31758 _uvC.set( 1, 1 ); 31759 31760 // check first triangle 31761 let intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC, false, _intersectPoint ); 31762 31763 if ( intersect === null ) { 31764 31765 // check second triangle 31766 transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); 31767 _uvB.set( 0, 1 ); 31768 31769 intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB, false, _intersectPoint ); 31770 if ( intersect === null ) { 31771 31772 return; 31773 31774 } 31775 31776 } 31777 31778 const distance = raycaster.ray.origin.distanceTo( _intersectPoint ); 31779 31780 if ( distance < raycaster.near || distance > raycaster.far ) return; 31781 31782 intersects.push( { 31783 31784 distance: distance, 31785 point: _intersectPoint.clone(), 31786 uv: Triangle.getInterpolation( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), 31787 face: null, 31788 object: this 31789 31790 } ); 31791 31792 } 31793 31794 copy( source, recursive ) { 31795 31796 super.copy( source, recursive ); 31797 31798 if ( source.center !== undefined ) this.center.copy( source.center ); 31799 31800 this.material = source.material; 31801 31802 return this; 31803 31804 } 31805 31806} 31807 31808function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) { 31809 31810 // compute position in camera space 31811 _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale ); 31812 31813 // to check if rotation is not zero 31814 if ( sin !== undefined ) { 31815 31816 _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y ); 31817 _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y ); 31818 31819 } else { 31820 31821 _rotatedPosition.copy( _alignedPosition ); 31822 31823 } 31824 31825 31826 vertexPosition.copy( mvPosition ); 31827 vertexPosition.x += _rotatedPosition.x; 31828 vertexPosition.y += _rotatedPosition.y; 31829 31830 // transform to world space 31831 vertexPosition.applyMatrix4( _viewWorldMatrix ); 31832 31833} 31834 31835const _v1$2 = /*@__PURE__*/ new Vector3(); 31836const _v2$1 = /*@__PURE__*/ new Vector3(); 31837 31838class LOD extends Object3D { 31839 31840 constructor() { 31841 31842 super(); 31843 31844 this._currentLevel = 0; 31845 31846 this.type = 'LOD'; 31847 31848 Object.defineProperties( this, { 31849 levels: { 31850 enumerable: true, 31851 value: [] 31852 }, 31853 isLOD: { 31854 value: true, 31855 } 31856 } ); 31857 31858 this.autoUpdate = true; 31859 31860 } 31861 31862 copy( source ) { 31863 31864 super.copy( source, false ); 31865 31866 const levels = source.levels; 31867 31868 for ( let i = 0, l = levels.length; i < l; i ++ ) { 31869 31870 const level = levels[ i ]; 31871 31872 this.addLevel( level.object.clone(), level.distance, level.hysteresis ); 31873 31874 } 31875 31876 this.autoUpdate = source.autoUpdate; 31877 31878 return this; 31879 31880 } 31881 31882 addLevel( object, distance = 0, hysteresis = 0 ) { 31883 31884 distance = Math.abs( distance ); 31885 31886 const levels = this.levels; 31887 31888 let l; 31889 31890 for ( l = 0; l < levels.length; l ++ ) { 31891 31892 if ( distance < levels[ l ].distance ) { 31893 31894 break; 31895 31896 } 31897 31898 } 31899 31900 levels.splice( l, 0, { distance: distance, hysteresis: hysteresis, object: object } ); 31901 31902 this.add( object ); 31903 31904 return this; 31905 31906 } 31907 31908 getCurrentLevel() { 31909 31910 return this._currentLevel; 31911 31912 } 31913 31914 31915 31916 getObjectForDistance( distance ) { 31917 31918 const levels = this.levels; 31919 31920 if ( levels.length > 0 ) { 31921 31922 let i, l; 31923 31924 for ( i = 1, l = levels.length; i < l; i ++ ) { 31925 31926 let levelDistance = levels[ i ].distance; 31927 31928 if ( levels[ i ].object.visible ) { 31929 31930 levelDistance -= levelDistance * levels[ i ].hysteresis; 31931 31932 } 31933 31934 if ( distance < levelDistance ) { 31935 31936 break; 31937 31938 } 31939 31940 } 31941 31942 return levels[ i - 1 ].object; 31943 31944 } 31945 31946 return null; 31947 31948 } 31949 31950 raycast( raycaster, intersects ) { 31951 31952 const levels = this.levels; 31953 31954 if ( levels.length > 0 ) { 31955 31956 _v1$2.setFromMatrixPosition( this.matrixWorld ); 31957 31958 const distance = raycaster.ray.origin.distanceTo( _v1$2 ); 31959 31960 this.getObjectForDistance( distance ).raycast( raycaster, intersects ); 31961 31962 } 31963 31964 } 31965 31966 update( camera ) { 31967 31968 const levels = this.levels; 31969 31970 if ( levels.length > 1 ) { 31971 31972 _v1$2.setFromMatrixPosition( camera.matrixWorld ); 31973 _v2$1.setFromMatrixPosition( this.matrixWorld ); 31974 31975 const distance = _v1$2.distanceTo( _v2$1 ) / camera.zoom; 31976 31977 levels[ 0 ].object.visible = true; 31978 31979 let i, l; 31980 31981 for ( i = 1, l = levels.length; i < l; i ++ ) { 31982 31983 let levelDistance = levels[ i ].distance; 31984 31985 if ( levels[ i ].object.visible ) { 31986 31987 levelDistance -= levelDistance * levels[ i ].hysteresis; 31988 31989 } 31990 31991 if ( distance >= levelDistance ) { 31992 31993 levels[ i - 1 ].object.visible = false;
vendor: 4,383 bytes, lines 31994-32227
31994 levels[ i ].object.visible = true; 31995 31996 } else { 31997 31998 break; 31999 32000 } 32001 32002 } 32003 32004 this._currentLevel = i - 1; 32005 32006 for ( ; i < l; i ++ ) { 32007 32008 levels[ i ].object.visible = false; 32009 32010 } 32011 32012 } 32013 32014 } 32015 32016 toJSON( meta ) { 32017 32018 const data = super.toJSON( meta ); 32019 32020 if ( this.autoUpdate === false ) data.object.autoUpdate = false; 32021 32022 data.object.levels = []; 32023 32024 const levels = this.levels; 32025 32026 for ( let i = 0, l = levels.length; i < l; i ++ ) { 32027 32028 const level = levels[ i ]; 32029 32030 data.object.levels.push( { 32031 object: level.object.uuid, 32032 distance: level.distance, 32033 hysteresis: level.hysteresis 32034 } ); 32035 32036 } 32037 32038 return data; 32039 32040 } 32041 32042} 32043 32044const _basePosition = /*@__PURE__*/ new Vector3(); 32045 32046const _skinIndex = /*@__PURE__*/ new Vector4(); 32047const _skinWeight = /*@__PURE__*/ new Vector4(); 32048 32049const _vector3 = /*@__PURE__*/ new Vector3(); 32050const _matrix4 = /*@__PURE__*/ new Matrix4(); 32051const _vertex = /*@__PURE__*/ new Vector3(); 32052 32053const _sphere$4 = /*@__PURE__*/ new Sphere(); 32054const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); 32055const _ray$2 = /*@__PURE__*/ new Ray(); 32056 32057class SkinnedMesh extends Mesh { 32058 32059 constructor( geometry, material ) { 32060 32061 super( geometry, material ); 32062 32063 this.isSkinnedMesh = true; 32064 32065 this.type = 'SkinnedMesh'; 32066 32067 this.bindMode = AttachedBindMode; 32068 this.bindMatrix = new Matrix4(); 32069 this.bindMatrixInverse = new Matrix4(); 32070 32071 this.boundingBox = null; 32072 this.boundingSphere = null; 32073 32074 } 32075 32076 computeBoundingBox() { 32077 32078 const geometry = this.geometry; 32079 32080 if ( this.boundingBox === null ) { 32081 32082 this.boundingBox = new Box3(); 32083 32084 } 32085 32086 this.boundingBox.makeEmpty(); 32087 32088 const positionAttribute = geometry.getAttribute( 'position' ); 32089 32090 for ( let i = 0; i < positionAttribute.count; i ++ ) { 32091 32092 this.getVertexPosition( i, _vertex ); 32093 this.boundingBox.expandByPoint( _vertex ); 32094 32095 } 32096 32097 } 32098 32099 computeBoundingSphere() { 32100 32101 const geometry = this.geometry; 32102 32103 if ( this.boundingSphere === null ) { 32104 32105 this.boundingSphere = new Sphere(); 32106 32107 } 32108 32109 this.boundingSphere.makeEmpty(); 32110 32111 const positionAttribute = geometry.getAttribute( 'position' ); 32112 32113 for ( let i = 0; i < positionAttribute.count; i ++ ) { 32114 32115 this.getVertexPosition( i, _vertex ); 32116 this.boundingSphere.expandByPoint( _vertex ); 32117 32118 } 32119 32120 } 32121 32122 copy( source, recursive ) { 32123 32124 super.copy( source, recursive ); 32125 32126 this.bindMode = source.bindMode; 32127 this.bindMatrix.copy( source.bindMatrix ); 32128 this.bindMatrixInverse.copy( source.bindMatrixInverse ); 32129 32130 this.skeleton = source.skeleton; 32131 32132 if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); 32133 if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); 32134 32135 return this; 32136 32137 } 32138 32139 raycast( raycaster, intersects ) { 32140 32141 const material = this.material; 32142 const matrixWorld = this.matrixWorld; 32143 32144 if ( material === undefined ) return; 32145 32146 // test with bounding sphere in world space 32147 32148 if ( this.boundingSphere === null ) this.computeBoundingSphere(); 32149 32150 _sphere$4.copy( this.boundingSphere ); 32151 _sphere$4.applyMatrix4( matrixWorld ); 32152 32153 if ( raycaster.ray.intersectsSphere( _sphere$4 ) === false ) return; 32154 32155 // convert ray to local space of skinned mesh 32156 32157 _inverseMatrix$2.copy( matrixWorld ).invert(); 32158 _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); 32159 32160 // test with bounding box in local space 32161 32162 if ( this.boundingBox !== null ) { 32163 32164 if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return; 32165 32166 } 32167 32168 // test for intersections with geometry 32169 32170 this._computeIntersections( raycaster, intersects, _ray$2 ); 32171 32172 } 32173 32174 getVertexPosition( index, target ) { 32175 32176 super.getVertexPosition( index, target ); 32177 32178 this.applyBoneTransform( index, target ); 32179 32180 return target; 32181 32182 } 32183 32184 bind( skeleton, bindMatrix ) { 32185 32186 this.skeleton = skeleton; 32187 32188 if ( bindMatrix === undefined ) { 32189 32190 this.updateMatrixWorld( true ); 32191 32192 this.skeleton.calculateInverses(); 32193 32194 bindMatrix = this.matrixWorld; 32195 32196 } 32197 32198 this.bindMatrix.copy( bindMatrix ); 32199 this.bindMatrixInverse.copy( bindMatrix ).invert(); 32200 32201 } 32202 32203 pose() { 32204 32205 this.skeleton.pose(); 32206 32207 } 32208 32209 normalizeSkinWeights() { 32210 32211 const vector = new Vector4(); 32212 32213 const skinWeight = this.geometry.attributes.skinWeight; 32214 32215 for ( let i = 0, l = skinWeight.count; i < l; i ++ ) { 32216 32217 vector.fromBufferAttribute( skinWeight, i ); 32218 32219 const scale = 1.0 / vector.manhattanLength(); 32220 32221 if ( scale !== Infinity ) { 32222 32223 vector.multiplyScalar( scale ); 32224 32225 } else { 32226 32227 vector.set( 1, 0, 0, 0 );
vendor: 11,452 bytes, lines 32227-32822
32227 // do something reasonable 32228 32229 } 32230 32231 skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w ); 32232 32233 } 32234 32235 } 32236 32237 updateMatrixWorld( force ) { 32238 32239 super.updateMatrixWorld( force ); 32240 32241 if ( this.bindMode === AttachedBindMode ) { 32242 32243 this.bindMatrixInverse.copy( this.matrixWorld ).invert(); 32244 32245 } else if ( this.bindMode === DetachedBindMode ) { 32246 32247 this.bindMatrixInverse.copy( this.bindMatrix ).invert(); 32248 32249 } else { 32250 32251 console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); 32252 32253 } 32254 32255 } 32256 32257 applyBoneTransform( index, vector ) { 32258 32259 const skeleton = this.skeleton; 32260 const geometry = this.geometry; 32261 32262 _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); 32263 _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); 32264 32265 _basePosition.copy( vector ).applyMatrix4( this.bindMatrix ); 32266 32267 vector.set( 0, 0, 0 ); 32268 32269 for ( let i = 0; i < 4; i ++ ) { 32270 32271 const weight = _skinWeight.getComponent( i ); 32272 32273 if ( weight !== 0 ) { 32274 32275 const boneIndex = _skinIndex.getComponent( i ); 32276 32277 _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); 32278 32279 vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); 32280 32281 } 32282 32283 } 32284 32285 return vector.applyMatrix4( this.bindMatrixInverse ); 32286 32287 } 32288 32289 boneTransform( index, vector ) { // @deprecated, r151 32290 32291 console.warn( 'THREE.SkinnedMesh: .boneTransform() was renamed to .applyBoneTransform() in r151.' ); 32292 return this.applyBoneTransform( index, vector ); 32293 32294 } 32295 32296 32297} 32298 32299class Bone extends Object3D { 32300 32301 constructor() { 32302 32303 super(); 32304 32305 this.isBone = true; 32306 32307 this.type = 'Bone'; 32308 32309 } 32310 32311} 32312 32313class DataTexture extends Texture { 32314 32315 constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { 32316 32317 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); 32318 32319 this.isDataTexture = true; 32320 32321 this.image = { data: data, width: width, height: height }; 32322 32323 this.generateMipmaps = false; 32324 this.flipY = false; 32325 this.unpackAlignment = 1; 32326 32327 } 32328 32329} 32330 32331const _offsetMatrix = /*@__PURE__*/ new Matrix4(); 32332const _identityMatrix$1 = /*@__PURE__*/ new Matrix4(); 32333 32334class Skeleton { 32335 32336 constructor( bones = [], boneInverses = [] ) { 32337 32338 this.uuid = generateUUID(); 32339 32340 this.bones = bones.slice( 0 ); 32341 this.boneInverses = boneInverses; 32342 this.boneMatrices = null; 32343 32344 this.boneTexture = null; 32345 32346 this.init(); 32347 32348 } 32349 32350 init() { 32351 32352 const bones = this.bones; 32353 const boneInverses = this.boneInverses; 32354 32355 this.boneMatrices = new Float32Array( bones.length * 16 ); 32356 32357 // calculate inverse bone matrices if necessary 32358 32359 if ( boneInverses.length === 0 ) { 32360 32361 this.calculateInverses(); 32362 32363 } else { 32364 32365 // handle special case 32366 32367 if ( bones.length !== boneInverses.length ) { 32368 32369 console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' ); 32370 32371 this.boneInverses = []; 32372 32373 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32374 32375 this.boneInverses.push( new Matrix4() ); 32376 32377 } 32378 32379 } 32380 32381 } 32382 32383 } 32384 32385 calculateInverses() { 32386 32387 this.boneInverses.length = 0; 32388 32389 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32390 32391 const inverse = new Matrix4(); 32392 32393 if ( this.bones[ i ] ) { 32394 32395 inverse.copy( this.bones[ i ].matrixWorld ).invert(); 32396 32397 } 32398 32399 this.boneInverses.push( inverse ); 32400 32401 } 32402 32403 } 32404 32405 pose() { 32406 32407 // recover the bind-time world matrices 32408 32409 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32410 32411 const bone = this.bones[ i ]; 32412 32413 if ( bone ) { 32414 32415 bone.matrixWorld.copy( this.boneInverses[ i ] ).invert(); 32416 32417 } 32418 32419 } 32420 32421 // compute the local matrices, positions, rotations and scales 32422 32423 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32424 32425 const bone = this.bones[ i ]; 32426 32427 if ( bone ) { 32428 32429 if ( bone.parent && bone.parent.isBone ) { 32430 32431 bone.matrix.copy( bone.parent.matrixWorld ).invert(); 32432 bone.matrix.multiply( bone.matrixWorld ); 32433 32434 } else { 32435 32436 bone.matrix.copy( bone.matrixWorld ); 32437 32438 } 32439 32440 bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); 32441 32442 } 32443 32444 } 32445 32446 } 32447 32448 update() { 32449 32450 const bones = this.bones; 32451 const boneInverses = this.boneInverses; 32452 const boneMatrices = this.boneMatrices; 32453 const boneTexture = this.boneTexture; 32454 32455 // flatten bone matrices to array 32456 32457 for ( let i = 0, il = bones.length; i < il; i ++ ) { 32458 32459 // compute the offset between the current and the original transform 32460 32461 const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix$1; 32462 32463 _offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); 32464 _offsetMatrix.toArray( boneMatrices, i * 16 ); 32465 32466 } 32467 32468 if ( boneTexture !== null ) { 32469 32470 boneTexture.needsUpdate = true; 32471 32472 } 32473 32474 } 32475 32476 clone() { 32477 32478 return new Skeleton( this.bones, this.boneInverses ); 32479 32480 } 32481 32482 computeBoneTexture() { 32483 32484 // layout (1 matrix = 4 pixels) 32485 // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) 32486 // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) 32487 // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) 32488 // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) 32489 // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) 32490 32491 let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix 32492 size = Math.ceil( size / 4 ) * 4; 32493 size = Math.max( size, 4 ); 32494 32495 const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel 32496 boneMatrices.set( this.boneMatrices ); // copy current values 32497 32498 const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); 32499 boneTexture.needsUpdate = true; 32500 32501 this.boneMatrices = boneMatrices; 32502 this.boneTexture = boneTexture; 32503 32504 return this; 32505 32506 } 32507 32508 getBoneByName( name ) { 32509 32510 for ( let i = 0, il = this.bones.length; i < il; i ++ ) { 32511 32512 const bone = this.bones[ i ]; 32513 32514 if ( bone.name === name ) { 32515 32516 return bone; 32517 32518 } 32519 32520 } 32521 32522 return undefined; 32523 32524 } 32525 32526 dispose( ) { 32527 32528 if ( this.boneTexture !== null ) { 32529 32530 this.boneTexture.dispose(); 32531 32532 this.boneTexture = null; 32533 32534 } 32535 32536 } 32537 32538 fromJSON( json, bones ) { 32539 32540 this.uuid = json.uuid; 32541 32542 for ( let i = 0, l = json.bones.length; i < l; i ++ ) { 32543 32544 const uuid = json.bones[ i ]; 32545 let bone = bones[ uuid ]; 32546 32547 if ( bone === undefined ) { 32548 32549 console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid ); 32550 bone = new Bone(); 32551 32552 } 32553 32554 this.bones.push( bone ); 32555 this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) ); 32556 32557 } 32558 32559 this.init(); 32560 32561 return this; 32562 32563 } 32564 32565 toJSON() { 32566 32567 const data = { 32568 metadata: { 32569 version: 4.6, 32570 type: 'Skeleton', 32571 generator: 'Skeleton.toJSON' 32572 }, 32573 bones: [], 32574 boneInverses: [] 32575 }; 32576 32577 data.uuid = this.uuid; 32578 32579 const bones = this.bones; 32580 const boneInverses = this.boneInverses; 32581 32582 for ( let i = 0, l = bones.length; i < l; i ++ ) { 32583 32584 const bone = bones[ i ]; 32585 data.bones.push( bone.uuid ); 32586 32587 const boneInverse = boneInverses[ i ]; 32588 data.boneInverses.push( boneInverse.toArray() ); 32589 32590 } 32591 32592 return data; 32593 32594 } 32595 32596} 32597 32598class InstancedBufferAttribute extends BufferAttribute { 32599 32600 constructor( array, itemSize, normalized, meshPerAttribute = 1 ) { 32601 32602 super( array, itemSize, normalized ); 32603 32604 this.isInstancedBufferAttribute = true; 32605 32606 this.meshPerAttribute = meshPerAttribute; 32607 32608 } 32609 32610 copy( source ) { 32611 32612 super.copy( source ); 32613 32614 this.meshPerAttribute = source.meshPerAttribute; 32615 32616 return this; 32617 32618 } 32619 32620 toJSON() { 32621 32622 const data = super.toJSON(); 32623 32624 data.meshPerAttribute = this.meshPerAttribute; 32625 32626 data.isInstancedBufferAttribute = true; 32627 32628 return data; 32629 32630 } 32631 32632} 32633 32634const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4(); 32635const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4(); 32636 32637const _instanceIntersects = []; 32638 32639const _box3 = /*@__PURE__*/ new Box3(); 32640const _identity = /*@__PURE__*/ new Matrix4(); 32641const _mesh$1 = /*@__PURE__*/ new Mesh(); 32642const _sphere$3 = /*@__PURE__*/ new Sphere(); 32643 32644class InstancedMesh extends Mesh { 32645 32646 constructor( geometry, material, count ) { 32647 32648 super( geometry, material ); 32649 32650 this.isInstancedMesh = true; 32651 32652 this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 ); 32653 this.instanceColor = null; 32654 32655 this.count = count; 32656 32657 this.boundingBox = null; 32658 this.boundingSphere = null; 32659 32660 for ( let i = 0; i < count; i ++ ) { 32661 32662 this.setMatrixAt( i, _identity ); 32663 32664 } 32665 32666 } 32667 32668 computeBoundingBox() { 32669 32670 const geometry = this.geometry; 32671 const count = this.count; 32672 32673 if ( this.boundingBox === null ) { 32674 32675 this.boundingBox = new Box3(); 32676 32677 } 32678 32679 if ( geometry.boundingBox === null ) { 32680 32681 geometry.computeBoundingBox(); 32682 32683 } 32684 32685 this.boundingBox.makeEmpty(); 32686 32687 for ( let i = 0; i < count; i ++ ) { 32688 32689 this.getMatrixAt( i, _instanceLocalMatrix ); 32690 32691 _box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix ); 32692 32693 this.boundingBox.union( _box3 ); 32694 32695 } 32696 32697 } 32698 32699 computeBoundingSphere() { 32700 32701 const geometry = this.geometry; 32702 const count = this.count; 32703 32704 if ( this.boundingSphere === null ) { 32705 32706 this.boundingSphere = new Sphere(); 32707 32708 } 32709 32710 if ( geometry.boundingSphere === null ) { 32711 32712 geometry.computeBoundingSphere(); 32713 32714 } 32715 32716 this.boundingSphere.makeEmpty(); 32717 32718 for ( let i = 0; i < count; i ++ ) { 32719 32720 this.getMatrixAt( i, _instanceLocalMatrix ); 32721 32722 _sphere$3.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix ); 32723 32724 this.boundingSphere.union( _sphere$3 ); 32725 32726 } 32727 32728 } 32729 32730 copy( source, recursive ) { 32731 32732 super.copy( source, recursive ); 32733 32734 this.instanceMatrix.copy( source.instanceMatrix ); 32735 32736 if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone(); 32737 32738 this.count = source.count; 32739 32740 if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); 32741 if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); 32742 32743 return this; 32744 32745 } 32746 32747 getColorAt( index, color ) { 32748 32749 color.fromArray( this.instanceColor.array, index * 3 ); 32750 32751 } 32752 32753 getMatrixAt( index, matrix ) { 32754 32755 matrix.fromArray( this.instanceMatrix.array, index * 16 ); 32756 32757 } 32758 32759 raycast( raycaster, intersects ) { 32760 32761 const matrixWorld = this.matrixWorld; 32762 const raycastTimes = this.count; 32763 32764 _mesh$1.geometry = this.geometry; 32765 _mesh$1.material = this.material; 32766 32767 if ( _mesh$1.material === undefined ) return; 32768 32769 // test with bounding sphere first 32770 32771 if ( this.boundingSphere === null ) this.computeBoundingSphere(); 32772 32773 _sphere$3.copy( this.boundingSphere ); 32774 _sphere$3.applyMatrix4( matrixWorld ); 32775 32776 if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return; 32777 32778 // now test each instance 32779 32780 for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) { 32781 32782 // calculate the world matrix for each instance 32783 32784 this.getMatrixAt( instanceId, _instanceLocalMatrix ); 32785 32786 _instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix ); 32787 32788 // the mesh represents this single instance 32789 32790 _mesh$1.matrixWorld = _instanceWorldMatrix; 32791 32792 _mesh$1.raycast( raycaster, _instanceIntersects ); 32793 32794 // process the result of raycast 32795 32796 for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) { 32797 32798 const intersect = _instanceIntersects[ i ]; 32799 intersect.instanceId = instanceId; 32800 intersect.object = this; 32801 intersects.push( intersect ); 32802 32803 } 32804 32805 _instanceIntersects.length = 0; 32806 32807 } 32808 32809 } 32810 32811 setColorAt( index, color ) { 32812 32813 if ( this.instanceColor === null ) { 32814 32815 this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ), 3 ); 32816 32817 } 32818 32819 color.toArray( this.instanceColor.array, index * 3 ); 32820 32821 } 32822
32823 setMatrixAt( index, matrix ) { 32824 32825 matrix.toArray( this.instanceMatrix.array, index * 16 ); 32826 32827 } 32828 32829 updateMorphTargets() { 32830 32831 } 32832 32833 dispose() { 32834 32835 this.dispatchEvent( { type: 'dispose' } ); 32836 32837 } 32838 32839} 32840 32841function sortOpaque( a, b ) { 32842 32843 return a.z - b.z; 32844 32845} 32846 32847function sortTransparent( a, b ) { 32848 32849 return b.z - a.z; 32850 32851} 32852 32853class MultiDrawRenderList { 32854 32855 constructor() { 32856 32857 this.index = 0; 32858 this.pool = []; 32859 this.list = []; 32860 32861 } 32862 32863 push( drawRange, z ) { 32864 32865 const pool = this.pool; 32866 const list = this.list; 32867 if ( this.index >= pool.length ) { 32868 32869 pool.push( { 32870 32871 start: - 1, 32872 count: - 1, 32873 z: - 1, 32874 32875 } ); 32876 32877 } 32878 32879 const item = pool[ this.index ]; 32880 list.push( item ); 32881 this.index ++; 32882 32883 item.start = drawRange.start; 32884 item.count = drawRange.count; 32885 item.z = z; 32886 32887 } 32888 32889 reset() { 32890 32891 this.list.length = 0; 32892 this.index = 0; 32893 32894 } 32895 32896} 32897 32898const ID_ATTR_NAME = 'batchId'; 32899const _matrix = /*@__PURE__*/ new Matrix4(); 32900const _invMatrixWorld = /*@__PURE__*/ new Matrix4(); 32901const _identityMatrix = /*@__PURE__*/ new Matrix4(); 32902const _projScreenMatrix$2 = /*@__PURE__*/ new Matrix4(); 32903const _frustum = /*@__PURE__*/ new Frustum(); 32904const _box$1 = /*@__PURE__*/ new Box3(); 32905const _sphere$2 = /*@__PURE__*/ new Sphere(); 32906const _vector$5 = /*@__PURE__*/ new Vector3(); 32907const _renderList = /*@__PURE__*/ new MultiDrawRenderList(); 32908const _mesh = /*@__PURE__*/ new Mesh(); 32909const _batchIntersects = []; 32910 32911// @TODO: SkinnedMesh support? 32912// @TODO: geometry.groups support? 32913// @TODO: geometry.drawRange support? 32914// @TODO: geometry.morphAttributes support? 32915// @TODO: Support uniform parameter per geometry 32916// @TODO: Add an "optimize" function to pack geometry and remove data gaps 32917 32918// copies data from attribute "src" into "target" starting at "targetOffset" 32919function copyAttributeData( src, target, targetOffset = 0 ) { 32920 32921 const itemSize = target.itemSize; 32922 if ( src.isInterleavedBufferAttribute || src.array.constructor !== target.array.constructor ) { 32923 32924 // use the component getters and setters if the array data cannot 32925 // be copied directly 32926 const vertexCount = src.count; 32927 for ( let i = 0; i < vertexCount; i ++ ) { 32928 32929 for ( let c = 0; c < itemSize; c ++ ) { 32930 32931 target.setComponent( i + targetOffset, c, src.getComponent( i, c ) ); 32932 32933 } 32934 32935 } 32936 32937 } else { 32938 32939 // faster copy approach using typed array set function 32940 target.array.set( src.array, targetOffset * itemSize ); 32941 32942 } 32943 32944 target.needsUpdate = true; 32945 32946} 32947 32948class BatchedMesh extends Mesh { 32949 32950 get maxGeometryCount() { 32951 32952 return this._maxGeometryCount; 32953 32954 } 32955 32956 constructor( maxGeometryCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material ) { 32957 32958 super( new BufferGeometry(), material ); 32959 32960 this.isBatchedMesh = true; 32961 this.perObjectFrustumCulled = true; 32962 this.sortObjects = true; 32963 this.boundingBox = null; 32964 this.boundingSphere = null; 32965 this.customSort = null; 32966 32967 this._drawRanges = []; 32968 this._reservedRanges = []; 32969 32970 this._visibility = []; 32971 this._active = []; 32972 this._bounds = []; 32973 32974 this._maxGeometryCount = maxGeometryCount; 32975 this._maxVertexCount = maxVertexCount; 32976 this._maxIndexCount = maxIndexCount; 32977 32978 this._geometryInitialized = false; 32979 this._geometryCount = 0; 32980 this._multiDrawCounts = new Int32Array( maxGeometryCount ); 32981 this._multiDrawStarts = new Int32Array( maxGeometryCount ); 32982 this._multiDrawCount = 0; 32983 this._visibilityChanged = true; 32984 32985 // Local matrix per geometry by using data texture 32986 this._matricesTexture = null; 32987 32988 this._initMatricesTexture(); 32989 32990 } 32991 32992 _initMatricesTexture() { 32993 32994 // layout (1 matrix = 4 pixels) 32995 // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) 32996 // with 8x8 pixel texture max 16 matrices * 4 pixels = (8 * 8) 32997 // 16x16 pixel texture max 64 matrices * 4 pixels = (16 * 16) 32998 // 32x32 pixel texture max 256 matrices * 4 pixels = (32 * 32) 32999 // 64x64 pixel texture max 1024 matrices * 4 pixels = (64 * 64) 33000 33001 let size = Math.sqrt( this._maxGeometryCount * 4 ); // 4 pixels needed for 1 matrix 33002 size = Math.ceil( size / 4 ) * 4; 33003 size = Math.max( size, 4 ); 33004 33005 const matricesArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel 33006 const matricesTexture = new DataTexture( matricesArray, size, size, RGBAFormat, FloatType ); 33007 33008 this._matricesTexture = matricesTexture; 33009 33010 } 33011 33012 _initializeGeometry( reference ) { 33013 33014 const geometry = this.geometry; 33015 const maxVertexCount = this._maxVertexCount; 33016 const maxGeometryCount = this._maxGeometryCount; 33017 const maxIndexCount = this._maxIndexCount; 33018 if ( this._geometryInitialized === false ) { 33019 33020 for ( const attributeName in reference.attributes ) { 33021 33022 const srcAttribute = reference.getAttribute( attributeName ); 33023 const { array, itemSize, normalized } = srcAttribute; 33024 33025 const dstArray = new array.constructor( maxVertexCount * itemSize ); 33026 const dstAttribute = new srcAttribute.constructor( dstArray, itemSize, normalized ); 33027 dstAttribute.setUsage( srcAttribute.usage ); 33028 33029 geometry.setAttribute( attributeName, dstAttribute ); 33030 33031 } 33032 33033 if ( reference.getIndex() !== null ) { 33034 33035 const indexArray = maxVertexCount > 65536 33036 ? new Uint32Array( maxIndexCount ) 33037 : new Uint16Array( maxIndexCount ); 33038 33039 geometry.setIndex( new BufferAttribute( indexArray, 1 ) ); 33040 33041 } 33042 33043 const idArray = maxGeometryCount > 65536 33044 ? new Uint32Array( maxVertexCount ) 33045 : new Uint16Array( maxVertexCount ); 33046 geometry.setAttribute( ID_ATTR_NAME, new BufferAttribute( idArray, 1 ) ); 33047 33048 this._geometryInitialized = true; 33049 33050 } 33051 33052 } 33053 33054 // Make sure the geometry is compatible with the existing combined geometry atributes 33055 _validateGeometry( geometry ) { 33056
33057 // check that the geometry doesn't have a version of our reserved id attribute 33058 if ( geometry.getAttribute( ID_ATTR_NAME ) ) { 33059 33060 throw new Error( `BatchedMesh: Geometry cannot use attribute "${ ID_ATTR_NAME }"` ); 33061 33062 } 33063 33064 // check to ensure the geometries are using consistent attributes and indices 33065 const batchGeometry = this.geometry; 33066 if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) { 33067 33068 throw new Error( 'BatchedMesh: All geometries must consistently have "index".' ); 33069 33070 } 33071 33072 for ( const attributeName in batchGeometry.attributes ) { 33073 33074 if ( attributeName === ID_ATTR_NAME ) { 33075 33076 continue; 33077 33078 } 33079 33080 if ( ! geometry.hasAttribute( attributeName ) ) { 33081 33082 throw new Error( `BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` ); 33083 33084 } 33085 33086 const srcAttribute = geometry.getAttribute( attributeName ); 33087 const dstAttribute = batchGeometry.getAttribute( attributeName ); 33088 if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) { 33089 33090 throw new Error( 'BatchedMesh: All attributes must have a consistent itemSize and normalized value.' ); 33091 33092 } 33093 33094 } 33095 33096 } 33097 33098 setCustomSort( func ) { 33099 33100 this.customSort = func; 33101 return this; 33102 33103 } 33104 33105 computeBoundingBox() { 33106 33107 if ( this.boundingBox === null ) { 33108 33109 this.boundingBox = new Box3(); 33110 33111 } 33112 33113 const geometryCount = this._geometryCount; 33114 const boundingBox = this.boundingBox; 33115 const active = this._active; 33116 33117 boundingBox.makeEmpty(); 33118 for ( let i = 0; i < geometryCount; i ++ ) { 33119 33120 if ( active[ i ] === false ) continue; 33121 33122 this.getMatrixAt( i, _matrix ); 33123 this.getBoundingBoxAt( i, _box$1 ).applyMatrix4( _matrix ); 33124 boundingBox.union( _box$1 ); 33125 33126 } 33127 33128 } 33129 33130 computeBoundingSphere() { 33131 33132 if ( this.boundingSphere === null ) { 33133 33134 this.boundingSphere = new Sphere(); 33135 33136 } 33137 33138 const geometryCount = this._geometryCount; 33139 const boundingSphere = this.boundingSphere; 33140 const active = this._active; 33141 33142 boundingSphere.makeEmpty(); 33143 for ( let i = 0; i < geometryCount; i ++ ) { 33144 33145 if ( active[ i ] === false ) continue; 33146 33147 this.getMatrixAt( i, _matrix ); 33148 this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix ); 33149 boundingSphere.union( _sphere$2 ); 33150 33151 } 33152 33153 } 33154 33155 addGeometry( geometry, vertexCount = - 1, indexCount = - 1 ) { 33156 33157 this._initializeGeometry( geometry ); 33158 33159 this._validateGeometry( geometry ); 33160 33161 // ensure we're not over geometry 33162 if ( this._geometryCount >= this._maxGeometryCount ) { 33163 33164 throw new Error( 'BatchedMesh: Maximum geometry count reached.' ); 33165 33166 } 33167 33168 // get the necessary range fo the geometry 33169 const reservedRange = { 33170 vertexStart: - 1, 33171 vertexCount: - 1, 33172 indexStart: - 1, 33173 indexCount: - 1, 33174 }; 33175 33176 let lastRange = null; 33177 const reservedRanges = this._reservedRanges; 33178 const drawRanges = this._drawRanges; 33179 const bounds = this._bounds; 33180 if ( this._geometryCount !== 0 ) { 33181 33182 lastRange = reservedRanges[ reservedRanges.length - 1 ]; 33183 33184 } 33185 33186 if ( vertexCount === - 1 ) { 33187 33188 reservedRange.vertexCount = geometry.getAttribute( 'position' ).count; 33189 33190 } else { 33191 33192 reservedRange.vertexCount = vertexCount; 33193 33194 } 33195 33196 if ( lastRange === null ) { 33197 33198 reservedRange.vertexStart = 0; 33199 33200 } else { 33201 33202 reservedRange.vertexStart = lastRange.vertexStart + lastRange.vertexCount; 33203 33204 } 33205 33206 const index = geometry.getIndex(); 33207 const hasIndex = index !== null; 33208 if ( hasIndex ) { 33209 33210 if ( indexCount === - 1 ) { 33211 33212 reservedRange.indexCount = index.count; 33213 33214 } else { 33215 33216 reservedRange.indexCount = indexCount; 33217 33218 } 33219 33220 if ( lastRange === null ) { 33221 33222 reservedRange.indexStart = 0; 33223 33224 } else { 33225 33226 reservedRange.indexStart = lastRange.indexStart + lastRange.indexCount; 33227 33228 } 33229 33230 } 33231 33232 if ( 33233 reservedRange.indexStart !== - 1 && 33234 reservedRange.indexStart + reservedRange.indexCount > this._maxIndexCount || 33235 reservedRange.vertexStart + reservedRange.vertexCount > this._maxVertexCount 33236 ) { 33237 33238 throw new Error( 'BatchedMesh: Reserved space request exceeds the maximum buffer size.' ); 33239 33240 } 33241 33242 const visibility = this._visibility; 33243 const active = this._active; 33244 const matricesTexture = this._matricesTexture; 33245 const matricesArray = this._matricesTexture.image.data; 33246 33247 // push new visibility states 33248 visibility.push( true ); 33249 active.push( true ); 33250 33251 // update id 33252 const geometryId = this._geometryCount; 33253 this._geometryCount ++; 33254 33255 // initialize matrix information 33256 _identityMatrix.toArray( matricesArray, geometryId * 16 ); 33257 matricesTexture.needsUpdate = true; 33258 33259 // add the reserved range and draw range objects 33260 reservedRanges.push( reservedRange ); 33261 drawRanges.push( { 33262 start: hasIndex ? reservedRange.indexStart : reservedRange.vertexStart, 33263 count: - 1 33264 } ); 33265 bounds.push( { 33266 boxInitialized: false, 33267 box: new Box3(), 33268 33269 sphereInitialized: false, 33270 sphere: new Sphere() 33271 } ); 33272 33273 // set the id for the geometry 33274 const idAttribute = this.geometry.getAttribute( ID_ATTR_NAME ); 33275 for ( let i = 0; i < reservedRange.vertexCount; i ++ ) { 33276 33277 idAttribute.setX( reservedRange.vertexStart + i, geometryId ); 33278 33279 } 33280 33281 idAttribute.needsUpdate = true; 33282 33283 // update the geometry 33284 this.setGeometryAt( geometryId, geometry ); 33285 33286 return geometryId; 33287 33288 } 33289 33290 setGeometryAt( id, geometry ) { 33291 33292 if ( id >= this._geometryCount ) { 33293 33294 throw new Error( 'BatchedMesh: Maximum geometry count reached.' ); 33295 33296 } 33297
33298 this._validateGeometry( geometry ); 33299 33300 const batchGeometry = this.geometry; 33301 const hasIndex = batchGeometry.getIndex() !== null; 33302 const dstIndex = batchGeometry.getIndex(); 33303 const srcIndex = geometry.getIndex(); 33304 const reservedRange = this._reservedRanges[ id ]; 33305 if ( 33306 hasIndex && 33307 srcIndex.count > reservedRange.indexCount || 33308 geometry.attributes.position.count > reservedRange.vertexCount 33309 ) { 33310 33311 throw new Error( 'BatchedMesh: Reserved space not large enough for provided geometry.' ); 33312 33313 } 33314 33315 // copy geometry over 33316 const vertexStart = reservedRange.vertexStart; 33317 const vertexCount = reservedRange.vertexCount; 33318 for ( const attributeName in batchGeometry.attributes ) { 33319 33320 if ( attributeName === ID_ATTR_NAME ) { 33321 33322 continue; 33323 33324 } 33325 33326 // copy attribute data 33327 const srcAttribute = geometry.getAttribute( attributeName ); 33328 const dstAttribute = batchGeometry.getAttribute( attributeName ); 33329 copyAttributeData( srcAttribute, dstAttribute, vertexStart ); 33330 33331 // fill the rest in with zeroes 33332 const itemSize = srcAttribute.itemSize; 33333 for ( let i = srcAttribute.count, l = vertexCount; i < l; i ++ ) { 33334 33335 const index = vertexStart + i; 33336 for ( let c = 0; c < itemSize; c ++ ) { 33337 33338 dstAttribute.setComponent( index, c, 0 ); 33339 33340 } 33341 33342 } 33343 33344 dstAttribute.needsUpdate = true; 33345 33346 } 33347 33348 // copy index 33349 if ( hasIndex ) { 33350 33351 const indexStart = reservedRange.indexStart; 33352 33353 // copy index data over 33354 for ( let i = 0; i < srcIndex.count; i ++ ) { 33355 33356 dstIndex.setX( indexStart + i, vertexStart + srcIndex.getX( i ) ); 33357 33358 } 33359 33360 // fill the rest in with zeroes 33361 for ( let i = srcIndex.count, l = reservedRange.indexCount; i < l; i ++ ) { 33362 33363 dstIndex.setX( indexStart + i, vertexStart ); 33364 33365 } 33366 33367 dstIndex.needsUpdate = true; 33368 33369 } 33370 33371 // store the bounding boxes 33372 const bound = this._bounds[ id ]; 33373 if ( geometry.boundingBox !== null ) { 33374 33375 bound.box.copy( geometry.boundingBox ); 33376 bound.boxInitialized = true; 33377 33378 } else { 33379 33380 bound.boxInitialized = false; 33381 33382 } 33383 33384 if ( geometry.boundingSphere !== null ) { 33385 33386 bound.sphere.copy( geometry.boundingSphere ); 33387 bound.sphereInitialized = true; 33388 33389 } else { 33390 33391 bound.sphereInitialized = false; 33392 33393 } 33394 33395 // set drawRange count 33396 const drawRange = this._drawRanges[ id ]; 33397 const posAttr = geometry.getAttribute( 'position' ); 33398 drawRange.count = hasIndex ? srcIndex.count : posAttr.count; 33399 this._visibilityChanged = true; 33400 33401 return id; 33402 33403 } 33404 33405 deleteGeometry( geometryId ) { 33406 33407 // Note: User needs to call optimize() afterward to pack the data. 33408 33409 const active = this._active; 33410 if ( geometryId >= active.length || active[ geometryId ] === false ) { 33411 33412 return this; 33413 33414 } 33415 33416 active[ geometryId ] = false; 33417 this._visibilityChanged = true; 33418 33419 return this; 33420 33421 } 33422 33423 // get bounding box and compute it if it doesn't exist 33424 getBoundingBoxAt( id, target ) { 33425 33426 const active = this._active; 33427 if ( active[ id ] === false ) { 33428 33429 return this; 33430 33431 } 33432 33433 // compute bounding box 33434 const bound = this._bounds[ id ]; 33435 const box = bound.box; 33436 const geometry = this.geometry; 33437 if ( bound.boxInitialized === false ) { 33438 33439 box.makeEmpty(); 33440 33441 const index = geometry.index; 33442 const position = geometry.attributes.position; 33443 const drawRange = this._drawRanges[ id ]; 33444 for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) { 33445 33446 let iv = i; 33447 if ( index ) { 33448 33449 iv = index.getX( iv ); 33450 33451 } 33452 33453 box.expandByPoint( _vector$5.fromBufferAttribute( position, iv ) ); 33454 33455 } 33456 33457 bound.boxInitialized = true; 33458 33459 } 33460 33461 target.copy( box ); 33462 return target; 33463 33464 } 33465 33466 // get bounding sphere and compute it if it doesn't exist 33467 getBoundingSphereAt( id, target ) { 33468 33469 const active = this._active; 33470 if ( active[ id ] === false ) { 33471 33472 return this; 33473 33474 } 33475 33476 // compute bounding sphere 33477 const bound = this._bounds[ id ]; 33478 const sphere = bound.sphere; 33479 const geometry = this.geometry; 33480 if ( bound.sphereInitialized === false ) { 33481 33482 sphere.makeEmpty(); 33483 33484 this.getBoundingBoxAt( id, _box$1 ); 33485 _box$1.getCenter( sphere.center ); 33486 33487 const index = geometry.index; 33488 const position = geometry.attributes.position; 33489 const drawRange = this._drawRanges[ id ]; 33490 33491 let maxRadiusSq = 0; 33492 for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) { 33493 33494 let iv = i; 33495 if ( index ) { 33496 33497 iv = index.getX( iv ); 33498 33499 } 33500 33501 _vector$5.fromBufferAttribute( position, iv ); 33502 maxRadiusSq = Math.max( maxRadiusSq, sphere.center.distanceToSquared( _vector$5 ) ); 33503 33504 } 33505 33506 sphere.radius = Math.sqrt( maxRadiusSq ); 33507 bound.sphereInitialized = true; 33508 33509 } 33510 33511 target.copy( sphere ); 33512 return target; 33513 33514 } 33515
33516 setMatrixAt( geometryId, matrix ) { 33517 33518 // @TODO: Map geometryId to index of the arrays because 33519 // optimize() can make geometryId mismatch the index 33520 33521 const active = this._active; 33522 const matricesTexture = this._matricesTexture; 33523 const matricesArray = this._matricesTexture.image.data; 33524 const geometryCount = this._geometryCount; 33525 if ( geometryId >= geometryCount || active[ geometryId ] === false ) { 33526 33527 return this; 33528 33529 } 33530 33531 matrix.toArray( matricesArray, geometryId * 16 ); 33532 matricesTexture.needsUpdate = true; 33533 33534 return this; 33535 33536 } 33537 33538 getMatrixAt( geometryId, matrix ) { 33539 33540 const active = this._active; 33541 const matricesArray = this._matricesTexture.image.data; 33542 const geometryCount = this._geometryCount; 33543 if ( geometryId >= geometryCount || active[ geometryId ] === false ) { 33544 33545 return null; 33546 33547 } 33548 33549 return matrix.fromArray( matricesArray, geometryId * 16 ); 33550 33551 } 33552 33553 setVisibleAt( geometryId, value ) { 33554 33555 const visibility = this._visibility; 33556 const active = this._active; 33557 const geometryCount = this._geometryCount; 33558 33559 // if the geometry is out of range, not active, or visibility state 33560 // does not change then return early 33561 if ( 33562 geometryId >= geometryCount || 33563 active[ geometryId ] === false || 33564 visibility[ geometryId ] === value 33565 ) { 33566 33567 return this; 33568 33569 } 33570 33571 visibility[ geometryId ] = value; 33572 this._visibilityChanged = true; 33573 33574 return this; 33575 33576 } 33577 33578 getVisibleAt( geometryId ) { 33579 33580 const visibility = this._visibility; 33581 const active = this._active; 33582 const geometryCount = this._geometryCount; 33583 33584 // return early if the geometry is out of range or not active 33585 if ( geometryId >= geometryCount || active[ geometryId ] === false ) { 33586 33587 return false; 33588 33589 } 33590 33591 return visibility[ geometryId ]; 33592 33593 } 33594 33595 raycast( raycaster, intersects ) { 33596 33597 const visibility = this._visibility; 33598 const active = this._active; 33599 const drawRanges = this._drawRanges; 33600 const geometryCount = this._geometryCount; 33601 const matrixWorld = this.matrixWorld; 33602 const batchGeometry = this.geometry; 33603 33604 // iterate over each geometry 33605 _mesh.material = this.material; 33606 _mesh.geometry.index = batchGeometry.index; 33607 _mesh.geometry.attributes = batchGeometry.attributes; 33608 if ( _mesh.geometry.boundingBox === null ) { 33609 33610 _mesh.geometry.boundingBox = new Box3(); 33611 33612 } 33613 33614 if ( _mesh.geometry.boundingSphere === null ) { 33615 33616 _mesh.geometry.boundingSphere = new Sphere(); 33617 33618 } 33619 33620 for ( let i = 0; i < geometryCount; i ++ ) { 33621 33622 if ( ! visibility[ i ] || ! active[ i ] ) { 33623 33624 continue; 33625 33626 } 33627 33628 const drawRange = drawRanges[ i ]; 33629 _mesh.geometry.setDrawRange( drawRange.start, drawRange.count ); 33630 33631 // ge the intersects 33632 this.getMatrixAt( i, _mesh.matrixWorld ).premultiply( matrixWorld ); 33633 this.getBoundingBoxAt( i, _mesh.geometry.boundingBox ); 33634 this.getBoundingSphereAt( i, _mesh.geometry.boundingSphere ); 33635 _mesh.raycast( raycaster, _batchIntersects ); 33636 33637 // add batch id to the intersects 33638 for ( let j = 0, l = _batchIntersects.length; j < l; j ++ ) { 33639 33640 const intersect = _batchIntersects[ j ]; 33641 intersect.object = this; 33642 intersect.batchId = i; 33643 intersects.push( intersect ); 33644 33645 } 33646 33647 _batchIntersects.length = 0; 33648 33649 } 33650 33651 _mesh.material = null; 33652 _mesh.geometry.index = null; 33653 _mesh.geometry.attributes = {}; 33654 _mesh.geometry.setDrawRange( 0, Infinity ); 33655 33656 } 33657 33658 copy( source ) { 33659 33660 super.copy( source ); 33661 33662 this.geometry = source.geometry.clone(); 33663 this.perObjectFrustumCulled = source.perObjectFrustumCulled; 33664 this.sortObjects = source.sortObjects; 33665 this.boundingBox = source.boundingBox !== null ? source.boundingBox.clone() : null; 33666 this.boundingSphere = source.boundingSphere !== null ? source.boundingSphere.clone() : null; 33667 33668 this._drawRanges = source._drawRanges.map( range => ( { ...range } ) ); 33669 this._reservedRanges = source._reservedRanges.map( range => ( { ...range } ) ); 33670 33671 this._visibility = source._visibility.slice(); 33672 this._active = source._active.slice(); 33673 this._bounds = source._bounds.map( bound => ( { 33674 boxInitialized: bound.boxInitialized, 33675 box: bound.box.clone(), 33676 33677 sphereInitialized: bound.sphereInitialized, 33678 sphere: bound.sphere.clone() 33679 } ) ); 33680 33681 this._maxGeometryCount = source._maxGeometryCount; 33682 this._maxVertexCount = source._maxVertexCount; 33683 this._maxIndexCount = source._maxIndexCount; 33684 33685 this._geometryInitialized = source._geometryInitialized; 33686 this._geometryCount = source._geometryCount; 33687 this._multiDrawCounts = source._multiDrawCounts.slice(); 33688 this._multiDrawStarts = source._multiDrawStarts.slice(); 33689 33690 this._matricesTexture = source._matricesTexture.clone(); 33691 this._matricesTexture.image.data = this._matricesTexture.image.slice(); 33692 33693 return this; 33694 33695 } 33696 33697 dispose() { 33698 33699 // Assuming the geometry is not shared with other meshes 33700 this.geometry.dispose(); 33701 33702 this._matricesTexture.dispose(); 33703 this._matricesTexture = null; 33704 return this; 33705 33706 } 33707 33708 onBeforeRender( renderer, scene, camera, geometry, material/*, _group*/ ) { 33709 33710 // if visibility has not changed and frustum culling and object sorting is not required 33711 // then skip iterating over all items 33712 if ( ! this._visibilityChanged && ! this.perObjectFrustumCulled && ! this.sortObjects ) { 33713 33714 return; 33715 33716 } 33717 33718 // the indexed version of the multi draw function requires specifying the start 33719 // offset in bytes. 33720 const index = geometry.getIndex(); 33721 const bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT; 33722 33723 const visibility = this._visibility; 33724 const multiDrawStarts = this._multiDrawStarts; 33725 const multiDrawCounts = this._multiDrawCounts; 33726 const drawRanges = this._drawRanges; 33727 const perObjectFrustumCulled = this.perObjectFrustumCulled; 33728 33729 // prepare the frustum in the local frame 33730 if ( perObjectFrustumCulled ) { 33731 33732 _projScreenMatrix$2 33733 .multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ) 33734 .multiply( this.matrixWorld ); 33735 _frustum.setFromProjectionMatrix( 33736 _projScreenMatrix$2, 33737 renderer.isWebGPURenderer ? WebGPUCoordinateSystem : WebGLCoordinateSystem 33738 ); 33739 33740 } 33741 33742 let count = 0; 33743 if ( this.sortObjects ) { 33744 33745 // get the camera position in the local frame 33746 _invMatrixWorld.copy( this.matrixWorld ).invert(); 33747 _vector$5.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4( _invMatrixWorld ); 33748 33749 for ( let i = 0, l = visibility.length; i < l; i ++ ) { 33750 33751 if ( visibility[ i ] ) { 33752 33753 // get the bounds in world space 33754 this.getMatrixAt( i, _matrix ); 33755 this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix ); 33756 33757 // determine whether the batched geometry is within the frustum
vendor: 13,526 bytes, lines 33758-34378
33758 let culled = false; 33759 if ( perObjectFrustumCulled ) { 33760 33761 culled = ! _frustum.intersectsSphere( _sphere$2 ); 33762 33763 } 33764 33765 if ( ! culled ) { 33766 33767 // get the distance from camera used for sorting 33768 const z = _vector$5.distanceTo( _sphere$2.center ); 33769 _renderList.push( drawRanges[ i ], z ); 33770 33771 } 33772 33773 } 33774 33775 } 33776 33777 // Sort the draw ranges and prep for rendering 33778 const list = _renderList.list; 33779 const customSort = this.customSort; 33780 if ( customSort === null ) { 33781 33782 list.sort( material.transparent ? sortTransparent : sortOpaque ); 33783 33784 } else { 33785 33786 customSort.call( this, list, camera ); 33787 33788 } 33789 33790 for ( let i = 0, l = list.length; i < l; i ++ ) { 33791 33792 const item = list[ i ]; 33793 multiDrawStarts[ count ] = item.start * bytesPerElement; 33794 multiDrawCounts[ count ] = item.count; 33795 count ++; 33796 33797 } 33798 33799 _renderList.reset(); 33800 33801 } else { 33802 33803 for ( let i = 0, l = visibility.length; i < l; i ++ ) { 33804 33805 if ( visibility[ i ] ) { 33806 33807 // determine whether the batched geometry is within the frustum 33808 let culled = false; 33809 if ( perObjectFrustumCulled ) { 33810 33811 // get the bounds in world space 33812 this.getMatrixAt( i, _matrix ); 33813 this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix ); 33814 culled = ! _frustum.intersectsSphere( _sphere$2 ); 33815 33816 } 33817 33818 if ( ! culled ) { 33819 33820 const range = drawRanges[ i ]; 33821 multiDrawStarts[ count ] = range.start * bytesPerElement; 33822 multiDrawCounts[ count ] = range.count; 33823 count ++; 33824 33825 } 33826 33827 } 33828 33829 } 33830 33831 } 33832 33833 this._multiDrawCount = count; 33834 this._visibilityChanged = false; 33835 33836 } 33837 33838 onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial/* , group */ ) { 33839 33840 this.onBeforeRender( renderer, null, shadowCamera, geometry, depthMaterial ); 33841 33842 } 33843 33844} 33845 33846class LineBasicMaterial extends Material { 33847 33848 constructor( parameters ) { 33849 33850 super(); 33851 33852 this.isLineBasicMaterial = true; 33853 33854 this.type = 'LineBasicMaterial'; 33855 33856 this.color = new Color( 0xffffff ); 33857 33858 this.map = null; 33859 33860 this.linewidth = 1; 33861 this.linecap = 'round'; 33862 this.linejoin = 'round'; 33863 33864 this.fog = true; 33865 33866 this.setValues( parameters ); 33867 33868 } 33869 33870 33871 copy( source ) { 33872 33873 super.copy( source ); 33874 33875 this.color.copy( source.color ); 33876 33877 this.map = source.map; 33878 33879 this.linewidth = source.linewidth; 33880 this.linecap = source.linecap; 33881 this.linejoin = source.linejoin; 33882 33883 this.fog = source.fog; 33884 33885 return this; 33886 33887 } 33888 33889} 33890 33891const _start$1 = /*@__PURE__*/ new Vector3(); 33892const _end$1 = /*@__PURE__*/ new Vector3(); 33893const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4(); 33894const _ray$1 = /*@__PURE__*/ new Ray(); 33895const _sphere$1 = /*@__PURE__*/ new Sphere(); 33896 33897class Line extends Object3D { 33898 33899 constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) { 33900 33901 super(); 33902 33903 this.isLine = true; 33904 33905 this.type = 'Line'; 33906 33907 this.geometry = geometry; 33908 this.material = material; 33909 33910 this.updateMorphTargets(); 33911 33912 } 33913 33914 copy( source, recursive ) { 33915 33916 super.copy( source, recursive ); 33917 33918 this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; 33919 this.geometry = source.geometry; 33920 33921 return this; 33922 33923 } 33924 33925 computeLineDistances() { 33926 33927 const geometry = this.geometry; 33928 33929 // we assume non-indexed geometry 33930 33931 if ( geometry.index === null ) { 33932 33933 const positionAttribute = geometry.attributes.position; 33934 const lineDistances = [ 0 ]; 33935 33936 for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) { 33937 33938 _start$1.fromBufferAttribute( positionAttribute, i - 1 ); 33939 _end$1.fromBufferAttribute( positionAttribute, i ); 33940 33941 lineDistances[ i ] = lineDistances[ i - 1 ]; 33942 lineDistances[ i ] += _start$1.distanceTo( _end$1 ); 33943 33944 } 33945 33946 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); 33947 33948 } else { 33949 33950 console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); 33951 33952 } 33953 33954 return this; 33955 33956 } 33957 33958 raycast( raycaster, intersects ) { 33959 33960 const geometry = this.geometry; 33961 const matrixWorld = this.matrixWorld; 33962 const threshold = raycaster.params.Line.threshold; 33963 const drawRange = geometry.drawRange; 33964 33965 // Checking boundingSphere distance to ray 33966 33967 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 33968 33969 _sphere$1.copy( geometry.boundingSphere ); 33970 _sphere$1.applyMatrix4( matrixWorld ); 33971 _sphere$1.radius += threshold; 33972 33973 if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return; 33974 33975 // 33976 33977 _inverseMatrix$1.copy( matrixWorld ).invert(); 33978 _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 ); 33979 33980 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); 33981 const localThresholdSq = localThreshold * localThreshold; 33982 33983 const vStart = new Vector3(); 33984 const vEnd = new Vector3(); 33985 const interSegment = new Vector3(); 33986 const interRay = new Vector3(); 33987 const step = this.isLineSegments ? 2 : 1; 33988 33989 const index = geometry.index; 33990 const attributes = geometry.attributes; 33991 const positionAttribute = attributes.position; 33992 33993 if ( index !== null ) { 33994 33995 const start = Math.max( 0, drawRange.start ); 33996 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); 33997 33998 for ( let i = start, l = end - 1; i < l; i += step ) { 33999 34000 const a = index.getX( i ); 34001 const b = index.getX( i + 1 ); 34002 34003 vStart.fromBufferAttribute( positionAttribute, a ); 34004 vEnd.fromBufferAttribute( positionAttribute, b ); 34005 34006 const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); 34007 34008 if ( distSq > localThresholdSq ) continue; 34009 34010 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation 34011 34012 const distance = raycaster.ray.origin.distanceTo( interRay ); 34013 34014 if ( distance < raycaster.near || distance > raycaster.far ) continue; 34015 34016 intersects.push( { 34017 34018 distance: distance, 34019 // What do we want? intersection point on the ray or on the segment?? 34020 // point: raycaster.ray.at( distance ), 34021 point: interSegment.clone().applyMatrix4( this.matrixWorld ), 34022 index: i, 34023 face: null, 34024 faceIndex: null, 34025 object: this 34026 34027 } ); 34028 34029 } 34030 34031 } else { 34032 34033 const start = Math.max( 0, drawRange.start ); 34034 const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); 34035 34036 for ( let i = start, l = end - 1; i < l; i += step ) { 34037 34038 vStart.fromBufferAttribute( positionAttribute, i ); 34039 vEnd.fromBufferAttribute( positionAttribute, i + 1 ); 34040 34041 const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); 34042 34043 if ( distSq > localThresholdSq ) continue; 34044 34045 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation 34046 34047 const distance = raycaster.ray.origin.distanceTo( interRay ); 34048 34049 if ( distance < raycaster.near || distance > raycaster.far ) continue; 34050 34051 intersects.push( { 34052 34053 distance: distance, 34054 // What do we want? intersection point on the ray or on the segment?? 34055 // point: raycaster.ray.at( distance ), 34056 point: interSegment.clone().applyMatrix4( this.matrixWorld ), 34057 index: i, 34058 face: null, 34059 faceIndex: null, 34060 object: this 34061 34062 } ); 34063 34064 } 34065 34066 } 34067 34068 } 34069 34070 updateMorphTargets() { 34071 34072 const geometry = this.geometry; 34073 34074 const morphAttributes = geometry.morphAttributes; 34075 const keys = Object.keys( morphAttributes ); 34076 34077 if ( keys.length > 0 ) { 34078 34079 const morphAttribute = morphAttributes[ keys[ 0 ] ]; 34080 34081 if ( morphAttribute !== undefined ) { 34082 34083 this.morphTargetInfluences = []; 34084 this.morphTargetDictionary = {}; 34085 34086 for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 34087 34088 const name = morphAttribute[ m ].name || String( m ); 34089 34090 this.morphTargetInfluences.push( 0 ); 34091 this.morphTargetDictionary[ name ] = m; 34092 34093 } 34094 34095 } 34096 34097 } 34098 34099 } 34100 34101} 34102 34103const _start = /*@__PURE__*/ new Vector3(); 34104const _end = /*@__PURE__*/ new Vector3(); 34105 34106class LineSegments extends Line { 34107 34108 constructor( geometry, material ) { 34109 34110 super( geometry, material ); 34111 34112 this.isLineSegments = true; 34113 34114 this.type = 'LineSegments'; 34115 34116 } 34117 34118 computeLineDistances() { 34119 34120 const geometry = this.geometry; 34121 34122 // we assume non-indexed geometry 34123 34124 if ( geometry.index === null ) { 34125 34126 const positionAttribute = geometry.attributes.position; 34127 const lineDistances = []; 34128 34129 for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) { 34130 34131 _start.fromBufferAttribute( positionAttribute, i ); 34132 _end.fromBufferAttribute( positionAttribute, i + 1 ); 34133 34134 lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ]; 34135 lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end ); 34136 34137 } 34138 34139 geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); 34140 34141 } else { 34142 34143 console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); 34144 34145 } 34146 34147 return this; 34148 34149 } 34150 34151} 34152 34153class LineLoop extends Line { 34154 34155 constructor( geometry, material ) { 34156 34157 super( geometry, material ); 34158 34159 this.isLineLoop = true; 34160 34161 this.type = 'LineLoop'; 34162 34163 } 34164 34165} 34166 34167class PointsMaterial extends Material { 34168 34169 constructor( parameters ) { 34170 34171 super(); 34172 34173 this.isPointsMaterial = true; 34174 34175 this.type = 'PointsMaterial'; 34176 34177 this.color = new Color( 0xffffff ); 34178 34179 this.map = null; 34180 34181 this.alphaMap = null; 34182 34183 this.size = 1; 34184 this.sizeAttenuation = true; 34185 34186 this.fog = true; 34187 34188 this.setValues( parameters ); 34189 34190 } 34191 34192 copy( source ) { 34193 34194 super.copy( source ); 34195 34196 this.color.copy( source.color ); 34197 34198 this.map = source.map; 34199 34200 this.alphaMap = source.alphaMap; 34201 34202 this.size = source.size; 34203 this.sizeAttenuation = source.sizeAttenuation; 34204 34205 this.fog = source.fog; 34206 34207 return this; 34208 34209 } 34210 34211} 34212 34213const _inverseMatrix = /*@__PURE__*/ new Matrix4(); 34214const _ray = /*@__PURE__*/ new Ray(); 34215const _sphere = /*@__PURE__*/ new Sphere(); 34216const _position$2 = /*@__PURE__*/ new Vector3(); 34217 34218class Points extends Object3D { 34219 34220 constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) { 34221 34222 super(); 34223 34224 this.isPoints = true; 34225 34226 this.type = 'Points'; 34227 34228 this.geometry = geometry; 34229 this.material = material; 34230 34231 this.updateMorphTargets(); 34232 34233 } 34234 34235 copy( source, recursive ) { 34236 34237 super.copy( source, recursive ); 34238 34239 this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; 34240 this.geometry = source.geometry; 34241 34242 return this; 34243 34244 } 34245 34246 raycast( raycaster, intersects ) { 34247 34248 const geometry = this.geometry; 34249 const matrixWorld = this.matrixWorld; 34250 const threshold = raycaster.params.Points.threshold; 34251 const drawRange = geometry.drawRange; 34252 34253 // Checking boundingSphere distance to ray 34254 34255 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 34256 34257 _sphere.copy( geometry.boundingSphere ); 34258 _sphere.applyMatrix4( matrixWorld ); 34259 _sphere.radius += threshold; 34260 34261 if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return; 34262 34263 // 34264 34265 _inverseMatrix.copy( matrixWorld ).invert(); 34266 _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix ); 34267 34268 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); 34269 const localThresholdSq = localThreshold * localThreshold; 34270 34271 const index = geometry.index; 34272 const attributes = geometry.attributes; 34273 const positionAttribute = attributes.position; 34274 34275 if ( index !== null ) { 34276 34277 const start = Math.max( 0, drawRange.start ); 34278 const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); 34279 34280 for ( let i = start, il = end; i < il; i ++ ) { 34281 34282 const a = index.getX( i ); 34283 34284 _position$2.fromBufferAttribute( positionAttribute, a ); 34285 34286 testPoint( _position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this ); 34287 34288 } 34289 34290 } else { 34291 34292 const start = Math.max( 0, drawRange.start ); 34293 const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); 34294 34295 for ( let i = start, l = end; i < l; i ++ ) { 34296 34297 _position$2.fromBufferAttribute( positionAttribute, i ); 34298 34299 testPoint( _position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this ); 34300 34301 } 34302 34303 } 34304 34305 } 34306 34307 updateMorphTargets() { 34308 34309 const geometry = this.geometry; 34310 34311 const morphAttributes = geometry.morphAttributes; 34312 const keys = Object.keys( morphAttributes ); 34313 34314 if ( keys.length > 0 ) { 34315 34316 const morphAttribute = morphAttributes[ keys[ 0 ] ]; 34317 34318 if ( morphAttribute !== undefined ) { 34319 34320 this.morphTargetInfluences = []; 34321 this.morphTargetDictionary = {}; 34322 34323 for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 34324 34325 const name = morphAttribute[ m ].name || String( m ); 34326 34327 this.morphTargetInfluences.push( 0 ); 34328 this.morphTargetDictionary[ name ] = m; 34329 34330 } 34331 34332 } 34333 34334 } 34335 34336 } 34337 34338} 34339 34340function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) { 34341 34342 const rayPointDistanceSq = _ray.distanceSqToPoint( point ); 34343 34344 if ( rayPointDistanceSq < localThresholdSq ) { 34345 34346 const intersectPoint = new Vector3(); 34347 34348 _ray.closestPointToPoint( point, intersectPoint ); 34349 intersectPoint.applyMatrix4( matrixWorld ); 34350 34351 const distance = raycaster.ray.origin.distanceTo( intersectPoint ); 34352 34353 if ( distance < raycaster.near || distance > raycaster.far ) return; 34354 34355 intersects.push( { 34356 34357 distance: distance, 34358 distanceToRay: Math.sqrt( rayPointDistanceSq ), 34359 point: intersectPoint, 34360 index: index, 34361 face: null, 34362 object: object 34363 34364 } ); 34365 34366 } 34367 34368} 34369 34370class VideoTexture extends Texture { 34371 34372 constructor( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { 34373 34374 super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 34375 34376 this.isVideoTexture = true; 34377 34378 this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
34379 this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; 34380 34381 this.generateMipmaps = false; 34382 34383 const scope = this; 34384 34385 function updateVideo() { 34386 34387 scope.needsUpdate = true; 34388 video.requestVideoFrameCallback( updateVideo ); 34389 34390 } 34391 34392 if ( 'requestVideoFrameCallback' in video ) { 34393 34394 video.requestVideoFrameCallback( updateVideo ); 34395 34396 } 34397 34398 } 34399 34400 clone() { 34401 34402 return new this.constructor( this.image ).copy( this ); 34403 34404 } 34405 34406 update() { 34407 34408 const video = this.image; 34409 const hasVideoFrameCallback = 'requestVideoFrameCallback' in video; 34410 34411 if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) { 34412 34413 this.needsUpdate = true; 34414 34415 } 34416 34417 } 34418 34419} 34420 34421class FramebufferTexture extends Texture { 34422 34423 constructor( width, height ) { 34424 34425 super( { width, height } ); 34426 34427 this.isFramebufferTexture = true; 34428 34429 this.magFilter = NearestFilter; 34430 this.minFilter = NearestFilter; 34431 34432 this.generateMipmaps = false; 34433 34434 this.needsUpdate = true; 34435 34436 } 34437 34438} 34439 34440class CompressedTexture extends Texture { 34441 34442 constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) { 34443 34444 super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); 34445 34446 this.isCompressedTexture = true; 34447 34448 this.image = { width: width, height: height }; 34449 this.mipmaps = mipmaps; 34450 34451 // no flipping for cube textures 34452 // (also flipping doesn't work for compressed textures ) 34453 34454 this.flipY = false; 34455 34456 // can't generate mipmaps for compressed textures 34457 // mips must be embedded in DDS files 34458 34459 this.generateMipmaps = false; 34460 34461 } 34462 34463} 34464 34465class CompressedArrayTexture extends CompressedTexture { 34466 34467 constructor( mipmaps, width, height, depth, format, type ) { 34468 34469 super( mipmaps, width, height, format, type ); 34470 34471 this.isCompressedArrayTexture = true; 34472 this.image.depth = depth; 34473 this.wrapR = ClampToEdgeWrapping; 34474 34475 } 34476 34477} 34478 34479class CompressedCubeTexture extends CompressedTexture { 34480 34481 constructor( images, format, type ) { 34482 34483 super( undefined, images[ 0 ].width, images[ 0 ].height, format, type, CubeReflectionMapping ); 34484 34485 this.isCompressedCubeTexture = true; 34486 this.isCubeTexture = true; 34487 34488 this.image = images; 34489 34490 } 34491 34492} 34493 34494class CanvasTexture extends Texture { 34495 34496 constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { 34497 34498 super( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 34499 34500 this.isCanvasTexture = true; 34501 34502 this.needsUpdate = true; 34503 34504 } 34505 34506} 34507 34508/** 34509 * Extensible curve object. 34510 * 34511 * Some common of curve methods: 34512 * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget ) 34513 * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget ) 34514 * .getPoints(), .getSpacedPoints() 34515 * .getLength() 34516 * .updateArcLengths() 34517 * 34518 * This following curves inherit from THREE.Curve: 34519 * 34520 * -- 2D curves -- 34521 * THREE.ArcCurve 34522 * THREE.CubicBezierCurve 34523 * THREE.EllipseCurve 34524 * THREE.LineCurve 34525 * THREE.QuadraticBezierCurve 34526 * THREE.SplineCurve 34527 * 34528 * -- 3D curves -- 34529 * THREE.CatmullRomCurve3 34530 * THREE.CubicBezierCurve3 34531 * THREE.LineCurve3 34532 * THREE.QuadraticBezierCurve3 34533 * 34534 * A series of curves can be represented as a THREE.CurvePath. 34535 * 34536 **/ 34537 34538class Curve { 34539 34540 constructor() { 34541 34542 this.type = 'Curve'; 34543 34544 this.arcLengthDivisions = 200; 34545 34546 } 34547 34548 // Virtual base class method to overwrite and implement in subclasses 34549 // - t [0 .. 1] 34550 34551 getPoint( /* t, optionalTarget */ ) { 34552 34553 console.warn( 'THREE.Curve: .getPoint() not implemented.' ); 34554 return null; 34555 34556 } 34557 34558 // Get point at relative position in curve according to arc length 34559 // - u [0 .. 1] 34560 34561 getPointAt( u, optionalTarget ) { 34562 34563 const t = this.getUtoTmapping( u ); 34564 return this.getPoint( t, optionalTarget ); 34565 34566 } 34567 34568 // Get sequence of points using getPoint( t ) 34569 34570 getPoints( divisions = 5 ) { 34571 34572 const points = []; 34573 34574 for ( let d = 0; d <= divisions; d ++ ) { 34575 34576 points.push( this.getPoint( d / divisions ) ); 34577 34578 } 34579 34580 return points; 34581 34582 } 34583 34584 // Get sequence of points using getPointAt( u ) 34585 34586 getSpacedPoints( divisions = 5 ) { 34587 34588 const points = []; 34589 34590 for ( let d = 0; d <= divisions; d ++ ) { 34591 34592 points.push( this.getPointAt( d / divisions ) ); 34593 34594 } 34595 34596 return points; 34597 34598 } 34599 34600 // Get total curve arc length 34601 34602 getLength() { 34603 34604 const lengths = this.getLengths(); 34605 return lengths[ lengths.length - 1 ]; 34606 34607 } 34608 34609 // Get list of cumulative segment lengths 34610 34611 getLengths( divisions = this.arcLengthDivisions ) { 34612 34613 if ( this.cacheArcLengths && 34614 ( this.cacheArcLengths.length === divisions + 1 ) && 34615 ! this.needsUpdate ) { 34616 34617 return this.cacheArcLengths; 34618 34619 } 34620 34621 this.needsUpdate = false;
vendor: 7,518 bytes, lines 34622-35013
34622 34623 const cache = []; 34624 let current, last = this.getPoint( 0 ); 34625 let sum = 0; 34626 34627 cache.push( 0 ); 34628 34629 for ( let p = 1; p <= divisions; p ++ ) { 34630 34631 current = this.getPoint( p / divisions ); 34632 sum += current.distanceTo( last ); 34633 cache.push( sum ); 34634 last = current; 34635 34636 } 34637 34638 this.cacheArcLengths = cache; 34639 34640 return cache; // { sums: cache, sum: sum }; Sum is in the last element. 34641 34642 } 34643 34644 updateArcLengths() { 34645 34646 this.needsUpdate = true; 34647 this.getLengths(); 34648 34649 } 34650 34651 // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant 34652 34653 getUtoTmapping( u, distance ) { 34654 34655 const arcLengths = this.getLengths(); 34656 34657 let i = 0; 34658 const il = arcLengths.length; 34659 34660 let targetArcLength; // The targeted u distance value to get 34661 34662 if ( distance ) { 34663 34664 targetArcLength = distance; 34665 34666 } else { 34667 34668 targetArcLength = u * arcLengths[ il - 1 ]; 34669 34670 } 34671 34672 // binary search for the index with largest value smaller than target u distance 34673 34674 let low = 0, high = il - 1, comparison; 34675 34676 while ( low <= high ) { 34677 34678 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 34679 34680 comparison = arcLengths[ i ] - targetArcLength; 34681 34682 if ( comparison < 0 ) { 34683 34684 low = i + 1; 34685 34686 } else if ( comparison > 0 ) { 34687 34688 high = i - 1; 34689 34690 } else { 34691 34692 high = i; 34693 break; 34694 34695 // DONE 34696 34697 } 34698 34699 } 34700 34701 i = high; 34702 34703 if ( arcLengths[ i ] === targetArcLength ) { 34704 34705 return i / ( il - 1 ); 34706 34707 } 34708 34709 // we could get finer grain at lengths, or use simple interpolation between two points 34710 34711 const lengthBefore = arcLengths[ i ]; 34712 const lengthAfter = arcLengths[ i + 1 ]; 34713 34714 const segmentLength = lengthAfter - lengthBefore; 34715 34716 // determine where we are between the 'before' and 'after' points 34717 34718 const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; 34719 34720 // add that fractional amount to t 34721 34722 const t = ( i + segmentFraction ) / ( il - 1 ); 34723 34724 return t; 34725 34726 } 34727 34728 // Returns a unit vector tangent at t 34729 // In case any sub curve does not implement its tangent derivation, 34730 // 2 points a small delta apart will be used to find its gradient 34731 // which seems to give a reasonable approximation 34732 34733 getTangent( t, optionalTarget ) { 34734 34735 const delta = 0.0001; 34736 let t1 = t - delta; 34737 let t2 = t + delta; 34738 34739 // Capping in case of danger 34740 34741 if ( t1 < 0 ) t1 = 0; 34742 if ( t2 > 1 ) t2 = 1; 34743 34744 const pt1 = this.getPoint( t1 ); 34745 const pt2 = this.getPoint( t2 ); 34746 34747 const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() ); 34748 34749 tangent.copy( pt2 ).sub( pt1 ).normalize(); 34750 34751 return tangent; 34752 34753 } 34754 34755 getTangentAt( u, optionalTarget ) { 34756 34757 const t = this.getUtoTmapping( u ); 34758 return this.getTangent( t, optionalTarget ); 34759 34760 } 34761 34762 computeFrenetFrames( segments, closed ) { 34763 34764 // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf 34765 34766 const normal = new Vector3(); 34767 34768 const tangents = []; 34769 const normals = []; 34770 const binormals = []; 34771 34772 const vec = new Vector3(); 34773 const mat = new Matrix4(); 34774 34775 // compute the tangent vectors for each segment on the curve 34776 34777 for ( let i = 0; i <= segments; i ++ ) { 34778 34779 const u = i / segments; 34780 34781 tangents[ i ] = this.getTangentAt( u, new Vector3() ); 34782 34783 } 34784 34785 // select an initial normal vector perpendicular to the first tangent vector, 34786 // and in the direction of the minimum tangent xyz component 34787 34788 normals[ 0 ] = new Vector3(); 34789 binormals[ 0 ] = new Vector3(); 34790 let min = Number.MAX_VALUE; 34791 const tx = Math.abs( tangents[ 0 ].x ); 34792 const ty = Math.abs( tangents[ 0 ].y ); 34793 const tz = Math.abs( tangents[ 0 ].z ); 34794 34795 if ( tx <= min ) { 34796 34797 min = tx; 34798 normal.set( 1, 0, 0 ); 34799 34800 } 34801 34802 if ( ty <= min ) { 34803 34804 min = ty; 34805 normal.set( 0, 1, 0 ); 34806 34807 } 34808 34809 if ( tz <= min ) { 34810 34811 normal.set( 0, 0, 1 ); 34812 34813 } 34814 34815 vec.crossVectors( tangents[ 0 ], normal ).normalize(); 34816 34817 normals[ 0 ].crossVectors( tangents[ 0 ], vec ); 34818 binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ); 34819 34820 34821 // compute the slowly-varying normal and binormal vectors for each segment on the curve 34822 34823 for ( let i = 1; i <= segments; i ++ ) { 34824 34825 normals[ i ] = normals[ i - 1 ].clone(); 34826 34827 binormals[ i ] = binormals[ i - 1 ].clone(); 34828 34829 vec.crossVectors( tangents[ i - 1 ], tangents[ i ] ); 34830 34831 if ( vec.length() > Number.EPSILON ) { 34832 34833 vec.normalize(); 34834 34835 const theta = Math.acos( clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors 34836 34837 normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) ); 34838 34839 } 34840 34841 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); 34842 34843 } 34844 34845 // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same 34846 34847 if ( closed === true ) { 34848 34849 let theta = Math.acos( clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) ); 34850 theta /= segments; 34851 34852 if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) { 34853 34854 theta = - theta; 34855 34856 } 34857 34858 for ( let i = 1; i <= segments; i ++ ) { 34859 34860 // twist a little... 34861 normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) ); 34862 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); 34863 34864 } 34865 34866 } 34867 34868 return { 34869 tangents: tangents, 34870 normals: normals, 34871 binormals: binormals 34872 }; 34873 34874 } 34875 34876 clone() { 34877 34878 return new this.constructor().copy( this ); 34879 34880 } 34881 34882 copy( source ) { 34883 34884 this.arcLengthDivisions = source.arcLengthDivisions; 34885 34886 return this; 34887 34888 } 34889 34890 toJSON() { 34891 34892 const data = { 34893 metadata: { 34894 version: 4.6, 34895 type: 'Curve', 34896 generator: 'Curve.toJSON' 34897 } 34898 }; 34899 34900 data.arcLengthDivisions = this.arcLengthDivisions; 34901 data.type = this.type; 34902 34903 return data; 34904 34905 } 34906 34907 fromJSON( json ) { 34908 34909 this.arcLengthDivisions = json.arcLengthDivisions; 34910 34911 return this; 34912 34913 } 34914 34915} 34916 34917class EllipseCurve extends Curve { 34918 34919 constructor( aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0 ) { 34920 34921 super(); 34922 34923 this.isEllipseCurve = true; 34924 34925 this.type = 'EllipseCurve'; 34926 34927 this.aX = aX; 34928 this.aY = aY; 34929 34930 this.xRadius = xRadius; 34931 this.yRadius = yRadius; 34932 34933 this.aStartAngle = aStartAngle; 34934 this.aEndAngle = aEndAngle; 34935 34936 this.aClockwise = aClockwise; 34937 34938 this.aRotation = aRotation; 34939 34940 } 34941 34942 getPoint( t, optionalTarget ) { 34943 34944 const point = optionalTarget || new Vector2(); 34945 34946 const twoPi = Math.PI * 2; 34947 let deltaAngle = this.aEndAngle - this.aStartAngle; 34948 const samePoints = Math.abs( deltaAngle ) < Number.EPSILON; 34949 34950 // ensures that deltaAngle is 0 .. 2 PI 34951 while ( deltaAngle < 0 ) deltaAngle += twoPi; 34952 while ( deltaAngle > twoPi ) deltaAngle -= twoPi; 34953 34954 if ( deltaAngle < Number.EPSILON ) { 34955 34956 if ( samePoints ) { 34957 34958 deltaAngle = 0; 34959 34960 } else { 34961 34962 deltaAngle = twoPi; 34963 34964 } 34965 34966 } 34967 34968 if ( this.aClockwise === true && ! samePoints ) { 34969 34970 if ( deltaAngle === twoPi ) { 34971 34972 deltaAngle = - twoPi; 34973 34974 } else { 34975 34976 deltaAngle = deltaAngle - twoPi; 34977 34978 } 34979 34980 } 34981 34982 const angle = this.aStartAngle + t * deltaAngle; 34983 let x = this.aX + this.xRadius * Math.cos( angle ); 34984 let y = this.aY + this.yRadius * Math.sin( angle ); 34985 34986 if ( this.aRotation !== 0 ) { 34987 34988 const cos = Math.cos( this.aRotation ); 34989 const sin = Math.sin( this.aRotation ); 34990 34991 const tx = x - this.aX; 34992 const ty = y - this.aY; 34993 34994 // Rotate the point about the center of the ellipse. 34995 x = tx * cos - ty * sin + this.aX; 34996 y = tx * sin + ty * cos + this.aY; 34997 34998 } 34999 35000 return point.set( x, y ); 35001 35002 } 35003 35004 copy( source ) { 35005 35006 super.copy( source ); 35007 35008 this.aX = source.aX; 35009 this.aY = source.aY; 35010 35011 this.xRadius = source.xRadius; 35012 this.yRadius = source.yRadius; 35013
vendor: 29,619 bytes, lines 35014-36696
35014 this.aStartAngle = source.aStartAngle; 35015 this.aEndAngle = source.aEndAngle; 35016 35017 this.aClockwise = source.aClockwise; 35018 35019 this.aRotation = source.aRotation; 35020 35021 return this; 35022 35023 } 35024 35025 toJSON() { 35026 35027 const data = super.toJSON(); 35028 35029 data.aX = this.aX; 35030 data.aY = this.aY; 35031 35032 data.xRadius = this.xRadius; 35033 data.yRadius = this.yRadius; 35034 35035 data.aStartAngle = this.aStartAngle; 35036 data.aEndAngle = this.aEndAngle; 35037 35038 data.aClockwise = this.aClockwise; 35039 35040 data.aRotation = this.aRotation; 35041 35042 return data; 35043 35044 } 35045 35046 fromJSON( json ) { 35047 35048 super.fromJSON( json ); 35049 35050 this.aX = json.aX; 35051 this.aY = json.aY; 35052 35053 this.xRadius = json.xRadius; 35054 this.yRadius = json.yRadius; 35055 35056 this.aStartAngle = json.aStartAngle; 35057 this.aEndAngle = json.aEndAngle; 35058 35059 this.aClockwise = json.aClockwise; 35060 35061 this.aRotation = json.aRotation; 35062 35063 return this; 35064 35065 } 35066 35067} 35068 35069class ArcCurve extends EllipseCurve { 35070 35071 constructor( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 35072 35073 super( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); 35074 35075 this.isArcCurve = true; 35076 35077 this.type = 'ArcCurve'; 35078 35079 } 35080 35081} 35082 35083/** 35084 * Centripetal CatmullRom Curve - which is useful for avoiding 35085 * cusps and self-intersections in non-uniform catmull rom curves. 35086 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf 35087 * 35088 * curve.type accepts centripetal(default), chordal and catmullrom 35089 * curve.tension is used for catmullrom which defaults to 0.5 35090 */ 35091 35092 35093/* 35094Based on an optimized c++ solution in 35095 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/ 35096 - http://ideone.com/NoEbVM 35097 35098This CubicPoly class could be used for reusing some variables and calculations, 35099but for three.js curve use, it could be possible inlined and flatten into a single function call 35100which can be placed in CurveUtils. 35101*/ 35102 35103function CubicPoly() { 35104 35105 let c0 = 0, c1 = 0, c2 = 0, c3 = 0; 35106 35107 /* 35108 * Compute coefficients for a cubic polynomial 35109 * p(s) = c0 + c1*s + c2*s^2 + c3*s^3 35110 * such that 35111 * p(0) = x0, p(1) = x1 35112 * and 35113 * p'(0) = t0, p'(1) = t1. 35114 */ 35115 function init( x0, x1, t0, t1 ) { 35116 35117 c0 = x0; 35118 c1 = t0; 35119 c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1; 35120 c3 = 2 * x0 - 2 * x1 + t0 + t1; 35121 35122 } 35123 35124 return { 35125 35126 initCatmullRom: function ( x0, x1, x2, x3, tension ) { 35127 35128 init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) ); 35129 35130 }, 35131 35132 initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) { 35133 35134 // compute tangents when parameterized in [t1,t2] 35135 let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1; 35136 let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2; 35137 35138 // rescale tangents for parametrization in [0,1] 35139 t1 *= dt1; 35140 t2 *= dt1; 35141 35142 init( x1, x2, t1, t2 ); 35143 35144 }, 35145 35146 calc: function ( t ) { 35147 35148 const t2 = t * t; 35149 const t3 = t2 * t; 35150 return c0 + c1 * t + c2 * t2 + c3 * t3; 35151 35152 } 35153 35154 }; 35155 35156} 35157 35158// 35159 35160const tmp = /*@__PURE__*/ new Vector3(); 35161const px = /*@__PURE__*/ new CubicPoly(); 35162const py = /*@__PURE__*/ new CubicPoly(); 35163const pz = /*@__PURE__*/ new CubicPoly(); 35164 35165class CatmullRomCurve3 extends Curve { 35166 35167 constructor( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) { 35168 35169 super(); 35170 35171 this.isCatmullRomCurve3 = true; 35172 35173 this.type = 'CatmullRomCurve3'; 35174 35175 this.points = points; 35176 this.closed = closed; 35177 this.curveType = curveType; 35178 this.tension = tension; 35179 35180 } 35181 35182 getPoint( t, optionalTarget = new Vector3() ) { 35183 35184 const point = optionalTarget; 35185 35186 const points = this.points; 35187 const l = points.length; 35188 35189 const p = ( l - ( this.closed ? 0 : 1 ) ) * t; 35190 let intPoint = Math.floor( p ); 35191 let weight = p - intPoint; 35192 35193 if ( this.closed ) { 35194 35195 intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l; 35196 35197 } else if ( weight === 0 && intPoint === l - 1 ) { 35198 35199 intPoint = l - 2; 35200 weight = 1; 35201 35202 } 35203 35204 let p0, p3; // 4 points (p1 & p2 defined below) 35205 35206 if ( this.closed || intPoint > 0 ) { 35207 35208 p0 = points[ ( intPoint - 1 ) % l ]; 35209 35210 } else { 35211 35212 // extrapolate first point 35213 tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] ); 35214 p0 = tmp; 35215 35216 } 35217 35218 const p1 = points[ intPoint % l ]; 35219 const p2 = points[ ( intPoint + 1 ) % l ]; 35220 35221 if ( this.closed || intPoint + 2 < l ) { 35222 35223 p3 = points[ ( intPoint + 2 ) % l ]; 35224 35225 } else { 35226 35227 // extrapolate last point 35228 tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] ); 35229 p3 = tmp; 35230 35231 } 35232 35233 if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) { 35234 35235 // init Centripetal / Chordal Catmull-Rom 35236 const pow = this.curveType === 'chordal' ? 0.5 : 0.25; 35237 let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow ); 35238 let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow ); 35239 let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow ); 35240 35241 // safety check for repeated points 35242 if ( dt1 < 1e-4 ) dt1 = 1.0; 35243 if ( dt0 < 1e-4 ) dt0 = dt1; 35244 if ( dt2 < 1e-4 ) dt2 = dt1; 35245 35246 px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 ); 35247 py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 ); 35248 pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 ); 35249 35250 } else if ( this.curveType === 'catmullrom' ) { 35251 35252 px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension ); 35253 py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension ); 35254 pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension ); 35255 35256 } 35257 35258 point.set( 35259 px.calc( weight ), 35260 py.calc( weight ), 35261 pz.calc( weight ) 35262 ); 35263 35264 return point; 35265 35266 } 35267 35268 copy( source ) { 35269 35270 super.copy( source ); 35271 35272 this.points = []; 35273 35274 for ( let i = 0, l = source.points.length; i < l; i ++ ) { 35275 35276 const point = source.points[ i ]; 35277 35278 this.points.push( point.clone() ); 35279 35280 } 35281 35282 this.closed = source.closed; 35283 this.curveType = source.curveType; 35284 this.tension = source.tension; 35285 35286 return this; 35287 35288 } 35289 35290 toJSON() { 35291 35292 const data = super.toJSON(); 35293 35294 data.points = []; 35295 35296 for ( let i = 0, l = this.points.length; i < l; i ++ ) { 35297 35298 const point = this.points[ i ]; 35299 data.points.push( point.toArray() ); 35300 35301 } 35302 35303 data.closed = this.closed; 35304 data.curveType = this.curveType; 35305 data.tension = this.tension; 35306 35307 return data; 35308 35309 } 35310 35311 fromJSON( json ) { 35312 35313 super.fromJSON( json ); 35314 35315 this.points = []; 35316 35317 for ( let i = 0, l = json.points.length; i < l; i ++ ) { 35318 35319 const point = json.points[ i ]; 35320 this.points.push( new Vector3().fromArray( point ) ); 35321 35322 } 35323 35324 this.closed = json.closed; 35325 this.curveType = json.curveType; 35326 this.tension = json.tension; 35327 35328 return this; 35329 35330 } 35331 35332} 35333 35334/** 35335 * Bezier Curves formulas obtained from 35336 * https://en.wikipedia.org/wiki/B%C3%A9zier_curve 35337 */ 35338 35339function CatmullRom( t, p0, p1, p2, p3 ) { 35340 35341 const v0 = ( p2 - p0 ) * 0.5; 35342 const v1 = ( p3 - p1 ) * 0.5; 35343 const t2 = t * t; 35344 const t3 = t * t2; 35345 return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1; 35346 35347} 35348 35349// 35350 35351function QuadraticBezierP0( t, p ) { 35352 35353 const k = 1 - t; 35354 return k * k * p; 35355 35356} 35357 35358function QuadraticBezierP1( t, p ) { 35359 35360 return 2 * ( 1 - t ) * t * p; 35361 35362} 35363 35364function QuadraticBezierP2( t, p ) { 35365 35366 return t * t * p; 35367 35368} 35369 35370function QuadraticBezier( t, p0, p1, p2 ) { 35371 35372 return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) + 35373 QuadraticBezierP2( t, p2 ); 35374 35375} 35376 35377// 35378 35379function CubicBezierP0( t, p ) { 35380 35381 const k = 1 - t; 35382 return k * k * k * p; 35383 35384} 35385 35386function CubicBezierP1( t, p ) { 35387 35388 const k = 1 - t; 35389 return 3 * k * k * t * p; 35390 35391} 35392 35393function CubicBezierP2( t, p ) { 35394 35395 return 3 * ( 1 - t ) * t * t * p; 35396 35397} 35398 35399function CubicBezierP3( t, p ) { 35400 35401 return t * t * t * p; 35402 35403} 35404 35405function CubicBezier( t, p0, p1, p2, p3 ) { 35406 35407 return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) + 35408 CubicBezierP3( t, p3 ); 35409 35410} 35411 35412class CubicBezierCurve extends Curve { 35413 35414 constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) { 35415 35416 super(); 35417 35418 this.isCubicBezierCurve = true; 35419 35420 this.type = 'CubicBezierCurve'; 35421 35422 this.v0 = v0; 35423 this.v1 = v1; 35424 this.v2 = v2; 35425 this.v3 = v3; 35426 35427 } 35428 35429 getPoint( t, optionalTarget = new Vector2() ) { 35430 35431 const point = optionalTarget; 35432 35433 const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; 35434 35435 point.set( 35436 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), 35437 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ) 35438 ); 35439 35440 return point; 35441 35442 } 35443 35444 copy( source ) { 35445 35446 super.copy( source ); 35447 35448 this.v0.copy( source.v0 ); 35449 this.v1.copy( source.v1 ); 35450 this.v2.copy( source.v2 ); 35451 this.v3.copy( source.v3 ); 35452 35453 return this; 35454 35455 } 35456 35457 toJSON() { 35458 35459 const data = super.toJSON(); 35460 35461 data.v0 = this.v0.toArray(); 35462 data.v1 = this.v1.toArray(); 35463 data.v2 = this.v2.toArray(); 35464 data.v3 = this.v3.toArray(); 35465 35466 return data; 35467 35468 } 35469 35470 fromJSON( json ) { 35471 35472 super.fromJSON( json ); 35473 35474 this.v0.fromArray( json.v0 ); 35475 this.v1.fromArray( json.v1 ); 35476 this.v2.fromArray( json.v2 ); 35477 this.v3.fromArray( json.v3 ); 35478 35479 return this; 35480 35481 } 35482 35483} 35484 35485class CubicBezierCurve3 extends Curve { 35486 35487 constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) { 35488 35489 super(); 35490 35491 this.isCubicBezierCurve3 = true; 35492 35493 this.type = 'CubicBezierCurve3'; 35494 35495 this.v0 = v0; 35496 this.v1 = v1; 35497 this.v2 = v2; 35498 this.v3 = v3; 35499 35500 } 35501 35502 getPoint( t, optionalTarget = new Vector3() ) { 35503 35504 const point = optionalTarget; 35505 35506 const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; 35507 35508 point.set( 35509 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), 35510 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ), 35511 CubicBezier( t, v0.z, v1.z, v2.z, v3.z ) 35512 ); 35513 35514 return point; 35515 35516 } 35517 35518 copy( source ) { 35519 35520 super.copy( source ); 35521 35522 this.v0.copy( source.v0 ); 35523 this.v1.copy( source.v1 ); 35524 this.v2.copy( source.v2 ); 35525 this.v3.copy( source.v3 ); 35526 35527 return this; 35528 35529 } 35530 35531 toJSON() { 35532 35533 const data = super.toJSON(); 35534 35535 data.v0 = this.v0.toArray(); 35536 data.v1 = this.v1.toArray(); 35537 data.v2 = this.v2.toArray(); 35538 data.v3 = this.v3.toArray(); 35539 35540 return data; 35541 35542 } 35543 35544 fromJSON( json ) { 35545 35546 super.fromJSON( json ); 35547 35548 this.v0.fromArray( json.v0 ); 35549 this.v1.fromArray( json.v1 ); 35550 this.v2.fromArray( json.v2 ); 35551 this.v3.fromArray( json.v3 ); 35552 35553 return this; 35554 35555 } 35556 35557} 35558 35559class LineCurve extends Curve { 35560 35561 constructor( v1 = new Vector2(), v2 = new Vector2() ) { 35562 35563 super(); 35564 35565 this.isLineCurve = true; 35566 35567 this.type = 'LineCurve'; 35568 35569 this.v1 = v1; 35570 this.v2 = v2; 35571 35572 } 35573 35574 getPoint( t, optionalTarget = new Vector2() ) { 35575 35576 const point = optionalTarget; 35577 35578 if ( t === 1 ) { 35579 35580 point.copy( this.v2 ); 35581 35582 } else { 35583 35584 point.copy( this.v2 ).sub( this.v1 ); 35585 point.multiplyScalar( t ).add( this.v1 ); 35586 35587 } 35588 35589 return point; 35590 35591 } 35592 35593 // Line curve is linear, so we can overwrite default getPointAt 35594 getPointAt( u, optionalTarget ) { 35595 35596 return this.getPoint( u, optionalTarget ); 35597 35598 } 35599 35600 getTangent( t, optionalTarget = new Vector2() ) { 35601 35602 return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); 35603 35604 } 35605 35606 getTangentAt( u, optionalTarget ) { 35607 35608 return this.getTangent( u, optionalTarget ); 35609 35610 } 35611 35612 copy( source ) { 35613 35614 super.copy( source ); 35615 35616 this.v1.copy( source.v1 ); 35617 this.v2.copy( source.v2 ); 35618 35619 return this; 35620 35621 } 35622 35623 toJSON() { 35624 35625 const data = super.toJSON(); 35626 35627 data.v1 = this.v1.toArray(); 35628 data.v2 = this.v2.toArray(); 35629 35630 return data; 35631 35632 } 35633 35634 fromJSON( json ) { 35635 35636 super.fromJSON( json ); 35637 35638 this.v1.fromArray( json.v1 ); 35639 this.v2.fromArray( json.v2 ); 35640 35641 return this; 35642 35643 } 35644 35645} 35646 35647class LineCurve3 extends Curve { 35648 35649 constructor( v1 = new Vector3(), v2 = new Vector3() ) { 35650 35651 super(); 35652 35653 this.isLineCurve3 = true; 35654 35655 this.type = 'LineCurve3'; 35656 35657 this.v1 = v1; 35658 this.v2 = v2; 35659 35660 } 35661 35662 getPoint( t, optionalTarget = new Vector3() ) { 35663 35664 const point = optionalTarget; 35665 35666 if ( t === 1 ) { 35667 35668 point.copy( this.v2 ); 35669 35670 } else { 35671 35672 point.copy( this.v2 ).sub( this.v1 ); 35673 point.multiplyScalar( t ).add( this.v1 ); 35674 35675 } 35676 35677 return point; 35678 35679 } 35680 35681 // Line curve is linear, so we can overwrite default getPointAt 35682 getPointAt( u, optionalTarget ) { 35683 35684 return this.getPoint( u, optionalTarget ); 35685 35686 } 35687 35688 getTangent( t, optionalTarget = new Vector3() ) { 35689 35690 return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); 35691 35692 } 35693 35694 getTangentAt( u, optionalTarget ) { 35695 35696 return this.getTangent( u, optionalTarget ); 35697 35698 } 35699 35700 copy( source ) { 35701 35702 super.copy( source ); 35703 35704 this.v1.copy( source.v1 ); 35705 this.v2.copy( source.v2 ); 35706 35707 return this; 35708 35709 } 35710 35711 toJSON() { 35712 35713 const data = super.toJSON(); 35714 35715 data.v1 = this.v1.toArray(); 35716 data.v2 = this.v2.toArray(); 35717 35718 return data; 35719 35720 } 35721 35722 fromJSON( json ) { 35723 35724 super.fromJSON( json ); 35725 35726 this.v1.fromArray( json.v1 ); 35727 this.v2.fromArray( json.v2 ); 35728 35729 return this; 35730 35731 } 35732 35733} 35734 35735class QuadraticBezierCurve extends Curve { 35736 35737 constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) { 35738 35739 super(); 35740 35741 this.isQuadraticBezierCurve = true; 35742 35743 this.type = 'QuadraticBezierCurve'; 35744 35745 this.v0 = v0; 35746 this.v1 = v1; 35747 this.v2 = v2; 35748 35749 } 35750 35751 getPoint( t, optionalTarget = new Vector2() ) { 35752 35753 const point = optionalTarget; 35754 35755 const v0 = this.v0, v1 = this.v1, v2 = this.v2; 35756 35757 point.set( 35758 QuadraticBezier( t, v0.x, v1.x, v2.x ), 35759 QuadraticBezier( t, v0.y, v1.y, v2.y ) 35760 ); 35761 35762 return point; 35763 35764 } 35765 35766 copy( source ) { 35767 35768 super.copy( source ); 35769 35770 this.v0.copy( source.v0 ); 35771 this.v1.copy( source.v1 ); 35772 this.v2.copy( source.v2 ); 35773 35774 return this; 35775 35776 } 35777 35778 toJSON() { 35779 35780 const data = super.toJSON(); 35781 35782 data.v0 = this.v0.toArray(); 35783 data.v1 = this.v1.toArray(); 35784 data.v2 = this.v2.toArray(); 35785 35786 return data; 35787 35788 } 35789 35790 fromJSON( json ) { 35791 35792 super.fromJSON( json ); 35793 35794 this.v0.fromArray( json.v0 ); 35795 this.v1.fromArray( json.v1 ); 35796 this.v2.fromArray( json.v2 ); 35797 35798 return this; 35799 35800 } 35801 35802} 35803 35804class QuadraticBezierCurve3 extends Curve { 35805 35806 constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) { 35807 35808 super(); 35809 35810 this.isQuadraticBezierCurve3 = true; 35811 35812 this.type = 'QuadraticBezierCurve3'; 35813 35814 this.v0 = v0; 35815 this.v1 = v1; 35816 this.v2 = v2; 35817 35818 } 35819 35820 getPoint( t, optionalTarget = new Vector3() ) { 35821 35822 const point = optionalTarget; 35823 35824 const v0 = this.v0, v1 = this.v1, v2 = this.v2; 35825 35826 point.set( 35827 QuadraticBezier( t, v0.x, v1.x, v2.x ), 35828 QuadraticBezier( t, v0.y, v1.y, v2.y ), 35829 QuadraticBezier( t, v0.z, v1.z, v2.z ) 35830 ); 35831 35832 return point; 35833 35834 } 35835 35836 copy( source ) { 35837 35838 super.copy( source ); 35839 35840 this.v0.copy( source.v0 ); 35841 this.v1.copy( source.v1 ); 35842 this.v2.copy( source.v2 ); 35843 35844 return this; 35845 35846 } 35847 35848 toJSON() { 35849 35850 const data = super.toJSON(); 35851 35852 data.v0 = this.v0.toArray(); 35853 data.v1 = this.v1.toArray(); 35854 data.v2 = this.v2.toArray(); 35855 35856 return data; 35857 35858 } 35859 35860 fromJSON( json ) { 35861 35862 super.fromJSON( json ); 35863 35864 this.v0.fromArray( json.v0 ); 35865 this.v1.fromArray( json.v1 ); 35866 this.v2.fromArray( json.v2 ); 35867 35868 return this; 35869 35870 } 35871 35872} 35873 35874class SplineCurve extends Curve { 35875 35876 constructor( points = [] ) { 35877 35878 super(); 35879 35880 this.isSplineCurve = true; 35881 35882 this.type = 'SplineCurve'; 35883 35884 this.points = points; 35885 35886 } 35887 35888 getPoint( t, optionalTarget = new Vector2() ) { 35889 35890 const point = optionalTarget; 35891 35892 const points = this.points; 35893 const p = ( points.length - 1 ) * t; 35894 35895 const intPoint = Math.floor( p ); 35896 const weight = p - intPoint; 35897 35898 const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ]; 35899 const p1 = points[ intPoint ]; 35900 const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ]; 35901 const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ]; 35902 35903 point.set( 35904 CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ), 35905 CatmullRom( weight, p0.y, p1.y, p2.y, p3.y ) 35906 ); 35907 35908 return point; 35909 35910 } 35911 35912 copy( source ) { 35913 35914 super.copy( source ); 35915 35916 this.points = []; 35917 35918 for ( let i = 0, l = source.points.length; i < l; i ++ ) { 35919 35920 const point = source.points[ i ]; 35921 35922 this.points.push( point.clone() ); 35923 35924 } 35925 35926 return this; 35927 35928 } 35929 35930 toJSON() { 35931 35932 const data = super.toJSON(); 35933 35934 data.points = []; 35935 35936 for ( let i = 0, l = this.points.length; i < l; i ++ ) { 35937 35938 const point = this.points[ i ]; 35939 data.points.push( point.toArray() ); 35940 35941 } 35942 35943 return data; 35944 35945 } 35946 35947 fromJSON( json ) { 35948 35949 super.fromJSON( json ); 35950 35951 this.points = []; 35952 35953 for ( let i = 0, l = json.points.length; i < l; i ++ ) { 35954 35955 const point = json.points[ i ]; 35956 this.points.push( new Vector2().fromArray( point ) ); 35957 35958 } 35959 35960 return this; 35961 35962 } 35963 35964} 35965 35966var Curves = /*#__PURE__*/Object.freeze({ 35967 __proto__: null, 35968 ArcCurve: ArcCurve, 35969 CatmullRomCurve3: CatmullRomCurve3, 35970 CubicBezierCurve: CubicBezierCurve, 35971 CubicBezierCurve3: CubicBezierCurve3, 35972 EllipseCurve: EllipseCurve, 35973 LineCurve: LineCurve, 35974 LineCurve3: LineCurve3, 35975 QuadraticBezierCurve: QuadraticBezierCurve, 35976 QuadraticBezierCurve3: QuadraticBezierCurve3, 35977 SplineCurve: SplineCurve 35978}); 35979 35980/************************************************************** 35981 * Curved Path - a curve path is simply a array of connected 35982 * curves, but retains the api of a curve 35983 **************************************************************/ 35984 35985class CurvePath extends Curve { 35986 35987 constructor() { 35988 35989 super(); 35990 35991 this.type = 'CurvePath'; 35992 35993 this.curves = []; 35994 this.autoClose = false; // Automatically closes the path 35995 35996 } 35997 35998 add( curve ) { 35999 36000 this.curves.push( curve ); 36001 36002 } 36003 36004 closePath() { 36005 36006 // Add a line curve if start and end of lines are not connected 36007 const startPoint = this.curves[ 0 ].getPoint( 0 ); 36008 const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 ); 36009 36010 if ( ! startPoint.equals( endPoint ) ) { 36011 36012 const lineType = ( startPoint.isVector2 === true ) ? 'LineCurve' : 'LineCurve3'; 36013 this.curves.push( new Curves[ lineType ]( endPoint, startPoint ) ); 36014 36015 } 36016 36017 return this; 36018 36019 } 36020 36021 // To get accurate point with reference to 36022 // entire path distance at time t, 36023 // following has to be done: 36024 36025 // 1. Length of each sub path have to be known 36026 // 2. Locate and identify type of curve 36027 // 3. Get t for the curve 36028 // 4. Return curve.getPointAt(t') 36029 36030 getPoint( t, optionalTarget ) { 36031 36032 const d = t * this.getLength(); 36033 const curveLengths = this.getCurveLengths(); 36034 let i = 0; 36035 36036 // To think about boundaries points. 36037 36038 while ( i < curveLengths.length ) { 36039 36040 if ( curveLengths[ i ] >= d ) { 36041 36042 const diff = curveLengths[ i ] - d; 36043 const curve = this.curves[ i ]; 36044 36045 const segmentLength = curve.getLength(); 36046 const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength; 36047 36048 return curve.getPointAt( u, optionalTarget ); 36049 36050 } 36051 36052 i ++; 36053 36054 } 36055 36056 return null; 36057 36058 // loop where sum != 0, sum > d , sum+1 <d 36059 36060 } 36061 36062 // We cannot use the default THREE.Curve getPoint() with getLength() because in 36063 // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath 36064 // getPoint() depends on getLength 36065 36066 getLength() { 36067 36068 const lens = this.getCurveLengths(); 36069 return lens[ lens.length - 1 ]; 36070 36071 } 36072 36073 // cacheLengths must be recalculated. 36074 updateArcLengths() { 36075 36076 this.needsUpdate = true; 36077 this.cacheLengths = null; 36078 this.getCurveLengths(); 36079 36080 } 36081 36082 // Compute lengths and cache them 36083 // We cannot overwrite getLengths() because UtoT mapping uses it. 36084 36085 getCurveLengths() { 36086 36087 // We use cache values if curves and cache array are same length 36088 36089 if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) { 36090 36091 return this.cacheLengths; 36092 36093 } 36094 36095 // Get length of sub-curve 36096 // Push sums into cached array 36097 36098 const lengths = []; 36099 let sums = 0; 36100 36101 for ( let i = 0, l = this.curves.length; i < l; i ++ ) { 36102 36103 sums += this.curves[ i ].getLength(); 36104 lengths.push( sums ); 36105 36106 } 36107 36108 this.cacheLengths = lengths; 36109 36110 return lengths; 36111 36112 } 36113 36114 getSpacedPoints( divisions = 40 ) { 36115 36116 const points = []; 36117 36118 for ( let i = 0; i <= divisions; i ++ ) { 36119 36120 points.push( this.getPoint( i / divisions ) ); 36121 36122 } 36123 36124 if ( this.autoClose ) { 36125 36126 points.push( points[ 0 ] ); 36127 36128 } 36129 36130 return points; 36131 36132 } 36133 36134 getPoints( divisions = 12 ) { 36135 36136 const points = []; 36137 let last; 36138 36139 for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) { 36140 36141 const curve = curves[ i ]; 36142 const resolution = curve.isEllipseCurve ? divisions * 2 36143 : ( curve.isLineCurve || curve.isLineCurve3 ) ? 1 36144 : curve.isSplineCurve ? divisions * curve.points.length 36145 : divisions; 36146 36147 const pts = curve.getPoints( resolution ); 36148 36149 for ( let j = 0; j < pts.length; j ++ ) { 36150 36151 const point = pts[ j ]; 36152 36153 if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates 36154 36155 points.push( point ); 36156 last = point; 36157 36158 } 36159 36160 } 36161 36162 if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) { 36163 36164 points.push( points[ 0 ] ); 36165 36166 } 36167 36168 return points; 36169 36170 } 36171 36172 copy( source ) { 36173 36174 super.copy( source ); 36175 36176 this.curves = []; 36177 36178 for ( let i = 0, l = source.curves.length; i < l; i ++ ) { 36179 36180 const curve = source.curves[ i ]; 36181 36182 this.curves.push( curve.clone() ); 36183 36184 } 36185 36186 this.autoClose = source.autoClose; 36187 36188 return this; 36189 36190 } 36191 36192 toJSON() { 36193 36194 const data = super.toJSON(); 36195 36196 data.autoClose = this.autoClose; 36197 data.curves = []; 36198 36199 for ( let i = 0, l = this.curves.length; i < l; i ++ ) { 36200 36201 const curve = this.curves[ i ]; 36202 data.curves.push( curve.toJSON() ); 36203 36204 } 36205 36206 return data; 36207 36208 } 36209 36210 fromJSON( json ) { 36211 36212 super.fromJSON( json ); 36213 36214 this.autoClose = json.autoClose; 36215 this.curves = []; 36216 36217 for ( let i = 0, l = json.curves.length; i < l; i ++ ) { 36218 36219 const curve = json.curves[ i ]; 36220 this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) ); 36221 36222 } 36223 36224 return this; 36225 36226 } 36227 36228} 36229 36230class Path extends CurvePath { 36231 36232 constructor( points ) { 36233 36234 super(); 36235 36236 this.type = 'Path'; 36237 36238 this.currentPoint = new Vector2(); 36239 36240 if ( points ) { 36241 36242 this.setFromPoints( points ); 36243 36244 } 36245 36246 } 36247 36248 setFromPoints( points ) { 36249 36250 this.moveTo( points[ 0 ].x, points[ 0 ].y ); 36251 36252 for ( let i = 1, l = points.length; i < l; i ++ ) { 36253 36254 this.lineTo( points[ i ].x, points[ i ].y ); 36255 36256 } 36257 36258 return this; 36259 36260 } 36261 36262 moveTo( x, y ) { 36263 36264 this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying? 36265 36266 return this; 36267 36268 } 36269 36270 lineTo( x, y ) { 36271 36272 const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) ); 36273 this.curves.push( curve ); 36274 36275 this.currentPoint.set( x, y ); 36276 36277 return this; 36278 36279 } 36280 36281 quadraticCurveTo( aCPx, aCPy, aX, aY ) { 36282 36283 const curve = new QuadraticBezierCurve( 36284 this.currentPoint.clone(), 36285 new Vector2( aCPx, aCPy ), 36286 new Vector2( aX, aY ) 36287 ); 36288 36289 this.curves.push( curve ); 36290 36291 this.currentPoint.set( aX, aY ); 36292 36293 return this; 36294 36295 } 36296 36297 bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { 36298 36299 const curve = new CubicBezierCurve( 36300 this.currentPoint.clone(), 36301 new Vector2( aCP1x, aCP1y ), 36302 new Vector2( aCP2x, aCP2y ), 36303 new Vector2( aX, aY ) 36304 ); 36305 36306 this.curves.push( curve ); 36307 36308 this.currentPoint.set( aX, aY ); 36309 36310 return this; 36311 36312 } 36313 36314 splineThru( pts /*Array of Vector*/ ) { 36315 36316 const npts = [ this.currentPoint.clone() ].concat( pts ); 36317 36318 const curve = new SplineCurve( npts ); 36319 this.curves.push( curve ); 36320 36321 this.currentPoint.copy( pts[ pts.length - 1 ] ); 36322 36323 return this; 36324 36325 } 36326 36327 arc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 36328 36329 const x0 = this.currentPoint.x; 36330 const y0 = this.currentPoint.y; 36331 36332 this.absarc( aX + x0, aY + y0, aRadius, 36333 aStartAngle, aEndAngle, aClockwise ); 36334 36335 return this; 36336 36337 } 36338 36339 absarc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 36340 36341 this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); 36342 36343 return this; 36344 36345 } 36346 36347 ellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { 36348 36349 const x0 = this.currentPoint.x; 36350 const y0 = this.currentPoint.y; 36351 36352 this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); 36353 36354 return this; 36355 36356 } 36357 36358 absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { 36359 36360 const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); 36361 36362 if ( this.curves.length > 0 ) { 36363 36364 // if a previous curve is present, attempt to join 36365 const firstPoint = curve.getPoint( 0 ); 36366 36367 if ( ! firstPoint.equals( this.currentPoint ) ) { 36368 36369 this.lineTo( firstPoint.x, firstPoint.y ); 36370 36371 } 36372 36373 } 36374 36375 this.curves.push( curve ); 36376 36377 const lastPoint = curve.getPoint( 1 ); 36378 this.currentPoint.copy( lastPoint ); 36379 36380 return this; 36381 36382 } 36383 36384 copy( source ) { 36385 36386 super.copy( source ); 36387 36388 this.currentPoint.copy( source.currentPoint ); 36389 36390 return this; 36391 36392 } 36393 36394 toJSON() { 36395 36396 const data = super.toJSON(); 36397 36398 data.currentPoint = this.currentPoint.toArray(); 36399 36400 return data; 36401 36402 } 36403 36404 fromJSON( json ) { 36405 36406 super.fromJSON( json ); 36407 36408 this.currentPoint.fromArray( json.currentPoint ); 36409 36410 return this; 36411 36412 } 36413 36414} 36415 36416class LatheGeometry extends BufferGeometry { 36417 36418 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 ) { 36419 36420 super(); 36421 36422 this.type = 'LatheGeometry'; 36423 36424 this.parameters = { 36425 points: points, 36426 segments: segments, 36427 phiStart: phiStart, 36428 phiLength: phiLength 36429 }; 36430 36431 segments = Math.floor( segments ); 36432 36433 // clamp phiLength so it's in range of [ 0, 2PI ] 36434 36435 phiLength = clamp( phiLength, 0, Math.PI * 2 ); 36436 36437 // buffers 36438 36439 const indices = []; 36440 const vertices = []; 36441 const uvs = []; 36442 const initNormals = []; 36443 const normals = []; 36444 36445 // helper variables 36446 36447 const inverseSegments = 1.0 / segments; 36448 const vertex = new Vector3(); 36449 const uv = new Vector2(); 36450 const normal = new Vector3(); 36451 const curNormal = new Vector3(); 36452 const prevNormal = new Vector3(); 36453 let dx = 0; 36454 let dy = 0; 36455 36456 // pre-compute normals for initial "meridian" 36457 36458 for ( let j = 0; j <= ( points.length - 1 ); j ++ ) { 36459 36460 switch ( j ) { 36461 36462 case 0: // special handling for 1st vertex on path 36463 36464 dx = points[ j + 1 ].x - points[ j ].x; 36465 dy = points[ j + 1 ].y - points[ j ].y; 36466 36467 normal.x = dy * 1.0; 36468 normal.y = - dx; 36469 normal.z = dy * 0.0; 36470 36471 prevNormal.copy( normal ); 36472 36473 normal.normalize(); 36474 36475 initNormals.push( normal.x, normal.y, normal.z ); 36476 36477 break; 36478 36479 case ( points.length - 1 ): // special handling for last Vertex on path 36480 36481 initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z ); 36482 36483 break; 36484 36485 default: // default handling for all vertices in between 36486 36487 dx = points[ j + 1 ].x - points[ j ].x; 36488 dy = points[ j + 1 ].y - points[ j ].y; 36489 36490 normal.x = dy * 1.0; 36491 normal.y = - dx; 36492 normal.z = dy * 0.0; 36493 36494 curNormal.copy( normal ); 36495 36496 normal.x += prevNormal.x; 36497 normal.y += prevNormal.y; 36498 normal.z += prevNormal.z; 36499 36500 normal.normalize(); 36501 36502 initNormals.push( normal.x, normal.y, normal.z ); 36503 36504 prevNormal.copy( curNormal ); 36505 36506 } 36507 36508 } 36509 36510 // generate vertices, uvs and normals 36511 36512 for ( let i = 0; i <= segments; i ++ ) { 36513 36514 const phi = phiStart + i * inverseSegments * phiLength; 36515 36516 const sin = Math.sin( phi ); 36517 const cos = Math.cos( phi ); 36518 36519 for ( let j = 0; j <= ( points.length - 1 ); j ++ ) { 36520 36521 // vertex 36522 36523 vertex.x = points[ j ].x * sin; 36524 vertex.y = points[ j ].y; 36525 vertex.z = points[ j ].x * cos; 36526 36527 vertices.push( vertex.x, vertex.y, vertex.z ); 36528 36529 // uv 36530 36531 uv.x = i / segments; 36532 uv.y = j / ( points.length - 1 ); 36533 36534 uvs.push( uv.x, uv.y ); 36535 36536 // normal 36537 36538 const x = initNormals[ 3 * j + 0 ] * sin; 36539 const y = initNormals[ 3 * j + 1 ]; 36540 const z = initNormals[ 3 * j + 0 ] * cos; 36541 36542 normals.push( x, y, z ); 36543 36544 } 36545 36546 } 36547 36548 // indices 36549 36550 for ( let i = 0; i < segments; i ++ ) { 36551 36552 for ( let j = 0; j < ( points.length - 1 ); j ++ ) { 36553 36554 const base = j + i * points.length; 36555 36556 const a = base; 36557 const b = base + points.length; 36558 const c = base + points.length + 1; 36559 const d = base + 1; 36560 36561 // faces 36562 36563 indices.push( a, b, d ); 36564 indices.push( c, d, b ); 36565 36566 } 36567 36568 } 36569 36570 // build geometry 36571 36572 this.setIndex( indices ); 36573 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 36574 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 36575 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 36576 36577 } 36578 36579 copy( source ) { 36580 36581 super.copy( source ); 36582 36583 this.parameters = Object.assign( {}, source.parameters ); 36584 36585 return this; 36586 36587 } 36588 36589 static fromJSON( data ) { 36590 36591 return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength ); 36592 36593 } 36594 36595} 36596 36597class CapsuleGeometry extends LatheGeometry { 36598 36599 constructor( radius = 1, length = 1, capSegments = 4, radialSegments = 8 ) { 36600 36601 const path = new Path(); 36602 path.absarc( 0, - length / 2, radius, Math.PI * 1.5, 0 ); 36603 path.absarc( 0, length / 2, radius, 0, Math.PI * 0.5 ); 36604 36605 super( path.getPoints( capSegments ), radialSegments ); 36606 36607 this.type = 'CapsuleGeometry'; 36608 36609 this.parameters = { 36610 radius: radius, 36611 length: length, 36612 capSegments: capSegments, 36613 radialSegments: radialSegments, 36614 }; 36615 36616 } 36617 36618 static fromJSON( data ) { 36619 36620 return new CapsuleGeometry( data.radius, data.length, data.capSegments, data.radialSegments ); 36621 36622 } 36623 36624} 36625 36626class CircleGeometry extends BufferGeometry { 36627 36628 constructor( radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2 ) { 36629 36630 super(); 36631 36632 this.type = 'CircleGeometry'; 36633 36634 this.parameters = { 36635 radius: radius, 36636 segments: segments, 36637 thetaStart: thetaStart, 36638 thetaLength: thetaLength 36639 }; 36640 36641 segments = Math.max( 3, segments ); 36642 36643 // buffers 36644 36645 const indices = []; 36646 const vertices = []; 36647 const normals = []; 36648 const uvs = []; 36649 36650 // helper variables 36651 36652 const vertex = new Vector3(); 36653 const uv = new Vector2(); 36654 36655 // center point 36656 36657 vertices.push( 0, 0, 0 ); 36658 normals.push( 0, 0, 1 ); 36659 uvs.push( 0.5, 0.5 ); 36660 36661 for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) { 36662 36663 const segment = thetaStart + s / segments * thetaLength; 36664 36665 // vertex 36666 36667 vertex.x = radius * Math.cos( segment ); 36668 vertex.y = radius * Math.sin( segment ); 36669 36670 vertices.push( vertex.x, vertex.y, vertex.z ); 36671 36672 // normal 36673 36674 normals.push( 0, 0, 1 ); 36675 36676 // uvs 36677 36678 uv.x = ( vertices[ i ] / radius + 1 ) / 2; 36679 uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2; 36680 36681 uvs.push( uv.x, uv.y ); 36682 36683 } 36684 36685 // indices 36686 36687 for ( let i = 1; i <= segments; i ++ ) { 36688 36689 indices.push( i, i + 1, 0 ); 36690 36691 } 36692 36693 // build geometry 36694 36695 this.setIndex( indices ); 36696 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,756 bytes, lines 36697-36922
36697 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 36698 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 36699 36700 } 36701 36702 copy( source ) { 36703 36704 super.copy( source ); 36705 36706 this.parameters = Object.assign( {}, source.parameters ); 36707 36708 return this; 36709 36710 } 36711 36712 static fromJSON( data ) { 36713 36714 return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength ); 36715 36716 } 36717 36718} 36719 36720class CylinderGeometry extends BufferGeometry { 36721 36722 constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { 36723 36724 super(); 36725 36726 this.type = 'CylinderGeometry'; 36727 36728 this.parameters = { 36729 radiusTop: radiusTop, 36730 radiusBottom: radiusBottom, 36731 height: height, 36732 radialSegments: radialSegments, 36733 heightSegments: heightSegments, 36734 openEnded: openEnded, 36735 thetaStart: thetaStart, 36736 thetaLength: thetaLength 36737 }; 36738 36739 const scope = this; 36740 36741 radialSegments = Math.floor( radialSegments ); 36742 heightSegments = Math.floor( heightSegments ); 36743 36744 // buffers 36745 36746 const indices = []; 36747 const vertices = []; 36748 const normals = []; 36749 const uvs = []; 36750 36751 // helper variables 36752 36753 let index = 0; 36754 const indexArray = []; 36755 const halfHeight = height / 2; 36756 let groupStart = 0; 36757 36758 // generate geometry 36759 36760 generateTorso(); 36761 36762 if ( openEnded === false ) { 36763 36764 if ( radiusTop > 0 ) generateCap( true ); 36765 if ( radiusBottom > 0 ) generateCap( false ); 36766 36767 } 36768 36769 // build geometry 36770 36771 this.setIndex( indices ); 36772 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 36773 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 36774 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 36775 36776 function generateTorso() { 36777 36778 const normal = new Vector3(); 36779 const vertex = new Vector3(); 36780 36781 let groupCount = 0; 36782 36783 // this will be used to calculate the normal 36784 const slope = ( radiusBottom - radiusTop ) / height; 36785 36786 // generate vertices, normals and uvs 36787 36788 for ( let y = 0; y <= heightSegments; y ++ ) { 36789 36790 const indexRow = []; 36791 36792 const v = y / heightSegments; 36793 36794 // calculate the radius of the current row 36795 36796 const radius = v * ( radiusBottom - radiusTop ) + radiusTop; 36797 36798 for ( let x = 0; x <= radialSegments; x ++ ) { 36799 36800 const u = x / radialSegments; 36801 36802 const theta = u * thetaLength + thetaStart; 36803 36804 const sinTheta = Math.sin( theta ); 36805 const cosTheta = Math.cos( theta ); 36806 36807 // vertex 36808 36809 vertex.x = radius * sinTheta; 36810 vertex.y = - v * height + halfHeight; 36811 vertex.z = radius * cosTheta; 36812 vertices.push( vertex.x, vertex.y, vertex.z ); 36813 36814 // normal 36815 36816 normal.set( sinTheta, slope, cosTheta ).normalize(); 36817 normals.push( normal.x, normal.y, normal.z ); 36818 36819 // uv 36820 36821 uvs.push( u, 1 - v ); 36822 36823 // save index of vertex in respective row 36824 36825 indexRow.push( index ++ ); 36826 36827 } 36828 36829 // now save vertices of the row in our index array 36830 36831 indexArray.push( indexRow ); 36832 36833 } 36834 36835 // generate indices 36836 36837 for ( let x = 0; x < radialSegments; x ++ ) { 36838 36839 for ( let y = 0; y < heightSegments; y ++ ) { 36840 36841 // we use the index array to access the correct indices 36842 36843 const a = indexArray[ y ][ x ]; 36844 const b = indexArray[ y + 1 ][ x ]; 36845 const c = indexArray[ y + 1 ][ x + 1 ]; 36846 const d = indexArray[ y ][ x + 1 ]; 36847 36848 // faces 36849 36850 indices.push( a, b, d ); 36851 indices.push( b, c, d ); 36852 36853 // update group counter 36854 36855 groupCount += 6; 36856 36857 } 36858 36859 } 36860 36861 // add a group to the geometry. this will ensure multi material support 36862 36863 scope.addGroup( groupStart, groupCount, 0 ); 36864 36865 // calculate new start value for groups 36866 36867 groupStart += groupCount; 36868 36869 } 36870 36871 function generateCap( top ) { 36872 36873 // save the index of the first center vertex 36874 const centerIndexStart = index; 36875 36876 const uv = new Vector2(); 36877 const vertex = new Vector3(); 36878 36879 let groupCount = 0; 36880 36881 const radius = ( top === true ) ? radiusTop : radiusBottom; 36882 const sign = ( top === true ) ? 1 : - 1; 36883 36884 // first we generate the center vertex data of the cap. 36885 // because the geometry needs one set of uvs per face, 36886 // we must generate a center vertex per face/segment 36887 36888 for ( let x = 1; x <= radialSegments; x ++ ) { 36889 36890 // vertex 36891 36892 vertices.push( 0, halfHeight * sign, 0 ); 36893 36894 // normal 36895 36896 normals.push( 0, sign, 0 ); 36897 36898 // uv 36899 36900 uvs.push( 0.5, 0.5 ); 36901 36902 // increase index 36903 36904 index ++; 36905 36906 } 36907 36908 // save the index of the last center vertex 36909 const centerIndexEnd = index; 36910 36911 // now we generate the surrounding vertices, normals and uvs 36912 36913 for ( let x = 0; x <= radialSegments; x ++ ) { 36914 36915 const u = x / radialSegments; 36916 const theta = u * thetaLength + thetaStart; 36917 36918 const cosTheta = Math.cos( theta ); 36919 const sinTheta = Math.sin( theta ); 36920 36921 // vertex 36922
vendor: 16,069 bytes, lines 36923-37701
36923 vertex.x = radius * sinTheta; 36924 vertex.y = halfHeight * sign; 36925 vertex.z = radius * cosTheta; 36926 vertices.push( vertex.x, vertex.y, vertex.z ); 36927 36928 // normal 36929 36930 normals.push( 0, sign, 0 ); 36931 36932 // uv 36933 36934 uv.x = ( cosTheta * 0.5 ) + 0.5; 36935 uv.y = ( sinTheta * 0.5 * sign ) + 0.5; 36936 uvs.push( uv.x, uv.y ); 36937 36938 // increase index 36939 36940 index ++; 36941 36942 } 36943 36944 // generate indices 36945 36946 for ( let x = 0; x < radialSegments; x ++ ) { 36947 36948 const c = centerIndexStart + x; 36949 const i = centerIndexEnd + x; 36950 36951 if ( top === true ) { 36952 36953 // face top 36954 36955 indices.push( i, i + 1, c ); 36956 36957 } else { 36958 36959 // face bottom 36960 36961 indices.push( i + 1, i, c ); 36962 36963 } 36964 36965 groupCount += 3; 36966 36967 } 36968 36969 // add a group to the geometry. this will ensure multi material support 36970 36971 scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); 36972 36973 // calculate new start value for groups 36974 36975 groupStart += groupCount; 36976 36977 } 36978 36979 } 36980 36981 copy( source ) { 36982 36983 super.copy( source ); 36984 36985 this.parameters = Object.assign( {}, source.parameters ); 36986 36987 return this; 36988 36989 } 36990 36991 static fromJSON( data ) { 36992 36993 return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); 36994 36995 } 36996 36997} 36998 36999class ConeGeometry extends CylinderGeometry { 37000 37001 constructor( radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { 37002 37003 super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); 37004 37005 this.type = 'ConeGeometry'; 37006 37007 this.parameters = { 37008 radius: radius, 37009 height: height, 37010 radialSegments: radialSegments, 37011 heightSegments: heightSegments, 37012 openEnded: openEnded, 37013 thetaStart: thetaStart, 37014 thetaLength: thetaLength 37015 }; 37016 37017 } 37018 37019 static fromJSON( data ) { 37020 37021 return new ConeGeometry( data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); 37022 37023 } 37024 37025} 37026 37027class PolyhedronGeometry extends BufferGeometry { 37028 37029 constructor( vertices = [], indices = [], radius = 1, detail = 0 ) { 37030 37031 super(); 37032 37033 this.type = 'PolyhedronGeometry'; 37034 37035 this.parameters = { 37036 vertices: vertices, 37037 indices: indices, 37038 radius: radius, 37039 detail: detail 37040 }; 37041 37042 // default buffer data 37043 37044 const vertexBuffer = []; 37045 const uvBuffer = []; 37046 37047 // the subdivision creates the vertex buffer data 37048 37049 subdivide( detail ); 37050 37051 // all vertices should lie on a conceptual sphere with a given radius 37052 37053 applyRadius( radius ); 37054 37055 // finally, create the uv data 37056 37057 generateUVs(); 37058 37059 // build non-indexed geometry 37060 37061 this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) ); 37062 this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) ); 37063 this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) ); 37064 37065 if ( detail === 0 ) { 37066 37067 this.computeVertexNormals(); // flat normals 37068 37069 } else { 37070 37071 this.normalizeNormals(); // smooth normals 37072 37073 } 37074 37075 // helper functions 37076 37077 function subdivide( detail ) { 37078 37079 const a = new Vector3(); 37080 const b = new Vector3(); 37081 const c = new Vector3(); 37082 37083 // iterate over all faces and apply a subdivision with the given detail value 37084 37085 for ( let i = 0; i < indices.length; i += 3 ) { 37086 37087 // get the vertices of the face 37088 37089 getVertexByIndex( indices[ i + 0 ], a ); 37090 getVertexByIndex( indices[ i + 1 ], b ); 37091 getVertexByIndex( indices[ i + 2 ], c ); 37092 37093 // perform subdivision 37094 37095 subdivideFace( a, b, c, detail ); 37096 37097 } 37098 37099 } 37100 37101 function subdivideFace( a, b, c, detail ) { 37102 37103 const cols = detail + 1; 37104 37105 // we use this multidimensional array as a data structure for creating the subdivision 37106 37107 const v = []; 37108 37109 // construct all of the vertices for this subdivision 37110 37111 for ( let i = 0; i <= cols; i ++ ) { 37112 37113 v[ i ] = []; 37114 37115 const aj = a.clone().lerp( c, i / cols ); 37116 const bj = b.clone().lerp( c, i / cols ); 37117 37118 const rows = cols - i; 37119 37120 for ( let j = 0; j <= rows; j ++ ) { 37121 37122 if ( j === 0 && i === cols ) { 37123 37124 v[ i ][ j ] = aj; 37125 37126 } else { 37127 37128 v[ i ][ j ] = aj.clone().lerp( bj, j / rows ); 37129 37130 } 37131 37132 } 37133 37134 } 37135 37136 // construct all of the faces 37137 37138 for ( let i = 0; i < cols; i ++ ) { 37139 37140 for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) { 37141 37142 const k = Math.floor( j / 2 ); 37143 37144 if ( j % 2 === 0 ) { 37145 37146 pushVertex( v[ i ][ k + 1 ] ); 37147 pushVertex( v[ i + 1 ][ k ] ); 37148 pushVertex( v[ i ][ k ] ); 37149 37150 } else { 37151 37152 pushVertex( v[ i ][ k + 1 ] ); 37153 pushVertex( v[ i + 1 ][ k + 1 ] ); 37154 pushVertex( v[ i + 1 ][ k ] ); 37155 37156 } 37157 37158 } 37159 37160 } 37161 37162 } 37163 37164 function applyRadius( radius ) { 37165 37166 const vertex = new Vector3(); 37167 37168 // iterate over the entire buffer and apply the radius to each vertex 37169 37170 for ( let i = 0; i < vertexBuffer.length; i += 3 ) { 37171 37172 vertex.x = vertexBuffer[ i + 0 ]; 37173 vertex.y = vertexBuffer[ i + 1 ]; 37174 vertex.z = vertexBuffer[ i + 2 ]; 37175 37176 vertex.normalize().multiplyScalar( radius ); 37177 37178 vertexBuffer[ i + 0 ] = vertex.x; 37179 vertexBuffer[ i + 1 ] = vertex.y; 37180 vertexBuffer[ i + 2 ] = vertex.z; 37181 37182 } 37183 37184 } 37185 37186 function generateUVs() { 37187 37188 const vertex = new Vector3(); 37189 37190 for ( let i = 0; i < vertexBuffer.length; i += 3 ) { 37191 37192 vertex.x = vertexBuffer[ i + 0 ]; 37193 vertex.y = vertexBuffer[ i + 1 ]; 37194 vertex.z = vertexBuffer[ i + 2 ]; 37195 37196 const u = azimuth( vertex ) / 2 / Math.PI + 0.5; 37197 const v = inclination( vertex ) / Math.PI + 0.5; 37198 uvBuffer.push( u, 1 - v ); 37199 37200 } 37201 37202 correctUVs(); 37203 37204 correctSeam(); 37205 37206 } 37207 37208 function correctSeam() { 37209 37210 // handle case when face straddles the seam, see #3269 37211 37212 for ( let i = 0; i < uvBuffer.length; i += 6 ) { 37213 37214 // uv data of a single face 37215 37216 const x0 = uvBuffer[ i + 0 ]; 37217 const x1 = uvBuffer[ i + 2 ]; 37218 const x2 = uvBuffer[ i + 4 ]; 37219 37220 const max = Math.max( x0, x1, x2 ); 37221 const min = Math.min( x0, x1, x2 ); 37222 37223 // 0.9 is somewhat arbitrary 37224 37225 if ( max > 0.9 && min < 0.1 ) { 37226 37227 if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1; 37228 if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1; 37229 if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1; 37230 37231 } 37232 37233 } 37234 37235 } 37236 37237 function pushVertex( vertex ) { 37238 37239 vertexBuffer.push( vertex.x, vertex.y, vertex.z ); 37240 37241 } 37242 37243 function getVertexByIndex( index, vertex ) { 37244 37245 const stride = index * 3; 37246 37247 vertex.x = vertices[ stride + 0 ]; 37248 vertex.y = vertices[ stride + 1 ]; 37249 vertex.z = vertices[ stride + 2 ]; 37250 37251 } 37252 37253 function correctUVs() { 37254 37255 const a = new Vector3(); 37256 const b = new Vector3(); 37257 const c = new Vector3(); 37258 37259 const centroid = new Vector3(); 37260 37261 const uvA = new Vector2(); 37262 const uvB = new Vector2(); 37263 const uvC = new Vector2(); 37264 37265 for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) { 37266 37267 a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] ); 37268 b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] ); 37269 c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] ); 37270 37271 uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] ); 37272 uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] ); 37273 uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] ); 37274 37275 centroid.copy( a ).add( b ).add( c ).divideScalar( 3 ); 37276 37277 const azi = azimuth( centroid ); 37278 37279 correctUV( uvA, j + 0, a, azi ); 37280 correctUV( uvB, j + 2, b, azi ); 37281 correctUV( uvC, j + 4, c, azi ); 37282 37283 } 37284 37285 } 37286 37287 function correctUV( uv, stride, vector, azimuth ) { 37288 37289 if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) { 37290 37291 uvBuffer[ stride ] = uv.x - 1; 37292 37293 } 37294 37295 if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) { 37296 37297 uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5; 37298 37299 } 37300 37301 } 37302 37303 // Angle around the Y axis, counter-clockwise when looking from above. 37304 37305 function azimuth( vector ) { 37306 37307 return Math.atan2( vector.z, - vector.x ); 37308 37309 } 37310 37311 37312 // Angle above the XZ plane. 37313 37314 function inclination( vector ) { 37315 37316 return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) ); 37317 37318 } 37319 37320 } 37321 37322 copy( source ) { 37323 37324 super.copy( source ); 37325 37326 this.parameters = Object.assign( {}, source.parameters ); 37327 37328 return this; 37329 37330 } 37331 37332 static fromJSON( data ) { 37333 37334 return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details ); 37335 37336 } 37337 37338} 37339 37340class DodecahedronGeometry extends PolyhedronGeometry { 37341 37342 constructor( radius = 1, detail = 0 ) { 37343 37344 const t = ( 1 + Math.sqrt( 5 ) ) / 2; 37345 const r = 1 / t; 37346 37347 const vertices = [ 37348 37349 // (±1, ±1, ±1) 37350 - 1, - 1, - 1, - 1, - 1, 1, 37351 - 1, 1, - 1, - 1, 1, 1, 37352 1, - 1, - 1, 1, - 1, 1, 37353 1, 1, - 1, 1, 1, 1, 37354 37355 // (0, ±1/Ï, ±Ï) 37356 0, - r, - t, 0, - r, t, 37357 0, r, - t, 0, r, t, 37358 37359 // (±1/Ï, ±Ï, 0) 37360 - r, - t, 0, - r, t, 0, 37361 r, - t, 0, r, t, 0, 37362 37363 // (±Ï, 0, ±1/Ï) 37364 - t, 0, - r, t, 0, - r, 37365 - t, 0, r, t, 0, r 37366 ]; 37367 37368 const indices = [ 37369 3, 11, 7, 3, 7, 15, 3, 15, 13, 37370 7, 19, 17, 7, 17, 6, 7, 6, 15, 37371 17, 4, 8, 17, 8, 10, 17, 10, 6, 37372 8, 0, 16, 8, 16, 2, 8, 2, 10, 37373 0, 12, 1, 0, 1, 18, 0, 18, 16, 37374 6, 10, 2, 6, 2, 13, 6, 13, 15, 37375 2, 16, 18, 2, 18, 3, 2, 3, 13, 37376 18, 1, 9, 18, 9, 11, 18, 11, 3, 37377 4, 14, 12, 4, 12, 0, 4, 0, 8, 37378 11, 9, 5, 11, 5, 19, 11, 19, 7, 37379 19, 5, 14, 19, 14, 4, 19, 4, 17, 37380 1, 12, 14, 1, 14, 5, 1, 5, 9 37381 ]; 37382 37383 super( vertices, indices, radius, detail ); 37384 37385 this.type = 'DodecahedronGeometry'; 37386 37387 this.parameters = { 37388 radius: radius, 37389 detail: detail 37390 }; 37391 37392 } 37393 37394 static fromJSON( data ) { 37395 37396 return new DodecahedronGeometry( data.radius, data.detail ); 37397 37398 } 37399 37400} 37401 37402const _v0 = /*@__PURE__*/ new Vector3(); 37403const _v1$1 = /*@__PURE__*/ new Vector3(); 37404const _normal = /*@__PURE__*/ new Vector3(); 37405const _triangle = /*@__PURE__*/ new Triangle(); 37406 37407class EdgesGeometry extends BufferGeometry { 37408 37409 constructor( geometry = null, thresholdAngle = 1 ) { 37410 37411 super(); 37412 37413 this.type = 'EdgesGeometry'; 37414 37415 this.parameters = { 37416 geometry: geometry, 37417 thresholdAngle: thresholdAngle 37418 }; 37419 37420 if ( geometry !== null ) { 37421 37422 const precisionPoints = 4; 37423 const precision = Math.pow( 10, precisionPoints ); 37424 const thresholdDot = Math.cos( DEG2RAD * thresholdAngle ); 37425 37426 const indexAttr = geometry.getIndex(); 37427 const positionAttr = geometry.getAttribute( 'position' ); 37428 const indexCount = indexAttr ? indexAttr.count : positionAttr.count; 37429 37430 const indexArr = [ 0, 0, 0 ]; 37431 const vertKeys = [ 'a', 'b', 'c' ]; 37432 const hashes = new Array( 3 ); 37433 37434 const edgeData = {}; 37435 const vertices = []; 37436 for ( let i = 0; i < indexCount; i += 3 ) { 37437 37438 if ( indexAttr ) { 37439 37440 indexArr[ 0 ] = indexAttr.getX( i ); 37441 indexArr[ 1 ] = indexAttr.getX( i + 1 ); 37442 indexArr[ 2 ] = indexAttr.getX( i + 2 ); 37443 37444 } else { 37445 37446 indexArr[ 0 ] = i; 37447 indexArr[ 1 ] = i + 1; 37448 indexArr[ 2 ] = i + 2; 37449 37450 } 37451 37452 const { a, b, c } = _triangle; 37453 a.fromBufferAttribute( positionAttr, indexArr[ 0 ] ); 37454 b.fromBufferAttribute( positionAttr, indexArr[ 1 ] ); 37455 c.fromBufferAttribute( positionAttr, indexArr[ 2 ] ); 37456 _triangle.getNormal( _normal ); 37457 37458 // create hashes for the edge from the vertices 37459 hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`; 37460 hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`; 37461 hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`; 37462 37463 // skip degenerate triangles 37464 if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) { 37465 37466 continue; 37467 37468 } 37469 37470 // iterate over every edge 37471 for ( let j = 0; j < 3; j ++ ) { 37472 37473 // get the first and next vertex making up the edge 37474 const jNext = ( j + 1 ) % 3; 37475 const vecHash0 = hashes[ j ]; 37476 const vecHash1 = hashes[ jNext ]; 37477 const v0 = _triangle[ vertKeys[ j ] ]; 37478 const v1 = _triangle[ vertKeys[ jNext ] ]; 37479 37480 const hash = `${ vecHash0 }_${ vecHash1 }`; 37481 const reverseHash = `${ vecHash1 }_${ vecHash0 }`; 37482 37483 if ( reverseHash in edgeData && edgeData[ reverseHash ] ) { 37484 37485 // if we found a sibling edge add it into the vertex array if 37486 // it meets the angle threshold and delete the edge from the map. 37487 if ( _normal.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) { 37488 37489 vertices.push( v0.x, v0.y, v0.z ); 37490 vertices.push( v1.x, v1.y, v1.z ); 37491 37492 } 37493 37494 edgeData[ reverseHash ] = null; 37495 37496 } else if ( ! ( hash in edgeData ) ) { 37497 37498 // if we've already got an edge here then skip adding a new one 37499 edgeData[ hash ] = { 37500 37501 index0: indexArr[ j ], 37502 index1: indexArr[ jNext ], 37503 normal: _normal.clone(), 37504 37505 }; 37506 37507 } 37508 37509 } 37510 37511 } 37512 37513 // iterate over all remaining, unmatched edges and add them to the vertex array 37514 for ( const key in edgeData ) { 37515 37516 if ( edgeData[ key ] ) { 37517 37518 const { index0, index1 } = edgeData[ key ]; 37519 _v0.fromBufferAttribute( positionAttr, index0 ); 37520 _v1$1.fromBufferAttribute( positionAttr, index1 ); 37521 37522 vertices.push( _v0.x, _v0.y, _v0.z ); 37523 vertices.push( _v1$1.x, _v1$1.y, _v1$1.z ); 37524 37525 } 37526 37527 } 37528 37529 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 37530 37531 } 37532 37533 } 37534 37535 copy( source ) { 37536 37537 super.copy( source ); 37538 37539 this.parameters = Object.assign( {}, source.parameters ); 37540 37541 return this; 37542 37543 } 37544 37545} 37546 37547class Shape extends Path { 37548 37549 constructor( points ) { 37550 37551 super( points ); 37552 37553 this.uuid = generateUUID(); 37554 37555 this.type = 'Shape'; 37556 37557 this.holes = []; 37558 37559 } 37560 37561 getPointsHoles( divisions ) { 37562 37563 const holesPts = []; 37564 37565 for ( let i = 0, l = this.holes.length; i < l; i ++ ) { 37566 37567 holesPts[ i ] = this.holes[ i ].getPoints( divisions ); 37568 37569 } 37570 37571 return holesPts; 37572 37573 } 37574 37575 // get points of shape and holes (keypoints based on segments parameter) 37576 37577 extractPoints( divisions ) { 37578 37579 return { 37580 37581 shape: this.getPoints( divisions ), 37582 holes: this.getPointsHoles( divisions ) 37583 37584 }; 37585 37586 } 37587 37588 copy( source ) { 37589 37590 super.copy( source ); 37591 37592 this.holes = []; 37593 37594 for ( let i = 0, l = source.holes.length; i < l; i ++ ) { 37595 37596 const hole = source.holes[ i ]; 37597 37598 this.holes.push( hole.clone() ); 37599 37600 } 37601 37602 return this; 37603 37604 } 37605 37606 toJSON() { 37607 37608 const data = super.toJSON(); 37609 37610 data.uuid = this.uuid; 37611 data.holes = []; 37612 37613 for ( let i = 0, l = this.holes.length; i < l; i ++ ) { 37614 37615 const hole = this.holes[ i ]; 37616 data.holes.push( hole.toJSON() ); 37617 37618 } 37619 37620 return data; 37621 37622 } 37623 37624 fromJSON( json ) { 37625 37626 super.fromJSON( json ); 37627 37628 this.uuid = json.uuid; 37629 this.holes = []; 37630 37631 for ( let i = 0, l = json.holes.length; i < l; i ++ ) { 37632 37633 const hole = json.holes[ i ]; 37634 this.holes.push( new Path().fromJSON( hole ) ); 37635 37636 } 37637 37638 return this; 37639 37640 } 37641 37642} 37643 37644/** 37645 * Port from https://github.com/mapbox/earcut (v2.2.4) 37646 */ 37647 37648const Earcut = { 37649 37650 triangulate: function ( data, holeIndices, dim = 2 ) { 37651 37652 const hasHoles = holeIndices && holeIndices.length; 37653 const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length; 37654 let outerNode = linkedList( data, 0, outerLen, dim, true ); 37655 const triangles = []; 37656 37657 if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles; 37658 37659 let minX, minY, maxX, maxY, x, y, invSize; 37660 37661 if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim ); 37662 37663 // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox 37664 if ( data.length > 80 * dim ) { 37665 37666 minX = maxX = data[ 0 ]; 37667 minY = maxY = data[ 1 ]; 37668 37669 for ( let i = dim; i < outerLen; i += dim ) { 37670 37671 x = data[ i ]; 37672 y = data[ i + 1 ]; 37673 if ( x < minX ) minX = x; 37674 if ( y < minY ) minY = y; 37675 if ( x > maxX ) maxX = x; 37676 if ( y > maxY ) maxY = y; 37677 37678 } 37679 37680 // minX, minY and invSize are later used to transform coords into integers for z-order calculation 37681 invSize = Math.max( maxX - minX, maxY - minY ); 37682 invSize = invSize !== 0 ? 32767 / invSize : 0; 37683 37684 } 37685 37686 earcutLinked( outerNode, triangles, dim, minX, minY, invSize, 0 ); 37687 37688 return triangles; 37689 37690 } 37691 37692}; 37693 37694// create a circular doubly linked list from polygon points in the specified winding order 37695function linkedList( data, start, end, dim, clockwise ) { 37696 37697 let i, last; 37698 37699 if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) { 37700 37701 for ( i = start; i < end;
vendor: 10,405 bytes, lines 37701-38174
37701 i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); 37702 37703 } else { 37704 37705 for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); 37706 37707 } 37708 37709 if ( last && equals( last, last.next ) ) { 37710 37711 removeNode( last ); 37712 last = last.next; 37713 37714 } 37715 37716 return last; 37717 37718} 37719 37720// eliminate colinear or duplicate points 37721function filterPoints( start, end ) { 37722 37723 if ( ! start ) return start; 37724 if ( ! end ) end = start; 37725 37726 let p = start, 37727 again; 37728 do { 37729 37730 again = false; 37731 37732 if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) { 37733 37734 removeNode( p ); 37735 p = end = p.prev; 37736 if ( p === p.next ) break; 37737 again = true; 37738 37739 } else { 37740 37741 p = p.next; 37742 37743 } 37744 37745 } while ( again || p !== end ); 37746 37747 return end; 37748 37749} 37750 37751// main ear slicing loop which triangulates a polygon (given as a linked list) 37752function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) { 37753 37754 if ( ! ear ) return; 37755 37756 // interlink polygon nodes in z-order 37757 if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize ); 37758 37759 let stop = ear, 37760 prev, next; 37761 37762 // iterate through ears, slicing them one by one 37763 while ( ear.prev !== ear.next ) { 37764 37765 prev = ear.prev; 37766 next = ear.next; 37767 37768 if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) { 37769 37770 // cut off the triangle 37771 triangles.push( prev.i / dim | 0 ); 37772 triangles.push( ear.i / dim | 0 ); 37773 triangles.push( next.i / dim | 0 ); 37774 37775 removeNode( ear ); 37776 37777 // skipping the next vertex leads to less sliver triangles 37778 ear = next.next; 37779 stop = next.next; 37780 37781 continue; 37782 37783 } 37784 37785 ear = next; 37786 37787 // if we looped through the whole remaining polygon and can't find any more ears 37788 if ( ear === stop ) { 37789 37790 // try filtering points and slicing again 37791 if ( ! pass ) { 37792 37793 earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 ); 37794 37795 // if this didn't work, try curing all small self-intersections locally 37796 37797 } else if ( pass === 1 ) { 37798 37799 ear = cureLocalIntersections( filterPoints( ear ), triangles, dim ); 37800 earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 ); 37801 37802 // as a last resort, try splitting the remaining polygon into two 37803 37804 } else if ( pass === 2 ) { 37805 37806 splitEarcut( ear, triangles, dim, minX, minY, invSize ); 37807 37808 } 37809 37810 break; 37811 37812 } 37813 37814 } 37815 37816} 37817 37818// check whether a polygon node forms a valid ear with adjacent nodes 37819function isEar( ear ) { 37820 37821 const a = ear.prev, 37822 b = ear, 37823 c = ear.next; 37824 37825 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear 37826 37827 // now make sure we don't have other points inside the potential ear 37828 const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; 37829 37830 // triangle bbox; min & max are calculated like this for speed 37831 const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ), 37832 y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ), 37833 x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ), 37834 y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy ); 37835 37836 let p = c.next; 37837 while ( p !== a ) { 37838 37839 if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && 37840 pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && 37841 area( p.prev, p, p.next ) >= 0 ) return false; 37842 p = p.next; 37843 37844 } 37845 37846 return true; 37847 37848} 37849 37850function isEarHashed( ear, minX, minY, invSize ) { 37851 37852 const a = ear.prev, 37853 b = ear, 37854 c = ear.next; 37855 37856 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear 37857 37858 const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; 37859 37860 // triangle bbox; min & max are calculated like this for speed 37861 const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ), 37862 y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ), 37863 x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ), 37864 y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy ); 37865 37866 // z-order range for the current triangle bbox; 37867 const minZ = zOrder( x0, y0, minX, minY, invSize ), 37868 maxZ = zOrder( x1, y1, minX, minY, invSize ); 37869 37870 let p = ear.prevZ, 37871 n = ear.nextZ; 37872 37873 // look for points inside the triangle in both directions 37874 while ( p && p.z >= minZ && n && n.z <= maxZ ) { 37875 37876 if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && 37877 pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false; 37878 p = p.prevZ; 37879 37880 if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && 37881 pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false; 37882 n = n.nextZ; 37883 37884 } 37885 37886 // look for remaining points in decreasing z-order 37887 while ( p && p.z >= minZ ) { 37888 37889 if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && 37890 pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false; 37891 p = p.prevZ; 37892 37893 } 37894 37895 // look for remaining points in increasing z-order 37896 while ( n && n.z <= maxZ ) { 37897 37898 if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && 37899 pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false; 37900 n = n.nextZ; 37901 37902 } 37903 37904 return true; 37905 37906} 37907 37908// go through all polygon nodes and cure small local self-intersections 37909function cureLocalIntersections( start, triangles, dim ) { 37910 37911 let p = start; 37912 do { 37913 37914 const a = p.prev, 37915 b = p.next.next; 37916 37917 if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) { 37918 37919 triangles.push( a.i / dim | 0 ); 37920 triangles.push( p.i / dim | 0 ); 37921 triangles.push( b.i / dim | 0 ); 37922 37923 // remove two nodes involved 37924 removeNode( p ); 37925 removeNode( p.next ); 37926 37927 p = start = b; 37928 37929 } 37930 37931 p = p.next; 37932 37933 } while ( p !== start ); 37934 37935 return filterPoints( p ); 37936 37937} 37938 37939// try splitting polygon into two and triangulate them independently 37940function splitEarcut( start, triangles, dim, minX, minY, invSize ) { 37941 37942 // look for a valid diagonal that divides the polygon into two 37943 let a = start; 37944 do { 37945 37946 let b = a.next.next; 37947 while ( b !== a.prev ) { 37948 37949 if ( a.i !== b.i && isValidDiagonal( a, b ) ) { 37950 37951 // split the polygon in two by the diagonal 37952 let c = splitPolygon( a, b ); 37953 37954 // filter colinear points around the cuts 37955 a = filterPoints( a, a.next ); 37956 c = filterPoints( c, c.next ); 37957 37958 // run earcut on each half 37959 earcutLinked( a, triangles, dim, minX, minY, invSize, 0 ); 37960 earcutLinked( c, triangles, dim, minX, minY, invSize, 0 ); 37961 return; 37962 37963 } 37964 37965 b = b.next; 37966 37967 } 37968 37969 a = a.next; 37970 37971 } while ( a !== start ); 37972 37973} 37974 37975// link every hole into the outer loop, producing a single-ring polygon without holes 37976function eliminateHoles( data, holeIndices, outerNode, dim ) { 37977 37978 const queue = []; 37979 let i, len, start, end, list; 37980 37981 for ( i = 0, len = holeIndices.length; i < len; i ++ ) { 37982 37983 start = holeIndices[ i ] * dim; 37984 end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length; 37985 list = linkedList( data, start, end, dim, false ); 37986 if ( list === list.next ) list.steiner = true; 37987 queue.push( getLeftmost( list ) ); 37988 37989 } 37990 37991 queue.sort( compareX ); 37992 37993 // process holes from left to right 37994 for ( i = 0; i < queue.length; i ++ ) { 37995 37996 outerNode = eliminateHole( queue[ i ], outerNode ); 37997 37998 } 37999 38000 return outerNode; 38001 38002} 38003 38004function compareX( a, b ) { 38005 38006 return a.x - b.x; 38007 38008} 38009 38010// find a bridge between vertices that connects hole with an outer ring and link it 38011function eliminateHole( hole, outerNode ) { 38012 38013 const bridge = findHoleBridge( hole, outerNode ); 38014 if ( ! bridge ) { 38015 38016 return outerNode; 38017 38018 } 38019 38020 const bridgeReverse = splitPolygon( bridge, hole ); 38021 38022 // filter collinear points around the cuts 38023 filterPoints( bridgeReverse, bridgeReverse.next ); 38024 return filterPoints( bridge, bridge.next ); 38025 38026} 38027 38028// David Eberly's algorithm for finding a bridge between hole and outer polygon 38029function findHoleBridge( hole, outerNode ) { 38030 38031 let p = outerNode, 38032 qx = - Infinity, 38033 m; 38034 38035 const hx = hole.x, hy = hole.y; 38036 38037 // find a segment intersected by a ray from the hole's leftmost point to the left; 38038 // segment's endpoint with lesser x will be potential connection point 38039 do { 38040 38041 if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) { 38042 38043 const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y ); 38044 if ( x <= hx && x > qx ) { 38045 38046 qx = x; 38047 m = p.x < p.next.x ? p : p.next; 38048 if ( x === hx ) return m; // hole touches outer segment; pick leftmost endpoint 38049 38050 } 38051 38052 } 38053 38054 p = p.next; 38055 38056 } while ( p !== outerNode ); 38057 38058 if ( ! m ) return null; 38059 38060 // look for points inside the triangle of hole point, segment intersection and endpoint; 38061 // if there are no points found, we have a valid connection; 38062 // otherwise choose the point of the minimum angle with the ray as connection point 38063 38064 const stop = m, 38065 mx = m.x, 38066 my = m.y; 38067 let tanMin = Infinity, tan; 38068 38069 p = m; 38070 38071 do { 38072 38073 if ( hx >= p.x && p.x >= mx && hx !== p.x && 38074 pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) { 38075 38076 tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential 38077 38078 if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) { 38079 38080 m = p; 38081 tanMin = tan; 38082 38083 } 38084 38085 } 38086 38087 p = p.next; 38088 38089 } while ( p !== stop ); 38090 38091 return m; 38092 38093} 38094 38095// whether sector in vertex m contains sector in vertex p in the same coordinates 38096function sectorContainsSector( m, p ) { 38097 38098 return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0; 38099 38100} 38101 38102// interlink polygon nodes in z-order 38103function indexCurve( start, minX, minY, invSize ) { 38104 38105 let p = start; 38106 do { 38107 38108 if ( p.z === 0 ) p.z = zOrder( p.x, p.y, minX, minY, invSize ); 38109 p.prevZ = p.prev; 38110 p.nextZ = p.next; 38111 p = p.next; 38112 38113 } while ( p !== start ); 38114 38115 p.prevZ.nextZ = null; 38116 p.prevZ = null; 38117 38118 sortLinked( p ); 38119 38120} 38121 38122// Simon Tatham's linked list merge sort algorithm 38123// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html 38124function sortLinked( list ) { 38125 38126 let i, p, q, e, tail, numMerges, pSize, qSize, 38127 inSize = 1; 38128 38129 do { 38130 38131 p = list; 38132 list = null; 38133 tail = null; 38134 numMerges = 0; 38135 38136 while ( p ) { 38137 38138 numMerges ++; 38139 q = p; 38140 pSize = 0; 38141 for ( i = 0; i < inSize; i ++ ) { 38142 38143 pSize ++; 38144 q = q.nextZ; 38145 if ( ! q ) break; 38146 38147 } 38148 38149 qSize = inSize; 38150 38151 while ( pSize > 0 || ( qSize > 0 && q ) ) { 38152 38153 if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) { 38154 38155 e = p; 38156 p = p.nextZ; 38157 pSize --; 38158 38159 } else { 38160 38161 e = q; 38162 q = q.nextZ; 38163 qSize --; 38164 38165 } 38166 38167 if ( tail ) tail.nextZ = e; 38168 else list = e; 38169 38170 e.prevZ = tail; 38171 tail = e; 38172 38173 } 38174
vendor: 9,707 bytes, lines 38175-38602
38175 p = q; 38176 38177 } 38178 38179 tail.nextZ = null; 38180 inSize *= 2; 38181 38182 } while ( numMerges > 1 ); 38183 38184 return list; 38185 38186} 38187 38188// z-order of a point given coords and inverse of the longer side of data bbox 38189function zOrder( x, y, minX, minY, invSize ) { 38190 38191 // coords are transformed into non-negative 15-bit integer range 38192 x = ( x - minX ) * invSize | 0; 38193 y = ( y - minY ) * invSize | 0; 38194 38195 x = ( x | ( x << 8 ) ) & 0x00FF00FF; 38196 x = ( x | ( x << 4 ) ) & 0x0F0F0F0F; 38197 x = ( x | ( x << 2 ) ) & 0x33333333; 38198 x = ( x | ( x << 1 ) ) & 0x55555555; 38199 38200 y = ( y | ( y << 8 ) ) & 0x00FF00FF; 38201 y = ( y | ( y << 4 ) ) & 0x0F0F0F0F; 38202 y = ( y | ( y << 2 ) ) & 0x33333333; 38203 y = ( y | ( y << 1 ) ) & 0x55555555; 38204 38205 return x | ( y << 1 ); 38206 38207} 38208 38209// find the leftmost node of a polygon ring 38210function getLeftmost( start ) { 38211 38212 let p = start, 38213 leftmost = start; 38214 do { 38215 38216 if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p; 38217 p = p.next; 38218 38219 } while ( p !== start ); 38220 38221 return leftmost; 38222 38223} 38224 38225// check if a point lies within a convex triangle 38226function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) { 38227 38228 return ( cx - px ) * ( ay - py ) >= ( ax - px ) * ( cy - py ) && 38229 ( ax - px ) * ( by - py ) >= ( bx - px ) * ( ay - py ) && 38230 ( bx - px ) * ( cy - py ) >= ( cx - px ) * ( by - py ); 38231 38232} 38233 38234// check if a diagonal between two polygon nodes is valid (lies in polygon interior) 38235function isValidDiagonal( a, b ) { 38236 38237 return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges 38238 ( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible 38239 ( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors 38240 equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case 38241 38242} 38243 38244// signed area of a triangle 38245function area( p, q, r ) { 38246 38247 return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y ); 38248 38249} 38250 38251// check if two points are equal 38252function equals( p1, p2 ) { 38253 38254 return p1.x === p2.x && p1.y === p2.y; 38255 38256} 38257 38258// check if two segments intersect 38259function intersects( p1, q1, p2, q2 ) { 38260 38261 const o1 = sign( area( p1, q1, p2 ) ); 38262 const o2 = sign( area( p1, q1, q2 ) ); 38263 const o3 = sign( area( p2, q2, p1 ) ); 38264 const o4 = sign( area( p2, q2, q1 ) ); 38265 38266 if ( o1 !== o2 && o3 !== o4 ) return true; // general case 38267 38268 if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1 38269 if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1 38270 if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2 38271 if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2 38272 38273 return false; 38274 38275} 38276 38277// for collinear points p, q, r, check if point q lies on segment pr 38278function onSegment( p, q, r ) { 38279 38280 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 ); 38281 38282} 38283 38284function sign( num ) { 38285 38286 return num > 0 ? 1 : num < 0 ? - 1 : 0; 38287 38288} 38289 38290// check if a polygon diagonal intersects any polygon segments 38291function intersectsPolygon( a, b ) { 38292 38293 let p = a; 38294 do { 38295 38296 if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && 38297 intersects( p, p.next, a, b ) ) return true; 38298 p = p.next; 38299 38300 } while ( p !== a ); 38301 38302 return false; 38303 38304} 38305 38306// check if a polygon diagonal is locally inside the polygon 38307function locallyInside( a, b ) { 38308 38309 return area( a.prev, a, a.next ) < 0 ? 38310 area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 : 38311 area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0; 38312 38313} 38314 38315// check if the middle point of a polygon diagonal is inside the polygon 38316function middleInside( a, b ) { 38317 38318 let p = a, 38319 inside = false; 38320 const px = ( a.x + b.x ) / 2, 38321 py = ( a.y + b.y ) / 2; 38322 do { 38323 38324 if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y && 38325 ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) 38326 inside = ! inside; 38327 p = p.next; 38328 38329 } while ( p !== a ); 38330 38331 return inside; 38332 38333} 38334 38335// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; 38336// if one belongs to the outer ring and another to a hole, it merges it into a single ring 38337function splitPolygon( a, b ) { 38338 38339 const a2 = new Node( a.i, a.x, a.y ), 38340 b2 = new Node( b.i, b.x, b.y ), 38341 an = a.next, 38342 bp = b.prev; 38343 38344 a.next = b; 38345 b.prev = a; 38346 38347 a2.next = an; 38348 an.prev = a2; 38349 38350 b2.next = a2; 38351 a2.prev = b2; 38352 38353 bp.next = b2; 38354 b2.prev = bp; 38355 38356 return b2; 38357 38358} 38359 38360// create a node and optionally link it with previous one (in a circular doubly linked list) 38361function insertNode( i, x, y, last ) { 38362 38363 const p = new Node( i, x, y ); 38364 38365 if ( ! last ) { 38366 38367 p.prev = p; 38368 p.next = p; 38369 38370 } else { 38371 38372 p.next = last.next; 38373 p.prev = last; 38374 last.next.prev = p; 38375 last.next = p; 38376 38377 } 38378 38379 return p; 38380 38381} 38382 38383function removeNode( p ) { 38384 38385 p.next.prev = p.prev; 38386 p.prev.next = p.next; 38387 38388 if ( p.prevZ ) p.prevZ.nextZ = p.nextZ; 38389 if ( p.nextZ ) p.nextZ.prevZ = p.prevZ; 38390 38391} 38392 38393function Node( i, x, y ) { 38394 38395 // vertex index in coordinates array 38396 this.i = i; 38397 38398 // vertex coordinates 38399 this.x = x; 38400 this.y = y; 38401 38402 // previous and next vertex nodes in a polygon ring 38403 this.prev = null; 38404 this.next = null; 38405 38406 // z-order curve value 38407 this.z = 0; 38408 38409 // previous and next nodes in z-order 38410 this.prevZ = null; 38411 this.nextZ = null; 38412 38413 // indicates whether this is a steiner point 38414 this.steiner = false; 38415 38416} 38417 38418function signedArea( data, start, end, dim ) { 38419 38420 let sum = 0; 38421 for ( let i = start, j = end - dim; i < end; i += dim ) { 38422 38423 sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] ); 38424 j = i; 38425 38426 } 38427 38428 return sum; 38429 38430} 38431 38432class ShapeUtils { 38433 38434 // calculate area of the contour polygon 38435 38436 static area( contour ) { 38437 38438 const n = contour.length; 38439 let a = 0.0; 38440 38441 for ( let p = n - 1, q = 0; q < n; p = q ++ ) { 38442 38443 a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y; 38444 38445 } 38446 38447 return a * 0.5; 38448 38449 } 38450 38451 static isClockWise( pts ) { 38452 38453 return ShapeUtils.area( pts ) < 0; 38454 38455 } 38456 38457 static triangulateShape( contour, holes ) { 38458 38459 const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ] 38460 const holeIndices = []; // array of hole indices 38461 const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ] 38462 38463 removeDupEndPts( contour ); 38464 addContour( vertices, contour ); 38465 38466 // 38467 38468 let holeIndex = contour.length; 38469 38470 holes.forEach( removeDupEndPts ); 38471 38472 for ( let i = 0; i < holes.length; i ++ ) { 38473 38474 holeIndices.push( holeIndex ); 38475 holeIndex += holes[ i ].length; 38476 addContour( vertices, holes[ i ] ); 38477 38478 } 38479 38480 // 38481 38482 const triangles = Earcut.triangulate( vertices, holeIndices ); 38483 38484 // 38485 38486 for ( let i = 0; i < triangles.length; i += 3 ) { 38487 38488 faces.push( triangles.slice( i, i + 3 ) ); 38489 38490 } 38491 38492 return faces; 38493 38494 } 38495 38496} 38497 38498function removeDupEndPts( points ) { 38499 38500 const l = points.length; 38501 38502 if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) { 38503 38504 points.pop(); 38505 38506 } 38507 38508} 38509 38510function addContour( vertices, contour ) { 38511 38512 for ( let i = 0; i < contour.length; i ++ ) { 38513 38514 vertices.push( contour[ i ].x ); 38515 vertices.push( contour[ i ].y ); 38516 38517 } 38518 38519} 38520 38521/** 38522 * Creates extruded geometry from a path shape. 38523 * 38524 * parameters = { 38525 * 38526 * curveSegments: <int>, // number of points on the curves 38527 * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too 38528 * depth: <float>, // Depth to extrude the shape 38529 * 38530 * bevelEnabled: <bool>, // turn on bevel 38531 * bevelThickness: <float>, // how deep into the original shape bevel goes 38532 * bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel 38533 * bevelOffset: <float>, // how far from shape outline does bevel start 38534 * bevelSegments: <int>, // number of bevel layers 38535 * 38536 * extrudePath: <THREE.Curve> // curve to extrude shape along 38537 * 38538 * UVGenerator: <Object> // object that provides UV generator functions 38539 * 38540 * } 38541 */ 38542 38543 38544class ExtrudeGeometry extends BufferGeometry { 38545 38546 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 = {} ) { 38547 38548 super(); 38549 38550 this.type = 'ExtrudeGeometry'; 38551 38552 this.parameters = { 38553 shapes: shapes, 38554 options: options 38555 }; 38556 38557 shapes = Array.isArray( shapes ) ? shapes : [ shapes ]; 38558 38559 const scope = this; 38560 38561 const verticesArray = []; 38562 const uvArray = []; 38563 38564 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 38565 38566 const shape = shapes[ i ]; 38567 addShape( shape ); 38568 38569 } 38570 38571 // build geometry 38572 38573 this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) ); 38574 this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) ); 38575 38576 this.computeVertexNormals(); 38577 38578 // functions 38579 38580 function addShape( shape ) { 38581 38582 const placeholder = []; 38583 38584 // options 38585 38586 const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12; 38587 const steps = options.steps !== undefined ? options.steps : 1; 38588 const depth = options.depth !== undefined ? options.depth : 1; 38589 38590 let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; 38591 let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2; 38592 let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1; 38593 let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0; 38594 let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3; 38595 38596 const extrudePath = options.extrudePath; 38597 38598 const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator; 38599 38600 // 38601 38602 let extrudePts, extrudeByPath = false;
vendor: 2,791 bytes, lines 38603-38716
38603 let splineTube, binormal, normal, position2; 38604 38605 if ( extrudePath ) { 38606 38607 extrudePts = extrudePath.getSpacedPoints( steps ); 38608 38609 extrudeByPath = true; 38610 bevelEnabled = false; // bevels not supported for path extrusion 38611 38612 // SETUP TNB variables 38613 38614 // TODO1 - have a .isClosed in spline? 38615 38616 splineTube = extrudePath.computeFrenetFrames( steps, false ); 38617 38618 // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length); 38619 38620 binormal = new Vector3(); 38621 normal = new Vector3(); 38622 position2 = new Vector3(); 38623 38624 } 38625 38626 // Safeguards if bevels are not enabled 38627 38628 if ( ! bevelEnabled ) { 38629 38630 bevelSegments = 0; 38631 bevelThickness = 0; 38632 bevelSize = 0; 38633 bevelOffset = 0; 38634 38635 } 38636 38637 // Variables initialization 38638 38639 const shapePoints = shape.extractPoints( curveSegments ); 38640 38641 let vertices = shapePoints.shape; 38642 const holes = shapePoints.holes; 38643 38644 const reverse = ! ShapeUtils.isClockWise( vertices ); 38645 38646 if ( reverse ) { 38647 38648 vertices = vertices.reverse(); 38649 38650 // Maybe we should also check if holes are in the opposite direction, just to be safe ... 38651 38652 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 38653 38654 const ahole = holes[ h ]; 38655 38656 if ( ShapeUtils.isClockWise( ahole ) ) { 38657 38658 holes[ h ] = ahole.reverse(); 38659 38660 } 38661 38662 } 38663 38664 } 38665 38666 38667 const faces = ShapeUtils.triangulateShape( vertices, holes ); 38668 38669 /* Vertices */ 38670 38671 const contour = vertices; // vertices has all points but contour has only points of circumference 38672 38673 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 38674 38675 const ahole = holes[ h ]; 38676 38677 vertices = vertices.concat( ahole ); 38678 38679 } 38680 38681 38682 function scalePt2( pt, vec, size ) { 38683 38684 if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' ); 38685 38686 return pt.clone().addScaledVector( vec, size ); 38687 38688 } 38689 38690 const vlen = vertices.length, flen = faces.length; 38691 38692 38693 // Find directions for point movement 38694 38695 38696 function getBevelVec( inPt, inPrev, inNext ) { 38697 38698 // computes for inPt the corresponding point inPt' on a new contour 38699 // shifted by 1 unit (length of normalized vector) to the left 38700 // if we walk along contour clockwise, this new contour is outside the old one 38701 // 38702 // inPt' is the intersection of the two lines parallel to the two 38703 // adjacent edges of inPt at a distance of 1 unit on the left side. 38704 38705 let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt 38706 38707 // good reading for geometry algorithms (here: line-line intersection) 38708 // http://geomalgorithms.com/a05-_intersect-1.html 38709 38710 const v_prev_x = inPt.x - inPrev.x, 38711 v_prev_y = inPt.y - inPrev.y; 38712 const v_next_x = inNext.x - inPt.x, 38713 v_next_y = inNext.y - inPt.y; 38714 38715 const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y ); 38716
vendor: 17,452 bytes, lines 38717-39568
38717 // check for collinear edges 38718 const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x ); 38719 38720 if ( Math.abs( collinear0 ) > Number.EPSILON ) { 38721 38722 // not collinear 38723 38724 // length of vectors for normalizing 38725 38726 const v_prev_len = Math.sqrt( v_prev_lensq ); 38727 const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y ); 38728 38729 // shift adjacent points by unit vectors to the left 38730 38731 const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len ); 38732 const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len ); 38733 38734 const ptNextShift_x = ( inNext.x - v_next_y / v_next_len ); 38735 const ptNextShift_y = ( inNext.y + v_next_x / v_next_len ); 38736 38737 // scaling factor for v_prev to intersection point 38738 38739 const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y - 38740 ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) / 38741 ( v_prev_x * v_next_y - v_prev_y * v_next_x ); 38742 38743 // vector from inPt to intersection point 38744 38745 v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x ); 38746 v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y ); 38747 38748 // Don't normalize!, otherwise sharp corners become ugly 38749 // but prevent crazy spikes 38750 const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y ); 38751 if ( v_trans_lensq <= 2 ) { 38752 38753 return new Vector2( v_trans_x, v_trans_y ); 38754 38755 } else { 38756 38757 shrink_by = Math.sqrt( v_trans_lensq / 2 ); 38758 38759 } 38760 38761 } else { 38762 38763 // handle special case of collinear edges 38764 38765 let direction_eq = false; // assumes: opposite 38766 38767 if ( v_prev_x > Number.EPSILON ) { 38768 38769 if ( v_next_x > Number.EPSILON ) { 38770 38771 direction_eq = true; 38772 38773 } 38774 38775 } else { 38776 38777 if ( v_prev_x < - Number.EPSILON ) { 38778 38779 if ( v_next_x < - Number.EPSILON ) { 38780 38781 direction_eq = true; 38782 38783 } 38784 38785 } else { 38786 38787 if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) { 38788 38789 direction_eq = true; 38790 38791 } 38792 38793 } 38794 38795 } 38796 38797 if ( direction_eq ) { 38798 38799 // console.log("Warning: lines are a straight sequence"); 38800 v_trans_x = - v_prev_y; 38801 v_trans_y = v_prev_x; 38802 shrink_by = Math.sqrt( v_prev_lensq ); 38803 38804 } else { 38805 38806 // console.log("Warning: lines are a straight spike"); 38807 v_trans_x = v_prev_x; 38808 v_trans_y = v_prev_y; 38809 shrink_by = Math.sqrt( v_prev_lensq / 2 ); 38810 38811 } 38812 38813 } 38814 38815 return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by ); 38816 38817 } 38818 38819 38820 const contourMovements = []; 38821 38822 for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { 38823 38824 if ( j === il ) j = 0; 38825 if ( k === il ) k = 0; 38826 38827 // (j)---(i)---(k) 38828 // console.log('i,j,k', i, j , k) 38829 38830 contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); 38831 38832 } 38833 38834 const holesMovements = []; 38835 let oneHoleMovements, verticesMovements = contourMovements.concat(); 38836 38837 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 38838 38839 const ahole = holes[ h ]; 38840 38841 oneHoleMovements = []; 38842 38843 for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { 38844 38845 if ( j === il ) j = 0; 38846 if ( k === il ) k = 0; 38847 38848 // (j)---(i)---(k) 38849 oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] ); 38850 38851 } 38852 38853 holesMovements.push( oneHoleMovements ); 38854 verticesMovements = verticesMovements.concat( oneHoleMovements ); 38855 38856 } 38857 38858 38859 // Loop bevelSegments, 1 for the front, 1 for the back 38860 38861 for ( let b = 0; b < bevelSegments; b ++ ) { 38862 38863 //for ( b = bevelSegments; b > 0; b -- ) { 38864 38865 const t = b / bevelSegments; 38866 const z = bevelThickness * Math.cos( t * Math.PI / 2 ); 38867 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset; 38868 38869 // contract shape 38870 38871 for ( let i = 0, il = contour.length; i < il; i ++ ) { 38872 38873 const vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); 38874 38875 v( vert.x, vert.y, - z ); 38876 38877 } 38878 38879 // expand holes 38880 38881 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 38882 38883 const ahole = holes[ h ]; 38884 oneHoleMovements = holesMovements[ h ]; 38885 38886 for ( let i = 0, il = ahole.length; i < il; i ++ ) { 38887 38888 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); 38889 38890 v( vert.x, vert.y, - z ); 38891 38892 } 38893 38894 } 38895 38896 } 38897 38898 const bs = bevelSize + bevelOffset; 38899 38900 // Back facing vertices 38901 38902 for ( let i = 0; i < vlen; i ++ ) { 38903 38904 const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; 38905 38906 if ( ! extrudeByPath ) { 38907 38908 v( vert.x, vert.y, 0 ); 38909 38910 } else { 38911 38912 // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x ); 38913 38914 normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x ); 38915 binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y ); 38916 38917 position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal ); 38918 38919 v( position2.x, position2.y, position2.z ); 38920 38921 } 38922 38923 } 38924 38925 // Add stepped vertices... 38926 // Including front facing vertices 38927 38928 for ( let s = 1; s <= steps; s ++ ) { 38929 38930 for ( let i = 0; i < vlen; i ++ ) { 38931 38932 const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; 38933 38934 if ( ! extrudeByPath ) { 38935 38936 v( vert.x, vert.y, depth / steps * s ); 38937 38938 } else { 38939 38940 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x ); 38941 38942 normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x ); 38943 binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y ); 38944 38945 position2.copy( extrudePts[ s ] ).add( normal ).add( binormal ); 38946 38947 v( position2.x, position2.y, position2.z ); 38948 38949 } 38950 38951 } 38952 38953 } 38954 38955 38956 // Add bevel segments planes 38957 38958 //for ( b = 1; b <= bevelSegments; b ++ ) { 38959 for ( let b = bevelSegments - 1; b >= 0; b -- ) { 38960 38961 const t = b / bevelSegments; 38962 const z = bevelThickness * Math.cos( t * Math.PI / 2 ); 38963 const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset; 38964 38965 // contract shape 38966 38967 for ( let i = 0, il = contour.length; i < il; i ++ ) { 38968 38969 const vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); 38970 v( vert.x, vert.y, depth + z ); 38971 38972 } 38973 38974 // expand holes 38975 38976 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 38977 38978 const ahole = holes[ h ]; 38979 oneHoleMovements = holesMovements[ h ]; 38980 38981 for ( let i = 0, il = ahole.length; i < il; i ++ ) { 38982 38983 const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); 38984 38985 if ( ! extrudeByPath ) { 38986 38987 v( vert.x, vert.y, depth + z ); 38988 38989 } else { 38990 38991 v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z ); 38992 38993 } 38994 38995 } 38996 38997 } 38998 38999 } 39000 39001 /* Faces */ 39002 39003 // Top and bottom faces 39004 39005 buildLidFaces(); 39006 39007 // Sides faces 39008 39009 buildSideFaces(); 39010 39011 39012 ///// Internal functions 39013 39014 function buildLidFaces() { 39015 39016 const start = verticesArray.length / 3; 39017 39018 if ( bevelEnabled ) { 39019 39020 let layer = 0; // steps + 1 39021 let offset = vlen * layer; 39022 39023 // Bottom faces 39024 39025 for ( let i = 0; i < flen; i ++ ) { 39026 39027 const face = faces[ i ]; 39028 f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset ); 39029 39030 } 39031 39032 layer = steps + bevelSegments * 2; 39033 offset = vlen * layer; 39034 39035 // Top faces 39036 39037 for ( let i = 0; i < flen; i ++ ) { 39038 39039 const face = faces[ i ]; 39040 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset ); 39041 39042 } 39043 39044 } else { 39045 39046 // Bottom faces 39047 39048 for ( let i = 0; i < flen; i ++ ) { 39049 39050 const face = faces[ i ]; 39051 f3( face[ 2 ], face[ 1 ], face[ 0 ] ); 39052 39053 } 39054 39055 // Top faces 39056 39057 for ( let i = 0; i < flen; i ++ ) { 39058 39059 const face = faces[ i ]; 39060 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps ); 39061 39062 } 39063 39064 } 39065 39066 scope.addGroup( start, verticesArray.length / 3 - start, 0 ); 39067 39068 } 39069 39070 // Create faces for the z-sides of the shape 39071 39072 function buildSideFaces() { 39073 39074 const start = verticesArray.length / 3; 39075 let layeroffset = 0; 39076 sidewalls( contour, layeroffset ); 39077 layeroffset += contour.length; 39078 39079 for ( let h = 0, hl = holes.length; h < hl; h ++ ) { 39080 39081 const ahole = holes[ h ]; 39082 sidewalls( ahole, layeroffset ); 39083 39084 //, true 39085 layeroffset += ahole.length; 39086 39087 } 39088 39089 39090 scope.addGroup( start, verticesArray.length / 3 - start, 1 ); 39091 39092 39093 } 39094 39095 function sidewalls( contour, layeroffset ) { 39096 39097 let i = contour.length; 39098 39099 while ( -- i >= 0 ) { 39100 39101 const j = i; 39102 let k = i - 1; 39103 if ( k < 0 ) k = contour.length - 1; 39104 39105 //console.log('b', i,j, i-1, k,vertices.length); 39106 39107 for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) { 39108 39109 const slen1 = vlen * s; 39110 const slen2 = vlen * ( s + 1 ); 39111 39112 const a = layeroffset + j + slen1, 39113 b = layeroffset + k + slen1, 39114 c = layeroffset + k + slen2, 39115 d = layeroffset + j + slen2; 39116 39117 f4( a, b, c, d ); 39118 39119 } 39120 39121 } 39122 39123 } 39124 39125 function v( x, y, z ) { 39126 39127 placeholder.push( x ); 39128 placeholder.push( y ); 39129 placeholder.push( z ); 39130 39131 } 39132 39133 39134 function f3( a, b, c ) { 39135 39136 addVertex( a ); 39137 addVertex( b ); 39138 addVertex( c ); 39139 39140 const nextIndex = verticesArray.length / 3; 39141 const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); 39142 39143 addUV( uvs[ 0 ] ); 39144 addUV( uvs[ 1 ] ); 39145 addUV( uvs[ 2 ] ); 39146 39147 } 39148 39149 function f4( a, b, c, d ) { 39150 39151 addVertex( a ); 39152 addVertex( b ); 39153 addVertex( d ); 39154 39155 addVertex( b ); 39156 addVertex( c ); 39157 addVertex( d ); 39158 39159 39160 const nextIndex = verticesArray.length / 3; 39161 const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); 39162 39163 addUV( uvs[ 0 ] ); 39164 addUV( uvs[ 1 ] ); 39165 addUV( uvs[ 3 ] ); 39166 39167 addUV( uvs[ 1 ] ); 39168 addUV( uvs[ 2 ] ); 39169 addUV( uvs[ 3 ] ); 39170 39171 } 39172 39173 function addVertex( index ) { 39174 39175 verticesArray.push( placeholder[ index * 3 + 0 ] ); 39176 verticesArray.push( placeholder[ index * 3 + 1 ] ); 39177 verticesArray.push( placeholder[ index * 3 + 2 ] ); 39178 39179 } 39180 39181 39182 function addUV( vector2 ) { 39183 39184 uvArray.push( vector2.x ); 39185 uvArray.push( vector2.y ); 39186 39187 } 39188 39189 } 39190 39191 } 39192 39193 copy( source ) { 39194 39195 super.copy( source ); 39196 39197 this.parameters = Object.assign( {}, source.parameters ); 39198 39199 return this; 39200 39201 } 39202 39203 toJSON() { 39204 39205 const data = super.toJSON(); 39206 39207 const shapes = this.parameters.shapes; 39208 const options = this.parameters.options; 39209 39210 return toJSON$1( shapes, options, data ); 39211 39212 } 39213 39214 static fromJSON( data, shapes ) { 39215 39216 const geometryShapes = []; 39217 39218 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) { 39219 39220 const shape = shapes[ data.shapes[ j ] ]; 39221 39222 geometryShapes.push( shape ); 39223 39224 } 39225 39226 const extrudePath = data.options.extrudePath; 39227 39228 if ( extrudePath !== undefined ) { 39229 39230 data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath ); 39231 39232 } 39233 39234 return new ExtrudeGeometry( geometryShapes, data.options ); 39235 39236 } 39237 39238} 39239 39240const WorldUVGenerator = { 39241 39242 generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) { 39243 39244 const a_x = vertices[ indexA * 3 ]; 39245 const a_y = vertices[ indexA * 3 + 1 ]; 39246 const b_x = vertices[ indexB * 3 ]; 39247 const b_y = vertices[ indexB * 3 + 1 ]; 39248 const c_x = vertices[ indexC * 3 ]; 39249 const c_y = vertices[ indexC * 3 + 1 ]; 39250 39251 return [ 39252 new Vector2( a_x, a_y ), 39253 new Vector2( b_x, b_y ), 39254 new Vector2( c_x, c_y ) 39255 ]; 39256 39257 }, 39258 39259 generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) { 39260 39261 const a_x = vertices[ indexA * 3 ]; 39262 const a_y = vertices[ indexA * 3 + 1 ]; 39263 const a_z = vertices[ indexA * 3 + 2 ]; 39264 const b_x = vertices[ indexB * 3 ]; 39265 const b_y = vertices[ indexB * 3 + 1 ]; 39266 const b_z = vertices[ indexB * 3 + 2 ]; 39267 const c_x = vertices[ indexC * 3 ]; 39268 const c_y = vertices[ indexC * 3 + 1 ]; 39269 const c_z = vertices[ indexC * 3 + 2 ]; 39270 const d_x = vertices[ indexD * 3 ]; 39271 const d_y = vertices[ indexD * 3 + 1 ]; 39272 const d_z = vertices[ indexD * 3 + 2 ]; 39273 39274 if ( Math.abs( a_y - b_y ) < Math.abs( a_x - b_x ) ) { 39275 39276 return [ 39277 new Vector2( a_x, 1 - a_z ), 39278 new Vector2( b_x, 1 - b_z ), 39279 new Vector2( c_x, 1 - c_z ), 39280 new Vector2( d_x, 1 - d_z ) 39281 ]; 39282 39283 } else { 39284 39285 return [ 39286 new Vector2( a_y, 1 - a_z ), 39287 new Vector2( b_y, 1 - b_z ), 39288 new Vector2( c_y, 1 - c_z ), 39289 new Vector2( d_y, 1 - d_z ) 39290 ]; 39291 39292 } 39293 39294 } 39295 39296}; 39297 39298function toJSON$1( shapes, options, data ) { 39299 39300 data.shapes = []; 39301 39302 if ( Array.isArray( shapes ) ) { 39303 39304 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 39305 39306 const shape = shapes[ i ]; 39307 39308 data.shapes.push( shape.uuid ); 39309 39310 } 39311 39312 } else { 39313 39314 data.shapes.push( shapes.uuid ); 39315 39316 } 39317 39318 data.options = Object.assign( {}, options ); 39319 39320 if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON(); 39321 39322 return data; 39323 39324} 39325 39326class IcosahedronGeometry extends PolyhedronGeometry { 39327 39328 constructor( radius = 1, detail = 0 ) { 39329 39330 const t = ( 1 + Math.sqrt( 5 ) ) / 2; 39331 39332 const vertices = [ 39333 - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0, 39334 0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 39335 t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1 39336 ]; 39337 39338 const indices = [ 39339 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 39340 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, 39341 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 39342 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1 39343 ]; 39344 39345 super( vertices, indices, radius, detail ); 39346 39347 this.type = 'IcosahedronGeometry'; 39348 39349 this.parameters = { 39350 radius: radius, 39351 detail: detail 39352 }; 39353 39354 } 39355 39356 static fromJSON( data ) { 39357 39358 return new IcosahedronGeometry( data.radius, data.detail ); 39359 39360 } 39361 39362} 39363 39364class OctahedronGeometry extends PolyhedronGeometry { 39365 39366 constructor( radius = 1, detail = 0 ) { 39367 39368 const vertices = [ 39369 1, 0, 0, - 1, 0, 0, 0, 1, 0, 39370 0, - 1, 0, 0, 0, 1, 0, 0, - 1 39371 ]; 39372 39373 const indices = [ 39374 0, 2, 4, 0, 4, 3, 0, 3, 5, 39375 0, 5, 2, 1, 2, 5, 1, 5, 3, 39376 1, 3, 4, 1, 4, 2 39377 ]; 39378 39379 super( vertices, indices, radius, detail ); 39380 39381 this.type = 'OctahedronGeometry'; 39382 39383 this.parameters = { 39384 radius: radius, 39385 detail: detail 39386 }; 39387 39388 } 39389 39390 static fromJSON( data ) { 39391 39392 return new OctahedronGeometry( data.radius, data.detail ); 39393 39394 } 39395 39396} 39397 39398class RingGeometry extends BufferGeometry { 39399 39400 constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) { 39401 39402 super(); 39403 39404 this.type = 'RingGeometry'; 39405 39406 this.parameters = { 39407 innerRadius: innerRadius, 39408 outerRadius: outerRadius, 39409 thetaSegments: thetaSegments, 39410 phiSegments: phiSegments, 39411 thetaStart: thetaStart, 39412 thetaLength: thetaLength 39413 }; 39414 39415 thetaSegments = Math.max( 3, thetaSegments ); 39416 phiSegments = Math.max( 1, phiSegments ); 39417 39418 // buffers 39419 39420 const indices = []; 39421 const vertices = []; 39422 const normals = []; 39423 const uvs = []; 39424 39425 // some helper variables 39426 39427 let radius = innerRadius; 39428 const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments ); 39429 const vertex = new Vector3(); 39430 const uv = new Vector2(); 39431 39432 // generate vertices, normals and uvs 39433 39434 for ( let j = 0; j <= phiSegments; j ++ ) { 39435 39436 for ( let i = 0; i <= thetaSegments; i ++ ) { 39437 39438 // values are generate from the inside of the ring to the outside 39439 39440 const segment = thetaStart + i / thetaSegments * thetaLength; 39441 39442 // vertex 39443 39444 vertex.x = radius * Math.cos( segment ); 39445 vertex.y = radius * Math.sin( segment ); 39446 39447 vertices.push( vertex.x, vertex.y, vertex.z ); 39448 39449 // normal 39450 39451 normals.push( 0, 0, 1 ); 39452 39453 // uv 39454 39455 uv.x = ( vertex.x / outerRadius + 1 ) / 2; 39456 uv.y = ( vertex.y / outerRadius + 1 ) / 2; 39457 39458 uvs.push( uv.x, uv.y ); 39459 39460 } 39461 39462 // increase the radius for next row of vertices 39463 39464 radius += radiusStep; 39465 39466 } 39467 39468 // indices 39469 39470 for ( let j = 0; j < phiSegments; j ++ ) { 39471 39472 const thetaSegmentLevel = j * ( thetaSegments + 1 ); 39473 39474 for ( let i = 0; i < thetaSegments; i ++ ) { 39475 39476 const segment = i + thetaSegmentLevel; 39477 39478 const a = segment; 39479 const b = segment + thetaSegments + 1; 39480 const c = segment + thetaSegments + 2; 39481 const d = segment + 1; 39482 39483 // faces 39484 39485 indices.push( a, b, d ); 39486 indices.push( b, c, d ); 39487 39488 } 39489 39490 } 39491 39492 // build geometry 39493 39494 this.setIndex( indices ); 39495 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 39496 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 39497 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 39498 39499 } 39500 39501 copy( source ) { 39502 39503 super.copy( source ); 39504 39505 this.parameters = Object.assign( {}, source.parameters ); 39506 39507 return this; 39508 39509 } 39510 39511 static fromJSON( data ) { 39512 39513 return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength ); 39514 39515 } 39516 39517} 39518 39519class ShapeGeometry extends BufferGeometry { 39520 39521 constructor( shapes = new Shape( [ new Vector2( 0, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), curveSegments = 12 ) { 39522 39523 super(); 39524 39525 this.type = 'ShapeGeometry'; 39526 39527 this.parameters = { 39528 shapes: shapes, 39529 curveSegments: curveSegments 39530 }; 39531 39532 // buffers 39533 39534 const indices = []; 39535 const vertices = []; 39536 const normals = []; 39537 const uvs = []; 39538 39539 // helper variables 39540 39541 let groupStart = 0; 39542 let groupCount = 0; 39543 39544 // allow single and array values for "shapes" parameter 39545 39546 if ( Array.isArray( shapes ) === false ) { 39547 39548 addShape( shapes ); 39549 39550 } else { 39551 39552 for ( let i = 0; i < shapes.length; i ++ ) { 39553 39554 addShape( shapes[ i ] ); 39555 39556 this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support 39557 39558 groupStart += groupCount; 39559 groupCount = 0; 39560 39561 } 39562 39563 } 39564 39565 // build geometry 39566 39567 this.setIndex( indices ); 39568 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,878 bytes, lines 39569-39815
39569 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 39570 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 39571 39572 39573 // helper functions 39574 39575 function addShape( shape ) { 39576 39577 const indexOffset = vertices.length / 3; 39578 const points = shape.extractPoints( curveSegments ); 39579 39580 let shapeVertices = points.shape; 39581 const shapeHoles = points.holes; 39582 39583 // check direction of vertices 39584 39585 if ( ShapeUtils.isClockWise( shapeVertices ) === false ) { 39586 39587 shapeVertices = shapeVertices.reverse(); 39588 39589 } 39590 39591 for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) { 39592 39593 const shapeHole = shapeHoles[ i ]; 39594 39595 if ( ShapeUtils.isClockWise( shapeHole ) === true ) { 39596 39597 shapeHoles[ i ] = shapeHole.reverse(); 39598 39599 } 39600 39601 } 39602 39603 const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles ); 39604 39605 // join vertices of inner and outer paths to a single array 39606 39607 for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) { 39608 39609 const shapeHole = shapeHoles[ i ]; 39610 shapeVertices = shapeVertices.concat( shapeHole ); 39611 39612 } 39613 39614 // vertices, normals, uvs 39615 39616 for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) { 39617 39618 const vertex = shapeVertices[ i ]; 39619 39620 vertices.push( vertex.x, vertex.y, 0 ); 39621 normals.push( 0, 0, 1 ); 39622 uvs.push( vertex.x, vertex.y ); // world uvs 39623 39624 } 39625 39626 // indices 39627 39628 for ( let i = 0, l = faces.length; i < l; i ++ ) { 39629 39630 const face = faces[ i ]; 39631 39632 const a = face[ 0 ] + indexOffset; 39633 const b = face[ 1 ] + indexOffset; 39634 const c = face[ 2 ] + indexOffset; 39635 39636 indices.push( a, b, c ); 39637 groupCount += 3; 39638 39639 } 39640 39641 } 39642 39643 } 39644 39645 copy( source ) { 39646 39647 super.copy( source ); 39648 39649 this.parameters = Object.assign( {}, source.parameters ); 39650 39651 return this; 39652 39653 } 39654 39655 toJSON() { 39656 39657 const data = super.toJSON(); 39658 39659 const shapes = this.parameters.shapes; 39660 39661 return toJSON( shapes, data ); 39662 39663 } 39664 39665 static fromJSON( data, shapes ) { 39666 39667 const geometryShapes = []; 39668 39669 for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) { 39670 39671 const shape = shapes[ data.shapes[ j ] ]; 39672 39673 geometryShapes.push( shape ); 39674 39675 } 39676 39677 return new ShapeGeometry( geometryShapes, data.curveSegments ); 39678 39679 } 39680 39681} 39682 39683function toJSON( shapes, data ) { 39684 39685 data.shapes = []; 39686 39687 if ( Array.isArray( shapes ) ) { 39688 39689 for ( let i = 0, l = shapes.length; i < l; i ++ ) { 39690 39691 const shape = shapes[ i ]; 39692 39693 data.shapes.push( shape.uuid ); 39694 39695 } 39696 39697 } else { 39698 39699 data.shapes.push( shapes.uuid ); 39700 39701 } 39702 39703 return data; 39704 39705} 39706 39707class SphereGeometry extends BufferGeometry { 39708 39709 constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) { 39710 39711 super(); 39712 39713 this.type = 'SphereGeometry'; 39714 39715 this.parameters = { 39716 radius: radius, 39717 widthSegments: widthSegments, 39718 heightSegments: heightSegments, 39719 phiStart: phiStart, 39720 phiLength: phiLength, 39721 thetaStart: thetaStart, 39722 thetaLength: thetaLength 39723 }; 39724 39725 widthSegments = Math.max( 3, Math.floor( widthSegments ) ); 39726 heightSegments = Math.max( 2, Math.floor( heightSegments ) ); 39727 39728 const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI ); 39729 39730 let index = 0; 39731 const grid = []; 39732 39733 const vertex = new Vector3(); 39734 const normal = new Vector3(); 39735 39736 // buffers 39737 39738 const indices = []; 39739 const vertices = []; 39740 const normals = []; 39741 const uvs = []; 39742 39743 // generate vertices, normals and uvs 39744 39745 for ( let iy = 0; iy <= heightSegments; iy ++ ) { 39746 39747 const verticesRow = []; 39748 39749 const v = iy / heightSegments; 39750 39751 // special case for the poles 39752 39753 let uOffset = 0; 39754 39755 if ( iy === 0 && thetaStart === 0 ) { 39756 39757 uOffset = 0.5 / widthSegments; 39758 39759 } else if ( iy === heightSegments && thetaEnd === Math.PI ) { 39760 39761 uOffset = - 0.5 / widthSegments; 39762 39763 } 39764 39765 for ( let ix = 0; ix <= widthSegments; ix ++ ) { 39766 39767 const u = ix / widthSegments; 39768 39769 // vertex 39770 39771 vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); 39772 vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); 39773 vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); 39774 39775 vertices.push( vertex.x, vertex.y, vertex.z ); 39776 39777 // normal 39778 39779 normal.copy( vertex ).normalize(); 39780 normals.push( normal.x, normal.y, normal.z ); 39781 39782 // uv 39783 39784 uvs.push( u + uOffset, 1 - v ); 39785 39786 verticesRow.push( index ++ ); 39787 39788 } 39789 39790 grid.push( verticesRow ); 39791 39792 } 39793 39794 // indices 39795 39796 for ( let iy = 0; iy < heightSegments; iy ++ ) { 39797 39798 for ( let ix = 0; ix < widthSegments; ix ++ ) { 39799 39800 const a = grid[ iy ][ ix + 1 ]; 39801 const b = grid[ iy ][ ix ]; 39802 const c = grid[ iy + 1 ][ ix ]; 39803 const d = grid[ iy + 1 ][ ix + 1 ]; 39804 39805 if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d ); 39806 if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d ); 39807 39808 } 39809 39810 } 39811 39812 // build geometry 39813 39814 this.setIndex( indices ); 39815 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 6,566 bytes, lines 39816-40108
39816 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 39817 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 39818 39819 } 39820 39821 copy( source ) { 39822 39823 super.copy( source ); 39824 39825 this.parameters = Object.assign( {}, source.parameters ); 39826 39827 return this; 39828 39829 } 39830 39831 static fromJSON( data ) { 39832 39833 return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); 39834 39835 } 39836 39837} 39838 39839class TetrahedronGeometry extends PolyhedronGeometry { 39840 39841 constructor( radius = 1, detail = 0 ) { 39842 39843 const vertices = [ 39844 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1 39845 ]; 39846 39847 const indices = [ 39848 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 39849 ]; 39850 39851 super( vertices, indices, radius, detail ); 39852 39853 this.type = 'TetrahedronGeometry'; 39854 39855 this.parameters = { 39856 radius: radius, 39857 detail: detail 39858 }; 39859 39860 } 39861 39862 static fromJSON( data ) { 39863 39864 return new TetrahedronGeometry( data.radius, data.detail ); 39865 39866 } 39867 39868} 39869 39870class TorusGeometry extends BufferGeometry { 39871 39872 constructor( radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2 ) { 39873 39874 super(); 39875 39876 this.type = 'TorusGeometry'; 39877 39878 this.parameters = { 39879 radius: radius, 39880 tube: tube, 39881 radialSegments: radialSegments, 39882 tubularSegments: tubularSegments, 39883 arc: arc 39884 }; 39885 39886 radialSegments = Math.floor( radialSegments ); 39887 tubularSegments = Math.floor( tubularSegments ); 39888 39889 // buffers 39890 39891 const indices = []; 39892 const vertices = []; 39893 const normals = []; 39894 const uvs = []; 39895 39896 // helper variables 39897 39898 const center = new Vector3(); 39899 const vertex = new Vector3(); 39900 const normal = new Vector3(); 39901 39902 // generate vertices, normals and uvs 39903 39904 for ( let j = 0; j <= radialSegments; j ++ ) { 39905 39906 for ( let i = 0; i <= tubularSegments; i ++ ) { 39907 39908 const u = i / tubularSegments * arc; 39909 const v = j / radialSegments * Math.PI * 2; 39910 39911 // vertex 39912 39913 vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u ); 39914 vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u ); 39915 vertex.z = tube * Math.sin( v ); 39916 39917 vertices.push( vertex.x, vertex.y, vertex.z ); 39918 39919 // normal 39920 39921 center.x = radius * Math.cos( u ); 39922 center.y = radius * Math.sin( u ); 39923 normal.subVectors( vertex, center ).normalize(); 39924 39925 normals.push( normal.x, normal.y, normal.z ); 39926 39927 // uv 39928 39929 uvs.push( i / tubularSegments ); 39930 uvs.push( j / radialSegments ); 39931 39932 } 39933 39934 } 39935 39936 // generate indices 39937 39938 for ( let j = 1; j <= radialSegments; j ++ ) { 39939 39940 for ( let i = 1; i <= tubularSegments; i ++ ) { 39941 39942 // indices 39943 39944 const a = ( tubularSegments + 1 ) * j + i - 1; 39945 const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1; 39946 const c = ( tubularSegments + 1 ) * ( j - 1 ) + i; 39947 const d = ( tubularSegments + 1 ) * j + i; 39948 39949 // faces 39950 39951 indices.push( a, b, d ); 39952 indices.push( b, c, d ); 39953 39954 } 39955 39956 } 39957 39958 // build geometry 39959 39960 this.setIndex( indices ); 39961 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 39962 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 39963 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 39964 39965 } 39966 39967 copy( source ) { 39968 39969 super.copy( source ); 39970 39971 this.parameters = Object.assign( {}, source.parameters ); 39972 39973 return this; 39974 39975 } 39976 39977 static fromJSON( data ) { 39978 39979 return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc ); 39980 39981 } 39982 39983} 39984 39985class TorusKnotGeometry extends BufferGeometry { 39986 39987 constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) { 39988 39989 super(); 39990 39991 this.type = 'TorusKnotGeometry'; 39992 39993 this.parameters = { 39994 radius: radius, 39995 tube: tube, 39996 tubularSegments: tubularSegments, 39997 radialSegments: radialSegments, 39998 p: p, 39999 q: q 40000 }; 40001 40002 tubularSegments = Math.floor( tubularSegments ); 40003 radialSegments = Math.floor( radialSegments ); 40004 40005 // buffers 40006 40007 const indices = []; 40008 const vertices = []; 40009 const normals = []; 40010 const uvs = []; 40011 40012 // helper variables 40013 40014 const vertex = new Vector3(); 40015 const normal = new Vector3(); 40016 40017 const P1 = new Vector3(); 40018 const P2 = new Vector3(); 40019 40020 const B = new Vector3(); 40021 const T = new Vector3(); 40022 const N = new Vector3(); 40023 40024 // generate vertices, normals and uvs 40025 40026 for ( let i = 0; i <= tubularSegments; ++ i ) { 40027 40028 // the radian "u" is used to calculate the position on the torus curve of the current tubular segment 40029 40030 const u = i / tubularSegments * p * Math.PI * 2; 40031 40032 // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead. 40033 // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions 40034 40035 calculatePositionOnCurve( u, p, q, radius, P1 ); 40036 calculatePositionOnCurve( u + 0.01, p, q, radius, P2 ); 40037 40038 // calculate orthonormal basis 40039 40040 T.subVectors( P2, P1 ); 40041 N.addVectors( P2, P1 ); 40042 B.crossVectors( T, N ); 40043 N.crossVectors( B, T ); 40044 40045 // normalize B, N. T can be ignored, we don't use it 40046 40047 B.normalize(); 40048 N.normalize(); 40049 40050 for ( let j = 0; j <= radialSegments; ++ j ) { 40051 40052 // now calculate the vertices. they are nothing more than an extrusion of the torus curve. 40053 // because we extrude a shape in the xy-plane, there is no need to calculate a z-value. 40054 40055 const v = j / radialSegments * Math.PI * 2; 40056 const cx = - tube * Math.cos( v ); 40057 const cy = tube * Math.sin( v ); 40058 40059 // now calculate the final vertex position. 40060 // first we orient the extrusion with our basis vectors, then we add it to the current position on the curve 40061 40062 vertex.x = P1.x + ( cx * N.x + cy * B.x ); 40063 vertex.y = P1.y + ( cx * N.y + cy * B.y ); 40064 vertex.z = P1.z + ( cx * N.z + cy * B.z ); 40065 40066 vertices.push( vertex.x, vertex.y, vertex.z ); 40067 40068 // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal) 40069 40070 normal.subVectors( vertex, P1 ).normalize(); 40071 40072 normals.push( normal.x, normal.y, normal.z ); 40073 40074 // uv 40075 40076 uvs.push( i / tubularSegments ); 40077 uvs.push( j / radialSegments ); 40078 40079 } 40080 40081 } 40082 40083 // generate indices 40084 40085 for ( let j = 1; j <= tubularSegments; j ++ ) { 40086 40087 for ( let i = 1; i <= radialSegments; i ++ ) { 40088 40089 // indices 40090 40091 const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); 40092 const b = ( radialSegments + 1 ) * j + ( i - 1 ); 40093 const c = ( radialSegments + 1 ) * j + i; 40094 const d = ( radialSegments + 1 ) * ( j - 1 ) + i; 40095 40096 // faces 40097 40098 indices.push( a, b, d ); 40099 indices.push( b, c, d ); 40100 40101 } 40102 40103 } 40104 40105 // build geometry 40106 40107 this.setIndex( indices ); 40108 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 7,450 bytes, lines 40109-40467
40109 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 40110 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 40111 40112 // this function calculates the current position on the torus curve 40113 40114 function calculatePositionOnCurve( u, p, q, radius, position ) { 40115 40116 const cu = Math.cos( u ); 40117 const su = Math.sin( u ); 40118 const quOverP = q / p * u; 40119 const cs = Math.cos( quOverP ); 40120 40121 position.x = radius * ( 2 + cs ) * 0.5 * cu; 40122 position.y = radius * ( 2 + cs ) * su * 0.5; 40123 position.z = radius * Math.sin( quOverP ) * 0.5; 40124 40125 } 40126 40127 } 40128 40129 copy( source ) { 40130 40131 super.copy( source ); 40132 40133 this.parameters = Object.assign( {}, source.parameters ); 40134 40135 return this; 40136 40137 } 40138 40139 static fromJSON( data ) { 40140 40141 return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q ); 40142 40143 } 40144 40145} 40146 40147class TubeGeometry extends BufferGeometry { 40148 40149 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 ) { 40150 40151 super(); 40152 40153 this.type = 'TubeGeometry'; 40154 40155 this.parameters = { 40156 path: path, 40157 tubularSegments: tubularSegments, 40158 radius: radius, 40159 radialSegments: radialSegments, 40160 closed: closed 40161 }; 40162 40163 const frames = path.computeFrenetFrames( tubularSegments, closed ); 40164 40165 // expose internals 40166 40167 this.tangents = frames.tangents; 40168 this.normals = frames.normals; 40169 this.binormals = frames.binormals; 40170 40171 // helper variables 40172 40173 const vertex = new Vector3(); 40174 const normal = new Vector3(); 40175 const uv = new Vector2(); 40176 let P = new Vector3(); 40177 40178 // buffer 40179 40180 const vertices = []; 40181 const normals = []; 40182 const uvs = []; 40183 const indices = []; 40184 40185 // create buffer data 40186 40187 generateBufferData(); 40188 40189 // build geometry 40190 40191 this.setIndex( indices ); 40192 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 40193 this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 40194 this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 40195 40196 // functions 40197 40198 function generateBufferData() { 40199 40200 for ( let i = 0; i < tubularSegments; i ++ ) { 40201 40202 generateSegment( i ); 40203 40204 } 40205 40206 // if the geometry is not closed, generate the last row of vertices and normals 40207 // at the regular position on the given path 40208 // 40209 // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ) 40210 40211 generateSegment( ( closed === false ) ? tubularSegments : 0 ); 40212 40213 // uvs are generated in a separate function. 40214 // this makes it easy compute correct values for closed geometries 40215 40216 generateUVs(); 40217 40218 // finally create faces 40219 40220 generateIndices(); 40221 40222 } 40223 40224 function generateSegment( i ) { 40225 40226 // we use getPointAt to sample evenly distributed points from the given path 40227 40228 P = path.getPointAt( i / tubularSegments, P ); 40229 40230 // retrieve corresponding normal and binormal 40231 40232 const N = frames.normals[ i ]; 40233 const B = frames.binormals[ i ]; 40234 40235 // generate normals and vertices for the current segment 40236 40237 for ( let j = 0; j <= radialSegments; j ++ ) { 40238 40239 const v = j / radialSegments * Math.PI * 2; 40240 40241 const sin = Math.sin( v ); 40242 const cos = - Math.cos( v ); 40243 40244 // normal 40245 40246 normal.x = ( cos * N.x + sin * B.x ); 40247 normal.y = ( cos * N.y + sin * B.y ); 40248 normal.z = ( cos * N.z + sin * B.z ); 40249 normal.normalize(); 40250 40251 normals.push( normal.x, normal.y, normal.z ); 40252 40253 // vertex 40254 40255 vertex.x = P.x + radius * normal.x; 40256 vertex.y = P.y + radius * normal.y; 40257 vertex.z = P.z + radius * normal.z; 40258 40259 vertices.push( vertex.x, vertex.y, vertex.z ); 40260 40261 } 40262 40263 } 40264 40265 function generateIndices() { 40266 40267 for ( let j = 1; j <= tubularSegments; j ++ ) { 40268 40269 for ( let i = 1; i <= radialSegments; i ++ ) { 40270 40271 const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); 40272 const b = ( radialSegments + 1 ) * j + ( i - 1 ); 40273 const c = ( radialSegments + 1 ) * j + i; 40274 const d = ( radialSegments + 1 ) * ( j - 1 ) + i; 40275 40276 // faces 40277 40278 indices.push( a, b, d ); 40279 indices.push( b, c, d ); 40280 40281 } 40282 40283 } 40284 40285 } 40286 40287 function generateUVs() { 40288 40289 for ( let i = 0; i <= tubularSegments; i ++ ) { 40290 40291 for ( let j = 0; j <= radialSegments; j ++ ) { 40292 40293 uv.x = i / tubularSegments; 40294 uv.y = j / radialSegments; 40295 40296 uvs.push( uv.x, uv.y ); 40297 40298 } 40299 40300 } 40301 40302 } 40303 40304 } 40305 40306 copy( source ) { 40307 40308 super.copy( source ); 40309 40310 this.parameters = Object.assign( {}, source.parameters ); 40311 40312 return this; 40313 40314 } 40315 40316 toJSON() { 40317 40318 const data = super.toJSON(); 40319 40320 data.path = this.parameters.path.toJSON(); 40321 40322 return data; 40323 40324 } 40325 40326 static fromJSON( data ) { 40327 40328 // This only works for built-in curves (e.g. CatmullRomCurve3). 40329 // User defined curves or instances of CurvePath will not be deserialized. 40330 return new TubeGeometry( 40331 new Curves[ data.path.type ]().fromJSON( data.path ), 40332 data.tubularSegments, 40333 data.radius, 40334 data.radialSegments, 40335 data.closed 40336 ); 40337 40338 } 40339 40340} 40341 40342class WireframeGeometry extends BufferGeometry { 40343 40344 constructor( geometry = null ) { 40345 40346 super(); 40347 40348 this.type = 'WireframeGeometry'; 40349 40350 this.parameters = { 40351 geometry: geometry 40352 }; 40353 40354 if ( geometry !== null ) { 40355 40356 // buffer 40357 40358 const vertices = []; 40359 const edges = new Set(); 40360 40361 // helper variables 40362 40363 const start = new Vector3(); 40364 const end = new Vector3(); 40365 40366 if ( geometry.index !== null ) { 40367 40368 // indexed BufferGeometry 40369 40370 const position = geometry.attributes.position; 40371 const indices = geometry.index; 40372 let groups = geometry.groups; 40373 40374 if ( groups.length === 0 ) { 40375 40376 groups = [ { start: 0, count: indices.count, materialIndex: 0 } ]; 40377 40378 } 40379 40380 // create a data structure that contains all edges without duplicates 40381 40382 for ( let o = 0, ol = groups.length; o < ol; ++ o ) { 40383 40384 const group = groups[ o ]; 40385 40386 const groupStart = group.start; 40387 const groupCount = group.count; 40388 40389 for ( let i = groupStart, l = ( groupStart + groupCount ); i < l; i += 3 ) { 40390 40391 for ( let j = 0; j < 3; j ++ ) { 40392 40393 const index1 = indices.getX( i + j ); 40394 const index2 = indices.getX( i + ( j + 1 ) % 3 ); 40395 40396 start.fromBufferAttribute( position, index1 ); 40397 end.fromBufferAttribute( position, index2 ); 40398 40399 if ( isUniqueEdge( start, end, edges ) === true ) { 40400 40401 vertices.push( start.x, start.y, start.z ); 40402 vertices.push( end.x, end.y, end.z ); 40403 40404 } 40405 40406 } 40407 40408 } 40409 40410 } 40411 40412 } else { 40413 40414 // non-indexed BufferGeometry 40415 40416 const position = geometry.attributes.position; 40417 40418 for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) { 40419 40420 for ( let j = 0; j < 3; j ++ ) { 40421 40422 // three edges per triangle, an edge is represented as (index1, index2) 40423 // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0) 40424 40425 const index1 = 3 * i + j; 40426 const index2 = 3 * i + ( ( j + 1 ) % 3 ); 40427 40428 start.fromBufferAttribute( position, index1 ); 40429 end.fromBufferAttribute( position, index2 ); 40430 40431 if ( isUniqueEdge( start, end, edges ) === true ) { 40432 40433 vertices.push( start.x, start.y, start.z ); 40434 vertices.push( end.x, end.y, end.z ); 40435 40436 } 40437 40438 } 40439 40440 } 40441 40442 } 40443 40444 // build geometry 40445 40446 this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 40447 40448 } 40449 40450 } 40451 40452 copy( source ) { 40453 40454 super.copy( source ); 40455 40456 this.parameters = Object.assign( {}, source.parameters ); 40457 40458 return this; 40459 40460 } 40461 40462} 40463 40464function isUniqueEdge( start, end, edges ) { 40465 40466 const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`; 40467 const hash2 = `${end.x}
40467,${end.y},${end.z}-${start.x},${start.y},${start.z}`; // coincident edge 40468 40469 if ( edges.has( hash1 ) === true || edges.has( hash2 ) === true ) { 40470 40471 return false; 40472 40473 } else { 40474 40475 edges.add( hash1 ); 40476 edges.add( hash2 ); 40477 return true; 40478 40479 } 40480 40481} 40482 40483var Geometries = /*#__PURE__*/Object.freeze({ 40484 __proto__: null, 40485 BoxGeometry: BoxGeometry, 40486 CapsuleGeometry: CapsuleGeometry, 40487 CircleGeometry: CircleGeometry, 40488 ConeGeometry: ConeGeometry, 40489 CylinderGeometry: CylinderGeometry, 40490 DodecahedronGeometry: DodecahedronGeometry, 40491 EdgesGeometry: EdgesGeometry, 40492 ExtrudeGeometry: ExtrudeGeometry, 40493 IcosahedronGeometry: IcosahedronGeometry, 40494 LatheGeometry: LatheGeometry, 40495 OctahedronGeometry: OctahedronGeometry, 40496 PlaneGeometry: PlaneGeometry, 40497 PolyhedronGeometry: PolyhedronGeometry, 40498 RingGeometry: RingGeometry, 40499 ShapeGeometry: ShapeGeometry, 40500 SphereGeometry: SphereGeometry, 40501 TetrahedronGeometry: TetrahedronGeometry, 40502 TorusGeometry: TorusGeometry, 40503 TorusKnotGeometry: TorusKnotGeometry, 40504 TubeGeometry: TubeGeometry, 40505 WireframeGeometry: WireframeGeometry 40506}); 40507 40508class ShadowMaterial extends Material { 40509 40510 constructor( parameters ) { 40511 40512 super(); 40513 40514 this.isShadowMaterial = true; 40515 40516 this.type = 'ShadowMaterial'; 40517 40518 this.color = new Color( 0x000000 ); 40519 this.transparent = true; 40520 40521 this.fog = true; 40522 40523 this.setValues( parameters ); 40524 40525 } 40526 40527 copy( source ) { 40528 40529 super.copy( source ); 40530 40531 this.color.copy( source.color ); 40532 40533 this.fog = source.fog; 40534 40535 return this; 40536 40537 } 40538 40539} 40540 40541class RawShaderMaterial extends ShaderMaterial { 40542 40543 constructor( parameters ) { 40544 40545 super( parameters ); 40546 40547 this.isRawShaderMaterial = true; 40548 40549 this.type = 'RawShaderMaterial'; 40550 40551 } 40552 40553} 40554 40555class MeshStandardMaterial extends Material { 40556 40557 constructor( parameters ) { 40558 40559 super(); 40560 40561 this.isMeshStandardMaterial = true; 40562 40563 this.defines = { 'STANDARD': '' }; 40564 40565 this.type = 'MeshStandardMaterial'; 40566 40567 this.color = new Color( 0xffffff ); // diffuse 40568 this.roughness = 1.0; 40569 this.metalness = 0.0; 40570 40571 this.map = null; 40572 40573 this.lightMap = null; 40574 this.lightMapIntensity = 1.0; 40575 40576 this.aoMap = null; 40577 this.aoMapIntensity = 1.0; 40578 40579 this.emissive = new Color( 0x000000 ); 40580 this.emissiveIntensity = 1.0; 40581 this.emissiveMap = null; 40582 40583 this.bumpMap = null; 40584 this.bumpScale = 1; 40585 40586 this.normalMap = null; 40587 this.normalMapType = TangentSpaceNormalMap; 40588 this.normalScale = new Vector2( 1, 1 ); 40589 40590 this.displacementMap = null; 40591 this.displacementScale = 1; 40592 this.displacementBias = 0; 40593 40594 this.roughnessMap = null; 40595 40596 this.metalnessMap = null; 40597 40598 this.alphaMap = null; 40599 40600 this.envMap = null; 40601 this.envMapIntensity = 1.0; 40602 40603 this.wireframe = false; 40604 this.wireframeLinewidth = 1; 40605 this.wireframeLinecap = 'round'; 40606 this.wireframeLinejoin = 'round'; 40607 40608 this.flatShading = false; 40609 40610 this.fog = true; 40611 40612 this.setValues( parameters ); 40613 40614 } 40615 40616 copy( source ) { 40617 40618 super.copy( source ); 40619 40620 this.defines = { 'STANDARD': '' }; 40621 40622 this.color.copy( source.color ); 40623 this.roughness = source.roughness; 40624 this.metalness = source.metalness; 40625 40626 this.map = source.map; 40627 40628 this.lightMap = source.lightMap; 40629 this.lightMapIntensity = source.lightMapIntensity; 40630 40631 this.aoMap = source.aoMap; 40632 this.aoMapIntensity = source.aoMapIntensity; 40633 40634 this.emissive.copy( source.emissive ); 40635 this.emissiveMap = source.emissiveMap; 40636 this.emissiveIntensity = source.emissiveIntensity; 40637 40638 this.bumpMap = source.bumpMap; 40639 this.bumpScale = source.bumpScale; 40640 40641 this.normalMap = source.normalMap; 40642 this.normalMapType = source.normalMapType; 40643 this.normalScale.copy( source.normalScale ); 40644 40645 this.displacementMap = source.displacementMap; 40646 this.displacementScale = source.displacementScale; 40647 this.displacementBias = source.displacementBias; 40648 40649 this.roughnessMap = source.roughnessMap; 40650 40651 this.metalnessMap = source.metalnessMap; 40652 40653 this.alphaMap = source.alphaMap; 40654 40655 this.envMap = source.envMap; 40656 this.envMapIntensity = source.envMapIntensity; 40657 40658 this.wireframe = source.wireframe; 40659 this.wireframeLinewidth = source.wireframeLinewidth; 40660 this.wireframeLinecap = source.wireframeLinecap; 40661 this.wireframeLinejoin = source.wireframeLinejoin; 40662 40663 this.flatShading = source.flatShading; 40664 40665 this.fog = source.fog; 40666 40667 return this; 40668 40669 } 40670 40671} 40672 40673class MeshPhysicalMaterial extends MeshStandardMaterial { 40674 40675 constructor( parameters ) { 40676 40677 super(); 40678 40679 this.isMeshPhysicalMaterial = true; 40680 40681 this.defines = { 40682 40683 'STANDARD': '', 40684 'PHYSICAL': '' 40685 40686 }; 40687 40688 this.type = 'MeshPhysicalMaterial'; 40689 40690 this.anisotropyRotation = 0; 40691 this.anisotropyMap = null; 40692 40693 this.clearcoatMap = null; 40694 this.clearcoatRoughness = 0.0; 40695 this.clearcoatRoughnessMap = null; 40696 this.clearcoatNormalScale = new Vector2( 1, 1 ); 40697 this.clearcoatNormalMap = null; 40698 40699 this.ior = 1.5; 40700 40701 Object.defineProperty( this, 'reflectivity', { 40702 get: function () { 40703 40704 return ( clamp( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) ); 40705 40706 },
vendor: 29,008 bytes, lines 40707-42164
40707 set: function ( reflectivity ) { 40708 40709 this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity ); 40710 40711 } 40712 } ); 40713 40714 this.iridescenceMap = null; 40715 this.iridescenceIOR = 1.3; 40716 this.iridescenceThicknessRange = [ 100, 400 ]; 40717 this.iridescenceThicknessMap = null; 40718 40719 this.sheenColor = new Color( 0x000000 ); 40720 this.sheenColorMap = null; 40721 this.sheenRoughness = 1.0; 40722 this.sheenRoughnessMap = null; 40723 40724 this.transmissionMap = null; 40725 40726 this.thickness = 0; 40727 this.thicknessMap = null; 40728 this.attenuationDistance = Infinity; 40729 this.attenuationColor = new Color( 1, 1, 1 ); 40730 40731 this.specularIntensity = 1.0; 40732 this.specularIntensityMap = null; 40733 this.specularColor = new Color( 1, 1, 1 ); 40734 this.specularColorMap = null; 40735 40736 this._anisotropy = 0; 40737 this._clearcoat = 0; 40738 this._iridescence = 0; 40739 this._sheen = 0.0; 40740 this._transmission = 0; 40741 40742 this.setValues( parameters ); 40743 40744 } 40745 40746 get anisotropy() { 40747 40748 return this._anisotropy; 40749 40750 } 40751 40752 set anisotropy( value ) { 40753 40754 if ( this._anisotropy > 0 !== value > 0 ) { 40755 40756 this.version ++; 40757 40758 } 40759 40760 this._anisotropy = value; 40761 40762 } 40763 40764 get clearcoat() { 40765 40766 return this._clearcoat; 40767 40768 } 40769 40770 set clearcoat( value ) { 40771 40772 if ( this._clearcoat > 0 !== value > 0 ) { 40773 40774 this.version ++; 40775 40776 } 40777 40778 this._clearcoat = value; 40779 40780 } 40781 40782 get iridescence() { 40783 40784 return this._iridescence; 40785 40786 } 40787 40788 set iridescence( value ) { 40789 40790 if ( this._iridescence > 0 !== value > 0 ) { 40791 40792 this.version ++; 40793 40794 } 40795 40796 this._iridescence = value; 40797 40798 } 40799 40800 get sheen() { 40801 40802 return this._sheen; 40803 40804 } 40805 40806 set sheen( value ) { 40807 40808 if ( this._sheen > 0 !== value > 0 ) { 40809 40810 this.version ++; 40811 40812 } 40813 40814 this._sheen = value; 40815 40816 } 40817 40818 get transmission() { 40819 40820 return this._transmission; 40821 40822 } 40823 40824 set transmission( value ) { 40825 40826 if ( this._transmission > 0 !== value > 0 ) { 40827 40828 this.version ++; 40829 40830 } 40831 40832 this._transmission = value; 40833 40834 } 40835 40836 copy( source ) { 40837 40838 super.copy( source ); 40839 40840 this.defines = { 40841 40842 'STANDARD': '', 40843 'PHYSICAL': '' 40844 40845 }; 40846 40847 this.anisotropy = source.anisotropy; 40848 this.anisotropyRotation = source.anisotropyRotation; 40849 this.anisotropyMap = source.anisotropyMap; 40850 40851 this.clearcoat = source.clearcoat; 40852 this.clearcoatMap = source.clearcoatMap; 40853 this.clearcoatRoughness = source.clearcoatRoughness; 40854 this.clearcoatRoughnessMap = source.clearcoatRoughnessMap; 40855 this.clearcoatNormalMap = source.clearcoatNormalMap; 40856 this.clearcoatNormalScale.copy( source.clearcoatNormalScale ); 40857 40858 this.ior = source.ior; 40859 40860 this.iridescence = source.iridescence; 40861 this.iridescenceMap = source.iridescenceMap; 40862 this.iridescenceIOR = source.iridescenceIOR; 40863 this.iridescenceThicknessRange = [ ...source.iridescenceThicknessRange ]; 40864 this.iridescenceThicknessMap = source.iridescenceThicknessMap; 40865 40866 this.sheen = source.sheen; 40867 this.sheenColor.copy( source.sheenColor ); 40868 this.sheenColorMap = source.sheenColorMap; 40869 this.sheenRoughness = source.sheenRoughness; 40870 this.sheenRoughnessMap = source.sheenRoughnessMap; 40871 40872 this.transmission = source.transmission; 40873 this.transmissionMap = source.transmissionMap; 40874 40875 this.thickness = source.thickness; 40876 this.thicknessMap = source.thicknessMap; 40877 this.attenuationDistance = source.attenuationDistance; 40878 this.attenuationColor.copy( source.attenuationColor ); 40879 40880 this.specularIntensity = source.specularIntensity; 40881 this.specularIntensityMap = source.specularIntensityMap; 40882 this.specularColor.copy( source.specularColor ); 40883 this.specularColorMap = source.specularColorMap; 40884 40885 return this; 40886 40887 } 40888 40889} 40890 40891class MeshPhongMaterial extends Material { 40892 40893 constructor( parameters ) { 40894 40895 super(); 40896 40897 this.isMeshPhongMaterial = true; 40898 40899 this.type = 'MeshPhongMaterial'; 40900 40901 this.color = new Color( 0xffffff ); // diffuse 40902 this.specular = new Color( 0x111111 ); 40903 this.shininess = 30; 40904 40905 this.map = null; 40906 40907 this.lightMap = null; 40908 this.lightMapIntensity = 1.0; 40909 40910 this.aoMap = null; 40911 this.aoMapIntensity = 1.0; 40912 40913 this.emissive = new Color( 0x000000 ); 40914 this.emissiveIntensity = 1.0; 40915 this.emissiveMap = null; 40916 40917 this.bumpMap = null; 40918 this.bumpScale = 1; 40919 40920 this.normalMap = null; 40921 this.normalMapType = TangentSpaceNormalMap; 40922 this.normalScale = new Vector2( 1, 1 ); 40923 40924 this.displacementMap = null; 40925 this.displacementScale = 1; 40926 this.displacementBias = 0; 40927 40928 this.specularMap = null; 40929 40930 this.alphaMap = null; 40931 40932 this.envMap = null; 40933 this.combine = MultiplyOperation; 40934 this.reflectivity = 1; 40935 this.refractionRatio = 0.98; 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.color.copy( source.color ); 40955 this.specular.copy( source.specular ); 40956 this.shininess = source.shininess; 40957 40958 this.map = source.map; 40959 40960 this.lightMap = source.lightMap; 40961 this.lightMapIntensity = source.lightMapIntensity; 40962 40963 this.aoMap = source.aoMap; 40964 this.aoMapIntensity = source.aoMapIntensity; 40965 40966 this.emissive.copy( source.emissive ); 40967 this.emissiveMap = source.emissiveMap; 40968 this.emissiveIntensity = source.emissiveIntensity; 40969 40970 this.bumpMap = source.bumpMap; 40971 this.bumpScale = source.bumpScale; 40972 40973 this.normalMap = source.normalMap; 40974 this.normalMapType = source.normalMapType; 40975 this.normalScale.copy( source.normalScale ); 40976 40977 this.displacementMap = source.displacementMap; 40978 this.displacementScale = source.displacementScale; 40979 this.displacementBias = source.displacementBias; 40980 40981 this.specularMap = source.specularMap; 40982 40983 this.alphaMap = source.alphaMap; 40984 40985 this.envMap = source.envMap; 40986 this.combine = source.combine; 40987 this.reflectivity = source.reflectivity; 40988 this.refractionRatio = source.refractionRatio; 40989 40990 this.wireframe = source.wireframe; 40991 this.wireframeLinewidth = source.wireframeLinewidth; 40992 this.wireframeLinecap = source.wireframeLinecap; 40993 this.wireframeLinejoin = source.wireframeLinejoin; 40994 40995 this.flatShading = source.flatShading; 40996 40997 this.fog = source.fog; 40998 40999 return this; 41000 41001 } 41002 41003} 41004 41005class MeshToonMaterial extends Material { 41006 41007 constructor( parameters ) { 41008 41009 super(); 41010 41011 this.isMeshToonMaterial = true; 41012 41013 this.defines = { 'TOON': '' }; 41014 41015 this.type = 'MeshToonMaterial'; 41016 41017 this.color = new Color( 0xffffff ); 41018 41019 this.map = null; 41020 this.gradientMap = null; 41021 41022 this.lightMap = null; 41023 this.lightMapIntensity = 1.0; 41024 41025 this.aoMap = null; 41026 this.aoMapIntensity = 1.0; 41027 41028 this.emissive = new Color( 0x000000 ); 41029 this.emissiveIntensity = 1.0; 41030 this.emissiveMap = null; 41031 41032 this.bumpMap = null; 41033 this.bumpScale = 1; 41034 41035 this.normalMap = null; 41036 this.normalMapType = TangentSpaceNormalMap; 41037 this.normalScale = new Vector2( 1, 1 ); 41038 41039 this.displacementMap = null; 41040 this.displacementScale = 1; 41041 this.displacementBias = 0; 41042 41043 this.alphaMap = null; 41044 41045 this.wireframe = false; 41046 this.wireframeLinewidth = 1; 41047 this.wireframeLinecap = 'round'; 41048 this.wireframeLinejoin = 'round'; 41049 41050 this.fog = true; 41051 41052 this.setValues( parameters ); 41053 41054 } 41055 41056 copy( source ) { 41057 41058 super.copy( source ); 41059 41060 this.color.copy( source.color ); 41061 41062 this.map = source.map; 41063 this.gradientMap = source.gradientMap; 41064 41065 this.lightMap = source.lightMap; 41066 this.lightMapIntensity = source.lightMapIntensity; 41067 41068 this.aoMap = source.aoMap; 41069 this.aoMapIntensity = source.aoMapIntensity; 41070 41071 this.emissive.copy( source.emissive ); 41072 this.emissiveMap = source.emissiveMap; 41073 this.emissiveIntensity = source.emissiveIntensity; 41074 41075 this.bumpMap = source.bumpMap; 41076 this.bumpScale = source.bumpScale; 41077 41078 this.normalMap = source.normalMap; 41079 this.normalMapType = source.normalMapType; 41080 this.normalScale.copy( source.normalScale ); 41081 41082 this.displacementMap = source.displacementMap; 41083 this.displacementScale = source.displacementScale; 41084 this.displacementBias = source.displacementBias; 41085 41086 this.alphaMap = source.alphaMap; 41087 41088 this.wireframe = source.wireframe; 41089 this.wireframeLinewidth = source.wireframeLinewidth; 41090 this.wireframeLinecap = source.wireframeLinecap; 41091 this.wireframeLinejoin = source.wireframeLinejoin; 41092 41093 this.fog = source.fog; 41094 41095 return this; 41096 41097 } 41098 41099} 41100 41101class MeshNormalMaterial extends Material { 41102 41103 constructor( parameters ) { 41104 41105 super(); 41106 41107 this.isMeshNormalMaterial = true; 41108 41109 this.type = 'MeshNormalMaterial'; 41110 41111 this.bumpMap = null; 41112 this.bumpScale = 1; 41113 41114 this.normalMap = null; 41115 this.normalMapType = TangentSpaceNormalMap; 41116 this.normalScale = new Vector2( 1, 1 ); 41117 41118 this.displacementMap = null; 41119 this.displacementScale = 1; 41120 this.displacementBias = 0; 41121 41122 this.wireframe = false; 41123 this.wireframeLinewidth = 1; 41124 41125 this.flatShading = false; 41126 41127 this.setValues( parameters ); 41128 41129 } 41130 41131 copy( source ) { 41132 41133 super.copy( source ); 41134 41135 this.bumpMap = source.bumpMap; 41136 this.bumpScale = source.bumpScale; 41137 41138 this.normalMap = source.normalMap; 41139 this.normalMapType = source.normalMapType; 41140 this.normalScale.copy( source.normalScale ); 41141 41142 this.displacementMap = source.displacementMap; 41143 this.displacementScale = source.displacementScale; 41144 this.displacementBias = source.displacementBias; 41145 41146 this.wireframe = source.wireframe; 41147 this.wireframeLinewidth = source.wireframeLinewidth; 41148 41149 this.flatShading = source.flatShading; 41150 41151 return this; 41152 41153 } 41154 41155} 41156 41157class MeshLambertMaterial extends Material { 41158 41159 constructor( parameters ) { 41160 41161 super(); 41162 41163 this.isMeshLambertMaterial = true; 41164 41165 this.type = 'MeshLambertMaterial'; 41166 41167 this.color = new Color( 0xffffff ); // diffuse 41168 41169 this.map = null; 41170 41171 this.lightMap = null; 41172 this.lightMapIntensity = 1.0; 41173 41174 this.aoMap = null; 41175 this.aoMapIntensity = 1.0; 41176 41177 this.emissive = new Color( 0x000000 ); 41178 this.emissiveIntensity = 1.0; 41179 this.emissiveMap = null; 41180 41181 this.bumpMap = null; 41182 this.bumpScale = 1; 41183 41184 this.normalMap = null; 41185 this.normalMapType = TangentSpaceNormalMap; 41186 this.normalScale = new Vector2( 1, 1 ); 41187 41188 this.displacementMap = null; 41189 this.displacementScale = 1; 41190 this.displacementBias = 0; 41191 41192 this.specularMap = null; 41193 41194 this.alphaMap = null; 41195 41196 this.envMap = null; 41197 this.combine = MultiplyOperation; 41198 this.reflectivity = 1; 41199 this.refractionRatio = 0.98; 41200 41201 this.wireframe = false; 41202 this.wireframeLinewidth = 1; 41203 this.wireframeLinecap = 'round'; 41204 this.wireframeLinejoin = 'round'; 41205 41206 this.flatShading = false; 41207 41208 this.fog = true; 41209 41210 this.setValues( parameters ); 41211 41212 } 41213 41214 copy( source ) { 41215 41216 super.copy( source ); 41217 41218 this.color.copy( source.color ); 41219 41220 this.map = source.map; 41221 41222 this.lightMap = source.lightMap; 41223 this.lightMapIntensity = source.lightMapIntensity; 41224 41225 this.aoMap = source.aoMap; 41226 this.aoMapIntensity = source.aoMapIntensity; 41227 41228 this.emissive.copy( source.emissive ); 41229 this.emissiveMap = source.emissiveMap; 41230 this.emissiveIntensity = source.emissiveIntensity; 41231 41232 this.bumpMap = source.bumpMap; 41233 this.bumpScale = source.bumpScale; 41234 41235 this.normalMap = source.normalMap; 41236 this.normalMapType = source.normalMapType; 41237 this.normalScale.copy( source.normalScale ); 41238 41239 this.displacementMap = source.displacementMap; 41240 this.displacementScale = source.displacementScale; 41241 this.displacementBias = source.displacementBias; 41242 41243 this.specularMap = source.specularMap; 41244 41245 this.alphaMap = source.alphaMap; 41246 41247 this.envMap = source.envMap; 41248 this.combine = source.combine; 41249 this.reflectivity = source.reflectivity; 41250 this.refractionRatio = source.refractionRatio; 41251 41252 this.wireframe = source.wireframe; 41253 this.wireframeLinewidth = source.wireframeLinewidth; 41254 this.wireframeLinecap = source.wireframeLinecap; 41255 this.wireframeLinejoin = source.wireframeLinejoin; 41256 41257 this.flatShading = source.flatShading; 41258 41259 this.fog = source.fog; 41260 41261 return this; 41262 41263 } 41264 41265} 41266 41267class MeshMatcapMaterial extends Material { 41268 41269 constructor( parameters ) { 41270 41271 super(); 41272 41273 this.isMeshMatcapMaterial = true; 41274 41275 this.defines = { 'MATCAP': '' }; 41276 41277 this.type = 'MeshMatcapMaterial'; 41278 41279 this.color = new Color( 0xffffff ); // diffuse 41280 41281 this.matcap = null; 41282 41283 this.map = null; 41284 41285 this.bumpMap = null; 41286 this.bumpScale = 1; 41287 41288 this.normalMap = null; 41289 this.normalMapType = TangentSpaceNormalMap; 41290 this.normalScale = new Vector2( 1, 1 ); 41291 41292 this.displacementMap = null; 41293 this.displacementScale = 1; 41294 this.displacementBias = 0; 41295 41296 this.alphaMap = null; 41297 41298 this.flatShading = false; 41299 41300 this.fog = true; 41301 41302 this.setValues( parameters ); 41303 41304 } 41305 41306 41307 copy( source ) { 41308 41309 super.copy( source ); 41310 41311 this.defines = { 'MATCAP': '' }; 41312 41313 this.color.copy( source.color ); 41314 41315 this.matcap = source.matcap; 41316 41317 this.map = source.map; 41318 41319 this.bumpMap = source.bumpMap; 41320 this.bumpScale = source.bumpScale; 41321 41322 this.normalMap = source.normalMap; 41323 this.normalMapType = source.normalMapType; 41324 this.normalScale.copy( source.normalScale ); 41325 41326 this.displacementMap = source.displacementMap; 41327 this.displacementScale = source.displacementScale; 41328 this.displacementBias = source.displacementBias; 41329 41330 this.alphaMap = source.alphaMap; 41331 41332 this.flatShading = source.flatShading; 41333 41334 this.fog = source.fog; 41335 41336 return this; 41337 41338 } 41339 41340} 41341 41342class LineDashedMaterial extends LineBasicMaterial { 41343 41344 constructor( parameters ) { 41345 41346 super(); 41347 41348 this.isLineDashedMaterial = true; 41349 41350 this.type = 'LineDashedMaterial'; 41351 41352 this.scale = 1; 41353 this.dashSize = 3; 41354 this.gapSize = 1; 41355 41356 this.setValues( parameters ); 41357 41358 } 41359 41360 copy( source ) { 41361 41362 super.copy( source ); 41363 41364 this.scale = source.scale; 41365 this.dashSize = source.dashSize; 41366 this.gapSize = source.gapSize; 41367 41368 return this; 41369 41370 } 41371 41372} 41373 41374// converts an array to a specific type 41375function convertArray( array, type, forceClone ) { 41376 41377 if ( ! array || // let 'undefined' and 'null' pass 41378 ! forceClone && array.constructor === type ) return array; 41379 41380 if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { 41381 41382 return new type( array ); // create typed array 41383 41384 } 41385 41386 return Array.prototype.slice.call( array ); // create Array 41387 41388} 41389 41390function isTypedArray( object ) { 41391 41392 return ArrayBuffer.isView( object ) && 41393 ! ( object instanceof DataView ); 41394 41395} 41396 41397// returns an array by which times and values can be sorted 41398function getKeyframeOrder( times ) { 41399 41400 function compareTime( i, j ) { 41401 41402 return times[ i ] - times[ j ]; 41403 41404 } 41405 41406 const n = times.length; 41407 const result = new Array( n ); 41408 for ( let i = 0; i !== n; ++ i ) result[ i ] = i; 41409 41410 result.sort( compareTime ); 41411 41412 return result; 41413 41414} 41415 41416// uses the array previously returned by 'getKeyframeOrder' to sort data 41417function sortedArray( values, stride, order ) { 41418 41419 const nValues = values.length; 41420 const result = new values.constructor( nValues ); 41421 41422 for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { 41423 41424 const srcOffset = order[ i ] * stride; 41425 41426 for ( let j = 0; j !== stride; ++ j ) { 41427 41428 result[ dstOffset ++ ] = values[ srcOffset + j ]; 41429 41430 } 41431 41432 } 41433 41434 return result; 41435 41436} 41437 41438// function for parsing AOS keyframe formats 41439function flattenJSON( jsonKeys, times, values, valuePropertyName ) { 41440 41441 let i = 1, key = jsonKeys[ 0 ]; 41442 41443 while ( key !== undefined && key[ valuePropertyName ] === undefined ) { 41444 41445 key = jsonKeys[ i ++ ]; 41446 41447 } 41448 41449 if ( key === undefined ) return; // no data 41450 41451 let value = key[ valuePropertyName ]; 41452 if ( value === undefined ) return; // no data 41453 41454 if ( Array.isArray( value ) ) { 41455 41456 do { 41457 41458 value = key[ valuePropertyName ]; 41459 41460 if ( value !== undefined ) { 41461 41462 times.push( key.time ); 41463 values.push.apply( values, value ); // push all elements 41464 41465 } 41466 41467 key = jsonKeys[ i ++ ]; 41468 41469 } while ( key !== undefined ); 41470 41471 } else if ( value.toArray !== undefined ) { 41472 41473 // ...assume THREE.Math-ish 41474 41475 do { 41476 41477 value = key[ valuePropertyName ]; 41478 41479 if ( value !== undefined ) { 41480 41481 times.push( key.time ); 41482 value.toArray( values, values.length ); 41483 41484 } 41485 41486 key = jsonKeys[ i ++ ]; 41487 41488 } while ( key !== undefined ); 41489 41490 } else { 41491 41492 // otherwise push as-is 41493 41494 do { 41495 41496 value = key[ valuePropertyName ]; 41497 41498 if ( value !== undefined ) { 41499 41500 times.push( key.time ); 41501 values.push( value ); 41502 41503 } 41504 41505 key = jsonKeys[ i ++ ]; 41506 41507 } while ( key !== undefined ); 41508 41509 } 41510 41511} 41512 41513function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) { 41514 41515 const clip = sourceClip.clone(); 41516 41517 clip.name = name; 41518 41519 const tracks = []; 41520 41521 for ( let i = 0; i < clip.tracks.length; ++ i ) { 41522 41523 const track = clip.tracks[ i ]; 41524 const valueSize = track.getValueSize(); 41525 41526 const times = []; 41527 const values = []; 41528 41529 for ( let j = 0; j < track.times.length; ++ j ) { 41530 41531 const frame = track.times[ j ] * fps; 41532 41533 if ( frame < startFrame || frame >= endFrame ) continue; 41534 41535 times.push( track.times[ j ] ); 41536 41537 for ( let k = 0; k < valueSize; ++ k ) { 41538 41539 values.push( track.values[ j * valueSize + k ] ); 41540 41541 } 41542 41543 } 41544 41545 if ( times.length === 0 ) continue; 41546 41547 track.times = convertArray( times, track.times.constructor ); 41548 track.values = convertArray( values, track.values.constructor ); 41549 41550 tracks.push( track ); 41551 41552 } 41553 41554 clip.tracks = tracks; 41555 41556 // find minimum .times value across all tracks in the trimmed clip 41557 41558 let minStartTime = Infinity; 41559 41560 for ( let i = 0; i < clip.tracks.length; ++ i ) { 41561 41562 if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) { 41563 41564 minStartTime = clip.tracks[ i ].times[ 0 ]; 41565 41566 } 41567 41568 } 41569 41570 // shift all tracks such that clip begins at t=0 41571 41572 for ( let i = 0; i < clip.tracks.length; ++ i ) { 41573 41574 clip.tracks[ i ].shift( - 1 * minStartTime ); 41575 41576 } 41577 41578 clip.resetDuration(); 41579 41580 return clip; 41581 41582} 41583 41584function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) { 41585 41586 if ( fps <= 0 ) fps = 30; 41587 41588 const numTracks = referenceClip.tracks.length; 41589 const referenceTime = referenceFrame / fps; 41590 41591 // Make each track's values relative to the values at the reference frame 41592 for ( let i = 0; i < numTracks; ++ i ) { 41593 41594 const referenceTrack = referenceClip.tracks[ i ]; 41595 const referenceTrackType = referenceTrack.ValueTypeName; 41596 41597 // Skip this track if it's non-numeric 41598 if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue; 41599 41600 // Find the track in the target clip whose name and type matches the reference track 41601 const targetTrack = targetClip.tracks.find( function ( track ) { 41602 41603 return track.name === referenceTrack.name 41604 && track.ValueTypeName === referenceTrackType; 41605 41606 } ); 41607 41608 if ( targetTrack === undefined ) continue; 41609 41610 let referenceOffset = 0; 41611 const referenceValueSize = referenceTrack.getValueSize(); 41612 41613 if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { 41614 41615 referenceOffset = referenceValueSize / 3; 41616 41617 } 41618 41619 let targetOffset = 0; 41620 const targetValueSize = targetTrack.getValueSize(); 41621 41622 if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { 41623 41624 targetOffset = targetValueSize / 3; 41625 41626 } 41627 41628 const lastIndex = referenceTrack.times.length - 1; 41629 let referenceValue; 41630 41631 // Find the value to subtract out of the track 41632 if ( referenceTime <= referenceTrack.times[ 0 ] ) { 41633 41634 // Reference frame is earlier than the first keyframe, so just use the first keyframe 41635 const startIndex = referenceOffset; 41636 const endIndex = referenceValueSize - referenceOffset; 41637 referenceValue = referenceTrack.values.slice( startIndex, endIndex ); 41638 41639 } else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) { 41640 41641 // Reference frame is after the last keyframe, so just use the last keyframe 41642 const startIndex = lastIndex * referenceValueSize + referenceOffset; 41643 const endIndex = startIndex + referenceValueSize - referenceOffset; 41644 referenceValue = referenceTrack.values.slice( startIndex, endIndex ); 41645 41646 } else { 41647 41648 // Interpolate to the reference value 41649 const interpolant = referenceTrack.createInterpolant(); 41650 const startIndex = referenceOffset; 41651 const endIndex = referenceValueSize - referenceOffset; 41652 interpolant.evaluate( referenceTime ); 41653 referenceValue = interpolant.resultBuffer.slice( startIndex, endIndex ); 41654 41655 } 41656 41657 // Conjugate the quaternion 41658 if ( referenceTrackType === 'quaternion' ) { 41659 41660 const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate(); 41661 referenceQuat.toArray( referenceValue ); 41662 41663 } 41664 41665 // Subtract the reference value from all of the track values 41666 41667 const numTimes = targetTrack.times.length; 41668 for ( let j = 0; j < numTimes; ++ j ) { 41669 41670 const valueStart = j * targetValueSize + targetOffset; 41671 41672 if ( referenceTrackType === 'quaternion' ) { 41673 41674 // Multiply the conjugate for quaternion track types 41675 Quaternion.multiplyQuaternionsFlat( 41676 targetTrack.values, 41677 valueStart, 41678 referenceValue, 41679 0, 41680 targetTrack.values, 41681 valueStart 41682 ); 41683 41684 } else { 41685 41686 const valueEnd = targetValueSize - targetOffset * 2; 41687 41688 // Subtract each value for all other numeric track types 41689 for ( let k = 0; k < valueEnd; ++ k ) { 41690 41691 targetTrack.values[ valueStart + k ] -= referenceValue[ k ]; 41692 41693 } 41694 41695 } 41696 41697 } 41698 41699 } 41700 41701 targetClip.blendMode = AdditiveAnimationBlendMode; 41702 41703 return targetClip; 41704 41705} 41706 41707const AnimationUtils = { 41708 convertArray: convertArray, 41709 isTypedArray: isTypedArray, 41710 getKeyframeOrder: getKeyframeOrder, 41711 sortedArray: sortedArray, 41712 flattenJSON: flattenJSON, 41713 subclip: subclip, 41714 makeClipAdditive: makeClipAdditive 41715}; 41716 41717/** 41718 * Abstract base class of interpolants over parametric samples. 41719 * 41720 * The parameter domain is one dimensional, typically the time or a path 41721 * along a curve defined by the data. 41722 * 41723 * The sample values can have any dimensionality and derived classes may 41724 * apply special interpretations to the data. 41725 * 41726 * This class provides the interval seek in a Template Method, deferring 41727 * the actual interpolation to derived classes. 41728 * 41729 * Time complexity is O(1) for linear access crossing at most two points 41730 * and O(log N) for random access, where N is the number of positions. 41731 * 41732 * References: 41733 * 41734 * http://www.oodesign.com/template-method-pattern.html 41735 * 41736 */ 41737 41738class Interpolant { 41739 41740 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 41741 41742 this.parameterPositions = parameterPositions; 41743 this._cachedIndex = 0; 41744 41745 this.resultBuffer = resultBuffer !== undefined ? 41746 resultBuffer : new sampleValues.constructor( sampleSize ); 41747 this.sampleValues = sampleValues; 41748 this.valueSize = sampleSize; 41749 41750 this.settings = null; 41751 this.DefaultSettings_ = {}; 41752 41753 } 41754 41755 evaluate( t ) { 41756 41757 const pp = this.parameterPositions; 41758 let i1 = this._cachedIndex, 41759 t1 = pp[ i1 ], 41760 t0 = pp[ i1 - 1 ]; 41761 41762 validate_interval: { 41763 41764 seek: { 41765 41766 let right; 41767 41768 linear_scan: { 41769 41770 //- See http://jsperf.com/comparison-to-undefined/3 41771 //- slower code: 41772 //- 41773 //- if ( t >= t1 || t1 === undefined ) { 41774 forward_scan: if ( ! ( t < t1 ) ) { 41775 41776 for ( let giveUpAt = i1 + 2; ; ) { 41777 41778 if ( t1 === undefined ) { 41779 41780 if ( t < t0 ) break forward_scan; 41781 41782 // after end 41783 41784 i1 = pp.length; 41785 this._cachedIndex = i1; 41786 return this.copySampleValue_( i1 - 1 ); 41787 41788 } 41789 41790 if ( i1 === giveUpAt ) break; // this loop 41791 41792 t0 = t1; 41793 t1 = pp[ ++ i1 ]; 41794 41795 if ( t < t1 ) { 41796 41797 // we have arrived at the sought interval 41798 break seek; 41799 41800 } 41801 41802 } 41803 41804 // prepare binary search on the right side of the index 41805 right = pp.length; 41806 break linear_scan; 41807 41808 } 41809 41810 //- slower code: 41811 //- if ( t < t0 || t0 === undefined ) { 41812 if ( ! ( t >= t0 ) ) { 41813 41814 // looping? 41815 41816 const t1global = pp[ 1 ]; 41817 41818 if ( t < t1global ) { 41819 41820 i1 = 2; // + 1, using the scan for the details 41821 t0 = t1global; 41822 41823 } 41824 41825 // linear reverse scan 41826 41827 for ( let giveUpAt = i1 - 2; ; ) { 41828 41829 if ( t0 === undefined ) { 41830 41831 // before start 41832 41833 this._cachedIndex = 0; 41834 return this.copySampleValue_( 0 ); 41835 41836 } 41837 41838 if ( i1 === giveUpAt ) break; // this loop 41839 41840 t1 = t0; 41841 t0 = pp[ -- i1 - 1 ]; 41842 41843 if ( t >= t0 ) { 41844 41845 // we have arrived at the sought interval 41846 break seek; 41847 41848 } 41849 41850 } 41851 41852 // prepare binary search on the left side of the index 41853 right = i1; 41854 i1 = 0; 41855 break linear_scan; 41856 41857 } 41858 41859 // the interval is valid 41860 41861 break validate_interval; 41862 41863 } // linear scan 41864 41865 // binary search 41866 41867 while ( i1 < right ) { 41868 41869 const mid = ( i1 + right ) >>> 1; 41870 41871 if ( t < pp[ mid ] ) { 41872 41873 right = mid; 41874 41875 } else { 41876 41877 i1 = mid + 1; 41878 41879 } 41880 41881 } 41882 41883 t1 = pp[ i1 ]; 41884 t0 = pp[ i1 - 1 ]; 41885 41886 // check boundary cases, again 41887 41888 if ( t0 === undefined ) { 41889 41890 this._cachedIndex = 0; 41891 return this.copySampleValue_( 0 ); 41892 41893 } 41894 41895 if ( t1 === undefined ) { 41896 41897 i1 = pp.length; 41898 this._cachedIndex = i1; 41899 return this.copySampleValue_( i1 - 1 ); 41900 41901 } 41902 41903 } // seek 41904 41905 this._cachedIndex = i1; 41906 41907 this.intervalChanged_( i1, t0, t1 ); 41908 41909 } // validate_interval 41910 41911 return this.interpolate_( i1, t0, t, t1 ); 41912 41913 } 41914 41915 getSettings_() { 41916 41917 return this.settings || this.DefaultSettings_; 41918 41919 } 41920 41921 copySampleValue_( index ) { 41922 41923 // copies a sample value to the result buffer 41924 41925 const result = this.resultBuffer, 41926 values = this.sampleValues, 41927 stride = this.valueSize, 41928 offset = index * stride; 41929 41930 for ( let i = 0; i !== stride; ++ i ) { 41931 41932 result[ i ] = values[ offset + i ]; 41933 41934 } 41935 41936 return result; 41937 41938 } 41939 41940 // Template methods for derived classes: 41941 41942 interpolate_( /* i1, t0, t, t1 */ ) { 41943 41944 throw new Error( 'call to abstract method' ); 41945 // implementations shall return this.resultBuffer 41946 41947 } 41948 41949 intervalChanged_( /* i1, t0, t1 */ ) { 41950 41951 // empty 41952 41953 } 41954 41955} 41956 41957/** 41958 * Fast and simple cubic spline interpolant. 41959 * 41960 * It was derived from a Hermitian construction setting the first derivative 41961 * at each sample position to the linear slope between neighboring positions 41962 * over their parameter interval. 41963 */ 41964 41965class CubicInterpolant extends Interpolant { 41966 41967 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 41968 41969 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 41970 41971 this._weightPrev = - 0; 41972 this._offsetPrev = - 0; 41973 this._weightNext = - 0; 41974 this._offsetNext = - 0; 41975 41976 this.DefaultSettings_ = { 41977 41978 endingStart: ZeroCurvatureEnding, 41979 endingEnd: ZeroCurvatureEnding 41980 41981 }; 41982 41983 } 41984 41985 intervalChanged_( i1, t0, t1 ) { 41986 41987 const pp = this.parameterPositions; 41988 let iPrev = i1 - 2, 41989 iNext = i1 + 1, 41990 41991 tPrev = pp[ iPrev ], 41992 tNext = pp[ iNext ]; 41993 41994 if ( tPrev === undefined ) { 41995 41996 switch ( this.getSettings_().endingStart ) { 41997 41998 case ZeroSlopeEnding: 41999 42000 // f'(t0) = 0 42001 iPrev = i1; 42002 tPrev = 2 * t0 - t1; 42003 42004 break; 42005 42006 case WrapAroundEnding: 42007 42008 // use the other end of the curve 42009 iPrev = pp.length - 2; 42010 tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; 42011 42012 break; 42013 42014 default: // ZeroCurvatureEnding 42015 42016 // f''(t0) = 0 a.k.a. Natural Spline 42017 iPrev = i1; 42018 tPrev = t1; 42019 42020 } 42021 42022 } 42023 42024 if ( tNext === undefined ) { 42025 42026 switch ( this.getSettings_().endingEnd ) { 42027 42028 case ZeroSlopeEnding: 42029 42030 // f'(tN) = 0 42031 iNext = i1; 42032 tNext = 2 * t1 - t0; 42033 42034 break; 42035 42036 case WrapAroundEnding: 42037 42038 // use the other end of the curve 42039 iNext = 1; 42040 tNext = t1 + pp[ 1 ] - pp[ 0 ]; 42041 42042 break; 42043 42044 default: // ZeroCurvatureEnding 42045 42046 // f''(tN) = 0, a.k.a. Natural Spline 42047 iNext = i1 - 1; 42048 tNext = t0; 42049 42050 } 42051 42052 } 42053 42054 const halfDt = ( t1 - t0 ) * 0.5, 42055 stride = this.valueSize; 42056 42057 this._weightPrev = halfDt / ( t0 - tPrev ); 42058 this._weightNext = halfDt / ( tNext - t1 ); 42059 this._offsetPrev = iPrev * stride; 42060 this._offsetNext = iNext * stride; 42061 42062 } 42063 42064 interpolate_( i1, t0, t, t1 ) { 42065 42066 const result = this.resultBuffer, 42067 values = this.sampleValues, 42068 stride = this.valueSize, 42069 42070 o1 = i1 * stride, o0 = o1 - stride, 42071 oP = this._offsetPrev, oN = this._offsetNext, 42072 wP = this._weightPrev, wN = this._weightNext, 42073 42074 p = ( t - t0 ) / ( t1 - t0 ), 42075 pp = p * p, 42076 ppp = pp * p; 42077 42078 // evaluate polynomials 42079 42080 const sP = - wP * ppp + 2 * wP * pp - wP * p; 42081 const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1; 42082 const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p; 42083 const sN = wN * ppp - wN * pp; 42084 42085 // combine data linearly 42086 42087 for ( let i = 0; i !== stride; ++ i ) { 42088 42089 result[ i ] = 42090 sP * values[ oP + i ] + 42091 s0 * values[ o0 + i ] + 42092 s1 * values[ o1 + i ] + 42093 sN * values[ oN + i ]; 42094 42095 } 42096 42097 return result; 42098 42099 } 42100 42101} 42102 42103class LinearInterpolant extends Interpolant { 42104 42105 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 42106 42107 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 42108 42109 } 42110 42111 interpolate_( i1, t0, t, t1 ) { 42112 42113 const result = this.resultBuffer, 42114 values = this.sampleValues, 42115 stride = this.valueSize, 42116 42117 offset1 = i1 * stride, 42118 offset0 = offset1 - stride, 42119 42120 weight1 = ( t - t0 ) / ( t1 - t0 ), 42121 weight0 = 1 - weight1; 42122 42123 for ( let i = 0; i !== stride; ++ i ) { 42124 42125 result[ i ] = 42126 values[ offset0 + i ] * weight0 + 42127 values[ offset1 + i ] * weight1; 42128 42129 } 42130 42131 return result; 42132 42133 } 42134 42135} 42136 42137/** 42138 * 42139 * Interpolant that evaluates to the sample value at the position preceding 42140 * the parameter. 42141 */ 42142 42143class DiscreteInterpolant extends Interpolant { 42144 42145 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 42146 42147 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 42148 42149 } 42150 42151 interpolate_( i1 /*, t0, t, t1 */ ) { 42152 42153 return this.copySampleValue_( i1 - 1 ); 42154 42155 } 42156 42157} 42158 42159class KeyframeTrack { 42160 42161 constructor( name, times, values, interpolation ) { 42162 42163 if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); 42164 if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + n
vendor: 22,243 bytes, lines 42164-43354
42164ame ); 42165 42166 this.name = name; 42167 42168 this.times = convertArray( times, this.TimeBufferType ); 42169 this.values = convertArray( values, this.ValueBufferType ); 42170 42171 this.setInterpolation( interpolation || this.DefaultInterpolation ); 42172 42173 } 42174 42175 // Serialization (in static context, because of constructor invocation 42176 // and automatic invocation of .toJSON): 42177 42178 static toJSON( track ) { 42179 42180 const trackType = track.constructor; 42181 42182 let json; 42183 42184 // derived classes can define a static toJSON method 42185 if ( trackType.toJSON !== this.toJSON ) { 42186 42187 json = trackType.toJSON( track ); 42188 42189 } else { 42190 42191 // by default, we assume the data can be serialized as-is 42192 json = { 42193 42194 'name': track.name, 42195 'times': convertArray( track.times, Array ), 42196 'values': convertArray( track.values, Array ) 42197 42198 }; 42199 42200 const interpolation = track.getInterpolation(); 42201 42202 if ( interpolation !== track.DefaultInterpolation ) { 42203 42204 json.interpolation = interpolation; 42205 42206 } 42207 42208 } 42209 42210 json.type = track.ValueTypeName; // mandatory 42211 42212 return json; 42213 42214 } 42215 42216 InterpolantFactoryMethodDiscrete( result ) { 42217 42218 return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); 42219 42220 } 42221 42222 InterpolantFactoryMethodLinear( result ) { 42223 42224 return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); 42225 42226 } 42227 42228 InterpolantFactoryMethodSmooth( result ) { 42229 42230 return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); 42231 42232 } 42233 42234 setInterpolation( interpolation ) { 42235 42236 let factoryMethod; 42237 42238 switch ( interpolation ) { 42239 42240 case InterpolateDiscrete: 42241 42242 factoryMethod = this.InterpolantFactoryMethodDiscrete; 42243 42244 break; 42245 42246 case InterpolateLinear: 42247 42248 factoryMethod = this.InterpolantFactoryMethodLinear; 42249 42250 break; 42251 42252 case InterpolateSmooth: 42253 42254 factoryMethod = this.InterpolantFactoryMethodSmooth; 42255 42256 break; 42257 42258 } 42259 42260 if ( factoryMethod === undefined ) { 42261 42262 const message = 'unsupported interpolation for ' + 42263 this.ValueTypeName + ' keyframe track named ' + this.name; 42264 42265 if ( this.createInterpolant === undefined ) { 42266 42267 // fall back to default, unless the default itself is messed up 42268 if ( interpolation !== this.DefaultInterpolation ) { 42269 42270 this.setInterpolation( this.DefaultInterpolation ); 42271 42272 } else { 42273 42274 throw new Error( message ); // fatal, in this case 42275 42276 } 42277 42278 } 42279 42280 console.warn( 'THREE.KeyframeTrack:', message ); 42281 return this; 42282 42283 } 42284 42285 this.createInterpolant = factoryMethod; 42286 42287 return this; 42288 42289 } 42290 42291 getInterpolation() { 42292 42293 switch ( this.createInterpolant ) { 42294 42295 case this.InterpolantFactoryMethodDiscrete: 42296 42297 return InterpolateDiscrete; 42298 42299 case this.InterpolantFactoryMethodLinear: 42300 42301 return InterpolateLinear; 42302 42303 case this.InterpolantFactoryMethodSmooth: 42304 42305 return InterpolateSmooth; 42306 42307 } 42308 42309 } 42310 42311 getValueSize() { 42312 42313 return this.values.length / this.times.length; 42314 42315 } 42316 42317 // move all keyframes either forwards or backwards in time 42318 shift( timeOffset ) { 42319 42320 if ( timeOffset !== 0.0 ) { 42321 42322 const times = this.times; 42323 42324 for ( let i = 0, n = times.length; i !== n; ++ i ) { 42325 42326 times[ i ] += timeOffset; 42327 42328 } 42329 42330 } 42331 42332 return this; 42333 42334 } 42335 42336 // scale all keyframe times by a factor (useful for frame <-> seconds conversions) 42337 scale( timeScale ) { 42338 42339 if ( timeScale !== 1.0 ) { 42340 42341 const times = this.times; 42342 42343 for ( let i = 0, n = times.length; i !== n; ++ i ) { 42344 42345 times[ i ] *= timeScale; 42346 42347 } 42348 42349 } 42350 42351 return this; 42352 42353 } 42354 42355 // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. 42356 // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values 42357 trim( startTime, endTime ) { 42358 42359 const times = this.times, 42360 nKeys = times.length; 42361 42362 let from = 0, 42363 to = nKeys - 1; 42364 42365 while ( from !== nKeys && times[ from ] < startTime ) { 42366 42367 ++ from; 42368 42369 } 42370 42371 while ( to !== - 1 && times[ to ] > endTime ) { 42372 42373 -- to; 42374 42375 } 42376 42377 ++ to; // inclusive -> exclusive bound 42378 42379 if ( from !== 0 || to !== nKeys ) { 42380 42381 // empty tracks are forbidden, so keep at least one keyframe 42382 if ( from >= to ) { 42383 42384 to = Math.max( to, 1 ); 42385 from = to - 1; 42386 42387 } 42388 42389 const stride = this.getValueSize(); 42390 this.times = times.slice( from, to ); 42391 this.values = this.values.slice( from * stride, to * stride ); 42392 42393 } 42394 42395 return this; 42396 42397 } 42398 42399 // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable 42400 validate() { 42401 42402 let valid = true; 42403 42404 const valueSize = this.getValueSize(); 42405 if ( valueSize - Math.floor( valueSize ) !== 0 ) { 42406 42407 console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); 42408 valid = false; 42409 42410 } 42411 42412 const times = this.times, 42413 values = this.values, 42414 42415 nKeys = times.length; 42416 42417 if ( nKeys === 0 ) { 42418 42419 console.error( 'THREE.KeyframeTrack: Track is empty.', this ); 42420 valid = false; 42421 42422 } 42423 42424 let prevTime = null; 42425 42426 for ( let i = 0; i !== nKeys; i ++ ) { 42427 42428 const currTime = times[ i ]; 42429 42430 if ( typeof currTime === 'number' && isNaN( currTime ) ) { 42431 42432 console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); 42433 valid = false; 42434 break; 42435 42436 } 42437 42438 if ( prevTime !== null && prevTime > currTime ) { 42439 42440 console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); 42441 valid = false; 42442 break; 42443 42444 } 42445 42446 prevTime = currTime; 42447 42448 } 42449 42450 if ( values !== undefined ) { 42451 42452 if ( isTypedArray( values ) ) { 42453 42454 for ( let i = 0, n = values.length; i !== n; ++ i ) { 42455 42456 const value = values[ i ]; 42457 42458 if ( isNaN( value ) ) { 42459 42460 console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); 42461 valid = false; 42462 break; 42463 42464 } 42465 42466 } 42467 42468 } 42469 42470 } 42471 42472 return valid; 42473 42474 } 42475 42476 // removes equivalent sequential keys as common in morph target sequences 42477 // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) 42478 optimize() { 42479 42480 // times or values may be shared with other tracks, so overwriting is unsafe 42481 const times = this.times.slice(), 42482 values = this.values.slice(), 42483 stride = this.getValueSize(), 42484 42485 smoothInterpolation = this.getInterpolation() === InterpolateSmooth, 42486 42487 lastIndex = times.length - 1; 42488 42489 let writeIndex = 1; 42490 42491 for ( let i = 1; i < lastIndex; ++ i ) { 42492 42493 let keep = false; 42494 42495 const time = times[ i ]; 42496 const timeNext = times[ i + 1 ]; 42497 42498 // remove adjacent keyframes scheduled at the same time 42499 42500 if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) { 42501 42502 if ( ! smoothInterpolation ) { 42503 42504 // remove unnecessary keyframes same as their neighbors 42505 42506 const offset = i * stride, 42507 offsetP = offset - stride, 42508 offsetN = offset + stride; 42509 42510 for ( let j = 0; j !== stride; ++ j ) { 42511 42512 const value = values[ offset + j ]; 42513 42514 if ( value !== values[ offsetP + j ] || 42515 value !== values[ offsetN + j ] ) { 42516 42517 keep = true; 42518 break; 42519 42520 } 42521 42522 } 42523 42524 } else { 42525 42526 keep = true; 42527 42528 } 42529 42530 } 42531 42532 // in-place compaction 42533 42534 if ( keep ) { 42535 42536 if ( i !== writeIndex ) { 42537 42538 times[ writeIndex ] = times[ i ]; 42539 42540 const readOffset = i * stride, 42541 writeOffset = writeIndex * stride; 42542 42543 for ( let j = 0; j !== stride; ++ j ) { 42544 42545 values[ writeOffset + j ] = values[ readOffset + j ]; 42546 42547 } 42548 42549 } 42550 42551 ++ writeIndex; 42552 42553 } 42554 42555 } 42556 42557 // flush last keyframe (compaction looks ahead) 42558 42559 if ( lastIndex > 0 ) { 42560 42561 times[ writeIndex ] = times[ lastIndex ]; 42562 42563 for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { 42564 42565 values[ writeOffset + j ] = values[ readOffset + j ]; 42566 42567 } 42568 42569 ++ writeIndex; 42570 42571 } 42572 42573 if ( writeIndex !== times.length ) { 42574 42575 this.times = times.slice( 0, writeIndex ); 42576 this.values = values.slice( 0, writeIndex * stride ); 42577 42578 } else { 42579 42580 this.times = times; 42581 this.values = values; 42582 42583 } 42584 42585 return this; 42586 42587 } 42588 42589 clone() { 42590 42591 const times = this.times.slice(); 42592 const values = this.values.slice(); 42593 42594 const TypedKeyframeTrack = this.constructor; 42595 const track = new TypedKeyframeTrack( this.name, times, values ); 42596 42597 // Interpolant argument to constructor is not saved, so copy the factory method directly. 42598 track.createInterpolant = this.createInterpolant; 42599 42600 return track; 42601 42602 } 42603 42604} 42605 42606KeyframeTrack.prototype.TimeBufferType = Float32Array; 42607KeyframeTrack.prototype.ValueBufferType = Float32Array; 42608KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; 42609 42610/** 42611 * A Track of Boolean keyframe values. 42612 */ 42613class BooleanKeyframeTrack extends KeyframeTrack {} 42614 42615BooleanKeyframeTrack.prototype.ValueTypeName = 'bool'; 42616BooleanKeyframeTrack.prototype.ValueBufferType = Array; 42617BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; 42618BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; 42619BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; 42620 42621/** 42622 * A Track of keyframe values that represent color. 42623 */ 42624class ColorKeyframeTrack extends KeyframeTrack {} 42625 42626ColorKeyframeTrack.prototype.ValueTypeName = 'color'; 42627 42628/** 42629 * A Track of numeric keyframe values. 42630 */ 42631class NumberKeyframeTrack extends KeyframeTrack {} 42632 42633NumberKeyframeTrack.prototype.ValueTypeName = 'number'; 42634 42635/** 42636 * Spherical linear unit quaternion interpolant. 42637 */ 42638 42639class QuaternionLinearInterpolant extends Interpolant { 42640 42641 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 42642 42643 super( parameterPositions, sampleValues, sampleSize, resultBuffer ); 42644 42645 } 42646 42647 interpolate_( i1, t0, t, t1 ) { 42648 42649 const result = this.resultBuffer, 42650 values = this.sampleValues, 42651 stride = this.valueSize, 42652 42653 alpha = ( t - t0 ) / ( t1 - t0 ); 42654 42655 let offset = i1 * stride; 42656 42657 for ( let end = offset + stride; offset !== end; offset += 4 ) { 42658 42659 Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); 42660 42661 } 42662 42663 return result; 42664 42665 } 42666 42667} 42668 42669/** 42670 * A Track of quaternion keyframe values. 42671 */ 42672class QuaternionKeyframeTrack extends KeyframeTrack { 42673 42674 InterpolantFactoryMethodLinear( result ) { 42675 42676 return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); 42677 42678 } 42679 42680} 42681 42682QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion'; 42683// ValueBufferType is inherited 42684QuaternionKeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; 42685QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; 42686 42687/** 42688 * A Track that interpolates Strings 42689 */ 42690class StringKeyframeTrack extends KeyframeTrack {} 42691 42692StringKeyframeTrack.prototype.ValueTypeName = 'string'; 42693StringKeyframeTrack.prototype.ValueBufferType = Array; 42694StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; 42695StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; 42696StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; 42697 42698/** 42699 * A Track of vectored keyframe values. 42700 */ 42701class VectorKeyframeTrack extends KeyframeTrack {} 42702 42703VectorKeyframeTrack.prototype.ValueTypeName = 'vector'; 42704 42705class AnimationClip { 42706 42707 constructor( name, duration = - 1, tracks, blendMode = NormalAnimationBlendMode ) { 42708 42709 this.name = name; 42710 this.tracks = tracks; 42711 this.duration = duration; 42712 this.blendMode = blendMode; 42713 42714 this.uuid = generateUUID(); 42715 42716 // this means it should figure out its duration by scanning the tracks 42717 if ( this.duration < 0 ) { 42718 42719 this.resetDuration(); 42720 42721 } 42722 42723 } 42724 42725 42726 static parse( json ) { 42727 42728 const tracks = [], 42729 jsonTracks = json.tracks, 42730 frameTime = 1.0 / ( json.fps || 1.0 ); 42731 42732 for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) { 42733 42734 tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) ); 42735 42736 } 42737 42738 const clip = new this( json.name, json.duration, tracks, json.blendMode ); 42739 clip.uuid = json.uuid; 42740 42741 return clip; 42742 42743 } 42744 42745 static toJSON( clip ) { 42746 42747 const tracks = [], 42748 clipTracks = clip.tracks; 42749 42750 const json = { 42751 42752 'name': clip.name, 42753 'duration': clip.duration, 42754 'tracks': tracks, 42755 'uuid': clip.uuid, 42756 'blendMode': clip.blendMode 42757 42758 }; 42759 42760 for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) { 42761 42762 tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); 42763 42764 } 42765 42766 return json; 42767 42768 } 42769 42770 static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) { 42771 42772 const numMorphTargets = morphTargetSequence.length; 42773 const tracks = []; 42774 42775 for ( let i = 0; i < numMorphTargets; i ++ ) { 42776 42777 let times = []; 42778 let values = []; 42779 42780 times.push( 42781 ( i + numMorphTargets - 1 ) % numMorphTargets, 42782 i, 42783 ( i + 1 ) % numMorphTargets ); 42784 42785 values.push( 0, 1, 0 ); 42786 42787 const order = getKeyframeOrder( times ); 42788 times = sortedArray( times, 1, order ); 42789 values = sortedArray( values, 1, order ); 42790 42791 // if there is a key at the first frame, duplicate it as the 42792 // last frame as well for perfect loop. 42793 if ( ! noLoop && times[ 0 ] === 0 ) { 42794 42795 times.push( numMorphTargets ); 42796 values.push( values[ 0 ] ); 42797 42798 } 42799 42800 tracks.push( 42801 new NumberKeyframeTrack( 42802 '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', 42803 times, values 42804 ).scale( 1.0 / fps ) ); 42805 42806 } 42807 42808 return new this( name, - 1, tracks ); 42809 42810 } 42811 42812 static findByName( objectOrClipArray, name ) { 42813 42814 let clipArray = objectOrClipArray; 42815 42816 if ( ! Array.isArray( objectOrClipArray ) ) { 42817 42818 const o = objectOrClipArray; 42819 clipArray = o.geometry && o.geometry.animations || o.animations; 42820 42821 } 42822 42823 for ( let i = 0; i < clipArray.length; i ++ ) { 42824 42825 if ( clipArray[ i ].name === name ) { 42826 42827 return clipArray[ i ]; 42828 42829 } 42830 42831 } 42832 42833 return null; 42834 42835 } 42836 42837 static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) { 42838 42839 const animationToMorphTargets = {}; 42840 42841 // tested with https://regex101.com/ on trick sequences 42842 // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 42843 const pattern = /^([\w-]*?)([\d]+)$/; 42844 42845 // sort morph target names into animation groups based 42846 // patterns like Walk_001, Walk_002, Run_001, Run_002 42847 for ( let i = 0, il = morphTargets.length; i < il; i ++ ) { 42848 42849 const morphTarget = morphTargets[ i ]; 42850 const parts = morphTarget.name.match( pattern ); 42851 42852 if ( parts && parts.length > 1 ) { 42853 42854 const name = parts[ 1 ]; 42855 42856 let animationMorphTargets = animationToMorphTargets[ name ]; 42857 42858 if ( ! animationMorphTargets ) { 42859 42860 animationToMorphTargets[ name ] = animationMorphTargets = []; 42861 42862 } 42863 42864 animationMorphTargets.push( morphTarget ); 42865 42866 } 42867 42868 } 42869 42870 const clips = []; 42871 42872 for ( const name in animationToMorphTargets ) { 42873 42874 clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); 42875 42876 } 42877 42878 return clips; 42879 42880 } 42881 42882 // parse the animation.hierarchy format 42883 static parseAnimation( animation, bones ) { 42884 42885 if ( ! animation ) { 42886 42887 console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); 42888 return null; 42889 42890 } 42891 42892 const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { 42893 42894 // only return track if there are actually keys. 42895 if ( animationKeys.length !== 0 ) { 42896 42897 const times = []; 42898 const values = []; 42899 42900 flattenJSON( animationKeys, times, values, propertyName ); 42901 42902 // empty keys are filtered out, so check again 42903 if ( times.length !== 0 ) { 42904 42905 destTracks.push( new trackType( trackName, times, values ) ); 42906 42907 } 42908 42909 } 42910 42911 }; 42912 42913 const tracks = []; 42914 42915 const clipName = animation.name || 'default'; 42916 const fps = animation.fps || 30; 42917 const blendMode = animation.blendMode; 42918 42919 // automatic length determination in AnimationClip. 42920 let duration = animation.length || - 1; 42921 42922 const hierarchyTracks = animation.hierarchy || []; 42923 42924 for ( let h = 0; h < hierarchyTracks.length; h ++ ) { 42925 42926 const animationKeys = hierarchyTracks[ h ].keys; 42927 42928 // skip empty tracks 42929 if ( ! animationKeys || animationKeys.length === 0 ) continue; 42930 42931 // process morph targets 42932 if ( animationKeys[ 0 ].morphTargets ) { 42933 42934 // figure out all morph targets used in this track 42935 const morphTargetNames = {}; 42936 42937 let k; 42938 42939 for ( k = 0; k < animationKeys.length; k ++ ) { 42940 42941 if ( animationKeys[ k ].morphTargets ) { 42942 42943 for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { 42944 42945 morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; 42946 42947 } 42948 42949 } 42950 42951 } 42952 42953 // create a track for each morph target with all zero 42954 // morphTargetInfluences except for the keys in which 42955 // the morphTarget is named. 42956 for ( const morphTargetName in morphTargetNames ) { 42957 42958 const times = []; 42959 const values = []; 42960 42961 for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { 42962 42963 const animationKey = animationKeys[ k ]; 42964 42965 times.push( animationKey.time ); 42966 values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); 42967 42968 } 42969 42970 tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); 42971 42972 } 42973 42974 duration = morphTargetNames.length * fps; 42975 42976 } else { 42977 42978 // ...assume skeletal animation 42979 42980 const boneName = '.bones[' + bones[ h ].name + ']'; 42981 42982 addNonemptyTrack( 42983 VectorKeyframeTrack, boneName + '.position', 42984 animationKeys, 'pos', tracks ); 42985 42986 addNonemptyTrack( 42987 QuaternionKeyframeTrack, boneName + '.quaternion', 42988 animationKeys, 'rot', tracks ); 42989 42990 addNonemptyTrack( 42991 VectorKeyframeTrack, boneName + '.scale', 42992 animationKeys, 'scl', tracks ); 42993 42994 } 42995 42996 } 42997 42998 if ( tracks.length === 0 ) { 42999 43000 return null; 43001 43002 } 43003 43004 const clip = new this( clipName, duration, tracks, blendMode ); 43005 43006 return clip; 43007 43008 } 43009 43010 resetDuration() { 43011 43012 const tracks = this.tracks; 43013 let duration = 0; 43014 43015 for ( let i = 0, n = tracks.length; i !== n; ++ i ) { 43016 43017 const track = this.tracks[ i ]; 43018 43019 duration = Math.max( duration, track.times[ track.times.length - 1 ] ); 43020 43021 } 43022 43023 this.duration = duration; 43024 43025 return this; 43026 43027 } 43028 43029 trim() { 43030 43031 for ( let i = 0; i < this.tracks.length; i ++ ) { 43032 43033 this.tracks[ i ].trim( 0, this.duration ); 43034 43035 } 43036 43037 return this; 43038 43039 } 43040 43041 validate() { 43042 43043 let valid = true; 43044 43045 for ( let i = 0; i < this.tracks.length; i ++ ) { 43046 43047 valid = valid && this.tracks[ i ].validate(); 43048 43049 } 43050 43051 return valid; 43052 43053 } 43054 43055 optimize() { 43056 43057 for ( let i = 0; i < this.tracks.length; i ++ ) { 43058 43059 this.tracks[ i ].optimize(); 43060 43061 } 43062 43063 return this; 43064 43065 } 43066 43067 clone() { 43068 43069 const tracks = []; 43070 43071 for ( let i = 0; i < this.tracks.length; i ++ ) { 43072 43073 tracks.push( this.tracks[ i ].clone() ); 43074 43075 } 43076 43077 return new this.constructor( this.name, this.duration, tracks, this.blendMode ); 43078 43079 } 43080 43081 toJSON() { 43082 43083 return this.constructor.toJSON( this ); 43084 43085 } 43086 43087} 43088 43089function getTrackTypeForValueTypeName( typeName ) { 43090 43091 switch ( typeName.toLowerCase() ) { 43092 43093 case 'scalar': 43094 case 'double': 43095 case 'float': 43096 case 'number': 43097 case 'integer': 43098 43099 return NumberKeyframeTrack; 43100 43101 case 'vector': 43102 case 'vector2': 43103 case 'vector3': 43104 case 'vector4': 43105 43106 return VectorKeyframeTrack; 43107 43108 case 'color': 43109 43110 return ColorKeyframeTrack; 43111 43112 case 'quaternion': 43113 43114 return QuaternionKeyframeTrack; 43115 43116 case 'bool': 43117 case 'boolean': 43118 43119 return BooleanKeyframeTrack; 43120 43121 case 'string': 43122 43123 return StringKeyframeTrack; 43124 43125 } 43126 43127 throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); 43128 43129} 43130 43131function parseKeyframeTrack( json ) { 43132 43133 if ( json.type === undefined ) { 43134 43135 throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); 43136 43137 } 43138 43139 const trackType = getTrackTypeForValueTypeName( json.type ); 43140 43141 if ( json.times === undefined ) { 43142 43143 const times = [], values = []; 43144 43145 flattenJSON( json.keys, times, values, 'value' ); 43146 43147 json.times = times; 43148 json.values = values; 43149 43150 } 43151 43152 // derived classes can define a static parse method 43153 if ( trackType.parse !== undefined ) { 43154 43155 return trackType.parse( json ); 43156 43157 } else { 43158 43159 // by default, we assume a constructor compatible with the base 43160 return new trackType( json.name, json.times, json.values, json.interpolation ); 43161 43162 } 43163 43164} 43165 43166const Cache = { 43167 43168 enabled: false, 43169 43170 files: {}, 43171 43172 add: function ( key, file ) { 43173 43174 if ( this.enabled === false ) return; 43175 43176 // console.log( 'THREE.Cache', 'Adding key:', key ); 43177 43178 this.files[ key ] = file; 43179 43180 }, 43181 43182 get: function ( key ) { 43183 43184 if ( this.enabled === false ) return; 43185 43186 // console.log( 'THREE.Cache', 'Checking key:', key ); 43187 43188 return this.files[ key ]; 43189 43190 }, 43191 43192 remove: function ( key ) { 43193 43194 delete this.files[ key ]; 43195 43196 }, 43197 43198 clear: function () { 43199 43200 this.files = {}; 43201 43202 } 43203 43204}; 43205 43206class LoadingManager { 43207 43208 constructor( onLoad, onProgress, onError ) { 43209 43210 const scope = this; 43211 43212 let isLoading = false; 43213 let itemsLoaded = 0; 43214 let itemsTotal = 0; 43215 let urlModifier = undefined; 43216 const handlers = []; 43217 43218 // Refer to #5689 for the reason why we don't set .onStart 43219 // in the constructor 43220 43221 this.onStart = undefined; 43222 this.onLoad = onLoad; 43223 this.onProgress = onProgress; 43224 this.onError = onError; 43225 43226 this.itemStart = function ( url ) { 43227 43228 itemsTotal ++; 43229 43230 if ( isLoading === false ) { 43231 43232 if ( scope.onStart !== undefined ) { 43233 43234 scope.onStart( url, itemsLoaded, itemsTotal ); 43235 43236 } 43237 43238 } 43239 43240 isLoading = true; 43241 43242 }; 43243 43244 this.itemEnd = function ( url ) { 43245 43246 itemsLoaded ++; 43247 43248 if ( scope.onProgress !== undefined ) { 43249 43250 scope.onProgress( url, itemsLoaded, itemsTotal ); 43251 43252 } 43253 43254 if ( itemsLoaded === itemsTotal ) { 43255 43256 isLoading = false; 43257 43258 if ( scope.onLoad !== undefined ) { 43259 43260 scope.onLoad(); 43261 43262 } 43263 43264 } 43265 43266 }; 43267 43268 this.itemError = function ( url ) { 43269 43270 if ( scope.onError !== undefined ) { 43271 43272 scope.onError( url ); 43273 43274 } 43275 43276 }; 43277 43278 this.resolveURL = function ( url ) { 43279 43280 if ( urlModifier ) { 43281 43282 return urlModifier( url ); 43283 43284 } 43285 43286 return url; 43287 43288 }; 43289 43290 this.setURLModifier = function ( transform ) { 43291 43292 urlModifier = transform; 43293 43294 return this; 43295 43296 }; 43297 43298 this.addHandler = function ( regex, loader ) { 43299 43300 handlers.push( regex, loader ); 43301 43302 return this; 43303 43304 }; 43305 43306 this.removeHandler = function ( regex ) { 43307 43308 const index = handlers.indexOf( regex ); 43309 43310 if ( index !== - 1 ) { 43311 43312 handlers.splice( index, 2 ); 43313 43314 } 43315 43316 return this; 43317 43318 }; 43319 43320 this.getHandler = function ( file ) { 43321 43322 for ( let i = 0, l = handlers.length; i < l; i += 2 ) { 43323 43324 const regex = handlers[ i ]; 43325 const loader = handlers[ i + 1 ]; 43326 43327 if ( regex.global ) regex.lastIndex = 0; // see #17920 43328 43329 if ( regex.test( file ) ) { 43330 43331 return loader; 43332 43333 } 43334 43335 } 43336 43337 return null; 43338 43339 }; 43340 43341 } 43342 43343} 43344 43345const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager(); 43346 43347class Loader { 43348 43349 constructor( manager ) { 43350 43351 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 43352 43353 this.crossOrigin = 'anonymous'; 43354 this.withCredentials = false;
vendor: 12,888 bytes, lines 43355-44080
43355 this.path = ''; 43356 this.resourcePath = ''; 43357 this.requestHeader = {}; 43358 43359 } 43360 43361 load( /* url, onLoad, onProgress, onError */ ) {} 43362 43363 loadAsync( url, onProgress ) { 43364 43365 const scope = this; 43366 43367 return new Promise( function ( resolve, reject ) { 43368 43369 scope.load( url, resolve, onProgress, reject ); 43370 43371 } ); 43372 43373 } 43374 43375 parse( /* data */ ) {} 43376 43377 setCrossOrigin( crossOrigin ) { 43378 43379 this.crossOrigin = crossOrigin; 43380 return this; 43381 43382 } 43383 43384 setWithCredentials( value ) { 43385 43386 this.withCredentials = value; 43387 return this; 43388 43389 } 43390 43391 setPath( path ) { 43392 43393 this.path = path; 43394 return this; 43395 43396 } 43397 43398 setResourcePath( resourcePath ) { 43399 43400 this.resourcePath = resourcePath; 43401 return this; 43402 43403 } 43404 43405 setRequestHeader( requestHeader ) { 43406 43407 this.requestHeader = requestHeader; 43408 return this; 43409 43410 } 43411 43412} 43413 43414Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT'; 43415 43416const loading = {}; 43417 43418class HttpError extends Error { 43419 43420 constructor( message, response ) { 43421 43422 super( message ); 43423 this.response = response; 43424 43425 } 43426 43427} 43428 43429class FileLoader extends Loader { 43430 43431 constructor( manager ) { 43432 43433 super( manager ); 43434 43435 } 43436 43437 load( url, onLoad, onProgress, onError ) { 43438 43439 if ( url === undefined ) url = ''; 43440 43441 if ( this.path !== undefined ) url = this.path + url; 43442 43443 url = this.manager.resolveURL( url ); 43444 43445 const cached = Cache.get( url ); 43446 43447 if ( cached !== undefined ) { 43448 43449 this.manager.itemStart( url ); 43450 43451 setTimeout( () => { 43452 43453 if ( onLoad ) onLoad( cached ); 43454 43455 this.manager.itemEnd( url ); 43456 43457 }, 0 ); 43458 43459 return cached; 43460 43461 } 43462 43463 // Check if request is duplicate 43464 43465 if ( loading[ url ] !== undefined ) { 43466 43467 loading[ url ].push( { 43468 43469 onLoad: onLoad, 43470 onProgress: onProgress, 43471 onError: onError 43472 43473 } ); 43474 43475 return; 43476 43477 } 43478 43479 // Initialise array for duplicate requests 43480 loading[ url ] = []; 43481 43482 loading[ url ].push( { 43483 onLoad: onLoad, 43484 onProgress: onProgress, 43485 onError: onError, 43486 } ); 43487 43488 // create request 43489 const req = new Request( url, { 43490 headers: new Headers( this.requestHeader ), 43491 credentials: this.withCredentials ? 'include' : 'same-origin', 43492 // An abort controller could be added within a future PR 43493 } ); 43494 43495 // record states ( avoid data race ) 43496 const mimeType = this.mimeType; 43497 const responseType = this.responseType; 43498 43499 // start the fetch 43500 fetch( req ) 43501 .then( response => { 43502 43503 if ( response.status === 200 || response.status === 0 ) { 43504 43505 // Some browsers return HTTP Status 0 when using non-http protocol 43506 // e.g. 'file://' or 'data://'. Handle as success. 43507 43508 if ( response.status === 0 ) { 43509 43510 console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); 43511 43512 } 43513 43514 // Workaround: Checking if response.body === undefined for Alipay browser #23548 43515 43516 if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) { 43517 43518 return response; 43519 43520 } 43521 43522 const callbacks = loading[ url ]; 43523 const reader = response.body.getReader(); 43524 43525 // Nginx needs X-File-Size check 43526 // https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content 43527 const contentLength = response.headers.get( 'Content-Length' ) || response.headers.get( 'X-File-Size' ); 43528 const total = contentLength ? parseInt( contentLength ) : 0; 43529 const lengthComputable = total !== 0; 43530 let loaded = 0; 43531 43532 // periodically read data into the new stream tracking while download progress 43533 const stream = new ReadableStream( { 43534 start( controller ) { 43535 43536 readData(); 43537 43538 function readData() { 43539 43540 reader.read().then( ( { done, value } ) => { 43541 43542 if ( done ) { 43543 43544 controller.close(); 43545 43546 } else { 43547 43548 loaded += value.byteLength; 43549 43550 const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } ); 43551 for ( let i = 0, il = callbacks.length; i < il; i ++ ) { 43552 43553 const callback = callbacks[ i ]; 43554 if ( callback.onProgress ) callback.onProgress( event ); 43555 43556 } 43557 43558 controller.enqueue( value ); 43559 readData(); 43560 43561 } 43562 43563 } ); 43564 43565 } 43566 43567 } 43568 43569 } ); 43570 43571 return new Response( stream ); 43572 43573 } else { 43574 43575 throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response ); 43576 43577 } 43578 43579 } ) 43580 .then( response => { 43581 43582 switch ( responseType ) { 43583 43584 case 'arraybuffer': 43585 43586 return response.arrayBuffer(); 43587 43588 case 'blob': 43589 43590 return response.blob(); 43591 43592 case 'document': 43593 43594 return response.text() 43595 .then( text => { 43596 43597 const parser = new DOMParser(); 43598 return parser.parseFromString( text, mimeType ); 43599 43600 } ); 43601 43602 case 'json': 43603 43604 return response.json(); 43605 43606 default: 43607 43608 if ( mimeType === undefined ) { 43609 43610 return response.text(); 43611 43612 } else { 43613 43614 // sniff encoding 43615 const re = /charset="?([^;"\s]*)"?/i; 43616 const exec = re.exec( mimeType ); 43617 const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined; 43618 const decoder = new TextDecoder( label ); 43619 return response.arrayBuffer().then( ab => decoder.decode( ab ) ); 43620 43621 } 43622 43623 } 43624 43625 } ) 43626 .then( data => { 43627 43628 // Add to cache only on HTTP success, so that we do not cache 43629 // error response bodies as proper responses to requests. 43630 Cache.add( url, data ); 43631 43632 const callbacks = loading[ url ]; 43633 delete loading[ url ]; 43634 43635 for ( let i = 0, il = callbacks.length; i < il; i ++ ) { 43636 43637 const callback = callbacks[ i ]; 43638 if ( callback.onLoad ) callback.onLoad( data ); 43639 43640 } 43641 43642 } ) 43643 .catch( err => { 43644 43645 // Abort errors and other errors are handled the same 43646 43647 const callbacks = loading[ url ]; 43648 43649 if ( callbacks === undefined ) { 43650 43651 // When onLoad was called and url was deleted in `loading` 43652 this.manager.itemError( url ); 43653 throw err; 43654 43655 } 43656 43657 delete loading[ url ]; 43658 43659 for ( let i = 0, il = callbacks.length; i < il; i ++ ) { 43660 43661 const callback = callbacks[ i ]; 43662 if ( callback.onError ) callback.onError( err ); 43663 43664 } 43665 43666 this.manager.itemError( url ); 43667 43668 } ) 43669 .finally( () => { 43670 43671 this.manager.itemEnd( url ); 43672 43673 } ); 43674 43675 this.manager.itemStart( url ); 43676 43677 } 43678 43679 setResponseType( value ) { 43680 43681 this.responseType = value; 43682 return this; 43683 43684 } 43685 43686 setMimeType( value ) { 43687 43688 this.mimeType = value; 43689 return this; 43690 43691 } 43692 43693} 43694 43695class AnimationLoader extends Loader { 43696 43697 constructor( manager ) { 43698 43699 super( manager ); 43700 43701 } 43702 43703 load( url, onLoad, onProgress, onError ) { 43704 43705 const scope = this; 43706 43707 const loader = new FileLoader( this.manager ); 43708 loader.setPath( this.path ); 43709 loader.setRequestHeader( this.requestHeader ); 43710 loader.setWithCredentials( this.withCredentials ); 43711 loader.load( url, function ( text ) { 43712 43713 try { 43714 43715 onLoad( scope.parse( JSON.parse( text ) ) ); 43716 43717 } catch ( e ) { 43718 43719 if ( onError ) { 43720 43721 onError( e ); 43722 43723 } else { 43724 43725 console.error( e ); 43726 43727 } 43728 43729 scope.manager.itemError( url ); 43730 43731 } 43732 43733 }, onProgress, onError ); 43734 43735 } 43736 43737 parse( json ) { 43738 43739 const animations = []; 43740 43741 for ( let i = 0; i < json.length; i ++ ) { 43742 43743 const clip = AnimationClip.parse( json[ i ] ); 43744 43745 animations.push( clip ); 43746 43747 } 43748 43749 return animations; 43750 43751 } 43752 43753} 43754 43755/** 43756 * Abstract Base class to block based textures loader (dds, pvr, ...) 43757 * 43758 * Sub classes have to implement the parse() method which will be used in load(). 43759 */ 43760 43761class CompressedTextureLoader extends Loader { 43762 43763 constructor( manager ) { 43764 43765 super( manager ); 43766 43767 } 43768 43769 load( url, onLoad, onProgress, onError ) { 43770 43771 const scope = this; 43772 43773 const images = []; 43774 43775 const texture = new CompressedTexture(); 43776 43777 const loader = new FileLoader( this.manager ); 43778 loader.setPath( this.path ); 43779 loader.setResponseType( 'arraybuffer' ); 43780 loader.setRequestHeader( this.requestHeader ); 43781 loader.setWithCredentials( scope.withCredentials ); 43782 43783 let loaded = 0; 43784 43785 function loadTexture( i ) { 43786 43787 loader.load( url[ i ], function ( buffer ) { 43788 43789 const texDatas = scope.parse( buffer, true ); 43790 43791 images[ i ] = { 43792 width: texDatas.width, 43793 height: texDatas.height, 43794 format: texDatas.format, 43795 mipmaps: texDatas.mipmaps 43796 }; 43797 43798 loaded += 1; 43799 43800 if ( loaded === 6 ) { 43801 43802 if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter; 43803 43804 texture.image = images; 43805 texture.format = texDatas.format; 43806 texture.needsUpdate = true; 43807 43808 if ( onLoad ) onLoad( texture ); 43809 43810 } 43811 43812 }, onProgress, onError ); 43813 43814 } 43815 43816 if ( Array.isArray( url ) ) { 43817 43818 for ( let i = 0, il = url.length; i < il; ++ i ) { 43819 43820 loadTexture( i ); 43821 43822 } 43823 43824 } else { 43825 43826 // compressed cubemap texture stored in a single DDS file 43827 43828 loader.load( url, function ( buffer ) { 43829 43830 const texDatas = scope.parse( buffer, true ); 43831 43832 if ( texDatas.isCubemap ) { 43833 43834 const faces = texDatas.mipmaps.length / texDatas.mipmapCount; 43835 43836 for ( let f = 0; f < faces; f ++ ) { 43837 43838 images[ f ] = { mipmaps: [] }; 43839 43840 for ( let i = 0; i < texDatas.mipmapCount; i ++ ) { 43841 43842 images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] ); 43843 images[ f ].format = texDatas.format; 43844 images[ f ].width = texDatas.width; 43845 images[ f ].height = texDatas.height; 43846 43847 } 43848 43849 } 43850 43851 texture.image = images; 43852 43853 } else { 43854 43855 texture.image.width = texDatas.width; 43856 texture.image.height = texDatas.height; 43857 texture.mipmaps = texDatas.mipmaps; 43858 43859 } 43860 43861 if ( texDatas.mipmapCount === 1 ) { 43862 43863 texture.minFilter = LinearFilter; 43864 43865 } 43866 43867 texture.format = texDatas.format; 43868 texture.needsUpdate = true; 43869 43870 if ( onLoad ) onLoad( texture ); 43871 43872 }, onProgress, onError ); 43873 43874 } 43875 43876 return texture; 43877 43878 } 43879 43880} 43881 43882class ImageLoader extends Loader { 43883 43884 constructor( manager ) { 43885 43886 super( manager ); 43887 43888 } 43889 43890 load( url, onLoad, onProgress, onError ) { 43891 43892 if ( this.path !== undefined ) url = this.path + url; 43893 43894 url = this.manager.resolveURL( url ); 43895 43896 const scope = this; 43897 43898 const cached = Cache.get( url ); 43899 43900 if ( cached !== undefined ) { 43901 43902 scope.manager.itemStart( url ); 43903 43904 setTimeout( function () { 43905 43906 if ( onLoad ) onLoad( cached ); 43907 43908 scope.manager.itemEnd( url ); 43909 43910 }, 0 ); 43911 43912 return cached; 43913 43914 } 43915 43916 const image = createElementNS( 'img' ); 43917 43918 function onImageLoad() { 43919 43920 removeEventListeners(); 43921 43922 Cache.add( url, this ); 43923 43924 if ( onLoad ) onLoad( this ); 43925 43926 scope.manager.itemEnd( url ); 43927 43928 } 43929 43930 function onImageError( event ) { 43931 43932 removeEventListeners(); 43933 43934 if ( onError ) onError( event ); 43935 43936 scope.manager.itemError( url ); 43937 scope.manager.itemEnd( url ); 43938 43939 } 43940 43941 function removeEventListeners() { 43942 43943 image.removeEventListener( 'load', onImageLoad, false ); 43944 image.removeEventListener( 'error', onImageError, false ); 43945 43946 } 43947 43948 image.addEventListener( 'load', onImageLoad, false ); 43949 image.addEventListener( 'error', onImageError, false ); 43950 43951 if ( url.slice( 0, 5 ) !== 'data:' ) { 43952 43953 if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; 43954 43955 } 43956 43957 scope.manager.itemStart( url ); 43958 43959 image.src = url; 43960 43961 return image; 43962 43963 } 43964 43965} 43966 43967class CubeTextureLoader extends Loader { 43968 43969 constructor( manager ) { 43970 43971 super( manager ); 43972 43973 } 43974 43975 load( urls, onLoad, onProgress, onError ) { 43976 43977 const texture = new CubeTexture(); 43978 texture.colorSpace = SRGBColorSpace; 43979 43980 const loader = new ImageLoader( this.manager ); 43981 loader.setCrossOrigin( this.crossOrigin ); 43982 loader.setPath( this.path ); 43983 43984 let loaded = 0; 43985 43986 function loadTexture( i ) { 43987 43988 loader.load( urls[ i ], function ( image ) { 43989 43990 texture.images[ i ] = image; 43991 43992 loaded ++; 43993 43994 if ( loaded === 6 ) { 43995 43996 texture.needsUpdate = true; 43997 43998 if ( onLoad ) onLoad( texture ); 43999 44000 } 44001 44002 }, undefined, onError ); 44003 44004 } 44005 44006 for ( let i = 0; i < urls.length; ++ i ) { 44007 44008 loadTexture( i ); 44009 44010 } 44011 44012 return texture; 44013 44014 } 44015 44016} 44017 44018/** 44019 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) 44020 * 44021 * Sub classes have to implement the parse() method which will be used in load(). 44022 */ 44023 44024class DataTextureLoader extends Loader { 44025 44026 constructor( manager ) { 44027 44028 super( manager ); 44029 44030 } 44031 44032 load( url, onLoad, onProgress, onError ) { 44033 44034 const scope = this; 44035 44036 const texture = new DataTexture(); 44037 44038 const loader = new FileLoader( this.manager ); 44039 loader.setResponseType( 'arraybuffer' ); 44040 loader.setRequestHeader( this.requestHeader ); 44041 loader.setPath( this.path ); 44042 loader.setWithCredentials( scope.withCredentials ); 44043 loader.load( url, function ( buffer ) { 44044 44045 let texData; 44046 44047 try { 44048 44049 texData = scope.parse( buffer ); 44050 44051 } catch ( error ) { 44052 44053 if ( onError !== undefined ) { 44054 44055 onError( error ); 44056 44057 } else { 44058 44059 console.error( error ); 44060 return; 44061 44062 } 44063 44064 } 44065 44066 if ( texData.image !== undefined ) { 44067 44068 texture.image = texData.image; 44069 44070 } else if ( texData.data !== undefined ) { 44071 44072 texture.image.width = texData.width; 44073 texture.image.height = texData.height; 44074 texture.image.data = texData.data; 44075 44076 } 44077 44078 texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping; 44079 texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping; 44080
vendor: 5,067 bytes, lines 44081-44371
44081 texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter; 44082 texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter; 44083 44084 texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; 44085 44086 if ( texData.colorSpace !== undefined ) { 44087 44088 texture.colorSpace = texData.colorSpace; 44089 44090 } else if ( texData.encoding !== undefined ) { // @deprecated, r152 44091 44092 texture.encoding = texData.encoding; 44093 44094 } 44095 44096 if ( texData.flipY !== undefined ) { 44097 44098 texture.flipY = texData.flipY; 44099 44100 } 44101 44102 if ( texData.format !== undefined ) { 44103 44104 texture.format = texData.format; 44105 44106 } 44107 44108 if ( texData.type !== undefined ) { 44109 44110 texture.type = texData.type; 44111 44112 } 44113 44114 if ( texData.mipmaps !== undefined ) { 44115 44116 texture.mipmaps = texData.mipmaps; 44117 texture.minFilter = LinearMipmapLinearFilter; // presumably... 44118 44119 } 44120 44121 if ( texData.mipmapCount === 1 ) { 44122 44123 texture.minFilter = LinearFilter; 44124 44125 } 44126 44127 if ( texData.generateMipmaps !== undefined ) { 44128 44129 texture.generateMipmaps = texData.generateMipmaps; 44130 44131 } 44132 44133 texture.needsUpdate = true; 44134 44135 if ( onLoad ) onLoad( texture, texData ); 44136 44137 }, onProgress, onError ); 44138 44139 44140 return texture; 44141 44142 } 44143 44144} 44145 44146class TextureLoader extends Loader { 44147 44148 constructor( manager ) { 44149 44150 super( manager ); 44151 44152 } 44153 44154 load( url, onLoad, onProgress, onError ) { 44155 44156 const texture = new Texture(); 44157 44158 const loader = new ImageLoader( this.manager ); 44159 loader.setCrossOrigin( this.crossOrigin ); 44160 loader.setPath( this.path ); 44161 44162 loader.load( url, function ( image ) { 44163 44164 texture.image = image; 44165 texture.needsUpdate = true; 44166 44167 if ( onLoad !== undefined ) { 44168 44169 onLoad( texture ); 44170 44171 } 44172 44173 }, onProgress, onError ); 44174 44175 return texture; 44176 44177 } 44178 44179} 44180 44181class Light extends Object3D { 44182 44183 constructor( color, intensity = 1 ) { 44184 44185 super(); 44186 44187 this.isLight = true; 44188 44189 this.type = 'Light'; 44190 44191 this.color = new Color( color ); 44192 this.intensity = intensity; 44193 44194 } 44195 44196 dispose() { 44197 44198 // Empty here in base class; some subclasses override. 44199 44200 } 44201 44202 copy( source, recursive ) { 44203 44204 super.copy( source, recursive ); 44205 44206 this.color.copy( source.color ); 44207 this.intensity = source.intensity; 44208 44209 return this; 44210 44211 } 44212 44213 toJSON( meta ) { 44214 44215 const data = super.toJSON( meta ); 44216 44217 data.object.color = this.color.getHex(); 44218 data.object.intensity = this.intensity; 44219 44220 if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); 44221 44222 if ( this.distance !== undefined ) data.object.distance = this.distance; 44223 if ( this.angle !== undefined ) data.object.angle = this.angle; 44224 if ( this.decay !== undefined ) data.object.decay = this.decay; 44225 if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; 44226 44227 if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); 44228 44229 return data; 44230 44231 } 44232 44233} 44234 44235class HemisphereLight extends Light { 44236 44237 constructor( skyColor, groundColor, intensity ) { 44238 44239 super( skyColor, intensity ); 44240 44241 this.isHemisphereLight = true; 44242 44243 this.type = 'HemisphereLight'; 44244 44245 this.position.copy( Object3D.DEFAULT_UP ); 44246 this.updateMatrix(); 44247 44248 this.groundColor = new Color( groundColor ); 44249 44250 } 44251 44252 copy( source, recursive ) { 44253 44254 super.copy( source, recursive ); 44255 44256 this.groundColor.copy( source.groundColor ); 44257 44258 return this; 44259 44260 } 44261 44262} 44263 44264const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4(); 44265const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3(); 44266const _lookTarget$1 = /*@__PURE__*/ new Vector3(); 44267 44268class LightShadow { 44269 44270 constructor( camera ) { 44271 44272 this.camera = camera; 44273 44274 this.bias = 0; 44275 this.normalBias = 0; 44276 this.radius = 1; 44277 this.blurSamples = 8; 44278 44279 this.mapSize = new Vector2( 512, 512 ); 44280 44281 this.map = null; 44282 this.mapPass = null; 44283 this.matrix = new Matrix4(); 44284 44285 this.autoUpdate = true; 44286 this.needsUpdate = false; 44287 44288 this._frustum = new Frustum(); 44289 this._frameExtents = new Vector2( 1, 1 ); 44290 44291 this._viewportCount = 1; 44292 44293 this._viewports = [ 44294 44295 new Vector4( 0, 0, 1, 1 ) 44296 44297 ]; 44298 44299 } 44300 44301 getViewportCount() { 44302 44303 return this._viewportCount; 44304 44305 } 44306 44307 getFrustum() { 44308 44309 return this._frustum; 44310 44311 } 44312 44313 updateMatrices( light ) { 44314 44315 const shadowCamera = this.camera; 44316 const shadowMatrix = this.matrix; 44317 44318 _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld ); 44319 shadowCamera.position.copy( _lightPositionWorld$1 ); 44320 44321 _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld ); 44322 shadowCamera.lookAt( _lookTarget$1 ); 44323 shadowCamera.updateMatrixWorld(); 44324 44325 _projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); 44326 this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 ); 44327 44328 shadowMatrix.set( 44329 0.5, 0.0, 0.0, 0.5, 44330 0.0, 0.5, 0.0, 0.5, 44331 0.0, 0.0, 0.5, 0.5, 44332 0.0, 0.0, 0.0, 1.0 44333 ); 44334 44335 shadowMatrix.multiply( _projScreenMatrix$1 ); 44336 44337 } 44338 44339 getViewport( viewportIndex ) { 44340 44341 return this._viewports[ viewportIndex ]; 44342 44343 } 44344 44345 getFrameExtents() { 44346 44347 return this._frameExtents; 44348 44349 } 44350 44351 dispose() { 44352 44353 if ( this.map ) { 44354 44355 this.map.dispose(); 44356 44357 } 44358 44359 if ( this.mapPass ) { 44360 44361 this.mapPass.dispose(); 44362 44363 } 44364 44365 } 44366 44367 copy( source ) { 44368 44369 this.camera = source.camera.clone(); 44370 44371 this.bias = source.bias;
vendor: 5,709 bytes, lines 44372-44659
44372 this.radius = source.radius; 44373 44374 this.mapSize.copy( source.mapSize ); 44375 44376 return this; 44377 44378 } 44379 44380 clone() { 44381 44382 return new this.constructor().copy( this ); 44383 44384 } 44385 44386 toJSON() { 44387 44388 const object = {}; 44389 44390 if ( this.bias !== 0 ) object.bias = this.bias; 44391 if ( this.normalBias !== 0 ) object.normalBias = this.normalBias; 44392 if ( this.radius !== 1 ) object.radius = this.radius; 44393 if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray(); 44394 44395 object.camera = this.camera.toJSON( false ).object; 44396 delete object.camera.matrix; 44397 44398 return object; 44399 44400 } 44401 44402} 44403 44404class SpotLightShadow extends LightShadow { 44405 44406 constructor() { 44407 44408 super( new PerspectiveCamera( 50, 1, 0.5, 500 ) ); 44409 44410 this.isSpotLightShadow = true; 44411 44412 this.focus = 1; 44413 44414 } 44415 44416 updateMatrices( light ) { 44417 44418 const camera = this.camera; 44419 44420 const fov = RAD2DEG * 2 * light.angle * this.focus; 44421 const aspect = this.mapSize.width / this.mapSize.height; 44422 const far = light.distance || camera.far; 44423 44424 if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { 44425 44426 camera.fov = fov; 44427 camera.aspect = aspect; 44428 camera.far = far; 44429 camera.updateProjectionMatrix(); 44430 44431 } 44432 44433 super.updateMatrices( light ); 44434 44435 } 44436 44437 copy( source ) { 44438 44439 super.copy( source ); 44440 44441 this.focus = source.focus; 44442 44443 return this; 44444 44445 } 44446 44447} 44448 44449class SpotLight extends Light { 44450 44451 constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) { 44452 44453 super( color, intensity ); 44454 44455 this.isSpotLight = true; 44456 44457 this.type = 'SpotLight'; 44458 44459 this.position.copy( Object3D.DEFAULT_UP ); 44460 this.updateMatrix(); 44461 44462 this.target = new Object3D(); 44463 44464 this.distance = distance; 44465 this.angle = angle; 44466 this.penumbra = penumbra; 44467 this.decay = decay; 44468 44469 this.map = null; 44470 44471 this.shadow = new SpotLightShadow(); 44472 44473 } 44474 44475 get power() { 44476 44477 // compute the light's luminous power (in lumens) from its intensity (in candela) 44478 // by convention for a spotlight, luminous power (lm) = Ï * luminous intensity (cd) 44479 return this.intensity * Math.PI; 44480 44481 } 44482 44483 set power( power ) { 44484 44485 // set the light's intensity (in candela) from the desired luminous power (in lumens) 44486 this.intensity = power / Math.PI; 44487 44488 } 44489 44490 dispose() { 44491 44492 this.shadow.dispose(); 44493 44494 } 44495 44496 copy( source, recursive ) { 44497 44498 super.copy( source, recursive ); 44499 44500 this.distance = source.distance; 44501 this.angle = source.angle; 44502 this.penumbra = source.penumbra; 44503 this.decay = source.decay; 44504 44505 this.target = source.target.clone(); 44506 44507 this.shadow = source.shadow.clone(); 44508 44509 return this; 44510 44511 } 44512 44513} 44514 44515const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); 44516const _lightPositionWorld = /*@__PURE__*/ new Vector3(); 44517const _lookTarget = /*@__PURE__*/ new Vector3(); 44518 44519class PointLightShadow extends LightShadow { 44520 44521 constructor() { 44522 44523 super( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); 44524 44525 this.isPointLightShadow = true; 44526 44527 this._frameExtents = new Vector2( 4, 2 ); 44528 44529 this._viewportCount = 6; 44530 44531 this._viewports = [ 44532 // These viewports map a cube-map onto a 2D texture with the 44533 // following orientation: 44534 // 44535 // xzXZ 44536 // y Y 44537 // 44538 // X - Positive x direction 44539 // x - Negative x direction 44540 // Y - Positive y direction 44541 // y - Negative y direction 44542 // Z - Positive z direction 44543 // z - Negative z direction 44544 44545 // positive X 44546 new Vector4( 2, 1, 1, 1 ), 44547 // negative X 44548 new Vector4( 0, 1, 1, 1 ), 44549 // positive Z 44550 new Vector4( 3, 1, 1, 1 ), 44551 // negative Z 44552 new Vector4( 1, 1, 1, 1 ), 44553 // positive Y 44554 new Vector4( 3, 0, 1, 1 ), 44555 // negative Y 44556 new Vector4( 1, 0, 1, 1 ) 44557 ]; 44558 44559 this._cubeDirections = [ 44560 new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), 44561 new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) 44562 ]; 44563 44564 this._cubeUps = [ 44565 new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), 44566 new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) 44567 ]; 44568 44569 } 44570 44571 updateMatrices( light, viewportIndex = 0 ) { 44572 44573 const camera = this.camera; 44574 const shadowMatrix = this.matrix; 44575 44576 const far = light.distance || camera.far; 44577 44578 if ( far !== camera.far ) { 44579 44580 camera.far = far; 44581 camera.updateProjectionMatrix(); 44582 44583 } 44584 44585 _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); 44586 camera.position.copy( _lightPositionWorld ); 44587 44588 _lookTarget.copy( camera.position ); 44589 _lookTarget.add( this._cubeDirections[ viewportIndex ] ); 44590 camera.up.copy( this._cubeUps[ viewportIndex ] ); 44591 camera.lookAt( _lookTarget ); 44592 camera.updateMatrixWorld(); 44593 44594 shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); 44595 44596 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); 44597 this._frustum.setFromProjectionMatrix( _projScreenMatrix ); 44598 44599 } 44600 44601} 44602 44603class PointLight extends Light { 44604 44605 constructor( color, intensity, distance = 0, decay = 2 ) { 44606 44607 super( color, intensity ); 44608 44609 this.isPointLight = true; 44610 44611 this.type = 'PointLight'; 44612 44613 this.distance = distance; 44614 this.decay = decay; 44615 44616 this.shadow = new PointLightShadow(); 44617 44618 } 44619 44620 get power() { 44621 44622 // compute the light's luminous power (in lumens) from its intensity (in candela) 44623 // for an isotropic light source, luminous power (lm) = 4 Ï luminous intensity (cd) 44624 return this.intensity * 4 * Math.PI; 44625 44626 } 44627 44628 set power( power ) { 44629 44630 // set the light's intensity (in candela) from the desired luminous power (in lumens) 44631 this.intensity = power / ( 4 * Math.PI ); 44632 44633 } 44634 44635 dispose() { 44636 44637 this.shadow.dispose(); 44638 44639 } 44640 44641 copy( source, recursive ) { 44642 44643 super.copy( source, recursive ); 44644 44645 this.distance = source.distance; 44646 this.decay = source.decay; 44647 44648 this.shadow = source.shadow.clone(); 44649 44650 return this; 44651 44652 } 44653 44654} 44655 44656class DirectionalLightShadow extends LightShadow { 44657 44658 constructor() { 44659
vendor: 4,273 bytes, lines 44660-44881
44660 super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); 44661 44662 this.isDirectionalLightShadow = true; 44663 44664 } 44665 44666} 44667 44668class DirectionalLight extends Light { 44669 44670 constructor( color, intensity ) { 44671 44672 super( color, intensity ); 44673 44674 this.isDirectionalLight = true; 44675 44676 this.type = 'DirectionalLight'; 44677 44678 this.position.copy( Object3D.DEFAULT_UP ); 44679 this.updateMatrix(); 44680 44681 this.target = new Object3D(); 44682 44683 this.shadow = new DirectionalLightShadow(); 44684 44685 } 44686 44687 dispose() { 44688 44689 this.shadow.dispose(); 44690 44691 } 44692 44693 copy( source ) { 44694 44695 super.copy( source ); 44696 44697 this.target = source.target.clone(); 44698 this.shadow = source.shadow.clone(); 44699 44700 return this; 44701 44702 } 44703 44704} 44705 44706class AmbientLight extends Light { 44707 44708 constructor( color, intensity ) { 44709 44710 super( color, intensity ); 44711 44712 this.isAmbientLight = true; 44713 44714 this.type = 'AmbientLight'; 44715 44716 } 44717 44718} 44719 44720class RectAreaLight extends Light { 44721 44722 constructor( color, intensity, width = 10, height = 10 ) { 44723 44724 super( color, intensity ); 44725 44726 this.isRectAreaLight = true; 44727 44728 this.type = 'RectAreaLight'; 44729 44730 this.width = width; 44731 this.height = height; 44732 44733 } 44734 44735 get power() { 44736 44737 // compute the light's luminous power (in lumens) from its intensity (in nits) 44738 return this.intensity * this.width * this.height * Math.PI; 44739 44740 } 44741 44742 set power( power ) { 44743 44744 // set the light's intensity (in nits) from the desired luminous power (in lumens) 44745 this.intensity = power / ( this.width * this.height * Math.PI ); 44746 44747 } 44748 44749 copy( source ) { 44750 44751 super.copy( source ); 44752 44753 this.width = source.width; 44754 this.height = source.height; 44755 44756 return this; 44757 44758 } 44759 44760 toJSON( meta ) { 44761 44762 const data = super.toJSON( meta ); 44763 44764 data.object.width = this.width; 44765 data.object.height = this.height; 44766 44767 return data; 44768 44769 } 44770 44771} 44772 44773/** 44774 * Primary reference: 44775 * https://graphics.stanford.edu/papers/envmap/envmap.pdf 44776 * 44777 * Secondary reference: 44778 * https://www.ppsloan.org/publications/StupidSH36.pdf 44779 */ 44780 44781// 3-band SH defined by 9 coefficients 44782 44783class SphericalHarmonics3 { 44784 44785 constructor() { 44786 44787 this.isSphericalHarmonics3 = true; 44788 44789 this.coefficients = []; 44790 44791 for ( let i = 0; i < 9; i ++ ) { 44792 44793 this.coefficients.push( new Vector3() ); 44794 44795 } 44796 44797 } 44798 44799 set( coefficients ) { 44800 44801 for ( let i = 0; i < 9; i ++ ) { 44802 44803 this.coefficients[ i ].copy( coefficients[ i ] ); 44804 44805 } 44806 44807 return this; 44808 44809 } 44810 44811 zero() { 44812 44813 for ( let i = 0; i < 9; i ++ ) { 44814 44815 this.coefficients[ i ].set( 0, 0, 0 ); 44816 44817 } 44818 44819 return this; 44820 44821 } 44822 44823 // get the radiance in the direction of the normal 44824 // target is a Vector3 44825 getAt( normal, target ) { 44826 44827 // normal is assumed to be unit length 44828 44829 const x = normal.x, y = normal.y, z = normal.z; 44830 44831 const coeff = this.coefficients; 44832 44833 // band 0 44834 target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 ); 44835 44836 // band 1 44837 target.addScaledVector( coeff[ 1 ], 0.488603 * y ); 44838 target.addScaledVector( coeff[ 2 ], 0.488603 * z ); 44839 target.addScaledVector( coeff[ 3 ], 0.488603 * x ); 44840 44841 // band 2 44842 target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) ); 44843 target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) ); 44844 target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) ); 44845 target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) ); 44846 target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) ); 44847 44848 return target; 44849 44850 } 44851 44852 // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal 44853 // target is a Vector3 44854 // https://graphics.stanford.edu/papers/envmap/envmap.pdf 44855 getIrradianceAt( normal, target ) { 44856 44857 // normal is assumed to be unit length 44858 44859 const x = normal.x, y = normal.y, z = normal.z; 44860 44861 const coeff = this.coefficients; 44862 44863 // band 0 44864 target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // Ï * 0.282095 44865 44866 // band 1 44867 target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * Ï / 3 ) * 0.488603 44868 target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z ); 44869 target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x ); 44870 44871 // band 2 44872 target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( Ï / 4 ) * 1.092548 44873 target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z ); 44874 target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( Ï / 4 ) * 0.315392 * 3 44875 target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z ); 44876 target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( Ï / 4 ) * 0.546274 44877 44878 return target; 44879 44880 } 44881
vendor: 39,459 bytes, lines 44882-46521
44882 add( sh ) { 44883 44884 for ( let i = 0; i < 9; i ++ ) { 44885 44886 this.coefficients[ i ].add( sh.coefficients[ i ] ); 44887 44888 } 44889 44890 return this; 44891 44892 } 44893 44894 addScaledSH( sh, s ) { 44895 44896 for ( let i = 0; i < 9; i ++ ) { 44897 44898 this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s ); 44899 44900 } 44901 44902 return this; 44903 44904 } 44905 44906 scale( s ) { 44907 44908 for ( let i = 0; i < 9; i ++ ) { 44909 44910 this.coefficients[ i ].multiplyScalar( s ); 44911 44912 } 44913 44914 return this; 44915 44916 } 44917 44918 lerp( sh, alpha ) { 44919 44920 for ( let i = 0; i < 9; i ++ ) { 44921 44922 this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha ); 44923 44924 } 44925 44926 return this; 44927 44928 } 44929 44930 equals( sh ) { 44931 44932 for ( let i = 0; i < 9; i ++ ) { 44933 44934 if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) { 44935 44936 return false; 44937 44938 } 44939 44940 } 44941 44942 return true; 44943 44944 } 44945 44946 copy( sh ) { 44947 44948 return this.set( sh.coefficients ); 44949 44950 } 44951 44952 clone() { 44953 44954 return new this.constructor().copy( this ); 44955 44956 } 44957 44958 fromArray( array, offset = 0 ) { 44959 44960 const coefficients = this.coefficients; 44961 44962 for ( let i = 0; i < 9; i ++ ) { 44963 44964 coefficients[ i ].fromArray( array, offset + ( i * 3 ) ); 44965 44966 } 44967 44968 return this; 44969 44970 } 44971 44972 toArray( array = [], offset = 0 ) { 44973 44974 const coefficients = this.coefficients; 44975 44976 for ( let i = 0; i < 9; i ++ ) { 44977 44978 coefficients[ i ].toArray( array, offset + ( i * 3 ) ); 44979 44980 } 44981 44982 return array; 44983 44984 } 44985 44986 // evaluate the basis functions 44987 // shBasis is an Array[ 9 ] 44988 static getBasisAt( normal, shBasis ) { 44989 44990 // normal is assumed to be unit length 44991 44992 const x = normal.x, y = normal.y, z = normal.z; 44993 44994 // band 0 44995 shBasis[ 0 ] = 0.282095; 44996 44997 // band 1 44998 shBasis[ 1 ] = 0.488603 * y; 44999 shBasis[ 2 ] = 0.488603 * z; 45000 shBasis[ 3 ] = 0.488603 * x; 45001 45002 // band 2 45003 shBasis[ 4 ] = 1.092548 * x * y; 45004 shBasis[ 5 ] = 1.092548 * y * z; 45005 shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 ); 45006 shBasis[ 7 ] = 1.092548 * x * z; 45007 shBasis[ 8 ] = 0.546274 * ( x * x - y * y ); 45008 45009 } 45010 45011} 45012 45013class LightProbe extends Light { 45014 45015 constructor( sh = new SphericalHarmonics3(), intensity = 1 ) { 45016 45017 super( undefined, intensity ); 45018 45019 this.isLightProbe = true; 45020 45021 this.sh = sh; 45022 45023 } 45024 45025 copy( source ) { 45026 45027 super.copy( source ); 45028 45029 this.sh.copy( source.sh ); 45030 45031 return this; 45032 45033 } 45034 45035 fromJSON( json ) { 45036 45037 this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON(); 45038 this.sh.fromArray( json.sh ); 45039 45040 return this; 45041 45042 } 45043 45044 toJSON( meta ) { 45045 45046 const data = super.toJSON( meta ); 45047 45048 data.object.sh = this.sh.toArray(); 45049 45050 return data; 45051 45052 } 45053 45054} 45055 45056class MaterialLoader extends Loader { 45057 45058 constructor( manager ) { 45059 45060 super( manager ); 45061 this.textures = {}; 45062 45063 } 45064 45065 load( url, onLoad, onProgress, onError ) { 45066 45067 const scope = this; 45068 45069 const loader = new FileLoader( scope.manager ); 45070 loader.setPath( scope.path ); 45071 loader.setRequestHeader( scope.requestHeader ); 45072 loader.setWithCredentials( scope.withCredentials ); 45073 loader.load( url, function ( text ) { 45074 45075 try { 45076 45077 onLoad( scope.parse( JSON.parse( text ) ) ); 45078 45079 } catch ( e ) { 45080 45081 if ( onError ) { 45082 45083 onError( e ); 45084 45085 } else { 45086 45087 console.error( e ); 45088 45089 } 45090 45091 scope.manager.itemError( url ); 45092 45093 } 45094 45095 }, onProgress, onError ); 45096 45097 } 45098 45099 parse( json ) { 45100 45101 const textures = this.textures; 45102 45103 function getTexture( name ) { 45104 45105 if ( textures[ name ] === undefined ) { 45106 45107 console.warn( 'THREE.MaterialLoader: Undefined texture', name ); 45108 45109 } 45110 45111 return textures[ name ]; 45112 45113 } 45114 45115 const material = MaterialLoader.createMaterialFromType( json.type ); 45116 45117 if ( json.uuid !== undefined ) material.uuid = json.uuid; 45118 if ( json.name !== undefined ) material.name = json.name; 45119 if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color ); 45120 if ( json.roughness !== undefined ) material.roughness = json.roughness; 45121 if ( json.metalness !== undefined ) material.metalness = json.metalness; 45122 if ( json.sheen !== undefined ) material.sheen = json.sheen; 45123 if ( json.sheenColor !== undefined ) material.sheenColor = new Color().setHex( json.sheenColor ); 45124 if ( json.sheenRoughness !== undefined ) material.sheenRoughness = json.sheenRoughness; 45125 if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive ); 45126 if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular ); 45127 if ( json.specularIntensity !== undefined ) material.specularIntensity = json.specularIntensity; 45128 if ( json.specularColor !== undefined && material.specularColor !== undefined ) material.specularColor.setHex( json.specularColor ); 45129 if ( json.shininess !== undefined ) material.shininess = json.shininess; 45130 if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat; 45131 if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness; 45132 if ( json.iridescence !== undefined ) material.iridescence = json.iridescence; 45133 if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR; 45134 if ( json.iridescenceThicknessRange !== undefined ) material.iridescenceThicknessRange = json.iridescenceThicknessRange; 45135 if ( json.transmission !== undefined ) material.transmission = json.transmission; 45136 if ( json.thickness !== undefined ) material.thickness = json.thickness; 45137 if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance; 45138 if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor ); 45139 if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy; 45140 if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation; 45141 if ( json.fog !== undefined ) material.fog = json.fog; 45142 if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; 45143 if ( json.blending !== undefined ) material.blending = json.blending; 45144 if ( json.combine !== undefined ) material.combine = json.combine; 45145 if ( json.side !== undefined ) material.side = json.side; 45146 if ( json.shadowSide !== undefined ) material.shadowSide = json.shadowSide; 45147 if ( json.opacity !== undefined ) material.opacity = json.opacity; 45148 if ( json.transparent !== undefined ) material.transparent = json.transparent; 45149 if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest; 45150 if ( json.alphaHash !== undefined ) material.alphaHash = json.alphaHash; 45151 if ( json.depthFunc !== undefined ) material.depthFunc = json.depthFunc; 45152 if ( json.depthTest !== undefined ) material.depthTest = json.depthTest; 45153 if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite; 45154 if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite; 45155 if ( json.blendSrc !== undefined ) material.blendSrc = json.blendSrc; 45156 if ( json.blendDst !== undefined ) material.blendDst = json.blendDst; 45157 if ( json.blendEquation !== undefined ) material.blendEquation = json.blendEquation; 45158 if ( json.blendSrcAlpha !== undefined ) material.blendSrcAlpha = json.blendSrcAlpha; 45159 if ( json.blendDstAlpha !== undefined ) material.blendDstAlpha = json.blendDstAlpha; 45160 if ( json.blendEquationAlpha !== undefined ) material.blendEquationAlpha = json.blendEquationAlpha; 45161 if ( json.blendColor !== undefined && material.blendColor !== undefined ) material.blendColor.setHex( json.blendColor ); 45162 if ( json.blendAlpha !== undefined ) material.blendAlpha = json.blendAlpha; 45163 if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask; 45164 if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc; 45165 if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef; 45166 if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask; 45167 if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail; 45168 if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail; 45169 if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass; 45170 if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite; 45171 45172 if ( json.wireframe !== undefined ) material.wireframe = json.wireframe; 45173 if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth; 45174 if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap; 45175 if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin; 45176 45177 if ( json.rotation !== undefined ) material.rotation = json.rotation; 45178 45179 if ( json.linewidth !== undefined ) material.linewidth = json.linewidth; 45180 if ( json.dashSize !== undefined ) material.dashSize = json.dashSize; 45181 if ( json.gapSize !== undefined ) material.gapSize = json.gapSize; 45182 if ( json.scale !== undefined ) material.scale = json.scale; 45183 45184 if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset; 45185 if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor; 45186 if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits; 45187 45188 if ( json.dithering !== undefined ) material.dithering = json.dithering; 45189 45190 if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage; 45191 if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha; 45192 if ( json.forceSinglePass !== undefined ) material.forceSinglePass = json.forceSinglePass; 45193 45194 if ( json.visible !== undefined ) material.visible = json.visible; 45195 45196 if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped; 45197 45198 if ( json.userData !== undefined ) material.userData = json.userData; 45199 45200 if ( json.vertexColors !== undefined ) { 45201 45202 if ( typeof json.vertexColors === 'number' ) { 45203 45204 material.vertexColors = ( json.vertexColors > 0 ) ? true : false; 45205 45206 } else { 45207 45208 material.vertexColors = json.vertexColors; 45209 45210 } 45211 45212 } 45213 45214 // Shader Material 45215 45216 if ( json.uniforms !== undefined ) { 45217 45218 for ( const name in json.uniforms ) { 45219 45220 const uniform = json.uniforms[ name ]; 45221 45222 material.uniforms[ name ] = {}; 45223 45224 switch ( uniform.type ) { 45225 45226 case 't': 45227 material.uniforms[ name ].value = getTexture( uniform.value ); 45228 break; 45229 45230 case 'c': 45231 material.uniforms[ name ].value = new Color().setHex( uniform.value ); 45232 break; 45233 45234 case 'v2': 45235 material.uniforms[ name ].value = new Vector2().fromArray( uniform.value ); 45236 break; 45237 45238 case 'v3': 45239 material.uniforms[ name ].value = new Vector3().fromArray( uniform.value ); 45240 break; 45241 45242 case 'v4': 45243 material.uniforms[ name ].value = new Vector4().fromArray( uniform.value ); 45244 break; 45245 45246 case 'm3': 45247 material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value ); 45248 break; 45249 45250 case 'm4': 45251 material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value ); 45252 break; 45253 45254 default: 45255 material.uniforms[ name ].value = uniform.value; 45256 45257 } 45258 45259 } 45260 45261 } 45262 45263 if ( json.defines !== undefined ) material.defines = json.defines; 45264 if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader; 45265 if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; 45266 if ( json.glslVersion !== undefined ) material.glslVersion = json.glslVersion; 45267 45268 if ( json.extensions !== undefined ) { 45269 45270 for ( const key in json.extensions ) { 45271 45272 material.extensions[ key ] = json.extensions[ key ]; 45273 45274 } 45275 45276 } 45277 45278 if ( json.lights !== undefined ) material.lights = json.lights; 45279 if ( json.clipping !== undefined ) material.clipping = json.clipping; 45280 45281 // for PointsMaterial 45282 45283 if ( json.size !== undefined ) material.size = json.size; 45284 if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation; 45285 45286 // maps 45287 45288 if ( json.map !== undefined ) material.map = getTexture( json.map ); 45289 if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap ); 45290 45291 if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap ); 45292 45293 if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap ); 45294 if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale; 45295 45296 if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap ); 45297 if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType; 45298 if ( json.normalScale !== undefined ) { 45299 45300 let normalScale = json.normalScale; 45301 45302 if ( Array.isArray( normalScale ) === false ) { 45303 45304 // Blender exporter used to export a scalar. See #7459 45305 45306 normalScale = [ normalScale, normalScale ]; 45307 45308 } 45309 45310 material.normalScale = new Vector2().fromArray( normalScale ); 45311 45312 } 45313 45314 if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap ); 45315 if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale; 45316 if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias; 45317 45318 if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap ); 45319 if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap ); 45320 45321 if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap ); 45322 if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity; 45323 45324 if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap ); 45325 if ( json.specularIntensityMap !== undefined ) material.specularIntensityMap = getTexture( json.specularIntensityMap ); 45326 if ( json.specularColorMap !== undefined ) material.specularColorMap = getTexture( json.specularColorMap ); 45327 45328 if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap ); 45329 if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity; 45330 45331 if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity; 45332 if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio; 45333 45334 if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap ); 45335 if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity; 45336 45337 if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap ); 45338 if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity; 45339 45340 if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap ); 45341 45342 if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap ); 45343 if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap ); 45344 if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap ); 45345 if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale ); 45346 45347 if ( json.iridescenceMap !== undefined ) material.iridescenceMap = getTexture( json.iridescenceMap ); 45348 if ( json.iridescenceThicknessMap !== undefined ) material.iridescenceThicknessMap = getTexture( json.iridescenceThicknessMap ); 45349 45350 if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap ); 45351 if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap ); 45352 45353 if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap ); 45354 45355 if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap ); 45356 if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap ); 45357 45358 return material; 45359 45360 } 45361 45362 setTextures( value ) { 45363 45364 this.textures = value; 45365 return this; 45366 45367 } 45368 45369 static createMaterialFromType( type ) { 45370 45371 const materialLib = { 45372 ShadowMaterial, 45373 SpriteMaterial, 45374 RawShaderMaterial, 45375 ShaderMaterial, 45376 PointsMaterial, 45377 MeshPhysicalMaterial, 45378 MeshStandardMaterial, 45379 MeshPhongMaterial, 45380 MeshToonMaterial, 45381 MeshNormalMaterial, 45382 MeshLambertMaterial, 45383 MeshDepthMaterial, 45384 MeshDistanceMaterial, 45385 MeshBasicMaterial, 45386 MeshMatcapMaterial, 45387 LineDashedMaterial, 45388 LineBasicMaterial, 45389 Material 45390 }; 45391 45392 return new materialLib[ type ](); 45393 45394 } 45395 45396} 45397 45398class LoaderUtils { 45399 45400 static decodeText( array ) { 45401 45402 if ( typeof TextDecoder !== 'undefined' ) { 45403 45404 return new TextDecoder().decode( array ); 45405 45406 } 45407 45408 // Avoid the String.fromCharCode.apply(null, array) shortcut, which 45409 // throws a "maximum call stack size exceeded" error for large arrays. 45410 45411 let s = ''; 45412 45413 for ( let i = 0, il = array.length; i < il; i ++ ) { 45414 45415 // Implicitly assumes little-endian. 45416 s += String.fromCharCode( array[ i ] ); 45417 45418 } 45419 45420 try { 45421 45422 // merges multi-byte utf-8 characters. 45423 45424 return decodeURIComponent( escape( s ) ); 45425 45426 } catch ( e ) { // see #16358 45427 45428 return s; 45429 45430 } 45431 45432 } 45433 45434 static extractUrlBase( url ) { 45435 45436 const index = url.lastIndexOf( '/' ); 45437 45438 if ( index === - 1 ) return './'; 45439 45440 return url.slice( 0, index + 1 ); 45441 45442 } 45443 45444 static resolveURL( url, path ) { 45445 45446 // Invalid URL 45447 if ( typeof url !== 'string' || url === '' ) return ''; 45448 45449 // Host Relative URL 45450 if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) { 45451 45452 path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' ); 45453 45454 } 45455 45456 // Absolute URL http://,https://,// 45457 if ( /^(https?:)?\/\//i.test( url ) ) return url; 45458 45459 // Data URI 45460 if ( /^data:.*,.*$/i.test( url ) ) return url; 45461 45462 // Blob URL 45463 if ( /^blob:.*$/i.test( url ) ) return url; 45464 45465 // Relative URL 45466 return path + url; 45467 45468 } 45469 45470} 45471 45472class InstancedBufferGeometry extends BufferGeometry { 45473 45474 constructor() { 45475 45476 super(); 45477 45478 this.isInstancedBufferGeometry = true; 45479 45480 this.type = 'InstancedBufferGeometry'; 45481 this.instanceCount = Infinity; 45482 45483 } 45484 45485 copy( source ) { 45486 45487 super.copy( source ); 45488 45489 this.instanceCount = source.instanceCount; 45490 45491 return this; 45492 45493 } 45494 45495 toJSON() { 45496 45497 const data = super.toJSON(); 45498 45499 data.instanceCount = this.instanceCount; 45500 45501 data.isInstancedBufferGeometry = true; 45502 45503 return data; 45504 45505 } 45506 45507} 45508 45509class BufferGeometryLoader extends Loader { 45510 45511 constructor( manager ) { 45512 45513 super( manager ); 45514 45515 } 45516 45517 load( url, onLoad, onProgress, onError ) { 45518 45519 const scope = this; 45520 45521 const loader = new FileLoader( scope.manager ); 45522 loader.setPath( scope.path ); 45523 loader.setRequestHeader( scope.requestHeader ); 45524 loader.setWithCredentials( scope.withCredentials ); 45525 loader.load( url, function ( text ) { 45526 45527 try { 45528 45529 onLoad( scope.parse( JSON.parse( text ) ) ); 45530 45531 } catch ( e ) { 45532 45533 if ( onError ) { 45534 45535 onError( e ); 45536 45537 } else { 45538 45539 console.error( e ); 45540 45541 } 45542 45543 scope.manager.itemError( url ); 45544 45545 } 45546 45547 }, onProgress, onError ); 45548 45549 } 45550 45551 parse( json ) { 45552 45553 const interleavedBufferMap = {}; 45554 const arrayBufferMap = {}; 45555 45556 function getInterleavedBuffer( json, uuid ) { 45557 45558 if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ]; 45559 45560 const interleavedBuffers = json.interleavedBuffers; 45561 const interleavedBuffer = interleavedBuffers[ uuid ]; 45562 45563 const buffer = getArrayBuffer( json, interleavedBuffer.buffer ); 45564 45565 const array = getTypedArray( interleavedBuffer.type, buffer ); 45566 const ib = new InterleavedBuffer( array, interleavedBuffer.stride ); 45567 ib.uuid = interleavedBuffer.uuid; 45568 45569 interleavedBufferMap[ uuid ] = ib; 45570 45571 return ib; 45572 45573 } 45574 45575 function getArrayBuffer( json, uuid ) { 45576 45577 if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ]; 45578 45579 const arrayBuffers = json.arrayBuffers; 45580 const arrayBuffer = arrayBuffers[ uuid ]; 45581 45582 const ab = new Uint32Array( arrayBuffer ).buffer; 45583 45584 arrayBufferMap[ uuid ] = ab; 45585 45586 return ab; 45587 45588 } 45589 45590 const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry(); 45591 45592 const index = json.data.index; 45593 45594 if ( index !== undefined ) { 45595 45596 const typedArray = getTypedArray( index.type, index.array ); 45597 geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); 45598 45599 } 45600 45601 const attributes = json.data.attributes; 45602 45603 for ( const key in attributes ) { 45604 45605 const attribute = attributes[ key ]; 45606 let bufferAttribute; 45607 45608 if ( attribute.isInterleavedBufferAttribute ) { 45609 45610 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); 45611 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); 45612 45613 } else { 45614 45615 const typedArray = getTypedArray( attribute.type, attribute.array ); 45616 const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute; 45617 bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized ); 45618 45619 } 45620 45621 if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; 45622 if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage ); 45623 45624 geometry.setAttribute( key, bufferAttribute ); 45625 45626 } 45627 45628 const morphAttributes = json.data.morphAttributes; 45629 45630 if ( morphAttributes ) { 45631 45632 for ( const key in morphAttributes ) { 45633 45634 const attributeArray = morphAttributes[ key ]; 45635 45636 const array = []; 45637 45638 for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { 45639 45640 const attribute = attributeArray[ i ]; 45641 let bufferAttribute; 45642 45643 if ( attribute.isInterleavedBufferAttribute ) { 45644 45645 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); 45646 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); 45647 45648 } else { 45649 45650 const typedArray = getTypedArray( attribute.type, attribute.array ); 45651 bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ); 45652 45653 } 45654 45655 if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; 45656 array.push( bufferAttribute ); 45657 45658 } 45659 45660 geometry.morphAttributes[ key ] = array; 45661 45662 } 45663 45664 } 45665 45666 const morphTargetsRelative = json.data.morphTargetsRelative; 45667 45668 if ( morphTargetsRelative ) { 45669 45670 geometry.morphTargetsRelative = true; 45671 45672 } 45673 45674 const groups = json.data.groups || json.data.drawcalls || json.data.offsets; 45675 45676 if ( groups !== undefined ) { 45677 45678 for ( let i = 0, n = groups.length; i !== n; ++ i ) { 45679 45680 const group = groups[ i ]; 45681 45682 geometry.addGroup( group.start, group.count, group.materialIndex ); 45683 45684 } 45685 45686 } 45687 45688 const boundingSphere = json.data.boundingSphere; 45689 45690 if ( boundingSphere !== undefined ) { 45691 45692 const center = new Vector3(); 45693 45694 if ( boundingSphere.center !== undefined ) { 45695 45696 center.fromArray( boundingSphere.center ); 45697 45698 } 45699 45700 geometry.boundingSphere = new Sphere( center, boundingSphere.radius ); 45701 45702 } 45703 45704 if ( json.name ) geometry.name = json.name; 45705 if ( json.userData ) geometry.userData = json.userData; 45706 45707 return geometry; 45708 45709 } 45710 45711} 45712 45713class ObjectLoader extends Loader { 45714 45715 constructor( manager ) { 45716 45717 super( manager ); 45718 45719 } 45720 45721 load( url, onLoad, onProgress, onError ) { 45722 45723 const scope = this; 45724 45725 const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; 45726 this.resourcePath = this.resourcePath || path; 45727 45728 const loader = new FileLoader( this.manager ); 45729 loader.setPath( this.path ); 45730 loader.setRequestHeader( this.requestHeader ); 45731 loader.setWithCredentials( this.withCredentials ); 45732 loader.load( url, function ( text ) { 45733 45734 let json = null; 45735 45736 try { 45737 45738 json = JSON.parse( text ); 45739 45740 } catch ( error ) { 45741 45742 if ( onError !== undefined ) onError( error ); 45743 45744 console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); 45745 45746 return; 45747 45748 } 45749 45750 const metadata = json.metadata; 45751 45752 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { 45753 45754 if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) ); 45755 45756 console.error( 'THREE.ObjectLoader: Can\'t load ' + url ); 45757 return; 45758 45759 } 45760 45761 scope.parse( json, onLoad ); 45762 45763 }, onProgress, onError ); 45764 45765 } 45766 45767 async loadAsync( url, onProgress ) { 45768 45769 const scope = this; 45770 45771 const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; 45772 this.resourcePath = this.resourcePath || path; 45773 45774 const loader = new FileLoader( this.manager ); 45775 loader.setPath( this.path ); 45776 loader.setRequestHeader( this.requestHeader ); 45777 loader.setWithCredentials( this.withCredentials ); 45778 45779 const text = await loader.loadAsync( url, onProgress ); 45780 45781 const json = JSON.parse( text ); 45782 45783 const metadata = json.metadata; 45784 45785 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { 45786 45787 throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url ); 45788 45789 } 45790 45791 return await scope.parseAsync( json ); 45792 45793 } 45794 45795 parse( json, onLoad ) { 45796 45797 const animations = this.parseAnimations( json.animations ); 45798 const shapes = this.parseShapes( json.shapes ); 45799 const geometries = this.parseGeometries( json.geometries, shapes ); 45800 45801 const images = this.parseImages( json.images, function () { 45802 45803 if ( onLoad !== undefined ) onLoad( object ); 45804 45805 } ); 45806 45807 const textures = this.parseTextures( json.textures, images ); 45808 const materials = this.parseMaterials( json.materials, textures ); 45809 45810 const object = this.parseObject( json.object, geometries, materials, textures, animations ); 45811 const skeletons = this.parseSkeletons( json.skeletons, object ); 45812 45813 this.bindSkeletons( object, skeletons ); 45814 45815 // 45816 45817 if ( onLoad !== undefined ) { 45818 45819 let hasImages = false; 45820 45821 for ( const uuid in images ) { 45822 45823 if ( images[ uuid ].data instanceof HTMLImageElement ) { 45824 45825 hasImages = true; 45826 break; 45827 45828 } 45829 45830 } 45831 45832 if ( hasImages === false ) onLoad( object ); 45833 45834 } 45835 45836 return object; 45837 45838 } 45839 45840 async parseAsync( json ) { 45841 45842 const animations = this.parseAnimations( json.animations ); 45843 const shapes = this.parseShapes( json.shapes ); 45844 const geometries = this.parseGeometries( json.geometries, shapes ); 45845 45846 const images = await this.parseImagesAsync( json.images ); 45847 45848 const textures = this.parseTextures( json.textures, images ); 45849 const materials = this.parseMaterials( json.materials, textures ); 45850 45851 const object = this.parseObject( json.object, geometries, materials, textures, animations ); 45852 const skeletons = this.parseSkeletons( json.skeletons, object ); 45853 45854 this.bindSkeletons( object, skeletons ); 45855 45856 return object; 45857 45858 } 45859 45860 parseShapes( json ) { 45861 45862 const shapes = {}; 45863 45864 if ( json !== undefined ) { 45865 45866 for ( let i = 0, l = json.length; i < l; i ++ ) { 45867 45868 const shape = new Shape().fromJSON( json[ i ] ); 45869 45870 shapes[ shape.uuid ] = shape; 45871 45872 } 45873 45874 } 45875 45876 return shapes; 45877 45878 } 45879 45880 parseSkeletons( json, object ) { 45881 45882 const skeletons = {}; 45883 const bones = {}; 45884 45885 // generate bone lookup table 45886 45887 object.traverse( function ( child ) { 45888 45889 if ( child.isBone ) bones[ child.uuid ] = child; 45890 45891 } ); 45892 45893 // create skeletons 45894 45895 if ( json !== undefined ) { 45896 45897 for ( let i = 0, l = json.length; i < l; i ++ ) { 45898 45899 const skeleton = new Skeleton().fromJSON( json[ i ], bones ); 45900 45901 skeletons[ skeleton.uuid ] = skeleton; 45902 45903 } 45904 45905 } 45906 45907 return skeletons; 45908 45909 } 45910 45911 parseGeometries( json, shapes ) { 45912 45913 const geometries = {}; 45914 45915 if ( json !== undefined ) { 45916 45917 const bufferGeometryLoader = new BufferGeometryLoader(); 45918 45919 for ( let i = 0, l = json.length; i < l; i ++ ) { 45920 45921 let geometry; 45922 const data = json[ i ]; 45923 45924 switch ( data.type ) { 45925 45926 case 'BufferGeometry': 45927 case 'InstancedBufferGeometry': 45928 45929 geometry = bufferGeometryLoader.parse( data ); 45930 break; 45931 45932 default: 45933 45934 if ( data.type in Geometries ) { 45935 45936 geometry = Geometries[ data.type ].fromJSON( data, shapes ); 45937 45938 } else { 45939 45940 console.warn( `THREE.ObjectLoader: Unsupported geometry type "${ data.type }"` ); 45941 45942 } 45943 45944 } 45945 45946 geometry.uuid = data.uuid; 45947 45948 if ( data.name !== undefined ) geometry.name = data.name; 45949 if ( data.userData !== undefined ) geometry.userData = data.userData; 45950 45951 geometries[ data.uuid ] = geometry; 45952 45953 } 45954 45955 } 45956 45957 return geometries; 45958 45959 } 45960 45961 parseMaterials( json, textures ) { 45962 45963 const cache = {}; // MultiMaterial 45964 const materials = {}; 45965 45966 if ( json !== undefined ) { 45967 45968 const loader = new MaterialLoader(); 45969 loader.setTextures( textures ); 45970 45971 for ( let i = 0, l = json.length; i < l; i ++ ) { 45972 45973 const data = json[ i ]; 45974 45975 if ( cache[ data.uuid ] === undefined ) { 45976 45977 cache[ data.uuid ] = loader.parse( data ); 45978 45979 } 45980 45981 materials[ data.uuid ] = cache[ data.uuid ]; 45982 45983 } 45984 45985 } 45986 45987 return materials; 45988 45989 } 45990 45991 parseAnimations( json ) { 45992 45993 const animations = {}; 45994 45995 if ( json !== undefined ) { 45996 45997 for ( let i = 0; i < json.length; i ++ ) { 45998 45999 const data = json[ i ]; 46000 46001 const clip = AnimationClip.parse( data ); 46002 46003 animations[ clip.uuid ] = clip; 46004 46005 } 46006 46007 } 46008 46009 return animations; 46010 46011 } 46012 46013 parseImages( json, onLoad ) { 46014 46015 const scope = this; 46016 const images = {}; 46017 46018 let loader; 46019 46020 function loadImage( url ) { 46021 46022 scope.manager.itemStart( url ); 46023 46024 return loader.load( url, function () { 46025 46026 scope.manager.itemEnd( url ); 46027 46028 }, undefined, function () { 46029 46030 scope.manager.itemError( url ); 46031 scope.manager.itemEnd( url ); 46032 46033 } ); 46034 46035 } 46036 46037 function deserializeImage( image ) { 46038 46039 if ( typeof image === 'string' ) { 46040 46041 const url = image; 46042 46043 const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; 46044 46045 return loadImage( path ); 46046 46047 } else { 46048 46049 if ( image.data ) { 46050 46051 return { 46052 data: getTypedArray( image.type, image.data ), 46053 width: image.width, 46054 height: image.height 46055 }; 46056 46057 } else { 46058 46059 return null; 46060 46061 } 46062 46063 } 46064 46065 } 46066 46067 if ( json !== undefined && json.length > 0 ) { 46068 46069 const manager = new LoadingManager( onLoad ); 46070 46071 loader = new ImageLoader( manager ); 46072 loader.setCrossOrigin( this.crossOrigin ); 46073 46074 for ( let i = 0, il = json.length; i < il; i ++ ) { 46075 46076 const image = json[ i ]; 46077 const url = image.url; 46078 46079 if ( Array.isArray( url ) ) { 46080 46081 // load array of images e.g CubeTexture 46082 46083 const imageArray = []; 46084 46085 for ( let j = 0, jl = url.length; j < jl; j ++ ) { 46086 46087 const currentUrl = url[ j ]; 46088 46089 const deserializedImage = deserializeImage( currentUrl ); 46090 46091 if ( deserializedImage !== null ) { 46092 46093 if ( deserializedImage instanceof HTMLImageElement ) { 46094 46095 imageArray.push( deserializedImage ); 46096 46097 } else { 46098 46099 // special case: handle array of data textures for cube textures 46100 46101 imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); 46102 46103 } 46104 46105 } 46106 46107 } 46108 46109 images[ image.uuid ] = new Source( imageArray ); 46110 46111 } else { 46112 46113 // load single image 46114 46115 const deserializedImage = deserializeImage( image.url ); 46116 images[ image.uuid ] = new Source( deserializedImage ); 46117 46118 46119 } 46120 46121 } 46122 46123 } 46124 46125 return images; 46126 46127 } 46128 46129 async parseImagesAsync( json ) { 46130 46131 const scope = this; 46132 const images = {}; 46133 46134 let loader; 46135 46136 async function deserializeImage( image ) { 46137 46138 if ( typeof image === 'string' ) { 46139 46140 const url = image; 46141 46142 const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; 46143 46144 return await loader.loadAsync( path ); 46145 46146 } else { 46147 46148 if ( image.data ) { 46149 46150 return { 46151 data: getTypedArray( image.type, image.data ), 46152 width: image.width, 46153 height: image.height 46154 }; 46155 46156 } else { 46157 46158 return null; 46159 46160 } 46161 46162 } 46163 46164 } 46165 46166 if ( json !== undefined && json.length > 0 ) { 46167 46168 loader = new ImageLoader( this.manager ); 46169 loader.setCrossOrigin( this.crossOrigin ); 46170 46171 for ( let i = 0, il = json.length; i < il; i ++ ) { 46172 46173 const image = json[ i ]; 46174 const url = image.url; 46175 46176 if ( Array.isArray( url ) ) { 46177 46178 // load array of images e.g CubeTexture 46179 46180 const imageArray = []; 46181 46182 for ( let j = 0, jl = url.length; j < jl; j ++ ) { 46183 46184 const currentUrl = url[ j ]; 46185 46186 const deserializedImage = await deserializeImage( currentUrl ); 46187 46188 if ( deserializedImage !== null ) { 46189 46190 if ( deserializedImage instanceof HTMLImageElement ) { 46191 46192 imageArray.push( deserializedImage ); 46193 46194 } else { 46195 46196 // special case: handle array of data textures for cube textures 46197 46198 imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); 46199 46200 } 46201 46202 } 46203 46204 } 46205 46206 images[ image.uuid ] = new Source( imageArray ); 46207 46208 } else { 46209 46210 // load single image 46211 46212 const deserializedImage = await deserializeImage( image.url ); 46213 images[ image.uuid ] = new Source( deserializedImage ); 46214 46215 } 46216 46217 } 46218 46219 } 46220 46221 return images; 46222 46223 } 46224 46225 parseTextures( json, images ) { 46226 46227 function parseConstant( value, type ) { 46228 46229 if ( typeof value === 'number' ) return value; 46230 46231 console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); 46232 46233 return type[ value ]; 46234 46235 } 46236 46237 const textures = {}; 46238 46239 if ( json !== undefined ) { 46240 46241 for ( let i = 0, l = json.length; i < l; i ++ ) { 46242 46243 const data = json[ i ]; 46244 46245 if ( data.image === undefined ) { 46246 46247 console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); 46248 46249 } 46250 46251 if ( images[ data.image ] === undefined ) { 46252 46253 console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); 46254 46255 } 46256 46257 const source = images[ data.image ]; 46258 const image = source.data; 46259 46260 let texture; 46261 46262 if ( Array.isArray( image ) ) { 46263 46264 texture = new CubeTexture(); 46265 46266 if ( image.length === 6 ) texture.needsUpdate = true; 46267 46268 } else { 46269 46270 if ( image && image.data ) { 46271 46272 texture = new DataTexture(); 46273 46274 } else { 46275 46276 texture = new Texture(); 46277 46278 } 46279 46280 if ( image ) texture.needsUpdate = true; // textures can have undefined image data 46281 46282 } 46283 46284 texture.source = source; 46285 46286 texture.uuid = data.uuid; 46287 46288 if ( data.name !== undefined ) texture.name = data.name; 46289 46290 if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); 46291 if ( data.channel !== undefined ) texture.channel = data.channel; 46292 46293 if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); 46294 if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); 46295 if ( data.center !== undefined ) texture.center.fromArray( data.center ); 46296 if ( data.rotation !== undefined ) texture.rotation = data.rotation; 46297 46298 if ( data.wrap !== undefined ) { 46299 46300 texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); 46301 texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); 46302 46303 } 46304 46305 if ( data.format !== undefined ) texture.format = data.format; 46306 if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat; 46307 if ( data.type !== undefined ) texture.type = data.type; 46308 if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace; 46309 if ( data.encoding !== undefined ) texture.encoding = data.encoding; // @deprecated, r152 46310 46311 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); 46312 if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); 46313 if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy; 46314 46315 if ( data.flipY !== undefined ) texture.flipY = data.flipY; 46316 46317 if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps; 46318 if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha; 46319 if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment; 46320 if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction; 46321 46322 if ( data.userData !== undefined ) texture.userData = data.userData; 46323 46324 textures[ data.uuid ] = texture; 46325 46326 } 46327 46328 } 46329 46330 return textures; 46331 46332 } 46333 46334 parseObject( data, geometries, materials, textures, animations ) { 46335 46336 let object; 46337 46338 function getGeometry( name ) { 46339 46340 if ( geometries[ name ] === undefined ) { 46341 46342 console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); 46343 46344 } 46345 46346 return geometries[ name ]; 46347 46348 } 46349 46350 function getMaterial( name ) { 46351 46352 if ( name === undefined ) return undefined; 46353 46354 if ( Array.isArray( name ) ) { 46355 46356 const array = []; 46357 46358 for ( let i = 0, l = name.length; i < l; i ++ ) { 46359 46360 const uuid = name[ i ]; 46361 46362 if ( materials[ uuid ] === undefined ) { 46363 46364 console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); 46365 46366 } 46367 46368 array.push( materials[ uuid ] ); 46369 46370 } 46371 46372 return array; 46373 46374 } 46375 46376 if ( materials[ name ] === undefined ) { 46377 46378 console.warn( 'THREE.ObjectLoader: Undefined material', name ); 46379 46380 } 46381 46382 return materials[ name ]; 46383 46384 } 46385 46386 function getTexture( uuid ) { 46387 46388 if ( textures[ uuid ] === undefined ) { 46389 46390 console.warn( 'THREE.ObjectLoader: Undefined texture', uuid ); 46391 46392 } 46393 46394 return textures[ uuid ]; 46395 46396 } 46397 46398 let geometry, material; 46399 46400 switch ( data.type ) { 46401 46402 case 'Scene': 46403 46404 object = new Scene(); 46405 46406 if ( data.background !== undefined ) { 46407 46408 if ( Number.isInteger( data.background ) ) { 46409 46410 object.background = new Color( data.background ); 46411 46412 } else { 46413 46414 object.background = getTexture( data.background ); 46415 46416 } 46417 46418 } 46419 46420 if ( data.environment !== undefined ) { 46421 46422 object.environment = getTexture( data.environment ); 46423 46424 } 46425 46426 if ( data.fog !== undefined ) { 46427 46428 if ( data.fog.type === 'Fog' ) { 46429 46430 object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); 46431 46432 } else if ( data.fog.type === 'FogExp2' ) { 46433 46434 object.fog = new FogExp2( data.fog.color, data.fog.density ); 46435 46436 } 46437 46438 if ( data.fog.name !== '' ) { 46439 46440 object.fog.name = data.fog.name; 46441 46442 } 46443 46444 } 46445 46446 if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness; 46447 if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity; 46448 46449 break; 46450 46451 case 'PerspectiveCamera': 46452 46453 object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); 46454 46455 if ( data.focus !== undefined ) object.focus = data.focus; 46456 if ( data.zoom !== undefined ) object.zoom = data.zoom; 46457 if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge; 46458 if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset; 46459 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); 46460 46461 break; 46462 46463 case 'OrthographicCamera': 46464 46465 object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); 46466 46467 if ( data.zoom !== undefined ) object.zoom = data.zoom; 46468 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); 46469 46470 break; 46471 46472 case 'AmbientLight': 46473 46474 object = new AmbientLight( data.color, data.intensity ); 46475 46476 break; 46477 46478 case 'DirectionalLight': 46479 46480 object = new DirectionalLight( data.color, data.intensity ); 46481 46482 break; 46483 46484 case 'PointLight': 46485 46486 object = new PointLight( data.color, data.intensity, data.distance, data.decay ); 46487 46488 break; 46489 46490 case 'RectAreaLight': 46491 46492 object = new RectAreaLight( data.color, data.intensity, data.width, data.height ); 46493 46494 break; 46495 46496 case 'SpotLight': 46497 46498 object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay ); 46499 46500 break; 46501 46502 case 'HemisphereLight': 46503 46504 object = new HemisphereLight( data.color, data.groundColor, data.intensity ); 46505 46506 break; 46507 46508 case 'LightProbe': 46509 46510 object = new LightProbe().fromJSON( data ); 46511 46512 break; 46513 46514 case 'SkinnedMesh': 46515 46516 geometry = getGeometry( data.geometry ); 46517 material = getMaterial( data.material ); 46518 46519 object = new SkinnedMesh( geometry, material ); 46520 46521 if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
vendor: 17,451 bytes, lines 46522-47352
46522 if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix ); 46523 if ( data.skeleton !== undefined ) object.skeleton = data.skeleton; 46524 46525 break; 46526 46527 case 'Mesh': 46528 46529 geometry = getGeometry( data.geometry ); 46530 material = getMaterial( data.material ); 46531 46532 object = new Mesh( geometry, material ); 46533 46534 break; 46535 46536 case 'InstancedMesh': 46537 46538 geometry = getGeometry( data.geometry ); 46539 material = getMaterial( data.material ); 46540 const count = data.count; 46541 const instanceMatrix = data.instanceMatrix; 46542 const instanceColor = data.instanceColor; 46543 46544 object = new InstancedMesh( geometry, material, count ); 46545 object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 ); 46546 if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize ); 46547 46548 break; 46549 46550 case 'BatchedMesh': 46551 46552 geometry = getGeometry( data.geometry ); 46553 material = getMaterial( data.material ); 46554 46555 object = new BatchedMesh( data.maxGeometryCount, data.maxVertexCount, data.maxIndexCount, material ); 46556 object.geometry = geometry; 46557 object.perObjectFrustumCulled = data.perObjectFrustumCulled; 46558 object.sortObjects = data.sortObjects; 46559 46560 object._drawRanges = data.drawRanges; 46561 object._reservedRanges = data.reservedRanges; 46562 46563 object._visibility = data.visibility; 46564 object._active = data.active; 46565 object._bounds = data.bounds.map( bound => { 46566 46567 const box = new Box3(); 46568 box.min.fromArray( bound.boxMin ); 46569 box.max.fromArray( bound.boxMax ); 46570 46571 const sphere = new Sphere(); 46572 sphere.radius = bound.sphereRadius; 46573 sphere.center.fromArray( bound.sphereCenter ); 46574 46575 return { 46576 boxInitialized: bound.boxInitialized, 46577 box: box, 46578 46579 sphereInitialized: bound.sphereInitialized, 46580 sphere: sphere 46581 }; 46582 46583 } ); 46584 46585 object._maxGeometryCount = data.maxGeometryCount; 46586 object._maxVertexCount = data.maxVertexCount; 46587 object._maxIndexCount = data.maxIndexCount; 46588 46589 object._geometryInitialized = data.geometryInitialized; 46590 object._geometryCount = data.geometryCount; 46591 46592 object._matricesTexture = getTexture( data.matricesTexture.uuid ); 46593 46594 break; 46595 46596 case 'LOD': 46597 46598 object = new LOD(); 46599 46600 break; 46601 46602 case 'Line': 46603 46604 object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) ); 46605 46606 break; 46607 46608 case 'LineLoop': 46609 46610 object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); 46611 46612 break; 46613 46614 case 'LineSegments': 46615 46616 object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); 46617 46618 break; 46619 46620 case 'PointCloud': 46621 case 'Points': 46622 46623 object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) ); 46624 46625 break; 46626 46627 case 'Sprite': 46628 46629 object = new Sprite( getMaterial( data.material ) ); 46630 46631 break; 46632 46633 case 'Group': 46634 46635 object = new Group(); 46636 46637 break; 46638 46639 case 'Bone': 46640 46641 object = new Bone(); 46642 46643 break; 46644 46645 default: 46646 46647 object = new Object3D(); 46648 46649 } 46650 46651 object.uuid = data.uuid; 46652 46653 if ( data.name !== undefined ) object.name = data.name; 46654 46655 if ( data.matrix !== undefined ) { 46656 46657 object.matrix.fromArray( data.matrix ); 46658 46659 if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate; 46660 if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale ); 46661 46662 } else { 46663 46664 if ( data.position !== undefined ) object.position.fromArray( data.position ); 46665 if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation ); 46666 if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion ); 46667 if ( data.scale !== undefined ) object.scale.fromArray( data.scale ); 46668 46669 } 46670 46671 if ( data.up !== undefined ) object.up.fromArray( data.up ); 46672 46673 if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; 46674 if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; 46675 46676 if ( data.shadow ) { 46677 46678 if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias; 46679 if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias; 46680 if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius; 46681 if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize ); 46682 if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera ); 46683 46684 } 46685 46686 if ( data.visible !== undefined ) object.visible = data.visible; 46687 if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled; 46688 if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder; 46689 if ( data.userData !== undefined ) object.userData = data.userData; 46690 if ( data.layers !== undefined ) object.layers.mask = data.layers; 46691 46692 if ( data.children !== undefined ) { 46693 46694 const children = data.children; 46695 46696 for ( let i = 0; i < children.length; i ++ ) { 46697 46698 object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) ); 46699 46700 } 46701 46702 } 46703 46704 if ( data.animations !== undefined ) { 46705 46706 const objectAnimations = data.animations; 46707 46708 for ( let i = 0; i < objectAnimations.length; i ++ ) { 46709 46710 const uuid = objectAnimations[ i ]; 46711 46712 object.animations.push( animations[ uuid ] ); 46713 46714 } 46715 46716 } 46717 46718 if ( data.type === 'LOD' ) { 46719 46720 if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate; 46721 46722 const levels = data.levels; 46723 46724 for ( let l = 0; l < levels.length; l ++ ) { 46725 46726 const level = levels[ l ]; 46727 const child = object.getObjectByProperty( 'uuid', level.object ); 46728 46729 if ( child !== undefined ) { 46730 46731 object.addLevel( child, level.distance, level.hysteresis ); 46732 46733 } 46734 46735 } 46736 46737 } 46738 46739 return object; 46740 46741 } 46742 46743 bindSkeletons( object, skeletons ) { 46744 46745 if ( Object.keys( skeletons ).length === 0 ) return; 46746 46747 object.traverse( function ( child ) { 46748 46749 if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) { 46750 46751 const skeleton = skeletons[ child.skeleton ]; 46752 46753 if ( skeleton === undefined ) { 46754 46755 console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton ); 46756 46757 } else { 46758 46759 child.bind( skeleton, child.bindMatrix ); 46760 46761 } 46762 46763 } 46764 46765 } ); 46766 46767 } 46768 46769} 46770 46771const TEXTURE_MAPPING = { 46772 UVMapping: UVMapping, 46773 CubeReflectionMapping: CubeReflectionMapping, 46774 CubeRefractionMapping: CubeRefractionMapping, 46775 EquirectangularReflectionMapping: EquirectangularReflectionMapping, 46776 EquirectangularRefractionMapping: EquirectangularRefractionMapping, 46777 CubeUVReflectionMapping: CubeUVReflectionMapping 46778}; 46779 46780const TEXTURE_WRAPPING = { 46781 RepeatWrapping: RepeatWrapping, 46782 ClampToEdgeWrapping: ClampToEdgeWrapping, 46783 MirroredRepeatWrapping: MirroredRepeatWrapping 46784}; 46785 46786const TEXTURE_FILTER = { 46787 NearestFilter: NearestFilter, 46788 NearestMipmapNearestFilter: NearestMipmapNearestFilter, 46789 NearestMipmapLinearFilter: NearestMipmapLinearFilter, 46790 LinearFilter: LinearFilter, 46791 LinearMipmapNearestFilter: LinearMipmapNearestFilter, 46792 LinearMipmapLinearFilter: LinearMipmapLinearFilter 46793}; 46794 46795class ImageBitmapLoader extends Loader { 46796 46797 constructor( manager ) { 46798 46799 super( manager ); 46800 46801 this.isImageBitmapLoader = true; 46802 46803 if ( typeof createImageBitmap === 'undefined' ) { 46804 46805 console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' ); 46806 46807 } 46808 46809 if ( typeof fetch === 'undefined' ) { 46810 46811 console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' ); 46812 46813 } 46814 46815 this.options = { premultiplyAlpha: 'none' }; 46816 46817 } 46818 46819 setOptions( options ) { 46820 46821 this.options = options; 46822 46823 return this; 46824 46825 } 46826 46827 load( url, onLoad, onProgress, onError ) { 46828 46829 if ( url === undefined ) url = ''; 46830 46831 if ( this.path !== undefined ) url = this.path + url; 46832 46833 url = this.manager.resolveURL( url ); 46834 46835 const scope = this; 46836 46837 const cached = Cache.get( url ); 46838 46839 if ( cached !== undefined ) { 46840 46841 scope.manager.itemStart( url ); 46842 46843 // If cached is a promise, wait for it to resolve 46844 if ( cached.then ) { 46845 46846 cached.then( imageBitmap => { 46847 46848 if ( onLoad ) onLoad( imageBitmap ); 46849 46850 scope.manager.itemEnd( url ); 46851 46852 } ).catch( e => { 46853 46854 if ( onError ) onError( e ); 46855 46856 } ); 46857 return; 46858 46859 } 46860 46861 // If cached is not a promise (i.e., it's already an imageBitmap) 46862 setTimeout( function () { 46863 46864 if ( onLoad ) onLoad( cached ); 46865 46866 scope.manager.itemEnd( url ); 46867 46868 }, 0 ); 46869 46870 return cached; 46871 46872 } 46873 46874 const fetchOptions = {}; 46875 fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include'; 46876 fetchOptions.headers = this.requestHeader; 46877 46878 const promise = fetch( url, fetchOptions ).then( function ( res ) { 46879 46880 return res.blob(); 46881 46882 } ).then( function ( blob ) { 46883 46884 return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) ); 46885 46886 } ).then( function ( imageBitmap ) { 46887 46888 Cache.add( url, imageBitmap ); 46889 46890 if ( onLoad ) onLoad( imageBitmap ); 46891 46892 scope.manager.itemEnd( url ); 46893 46894 return imageBitmap; 46895 46896 } ).catch( function ( e ) { 46897 46898 if ( onError ) onError( e ); 46899 46900 Cache.remove( url ); 46901 46902 scope.manager.itemError( url ); 46903 scope.manager.itemEnd( url ); 46904 46905 } ); 46906 46907 Cache.add( url, promise ); 46908 scope.manager.itemStart( url ); 46909 46910 } 46911 46912} 46913 46914let _context; 46915 46916class AudioContext { 46917 46918 static getContext() { 46919 46920 if ( _context === undefined ) { 46921 46922 _context = new ( window.AudioContext || window.webkitAudioContext )(); 46923 46924 } 46925 46926 return _context; 46927 46928 } 46929 46930 static setContext( value ) { 46931 46932 _context = value; 46933 46934 } 46935 46936} 46937 46938class AudioLoader extends Loader { 46939 46940 constructor( manager ) { 46941 46942 super( manager ); 46943 46944 } 46945 46946 load( url, onLoad, onProgress, onError ) { 46947 46948 const scope = this; 46949 46950 const loader = new FileLoader( this.manager ); 46951 loader.setResponseType( 'arraybuffer' ); 46952 loader.setPath( this.path ); 46953 loader.setRequestHeader( this.requestHeader ); 46954 loader.setWithCredentials( this.withCredentials ); 46955 loader.load( url, function ( buffer ) { 46956 46957 try { 46958 46959 // Create a copy of the buffer. The `decodeAudioData` method 46960 // detaches the buffer when complete, preventing reuse. 46961 const bufferCopy = buffer.slice( 0 ); 46962 46963 const context = AudioContext.getContext(); 46964 context.decodeAudioData( bufferCopy, function ( audioBuffer ) { 46965 46966 onLoad( audioBuffer ); 46967 46968 } ).catch( handleError ); 46969 46970 } catch ( e ) { 46971 46972 handleError( e ); 46973 46974 } 46975 46976 }, onProgress, onError ); 46977 46978 function handleError( e ) { 46979 46980 if ( onError ) { 46981 46982 onError( e ); 46983 46984 } else { 46985 46986 console.error( e ); 46987 46988 } 46989 46990 scope.manager.itemError( url ); 46991 46992 } 46993 46994 } 46995 46996} 46997 46998const _eyeRight = /*@__PURE__*/ new Matrix4(); 46999const _eyeLeft = /*@__PURE__*/ new Matrix4(); 47000const _projectionMatrix = /*@__PURE__*/ new Matrix4(); 47001 47002class StereoCamera { 47003 47004 constructor() { 47005 47006 this.type = 'StereoCamera'; 47007 47008 this.aspect = 1; 47009 47010 this.eyeSep = 0.064; 47011 47012 this.cameraL = new PerspectiveCamera(); 47013 this.cameraL.layers.enable( 1 ); 47014 this.cameraL.matrixAutoUpdate = false; 47015 47016 this.cameraR = new PerspectiveCamera(); 47017 this.cameraR.layers.enable( 2 ); 47018 this.cameraR.matrixAutoUpdate = false; 47019 47020 this._cache = { 47021 focus: null, 47022 fov: null, 47023 aspect: null, 47024 near: null, 47025 far: null, 47026 zoom: null, 47027 eyeSep: null 47028 }; 47029 47030 } 47031 47032 update( camera ) { 47033 47034 const cache = this._cache; 47035 47036 const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov || 47037 cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near || 47038 cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep; 47039 47040 if ( needsUpdate ) { 47041 47042 cache.focus = camera.focus; 47043 cache.fov = camera.fov; 47044 cache.aspect = camera.aspect * this.aspect; 47045 cache.near = camera.near; 47046 cache.far = camera.far; 47047 cache.zoom = camera.zoom; 47048 cache.eyeSep = this.eyeSep; 47049 47050 // Off-axis stereoscopic effect based on 47051 // http://paulbourke.net/stereographics/stereorender/ 47052 47053 _projectionMatrix.copy( camera.projectionMatrix ); 47054 const eyeSepHalf = cache.eyeSep / 2; 47055 const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus; 47056 const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom; 47057 let xmin, xmax; 47058 47059 // translate xOffset 47060 47061 _eyeLeft.elements[ 12 ] = - eyeSepHalf; 47062 _eyeRight.elements[ 12 ] = eyeSepHalf; 47063 47064 // for left eye 47065 47066 xmin = - ymax * cache.aspect + eyeSepOnProjection; 47067 xmax = ymax * cache.aspect + eyeSepOnProjection; 47068 47069 _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); 47070 _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); 47071 47072 this.cameraL.projectionMatrix.copy( _projectionMatrix ); 47073 47074 // for right eye 47075 47076 xmin = - ymax * cache.aspect - eyeSepOnProjection; 47077 xmax = ymax * cache.aspect - eyeSepOnProjection; 47078 47079 _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); 47080 _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); 47081 47082 this.cameraR.projectionMatrix.copy( _projectionMatrix ); 47083 47084 } 47085 47086 this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft ); 47087 this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight ); 47088 47089 } 47090 47091} 47092 47093class Clock { 47094 47095 constructor( autoStart = true ) { 47096 47097 this.autoStart = autoStart; 47098 47099 this.startTime = 0; 47100 this.oldTime = 0; 47101 this.elapsedTime = 0; 47102 47103 this.running = false; 47104 47105 } 47106 47107 start() { 47108 47109 this.startTime = now(); 47110 47111 this.oldTime = this.startTime; 47112 this.elapsedTime = 0; 47113 this.running = true; 47114 47115 } 47116 47117 stop() { 47118 47119 this.getElapsedTime(); 47120 this.running = false; 47121 this.autoStart = false; 47122 47123 } 47124 47125 getElapsedTime() { 47126 47127 this.getDelta(); 47128 return this.elapsedTime; 47129 47130 } 47131 47132 getDelta() { 47133 47134 let diff = 0; 47135 47136 if ( this.autoStart && ! this.running ) { 47137 47138 this.start(); 47139 return 0; 47140 47141 } 47142 47143 if ( this.running ) { 47144 47145 const newTime = now(); 47146 47147 diff = ( newTime - this.oldTime ) / 1000; 47148 this.oldTime = newTime; 47149 47150 this.elapsedTime += diff; 47151 47152 } 47153 47154 return diff; 47155 47156 } 47157 47158} 47159 47160function now() { 47161 47162 return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732 47163 47164} 47165 47166const _position$1 = /*@__PURE__*/ new Vector3(); 47167const _quaternion$1 = /*@__PURE__*/ new Quaternion(); 47168const _scale$1 = /*@__PURE__*/ new Vector3(); 47169const _orientation$1 = /*@__PURE__*/ new Vector3(); 47170 47171class AudioListener extends Object3D { 47172 47173 constructor() { 47174 47175 super(); 47176 47177 this.type = 'AudioListener'; 47178 47179 this.context = AudioContext.getContext(); 47180 47181 this.gain = this.context.createGain(); 47182 this.gain.connect( this.context.destination ); 47183 47184 this.filter = null; 47185 47186 this.timeDelta = 0; 47187 47188 // private 47189 47190 this._clock = new Clock(); 47191 47192 } 47193 47194 getInput() { 47195 47196 return this.gain; 47197 47198 } 47199 47200 removeFilter() { 47201 47202 if ( this.filter !== null ) { 47203 47204 this.gain.disconnect( this.filter ); 47205 this.filter.disconnect( this.context.destination ); 47206 this.gain.connect( this.context.destination ); 47207 this.filter = null; 47208 47209 } 47210 47211 return this; 47212 47213 } 47214 47215 getFilter() { 47216 47217 return this.filter; 47218 47219 } 47220 47221 setFilter( value ) { 47222 47223 if ( this.filter !== null ) { 47224 47225 this.gain.disconnect( this.filter ); 47226 this.filter.disconnect( this.context.destination ); 47227 47228 } else { 47229 47230 this.gain.disconnect( this.context.destination ); 47231 47232 } 47233 47234 this.filter = value; 47235 this.gain.connect( this.filter ); 47236 this.filter.connect( this.context.destination ); 47237 47238 return this; 47239 47240 } 47241 47242 getMasterVolume() { 47243 47244 return this.gain.gain.value; 47245 47246 } 47247 47248 setMasterVolume( value ) { 47249 47250 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); 47251 47252 return this; 47253 47254 } 47255 47256 updateMatrixWorld( force ) { 47257 47258 super.updateMatrixWorld( force ); 47259 47260 const listener = this.context.listener; 47261 const up = this.up; 47262 47263 this.timeDelta = this._clock.getDelta(); 47264 47265 this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 ); 47266 47267 _orientation$1.set( 0, 0, - 1 ).applyQuaternion( _quaternion$1 ); 47268 47269 if ( listener.positionX ) { 47270 47271 // code path for Chrome (see #14393) 47272 47273 const endTime = this.context.currentTime + this.timeDelta; 47274 47275 listener.positionX.linearRampToValueAtTime( _position$1.x, endTime ); 47276 listener.positionY.linearRampToValueAtTime( _position$1.y, endTime ); 47277 listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime ); 47278 listener.forwardX.linearRampToValueAtTime( _orientation$1.x, endTime ); 47279 listener.forwardY.linearRampToValueAtTime( _orientation$1.y, endTime ); 47280 listener.forwardZ.linearRampToValueAtTime( _orientation$1.z, endTime ); 47281 listener.upX.linearRampToValueAtTime( up.x, endTime ); 47282 listener.upY.linearRampToValueAtTime( up.y, endTime ); 47283 listener.upZ.linearRampToValueAtTime( up.z, endTime ); 47284 47285 } else { 47286 47287 listener.setPosition( _position$1.x, _position$1.y, _position$1.z ); 47288 listener.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z ); 47289 47290 } 47291 47292 } 47293 47294} 47295 47296class Audio extends Object3D { 47297 47298 constructor( listener ) { 47299 47300 super(); 47301 47302 this.type = 'Audio'; 47303 47304 this.listener = listener; 47305 this.context = listener.context; 47306 47307 this.gain = this.context.createGain(); 47308 this.gain.connect( listener.getInput() ); 47309 47310 this.autoplay = false; 47311 47312 this.buffer = null; 47313 this.detune = 0; 47314 this.loop = false; 47315 this.loopStart = 0; 47316 this.loopEnd = 0; 47317 this.offset = 0; 47318 this.duration = undefined; 47319 this.playbackRate = 1; 47320 this.isPlaying = false; 47321 this.hasPlaybackControl = true; 47322 this.source = null; 47323 this.sourceType = 'empty'; 47324 47325 this._startedAt = 0; 47326 this._progress = 0; 47327 this._connected = false; 47328 47329 this.filters = []; 47330 47331 } 47332 47333 getOutput() { 47334 47335 return this.gain; 47336 47337 } 47338 47339 setNodeSource( audioNode ) { 47340 47341 this.hasPlaybackControl = false; 47342 this.sourceType = 'audioNode'; 47343 this.source = audioNode; 47344 this.connect(); 47345 47346 return this; 47347 47348 } 47349 47350 setMediaElementSource( mediaElement ) { 47351 47352 this.hasPlaybackControl = false;
vendor: 8,731 bytes, lines 47353-47898
47353 this.sourceType = 'mediaNode'; 47354 this.source = this.context.createMediaElementSource( mediaElement ); 47355 this.connect(); 47356 47357 return this; 47358 47359 } 47360 47361 setMediaStreamSource( mediaStream ) { 47362 47363 this.hasPlaybackControl = false; 47364 this.sourceType = 'mediaStreamNode'; 47365 this.source = this.context.createMediaStreamSource( mediaStream ); 47366 this.connect(); 47367 47368 return this; 47369 47370 } 47371 47372 setBuffer( audioBuffer ) { 47373 47374 this.buffer = audioBuffer; 47375 this.sourceType = 'buffer'; 47376 47377 if ( this.autoplay ) this.play(); 47378 47379 return this; 47380 47381 } 47382 47383 play( delay = 0 ) { 47384 47385 if ( this.isPlaying === true ) { 47386 47387 console.warn( 'THREE.Audio: Audio is already playing.' ); 47388 return; 47389 47390 } 47391 47392 if ( this.hasPlaybackControl === false ) { 47393 47394 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47395 return; 47396 47397 } 47398 47399 this._startedAt = this.context.currentTime + delay; 47400 47401 const source = this.context.createBufferSource(); 47402 source.buffer = this.buffer; 47403 source.loop = this.loop; 47404 source.loopStart = this.loopStart; 47405 source.loopEnd = this.loopEnd; 47406 source.onended = this.onEnded.bind( this ); 47407 source.start( this._startedAt, this._progress + this.offset, this.duration ); 47408 47409 this.isPlaying = true; 47410 47411 this.source = source; 47412 47413 this.setDetune( this.detune ); 47414 this.setPlaybackRate( this.playbackRate ); 47415 47416 return this.connect(); 47417 47418 } 47419 47420 pause() { 47421 47422 if ( this.hasPlaybackControl === false ) { 47423 47424 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47425 return; 47426 47427 } 47428 47429 if ( this.isPlaying === true ) { 47430 47431 // update current progress 47432 47433 this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate; 47434 47435 if ( this.loop === true ) { 47436 47437 // ensure _progress does not exceed duration with looped audios 47438 47439 this._progress = this._progress % ( this.duration || this.buffer.duration ); 47440 47441 } 47442 47443 this.source.stop(); 47444 this.source.onended = null; 47445 47446 this.isPlaying = false; 47447 47448 } 47449 47450 return this; 47451 47452 } 47453 47454 stop() { 47455 47456 if ( this.hasPlaybackControl === false ) { 47457 47458 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47459 return; 47460 47461 } 47462 47463 this._progress = 0; 47464 47465 if ( this.source !== null ) { 47466 47467 this.source.stop(); 47468 this.source.onended = null; 47469 47470 } 47471 47472 this.isPlaying = false; 47473 47474 return this; 47475 47476 } 47477 47478 connect() { 47479 47480 if ( this.filters.length > 0 ) { 47481 47482 this.source.connect( this.filters[ 0 ] ); 47483 47484 for ( let i = 1, l = this.filters.length; i < l; i ++ ) { 47485 47486 this.filters[ i - 1 ].connect( this.filters[ i ] ); 47487 47488 } 47489 47490 this.filters[ this.filters.length - 1 ].connect( this.getOutput() ); 47491 47492 } else { 47493 47494 this.source.connect( this.getOutput() ); 47495 47496 } 47497 47498 this._connected = true; 47499 47500 return this; 47501 47502 } 47503 47504 disconnect() { 47505 47506 if ( this._connected === false ) { 47507 47508 return; 47509 47510 } 47511 47512 if ( this.filters.length > 0 ) { 47513 47514 this.source.disconnect( this.filters[ 0 ] ); 47515 47516 for ( let i = 1, l = this.filters.length; i < l; i ++ ) { 47517 47518 this.filters[ i - 1 ].disconnect( this.filters[ i ] ); 47519 47520 } 47521 47522 this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() ); 47523 47524 } else { 47525 47526 this.source.disconnect( this.getOutput() ); 47527 47528 } 47529 47530 this._connected = false; 47531 47532 return this; 47533 47534 } 47535 47536 getFilters() { 47537 47538 return this.filters; 47539 47540 } 47541 47542 setFilters( value ) { 47543 47544 if ( ! value ) value = []; 47545 47546 if ( this._connected === true ) { 47547 47548 this.disconnect(); 47549 this.filters = value.slice(); 47550 this.connect(); 47551 47552 } else { 47553 47554 this.filters = value.slice(); 47555 47556 } 47557 47558 return this; 47559 47560 } 47561 47562 setDetune( value ) { 47563 47564 this.detune = value; 47565 47566 if ( this.source.detune === undefined ) return; // only set detune when available 47567 47568 if ( this.isPlaying === true ) { 47569 47570 this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 ); 47571 47572 } 47573 47574 return this; 47575 47576 } 47577 47578 getDetune() { 47579 47580 return this.detune; 47581 47582 } 47583 47584 getFilter() { 47585 47586 return this.getFilters()[ 0 ]; 47587 47588 } 47589 47590 setFilter( filter ) { 47591 47592 return this.setFilters( filter ? [ filter ] : [] ); 47593 47594 } 47595 47596 setPlaybackRate( value ) { 47597 47598 if ( this.hasPlaybackControl === false ) { 47599 47600 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47601 return; 47602 47603 } 47604 47605 this.playbackRate = value; 47606 47607 if ( this.isPlaying === true ) { 47608 47609 this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 ); 47610 47611 } 47612 47613 return this; 47614 47615 } 47616 47617 getPlaybackRate() { 47618 47619 return this.playbackRate; 47620 47621 } 47622 47623 onEnded() { 47624 47625 this.isPlaying = false; 47626 47627 } 47628 47629 getLoop() { 47630 47631 if ( this.hasPlaybackControl === false ) { 47632 47633 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47634 return false; 47635 47636 } 47637 47638 return this.loop; 47639 47640 } 47641 47642 setLoop( value ) { 47643 47644 if ( this.hasPlaybackControl === false ) { 47645 47646 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 47647 return; 47648 47649 } 47650 47651 this.loop = value; 47652 47653 if ( this.isPlaying === true ) { 47654 47655 this.source.loop = this.loop; 47656 47657 } 47658 47659 return this; 47660 47661 } 47662 47663 setLoopStart( value ) { 47664 47665 this.loopStart = value; 47666 47667 return this; 47668 47669 } 47670 47671 setLoopEnd( value ) { 47672 47673 this.loopEnd = value; 47674 47675 return this; 47676 47677 } 47678 47679 getVolume() { 47680 47681 return this.gain.gain.value; 47682 47683 } 47684 47685 setVolume( value ) { 47686 47687 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); 47688 47689 return this; 47690 47691 } 47692 47693} 47694 47695const _position = /*@__PURE__*/ new Vector3(); 47696const _quaternion = /*@__PURE__*/ new Quaternion(); 47697const _scale = /*@__PURE__*/ new Vector3(); 47698const _orientation = /*@__PURE__*/ new Vector3(); 47699 47700class PositionalAudio extends Audio { 47701 47702 constructor( listener ) { 47703 47704 super( listener ); 47705 47706 this.panner = this.context.createPanner(); 47707 this.panner.panningModel = 'HRTF'; 47708 this.panner.connect( this.gain ); 47709 47710 } 47711 47712 connect() { 47713 47714 super.connect(); 47715 47716 this.panner.connect( this.gain ); 47717 47718 } 47719 47720 disconnect() { 47721 47722 super.disconnect(); 47723 47724 this.panner.disconnect( this.gain ); 47725 47726 } 47727 47728 getOutput() { 47729 47730 return this.panner; 47731 47732 } 47733 47734 getRefDistance() { 47735 47736 return this.panner.refDistance; 47737 47738 } 47739 47740 setRefDistance( value ) { 47741 47742 this.panner.refDistance = value; 47743 47744 return this; 47745 47746 } 47747 47748 getRolloffFactor() { 47749 47750 return this.panner.rolloffFactor; 47751 47752 } 47753 47754 setRolloffFactor( value ) { 47755 47756 this.panner.rolloffFactor = value; 47757 47758 return this; 47759 47760 } 47761 47762 getDistanceModel() { 47763 47764 return this.panner.distanceModel; 47765 47766 } 47767 47768 setDistanceModel( value ) { 47769 47770 this.panner.distanceModel = value; 47771 47772 return this; 47773 47774 } 47775 47776 getMaxDistance() { 47777 47778 return this.panner.maxDistance; 47779 47780 } 47781 47782 setMaxDistance( value ) { 47783 47784 this.panner.maxDistance = value; 47785 47786 return this; 47787 47788 } 47789 47790 setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) { 47791 47792 this.panner.coneInnerAngle = coneInnerAngle; 47793 this.panner.coneOuterAngle = coneOuterAngle; 47794 this.panner.coneOuterGain = coneOuterGain; 47795 47796 return this; 47797 47798 } 47799 47800 updateMatrixWorld( force ) { 47801 47802 super.updateMatrixWorld( force ); 47803 47804 if ( this.hasPlaybackControl === true && this.isPlaying === false ) return; 47805 47806 this.matrixWorld.decompose( _position, _quaternion, _scale ); 47807 47808 _orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion ); 47809 47810 const panner = this.panner; 47811 47812 if ( panner.positionX ) { 47813 47814 // code path for Chrome and Firefox (see #14393) 47815 47816 const endTime = this.context.currentTime + this.listener.timeDelta; 47817 47818 panner.positionX.linearRampToValueAtTime( _position.x, endTime ); 47819 panner.positionY.linearRampToValueAtTime( _position.y, endTime ); 47820 panner.positionZ.linearRampToValueAtTime( _position.z, endTime ); 47821 panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime ); 47822 panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime ); 47823 panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime ); 47824 47825 } else { 47826 47827 panner.setPosition( _position.x, _position.y, _position.z ); 47828 panner.setOrientation( _orientation.x, _orientation.y, _orientation.z ); 47829 47830 } 47831 47832 } 47833 47834} 47835 47836class AudioAnalyser { 47837 47838 constructor( audio, fftSize = 2048 ) { 47839 47840 this.analyser = audio.context.createAnalyser(); 47841 this.analyser.fftSize = fftSize; 47842 47843 this.data = new Uint8Array( this.analyser.frequencyBinCount ); 47844 47845 audio.getOutput().connect( this.analyser ); 47846 47847 } 47848 47849 47850 getFrequencyData() { 47851 47852 this.analyser.getByteFrequencyData( this.data ); 47853 47854 return this.data; 47855 47856 } 47857 47858 getAverageFrequency() { 47859 47860 let value = 0; 47861 const data = this.getFrequencyData(); 47862 47863 for ( let i = 0; i < data.length; i ++ ) { 47864 47865 value += data[ i ]; 47866 47867 } 47868 47869 return value / data.length; 47870 47871 } 47872 47873} 47874 47875class PropertyMixer { 47876 47877 constructor( binding, typeName, valueSize ) { 47878 47879 this.binding = binding; 47880 this.valueSize = valueSize; 47881 47882 let mixFunction, 47883 mixFunctionAdditive, 47884 setIdentity; 47885 47886 // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ] 47887 // 47888 // interpolators can use .buffer as their .result 47889 // the data then goes to 'incoming' 47890 // 47891 // 'accu0' and 'accu1' are used frame-interleaved for 47892 // the cumulative result and are compared to detect 47893 // changes 47894 // 47895 // 'orig' stores the original state of the property 47896 // 47897 // 'add' is used for additive cumulative results 47898 //
vendor: 13,778 bytes, lines 47899-48529
47899 // 'work' is optional and is only present for quaternion types. It is used 47900 // to store intermediate quaternion multiplication results 47901 47902 switch ( typeName ) { 47903 47904 case 'quaternion': 47905 mixFunction = this._slerp; 47906 mixFunctionAdditive = this._slerpAdditive; 47907 setIdentity = this._setAdditiveIdentityQuaternion; 47908 47909 this.buffer = new Float64Array( valueSize * 6 ); 47910 this._workIndex = 5; 47911 break; 47912 47913 case 'string': 47914 case 'bool': 47915 mixFunction = this._select; 47916 47917 // Use the regular mix function and for additive on these types, 47918 // additive is not relevant for non-numeric types 47919 mixFunctionAdditive = this._select; 47920 47921 setIdentity = this._setAdditiveIdentityOther; 47922 47923 this.buffer = new Array( valueSize * 5 ); 47924 break; 47925 47926 default: 47927 mixFunction = this._lerp; 47928 mixFunctionAdditive = this._lerpAdditive; 47929 setIdentity = this._setAdditiveIdentityNumeric; 47930 47931 this.buffer = new Float64Array( valueSize * 5 ); 47932 47933 } 47934 47935 this._mixBufferRegion = mixFunction; 47936 this._mixBufferRegionAdditive = mixFunctionAdditive; 47937 this._setIdentity = setIdentity; 47938 this._origIndex = 3; 47939 this._addIndex = 4; 47940 47941 this.cumulativeWeight = 0; 47942 this.cumulativeWeightAdditive = 0; 47943 47944 this.useCount = 0; 47945 this.referenceCount = 0; 47946 47947 } 47948 47949 // accumulate data in the 'incoming' region into 'accu<i>' 47950 accumulate( accuIndex, weight ) { 47951 47952 // note: happily accumulating nothing when weight = 0, the caller knows 47953 // the weight and shouldn't have made the call in the first place 47954 47955 const buffer = this.buffer, 47956 stride = this.valueSize, 47957 offset = accuIndex * stride + stride; 47958 47959 let currentWeight = this.cumulativeWeight; 47960 47961 if ( currentWeight === 0 ) { 47962 47963 // accuN := incoming * weight 47964 47965 for ( let i = 0; i !== stride; ++ i ) { 47966 47967 buffer[ offset + i ] = buffer[ i ]; 47968 47969 } 47970 47971 currentWeight = weight; 47972 47973 } else { 47974 47975 // accuN := accuN + incoming * weight 47976 47977 currentWeight += weight; 47978 const mix = weight / currentWeight; 47979 this._mixBufferRegion( buffer, offset, 0, mix, stride ); 47980 47981 } 47982 47983 this.cumulativeWeight = currentWeight; 47984 47985 } 47986 47987 // accumulate data in the 'incoming' region into 'add' 47988 accumulateAdditive( weight ) { 47989 47990 const buffer = this.buffer, 47991 stride = this.valueSize, 47992 offset = stride * this._addIndex; 47993 47994 if ( this.cumulativeWeightAdditive === 0 ) { 47995 47996 // add = identity 47997 47998 this._setIdentity(); 47999 48000 } 48001 48002 // add := add + incoming * weight 48003 48004 this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride ); 48005 this.cumulativeWeightAdditive += weight; 48006 48007 } 48008 48009 // apply the state of 'accu<i>' to the binding when accus differ 48010 apply( accuIndex ) { 48011 48012 const stride = this.valueSize, 48013 buffer = this.buffer, 48014 offset = accuIndex * stride + stride, 48015 48016 weight = this.cumulativeWeight, 48017 weightAdditive = this.cumulativeWeightAdditive, 48018 48019 binding = this.binding; 48020 48021 this.cumulativeWeight = 0; 48022 this.cumulativeWeightAdditive = 0; 48023 48024 if ( weight < 1 ) { 48025 48026 // accuN := accuN + original * ( 1 - cumulativeWeight ) 48027 48028 const originalValueOffset = stride * this._origIndex; 48029 48030 this._mixBufferRegion( 48031 buffer, offset, originalValueOffset, 1 - weight, stride ); 48032 48033 } 48034 48035 if ( weightAdditive > 0 ) { 48036 48037 // accuN := accuN + additive accuN 48038 48039 this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride ); 48040 48041 } 48042 48043 for ( let i = stride, e = stride + stride; i !== e; ++ i ) { 48044 48045 if ( buffer[ i ] !== buffer[ i + stride ] ) { 48046 48047 // value has changed -> update scene graph 48048 48049 binding.setValue( buffer, offset ); 48050 break; 48051 48052 } 48053 48054 } 48055 48056 } 48057 48058 // remember the state of the bound property and copy it to both accus 48059 saveOriginalState() { 48060 48061 const binding = this.binding; 48062 48063 const buffer = this.buffer, 48064 stride = this.valueSize, 48065 48066 originalValueOffset = stride * this._origIndex; 48067 48068 binding.getValue( buffer, originalValueOffset ); 48069 48070 // accu[0..1] := orig -- initially detect changes against the original 48071 for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) { 48072 48073 buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ]; 48074 48075 } 48076 48077 // Add to identity for additive 48078 this._setIdentity(); 48079 48080 this.cumulativeWeight = 0; 48081 this.cumulativeWeightAdditive = 0; 48082 48083 } 48084 48085 // apply the state previously taken via 'saveOriginalState' to the binding 48086 restoreOriginalState() { 48087 48088 const originalValueOffset = this.valueSize * 3; 48089 this.binding.setValue( this.buffer, originalValueOffset ); 48090 48091 } 48092 48093 _setAdditiveIdentityNumeric() { 48094 48095 const startIndex = this._addIndex * this.valueSize; 48096 const endIndex = startIndex + this.valueSize; 48097 48098 for ( let i = startIndex; i < endIndex; i ++ ) { 48099 48100 this.buffer[ i ] = 0; 48101 48102 } 48103 48104 } 48105 48106 _setAdditiveIdentityQuaternion() { 48107 48108 this._setAdditiveIdentityNumeric(); 48109 this.buffer[ this._addIndex * this.valueSize + 3 ] = 1; 48110 48111 } 48112 48113 _setAdditiveIdentityOther() { 48114 48115 const startIndex = this._origIndex * this.valueSize; 48116 const targetIndex = this._addIndex * this.valueSize; 48117 48118 for ( let i = 0; i < this.valueSize; i ++ ) { 48119 48120 this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ]; 48121 48122 } 48123 48124 } 48125 48126 48127 // mix functions 48128 48129 _select( buffer, dstOffset, srcOffset, t, stride ) { 48130 48131 if ( t >= 0.5 ) { 48132 48133 for ( let i = 0; i !== stride; ++ i ) { 48134 48135 buffer[ dstOffset + i ] = buffer[ srcOffset + i ]; 48136 48137 } 48138 48139 } 48140 48141 } 48142 48143 _slerp( buffer, dstOffset, srcOffset, t ) { 48144 48145 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t ); 48146 48147 } 48148 48149 _slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { 48150 48151 const workOffset = this._workIndex * stride; 48152 48153 // Store result in intermediate buffer offset 48154 Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset ); 48155 48156 // Slerp to the intermediate result 48157 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t ); 48158 48159 } 48160 48161 _lerp( buffer, dstOffset, srcOffset, t, stride ) { 48162 48163 const s = 1 - t; 48164 48165 for ( let i = 0; i !== stride; ++ i ) { 48166 48167 const j = dstOffset + i; 48168 48169 buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t; 48170 48171 } 48172 48173 } 48174 48175 _lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { 48176 48177 for ( let i = 0; i !== stride; ++ i ) { 48178 48179 const j = dstOffset + i; 48180 48181 buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t; 48182 48183 } 48184 48185 } 48186 48187} 48188 48189// Characters [].:/ are reserved for track binding syntax. 48190const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/'; 48191const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' ); 48192 48193// Attempts to allow node names from any language. ES5's `\w` regexp matches 48194// only latin characters, and the unicode \p{L} is not yet supported. So 48195// instead, we exclude reserved characters and match everything else. 48196const _wordChar = '[^' + _RESERVED_CHARS_RE + ']'; 48197const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']'; 48198 48199// Parent directories, delimited by '/' or ':'. Currently unused, but must 48200// be matched to parse the rest of the track name. 48201const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar ); 48202 48203// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'. 48204const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot ); 48205 48206// Object on target node, and accessor. May not contain reserved 48207// characters. Accessor may contain any character except closing bracket. 48208const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar ); 48209 48210// Property and accessor. May not contain reserved characters. Accessor may 48211// contain any non-bracket characters. 48212const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar ); 48213 48214const _trackRe = new RegExp( '' 48215 + '^' 48216 + _directoryRe 48217 + _nodeRe 48218 + _objectRe 48219 + _propertyRe 48220 + '$' 48221); 48222 48223const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ]; 48224 48225class Composite { 48226 48227 constructor( targetGroup, path, optionalParsedPath ) { 48228 48229 const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); 48230 48231 this._targetGroup = targetGroup; 48232 this._bindings = targetGroup.subscribe_( path, parsedPath ); 48233 48234 } 48235 48236 getValue( array, offset ) { 48237 48238 this.bind(); // bind all binding 48239 48240 const firstValidIndex = this._targetGroup.nCachedObjects_, 48241 binding = this._bindings[ firstValidIndex ]; 48242 48243 // and only call .getValue on the first 48244 if ( binding !== undefined ) binding.getValue( array, offset ); 48245 48246 } 48247 48248 setValue( array, offset ) { 48249 48250 const bindings = this._bindings; 48251 48252 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { 48253 48254 bindings[ i ].setValue( array, offset ); 48255 48256 } 48257 48258 } 48259 48260 bind() { 48261 48262 const bindings = this._bindings; 48263 48264 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { 48265 48266 bindings[ i ].bind(); 48267 48268 } 48269 48270 } 48271 48272 unbind() { 48273 48274 const bindings = this._bindings; 48275 48276 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { 48277 48278 bindings[ i ].unbind(); 48279 48280 } 48281 48282 } 48283 48284} 48285 48286// Note: This class uses a State pattern on a per-method basis: 48287// 'bind' sets 'this.getValue' / 'setValue' and shadows the 48288// prototype version of these methods with one that represents 48289// the bound state. When the property is not found, the methods 48290// become no-ops. 48291class PropertyBinding { 48292 48293 constructor( rootNode, path, parsedPath ) { 48294 48295 this.path = path; 48296 this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); 48297 48298 this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ); 48299 48300 this.rootNode = rootNode; 48301 48302 // initial state of these methods that calls 'bind' 48303 this.getValue = this._getValue_unbound; 48304 this.setValue = this._setValue_unbound; 48305 48306 } 48307 48308 48309 static create( root, path, parsedPath ) { 48310 48311 if ( ! ( root && root.isAnimationObjectGroup ) ) { 48312 48313 return new PropertyBinding( root, path, parsedPath ); 48314 48315 } else { 48316 48317 return new PropertyBinding.Composite( root, path, parsedPath ); 48318 48319 } 48320 48321 } 48322 48323 /** 48324 * Replaces spaces with underscores and removes unsupported characters from 48325 * node names, to ensure compatibility with parseTrackName(). 48326 * 48327 * @param {string} name Node name to be sanitized. 48328 * @return {string} 48329 */ 48330 static sanitizeNodeName( name ) { 48331 48332 return name.replace( /\s/g, '_' ).replace( _reservedRe, '' ); 48333 48334 } 48335 48336 static parseTrackName( trackName ) { 48337 48338 const matches = _trackRe.exec( trackName ); 48339 48340 if ( matches === null ) { 48341 48342 throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName ); 48343 48344 } 48345 48346 const results = { 48347 // directoryName: matches[ 1 ], // (tschw) currently unused 48348 nodeName: matches[ 2 ], 48349 objectName: matches[ 3 ], 48350 objectIndex: matches[ 4 ], 48351 propertyName: matches[ 5 ], // required 48352 propertyIndex: matches[ 6 ] 48353 }; 48354 48355 const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' ); 48356 48357 if ( lastDot !== undefined && lastDot !== - 1 ) { 48358 48359 const objectName = results.nodeName.substring( lastDot + 1 ); 48360 48361 // Object names must be checked against an allowlist. Otherwise, there 48362 // is no way to parse 'foo.bar.baz': 'baz' must be a property, but 48363 // 'bar' could be the objectName, or part of a nodeName (which can 48364 // include '.' characters). 48365 if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) { 48366 48367 results.nodeName = results.nodeName.substring( 0, lastDot ); 48368 results.objectName = objectName; 48369 48370 } 48371 48372 } 48373 48374 if ( results.propertyName === null || results.propertyName.length === 0 ) { 48375 48376 throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName ); 48377 48378 } 48379 48380 return results; 48381 48382 } 48383 48384 static findNode( root, nodeName ) { 48385 48386 if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { 48387 48388 return root; 48389 48390 } 48391 48392 // search into skeleton bones. 48393 if ( root.skeleton ) { 48394 48395 const bone = root.skeleton.getBoneByName( nodeName ); 48396 48397 if ( bone !== undefined ) { 48398 48399 return bone; 48400 48401 } 48402 48403 } 48404 48405 // search into node subtree. 48406 if ( root.children ) { 48407 48408 const searchNodeSubtree = function ( children ) { 48409 48410 for ( let i = 0; i < children.length; i ++ ) { 48411 48412 const childNode = children[ i ]; 48413 48414 if ( childNode.name === nodeName || childNode.uuid === nodeName ) { 48415 48416 return childNode; 48417 48418 } 48419 48420 const result = searchNodeSubtree( childNode.children ); 48421 48422 if ( result ) return result; 48423 48424 } 48425 48426 return null; 48427 48428 }; 48429 48430 const subTreeNode = searchNodeSubtree( root.children ); 48431 48432 if ( subTreeNode ) { 48433 48434 return subTreeNode; 48435 48436 } 48437 48438 } 48439 48440 return null; 48441 48442 } 48443 48444 // these are used to "bind" a nonexistent property 48445 _getValue_unavailable() {} 48446 _setValue_unavailable() {} 48447 48448 // Getters 48449 48450 _getValue_direct( buffer, offset ) { 48451 48452 buffer[ offset ] = this.targetObject[ this.propertyName ]; 48453 48454 } 48455 48456 _getValue_array( buffer, offset ) { 48457 48458 const source = this.resolvedProperty; 48459 48460 for ( let i = 0, n = source.length; i !== n; ++ i ) { 48461 48462 buffer[ offset ++ ] = source[ i ]; 48463 48464 } 48465 48466 } 48467 48468 _getValue_arrayElement( buffer, offset ) { 48469 48470 buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; 48471 48472 } 48473 48474 _getValue_toArray( buffer, offset ) { 48475 48476 this.resolvedProperty.toArray( buffer, offset ); 48477 48478 } 48479 48480 // Direct 48481 48482 _setValue_direct( buffer, offset ) { 48483 48484 this.targetObject[ this.propertyName ] = buffer[ offset ]; 48485 48486 } 48487 48488 _setValue_direct_setNeedsUpdate( buffer, offset ) { 48489 48490 this.targetObject[ this.propertyName ] = buffer[ offset ]; 48491 this.targetObject.needsUpdate = true; 48492 48493 } 48494 48495 _setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { 48496 48497 this.targetObject[ this.propertyName ] = buffer[ offset ]; 48498 this.targetObject.matrixWorldNeedsUpdate = true; 48499 48500 } 48501 48502 // EntireArray 48503 48504 _setValue_array( buffer, offset ) { 48505 48506 const dest = this.resolvedProperty; 48507 48508 for ( let i = 0, n = dest.length; i !== n; ++ i ) { 48509 48510 dest[ i ] = buffer[ offset ++ ]; 48511 48512 } 48513 48514 } 48515 48516 _setValue_array_setNeedsUpdate( buffer, offset ) { 48517 48518 const dest = this.resolvedProperty; 48519 48520 for ( let i = 0, n = dest.length; i !== n; ++ i ) { 48521 48522 dest[ i ] = buffer[ offset ++ ]; 48523 48524 } 48525 48526 this.targetObject.needsUpdate = true; 48527 48528 } 48529
vendor: 8,185 bytes, lines 48530-48885
48530 _setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { 48531 48532 const dest = this.resolvedProperty; 48533 48534 for ( let i = 0, n = dest.length; i !== n; ++ i ) { 48535 48536 dest[ i ] = buffer[ offset ++ ]; 48537 48538 } 48539 48540 this.targetObject.matrixWorldNeedsUpdate = true; 48541 48542 } 48543 48544 // ArrayElement 48545 48546 _setValue_arrayElement( buffer, offset ) { 48547 48548 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 48549 48550 } 48551 48552 _setValue_arrayElement_setNeedsUpdate( buffer, offset ) { 48553 48554 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 48555 this.targetObject.needsUpdate = true; 48556 48557 } 48558 48559 _setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { 48560 48561 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 48562 this.targetObject.matrixWorldNeedsUpdate = true; 48563 48564 } 48565 48566 // HasToFromArray 48567 48568 _setValue_fromArray( buffer, offset ) { 48569 48570 this.resolvedProperty.fromArray( buffer, offset ); 48571 48572 } 48573 48574 _setValue_fromArray_setNeedsUpdate( buffer, offset ) { 48575 48576 this.resolvedProperty.fromArray( buffer, offset ); 48577 this.targetObject.needsUpdate = true; 48578 48579 } 48580 48581 _setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { 48582 48583 this.resolvedProperty.fromArray( buffer, offset ); 48584 this.targetObject.matrixWorldNeedsUpdate = true; 48585 48586 } 48587 48588 _getValue_unbound( targetArray, offset ) { 48589 48590 this.bind(); 48591 this.getValue( targetArray, offset ); 48592 48593 } 48594 48595 _setValue_unbound( sourceArray, offset ) { 48596 48597 this.bind(); 48598 this.setValue( sourceArray, offset ); 48599 48600 } 48601 48602 // create getter / setter pair for a property in the scene graph 48603 bind() { 48604 48605 let targetObject = this.node; 48606 const parsedPath = this.parsedPath; 48607 48608 const objectName = parsedPath.objectName; 48609 const propertyName = parsedPath.propertyName; 48610 let propertyIndex = parsedPath.propertyIndex; 48611 48612 if ( ! targetObject ) { 48613 48614 targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ); 48615 48616 this.node = targetObject; 48617 48618 } 48619 48620 // set fail state so we can just 'return' on error 48621 this.getValue = this._getValue_unavailable; 48622 this.setValue = this._setValue_unavailable; 48623 48624 // ensure there is a value node 48625 if ( ! targetObject ) { 48626 48627 console.warn( 'THREE.PropertyBinding: No target node found for track: ' + this.path + '.' ); 48628 return; 48629 48630 } 48631 48632 if ( objectName ) { 48633 48634 let objectIndex = parsedPath.objectIndex; 48635 48636 // special cases were we need to reach deeper into the hierarchy to get the face materials.... 48637 switch ( objectName ) { 48638 48639 case 'materials': 48640 48641 if ( ! targetObject.material ) { 48642 48643 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); 48644 return; 48645 48646 } 48647 48648 if ( ! targetObject.material.materials ) { 48649 48650 console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this ); 48651 return; 48652 48653 } 48654 48655 targetObject = targetObject.material.materials; 48656 48657 break; 48658 48659 case 'bones': 48660 48661 if ( ! targetObject.skeleton ) { 48662 48663 console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this ); 48664 return; 48665 48666 } 48667 48668 // potential future optimization: skip this if propertyIndex is already an integer 48669 // and convert the integer string to a true integer. 48670 48671 targetObject = targetObject.skeleton.bones; 48672 48673 // support resolving morphTarget names into indices. 48674 for ( let i = 0; i < targetObject.length; i ++ ) { 48675 48676 if ( targetObject[ i ].name === objectIndex ) { 48677 48678 objectIndex = i; 48679 break; 48680 48681 } 48682 48683 } 48684 48685 break; 48686 48687 case 'map': 48688 48689 if ( 'map' in targetObject ) { 48690 48691 targetObject = targetObject.map; 48692 break; 48693 48694 } 48695 48696 if ( ! targetObject.material ) { 48697 48698 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); 48699 return; 48700 48701 } 48702 48703 if ( ! targetObject.material.map ) { 48704 48705 console.error( 'THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.', this ); 48706 return; 48707 48708 } 48709 48710 targetObject = targetObject.material.map; 48711 break; 48712 48713 default: 48714 48715 if ( targetObject[ objectName ] === undefined ) { 48716 48717 console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this ); 48718 return; 48719 48720 } 48721 48722 targetObject = targetObject[ objectName ]; 48723 48724 } 48725 48726 48727 if ( objectIndex !== undefined ) { 48728 48729 if ( targetObject[ objectIndex ] === undefined ) { 48730 48731 console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject ); 48732 return; 48733 48734 } 48735 48736 targetObject = targetObject[ objectIndex ]; 48737 48738 } 48739 48740 } 48741 48742 // resolve property 48743 const nodeProperty = targetObject[ propertyName ]; 48744 48745 if ( nodeProperty === undefined ) { 48746 48747 const nodeName = parsedPath.nodeName; 48748 48749 console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName + 48750 '.' + propertyName + ' but it wasn\'t found.', targetObject ); 48751 return; 48752 48753 } 48754 48755 // determine versioning scheme 48756 let versioning = this.Versioning.None; 48757 48758 this.targetObject = targetObject; 48759 48760 if ( targetObject.needsUpdate !== undefined ) { // material 48761 48762 versioning = this.Versioning.NeedsUpdate; 48763 48764 } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform 48765 48766 versioning = this.Versioning.MatrixWorldNeedsUpdate; 48767 48768 } 48769 48770 // determine how the property gets bound 48771 let bindingType = this.BindingType.Direct; 48772 48773 if ( propertyIndex !== undefined ) { 48774 48775 // access a sub element of the property array (only primitives are supported right now) 48776 48777 if ( propertyName === 'morphTargetInfluences' ) { 48778 48779 // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer. 48780 48781 // support resolving morphTarget names into indices. 48782 if ( ! targetObject.geometry ) { 48783 48784 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this ); 48785 return; 48786 48787 } 48788 48789 if ( ! targetObject.geometry.morphAttributes ) { 48790 48791 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this ); 48792 return; 48793 48794 } 48795 48796 if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) { 48797 48798 propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ]; 48799 48800 } 48801 48802 } 48803 48804 bindingType = this.BindingType.ArrayElement; 48805 48806 this.resolvedProperty = nodeProperty; 48807 this.propertyIndex = propertyIndex; 48808 48809 } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) { 48810 48811 // must use copy for Object3D.Euler/Quaternion 48812 48813 bindingType = this.BindingType.HasFromToArray; 48814 48815 this.resolvedProperty = nodeProperty; 48816 48817 } else if ( Array.isArray( nodeProperty ) ) { 48818 48819 bindingType = this.BindingType.EntireArray; 48820 48821 this.resolvedProperty = nodeProperty; 48822 48823 } else { 48824 48825 this.propertyName = propertyName; 48826 48827 } 48828 48829 // select getter / setter 48830 this.getValue = this.GetterByBindingType[ bindingType ]; 48831 this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; 48832 48833 } 48834 48835 unbind() { 48836 48837 this.node = null; 48838 48839 // back to the prototype version of getValue / setValue 48840 // note: avoiding to mutate the shape of 'this' via 'delete' 48841 this.getValue = this._getValue_unbound; 48842 this.setValue = this._setValue_unbound; 48843 48844 } 48845 48846} 48847 48848PropertyBinding.Composite = Composite; 48849 48850PropertyBinding.prototype.BindingType = { 48851 Direct: 0, 48852 EntireArray: 1, 48853 ArrayElement: 2, 48854 HasFromToArray: 3 48855}; 48856 48857PropertyBinding.prototype.Versioning = { 48858 None: 0, 48859 NeedsUpdate: 1, 48860 MatrixWorldNeedsUpdate: 2 48861}; 48862 48863PropertyBinding.prototype.GetterByBindingType = [ 48864 48865 PropertyBinding.prototype._getValue_direct, 48866 PropertyBinding.prototype._getValue_array, 48867 PropertyBinding.prototype._getValue_arrayElement, 48868 PropertyBinding.prototype._getValue_toArray, 48869 48870]; 48871 48872PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [ 48873 48874 [ 48875 // Direct 48876 PropertyBinding.prototype._setValue_direct, 48877 PropertyBinding.prototype._setValue_direct_setNeedsUpdate, 48878 PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate, 48879 48880 ], [ 48881 48882 // EntireArray 48883 48884 PropertyBinding.prototype._setValue_array, 48885 PropertyBinding.prototype._setValue_array_setNeedsUpdate,
vendor: 4,282 bytes, lines 48886-49066
48886 PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate, 48887 48888 ], [ 48889 48890 // ArrayElement 48891 PropertyBinding.prototype._setValue_arrayElement, 48892 PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate, 48893 PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate, 48894 48895 ], [ 48896 48897 // HasToFromArray 48898 PropertyBinding.prototype._setValue_fromArray, 48899 PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate, 48900 PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate, 48901 48902 ] 48903 48904]; 48905 48906/** 48907 * 48908 * A group of objects that receives a shared animation state. 48909 * 48910 * Usage: 48911 * 48912 * - Add objects you would otherwise pass as 'root' to the 48913 * constructor or the .clipAction method of AnimationMixer. 48914 * 48915 * - Instead pass this object as 'root'. 48916 * 48917 * - You can also add and remove objects later when the mixer 48918 * is running. 48919 * 48920 * Note: 48921 * 48922 * Objects of this class appear as one object to the mixer, 48923 * so cache control of the individual objects must be done 48924 * on the group. 48925 * 48926 * Limitation: 48927 * 48928 * - The animated properties must be compatible among the 48929 * all objects in the group. 48930 * 48931 * - A single property can either be controlled through a 48932 * target group or directly, but not both. 48933 */ 48934 48935class AnimationObjectGroup { 48936 48937 constructor() { 48938 48939 this.isAnimationObjectGroup = true; 48940 48941 this.uuid = generateUUID(); 48942 48943 // cached objects followed by the active ones 48944 this._objects = Array.prototype.slice.call( arguments ); 48945 48946 this.nCachedObjects_ = 0; // threshold 48947 // note: read by PropertyBinding.Composite 48948 48949 const indices = {}; 48950 this._indicesByUUID = indices; // for bookkeeping 48951 48952 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 48953 48954 indices[ arguments[ i ].uuid ] = i; 48955 48956 } 48957 48958 this._paths = []; // inside: string 48959 this._parsedPaths = []; // inside: { we don't care, here } 48960 this._bindings = []; // inside: Array< PropertyBinding > 48961 this._bindingsIndicesByPath = {}; // inside: indices in these arrays 48962 48963 const scope = this; 48964 48965 this.stats = { 48966 48967 objects: { 48968 get total() { 48969 48970 return scope._objects.length; 48971 48972 }, 48973 get inUse() { 48974 48975 return this.total - scope.nCachedObjects_; 48976 48977 } 48978 }, 48979 get bindingsPerObject() { 48980 48981 return scope._bindings.length; 48982 48983 } 48984 48985 }; 48986 48987 } 48988 48989 add() { 48990 48991 const objects = this._objects, 48992 indicesByUUID = this._indicesByUUID, 48993 paths = this._paths, 48994 parsedPaths = this._parsedPaths, 48995 bindings = this._bindings, 48996 nBindings = bindings.length; 48997 48998 let knownObject = undefined, 48999 nObjects = objects.length, 49000 nCachedObjects = this.nCachedObjects_; 49001 49002 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 49003 49004 const object = arguments[ i ], 49005 uuid = object.uuid; 49006 let index = indicesByUUID[ uuid ]; 49007 49008 if ( index === undefined ) { 49009 49010 // unknown object -> add it to the ACTIVE region 49011 49012 index = nObjects ++; 49013 indicesByUUID[ uuid ] = index; 49014 objects.push( object ); 49015 49016 // accounting is done, now do the same for all bindings 49017 49018 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 49019 49020 bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); 49021 49022 } 49023 49024 } else if ( index < nCachedObjects ) { 49025 49026 knownObject = objects[ index ]; 49027 49028 // move existing object to the ACTIVE region 49029 49030 const firstActiveIndex = -- nCachedObjects, 49031 lastCachedObject = objects[ firstActiveIndex ]; 49032 49033 indicesByUUID[ lastCachedObject.uuid ] = index; 49034 objects[ index ] = lastCachedObject; 49035 49036 indicesByUUID[ uuid ] = firstActiveIndex; 49037 objects[ firstActiveIndex ] = object; 49038 49039 // accounting is done, now do the same for all bindings 49040 49041 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 49042 49043 const bindingsForPath = bindings[ j ], 49044 lastCached = bindingsForPath[ firstActiveIndex ]; 49045 49046 let binding = bindingsForPath[ index ]; 49047 49048 bindingsForPath[ index ] = lastCached; 49049 49050 if ( binding === undefined ) { 49051 49052 // since we do not bother to create new bindings 49053 // for objects that are cached, the binding may 49054 // or may not exist 49055 49056 binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); 49057 49058 } 49059 49060 bindingsForPath[ firstActiveIndex ] = binding; 49061 49062 } 49063 49064 } else if ( objects[ index ] !== knownObject ) { 49065 49066 console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
vendor: 4,120 bytes, lines 49067-49233
49067 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); 49068 49069 } // else the object is already where we want it to be 49070 49071 } // for arguments 49072 49073 this.nCachedObjects_ = nCachedObjects; 49074 49075 } 49076 49077 remove() { 49078 49079 const objects = this._objects, 49080 indicesByUUID = this._indicesByUUID, 49081 bindings = this._bindings, 49082 nBindings = bindings.length; 49083 49084 let nCachedObjects = this.nCachedObjects_; 49085 49086 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 49087 49088 const object = arguments[ i ], 49089 uuid = object.uuid, 49090 index = indicesByUUID[ uuid ]; 49091 49092 if ( index !== undefined && index >= nCachedObjects ) { 49093 49094 // move existing object into the CACHED region 49095 49096 const lastCachedIndex = nCachedObjects ++, 49097 firstActiveObject = objects[ lastCachedIndex ]; 49098 49099 indicesByUUID[ firstActiveObject.uuid ] = index; 49100 objects[ index ] = firstActiveObject; 49101 49102 indicesByUUID[ uuid ] = lastCachedIndex; 49103 objects[ lastCachedIndex ] = object; 49104 49105 // accounting is done, now do the same for all bindings 49106 49107 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 49108 49109 const bindingsForPath = bindings[ j ], 49110 firstActive = bindingsForPath[ lastCachedIndex ], 49111 binding = bindingsForPath[ index ]; 49112 49113 bindingsForPath[ index ] = firstActive; 49114 bindingsForPath[ lastCachedIndex ] = binding; 49115 49116 } 49117 49118 } 49119 49120 } // for arguments 49121 49122 this.nCachedObjects_ = nCachedObjects; 49123 49124 } 49125 49126 // remove & forget 49127 uncache() { 49128 49129 const objects = this._objects, 49130 indicesByUUID = this._indicesByUUID, 49131 bindings = this._bindings, 49132 nBindings = bindings.length; 49133 49134 let nCachedObjects = this.nCachedObjects_, 49135 nObjects = objects.length; 49136 49137 for ( let i = 0, n = arguments.length; i !== n; ++ i ) { 49138 49139 const object = arguments[ i ], 49140 uuid = object.uuid, 49141 index = indicesByUUID[ uuid ]; 49142 49143 if ( index !== undefined ) { 49144 49145 delete indicesByUUID[ uuid ]; 49146 49147 if ( index < nCachedObjects ) { 49148 49149 // object is cached, shrink the CACHED region 49150 49151 const firstActiveIndex = -- nCachedObjects, 49152 lastCachedObject = objects[ firstActiveIndex ], 49153 lastIndex = -- nObjects, 49154 lastObject = objects[ lastIndex ]; 49155 49156 // last cached object takes this object's place 49157 indicesByUUID[ lastCachedObject.uuid ] = index; 49158 objects[ index ] = lastCachedObject; 49159 49160 // last object goes to the activated slot and pop 49161 indicesByUUID[ lastObject.uuid ] = firstActiveIndex; 49162 objects[ firstActiveIndex ] = lastObject; 49163 objects.pop(); 49164 49165 // accounting is done, now do the same for all bindings 49166 49167 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 49168 49169 const bindingsForPath = bindings[ j ], 49170 lastCached = bindingsForPath[ firstActiveIndex ], 49171 last = bindingsForPath[ lastIndex ]; 49172 49173 bindingsForPath[ index ] = lastCached; 49174 bindingsForPath[ firstActiveIndex ] = last; 49175 bindingsForPath.pop(); 49176 49177 } 49178 49179 } else { 49180 49181 // object is active, just swap with the last and pop 49182 49183 const lastIndex = -- nObjects, 49184 lastObject = objects[ lastIndex ]; 49185 49186 if ( lastIndex > 0 ) { 49187 49188 indicesByUUID[ lastObject.uuid ] = index; 49189 49190 } 49191 49192 objects[ index ] = lastObject; 49193 objects.pop(); 49194 49195 // accounting is done, now do the same for all bindings 49196 49197 for ( let j = 0, m = nBindings; j !== m; ++ j ) { 49198 49199 const bindingsForPath = bindings[ j ]; 49200 49201 bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; 49202 bindingsForPath.pop(); 49203 49204 } 49205 49206 } // cached or active 49207 49208 } // if object is known 49209 49210 } // for arguments 49211 49212 this.nCachedObjects_ = nCachedObjects; 49213 49214 } 49215 49216 // Internal interface used by befriended PropertyBinding.Composite: 49217 49218 subscribe_( path, parsedPath ) { 49219 49220 // returns an array of bindings for the given path that is changed 49221 // according to the contained objects in the group 49222 49223 const indicesByPath = this._bindingsIndicesByPath; 49224 let index = indicesByPath[ path ]; 49225 const bindings = this._bindings; 49226 49227 if ( index !== undefined ) return bindings[ index ]; 49228 49229 const paths = this._paths, 49230 parsedPaths = this._parsedPaths, 49231 objects = this._objects, 49232 nObjects = objects.length, 49233 nCachedObjects = this.nCachedObjects_,
vendor: 7,613 bytes, lines 49234-49627
49234 bindingsForPath = new Array( nObjects ); 49235 49236 index = bindings.length; 49237 49238 indicesByPath[ path ] = index; 49239 49240 paths.push( path ); 49241 parsedPaths.push( parsedPath ); 49242 bindings.push( bindingsForPath ); 49243 49244 for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) { 49245 49246 const object = objects[ i ]; 49247 bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); 49248 49249 } 49250 49251 return bindingsForPath; 49252 49253 } 49254 49255 unsubscribe_( path ) { 49256 49257 // tells the group to forget about a property path and no longer 49258 // update the array previously obtained with 'subscribe_' 49259 49260 const indicesByPath = this._bindingsIndicesByPath, 49261 index = indicesByPath[ path ]; 49262 49263 if ( index !== undefined ) { 49264 49265 const paths = this._paths, 49266 parsedPaths = this._parsedPaths, 49267 bindings = this._bindings, 49268 lastBindingsIndex = bindings.length - 1, 49269 lastBindings = bindings[ lastBindingsIndex ], 49270 lastBindingsPath = path[ lastBindingsIndex ]; 49271 49272 indicesByPath[ lastBindingsPath ] = index; 49273 49274 bindings[ index ] = lastBindings; 49275 bindings.pop(); 49276 49277 parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; 49278 parsedPaths.pop(); 49279 49280 paths[ index ] = paths[ lastBindingsIndex ]; 49281 paths.pop(); 49282 49283 } 49284 49285 } 49286 49287} 49288 49289class AnimationAction { 49290 49291 constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) { 49292 49293 this._mixer = mixer; 49294 this._clip = clip; 49295 this._localRoot = localRoot; 49296 this.blendMode = blendMode; 49297 49298 const tracks = clip.tracks, 49299 nTracks = tracks.length, 49300 interpolants = new Array( nTracks ); 49301 49302 const interpolantSettings = { 49303 endingStart: ZeroCurvatureEnding, 49304 endingEnd: ZeroCurvatureEnding 49305 }; 49306 49307 for ( let i = 0; i !== nTracks; ++ i ) { 49308 49309 const interpolant = tracks[ i ].createInterpolant( null ); 49310 interpolants[ i ] = interpolant; 49311 interpolant.settings = interpolantSettings; 49312 49313 } 49314 49315 this._interpolantSettings = interpolantSettings; 49316 49317 this._interpolants = interpolants; // bound by the mixer 49318 49319 // inside: PropertyMixer (managed by the mixer) 49320 this._propertyBindings = new Array( nTracks ); 49321 49322 this._cacheIndex = null; // for the memory manager 49323 this._byClipCacheIndex = null; // for the memory manager 49324 49325 this._timeScaleInterpolant = null; 49326 this._weightInterpolant = null; 49327 49328 this.loop = LoopRepeat; 49329 this._loopCount = - 1; 49330 49331 // global mixer time when the action is to be started 49332 // it's set back to 'null' upon start of the action 49333 this._startTime = null; 49334 49335 // scaled local time of the action 49336 // gets clamped or wrapped to 0..clip.duration according to loop 49337 this.time = 0; 49338 49339 this.timeScale = 1; 49340 this._effectiveTimeScale = 1; 49341 49342 this.weight = 1; 49343 this._effectiveWeight = 1; 49344 49345 this.repetitions = Infinity; // no. of repetitions when looping 49346 49347 this.paused = false; // true -> zero effective time scale 49348 this.enabled = true; // false -> zero effective weight 49349 49350 this.clampWhenFinished = false;// keep feeding the last frame? 49351 49352 this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate 49353 this.zeroSlopeAtEnd = true;// clips for start, loop and end 49354 49355 } 49356 49357 // State & Scheduling 49358 49359 play() { 49360 49361 this._mixer._activateAction( this ); 49362 49363 return this; 49364 49365 } 49366 49367 stop() { 49368 49369 this._mixer._deactivateAction( this ); 49370 49371 return this.reset(); 49372 49373 } 49374 49375 reset() { 49376 49377 this.paused = false; 49378 this.enabled = true; 49379 49380 this.time = 0; // restart clip 49381 this._loopCount = - 1;// forget previous loops 49382 this._startTime = null;// forget scheduling 49383 49384 return this.stopFading().stopWarping(); 49385 49386 } 49387 49388 isRunning() { 49389 49390 return this.enabled && ! this.paused && this.timeScale !== 0 && 49391 this._startTime === null && this._mixer._isActiveAction( this ); 49392 49393 } 49394 49395 // return true when play has been called 49396 isScheduled() { 49397 49398 return this._mixer._isActiveAction( this ); 49399 49400 } 49401 49402 startAt( time ) { 49403 49404 this._startTime = time; 49405 49406 return this; 49407 49408 } 49409 49410 setLoop( mode, repetitions ) { 49411 49412 this.loop = mode; 49413 this.repetitions = repetitions; 49414 49415 return this; 49416 49417 } 49418 49419 // Weight 49420 49421 // set the weight stopping any scheduled fading 49422 // although .enabled = false yields an effective weight of zero, this 49423 // method does *not* change .enabled, because it would be confusing 49424 setEffectiveWeight( weight ) { 49425 49426 this.weight = weight; 49427 49428 // note: same logic as when updated at runtime 49429 this._effectiveWeight = this.enabled ? weight : 0; 49430 49431 return this.stopFading(); 49432 49433 } 49434 49435 // return the weight considering fading and .enabled 49436 getEffectiveWeight() { 49437 49438 return this._effectiveWeight; 49439 49440 } 49441 49442 fadeIn( duration ) { 49443 49444 return this._scheduleFading( duration, 0, 1 ); 49445 49446 } 49447 49448 fadeOut( duration ) { 49449 49450 return this._scheduleFading( duration, 1, 0 ); 49451 49452 } 49453 49454 crossFadeFrom( fadeOutAction, duration, warp ) { 49455 49456 fadeOutAction.fadeOut( duration ); 49457 this.fadeIn( duration ); 49458 49459 if ( warp ) { 49460 49461 const fadeInDuration = this._clip.duration, 49462 fadeOutDuration = fadeOutAction._clip.duration, 49463 49464 startEndRatio = fadeOutDuration / fadeInDuration, 49465 endStartRatio = fadeInDuration / fadeOutDuration; 49466 49467 fadeOutAction.warp( 1.0, startEndRatio, duration ); 49468 this.warp( endStartRatio, 1.0, duration ); 49469 49470 } 49471 49472 return this; 49473 49474 } 49475 49476 crossFadeTo( fadeInAction, duration, warp ) { 49477 49478 return fadeInAction.crossFadeFrom( this, duration, warp ); 49479 49480 } 49481 49482 stopFading() { 49483 49484 const weightInterpolant = this._weightInterpolant; 49485 49486 if ( weightInterpolant !== null ) { 49487 49488 this._weightInterpolant = null; 49489 this._mixer._takeBackControlInterpolant( weightInterpolant ); 49490 49491 } 49492 49493 return this; 49494 49495 } 49496 49497 // Time Scale Control 49498 49499 // set the time scale stopping any scheduled warping 49500 // although .paused = true yields an effective time scale of zero, this 49501 // method does *not* change .paused, because it would be confusing 49502 setEffectiveTimeScale( timeScale ) { 49503 49504 this.timeScale = timeScale; 49505 this._effectiveTimeScale = this.paused ? 0 : timeScale; 49506 49507 return this.stopWarping(); 49508 49509 } 49510 49511 // return the time scale considering warping and .paused 49512 getEffectiveTimeScale() { 49513 49514 return this._effectiveTimeScale; 49515 49516 } 49517 49518 setDuration( duration ) { 49519 49520 this.timeScale = this._clip.duration / duration; 49521 49522 return this.stopWarping(); 49523 49524 } 49525 49526 syncWith( action ) { 49527 49528 this.time = action.time; 49529 this.timeScale = action.timeScale; 49530 49531 return this.stopWarping(); 49532 49533 } 49534 49535 halt( duration ) { 49536 49537 return this.warp( this._effectiveTimeScale, 0, duration ); 49538 49539 } 49540 49541 warp( startTimeScale, endTimeScale, duration ) { 49542 49543 const mixer = this._mixer, 49544 now = mixer.time, 49545 timeScale = this.timeScale; 49546 49547 let interpolant = this._timeScaleInterpolant; 49548 49549 if ( interpolant === null ) { 49550 49551 interpolant = mixer._lendControlInterpolant(); 49552 this._timeScaleInterpolant = interpolant; 49553 49554 } 49555 49556 const times = interpolant.parameterPositions, 49557 values = interpolant.sampleValues; 49558 49559 times[ 0 ] = now; 49560 times[ 1 ] = now + duration; 49561 49562 values[ 0 ] = startTimeScale / timeScale; 49563 values[ 1 ] = endTimeScale / timeScale; 49564 49565 return this; 49566 49567 } 49568 49569 stopWarping() { 49570 49571 const timeScaleInterpolant = this._timeScaleInterpolant; 49572 49573 if ( timeScaleInterpolant !== null ) { 49574 49575 this._timeScaleInterpolant = null; 49576 this._mixer._takeBackControlInterpolant( timeScaleInterpolant ); 49577 49578 } 49579 49580 return this; 49581 49582 } 49583 49584 // Object Accessors 49585 49586 getMixer() { 49587 49588 return this._mixer; 49589 49590 } 49591 49592 getClip() { 49593 49594 return this._clip; 49595 49596 } 49597 49598 getRoot() { 49599 49600 return this._localRoot || this._mixer._root; 49601 49602 } 49603 49604 // Interna 49605 49606 _update( time, deltaTime, timeDirection, accuIndex ) { 49607 49608 // called by the mixer 49609 49610 if ( ! this.enabled ) { 49611 49612 // call ._updateWeight() to update ._effectiveWeight 49613 49614 this._updateWeight( time ); 49615 return; 49616 49617 } 49618 49619 const startTime = this._startTime; 49620 49621 if ( startTime !== null ) { 49622 49623 // check for scheduled start of action 49624 49625 const timeRunning = ( time - startTime ) * timeDirection; 49626 if ( timeRunning < 0 || timeDirection === 0 ) { 49627
vendor: 6,044 bytes, lines 49628-49986
49628 deltaTime = 0; 49629 49630 } else { 49631 49632 49633 this._startTime = null; // unschedule 49634 deltaTime = timeDirection * timeRunning; 49635 49636 } 49637 49638 } 49639 49640 // apply time scale and advance time 49641 49642 deltaTime *= this._updateTimeScale( time ); 49643 const clipTime = this._updateTime( deltaTime ); 49644 49645 // note: _updateTime may disable the action resulting in 49646 // an effective weight of 0 49647 49648 const weight = this._updateWeight( time ); 49649 49650 if ( weight > 0 ) { 49651 49652 const interpolants = this._interpolants; 49653 const propertyMixers = this._propertyBindings; 49654 49655 switch ( this.blendMode ) { 49656 49657 case AdditiveAnimationBlendMode: 49658 49659 for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { 49660 49661 interpolants[ j ].evaluate( clipTime ); 49662 propertyMixers[ j ].accumulateAdditive( weight ); 49663 49664 } 49665 49666 break; 49667 49668 case NormalAnimationBlendMode: 49669 default: 49670 49671 for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { 49672 49673 interpolants[ j ].evaluate( clipTime ); 49674 propertyMixers[ j ].accumulate( accuIndex, weight ); 49675 49676 } 49677 49678 } 49679 49680 } 49681 49682 } 49683 49684 _updateWeight( time ) { 49685 49686 let weight = 0; 49687 49688 if ( this.enabled ) { 49689 49690 weight = this.weight; 49691 const interpolant = this._weightInterpolant; 49692 49693 if ( interpolant !== null ) { 49694 49695 const interpolantValue = interpolant.evaluate( time )[ 0 ]; 49696 49697 weight *= interpolantValue; 49698 49699 if ( time > interpolant.parameterPositions[ 1 ] ) { 49700 49701 this.stopFading(); 49702 49703 if ( interpolantValue === 0 ) { 49704 49705 // faded out, disable 49706 this.enabled = false; 49707 49708 } 49709 49710 } 49711 49712 } 49713 49714 } 49715 49716 this._effectiveWeight = weight; 49717 return weight; 49718 49719 } 49720 49721 _updateTimeScale( time ) { 49722 49723 let timeScale = 0; 49724 49725 if ( ! this.paused ) { 49726 49727 timeScale = this.timeScale; 49728 49729 const interpolant = this._timeScaleInterpolant; 49730 49731 if ( interpolant !== null ) { 49732 49733 const interpolantValue = interpolant.evaluate( time )[ 0 ]; 49734 49735 timeScale *= interpolantValue; 49736 49737 if ( time > interpolant.parameterPositions[ 1 ] ) { 49738 49739 this.stopWarping(); 49740 49741 if ( timeScale === 0 ) { 49742 49743 // motion has halted, pause 49744 this.paused = true; 49745 49746 } else { 49747 49748 // warp done - apply final time scale 49749 this.timeScale = timeScale; 49750 49751 } 49752 49753 } 49754 49755 } 49756 49757 } 49758 49759 this._effectiveTimeScale = timeScale; 49760 return timeScale; 49761 49762 } 49763 49764 _updateTime( deltaTime ) { 49765 49766 const duration = this._clip.duration; 49767 const loop = this.loop; 49768 49769 let time = this.time + deltaTime; 49770 let loopCount = this._loopCount; 49771 49772 const pingPong = ( loop === LoopPingPong ); 49773 49774 if ( deltaTime === 0 ) { 49775 49776 if ( loopCount === - 1 ) return time; 49777 49778 return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time; 49779 49780 } 49781 49782 if ( loop === LoopOnce ) { 49783 49784 if ( loopCount === - 1 ) { 49785 49786 // just started 49787 49788 this._loopCount = 0; 49789 this._setEndings( true, true, false ); 49790 49791 } 49792 49793 handle_stop: { 49794 49795 if ( time >= duration ) { 49796 49797 time = duration; 49798 49799 } else if ( time < 0 ) { 49800 49801 time = 0; 49802 49803 } else { 49804 49805 this.time = time; 49806 49807 break handle_stop; 49808 49809 } 49810 49811 if ( this.clampWhenFinished ) this.paused = true; 49812 else this.enabled = false; 49813 49814 this.time = time; 49815 49816 this._mixer.dispatchEvent( { 49817 type: 'finished', action: this, 49818 direction: deltaTime < 0 ? - 1 : 1 49819 } ); 49820 49821 } 49822 49823 } else { // repetitive Repeat or PingPong 49824 49825 if ( loopCount === - 1 ) { 49826 49827 // just started 49828 49829 if ( deltaTime >= 0 ) { 49830 49831 loopCount = 0; 49832 49833 this._setEndings( true, this.repetitions === 0, pingPong ); 49834 49835 } else { 49836 49837 // when looping in reverse direction, the initial 49838 // transition through zero counts as a repetition, 49839 // so leave loopCount at -1 49840 49841 this._setEndings( this.repetitions === 0, true, pingPong ); 49842 49843 } 49844 49845 } 49846 49847 if ( time >= duration || time < 0 ) { 49848 49849 // wrap around 49850 49851 const loopDelta = Math.floor( time / duration ); // signed 49852 time -= duration * loopDelta; 49853 49854 loopCount += Math.abs( loopDelta ); 49855 49856 const pending = this.repetitions - loopCount; 49857 49858 if ( pending <= 0 ) { 49859 49860 // have to stop (switch state, clamp time, fire event) 49861 49862 if ( this.clampWhenFinished ) this.paused = true; 49863 else this.enabled = false; 49864 49865 time = deltaTime > 0 ? duration : 0; 49866 49867 this.time = time; 49868 49869 this._mixer.dispatchEvent( { 49870 type: 'finished', action: this, 49871 direction: deltaTime > 0 ? 1 : - 1 49872 } ); 49873 49874 } else { 49875 49876 // keep running 49877 49878 if ( pending === 1 ) { 49879 49880 // entering the last round 49881 49882 const atStart = deltaTime < 0; 49883 this._setEndings( atStart, ! atStart, pingPong ); 49884 49885 } else { 49886 49887 this._setEndings( false, false, pingPong ); 49888 49889 } 49890 49891 this._loopCount = loopCount; 49892 49893 this.time = time; 49894 49895 this._mixer.dispatchEvent( { 49896 type: 'loop', action: this, loopDelta: loopDelta 49897 } ); 49898 49899 } 49900 49901 } else { 49902 49903 this.time = time; 49904 49905 } 49906 49907 if ( pingPong && ( loopCount & 1 ) === 1 ) { 49908 49909 // invert time for the "pong round" 49910 49911 return duration - time; 49912 49913 } 49914 49915 } 49916 49917 return time; 49918 49919 } 49920 49921 _setEndings( atStart, atEnd, pingPong ) { 49922 49923 const settings = this._interpolantSettings; 49924 49925 if ( pingPong ) { 49926 49927 settings.endingStart = ZeroSlopeEnding; 49928 settings.endingEnd = ZeroSlopeEnding; 49929 49930 } else { 49931 49932 // assuming for LoopOnce atStart == atEnd == true 49933 49934 if ( atStart ) { 49935 49936 settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding; 49937 49938 } else { 49939 49940 settings.endingStart = WrapAroundEnding; 49941 49942 } 49943 49944 if ( atEnd ) { 49945 49946 settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding; 49947 49948 } else { 49949 49950 settings.endingEnd = WrapAroundEnding; 49951 49952 } 49953 49954 } 49955 49956 } 49957 49958 _scheduleFading( duration, weightNow, weightThen ) { 49959 49960 const mixer = this._mixer, now = mixer.time; 49961 let interpolant = this._weightInterpolant; 49962 49963 if ( interpolant === null ) { 49964 49965 interpolant = mixer._lendControlInterpolant(); 49966 this._weightInterpolant = interpolant; 49967 49968 } 49969 49970 const times = interpolant.parameterPositions, 49971 values = interpolant.sampleValues; 49972 49973 times[ 0 ] = now; 49974 values[ 0 ] = weightNow; 49975 times[ 1 ] = now + duration; 49976 values[ 1 ] = weightThen; 49977 49978 return this; 49979 49980 } 49981 49982} 49983 49984const _controlInterpolantsResultBuffer = new Float32Array( 1 ); 49985 49986
vendor: 13,381 bytes, lines 49987-50627
49987class AnimationMixer extends EventDispatcher { 49988 49989 constructor( root ) { 49990 49991 super(); 49992 49993 this._root = root; 49994 this._initMemoryManager(); 49995 this._accuIndex = 0; 49996 this.time = 0; 49997 this.timeScale = 1.0; 49998 49999 } 50000 50001 _bindAction( action, prototypeAction ) { 50002 50003 const root = action._localRoot || this._root, 50004 tracks = action._clip.tracks, 50005 nTracks = tracks.length, 50006 bindings = action._propertyBindings, 50007 interpolants = action._interpolants, 50008 rootUuid = root.uuid, 50009 bindingsByRoot = this._bindingsByRootAndName; 50010 50011 let bindingsByName = bindingsByRoot[ rootUuid ]; 50012 50013 if ( bindingsByName === undefined ) { 50014 50015 bindingsByName = {}; 50016 bindingsByRoot[ rootUuid ] = bindingsByName; 50017 50018 } 50019 50020 for ( let i = 0; i !== nTracks; ++ i ) { 50021 50022 const track = tracks[ i ], 50023 trackName = track.name; 50024 50025 let binding = bindingsByName[ trackName ]; 50026 50027 if ( binding !== undefined ) { 50028 50029 ++ binding.referenceCount; 50030 bindings[ i ] = binding; 50031 50032 } else { 50033 50034 binding = bindings[ i ]; 50035 50036 if ( binding !== undefined ) { 50037 50038 // existing binding, make sure the cache knows 50039 50040 if ( binding._cacheIndex === null ) { 50041 50042 ++ binding.referenceCount; 50043 this._addInactiveBinding( binding, rootUuid, trackName ); 50044 50045 } 50046 50047 continue; 50048 50049 } 50050 50051 const path = prototypeAction && prototypeAction. 50052 _propertyBindings[ i ].binding.parsedPath; 50053 50054 binding = new PropertyMixer( 50055 PropertyBinding.create( root, trackName, path ), 50056 track.ValueTypeName, track.getValueSize() ); 50057 50058 ++ binding.referenceCount; 50059 this._addInactiveBinding( binding, rootUuid, trackName ); 50060 50061 bindings[ i ] = binding; 50062 50063 } 50064 50065 interpolants[ i ].resultBuffer = binding.buffer; 50066 50067 } 50068 50069 } 50070 50071 _activateAction( action ) { 50072 50073 if ( ! this._isActiveAction( action ) ) { 50074 50075 if ( action._cacheIndex === null ) { 50076 50077 // this action has been forgotten by the cache, but the user 50078 // appears to be still using it -> rebind 50079 50080 const rootUuid = ( action._localRoot || this._root ).uuid, 50081 clipUuid = action._clip.uuid, 50082 actionsForClip = this._actionsByClip[ clipUuid ]; 50083 50084 this._bindAction( action, 50085 actionsForClip && actionsForClip.knownActions[ 0 ] ); 50086 50087 this._addInactiveAction( action, clipUuid, rootUuid ); 50088 50089 } 50090 50091 const bindings = action._propertyBindings; 50092 50093 // increment reference counts / sort out state 50094 for ( let i = 0, n = bindings.length; i !== n; ++ i ) { 50095 50096 const binding = bindings[ i ]; 50097 50098 if ( binding.useCount ++ === 0 ) { 50099 50100 this._lendBinding( binding ); 50101 binding.saveOriginalState(); 50102 50103 } 50104 50105 } 50106 50107 this._lendAction( action ); 50108 50109 } 50110 50111 } 50112 50113 _deactivateAction( action ) { 50114 50115 if ( this._isActiveAction( action ) ) { 50116 50117 const bindings = action._propertyBindings; 50118 50119 // decrement reference counts / sort out state 50120 for ( let i = 0, n = bindings.length; i !== n; ++ i ) { 50121 50122 const binding = bindings[ i ]; 50123 50124 if ( -- binding.useCount === 0 ) { 50125 50126 binding.restoreOriginalState(); 50127 this._takeBackBinding( binding ); 50128 50129 } 50130 50131 } 50132 50133 this._takeBackAction( action ); 50134 50135 } 50136 50137 } 50138 50139 // Memory manager 50140 50141 _initMemoryManager() { 50142 50143 this._actions = []; // 'nActiveActions' followed by inactive ones 50144 this._nActiveActions = 0; 50145 50146 this._actionsByClip = {}; 50147 // inside: 50148 // { 50149 // knownActions: Array< AnimationAction > - used as prototypes 50150 // actionByRoot: AnimationAction - lookup 50151 // } 50152 50153 50154 this._bindings = []; // 'nActiveBindings' followed by inactive ones 50155 this._nActiveBindings = 0; 50156 50157 this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer > 50158 50159 50160 this._controlInterpolants = []; // same game as above 50161 this._nActiveControlInterpolants = 0; 50162 50163 const scope = this; 50164 50165 this.stats = { 50166 50167 actions: { 50168 get total() { 50169 50170 return scope._actions.length; 50171 50172 }, 50173 get inUse() { 50174 50175 return scope._nActiveActions; 50176 50177 } 50178 }, 50179 bindings: { 50180 get total() { 50181 50182 return scope._bindings.length; 50183 50184 }, 50185 get inUse() { 50186 50187 return scope._nActiveBindings; 50188 50189 } 50190 }, 50191 controlInterpolants: { 50192 get total() { 50193 50194 return scope._controlInterpolants.length; 50195 50196 }, 50197 get inUse() { 50198 50199 return scope._nActiveControlInterpolants; 50200 50201 } 50202 } 50203 50204 }; 50205 50206 } 50207 50208 // Memory management for AnimationAction objects 50209 50210 _isActiveAction( action ) { 50211 50212 const index = action._cacheIndex; 50213 return index !== null && index < this._nActiveActions; 50214 50215 } 50216 50217 _addInactiveAction( action, clipUuid, rootUuid ) { 50218 50219 const actions = this._actions, 50220 actionsByClip = this._actionsByClip; 50221 50222 let actionsForClip = actionsByClip[ clipUuid ]; 50223 50224 if ( actionsForClip === undefined ) { 50225 50226 actionsForClip = { 50227 50228 knownActions: [ action ], 50229 actionByRoot: {} 50230 50231 }; 50232 50233 action._byClipCacheIndex = 0; 50234 50235 actionsByClip[ clipUuid ] = actionsForClip; 50236 50237 } else { 50238 50239 const knownActions = actionsForClip.knownActions; 50240 50241 action._byClipCacheIndex = knownActions.length; 50242 knownActions.push( action ); 50243 50244 } 50245 50246 action._cacheIndex = actions.length; 50247 actions.push( action ); 50248 50249 actionsForClip.actionByRoot[ rootUuid ] = action; 50250 50251 } 50252 50253 _removeInactiveAction( action ) { 50254 50255 const actions = this._actions, 50256 lastInactiveAction = actions[ actions.length - 1 ], 50257 cacheIndex = action._cacheIndex; 50258 50259 lastInactiveAction._cacheIndex = cacheIndex; 50260 actions[ cacheIndex ] = lastInactiveAction; 50261 actions.pop(); 50262 50263 action._cacheIndex = null; 50264 50265 50266 const clipUuid = action._clip.uuid, 50267 actionsByClip = this._actionsByClip, 50268 actionsForClip = actionsByClip[ clipUuid ], 50269 knownActionsForClip = actionsForClip.knownActions, 50270 50271 lastKnownAction = 50272 knownActionsForClip[ knownActionsForClip.length - 1 ], 50273 50274 byClipCacheIndex = action._byClipCacheIndex; 50275 50276 lastKnownAction._byClipCacheIndex = byClipCacheIndex; 50277 knownActionsForClip[ byClipCacheIndex ] = lastKnownAction; 50278 knownActionsForClip.pop(); 50279 50280 action._byClipCacheIndex = null; 50281 50282 50283 const actionByRoot = actionsForClip.actionByRoot, 50284 rootUuid = ( action._localRoot || this._root ).uuid; 50285 50286 delete actionByRoot[ rootUuid ]; 50287 50288 if ( knownActionsForClip.length === 0 ) { 50289 50290 delete actionsByClip[ clipUuid ]; 50291 50292 } 50293 50294 this._removeInactiveBindingsForAction( action ); 50295 50296 } 50297 50298 _removeInactiveBindingsForAction( action ) { 50299 50300 const bindings = action._propertyBindings; 50301 50302 for ( let i = 0, n = bindings.length; i !== n; ++ i ) { 50303 50304 const binding = bindings[ i ]; 50305 50306 if ( -- binding.referenceCount === 0 ) { 50307 50308 this._removeInactiveBinding( binding ); 50309 50310 } 50311 50312 } 50313 50314 } 50315 50316 _lendAction( action ) { 50317 50318 // [ active actions | inactive actions ] 50319 // [ active actions >| inactive actions ] 50320 // s a 50321 // <-swap-> 50322 // a s 50323 50324 const actions = this._actions, 50325 prevIndex = action._cacheIndex, 50326 50327 lastActiveIndex = this._nActiveActions ++, 50328 50329 firstInactiveAction = actions[ lastActiveIndex ]; 50330 50331 action._cacheIndex = lastActiveIndex; 50332 actions[ lastActiveIndex ] = action; 50333 50334 firstInactiveAction._cacheIndex = prevIndex; 50335 actions[ prevIndex ] = firstInactiveAction; 50336 50337 } 50338 50339 _takeBackAction( action ) { 50340 50341 // [ active actions | inactive actions ] 50342 // [ active actions |< inactive actions ] 50343 // a s 50344 // <-swap-> 50345 // s a 50346 50347 const actions = this._actions, 50348 prevIndex = action._cacheIndex, 50349 50350 firstInactiveIndex = -- this._nActiveActions, 50351 50352 lastActiveAction = actions[ firstInactiveIndex ]; 50353 50354 action._cacheIndex = firstInactiveIndex; 50355 actions[ firstInactiveIndex ] = action; 50356 50357 lastActiveAction._cacheIndex = prevIndex; 50358 actions[ prevIndex ] = lastActiveAction; 50359 50360 } 50361 50362 // Memory management for PropertyMixer objects 50363 50364 _addInactiveBinding( binding, rootUuid, trackName ) { 50365 50366 const bindingsByRoot = this._bindingsByRootAndName, 50367 bindings = this._bindings; 50368 50369 let bindingByName = bindingsByRoot[ rootUuid ]; 50370 50371 if ( bindingByName === undefined ) { 50372 50373 bindingByName = {}; 50374 bindingsByRoot[ rootUuid ] = bindingByName; 50375 50376 } 50377 50378 bindingByName[ trackName ] = binding; 50379 50380 binding._cacheIndex = bindings.length; 50381 bindings.push( binding ); 50382 50383 } 50384 50385 _removeInactiveBinding( binding ) { 50386 50387 const bindings = this._bindings, 50388 propBinding = binding.binding, 50389 rootUuid = propBinding.rootNode.uuid, 50390 trackName = propBinding.path, 50391 bindingsByRoot = this._bindingsByRootAndName, 50392 bindingByName = bindingsByRoot[ rootUuid ], 50393 50394 lastInactiveBinding = bindings[ bindings.length - 1 ], 50395 cacheIndex = binding._cacheIndex; 50396 50397 lastInactiveBinding._cacheIndex = cacheIndex; 50398 bindings[ cacheIndex ] = lastInactiveBinding; 50399 bindings.pop(); 50400 50401 delete bindingByName[ trackName ]; 50402 50403 if ( Object.keys( bindingByName ).length === 0 ) { 50404 50405 delete bindingsByRoot[ rootUuid ]; 50406 50407 } 50408 50409 } 50410 50411 _lendBinding( binding ) { 50412 50413 const bindings = this._bindings, 50414 prevIndex = binding._cacheIndex, 50415 50416 lastActiveIndex = this._nActiveBindings ++, 50417 50418 firstInactiveBinding = bindings[ lastActiveIndex ]; 50419 50420 binding._cacheIndex = lastActiveIndex; 50421 bindings[ lastActiveIndex ] = binding; 50422 50423 firstInactiveBinding._cacheIndex = prevIndex; 50424 bindings[ prevIndex ] = firstInactiveBinding; 50425 50426 } 50427 50428 _takeBackBinding( binding ) { 50429 50430 const bindings = this._bindings, 50431 prevIndex = binding._cacheIndex, 50432 50433 firstInactiveIndex = -- this._nActiveBindings, 50434 50435 lastActiveBinding = bindings[ firstInactiveIndex ]; 50436 50437 binding._cacheIndex = firstInactiveIndex; 50438 bindings[ firstInactiveIndex ] = binding; 50439 50440 lastActiveBinding._cacheIndex = prevIndex; 50441 bindings[ prevIndex ] = lastActiveBinding; 50442 50443 } 50444 50445 50446 // Memory management of Interpolants for weight and time scale 50447 50448 _lendControlInterpolant() { 50449 50450 const interpolants = this._controlInterpolants, 50451 lastActiveIndex = this._nActiveControlInterpolants ++; 50452 50453 let interpolant = interpolants[ lastActiveIndex ]; 50454 50455 if ( interpolant === undefined ) { 50456 50457 interpolant = new LinearInterpolant( 50458 new Float32Array( 2 ), new Float32Array( 2 ), 50459 1, _controlInterpolantsResultBuffer ); 50460 50461 interpolant.__cacheIndex = lastActiveIndex; 50462 interpolants[ lastActiveIndex ] = interpolant; 50463 50464 } 50465 50466 return interpolant; 50467 50468 } 50469 50470 _takeBackControlInterpolant( interpolant ) { 50471 50472 const interpolants = this._controlInterpolants, 50473 prevIndex = interpolant.__cacheIndex, 50474 50475 firstInactiveIndex = -- this._nActiveControlInterpolants, 50476 50477 lastActiveInterpolant = interpolants[ firstInactiveIndex ]; 50478 50479 interpolant.__cacheIndex = firstInactiveIndex; 50480 interpolants[ firstInactiveIndex ] = interpolant; 50481 50482 lastActiveInterpolant.__cacheIndex = prevIndex; 50483 interpolants[ prevIndex ] = lastActiveInterpolant; 50484 50485 } 50486 50487 // return an action for a clip optionally using a custom root target 50488 // object (this method allocates a lot of dynamic memory in case a 50489 // previously unknown clip/root combination is specified) 50490 clipAction( clip, optionalRoot, blendMode ) { 50491 50492 const root = optionalRoot || this._root, 50493 rootUuid = root.uuid; 50494 50495 let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip; 50496 50497 const clipUuid = clipObject !== null ? clipObject.uuid : clip; 50498 50499 const actionsForClip = this._actionsByClip[ clipUuid ]; 50500 let prototypeAction = null; 50501 50502 if ( blendMode === undefined ) { 50503 50504 if ( clipObject !== null ) { 50505 50506 blendMode = clipObject.blendMode; 50507 50508 } else { 50509 50510 blendMode = NormalAnimationBlendMode; 50511 50512 } 50513 50514 } 50515 50516 if ( actionsForClip !== undefined ) { 50517 50518 const existingAction = actionsForClip.actionByRoot[ rootUuid ]; 50519 50520 if ( existingAction !== undefined && existingAction.blendMode === blendMode ) { 50521 50522 return existingAction; 50523 50524 } 50525 50526 // we know the clip, so we don't have to parse all 50527 // the bindings again but can just copy 50528 prototypeAction = actionsForClip.knownActions[ 0 ]; 50529 50530 // also, take the clip from the prototype action 50531 if ( clipObject === null ) 50532 clipObject = prototypeAction._clip; 50533 50534 } 50535 50536 // clip must be known when specified via string 50537 if ( clipObject === null ) return null; 50538 50539 // allocate all resources required to run it 50540 const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode ); 50541 50542 this._bindAction( newAction, prototypeAction ); 50543 50544 // and make the action known to the memory manager 50545 this._addInactiveAction( newAction, clipUuid, rootUuid ); 50546 50547 return newAction; 50548 50549 } 50550 50551 // get an existing action 50552 existingAction( clip, optionalRoot ) { 50553 50554 const root = optionalRoot || this._root, 50555 rootUuid = root.uuid, 50556 50557 clipObject = typeof clip === 'string' ? 50558 AnimationClip.findByName( root, clip ) : clip, 50559 50560 clipUuid = clipObject ? clipObject.uuid : clip, 50561 50562 actionsForClip = this._actionsByClip[ clipUuid ]; 50563 50564 if ( actionsForClip !== undefined ) { 50565 50566 return actionsForClip.actionByRoot[ rootUuid ] || null; 50567 50568 } 50569 50570 return null; 50571 50572 } 50573 50574 // deactivates all previously scheduled actions 50575 stopAllAction() { 50576 50577 const actions = this._actions, 50578 nActions = this._nActiveActions; 50579 50580 for ( let i = nActions - 1; i >= 0; -- i ) { 50581 50582 actions[ i ].stop(); 50583 50584 } 50585 50586 return this; 50587 50588 } 50589 50590 // advance the time and update apply the animation 50591 update( deltaTime ) { 50592 50593 deltaTime *= this.timeScale; 50594 50595 const actions = this._actions, 50596 nActions = this._nActiveActions, 50597 50598 time = this.time += deltaTime, 50599 timeDirection = Math.sign( deltaTime ), 50600 50601 accuIndex = this._accuIndex ^= 1; 50602 50603 // run active actions 50604 50605 for ( let i = 0; i !== nActions; ++ i ) { 50606 50607 const action = actions[ i ]; 50608 50609 action._update( time, deltaTime, timeDirection, accuIndex ); 50610 50611 } 50612 50613 // update scene graph 50614 50615 const bindings = this._bindings, 50616 nBindings = this._nActiveBindings; 50617 50618 for ( let i = 0; i !== nBindings; ++ i ) { 50619 50620 bindings[ i ].apply( accuIndex ); 50621 50622 } 50623 50624 return this; 50625 50626 } 50627
vendor: 2,763 bytes, lines 50628-50761
50628 // Allows you to seek to a specific time in an animation. 50629 setTime( timeInSeconds ) { 50630 50631 this.time = 0; // Zero out time attribute for AnimationMixer object; 50632 for ( let i = 0; i < this._actions.length; i ++ ) { 50633 50634 this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects. 50635 50636 } 50637 50638 return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object. 50639 50640 } 50641 50642 // return this mixer's root target object 50643 getRoot() { 50644 50645 return this._root; 50646 50647 } 50648 50649 // free all resources specific to a particular clip 50650 uncacheClip( clip ) { 50651 50652 const actions = this._actions, 50653 clipUuid = clip.uuid, 50654 actionsByClip = this._actionsByClip, 50655 actionsForClip = actionsByClip[ clipUuid ]; 50656 50657 if ( actionsForClip !== undefined ) { 50658 50659 // note: just calling _removeInactiveAction would mess up the 50660 // iteration state and also require updating the state we can 50661 // just throw away 50662 50663 const actionsToRemove = actionsForClip.knownActions; 50664 50665 for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) { 50666 50667 const action = actionsToRemove[ i ]; 50668 50669 this._deactivateAction( action ); 50670 50671 const cacheIndex = action._cacheIndex, 50672 lastInactiveAction = actions[ actions.length - 1 ]; 50673 50674 action._cacheIndex = null; 50675 action._byClipCacheIndex = null; 50676 50677 lastInactiveAction._cacheIndex = cacheIndex; 50678 actions[ cacheIndex ] = lastInactiveAction; 50679 actions.pop(); 50680 50681 this._removeInactiveBindingsForAction( action ); 50682 50683 } 50684 50685 delete actionsByClip[ clipUuid ]; 50686 50687 } 50688 50689 } 50690 50691 // free all resources specific to a particular root target object 50692 uncacheRoot( root ) { 50693 50694 const rootUuid = root.uuid, 50695 actionsByClip = this._actionsByClip; 50696 50697 for ( const clipUuid in actionsByClip ) { 50698 50699 const actionByRoot = actionsByClip[ clipUuid ].actionByRoot, 50700 action = actionByRoot[ rootUuid ]; 50701 50702 if ( action !== undefined ) { 50703 50704 this._deactivateAction( action ); 50705 this._removeInactiveAction( action ); 50706 50707 } 50708 50709 } 50710 50711 const bindingsByRoot = this._bindingsByRootAndName, 50712 bindingByName = bindingsByRoot[ rootUuid ]; 50713 50714 if ( bindingByName !== undefined ) { 50715 50716 for ( const trackName in bindingByName ) { 50717 50718 const binding = bindingByName[ trackName ]; 50719 binding.restoreOriginalState(); 50720 this._removeInactiveBinding( binding ); 50721 50722 } 50723 50724 } 50725 50726 } 50727 50728 // remove a targeted clip from the cache 50729 uncacheAction( clip, optionalRoot ) { 50730 50731 const action = this.existingAction( clip, optionalRoot ); 50732 50733 if ( action !== null ) { 50734 50735 this._deactivateAction( action ); 50736 this._removeInactiveAction( action ); 50737 50738 } 50739 50740 } 50741 50742} 50743 50744class Uniform { 50745 50746 constructor( value ) { 50747 50748 this.value = value; 50749 50750 } 50751 50752 clone() { 50753 50754 return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() ); 50755 50756 } 50757 50758} 50759 50760let _id = 0; 50761
vendor: 4,926 bytes, lines 50762-51073
50762class UniformsGroup extends EventDispatcher { 50763 50764 constructor() { 50765 50766 super(); 50767 50768 this.isUniformsGroup = true; 50769 50770 Object.defineProperty( this, 'id', { value: _id ++ } ); 50771 50772 this.name = ''; 50773 50774 this.usage = StaticDrawUsage; 50775 this.uniforms = []; 50776 50777 } 50778 50779 add( uniform ) { 50780 50781 this.uniforms.push( uniform ); 50782 50783 return this; 50784 50785 } 50786 50787 remove( uniform ) { 50788 50789 const index = this.uniforms.indexOf( uniform ); 50790 50791 if ( index !== - 1 ) this.uniforms.splice( index, 1 ); 50792 50793 return this; 50794 50795 } 50796 50797 setName( name ) { 50798 50799 this.name = name; 50800 50801 return this; 50802 50803 } 50804 50805 setUsage( value ) { 50806 50807 this.usage = value; 50808 50809 return this; 50810 50811 } 50812 50813 dispose() { 50814 50815 this.dispatchEvent( { type: 'dispose' } ); 50816 50817 return this; 50818 50819 } 50820 50821 copy( source ) { 50822 50823 this.name = source.name; 50824 this.usage = source.usage; 50825 50826 const uniformsSource = source.uniforms; 50827 50828 this.uniforms.length = 0; 50829 50830 for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) { 50831 50832 const uniforms = Array.isArray( uniformsSource[ i ] ) ? uniformsSource[ i ] : [ uniformsSource[ i ] ]; 50833 50834 for ( let j = 0; j < uniforms.length; j ++ ) { 50835 50836 this.uniforms.push( uniforms[ j ].clone() ); 50837 50838 } 50839 50840 } 50841 50842 return this; 50843 50844 } 50845 50846 clone() { 50847 50848 return new this.constructor().copy( this ); 50849 50850 } 50851 50852} 50853 50854class InstancedInterleavedBuffer extends InterleavedBuffer { 50855 50856 constructor( array, stride, meshPerAttribute = 1 ) { 50857 50858 super( array, stride ); 50859 50860 this.isInstancedInterleavedBuffer = true; 50861 50862 this.meshPerAttribute = meshPerAttribute; 50863 50864 } 50865 50866 copy( source ) { 50867 50868 super.copy( source ); 50869 50870 this.meshPerAttribute = source.meshPerAttribute; 50871 50872 return this; 50873 50874 } 50875 50876 clone( data ) { 50877 50878 const ib = super.clone( data ); 50879 50880 ib.meshPerAttribute = this.meshPerAttribute; 50881 50882 return ib; 50883 50884 } 50885 50886 toJSON( data ) { 50887 50888 const json = super.toJSON( data ); 50889 50890 json.isInstancedInterleavedBuffer = true; 50891 json.meshPerAttribute = this.meshPerAttribute; 50892 50893 return json; 50894 50895 } 50896 50897} 50898 50899class GLBufferAttribute { 50900 50901 constructor( buffer, type, itemSize, elementSize, count ) { 50902 50903 this.isGLBufferAttribute = true; 50904 50905 this.name = ''; 50906 50907 this.buffer = buffer; 50908 this.type = type; 50909 this.itemSize = itemSize; 50910 this.elementSize = elementSize; 50911 this.count = count; 50912 50913 this.version = 0; 50914 50915 } 50916 50917 set needsUpdate( value ) { 50918 50919 if ( value === true ) this.version ++; 50920 50921 } 50922 50923 setBuffer( buffer ) { 50924 50925 this.buffer = buffer; 50926 50927 return this; 50928 50929 } 50930 50931 setType( type, elementSize ) { 50932 50933 this.type = type; 50934 this.elementSize = elementSize; 50935 50936 return this; 50937 50938 } 50939 50940 setItemSize( itemSize ) { 50941 50942 this.itemSize = itemSize; 50943 50944 return this; 50945 50946 } 50947 50948 setCount( count ) { 50949 50950 this.count = count; 50951 50952 return this; 50953 50954 } 50955 50956} 50957 50958class Raycaster { 50959 50960 constructor( origin, direction, near = 0, far = Infinity ) { 50961 50962 this.ray = new Ray( origin, direction ); 50963 // direction is assumed to be normalized (for accurate distance calculations) 50964 50965 this.near = near; 50966 this.far = far; 50967 this.camera = null; 50968 this.layers = new Layers(); 50969 50970 this.params = { 50971 Mesh: {}, 50972 Line: { threshold: 1 }, 50973 LOD: {}, 50974 Points: { threshold: 1 }, 50975 Sprite: {} 50976 }; 50977 50978 } 50979 50980 set( origin, direction ) { 50981 50982 // direction is assumed to be normalized (for accurate distance calculations) 50983 50984 this.ray.set( origin, direction ); 50985 50986 } 50987 50988 setFromCamera( coords, camera ) { 50989 50990 if ( camera.isPerspectiveCamera ) { 50991 50992 this.ray.origin.setFromMatrixPosition( camera.matrixWorld ); 50993 this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize(); 50994 this.camera = camera; 50995 50996 } else if ( camera.isOrthographicCamera ) { 50997 50998 this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera 50999 this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); 51000 this.camera = camera; 51001 51002 } else { 51003 51004 console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type ); 51005 51006 } 51007 51008 } 51009 51010 intersectObject( object, recursive = true, intersects = [] ) { 51011 51012 intersectObject( object, this, intersects, recursive ); 51013 51014 intersects.sort( ascSort ); 51015 51016 return intersects; 51017 51018 } 51019 51020 intersectObjects( objects, recursive = true, intersects = [] ) { 51021 51022 for ( let i = 0, l = objects.length; i < l; i ++ ) { 51023 51024 intersectObject( objects[ i ], this, intersects, recursive ); 51025 51026 } 51027 51028 intersects.sort( ascSort ); 51029 51030 return intersects; 51031 51032 } 51033 51034} 51035 51036function ascSort( a, b ) { 51037 51038 return a.distance - b.distance; 51039 51040} 51041 51042function intersectObject( object, raycaster, intersects, recursive ) { 51043 51044 if ( object.layers.test( raycaster.layers ) ) { 51045 51046 object.raycast( raycaster, intersects ); 51047 51048 } 51049 51050 if ( recursive === true ) { 51051 51052 const children = object.children; 51053 51054 for ( let i = 0, l = children.length; i < l; i ++ ) { 51055 51056 intersectObject( children[ i ], raycaster, intersects, true ); 51057 51058 } 51059 51060 } 51061 51062} 51063 51064/** 51065 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system 51066 * 51067 * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up. 51068 * The azimuthal angle (theta) is measured from the positive z-axis. 51069 */ 51070 51071 51072class Spherical { 51073
vendor: 20,801 bytes, lines 51074-52209
51074 constructor( radius = 1, phi = 0, theta = 0 ) { 51075 51076 this.radius = radius; 51077 this.phi = phi; // polar angle 51078 this.theta = theta; // azimuthal angle 51079 51080 return this; 51081 51082 } 51083 51084 set( radius, phi, theta ) { 51085 51086 this.radius = radius; 51087 this.phi = phi; 51088 this.theta = theta; 51089 51090 return this; 51091 51092 } 51093 51094 copy( other ) { 51095 51096 this.radius = other.radius; 51097 this.phi = other.phi; 51098 this.theta = other.theta; 51099 51100 return this; 51101 51102 } 51103 51104 // restrict phi to be between EPS and PI-EPS 51105 makeSafe() { 51106 51107 const EPS = 0.000001; 51108 this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) ); 51109 51110 return this; 51111 51112 } 51113 51114 setFromVector3( v ) { 51115 51116 return this.setFromCartesianCoords( v.x, v.y, v.z ); 51117 51118 } 51119 51120 setFromCartesianCoords( x, y, z ) { 51121 51122 this.radius = Math.sqrt( x * x + y * y + z * z ); 51123 51124 if ( this.radius === 0 ) { 51125 51126 this.theta = 0; 51127 this.phi = 0; 51128 51129 } else { 51130 51131 this.theta = Math.atan2( x, z ); 51132 this.phi = Math.acos( clamp( y / this.radius, - 1, 1 ) ); 51133 51134 } 51135 51136 return this; 51137 51138 } 51139 51140 clone() { 51141 51142 return new this.constructor().copy( this ); 51143 51144 } 51145 51146} 51147 51148/** 51149 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system 51150 */ 51151 51152class Cylindrical { 51153 51154 constructor( radius = 1, theta = 0, y = 0 ) { 51155 51156 this.radius = radius; // distance from the origin to a point in the x-z plane 51157 this.theta = theta; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis 51158 this.y = y; // height above the x-z plane 51159 51160 return this; 51161 51162 } 51163 51164 set( radius, theta, y ) { 51165 51166 this.radius = radius; 51167 this.theta = theta; 51168 this.y = y; 51169 51170 return this; 51171 51172 } 51173 51174 copy( other ) { 51175 51176 this.radius = other.radius; 51177 this.theta = other.theta; 51178 this.y = other.y; 51179 51180 return this; 51181 51182 } 51183 51184 setFromVector3( v ) { 51185 51186 return this.setFromCartesianCoords( v.x, v.y, v.z ); 51187 51188 } 51189 51190 setFromCartesianCoords( x, y, z ) { 51191 51192 this.radius = Math.sqrt( x * x + z * z ); 51193 this.theta = Math.atan2( x, z ); 51194 this.y = y; 51195 51196 return this; 51197 51198 } 51199 51200 clone() { 51201 51202 return new this.constructor().copy( this ); 51203 51204 } 51205 51206} 51207 51208const _vector$4 = /*@__PURE__*/ new Vector2(); 51209 51210class Box2 { 51211 51212 constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) { 51213 51214 this.isBox2 = true; 51215 51216 this.min = min; 51217 this.max = max; 51218 51219 } 51220 51221 set( min, max ) { 51222 51223 this.min.copy( min ); 51224 this.max.copy( max ); 51225 51226 return this; 51227 51228 } 51229 51230 setFromPoints( points ) { 51231 51232 this.makeEmpty(); 51233 51234 for ( let i = 0, il = points.length; i < il; i ++ ) { 51235 51236 this.expandByPoint( points[ i ] ); 51237 51238 } 51239 51240 return this; 51241 51242 } 51243 51244 setFromCenterAndSize( center, size ) { 51245 51246 const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 ); 51247 this.min.copy( center ).sub( halfSize ); 51248 this.max.copy( center ).add( halfSize ); 51249 51250 return this; 51251 51252 } 51253 51254 clone() { 51255 51256 return new this.constructor().copy( this ); 51257 51258 } 51259 51260 copy( box ) { 51261 51262 this.min.copy( box.min ); 51263 this.max.copy( box.max ); 51264 51265 return this; 51266 51267 } 51268 51269 makeEmpty() { 51270 51271 this.min.x = this.min.y = + Infinity; 51272 this.max.x = this.max.y = - Infinity; 51273 51274 return this; 51275 51276 } 51277 51278 isEmpty() { 51279 51280 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes 51281 51282 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); 51283 51284 } 51285 51286 getCenter( target ) { 51287 51288 return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); 51289 51290 } 51291 51292 getSize( target ) { 51293 51294 return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min ); 51295 51296 } 51297 51298 expandByPoint( point ) { 51299 51300 this.min.min( point ); 51301 this.max.max( point ); 51302 51303 return this; 51304 51305 } 51306 51307 expandByVector( vector ) { 51308 51309 this.min.sub( vector ); 51310 this.max.add( vector ); 51311 51312 return this; 51313 51314 } 51315 51316 expandByScalar( scalar ) { 51317 51318 this.min.addScalar( - scalar ); 51319 this.max.addScalar( scalar ); 51320 51321 return this; 51322 51323 } 51324 51325 containsPoint( point ) { 51326 51327 return point.x < this.min.x || point.x > this.max.x || 51328 point.y < this.min.y || point.y > this.max.y ? false : true; 51329 51330 } 51331 51332 containsBox( box ) { 51333 51334 return this.min.x <= box.min.x && box.max.x <= this.max.x && 51335 this.min.y <= box.min.y && box.max.y <= this.max.y; 51336 51337 } 51338 51339 getParameter( point, target ) { 51340 51341 // This can potentially have a divide by zero if the box 51342 // has a size dimension of 0. 51343 51344 return target.set( 51345 ( point.x - this.min.x ) / ( this.max.x - this.min.x ), 51346 ( point.y - this.min.y ) / ( this.max.y - this.min.y ) 51347 ); 51348 51349 } 51350 51351 intersectsBox( box ) { 51352 51353 // using 4 splitting planes to rule out intersections 51354 51355 return box.max.x < this.min.x || box.min.x > this.max.x || 51356 box.max.y < this.min.y || box.min.y > this.max.y ? false : true; 51357 51358 } 51359 51360 clampPoint( point, target ) { 51361 51362 return target.copy( point ).clamp( this.min, this.max ); 51363 51364 } 51365 51366 distanceToPoint( point ) { 51367 51368 return this.clampPoint( point, _vector$4 ).distanceTo( point ); 51369 51370 } 51371 51372 intersect( box ) { 51373 51374 this.min.max( box.min ); 51375 this.max.min( box.max ); 51376 51377 if ( this.isEmpty() ) this.makeEmpty(); 51378 51379 return this; 51380 51381 } 51382 51383 union( box ) { 51384 51385 this.min.min( box.min ); 51386 this.max.max( box.max ); 51387 51388 return this; 51389 51390 } 51391 51392 translate( offset ) { 51393 51394 this.min.add( offset ); 51395 this.max.add( offset ); 51396 51397 return this; 51398 51399 } 51400 51401 equals( box ) { 51402 51403 return box.min.equals( this.min ) && box.max.equals( this.max ); 51404 51405 } 51406 51407} 51408 51409const _startP = /*@__PURE__*/ new Vector3(); 51410const _startEnd = /*@__PURE__*/ new Vector3(); 51411 51412class Line3 { 51413 51414 constructor( start = new Vector3(), end = new Vector3() ) { 51415 51416 this.start = start; 51417 this.end = end; 51418 51419 } 51420 51421 set( start, end ) { 51422 51423 this.start.copy( start ); 51424 this.end.copy( end ); 51425 51426 return this; 51427 51428 } 51429 51430 copy( line ) { 51431 51432 this.start.copy( line.start ); 51433 this.end.copy( line.end ); 51434 51435 return this; 51436 51437 } 51438 51439 getCenter( target ) { 51440 51441 return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); 51442 51443 } 51444 51445 delta( target ) { 51446 51447 return target.subVectors( this.end, this.start ); 51448 51449 } 51450 51451 distanceSq() { 51452 51453 return this.start.distanceToSquared( this.end ); 51454 51455 } 51456 51457 distance() { 51458 51459 return this.start.distanceTo( this.end ); 51460 51461 } 51462 51463 at( t, target ) { 51464 51465 return this.delta( target ).multiplyScalar( t ).add( this.start ); 51466 51467 } 51468 51469 closestPointToPointParameter( point, clampToLine ) { 51470 51471 _startP.subVectors( point, this.start ); 51472 _startEnd.subVectors( this.end, this.start ); 51473 51474 const startEnd2 = _startEnd.dot( _startEnd ); 51475 const startEnd_startP = _startEnd.dot( _startP ); 51476 51477 let t = startEnd_startP / startEnd2; 51478 51479 if ( clampToLine ) { 51480 51481 t = clamp( t, 0, 1 ); 51482 51483 } 51484 51485 return t; 51486 51487 } 51488 51489 closestPointToPoint( point, clampToLine, target ) { 51490 51491 const t = this.closestPointToPointParameter( point, clampToLine ); 51492 51493 return this.delta( target ).multiplyScalar( t ).add( this.start ); 51494 51495 } 51496 51497 applyMatrix4( matrix ) { 51498 51499 this.start.applyMatrix4( matrix ); 51500 this.end.applyMatrix4( matrix ); 51501 51502 return this; 51503 51504 } 51505 51506 equals( line ) { 51507 51508 return line.start.equals( this.start ) && line.end.equals( this.end ); 51509 51510 } 51511 51512 clone() { 51513 51514 return new this.constructor().copy( this ); 51515 51516 } 51517 51518} 51519 51520const _vector$3 = /*@__PURE__*/ new Vector3(); 51521 51522class SpotLightHelper extends Object3D { 51523 51524 constructor( light, color ) { 51525 51526 super(); 51527 51528 this.light = light; 51529 51530 this.matrix = light.matrixWorld; 51531 this.matrixAutoUpdate = false; 51532 51533 this.color = color; 51534 51535 this.type = 'SpotLightHelper'; 51536 51537 const geometry = new BufferGeometry(); 51538 51539 const positions = [ 51540 0, 0, 0, 0, 0, 1, 51541 0, 0, 0, 1, 0, 1, 51542 0, 0, 0, - 1, 0, 1, 51543 0, 0, 0, 0, 1, 1, 51544 0, 0, 0, 0, - 1, 1 51545 ]; 51546 51547 for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) { 51548 51549 const p1 = ( i / l ) * Math.PI * 2; 51550 const p2 = ( j / l ) * Math.PI * 2; 51551 51552 positions.push( 51553 Math.cos( p1 ), Math.sin( p1 ), 1, 51554 Math.cos( p2 ), Math.sin( p2 ), 1 51555 ); 51556 51557 } 51558 51559 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 51560 51561 const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); 51562 51563 this.cone = new LineSegments( geometry, material ); 51564 this.add( this.cone ); 51565 51566 this.update(); 51567 51568 } 51569 51570 dispose() { 51571 51572 this.cone.geometry.dispose(); 51573 this.cone.material.dispose(); 51574 51575 } 51576 51577 update() { 51578 51579 this.light.updateWorldMatrix( true, false ); 51580 this.light.target.updateWorldMatrix( true, false ); 51581 51582 const coneLength = this.light.distance ? this.light.distance : 1000; 51583 const coneWidth = coneLength * Math.tan( this.light.angle ); 51584 51585 this.cone.scale.set( coneWidth, coneWidth, coneLength ); 51586 51587 _vector$3.setFromMatrixPosition( this.light.target.matrixWorld ); 51588 51589 this.cone.lookAt( _vector$3 ); 51590 51591 if ( this.color !== undefined ) { 51592 51593 this.cone.material.color.set( this.color ); 51594 51595 } else { 51596 51597 this.cone.material.color.copy( this.light.color ); 51598 51599 } 51600 51601 } 51602 51603} 51604 51605const _vector$2 = /*@__PURE__*/ new Vector3(); 51606const _boneMatrix = /*@__PURE__*/ new Matrix4(); 51607const _matrixWorldInv = /*@__PURE__*/ new Matrix4(); 51608 51609 51610class SkeletonHelper extends LineSegments { 51611 51612 constructor( object ) { 51613 51614 const bones = getBoneList( object ); 51615 51616 const geometry = new BufferGeometry(); 51617 51618 const vertices = []; 51619 const colors = []; 51620 51621 const color1 = new Color( 0, 0, 1 ); 51622 const color2 = new Color( 0, 1, 0 ); 51623 51624 for ( let i = 0; i < bones.length; i ++ ) { 51625 51626 const bone = bones[ i ]; 51627 51628 if ( bone.parent && bone.parent.isBone ) { 51629 51630 vertices.push( 0, 0, 0 ); 51631 vertices.push( 0, 0, 0 ); 51632 colors.push( color1.r, color1.g, color1.b ); 51633 colors.push( color2.r, color2.g, color2.b ); 51634 51635 } 51636 51637 } 51638 51639 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 51640 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 51641 51642 const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } ); 51643 51644 super( geometry, material ); 51645 51646 this.isSkeletonHelper = true; 51647 51648 this.type = 'SkeletonHelper'; 51649 51650 this.root = object; 51651 this.bones = bones; 51652 51653 this.matrix = object.matrixWorld; 51654 this.matrixAutoUpdate = false; 51655 51656 } 51657 51658 updateMatrixWorld( force ) { 51659 51660 const bones = this.bones; 51661 51662 const geometry = this.geometry; 51663 const position = geometry.getAttribute( 'position' ); 51664 51665 _matrixWorldInv.copy( this.root.matrixWorld ).invert(); 51666 51667 for ( let i = 0, j = 0; i < bones.length; i ++ ) { 51668 51669 const bone = bones[ i ]; 51670 51671 if ( bone.parent && bone.parent.isBone ) { 51672 51673 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld ); 51674 _vector$2.setFromMatrixPosition( _boneMatrix ); 51675 position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z ); 51676 51677 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld ); 51678 _vector$2.setFromMatrixPosition( _boneMatrix ); 51679 position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z ); 51680 51681 j += 2; 51682 51683 } 51684 51685 } 51686 51687 geometry.getAttribute( 'position' ).needsUpdate = true; 51688 51689 super.updateMatrixWorld( force ); 51690 51691 } 51692 51693 dispose() { 51694 51695 this.geometry.dispose(); 51696 this.material.dispose(); 51697 51698 } 51699 51700} 51701 51702 51703function getBoneList( object ) { 51704 51705 const boneList = []; 51706 51707 if ( object.isBone === true ) { 51708 51709 boneList.push( object ); 51710 51711 } 51712 51713 for ( let i = 0; i < object.children.length; i ++ ) { 51714 51715 boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); 51716 51717 } 51718 51719 return boneList; 51720 51721} 51722 51723class PointLightHelper extends Mesh { 51724 51725 constructor( light, sphereSize, color ) { 51726 51727 const geometry = new SphereGeometry( sphereSize, 4, 2 ); 51728 const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); 51729 51730 super( geometry, material ); 51731 51732 this.light = light; 51733 51734 this.color = color; 51735 51736 this.type = 'PointLightHelper'; 51737 51738 this.matrix = this.light.matrixWorld; 51739 this.matrixAutoUpdate = false; 51740 51741 this.update(); 51742 51743 51744 /* 51745 // TODO: delete this comment? 51746 const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); 51747 const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); 51748 51749 this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); 51750 this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); 51751 51752 const d = light.distance; 51753 51754 if ( d === 0.0 ) { 51755 51756 this.lightDistance.visible = false; 51757 51758 } else { 51759 51760 this.lightDistance.scale.set( d, d, d ); 51761 51762 } 51763 51764 this.add( this.lightDistance ); 51765 */ 51766 51767 } 51768 51769 dispose() { 51770 51771 this.geometry.dispose(); 51772 this.material.dispose(); 51773 51774 } 51775 51776 update() { 51777 51778 this.light.updateWorldMatrix( true, false ); 51779 51780 if ( this.color !== undefined ) { 51781 51782 this.material.color.set( this.color ); 51783 51784 } else { 51785 51786 this.material.color.copy( this.light.color ); 51787 51788 } 51789 51790 /* 51791 const d = this.light.distance; 51792 51793 if ( d === 0.0 ) { 51794 51795 this.lightDistance.visible = false; 51796 51797 } else { 51798 51799 this.lightDistance.visible = true; 51800 this.lightDistance.scale.set( d, d, d ); 51801 51802 } 51803 */ 51804 51805 } 51806 51807} 51808 51809const _vector$1 = /*@__PURE__*/ new Vector3(); 51810const _color1 = /*@__PURE__*/ new Color(); 51811const _color2 = /*@__PURE__*/ new Color(); 51812 51813class HemisphereLightHelper extends Object3D { 51814 51815 constructor( light, size, color ) { 51816 51817 super(); 51818 51819 this.light = light; 51820 51821 this.matrix = light.matrixWorld; 51822 this.matrixAutoUpdate = false; 51823 51824 this.color = color; 51825 51826 this.type = 'HemisphereLightHelper'; 51827 51828 const geometry = new OctahedronGeometry( size ); 51829 geometry.rotateY( Math.PI * 0.5 ); 51830 51831 this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); 51832 if ( this.color === undefined ) this.material.vertexColors = true; 51833 51834 const position = geometry.getAttribute( 'position' ); 51835 const colors = new Float32Array( position.count * 3 ); 51836 51837 geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) ); 51838 51839 this.add( new Mesh( geometry, this.material ) ); 51840 51841 this.update(); 51842 51843 } 51844 51845 dispose() { 51846 51847 this.children[ 0 ].geometry.dispose(); 51848 this.children[ 0 ].material.dispose(); 51849 51850 } 51851 51852 update() { 51853 51854 const mesh = this.children[ 0 ]; 51855 51856 if ( this.color !== undefined ) { 51857 51858 this.material.color.set( this.color ); 51859 51860 } else { 51861 51862 const colors = mesh.geometry.getAttribute( 'color' ); 51863 51864 _color1.copy( this.light.color ); 51865 _color2.copy( this.light.groundColor ); 51866 51867 for ( let i = 0, l = colors.count; i < l; i ++ ) { 51868 51869 const color = ( i < ( l / 2 ) ) ? _color1 : _color2; 51870 51871 colors.setXYZ( i, color.r, color.g, color.b ); 51872 51873 } 51874 51875 colors.needsUpdate = true; 51876 51877 } 51878 51879 this.light.updateWorldMatrix( true, false ); 51880 51881 mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() ); 51882 51883 } 51884 51885} 51886 51887class GridHelper extends LineSegments { 51888 51889 constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) { 51890 51891 color1 = new Color( color1 ); 51892 color2 = new Color( color2 ); 51893 51894 const center = divisions / 2; 51895 const step = size / divisions; 51896 const halfSize = size / 2; 51897 51898 const vertices = [], colors = []; 51899 51900 for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) { 51901 51902 vertices.push( - halfSize, 0, k, halfSize, 0, k ); 51903 vertices.push( k, 0, - halfSize, k, 0, halfSize ); 51904 51905 const color = i === center ? color1 : color2; 51906 51907 color.toArray( colors, j ); j += 3; 51908 color.toArray( colors, j ); j += 3; 51909 color.toArray( colors, j ); j += 3; 51910 color.toArray( colors, j ); j += 3; 51911 51912 } 51913 51914 const geometry = new BufferGeometry(); 51915 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 51916 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 51917 51918 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); 51919 51920 super( geometry, material ); 51921 51922 this.type = 'GridHelper'; 51923 51924 } 51925 51926 dispose() { 51927 51928 this.geometry.dispose(); 51929 this.material.dispose(); 51930 51931 } 51932 51933} 51934 51935class PolarGridHelper extends LineSegments { 51936 51937 constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) { 51938 51939 color1 = new Color( color1 ); 51940 color2 = new Color( color2 ); 51941 51942 const vertices = []; 51943 const colors = []; 51944 51945 // create the sectors 51946 51947 if ( sectors > 1 ) { 51948 51949 for ( let i = 0; i < sectors; i ++ ) { 51950 51951 const v = ( i / sectors ) * ( Math.PI * 2 ); 51952 51953 const x = Math.sin( v ) * radius; 51954 const z = Math.cos( v ) * radius; 51955 51956 vertices.push( 0, 0, 0 ); 51957 vertices.push( x, 0, z ); 51958 51959 const color = ( i & 1 ) ? color1 : color2; 51960 51961 colors.push( color.r, color.g, color.b ); 51962 colors.push( color.r, color.g, color.b ); 51963 51964 } 51965 51966 } 51967 51968 // create the rings 51969 51970 for ( let i = 0; i < rings; i ++ ) { 51971 51972 const color = ( i & 1 ) ? color1 : color2; 51973 51974 const r = radius - ( radius / rings * i ); 51975 51976 for ( let j = 0; j < divisions; j ++ ) { 51977 51978 // first vertex 51979 51980 let v = ( j / divisions ) * ( Math.PI * 2 ); 51981 51982 let x = Math.sin( v ) * r; 51983 let z = Math.cos( v ) * r; 51984 51985 vertices.push( x, 0, z ); 51986 colors.push( color.r, color.g, color.b ); 51987 51988 // second vertex 51989 51990 v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 ); 51991 51992 x = Math.sin( v ) * r; 51993 z = Math.cos( v ) * r; 51994 51995 vertices.push( x, 0, z ); 51996 colors.push( color.r, color.g, color.b ); 51997 51998 } 51999 52000 } 52001 52002 const geometry = new BufferGeometry(); 52003 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 52004 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 52005 52006 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); 52007 52008 super( geometry, material ); 52009 52010 this.type = 'PolarGridHelper'; 52011 52012 } 52013 52014 dispose() { 52015 52016 this.geometry.dispose(); 52017 this.material.dispose(); 52018 52019 } 52020 52021} 52022 52023const _v1 = /*@__PURE__*/ new Vector3(); 52024const _v2 = /*@__PURE__*/ new Vector3(); 52025const _v3 = /*@__PURE__*/ new Vector3(); 52026 52027class DirectionalLightHelper extends Object3D { 52028 52029 constructor( light, size, color ) { 52030 52031 super(); 52032 52033 this.light = light; 52034 52035 this.matrix = light.matrixWorld; 52036 this.matrixAutoUpdate = false; 52037 52038 this.color = color; 52039 52040 this.type = 'DirectionalLightHelper'; 52041 52042 if ( size === undefined ) size = 1; 52043 52044 let geometry = new BufferGeometry(); 52045 geometry.setAttribute( 'position', new Float32BufferAttribute( [ 52046 - size, size, 0, 52047 size, size, 0, 52048 size, - size, 0, 52049 - size, - size, 0, 52050 - size, size, 0 52051 ], 3 ) ); 52052 52053 const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); 52054 52055 this.lightPlane = new Line( geometry, material ); 52056 this.add( this.lightPlane ); 52057 52058 geometry = new BufferGeometry(); 52059 geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); 52060 52061 this.targetLine = new Line( geometry, material ); 52062 this.add( this.targetLine ); 52063 52064 this.update(); 52065 52066 } 52067 52068 dispose() { 52069 52070 this.lightPlane.geometry.dispose(); 52071 this.lightPlane.material.dispose(); 52072 this.targetLine.geometry.dispose(); 52073 this.targetLine.material.dispose(); 52074 52075 } 52076 52077 update() { 52078 52079 this.light.updateWorldMatrix( true, false ); 52080 this.light.target.updateWorldMatrix( true, false ); 52081 52082 _v1.setFromMatrixPosition( this.light.matrixWorld ); 52083 _v2.setFromMatrixPosition( this.light.target.matrixWorld ); 52084 _v3.subVectors( _v2, _v1 ); 52085 52086 this.lightPlane.lookAt( _v2 ); 52087 52088 if ( this.color !== undefined ) { 52089 52090 this.lightPlane.material.color.set( this.color ); 52091 this.targetLine.material.color.set( this.color ); 52092 52093 } else { 52094 52095 this.lightPlane.material.color.copy( this.light.color ); 52096 this.targetLine.material.color.copy( this.light.color ); 52097 52098 } 52099 52100 this.targetLine.lookAt( _v2 ); 52101 this.targetLine.scale.z = _v3.length(); 52102 52103 } 52104 52105} 52106 52107const _vector = /*@__PURE__*/ new Vector3(); 52108const _camera = /*@__PURE__*/ new Camera(); 52109 52110/** 52111 * - shows frustum, line of sight and up of the camera 52112 * - suitable for fast updates 52113 * - based on frustum visualization in lightgl.js shadowmap example 52114 * https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html 52115 */ 52116 52117class CameraHelper extends LineSegments { 52118 52119 constructor( camera ) { 52120 52121 const geometry = new BufferGeometry(); 52122 const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } ); 52123 52124 const vertices = []; 52125 const colors = []; 52126 52127 const pointMap = {}; 52128 52129 // near 52130 52131 addLine( 'n1', 'n2' ); 52132 addLine( 'n2', 'n4' ); 52133 addLine( 'n4', 'n3' ); 52134 addLine( 'n3', 'n1' ); 52135 52136 // far 52137 52138 addLine( 'f1', 'f2' ); 52139 addLine( 'f2', 'f4' ); 52140 addLine( 'f4', 'f3' ); 52141 addLine( 'f3', 'f1' ); 52142 52143 // sides 52144 52145 addLine( 'n1', 'f1' ); 52146 addLine( 'n2', 'f2' ); 52147 addLine( 'n3', 'f3' ); 52148 addLine( 'n4', 'f4' ); 52149 52150 // cone 52151 52152 addLine( 'p', 'n1' ); 52153 addLine( 'p', 'n2' ); 52154 addLine( 'p', 'n3' ); 52155 addLine( 'p', 'n4' ); 52156 52157 // up 52158 52159 addLine( 'u1', 'u2' ); 52160 addLine( 'u2', 'u3' ); 52161 addLine( 'u3', 'u1' ); 52162 52163 // target 52164 52165 addLine( 'c', 't' ); 52166 addLine( 'p', 'c' ); 52167 52168 // cross 52169 52170 addLine( 'cn1', 'cn2' ); 52171 addLine( 'cn3', 'cn4' ); 52172 52173 addLine( 'cf1', 'cf2' ); 52174 addLine( 'cf3', 'cf4' ); 52175 52176 function addLine( a, b ) { 52177 52178 addPoint( a ); 52179 addPoint( b ); 52180 52181 } 52182 52183 function addPoint( id ) { 52184 52185 vertices.push( 0, 0, 0 ); 52186 colors.push( 0, 0, 0 ); 52187 52188 if ( pointMap[ id ] === undefined ) { 52189 52190 pointMap[ id ] = []; 52191 52192 } 52193 52194 pointMap[ id ].push( ( vertices.length / 3 ) - 1 ); 52195 52196 } 52197 52198 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 52199 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 52200 52201 super( geometry, material ); 52202 52203 this.type = 'CameraHelper'; 52204 52205 this.camera = camera; 52206 if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix(); 52207 52208 this.matrix = camera.matrixWorld; 52209 this.matrixAutoUpdate = false;
52210 52211 this.pointMap = pointMap; 52212 52213 this.update(); 52214 52215 // colors 52216 52217 const colorFrustum = new Color( 0xffaa00 ); 52218 const colorCone = new Color( 0xff0000 ); 52219 const colorUp = new Color( 0x00aaff ); 52220 const colorTarget = new Color( 0xffffff ); 52221 const colorCross = new Color( 0x333333 ); 52222 52223 this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross ); 52224 52225 } 52226 52227 setColors( frustum, cone, up, target, cross ) { 52228 52229 const geometry = this.geometry; 52230 52231 const colorAttribute = geometry.getAttribute( 'color' ); 52232 52233 // near 52234 52235 colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2 52236 colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4 52237 colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3 52238 colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1 52239 52240 // far 52241 52242 colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2 52243 colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4 52244 colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3 52245 colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1 52246 52247 // sides 52248 52249 colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1 52250 colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2 52251 colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3 52252 colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4 52253 52254 // cone 52255 52256 colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1 52257 colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2 52258 colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3 52259 colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4 52260 52261 // up 52262 52263 colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2 52264 colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3 52265 colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1 52266 52267 // target 52268 52269 colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t 52270 colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c 52271 52272 // cross 52273 52274 colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2 52275 colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4 52276 52277 colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2 52278 colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4 52279 52280 colorAttribute.needsUpdate = true; 52281 52282 } 52283 52284 update() { 52285 52286 const geometry = this.geometry; 52287 const pointMap = this.pointMap; 52288 52289 const w = 1, h = 1; 52290 52291 // we need just camera projection matrix inverse 52292 // world matrix must be identity 52293 52294 _camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse ); 52295 52296 // center / target 52297 52298 setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 ); 52299 setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 ); 52300 52301 // near 52302 52303 setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 ); 52304 setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 ); 52305 setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 ); 52306 setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 ); 52307 52308 // far 52309 52310 setPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 ); 52311 setPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 ); 52312 setPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 ); 52313 setPoint( 'f4', pointMap, geometry, _camera, w, h, 1 ); 52314 52315 // up 52316 52317 setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 ); 52318 setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 ); 52319 setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 ); 52320 52321 // cross 52322 52323 setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 ); 52324 setPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 ); 52325 setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 ); 52326 setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 ); 52327 52328 setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 ); 52329 setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 ); 52330 setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 ); 52331 setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 ); 52332 52333 geometry.getAttribute( 'position' ).needsUpdate = true; 52334 52335 } 52336 52337 dispose() { 52338 52339 this.geometry.dispose(); 52340 this.material.dispose(); 52341 52342 } 52343 52344} 52345 52346 52347function setPoint( point, pointMap, geometry, camera, x, y, z ) { 52348 52349 _vector.set( x, y, z ).unproject( camera ); 52350 52351 const points = pointMap[ point ]; 52352 52353 if ( points !== undefined ) { 52354 52355 const position = geometry.getAttribute( 'position' ); 52356 52357 for ( let i = 0, l = points.length; i < l; i ++ ) { 52358 52359 position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z ); 52360 52361 } 52362 52363 } 52364 52365} 52366 52367const _box = /*@__PURE__*/ new Box3(); 52368 52369class BoxHelper extends LineSegments { 52370 52371 constructor( object, color = 0xffff00 ) { 52372 52373 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 ] ); 52374 const positions = new Float32Array( 8 * 3 ); 52375 52376 const geometry = new BufferGeometry(); 52377 geometry.setIndex( new BufferAttribute( indices, 1 ) ); 52378 geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) ); 52379 52380 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 52381 52382 this.object = object; 52383 this.type = 'BoxHelper'; 52384 52385 this.matrixAutoUpdate = false;
vendor: 4,705 bytes, lines 52386-52602
52386 52387 this.update(); 52388 52389 } 52390 52391 update( object ) { 52392 52393 if ( object !== undefined ) { 52394 52395 console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' ); 52396 52397 } 52398 52399 if ( this.object !== undefined ) { 52400 52401 _box.setFromObject( this.object ); 52402 52403 } 52404 52405 if ( _box.isEmpty() ) return; 52406 52407 const min = _box.min; 52408 const max = _box.max; 52409 52410 /* 52411 5____4 52412 1/___0/| 52413 | 6__|_7 52414 2/___3/ 52415 52416 0: max.x, max.y, max.z 52417 1: min.x, max.y, max.z 52418 2: min.x, min.y, max.z 52419 3: max.x, min.y, max.z 52420 4: max.x, max.y, min.z 52421 5: min.x, max.y, min.z 52422 6: min.x, min.y, min.z 52423 7: max.x, min.y, min.z 52424 */ 52425 52426 const position = this.geometry.attributes.position; 52427 const array = position.array; 52428 52429 array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z; 52430 array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z; 52431 array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z; 52432 array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z; 52433 array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z; 52434 array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z; 52435 array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z; 52436 array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z; 52437 52438 position.needsUpdate = true; 52439 52440 this.geometry.computeBoundingSphere(); 52441 52442 } 52443 52444 setFromObject( object ) { 52445 52446 this.object = object; 52447 this.update(); 52448 52449 return this; 52450 52451 } 52452 52453 copy( source, recursive ) { 52454 52455 super.copy( source, recursive ); 52456 52457 this.object = source.object; 52458 52459 return this; 52460 52461 } 52462 52463 dispose() { 52464 52465 this.geometry.dispose(); 52466 this.material.dispose(); 52467 52468 } 52469 52470} 52471 52472class Box3Helper extends LineSegments { 52473 52474 constructor( box, color = 0xffff00 ) { 52475 52476 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 ] ); 52477 52478 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 ]; 52479 52480 const geometry = new BufferGeometry(); 52481 52482 geometry.setIndex( new BufferAttribute( indices, 1 ) ); 52483 52484 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 52485 52486 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 52487 52488 this.box = box; 52489 52490 this.type = 'Box3Helper'; 52491 52492 this.geometry.computeBoundingSphere(); 52493 52494 } 52495 52496 updateMatrixWorld( force ) { 52497 52498 const box = this.box; 52499 52500 if ( box.isEmpty() ) return; 52501 52502 box.getCenter( this.position ); 52503 52504 box.getSize( this.scale ); 52505 52506 this.scale.multiplyScalar( 0.5 ); 52507 52508 super.updateMatrixWorld( force ); 52509 52510 } 52511 52512 dispose() { 52513 52514 this.geometry.dispose(); 52515 this.material.dispose(); 52516 52517 } 52518 52519} 52520 52521class PlaneHelper extends Line { 52522 52523 constructor( plane, size = 1, hex = 0xffff00 ) { 52524 52525 const color = hex; 52526 52527 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 ]; 52528 52529 const geometry = new BufferGeometry(); 52530 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 52531 geometry.computeBoundingSphere(); 52532 52533 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 52534 52535 this.type = 'PlaneHelper'; 52536 52537 this.plane = plane; 52538 52539 this.size = size; 52540 52541 const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ]; 52542 52543 const geometry2 = new BufferGeometry(); 52544 geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); 52545 geometry2.computeBoundingSphere(); 52546 52547 this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) ); 52548 52549 } 52550 52551 updateMatrixWorld( force ) { 52552 52553 this.position.set( 0, 0, 0 ); 52554 52555 this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 ); 52556 52557 this.lookAt( this.plane.normal ); 52558 52559 this.translateZ( - this.plane.constant ); 52560 52561 super.updateMatrixWorld( force ); 52562 52563 } 52564 52565 dispose() { 52566 52567 this.geometry.dispose(); 52568 this.material.dispose(); 52569 this.children[ 0 ].geometry.dispose(); 52570 this.children[ 0 ].material.dispose(); 52571 52572 } 52573 52574} 52575 52576const _axis = /*@__PURE__*/ new Vector3(); 52577let _lineGeometry, _coneGeometry; 52578 52579class ArrowHelper extends Object3D { 52580 52581 // dir is assumed to be normalized 52582 52583 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 ) { 52584 52585 super(); 52586 52587 this.type = 'ArrowHelper'; 52588 52589 if ( _lineGeometry === undefined ) { 52590 52591 _lineGeometry = new BufferGeometry(); 52592 _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); 52593 52594 _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 ); 52595 _coneGeometry.translate( 0, - 0.5, 0 ); 52596 52597 } 52598 52599 this.position.copy( origin ); 52600 52601 this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); 52602 this.line.matrixAutoUpdate = false;
vendor: 3,957 bytes, lines 52603-52822
52603 this.add( this.line ); 52604 52605 this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) ); 52606 this.cone.matrixAutoUpdate = false; 52607 this.add( this.cone ); 52608 52609 this.setDirection( dir ); 52610 this.setLength( length, headLength, headWidth ); 52611 52612 } 52613 52614 setDirection( dir ) { 52615 52616 // dir is assumed to be normalized 52617 52618 if ( dir.y > 0.99999 ) { 52619 52620 this.quaternion.set( 0, 0, 0, 1 ); 52621 52622 } else if ( dir.y < - 0.99999 ) { 52623 52624 this.quaternion.set( 1, 0, 0, 0 ); 52625 52626 } else { 52627 52628 _axis.set( dir.z, 0, - dir.x ).normalize(); 52629 52630 const radians = Math.acos( dir.y ); 52631 52632 this.quaternion.setFromAxisAngle( _axis, radians ); 52633 52634 } 52635 52636 } 52637 52638 setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) { 52639 52640 this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458 52641 this.line.updateMatrix(); 52642 52643 this.cone.scale.set( headWidth, headLength, headWidth ); 52644 this.cone.position.y = length; 52645 this.cone.updateMatrix(); 52646 52647 } 52648 52649 setColor( color ) { 52650 52651 this.line.material.color.set( color ); 52652 this.cone.material.color.set( color ); 52653 52654 } 52655 52656 copy( source ) { 52657 52658 super.copy( source, false ); 52659 52660 this.line.copy( source.line ); 52661 this.cone.copy( source.cone ); 52662 52663 return this; 52664 52665 } 52666 52667 dispose() { 52668 52669 this.line.geometry.dispose(); 52670 this.line.material.dispose(); 52671 this.cone.geometry.dispose(); 52672 this.cone.material.dispose(); 52673 52674 } 52675 52676} 52677 52678class AxesHelper extends LineSegments { 52679 52680 constructor( size = 1 ) { 52681 52682 const vertices = [ 52683 0, 0, 0, size, 0, 0, 52684 0, 0, 0, 0, size, 0, 52685 0, 0, 0, 0, 0, size 52686 ]; 52687 52688 const colors = [ 52689 1, 0, 0, 1, 0.6, 0, 52690 0, 1, 0, 0.6, 1, 0, 52691 0, 0, 1, 0, 0.6, 1 52692 ]; 52693 52694 const geometry = new BufferGeometry(); 52695 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 52696 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 52697 52698 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); 52699 52700 super( geometry, material ); 52701 52702 this.type = 'AxesHelper'; 52703 52704 } 52705 52706 setColors( xAxisColor, yAxisColor, zAxisColor ) { 52707 52708 const color = new Color(); 52709 const array = this.geometry.attributes.color.array; 52710 52711 color.set( xAxisColor ); 52712 color.toArray( array, 0 ); 52713 color.toArray( array, 3 ); 52714 52715 color.set( yAxisColor ); 52716 color.toArray( array, 6 ); 52717 color.toArray( array, 9 ); 52718 52719 color.set( zAxisColor ); 52720 color.toArray( array, 12 ); 52721 color.toArray( array, 15 ); 52722 52723 this.geometry.attributes.color.needsUpdate = true; 52724 52725 return this; 52726 52727 } 52728 52729 dispose() { 52730 52731 this.geometry.dispose(); 52732 this.material.dispose(); 52733 52734 } 52735 52736} 52737 52738class ShapePath { 52739 52740 constructor() { 52741 52742 this.type = 'ShapePath'; 52743 52744 this.color = new Color(); 52745 52746 this.subPaths = []; 52747 this.currentPath = null; 52748 52749 } 52750 52751 moveTo( x, y ) { 52752 52753 this.currentPath = new Path(); 52754 this.subPaths.push( this.currentPath ); 52755 this.currentPath.moveTo( x, y ); 52756 52757 return this; 52758 52759 } 52760 52761 lineTo( x, y ) { 52762 52763 this.currentPath.lineTo( x, y ); 52764 52765 return this; 52766 52767 } 52768 52769 quadraticCurveTo( aCPx, aCPy, aX, aY ) { 52770 52771 this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY ); 52772 52773 return this; 52774 52775 } 52776 52777 bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { 52778 52779 this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ); 52780 52781 return this; 52782 52783 } 52784 52785 splineThru( pts ) { 52786 52787 this.currentPath.splineThru( pts ); 52788 52789 return this; 52790 52791 } 52792 52793 toShapes( isCCW ) { 52794 52795 function toShapesNoHoles( inSubpaths ) { 52796 52797 const shapes = []; 52798 52799 for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) { 52800 52801 const tmpPath = inSubpaths[ i ]; 52802 52803 const tmpShape = new Shape(); 52804 tmpShape.curves = tmpPath.curves; 52805 52806 shapes.push( tmpShape ); 52807 52808 } 52809 52810 return shapes; 52811 52812 } 52813 52814 function isPointInsidePolygon( inPt, inPolygon ) { 52815 52816 const polyLen = inPolygon.length; 52817 52818 // inPt on polygon contour => immediate success or 52819 // toggling of inside/outside at every single! intersection point of an edge 52820 // with the horizontal line through inPt, left of inPt 52821 // not counting lowerY endpoints of edges and whole edges on that line 52822 let inside = false;
52823 for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { 52824 52825 let edgeLowPt = inPolygon[ p ]; 52826 let edgeHighPt = inPolygon[ q ]; 52827 52828 let edgeDx = edgeHighPt.x - edgeLowPt.x; 52829 let edgeDy = edgeHighPt.y - edgeLowPt.y; 52830 52831 if ( Math.abs( edgeDy ) > Number.EPSILON ) { 52832 52833 // not parallel 52834 if ( edgeDy < 0 ) { 52835 52836 edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx; 52837 edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy; 52838 52839 } 52840 52841 if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue; 52842 52843 if ( inPt.y === edgeLowPt.y ) { 52844 52845 if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ? 52846 // continue; // no intersection or edgeLowPt => doesn't count !!! 52847 52848 } else { 52849 52850 const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y ); 52851 if ( perpEdge === 0 ) return true; // inPt is on contour ? 52852 if ( perpEdge < 0 ) continue; 52853 inside = ! inside; // true intersection left of inPt 52854 52855 } 52856 52857 } else { 52858 52859 // parallel or collinear 52860 if ( inPt.y !== edgeLowPt.y ) continue; // parallel 52861 // edge lies on the same horizontal line as inPt 52862 if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || 52863 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour ! 52864 // continue; 52865 52866 } 52867 52868 } 52869 52870 return inside; 52871 52872 } 52873 52874 const isClockWise = ShapeUtils.isClockWise; 52875 52876 const subPaths = this.subPaths; 52877 if ( subPaths.length === 0 ) return []; 52878 52879 let solid, tmpPath, tmpShape; 52880 const shapes = []; 52881 52882 if ( subPaths.length === 1 ) { 52883 52884 tmpPath = subPaths[ 0 ]; 52885 tmpShape = new Shape(); 52886 tmpShape.curves = tmpPath.curves; 52887 shapes.push( tmpShape ); 52888 return shapes; 52889 52890 } 52891 52892 let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); 52893 holesFirst = isCCW ? ! holesFirst : holesFirst; 52894 52895 // console.log("Holes first", holesFirst); 52896 52897 const betterShapeHoles = []; 52898 const newShapes = []; 52899 let newShapeHoles = []; 52900 let mainIdx = 0; 52901 let tmpPoints; 52902 52903 newShapes[ mainIdx ] = undefined; 52904 newShapeHoles[ mainIdx ] = []; 52905 52906 for ( let i = 0, l = subPaths.length; i < l; i ++ ) { 52907 52908 tmpPath = subPaths[ i ]; 52909 tmpPoints = tmpPath.getPoints(); 52910 solid = isClockWise( tmpPoints ); 52911 solid = isCCW ? ! solid : solid; 52912 52913 if ( solid ) { 52914 52915 if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++; 52916 52917 newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints }; 52918 newShapes[ mainIdx ].s.curves = tmpPath.curves; 52919 52920 if ( holesFirst ) mainIdx ++; 52921 newShapeHoles[ mainIdx ] = []; 52922 52923 //console.log('cw', i); 52924 52925 } else { 52926 52927 newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); 52928 52929 //console.log('ccw', i); 52930 52931 } 52932 52933 } 52934 52935 // only Holes? -> probably all Shapes with wrong orientation 52936 if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths ); 52937 52938 52939 if ( newShapes.length > 1 ) { 52940 52941 let ambiguous = false; 52942 let toChange = 0; 52943 52944 for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { 52945 52946 betterShapeHoles[ sIdx ] = []; 52947 52948 } 52949 52950 for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { 52951 52952 const sho = newShapeHoles[ sIdx ]; 52953 52954 for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) { 52955 52956 const ho = sho[ hIdx ]; 52957 let hole_unassigned = true; 52958 52959 for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) { 52960 52961 if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) { 52962 52963 if ( sIdx !== s2Idx ) toChange ++; 52964 52965 if ( hole_unassigned ) { 52966 52967 hole_unassigned = false; 52968 betterShapeHoles[ s2Idx ].push( ho ); 52969 52970 } else { 52971 52972 ambiguous = true; 52973 52974 } 52975 52976 } 52977 52978 } 52979 52980 if ( hole_unassigned ) { 52981 52982 betterShapeHoles[ sIdx ].push( ho ); 52983 52984 } 52985 52986 } 52987 52988 } 52989 52990 if ( toChange > 0 && ambiguous === false ) { 52991 52992 newShapeHoles = betterShapeHoles; 52993 52994 } 52995 52996 } 52997 52998 let tmpHoles; 52999 53000 for ( let i = 0, il = newShapes.length; i < il; i ++ ) { 53001 53002 tmpShape = newShapes[ i ].s; 53003 shapes.push( tmpShape ); 53004 tmpHoles = newShapeHoles[ i ]; 53005 53006 for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) { 53007 53008 tmpShape.holes.push( tmpHoles[ j ].h ); 53009 53010 } 53011 53012 } 53013 53014 //console.log("shape", shapes); 53015 53016 return shapes; 53017 53018 } 53019 53020} 53021 53022if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { 53023 53024 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: { 53025 revision: REVISION, 53026 } } ) ); 53027 53028} 53029 53030if ( typeof window !== 'undefined' ) { 53031 53032 if ( window.__THREE__ ) { 53033 53034 console.warn( 'WARNING: Multiple instances of Three.js being imported.' ); 53035 53036 } else { 53037 53038 window.__THREE__ = REVISION; 53039 53040 } 53041 53042} 53043 53044export { 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, C
53044onstantColorFactor, 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, Float64BufferAttribute, 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, LinearEncoding, 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, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, 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, 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, Rever
53044seSubtractEquation, 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, TwoPassDoubleSide, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoTexture, WebGL1Renderer, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLRenderTarget, WebGLRenderer, WebGLUtils, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, _SRGBAFormat, createCanvasElement, sRGBEncoding };
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.