1import { 2 ACESFilmicToneMapping, 3 AnimationClip, 4 BasicShadowMap, 5 Bone, 6 Box3, 7 BoxGeometry, 8 BufferAttribute, 9 BufferGeometry, 10 Camera, 11 ClampToEdgeWrapping, 12 Clock, 13 Color, 14 CompressedTexture, 15 DirectionalLight, 16 DoubleSide, 17 DynamicDrawUsage, 18 FileLoader, 19 FrontSide, 20 Group, 21 ImageBitmapLoader, 22 InstancedBufferAttribute, 23 InstancedMesh, 24 InterleavedBuffer, 25 InterleavedBufferAttribute, 26 Interpolant, 27 InterpolateDiscrete, 28 InterpolateLinear, 29 Line, 30 LineBasicMaterial, 31 LineLoop, 32 LineSegments, 33 LinearFilter, 34 LinearMipmapLinearFilter, 35 LinearMipmapNearestFilter, 36 LinearSRGBColorSpace, 37 Loader, 38 LoaderUtils, 39 MOUSE, 40 Material, 41 MathUtils, 42 Matrix4, 43 Mesh, 44 MeshBasicMaterial, 45 MeshPhysicalMaterial, 46 MeshStandardMaterial, 47 MirroredRepeatWrapping, 48 NearestFilter, 49 NearestMipmapLinearFilter, 50 NearestMipmapNearestFilter, 51 NoToneMapping, 52 NumberKeyframeTrack, 53 Object3D, 54 OrthographicCamera, 55 PCFShadowMap, 56 PCFSoftShadowMap, 57 PerspectiveCamera, 58 PlaneGeometry, 59 PointLight, 60 Points, 61 PointsMaterial, 62 PropertyBinding, 63 Quaternion, 64 QuaternionKeyframeTrack, 65 REVISION, 66 RGBAFormat, 67 Raycaster, 68 RepeatWrapping, 69 SRGBColorSpace, 70 Scene, 71 ShaderMaterial, 72 Show, 73 Skeleton, 74 SkinnedMesh, 75 Sphere, 76 SphereGeometry, 77 SpotLight, 78 Texture, 79 TextureLoader, 80 TriangleFanDrawMode, 81 TriangleStripDrawMode, 82 TrianglesDrawMode, 83 Uniform, 84 UnsignedByteType, 85 VSMShadowMap, 86 Vector2, 87 Vector3, 88 VectorKeyframeTrack, 89 WebGLRenderer, 90 children, 91 className, 92 createComponent, 93 createComputed, 94 createContext, 95 createEffect, 96 createMemo, 97 createRenderEffect, 98 createResource, 99 createRoot, 100 createSignal, 101 getOwner, 102 isServer, 103 mapArray, 104 memo, 105 mergeProps, 106 onCleanup, 107 onMount, 108 splitProps, 109 style, 110 template, 111 untrack, 112 use, 113 useContext 114} from "./chunk-47C2ISC4.js"; 115
vendor: 1,053 bytes, lines 116-153
116// node_modules/solid-three/node_modules/@solid-primitives/utils/dist/index.js 117var noop = (() => void 0); 118var isNonNullable = (i) => i != null; 119var filterNonNullable = (arr) => arr.filter(isNonNullable); 120var access = (v) => typeof v === "function" && !v.length ? v() : v; 121var asArray = (value) => Array.isArray(value) ? value : value ? [value] : []; 122function handleDiffArray(current, prev, handleAdded, handleRemoved) { 123 const currLength = current.length; 124 const prevLength = prev.length; 125 let i = 0; 126 if (!prevLength) { 127 for (; i < currLength; i++) 128 handleAdded(current[i]); 129 return; 130 } 131 if (!currLength) { 132 for (; i < prevLength; i++) 133 handleRemoved(prev[i]); 134 return; 135 } 136 for (; i < prevLength; i++) { 137 if (prev[i] !== current[i]) 138 break; 139 } 140 let prevEl; 141 let currEl; 142 prev = prev.slice(i); 143 current = current.slice(i); 144 for (prevEl of prev) { 145 if (!current.includes(prevEl)) 146 handleRemoved(prevEl); 147 } 148 for (currEl of current) { 149 if (!prev.includes(currEl)) 150 handleAdded(currEl); 151 } 152} 153
vendor: 1,202 bytes, lines 154-184
154// node_modules/solid-three/node_modules/@solid-primitives/resize-observer/dist/index.js 155function makeResizeObserver(callback, options) { 156 if (isServer) { 157 return { observe: noop, unobserve: noop }; 158 } 159 const observer = new ResizeObserver(callback); 160 onCleanup(observer.disconnect.bind(observer)); 161 return { 162 observe: (ref) => observer.observe(ref, options), 163 unobserve: observer.unobserve.bind(observer) 164 }; 165} 166function createResizeObserver(targets, onResize, options) { 167 if (isServer) 168 return; 169 const previousMap = /* @__PURE__ */ new WeakMap(), { observe, unobserve } = makeResizeObserver((entries) => { 170 for (const entry of entries) { 171 const { contentRect, target } = entry, width = Math.round(contentRect.width), height = Math.round(contentRect.height), previous = previousMap.get(target); 172 if (!previous || previous.width !== width || previous.height !== height) { 173 onResize(contentRect, target, entry); 174 previousMap.set(target, { width, height }); 175 } 176 } 177 }, options); 178 createEffect((prev) => { 179 const refs = filterNonNullable(asArray(access(targets))); 180 handleDiffArray(refs, prev, observe, unobserve); 181 return refs; 182 }, []); 183} 184
vendor: 785 bytes, lines 185-209
185// node_modules/@bigmistqke/solid-whenever/dist/index.js 186function resolve(value) { 187 return typeof value !== "function" ? value : value(); 188} 189var check = (accessor, callback, fallback) => { 190 const value = resolve(accessor); 191 return value ? callback(value) : fallback ? fallback() : void 0; 192}; 193var when = (accessor, callback, fallback) => { 194 return (...args) => check( 195 accessor, 196 (value) => callback(value, ...args), 197 fallback ? () => fallback(...args) : void 0 198 ); 199}; 200function whenify(fn) { 201 return function(accessor, callback, fallback) { 202 return fn(when(accessor, callback, fallback)); 203 }; 204} 205var whenMemo = whenify(createMemo); 206var whenEffect = whenify(createEffect); 207var whenRenderEffect = whenify(createRenderEffect); 208var whenComputed = whenify(createComputed); 209
vendor: 53,852 bytes, lines 210-1971
210// node_modules/solid-three/dist/index.js 211var $S3C = /* @__PURE__ */ Symbol("solid-three"); 212function isRecord(value) { 213 return !Array.isArray(value) && typeof value === "object"; 214} 215var isOrthographicCamera = (def) => "isOrthographicCamera" in def && !!def.isOrthographicCamera; 216var isVector3 = (def) => "isVector3" in def && !!def.isVector3; 217function autodispose(object) { 218 if (object.dispose) { 219 onCleanup(() => object.dispose?.()); 220 } 221 return object; 222} 223function meta(instance, augmentation = { props: {} }) { 224 if (hasMeta(instance)) { 225 return instance; 226 } 227 const _instance = instance; 228 _instance[$S3C] = mergeProps( 229 { children: /* @__PURE__ */ new Set(), parent: void 0 }, 230 augmentation 231 ); 232 return _instance; 233} 234function getMeta(value) { 235 return hasMeta(value) ? value[$S3C] : void 0; 236} 237function hasMeta(element) { 238 return typeof element === "object" && element && $S3C in element; 239} 240async function awaitMapObject(object, callback) { 241 const result = {}; 242 for (const key in object) { 243 result[key] = await callback(object[key], key); 244 } 245 return result; 246} 247function bubbleUp(node, callback) { 248 let current = node; 249 while (current) { 250 callback(current); 251 current = "parent" in current ? current.parent : void 0; 252 } 253} 254function defaultProps(props, defaults) { 255 return mergeProps(defaults, props); 256} 257var hasColorSpace = (object) => "colorSpace" in object || "outputColorSpace" in object; 258function isConstructor(value) { 259 return typeof value === "function" && value.prototype !== void 0; 260} 261function isMaterial(value) { 262 return !!value && value.isMaterial === true; 263} 264function isBufferGeometry(value) { 265 return !!value && value.isBufferGeometry === true; 266} 267function isFog(value) { 268 return !!value && value.isFog === true; 269} 270function isObject3D(value) { 271 return !!value && value.isObject3D === true; 272} 273function isWritable(object, propertyName) { 274 return Object.getOwnPropertyDescriptor(object, propertyName)?.writable; 275} 276function isRenderer(value) { 277 return typeof value === "object" && value !== null && typeof value.render === "function" && typeof value.setSize === "function"; 278} 279function isWebGLShadowMap(value) { 280 return !!value && "needsUpdate" in value; 281} 282function getPendingInit(renderer) { 283 const init = renderer.init; 284 const hasInitialized = renderer.hasInitialized; 285 if (typeof init !== "function") return void 0; 286 if (hasInitialized?.call(renderer)) return void 0; 287 return () => init.call(renderer); 288} 289var removeElementFromArray = (array, value) => { 290 const index = array.indexOf(value); 291 if (index !== -1) array.splice(index, 1); 292 return array; 293}; 294function resolve2(child, recursive = false) { 295 if (isConstructor(child)) { 296 return child; 297 } 298 if (typeof child === "function") { 299 const value = child(); 300 if (recursive) { 301 return resolve2(value); 302 } 303 return value; 304 } 305 return child; 306} 307function withMultiContexts(children3, values) { 308 let result; 309 values.reduce((acc, [context, value], index) => { 310 return () => context.Provider({ 311 value, 312 children: () => { 313 if (index === 0) result = acc(); 314 else acc(); 315 } 316 }); 317 }, children3)(); 318 return result; 319} 320async function load(loader, input) { 321 if (isRecord(input)) { 322 return await awaitMapObject(input, (path) => load(loader, path)); 323 } 324 return new Promise((resolve22, reject) => loader.load(input, resolve22, void 0, reject)); 325} 326function useRef(props, value) { 327 createRenderEffect(() => { 328 const result = typeof value === "function" ? ( 329 // @ts-expect-error â T may itself be callable; the Accessor branch is intended 330 value() 331 ) : value; 332 if (typeof props.ref === "function") { 333 const cleanup = props.ref(result); 334 if (typeof cleanup === "function") onCleanup(cleanup); 335 } else { 336 props.ref = result; 337 } 338 }); 339} 340var tempTarget = new Vector3(); 341var position = new Vector3(); 342function getCurrentViewport(_camera, target, { width, height, top, left }) { 343 const aspect = width / height; 344 if (isVector3(target)) { 345 tempTarget.copy(target); 346 } else { 347 tempTarget.set(...target); 348 } 349 const distance = _camera.getWorldPosition(position).distanceTo(tempTarget); 350 if (isOrthographicCamera(_camera)) { 351 return { 352 width: width / _camera.zoom, 353 height: height / _camera.zoom, 354 top, 355 left, 356 factor: 1, 357 distance, 358 aspect 359 }; 360 } 361 const fov = _camera.fov * Math.PI / 180; 362 const h = 2 * Math.tan(fov / 2) * distance; 363 const w = h * (width / height); 364 return { width: w, height: h, top, left, factor: width / w, distance, aspect }; 365} 366function binarySearch(array, target) { 367 let left = 0; 368 let right = array.length; 369 while (left < right) { 370 const mid = Math.floor((left + right) / 2); 371 if (array[mid] < target) { 372 left = mid + 1; 373 } else { 374 right = mid; 375 } 376 } 377 return left; 378} 379var eventNameMap = { 380 onClick: "click", 381 onContextMenu: "contextmenu", 382 onDoubleClick: "dblclick", 383 onMouseDown: "mousedown", 384 onMouseMove: "mousemove", 385 onMouseUp: "mouseup", 386 onMouseLeave: "mouseleave", 387 onPointerUp: "pointerup", 388 onPointerDown: "pointerdown", 389 onPointerMove: "pointermove", 390 onPointerLeave: "pointerleave", 391 onWheel: "wheel" 392}; 393function createRegistry() { 394 const array = []; 395 return { 396 array, 397 add(instance) { 398 array.push(instance); 399 return () => { 400 array.splice( 401 array.findIndex((_instance) => _instance === instance), 402 1 403 ); 404 }; 405 } 406 }; 407} 408var isEventType = (type) => /^on(Pointer|Click|DoubleClick|ContextMenu|Wheel|Mouse)/.test(type); 409function createThreeEvent(nativeEvent, { stoppable = true, intersections } = {}) { 410 const event = stoppable ? { 411 nativeEvent, 412 stopped: false, 413 stopPropagation() { 414 event.stopped = true; 415 } 416 } : { nativeEvent }; 417 if (intersections) { 418 event.intersections = intersections; 419 event.intersection = intersections[0]; 420 } 421 return event; 422} 423function raycast(context, registry, event) { 424 if ("update" in context.raycaster) { 425 context.raycaster.update(event, context); 426 } 427 const nodeSet = /* @__PURE__ */ new Set(); 428 const visitedSet = /* @__PURE__ */ new Set(); 429 const stack = [...registry]; 430 for (const object of stack) { 431 if (visitedSet.has(object)) continue; 432 visitedSet.add(object); 433 const meta2 = getMeta(object); 434 if (meta2 && meta2.props.raycastable !== false) { 435 nodeSet.add(object); 436 } 437 stack.push(...object.children); 438 } 439 return context.raycaster.intersectObjects(Array.from(nodeSet), false); 440} 441function createMissableEventRegistry(type, context) { 442 const registry = createRegistry(); 443 context.canvas.addEventListener(eventNameMap[type], (nativeEvent) => { 444 const missedType = `${type}Missed`; 445 if (registry.array.length === 0 && !context.props[type] && !context.props[missedType]) return; 446 const missedObjects = new Set(registry.array); 447 const visitedObjects = /* @__PURE__ */ new Set(); 448 const intersections = raycast(context, registry.array, nativeEvent); 449 const stoppableEvent = createThreeEvent(nativeEvent, { intersections }); 450 for (const intersection of intersections) { 451 stoppableEvent.currentIntersection = intersection; 452 let node = intersection.object; 453 while (node && !stoppableEvent.stopped && !visitedObjects.has(node)) { 454 missedObjects.delete(node); 455 visitedObjects.add(node); 456 getMeta(node)?.props[type]?.( 457 // @ts-expect-error TODO: fix type-error 458 stoppableEvent 459 ); 460 node = node.parent; 461 } 462 } 463 if (!stoppableEvent.stopped) { 464 delete stoppableEvent.currentIntersection; 465 context.props[type]?.(stoppableEvent); 466 } 467 for (const remainingObject of missedObjects) { 468 const intersections2 = context.raycaster.intersectObject(remainingObject, true); 469 for (const { object } of intersections2) { 470 let node = object; 471 while (node && !visitedObjects.has(node)) { 472 missedObjects.delete(node); 473 visitedObjects.add(node); 474 node = node.parent; 475 } 476 } 477 } 478 const missedEvent = createThreeEvent(nativeEvent, { stoppable: false }); 479 for (const object of missedObjects) { 480 getMeta(object)?.props[missedType]?.(missedEvent); 481 } 482 if (intersections.length === 0) { 483 context.props[`${type}Missed`]?.(missedEvent); 484 } 485 }); 486 return registry; 487} 488function createHoverEventRegistry(type, context) { 489 const registry = createRegistry(); 490 let hoveredSet = /* @__PURE__ */ new Set(); 491 let intersections = []; 492 let hoveredCanvas = false; 493 context.canvas.addEventListener(eventNameMap[`on${type}Move`], (nativeEvent) => { 494 intersections = raycast(context, registry.array, nativeEvent); 495 const enterEvent = createThreeEvent(nativeEvent, { stoppable: false, intersections }); 496 const enterSet = /* @__PURE__ */ new Set(); 497 for (const intersection of intersections) { 498 enterEvent.currentIntersection = intersection; 499 let current = intersection.object; 500 while (current && !enterSet.has(current)) { 501 enterSet.add(current); 502 if (!hoveredSet.has(current)) { 503 getMeta(current)?.props[`on${type}Enter`]?.( 504 // @ts-expect-error TODO: fix type-error 505 enterEvent 506 ); 507 } 508 current = current.parent; 509 } 510 } 511 if (hoveredCanvas === false) { 512 context.props[`on${type}Enter`]?.( 513 // @ts-expect-error TODO: fix type-error 514 enterEvent 515 ); 516 hoveredCanvas = true; 517 } 518 const moveEvent = createThreeEvent(nativeEvent, { intersections }); 519 const moveSet = /* @__PURE__ */ new Set(); 520 for (const intersection of intersections) { 521 moveEvent.currentIntersection = intersection; 522 let current = intersection.object; 523 while (current && !moveSet.has(current)) { 524 moveSet.add(current); 525 const meta2 = getMeta(current); 526 if (meta2) { 527 meta2.props[`on${type}Move`]?.( 528 // @ts-expect-error TODO: fix type-error 529 moveEvent 530 ); 531 if (moveEvent.stopped) { 532 break; 533 } 534 } 535 current = current.parent; 536 } 537 } 538 if (!moveEvent.stopped) { 539 delete moveEvent.currentIntersection; 540 context.props[`on${type}Move`]?.( 541 // @ts-expect-error TODO: fix type-error 542 moveEvent 543 ); 544 } 545 const leaveEvent = createThreeEvent(nativeEvent, { intersections, stoppable: false }); 546 const prevHoveredSet = hoveredSet; 547 hoveredSet = enterSet; 548 for (const object of prevHoveredSet) { 549 if (enterSet.has(object)) continue; 550 getMeta(object)?.props[`on${type}Leave`]?.( 551 // @ts-expect-error TODO: fix type-error 552 leaveEvent 553 ); 554 } 555 }); 556 context.canvas.addEventListener(eventNameMap[`on${type}Leave`], (nativeEvent) => { 557 const leaveEvent = createThreeEvent(nativeEvent, { stoppable: false }); 558 context.props[`on${type}Leave`]?.(leaveEvent); 559 hoveredCanvas = false; 560 for (const object of hoveredSet) { 561 getMeta(object)?.props[`on${type}Leave`]?.( 562 // @ts-expect-error TODO: fix type-error 563 leaveEvent 564 ); 565 } 566 hoveredSet.clear(); 567 }); 568 return registry; 569} 570function createDefaultEventRegistry(type, context, options) { 571 const registry = createRegistry(); 572 context.canvas.addEventListener( 573 eventNameMap[type], 574 (nativeEvent) => { 575 const intersections = raycast(context, registry.array, nativeEvent); 576 const event = createThreeEvent(nativeEvent, { intersections }); 577 for (const intersection of intersections) { 578 event.currentIntersection = intersection; 579 let node = intersection.object; 580 while (node && !event.stopped) { 581 getMeta(node)?.props[type]?.( 582 // @ts-expect-error TODO: fix type-error 583 event 584 ); 585 node = node.parent; 586 } 587 } 588 if (!event.stopped) { 589 delete event.currentIntersection; 590 context.props[type]?.(event); 591 } 592 }, 593 options 594 ); 595 return registry; 596} 597function createEvents(context) { 598 const hoverMouseRegistry = createHoverEventRegistry("Mouse", context); 599 const hoverPointerRegistry = createHoverEventRegistry("Pointer", context); 600 const missableClickRegistry = createMissableEventRegistry("onClick", context); 601 const missableContextMenuRegistry = createMissableEventRegistry("onContextMenu", context); 602 const missableDoubleClickRegistry = createMissableEventRegistry("onDoubleClick", context); 603 const mouseDownRegistry = createDefaultEventRegistry("onMouseDown", context); 604 const mouseUpRegistry = createDefaultEventRegistry("onMouseUp", context); 605 const pointerDownRegistry = createDefaultEventRegistry("onPointerDown", context); 606 const pointerUpRegistry = createDefaultEventRegistry("onPointerUp", context); 607 const wheelRegistry = createDefaultEventRegistry("onWheel", context, { passive: true }); 608 return { 609 /** 610 * Registers an `AugmentedElement<Object3D>` with the event handling system. 611 * 612 * @param object - The 3D object to register. 613 * @param type - The type of event the object should listen for. 614 */ 615 addEventListener(object, type) { 616 switch (type) { 617 // Missable Events 618 case "onClick": 619 case "onClickMissed": 620 return missableClickRegistry.add(object); 621 case "onContextMenu": 622 case "onContextMenuMissed": 623 return missableContextMenuRegistry.add(object); 624 case "onDoubleClick": 625 case "onDoubleClickMissed": 626 return missableDoubleClickRegistry.add(object); 627 // Hover Events 628 case "onMouseEnter": 629 case "onMouseLeave": 630 case "onMouseMove": 631 return hoverMouseRegistry.add(object); 632 case "onPointerEnter": 633 case "onPointerLeave": 634 case "onPointerMove": 635 return hoverPointerRegistry.add(object); 636 // Default Events 637 case "onMouseDown": 638 return mouseDownRegistry.add(object); 639 case "onMouseUp": 640 return mouseUpRegistry.add(object); 641 case "onPointerDown": 642 return pointerDownRegistry.add(object); 643 case "onPointerUp": 644 return pointerUpRegistry.add(object); 645 case "onWheel": 646 return wheelRegistry.add(object); 647 } 648 } 649 }; 650} 651var Stack = class { 652 constructor(name = "") { 653 this.name = name; 654 [this.#array, this.#setArray] = createSignal([], { 655 equals: false 656 }); 657 } 658 name; 659 #array; 660 #setArray; 661 /** 662 * Returns the complete stack. 663 * @returns Returns the complete stack. 664 */ 665 all() { 666 return this.#array(); 667 } 668 /** 669 * Returns the top element of the stack without removing it. 670 * @returns The top element of the stack. 671 */ 672 peek() { 673 const array = this.#array(); 674 const top = array[array.length - 1]; 675 return typeof top === "function" ? top() : top; 676 } 677 /** 678 * Adds a value `T` or `Accessor<T>` to the stack. 679 * Value is automatically removed from stack on cleanup. 680 * @param value - The value to add to the stack. 681 * @returns A cleanup function to remove the value from the stack. 682 */ 683 push(value) { 684 this.#setArray((array) => { 685 const index = array.indexOf(value); 686 if (index !== -1) array.splice(index, 1); 687 array.push(value); 688 return array; 689 }); 690 onCleanup(() => this.remove(value)); 691 return () => this.remove(value); 692 } 693 /** 694 * Removes a value from the stack. 695 * @private 696 * @param value - The value to remove from the stack. 697 */ 698 remove(value) { 699 this.#setArray((array) => { 700 const index = array.indexOf(value); 701 if (index === -1) return array; 702 array.splice(index, 1); 703 return array; 704 }); 705 } 706}; 707var TreeNode = class { 708 constructor(key, parent) { 709 this.key = key; 710 this.parent = parent; 711 } 712 key; 713 parent; 714 children = /* @__PURE__ */ new Map(); 715 count = 0; 716 data; 717 delete() { 718 this.parent.children.delete(this.key); 719 } 720}; 721var TreeRegistry = class _TreeRegistry { 722 /** Map of child nodes at the root level */ 723 children = /* @__PURE__ */ new Map(); 724 /** Count of data nodes in this tree */ 725 count = 0; 726 #resolve(input, autocreate) { 727 const paths = Array.isArray(input) ? input : [input]; 728 let current = this; 729 for (let i = 0; i < paths.length; i++) { 730 let node = current.children.get(paths[i]); 731 if (!node) { 732 if (!autocreate) { 733 return void 0; 734 } 735 node = new TreeNode(paths[i], current); 736 current.children.set(paths[i], node); 737 } 738 current = node; 739 } 740 if (current instanceof _TreeRegistry) { 741 throw new Error(`Invalid resolution: ${paths}`); 742 } 743 return current; 744 } 745 /** 746 * Retrieves data stored at the specified path. 747 * @param input Path as a string or array of strings 748 * @returns The data stored at the path, or undefined if not found 749 */ 750 get(input, warn = true) { 751 const node = this.#resolve(input, false); 752 if (!node) { 753 return void 0; 754 } 755 return node.data; 756 } 757 /** 758 * Stores data at the specified path, creating nodes as needed. 759 * Automatically increments reference counts up the tree when storing new data. 760 * @param input Path as a string or array of strings 761 * @param data The data to store 762 */ 763 set(input, data) { 764 const node = this.#resolve(input, true); 765 if (!node.data) { 766 bubbleUp(node, (node2) => node2.count++); 767 } 768 node.data = data; 769 } 770 /** 771 * Deletes data at the specified path and cleans up empty branches. 772 * Automatically decrements reference counts and removes nodes with zero references. 773 * @param input Path as a string or array of strings 774 */ 775 delete(input) { 776 const node = this.#resolve(input, false); 777 if (!node) { 778 return; 779 } 780 bubbleUp(node, (node2) => { 781 node2.count--; 782 if (node2 instanceof TreeNode && node2.count === 0) { 783 node2.delete(); 784 } 785 }); 786 } 787}; 788var LoaderCache = class { 789 /** Map of loader instances to their respective tree registries */ 790 #treeRegistryMap = /* @__PURE__ */ new Map(); 791 /** Weak map for reverse lookup from data to cache nodes */ 792 #dataMap = /* @__PURE__ */ new WeakMap(); 793 /** Set of resources that do not have active references and can be safely cleaned up. */ 794 freeList = /* @__PURE__ */ new Set(); 795 /** 796 * Gets or creates a tree registry for a specific loader. 797 * @param loader The Three.js loader instance 798 * @returns The tree registry for this loader 799 * @private 800 */ 801 #registry(loader) { 802 let registry = this.#treeRegistryMap.get(loader); 803 if (!registry) { 804 this.#treeRegistryMap.set( 805 loader, 806 registry = new TreeRegistry() 807 ); 808 } 809 return registry; 810 } 811 /** 812 * Deletes a cache node and its associated resource. 813 * @param node The cache node to delete 814 * @param options.force Force deletion even if not in free list 815 * @private 816 */ 817 #delete(node, { force } = {}) { 818 if (!force && !this.freeList.has(node.data)) { 819 return; 820 } 821 node.dispose(); 822 } 823 /** 824 * Disposes all resources in the free list. 825 * Should be called periodically to clean up unused resources. 826 */ 827 disposeFreeList() { 828 this.freeList.forEach((resource) => this.#dataMap.get(resource)?.dispose()); 829 } 830 /** 831 * Manually deletes a specific resource from the cache. 832 * @param resource The resource object to delete 833 * @param options.force Force deletion even if resource has active references 834 */ 835 disposeResource(resource, options) { 836 const node = this.#dataMap.get(resource); 837 if (!node) { 838 return; 839 } 840 this.#delete(node, options); 841 } 842 /** 843 * Removes a resource from a specific loader's cache at the given path. 844 * @param loader The Three.js loader instance 845 * @param url The URL or path to the resource 846 * @param options.force Force deletion even if resource has active references 847 */ 848 delete(loader, url, options) { 849 const node = this.#registry(loader).get(url); 850 if (!node) { 851 return; 852 } 853 this.#delete(node, options); 854 } 855 /** 856 * Retrieves a resource from the cache and tracks its usage. 857 * Automatically integrates with Solid.js cleanup for reference counting. 858 * @param loader The Three.js loader instance 859 * @param url The URL or path to the resource 860 * @returns The resource promise, resolved data, or undefined if not found 861 */ 862 get(loader, url, warn) { 863 const node = this.#registry(loader).get(url, warn); 864 if (!node) return void 0; 865 return node.data; 866 } 867 /** 868 * Stores a resource in the cache at the specified path. 869 * @param loader The Three.js loader instance 870 * @param path The URL or path to store the resource at 871 * @param data The resource promise to cache 872 * @param options.force Force update even if resource already exists 873 * @returns The stored promise 874 */ 875 set(loader, path, data, options) { 876 const registry = this.#registry(loader); 877 let node = registry.get(path, false); 878 if (node) { 879 node.update(data, options); 880 } else { 881 node = new CacheNode(this.freeList, registry, path, data); 882 this.#dataMap.set(data, node); 883 registry.set(path, node); 884 } 885 return data; 886 } 887}; 888var CacheNode = class { 889 /** 890 * Creates a new cache node. 891 * @param free The global free list for deferred disposal 892 * @param registry The tree registry containing this node 893 * @param path The path where this resource is stored 894 * @param promise The resource promise to cache 895 */ 896 constructor(free, registry, path, promise) { 897 this.free = free; 898 this.registry = registry; 899 this.path = path; 900 this.data = promise; 901 this.#set(promise); 902 } 903 free; 904 registry; 905 path; 906 /** Reference count for this resource */ 907 count = 0; 908 /** The cached resource (promise or resolved value) */ 909 data; 910 /** 911 * Sets the promise and handles resolution. 912 * @param promise The resource promise 913 * @private 914 */ 915 #set(promise) { 916 this.data = promise; 917 Promise.resolve(promise).then((value) => { 918 if (this.data === promise) { 919 this.data = value; 920 } 921 }); 922 } 923 /** 924 * Disposes the Three.js resource if it has a dispose method. 925 * @private 926 */ 927 #dispose() { 928 if (isRecord(this.data) && "dispose" in this.data && typeof this.data.dispose === "function") { 929 this.data.dispose(); 930 } 931 } 932 /** 933 * Deletes this node and disposes its resource. 934 */ 935 dispose() { 936 this.#dispose(); 937 this.registry.delete(this.path); 938 } 939 /** 940 * Tracks usage of this resource within a Solid.js reactive context. 941 * Automatically increments reference count and schedules cleanup on component unmount. 942 */ 943 track() { 944 if (this.count === 0) { 945 this.free.delete(this.data); 946 } 947 this.count++; 948 if (!getOwner()) ; 949 else { 950 onCleanup(() => { 951 this.count -= 1; 952 if (this.count <= 0) { 953 this.free.add(this.data); 954 } 955 }); 956 } 957 } 958 /** 959 * Updates the cached resource with new data. 960 * @param data The new resource promise 961 * @param options.force Force update and dispose current resource (default: true) 962 */ 963 update(data, { force = true } = {}) { 964 if (this.data !== data && !force) ; 965 else { 966 this.#dispose(); 967 this.#set(data); 968 this.registry.set(this.path, this); 969 } 970 } 971}; 972var frameContext = createContext(); 973var useFrame = (callback, options) => { 974 const addFrameListener = useContext(frameContext); 975 if (!addFrameListener) { 976 throw new Error("S3: Hooks can only be used within the Canvas component!"); 977 } 978 return addFrameListener(callback, options); 979}; 980var threeContext = createContext(null); 981function useThree(callback) { 982 const store = useContext(threeContext); 983 if (!store) { 984 throw new Error("S3: Hooks can only be used within the Canvas component!"); 985 } 986 if (callback) return () => callback(store); 987 return store; 988} 989var LOADER_CACHE = /* @__PURE__ */ new Map(); 990function resolveUrls(base, url) { 991 if (Array.isArray(url)) { 992 return url.map((url2) => new URL(url2, base).href); 993 } else if (isRecord(url)) { 994 return Object.fromEntries( 995 Object.entries(url).map(([key, url2]) => [key, resolveUrls(base, url2)]) 996 ); 997 } else if (typeof url === "string") { 998 return new URL(url, base).href; 999 } 1000 throw new Error("Unexpected type"); 1001} 1002function useLoader(constructor, url, options) { 1003 const config = mergeProps({ cache: true }, options); 1004 const loader = createMemo(() => { 1005 const _constructor = resolve2(constructor); 1006 let loader2 = LOADER_CACHE.get(_constructor); 1007 if (!loader2) { 1008 LOADER_CACHE.set(_constructor, loader2 = new _constructor()); 1009 } 1010 return loader2; 1011 }); 1012 function getOrInsert(registry, loader2, input) { 1013 if (isRecord(input)) { 1014 return awaitMapObject(input, async (value) => getOrInsert(registry, loader2, value)); 1015 } else { 1016 const _input = input; 1017 const cachedPromise = registry.get(loader2, _input, false); 1018 if (cachedPromise) { 1019 return cachedPromise; 1020 } 1021 const promise = load(loader2, _input); 1022 registry.set(loader2, _input, promise); 1023 return promise; 1024 } 1025 } 1026 function loadUrl(url2) { 1027 if (config.cache === true) { 1028 if (!useLoader.cache) { 1029 return load(loader(), url2); 1030 } 1031 return getOrInsert(useLoader.cache, loader(), url2); 1032 } 1033 if (config.cache) { 1034 return getOrInsert(config.cache, loader(), url2); 1035 } 1036 return load(loader(), url2); 1037 } 1038 const [resource] = createResource( 1039 () => [resolve2(url), options?.base, loader()], 1040 async ([url2, base, loader2]) => { 1041 config.onBeforeLoad?.(loader2); 1042 url2 = base ? resolveUrls(base, url2) : url2; 1043 const result = await loadUrl(url2); 1044 config.onLoad?.(result); 1045 return result; 1046 } 1047 ); 1048 return resource; 1049} 1050useLoader.cache = new LoaderCache(); 1051var addToEventListeners = (object, type) => { 1052 const addToEventListeners2 = useContext(eventContext); 1053 if (!addToEventListeners2) { 1054 throw new Error("S3: Hooks can only be used within the Canvas component!"); 1055 } 1056 return addToEventListeners2(object, type); 1057}; 1058var eventContext = createContext(); 1059createContext(); 1060function applySceneGraph(parent, child) { 1061 const parentMeta = getMeta(parent); 1062 if (parentMeta) { 1063 parentMeta.children.add(child); 1064 onCleanup(() => parentMeta.children.delete(child)); 1065 } 1066 const childMeta = getMeta(child); 1067 if (childMeta) { 1068 childMeta.parent = parent; 1069 onCleanup(() => childMeta.parent = void 0); 1070 } 1071 let attachProp = childMeta?.props.attach; 1072 if (typeof attachProp === "function") { 1073 const cleanup = attachProp(parent, child); 1074 onCleanup(cleanup); 1075 return; 1076 } 1077 if (!attachProp) { 1078 if (isMaterial(child)) attachProp = "material"; 1079 else if (isBufferGeometry(child)) attachProp = "geometry"; 1080 else if (isFog(child)) attachProp = "fog"; 1081 } 1082 if (attachProp) { 1083 let target = parent; 1084 let property; 1085 const path = attachProp.split("-"); 1086 while (property = path.shift()) { 1087 if (path.length === 0) { 1088 target[property] = child; 1089 onCleanup(() => target[property] = void 0); 1090 break; 1091 } else { 1092 target = target[property]; 1093 } 1094 } 1095 return; 1096 } 1097 if (isObject3D(child) && isObject3D(parent)) return; 1098} 1099var useSceneGraph = (_parent, props) => { 1100 const c = children(() => props.children); 1101 createComputed( 1102 mapArray( 1103 () => c.toArray(), 1104 (_child) => createComputed(() => { 1105 const parent = resolve2(_parent); 1106 if (!parent) return; 1107 const child = resolve2(_child); 1108 if (!child) return; 1109 applySceneGraph(parent, child); 1110 props.onUpdate?.(parent); 1111 }) 1112 ) 1113 ); 1114 createComputed((previousManagedChildren) => { 1115 const parent = resolve2(_parent); 1116 if (!isObject3D(parent)) { 1117 return previousManagedChildren; 1118 } 1119 const childArray = c.toArray(); 1120 const managedChildren = /* @__PURE__ */ new Set(); 1121 for (const child of childArray) { 1122 if (!isObject3D(child) || getMeta(child)?.props.attach) continue; 1123 managedChildren.add(child); 1124 if (child.parent !== parent) { 1125 parent.add(child); 1126 } 1127 } 1128 for (const child of previousManagedChildren) { 1129 if (!managedChildren.has(child)) { 1130 parent.remove(child); 1131 } 1132 } 1133 let childArrayIndex = 0; 1134 for (let i = 0; i < parent.children.length; i++) { 1135 if (!managedChildren.has(parent.children[i])) { 1136 continue; 1137 } 1138 while (childArrayIndex < childArray.length) { 1139 const child = childArray[childArrayIndex++]; 1140 if (isObject3D(child) && !getMeta(child)?.props.attach) { 1141 parent.children[i] = child; 1142 break; 1143 } 1144 } 1145 } 1146 return managedChildren; 1147 }, /* @__PURE__ */ new Set()); 1148}; 1149var NEEDS_UPDATE = [ 1150 "map", 1151 "envMap", 1152 "bumpMap", 1153 "normalMap", 1154 "transparent", 1155 "morphTargets", 1156 "skinning", 1157 "alphaTest", 1158 "useVertexColors", 1159 "flatShading" 1160]; 1161function applyProp(context, source, type, value) { 1162 if (!source) { 1163 return; 1164 } 1165 if (value === void 0) return; 1166 if (type.indexOf("-") > -1) { 1167 const [property, ...rest] = type.split("-"); 1168 applyProp(context, source[property], rest.join("-"), value); 1169 return; 1170 } 1171 if (NEEDS_UPDATE.includes(type) && (!source[type] && value || source[type] && !value)) { 1172 source.needsUpdate = true; 1173 } 1174 if (hasColorSpace(source)) { 1175 const sRGBEncoding2 = 3001; 1176 const SRGBColorSpace22 = "srgb"; 1177 const LinearSRGBColorSpace22 = "srgb-linear"; 1178 if (type === "encoding") { 1179 type = "colorSpace"; 1180 value = value === sRGBEncoding2 ? SRGBColorSpace22 : LinearSRGBColorSpace22; 1181 } else if (type === "outputEncoding") { 1182 type = "outputColorSpace"; 1183 value = value === sRGBEncoding2 ? SRGBColorSpace22 : LinearSRGBColorSpace22; 1184 } 1185 } 1186 if (isEventType(type)) { 1187 if (isObject3D(source) && hasMeta(source)) { 1188 const cleanup = addToEventListeners(source, type); 1189 onCleanup(cleanup); 1190 } 1191 return; 1192 } 1193 const target = source[type]; 1194 try { 1195 if (target?.copy && target?.constructor === value?.constructor && !isWritable(source, type)) { 1196 target.copy(value); 1197 } else if (target?.set && Array.isArray(value)) { 1198 if (target.fromArray) target.fromArray(value); 1199 else target.set(...value); 1200 } else if (target?.set && typeof value !== "object") { 1201 const isColor = target instanceof Color; 1202 if (!isColor && target.setScalar && typeof value === "number") { 1203 target.setScalar(value); 1204 } else if (value !== void 0) { 1205 target.set(value); 1206 } 1207 } else { 1208 source[type] = value; 1209 if (source[type] instanceof Texture && // sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129 1210 source[type].format === RGBAFormat && source[type].type === UnsignedByteType) { 1211 createRenderEffect(() => { 1212 context.props.linear; 1213 context.props.flat; 1214 const texture = source[type]; 1215 if (hasColorSpace(texture) && hasColorSpace(context.gl)) { 1216 texture.colorSpace = context.gl.outputColorSpace; 1217 } else { 1218 texture.encoding = context.gl.outputEncoding; 1219 } 1220 }); 1221 } 1222 } 1223 } finally { 1224 if ("needsUpdate" in source) { 1225 source.needsUpdate = true; 1226 } 1227 if (context.props.frameloop === "demand") { 1228 context.requestRender(); 1229 } 1230 } 1231} 1232function useProps(accessor, props, context = useThree()) { 1233 const [local, instanceProps] = splitProps(props, ["ref", "args", "object", "attach", "children"]); 1234 useSceneGraph(accessor, props); 1235 createRenderEffect(() => { 1236 const object = resolve2(accessor); 1237 if (!object) return; 1238 createRenderEffect(() => { 1239 if (local.ref instanceof Function) local.ref(object); 1240 else local.ref = object; 1241 }); 1242 createRenderEffect(() => { 1243 const keys2 = Object.keys(instanceProps); 1244 for (const key of keys2) { 1245 const subKeys = keys2.filter((_key) => key !== _key && _key.includes(key)); 1246 createRenderEffect(() => { 1247 applyProp(context, object, key, props[key]); 1248 for (const subKey of subKeys) { 1249 applyProp(context, object, subKey, props[subKey]); 1250 } 1251 }); 1252 } 1253 untrack(() => props.onUpdate)?.(object); 1254 }); 1255 }); 1256} 1257var CursorRaycaster = class extends Raycaster { 1258 pointer = new Vector2(); 1259 update(event, context) { 1260 this.pointer.x = event.offsetX / context.bounds.width * 2 - 1; 1261 this.pointer.y = -(event.offsetY / context.bounds.height) * 2 + 1; 1262 this.setFromCamera(this.pointer, context.camera); 1263 } 1264}; 1265function debounce(callback, wait = 100, options = {}) { 1266 if (typeof callback !== "function") { 1267 throw new TypeError( 1268 `Expected the first parameter to be a function, got \`${typeof callback}\`.` 1269 ); 1270 } 1271 if (wait < 0) { 1272 throw new RangeError("`wait` must not be negative."); 1273 } 1274 const { immediate } = options; 1275 let storedContext; 1276 let storedArguments; 1277 let timeoutId; 1278 let timestamp; 1279 let result; 1280 function run() { 1281 const callContext = storedContext; 1282 const callArguments = storedArguments; 1283 storedContext = void 0; 1284 storedArguments = void 0; 1285 result = callback.apply(callContext, callArguments); 1286 return result; 1287 } 1288 function later() { 1289 const last = Date.now() - timestamp; 1290 if (last < wait && last >= 0) { 1291 timeoutId = setTimeout(later, wait - last); 1292 } else { 1293 timeoutId = void 0; 1294 if (!immediate) { 1295 result = run(); 1296 } 1297 } 1298 } 1299 function debounced(...args) { 1300 if (storedContext && this !== storedContext) { 1301 throw new Error("Debounced method called with different contexts."); 1302 } 1303 storedContext = this; 1304 storedArguments = args; 1305 timestamp = Date.now(); 1306 const callNow = immediate && !timeoutId; 1307 if (!timeoutId) { 1308 timeoutId = setTimeout(later, wait); 1309 } 1310 if (callNow) { 1311 result = run(); 1312 } 1313 return result; 1314 } 1315 debounced.clear = () => { 1316 if (!timeoutId) return; 1317 clearTimeout(timeoutId); 1318 timeoutId = void 0; 1319 }; 1320 debounced.flush = () => { 1321 if (!timeoutId) return; 1322 debounced.trigger(); 1323 }; 1324 debounced.trigger = () => { 1325 result = run(); 1326 debounced.clear(); 1327 }; 1328 return debounced; 1329} 1330function useMeasure(options) { 1331 const config = mergeProps( 1332 { 1333 debounce: 0, 1334 scroll: false, 1335 offsetSize: false 1336 }, 1337 options 1338 ); 1339 const ResizeObserver2 = config.polyfill || (typeof globalThis === "undefined" ? class ResizeObserver { 1340 } : globalThis.ResizeObserver); 1341 if (!ResizeObserver2) { 1342 throw new Error( 1343 "This browser does not support ResizeObserver out of the box. See: https://github.com/react-spring/react-use-measure/#resize-observer-polyfills" 1344 ); 1345 } 1346 const [element, setElement] = createSignal(null); 1347 const [bounds, setBounds] = createSignal({ 1348 left: 0, 1349 top: 0, 1350 width: 0, 1351 height: 0, 1352 bottom: 0, 1353 right: 0, 1354 x: 0, 1355 y: 0 1356 }); 1357 const scrollContainers = createMemo(() => findScrollContainers(element())); 1358 let lastBounds; 1359 const getDebounce = (type) => { 1360 const debounce2 = config.debounce ? typeof config.debounce === "number" ? config.debounce : config.debounce[type] : null; 1361 if (debounce2) return debounce(forceRefresh, debounce2); 1362 return forceRefresh; 1363 }; 1364 const forceRefresh = when(element, (element2) => { 1365 const { left, top, width, height, bottom, right, x, y } = element2.getBoundingClientRect(); 1366 const bounds2 = { 1367 left, 1368 top, 1369 width, 1370 height, 1371 bottom, 1372 right, 1373 x, 1374 y 1375 }; 1376 if (element2 instanceof HTMLElement && config.offsetSize) { 1377 bounds2.height = element2.offsetHeight; 1378 bounds2.width = element2.offsetWidth; 1379 } 1380 Object.freeze(bounds2); 1381 if (!lastBounds || !areBoundsEqual(lastBounds, bounds2)) { 1382 lastBounds = bounds2; 1383 setBounds(bounds2); 1384 } 1385 }); 1386 createEffect(() => { 1387 const onScroll = getDebounce("scroll"); 1388 createEffect(() => { 1389 if (!config.scroll) return; 1390 globalThis.addEventListener("scroll", onScroll, { capture: true, passive: true }); 1391 onCleanup(() => globalThis.removeEventListener("scroll", onScroll, true)); 1392 }); 1393 whenEffect(scrollContainers, (scrollContainers2) => { 1394 if (!config.scroll) return; 1395 scrollContainers2.forEach( 1396 (scrollContainer) => scrollContainer.addEventListener("scroll", onScroll, { 1397 capture: true, 1398 passive: true 1399 }) 1400 ); 1401 onCleanup(() => { 1402 scrollContainers2.forEach((element2) => { 1403 element2.removeEventListener("scroll", onScroll, true); 1404 }); 1405 }); 1406 }); 1407 }); 1408 createEffect(() => { 1409 const onResize = getDebounce("resize"); 1410 globalThis.addEventListener("resize", onResize); 1411 onCleanup(() => globalThis.removeEventListener("resize", onResize)); 1412 whenEffect(element, (element2) => { 1413 const observer = new ResizeObserver2(onResize); 1414 observer.observe(element2); 1415 onCleanup(() => observer.disconnect()); 1416 }); 1417 }); 1418 return { 1419 setElement: (source) => { 1420 if (!source || source === element()) return; 1421 setElement(source); 1422 forceRefresh(); 1423 }, 1424 bounds, 1425 forceRefresh 1426 }; 1427} 1428function findScrollContainers(element) { 1429 const result = []; 1430 if (!element || element === document.body) return result; 1431 const { overflow, overflowX, overflowY } = globalThis.getComputedStyle(element); 1432 if ([overflow, overflowX, overflowY].some((prop) => prop === "auto" || prop === "scroll")) 1433 result.push(element); 1434 return [...result, ...findScrollContainers(element.parentElement)]; 1435} 1436var keys = ["x", "y", "top", "bottom", "left", "right", "width", "height"]; 1437var areBoundsEqual = (a, b) => keys.every((key) => a[key] === b[key]); 1438function createThree(canvas, props) { 1439 const canvasProps = defaultProps(props, { 1440 frameloop: "always" 1441 }); 1442 const frameListeners = { 1443 before: { 1444 map: /* @__PURE__ */ new Map(), 1445 priorities: [] 1446 // Keep this sorted 1447 }, 1448 after: { 1449 map: /* @__PURE__ */ new Map(), 1450 priorities: [] 1451 } 1452 }; 1453 const addFrameListener = (callback, options) => { 1454 return createRoot((dispose) => { 1455 createRenderEffect(() => { 1456 const { 1457 stage = "before", 1458 priority = 0 1459 } = options ?? {}; 1460 const listeners = frameListeners[stage]; 1461 let array = listeners.map.get(priority); 1462 if (!array) { 1463 array = []; 1464 listeners.map.set(priority, array); 1465 const index = binarySearch(listeners.priorities, priority); 1466 listeners.priorities.splice(index, 0, priority); 1467 } 1468 array.push(callback); 1469 onCleanup(() => { 1470 removeElementFromArray(array, callback); 1471 if (array.length === 0) { 1472 listeners.map.delete(priority); 1473 listeners.priorities.splice(listeners.priorities.indexOf(priority), 1); 1474 } 1475 }); 1476 }); 1477 return dispose; 1478 }); 1479 }; 1480 function updateFrameListeners(stage, delta, frame) { 1481 for (const priority of frameListeners[stage].priorities) { 1482 const callbacks = frameListeners[stage].map.get(priority); 1483 for (const callback of callbacks) { 1484 callback(context, delta, frame); 1485 } 1486 } 1487 } 1488 let pendingRenderRequest; 1489 const isPresenting = () => !!context.gl?.xr?.isPresenting; 1490 function render(timestamp, frame) { 1491 if (!context.gl || rendererReady.state !== "ready") { 1492 return; 1493 } 1494 if (props.frameloop === "never") { 1495 context.clock.elapsedTime = timestamp; 1496 } 1497 pendingRenderRequest = void 0; 1498 const delta = context.clock.getDelta(); 1499 updateFrameListeners("before", delta, frame); 1500 context.gl.render(context.scene, context.camera); 1501 updateFrameListeners("after", delta, frame); 1502 } 1503 function requestRender() { 1504 if (isPresenting()) return; 1505 if (pendingRenderRequest) return; 1506 pendingRenderRequest = requestAnimationFrame(render); 1507 } 1508 onCleanup(() => pendingRenderRequest && cancelAnimationFrame(pendingRenderRequest)); 1509 const cameraIsInstance = createMemo(() => props.camera instanceof Camera); 1510 const orthographicFlag = createMemo(() => !!props.orthographic); 1511 const sceneIsInstance = createMemo(() => props.scene instanceof Scene); 1512 const raycasterIsInstance = createMemo(() => props.raycaster instanceof Raycaster); 1513 const glKind = createMemo(() => { 1514 const _propsGl = props.gl; 1515 if (typeof _propsGl === "function") return "factory"; 1516 if (isRenderer(_propsGl)) return "instance"; 1517 return "default"; 1518 }); 1519 const WEBGL_CONSTRUCTOR_KEYS = ["alpha", "antialias", "depth", "failIfMajorPerformanceCaveat", "logarithmicDepthBuffer", "powerPreference", "precision", "premultipliedAlpha", "preserveDrawingBuffer", "reversedDepthBuffer", "stencil"]; 1520 const camera = createMemo(() => { 1521 if (cameraIsInstance()) { 1522 return meta(props.camera, { 1523 get props() { 1524 return props.camera || {}; 1525 } 1526 }); 1527 } 1528 return meta(orthographicFlag() ? new OrthographicCamera() : new PerspectiveCamera(), { 1529 get props() { 1530 return props.camera || {}; 1531 } 1532 }); 1533 }); 1534 const cameraStack = new Stack("camera"); 1535 const scene = createMemo(() => { 1536 if (sceneIsInstance()) { 1537 return meta(props.scene, { 1538 get props() { 1539 return props.scene || {}; 1540 } 1541 }); 1542 } 1543 return meta(new Scene(), { 1544 get props() { 1545 return props.scene || {}; 1546 } 1547 }); 1548 }); 1549 const raycaster = createMemo(() => { 1550 if (raycasterIsInstance()) { 1551 return meta(props.raycaster, { 1552 get props() { 1553 return props.raycaster || {}; 1554 } 1555 }); 1556 } 1557 return meta(new CursorRaycaster(), { 1558 get props() { 1559 return props.raycaster || {}; 1560 } 1561 }); 1562 }); 1563 const raycasterStack = new Stack("raycaster"); 1564 let ownsCurrentRenderer = false; 1565 let initialConstructorArgs = {}; 1566 const gl = createMemo((previous) => { 1567 if (previous && ownsCurrentRenderer) { 1568 const old = previous; 1569 old.dispose?.(); 1570 if ("forceContextLoss" in old) old.forceContextLoss(); 1571 } 1572 const kind = glKind(); 1573 let _gl; 1574 if (kind === "factory") { 1575 _gl = props.gl(canvas); 1576 ownsCurrentRenderer = false; 1577 } else if (kind === "instance") { 1578 _gl = props.gl; 1579 ownsCurrentRenderer = false; 1580 } else { 1581 const flat = untrack(() => props.gl ?? {}); 1582 const constructorArgs = {}; 1583 for (const key of WEBGL_CONSTRUCTOR_KEYS) { 1584 if (key in flat) constructorArgs[key] = flat[key]; 1585 } 1586 initialConstructorArgs = constructorArgs; 1587 _gl = new WebGLRenderer({ 1588 alpha: true, 1589 ...constructorArgs, 1590 canvas 1591 }); 1592 ownsCurrentRenderer = true; 1593 } 1594 return meta(_gl, { 1595 get props() { 1596 return props.gl || {}; 1597 } 1598 }); 1599 }); 1600 const [rendererReady] = createResource(() => gl(), (renderer) => { 1601 const init = getPendingInit(renderer); 1602 if (!init) return true; 1603 const rect = canvas.getBoundingClientRect(); 1604 const ratio = globalThis.devicePixelRatio || 1; 1605 if (rect.width > 0 && rect.height > 0) { 1606 canvas.width = rect.width * ratio; 1607 canvas.height = rect.height * ratio; 1608 } 1609 return init().then(() => true); 1610 }); 1611 const measure = useMeasure(); 1612 measure.setElement(canvas); 1613 const defaultTarget = new Vector3(); 1614 const viewport = createMemo(() => getCurrentViewport(camera(), defaultTarget, measure.bounds())); 1615 const clock = new Clock(); 1616 clock.start(); 1617 const context = { 1618 get bounds() { 1619 return measure.bounds(); 1620 }, 1621 canvas, 1622 clock, 1623 get dpr() { 1624 return this.gl.getPixelRatio?.() ?? 1; 1625 }, 1626 props, 1627 render, 1628 requestRender, 1629 get viewport() { 1630 return viewport(); 1631 }, 1632 // elements 1633 get camera() { 1634 return cameraStack.peek() ?? camera(); 1635 }, 1636 setCamera(camera2) { 1637 return cameraStack.push(camera2); 1638 }, 1639 get scene() { 1640 return scene(); 1641 }, 1642 get raycaster() { 1643 return raycasterStack.peek() || raycaster(); 1644 }, 1645 setRaycaster(raycaster2) { 1646 return raycasterStack.push(raycaster2); 1647 }, 1648 get gl() { 1649 return gl(); 1650 } 1651 }; 1652 withMultiContexts(() => { 1653 createRenderEffect(() => { 1654 if (props.frameloop === "never") { 1655 context.clock.stop(); 1656 context.clock.elapsedTime = 0; 1657 } else { 1658 context.clock.start(); 1659 } 1660 }); 1661 createRenderEffect(() => { 1662 if (cameraStack.peek()) return; 1663 if (!props.camera || props.camera instanceof Camera) return; 1664 useProps(camera, props.camera); 1665 camera().updateMatrixWorld(true); 1666 }); 1667 createRenderEffect(() => { 1668 if (!props.scene || props.scene instanceof Scene) return; 1669 useProps(scene, props.scene); 1670 }); 1671 createRenderEffect(() => { 1672 if (!props.raycaster || props.raycaster instanceof Raycaster) return; 1673 useProps(raycaster, props.raycaster); 1674 }); 1675 createRenderEffect(() => { 1676 createRenderEffect(() => { 1677 const shadowMap = gl().shadowMap; 1678 if (!shadowMap) return; 1679 const oldEnabled = shadowMap.enabled; 1680 const oldType = shadowMap.type; 1681 shadowMap.enabled = !!props.shadows; 1682 if (typeof props.shadows === "boolean") { 1683 shadowMap.type = PCFSoftShadowMap; 1684 } else if (typeof props.shadows === "string") { 1685 const types = { 1686 basic: BasicShadowMap, 1687 percentage: PCFShadowMap, 1688 soft: PCFSoftShadowMap, 1689 variance: VSMShadowMap 1690 }; 1691 shadowMap.type = types[props.shadows] ?? PCFSoftShadowMap; 1692 } else if (typeof props.shadows === "object") { 1693 Object.assign(shadowMap, props.shadows); 1694 } 1695 if (isWebGLShadowMap(shadowMap) && (oldEnabled !== shadowMap.enabled || oldType !== shadowMap.type)) { 1696 shadowMap.needsUpdate = true; 1697 } 1698 }); 1699 const _gl = gl(); 1700 if ("outputColorSpace" in _gl) { 1701 useProps(gl, { 1702 get outputColorSpace() { 1703 return props.linear ? LinearSRGBColorSpace : SRGBColorSpace; 1704 } 1705 }); 1706 } 1707 if ("toneMapping" in _gl) { 1708 useProps(gl, { 1709 get toneMapping() { 1710 return props.flat ? NoToneMapping : ACESFilmicToneMapping; 1711 } 1712 }); 1713 } 1714 const _propsGl = props.gl; 1715 if (_propsGl && typeof _propsGl !== "function" && !isRenderer(_propsGl)) { 1716 useProps(gl, _propsGl); 1717 } 1718 let warnedCtorKeys = false; 1719 createEffect(() => { 1720 if (warnedCtorKeys) return; 1721 const flat = props.gl ?? {}; 1722 for (const key of WEBGL_CONSTRUCTOR_KEYS) { 1723 if (key in flat && flat[key] !== initialConstructorArgs[key]) { 1724 warnedCtorKeys = true; 1725 return; 1726 } 1727 } 1728 }); 1729 }); 1730 }, [[threeContext, context]]); 1731 let pendingLoopRequest; 1732 function loop(value) { 1733 if (isPresenting()) { 1734 pendingLoopRequest = void 0; 1735 return; 1736 } 1737 pendingLoopRequest = requestAnimationFrame(loop); 1738 context.render(value); 1739 } 1740 createRenderEffect(() => { 1741 if (canvasProps.frameloop === "always") { 1742 pendingLoopRequest = requestAnimationFrame(loop); 1743 } 1744 onCleanup(() => pendingLoopRequest && cancelAnimationFrame(pendingLoopRequest)); 1745 }); 1746 createRenderEffect(() => { 1747 const _gl = gl(); 1748 const xr = _gl.xr; 1749 if (!xr || typeof xr.addEventListener !== "function") return; 1750 const resume = () => { 1751 if (canvasProps.frameloop === "always") { 1752 if (!pendingLoopRequest) pendingLoopRequest = requestAnimationFrame(loop); 1753 } else if (canvasProps.frameloop === "demand") { 1754 requestRender(); 1755 } 1756 }; 1757 xr.addEventListener("sessionend", resume); 1758 onCleanup(() => xr.removeEventListener("sessionend", resume)); 1759 }); 1760 const { 1761 addEventListener 1762 } = createEvents(context); 1763 const c = children(() => createComponent(eventContext.Provider, { 1764 value: addEventListener, 1765 get children() { 1766 return createComponent(frameContext.Provider, { 1767 value: addFrameListener, 1768 get children() { 1769 return createComponent(threeContext.Provider, { 1770 value: context, 1771 get children() { 1772 return canvasProps.children; 1773 } 1774 }); 1775 } 1776 }); 1777 } 1778 })); 1779 useSceneGraph(context.scene, { 1780 get children() { 1781 return c(); 1782 } 1783 }); 1784 withMultiContexts(() => useRef(props, context), [[threeContext, context], [frameContext, addFrameListener]]); 1785 return mergeProps(context, { 1786 addFrameListener 1787 }); 1788} 1789var _tmpl$ = /* @__PURE__ */ template(`<div style=position:relative;width:100%;height:100%;overflow:hidden;contain:strict;display:flex><canvas>`); 1790function Canvas(props) { 1791 let canvas; 1792 let container; 1793 onMount(() => { 1794 if (!canvas || !container) return; 1795 const context = createThree(canvas, props); 1796 createResizeObserver(container, function onResize() { 1797 const { 1798 width, 1799 height 1800 } = container.getBoundingClientRect(); 1801 context.gl.setSize(width, height); 1802 context.gl.setPixelRatio?.(globalThis.devicePixelRatio); 1803 if (context.camera instanceof OrthographicCamera) { 1804 context.camera.left = width / -2; 1805 context.camera.right = width / 2; 1806 context.camera.top = height / 2; 1807 context.camera.bottom = height / -2; 1808 } else { 1809 context.camera.aspect = width / height; 1810 } 1811 context.camera.updateProjectionMatrix(); 1812 if (!context.gl?.xr?.isPresenting) context.render(performance.now()); 1813 }); 1814 }); 1815 return (() => { 1816 var _el$ = _tmpl$(), _el$2 = _el$.firstChild; 1817 var _ref$ = container; 1818 typeof _ref$ === "function" ? use(_ref$, _el$) : container = _el$; 1819 var _ref$2 = canvas; 1820 typeof _ref$2 === "function" ? use(_ref$2, _el$2) : canvas = _el$2; 1821 createRenderEffect((_p$) => { 1822 var _v$ = { 1823 ...props.style 1824 }, _v$2 = props.class; 1825 _p$.e = style(_el$, _v$, _p$.e); 1826 _v$2 !== _p$.t && className(_el$, _p$.t = _v$2); 1827 return _p$; 1828 }, { 1829 e: void 0, 1830 t: void 0 1831 }); 1832 return _el$; 1833 })(); 1834} 1835function Resource(props) { 1836 const [options, config, rest] = splitProps(props, ["base", "cache", "onBeforeLoad", "onLoad"], ["loader", "url", "children"]); 1837 const resource = useLoader(() => config.loader, () => config.url, options); 1838 const tagged = createMemo(() => { 1839 const value = resource(); 1840 if (!value || typeof value !== "object") return value; 1841 return hasMeta(value) ? value : meta(value, { 1842 props 1843 }); 1844 }); 1845 useProps(tagged, rest); 1846 return createComponent(Show, { 1847 get when() { 1848 return memo(() => "children" in config)() && tagged(); 1849 }, 1850 get fallback() { 1851 return tagged(); 1852 }, 1853 children: (value) => props.children?.(value) 1854 }); 1855} 1856function createT(catalogue) { 1857 const cache = /* @__PURE__ */ new Map(); 1858 return new Proxy({}, { 1859 get: (_, name) => { 1860 if (!cache.has(name)) { 1861 const constructor = catalogue[name]; 1862 if (!constructor) return void 0; 1863 cache.set(name, createEntity(constructor)); 1864 } 1865 return cache.get(name); 1866 } 1867 }); 1868} 1869function createEntity(Constructor) { 1870 return (props) => { 1871 const memo2 = createMemo(() => { 1872 props.key; 1873 try { 1874 return meta(autodispose(new Constructor(...props.args ?? [])), { 1875 props 1876 }); 1877 } catch (e) { 1878 throw new Error(""); 1879 } 1880 }); 1881 useProps(memo2, props); 1882 return memo2; 1883 }; 1884} 1885var xrContext = createContext(); 1886function useXR() { 1887 const state = useContext(xrContext); 1888 if (!state) { 1889 throw new Error("S3: useXR must be used within <xr.Provider> (from createXR())"); 1890 } 1891 return state; 1892} 1893function createXR() { 1894 const [context, setContext] = createSignal(); 1895 const [presenting, setPresenting] = createSignal(false); 1896 const [session, setSession] = createSignal(); 1897 createRenderEffect(() => { 1898 const ctx = context(); 1899 const gl = ctx ? ctx.gl : void 0; 1900 const xr = gl?.xr; 1901 if (!gl || !xr || typeof xr.addEventListener !== "function") return; 1902 const onStart = () => setPresenting(true); 1903 const onEnd = () => { 1904 setPresenting(false); 1905 setSession(void 0); 1906 gl.setAnimationLoop(null); 1907 gl.xr.enabled = false; 1908 }; 1909 xr.addEventListener("sessionstart", onStart); 1910 xr.addEventListener("sessionend", onEnd); 1911 onCleanup(() => { 1912 xr.removeEventListener("sessionstart", onStart); 1913 xr.removeEventListener("sessionend", onEnd); 1914 }); 1915 }); 1916 function connect(value) { 1917 setContext(value); 1918 return () => setContext(void 0); 1919 } 1920 function requestSession(mode, init) { 1921 if (!navigator.xr) { 1922 throw new Error("S3: WebXR unavailable (navigator.xr is undefined)"); 1923 } 1924 return navigator.xr.requestSession(mode, init); 1925 } 1926 async function enter(arg, init) { 1927 const ctx = context(); 1928 if (!ctx) { 1929 throw new Error("S3: createXR().enter() called before <Canvas ref={xr.connect}> connected"); 1930 } 1931 const gl = ctx.gl; 1932 if (!gl.xr) { 1933 throw new Error("S3: the active renderer has no xr manager"); 1934 } 1935 const xrSession = typeof arg === "string" ? await requestSession(arg, init) : arg; 1936 gl.setAnimationLoop(ctx.render); 1937 gl.xr.enabled = true; 1938 await gl.xr.setSession(xrSession); 1939 setSession(xrSession); 1940 return xrSession; 1941 } 1942 async function exit() { 1943 await session()?.end(); 1944 } 1945 function isSupported(mode) { 1946 return navigator.xr?.isSessionSupported(mode) ?? Promise.resolve(false); 1947 } 1948 const state = { 1949 isPresenting: presenting, 1950 session, 1951 exit 1952 }; 1953 function Provider(props) { 1954 return createComponent(xrContext.Provider, { 1955 value: state, 1956 get children() { 1957 return props.children; 1958 } 1959 }); 1960 } 1961 return { 1962 connect, 1963 enter, 1964 exit, 1965 isSupported, 1966 isPresenting: presenting, 1967 session, 1968 Provider 1969 }; 1970} 1971
vendor: 2,132 bytes, lines 1972-2031
1972// node_modules/three-stdlib/utils/BufferGeometryUtils.js 1973function toTrianglesDrawMode(geometry, drawMode) { 1974 if (drawMode === TrianglesDrawMode) { 1975 console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles."); 1976 return geometry; 1977 } 1978 if (drawMode === TriangleFanDrawMode || drawMode === TriangleStripDrawMode) { 1979 let index = geometry.getIndex(); 1980 if (index === null) { 1981 const indices = []; 1982 const position2 = geometry.getAttribute("position"); 1983 if (position2 !== void 0) { 1984 for (let i = 0; i < position2.count; i++) { 1985 indices.push(i); 1986 } 1987 geometry.setIndex(indices); 1988 index = geometry.getIndex(); 1989 } else { 1990 console.error( 1991 "THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible." 1992 ); 1993 return geometry; 1994 } 1995 } 1996 const numberOfTriangles = index.count - 2; 1997 const newIndices = []; 1998 if (index) { 1999 if (drawMode === TriangleFanDrawMode) { 2000 for (let i = 1; i <= numberOfTriangles; i++) { 2001 newIndices.push(index.getX(0)); 2002 newIndices.push(index.getX(i)); 2003 newIndices.push(index.getX(i + 1)); 2004 } 2005 } else { 2006 for (let i = 0; i < numberOfTriangles; i++) { 2007 if (i % 2 === 0) { 2008 newIndices.push(index.getX(i)); 2009 newIndices.push(index.getX(i + 1)); 2010 newIndices.push(index.getX(i + 2)); 2011 } else { 2012 newIndices.push(index.getX(i + 2)); 2013 newIndices.push(index.getX(i + 1)); 2014 newIndices.push(index.getX(i)); 2015 } 2016 } 2017 } 2018 } 2019 if (newIndices.length / 3 !== numberOfTriangles) { 2020 console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles."); 2021 } 2022 const newGeometry = geometry.clone(); 2023 newGeometry.setIndex(newIndices); 2024 newGeometry.clearGroups(); 2025 return newGeometry; 2026 } else { 2027 console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:", drawMode); 2028 return geometry; 2029 } 2030} 2031
vendor: 133 bytes, lines 2032-2034
2032// node_modules/three-stdlib/_polyfill/constants.js 2033var version = /* @__PURE__ */ (() => parseInt(REVISION.replace(/\D+/g, "")))(); 2034
vendor: 372 bytes, lines 2035-2050
2035// node_modules/three-stdlib/_polyfill/LoaderUtils.js 2036function decodeText(array) { 2037 if (typeof TextDecoder !== "undefined") { 2038 return new TextDecoder().decode(array); 2039 } 2040 let s = ""; 2041 for (let i = 0, il = array.length; i < il; i++) { 2042 s += String.fromCharCode(array[i]); 2043 } 2044 try { 2045 return decodeURIComponent(escape(s)); 2046 } catch (e) { 2047 return s; 2048 } 2049} 2050
vendor: 98,781 bytes, lines 2051-4669
2051// node_modules/three-stdlib/loaders/GLTFLoader.js 2052var SRGBColorSpace2 = "srgb"; 2053var LinearSRGBColorSpace2 = "srgb-linear"; 2054var sRGBEncoding = 3001; 2055var LinearEncoding = 3e3; 2056var GLTFLoader = class extends Loader { 2057 constructor(manager) { 2058 super(manager); 2059 this.dracoLoader = null; 2060 this.ktx2Loader = null; 2061 this.meshoptDecoder = null; 2062 this.pluginCallbacks = []; 2063 this.register(function(parser) { 2064 return new GLTFMaterialsClearcoatExtension(parser); 2065 }); 2066 this.register(function(parser) { 2067 return new GLTFMaterialsDispersionExtension(parser); 2068 }); 2069 this.register(function(parser) { 2070 return new GLTFTextureBasisUExtension(parser); 2071 }); 2072 this.register(function(parser) { 2073 return new GLTFTextureWebPExtension(parser); 2074 }); 2075 this.register(function(parser) { 2076 return new GLTFTextureAVIFExtension(parser); 2077 }); 2078 this.register(function(parser) { 2079 return new GLTFMaterialsSheenExtension(parser); 2080 }); 2081 this.register(function(parser) { 2082 return new GLTFMaterialsTransmissionExtension(parser); 2083 }); 2084 this.register(function(parser) { 2085 return new GLTFMaterialsVolumeExtension(parser); 2086 }); 2087 this.register(function(parser) { 2088 return new GLTFMaterialsIorExtension(parser); 2089 }); 2090 this.register(function(parser) { 2091 return new GLTFMaterialsEmissiveStrengthExtension(parser); 2092 }); 2093 this.register(function(parser) { 2094 return new GLTFMaterialsSpecularExtension(parser); 2095 }); 2096 this.register(function(parser) { 2097 return new GLTFMaterialsIridescenceExtension(parser); 2098 }); 2099 this.register(function(parser) { 2100 return new GLTFMaterialsAnisotropyExtension(parser); 2101 }); 2102 this.register(function(parser) { 2103 return new GLTFMaterialsBumpExtension(parser); 2104 }); 2105 this.register(function(parser) { 2106 return new GLTFLightsExtension(parser); 2107 }); 2108 this.register(function(parser) { 2109 return new GLTFMeshoptCompression(parser); 2110 }); 2111 this.register(function(parser) { 2112 return new GLTFMeshGpuInstancing(parser); 2113 }); 2114 } 2115 load(url, onLoad, onProgress, onError) { 2116 const scope = this; 2117 let resourcePath; 2118 if (this.resourcePath !== "") { 2119 resourcePath = this.resourcePath; 2120 } else if (this.path !== "") { 2121 const relativeUrl = LoaderUtils.extractUrlBase(url); 2122 resourcePath = LoaderUtils.resolveURL(relativeUrl, this.path); 2123 } else { 2124 resourcePath = LoaderUtils.extractUrlBase(url); 2125 } 2126 this.manager.itemStart(url); 2127 const _onError = function(e) { 2128 if (onError) { 2129 onError(e); 2130 } else { 2131 console.error(e); 2132 } 2133 scope.manager.itemError(url); 2134 scope.manager.itemEnd(url); 2135 }; 2136 const loader = new FileLoader(this.manager); 2137 loader.setPath(this.path); 2138 loader.setResponseType("arraybuffer"); 2139 loader.setRequestHeader(this.requestHeader); 2140 loader.setWithCredentials(this.withCredentials); 2141 loader.load( 2142 url, 2143 function(data) { 2144 try { 2145 scope.parse( 2146 data, 2147 resourcePath, 2148 function(gltf) { 2149 onLoad(gltf); 2150 scope.manager.itemEnd(url); 2151 }, 2152 _onError 2153 ); 2154 } catch (e) { 2155 _onError(e); 2156 } 2157 }, 2158 onProgress, 2159 _onError 2160 ); 2161 } 2162 setDRACOLoader(dracoLoader) { 2163 this.dracoLoader = dracoLoader; 2164 return this; 2165 } 2166 setDDSLoader() { 2167 throw new Error('THREE.GLTFLoader: "MSFT_texture_dds" no longer supported. Please update to "KHR_texture_basisu".'); 2168 } 2169 setKTX2Loader(ktx2Loader) { 2170 this.ktx2Loader = ktx2Loader; 2171 return this; 2172 } 2173 setMeshoptDecoder(meshoptDecoder) { 2174 this.meshoptDecoder = meshoptDecoder; 2175 return this; 2176 } 2177 register(callback) { 2178 if (this.pluginCallbacks.indexOf(callback) === -1) { 2179 this.pluginCallbacks.push(callback); 2180 } 2181 return this; 2182 } 2183 unregister(callback) { 2184 if (this.pluginCallbacks.indexOf(callback) !== -1) { 2185 this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(callback), 1); 2186 } 2187 return this; 2188 } 2189 parse(data, path, onLoad, onError) { 2190 let json; 2191 const extensions = {}; 2192 const plugins = {}; 2193 if (typeof data === "string") { 2194 json = JSON.parse(data); 2195 } else if (data instanceof ArrayBuffer) { 2196 const magic = decodeText(new Uint8Array(data.slice(0, 4))); 2197 if (magic === BINARY_EXTENSION_HEADER_MAGIC) { 2198 try { 2199 extensions[EXTENSIONS.KHR_BINARY_GLTF] = new GLTFBinaryExtension(data); 2200 } catch (error) { 2201 if (onError) 2202 onError(error); 2203 return; 2204 } 2205 json = JSON.parse(extensions[EXTENSIONS.KHR_BINARY_GLTF].content); 2206 } else { 2207 json = JSON.parse(decodeText(new Uint8Array(data))); 2208 } 2209 } else { 2210 json = data; 2211 } 2212 if (json.asset === void 0 || json.asset.version[0] < 2) { 2213 if (onError) 2214 onError(new Error("THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.")); 2215 return; 2216 } 2217 const parser = new GLTFParser(json, { 2218 path: path || this.resourcePath || "", 2219 crossOrigin: this.crossOrigin, 2220 requestHeader: this.requestHeader, 2221 manager: this.manager, 2222 ktx2Loader: this.ktx2Loader, 2223 meshoptDecoder: this.meshoptDecoder 2224 }); 2225 parser.fileLoader.setRequestHeader(this.requestHeader); 2226 for (let i = 0; i < this.pluginCallbacks.length; i++) { 2227 const plugin = this.pluginCallbacks[i](parser); 2228 if (!plugin.name) 2229 console.error("THREE.GLTFLoader: Invalid plugin found: missing name"); 2230 plugins[plugin.name] = plugin; 2231 extensions[plugin.name] = true; 2232 } 2233 if (json.extensionsUsed) { 2234 for (let i = 0; i < json.extensionsUsed.length; ++i) { 2235 const extensionName = json.extensionsUsed[i]; 2236 const extensionsRequired = json.extensionsRequired || []; 2237 switch (extensionName) { 2238 case EXTENSIONS.KHR_MATERIALS_UNLIT: 2239 extensions[extensionName] = new GLTFMaterialsUnlitExtension(); 2240 break; 2241 case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION: 2242 extensions[extensionName] = new GLTFDracoMeshCompressionExtension(json, this.dracoLoader); 2243 break; 2244 case EXTENSIONS.KHR_TEXTURE_TRANSFORM: 2245 extensions[extensionName] = new GLTFTextureTransformExtension(); 2246 break; 2247 case EXTENSIONS.KHR_MESH_QUANTIZATION: 2248 extensions[extensionName] = new GLTFMeshQuantizationExtension(); 2249 break; 2250 default: 2251 if (extensionsRequired.indexOf(extensionName) >= 0 && plugins[extensionName] === void 0) { 2252 console.warn('THREE.GLTFLoader: Unknown extension "' + extensionName + '".'); 2253 } 2254 } 2255 } 2256 } 2257 parser.setExtensions(extensions); 2258 parser.setPlugins(plugins); 2259 parser.parse(onLoad, onError); 2260 } 2261 parseAsync(data, path) { 2262 const scope = this; 2263 return new Promise(function(resolve3, reject) { 2264 scope.parse(data, path, resolve3, reject); 2265 }); 2266 } 2267}; 2268function GLTFRegistry() { 2269 let objects = {}; 2270 return { 2271 get: function(key) { 2272 return objects[key]; 2273 }, 2274 add: function(key, object) { 2275 objects[key] = object; 2276 }, 2277 remove: function(key) { 2278 delete objects[key]; 2279 }, 2280 removeAll: function() { 2281 objects = {}; 2282 } 2283 }; 2284} 2285var EXTENSIONS = { 2286 KHR_BINARY_GLTF: "KHR_binary_glTF", 2287 KHR_DRACO_MESH_COMPRESSION: "KHR_draco_mesh_compression", 2288 KHR_LIGHTS_PUNCTUAL: "KHR_lights_punctual", 2289 KHR_MATERIALS_CLEARCOAT: "KHR_materials_clearcoat", 2290 KHR_MATERIALS_DISPERSION: "KHR_materials_dispersion", 2291 KHR_MATERIALS_IOR: "KHR_materials_ior", 2292 KHR_MATERIALS_SHEEN: "KHR_materials_sheen", 2293 KHR_MATERIALS_SPECULAR: "KHR_materials_specular", 2294 KHR_MATERIALS_TRANSMISSION: "KHR_materials_transmission", 2295 KHR_MATERIALS_IRIDESCENCE: "KHR_materials_iridescence", 2296 KHR_MATERIALS_ANISOTROPY: "KHR_materials_anisotropy", 2297 KHR_MATERIALS_UNLIT: "KHR_materials_unlit", 2298 KHR_MATERIALS_VOLUME: "KHR_materials_volume", 2299 KHR_TEXTURE_BASISU: "KHR_texture_basisu", 2300 KHR_TEXTURE_TRANSFORM: "KHR_texture_transform", 2301 KHR_MESH_QUANTIZATION: "KHR_mesh_quantization", 2302 KHR_MATERIALS_EMISSIVE_STRENGTH: "KHR_materials_emissive_strength", 2303 EXT_MATERIALS_BUMP: "EXT_materials_bump", 2304 EXT_TEXTURE_WEBP: "EXT_texture_webp", 2305 EXT_TEXTURE_AVIF: "EXT_texture_avif", 2306 EXT_MESHOPT_COMPRESSION: "EXT_meshopt_compression", 2307 EXT_MESH_GPU_INSTANCING: "EXT_mesh_gpu_instancing" 2308}; 2309var GLTFLightsExtension = class { 2310 constructor(parser) { 2311 this.parser = parser; 2312 this.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL; 2313 this.cache = { refs: {}, uses: {} }; 2314 } 2315 _markDefs() { 2316 const parser = this.parser; 2317 const nodeDefs = this.parser.json.nodes || []; 2318 for (let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex++) { 2319 const nodeDef = nodeDefs[nodeIndex]; 2320 if (nodeDef.extensions && nodeDef.extensions[this.name] && nodeDef.extensions[this.name].light !== void 0) { 2321 parser._addNodeRef(this.cache, nodeDef.extensions[this.name].light); 2322 } 2323 } 2324 } 2325 _loadLight(lightIndex) { 2326 const parser = this.parser; 2327 const cacheKey = "light:" + lightIndex; 2328 let dependency = parser.cache.get(cacheKey); 2329 if (dependency) 2330 return dependency; 2331 const json = parser.json; 2332 const extensions = json.extensions && json.extensions[this.name] || {}; 2333 const lightDefs = extensions.lights || []; 2334 const lightDef = lightDefs[lightIndex]; 2335 let lightNode; 2336 const color = new Color(16777215); 2337 if (lightDef.color !== void 0) 2338 color.setRGB(lightDef.color[0], lightDef.color[1], lightDef.color[2], LinearSRGBColorSpace2); 2339 const range = lightDef.range !== void 0 ? lightDef.range : 0; 2340 switch (lightDef.type) { 2341 case "directional": 2342 lightNode = new DirectionalLight(color); 2343 lightNode.target.position.set(0, 0, -1); 2344 lightNode.add(lightNode.target); 2345 break; 2346 case "point": 2347 lightNode = new PointLight(color); 2348 lightNode.distance = range; 2349 break; 2350 case "spot": 2351 lightNode = new SpotLight(color); 2352 lightNode.distance = range; 2353 lightDef.spot = lightDef.spot || {}; 2354 lightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== void 0 ? lightDef.spot.innerConeAngle : 0; 2355 lightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== void 0 ? lightDef.spot.outerConeAngle : Math.PI / 4; 2356 lightNode.angle = lightDef.spot.outerConeAngle; 2357 lightNode.penumbra = 1 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle; 2358 lightNode.target.position.set(0, 0, -1); 2359 lightNode.add(lightNode.target); 2360 break; 2361 default: 2362 throw new Error("THREE.GLTFLoader: Unexpected light type: " + lightDef.type); 2363 } 2364 lightNode.position.set(0, 0, 0); 2365 lightNode.decay = 2; 2366 assignExtrasToUserData(lightNode, lightDef); 2367 if (lightDef.intensity !== void 0) 2368 lightNode.intensity = lightDef.intensity; 2369 lightNode.name = parser.createUniqueName(lightDef.name || "light_" + lightIndex); 2370 dependency = Promise.resolve(lightNode); 2371 parser.cache.add(cacheKey, dependency); 2372 return dependency; 2373 } 2374 getDependency(type, index) { 2375 if (type !== "light") 2376 return; 2377 return this._loadLight(index); 2378 } 2379 createNodeAttachment(nodeIndex) { 2380 const self2 = this; 2381 const parser = this.parser; 2382 const json = parser.json; 2383 const nodeDef = json.nodes[nodeIndex]; 2384 const lightDef = nodeDef.extensions && nodeDef.extensions[this.name] || {}; 2385 const lightIndex = lightDef.light; 2386 if (lightIndex === void 0) 2387 return null; 2388 return this._loadLight(lightIndex).then(function(light) { 2389 return parser._getNodeRef(self2.cache, lightIndex, light); 2390 }); 2391 } 2392}; 2393var GLTFMaterialsUnlitExtension = class { 2394 constructor() { 2395 this.name = EXTENSIONS.KHR_MATERIALS_UNLIT; 2396 } 2397 getMaterialType() { 2398 return MeshBasicMaterial; 2399 } 2400 extendParams(materialParams, materialDef, parser) { 2401 const pending = []; 2402 materialParams.color = new Color(1, 1, 1); 2403 materialParams.opacity = 1; 2404 const metallicRoughness = materialDef.pbrMetallicRoughness; 2405 if (metallicRoughness) { 2406 if (Array.isArray(metallicRoughness.baseColorFactor)) { 2407 const array = metallicRoughness.baseColorFactor; 2408 materialParams.color.setRGB(array[0], array[1], array[2], LinearSRGBColorSpace2); 2409 materialParams.opacity = array[3]; 2410 } 2411 if (metallicRoughness.baseColorTexture !== void 0) { 2412 pending.push(parser.assignTexture(materialParams, "map", metallicRoughness.baseColorTexture, SRGBColorSpace2)); 2413 } 2414 } 2415 return Promise.all(pending); 2416 } 2417}; 2418var GLTFMaterialsEmissiveStrengthExtension = class { 2419 constructor(parser) { 2420 this.parser = parser; 2421 this.name = EXTENSIONS.KHR_MATERIALS_EMISSIVE_STRENGTH; 2422 } 2423 extendMaterialParams(materialIndex, materialParams) { 2424 const parser = this.parser; 2425 const materialDef = parser.json.materials[materialIndex]; 2426 if (!materialDef.extensions || !materialDef.extensions[this.name]) { 2427 return Promise.resolve(); 2428 } 2429 const emissiveStrength = materialDef.extensions[this.name].emissiveStrength; 2430 if (emissiveStrength !== void 0) { 2431 materialParams.emissiveIntensity = emissiveStrength; 2432 } 2433 return Promise.resolve(); 2434 } 2435}; 2436var GLTFMaterialsClearcoatExtension = class { 2437 constructor(parser) { 2438 this.parser = parser; 2439 this.name = EXTENSIONS.KHR_MATERIALS_CLEARCOAT; 2440 } 2441 getMaterialType(materialIndex) { 2442 const parser = this.parser; 2443 const materialDef = parser.json.materials[materialIndex]; 2444 if (!materialDef.extensions || !materialDef.extensions[this.name]) 2445 return null; 2446 return MeshPhysicalMaterial; 2447 } 2448 extendMaterialParams(materialIndex, materialParams) { 2449 const parser = this.parser; 2450 const materialDef = parser.json.materials[materialIndex]; 2451 if (!materialDef.extensions || !materialDef.extensions[this.name]) { 2452 return Promise.resolve(); 2453 } 2454 const pending = []; 2455 const extension = materialDef.extensions[this.name]; 2456 if (extension.clearcoatFactor !== void 0) { 2457 materialParams.clearcoat = extension.clearcoatFactor; 2458 } 2459 if (extension.clearcoatTexture !== void 0) { 2460 pending.push(parser.assignTexture(materialParams, "clearcoatMap", extension.clearcoatTexture)); 2461 } 2462 if (extension.clearcoatRoughnessFactor !== void 0) { 2463 materialParams.clearcoatRoughness = extension.clearcoatRoughnessFactor; 2464 } 2465 if (extension.clearcoatRoughnessTexture !== void 0) { 2466 pending.push(parser.assignTexture(materialParams, "clearcoatRoughnessMap", extension.clearcoatRoughnessTexture)); 2467 } 2468 if (extension.clearcoatNormalTexture !== void 0) { 2469 pending.push(parser.assignTexture(materialParams, "clearcoatNormalMap", extension.clearcoatNormalTexture)); 2470 if (extension.clearcoatNormalTexture.scale !== void 0) { 2471 const scale = extension.clearcoatNormalTexture.scale; 2472 materialParams.clearcoatNormalScale = new Vector2(scale, scale); 2473 } 2474 } 2475 return Promise.all(pending); 2476 } 2477}; 2478var GLTFMaterialsDispersionExtension = class { 2479 constructor(parser) { 2480 this.parser = parser; 2481 this.name = EXTENSIONS.KHR_MATERIALS_DISPERSION; 2482 } 2483 getMaterialType(materialIndex) { 2484 const parser = this.parser; 2485 const materialDef = parser.json.materials[materialIndex]; 2486 if (!materialDef.extensions || !materialDef.extensions[this.name]) 2487 return null; 2488 return MeshPhysicalMaterial; 2489 } 2490 extendMaterialParams(materialIndex, materialParams) { 2491 const parser = this.parser; 2492 const materialDef = parser.json.materials[materialIndex]; 2493 if (!materialDef.extensions || !materialDef.extensions[this.name]) { 2494 return Promise.resolve(); 2495 } 2496 const extension = materialDef.extensions[this.name]; 2497 materialParams.dispersion = extension.dispersion !== void 0 ? extension.dispersion : 0; 2498 return Promise.resolve(); 2499 } 2500}; 2501var GLTFMaterialsIridescenceExtension = class { 2502 constructor(parser) { 2503 this.parser = parser; 2504 this.name = EXTENSIONS.KHR_MATERIALS_IRIDESCENCE; 2505 } 2506 getMaterialType(materialIndex) { 2507 const parser = this.parser; 2508 const materialDef = parser.json.materials[materialIndex]; 2509 if (!materialDef.extensions || !materialDef.extensions[this.name]) 2510 return null; 2511 return MeshPhysicalMaterial; 2512 } 2513 extendMaterialParams(materialIndex, materialParams) { 2514 const parser = this.parser; 2515 const materialDef = parser.json.materials[materialIndex]; 2516 if (!materialDef.extensions || !materialDef.extensions[this.name]) { 2517 return Promise.resolve(); 2518 } 2519 const pending = []; 2520 const extension = materialDef.extensions[this.name]; 2521 if (extension.iridescenceFactor !== void 0) { 2522 materialParams.iridescence = extension.iridescenceFactor; 2523 } 2524 if (extension.iridescenceTexture !== void 0) { 2525 pending.push(parser.assignTexture(materialParams, "iridescenceMap", extension.iridescenceTexture)); 2526 } 2527 if (extension.iridescenceIor !== void 0) { 2528 materialParams.iridescenceIOR = extension.iridescenceIor; 2529 } 2530 if (materialParams.iridescenceThicknessRange === void 0) { 2531 materialParams.iridescenceThicknessRange = [100, 400]; 2532 } 2533 if (extension.iridescenceThicknessMinimum !== void 0) { 2534 materialParams.iridescenceThicknessRange[0] = extension.iridescenceThicknessMinimum; 2535 } 2536 if (extension.iridescenceThicknessMaximum !== void 0) { 2537 materialParams.iridescenceThicknessRange[1] = extension.iridescenceThicknessMaximum; 2538 } 2539 if (extension.iridescenceThicknessTexture !== void 0) { 2540 pending.push( 2541 parser.assignTexture(materialParams, "iridescenceThicknessMap", extension.iridescenceThicknessTexture) 2542 ); 2543 } 2544 return Promise.all(pending); 2545 } 2546}; 2547var GLTFMaterialsSheenExtension = class { 2548 constructor(parser) { 2549 this.parser = parser; 2550 this.name = EXTENSIONS.KHR_MATERIALS_SHEEN; 2551 } 2552 getMaterialType(materialIndex) { 2553 const parser = this.parser; 2554 const materialDef = parser.json.materials[materialIndex]; 2555 if (!materialDef.extensions || !materialDef.extensions[this.name]) 2556 return null; 2557 return MeshPhysicalMaterial; 2558 } 2559 extendMaterialParams(materialIndex, materialParams) { 2560 const parser = this.parser; 2561 const materialDef = parser.json.materials[materialIndex]; 2562 if (!materialDef.extensions || !materialDef.extensions[this.name]) { 2563 return Promise.resolve(); 2564 } 2565 const pending = []; 2566 materialParams.sheenColor = new Color(0, 0, 0); 2567 materialParams.sheenRoughness = 0; 2568 materialParams.sheen = 1; 2569 const extension = materialDef.extensions[this.name]; 2570 if (extension.sheenColorFactor !== void 0) { 2571 const colorFactor = extension.sheenColorFactor; 2572 materialParams.sheenColor.setRGB(colorFactor[0], colorFactor[1], colorFactor[2], LinearSRGBColorSpace2); 2573 } 2574 if (extension.sheenRoughnessFactor !== void 0) { 2575 materialParams.sheenRoughness = extension.sheenRoughnessFactor; 2576 } 2577 if (extension.sheenColorTexture !== void 0) { 2578 pending.push(parser.assignTexture(materialParams, "sheenColorMap", extension.sheenColorTexture, SRGBColorSpace2)); 2579 } 2580 if (extension.sheenRoughnessTexture !== void 0) { 2581 pending.push(parser.assignTexture(materialParams, "sheenRoughnessMap", extension.sheenRoughnessTexture)); 2582 } 2583 return Promise.all(pending); 2584 } 2585}; 2586var GLTFMaterialsTransmissionExtension = class { 2587 constructor(parser) { 2588 this.parser = parser; 2589 this.name = EXTENSIONS.KHR_MATERIALS_TRANSMISSION; 2590 } 2591 getMaterialType(materialIndex) { 2592 const parser = this.parser; 2593 const materialDef = parser.json.materials[materialIndex]; 2594 if (!materialDef.extensions || !materialDef.extensions[this.name]) 2595 return null; 2596 return MeshPhysicalMaterial; 2597 } 2598 extendMaterialParams(materialIndex, materialParams) { 2599 const parser = this.parser; 2600 const materialDef = parser.json.materials[materialIndex]; 2601 if (!materialDef.extensions || !materialDef.extensions[this.name]) { 2602 return Promise.resolve(); 2603 } 2604 const pending = []; 2605 const extension = materialDef.extensions[this.name]; 2606 if (extension.transmissionFactor !== void 0) { 2607 materialParams.transmission = extension.transmissionFactor; 2608 } 2609 if (extension.transmissionTexture !== void 0) { 2610 pending.push(parser.assignTexture(materialParams, "transmissionMap", extension.transmissionTexture)); 2611 } 2612 return Promise.all(pending); 2613 } 2614}; 2615var GLTFMaterialsVolumeExtension = class { 2616 constructor(parser) { 2617 this.parser = parser; 2618 this.name = EXTENSIONS.KHR_MATERIALS_VOLUME; 2619 } 2620 getMaterialType(materialIndex) { 2621 const parser = this.parser; 2622 const materialDef = parser.json.materials[materialIndex]; 2623 if (!materialDef.extensions || !materialDef.extensions[this.name]) 2624 return null; 2625 return MeshPhysicalMaterial; 2626 } 2627 extendMaterialParams(materialIndex, materialParams) { 2628 const parser = this.parser; 2629 const materialDef = parser.json.materials[materialIndex]; 2630 if (!materialDef.extensions || !materialDef.extensions[this.name]) { 2631 return Promise.resolve(); 2632 } 2633 const pending = []; 2634 const extension = materialDef.extensions[this.name]; 2635 materialParams.thickness = extension.thicknessFactor !== void 0 ? extension.thicknessFactor : 0; 2636 if (extension.thicknessTexture !== void 0) { 2637 pending.push(parser.assignTexture(materialParams, "thicknessMap", extension.thicknessTexture)); 2638 } 2639 materialParams.attenuationDistance = extension.attenuationDistance || Infinity; 2640 const colorArray = extension.attenuationColor || [1, 1, 1]; 2641 materialParams.attenuationColor = new Color().setRGB( 2642 colorArray[0], 2643 colorArray[1], 2644 colorArray[2], 2645 LinearSRGBColorSpace2 2646 ); 2647 return Promise.all(pending); 2648 } 2649}; 2650var GLTFMaterialsIorExtension = class { 2651 constructor(parser) { 2652 this.parser = parser; 2653 this.name = EXTENSIONS.KHR_MATERIALS_IOR; 2654 } 2655 getMaterialType(materialIndex) { 2656 const parser = this.parser; 2657 const materialDef = parser.json.materials[materialIndex]; 2658 if (!materialDef.extensions || !materialDef.extensions[this.name]) 2659 return null; 2660 return MeshPhysicalMaterial; 2661 } 2662 extendMaterialParams(materialIndex, materialParams) { 2663 const parser = this.parser; 2664 const materialDef = parser.json.materials[materialIndex]; 2665 if (!materialDef.extensions || !materialDef.extensions[this.name]) { 2666 return Promise.resolve(); 2667 } 2668 const extension = materialDef.extensions[this.name]; 2669 materialParams.ior = extension.ior !== void 0 ? extension.ior : 1.5; 2670 return Promise.resolve(); 2671 } 2672}; 2673var GLTFMaterialsSpecularExtension = class { 2674 constructor(parser) { 2675 this.parser = parser; 2676 this.name = EXTENSIONS.KHR_MATERIALS_SPECULAR; 2677 } 2678 getMaterialType(materialIndex) { 2679 const parser = this.parser; 2680 const materialDef = parser.json.materials[materialIndex]; 2681 if (!materialDef.extensions || !materialDef.extensions[this.name]) 2682 return null; 2683 return MeshPhysicalMaterial; 2684 } 2685 extendMaterialParams(materialIndex, materialParams) { 2686 const parser = this.parser; 2687 const materialDef = parser.json.materials[materialIndex]; 2688 if (!materialDef.extensions || !materialDef.extensions[this.name]) { 2689 return Promise.resolve(); 2690 } 2691 const pending = []; 2692 const extension = materialDef.extensions[this.name]; 2693 materialParams.specularIntensity = extension.specularFactor !== void 0 ? extension.specularFactor : 1; 2694 if (extension.specularTexture !== void 0) { 2695 pending.push(parser.assignTexture(materialParams, "specularIntensityMap", extension.specularTexture)); 2696 } 2697 const colorArray = extension.specularColorFactor || [1, 1, 1]; 2698 materialParams.specularColor = new Color().setRGB(colorArray[0], colorArray[1], colorArray[2], LinearSRGBColorSpace2); 2699 if (extension.specularColorTexture !== void 0) { 2700 pending.push( 2701 parser.assignTexture(materialParams, "specularColorMap", extension.specularColorTexture, SRGBColorSpace2) 2702 ); 2703 } 2704 return Promise.all(pending); 2705 } 2706}; 2707var GLTFMaterialsBumpExtension = class { 2708 constructor(parser) { 2709 this.parser = parser; 2710 this.name = EXTENSIONS.EXT_MATERIALS_BUMP; 2711 } 2712 getMaterialType(materialIndex) { 2713 const parser = this.parser; 2714 const materialDef = parser.json.materials[materialIndex]; 2715 if (!materialDef.extensions || !materialDef.extensions[this.name]) 2716 return null; 2717 return MeshPhysicalMaterial; 2718 } 2719 extendMaterialParams(materialIndex, materialParams) { 2720 const parser = this.parser; 2721 const materialDef = parser.json.materials[materialIndex]; 2722 if (!materialDef.extensions || !materialDef.extensions[this.name]) { 2723 return Promise.resolve(); 2724 } 2725 const pending = []; 2726 const extension = materialDef.extensions[this.name]; 2727 materialParams.bumpScale = extension.bumpFactor !== void 0 ? extension.bumpFactor : 1; 2728 if (extension.bumpTexture !== void 0) { 2729 pending.push(parser.assignTexture(materialParams, "bumpMap", extension.bumpTexture)); 2730 } 2731 return Promise.all(pending); 2732 } 2733}; 2734var GLTFMaterialsAnisotropyExtension = class { 2735 constructor(parser) { 2736 this.parser = parser; 2737 this.name = EXTENSIONS.KHR_MATERIALS_ANISOTROPY; 2738 } 2739 getMaterialType(materialIndex) { 2740 const parser = this.parser; 2741 const materialDef = parser.json.materials[materialIndex]; 2742 if (!materialDef.extensions || !materialDef.extensions[this.name]) 2743 return null; 2744 return MeshPhysicalMaterial; 2745 } 2746 extendMaterialParams(materialIndex, materialParams) { 2747 const parser = this.parser; 2748 const materialDef = parser.json.materials[materialIndex]; 2749 if (!materialDef.extensions || !materialDef.extensions[this.name]) { 2750 return Promise.resolve(); 2751 } 2752 const pending = []; 2753 const extension = materialDef.extensions[this.name]; 2754 if (extension.anisotropyStrength !== void 0) { 2755 materialParams.anisotropy = extension.anisotropyStrength; 2756 } 2757 if (extension.anisotropyRotation !== void 0) { 2758 materialParams.anisotropyRotation = extension.anisotropyRotation; 2759 } 2760 if (extension.anisotropyTexture !== void 0) { 2761 pending.push(parser.assignTexture(materialParams, "anisotropyMap", extension.anisotropyTexture)); 2762 } 2763 return Promise.all(pending); 2764 } 2765}; 2766var GLTFTextureBasisUExtension = class { 2767 constructor(parser) { 2768 this.parser = parser; 2769 this.name = EXTENSIONS.KHR_TEXTURE_BASISU; 2770 } 2771 loadTexture(textureIndex) { 2772 const parser = this.parser; 2773 const json = parser.json; 2774 const textureDef = json.textures[textureIndex]; 2775 if (!textureDef.extensions || !textureDef.extensions[this.name]) { 2776 return null; 2777 } 2778 const extension = textureDef.extensions[this.name]; 2779 const loader = parser.options.ktx2Loader; 2780 if (!loader) { 2781 if (json.extensionsRequired && json.extensionsRequired.indexOf(this.name) >= 0) { 2782 throw new Error("THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures"); 2783 } else { 2784 return null; 2785 } 2786 } 2787 return parser.loadTextureImage(textureIndex, extension.source, loader); 2788 } 2789}; 2790var GLTFTextureWebPExtension = class { 2791 constructor(parser) { 2792 this.parser = parser; 2793 this.name = EXTENSIONS.EXT_TEXTURE_WEBP; 2794 this.isSupported = null; 2795 } 2796 loadTexture(textureIndex) { 2797 const name = this.name; 2798 const parser = this.parser; 2799 const json = parser.json; 2800 const textureDef = json.textures[textureIndex]; 2801 if (!textureDef.extensions || !textureDef.extensions[name]) { 2802 return null; 2803 } 2804 const extension = textureDef.extensions[name]; 2805 const source = json.images[extension.source]; 2806 let loader = parser.textureLoader; 2807 if (source.uri) { 2808 const handler = parser.options.manager.getHandler(source.uri); 2809 if (handler !== null) 2810 loader = handler; 2811 } 2812 return this.detectSupport().then(function(isSupported) { 2813 if (isSupported) 2814 return parser.loadTextureImage(textureIndex, extension.source, loader); 2815 if (json.extensionsRequired && json.extensionsRequired.indexOf(name) >= 0) { 2816 throw new Error("THREE.GLTFLoader: WebP required by asset but unsupported."); 2817 } 2818 return parser.loadTexture(textureIndex); 2819 }); 2820 } 2821 detectSupport() { 2822 if (!this.isSupported) { 2823 this.isSupported = new Promise(function(resolve3) { 2824 const image = new Image(); 2825 image.src = "data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA"; 2826 image.onload = image.onerror = function() { 2827 resolve3(image.height === 1); 2828 }; 2829 }); 2830 } 2831 return this.isSupported; 2832 } 2833}; 2834var GLTFTextureAVIFExtension = class { 2835 constructor(parser) { 2836 this.parser = parser; 2837 this.name = EXTENSIONS.EXT_TEXTURE_AVIF; 2838 this.isSupported = null; 2839 } 2840 loadTexture(textureIndex) { 2841 const name = this.name; 2842 const parser = this.parser; 2843 const json = parser.json; 2844 const textureDef = json.textures[textureIndex]; 2845 if (!textureDef.extensions || !textureDef.extensions[name]) { 2846 return null; 2847 } 2848 const extension = textureDef.extensions[name]; 2849 const source = json.images[extension.source]; 2850 let loader = parser.textureLoader; 2851 if (source.uri) { 2852 const handler = parser.options.manager.getHandler(source.uri); 2853 if (handler !== null) 2854 loader = handler; 2855 } 2856 return this.detectSupport().then(function(isSupported) { 2857 if (isSupported) 2858 return parser.loadTextureImage(textureIndex, extension.source, loader); 2859 if (json.extensionsRequired && json.extensionsRequired.indexOf(name) >= 0) { 2860 throw new Error("THREE.GLTFLoader: AVIF required by asset but unsupported."); 2861 } 2862 return parser.loadTexture(textureIndex); 2863 }); 2864 } 2865 detectSupport() { 2866 if (!this.isSupported) { 2867 this.isSupported = new Promise(function(resolve3) { 2868 const image = new Image(); 2869 image.src = "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAABcAAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAEAAAABAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQAMAAAAABNjb2xybmNseAACAAIABoAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAAB9tZGF0EgAKCBgABogQEDQgMgkQAAAAB8dSLfI="; 2870 image.onload = image.onerror = function() { 2871 resolve3(image.height === 1); 2872 }; 2873 }); 2874 } 2875 return this.isSupported; 2876 } 2877}; 2878var GLTFMeshoptCompression = class { 2879 constructor(parser) { 2880 this.name = EXTENSIONS.EXT_MESHOPT_COMPRESSION; 2881 this.parser = parser; 2882 } 2883 loadBufferView(index) { 2884 const json = this.parser.json; 2885 const bufferView = json.bufferViews[index]; 2886 if (bufferView.extensions && bufferView.extensions[this.name]) { 2887 const extensionDef = bufferView.extensions[this.name]; 2888 const buffer = this.parser.getDependency("buffer", extensionDef.buffer); 2889 const decoder = this.parser.options.meshoptDecoder; 2890 if (!decoder || !decoder.supported) { 2891 if (json.extensionsRequired && json.extensionsRequired.indexOf(this.name) >= 0) { 2892 throw new Error("THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files"); 2893 } else { 2894 return null; 2895 } 2896 } 2897 return buffer.then(function(res) { 2898 const byteOffset = extensionDef.byteOffset || 0; 2899 const byteLength = extensionDef.byteLength || 0; 2900 const count = extensionDef.count; 2901 const stride = extensionDef.byteStride; 2902 const source = new Uint8Array(res, byteOffset, byteLength); 2903 if (decoder.decodeGltfBufferAsync) { 2904 return decoder.decodeGltfBufferAsync(count, stride, source, extensionDef.mode, extensionDef.filter).then(function(res2) { 2905 return res2.buffer; 2906 }); 2907 } else { 2908 return decoder.ready.then(function() { 2909 const result = new ArrayBuffer(count * stride); 2910 decoder.decodeGltfBuffer( 2911 new Uint8Array(result), 2912 count, 2913 stride, 2914 source, 2915 extensionDef.mode, 2916 extensionDef.filter 2917 ); 2918 return result; 2919 }); 2920 } 2921 }); 2922 } else { 2923 return null; 2924 } 2925 } 2926}; 2927var GLTFMeshGpuInstancing = class { 2928 constructor(parser) { 2929 this.name = EXTENSIONS.EXT_MESH_GPU_INSTANCING; 2930 this.parser = parser; 2931 } 2932 createNodeMesh(nodeIndex) { 2933 const json = this.parser.json; 2934 const nodeDef = json.nodes[nodeIndex]; 2935 if (!nodeDef.extensions || !nodeDef.extensions[this.name] || nodeDef.mesh === void 0) { 2936 return null; 2937 } 2938 const meshDef = json.meshes[nodeDef.mesh]; 2939 for (const primitive of meshDef.primitives) { 2940 if (primitive.mode !== WEBGL_CONSTANTS.TRIANGLES && primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_STRIP && primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_FAN && primitive.mode !== void 0) { 2941 return null; 2942 } 2943 } 2944 const extensionDef = nodeDef.extensions[this.name]; 2945 const attributesDef = extensionDef.attributes; 2946 const pending = []; 2947 const attributes = {}; 2948 for (const key in attributesDef) { 2949 pending.push( 2950 this.parser.getDependency("accessor", attributesDef[key]).then((accessor) => { 2951 attributes[key] = accessor; 2952 return attributes[key]; 2953 }) 2954 ); 2955 } 2956 if (pending.length < 1) { 2957 return null; 2958 } 2959 pending.push(this.parser.createNodeMesh(nodeIndex)); 2960 return Promise.all(pending).then((results) => { 2961 const nodeObject = results.pop(); 2962 const meshes = nodeObject.isGroup ? nodeObject.children : [nodeObject]; 2963 const count = results[0].count; 2964 const instancedMeshes = []; 2965 for (const mesh of meshes) { 2966 const m = new Matrix4(); 2967 const p = new Vector3(); 2968 const q = new Quaternion(); 2969 const s = new Vector3(1, 1, 1); 2970 const instancedMesh = new InstancedMesh(mesh.geometry, mesh.material, count); 2971 for (let i = 0; i < count; i++) { 2972 if (attributes.TRANSLATION) { 2973 p.fromBufferAttribute(attributes.TRANSLATION, i); 2974 } 2975 if (attributes.ROTATION) { 2976 q.fromBufferAttribute(attributes.ROTATION, i); 2977 } 2978 if (attributes.SCALE) { 2979 s.fromBufferAttribute(attributes.SCALE, i); 2980 } 2981 instancedMesh.setMatrixAt(i, m.compose(p, q, s)); 2982 } 2983 for (const attributeName in attributes) { 2984 if (attributeName === "_COLOR_0") { 2985 const attr = attributes[attributeName]; 2986 instancedMesh.instanceColor = new InstancedBufferAttribute(attr.array, attr.itemSize, attr.normalized); 2987 } else if (attributeName !== "TRANSLATION" && attributeName !== "ROTATION" && attributeName !== "SCALE") { 2988 mesh.geometry.setAttribute(attributeName, attributes[attributeName]); 2989 } 2990 } 2991 Object3D.prototype.copy.call(instancedMesh, mesh); 2992 this.parser.assignFinalMaterial(instancedMesh); 2993 instancedMeshes.push(instancedMesh); 2994 } 2995 if (nodeObject.isGroup) { 2996 nodeObject.clear(); 2997 nodeObject.add(...instancedMeshes); 2998 return nodeObject; 2999 } 3000 return instancedMeshes[0]; 3001 }); 3002 } 3003}; 3004var BINARY_EXTENSION_HEADER_MAGIC = "glTF"; 3005var BINARY_EXTENSION_HEADER_LENGTH = 12; 3006var BINARY_EXTENSION_CHUNK_TYPES = { JSON: 1313821514, BIN: 5130562 }; 3007var GLTFBinaryExtension = class { 3008 constructor(data) { 3009 this.name = EXTENSIONS.KHR_BINARY_GLTF; 3010 this.content = null; 3011 this.body = null; 3012 const headerView = new DataView(data, 0, BINARY_EXTENSION_HEADER_LENGTH); 3013 this.header = { 3014 magic: decodeText(new Uint8Array(data.slice(0, 4))), 3015 version: headerView.getUint32(4, true), 3016 length: headerView.getUint32(8, true) 3017 }; 3018 if (this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC) { 3019 throw new Error("THREE.GLTFLoader: Unsupported glTF-Binary header."); 3020 } else if (this.header.version < 2) { 3021 throw new Error("THREE.GLTFLoader: Legacy binary file detected."); 3022 } 3023 const chunkContentsLength = this.header.length - BINARY_EXTENSION_HEADER_LENGTH; 3024 const chunkView = new DataView(data, BINARY_EXTENSION_HEADER_LENGTH); 3025 let chunkIndex = 0; 3026 while (chunkIndex < chunkContentsLength) { 3027 const chunkLength = chunkView.getUint32(chunkIndex, true); 3028 chunkIndex += 4; 3029 const chunkType = chunkView.getUint32(chunkIndex, true); 3030 chunkIndex += 4; 3031 if (chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON) { 3032 const contentArray = new Uint8Array(data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength); 3033 this.content = decodeText(contentArray); 3034 } else if (chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN) { 3035 const byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex; 3036 this.body = data.slice(byteOffset, byteOffset + chunkLength); 3037 } 3038 chunkIndex += chunkLength; 3039 } 3040 if (this.content === null) { 3041 throw new Error("THREE.GLTFLoader: JSON content not found."); 3042 } 3043 } 3044}; 3045var GLTFDracoMeshCompressionExtension = class { 3046 constructor(json, dracoLoader) { 3047 if (!dracoLoader) { 3048 throw new Error("THREE.GLTFLoader: No DRACOLoader instance provided."); 3049 } 3050 this.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION; 3051 this.json = json; 3052 this.dracoLoader = dracoLoader; 3053 this.dracoLoader.preload(); 3054 } 3055 decodePrimitive(primitive, parser) { 3056 const json = this.json; 3057 const dracoLoader = this.dracoLoader; 3058 const bufferViewIndex = primitive.extensions[this.name].bufferView; 3059 const gltfAttributeMap = primitive.extensions[this.name].attributes; 3060 const threeAttributeMap = {}; 3061 const attributeNormalizedMap = {}; 3062 const attributeTypeMap = {}; 3063 for (const attributeName in gltfAttributeMap) { 3064 const threeAttributeName = ATTRIBUTES[attributeName] || attributeName.toLowerCase(); 3065 threeAttributeMap[threeAttributeName] = gltfAttributeMap[attributeName]; 3066 } 3067 for (const attributeName in primitive.attributes) { 3068 const threeAttributeName = ATTRIBUTES[attributeName] || attributeName.toLowerCase(); 3069 if (gltfAttributeMap[attributeName] !== void 0) { 3070 const accessorDef = json.accessors[primitive.attributes[attributeName]]; 3071 const componentType = WEBGL_COMPONENT_TYPES[accessorDef.componentType]; 3072 attributeTypeMap[threeAttributeName] = componentType.name; 3073 attributeNormalizedMap[threeAttributeName] = accessorDef.normalized === true; 3074 } 3075 } 3076 return parser.getDependency("bufferView", bufferViewIndex).then(function(bufferView) { 3077 return new Promise(function(resolve3, reject) { 3078 dracoLoader.decodeDracoFile( 3079 bufferView, 3080 function(geometry) { 3081 for (const attributeName in geometry.attributes) { 3082 const attribute = geometry.attributes[attributeName]; 3083 const normalized = attributeNormalizedMap[attributeName]; 3084 if (normalized !== void 0) 3085 attribute.normalized = normalized; 3086 } 3087 resolve3(geometry); 3088 }, 3089 threeAttributeMap, 3090 attributeTypeMap, 3091 LinearSRGBColorSpace2, 3092 reject 3093 ); 3094 }); 3095 }); 3096 } 3097}; 3098var GLTFTextureTransformExtension = class { 3099 constructor() { 3100 this.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM; 3101 } 3102 extendTexture(texture, transform) { 3103 if ((transform.texCoord === void 0 || transform.texCoord === texture.channel) && transform.offset === void 0 && transform.rotation === void 0 && transform.scale === void 0) { 3104 return texture; 3105 } 3106 texture = texture.clone(); 3107 if (transform.texCoord !== void 0) { 3108 texture.channel = transform.texCoord; 3109 } 3110 if (transform.offset !== void 0) { 3111 texture.offset.fromArray(transform.offset); 3112 } 3113 if (transform.rotation !== void 0) { 3114 texture.rotation = transform.rotation; 3115 } 3116 if (transform.scale !== void 0) { 3117 texture.repeat.fromArray(transform.scale); 3118 } 3119 texture.needsUpdate = true; 3120 return texture; 3121 } 3122}; 3123var GLTFMeshQuantizationExtension = class { 3124 constructor() { 3125 this.name = EXTENSIONS.KHR_MESH_QUANTIZATION; 3126 } 3127}; 3128var GLTFCubicSplineInterpolant = class extends Interpolant { 3129 constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) { 3130 super(parameterPositions, sampleValues, sampleSize, resultBuffer); 3131 } 3132 copySampleValue_(index) { 3133 const result = this.resultBuffer, values = this.sampleValues, valueSize = this.valueSize, offset = index * valueSize * 3 + valueSize; 3134 for (let i = 0; i !== valueSize; i++) { 3135 result[i] = values[offset + i]; 3136 } 3137 return result; 3138 } 3139 interpolate_(i1, t0, t, t1) { 3140 const result = this.resultBuffer; 3141 const values = this.sampleValues; 3142 const stride = this.valueSize; 3143 const stride2 = stride * 2; 3144 const stride3 = stride * 3; 3145 const td = t1 - t0; 3146 const p = (t - t0) / td; 3147 const pp = p * p; 3148 const ppp = pp * p; 3149 const offset1 = i1 * stride3; 3150 const offset0 = offset1 - stride3; 3151 const s2 = -2 * ppp + 3 * pp; 3152 const s3 = ppp - pp; 3153 const s0 = 1 - s2; 3154 const s1 = s3 - pp + p; 3155 for (let i = 0; i !== stride; i++) { 3156 const p0 = values[offset0 + i + stride]; 3157 const m0 = values[offset0 + i + stride2] * td; 3158 const p1 = values[offset1 + i + stride]; 3159 const m1 = values[offset1 + i] * td; 3160 result[i] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1; 3161 } 3162 return result; 3163 } 3164}; 3165var _q = /* @__PURE__ */ new Quaternion(); 3166var GLTFCubicSplineQuaternionInterpolant = class extends GLTFCubicSplineInterpolant { 3167 interpolate_(i1, t0, t, t1) { 3168 const result = super.interpolate_(i1, t0, t, t1); 3169 _q.fromArray(result).normalize().toArray(result); 3170 return result; 3171 } 3172}; 3173var WEBGL_CONSTANTS = { 3174 FLOAT: 5126, 3175 //FLOAT_MAT2: 35674, 3176 FLOAT_MAT3: 35675, 3177 FLOAT_MAT4: 35676, 3178 FLOAT_VEC2: 35664, 3179 FLOAT_VEC3: 35665, 3180 FLOAT_VEC4: 35666, 3181 LINEAR: 9729, 3182 REPEAT: 10497, 3183 SAMPLER_2D: 35678, 3184 POINTS: 0, 3185 LINES: 1, 3186 LINE_LOOP: 2, 3187 LINE_STRIP: 3, 3188 TRIANGLES: 4, 3189 TRIANGLE_STRIP: 5, 3190 TRIANGLE_FAN: 6, 3191 UNSIGNED_BYTE: 5121, 3192 UNSIGNED_SHORT: 5123 3193}; 3194var WEBGL_COMPONENT_TYPES = { 3195 5120: Int8Array, 3196 5121: Uint8Array, 3197 5122: Int16Array, 3198 5123: Uint16Array, 3199 5125: Uint32Array, 3200 5126: Float32Array 3201}; 3202var WEBGL_FILTERS = { 3203 9728: NearestFilter, 3204 9729: LinearFilter, 3205 9984: NearestMipmapNearestFilter, 3206 9985: LinearMipmapNearestFilter, 3207 9986: NearestMipmapLinearFilter, 3208 9987: LinearMipmapLinearFilter 3209}; 3210var WEBGL_WRAPPINGS = { 3211 33071: ClampToEdgeWrapping, 3212 33648: MirroredRepeatWrapping, 3213 10497: RepeatWrapping 3214}; 3215var WEBGL_TYPE_SIZES = { 3216 SCALAR: 1, 3217 VEC2: 2, 3218 VEC3: 3, 3219 VEC4: 4, 3220 MAT2: 4, 3221 MAT3: 9, 3222 MAT4: 16 3223}; 3224var ATTRIBUTES = { 3225 POSITION: "position", 3226 NORMAL: "normal", 3227 TANGENT: "tangent", 3228 // uv => uv1, 4 uv channels 3229 // https://github.com/mrdoob/three.js/pull/25943 3230 // https://github.com/mrdoob/three.js/pull/25788 3231 ...version >= 152 ? { 3232 TEXCOORD_0: "uv", 3233 TEXCOORD_1: "uv1", 3234 TEXCOORD_2: "uv2", 3235 TEXCOORD_3: "uv3" 3236 } : { 3237 TEXCOORD_0: "uv", 3238 TEXCOORD_1: "uv2" 3239 }, 3240 COLOR_0: "color", 3241 WEIGHTS_0: "skinWeight", 3242 JOINTS_0: "skinIndex" 3243}; 3244var PATH_PROPERTIES = { 3245 scale: "scale", 3246 translation: "position", 3247 rotation: "quaternion", 3248 weights: "morphTargetInfluences" 3249}; 3250var INTERPOLATION = { 3251 CUBICSPLINE: void 0, 3252 // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each 3253 // keyframe track will be initialized with a default interpolation type, then modified. 3254 LINEAR: InterpolateLinear, 3255 STEP: InterpolateDiscrete 3256}; 3257var ALPHA_MODES = { 3258 OPAQUE: "OPAQUE", 3259 MASK: "MASK", 3260 BLEND: "BLEND" 3261}; 3262function createDefaultMaterial(cache) { 3263 if (cache["DefaultMaterial"] === void 0) { 3264 cache["DefaultMaterial"] = new MeshStandardMaterial({ 3265 color: 16777215, 3266 emissive: 0, 3267 metalness: 1, 3268 roughness: 1, 3269 transparent: false, 3270 depthTest: true, 3271 side: FrontSide 3272 }); 3273 } 3274 return cache["DefaultMaterial"]; 3275} 3276function addUnknownExtensionsToUserData(knownExtensions, object, objectDef) { 3277 for (const name in objectDef.extensions) { 3278 if (knownExtensions[name] === void 0) { 3279 object.userData.gltfExtensions = object.userData.gltfExtensions || {}; 3280 object.userData.gltfExtensions[name] = objectDef.extensions[name]; 3281 } 3282 } 3283} 3284function assignExtrasToUserData(object, gltfDef) { 3285 if (gltfDef.extras !== void 0) { 3286 if (typeof gltfDef.extras === "object") { 3287 Object.assign(object.userData, gltfDef.extras); 3288 } else { 3289 console.warn("THREE.GLTFLoader: Ignoring primitive type .extras, " + gltfDef.extras); 3290 } 3291 } 3292} 3293function addMorphTargets(geometry, targets, parser) { 3294 let hasMorphPosition = false; 3295 let hasMorphNormal = false; 3296 let hasMorphColor = false; 3297 for (let i = 0, il = targets.length; i < il; i++) { 3298 const target = targets[i]; 3299 if (target.POSITION !== void 0) 3300 hasMorphPosition = true; 3301 if (target.NORMAL !== void 0) 3302 hasMorphNormal = true; 3303 if (target.COLOR_0 !== void 0) 3304 hasMorphColor = true; 3305 if (hasMorphPosition && hasMorphNormal && hasMorphColor) 3306 break; 3307 } 3308 if (!hasMorphPosition && !hasMorphNormal && !hasMorphColor) 3309 return Promise.resolve(geometry); 3310 const pendingPositionAccessors = []; 3311 const pendingNormalAccessors = []; 3312 const pendingColorAccessors = []; 3313 for (let i = 0, il = targets.length; i < il; i++) { 3314 const target = targets[i]; 3315 if (hasMorphPosition) { 3316 const pendingAccessor = target.POSITION !== void 0 ? parser.getDependency("accessor", target.POSITION) : geometry.attributes.position; 3317 pendingPositionAccessors.push(pendingAccessor); 3318 } 3319 if (hasMorphNormal) { 3320 const pendingAccessor = target.NORMAL !== void 0 ? parser.getDependency("accessor", target.NORMAL) : geometry.attributes.normal; 3321 pendingNormalAccessors.push(pendingAccessor); 3322 } 3323 if (hasMorphColor) { 3324 const pendingAccessor = target.COLOR_0 !== void 0 ? parser.getDependency("accessor", target.COLOR_0) : geometry.attributes.color; 3325 pendingColorAccessors.push(pendingAccessor); 3326 } 3327 } 3328 return Promise.all([ 3329 Promise.all(pendingPositionAccessors), 3330 Promise.all(pendingNormalAccessors), 3331 Promise.all(pendingColorAccessors) 3332 ]).then(function(accessors) { 3333 const morphPositions = accessors[0]; 3334 const morphNormals = accessors[1]; 3335 const morphColors = accessors[2]; 3336 if (hasMorphPosition) 3337 geometry.morphAttributes.position = morphPositions; 3338 if (hasMorphNormal) 3339 geometry.morphAttributes.normal = morphNormals; 3340 if (hasMorphColor) 3341 geometry.morphAttributes.color = morphColors; 3342 geometry.morphTargetsRelative = true; 3343 return geometry; 3344 }); 3345} 3346function updateMorphTargets(mesh, meshDef) { 3347 mesh.updateMorphTargets(); 3348 if (meshDef.weights !== void 0) { 3349 for (let i = 0, il = meshDef.weights.length; i < il; i++) { 3350 mesh.morphTargetInfluences[i] = meshDef.weights[i]; 3351 } 3352 } 3353 if (meshDef.extras && Array.isArray(meshDef.extras.targetNames)) { 3354 const targetNames = meshDef.extras.targetNames; 3355 if (mesh.morphTargetInfluences.length === targetNames.length) { 3356 mesh.morphTargetDictionary = {}; 3357 for (let i = 0, il = targetNames.length; i < il; i++) { 3358 mesh.morphTargetDictionary[targetNames[i]] = i; 3359 } 3360 } else { 3361 console.warn("THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names."); 3362 } 3363 } 3364} 3365function createPrimitiveKey(primitiveDef) { 3366 let geometryKey; 3367 const dracoExtension = primitiveDef.extensions && primitiveDef.extensions[EXTENSIONS.KHR_DRACO_MESH_COMPRESSION]; 3368 if (dracoExtension) { 3369 geometryKey = "draco:" + dracoExtension.bufferView + ":" + dracoExtension.indices + ":" + createAttributesKey(dracoExtension.attributes); 3370 } else { 3371 geometryKey = primitiveDef.indices + ":" + createAttributesKey(primitiveDef.attributes) + ":" + primitiveDef.mode; 3372 } 3373 if (primitiveDef.targets !== void 0) { 3374 for (let i = 0, il = primitiveDef.targets.length; i < il; i++) { 3375 geometryKey += ":" + createAttributesKey(primitiveDef.targets[i]); 3376 } 3377 } 3378 return geometryKey; 3379} 3380function createAttributesKey(attributes) { 3381 let attributesKey = ""; 3382 const keys2 = Object.keys(attributes).sort(); 3383 for (let i = 0, il = keys2.length; i < il; i++) { 3384 attributesKey += keys2[i] + ":" + attributes[keys2[i]] + ";"; 3385 } 3386 return attributesKey; 3387} 3388function getNormalizedComponentScale(constructor) { 3389 switch (constructor) { 3390 case Int8Array: 3391 return 1 / 127; 3392 case Uint8Array: 3393 return 1 / 255; 3394 case Int16Array: 3395 return 1 / 32767; 3396 case Uint16Array: 3397 return 1 / 65535; 3398 default: 3399 throw new Error("THREE.GLTFLoader: Unsupported normalized accessor component type."); 3400 } 3401} 3402function getImageURIMimeType(uri) { 3403 if (uri.search(/\.jpe?g($|\?)/i) > 0 || uri.search(/^data\:image\/jpeg/) === 0) 3404 return "image/jpeg"; 3405 if (uri.search(/\.webp($|\?)/i) > 0 || uri.search(/^data\:image\/webp/) === 0) 3406 return "image/webp"; 3407 return "image/png"; 3408} 3409var _identityMatrix = /* @__PURE__ */ new Matrix4(); 3410var GLTFParser = class { 3411 constructor(json = {}, options = {}) { 3412 this.json = json; 3413 this.extensions = {}; 3414 this.plugins = {}; 3415 this.options = options; 3416 this.cache = new GLTFRegistry(); 3417 this.associations = /* @__PURE__ */ new Map(); 3418 this.primitiveCache = {}; 3419 this.nodeCache = {}; 3420 this.meshCache = { refs: {}, uses: {} }; 3421 this.cameraCache = { refs: {}, uses: {} }; 3422 this.lightCache = { refs: {}, uses: {} }; 3423 this.sourceCache = {}; 3424 this.textureCache = {}; 3425 this.nodeNamesUsed = {}; 3426 let isSafari = false; 3427 let isFirefox = false; 3428 let firefoxVersion = -1; 3429 if (typeof navigator !== "undefined" && typeof navigator.userAgent !== "undefined") { 3430 isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent) === true; 3431 isFirefox = navigator.userAgent.indexOf("Firefox") > -1; 3432 firefoxVersion = isFirefox ? navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1] : -1; 3433 } 3434 if (typeof createImageBitmap === "undefined" || isSafari || isFirefox && firefoxVersion < 98) { 3435 this.textureLoader = new TextureLoader(this.options.manager); 3436 } else { 3437 this.textureLoader = new ImageBitmapLoader(this.options.manager); 3438 } 3439 this.textureLoader.setCrossOrigin(this.options.crossOrigin); 3440 this.textureLoader.setRequestHeader(this.options.requestHeader); 3441 this.fileLoader = new FileLoader(this.options.manager); 3442 this.fileLoader.setResponseType("arraybuffer"); 3443 if (this.options.crossOrigin === "use-credentials") { 3444 this.fileLoader.setWithCredentials(true); 3445 } 3446 } 3447 setExtensions(extensions) { 3448 this.extensions = extensions; 3449 } 3450 setPlugins(plugins) { 3451 this.plugins = plugins; 3452 } 3453 parse(onLoad, onError) { 3454 const parser = this; 3455 const json = this.json; 3456 const extensions = this.extensions; 3457 this.cache.removeAll(); 3458 this.nodeCache = {}; 3459 this._invokeAll(function(ext) { 3460 return ext._markDefs && ext._markDefs(); 3461 }); 3462 Promise.all( 3463 this._invokeAll(function(ext) { 3464 return ext.beforeRoot && ext.beforeRoot(); 3465 }) 3466 ).then(function() { 3467 return Promise.all([ 3468 parser.getDependencies("scene"), 3469 parser.getDependencies("animation"), 3470 parser.getDependencies("camera") 3471 ]); 3472 }).then(function(dependencies) { 3473 const result = { 3474 scene: dependencies[0][json.scene || 0], 3475 scenes: dependencies[0], 3476 animations: dependencies[1], 3477 cameras: dependencies[2], 3478 asset: json.asset, 3479 parser, 3480 userData: {} 3481 }; 3482 addUnknownExtensionsToUserData(extensions, result, json); 3483 assignExtrasToUserData(result, json); 3484 return Promise.all( 3485 parser._invokeAll(function(ext) { 3486 return ext.afterRoot && ext.afterRoot(result); 3487 }) 3488 ).then(function() { 3489 for (const scene of result.scenes) { 3490 scene.updateMatrixWorld(); 3491 } 3492 onLoad(result); 3493 }); 3494 }).catch(onError); 3495 } 3496 /** 3497 * Marks the special nodes/meshes in json for efficient parse. 3498 */ 3499 _markDefs() { 3500 const nodeDefs = this.json.nodes || []; 3501 const skinDefs = this.json.skins || []; 3502 const meshDefs = this.json.meshes || []; 3503 for (let skinIndex = 0, skinLength = skinDefs.length; skinIndex < skinLength; skinIndex++) { 3504 const joints = skinDefs[skinIndex].joints; 3505 for (let i = 0, il = joints.length; i < il; i++) { 3506 nodeDefs[joints[i]].isBone = true; 3507 } 3508 } 3509 for (let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex++) { 3510 const nodeDef = nodeDefs[nodeIndex]; 3511 if (nodeDef.mesh !== void 0) { 3512 this._addNodeRef(this.meshCache, nodeDef.mesh); 3513 if (nodeDef.skin !== void 0) { 3514 meshDefs[nodeDef.mesh].isSkinnedMesh = true; 3515 } 3516 } 3517 if (nodeDef.camera !== void 0) { 3518 this._addNodeRef(this.cameraCache, nodeDef.camera); 3519 } 3520 } 3521 } 3522 /** 3523 * Counts references to shared node / Object3D resources. These resources 3524 * can be reused, or "instantiated", at multiple nodes in the scene 3525 * hierarchy. Mesh, Camera, and Light instances are instantiated and must 3526 * be marked. Non-scenegraph resources (like Materials, Geometries, and 3527 * Textures) can be reused directly and are not marked here. 3528 * 3529 * Example: CesiumMilkTruck sample model reuses "Wheel" meshes. 3530 */ 3531 _addNodeRef(cache, index) { 3532 if (index === void 0) 3533 return; 3534 if (cache.refs[index] === void 0) { 3535 cache.refs[index] = cache.uses[index] = 0; 3536 } 3537 cache.refs[index]++; 3538 } 3539 /** Returns a reference to a shared resource, cloning it if necessary. */ 3540 _getNodeRef(cache, index, object) { 3541 if (cache.refs[index] <= 1) 3542 return object; 3543 const ref = object.clone(); 3544 const updateMappings = (original, clone) => { 3545 const mappings = this.associations.get(original); 3546 if (mappings != null) { 3547 this.associations.set(clone, mappings); 3548 } 3549 for (const [i, child] of original.children.entries()) { 3550 updateMappings(child, clone.children[i]); 3551 } 3552 }; 3553 updateMappings(object, ref); 3554 ref.name += "_instance_" + cache.uses[index]++; 3555 return ref; 3556 } 3557 _invokeOne(func) { 3558 const extensions = Object.values(this.plugins); 3559 extensions.push(this); 3560 for (let i = 0; i < extensions.length; i++) { 3561 const result = func(extensions[i]); 3562 if (result) 3563 return result; 3564 } 3565 return null; 3566 } 3567 _invokeAll(func) { 3568 const extensions = Object.values(this.plugins); 3569 extensions.unshift(this); 3570 const pending = []; 3571 for (let i = 0; i < extensions.length; i++) { 3572 const result = func(extensions[i]); 3573 if (result) 3574 pending.push(result); 3575 } 3576 return pending; 3577 } 3578 /** 3579 * Requests the specified dependency asynchronously, with caching. 3580 * @param {string} type 3581 * @param {number} index 3582 * @return {Promise<Object3D|Material|THREE.Texture|AnimationClip|ArrayBuffer|Object>} 3583 */ 3584 getDependency(type, index) { 3585 const cacheKey = type + ":" + index; 3586 let dependency = this.cache.get(cacheKey); 3587 if (!dependency) { 3588 switch (type) { 3589 case "scene": 3590 dependency = this.loadScene(index); 3591 break; 3592 case "node": 3593 dependency = this._invokeOne(function(ext) { 3594 return ext.loadNode && ext.loadNode(index); 3595 }); 3596 break; 3597 case "mesh": 3598 dependency = this._invokeOne(function(ext) { 3599 return ext.loadMesh && ext.loadMesh(index); 3600 }); 3601 break; 3602 case "accessor": 3603 dependency = this.loadAccessor(index); 3604 break; 3605 case "bufferView": 3606 dependency = this._invokeOne(function(ext) { 3607 return ext.loadBufferView && ext.loadBufferView(index); 3608 }); 3609 break; 3610 case "buffer": 3611 dependency = this.loadBuffer(index); 3612 break; 3613 case "material": 3614 dependency = this._invokeOne(function(ext) { 3615 return ext.loadMaterial && ext.loadMaterial(index); 3616 }); 3617 break; 3618 case "texture": 3619 dependency = this._invokeOne(function(ext) { 3620 return ext.loadTexture && ext.loadTexture(index); 3621 }); 3622 break; 3623 case "skin": 3624 dependency = this.loadSkin(index); 3625 break; 3626 case "animation": 3627 dependency = this._invokeOne(function(ext) { 3628 return ext.loadAnimation && ext.loadAnimation(index); 3629 }); 3630 break; 3631 case "camera": 3632 dependency = this.loadCamera(index); 3633 break; 3634 default: 3635 dependency = this._invokeOne(function(ext) { 3636 return ext != this && ext.getDependency && ext.getDependency(type, index); 3637 }); 3638 if (!dependency) { 3639 throw new Error("Unknown type: " + type); 3640 } 3641 break; 3642 } 3643 this.cache.add(cacheKey, dependency); 3644 } 3645 return dependency; 3646 } 3647 /** 3648 * Requests all dependencies of the specified type asynchronously, with caching. 3649 * @param {string} type 3650 * @return {Promise<Array<Object>>} 3651 */ 3652 getDependencies(type) { 3653 let dependencies = this.cache.get(type); 3654 if (!dependencies) { 3655 const parser = this; 3656 const defs = this.json[type + (type === "mesh" ? "es" : "s")] || []; 3657 dependencies = Promise.all( 3658 defs.map(function(def, index) { 3659 return parser.getDependency(type, index); 3660 }) 3661 ); 3662 this.cache.add(type, dependencies); 3663 } 3664 return dependencies; 3665 } 3666 /** 3667 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views 3668 * @param {number} bufferIndex 3669 * @return {Promise<ArrayBuffer>} 3670 */ 3671 loadBuffer(bufferIndex) { 3672 const bufferDef = this.json.buffers[bufferIndex]; 3673 const loader = this.fileLoader; 3674 if (bufferDef.type && bufferDef.type !== "arraybuffer") { 3675 throw new Error("THREE.GLTFLoader: " + bufferDef.type + " buffer type is not supported."); 3676 } 3677 if (bufferDef.uri === void 0 && bufferIndex === 0) { 3678 return Promise.resolve(this.extensions[EXTENSIONS.KHR_BINARY_GLTF].body); 3679 } 3680 const options = this.options; 3681 return new Promise(function(resolve3, reject) { 3682 loader.load(LoaderUtils.resolveURL(bufferDef.uri, options.path), resolve3, void 0, function() { 3683 reject(new Error('THREE.GLTFLoader: Failed to load buffer "' + bufferDef.uri + '".')); 3684 }); 3685 }); 3686 } 3687 /** 3688 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views 3689 * @param {number} bufferViewIndex 3690 * @return {Promise<ArrayBuffer>} 3691 */ 3692 loadBufferView(bufferViewIndex) { 3693 const bufferViewDef = this.json.bufferViews[bufferViewIndex]; 3694 return this.getDependency("buffer", bufferViewDef.buffer).then(function(buffer) { 3695 const byteLength = bufferViewDef.byteLength || 0; 3696 const byteOffset = bufferViewDef.byteOffset || 0; 3697 return buffer.slice(byteOffset, byteOffset + byteLength); 3698 }); 3699 } 3700 /** 3701 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#accessors 3702 * @param {number} accessorIndex 3703 * @return {Promise<BufferAttribute|InterleavedBufferAttribute>} 3704 */ 3705 loadAccessor(accessorIndex) { 3706 const parser = this; 3707 const json = this.json; 3708 const accessorDef = this.json.accessors[accessorIndex]; 3709 if (accessorDef.bufferView === void 0 && accessorDef.sparse === void 0) { 3710 const itemSize = WEBGL_TYPE_SIZES[accessorDef.type]; 3711 const TypedArray = WEBGL_COMPONENT_TYPES[accessorDef.componentType]; 3712 const normalized = accessorDef.normalized === true; 3713 const array = new TypedArray(accessorDef.count * itemSize); 3714 return Promise.resolve(new BufferAttribute(array, itemSize, normalized)); 3715 } 3716 const pendingBufferViews = []; 3717 if (accessorDef.bufferView !== void 0) { 3718 pendingBufferViews.push(this.getDependency("bufferView", accessorDef.bufferView)); 3719 } else { 3720 pendingBufferViews.push(null); 3721 } 3722 if (accessorDef.sparse !== void 0) { 3723 pendingBufferViews.push(this.getDependency("bufferView", accessorDef.sparse.indices.bufferView)); 3724 pendingBufferViews.push(this.getDependency("bufferView", accessorDef.sparse.values.bufferView)); 3725 } 3726 return Promise.all(pendingBufferViews).then(function(bufferViews) { 3727 const bufferView = bufferViews[0]; 3728 const itemSize = WEBGL_TYPE_SIZES[accessorDef.type]; 3729 const TypedArray = WEBGL_COMPONENT_TYPES[accessorDef.componentType]; 3730 const elementBytes = TypedArray.BYTES_PER_ELEMENT; 3731 const itemBytes = elementBytes * itemSize; 3732 const byteOffset = accessorDef.byteOffset || 0; 3733 const byteStride = accessorDef.bufferView !== void 0 ? json.bufferViews[accessorDef.bufferView].byteStride : void 0; 3734 const normalized = accessorDef.normalized === true; 3735 let array, bufferAttribute; 3736 if (byteStride && byteStride !== itemBytes) { 3737 const ibSlice = Math.floor(byteOffset / byteStride); 3738 const ibCacheKey = "InterleavedBuffer:" + accessorDef.bufferView + ":" + accessorDef.componentType + ":" + ibSlice + ":" + accessorDef.count; 3739 let ib = parser.cache.get(ibCacheKey); 3740 if (!ib) { 3741 array = new TypedArray(bufferView, ibSlice * byteStride, accessorDef.count * byteStride / elementBytes); 3742 ib = new InterleavedBuffer(array, byteStride / elementBytes); 3743 parser.cache.add(ibCacheKey, ib); 3744 } 3745 bufferAttribute = new InterleavedBufferAttribute( 3746 ib, 3747 itemSize, 3748 byteOffset % byteStride / elementBytes, 3749 normalized 3750 ); 3751 } else { 3752 if (bufferView === null) { 3753 array = new TypedArray(accessorDef.count * itemSize); 3754 } else { 3755 array = new TypedArray(bufferView, byteOffset, accessorDef.count * itemSize); 3756 } 3757 bufferAttribute = new BufferAttribute(array, itemSize, normalized); 3758 } 3759 if (accessorDef.sparse !== void 0) { 3760 const itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR; 3761 const TypedArrayIndices = WEBGL_COMPONENT_TYPES[accessorDef.sparse.indices.componentType]; 3762 const byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0; 3763 const byteOffsetValues = accessorDef.sparse.values.byteOffset || 0; 3764 const sparseIndices = new TypedArrayIndices( 3765 bufferViews[1], 3766 byteOffsetIndices, 3767 accessorDef.sparse.count * itemSizeIndices 3768 ); 3769 const sparseValues = new TypedArray(bufferViews[2], byteOffsetValues, accessorDef.sparse.count * itemSize); 3770 if (bufferView !== null) { 3771 bufferAttribute = new BufferAttribute( 3772 bufferAttribute.array.slice(), 3773 bufferAttribute.itemSize, 3774 bufferAttribute.normalized 3775 ); 3776 } 3777 for (let i = 0, il = sparseIndices.length; i < il; i++) { 3778 const index = sparseIndices[i]; 3779 bufferAttribute.setX(index, sparseValues[i * itemSize]); 3780 if (itemSize >= 2) 3781 bufferAttribute.setY(index, sparseValues[i * itemSize + 1]); 3782 if (itemSize >= 3) 3783 bufferAttribute.setZ(index, sparseValues[i * itemSize + 2]); 3784 if (itemSize >= 4) 3785 bufferAttribute.setW(index, sparseValues[i * itemSize + 3]); 3786 if (itemSize >= 5) 3787 throw new Error("THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute."); 3788 } 3789 } 3790 return bufferAttribute; 3791 }); 3792 } 3793 /** 3794 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures 3795 * @param {number} textureIndex 3796 * @return {Promise<THREE.Texture|null>} 3797 */ 3798 loadTexture(textureIndex) { 3799 const json = this.json; 3800 const options = this.options; 3801 const textureDef = json.textures[textureIndex]; 3802 const sourceIndex = textureDef.source; 3803 const sourceDef = json.images[sourceIndex]; 3804 let loader = this.textureLoader; 3805 if (sourceDef.uri) { 3806 const handler = options.manager.getHandler(sourceDef.uri); 3807 if (handler !== null) 3808 loader = handler; 3809 } 3810 return this.loadTextureImage(textureIndex, sourceIndex, loader); 3811 } 3812 loadTextureImage(textureIndex, sourceIndex, loader) { 3813 const parser = this; 3814 const json = this.json; 3815 const textureDef = json.textures[textureIndex]; 3816 const sourceDef = json.images[sourceIndex]; 3817 const cacheKey = (sourceDef.uri || sourceDef.bufferView) + ":" + textureDef.sampler; 3818 if (this.textureCache[cacheKey]) { 3819 return this.textureCache[cacheKey]; 3820 } 3821 const promise = this.loadImageSource(sourceIndex, loader).then(function(texture) { 3822 texture.flipY = false; 3823 texture.name = textureDef.name || sourceDef.name || ""; 3824 if (texture.name === "" && typeof sourceDef.uri === "string" && sourceDef.uri.startsWith("data:image/") === false) { 3825 texture.name = sourceDef.uri; 3826 } 3827 const samplers = json.samplers || {}; 3828 const sampler = samplers[textureDef.sampler] || {}; 3829 texture.magFilter = WEBGL_FILTERS[sampler.magFilter] || LinearFilter; 3830 texture.minFilter = WEBGL_FILTERS[sampler.minFilter] || LinearMipmapLinearFilter; 3831 texture.wrapS = WEBGL_WRAPPINGS[sampler.wrapS] || RepeatWrapping; 3832 texture.wrapT = WEBGL_WRAPPINGS[sampler.wrapT] || RepeatWrapping; 3833 parser.associations.set(texture, { textures: textureIndex }); 3834 return texture; 3835 }).catch(function() { 3836 return null; 3837 }); 3838 this.textureCache[cacheKey] = promise; 3839 return promise; 3840 } 3841 loadImageSource(sourceIndex, loader) { 3842 const parser = this; 3843 const json = this.json; 3844 const options = this.options; 3845 if (this.sourceCache[sourceIndex] !== void 0) { 3846 return this.sourceCache[sourceIndex].then((texture) => texture.clone()); 3847 } 3848 const sourceDef = json.images[sourceIndex]; 3849 const URL2 = self.URL || self.webkitURL; 3850 let sourceURI = sourceDef.uri || ""; 3851 let isObjectURL = false; 3852 if (sourceDef.bufferView !== void 0) { 3853 sourceURI = parser.getDependency("bufferView", sourceDef.bufferView).then(function(bufferView) { 3854 isObjectURL = true; 3855 const blob = new Blob([bufferView], { type: sourceDef.mimeType }); 3856 sourceURI = URL2.createObjectURL(blob); 3857 return sourceURI; 3858 }); 3859 } else if (sourceDef.uri === void 0) { 3860 throw new Error("THREE.GLTFLoader: Image " + sourceIndex + " is missing URI and bufferView"); 3861 } 3862 const promise = Promise.resolve(sourceURI).then(function(sourceURI2) { 3863 return new Promise(function(resolve3, reject) { 3864 let onLoad = resolve3; 3865 if (loader.isImageBitmapLoader === true) { 3866 onLoad = function(imageBitmap) { 3867 const texture = new Texture(imageBitmap); 3868 texture.needsUpdate = true; 3869 resolve3(texture); 3870 }; 3871 } 3872 loader.load(LoaderUtils.resolveURL(sourceURI2, options.path), onLoad, void 0, reject); 3873 }); 3874 }).then(function(texture) { 3875 if (isObjectURL === true) { 3876 URL2.revokeObjectURL(sourceURI); 3877 } 3878 assignExtrasToUserData(texture, sourceDef); 3879 texture.userData.mimeType = sourceDef.mimeType || getImageURIMimeType(sourceDef.uri); 3880 return texture; 3881 }).catch(function(error) { 3882 console.error("THREE.GLTFLoader: Couldn't load texture", sourceURI); 3883 throw error; 3884 }); 3885 this.sourceCache[sourceIndex] = promise; 3886 return promise; 3887 } 3888 /** 3889 * Asynchronously assigns a texture to the given material parameters. 3890 * @param {Object} materialParams 3891 * @param {string} mapName 3892 * @param {Object} mapDef 3893 * @return {Promise<Texture>} 3894 */ 3895 assignTexture(materialParams, mapName, mapDef, colorSpace) { 3896 const parser = this; 3897 return this.getDependency("texture", mapDef.index).then(function(texture) { 3898 if (!texture) 3899 return null; 3900 if (mapDef.texCoord !== void 0 && mapDef.texCoord > 0) { 3901 texture = texture.clone(); 3902 texture.channel = mapDef.texCoord; 3903 } 3904 if (parser.extensions[EXTENSIONS.KHR_TEXTURE_TRANSFORM]) { 3905 const transform = mapDef.extensions !== void 0 ? mapDef.extensions[EXTENSIONS.KHR_TEXTURE_TRANSFORM] : void 0; 3906 if (transform) { 3907 const gltfReference = parser.associations.get(texture); 3908 texture = parser.extensions[EXTENSIONS.KHR_TEXTURE_TRANSFORM].extendTexture(texture, transform); 3909 parser.associations.set(texture, gltfReference); 3910 } 3911 } 3912 if (colorSpace !== void 0) { 3913 if (typeof colorSpace === "number") 3914 colorSpace = colorSpace === sRGBEncoding ? SRGBColorSpace2 : LinearSRGBColorSpace2; 3915 if ("colorSpace" in texture) 3916 texture.colorSpace = colorSpace; 3917 else 3918 texture.encoding = colorSpace === SRGBColorSpace2 ? sRGBEncoding : LinearEncoding; 3919 } 3920 materialParams[mapName] = texture; 3921 return texture; 3922 }); 3923 } 3924 /** 3925 * Assigns final material to a Mesh, Line, or Points instance. The instance 3926 * already has a material (generated from the glTF material options alone) 3927 * but reuse of the same glTF material may require multiple threejs materials 3928 * to accommodate different primitive types, defines, etc. New materials will 3929 * be created if necessary, and reused from a cache. 3930 * @param {Object3D} mesh Mesh, Line, or Points instance. 3931 */ 3932 assignFinalMaterial(mesh) { 3933 const geometry = mesh.geometry; 3934 let material = mesh.material; 3935 const useDerivativeTangents = geometry.attributes.tangent === void 0; 3936 const useVertexColors = geometry.attributes.color !== void 0; 3937 const useFlatShading = geometry.attributes.normal === void 0; 3938 if (mesh.isPoints) { 3939 const cacheKey = "PointsMaterial:" + material.uuid; 3940 let pointsMaterial = this.cache.get(cacheKey); 3941 if (!pointsMaterial) { 3942 pointsMaterial = new PointsMaterial(); 3943 Material.prototype.copy.call(pointsMaterial, material); 3944 pointsMaterial.color.copy(material.color); 3945 pointsMaterial.map = material.map; 3946 pointsMaterial.sizeAttenuation = false; 3947 this.cache.add(cacheKey, pointsMaterial); 3948 } 3949 material = pointsMaterial; 3950 } else if (mesh.isLine) { 3951 const cacheKey = "LineBasicMaterial:" + material.uuid; 3952 let lineMaterial = this.cache.get(cacheKey); 3953 if (!lineMaterial) { 3954 lineMaterial = new LineBasicMaterial(); 3955 Material.prototype.copy.call(lineMaterial, material); 3956 lineMaterial.color.copy(material.color); 3957 lineMaterial.map = material.map; 3958 this.cache.add(cacheKey, lineMaterial); 3959 } 3960 material = lineMaterial; 3961 } 3962 if (useDerivativeTangents || useVertexColors || useFlatShading) { 3963 let cacheKey = "ClonedMaterial:" + material.uuid + ":"; 3964 if (useDerivativeTangents) 3965 cacheKey += "derivative-tangents:"; 3966 if (useVertexColors) 3967 cacheKey += "vertex-colors:"; 3968 if (useFlatShading) 3969 cacheKey += "flat-shading:"; 3970 let cachedMaterial = this.cache.get(cacheKey); 3971 if (!cachedMaterial) { 3972 cachedMaterial = material.clone(); 3973 if (useVertexColors) 3974 cachedMaterial.vertexColors = true; 3975 if (useFlatShading) 3976 cachedMaterial.flatShading = true; 3977 if (useDerivativeTangents) { 3978 if (cachedMaterial.normalScale) 3979 cachedMaterial.normalScale.y *= -1; 3980 if (cachedMaterial.clearcoatNormalScale) 3981 cachedMaterial.clearcoatNormalScale.y *= -1; 3982 } 3983 this.cache.add(cacheKey, cachedMaterial); 3984 this.associations.set(cachedMaterial, this.associations.get(material)); 3985 } 3986 material = cachedMaterial; 3987 } 3988 mesh.material = material; 3989 } 3990 getMaterialType() { 3991 return MeshStandardMaterial; 3992 } 3993 /** 3994 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials 3995 * @param {number} materialIndex 3996 * @return {Promise<Material>} 3997 */ 3998 loadMaterial(materialIndex) { 3999 const parser = this; 4000 const json = this.json; 4001 const extensions = this.extensions; 4002 const materialDef = json.materials[materialIndex]; 4003 let materialType; 4004 const materialParams = {}; 4005 const materialExtensions = materialDef.extensions || {}; 4006 const pending = []; 4007 if (materialExtensions[EXTENSIONS.KHR_MATERIALS_UNLIT]) { 4008 const kmuExtension = extensions[EXTENSIONS.KHR_MATERIALS_UNLIT]; 4009 materialType = kmuExtension.getMaterialType(); 4010 pending.push(kmuExtension.extendParams(materialParams, materialDef, parser)); 4011 } else { 4012 const metallicRoughness = materialDef.pbrMetallicRoughness || {}; 4013 materialParams.color = new Color(1, 1, 1); 4014 materialParams.opacity = 1; 4015 if (Array.isArray(metallicRoughness.baseColorFactor)) { 4016 const array = metallicRoughness.baseColorFactor; 4017 materialParams.color.setRGB(array[0], array[1], array[2], LinearSRGBColorSpace2); 4018 materialParams.opacity = array[3]; 4019 } 4020 if (metallicRoughness.baseColorTexture !== void 0) { 4021 pending.push(parser.assignTexture(materialParams, "map", metallicRoughness.baseColorTexture, SRGBColorSpace2)); 4022 } 4023 materialParams.metalness = metallicRoughness.metallicFactor !== void 0 ? metallicRoughness.metallicFactor : 1; 4024 materialParams.roughness = metallicRoughness.roughnessFactor !== void 0 ? metallicRoughness.roughnessFactor : 1; 4025 if (metallicRoughness.metallicRoughnessTexture !== void 0) { 4026 pending.push(parser.assignTexture(materialParams, "metalnessMap", metallicRoughness.metallicRoughnessTexture)); 4027 pending.push(parser.assignTexture(materialParams, "roughnessMap", metallicRoughness.metallicRoughnessTexture)); 4028 } 4029 materialType = this._invokeOne(function(ext) { 4030 return ext.getMaterialType && ext.getMaterialType(materialIndex); 4031 }); 4032 pending.push( 4033 Promise.all( 4034 this._invokeAll(function(ext) { 4035 return ext.extendMaterialParams && ext.extendMaterialParams(materialIndex, materialParams); 4036 }) 4037 ) 4038 ); 4039 } 4040 if (materialDef.doubleSided === true) { 4041 materialParams.side = DoubleSide; 4042 } 4043 const alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE; 4044 if (alphaMode === ALPHA_MODES.BLEND) { 4045 materialParams.transparent = true; 4046 materialParams.depthWrite = false; 4047 } else { 4048 materialParams.transparent = false; 4049 if (alphaMode === ALPHA_MODES.MASK) { 4050 materialParams.alphaTest = materialDef.alphaCutoff !== void 0 ? materialDef.alphaCutoff : 0.5; 4051 } 4052 } 4053 if (materialDef.normalTexture !== void 0 && materialType !== MeshBasicMaterial) { 4054 pending.push(parser.assignTexture(materialParams, "normalMap", materialDef.normalTexture)); 4055 materialParams.normalScale = new Vector2(1, 1); 4056 if (materialDef.normalTexture.scale !== void 0) { 4057 const scale = materialDef.normalTexture.scale; 4058 materialParams.normalScale.set(scale, scale); 4059 } 4060 } 4061 if (materialDef.occlusionTexture !== void 0 && materialType !== MeshBasicMaterial) { 4062 pending.push(parser.assignTexture(materialParams, "aoMap", materialDef.occlusionTexture)); 4063 if (materialDef.occlusionTexture.strength !== void 0) { 4064 materialParams.aoMapIntensity = materialDef.occlusionTexture.strength; 4065 } 4066 } 4067 if (materialDef.emissiveFactor !== void 0 && materialType !== MeshBasicMaterial) { 4068 const emissiveFactor = materialDef.emissiveFactor; 4069 materialParams.emissive = new Color().setRGB( 4070 emissiveFactor[0], 4071 emissiveFactor[1], 4072 emissiveFactor[2], 4073 LinearSRGBColorSpace2 4074 ); 4075 } 4076 if (materialDef.emissiveTexture !== void 0 && materialType !== MeshBasicMaterial) { 4077 pending.push(parser.assignTexture(materialParams, "emissiveMap", materialDef.emissiveTexture, SRGBColorSpace2)); 4078 } 4079 return Promise.all(pending).then(function() { 4080 const material = new materialType(materialParams); 4081 if (materialDef.name) 4082 material.name = materialDef.name; 4083 assignExtrasToUserData(material, materialDef); 4084 parser.associations.set(material, { materials: materialIndex }); 4085 if (materialDef.extensions) 4086 addUnknownExtensionsToUserData(extensions, material, materialDef); 4087 return material; 4088 }); 4089 } 4090 /** When Object3D instances are targeted by animation, they need unique names. */ 4091 createUniqueName(originalName) { 4092 const sanitizedName = PropertyBinding.sanitizeNodeName(originalName || ""); 4093 if (sanitizedName in this.nodeNamesUsed) { 4094 return sanitizedName + "_" + ++this.nodeNamesUsed[sanitizedName]; 4095 } else { 4096 this.nodeNamesUsed[sanitizedName] = 0; 4097 return sanitizedName; 4098 } 4099 } 4100 /** 4101 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry 4102 * 4103 * Creates BufferGeometries from primitives. 4104 * 4105 * @param {Array<GLTF.Primitive>} primitives 4106 * @return {Promise<Array<BufferGeometry>>} 4107 */ 4108 loadGeometries(primitives) { 4109 const parser = this; 4110 const extensions = this.extensions; 4111 const cache = this.primitiveCache; 4112 function createDracoPrimitive(primitive) { 4113 return extensions[EXTENSIONS.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(primitive, parser).then(function(geometry) { 4114 return addPrimitiveAttributes(geometry, primitive, parser); 4115 }); 4116 } 4117 const pending = []; 4118 for (let i = 0, il = primitives.length; i < il; i++) { 4119 const primitive = primitives[i]; 4120 const cacheKey = createPrimitiveKey(primitive); 4121 const cached = cache[cacheKey]; 4122 if (cached) { 4123 pending.push(cached.promise); 4124 } else { 4125 let geometryPromise; 4126 if (primitive.extensions && primitive.extensions[EXTENSIONS.KHR_DRACO_MESH_COMPRESSION]) { 4127 geometryPromise = createDracoPrimitive(primitive); 4128 } else { 4129 geometryPromise = addPrimitiveAttributes(new BufferGeometry(), primitive, parser); 4130 } 4131 cache[cacheKey] = { primitive, promise: geometryPromise }; 4132 pending.push(geometryPromise); 4133 } 4134 } 4135 return Promise.all(pending); 4136 } 4137 /** 4138 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes 4139 * @param {number} meshIndex 4140 * @return {Promise<Group|Mesh|SkinnedMesh>} 4141 */ 4142 loadMesh(meshIndex) { 4143 const parser = this; 4144 const json = this.json; 4145 const extensions = this.extensions; 4146 const meshDef = json.meshes[meshIndex]; 4147 const primitives = meshDef.primitives; 4148 const pending = []; 4149 for (let i = 0, il = primitives.length; i < il; i++) { 4150 const material = primitives[i].material === void 0 ? createDefaultMaterial(this.cache) : this.getDependency("material", primitives[i].material); 4151 pending.push(material); 4152 } 4153 pending.push(parser.loadGeometries(primitives)); 4154 return Promise.all(pending).then(function(results) { 4155 const materials = results.slice(0, results.length - 1); 4156 const geometries = results[results.length - 1]; 4157 const meshes = []; 4158 for (let i = 0, il = geometries.length; i < il; i++) { 4159 const geometry = geometries[i]; 4160 const primitive = primitives[i]; 4161 let mesh; 4162 const material = materials[i]; 4163 if (primitive.mode === WEBGL_CONSTANTS.TRIANGLES || primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP || primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN || primitive.mode === void 0) { 4164 mesh = meshDef.isSkinnedMesh === true ? new SkinnedMesh(geometry, material) : new Mesh(geometry, material); 4165 if (mesh.isSkinnedMesh === true) { 4166 mesh.normalizeSkinWeights(); 4167 } 4168 if (primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP) { 4169 mesh.geometry = toTrianglesDrawMode(mesh.geometry, TriangleStripDrawMode); 4170 } else if (primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN) { 4171 mesh.geometry = toTrianglesDrawMode(mesh.geometry, TriangleFanDrawMode); 4172 } 4173 } else if (primitive.mode === WEBGL_CONSTANTS.LINES) { 4174 mesh = new LineSegments(geometry, material); 4175 } else if (primitive.mode === WEBGL_CONSTANTS.LINE_STRIP) { 4176 mesh = new Line(geometry, material); 4177 } else if (primitive.mode === WEBGL_CONSTANTS.LINE_LOOP) { 4178 mesh = new LineLoop(geometry, material); 4179 } else if (primitive.mode === WEBGL_CONSTANTS.POINTS) { 4180 mesh = new Points(geometry, material); 4181 } else { 4182 throw new Error("THREE.GLTFLoader: Primitive mode unsupported: " + primitive.mode); 4183 } 4184 if (Object.keys(mesh.geometry.morphAttributes).length > 0) { 4185 updateMorphTargets(mesh, meshDef); 4186 } 4187 mesh.name = parser.createUniqueName(meshDef.name || "mesh_" + meshIndex); 4188 assignExtrasToUserData(mesh, meshDef); 4189 if (primitive.extensions) 4190 addUnknownExtensionsToUserData(extensions, mesh, primitive); 4191 parser.assignFinalMaterial(mesh); 4192 meshes.push(mesh); 4193 } 4194 for (let i = 0, il = meshes.length; i < il; i++) { 4195 parser.associations.set(meshes[i], { 4196 meshes: meshIndex, 4197 primitives: i 4198 }); 4199 } 4200 if (meshes.length === 1) { 4201 if (meshDef.extensions) 4202 addUnknownExtensionsToUserData(extensions, meshes[0], meshDef); 4203 return meshes[0]; 4204 } 4205 const group = new Group(); 4206 if (meshDef.extensions) 4207 addUnknownExtensionsToUserData(extensions, group, meshDef); 4208 parser.associations.set(group, { meshes: meshIndex }); 4209 for (let i = 0, il = meshes.length; i < il; i++) { 4210 group.add(meshes[i]); 4211 } 4212 return group; 4213 }); 4214 } 4215 /** 4216 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#cameras 4217 * @param {number} cameraIndex 4218 * @return {Promise<THREE.Camera>} 4219 */ 4220 loadCamera(cameraIndex) { 4221 let camera; 4222 const cameraDef = this.json.cameras[cameraIndex]; 4223 const params = cameraDef[cameraDef.type]; 4224 if (!params) { 4225 console.warn("THREE.GLTFLoader: Missing camera parameters."); 4226 return; 4227 } 4228 if (cameraDef.type === "perspective") { 4229 camera = new PerspectiveCamera( 4230 MathUtils.radToDeg(params.yfov), 4231 params.aspectRatio || 1, 4232 params.znear || 1, 4233 params.zfar || 2e6 4234 ); 4235 } else if (cameraDef.type === "orthographic") { 4236 camera = new OrthographicCamera(-params.xmag, params.xmag, params.ymag, -params.ymag, params.znear, params.zfar); 4237 } 4238 if (cameraDef.name) 4239 camera.name = this.createUniqueName(cameraDef.name); 4240 assignExtrasToUserData(camera, cameraDef); 4241 return Promise.resolve(camera); 4242 } 4243 /** 4244 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins 4245 * @param {number} skinIndex 4246 * @return {Promise<Skeleton>} 4247 */ 4248 loadSkin(skinIndex) { 4249 const skinDef = this.json.skins[skinIndex]; 4250 const pending = []; 4251 for (let i = 0, il = skinDef.joints.length; i < il; i++) { 4252 pending.push(this._loadNodeShallow(skinDef.joints[i])); 4253 } 4254 if (skinDef.inverseBindMatrices !== void 0) { 4255 pending.push(this.getDependency("accessor", skinDef.inverseBindMatrices)); 4256 } else { 4257 pending.push(null); 4258 } 4259 return Promise.all(pending).then(function(results) { 4260 const inverseBindMatrices = results.pop(); 4261 const jointNodes = results; 4262 const bones = []; 4263 const boneInverses = []; 4264 for (let i = 0, il = jointNodes.length; i < il; i++) { 4265 const jointNode = jointNodes[i]; 4266 if (jointNode) { 4267 bones.push(jointNode); 4268 const mat = new Matrix4(); 4269 if (inverseBindMatrices !== null) { 4270 mat.fromArray(inverseBindMatrices.array, i * 16); 4271 } 4272 boneInverses.push(mat); 4273 } else { 4274 console.warn('THREE.GLTFLoader: Joint "%s" could not be found.', skinDef.joints[i]); 4275 } 4276 } 4277 return new Skeleton(bones, boneInverses); 4278 }); 4279 } 4280 /** 4281 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#animations 4282 * @param {number} animationIndex 4283 * @return {Promise<AnimationClip>} 4284 */ 4285 loadAnimation(animationIndex) { 4286 const json = this.json; 4287 const parser = this; 4288 const animationDef = json.animations[animationIndex]; 4289 const animationName = animationDef.name ? animationDef.name : "animation_" + animationIndex; 4290 const pendingNodes = []; 4291 const pendingInputAccessors = []; 4292 const pendingOutputAccessors = []; 4293 const pendingSamplers = []; 4294 const pendingTargets = []; 4295 for (let i = 0, il = animationDef.channels.length; i < il; i++) { 4296 const channel = animationDef.channels[i]; 4297 const sampler = animationDef.samplers[channel.sampler]; 4298 const target = channel.target; 4299 const name = target.node; 4300 const input = animationDef.parameters !== void 0 ? animationDef.parameters[sampler.input] : sampler.input; 4301 const output = animationDef.parameters !== void 0 ? animationDef.parameters[sampler.output] : sampler.output; 4302 if (target.node === void 0) 4303 continue; 4304 pendingNodes.push(this.getDependency("node", name)); 4305 pendingInputAccessors.push(this.getDependency("accessor", input)); 4306 pendingOutputAccessors.push(this.getDependency("accessor", output)); 4307 pendingSamplers.push(sampler); 4308 pendingTargets.push(target); 4309 } 4310 return Promise.all([ 4311 Promise.all(pendingNodes), 4312 Promise.all(pendingInputAccessors), 4313 Promise.all(pendingOutputAccessors), 4314 Promise.all(pendingSamplers), 4315 Promise.all(pendingTargets) 4316 ]).then(function(dependencies) { 4317 const nodes = dependencies[0]; 4318 const inputAccessors = dependencies[1]; 4319 const outputAccessors = dependencies[2]; 4320 const samplers = dependencies[3]; 4321 const targets = dependencies[4]; 4322 const tracks = []; 4323 for (let i = 0, il = nodes.length; i < il; i++) { 4324 const node = nodes[i]; 4325 const inputAccessor = inputAccessors[i]; 4326 const outputAccessor = outputAccessors[i]; 4327 const sampler = samplers[i]; 4328 const target = targets[i]; 4329 if (node === void 0) 4330 continue; 4331 if (node.updateMatrix) { 4332 node.updateMatrix(); 4333 } 4334 const createdTracks = parser._createAnimationTracks(node, inputAccessor, outputAccessor, sampler, target); 4335 if (createdTracks) { 4336 for (let k = 0; k < createdTracks.length; k++) { 4337 tracks.push(createdTracks[k]); 4338 } 4339 } 4340 } 4341 return new AnimationClip(animationName, void 0, tracks); 4342 }); 4343 } 4344 createNodeMesh(nodeIndex) { 4345 const json = this.json; 4346 const parser = this; 4347 const nodeDef = json.nodes[nodeIndex]; 4348 if (nodeDef.mesh === void 0) 4349 return null; 4350 return parser.getDependency("mesh", nodeDef.mesh).then(function(mesh) { 4351 const node = parser._getNodeRef(parser.meshCache, nodeDef.mesh, mesh); 4352 if (nodeDef.weights !== void 0) { 4353 node.traverse(function(o) { 4354 if (!o.isMesh) 4355 return; 4356 for (let i = 0, il = nodeDef.weights.length; i < il; i++) { 4357 o.morphTargetInfluences[i] = nodeDef.weights[i]; 4358 } 4359 }); 4360 } 4361 return node; 4362 }); 4363 } 4364 /** 4365 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy 4366 * @param {number} nodeIndex 4367 * @return {Promise<Object3D>} 4368 */ 4369 loadNode(nodeIndex) { 4370 const json = this.json; 4371 const parser = this; 4372 const nodeDef = json.nodes[nodeIndex]; 4373 const nodePending = parser._loadNodeShallow(nodeIndex); 4374 const childPending = []; 4375 const childrenDef = nodeDef.children || []; 4376 for (let i = 0, il = childrenDef.length; i < il; i++) { 4377 childPending.push(parser.getDependency("node", childrenDef[i])); 4378 } 4379 const skeletonPending = nodeDef.skin === void 0 ? Promise.resolve(null) : parser.getDependency("skin", nodeDef.skin); 4380 return Promise.all([nodePending, Promise.all(childPending), skeletonPending]).then(function(results) { 4381 const node = results[0]; 4382 const children2 = results[1]; 4383 const skeleton = results[2]; 4384 if (skeleton !== null) { 4385 node.traverse(function(mesh) { 4386 if (!mesh.isSkinnedMesh) 4387 return; 4388 mesh.bind(skeleton, _identityMatrix); 4389 }); 4390 } 4391 for (let i = 0, il = children2.length; i < il; i++) { 4392 node.add(children2[i]); 4393 } 4394 return node; 4395 }); 4396 } 4397 // ._loadNodeShallow() parses a single node. 4398 // skin and child nodes are created and added in .loadNode() (no '_' prefix). 4399 _loadNodeShallow(nodeIndex) { 4400 const json = this.json; 4401 const extensions = this.extensions; 4402 const parser = this; 4403 if (this.nodeCache[nodeIndex] !== void 0) { 4404 return this.nodeCache[nodeIndex]; 4405 } 4406 const nodeDef = json.nodes[nodeIndex]; 4407 const nodeName = nodeDef.name ? parser.createUniqueName(nodeDef.name) : ""; 4408 const pending = []; 4409 const meshPromise = parser._invokeOne(function(ext) { 4410 return ext.createNodeMesh && ext.createNodeMesh(nodeIndex); 4411 }); 4412 if (meshPromise) { 4413 pending.push(meshPromise); 4414 } 4415 if (nodeDef.camera !== void 0) { 4416 pending.push( 4417 parser.getDependency("camera", nodeDef.camera).then(function(camera) { 4418 return parser._getNodeRef(parser.cameraCache, nodeDef.camera, camera); 4419 }) 4420 ); 4421 } 4422 parser._invokeAll(function(ext) { 4423 return ext.createNodeAttachment && ext.createNodeAttachment(nodeIndex); 4424 }).forEach(function(promise) { 4425 pending.push(promise); 4426 }); 4427 this.nodeCache[nodeIndex] = Promise.all(pending).then(function(objects) { 4428 let node; 4429 if (nodeDef.isBone === true) { 4430 node = new Bone(); 4431 } else if (objects.length > 1) { 4432 node = new Group(); 4433 } else if (objects.length === 1) { 4434 node = objects[0]; 4435 } else { 4436 node = new Object3D(); 4437 } 4438 if (node !== objects[0]) { 4439 for (let i = 0, il = objects.length; i < il; i++) { 4440 node.add(objects[i]); 4441 } 4442 } 4443 if (nodeDef.name) { 4444 node.userData.name = nodeDef.name; 4445 node.name = nodeName; 4446 } 4447 assignExtrasToUserData(node, nodeDef); 4448 if (nodeDef.extensions) 4449 addUnknownExtensionsToUserData(extensions, node, nodeDef); 4450 if (nodeDef.matrix !== void 0) { 4451 const matrix = new Matrix4(); 4452 matrix.fromArray(nodeDef.matrix); 4453 node.applyMatrix4(matrix); 4454 } else { 4455 if (nodeDef.translation !== void 0) { 4456 node.position.fromArray(nodeDef.translation); 4457 } 4458 if (nodeDef.rotation !== void 0) { 4459 node.quaternion.fromArray(nodeDef.rotation); 4460 } 4461 if (nodeDef.scale !== void 0) { 4462 node.scale.fromArray(nodeDef.scale); 4463 } 4464 } 4465 if (!parser.associations.has(node)) { 4466 parser.associations.set(node, {}); 4467 } 4468 parser.associations.get(node).nodes = nodeIndex; 4469 return node; 4470 }); 4471 return this.nodeCache[nodeIndex]; 4472 } 4473 /** 4474 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes 4475 * @param {number} sceneIndex 4476 * @return {Promise<Group>} 4477 */ 4478 loadScene(sceneIndex) { 4479 const extensions = this.extensions; 4480 const sceneDef = this.json.scenes[sceneIndex]; 4481 const parser = this; 4482 const scene = new Group(); 4483 if (sceneDef.name) 4484 scene.name = parser.createUniqueName(sceneDef.name); 4485 assignExtrasToUserData(scene, sceneDef); 4486 if (sceneDef.extensions) 4487 addUnknownExtensionsToUserData(extensions, scene, sceneDef); 4488 const nodeIds = sceneDef.nodes || []; 4489 const pending = []; 4490 for (let i = 0, il = nodeIds.length; i < il; i++) { 4491 pending.push(parser.getDependency("node", nodeIds[i])); 4492 } 4493 return Promise.all(pending).then(function(nodes) { 4494 for (let i = 0, il = nodes.length; i < il; i++) { 4495 scene.add(nodes[i]); 4496 } 4497 const reduceAssociations = (node) => { 4498 const reducedAssociations = /* @__PURE__ */ new Map(); 4499 for (const [key, value] of parser.associations) { 4500 if (key instanceof Material || key instanceof Texture) { 4501 reducedAssociations.set(key, value); 4502 } 4503 } 4504 node.traverse((node2) => { 4505 const mappings = parser.associations.get(node2); 4506 if (mappings != null) { 4507 reducedAssociations.set(node2, mappings); 4508 } 4509 }); 4510 return reducedAssociations; 4511 }; 4512 parser.associations = reduceAssociations(scene); 4513 return scene; 4514 }); 4515 } 4516 _createAnimationTracks(node, inputAccessor, outputAccessor, sampler, target) { 4517 const tracks = []; 4518 const targetName = node.name ? node.name : node.uuid; 4519 const targetNames = []; 4520 if (PATH_PROPERTIES[target.path] === PATH_PROPERTIES.weights) { 4521 node.traverse(function(object) { 4522 if (object.morphTargetInfluences) { 4523 targetNames.push(object.name ? object.name : object.uuid); 4524 } 4525 }); 4526 } else { 4527 targetNames.push(targetName); 4528 } 4529 let TypedKeyframeTrack; 4530 switch (PATH_PROPERTIES[target.path]) { 4531 case PATH_PROPERTIES.weights: 4532 TypedKeyframeTrack = NumberKeyframeTrack; 4533 break; 4534 case PATH_PROPERTIES.rotation: 4535 TypedKeyframeTrack = QuaternionKeyframeTrack; 4536 break; 4537 case PATH_PROPERTIES.position: 4538 case PATH_PROPERTIES.scale: 4539 TypedKeyframeTrack = VectorKeyframeTrack; 4540 break; 4541 default: 4542 switch (outputAccessor.itemSize) { 4543 case 1: 4544 TypedKeyframeTrack = NumberKeyframeTrack; 4545 break; 4546 case 2: 4547 case 3: 4548 default: 4549 TypedKeyframeTrack = VectorKeyframeTrack; 4550 break; 4551 } 4552 break; 4553 } 4554 const interpolation = sampler.interpolation !== void 0 ? INTERPOLATION[sampler.interpolation] : InterpolateLinear; 4555 const outputArray = this._getArrayFromAccessor(outputAccessor); 4556 for (let j = 0, jl = targetNames.length; j < jl; j++) { 4557 const track = new TypedKeyframeTrack( 4558 targetNames[j] + "." + PATH_PROPERTIES[target.path], 4559 inputAccessor.array, 4560 outputArray, 4561 interpolation 4562 ); 4563 if (sampler.interpolation === "CUBICSPLINE") { 4564 this._createCubicSplineTrackInterpolant(track); 4565 } 4566 tracks.push(track); 4567 } 4568 return tracks; 4569 } 4570 _getArrayFromAccessor(accessor) { 4571 let outputArray = accessor.array; 4572 if (accessor.normalized) { 4573 const scale = getNormalizedComponentScale(outputArray.constructor); 4574 const scaled = new Float32Array(outputArray.length); 4575 for (let j = 0, jl = outputArray.length; j < jl; j++) { 4576 scaled[j] = outputArray[j] * scale; 4577 } 4578 outputArray = scaled; 4579 } 4580 return outputArray; 4581 } 4582 _createCubicSplineTrackInterpolant(track) { 4583 track.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline(result) { 4584 const interpolantType = this instanceof QuaternionKeyframeTrack ? GLTFCubicSplineQuaternionInterpolant : GLTFCubicSplineInterpolant; 4585 return new interpolantType(this.times, this.values, this.getValueSize() / 3, result); 4586 }; 4587 track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true; 4588 } 4589}; 4590function computeBounds(geometry, primitiveDef, parser) { 4591 const attributes = primitiveDef.attributes; 4592 const box = new Box3(); 4593 if (attributes.POSITION !== void 0) { 4594 const accessor = parser.json.accessors[attributes.POSITION]; 4595 const min = accessor.min; 4596 const max = accessor.max; 4597 if (min !== void 0 && max !== void 0) { 4598 box.set(new Vector3(min[0], min[1], min[2]), new Vector3(max[0], max[1], max[2])); 4599 if (accessor.normalized) { 4600 const boxScale = getNormalizedComponentScale(WEBGL_COMPONENT_TYPES[accessor.componentType]); 4601 box.min.multiplyScalar(boxScale); 4602 box.max.multiplyScalar(boxScale); 4603 } 4604 } else { 4605 console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION."); 4606 return; 4607 } 4608 } else { 4609 return; 4610 } 4611 const targets = primitiveDef.targets; 4612 if (targets !== void 0) { 4613 const maxDisplacement = new Vector3(); 4614 const vector = new Vector3(); 4615 for (let i = 0, il = targets.length; i < il; i++) { 4616 const target = targets[i]; 4617 if (target.POSITION !== void 0) { 4618 const accessor = parser.json.accessors[target.POSITION]; 4619 const min = accessor.min; 4620 const max = accessor.max; 4621 if (min !== void 0 && max !== void 0) { 4622 vector.setX(Math.max(Math.abs(min[0]), Math.abs(max[0]))); 4623 vector.setY(Math.max(Math.abs(min[1]), Math.abs(max[1]))); 4624 vector.setZ(Math.max(Math.abs(min[2]), Math.abs(max[2]))); 4625 if (accessor.normalized) { 4626 const boxScale = getNormalizedComponentScale(WEBGL_COMPONENT_TYPES[accessor.componentType]); 4627 vector.multiplyScalar(boxScale); 4628 } 4629 maxDisplacement.max(vector); 4630 } else { 4631 console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION."); 4632 } 4633 } 4634 } 4635 box.expandByVector(maxDisplacement); 4636 } 4637 geometry.boundingBox = box; 4638 const sphere = new Sphere(); 4639 box.getCenter(sphere.center); 4640 sphere.radius = box.min.distanceTo(box.max) / 2; 4641 geometry.boundingSphere = sphere; 4642} 4643function addPrimitiveAttributes(geometry, primitiveDef, parser) { 4644 const attributes = primitiveDef.attributes; 4645 const pending = []; 4646 function assignAttributeAccessor(accessorIndex, attributeName) { 4647 return parser.getDependency("accessor", accessorIndex).then(function(accessor) { 4648 geometry.setAttribute(attributeName, accessor); 4649 }); 4650 } 4651 for (const gltfAttributeName in attributes) { 4652 const threeAttributeName = ATTRIBUTES[gltfAttributeName] || gltfAttributeName.toLowerCase(); 4653 if (threeAttributeName in geometry.attributes) 4654 continue; 4655 pending.push(assignAttributeAccessor(attributes[gltfAttributeName], threeAttributeName)); 4656 } 4657 if (primitiveDef.indices !== void 0 && !geometry.index) { 4658 const accessor = parser.getDependency("accessor", primitiveDef.indices).then(function(accessor2) { 4659 geometry.setIndex(accessor2); 4660 }); 4661 pending.push(accessor); 4662 } 4663 assignExtrasToUserData(geometry, primitiveDef); 4664 computeBounds(geometry, primitiveDef, parser); 4665 return Promise.all(pending).then(function() { 4666 return primitiveDef.targets !== void 0 ? addMorphTargets(geometry, primitiveDef.targets, parser) : geometry; 4667 }); 4668} 4669
vendor: 11,962 bytes, lines 4670-5008
4670// node_modules/three-stdlib/loaders/DRACOLoader.js 4671var _taskCache = /* @__PURE__ */ new WeakMap(); 4672var DRACOLoader = class extends Loader { 4673 constructor(manager) { 4674 super(manager); 4675 this.decoderPath = ""; 4676 this.decoderConfig = {}; 4677 this.decoderBinary = null; 4678 this.decoderPending = null; 4679 this.workerLimit = 4; 4680 this.workerPool = []; 4681 this.workerNextTaskID = 1; 4682 this.workerSourceURL = ""; 4683 this.defaultAttributeIDs = { 4684 position: "POSITION", 4685 normal: "NORMAL", 4686 color: "COLOR", 4687 uv: "TEX_COORD" 4688 }; 4689 this.defaultAttributeTypes = { 4690 position: "Float32Array", 4691 normal: "Float32Array", 4692 color: "Float32Array", 4693 uv: "Float32Array" 4694 }; 4695 } 4696 setDecoderPath(path) { 4697 this.decoderPath = path; 4698 return this; 4699 } 4700 setDecoderConfig(config) { 4701 this.decoderConfig = config; 4702 return this; 4703 } 4704 setWorkerLimit(workerLimit) { 4705 this.workerLimit = workerLimit; 4706 return this; 4707 } 4708 load(url, onLoad, onProgress, onError) { 4709 const loader = new FileLoader(this.manager); 4710 loader.setPath(this.path); 4711 loader.setResponseType("arraybuffer"); 4712 loader.setRequestHeader(this.requestHeader); 4713 loader.setWithCredentials(this.withCredentials); 4714 loader.load( 4715 url, 4716 (buffer) => { 4717 const taskConfig = { 4718 attributeIDs: this.defaultAttributeIDs, 4719 attributeTypes: this.defaultAttributeTypes, 4720 useUniqueIDs: false 4721 }; 4722 this.decodeGeometry(buffer, taskConfig).then(onLoad).catch(onError); 4723 }, 4724 onProgress, 4725 onError 4726 ); 4727 } 4728 /** @deprecated Kept for backward-compatibility with previous DRACOLoader versions. */ 4729 decodeDracoFile(buffer, callback, attributeIDs, attributeTypes) { 4730 const taskConfig = { 4731 attributeIDs: attributeIDs || this.defaultAttributeIDs, 4732 attributeTypes: attributeTypes || this.defaultAttributeTypes, 4733 useUniqueIDs: !!attributeIDs 4734 }; 4735 this.decodeGeometry(buffer, taskConfig).then(callback); 4736 } 4737 decodeGeometry(buffer, taskConfig) { 4738 for (const attribute in taskConfig.attributeTypes) { 4739 const type = taskConfig.attributeTypes[attribute]; 4740 if (type.BYTES_PER_ELEMENT !== void 0) { 4741 taskConfig.attributeTypes[attribute] = type.name; 4742 } 4743 } 4744 const taskKey = JSON.stringify(taskConfig); 4745 if (_taskCache.has(buffer)) { 4746 const cachedTask = _taskCache.get(buffer); 4747 if (cachedTask.key === taskKey) { 4748 return cachedTask.promise; 4749 } else if (buffer.byteLength === 0) { 4750 throw new Error( 4751 "THREE.DRACOLoader: Unable to re-decode a buffer with different settings. Buffer has already been transferred." 4752 ); 4753 } 4754 } 4755 let worker; 4756 const taskID = this.workerNextTaskID++; 4757 const taskCost = buffer.byteLength; 4758 const geometryPending = this._getWorker(taskID, taskCost).then((_worker) => { 4759 worker = _worker; 4760 return new Promise((resolve3, reject) => { 4761 worker._callbacks[taskID] = { resolve: resolve3, reject }; 4762 worker.postMessage({ type: "decode", id: taskID, taskConfig, buffer }, [buffer]); 4763 }); 4764 }).then((message) => this._createGeometry(message.geometry)); 4765 geometryPending.catch(() => true).then(() => { 4766 if (worker && taskID) { 4767 this._releaseTask(worker, taskID); 4768 } 4769 }); 4770 _taskCache.set(buffer, { 4771 key: taskKey, 4772 promise: geometryPending 4773 }); 4774 return geometryPending; 4775 } 4776 _createGeometry(geometryData) { 4777 const geometry = new BufferGeometry(); 4778 if (geometryData.index) { 4779 geometry.setIndex(new BufferAttribute(geometryData.index.array, 1)); 4780 } 4781 for (let i = 0; i < geometryData.attributes.length; i++) { 4782 const attribute = geometryData.attributes[i]; 4783 const name = attribute.name; 4784 const array = attribute.array; 4785 const itemSize = attribute.itemSize; 4786 geometry.setAttribute(name, new BufferAttribute(array, itemSize)); 4787 } 4788 return geometry; 4789 } 4790 _loadLibrary(url, responseType) { 4791 const loader = new FileLoader(this.manager); 4792 loader.setPath(this.decoderPath); 4793 loader.setResponseType(responseType); 4794 loader.setWithCredentials(this.withCredentials); 4795 return new Promise((resolve3, reject) => { 4796 loader.load(url, resolve3, void 0, reject); 4797 }); 4798 } 4799 preload() { 4800 this._initDecoder(); 4801 return this; 4802 } 4803 _initDecoder() { 4804 if (this.decoderPending) 4805 return this.decoderPending; 4806 const useJS = typeof WebAssembly !== "object" || this.decoderConfig.type === "js"; 4807 const librariesPending = []; 4808 if (useJS) { 4809 librariesPending.push(this._loadLibrary("draco_decoder.js", "text")); 4810 } else { 4811 librariesPending.push(this._loadLibrary("draco_wasm_wrapper.js", "text")); 4812 librariesPending.push(this._loadLibrary("draco_decoder.wasm", "arraybuffer")); 4813 } 4814 this.decoderPending = Promise.all(librariesPending).then((libraries) => { 4815 const jsContent = libraries[0]; 4816 if (!useJS) { 4817 this.decoderConfig.wasmBinary = libraries[1]; 4818 } 4819 const fn = DRACOWorker.toString(); 4820 const body = [ 4821 "/* draco decoder */", 4822 jsContent, 4823 "", 4824 "/* worker */", 4825 fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}")) 4826 ].join("\n"); 4827 this.workerSourceURL = URL.createObjectURL(new Blob([body])); 4828 }); 4829 return this.decoderPending; 4830 } 4831 _getWorker(taskID, taskCost) { 4832 return this._initDecoder().then(() => { 4833 if (this.workerPool.length < this.workerLimit) { 4834 const worker2 = new Worker(this.workerSourceURL); 4835 worker2._callbacks = {}; 4836 worker2._taskCosts = {}; 4837 worker2._taskLoad = 0; 4838 worker2.postMessage({ type: "init", decoderConfig: this.decoderConfig }); 4839 worker2.onmessage = function(e) { 4840 const message = e.data; 4841 switch (message.type) { 4842 case "decode": 4843 worker2._callbacks[message.id].resolve(message); 4844 break; 4845 case "error": 4846 worker2._callbacks[message.id].reject(message); 4847 break; 4848 default: 4849 console.error('THREE.DRACOLoader: Unexpected message, "' + message.type + '"'); 4850 } 4851 }; 4852 this.workerPool.push(worker2); 4853 } else { 4854 this.workerPool.sort(function(a, b) { 4855 return a._taskLoad > b._taskLoad ? -1 : 1; 4856 }); 4857 } 4858 const worker = this.workerPool[this.workerPool.length - 1]; 4859 worker._taskCosts[taskID] = taskCost; 4860 worker._taskLoad += taskCost; 4861 return worker; 4862 }); 4863 } 4864 _releaseTask(worker, taskID) { 4865 worker._taskLoad -= worker._taskCosts[taskID]; 4866 delete worker._callbacks[taskID]; 4867 delete worker._taskCosts[taskID]; 4868 } 4869 debug() { 4870 console.log( 4871 "Task load: ", 4872 this.workerPool.map((worker) => worker._taskLoad) 4873 ); 4874 } 4875 dispose() { 4876 for (let i = 0; i < this.workerPool.length; ++i) { 4877 this.workerPool[i].terminate(); 4878 } 4879 this.workerPool.length = 0; 4880 return this; 4881 } 4882}; 4883function DRACOWorker() { 4884 let decoderConfig; 4885 let decoderPending; 4886 onmessage = function(e) { 4887 const message = e.data; 4888 switch (message.type) { 4889 case "init": 4890 decoderConfig = message.decoderConfig; 4891 decoderPending = new Promise(function(resolve3) { 4892 decoderConfig.onModuleLoaded = function(draco) { 4893 resolve3({ draco }); 4894 }; 4895 DracoDecoderModule(decoderConfig); 4896 }); 4897 break; 4898 case "decode": 4899 const buffer = message.buffer; 4900 const taskConfig = message.taskConfig; 4901 decoderPending.then((module) => { 4902 const draco = module.draco; 4903 const decoder = new draco.Decoder(); 4904 const decoderBuffer = new draco.DecoderBuffer(); 4905 decoderBuffer.Init(new Int8Array(buffer), buffer.byteLength); 4906 try { 4907 const geometry = decodeGeometry(draco, decoder, decoderBuffer, taskConfig); 4908 const buffers = geometry.attributes.map((attr) => attr.array.buffer); 4909 if (geometry.index) 4910 buffers.push(geometry.index.array.buffer); 4911 self.postMessage({ type: "decode", id: message.id, geometry }, buffers); 4912 } catch (error) { 4913 console.error(error); 4914 self.postMessage({ type: "error", id: message.id, error: error.message }); 4915 } finally { 4916 draco.destroy(decoderBuffer); 4917 draco.destroy(decoder); 4918 } 4919 }); 4920 break; 4921 } 4922 }; 4923 function decodeGeometry(draco, decoder, decoderBuffer, taskConfig) { 4924 const attributeIDs = taskConfig.attributeIDs; 4925 const attributeTypes = taskConfig.attributeTypes; 4926 let dracoGeometry; 4927 let decodingStatus; 4928 const geometryType = decoder.GetEncodedGeometryType(decoderBuffer); 4929 if (geometryType === draco.TRIANGULAR_MESH) { 4930 dracoGeometry = new draco.Mesh(); 4931 decodingStatus = decoder.DecodeBufferToMesh(decoderBuffer, dracoGeometry); 4932 } else if (geometryType === draco.POINT_CLOUD) { 4933 dracoGeometry = new draco.PointCloud(); 4934 decodingStatus = decoder.DecodeBufferToPointCloud(decoderBuffer, dracoGeometry); 4935 } else { 4936 throw new Error("THREE.DRACOLoader: Unexpected geometry type."); 4937 } 4938 if (!decodingStatus.ok() || dracoGeometry.ptr === 0) { 4939 throw new Error("THREE.DRACOLoader: Decoding failed: " + decodingStatus.error_msg()); 4940 } 4941 const geometry = { index: null, attributes: [] }; 4942 for (const attributeName in attributeIDs) { 4943 const attributeType = self[attributeTypes[attributeName]]; 4944 let attribute; 4945 let attributeID; 4946 if (taskConfig.useUniqueIDs) { 4947 attributeID = attributeIDs[attributeName]; 4948 attribute = decoder.GetAttributeByUniqueId(dracoGeometry, attributeID); 4949 } else { 4950 attributeID = decoder.GetAttributeId(dracoGeometry, draco[attributeIDs[attributeName]]); 4951 if (attributeID === -1) 4952 continue; 4953 attribute = decoder.GetAttribute(dracoGeometry, attributeID); 4954 } 4955 geometry.attributes.push(decodeAttribute(draco, decoder, dracoGeometry, attributeName, attributeType, attribute)); 4956 } 4957 if (geometryType === draco.TRIANGULAR_MESH) { 4958 geometry.index = decodeIndex(draco, decoder, dracoGeometry); 4959 } 4960 draco.destroy(dracoGeometry); 4961 return geometry; 4962 } 4963 function decodeIndex(draco, decoder, dracoGeometry) { 4964 const numFaces = dracoGeometry.num_faces(); 4965 const numIndices = numFaces * 3; 4966 const byteLength = numIndices * 4; 4967 const ptr = draco._malloc(byteLength); 4968 decoder.GetTrianglesUInt32Array(dracoGeometry, byteLength, ptr); 4969 const index = new Uint32Array(draco.HEAPF32.buffer, ptr, numIndices).slice(); 4970 draco._free(ptr); 4971 return { array: index, itemSize: 1 }; 4972 } 4973 function decodeAttribute(draco, decoder, dracoGeometry, attributeName, attributeType, attribute) { 4974 const numComponents = attribute.num_components(); 4975 const numPoints = dracoGeometry.num_points(); 4976 const numValues = numPoints * numComponents; 4977 const byteLength = numValues * attributeType.BYTES_PER_ELEMENT; 4978 const dataType = getDracoDataType(draco, attributeType); 4979 const ptr = draco._malloc(byteLength); 4980 decoder.GetAttributeDataArrayForAllPoints(dracoGeometry, attribute, dataType, byteLength, ptr); 4981 const array = new attributeType(draco.HEAPF32.buffer, ptr, numValues).slice(); 4982 draco._free(ptr); 4983 return { 4984 name: attributeName, 4985 array, 4986 itemSize: numComponents 4987 }; 4988 } 4989 function getDracoDataType(draco, attributeType) { 4990 switch (attributeType) { 4991 case Float32Array: 4992 return draco.DT_FLOAT32; 4993 case Int8Array: 4994 return draco.DT_INT8; 4995 case Int16Array: 4996 return draco.DT_INT16; 4997 case Int32Array: 4998 return draco.DT_INT32; 4999 case Uint8Array: 5000 return draco.DT_UINT8; 5001 case Uint16Array: 5002 return draco.DT_UINT16; 5003 case Uint32Array: 5004 return draco.DT_UINT32; 5005 } 5006 } 5007} 5008
vendor: 4,484 bytes, lines 5009-5127
5009// node_modules/three-stdlib/renderers/CSS2DRenderer.js 5010var CSS2DObject = class extends Object3D { 5011 constructor(element = document.createElement("div")) { 5012 super(); 5013 this.isCSS2DObject = true; 5014 this.element = element; 5015 this.element.style.position = "absolute"; 5016 this.element.style.userSelect = "none"; 5017 this.element.setAttribute("draggable", false); 5018 this.center = new Vector2(0.5, 0.5); 5019 this.addEventListener("removed", function() { 5020 this.traverse(function(object) { 5021 if (object.element instanceof Element && object.element.parentNode !== null) { 5022 object.element.parentNode.removeChild(object.element); 5023 } 5024 }); 5025 }); 5026 } 5027 copy(source, recursive) { 5028 super.copy(source, recursive); 5029 this.element = source.element.cloneNode(true); 5030 this.center = source.center; 5031 return this; 5032 } 5033}; 5034var _vector = /* @__PURE__ */ new Vector3(); 5035var _viewMatrix = /* @__PURE__ */ new Matrix4(); 5036var _viewProjectionMatrix = /* @__PURE__ */ new Matrix4(); 5037var _a = /* @__PURE__ */ new Vector3(); 5038var _b = /* @__PURE__ */ new Vector3(); 5039var CSS2DRenderer = class { 5040 constructor(parameters = {}) { 5041 const _this = this; 5042 let _width, _height; 5043 let _widthHalf, _heightHalf; 5044 const cache = { 5045 objects: /* @__PURE__ */ new WeakMap() 5046 }; 5047 const domElement = parameters.element !== void 0 ? parameters.element : document.createElement("div"); 5048 domElement.style.overflow = "hidden"; 5049 this.domElement = domElement; 5050 this.getSize = function() { 5051 return { 5052 width: _width, 5053 height: _height 5054 }; 5055 }; 5056 this.render = function(scene, camera) { 5057 if (scene.matrixWorldAutoUpdate === true) 5058 scene.updateMatrixWorld(); 5059 if (camera.parent === null && camera.matrixWorldAutoUpdate === true) 5060 camera.updateMatrixWorld(); 5061 _viewMatrix.copy(camera.matrixWorldInverse); 5062 _viewProjectionMatrix.multiplyMatrices(camera.projectionMatrix, _viewMatrix); 5063 renderObject(scene, scene, camera); 5064 zOrder(scene); 5065 }; 5066 this.setSize = function(width, height) { 5067 _width = width; 5068 _height = height; 5069 _widthHalf = _width / 2; 5070 _heightHalf = _height / 2; 5071 domElement.style.width = width + "px"; 5072 domElement.style.height = height + "px"; 5073 }; 5074 function renderObject(object, scene, camera) { 5075 if (object.isCSS2DObject) { 5076 _vector.setFromMatrixPosition(object.matrixWorld); 5077 _vector.applyMatrix4(_viewProjectionMatrix); 5078 const visible = object.visible === true && _vector.z >= -1 && _vector.z <= 1 && object.layers.test(camera.layers) === true; 5079 object.element.style.display = visible === true ? "" : "none"; 5080 if (visible === true) { 5081 object.onBeforeRender(_this, scene, camera); 5082 const element = object.element; 5083 element.style.transform = "translate(" + -100 * object.center.x + "%," + -100 * object.center.y + "%)translate(" + (_vector.x * _widthHalf + _widthHalf) + "px," + (-_vector.y * _heightHalf + _heightHalf) + "px)"; 5084 if (element.parentNode !== domElement) { 5085 domElement.appendChild(element); 5086 } 5087 object.onAfterRender(_this, scene, camera); 5088 } 5089 const objectData = { 5090 distanceToCameraSquared: getDistanceToSquared(camera, object) 5091 }; 5092 cache.objects.set(object, objectData); 5093 } 5094 for (let i = 0, l = object.children.length; i < l; i++) { 5095 renderObject(object.children[i], scene, camera); 5096 } 5097 } 5098 function getDistanceToSquared(object1, object2) { 5099 _a.setFromMatrixPosition(object1.matrixWorld); 5100 _b.setFromMatrixPosition(object2.matrixWorld); 5101 return _a.distanceToSquared(_b); 5102 } 5103 function filterAndFlatten(scene) { 5104 const result = []; 5105 scene.traverse(function(object) { 5106 if (object.isCSS2DObject) 5107 result.push(object); 5108 }); 5109 return result; 5110 } 5111 function zOrder(scene) { 5112 const sorted = filterAndFlatten(scene).sort(function(a, b) { 5113 if (a.renderOrder !== b.renderOrder) { 5114 return b.renderOrder - a.renderOrder; 5115 } 5116 const distanceA = cache.objects.get(a).distanceToCameraSquared; 5117 const distanceB = cache.objects.get(b).distanceToCameraSquared; 5118 return distanceA - distanceB; 5119 }); 5120 const zMax = sorted.length; 5121 for (let i = 0, l = sorted.length; i < l; i++) { 5122 sorted[i].element.style.zIndex = zMax - i; 5123 } 5124 } 5125 } 5126}; 5127
vendor: 70,814 bytes, lines 5128-7049
5128// node_modules/three-stdlib/exporters/GLTFExporter.js 5129var __defProp = Object.defineProperty; 5130var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; 5131var __publicField = (obj, key, value) => { 5132 __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); 5133 return value; 5134}; 5135async function readAsDataURL(blob) { 5136 const buffer = await blob.arrayBuffer(); 5137 const data = btoa(String.fromCharCode(...new Uint8Array(buffer))); 5138 return `data:${blob.type || ""};base64,${data}`; 5139} 5140var _renderer; 5141var fullscreenQuadGeometry; 5142var fullscreenQuadMaterial; 5143var fullscreenQuad; 5144function decompress(texture, maxTextureSize = Infinity, renderer = null) { 5145 if (!fullscreenQuadGeometry) 5146 fullscreenQuadGeometry = new PlaneGeometry(2, 2, 1, 1); 5147 if (!fullscreenQuadMaterial) 5148 fullscreenQuadMaterial = new ShaderMaterial({ 5149 uniforms: { blitTexture: new Uniform(texture) }, 5150 vertexShader: ( 5151 /* glsl */ 5152 ` 5153 varying vec2 vUv; 5154 void main(){ 5155 vUv = uv; 5156 gl_Position = vec4(position.xy * 1.0,0.,.999999); 5157 } 5158 ` 5159 ), 5160 fragmentShader: ( 5161 /* glsl */ 5162 ` 5163 uniform sampler2D blitTexture; 5164 varying vec2 vUv; 5165 5166 void main(){ 5167 gl_FragColor = vec4(vUv.xy, 0, 1); 5168 5169 #ifdef IS_SRGB 5170 gl_FragColor = LinearTosRGB( texture2D( blitTexture, vUv) ); 5171 #else 5172 gl_FragColor = texture2D( blitTexture, vUv); 5173 #endif 5174 } 5175 ` 5176 ) 5177 }); 5178 fullscreenQuadMaterial.uniforms.blitTexture.value = texture; 5179 fullscreenQuadMaterial.defines.IS_SRGB = "colorSpace" in texture ? texture.colorSpace === "srgb" : texture.encoding === 3001; 5180 fullscreenQuadMaterial.needsUpdate = true; 5181 if (!fullscreenQuad) { 5182 fullscreenQuad = new Mesh(fullscreenQuadGeometry, fullscreenQuadMaterial); 5183 fullscreenQuad.frustrumCulled = false; 5184 } 5185 const _camera = new PerspectiveCamera(); 5186 const _scene = new Scene(); 5187 _scene.add(fullscreenQuad); 5188 if (!renderer) { 5189 renderer = _renderer = new WebGLRenderer({ antialias: false }); 5190 } 5191 renderer.setSize(Math.min(texture.image.width, maxTextureSize), Math.min(texture.image.height, maxTextureSize)); 5192 renderer.clear(); 5193 renderer.render(_scene, _camera); 5194 const readableTexture = new Texture(renderer.domElement); 5195 readableTexture.minFilter = texture.minFilter; 5196 readableTexture.magFilter = texture.magFilter; 5197 readableTexture.wrapS = texture.wrapS; 5198 readableTexture.wrapT = texture.wrapT; 5199 readableTexture.name = texture.name; 5200 if (_renderer) { 5201 _renderer.dispose(); 5202 _renderer = null; 5203 } 5204 return readableTexture; 5205} 5206var KHR_mesh_quantization_ExtraAttrTypes = { 5207 POSITION: [ 5208 "byte", 5209 "byte normalized", 5210 "unsigned byte", 5211 "unsigned byte normalized", 5212 "short", 5213 "short normalized", 5214 "unsigned short", 5215 "unsigned short normalized" 5216 ], 5217 NORMAL: ["byte normalized", "short normalized"], 5218 TANGENT: ["byte normalized", "short normalized"], 5219 TEXCOORD: ["byte", "byte normalized", "unsigned byte", "short", "short normalized", "unsigned short"] 5220}; 5221var GLTFExporter = /* @__PURE__ */ (() => { 5222 class GLTFExporter2 { 5223 constructor() { 5224 this.pluginCallbacks = []; 5225 this.register(function(writer) { 5226 return new GLTFLightExtension(writer); 5227 }); 5228 this.register(function(writer) { 5229 return new GLTFMaterialsUnlitExtension2(writer); 5230 }); 5231 this.register(function(writer) { 5232 return new GLTFMaterialsTransmissionExtension2(writer); 5233 }); 5234 this.register(function(writer) { 5235 return new GLTFMaterialsVolumeExtension2(writer); 5236 }); 5237 this.register(function(writer) { 5238 return new GLTFMaterialsIorExtension2(writer); 5239 }); 5240 this.register(function(writer) { 5241 return new GLTFMaterialsSpecularExtension2(writer); 5242 }); 5243 this.register(function(writer) { 5244 return new GLTFMaterialsClearcoatExtension2(writer); 5245 }); 5246 this.register(function(writer) { 5247 return new GLTFMaterialsIridescenceExtension2(writer); 5248 }); 5249 this.register(function(writer) { 5250 return new GLTFMaterialsSheenExtension2(writer); 5251 }); 5252 this.register(function(writer) { 5253 return new GLTFMaterialsAnisotropyExtension2(writer); 5254 }); 5255 this.register(function(writer) { 5256 return new GLTFMaterialsEmissiveStrengthExtension2(writer); 5257 }); 5258 } 5259 register(callback) { 5260 if (this.pluginCallbacks.indexOf(callback) === -1) { 5261 this.pluginCallbacks.push(callback); 5262 } 5263 return this; 5264 } 5265 unregister(callback) { 5266 if (this.pluginCallbacks.indexOf(callback) !== -1) { 5267 this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(callback), 1); 5268 } 5269 return this; 5270 } 5271 /** 5272 * Parse scenes and generate GLTF output 5273 * @param {Scene or [THREE.Scenes]} input Scene or Array of THREE.Scenes 5274 * @param {Function} onDone Callback on completed 5275 * @param {Function} onError Callback on errors 5276 * @param {Object} options options 5277 */ 5278 parse(input, onDone, onError, options) { 5279 const writer = new GLTFWriter(); 5280 const plugins = []; 5281 for (let i = 0, il = this.pluginCallbacks.length; i < il; i++) { 5282 plugins.push(this.pluginCallbacks[i](writer)); 5283 } 5284 writer.setPlugins(plugins); 5285 writer.write(input, onDone, options).catch(onError); 5286 } 5287 parseAsync(input, options) { 5288 const scope = this; 5289 return new Promise(function(resolve3, reject) { 5290 scope.parse(input, resolve3, reject, options); 5291 }); 5292 } 5293 } 5294 __publicField(GLTFExporter2, "Utils", { 5295 insertKeyframe: function(track, time) { 5296 const tolerance = 1e-3; 5297 const valueSize = track.getValueSize(); 5298 const times = new track.TimeBufferType(track.times.length + 1); 5299 const values = new track.ValueBufferType(track.values.length + valueSize); 5300 const interpolant = track.createInterpolant(new track.ValueBufferType(valueSize)); 5301 let index; 5302 if (track.times.length === 0) { 5303 times[0] = time; 5304 for (let i = 0; i < valueSize; i++) { 5305 values[i] = 0; 5306 } 5307 index = 0; 5308 } else if (time < track.times[0]) { 5309 if (Math.abs(track.times[0] - time) < tolerance) 5310 return 0; 5311 times[0] = time; 5312 times.set(track.times, 1); 5313 values.set(interpolant.evaluate(time), 0); 5314 values.set(track.values, valueSize); 5315 index = 0; 5316 } else if (time > track.times[track.times.length - 1]) { 5317 if (Math.abs(track.times[track.times.length - 1] - time) < tolerance) { 5318 return track.times.length - 1; 5319 } 5320 times[times.length - 1] = time; 5321 times.set(track.times, 0); 5322 values.set(track.values, 0); 5323 values.set(interpolant.evaluate(time), track.values.length); 5324 index = times.length - 1; 5325 } else { 5326 for (let i = 0; i < track.times.length; i++) { 5327 if (Math.abs(track.times[i] - time) < tolerance) 5328 return i; 5329 if (track.times[i] < time && track.times[i + 1] > time) { 5330 times.set(track.times.slice(0, i + 1), 0); 5331 times[i + 1] = time; 5332 times.set(track.times.slice(i + 1), i + 2); 5333 values.set(track.values.slice(0, (i + 1) * valueSize), 0); 5334 values.set(interpolant.evaluate(time), (i + 1) * valueSize); 5335 values.set(track.values.slice((i + 1) * valueSize), (i + 2) * valueSize); 5336 index = i + 1; 5337 break; 5338 } 5339 } 5340 } 5341 track.times = times; 5342 track.values = values; 5343 return index; 5344 }, 5345 mergeMorphTargetTracks: function(clip, root) { 5346 const tracks = []; 5347 const mergedTracks = {}; 5348 const sourceTracks = clip.tracks; 5349 for (let i = 0; i < sourceTracks.length; ++i) { 5350 let sourceTrack = sourceTracks[i]; 5351 const sourceTrackBinding = PropertyBinding.parseTrackName(sourceTrack.name); 5352 const sourceTrackNode = PropertyBinding.findNode(root, sourceTrackBinding.nodeName); 5353 if (sourceTrackBinding.propertyName !== "morphTargetInfluences" || sourceTrackBinding.propertyIndex === void 0) { 5354 tracks.push(sourceTrack); 5355 continue; 5356 } 5357 if (sourceTrack.createInterpolant !== sourceTrack.InterpolantFactoryMethodDiscrete && sourceTrack.createInterpolant !== sourceTrack.InterpolantFactoryMethodLinear) { 5358 if (sourceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline) { 5359 throw new Error("THREE.GLTFExporter: Cannot merge tracks with glTF CUBICSPLINE interpolation."); 5360 } 5361 console.warn("THREE.GLTFExporter: Morph target interpolation mode not yet supported. Using LINEAR instead."); 5362 sourceTrack = sourceTrack.clone(); 5363 sourceTrack.setInterpolation(InterpolateLinear); 5364 } 5365 const targetCount = sourceTrackNode.morphTargetInfluences.length; 5366 const targetIndex = sourceTrackNode.morphTargetDictionary[sourceTrackBinding.propertyIndex]; 5367 if (targetIndex === void 0) { 5368 throw new Error("THREE.GLTFExporter: Morph target name not found: " + sourceTrackBinding.propertyIndex); 5369 } 5370 let mergedTrack; 5371 if (mergedTracks[sourceTrackNode.uuid] === void 0) { 5372 mergedTrack = sourceTrack.clone(); 5373 const values = new mergedTrack.ValueBufferType(targetCount * mergedTrack.times.length); 5374 for (let j = 0; j < mergedTrack.times.length; j++) { 5375 values[j * targetCount + targetIndex] = mergedTrack.values[j]; 5376 } 5377 mergedTrack.name = (sourceTrackBinding.nodeName || "") + ".morphTargetInfluences"; 5378 mergedTrack.values = values; 5379 mergedTracks[sourceTrackNode.uuid] = mergedTrack; 5380 tracks.push(mergedTrack); 5381 continue; 5382 } 5383 const sourceInterpolant = sourceTrack.createInterpolant(new sourceTrack.ValueBufferType(1)); 5384 mergedTrack = mergedTracks[sourceTrackNode.uuid]; 5385 for (let j = 0; j < mergedTrack.times.length; j++) { 5386 mergedTrack.values[j * targetCount + targetIndex] = sourceInterpolant.evaluate(mergedTrack.times[j]); 5387 } 5388 for (let j = 0; j < sourceTrack.times.length; j++) { 5389 const keyframeIndex = this.insertKeyframe(mergedTrack, sourceTrack.times[j]); 5390 mergedTrack.values[keyframeIndex * targetCount + targetIndex] = sourceTrack.values[j]; 5391 } 5392 } 5393 clip.tracks = tracks; 5394 return clip; 5395 } 5396 }); 5397 return GLTFExporter2; 5398})(); 5399var WEBGL_CONSTANTS2 = { 5400 POINTS: 0, 5401 LINES: 1, 5402 LINE_LOOP: 2, 5403 LINE_STRIP: 3, 5404 TRIANGLES: 4, 5405 TRIANGLE_STRIP: 5, 5406 TRIANGLE_FAN: 6, 5407 BYTE: 5120, 5408 UNSIGNED_BYTE: 5121, 5409 SHORT: 5122, 5410 UNSIGNED_SHORT: 5123, 5411 INT: 5124, 5412 UNSIGNED_INT: 5125, 5413 FLOAT: 5126, 5414 ARRAY_BUFFER: 34962, 5415 ELEMENT_ARRAY_BUFFER: 34963, 5416 NEAREST: 9728, 5417 LINEAR: 9729, 5418 NEAREST_MIPMAP_NEAREST: 9984, 5419 LINEAR_MIPMAP_NEAREST: 9985, 5420 NEAREST_MIPMAP_LINEAR: 9986, 5421 LINEAR_MIPMAP_LINEAR: 9987, 5422 CLAMP_TO_EDGE: 33071, 5423 MIRRORED_REPEAT: 33648, 5424 REPEAT: 10497 5425}; 5426var KHR_MESH_QUANTIZATION = "KHR_mesh_quantization"; 5427var THREE_TO_WEBGL = {}; 5428THREE_TO_WEBGL[NearestFilter] = WEBGL_CONSTANTS2.NEAREST; 5429THREE_TO_WEBGL[NearestMipmapNearestFilter] = WEBGL_CONSTANTS2.NEAREST_MIPMAP_NEAREST; 5430THREE_TO_WEBGL[NearestMipmapLinearFilter] = WEBGL_CONSTANTS2.NEAREST_MIPMAP_LINEAR; 5431THREE_TO_WEBGL[LinearFilter] = WEBGL_CONSTANTS2.LINEAR; 5432THREE_TO_WEBGL[LinearMipmapNearestFilter] = WEBGL_CONSTANTS2.LINEAR_MIPMAP_NEAREST; 5433THREE_TO_WEBGL[LinearMipmapLinearFilter] = WEBGL_CONSTANTS2.LINEAR_MIPMAP_LINEAR; 5434THREE_TO_WEBGL[ClampToEdgeWrapping] = WEBGL_CONSTANTS2.CLAMP_TO_EDGE; 5435THREE_TO_WEBGL[RepeatWrapping] = WEBGL_CONSTANTS2.REPEAT; 5436THREE_TO_WEBGL[MirroredRepeatWrapping] = WEBGL_CONSTANTS2.MIRRORED_REPEAT; 5437var PATH_PROPERTIES2 = { 5438 scale: "scale", 5439 position: "translation", 5440 quaternion: "rotation", 5441 morphTargetInfluences: "weights" 5442}; 5443var DEFAULT_SPECULAR_COLOR = /* @__PURE__ */ new Color(); 5444var GLB_HEADER_BYTES = 12; 5445var GLB_HEADER_MAGIC = 1179937895; 5446var GLB_VERSION = 2; 5447var GLB_CHUNK_PREFIX_BYTES = 8; 5448var GLB_CHUNK_TYPE_JSON = 1313821514; 5449var GLB_CHUNK_TYPE_BIN = 5130562; 5450function equalArray(array1, array2) { 5451 return array1.length === array2.length && array1.every(function(element, index) { 5452 return element === array2[index]; 5453 }); 5454} 5455function stringToArrayBuffer(text) { 5456 return new TextEncoder().encode(text).buffer; 5457} 5458function isIdentityMatrix(matrix) { 5459 return equalArray(matrix.elements, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); 5460} 5461function getMinMax(attribute, start, count) { 5462 const output = { 5463 min: new Array(attribute.itemSize).fill(Number.POSITIVE_INFINITY), 5464 max: new Array(attribute.itemSize).fill(Number.NEGATIVE_INFINITY) 5465 }; 5466 for (let i = start; i < start + count; i++) { 5467 for (let a = 0; a < attribute.itemSize; a++) { 5468 let value; 5469 if (attribute.itemSize > 4) { 5470 value = attribute.array[i * attribute.itemSize + a]; 5471 } else { 5472 if (a === 0) 5473 value = attribute.getX(i); 5474 else if (a === 1) 5475 value = attribute.getY(i); 5476 else if (a === 2) 5477 value = attribute.getZ(i); 5478 else if (a === 3) 5479 value = attribute.getW(i); 5480 if (attribute.normalized === true) { 5481 value = MathUtils.normalize(value, attribute.array); 5482 } 5483 } 5484 output.min[a] = Math.min(output.min[a], value); 5485 output.max[a] = Math.max(output.max[a], value); 5486 } 5487 } 5488 return output; 5489} 5490function getPaddedBufferSize(bufferSize) { 5491 return Math.ceil(bufferSize / 4) * 4; 5492} 5493function getPaddedArrayBuffer(arrayBuffer, paddingByte = 0) { 5494 const paddedLength = getPaddedBufferSize(arrayBuffer.byteLength); 5495 if (paddedLength !== arrayBuffer.byteLength) { 5496 const array = new Uint8Array(paddedLength); 5497 array.set(new Uint8Array(arrayBuffer)); 5498 if (paddingByte !== 0) { 5499 for (let i = arrayBuffer.byteLength; i < paddedLength; i++) { 5500 array[i] = paddingByte; 5501 } 5502 } 5503 return array.buffer; 5504 } 5505 return arrayBuffer; 5506} 5507function getCanvas() { 5508 if (typeof document === "undefined" && typeof OffscreenCanvas !== "undefined") { 5509 return new OffscreenCanvas(1, 1); 5510 } 5511 return document.createElement("canvas"); 5512} 5513function getToBlobPromise(canvas, mimeType) { 5514 if (canvas.toBlob !== void 0) { 5515 return new Promise((resolve3) => canvas.toBlob(resolve3, mimeType)); 5516 } 5517 let quality; 5518 if (mimeType === "image/jpeg") { 5519 quality = 0.92; 5520 } else if (mimeType === "image/webp") { 5521 quality = 0.8; 5522 } 5523 return canvas.convertToBlob({ 5524 type: mimeType, 5525 quality 5526 }); 5527} 5528var GLTFWriter = class { 5529 constructor() { 5530 this.plugins = []; 5531 this.options = {}; 5532 this.pending = []; 5533 this.buffers = []; 5534 this.byteOffset = 0; 5535 this.buffers = []; 5536 this.nodeMap = /* @__PURE__ */ new Map(); 5537 this.skins = []; 5538 this.extensionsUsed = {}; 5539 this.extensionsRequired = {}; 5540 this.uids = /* @__PURE__ */ new Map(); 5541 this.uid = 0; 5542 this.json = { 5543 asset: { 5544 version: "2.0", 5545 generator: "THREE.GLTFExporter" 5546 } 5547 }; 5548 this.cache = { 5549 meshes: /* @__PURE__ */ new Map(), 5550 attributes: /* @__PURE__ */ new Map(), 5551 attributesNormalized: /* @__PURE__ */ new Map(), 5552 materials: /* @__PURE__ */ new Map(), 5553 textures: /* @__PURE__ */ new Map(), 5554 images: /* @__PURE__ */ new Map() 5555 }; 5556 } 5557 setPlugins(plugins) { 5558 this.plugins = plugins; 5559 } 5560 /** 5561 * Parse scenes and generate GLTF output 5562 * @param {Scene or [THREE.Scenes]} input Scene or Array of THREE.Scenes 5563 * @param {Function} onDone Callback on completed 5564 * @param {Object} options options 5565 */ 5566 async write(input, onDone, options = {}) { 5567 this.options = Object.assign( 5568 { 5569 // default options 5570 binary: false, 5571 trs: false, 5572 onlyVisible: true, 5573 maxTextureSize: Infinity, 5574 animations: [], 5575 includeCustomExtensions: false 5576 }, 5577 options 5578 ); 5579 if (this.options.animations.length > 0) { 5580 this.options.trs = true; 5581 } 5582 this.processInput(input); 5583 await Promise.all(this.pending); 5584 const writer = this; 5585 const buffers = writer.buffers; 5586 const json = writer.json; 5587 options = writer.options; 5588 const extensionsUsed = writer.extensionsUsed; 5589 const extensionsRequired = writer.extensionsRequired; 5590 const blob = new Blob(buffers, { type: "application/octet-stream" }); 5591 const extensionsUsedList = Object.keys(extensionsUsed); 5592 const extensionsRequiredList = Object.keys(extensionsRequired); 5593 if (extensionsUsedList.length > 0) 5594 json.extensionsUsed = extensionsUsedList; 5595 if (extensionsRequiredList.length > 0) 5596 json.extensionsRequired = extensionsRequiredList; 5597 if (json.buffers && json.buffers.length > 0) 5598 json.buffers[0].byteLength = blob.size; 5599 if (options.binary === true) { 5600 blob.arrayBuffer().then((result) => { 5601 const binaryChunk = getPaddedArrayBuffer(result); 5602 const binaryChunkPrefix = new DataView(new ArrayBuffer(GLB_CHUNK_PREFIX_BYTES)); 5603 binaryChunkPrefix.setUint32(0, binaryChunk.byteLength, true); 5604 binaryChunkPrefix.setUint32(4, GLB_CHUNK_TYPE_BIN, true); 5605 const jsonChunk = getPaddedArrayBuffer(stringToArrayBuffer(JSON.stringify(json)), 32); 5606 const jsonChunkPrefix = new DataView(new ArrayBuffer(GLB_CHUNK_PREFIX_BYTES)); 5607 jsonChunkPrefix.setUint32(0, jsonChunk.byteLength, true); 5608 jsonChunkPrefix.setUint32(4, GLB_CHUNK_TYPE_JSON, true); 5609 const header = new ArrayBuffer(GLB_HEADER_BYTES); 5610 const headerView = new DataView(header); 5611 headerView.setUint32(0, GLB_HEADER_MAGIC, true); 5612 headerView.setUint32(4, GLB_VERSION, true); 5613 const totalByteLength = GLB_HEADER_BYTES + jsonChunkPrefix.byteLength + jsonChunk.byteLength + binaryChunkPrefix.byteLength + binaryChunk.byteLength; 5614 headerView.setUint32(8, totalByteLength, true); 5615 const glbBlob = new Blob([header, jsonChunkPrefix, jsonChunk, binaryChunkPrefix, binaryChunk], { 5616 type: "application/octet-stream" 5617 }); 5618 glbBlob.arrayBuffer().then(onDone); 5619 }); 5620 } else { 5621 if (json.buffers && json.buffers.length > 0) { 5622 readAsDataURL(blob).then((uri) => { 5623 json.buffers[0].uri = uri; 5624 onDone(json); 5625 }); 5626 } else { 5627 onDone(json); 5628 } 5629 } 5630 } 5631 /** 5632 * Serializes a userData. 5633 * 5634 * @param {THREE.Object3D|THREE.Material} object 5635 * @param {Object} objectDef 5636 */ 5637 serializeUserData(object, objectDef) { 5638 if (Object.keys(object.userData).length === 0) 5639 return; 5640 const options = this.options; 5641 const extensionsUsed = this.extensionsUsed; 5642 try { 5643 const json = JSON.parse(JSON.stringify(object.userData)); 5644 if (options.includeCustomExtensions && json.gltfExtensions) { 5645 if (objectDef.extensions === void 0) 5646 objectDef.extensions = {}; 5647 for (const extensionName in json.gltfExtensions) { 5648 objectDef.extensions[extensionName] = json.gltfExtensions[extensionName]; 5649 extensionsUsed[extensionName] = true; 5650 } 5651 delete json.gltfExtensions; 5652 } 5653 if (Object.keys(json).length > 0) 5654 objectDef.extras = json; 5655 } catch (error) { 5656 console.warn( 5657 "THREE.GLTFExporter: userData of '" + object.name + "' won't be serialized because of JSON.stringify error - " + error.message 5658 ); 5659 } 5660 } 5661 /** 5662 * Returns ids for buffer attributes. 5663 * @param {Object} object 5664 * @return {Integer} 5665 */ 5666 getUID(attribute, isRelativeCopy = false) { 5667 if (this.uids.has(attribute) === false) { 5668 const uids2 = /* @__PURE__ */ new Map(); 5669 uids2.set(true, this.uid++); 5670 uids2.set(false, this.uid++); 5671 this.uids.set(attribute, uids2); 5672 } 5673 const uids = this.uids.get(attribute); 5674 return uids.get(isRelativeCopy); 5675 } 5676 /** 5677 * Checks if normal attribute values are normalized. 5678 * 5679 * @param {BufferAttribute} normal 5680 * @returns {Boolean} 5681 */ 5682 isNormalizedNormalAttribute(normal) { 5683 const cache = this.cache; 5684 if (cache.attributesNormalized.has(normal)) 5685 return false; 5686 const v = new Vector3(); 5687 for (let i = 0, il = normal.count; i < il; i++) { 5688 if (Math.abs(v.fromBufferAttribute(normal, i).length() - 1) > 5e-4) 5689 return false; 5690 } 5691 return true; 5692 } 5693 /** 5694 * Creates normalized normal buffer attribute. 5695 * 5696 * @param {BufferAttribute} normal 5697 * @returns {BufferAttribute} 5698 * 5699 */ 5700 createNormalizedNormalAttribute(normal) { 5701 const cache = this.cache; 5702 if (cache.attributesNormalized.has(normal)) 5703 return cache.attributesNormalized.get(normal); 5704 const attribute = normal.clone(); 5705 const v = new Vector3(); 5706 for (let i = 0, il = attribute.count; i < il; i++) { 5707 v.fromBufferAttribute(attribute, i); 5708 if (v.x === 0 && v.y === 0 && v.z === 0) { 5709 v.setX(1); 5710 } else { 5711 v.normalize(); 5712 } 5713 attribute.setXYZ(i, v.x, v.y, v.z); 5714 } 5715 cache.attributesNormalized.set(normal, attribute); 5716 return attribute; 5717 } 5718 /** 5719 * Applies a texture transform, if present, to the map definition. Requires 5720 * the KHR_texture_transform extension. 5721 * 5722 * @param {Object} mapDef 5723 * @param {THREE.Texture} texture 5724 */ 5725 applyTextureTransform(mapDef, texture) { 5726 let didTransform = false; 5727 const transformDef = {}; 5728 if (texture.offset.x !== 0 || texture.offset.y !== 0) { 5729 transformDef.offset = texture.offset.toArray(); 5730 didTransform = true; 5731 } 5732 if (texture.rotation !== 0) { 5733 transformDef.rotation = texture.rotation; 5734 didTransform = true; 5735 } 5736 if (texture.repeat.x !== 1 || texture.repeat.y !== 1) { 5737 transformDef.scale = texture.repeat.toArray(); 5738 didTransform = true; 5739 } 5740 if (didTransform) { 5741 mapDef.extensions = mapDef.extensions || {}; 5742 mapDef.extensions["KHR_texture_transform"] = transformDef; 5743 this.extensionsUsed["KHR_texture_transform"] = true; 5744 } 5745 } 5746 buildMetalRoughTexture(metalnessMap, roughnessMap) { 5747 if (metalnessMap === roughnessMap) 5748 return metalnessMap; 5749 function getEncodingConversion(map) { 5750 if ("colorSpace" in map ? map.colorSpace === "srgb" : map.encoding === 3001) { 5751 return function SRGBToLinear(c) { 5752 return c < 0.04045 ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4); 5753 }; 5754 } 5755 return function LinearToLinear(c) { 5756 return c; 5757 }; 5758 } 5759 console.warn("THREE.GLTFExporter: Merged metalnessMap and roughnessMap textures."); 5760 if (metalnessMap instanceof CompressedTexture) { 5761 metalnessMap = decompress(metalnessMap); 5762 } 5763 if (roughnessMap instanceof CompressedTexture) { 5764 roughnessMap = decompress(roughnessMap); 5765 } 5766 const metalness = metalnessMap ? metalnessMap.image : null; 5767 const roughness = roughnessMap ? roughnessMap.image : null; 5768 const width = Math.max(metalness ? metalness.width : 0, roughness ? roughness.width : 0); 5769 const height = Math.max(metalness ? metalness.height : 0, roughness ? roughness.height : 0); 5770 const canvas = getCanvas(); 5771 canvas.width = width; 5772 canvas.height = height; 5773 const context = canvas.getContext("2d"); 5774 context.fillStyle = "#00ffff"; 5775 context.fillRect(0, 0, width, height); 5776 const composite = context.getImageData(0, 0, width, height); 5777 if (metalness) { 5778 context.drawImage(metalness, 0, 0, width, height); 5779 const convert = getEncodingConversion(metalnessMap); 5780 const data = context.getImageData(0, 0, width, height).data; 5781 for (let i = 2; i < data.length; i += 4) { 5782 composite.data[i] = convert(data[i] / 256) * 256; 5783 } 5784 } 5785 if (roughness) { 5786 context.drawImage(roughness, 0, 0, width, height); 5787 const convert = getEncodingConversion(roughnessMap); 5788 const data = context.getImageData(0, 0, width, height).data; 5789 for (let i = 1; i < data.length; i += 4) { 5790 composite.data[i] = convert(data[i] / 256) * 256; 5791 } 5792 } 5793 context.putImageData(composite, 0, 0); 5794 const reference = metalnessMap || roughnessMap; 5795 const texture = reference.clone(); 5796 texture.source = new Texture(canvas).source; 5797 if ("colorSpace" in texture) 5798 texture.colorSpace = ""; 5799 else 5800 texture.encoding = 3e3; 5801 texture.channel = (metalnessMap || roughnessMap).channel; 5802 if (metalnessMap && roughnessMap && metalnessMap.channel !== roughnessMap.channel) { 5803 console.warn("THREE.GLTFExporter: UV channels for metalnessMap and roughnessMap textures must match."); 5804 } 5805 return texture; 5806 } 5807 /** 5808 * Process a buffer to append to the default one. 5809 * @param {ArrayBuffer} buffer 5810 * @return {Integer} 5811 */ 5812 processBuffer(buffer) { 5813 const json = this.json; 5814 const buffers = this.buffers; 5815 if (!json.buffers) 5816 json.buffers = [{ byteLength: 0 }]; 5817 buffers.push(buffer); 5818 return 0; 5819 } 5820 /** 5821 * Process and generate a BufferView 5822 * @param {BufferAttribute} attribute 5823 * @param {number} componentType 5824 * @param {number} start 5825 * @param {number} count 5826 * @param {number} target (Optional) Target usage of the BufferView 5827 * @return {Object} 5828 */ 5829 processBufferView(attribute, componentType, start, count, target) { 5830 const json = this.json; 5831 if (!json.bufferViews) 5832 json.bufferViews = []; 5833 let componentSize; 5834 switch (componentType) { 5835 case WEBGL_CONSTANTS2.BYTE: 5836 case WEBGL_CONSTANTS2.UNSIGNED_BYTE: 5837 componentSize = 1; 5838 break; 5839 case WEBGL_CONSTANTS2.SHORT: 5840 case WEBGL_CONSTANTS2.UNSIGNED_SHORT: 5841 componentSize = 2; 5842 break; 5843 default: 5844 componentSize = 4; 5845 } 5846 let byteStride = attribute.itemSize * componentSize; 5847 if (target === WEBGL_CONSTANTS2.ARRAY_BUFFER) { 5848 byteStride = Math.ceil(byteStride / 4) * 4; 5849 } 5850 const byteLength = getPaddedBufferSize(count * byteStride); 5851 const dataView = new DataView(new ArrayBuffer(byteLength)); 5852 let offset = 0; 5853 for (let i = start; i < start + count; i++) { 5854 for (let a = 0; a < attribute.itemSize; a++) { 5855 let value; 5856 if (attribute.itemSize > 4) { 5857 value = attribute.array[i * attribute.itemSize + a]; 5858 } else { 5859 if (a === 0) 5860 value = attribute.getX(i); 5861 else if (a === 1) 5862 value = attribute.getY(i); 5863 else if (a === 2) 5864 value = attribute.getZ(i); 5865 else if (a === 3) 5866 value = attribute.getW(i); 5867 if (attribute.normalized === true) { 5868 value = MathUtils.normalize(value, attribute.array); 5869 } 5870 } 5871 if (componentType === WEBGL_CONSTANTS2.FLOAT) { 5872 dataView.setFloat32(offset, value, true); 5873 } else if (componentType === WEBGL_CONSTANTS2.INT) { 5874 dataView.setInt32(offset, value, true); 5875 } else if (componentType === WEBGL_CONSTANTS2.UNSIGNED_INT) { 5876 dataView.setUint32(offset, value, true); 5877 } else if (componentType === WEBGL_CONSTANTS2.SHORT) { 5878 dataView.setInt16(offset, value, true); 5879 } else if (componentType === WEBGL_CONSTANTS2.UNSIGNED_SHORT) { 5880 dataView.setUint16(offset, value, true); 5881 } else if (componentType === WEBGL_CONSTANTS2.BYTE) { 5882 dataView.setInt8(offset, value); 5883 } else if (componentType === WEBGL_CONSTANTS2.UNSIGNED_BYTE) { 5884 dataView.setUint8(offset, value); 5885 } 5886 offset += componentSize; 5887 } 5888 if (offset % byteStride !== 0) { 5889 offset += byteStride - offset % byteStride; 5890 } 5891 } 5892 const bufferViewDef = { 5893 buffer: this.processBuffer(dataView.buffer), 5894 byteOffset: this.byteOffset, 5895 byteLength 5896 }; 5897 if (target !== void 0) 5898 bufferViewDef.target = target; 5899 if (target === WEBGL_CONSTANTS2.ARRAY_BUFFER) { 5900 bufferViewDef.byteStride = byteStride; 5901 } 5902 this.byteOffset += byteLength; 5903 json.bufferViews.push(bufferViewDef); 5904 const output = { 5905 id: json.bufferViews.length - 1, 5906 byteLength: 0 5907 }; 5908 return output; 5909 } 5910 /** 5911 * Process and generate a BufferView from an image Blob. 5912 * @param {Blob} blob 5913 * @return {Promise<Integer>} 5914 */ 5915 processBufferViewImage(blob) { 5916 const writer = this; 5917 const json = writer.json; 5918 if (!json.bufferViews) 5919 json.bufferViews = []; 5920 return blob.arrayBuffer().then((result) => { 5921 const buffer = getPaddedArrayBuffer(result); 5922 const bufferViewDef = { 5923 buffer: writer.processBuffer(buffer), 5924 byteOffset: writer.byteOffset, 5925 byteLength: buffer.byteLength 5926 }; 5927 writer.byteOffset += buffer.byteLength; 5928 return json.bufferViews.push(bufferViewDef) - 1; 5929 }); 5930 } 5931 /** 5932 * Process attribute to generate an accessor 5933 * @param {BufferAttribute} attribute Attribute to process 5934 * @param {THREE.BufferGeometry} geometry (Optional) Geometry used for truncated draw range 5935 * @param {Integer} start (Optional) 5936 * @param {Integer} count (Optional) 5937 * @return {Integer|null} Index of the processed accessor on the "accessors" array 5938 */ 5939 processAccessor(attribute, geometry, start, count) { 5940 const json = this.json; 5941 const types = { 5942 1: "SCALAR", 5943 2: "VEC2", 5944 3: "VEC3", 5945 4: "VEC4", 5946 9: "MAT3", 5947 16: "MAT4" 5948 }; 5949 let componentType; 5950 if (attribute.array.constructor === Float32Array) { 5951 componentType = WEBGL_CONSTANTS2.FLOAT; 5952 } else if (attribute.array.constructor === Int32Array) { 5953 componentType = WEBGL_CONSTANTS2.INT; 5954 } else if (attribute.array.constructor === Uint32Array) { 5955 componentType = WEBGL_CONSTANTS2.UNSIGNED_INT; 5956 } else if (attribute.array.constructor === Int16Array) { 5957 componentType = WEBGL_CONSTANTS2.SHORT; 5958 } else if (attribute.array.constructor === Uint16Array) { 5959 componentType = WEBGL_CONSTANTS2.UNSIGNED_SHORT; 5960 } else if (attribute.array.constructor === Int8Array) { 5961 componentType = WEBGL_CONSTANTS2.BYTE; 5962 } else if (attribute.array.constructor === Uint8Array) { 5963 componentType = WEBGL_CONSTANTS2.UNSIGNED_BYTE; 5964 } else { 5965 throw new Error( 5966 "THREE.GLTFExporter: Unsupported bufferAttribute component type: " + attribute.array.constructor.name 5967 ); 5968 } 5969 if (start === void 0) 5970 start = 0; 5971 if (count === void 0) 5972 count = attribute.count; 5973 if (count === 0) 5974 return null; 5975 const minMax = getMinMax(attribute, start, count); 5976 let bufferViewTarget; 5977 if (geometry !== void 0) { 5978 bufferViewTarget = attribute === geometry.index ? WEBGL_CONSTANTS2.ELEMENT_ARRAY_BUFFER : WEBGL_CONSTANTS2.ARRAY_BUFFER; 5979 } 5980 const bufferView = this.processBufferView(attribute, componentType, start, count, bufferViewTarget); 5981 const accessorDef = { 5982 bufferView: bufferView.id, 5983 byteOffset: bufferView.byteOffset, 5984 componentType, 5985 count, 5986 max: minMax.max, 5987 min: minMax.min, 5988 type: types[attribute.itemSize] 5989 }; 5990 if (attribute.normalized === true) 5991 accessorDef.normalized = true; 5992 if (!json.accessors) 5993 json.accessors = []; 5994 return json.accessors.push(accessorDef) - 1; 5995 } 5996 /** 5997 * Process image 5998 * @param {Image} image to process 5999 * @param {Integer} format of the image (RGBAFormat) 6000 * @param {Boolean} flipY before writing out the image 6001 * @param {String} mimeType export format 6002 * @return {Integer} Index of the processed texture in the "images" array 6003 */ 6004 processImage(image, format, flipY, mimeType = "image/png") { 6005 if (image !== null) { 6006 const writer = this; 6007 const cache = writer.cache; 6008 const json = writer.json; 6009 const options = writer.options; 6010 const pending = writer.pending; 6011 if (!cache.images.has(image)) 6012 cache.images.set(image, {}); 6013 const cachedImages = cache.images.get(image); 6014 const key = mimeType + ":flipY/" + flipY.toString(); 6015 if (cachedImages[key] !== void 0) 6016 return cachedImages[key]; 6017 if (!json.images) 6018 json.images = []; 6019 const imageDef = { mimeType }; 6020 const canvas = getCanvas(); 6021 canvas.width = Math.min(image.width, options.maxTextureSize); 6022 canvas.height = Math.min(image.height, options.maxTextureSize); 6023 const ctx = canvas.getContext("2d"); 6024 if (flipY === true) { 6025 ctx.translate(0, canvas.height); 6026 ctx.scale(1, -1); 6027 } 6028 if (image.data !== void 0) { 6029 if (format !== RGBAFormat) { 6030 console.error("GLTFExporter: Only RGBAFormat is supported.", format); 6031 } 6032 if (image.width > options.maxTextureSize || image.height > options.maxTextureSize) { 6033 console.warn("GLTFExporter: Image size is bigger than maxTextureSize", image); 6034 } 6035 const data = new Uint8ClampedArray(image.height * image.width * 4); 6036 for (let i = 0; i < data.length; i += 4) { 6037 data[i + 0] = image.data[i + 0]; 6038 data[i + 1] = image.data[i + 1]; 6039 data[i + 2] = image.data[i + 2]; 6040 data[i + 3] = image.data[i + 3]; 6041 } 6042 ctx.putImageData(new ImageData(data, image.width, image.height), 0, 0); 6043 } else { 6044 ctx.drawImage(image, 0, 0, canvas.width, canvas.height); 6045 } 6046 if (options.binary === true) { 6047 pending.push( 6048 getToBlobPromise(canvas, mimeType).then((blob) => writer.processBufferViewImage(blob)).then((bufferViewIndex) => { 6049 imageDef.bufferView = bufferViewIndex; 6050 }) 6051 ); 6052 } else { 6053 if (canvas.toDataURL !== void 0) { 6054 imageDef.uri = canvas.toDataURL(mimeType); 6055 } else { 6056 pending.push( 6057 getToBlobPromise(canvas, mimeType).then(readAsDataURL).then((uri) => { 6058 imageDef.uri = uri; 6059 }) 6060 ); 6061 } 6062 } 6063 const index = json.images.push(imageDef) - 1; 6064 cachedImages[key] = index; 6065 return index; 6066 } else { 6067 throw new Error("THREE.GLTFExporter: No valid image data found. Unable to process texture."); 6068 } 6069 } 6070 /** 6071 * Process sampler 6072 * @param {Texture} map Texture to process 6073 * @return {Integer} Index of the processed texture in the "samplers" array 6074 */ 6075 processSampler(map) { 6076 const json = this.json; 6077 if (!json.samplers) 6078 json.samplers = []; 6079 const samplerDef = { 6080 magFilter: THREE_TO_WEBGL[map.magFilter], 6081 minFilter: THREE_TO_WEBGL[map.minFilter], 6082 wrapS: THREE_TO_WEBGL[map.wrapS], 6083 wrapT: THREE_TO_WEBGL[map.wrapT] 6084 }; 6085 return json.samplers.push(samplerDef) - 1; 6086 } 6087 /** 6088 * Process texture 6089 * @param {Texture} map Map to process 6090 * @return {Integer} Index of the processed texture in the "textures" array 6091 */ 6092 processTexture(map) { 6093 const writer = this; 6094 const options = writer.options; 6095 const cache = this.cache; 6096 const json = this.json; 6097 if (cache.textures.has(map)) 6098 return cache.textures.get(map); 6099 if (!json.textures) 6100 json.textures = []; 6101 if (map instanceof CompressedTexture) { 6102 map = decompress(map, options.maxTextureSize); 6103 } 6104 let mimeType = map.userData.mimeType; 6105 if (mimeType === "image/webp") 6106 mimeType = "image/png"; 6107 const textureDef = { 6108 sampler: this.processSampler(map), 6109 source: this.processImage(map.image, map.format, map.flipY, mimeType) 6110 }; 6111 if (map.name) 6112 textureDef.name = map.name; 6113 this._invokeAll(function(ext) { 6114 ext.writeTexture && ext.writeTexture(map, textureDef); 6115 }); 6116 const index = json.textures.push(textureDef) - 1; 6117 cache.textures.set(map, index); 6118 return index; 6119 } 6120 /** 6121 * Process material 6122 * @param {THREE.Material} material Material to process 6123 * @return {Integer|null} Index of the processed material in the "materials" array 6124 */ 6125 processMaterial(material) { 6126 const cache = this.cache; 6127 const json = this.json; 6128 if (cache.materials.has(material)) 6129 return cache.materials.get(material); 6130 if (material.isShaderMaterial) { 6131 console.warn("GLTFExporter: THREE.ShaderMaterial not supported."); 6132 return null; 6133 } 6134 if (!json.materials) 6135 json.materials = []; 6136 const materialDef = { pbrMetallicRoughness: {} }; 6137 if (material.isMeshStandardMaterial !== true && material.isMeshBasicMaterial !== true) { 6138 console.warn("GLTFExporter: Use MeshStandardMaterial or MeshBasicMaterial for best results."); 6139 } 6140 const color = material.color.toArray().concat([material.opacity]); 6141 if (!equalArray(color, [1, 1, 1, 1])) { 6142 materialDef.pbrMetallicRoughness.baseColorFactor = color; 6143 } 6144 if (material.isMeshStandardMaterial) { 6145 materialDef.pbrMetallicRoughness.metallicFactor = material.metalness; 6146 materialDef.pbrMetallicRoughness.roughnessFactor = material.roughness; 6147 } else { 6148 materialDef.pbrMetallicRoughness.metallicFactor = 0.5; 6149 materialDef.pbrMetallicRoughness.roughnessFactor = 0.5; 6150 } 6151 if (material.metalnessMap || material.roughnessMap) { 6152 const metalRoughTexture = this.buildMetalRoughTexture(material.metalnessMap, material.roughnessMap); 6153 const metalRoughMapDef = { 6154 index: this.processTexture(metalRoughTexture), 6155 channel: metalRoughTexture.channel 6156 }; 6157 this.applyTextureTransform(metalRoughMapDef, metalRoughTexture); 6158 materialDef.pbrMetallicRoughness.metallicRoughnessTexture = metalRoughMapDef; 6159 } 6160 if (material.map) { 6161 const baseColorMapDef = { 6162 index: this.processTexture(material.map), 6163 texCoord: material.map.channel 6164 }; 6165 this.applyTextureTransform(baseColorMapDef, material.map); 6166 materialDef.pbrMetallicRoughness.baseColorTexture = baseColorMapDef; 6167 } 6168 if (material.emissive) { 6169 const emissive = material.emissive; 6170 const maxEmissiveComponent = Math.max(emissive.r, emissive.g, emissive.b); 6171 if (maxEmissiveComponent > 0) { 6172 materialDef.emissiveFactor = material.emissive.toArray(); 6173 } 6174 if (material.emissiveMap) { 6175 const emissiveMapDef = { 6176 index: this.processTexture(material.emissiveMap), 6177 texCoord: material.emissiveMap.channel 6178 }; 6179 this.applyTextureTransform(emissiveMapDef, material.emissiveMap); 6180 materialDef.emissiveTexture = emissiveMapDef; 6181 } 6182 } 6183 if (material.normalMap) { 6184 const normalMapDef = { 6185 index: this.processTexture(material.normalMap), 6186 texCoord: material.normalMap.channel 6187 }; 6188 if (material.normalScale && material.normalScale.x !== 1) { 6189 normalMapDef.scale = material.normalScale.x; 6190 } 6191 this.applyTextureTransform(normalMapDef, material.normalMap); 6192 materialDef.normalTexture = normalMapDef; 6193 } 6194 if (material.aoMap) { 6195 const occlusionMapDef = { 6196 index: this.processTexture(material.aoMap), 6197 texCoord: material.aoMap.channel 6198 }; 6199 if (material.aoMapIntensity !== 1) { 6200 occlusionMapDef.strength = material.aoMapIntensity; 6201 } 6202 this.applyTextureTransform(occlusionMapDef, material.aoMap); 6203 materialDef.occlusionTexture = occlusionMapDef; 6204 } 6205 if (material.transparent) { 6206 materialDef.alphaMode = "BLEND"; 6207 } else { 6208 if (material.alphaTest > 0) { 6209 materialDef.alphaMode = "MASK"; 6210 materialDef.alphaCutoff = material.alphaTest; 6211 } 6212 } 6213 if (material.side === DoubleSide) 6214 materialDef.doubleSided = true; 6215 if (material.name !== "") 6216 materialDef.name = material.name; 6217 this.serializeUserData(material, materialDef); 6218 this._invokeAll(function(ext) { 6219 ext.writeMaterial && ext.writeMaterial(material, materialDef); 6220 }); 6221 const index = json.materials.push(materialDef) - 1; 6222 cache.materials.set(material, index); 6223 return index; 6224 } 6225 /** 6226 * Process mesh 6227 * @param {THREE.Mesh} mesh Mesh to process 6228 * @return {Integer|null} Index of the processed mesh in the "meshes" array 6229 */ 6230 processMesh(mesh) { 6231 const cache = this.cache; 6232 const json = this.json; 6233 const meshCacheKeyParts = [mesh.geometry.uuid]; 6234 if (Array.isArray(mesh.material)) { 6235 for (let i = 0, l = mesh.material.length; i < l; i++) { 6236 meshCacheKeyParts.push(mesh.material[i].uuid); 6237 } 6238 } else { 6239 meshCacheKeyParts.push(mesh.material.uuid); 6240 } 6241 const meshCacheKey = meshCacheKeyParts.join(":"); 6242 if (cache.meshes.has(meshCacheKey)) 6243 return cache.meshes.get(meshCacheKey); 6244 const geometry = mesh.geometry; 6245 let mode; 6246 if (mesh.isLineSegments) { 6247 mode = WEBGL_CONSTANTS2.LINES; 6248 } else if (mesh.isLineLoop) { 6249 mode = WEBGL_CONSTANTS2.LINE_LOOP; 6250 } else if (mesh.isLine) { 6251 mode = WEBGL_CONSTANTS2.LINE_STRIP; 6252 } else if (mesh.isPoints) { 6253 mode = WEBGL_CONSTANTS2.POINTS; 6254 } else { 6255 mode = mesh.material.wireframe ? WEBGL_CONSTANTS2.LINES : WEBGL_CONSTANTS2.TRIANGLES; 6256 } 6257 const meshDef = {}; 6258 const attributes = {}; 6259 const primitives = []; 6260 const targets = []; 6261 const nameConversion = { 6262 ...version >= 152 ? { 6263 uv: "TEXCOORD_0", 6264 uv1: "TEXCOORD_1", 6265 uv2: "TEXCOORD_2", 6266 uv3: "TEXCOORD_3" 6267 } : { 6268 uv: "TEXCOORD_0", 6269 uv2: "TEXCOORD_1" 6270 }, 6271 color: "COLOR_0", 6272 skinWeight: "WEIGHTS_0", 6273 skinIndex: "JOINTS_0" 6274 }; 6275 const originalNormal = geometry.getAttribute("normal"); 6276 if (originalNormal !== void 0 && !this.isNormalizedNormalAttribute(originalNormal)) { 6277 console.warn("THREE.GLTFExporter: Creating normalized normal attribute from the non-normalized one."); 6278 geometry.setAttribute("normal", this.createNormalizedNormalAttribute(originalNormal)); 6279 } 6280 let modifiedAttribute = null; 6281 for (let attributeName in geometry.attributes) { 6282 if (attributeName.slice(0, 5) === "morph") 6283 continue; 6284 const attribute = geometry.attributes[attributeName]; 6285 attributeName = nameConversion[attributeName] || attributeName.toUpperCase(); 6286 const validVertexAttributes = /^(POSITION|NORMAL|TANGENT|TEXCOORD_\d+|COLOR_\d+|JOINTS_\d+|WEIGHTS_\d+)$/; 6287 if (!validVertexAttributes.test(attributeName)) 6288 attributeName = "_" + attributeName; 6289 if (cache.attributes.has(this.getUID(attribute))) { 6290 attributes[attributeName] = cache.attributes.get(this.getUID(attribute)); 6291 continue; 6292 } 6293 modifiedAttribute = null; 6294 const array = attribute.array; 6295 if (attributeName === "JOINTS_0" && !(array instanceof Uint16Array) && !(array instanceof Uint8Array)) { 6296 console.warn('GLTFExporter: Attribute "skinIndex" converted to type UNSIGNED_SHORT.'); 6297 modifiedAttribute = new BufferAttribute(new Uint16Array(array), attribute.itemSize, attribute.normalized); 6298 } 6299 const accessor = this.processAccessor(modifiedAttribute || attribute, geometry); 6300 if (accessor !== null) { 6301 if (!attributeName.startsWith("_")) { 6302 this.detectMeshQuantization(attributeName, attribute); 6303 } 6304 attributes[attributeName] = accessor; 6305 cache.attributes.set(this.getUID(attribute), accessor); 6306 } 6307 } 6308 if (originalNormal !== void 0) 6309 geometry.setAttribute("normal", originalNormal); 6310 if (Object.keys(attributes).length === 0) 6311 return null; 6312 if (mesh.morphTargetInfluences !== void 0 && mesh.morphTargetInfluences.length > 0) { 6313 const weights = []; 6314 const targetNames = []; 6315 const reverseDictionary = {}; 6316 if (mesh.morphTargetDictionary !== void 0) { 6317 for (const key in mesh.morphTargetDictionary) { 6318 reverseDictionary[mesh.morphTargetDictionary[key]] = key; 6319 } 6320 } 6321 for (let i = 0; i < mesh.morphTargetInfluences.length; ++i) { 6322 const target = {}; 6323 let warned = false; 6324 for (const attributeName in geometry.morphAttributes) { 6325 if (attributeName !== "position" && attributeName !== "normal") { 6326 if (!warned) { 6327 console.warn("GLTFExporter: Only POSITION and NORMAL morph are supported."); 6328 warned = true; 6329 } 6330 continue; 6331 } 6332 const attribute = geometry.morphAttributes[attributeName][i]; 6333 const gltfAttributeName = attributeName.toUpperCase(); 6334 const baseAttribute = geometry.attributes[attributeName]; 6335 if (cache.attributes.has(this.getUID(attribute, true))) { 6336 target[gltfAttributeName] = cache.attributes.get(this.getUID(attribute, true)); 6337 continue; 6338 } 6339 const relativeAttribute = attribute.clone(); 6340 if (!geometry.morphTargetsRelative) { 6341 for (let j = 0, jl = attribute.count; j < jl; j++) { 6342 for (let a = 0; a < attribute.itemSize; a++) { 6343 if (a === 0) 6344 relativeAttribute.setX(j, attribute.getX(j) - baseAttribute.getX(j)); 6345 if (a === 1) 6346 relativeAttribute.setY(j, attribute.getY(j) - baseAttribute.getY(j)); 6347 if (a === 2) 6348 relativeAttribute.setZ(j, attribute.getZ(j) - baseAttribute.getZ(j)); 6349 if (a === 3) 6350 relativeAttribute.setW(j, attribute.getW(j) - baseAttribute.getW(j)); 6351 } 6352 } 6353 } 6354 target[gltfAttributeName] = this.processAccessor(relativeAttribute, geometry); 6355 cache.attributes.set(this.getUID(baseAttribute, true), target[gltfAttributeName]); 6356 } 6357 targets.push(target); 6358 weights.push(mesh.morphTargetInfluences[i]); 6359 if (mesh.morphTargetDictionary !== void 0) 6360 targetNames.push(reverseDictionary[i]); 6361 } 6362 meshDef.weights = weights; 6363 if (targetNames.length > 0) { 6364 meshDef.extras = {}; 6365 meshDef.extras.targetNames = targetNames; 6366 } 6367 } 6368 const isMultiMaterial = Array.isArray(mesh.material); 6369 if (isMultiMaterial && geometry.groups.length === 0) 6370 return null; 6371 const materials = isMultiMaterial ? mesh.material : [mesh.material]; 6372 const groups = isMultiMaterial ? geometry.groups : [{ materialIndex: 0, start: void 0, count: void 0 }]; 6373 for (let i = 0, il = groups.length; i < il; i++) { 6374 const primitive = { 6375 mode, 6376 attributes 6377 }; 6378 this.serializeUserData(geometry, primitive); 6379 if (targets.length > 0) 6380 primitive.targets = targets; 6381 if (geometry.index !== null) { 6382 let cacheKey = this.getUID(geometry.index); 6383 if (groups[i].start !== void 0 || groups[i].count !== void 0) { 6384 cacheKey += ":" + groups[i].start + ":" + groups[i].count; 6385 } 6386 if (cache.attributes.has(cacheKey)) { 6387 primitive.indices = cache.attributes.get(cacheKey); 6388 } else { 6389 primitive.indices = this.processAccessor(geometry.index, geometry, groups[i].start, groups[i].count); 6390 cache.attributes.set(cacheKey, primitive.indices); 6391 } 6392 if (primitive.indices === null) 6393 delete primitive.indices; 6394 } 6395 const material = this.processMaterial(materials[groups[i].materialIndex]); 6396 if (material !== null) 6397 primitive.material = material; 6398 primitives.push(primitive); 6399 } 6400 meshDef.primitives = primitives; 6401 if (!json.meshes) 6402 json.meshes = []; 6403 this._invokeAll(function(ext) { 6404 ext.writeMesh && ext.writeMesh(mesh, meshDef); 6405 }); 6406 const index = json.meshes.push(meshDef) - 1; 6407 cache.meshes.set(meshCacheKey, index); 6408 return index; 6409 } 6410 /** 6411 * If a vertex attribute with a 6412 * [non-standard data type](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#meshes-overview) 6413 * is used, it is checked whether it is a valid data type according to the 6414 * [KHR_mesh_quantization](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_mesh_quantization/README.md) 6415 * extension. 6416 * In this case the extension is automatically added to the list of used extensions. 6417 * 6418 * @param {string} attributeName 6419 * @param {THREE.BufferAttribute} attribute 6420 */ 6421 detectMeshQuantization(attributeName, attribute) { 6422 if (this.extensionsUsed[KHR_MESH_QUANTIZATION]) 6423 return; 6424 let attrType = void 0; 6425 switch (attribute.array.constructor) { 6426 case Int8Array: 6427 attrType = "byte"; 6428 break; 6429 case Uint8Array: 6430 attrType = "unsigned byte"; 6431 break; 6432 case Int16Array: 6433 attrType = "short"; 6434 break; 6435 case Uint16Array: 6436 attrType = "unsigned short"; 6437 break; 6438 default: 6439 return; 6440 } 6441 if (attribute.normalized) 6442 attrType += " normalized"; 6443 const attrNamePrefix = attributeName.split("_", 1)[0]; 6444 if (KHR_mesh_quantization_ExtraAttrTypes[attrNamePrefix] && KHR_mesh_quantization_ExtraAttrTypes[attrNamePrefix].includes(attrType)) { 6445 this.extensionsUsed[KHR_MESH_QUANTIZATION] = true; 6446 this.extensionsRequired[KHR_MESH_QUANTIZATION] = true; 6447 } 6448 } 6449 /** 6450 * Process camera 6451 * @param {THREE.Camera} camera Camera to process 6452 * @return {Integer} Index of the processed mesh in the "camera" array 6453 */ 6454 processCamera(camera) { 6455 const json = this.json; 6456 if (!json.cameras) 6457 json.cameras = []; 6458 const isOrtho = camera.isOrthographicCamera; 6459 const cameraDef = { 6460 type: isOrtho ? "orthographic" : "perspective" 6461 }; 6462 if (isOrtho) { 6463 cameraDef.orthographic = { 6464 xmag: camera.right * 2, 6465 ymag: camera.top * 2, 6466 zfar: camera.far <= 0 ? 1e-3 : camera.far, 6467 znear: camera.near < 0 ? 0 : camera.near 6468 }; 6469 } else { 6470 cameraDef.perspective = { 6471 aspectRatio: camera.aspect, 6472 yfov: MathUtils.degToRad(camera.fov), 6473 zfar: camera.far <= 0 ? 1e-3 : camera.far, 6474 znear: camera.near < 0 ? 0 : camera.near 6475 }; 6476 } 6477 if (camera.name !== "") 6478 cameraDef.name = camera.type; 6479 return json.cameras.push(cameraDef) - 1; 6480 } 6481 /** 6482 * Creates glTF animation entry from AnimationClip object. 6483 * 6484 * Status: 6485 * - Only properties listed in PATH_PROPERTIES may be animated. 6486 * 6487 * @param {THREE.AnimationClip} clip 6488 * @param {THREE.Object3D} root 6489 * @return {number|null} 6490 */ 6491 processAnimation(clip, root) { 6492 const json = this.json; 6493 const nodeMap = this.nodeMap; 6494 if (!json.animations) 6495 json.animations = []; 6496 clip = GLTFExporter.Utils.mergeMorphTargetTracks(clip.clone(), root); 6497 const tracks = clip.tracks; 6498 const channels = []; 6499 const samplers = []; 6500 for (let i = 0; i < tracks.length; ++i) { 6501 const track = tracks[i]; 6502 const trackBinding = PropertyBinding.parseTrackName(track.name); 6503 let trackNode = PropertyBinding.findNode(root, trackBinding.nodeName); 6504 const trackProperty = PATH_PROPERTIES2[trackBinding.propertyName]; 6505 if (trackBinding.objectName === "bones") { 6506 if (trackNode.isSkinnedMesh === true) { 6507 trackNode = trackNode.skeleton.getBoneByName(trackBinding.objectIndex); 6508 } else { 6509 trackNode = void 0; 6510 } 6511 } 6512 if (!trackNode || !trackProperty) { 6513 console.warn('THREE.GLTFExporter: Could not export animation track "%s".', track.name); 6514 return null; 6515 } 6516 const inputItemSize = 1; 6517 let outputItemSize = track.values.length / track.times.length; 6518 if (trackProperty === PATH_PROPERTIES2.morphTargetInfluences) { 6519 outputItemSize /= trackNode.morphTargetInfluences.length; 6520 } 6521 let interpolation; 6522 if (track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline === true) { 6523 interpolation = "CUBICSPLINE"; 6524 outputItemSize /= 3; 6525 } else if (track.getInterpolation() === InterpolateDiscrete) { 6526 interpolation = "STEP"; 6527 } else { 6528 interpolation = "LINEAR"; 6529 } 6530 samplers.push({ 6531 input: this.processAccessor(new BufferAttribute(track.times, inputItemSize)), 6532 output: this.processAccessor(new BufferAttribute(track.values, outputItemSize)), 6533 interpolation 6534 }); 6535 channels.push({ 6536 sampler: samplers.length - 1, 6537 target: { 6538 node: nodeMap.get(trackNode), 6539 path: trackProperty 6540 } 6541 }); 6542 } 6543 json.animations.push({ 6544 name: clip.name || "clip_" + json.animations.length, 6545 samplers, 6546 channels 6547 }); 6548 return json.animations.length - 1; 6549 } 6550 /** 6551 * @param {THREE.Object3D} object 6552 * @return {number|null} 6553 */ 6554 processSkin(object) { 6555 const json = this.json; 6556 const nodeMap = this.nodeMap; 6557 const node = json.nodes[nodeMap.get(object)]; 6558 const skeleton = object.skeleton; 6559 if (skeleton === void 0) 6560 return null; 6561 const rootJoint = object.skeleton.bones[0]; 6562 if (rootJoint === void 0) 6563 return null; 6564 const joints = []; 6565 const inverseBindMatrices = new Float32Array(skeleton.bones.length * 16); 6566 const temporaryBoneInverse = new Matrix4(); 6567 for (let i = 0; i < skeleton.bones.length; ++i) { 6568 joints.push(nodeMap.get(skeleton.bones[i])); 6569 temporaryBoneInverse.copy(skeleton.boneInverses[i]); 6570 temporaryBoneInverse.multiply(object.bindMatrix).toArray(inverseBindMatrices, i * 16); 6571 } 6572 if (json.skins === void 0) 6573 json.skins = []; 6574 json.skins.push({ 6575 inverseBindMatrices: this.processAccessor(new BufferAttribute(inverseBindMatrices, 16)), 6576 joints, 6577 skeleton: nodeMap.get(rootJoint) 6578 }); 6579 const skinIndex = node.skin = json.skins.length - 1; 6580 return skinIndex; 6581 } 6582 /** 6583 * Process Object3D node 6584 * @param {THREE.Object3D} node Object3D to processNode 6585 * @return {Integer} Index of the node in the nodes list 6586 */ 6587 processNode(object) { 6588 const json = this.json; 6589 const options = this.options; 6590 const nodeMap = this.nodeMap; 6591 if (!json.nodes) 6592 json.nodes = []; 6593 const nodeDef = {}; 6594 if (options.trs) { 6595 const rotation = object.quaternion.toArray(); 6596 const position2 = object.position.toArray(); 6597 const scale = object.scale.toArray(); 6598 if (!equalArray(rotation, [0, 0, 0, 1])) { 6599 nodeDef.rotation = rotation; 6600 } 6601 if (!equalArray(position2, [0, 0, 0])) { 6602 nodeDef.translation = position2; 6603 } 6604 if (!equalArray(scale, [1, 1, 1])) { 6605 nodeDef.scale = scale; 6606 } 6607 } else { 6608 if (object.matrixAutoUpdate) { 6609 object.updateMatrix(); 6610 } 6611 if (isIdentityMatrix(object.matrix) === false) { 6612 nodeDef.matrix = object.matrix.elements; 6613 } 6614 } 6615 if (object.name !== "") 6616 nodeDef.name = String(object.name); 6617 this.serializeUserData(object, nodeDef); 6618 if (object.isMesh || object.isLine || object.isPoints) { 6619 const meshIndex = this.processMesh(object); 6620 if (meshIndex !== null) 6621 nodeDef.mesh = meshIndex; 6622 } else if (object.isCamera) { 6623 nodeDef.camera = this.processCamera(object); 6624 } 6625 if (object.isSkinnedMesh) 6626 this.skins.push(object); 6627 if (object.children.length > 0) { 6628 const children2 = []; 6629 for (let i = 0, l = object.children.length; i < l; i++) { 6630 const child = object.children[i]; 6631 if (child.visible || options.onlyVisible === false) { 6632 const nodeIndex2 = this.processNode(child); 6633 if (nodeIndex2 !== null) 6634 children2.push(nodeIndex2); 6635 } 6636 } 6637 if (children2.length > 0) 6638 nodeDef.children = children2; 6639 } 6640 this._invokeAll(function(ext) { 6641 ext.writeNode && ext.writeNode(object, nodeDef); 6642 }); 6643 const nodeIndex = json.nodes.push(nodeDef) - 1; 6644 nodeMap.set(object, nodeIndex); 6645 return nodeIndex; 6646 } 6647 /** 6648 * Process Scene 6649 * @param {Scene} node Scene to process 6650 */ 6651 processScene(scene) { 6652 const json = this.json; 6653 const options = this.options; 6654 if (!json.scenes) { 6655 json.scenes = []; 6656 json.scene = 0; 6657 } 6658 const sceneDef = {}; 6659 if (scene.name !== "") 6660 sceneDef.name = scene.name; 6661 json.scenes.push(sceneDef); 6662 const nodes = []; 6663 for (let i = 0, l = scene.children.length; i < l; i++) { 6664 const child = scene.children[i]; 6665 if (child.visible || options.onlyVisible === false) { 6666 const nodeIndex = this.processNode(child); 6667 if (nodeIndex !== null) 6668 nodes.push(nodeIndex); 6669 } 6670 } 6671 if (nodes.length > 0) 6672 sceneDef.nodes = nodes; 6673 this.serializeUserData(scene, sceneDef); 6674 } 6675 /** 6676 * Creates a Scene to hold a list of objects and parse it 6677 * @param {Array} objects List of objects to process 6678 */ 6679 processObjects(objects) { 6680 const scene = new Scene(); 6681 scene.name = "AuxScene"; 6682 for (let i = 0; i < objects.length; i++) { 6683 scene.children.push(objects[i]); 6684 } 6685 this.processScene(scene); 6686 } 6687 /** 6688 * @param {THREE.Object3D|Array<THREE.Object3D>} input 6689 */ 6690 processInput(input) { 6691 const options = this.options; 6692 input = input instanceof Array ? input : [input]; 6693 this._invokeAll(function(ext) { 6694 ext.beforeParse && ext.beforeParse(input); 6695 }); 6696 const objectsWithoutScene = []; 6697 for (let i = 0; i < input.length; i++) { 6698 if (input[i] instanceof Scene) { 6699 this.processScene(input[i]); 6700 } else { 6701 objectsWithoutScene.push(input[i]); 6702 } 6703 } 6704 if (objectsWithoutScene.length > 0) 6705 this.processObjects(objectsWithoutScene); 6706 for (let i = 0; i < this.skins.length; ++i) { 6707 this.processSkin(this.skins[i]); 6708 } 6709 for (let i = 0; i < options.animations.length; ++i) { 6710 this.processAnimation(options.animations[i], input[0]); 6711 } 6712 this._invokeAll(function(ext) { 6713 ext.afterParse && ext.afterParse(input); 6714 }); 6715 } 6716 _invokeAll(func) { 6717 for (let i = 0, il = this.plugins.length; i < il; i++) { 6718 func(this.plugins[i]); 6719 } 6720 } 6721}; 6722var GLTFLightExtension = class { 6723 constructor(writer) { 6724 this.writer = writer; 6725 this.name = "KHR_lights_punctual"; 6726 } 6727 writeNode(light, nodeDef) { 6728 if (!light.isLight) 6729 return; 6730 if (!light.isDirectionalLight && !light.isPointLight && !light.isSpotLight) { 6731 console.warn("THREE.GLTFExporter: Only directional, point, and spot lights are supported.", light); 6732 return; 6733 } 6734 const writer = this.writer; 6735 const json = writer.json; 6736 const extensionsUsed = writer.extensionsUsed; 6737 const lightDef = {}; 6738 if (light.name) 6739 lightDef.name = light.name; 6740 lightDef.color = light.color.toArray(); 6741 lightDef.intensity = light.intensity; 6742 if (light.isDirectionalLight) { 6743 lightDef.type = "directional"; 6744 } else if (light.isPointLight) { 6745 lightDef.type = "point"; 6746 if (light.distance > 0) 6747 lightDef.range = light.distance; 6748 } else if (light.isSpotLight) { 6749 lightDef.type = "spot"; 6750 if (light.distance > 0) 6751 lightDef.range = light.distance; 6752 lightDef.spot = {}; 6753 lightDef.spot.innerConeAngle = (light.penumbra - 1) * light.angle * -1; 6754 lightDef.spot.outerConeAngle = light.angle; 6755 } 6756 if (light.decay !== void 0 && light.decay !== 2) { 6757 console.warn( 6758 "THREE.GLTFExporter: Light decay may be lost. glTF is physically-based, and expects light.decay=2." 6759 ); 6760 } 6761 if (light.target && (light.target.parent !== light || light.target.position.x !== 0 || light.target.position.y !== 0 || light.target.position.z !== -1)) { 6762 console.warn( 6763 "THREE.GLTFExporter: Light direction may be lost. For best results, make light.target a child of the light with position 0,0,-1." 6764 ); 6765 } 6766 if (!extensionsUsed[this.name]) { 6767 json.extensions = json.extensions || {}; 6768 json.extensions[this.name] = { lights: [] }; 6769 extensionsUsed[this.name] = true; 6770 } 6771 const lights = json.extensions[this.name].lights; 6772 lights.push(lightDef); 6773 nodeDef.extensions = nodeDef.extensions || {}; 6774 nodeDef.extensions[this.name] = { light: lights.length - 1 }; 6775 } 6776}; 6777var GLTFMaterialsUnlitExtension2 = class { 6778 constructor(writer) { 6779 this.writer = writer; 6780 this.name = "KHR_materials_unlit"; 6781 } 6782 writeMaterial(material, materialDef) { 6783 if (!material.isMeshBasicMaterial) 6784 return; 6785 const writer = this.writer; 6786 const extensionsUsed = writer.extensionsUsed; 6787 materialDef.extensions = materialDef.extensions || {}; 6788 materialDef.extensions[this.name] = {}; 6789 extensionsUsed[this.name] = true; 6790 materialDef.pbrMetallicRoughness.metallicFactor = 0; 6791 materialDef.pbrMetallicRoughness.roughnessFactor = 0.9; 6792 } 6793}; 6794var GLTFMaterialsClearcoatExtension2 = class { 6795 constructor(writer) { 6796 this.writer = writer; 6797 this.name = "KHR_materials_clearcoat"; 6798 } 6799 writeMaterial(material, materialDef) { 6800 if (!material.isMeshPhysicalMaterial || material.clearcoat === 0) 6801 return; 6802 const writer = this.writer; 6803 const extensionsUsed = writer.extensionsUsed; 6804 const extensionDef = {}; 6805 extensionDef.clearcoatFactor = material.clearcoat; 6806 if (material.clearcoatMap) { 6807 const clearcoatMapDef = { 6808 index: writer.processTexture(material.clearcoatMap), 6809 texCoord: material.clearcoatMap.channel 6810 }; 6811 writer.applyTextureTransform(clearcoatMapDef, material.clearcoatMap); 6812 extensionDef.clearcoatTexture = clearcoatMapDef; 6813 } 6814 extensionDef.clearcoatRoughnessFactor = material.clearcoatRoughness; 6815 if (material.clearcoatRoughnessMap) { 6816 const clearcoatRoughnessMapDef = { 6817 index: writer.processTexture(material.clearcoatRoughnessMap), 6818 texCoord: material.clearcoatRoughnessMap.channel 6819 }; 6820 writer.applyTextureTransform(clearcoatRoughnessMapDef, material.clearcoatRoughnessMap); 6821 extensionDef.clearcoatRoughnessTexture = clearcoatRoughnessMapDef; 6822 } 6823 if (material.clearcoatNormalMap) { 6824 const clearcoatNormalMapDef = { 6825 index: writer.processTexture(material.clearcoatNormalMap), 6826 texCoord: material.clearcoatNormalMap.channel 6827 }; 6828 writer.applyTextureTransform(clearcoatNormalMapDef, material.clearcoatNormalMap); 6829 extensionDef.clearcoatNormalTexture = clearcoatNormalMapDef; 6830 } 6831 materialDef.extensions = materialDef.extensions || {}; 6832 materialDef.extensions[this.name] = extensionDef; 6833 extensionsUsed[this.name] = true; 6834 } 6835}; 6836var GLTFMaterialsIridescenceExtension2 = class { 6837 constructor(writer) { 6838 this.writer = writer; 6839 this.name = "KHR_materials_iridescence"; 6840 } 6841 writeMaterial(material, materialDef) { 6842 if (!material.isMeshPhysicalMaterial || material.iridescence === 0) 6843 return; 6844 const writer = this.writer; 6845 const extensionsUsed = writer.extensionsUsed; 6846 const extensionDef = {}; 6847 extensionDef.iridescenceFactor = material.iridescence; 6848 if (material.iridescenceMap) { 6849 const iridescenceMapDef = { 6850 index: writer.processTexture(material.iridescenceMap), 6851 texCoord: material.iridescenceMap.channel 6852 }; 6853 writer.applyTextureTransform(iridescenceMapDef, material.iridescenceMap); 6854 extensionDef.iridescenceTexture = iridescenceMapDef; 6855 } 6856 extensionDef.iridescenceIor = material.iridescenceIOR; 6857 extensionDef.iridescenceThicknessMinimum = material.iridescenceThicknessRange[0]; 6858 extensionDef.iridescenceThicknessMaximum = material.iridescenceThicknessRange[1]; 6859 if (material.iridescenceThicknessMap) { 6860 const iridescenceThicknessMapDef = { 6861 index: writer.processTexture(material.iridescenceThicknessMap), 6862 texCoord: material.iridescenceThicknessMap.channel 6863 }; 6864 writer.applyTextureTransform(iridescenceThicknessMapDef, material.iridescenceThicknessMap); 6865 extensionDef.iridescenceThicknessTexture = iridescenceThicknessMapDef; 6866 } 6867 materialDef.extensions = materialDef.extensions || {}; 6868 materialDef.extensions[this.name] = extensionDef; 6869 extensionsUsed[this.name] = true; 6870 } 6871}; 6872var GLTFMaterialsTransmissionExtension2 = class { 6873 constructor(writer) { 6874 this.writer = writer; 6875 this.name = "KHR_materials_transmission"; 6876 } 6877 writeMaterial(material, materialDef) { 6878 if (!material.isMeshPhysicalMaterial || material.transmission === 0) 6879 return; 6880 const writer = this.writer; 6881 const extensionsUsed = writer.extensionsUsed; 6882 const extensionDef = {}; 6883 extensionDef.transmissionFactor = material.transmission; 6884 if (material.transmissionMap) { 6885 const transmissionMapDef = { 6886 index: writer.processTexture(material.transmissionMap), 6887 texCoord: material.transmissionMap.channel 6888 }; 6889 writer.applyTextureTransform(transmissionMapDef, material.transmissionMap); 6890 extensionDef.transmissionTexture = transmissionMapDef; 6891 } 6892 materialDef.extensions = materialDef.extensions || {}; 6893 materialDef.extensions[this.name] = extensionDef; 6894 extensionsUsed[this.name] = true; 6895 } 6896}; 6897var GLTFMaterialsVolumeExtension2 = class { 6898 constructor(writer) { 6899 this.writer = writer; 6900 this.name = "KHR_materials_volume"; 6901 } 6902 writeMaterial(material, materialDef) { 6903 if (!material.isMeshPhysicalMaterial || material.transmission === 0) 6904 return; 6905 const writer = this.writer; 6906 const extensionsUsed = writer.extensionsUsed; 6907 const extensionDef = {}; 6908 extensionDef.thicknessFactor = material.thickness; 6909 if (material.thicknessMap) { 6910 const thicknessMapDef = { 6911 index: writer.processTexture(material.thicknessMap), 6912 texCoord: material.thicknessMap.channel 6913 }; 6914 writer.applyTextureTransform(thicknessMapDef, material.thicknessMap); 6915 extensionDef.thicknessTexture = thicknessMapDef; 6916 } 6917 extensionDef.attenuationDistance = material.attenuationDistance; 6918 extensionDef.attenuationColor = material.attenuationColor.toArray(); 6919 materialDef.extensions = materialDef.extensions || {}; 6920 materialDef.extensions[this.name] = extensionDef; 6921 extensionsUsed[this.name] = true; 6922 } 6923}; 6924var GLTFMaterialsIorExtension2 = class { 6925 constructor(writer) { 6926 this.writer = writer; 6927 this.name = "KHR_materials_ior"; 6928 } 6929 writeMaterial(material, materialDef) { 6930 if (!material.isMeshPhysicalMaterial || material.ior === 1.5) 6931 return; 6932 const writer = this.writer; 6933 const extensionsUsed = writer.extensionsUsed; 6934 const extensionDef = {}; 6935 extensionDef.ior = material.ior; 6936 materialDef.extensions = materialDef.extensions || {}; 6937 materialDef.extensions[this.name] = extensionDef; 6938 extensionsUsed[this.name] = true; 6939 } 6940}; 6941var GLTFMaterialsSpecularExtension2 = class { 6942 constructor(writer) { 6943 this.writer = writer; 6944 this.name = "KHR_materials_specular"; 6945 } 6946 writeMaterial(material, materialDef) { 6947 if (!material.isMeshPhysicalMaterial || material.specularIntensity === 1 && material.specularColor.equals(DEFAULT_SPECULAR_COLOR) && !material.specularIntensityMap && !material.specularColorTexture) 6948 return; 6949 const writer = this.writer; 6950 const extensionsUsed = writer.extensionsUsed; 6951 const extensionDef = {}; 6952 if (material.specularIntensityMap) { 6953 const specularIntensityMapDef = { 6954 index: writer.processTexture(material.specularIntensityMap), 6955 texCoord: material.specularIntensityMap.channel 6956 }; 6957 writer.applyTextureTransform(specularIntensityMapDef, material.specularIntensityMap); 6958 extensionDef.specularTexture = specularIntensityMapDef; 6959 } 6960 if (material.specularColorMap) { 6961 const specularColorMapDef = { 6962 index: writer.processTexture(material.specularColorMap), 6963 texCoord: material.specularColorMap.channel 6964 }; 6965 writer.applyTextureTransform(specularColorMapDef, material.specularColorMap); 6966 extensionDef.specularColorTexture = specularColorMapDef; 6967 } 6968 extensionDef.specularFactor = material.specularIntensity; 6969 extensionDef.specularColorFactor = material.specularColor.toArray(); 6970 materialDef.extensions = materialDef.extensions || {}; 6971 materialDef.extensions[this.name] = extensionDef; 6972 extensionsUsed[this.name] = true; 6973 } 6974}; 6975var GLTFMaterialsSheenExtension2 = class { 6976 constructor(writer) { 6977 this.writer = writer; 6978 this.name = "KHR_materials_sheen"; 6979 } 6980 writeMaterial(material, materialDef) { 6981 if (!material.isMeshPhysicalMaterial || material.sheen == 0) 6982 return; 6983 const writer = this.writer; 6984 const extensionsUsed = writer.extensionsUsed; 6985 const extensionDef = {}; 6986 if (material.sheenRoughnessMap) { 6987 const sheenRoughnessMapDef = { 6988 index: writer.processTexture(material.sheenRoughnessMap), 6989 texCoord: material.sheenRoughnessMap.channel 6990 }; 6991 writer.applyTextureTransform(sheenRoughnessMapDef, material.sheenRoughnessMap); 6992 extensionDef.sheenRoughnessTexture = sheenRoughnessMapDef; 6993 } 6994 if (material.sheenColorMap) { 6995 const sheenColorMapDef = { 6996 index: writer.processTexture(material.sheenColorMap), 6997 texCoord: material.sheenColorMap.channel 6998 }; 6999 writer.applyTextureTransform(sheenColorMapDef, material.sheenColorMap); 7000 extensionDef.sheenColorTexture = sheenColorMapDef; 7001 } 7002 extensionDef.sheenRoughnessFactor = material.sheenRoughness; 7003 extensionDef.sheenColorFactor = material.sheenColor.toArray(); 7004 materialDef.extensions = materialDef.extensions || {}; 7005 materialDef.extensions[this.name] = extensionDef; 7006 extensionsUsed[this.name] = true; 7007 } 7008}; 7009var GLTFMaterialsAnisotropyExtension2 = class { 7010 constructor(writer) { 7011 this.writer = writer; 7012 this.name = "KHR_materials_anisotropy"; 7013 } 7014 writeMaterial(material, materialDef) { 7015 if (!material.isMeshPhysicalMaterial || material.anisotropy == 0) 7016 return; 7017 const writer = this.writer; 7018 const extensionsUsed = writer.extensionsUsed; 7019 const extensionDef = {}; 7020 if (material.anisotropyMap) { 7021 const anisotropyMapDef = { index: writer.processTexture(material.anisotropyMap) }; 7022 writer.applyTextureTransform(anisotropyMapDef, material.anisotropyMap); 7023 extensionDef.anisotropyTexture = anisotropyMapDef; 7024 } 7025 extensionDef.anisotropyStrength = material.anisotropy; 7026 extensionDef.anisotropyRotation = material.anisotropyRotation; 7027 materialDef.extensions = materialDef.extensions || {}; 7028 materialDef.extensions[this.name] = extensionDef; 7029 extensionsUsed[this.name] = true; 7030 } 7031}; 7032var GLTFMaterialsEmissiveStrengthExtension2 = class { 7033 constructor(writer) { 7034 this.writer = writer; 7035 this.name = "KHR_materials_emissive_strength"; 7036 } 7037 writeMaterial(material, materialDef) { 7038 if (!material.isMeshStandardMaterial || material.emissiveIntensity === 1) 7039 return; 7040 const writer = this.writer; 7041 const extensionsUsed = writer.extensionsUsed; 7042 const extensionDef = {}; 7043 extensionDef.emissiveStrength = material.emissiveIntensity; 7044 materialDef.extensions = materialDef.extensions || {}; 7045 materialDef.extensions[this.name] = extensionDef; 7046 extensionsUsed[this.name] = true; 7047 } 7048}; 7049
vendor: 2,432 bytes, lines 7050-7124
7050// node_modules/three-stdlib/controls/EventDispatcher.js 7051var __defProp2 = Object.defineProperty; 7052var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; 7053var __publicField2 = (obj, key, value) => { 7054 __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value); 7055 return value; 7056}; 7057var EventDispatcher = class { 7058 constructor() { 7059 __publicField2(this, "_listeners"); 7060 } 7061 /** 7062 * Adds a listener to an event type. 7063 * @param type The type of event to listen to. 7064 * @param listener The function that gets called when the event is fired. 7065 */ 7066 addEventListener(type, listener) { 7067 if (this._listeners === void 0) 7068 this._listeners = {}; 7069 const listeners = this._listeners; 7070 if (listeners[type] === void 0) { 7071 listeners[type] = []; 7072 } 7073 if (listeners[type].indexOf(listener) === -1) { 7074 listeners[type].push(listener); 7075 } 7076 } 7077 /** 7078 * Checks if listener is added to an event type. 7079 * @param type The type of event to listen to. 7080 * @param listener The function that gets called when the event is fired. 7081 */ 7082 hasEventListener(type, listener) { 7083 if (this._listeners === void 0) 7084 return false; 7085 const listeners = this._listeners; 7086 return listeners[type] !== void 0 && listeners[type].indexOf(listener) !== -1; 7087 } 7088 /** 7089 * Removes a listener from an event type. 7090 * @param type The type of the listener that gets removed. 7091 * @param listener The listener function that gets removed. 7092 */ 7093 removeEventListener(type, listener) { 7094 if (this._listeners === void 0) 7095 return; 7096 const listeners = this._listeners; 7097 const listenerArray = listeners[type]; 7098 if (listenerArray !== void 0) { 7099 const index = listenerArray.indexOf(listener); 7100 if (index !== -1) { 7101 listenerArray.splice(index, 1); 7102 } 7103 } 7104 } 7105 /** 7106 * Fire an event type. 7107 * @param event The event that gets fired. 7108 */ 7109 dispatchEvent(event) { 7110 if (this._listeners === void 0) 7111 return; 7112 const listeners = this._listeners; 7113 const listenerArray = listeners[event.type]; 7114 if (listenerArray !== void 0) { 7115 event.target = this; 7116 const array = listenerArray.slice(0); 7117 for (let i = 0, l = array.length; i < l; i++) { 7118 array[i].call(this, event); 7119 } 7120 event.target = null; 7121 } 7122 } 7123}; 7124
vendor: 20,995 bytes, lines 7125-7619
7125// node_modules/three-stdlib/controls/TrackballControls.js 7126var __defProp3 = Object.defineProperty; 7127var __defNormalProp3 = (obj, key, value) => key in obj ? __defProp3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; 7128var __publicField3 = (obj, key, value) => { 7129 __defNormalProp3(obj, typeof key !== "symbol" ? key + "" : key, value); 7130 return value; 7131}; 7132var TrackballControls = class extends EventDispatcher { 7133 constructor(object, domElement) { 7134 super(); 7135 __publicField3(this, "enabled", true); 7136 __publicField3(this, "screen", { left: 0, top: 0, width: 0, height: 0 }); 7137 __publicField3(this, "rotateSpeed", 1); 7138 __publicField3(this, "zoomSpeed", 1.2); 7139 __publicField3(this, "panSpeed", 0.3); 7140 __publicField3(this, "noRotate", false); 7141 __publicField3(this, "noZoom", false); 7142 __publicField3(this, "noPan", false); 7143 __publicField3(this, "staticMoving", false); 7144 __publicField3(this, "dynamicDampingFactor", 0.2); 7145 __publicField3(this, "minDistance", 0); 7146 __publicField3(this, "maxDistance", Infinity); 7147 __publicField3(this, "keys", [ 7148 "KeyA", 7149 "KeyS", 7150 "KeyD" 7151 /*D*/ 7152 ]); 7153 __publicField3(this, "mouseButtons", { 7154 LEFT: MOUSE.ROTATE, 7155 MIDDLE: MOUSE.DOLLY, 7156 RIGHT: MOUSE.PAN 7157 }); 7158 __publicField3(this, "object"); 7159 __publicField3(this, "domElement"); 7160 __publicField3(this, "cursorZoom", false); 7161 __publicField3(this, "target", new Vector3()); 7162 __publicField3(this, "mousePosition", new Vector2()); 7163 __publicField3(this, "STATE", { 7164 NONE: -1, 7165 ROTATE: 0, 7166 ZOOM: 1, 7167 PAN: 2, 7168 TOUCH_ROTATE: 3, 7169 TOUCH_ZOOM_PAN: 4 7170 }); 7171 __publicField3(this, "EPS", 1e-6); 7172 __publicField3(this, "lastZoom", 1); 7173 __publicField3(this, "lastPosition", new Vector3()); 7174 __publicField3(this, "cursorVector", new Vector3()); 7175 __publicField3(this, "targetVector", new Vector3()); 7176 __publicField3(this, "_state", this.STATE.NONE); 7177 __publicField3(this, "_keyState", this.STATE.NONE); 7178 __publicField3(this, "_eye", new Vector3()); 7179 __publicField3(this, "_movePrev", new Vector2()); 7180 __publicField3(this, "_moveCurr", new Vector2()); 7181 __publicField3(this, "_lastAxis", new Vector3()); 7182 __publicField3(this, "_lastAngle", 0); 7183 __publicField3(this, "_zoomStart", new Vector2()); 7184 __publicField3(this, "_zoomEnd", new Vector2()); 7185 __publicField3(this, "_touchZoomDistanceStart", 0); 7186 __publicField3(this, "_touchZoomDistanceEnd", 0); 7187 __publicField3(this, "_panStart", new Vector2()); 7188 __publicField3(this, "_panEnd", new Vector2()); 7189 __publicField3(this, "target0"); 7190 __publicField3(this, "position0"); 7191 __publicField3(this, "up0"); 7192 __publicField3(this, "zoom0"); 7193 __publicField3(this, "changeEvent", { type: "change" }); 7194 __publicField3(this, "startEvent", { type: "start" }); 7195 __publicField3(this, "endEvent", { type: "end" }); 7196 __publicField3(this, "onScreenVector", new Vector2()); 7197 __publicField3(this, "getMouseOnScreen", (pageX, pageY) => { 7198 this.onScreenVector.set( 7199 (pageX - this.screen.left) / this.screen.width, 7200 (pageY - this.screen.top) / this.screen.height 7201 ); 7202 return this.onScreenVector; 7203 }); 7204 __publicField3(this, "onCircleVector", new Vector2()); 7205 __publicField3(this, "getMouseOnCircle", (pageX, pageY) => { 7206 this.onCircleVector.set( 7207 (pageX - this.screen.width * 0.5 - this.screen.left) / (this.screen.width * 0.5), 7208 (this.screen.height + 2 * (this.screen.top - pageY)) / this.screen.width 7209 // screen.width intentional 7210 ); 7211 return this.onCircleVector; 7212 }); 7213 __publicField3(this, "axis", new Vector3()); 7214 __publicField3(this, "quaternion", new Quaternion()); 7215 __publicField3(this, "eyeDirection", new Vector3()); 7216 __publicField3(this, "objectUpDirection", new Vector3()); 7217 __publicField3(this, "objectSidewaysDirection", new Vector3()); 7218 __publicField3(this, "moveDirection", new Vector3()); 7219 __publicField3(this, "angle", 0); 7220 __publicField3(this, "rotateCamera", () => { 7221 this.moveDirection.set(this._moveCurr.x - this._movePrev.x, this._moveCurr.y - this._movePrev.y, 0); 7222 this.angle = this.moveDirection.length(); 7223 if (this.angle) { 7224 this._eye.copy(this.object.position).sub(this.target); 7225 this.eyeDirection.copy(this._eye).normalize(); 7226 this.objectUpDirection.copy(this.object.up).normalize(); 7227 this.objectSidewaysDirection.crossVectors(this.objectUpDirection, this.eyeDirection).normalize(); 7228 this.objectUpDirection.setLength(this._moveCurr.y - this._movePrev.y); 7229 this.objectSidewaysDirection.setLength(this._moveCurr.x - this._movePrev.x); 7230 this.moveDirection.copy(this.objectUpDirection.add(this.objectSidewaysDirection)); 7231 this.axis.crossVectors(this.moveDirection, this._eye).normalize(); 7232 this.angle *= this.rotateSpeed; 7233 this.quaternion.setFromAxisAngle(this.axis, this.angle); 7234 this._eye.applyQuaternion(this.quaternion); 7235 this.object.up.applyQuaternion(this.quaternion); 7236 this._lastAxis.copy(this.axis); 7237 this._lastAngle = this.angle; 7238 } else if (!this.staticMoving && this._lastAngle) { 7239 this._lastAngle *= Math.sqrt(1 - this.dynamicDampingFactor); 7240 this._eye.copy(this.object.position).sub(this.target); 7241 this.quaternion.setFromAxisAngle(this._lastAxis, this._lastAngle); 7242 this._eye.applyQuaternion(this.quaternion); 7243 this.object.up.applyQuaternion(this.quaternion); 7244 } 7245 this._movePrev.copy(this._moveCurr); 7246 }); 7247 __publicField3(this, "zoomCamera", () => { 7248 let factor; 7249 if (this._state === this.STATE.TOUCH_ZOOM_PAN) { 7250 factor = this._touchZoomDistanceStart / this._touchZoomDistanceEnd; 7251 this._touchZoomDistanceStart = this._touchZoomDistanceEnd; 7252 if (this.object.isPerspectiveCamera) { 7253 this._eye.multiplyScalar(factor); 7254 } else if (this.object.isOrthographicCamera) { 7255 this.object.zoom /= factor; 7256 this.object.updateProjectionMatrix(); 7257 } else { 7258 console.warn("THREE.TrackballControls: Unsupported camera type"); 7259 } 7260 } else { 7261 factor = 1 + (this._zoomEnd.y - this._zoomStart.y) * this.zoomSpeed; 7262 if (Math.abs(factor - 1) > this.EPS && factor > 0) { 7263 if (this.object.isPerspectiveCamera) { 7264 if (factor > 1 && this._eye.length() >= this.maxDistance - this.EPS) { 7265 factor = 1; 7266 } 7267 this._eye.multiplyScalar(factor); 7268 } else if (this.object.isOrthographicCamera) { 7269 if (factor > 1 && this.object.zoom < this.maxDistance * this.maxDistance) { 7270 factor = 1; 7271 } 7272 this.object.zoom /= factor; 7273 } else { 7274 console.warn("THREE.TrackballControls: Unsupported camera type"); 7275 } 7276 } 7277 if (this.staticMoving) { 7278 this._zoomStart.copy(this._zoomEnd); 7279 } else { 7280 this._zoomStart.y += (this._zoomEnd.y - this._zoomStart.y) * this.dynamicDampingFactor; 7281 } 7282 if (this.cursorZoom) { 7283 this.targetVector.copy(this.target).project(this.object); 7284 let worldPos = this.cursorVector.set(this.mousePosition.x, this.mousePosition.y, this.targetVector.z).unproject(this.object); 7285 this.target.lerpVectors(worldPos, this.target, factor); 7286 } 7287 if (this.object.isOrthographicCamera) { 7288 this.object.updateProjectionMatrix(); 7289 } 7290 } 7291 }); 7292 __publicField3(this, "mouseChange", new Vector2()); 7293 __publicField3(this, "objectUp", new Vector3()); 7294 __publicField3(this, "pan", new Vector3()); 7295 __publicField3(this, "panCamera", () => { 7296 if (!this.domElement) 7297 return; 7298 this.mouseChange.copy(this._panEnd).sub(this._panStart); 7299 if (this.mouseChange.lengthSq() > this.EPS) { 7300 if (this.object.isOrthographicCamera) { 7301 const orthoObject = this.object; 7302 const scale_x = (orthoObject.right - orthoObject.left) / this.object.zoom; 7303 const scale_y = (orthoObject.top - orthoObject.bottom) / this.object.zoom; 7304 this.mouseChange.x *= scale_x; 7305 this.mouseChange.y *= scale_y; 7306 } else { 7307 this.mouseChange.multiplyScalar(this._eye.length() * this.panSpeed); 7308 } 7309 this.pan.copy(this._eye).cross(this.object.up).setLength(this.mouseChange.x); 7310 this.pan.add(this.objectUp.copy(this.object.up).setLength(this.mouseChange.y)); 7311 this.object.position.add(this.pan); 7312 this.target.add(this.pan); 7313 if (this.staticMoving) { 7314 this._panStart.copy(this._panEnd); 7315 } else { 7316 this._panStart.add( 7317 this.mouseChange.subVectors(this._panEnd, this._panStart).multiplyScalar(this.dynamicDampingFactor) 7318 ); 7319 } 7320 } 7321 }); 7322 __publicField3(this, "checkDistances", () => { 7323 if (!this.noZoom || !this.noPan) { 7324 if (this._eye.lengthSq() > this.maxDistance * this.maxDistance) { 7325 this.object.position.addVectors(this.target, this._eye.setLength(this.maxDistance)); 7326 this._zoomStart.copy(this._zoomEnd); 7327 } 7328 if (this._eye.lengthSq() < this.minDistance * this.minDistance) { 7329 this.object.position.addVectors(this.target, this._eye.setLength(this.minDistance)); 7330 this._zoomStart.copy(this._zoomEnd); 7331 } 7332 } 7333 }); 7334 __publicField3(this, "handleResize", () => { 7335 if (!this.domElement) 7336 return; 7337 const box = this.domElement.getBoundingClientRect(); 7338 const d = this.domElement.ownerDocument.documentElement; 7339 this.screen.left = box.left + window.pageXOffset - d.clientLeft; 7340 this.screen.top = box.top + window.pageYOffset - d.clientTop; 7341 this.screen.width = box.width; 7342 this.screen.height = box.height; 7343 }); 7344 __publicField3(this, "update", () => { 7345 this._eye.subVectors(this.object.position, this.target); 7346 if (!this.noRotate) { 7347 this.rotateCamera(); 7348 } 7349 if (!this.noZoom) { 7350 this.zoomCamera(); 7351 } 7352 if (!this.noPan) { 7353 this.panCamera(); 7354 } 7355 this.object.position.addVectors(this.target, this._eye); 7356 if (this.object.isPerspectiveCamera) { 7357 this.checkDistances(); 7358 this.object.lookAt(this.target); 7359 if (this.lastPosition.distanceToSquared(this.object.position) > this.EPS) { 7360 this.dispatchEvent(this.changeEvent); 7361 this.lastPosition.copy(this.object.position); 7362 } 7363 } else if (this.object.isOrthographicCamera) { 7364 this.object.lookAt(this.target); 7365 if (this.lastPosition.distanceToSquared(this.object.position) > this.EPS || this.lastZoom !== this.object.zoom) { 7366 this.dispatchEvent(this.changeEvent); 7367 this.lastPosition.copy(this.object.position); 7368 this.lastZoom = this.object.zoom; 7369 } 7370 } else { 7371 console.warn("THREE.TrackballControls: Unsupported camera type"); 7372 } 7373 }); 7374 __publicField3(this, "reset", () => { 7375 this._state = this.STATE.NONE; 7376 this._keyState = this.STATE.NONE; 7377 this.target.copy(this.target0); 7378 this.object.position.copy(this.position0); 7379 this.object.up.copy(this.up0); 7380 this.object.zoom = this.zoom0; 7381 this.object.updateProjectionMatrix(); 7382 this._eye.subVectors(this.object.position, this.target); 7383 this.object.lookAt(this.target); 7384 this.dispatchEvent(this.changeEvent); 7385 this.lastPosition.copy(this.object.position); 7386 this.lastZoom = this.object.zoom; 7387 }); 7388 __publicField3(this, "keydown", (event) => { 7389 if (this.enabled === false) 7390 return; 7391 window.removeEventListener("keydown", this.keydown); 7392 if (this._keyState !== this.STATE.NONE) { 7393 return; 7394 } else if (event.code === this.keys[this.STATE.ROTATE] && !this.noRotate) { 7395 this._keyState = this.STATE.ROTATE; 7396 } else if (event.code === this.keys[this.STATE.ZOOM] && !this.noZoom) { 7397 this._keyState = this.STATE.ZOOM; 7398 } else if (event.code === this.keys[this.STATE.PAN] && !this.noPan) { 7399 this._keyState = this.STATE.PAN; 7400 } 7401 }); 7402 __publicField3(this, "onPointerDown", (event) => { 7403 if (this.enabled === false) 7404 return; 7405 switch (event.pointerType) { 7406 case "mouse": 7407 case "pen": 7408 this.onMouseDown(event); 7409 break; 7410 } 7411 }); 7412 __publicField3(this, "onPointerMove", (event) => { 7413 if (this.enabled === false) 7414 return; 7415 switch (event.pointerType) { 7416 case "mouse": 7417 case "pen": 7418 this.onMouseMove(event); 7419 break; 7420 } 7421 }); 7422 __publicField3(this, "onPointerUp", (event) => { 7423 if (this.enabled === false) 7424 return; 7425 switch (event.pointerType) { 7426 case "mouse": 7427 case "pen": 7428 this.onMouseUp(); 7429 break; 7430 } 7431 }); 7432 __publicField3(this, "keyup", () => { 7433 if (this.enabled === false) 7434 return; 7435 this._keyState = this.STATE.NONE; 7436 window.addEventListener("keydown", this.keydown); 7437 }); 7438 __publicField3(this, "onMouseDown", (event) => { 7439 if (!this.domElement) 7440 return; 7441 if (this._state === this.STATE.NONE) { 7442 switch (event.button) { 7443 case this.mouseButtons.LEFT: 7444 this._state = this.STATE.ROTATE; 7445 break; 7446 case this.mouseButtons.MIDDLE: 7447 this._state = this.STATE.ZOOM; 7448 break; 7449 case this.mouseButtons.RIGHT: 7450 this._state = this.STATE.PAN; 7451 break; 7452 } 7453 } 7454 const state = this._keyState !== this.STATE.NONE ? this._keyState : this._state; 7455 if (state === this.STATE.ROTATE && !this.noRotate) { 7456 this._moveCurr.copy(this.getMouseOnCircle(event.pageX, event.pageY)); 7457 this._movePrev.copy(this._moveCurr); 7458 } else if (state === this.STATE.ZOOM && !this.noZoom) { 7459 this._zoomStart.copy(this.getMouseOnScreen(event.pageX, event.pageY)); 7460 this._zoomEnd.copy(this._zoomStart); 7461 } else if (state === this.STATE.PAN && !this.noPan) { 7462 this._panStart.copy(this.getMouseOnScreen(event.pageX, event.pageY)); 7463 this._panEnd.copy(this._panStart); 7464 } 7465 this.domElement.ownerDocument.addEventListener("pointermove", this.onPointerMove); 7466 this.domElement.ownerDocument.addEventListener("pointerup", this.onPointerUp); 7467 this.dispatchEvent(this.startEvent); 7468 }); 7469 __publicField3(this, "onMouseMove", (event) => { 7470 if (this.enabled === false) 7471 return; 7472 const state = this._keyState !== this.STATE.NONE ? this._keyState : this._state; 7473 if (state === this.STATE.ROTATE && !this.noRotate) { 7474 this._movePrev.copy(this._moveCurr); 7475 this._moveCurr.copy(this.getMouseOnCircle(event.pageX, event.pageY)); 7476 } else if (state === this.STATE.ZOOM && !this.noZoom) { 7477 this._zoomEnd.copy(this.getMouseOnScreen(event.pageX, event.pageY)); 7478 } else if (state === this.STATE.PAN && !this.noPan) { 7479 this._panEnd.copy(this.getMouseOnScreen(event.pageX, event.pageY)); 7480 } 7481 }); 7482 __publicField3(this, "onMouseUp", () => { 7483 if (!this.domElement) 7484 return; 7485 if (this.enabled === false) 7486 return; 7487 this._state = this.STATE.NONE; 7488 this.domElement.ownerDocument.removeEventListener("pointermove", this.onPointerMove); 7489 this.domElement.ownerDocument.removeEventListener("pointerup", this.onPointerUp); 7490 this.dispatchEvent(this.endEvent); 7491 }); 7492 __publicField3(this, "mousewheel", (event) => { 7493 if (this.enabled === false) 7494 return; 7495 if (this.noZoom === true) 7496 return; 7497 event.preventDefault(); 7498 switch (event.deltaMode) { 7499 case 2: 7500 this._zoomStart.y -= event.deltaY * 0.025; 7501 break; 7502 case 1: 7503 this._zoomStart.y -= event.deltaY * 0.01; 7504 break; 7505 default: 7506 this._zoomStart.y -= event.deltaY * 25e-5; 7507 break; 7508 } 7509 this.mousePosition.x = event.offsetX / this.screen.width * 2 - 1; 7510 this.mousePosition.y = -(event.offsetY / this.screen.height) * 2 + 1; 7511 this.dispatchEvent(this.startEvent); 7512 this.dispatchEvent(this.endEvent); 7513 }); 7514 __publicField3(this, "touchstart", (event) => { 7515 if (this.enabled === false) 7516 return; 7517 event.preventDefault(); 7518 switch (event.touches.length) { 7519 case 1: 7520 this._state = this.STATE.TOUCH_ROTATE; 7521 this._moveCurr.copy(this.getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY)); 7522 this._movePrev.copy(this._moveCurr); 7523 break; 7524 default: 7525 this._state = this.STATE.TOUCH_ZOOM_PAN; 7526 const dx = event.touches[0].pageX - event.touches[1].pageX; 7527 const dy = event.touches[0].pageY - event.touches[1].pageY; 7528 this._touchZoomDistanceEnd = this._touchZoomDistanceStart = Math.sqrt(dx * dx + dy * dy); 7529 const x = (event.touches[0].pageX + event.touches[1].pageX) / 2; 7530 const y = (event.touches[0].pageY + event.touches[1].pageY) / 2; 7531 this._panStart.copy(this.getMouseOnScreen(x, y)); 7532 this._panEnd.copy(this._panStart); 7533 break; 7534 } 7535 this.dispatchEvent(this.startEvent); 7536 }); 7537 __publicField3(this, "touchmove", (event) => { 7538 if (this.enabled === false) 7539 return; 7540 event.preventDefault(); 7541 switch (event.touches.length) { 7542 case 1: 7543 this._movePrev.copy(this._moveCurr); 7544 this._moveCurr.copy(this.getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY)); 7545 break; 7546 default: 7547 const dx = event.touches[0].pageX - event.touches[1].pageX; 7548 const dy = event.touches[0].pageY - event.touches[1].pageY; 7549 this._touchZoomDistanceEnd = Math.sqrt(dx * dx + dy * dy); 7550 const x = (event.touches[0].pageX + event.touches[1].pageX) / 2; 7551 const y = (event.touches[0].pageY + event.touches[1].pageY) / 2; 7552 this._panEnd.copy(this.getMouseOnScreen(x, y)); 7553 break; 7554 } 7555 }); 7556 __publicField3(this, "touchend", (event) => { 7557 if (this.enabled === false) 7558 return; 7559 switch (event.touches.length) { 7560 case 0: 7561 this._state = this.STATE.NONE; 7562 break; 7563 case 1: 7564 this._state = this.STATE.TOUCH_ROTATE; 7565 this._moveCurr.copy(this.getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY)); 7566 this._movePrev.copy(this._moveCurr); 7567 break; 7568 } 7569 this.dispatchEvent(this.endEvent); 7570 }); 7571 __publicField3(this, "contextmenu", (event) => { 7572 if (this.enabled === false) 7573 return; 7574 event.preventDefault(); 7575 }); 7576 __publicField3(this, "connect", (domElement2) => { 7577 if (domElement2 === document) { 7578 console.error( 7579 'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' 7580 ); 7581 } 7582 this.domElement = domElement2; 7583 this.domElement.addEventListener("contextmenu", this.contextmenu); 7584 this.domElement.addEventListener("pointerdown", this.onPointerDown); 7585 this.domElement.addEventListener("wheel", this.mousewheel); 7586 this.domElement.addEventListener("touchstart", this.touchstart); 7587 this.domElement.addEventListener("touchend", this.touchend); 7588 this.domElement.addEventListener("touchmove", this.touchmove); 7589 this.domElement.ownerDocument.addEventListener("pointermove", this.onPointerMove); 7590 this.domElement.ownerDocument.addEventListener("pointerup", this.onPointerUp); 7591 window.addEventListener("keydown", this.keydown); 7592 window.addEventListener("keyup", this.keyup); 7593 this.handleResize(); 7594 }); 7595 __publicField3(this, "dispose", () => { 7596 if (!this.domElement) 7597 return; 7598 this.domElement.removeEventListener("contextmenu", this.contextmenu); 7599 this.domElement.removeEventListener("pointerdown", this.onPointerDown); 7600 this.domElement.removeEventListener("wheel", this.mousewheel); 7601 this.domElement.removeEventListener("touchstart", this.touchstart); 7602 this.domElement.removeEventListener("touchend", this.touchend); 7603 this.domElement.removeEventListener("touchmove", this.touchmove); 7604 this.domElement.ownerDocument.removeEventListener("pointermove", this.onPointerMove); 7605 this.domElement.ownerDocument.removeEventListener("pointerup", this.onPointerUp); 7606 window.removeEventListener("keydown", this.keydown); 7607 window.removeEventListener("keyup", this.keyup); 7608 }); 7609 this.object = object; 7610 this.target0 = this.target.clone(); 7611 this.position0 = this.object.position.clone(); 7612 this.up0 = this.object.up.clone(); 7613 this.zoom0 = this.object.zoom; 7614 if (domElement !== void 0) 7615 this.connect(domElement); 7616 this.update(); 7617 } 7618}; 7619
vendor: 2,937 bytes, lines 7620-7699
7620// node_modules/three-stdlib/webxr/XRHandMeshModel.js 7621var __defProp4 = Object.defineProperty; 7622var __defNormalProp4 = (obj, key, value) => key in obj ? __defProp4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; 7623var __publicField4 = (obj, key, value) => { 7624 __defNormalProp4(obj, typeof key !== "symbol" ? key + "" : key, value); 7625 return value; 7626}; 7627var DEFAULT_HAND_PROFILE_PATH = "https://cdn.jsdelivr.net/npm/@webxr-input-profiles/[email protected]/dist/profiles/generic-hand/"; 7628var XRHandMeshModel = class { 7629 constructor(handModel, controller, path = DEFAULT_HAND_PROFILE_PATH, handedness, customModelPath) { 7630 __publicField4(this, "controller"); 7631 __publicField4(this, "handModel"); 7632 __publicField4(this, "bones"); 7633 this.controller = controller; 7634 this.handModel = handModel; 7635 this.bones = []; 7636 const loader = new GLTFLoader(); 7637 if (!customModelPath) 7638 loader.setPath(path); 7639 loader.load(customModelPath != null ? customModelPath : `${handedness}.glb`, (gltf) => { 7640 const object = gltf.scene.children[0]; 7641 this.handModel.add(object); 7642 const mesh = object.getObjectByProperty("type", "SkinnedMesh"); 7643 mesh.frustumCulled = false; 7644 mesh.castShadow = true; 7645 mesh.receiveShadow = true; 7646 const joints = [ 7647 "wrist", 7648 "thumb-metacarpal", 7649 "thumb-phalanx-proximal", 7650 "thumb-phalanx-distal", 7651 "thumb-tip", 7652 "index-finger-metacarpal", 7653 "index-finger-phalanx-proximal", 7654 "index-finger-phalanx-intermediate", 7655 "index-finger-phalanx-distal", 7656 "index-finger-tip", 7657 "middle-finger-metacarpal", 7658 "middle-finger-phalanx-proximal", 7659 "middle-finger-phalanx-intermediate", 7660 "middle-finger-phalanx-distal", 7661 "middle-finger-tip", 7662 "ring-finger-metacarpal", 7663 "ring-finger-phalanx-proximal", 7664 "ring-finger-phalanx-intermediate", 7665 "ring-finger-phalanx-distal", 7666 "ring-finger-tip", 7667 "pinky-finger-metacarpal", 7668 "pinky-finger-phalanx-proximal", 7669 "pinky-finger-phalanx-intermediate", 7670 "pinky-finger-phalanx-distal", 7671 "pinky-finger-tip" 7672 ]; 7673 joints.forEach((jointName) => { 7674 const bone = object.getObjectByName(jointName); 7675 if (bone !== void 0) { 7676 bone.jointName = jointName; 7677 } else { 7678 console.warn(`Couldn't find ${jointName} in ${handedness} hand mesh`); 7679 } 7680 this.bones.push(bone); 7681 }); 7682 }); 7683 } 7684 updateMesh() { 7685 const XRJoints = this.controller.joints; 7686 for (let i = 0; i < this.bones.length; i++) { 7687 const bone = this.bones[i]; 7688 if (bone) { 7689 const XRJoint = XRJoints[bone.jointName]; 7690 if (XRJoint.visible) { 7691 const position2 = XRJoint.position; 7692 bone.position.copy(position2); 7693 bone.quaternion.copy(XRJoint.quaternion); 7694 } 7695 } 7696 } 7697 } 7698}; 7699
vendor: 974 bytes, lines 7700-7728
7700// node_modules/three-stdlib/webxr/Text2D.js 7701function createText(message, height) { 7702 const canvas = document.createElement("canvas"); 7703 const context = canvas.getContext("2d"); 7704 let metrics = null; 7705 const textHeight = 100; 7706 context.font = "normal " + textHeight + "px Arial"; 7707 metrics = context.measureText(message); 7708 const textWidth = metrics.width; 7709 canvas.width = textWidth; 7710 canvas.height = textHeight; 7711 context.font = "normal " + textHeight + "px Arial"; 7712 context.textAlign = "center"; 7713 context.textBaseline = "middle"; 7714 context.fillStyle = "#ffffff"; 7715 context.fillText(message, textWidth / 2, textHeight / 2); 7716 const texture = new Texture(canvas); 7717 texture.needsUpdate = true; 7718 const material = new MeshBasicMaterial({ 7719 color: 16777215, 7720 side: DoubleSide, 7721 map: texture, 7722 transparent: true 7723 }); 7724 const geometry = new PlaneGeometry(height * textWidth / textHeight, height); 7725 const plane = new Mesh(geometry, material); 7726 return plane; 7727} 7728
vendor: 12,304 bytes, lines 7729-8049
7729// node_modules/three-stdlib/libs/MotionControllers.js 7730var __defProp5 = Object.defineProperty; 7731var __defNormalProp5 = (obj, key, value) => key in obj ? __defProp5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; 7732var __publicField5 = (obj, key, value) => { 7733 __defNormalProp5(obj, typeof key !== "symbol" ? key + "" : key, value); 7734 return value; 7735}; 7736var MotionControllerConstants = { 7737 Handedness: { 7738 NONE: "none", 7739 LEFT: "left", 7740 RIGHT: "right" 7741 }, 7742 ComponentState: { 7743 DEFAULT: "default", 7744 TOUCHED: "touched", 7745 PRESSED: "pressed" 7746 }, 7747 ComponentProperty: { 7748 BUTTON: "button", 7749 X_AXIS: "xAxis", 7750 Y_AXIS: "yAxis", 7751 STATE: "state" 7752 }, 7753 ComponentType: { 7754 TRIGGER: "trigger", 7755 SQUEEZE: "squeeze", 7756 TOUCHPAD: "touchpad", 7757 THUMBSTICK: "thumbstick", 7758 BUTTON: "button" 7759 }, 7760 ButtonTouchThreshold: 0.05, 7761 AxisTouchThreshold: 0.1, 7762 VisualResponseProperty: { 7763 TRANSFORM: "transform", 7764 VISIBILITY: "visibility" 7765 } 7766}; 7767async function fetchJsonFile(path) { 7768 const response = await fetch(path); 7769 if (!response.ok) { 7770 throw new Error(response.statusText); 7771 } else { 7772 return response.json(); 7773 } 7774} 7775async function fetchProfilesList(basePath) { 7776 if (!basePath) { 7777 throw new Error("No basePath supplied"); 7778 } 7779 const profileListFileName = "profilesList.json"; 7780 const profilesList = await fetchJsonFile(`${basePath}/${profileListFileName}`); 7781 return profilesList; 7782} 7783async function fetchProfile(xrInputSource, basePath, defaultProfile = null, getAssetPath = true) { 7784 if (!xrInputSource) { 7785 throw new Error("No xrInputSource supplied"); 7786 } 7787 if (!basePath) { 7788 throw new Error("No basePath supplied"); 7789 } 7790 const supportedProfilesList = await fetchProfilesList(basePath); 7791 let match = void 0; 7792 xrInputSource.profiles.some((profileId) => { 7793 const supportedProfile = supportedProfilesList[profileId]; 7794 if (supportedProfile) { 7795 match = { 7796 profileId, 7797 profilePath: `${basePath}/${supportedProfile.path}`, 7798 deprecated: !!supportedProfile.deprecated 7799 }; 7800 } 7801 return !!match; 7802 }); 7803 if (!match) { 7804 if (!defaultProfile) { 7805 throw new Error("No matching profile name found"); 7806 } 7807 const supportedProfile = supportedProfilesList[defaultProfile]; 7808 if (!supportedProfile) { 7809 throw new Error(`No matching profile name found and default profile "${defaultProfile}" missing.`); 7810 } 7811 match = { 7812 profileId: defaultProfile, 7813 profilePath: `${basePath}/${supportedProfile.path}`, 7814 deprecated: !!supportedProfile.deprecated 7815 }; 7816 } 7817 const profile = await fetchJsonFile(match.profilePath); 7818 let assetPath = void 0; 7819 if (getAssetPath) { 7820 let layout; 7821 if (xrInputSource.handedness === "any") { 7822 layout = profile.layouts[Object.keys(profile.layouts)[0]]; 7823 } else { 7824 layout = profile.layouts[xrInputSource.handedness]; 7825 } 7826 if (!layout) { 7827 throw new Error(`No matching handedness, ${xrInputSource.handedness}, in profile ${match.profileId}`); 7828 } 7829 if (layout.assetPath) { 7830 assetPath = match.profilePath.replace("profile.json", layout.assetPath); 7831 } 7832 } 7833 return { profile, assetPath }; 7834} 7835var defaultComponentValues = { 7836 xAxis: 0, 7837 yAxis: 0, 7838 button: 0, 7839 state: MotionControllerConstants.ComponentState.DEFAULT 7840}; 7841function normalizeAxes(x = 0, y = 0) { 7842 let xAxis = x; 7843 let yAxis = y; 7844 const hypotenuse = Math.sqrt(x * x + y * y); 7845 if (hypotenuse > 1) { 7846 const theta = Math.atan2(y, x); 7847 xAxis = Math.cos(theta); 7848 yAxis = Math.sin(theta); 7849 } 7850 const result = { 7851 normalizedXAxis: xAxis * 0.5 + 0.5, 7852 normalizedYAxis: yAxis * 0.5 + 0.5 7853 }; 7854 return result; 7855} 7856var VisualResponse = class { 7857 constructor(visualResponseDescription) { 7858 __publicField5(this, "value"); 7859 __publicField5(this, "componentProperty"); 7860 __publicField5(this, "states"); 7861 __publicField5(this, "valueNodeName"); 7862 __publicField5(this, "valueNodeProperty"); 7863 __publicField5(this, "minNodeName"); 7864 __publicField5(this, "maxNodeName"); 7865 __publicField5(this, "valueNode"); 7866 __publicField5(this, "minNode"); 7867 __publicField5(this, "maxNode"); 7868 this.componentProperty = visualResponseDescription.componentProperty; 7869 this.states = visualResponseDescription.states; 7870 this.valueNodeName = visualResponseDescription.valueNodeName; 7871 this.valueNodeProperty = visualResponseDescription.valueNodeProperty; 7872 if (this.valueNodeProperty === MotionControllerConstants.VisualResponseProperty.TRANSFORM) { 7873 this.minNodeName = visualResponseDescription.minNodeName; 7874 this.maxNodeName = visualResponseDescription.maxNodeName; 7875 } 7876 this.value = 0; 7877 this.updateFromComponent(defaultComponentValues); 7878 } 7879 /** 7880 * Computes the visual response's interpolation weight based on component state 7881 * @param {Object} componentValues - The component from which to update 7882 * @param {number | undefined} xAxis - The reported X axis value of the component 7883 * @param {number | undefined} yAxis - The reported Y axis value of the component 7884 * @param {number | undefined} button - The reported value of the component's button 7885 * @param {string} state - The component's active state 7886 */ 7887 updateFromComponent({ 7888 xAxis, 7889 yAxis, 7890 button, 7891 state 7892 }) { 7893 const { normalizedXAxis, normalizedYAxis } = normalizeAxes(xAxis, yAxis); 7894 switch (this.componentProperty) { 7895 case MotionControllerConstants.ComponentProperty.X_AXIS: 7896 this.value = this.states.includes(state) ? normalizedXAxis : 0.5; 7897 break; 7898 case MotionControllerConstants.ComponentProperty.Y_AXIS: 7899 this.value = this.states.includes(state) ? normalizedYAxis : 0.5; 7900 break; 7901 case MotionControllerConstants.ComponentProperty.BUTTON: 7902 this.value = this.states.includes(state) && button ? button : 0; 7903 break; 7904 case MotionControllerConstants.ComponentProperty.STATE: 7905 if (this.valueNodeProperty === MotionControllerConstants.VisualResponseProperty.VISIBILITY) { 7906 this.value = this.states.includes(state); 7907 } else { 7908 this.value = this.states.includes(state) ? 1 : 0; 7909 } 7910 break; 7911 default: 7912 throw new Error(`Unexpected visualResponse componentProperty ${this.componentProperty}`); 7913 } 7914 } 7915}; 7916var Component = class { 7917 /** 7918 * @param {string} componentId - Id of the component 7919 * @param {InputProfileComponent} componentDescription - Description of the component to be created 7920 */ 7921 constructor(componentId, componentDescription) { 7922 __publicField5(this, "id"); 7923 __publicField5(this, "values"); 7924 __publicField5(this, "type"); 7925 __publicField5(this, "gamepadIndices"); 7926 __publicField5(this, "rootNodeName"); 7927 __publicField5(this, "visualResponses"); 7928 __publicField5(this, "touchPointNodeName"); 7929 __publicField5(this, "touchPointNode"); 7930 if (!componentId || !componentDescription || !componentDescription.visualResponses || !componentDescription.gamepadIndices || Object.keys(componentDescription.gamepadIndices).length === 0) { 7931 throw new Error("Invalid arguments supplied"); 7932 } 7933 this.id = componentId; 7934 this.type = componentDescription.type; 7935 this.rootNodeName = componentDescription.rootNodeName; 7936 this.touchPointNodeName = componentDescription.touchPointNodeName; 7937 this.visualResponses = {}; 7938 Object.keys(componentDescription.visualResponses).forEach((responseName) => { 7939 const visualResponse = new VisualResponse(componentDescription.visualResponses[responseName]); 7940 this.visualResponses[responseName] = visualResponse; 7941 }); 7942 this.gamepadIndices = Object.assign({}, componentDescription.gamepadIndices); 7943 this.values = { 7944 state: MotionControllerConstants.ComponentState.DEFAULT, 7945 button: this.gamepadIndices.button !== void 0 ? 0 : void 0, 7946 xAxis: this.gamepadIndices.xAxis !== void 0 ? 0 : void 0, 7947 yAxis: this.gamepadIndices.yAxis !== void 0 ? 0 : void 0 7948 }; 7949 } 7950 get data() { 7951 const data = { id: this.id, ...this.values }; 7952 return data; 7953 } 7954 /** 7955 * @description Poll for updated data based on current gamepad state 7956 * @param {Object} gamepad - The gamepad object from which the component data should be polled 7957 */ 7958 updateFromGamepad(gamepad) { 7959 this.values.state = MotionControllerConstants.ComponentState.DEFAULT; 7960 if (this.gamepadIndices.button !== void 0 && gamepad.buttons.length > this.gamepadIndices.button) { 7961 const gamepadButton = gamepad.buttons[this.gamepadIndices.button]; 7962 this.values.button = gamepadButton.value; 7963 this.values.button = this.values.button < 0 ? 0 : this.values.button; 7964 this.values.button = this.values.button > 1 ? 1 : this.values.button; 7965 if (gamepadButton.pressed || this.values.button === 1) { 7966 this.values.state = MotionControllerConstants.ComponentState.PRESSED; 7967 } else if (gamepadButton.touched || this.values.button > MotionControllerConstants.ButtonTouchThreshold) { 7968 this.values.state = MotionControllerConstants.ComponentState.TOUCHED; 7969 } 7970 } 7971 if (this.gamepadIndices.xAxis !== void 0 && gamepad.axes.length > this.gamepadIndices.xAxis) { 7972 this.values.xAxis = gamepad.axes[this.gamepadIndices.xAxis]; 7973 this.values.xAxis = this.values.xAxis < -1 ? -1 : this.values.xAxis; 7974 this.values.xAxis = this.values.xAxis > 1 ? 1 : this.values.xAxis; 7975 if (this.values.state === MotionControllerConstants.ComponentState.DEFAULT && Math.abs(this.values.xAxis) > MotionControllerConstants.AxisTouchThreshold) { 7976 this.values.state = MotionControllerConstants.ComponentState.TOUCHED; 7977 } 7978 } 7979 if (this.gamepadIndices.yAxis !== void 0 && gamepad.axes.length > this.gamepadIndices.yAxis) { 7980 this.values.yAxis = gamepad.axes[this.gamepadIndices.yAxis]; 7981 this.values.yAxis = this.values.yAxis < -1 ? -1 : this.values.yAxis; 7982 this.values.yAxis = this.values.yAxis > 1 ? 1 : this.values.yAxis; 7983 if (this.values.state === MotionControllerConstants.ComponentState.DEFAULT && Math.abs(this.values.yAxis) > MotionControllerConstants.AxisTouchThreshold) { 7984 this.values.state = MotionControllerConstants.ComponentState.TOUCHED; 7985 } 7986 } 7987 Object.values(this.visualResponses).forEach((visualResponse) => { 7988 visualResponse.updateFromComponent(this.values); 7989 }); 7990 } 7991}; 7992var MotionController = class { 7993 /** 7994 * @param {XRInputSource} xrInputSource - The XRInputSource to build the MotionController around 7995 * @param {Profile} profile - The best matched profile description for the supplied xrInputSource 7996 * @param {string} assetUrl 7997 */ 7998 constructor(xrInputSource, profile, assetUrl) { 7999 __publicField5(this, "xrInputSource"); 8000 __publicField5(this, "assetUrl"); 8001 __publicField5(this, "layoutDescription"); 8002 __publicField5(this, "id"); 8003 __publicField5(this, "components"); 8004 if (!xrInputSource) { 8005 throw new Error("No xrInputSource supplied"); 8006 } 8007 if (!profile) { 8008 throw new Error("No profile supplied"); 8009 } 8010 if (!profile.layouts[xrInputSource.handedness]) { 8011 throw new Error("No layout for " + xrInputSource.handedness + " handedness"); 8012 } 8013 this.xrInputSource = xrInputSource; 8014 this.assetUrl = assetUrl; 8015 this.id = profile.profileId; 8016 this.layoutDescription = profile.layouts[xrInputSource.handedness]; 8017 this.components = {}; 8018 Object.keys(this.layoutDescription.components).forEach((componentId) => { 8019 const componentDescription = this.layoutDescription.components[componentId]; 8020 this.components[componentId] = new Component(componentId, componentDescription); 8021 }); 8022 this.updateFromGamepad(); 8023 } 8024 get gripSpace() { 8025 return this.xrInputSource.gripSpace; 8026 } 8027 get targetRaySpace() { 8028 return this.xrInputSource.targetRaySpace; 8029 } 8030 /** 8031 * @description Returns a subset of component data for simplified debugging 8032 */ 8033 get data() { 8034 const data = []; 8035 Object.values(this.components).forEach((component) => { 8036 data.push(component.data); 8037 }); 8038 return data; 8039 } 8040 /** 8041 * @description Poll for updated data based on current gamepad state 8042 */ 8043 updateFromGamepad() { 8044 Object.values(this.components).forEach((component) => { 8045 component.updateFromGamepad(this.xrInputSource.gamepad); 8046 }); 8047 } 8048}; 8049
vendor: 6,727 bytes, lines 8050-8219
8050// node_modules/three-stdlib/webxr/XRControllerModelFactory.js 8051var __defProp6 = Object.defineProperty; 8052var __defNormalProp6 = (obj, key, value) => key in obj ? __defProp6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; 8053var __publicField6 = (obj, key, value) => { 8054 __defNormalProp6(obj, typeof key !== "symbol" ? key + "" : key, value); 8055 return value; 8056}; 8057var DEFAULT_PROFILES_PATH = "https://cdn.jsdelivr.net/npm/@webxr-input-profiles/[email protected]/dist/profiles"; 8058var DEFAULT_PROFILE = "generic-trigger"; 8059var applyEnvironmentMap = (envMap, obj) => { 8060 obj.traverse((child) => { 8061 if (child instanceof Mesh && "envMap" in child.material) { 8062 child.material.envMap = envMap; 8063 child.material.needsUpdate = true; 8064 } 8065 }); 8066}; 8067var XRControllerModel = class extends Object3D { 8068 constructor() { 8069 super(); 8070 __publicField6(this, "envMap"); 8071 __publicField6(this, "motionController"); 8072 this.motionController = null; 8073 this.envMap = null; 8074 } 8075 setEnvironmentMap(envMap) { 8076 if (this.envMap == envMap) { 8077 return this; 8078 } 8079 this.envMap = envMap; 8080 applyEnvironmentMap(this.envMap, this); 8081 return this; 8082 } 8083 /** 8084 * Polls data from the XRInputSource and updates the model's components to match 8085 * the real world data 8086 */ 8087 updateMatrixWorld(force) { 8088 super.updateMatrixWorld(force); 8089 if (!this.motionController) 8090 return; 8091 this.motionController.updateFromGamepad(); 8092 Object.values(this.motionController.components).forEach((component) => { 8093 Object.values(component.visualResponses).forEach((visualResponse) => { 8094 const { valueNode, minNode, maxNode, value, valueNodeProperty } = visualResponse; 8095 if (!valueNode) 8096 return; 8097 if (valueNodeProperty === MotionControllerConstants.VisualResponseProperty.VISIBILITY && typeof value === "boolean") { 8098 valueNode.visible = value; 8099 } else if (valueNodeProperty === MotionControllerConstants.VisualResponseProperty.TRANSFORM && minNode && maxNode && typeof value === "number") { 8100 valueNode.quaternion.slerpQuaternions(minNode.quaternion, maxNode.quaternion, value); 8101 valueNode.position.lerpVectors(minNode.position, maxNode.position, value); 8102 } 8103 }); 8104 }); 8105 } 8106}; 8107function findNodes(motionController, scene) { 8108 Object.values(motionController.components).forEach((component) => { 8109 const { type, touchPointNodeName, visualResponses } = component; 8110 if (type === MotionControllerConstants.ComponentType.TOUCHPAD && touchPointNodeName) { 8111 component.touchPointNode = scene.getObjectByName(touchPointNodeName); 8112 if (component.touchPointNode) { 8113 const sphereGeometry = new SphereGeometry(1e-3); 8114 const material = new MeshBasicMaterial({ color: 255 }); 8115 const sphere = new Mesh(sphereGeometry, material); 8116 component.touchPointNode.add(sphere); 8117 } else { 8118 console.warn(`Could not find touch dot, ${component.touchPointNodeName}, in touchpad component ${component.id}`); 8119 } 8120 } 8121 Object.values(visualResponses).forEach((visualResponse) => { 8122 const { valueNodeName, minNodeName, maxNodeName, valueNodeProperty } = visualResponse; 8123 if (valueNodeProperty === MotionControllerConstants.VisualResponseProperty.TRANSFORM && minNodeName && maxNodeName) { 8124 visualResponse.minNode = scene.getObjectByName(minNodeName); 8125 visualResponse.maxNode = scene.getObjectByName(maxNodeName); 8126 if (!visualResponse.minNode) { 8127 console.warn(`Could not find ${minNodeName} in the model`); 8128 return; 8129 } 8130 if (!visualResponse.maxNode) { 8131 console.warn(`Could not find ${maxNodeName} in the model`); 8132 return; 8133 } 8134 } 8135 visualResponse.valueNode = scene.getObjectByName(valueNodeName); 8136 if (!visualResponse.valueNode) { 8137 console.warn(`Could not find ${valueNodeName} in the model`); 8138 } 8139 }); 8140 }); 8141} 8142function addAssetSceneToControllerModel(controllerModel, scene) { 8143 findNodes(controllerModel.motionController, scene); 8144 if (controllerModel.envMap) { 8145 applyEnvironmentMap(controllerModel.envMap, scene); 8146 } 8147 controllerModel.add(scene); 8148} 8149var XRControllerModelFactory = class { 8150 constructor(gltfLoader = null) { 8151 __publicField6(this, "gltfLoader"); 8152 __publicField6(this, "path"); 8153 __publicField6(this, "_assetCache"); 8154 this.gltfLoader = gltfLoader; 8155 this.path = DEFAULT_PROFILES_PATH; 8156 this._assetCache = {}; 8157 if (!this.gltfLoader) { 8158 this.gltfLoader = new GLTFLoader(); 8159 } 8160 } 8161 createControllerModel(controller) { 8162 const controllerModel = new XRControllerModel(); 8163 let scene = null; 8164 const onConnected = (event) => { 8165 const xrInputSource = event.data; 8166 if (xrInputSource.targetRayMode !== "tracked-pointer" || !xrInputSource.gamepad) 8167 return; 8168 fetchProfile(xrInputSource, this.path, DEFAULT_PROFILE).then(({ profile, assetPath }) => { 8169 if (!assetPath) { 8170 throw new Error("no asset path"); 8171 } 8172 controllerModel.motionController = new MotionController(xrInputSource, profile, assetPath); 8173 const assetUrl = controllerModel.motionController.assetUrl; 8174 const cachedAsset = this._assetCache[assetUrl]; 8175 if (cachedAsset) { 8176 scene = cachedAsset.scene.clone(); 8177 addAssetSceneToControllerModel(controllerModel, scene); 8178 } else { 8179 if (!this.gltfLoader) { 8180 throw new Error("GLTFLoader not set."); 8181 } 8182 this.gltfLoader.setPath(""); 8183 this.gltfLoader.load( 8184 controllerModel.motionController.assetUrl, 8185 (asset) => { 8186 if (!controllerModel.motionController) { 8187 console.warn("motionController gone while gltf load, bailing..."); 8188 return; 8189 } 8190 this._assetCache[assetUrl] = asset; 8191 scene = asset.scene.clone(); 8192 addAssetSceneToControllerModel(controllerModel, scene); 8193 }, 8194 () => { 8195 }, 8196 () => { 8197 throw new Error(`Asset ${assetUrl} missing or malformed.`); 8198 } 8199 ); 8200 } 8201 }).catch((err) => { 8202 console.warn(err); 8203 }); 8204 }; 8205 controller.addEventListener("connected", onConnected); 8206 const onDisconnected = () => { 8207 controller.removeEventListener("connected", onConnected); 8208 controller.removeEventListener("disconnected", onDisconnected); 8209 controllerModel.motionController = null; 8210 if (scene) { 8211 controllerModel.remove(scene); 8212 } 8213 scene = null; 8214 }; 8215 controller.addEventListener("disconnected", onDisconnected); 8216 return controllerModel; 8217 } 8218}; 8219
vendor: 2,269 bytes, lines 8220-8285
8220// node_modules/three-stdlib/webxr/XRHandPrimitiveModel.js 8221var _matrix = /* @__PURE__ */ new Matrix4(); 8222var _vector2 = /* @__PURE__ */ new Vector3(); 8223var XRHandPrimitiveModel = class { 8224 constructor(handModel, controller, path, handedness, options) { 8225 this.controller = controller; 8226 this.handModel = handModel; 8227 this.envMap = null; 8228 let geometry; 8229 if (!options || !options.primitive || options.primitive === "sphere") { 8230 geometry = new SphereGeometry(1, 10, 10); 8231 } else if (options.primitive === "box") { 8232 geometry = new BoxGeometry(1, 1, 1); 8233 } 8234 const material = new MeshStandardMaterial(); 8235 this.handMesh = new InstancedMesh(geometry, material, 30); 8236 this.handMesh.instanceMatrix.setUsage(DynamicDrawUsage); 8237 this.handMesh.castShadow = true; 8238 this.handMesh.receiveShadow = true; 8239 this.handModel.add(this.handMesh); 8240 this.joints = [ 8241 "wrist", 8242 "thumb-metacarpal", 8243 "thumb-phalanx-proximal", 8244 "thumb-phalanx-distal", 8245 "thumb-tip", 8246 "index-finger-metacarpal", 8247 "index-finger-phalanx-proximal", 8248 "index-finger-phalanx-intermediate", 8249 "index-finger-phalanx-distal", 8250 "index-finger-tip", 8251 "middle-finger-metacarpal", 8252 "middle-finger-phalanx-proximal", 8253 "middle-finger-phalanx-intermediate", 8254 "middle-finger-phalanx-distal", 8255 "middle-finger-tip", 8256 "ring-finger-metacarpal", 8257 "ring-finger-phalanx-proximal", 8258 "ring-finger-phalanx-intermediate", 8259 "ring-finger-phalanx-distal", 8260 "ring-finger-tip", 8261 "pinky-finger-metacarpal", 8262 "pinky-finger-phalanx-proximal", 8263 "pinky-finger-phalanx-intermediate", 8264 "pinky-finger-phalanx-distal", 8265 "pinky-finger-tip" 8266 ]; 8267 } 8268 updateMesh() { 8269 const defaultRadius = 8e-3; 8270 const joints = this.controller.joints; 8271 let count = 0; 8272 for (let i = 0; i < this.joints.length; i++) { 8273 const joint = joints[this.joints[i]]; 8274 if (joint.visible) { 8275 _vector2.setScalar(joint.jointRadius || defaultRadius); 8276 _matrix.compose(joint.position, joint.quaternion, _vector2); 8277 this.handMesh.setMatrixAt(i, _matrix); 8278 count++; 8279 } 8280 } 8281 this.handMesh.count = count; 8282 this.handMesh.instanceMatrix.needsUpdate = true; 8283 } 8284}; 8285
vendor: 1,926 bytes, lines 8286-8360
8286// node_modules/three-stdlib/webxr/XRHandModelFactory.js 8287var XRHandModel = class extends Object3D { 8288 constructor(controller) { 8289 super(); 8290 this.controller = controller; 8291 this.motionController = null; 8292 this.envMap = null; 8293 this.mesh = null; 8294 } 8295 updateMatrixWorld(force) { 8296 super.updateMatrixWorld(force); 8297 if (this.motionController) { 8298 this.motionController.updateMesh(); 8299 } 8300 } 8301}; 8302var XRHandModelFactory = class { 8303 constructor() { 8304 this.path = null; 8305 } 8306 setPath(path) { 8307 this.path = path; 8308 return this; 8309 } 8310 createHandModel(controller, profile) { 8311 const handModel = new XRHandModel(controller); 8312 controller.addEventListener("connected", (event) => { 8313 const xrInputSource = event.data; 8314 if (xrInputSource.hand && !handModel.motionController) { 8315 handModel.xrInputSource = xrInputSource; 8316 if (profile === void 0 || profile === "spheres") { 8317 handModel.motionController = new XRHandPrimitiveModel( 8318 handModel, 8319 controller, 8320 this.path, 8321 xrInputSource.handedness, 8322 { primitive: "sphere" } 8323 ); 8324 } else if (profile === "boxes") { 8325 handModel.motionController = new XRHandPrimitiveModel( 8326 handModel, 8327 controller, 8328 this.path, 8329 xrInputSource.handedness, 8330 { primitive: "box" } 8331 ); 8332 } else if (profile === "mesh") { 8333 handModel.motionController = new XRHandMeshModel(handModel, controller, this.path, xrInputSource.handedness); 8334 } 8335 } 8336 }); 8337 controller.addEventListener("disconnected", () => { 8338 }); 8339 return handModel; 8340 } 8341}; 8342 8343export { 8344 useFrame, 8345 useThree, 8346 Canvas, 8347 Resource, 8348 createT, 8349 useXR, 8350 createXR, 8351 CSS2DObject, 8352 CSS2DRenderer, 8353 GLTFExporter, 8354 TrackballControls, 8355 GLTFLoader, 8356 createText, 8357 XRControllerModelFactory, 8358 XRHandModelFactory, 8359 DRACOLoader 8360};
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.