@needle-tools/engine 4.12.5 → 4.13.0-next.2d429c0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +1 -1
  3. package/custom-elements.json +18 -1
  4. package/dist/{gltf-progressive-BqUnxvCx.umd.cjs → gltf-progressive-BURrJW0U.umd.cjs} +1 -1
  5. package/dist/{gltf-progressive-CSaX5HQb.min.js → gltf-progressive-DHLDFNvQ.min.js} +1 -1
  6. package/dist/{gltf-progressive-ChnIhDXx.js → gltf-progressive-eiJCrjLb.js} +3 -3
  7. package/dist/materialx-CnsT47BY.umd.cjs +90 -0
  8. package/dist/materialx-DTdTjiOL.min.js +90 -0
  9. package/dist/materialx-DUlX6ZVi.js +4642 -0
  10. package/dist/{needle-engine.bundle-Cj66livk.js → needle-engine.bundle-B9mInB8V.js} +3275 -3186
  11. package/dist/{needle-engine.bundle-Cnemui9H.umd.cjs → needle-engine.bundle-ChxvQROR.umd.cjs} +96 -96
  12. package/dist/{needle-engine.bundle-B_IGIr6Z.min.js → needle-engine.bundle-F7f5MEhj.min.js} +129 -129
  13. package/dist/needle-engine.d.ts +23 -1
  14. package/dist/needle-engine.js +415 -414
  15. package/dist/needle-engine.min.js +1 -1
  16. package/dist/needle-engine.umd.cjs +1 -1
  17. package/dist/{postprocessing-12-UW7je.min.js → postprocessing-BVNrgYZK.min.js} +1 -1
  18. package/dist/{postprocessing-B3Hu0Ryi.umd.cjs → postprocessing-CI2TjWpu.umd.cjs} +1 -1
  19. package/dist/{postprocessing-R535krvT.js → postprocessing-DdM-tz1j.js} +2 -2
  20. package/dist/{three-BzxwLtUE.umd.cjs → three-BW2s1Yl-.umd.cjs} +25 -25
  21. package/dist/{three-DMvLgxja.min.js → three-I__hSXzr.min.js} +26 -26
  22. package/dist/{three-D9pcFbxc.js → three-VvRoMeIN.js} +22 -0
  23. package/dist/{three-examples-F0MJj0vr.js → three-examples-BhfOE7NG.js} +1 -1
  24. package/dist/{three-examples-CjSwCv_b.umd.cjs → three-examples-Bpfu6ke_.umd.cjs} +1 -1
  25. package/dist/{three-examples-CIv2roOA.min.js → three-examples-D8zAE_7t.min.js} +1 -1
  26. package/dist/{three-mesh-ui-BLnJQzMl.umd.cjs → three-mesh-ui-BU55xDxJ.umd.cjs} +1 -1
  27. package/dist/{three-mesh-ui-BllgajJz.min.js → three-mesh-ui-C3QbemOV.min.js} +1 -1
  28. package/dist/{three-mesh-ui-DYyiRn5Y.js → three-mesh-ui-CcMp-FQm.js} +1 -1
  29. package/dist/{vendor-BIFy-gRe.js → vendor-BiyIZ61v.js} +1 -1
  30. package/dist/{vendor-BFgQSG2m.umd.cjs → vendor-COVQl0b8.umd.cjs} +1 -1
  31. package/dist/{vendor-ChgmXMYr.min.js → vendor-DW7zqjuT.min.js} +1 -1
  32. package/lib/engine/engine_loaders.js +7 -1
  33. package/lib/engine/engine_loaders.js.map +1 -1
  34. package/lib/engine/engine_modules.d.ts +9 -0
  35. package/lib/engine/engine_modules.js +25 -0
  36. package/lib/engine/engine_modules.js.map +1 -1
  37. package/lib/engine/engine_utils_format.d.ts +1 -1
  38. package/lib/engine/engine_utils_format.js +4 -1
  39. package/lib/engine/engine_utils_format.js.map +1 -1
  40. package/lib/engine/extensions/NEEDLE_materialx.d.ts +29 -0
  41. package/lib/engine/extensions/NEEDLE_materialx.js +115 -0
  42. package/lib/engine/extensions/NEEDLE_materialx.js.map +1 -0
  43. package/lib/engine/extensions/extensions.js +2 -0
  44. package/lib/engine/extensions/extensions.js.map +1 -1
  45. package/lib/engine/extensions/index.d.ts +1 -0
  46. package/lib/engine/extensions/index.js +1 -0
  47. package/lib/engine/extensions/index.js.map +1 -1
  48. package/lib/engine-components/ContactShadows.js +15 -0
  49. package/lib/engine-components/ContactShadows.js.map +1 -1
  50. package/lib/engine-components/Skybox.js +1 -1
  51. package/lib/engine-components/Skybox.js.map +1 -1
  52. package/package.json +3 -2
  53. package/plugins/vite/dependencies.js +9 -4
  54. package/plugins/vite/index.js +0 -2
  55. package/src/engine/engine_loaders.ts +9 -2
  56. package/src/engine/engine_modules.ts +24 -0
  57. package/src/engine/engine_utils_format.ts +6 -2
  58. package/src/engine/extensions/NEEDLE_materialx.ts +142 -0
  59. package/src/engine/extensions/extensions.ts +2 -0
  60. package/src/engine/extensions/index.ts +2 -1
  61. package/src/engine-components/ContactShadows.ts +15 -0
  62. package/src/engine-components/Skybox.ts +1 -1
  63. package/plugins/vite/materialx.js +0 -32
package/CHANGELOG.md CHANGED
@@ -4,6 +4,10 @@ All notable changes to this package will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [4.13.0] - 2026-02-10
8
+ - **NEW**: Needle Engine MaterialX loader added to core. No extra dependency to @needle-tools/materialx is required anymore
9
+ - Fix: ContactShadows not correctly rendering anymore
10
+
7
11
  ## [4.12.5] - 2026-02-09
8
12
  - Update three.js dependency
9
13
  - Minor log improvements in development mode
package/README.md CHANGED
@@ -65,7 +65,7 @@ npm install @needle-tools/engine
65
65
  | [![](https://cdn.needle.tools/static/images/changelog/follow-cursor-thumbnail.jpg)](https://engine.needle.tools/samples/look-at-cursor-interactive-3d-header) | [Cursor Follow](https://engine.needle.tools/samples/look-at-cursor-interactive-3d-header) | Cursor Follow sample |
66
66
  | [![](https://cdn.needle.tools/static/images/changelog/khr_animation_pointer-thumbnail.jpg?1)](https://khr-animation-pointer-zubcksz2dgy3k.needle.run/) | [Animate Anything](https://khr-animation-pointer-zubcksz2dgy3k.needle.run/) | Interactive animation system | [Code on Stackblitz](https://stackblitz.com/edit/needle-engine-animate-anything?file=src%2Fmain.ts) • [three.js Example](https://threejs.org/examples/?q=gltf#webgl_loader_gltf_animation_pointer) |
67
67
  | [![](https://cdn.needle.tools/static/images/changelog/magnifier-postprocessing-example-thumbnail.jpg)](https://antialiasing-and-postprocessing-zubcksz1o8daw.needle.run/) | [Postprocessing Effects](https://antialiasing-and-postprocessing-zubcksz1o8daw.needle.run/) | Custom magnifier effect with post-processing | [Code on Stackblitz](https://stackblitz.com/edit/needle-engine-postprocessing) |
68
- | [![](https://cloud.needle.tools/-/media/Xc99R6zbaD-kpoTw1cMRKA.gif)](https://engine.needle.tools/samples/material-x) | Unity ShaderGraph to MaterialX & mtlx materials | [Sample](https://engine.needle.tools/samples/material-x/) |
68
+ | [![](https://cloud.needle.tools/-/media/Xc99R6zbaD-kpoTw1cMRKA.gif)](https://engine.needle.tools/samples/material-x) | [Unity ShaderGraph to MaterialX & mtlx materials](https://engine.needle.tools/samples/material-x/) | Using [@needle-tools/materialx](https://www.npmjs.com/package/@needle-tools/materialx) |
69
69
  | [![](https://cdn.needle.tools/static/images/changelog/4.8.8-focus-thumbnail.jpg)](https://responsive-layout-z23hmxb22no6t.needle.run/) | [Camera Focus DIV 1](https://responsive-layout-z23hmxb22no6t.needle.run/) | Responsive layout with camera focus | [Code on Stackblitz](https://stackblitz.com/edit/needle-engine-camera-focus-rect?file=src%2Fsidebar.ts,index.html,src%2Fmain.ts) |
70
70
  | [![](https://cdn.needle.tools/static/images/changelog/4.8.8-focus-2-thumbnail.jpg)](https://responsive-layout-click-example-z23hmxbzuyk6y.needle.run/) | [Camera Focus DIV 2](https://responsive-layout-click-example-z23hmxbzuyk6y.needle.run/) | Click-to-move camera focus example | [Code on Stackblitz](https://stackblitz.com/edit/needle-engine-camera-focus-rect-click-to-move?file=index.html,src%2Fmain.ts) |
71
71
  | [![](https://cdn.needle.tools/static/images/changelog/fasthdr-thumbnail.jpg?1)](https://fasthdr-needle-engine-zubcks1li2iy.needle.run/) | [FastHDR Loading](https://fasthdr-needle-engine-zubcks1li2iy.needle.run/) | 10x faster than EXR, non-blocking, 95% less GPU memory | [Code on Stackblitz](https://stackblitz.com/edit/needle-fast-hdri-needle-engine) • [Learn more](https://cloud.needle.tools/hdris) |
@@ -255,7 +255,7 @@
255
255
  {
256
256
  "name": "contact-shadows",
257
257
  "description": "Enable/disable contact shadows in the rendered scene",
258
- "valueSet": "b",
258
+ "valueSet": "c",
259
259
  "references": [
260
260
  { "name": "Needle Engine reference", "url": "https://engine.needle.tools/docs/reference/needle-engine-attributes.html" }
261
261
  ]
@@ -415,6 +415,23 @@
415
415
  "name": "false"
416
416
  }
417
417
  ]
418
+ },
419
+ {
420
+ "name": "c",
421
+ "values": [
422
+ {
423
+ "name": "true"
424
+ },
425
+ {
426
+ "name": "1"
427
+ },
428
+ {
429
+ "name": "false"
430
+ },
431
+ {
432
+ "name": "0"
433
+ }
434
+ ]
418
435
  }
419
436
  ]
420
437
  }
@@ -1,4 +1,4 @@
1
- "use strict";const d=require("./three-BzxwLtUE.umd.cjs"),q=require("./three-examples-CjSwCv_b.umd.cjs");var ae=typeof document<"u"?document.currentScript:null;const Re="";globalThis.GLTF_PROGRESSIVE_VERSION=Re;console.debug("[gltf-progressive] version -");let k="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",V="https://cdn.needle.tools/static/three/0.179.1/basis2/";const Be=k,$e=V,De=new URL(k+"draco_decoder.js");De.searchParams.append("range","true");fetch(De,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(i=>{console.debug(`Failed to fetch remote Draco decoder from ${k} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),k===Be&&be("./include/draco/"),V===$e&&Oe("./include/ktx2/")}).finally(()=>{Se()});const Ge=()=>({dracoDecoderPath:k,ktx2TranscoderPath:V});function be(i){k=i,A&&A[ge]!=k?(console.debug("Updating Draco decoder path to "+i),A[ge]=k,A.setDecoderPath(k),A.preload()):console.debug("Setting Draco decoder path to "+i)}function Oe(i){V=i,R&&R.transcoderPath!=V?(console.debug("Updating KTX2 transcoder path to "+i),R.setTranscoderPath(V),R.init()):console.debug("Setting KTX2 transcoder path to "+i)}function ne(i){return Se(),i?R.detectSupport(i):i!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:A,ktx2Loader:R,meshoptDecoder:se}}function ye(i){i.dracoLoader||i.setDRACOLoader(A),i.ktx2Loader||i.setKTX2Loader(R),i.meshoptDecoder||i.setMeshoptDecoder(se)}const ge=Symbol("dracoDecoderPath");let A,se,R;function Se(){A||(A=new q.DRACOLoader,A[ge]=k,A.setDecoderPath(k),A.setDecoderConfig({type:"js"}),A.preload()),R||(R=new q.KTX2Loader,R.setTranscoderPath(V),R.init()),se||(se=q.MeshoptDecoder)}const pe=new WeakMap;function xe(i,t){let e=pe.get(i);e?e=Object.assign(e,t):e=t,pe.set(i,e)}const Fe=q.GLTFLoader.prototype.load;function Ue(...i){const t=pe.get(this);let e=i[0];const r=new URL(e,window.location.href);if(r.hostname.endsWith("needle.tools")){const s=t?.progressive!==void 0?t.progressive:!0,o=t?.usecase?t.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${o}`:this.requestHeader.Accept=`*/*;usecase=${o}`,e=r.toString()}return i[0]=e,Fe?.call(this,...i)}q.GLTFLoader.prototype.load=Ue;N("debugprogressive");function N(i){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(i);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function We(i,t){if(t===void 0||i===void 0||t.startsWith("./")||t.startsWith("http")||t.startsWith("data:")||t.startsWith("blob:"))return t;const e=i.lastIndexOf("/");if(e>=0){const r=i.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}function Te(){return j!==void 0||(j=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),N("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",j)),j}let j;function Le(){if(typeof window>"u")return!1;const i=new URL(window.location.href),t=i.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(i.hostname);return i.hostname==="127.0.0.1"||t}class ze{constructor(t=100,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,window.requestAnimationFrame(this.tick)}_running=new Map;_queue=[];debug=!1;tick=()=>{this.internalUpdate(),setTimeout(this.tick,10)};slot(t){return this.debug&&console.debug(`[PromiseQueue]: Requesting slot for key ${t}, running: ${this._running.size}, waiting: ${this._queue.length}`),new Promise(e=>{this._queue.push({key:t,resolve:e})})}add(t,e){this._running.has(t)||(this._running.set(t,e),e.finally(()=>{this._running.delete(t),this.debug&&console.debug(`[PromiseQueue]: Promise finished now running: ${this._running.size}, waiting: ${this._queue.length}. (finished ${t})`)}),this.debug&&console.debug(`[PromiseQueue]: Added new promise, now running: ${this._running.size}, waiting: ${this._queue.length}. (added ${t})`))}internalUpdate(){const t=this.maxConcurrent-this._running.size;for(let e=0;e<t&&this._queue.length>0;e++){this.debug&&console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);const{key:r,resolve:n}=this._queue.shift();n({use:s=>this.add(r,s)})}}}const Ee=typeof window>"u"&&typeof document>"u",me=Symbol("needle:raycast-mesh");function X(i){return i?.[me]instanceof d.BufferGeometry?i[me]:null}function Ve(i,t){if((i.type==="Mesh"||i.type==="SkinnedMesh")&&!X(i)){const r=qe(t);r.userData={isRaycastMesh:!0},i[me]=r}}function Ne(i=!0){if(i){if(Y)return;const t=Y=d.Mesh.prototype.raycast;d.Mesh.prototype.raycast=function(e,r){const n=this,s=X(n);let o;s&&n.isMesh&&(o=n.geometry,n.geometry=s),t.call(this,e,r),o&&(n.geometry=o)}}else{if(!Y)return;d.Mesh.prototype.raycast=Y,Y=null}}let Y=null;function qe(i){const t=new d.BufferGeometry;for(const e in i.attributes)t.setAttribute(e,i.getAttribute(e));return t.setIndex(i.getIndex()),t}const W=new Array,p=N("debugprogressive");let Q,E=-1;if(p){let i=function(){E+=1,E>=t&&(E=-1),console.log(`Toggle LOD level [${E}]`)},t=6;window.addEventListener("keyup",e=>{e.key==="p"&&i(),e.key==="w"&&(Q=!Q,console.log(`Toggle wireframe [${Q}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(E=r,console.log(`Set LOD level to [${E}]`))})}function Pe(i){if(p&&Q!==void 0)if(Array.isArray(i))for(const t of i)Pe(t);else i&&"wireframe"in i&&(i.wireframe=Q===!0)}const H=new Array;let Xe=0;const Ke=Te()?2:10;function je(i){if(H.length<Ke){const r=H.length;p&&console.warn(`[Worker] Creating new worker #${r}`);const n=we.createWorker(i||{});return H.push(n),n}const t=Xe++%H.length;return H[t]}class we{constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=r=>{const n=r.data;switch(this._debug&&console.log("[Worker] EVENT",n),n.type){case"loaded-gltf":for(const s of this._running)if(s.url===n.result.url){Ye(n.result),s.resolve(n.result);const o=s.url;o.startsWith("blob:")&&URL.revokeObjectURL(o)}}},t.onerror=r=>{console.error("[Worker] Error in gltf-progressive worker:",r)},t.postMessage({type:"init"})}static async createWorker(t){const e=new Worker(new URL("/loader.worker-C1GG9A7C.js",typeof document>"u"?require("url").pathToFileURL(__filename).href:ae&&ae.tagName.toUpperCase()==="SCRIPT"&&ae.src||new URL("gltf-progressive-BqUnxvCx.umd.cjs",document.baseURI).href),{type:"module"});return new we(e,t)}_running=[];_webglRenderer=null;async load(t,e){const r=Ge();let n=e?.renderer;n||(this._webglRenderer??=(async()=>{const{WebGLRenderer:u}=await Promise.resolve().then(()=>require("./three-BzxwLtUE.umd.cjs")).then(c=>c.THREE);return new u})(),n=await this._webglRenderer);const l=ne(n).ktx2Loader.workerConfig;t instanceof URL?t=t.toString():t.startsWith("file:")?t=URL.createObjectURL(new Blob([t])):!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")&&(t=new URL(t,window.location.href).toString());const a={type:"load",url:t,dracoDecoderPath:r.dracoDecoderPath,ktx2TranscoderPath:r.ktx2TranscoderPath,ktx2LoaderConfig:l};return this._debug&&console.debug("[Worker] Sending load request",a),this.worker.postMessage(a),new Promise(u=>{this._running.push({url:t.toString(),resolve:u})})}_debug=!1}function Ye(i){for(const t of i.geometries){const e=t.geometry,r=new d.BufferGeometry;if(r.name=e.name||"",e.index){const n=e.index;r.setIndex(le(n))}for(const n in e.attributes){const s=e.attributes[n],o=le(s);r.setAttribute(n,o)}if(e.morphAttributes)for(const n in e.morphAttributes){const o=e.morphAttributes[n].map(l=>le(l));r.morphAttributes[n]=o}if(r.morphTargetsRelative=e.morphTargetsRelative??!1,r.boundingBox=new d.Box3,r.boundingBox.min=new d.Vector3(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),r.boundingBox.max=new d.Vector3(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),r.boundingSphere=new d.Sphere(new d.Vector3(e.boundingSphere?.center.x,e.boundingSphere?.center.y,e.boundingSphere?.center.z),e.boundingSphere?.radius),e.groups)for(const n of e.groups)r.addGroup(n.start,n.count,n.materialIndex);e.userData&&(r.userData=e.userData),t.geometry=r}for(const t of i.textures){const e=t.texture;let r=null;if(e.isCompressedTexture){const n=e.mipmaps,s=e.image?.width||e.source?.data?.width||-1,o=e.image?.height||e.source?.data?.height||-1;r=new d.CompressedTexture(n,s,o,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else r=new d.Texture(e.image,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),r.mipmaps=e.mipmaps,r.channel=e.channel,r.source.data=e.source.data,r.flipY=e.flipY,r.premultiplyAlpha=e.premultiplyAlpha,r.unpackAlignment=e.unpackAlignment,r.matrix=new d.Matrix3(...e.matrix.elements);if(!r){console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");continue}t.texture=r}return i}function le(i){let t=i;if("isInterleavedBufferAttribute"in i&&i.isInterleavedBufferAttribute){const e=i.data,r=e.array,n=new d.InterleavedBuffer(r,e.stride);t=new d.InterleavedBufferAttribute(n,i.itemSize,r.byteOffset,i.normalized),t.offset=i.offset}else"isBufferAttribute"in i&&i.isBufferAttribute&&(t=new d.BufferAttribute(i.array,i.itemSize,i.normalized),t.usage=i.usage,t.gpuType=i.gpuType,t.updateRanges=i.updateRanges);return t}const He=N("gltf-progressive-worker"),Qe=N("gltf-progressive-reduce-mipmaps"),ue=Symbol("needle-progressive-texture"),F="NEEDLE_progressive";class m{get name(){return F}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e?.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){const e=this.getAssignedLODInformation(t)?.index;return e??-1}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const l of t)this.getMaterialMinMaxLODsCount(l,e);return t[n]=e,e}if(p==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const l=t;for(const a of Object.keys(l.uniforms)){const u=l.uniforms[a].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const l of Object.keys(t)){const a=t[l];a?.isTexture===!0&&o(a,e)}else p&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[n]=e,e;function o(l,a){const u=r.getAssignedLODInformation(l);if(u){const c=r.lodInfos.get(u.key);if(c&&c.lods){a.min_count=Math.min(a.min_count,c.lods.length),a.max_count=Math.max(a.max_count,c.lods.length);for(let y=0;y<c.lods.length;y++){const _=c.lods[y];_.width&&(a.lods[y]=a.lods[y]||{min_height:1/0,max_height:0},a.lods[y].min_height=Math.min(a.lods[y].min_height,_.height),a.lods[y].max_height=Math.max(a.lods[y].max_height,_.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const o=t[s];if(o&&o.isTexture&&this.hasLODLevelAvailable(o,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let r,n;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&r?.userData?.LODS){const s=r.userData.LODS;if(n=this.lodInfos.get(s.key),e===void 0)return n!=null;if(n)return Array.isArray(n.lods)?e<n.lods.length:e===0}return!1}static assignMeshLOD(t,e){if(!t)return Promise.resolve(null);if(t instanceof d.Mesh||t.isMesh===!0){const r=t.geometry,n=this.getAssignedLODInformation(r);if(!n)return Promise.resolve(null);for(const s of W)s.onBeforeGetLODMesh?.(t,e);return t["LOD:requested level"]=e,m.getOrLoadLOD(r,e).then(s=>{if(Array.isArray(s)){const o=n.index||0;s=s[o]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],s&&r!=s&&(s?.isBufferGeometry?t.geometry=s:p&&console.error("Invalid LOD geometry",s))),s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else p&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const o=this.assignTextureLOD(s,e);n.push(o)}return Promise.all(n).then(s=>{const o=new Array;for(const l of s)Array.isArray(l)&&o.push(...l);return o})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,n=[],s=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const l of Object.keys(o.uniforms)){const a=o.uniforms[l].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,l).then(c=>(c&&o.uniforms[l].value!=c&&(o.uniforms[l].value=c,o.uniformsNeedUpdate=!0),c));n.push(u),s.push(l)}}}else for(const o of Object.keys(r)){const l=r[o];if(l?.isTexture===!0){const a=this.assignTextureLODForSlot(l,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const l=new Array;for(let a=0;a<o.length;a++){const u=o[a],c=s[a];u&&u.isTexture===!0?l.push({material:r,slot:c,texture:u,level:e}):l.push({material:r,slot:c,texture:null,level:e})}return l})}if(t instanceof d.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):m.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(s?.isTexture===!0){if(s!=t&&r&&n){const o=r[n];if(o&&!p){const l=this.getAssignedLODInformation(o);if(l&&l?.level<e)return p==="verbose"&&console.warn("Assigned texture level is already higher: ",l.level,e,r,o,s),null}if(Qe&&s.mipmaps){const l=s.mipmaps.length;s.mipmaps.length=Math.min(s.mipmaps.length,3),l!==s.mipmaps.length&&p&&console.debug(`Reduced mipmap count from ${l} to ${s.mipmaps.length} for ${s.uuid}: ${s.image?.width}x${s.image?.height}.`)}r[n]=s}return s}else p=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}parser;url;constructor(t){const e=t.options.path;p&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}_isLoadingMesh;loadMesh=t=>{if(this._isLoadingMesh)return null;const e=this.parser.json.meshes[t]?.extensions?.[F];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>(this._isLoadingMesh=!1,r&&m.registerMesh(this.url,e.guid,r,e.lods?.length,0,e),r))):null};afterRoot(t){return p&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[F];if(n){if(!n.lods){p&&console.warn("Texture has no LODs",n);return}let s=!1;for(const o of this.parser.associations.keys())o.isTexture===!0&&this.parser.associations.get(o)?.textures===r&&(s=!0,m.registerTexture(this.url,o,n.lods?.length,r,n));s||this.parser.getDependency("texture",r).then(o=>{o&&m.registerTexture(this.url,o,n.lods?.length,r,n)})}}}),this.parser.json.meshes?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[F];if(n&&n.lods){for(const s of this.parser.associations.keys())if(s.isMesh){const o=this.parser.associations.get(s);o?.meshes===r&&m.registerMesh(this.url,n.guid,s,n.lods.length,o.primitives,n)}}}}),null}static registerTexture=(t,e,r,n,s)=>{if(!e){p&&console.error("!! gltf-progressive: Called register texture without texture");return}if(p){const l=e.image?.width||e.source?.data?.width||0,a=e.image?.height||e.source?.data?.height||0;console.log(`> gltf-progressive: register texture[${n}] "${e.name||e.uuid}", Current: ${l}x${a}, Max: ${s.lods[0]?.width}x${s.lods[0]?.height}, uuid: ${e.uuid}`,s,e)}e.source&&(e.source[ue]=s);const o=s.guid;m.assignLODInformation(t,e,o,r,n),m.lodInfos.set(o,s),m.lowresCache.set(o,e)};static registerMesh=(t,e,r,n,s,o)=>{const l=r.geometry;if(!l){p&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),p&&console.log("> Progressive: register mesh "+r.name,{index:s,uuid:r.uuid},o,r),m.assignLODInformation(t,l,e,n,s),m.lodInfos.set(e,o);let a=m.lowresCache.get(e);a?a.push(r.geometry):a=[r.geometry],m.lowresCache.set(e,a),n>0&&!X(r)&&Ve(r,l);for(const u of W)u.onRegisteredNewMesh?.(r,o)};static lodInfos=new Map;static previouslyLoaded=new Map;static lowresCache=new Map;static workers=[];static _workersIndex=0;static async getOrLoadLOD(t,e){const r=p=="verbose",n=this.getAssignedLODInformation(t);if(!n)return p&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const s=n?.key;let o;if(t.isTexture===!0){const a=t;a.source&&a.source[ue]&&(o=a.source[ue])}if(o||(o=m.lodInfos.get(s)),!o)p&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type,m.lodInfos);else{if(e>0){let c=!1;const y=Array.isArray(o.lods);if(y&&e>=o.lods.length?c=!0:y||(c=!0),c)return this.lowresCache.get(s)}const a=Array.isArray(o.lods)?o.lods[e]?.path:o.lods;if(!a)return p&&!o["missing:uri"]&&(o["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,o)),null;const u=We(n.url,a);if(u.endsWith(".glb")||u.endsWith(".gltf")){if(!o.guid)return console.warn("missing pointer for glb/gltf texture",o),null;const c=u+"_"+o.guid,y=await this.queue.slot(u),_=this.previouslyLoaded.get(c);if(_!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${c}`);let f=await _.catch(S=>(console.error(`Error loading LOD ${e} from ${u}
1
+ "use strict";const d=require("./three-BW2s1Yl-.umd.cjs"),q=require("./three-examples-Bpfu6ke_.umd.cjs");var ae=typeof document<"u"?document.currentScript:null;const Re="";globalThis.GLTF_PROGRESSIVE_VERSION=Re;console.debug("[gltf-progressive] version -");let k="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",V="https://cdn.needle.tools/static/three/0.179.1/basis2/";const Be=k,$e=V,De=new URL(k+"draco_decoder.js");De.searchParams.append("range","true");fetch(De,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(i=>{console.debug(`Failed to fetch remote Draco decoder from ${k} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),k===Be&&be("./include/draco/"),V===$e&&Oe("./include/ktx2/")}).finally(()=>{Se()});const Ge=()=>({dracoDecoderPath:k,ktx2TranscoderPath:V});function be(i){k=i,A&&A[ge]!=k?(console.debug("Updating Draco decoder path to "+i),A[ge]=k,A.setDecoderPath(k),A.preload()):console.debug("Setting Draco decoder path to "+i)}function Oe(i){V=i,R&&R.transcoderPath!=V?(console.debug("Updating KTX2 transcoder path to "+i),R.setTranscoderPath(V),R.init()):console.debug("Setting KTX2 transcoder path to "+i)}function ne(i){return Se(),i?R.detectSupport(i):i!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:A,ktx2Loader:R,meshoptDecoder:se}}function ye(i){i.dracoLoader||i.setDRACOLoader(A),i.ktx2Loader||i.setKTX2Loader(R),i.meshoptDecoder||i.setMeshoptDecoder(se)}const ge=Symbol("dracoDecoderPath");let A,se,R;function Se(){A||(A=new q.DRACOLoader,A[ge]=k,A.setDecoderPath(k),A.setDecoderConfig({type:"js"}),A.preload()),R||(R=new q.KTX2Loader,R.setTranscoderPath(V),R.init()),se||(se=q.MeshoptDecoder)}const pe=new WeakMap;function xe(i,t){let e=pe.get(i);e?e=Object.assign(e,t):e=t,pe.set(i,e)}const Fe=q.GLTFLoader.prototype.load;function Ue(...i){const t=pe.get(this);let e=i[0];const r=new URL(e,window.location.href);if(r.hostname.endsWith("needle.tools")){const s=t?.progressive!==void 0?t.progressive:!0,o=t?.usecase?t.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${o}`:this.requestHeader.Accept=`*/*;usecase=${o}`,e=r.toString()}return i[0]=e,Fe?.call(this,...i)}q.GLTFLoader.prototype.load=Ue;N("debugprogressive");function N(i){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(i);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function We(i,t){if(t===void 0||i===void 0||t.startsWith("./")||t.startsWith("http")||t.startsWith("data:")||t.startsWith("blob:"))return t;const e=i.lastIndexOf("/");if(e>=0){const r=i.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}function Te(){return j!==void 0||(j=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),N("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",j)),j}let j;function Le(){if(typeof window>"u")return!1;const i=new URL(window.location.href),t=i.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(i.hostname);return i.hostname==="127.0.0.1"||t}class ze{constructor(t=100,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,window.requestAnimationFrame(this.tick)}_running=new Map;_queue=[];debug=!1;tick=()=>{this.internalUpdate(),setTimeout(this.tick,10)};slot(t){return this.debug&&console.debug(`[PromiseQueue]: Requesting slot for key ${t}, running: ${this._running.size}, waiting: ${this._queue.length}`),new Promise(e=>{this._queue.push({key:t,resolve:e})})}add(t,e){this._running.has(t)||(this._running.set(t,e),e.finally(()=>{this._running.delete(t),this.debug&&console.debug(`[PromiseQueue]: Promise finished now running: ${this._running.size}, waiting: ${this._queue.length}. (finished ${t})`)}),this.debug&&console.debug(`[PromiseQueue]: Added new promise, now running: ${this._running.size}, waiting: ${this._queue.length}. (added ${t})`))}internalUpdate(){const t=this.maxConcurrent-this._running.size;for(let e=0;e<t&&this._queue.length>0;e++){this.debug&&console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);const{key:r,resolve:n}=this._queue.shift();n({use:s=>this.add(r,s)})}}}const Ee=typeof window>"u"&&typeof document>"u",me=Symbol("needle:raycast-mesh");function X(i){return i?.[me]instanceof d.BufferGeometry?i[me]:null}function Ve(i,t){if((i.type==="Mesh"||i.type==="SkinnedMesh")&&!X(i)){const r=qe(t);r.userData={isRaycastMesh:!0},i[me]=r}}function Ne(i=!0){if(i){if(Y)return;const t=Y=d.Mesh.prototype.raycast;d.Mesh.prototype.raycast=function(e,r){const n=this,s=X(n);let o;s&&n.isMesh&&(o=n.geometry,n.geometry=s),t.call(this,e,r),o&&(n.geometry=o)}}else{if(!Y)return;d.Mesh.prototype.raycast=Y,Y=null}}let Y=null;function qe(i){const t=new d.BufferGeometry;for(const e in i.attributes)t.setAttribute(e,i.getAttribute(e));return t.setIndex(i.getIndex()),t}const W=new Array,p=N("debugprogressive");let Q,E=-1;if(p){let i=function(){E+=1,E>=t&&(E=-1),console.log(`Toggle LOD level [${E}]`)},t=6;window.addEventListener("keyup",e=>{e.key==="p"&&i(),e.key==="w"&&(Q=!Q,console.log(`Toggle wireframe [${Q}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(E=r,console.log(`Set LOD level to [${E}]`))})}function Pe(i){if(p&&Q!==void 0)if(Array.isArray(i))for(const t of i)Pe(t);else i&&"wireframe"in i&&(i.wireframe=Q===!0)}const H=new Array;let Xe=0;const Ke=Te()?2:10;function je(i){if(H.length<Ke){const r=H.length;p&&console.warn(`[Worker] Creating new worker #${r}`);const n=we.createWorker(i||{});return H.push(n),n}const t=Xe++%H.length;return H[t]}class we{constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=r=>{const n=r.data;switch(this._debug&&console.log("[Worker] EVENT",n),n.type){case"loaded-gltf":for(const s of this._running)if(s.url===n.result.url){Ye(n.result),s.resolve(n.result);const o=s.url;o.startsWith("blob:")&&URL.revokeObjectURL(o)}}},t.onerror=r=>{console.error("[Worker] Error in gltf-progressive worker:",r)},t.postMessage({type:"init"})}static async createWorker(t){const e=new Worker(new URL("/loader.worker-C1GG9A7C.js",typeof document>"u"?require("url").pathToFileURL(__filename).href:ae&&ae.tagName.toUpperCase()==="SCRIPT"&&ae.src||new URL("gltf-progressive-BURrJW0U.umd.cjs",document.baseURI).href),{type:"module"});return new we(e,t)}_running=[];_webglRenderer=null;async load(t,e){const r=Ge();let n=e?.renderer;n||(this._webglRenderer??=(async()=>{const{WebGLRenderer:u}=await Promise.resolve().then(()=>require("./three-BW2s1Yl-.umd.cjs")).then(c=>c.THREE);return new u})(),n=await this._webglRenderer);const l=ne(n).ktx2Loader.workerConfig;t instanceof URL?t=t.toString():t.startsWith("file:")?t=URL.createObjectURL(new Blob([t])):!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")&&(t=new URL(t,window.location.href).toString());const a={type:"load",url:t,dracoDecoderPath:r.dracoDecoderPath,ktx2TranscoderPath:r.ktx2TranscoderPath,ktx2LoaderConfig:l};return this._debug&&console.debug("[Worker] Sending load request",a),this.worker.postMessage(a),new Promise(u=>{this._running.push({url:t.toString(),resolve:u})})}_debug=!1}function Ye(i){for(const t of i.geometries){const e=t.geometry,r=new d.BufferGeometry;if(r.name=e.name||"",e.index){const n=e.index;r.setIndex(le(n))}for(const n in e.attributes){const s=e.attributes[n],o=le(s);r.setAttribute(n,o)}if(e.morphAttributes)for(const n in e.morphAttributes){const o=e.morphAttributes[n].map(l=>le(l));r.morphAttributes[n]=o}if(r.morphTargetsRelative=e.morphTargetsRelative??!1,r.boundingBox=new d.Box3,r.boundingBox.min=new d.Vector3(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),r.boundingBox.max=new d.Vector3(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),r.boundingSphere=new d.Sphere(new d.Vector3(e.boundingSphere?.center.x,e.boundingSphere?.center.y,e.boundingSphere?.center.z),e.boundingSphere?.radius),e.groups)for(const n of e.groups)r.addGroup(n.start,n.count,n.materialIndex);e.userData&&(r.userData=e.userData),t.geometry=r}for(const t of i.textures){const e=t.texture;let r=null;if(e.isCompressedTexture){const n=e.mipmaps,s=e.image?.width||e.source?.data?.width||-1,o=e.image?.height||e.source?.data?.height||-1;r=new d.CompressedTexture(n,s,o,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else r=new d.Texture(e.image,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),r.mipmaps=e.mipmaps,r.channel=e.channel,r.source.data=e.source.data,r.flipY=e.flipY,r.premultiplyAlpha=e.premultiplyAlpha,r.unpackAlignment=e.unpackAlignment,r.matrix=new d.Matrix3(...e.matrix.elements);if(!r){console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");continue}t.texture=r}return i}function le(i){let t=i;if("isInterleavedBufferAttribute"in i&&i.isInterleavedBufferAttribute){const e=i.data,r=e.array,n=new d.InterleavedBuffer(r,e.stride);t=new d.InterleavedBufferAttribute(n,i.itemSize,r.byteOffset,i.normalized),t.offset=i.offset}else"isBufferAttribute"in i&&i.isBufferAttribute&&(t=new d.BufferAttribute(i.array,i.itemSize,i.normalized),t.usage=i.usage,t.gpuType=i.gpuType,t.updateRanges=i.updateRanges);return t}const He=N("gltf-progressive-worker"),Qe=N("gltf-progressive-reduce-mipmaps"),ue=Symbol("needle-progressive-texture"),F="NEEDLE_progressive";class m{get name(){return F}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e?.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){const e=this.getAssignedLODInformation(t)?.index;return e??-1}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const l of t)this.getMaterialMinMaxLODsCount(l,e);return t[n]=e,e}if(p==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const l=t;for(const a of Object.keys(l.uniforms)){const u=l.uniforms[a].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const l of Object.keys(t)){const a=t[l];a?.isTexture===!0&&o(a,e)}else p&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[n]=e,e;function o(l,a){const u=r.getAssignedLODInformation(l);if(u){const c=r.lodInfos.get(u.key);if(c&&c.lods){a.min_count=Math.min(a.min_count,c.lods.length),a.max_count=Math.max(a.max_count,c.lods.length);for(let y=0;y<c.lods.length;y++){const _=c.lods[y];_.width&&(a.lods[y]=a.lods[y]||{min_height:1/0,max_height:0},a.lods[y].min_height=Math.min(a.lods[y].min_height,_.height),a.lods[y].max_height=Math.max(a.lods[y].max_height,_.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const o=t[s];if(o&&o.isTexture&&this.hasLODLevelAvailable(o,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let r,n;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&r?.userData?.LODS){const s=r.userData.LODS;if(n=this.lodInfos.get(s.key),e===void 0)return n!=null;if(n)return Array.isArray(n.lods)?e<n.lods.length:e===0}return!1}static assignMeshLOD(t,e){if(!t)return Promise.resolve(null);if(t instanceof d.Mesh||t.isMesh===!0){const r=t.geometry,n=this.getAssignedLODInformation(r);if(!n)return Promise.resolve(null);for(const s of W)s.onBeforeGetLODMesh?.(t,e);return t["LOD:requested level"]=e,m.getOrLoadLOD(r,e).then(s=>{if(Array.isArray(s)){const o=n.index||0;s=s[o]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],s&&r!=s&&(s?.isBufferGeometry?t.geometry=s:p&&console.error("Invalid LOD geometry",s))),s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else p&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const o=this.assignTextureLOD(s,e);n.push(o)}return Promise.all(n).then(s=>{const o=new Array;for(const l of s)Array.isArray(l)&&o.push(...l);return o})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,n=[],s=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const l of Object.keys(o.uniforms)){const a=o.uniforms[l].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,l).then(c=>(c&&o.uniforms[l].value!=c&&(o.uniforms[l].value=c,o.uniformsNeedUpdate=!0),c));n.push(u),s.push(l)}}}else for(const o of Object.keys(r)){const l=r[o];if(l?.isTexture===!0){const a=this.assignTextureLODForSlot(l,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const l=new Array;for(let a=0;a<o.length;a++){const u=o[a],c=s[a];u&&u.isTexture===!0?l.push({material:r,slot:c,texture:u,level:e}):l.push({material:r,slot:c,texture:null,level:e})}return l})}if(t instanceof d.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):m.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(s?.isTexture===!0){if(s!=t&&r&&n){const o=r[n];if(o&&!p){const l=this.getAssignedLODInformation(o);if(l&&l?.level<e)return p==="verbose"&&console.warn("Assigned texture level is already higher: ",l.level,e,r,o,s),null}if(Qe&&s.mipmaps){const l=s.mipmaps.length;s.mipmaps.length=Math.min(s.mipmaps.length,3),l!==s.mipmaps.length&&p&&console.debug(`Reduced mipmap count from ${l} to ${s.mipmaps.length} for ${s.uuid}: ${s.image?.width}x${s.image?.height}.`)}r[n]=s}return s}else p=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}parser;url;constructor(t){const e=t.options.path;p&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}_isLoadingMesh;loadMesh=t=>{if(this._isLoadingMesh)return null;const e=this.parser.json.meshes[t]?.extensions?.[F];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>(this._isLoadingMesh=!1,r&&m.registerMesh(this.url,e.guid,r,e.lods?.length,0,e),r))):null};afterRoot(t){return p&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[F];if(n){if(!n.lods){p&&console.warn("Texture has no LODs",n);return}let s=!1;for(const o of this.parser.associations.keys())o.isTexture===!0&&this.parser.associations.get(o)?.textures===r&&(s=!0,m.registerTexture(this.url,o,n.lods?.length,r,n));s||this.parser.getDependency("texture",r).then(o=>{o&&m.registerTexture(this.url,o,n.lods?.length,r,n)})}}}),this.parser.json.meshes?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[F];if(n&&n.lods){for(const s of this.parser.associations.keys())if(s.isMesh){const o=this.parser.associations.get(s);o?.meshes===r&&m.registerMesh(this.url,n.guid,s,n.lods.length,o.primitives,n)}}}}),null}static registerTexture=(t,e,r,n,s)=>{if(!e){p&&console.error("!! gltf-progressive: Called register texture without texture");return}if(p){const l=e.image?.width||e.source?.data?.width||0,a=e.image?.height||e.source?.data?.height||0;console.log(`> gltf-progressive: register texture[${n}] "${e.name||e.uuid}", Current: ${l}x${a}, Max: ${s.lods[0]?.width}x${s.lods[0]?.height}, uuid: ${e.uuid}`,s,e)}e.source&&(e.source[ue]=s);const o=s.guid;m.assignLODInformation(t,e,o,r,n),m.lodInfos.set(o,s),m.lowresCache.set(o,e)};static registerMesh=(t,e,r,n,s,o)=>{const l=r.geometry;if(!l){p&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),p&&console.log("> Progressive: register mesh "+r.name,{index:s,uuid:r.uuid},o,r),m.assignLODInformation(t,l,e,n,s),m.lodInfos.set(e,o);let a=m.lowresCache.get(e);a?a.push(r.geometry):a=[r.geometry],m.lowresCache.set(e,a),n>0&&!X(r)&&Ve(r,l);for(const u of W)u.onRegisteredNewMesh?.(r,o)};static lodInfos=new Map;static previouslyLoaded=new Map;static lowresCache=new Map;static workers=[];static _workersIndex=0;static async getOrLoadLOD(t,e){const r=p=="verbose",n=this.getAssignedLODInformation(t);if(!n)return p&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const s=n?.key;let o;if(t.isTexture===!0){const a=t;a.source&&a.source[ue]&&(o=a.source[ue])}if(o||(o=m.lodInfos.get(s)),!o)p&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type,m.lodInfos);else{if(e>0){let c=!1;const y=Array.isArray(o.lods);if(y&&e>=o.lods.length?c=!0:y||(c=!0),c)return this.lowresCache.get(s)}const a=Array.isArray(o.lods)?o.lods[e]?.path:o.lods;if(!a)return p&&!o["missing:uri"]&&(o["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,o)),null;const u=We(n.url,a);if(u.endsWith(".glb")||u.endsWith(".gltf")){if(!o.guid)return console.warn("missing pointer for glb/gltf texture",o),null;const c=u+"_"+o.guid,y=await this.queue.slot(u),_=this.previouslyLoaded.get(c);if(_!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${c}`);let f=await _.catch(S=>(console.error(`Error loading LOD ${e} from ${u}
2
2
  `,S),null)),w=!1;if(f==null||(f instanceof d.Texture&&t instanceof d.Texture?f.image?.data||f.source?.data?f=this.copySettings(t,f):(w=!0,this.previouslyLoaded.delete(c)):f instanceof d.BufferGeometry&&t instanceof d.BufferGeometry&&(f.attributes.position?.array||(w=!0,this.previouslyLoaded.delete(c)))),!w)return f}if(!y.use)return p&&console.log(`LOD ${e} was aborted: ${u}`),null;const M=o,I=new Promise(async(f,w)=>{if(He){const x=await(await je({})).load(u);if(x.textures.length>0)for(const h of x.textures){let g=h.texture;return m.assignLODInformation(n.url,g,s,e,void 0),t instanceof d.Texture&&(g=this.copySettings(t,g)),g&&(g.guid=M.guid),f(g)}if(x.geometries.length>0){const h=new Array;for(const g of x.geometries){const D=g.geometry;m.assignLODInformation(n.url,D,s,e,g.primitiveIndex),h.push(D)}return f(h)}return f(null)}const S=new q.GLTFLoader;ye(S),p&&(await new Promise(L=>setTimeout(L,1e3)),r&&console.warn("Start loading (delayed) "+u,M.guid));let B=u;if(M&&Array.isArray(M.lods)){const L=M.lods[e];L.hash&&(B+="?v="+L.hash)}const v=await S.loadAsync(B).catch(L=>(console.error(`Error loading LOD ${e} from ${u}
3
3
  `,L),f(null)));if(!v)return f(null);const z=v.parser;r&&console.log("Loading finished "+u,M.guid);let T=0;if(v.parser.json.textures){let L=!1;for(const x of v.parser.json.textures){if(x?.extensions){const h=x?.extensions[F];if(h?.guid&&h.guid===M.guid){L=!0;break}}T++}if(L){let x=await z.getDependency("texture",T);return x&&m.assignLODInformation(n.url,x,s,e,void 0),r&&console.log('change "'+t.name+'" → "'+x.name+'"',u,T,x,c),t instanceof d.Texture&&(x=this.copySettings(t,x)),x&&(x.guid=M.guid),f(x)}else p&&console.warn("Could not find texture with guid",M.guid,v.parser.json)}if(T=0,v.parser.json.meshes){let L=!1;for(const x of v.parser.json.meshes){if(x?.extensions){const h=x?.extensions[F];if(h?.guid&&h.guid===M.guid){L=!0;break}}T++}if(L){const x=await z.getDependency("mesh",T);if(r&&console.log(`Loaded Mesh "${x.name}"`,u,T,x,c),x.isMesh===!0){const h=x.geometry;return m.assignLODInformation(n.url,h,s,e,0),f(h)}else{const h=new Array;for(let g=0;g<x.children.length;g++){const D=x.children[g];if(D.isMesh===!0){const O=D.geometry;m.assignLODInformation(n.url,O,s,e,g),h.push(O)}}return f(h)}}else p&&console.warn("Could not find mesh with guid",M.guid,v.parser.json)}return f(null)});return this.previouslyLoaded.set(c,I),y.use(I),await I}else if(t instanceof d.Texture){r&&console.log("Load texture from uri: "+u);const y=await new d.TextureLoader().loadAsync(u);return y?(y.guid=o.guid,y.flipY=!1,y.needsUpdate=!0,y.colorSpace=t.colorSpace,r&&console.log(o,y)):p&&console.warn("failed loading",u),y}}return null}static maxConcurrent=50;static queue=new ze(m.maxConcurrent,{debug:p!=!1});static assignLODInformation(t,e,r,n,s){if(!e)return;e.userData||(e.userData={});const o=new Je(t,r,n,s);e.userData.LODS=o,"source"in e&&typeof e.source=="object"&&(e.source.LODS=o)}static getAssignedLODInformation(t){return t?t.userData?.LODS?t.userData.LODS:"source"in t&&t.source?.LODS?t.source.LODS:null:null}static copySettings(t,e){return e?(p==="verbose"&&console.debug(`Copy texture settings
4
4
  `,t.uuid,`
@@ -1,4 +1,4 @@
1
- import{BufferGeometry as V,Mesh as j,Box3 as ie,Vector3 as I,Sphere as ve,CompressedTexture as $e,Texture as N,Matrix3 as Re,InterleavedBuffer as Ge,InterleavedBufferAttribute as je,BufferAttribute as Ne,TextureLoader as Ue,Matrix4 as Le,Clock as Fe,MeshStandardMaterial as We}from"./three-DMvLgxja.min.js";import{DRACOLoader as ze,KTX2Loader as qe,MeshoptDecoder as Ve,GLTFLoader as ae}from"./three-examples-CIv2roOA.min.js";const Xe="";globalThis.GLTF_PROGRESSIVE_VERSION=Xe,console.debug("[gltf-progressive] version -");let k="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",U="https://cdn.needle.tools/static/three/0.179.1/basis2/";const He=k,Ke=U,_e=new URL(k+"draco_decoder.js");_e.searchParams.append("range","true"),fetch(_e,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(i=>{console.debug(`Failed to fetch remote Draco decoder from ${k} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),k===He&&be("./include/draco/"),U===Ke&&De("./include/ktx2/")}).finally(()=>{Me()});const Ye=()=>({dracoDecoderPath:k,ktx2TranscoderPath:U});function be(i){k=i,P&&P[ue]!=k?(console.debug("Updating Draco decoder path to "+i),P[ue]=k,P.setDecoderPath(k),P.preload()):console.debug("Setting Draco decoder path to "+i)}function De(i){U=i,C&&C.transcoderPath!=U?(console.debug("Updating KTX2 transcoder path to "+i),C.setTranscoderPath(U),C.init()):console.debug("Setting KTX2 transcoder path to "+i)}function ee(i){return Me(),i?C.detectSupport(i):i!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:P,ktx2Loader:C,meshoptDecoder:te}}function le(i){i.dracoLoader||i.setDRACOLoader(P),i.ktx2Loader||i.setKTX2Loader(C),i.meshoptDecoder||i.setMeshoptDecoder(te)}const ue=Symbol("dracoDecoderPath");let P,te,C;function Me(){P||(P=new ze,P[ue]=k,P.setDecoderPath(k),P.setDecoderConfig({type:"js"}),P.preload()),C||(C=new qe,C.setTranscoderPath(U),C.init()),te||(te=Ve)}const de=new WeakMap;function ce(i,t){let e=de.get(i);e?e=Object.assign(e,t):e=t,de.set(i,e)}const Qe=ae.prototype.load;function Je(...i){const t=de.get(this);let e=i[0];const r=new URL(e,window.location.href);if(r.hostname.endsWith("needle.tools")){const o=t?.progressive!==void 0?t.progressive:!0,s=t?.usecase?t.usecase:"default";o?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${s}`:this.requestHeader.Accept=`*/*;usecase=${s}`,e=r.toString()}return i[0]=e,Qe?.call(this,...i)}ae.prototype.load=Je,F("debugprogressive");function F(i){if(typeof window>"u")return!1;const t=new URL(window.location.href).searchParams.get(i);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function Ze(i,t){if(t===void 0||i===void 0||t.startsWith("./")||t.startsWith("http")||t.startsWith("data:")||t.startsWith("blob:"))return t;const e=i.lastIndexOf("/");if(e>=0){const r=i.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}function Oe(){return re!==void 0||(re=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),F("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",re)),re}let re;function Se(){if(typeof window>"u")return!1;const i=new URL(window.location.href),t=i.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(i.hostname);return i.hostname==="127.0.0.1"||t}class et{constructor(t=100,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,window.requestAnimationFrame(this.tick)}_running=new Map;_queue=[];debug=!1;tick=()=>{this.internalUpdate(),setTimeout(this.tick,10)};slot(t){return this.debug&&console.debug(`[PromiseQueue]: Requesting slot for key ${t}, running: ${this._running.size}, waiting: ${this._queue.length}`),new Promise(e=>{this._queue.push({key:t,resolve:e})})}add(t,e){this._running.has(t)||(this._running.set(t,e),e.finally(()=>{this._running.delete(t),this.debug&&console.debug(`[PromiseQueue]: Promise finished now running: ${this._running.size}, waiting: ${this._queue.length}. (finished ${t})`)}),this.debug&&console.debug(`[PromiseQueue]: Added new promise, now running: ${this._running.size}, waiting: ${this._queue.length}. (added ${t})`))}internalUpdate(){const t=this.maxConcurrent-this._running.size;for(let e=0;e<t&&this._queue.length>0;e++){this.debug&&console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);const{key:r,resolve:o}=this._queue.shift();o({use:s=>this.add(r,s)})}}}const tt=typeof window>"u"&&typeof document>"u",he=Symbol("needle:raycast-mesh");function z(i){return i?.[he]instanceof V?i[he]:null}function rt(i,t){if((i.type==="Mesh"||i.type==="SkinnedMesh")&&!z(i)){const e=ot(t);e.userData={isRaycastMesh:!0},i[he]=e}}function st(i=!0){if(i){if(X)return;const t=X=j.prototype.raycast;j.prototype.raycast=function(e,r){const o=this,s=z(o);let n;s&&o.isMesh&&(n=o.geometry,o.geometry=s),t.call(this,e,r),n&&(o.geometry=n)}}else{if(!X)return;j.prototype.raycast=X,X=null}}let X=null;function ot(i){const t=new V;for(const e in i.attributes)t.setAttribute(e,i.getAttribute(e));return t.setIndex(i.getIndex()),t}const R=new Array,h=F("debugprogressive");let H,W=-1;if(h){let i=function(){W+=1,W>=t&&(W=-1),console.log(`Toggle LOD level [${W}]`)},t=6;window.addEventListener("keyup",e=>{e.key==="p"&&i(),e.key==="w"&&(H=!H,console.log(`Toggle wireframe [${H}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(W=r,console.log(`Set LOD level to [${W}]`))})}function Pe(i){if(h&&H!==void 0)if(Array.isArray(i))for(const t of i)Pe(t);else i&&"wireframe"in i&&(i.wireframe=H===!0)}const K=new Array;let nt=0;const it=Oe()?2:10;function at(i){if(K.length<it){const e=K.length;h&&console.warn(`[Worker] Creating new worker #${e}`);const r=ye.createWorker(i||{});return K.push(r),r}const t=nt++%K.length;return K[t]}class ye{constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=r=>{const o=r.data;switch(this._debug&&console.log("[Worker] EVENT",o),o.type){case"loaded-gltf":for(const s of this._running)if(s.url===o.result.url){lt(o.result),s.resolve(o.result);const n=s.url;n.startsWith("blob:")&&URL.revokeObjectURL(n)}}},t.onerror=r=>{console.error("[Worker] Error in gltf-progressive worker:",r)},t.postMessage({type:"init"})}static async createWorker(t){const e=new Worker(URL.createObjectURL(new Blob([`import '${new URL("./loader.worker-C1GG9A7C.js",import.meta.url).toString()}';`],{type:"text/javascript"})),{type:"module"});return new ye(e,t)}_running=[];_webglRenderer=null;async load(t,e){const r=Ye();let o=e?.renderer;o||(this._webglRenderer??=(async()=>{const{WebGLRenderer:l}=await import("./three-DMvLgxja.min.js").then(a=>a.THREE);return new l})(),o=await this._webglRenderer);const s=ee(o).ktx2Loader.workerConfig;t instanceof URL?t=t.toString():t.startsWith("file:")?t=URL.createObjectURL(new Blob([t])):!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")&&(t=new URL(t,window.location.href).toString());const n={type:"load",url:t,dracoDecoderPath:r.dracoDecoderPath,ktx2TranscoderPath:r.ktx2TranscoderPath,ktx2LoaderConfig:s};return this._debug&&console.debug("[Worker] Sending load request",n),this.worker.postMessage(n),new Promise(l=>{this._running.push({url:t.toString(),resolve:l})})}_debug=!1}function lt(i){for(const t of i.geometries){const e=t.geometry,r=new V;if(r.name=e.name||"",e.index){const o=e.index;r.setIndex(ge(o))}for(const o in e.attributes){const s=e.attributes[o],n=ge(s);r.setAttribute(o,n)}if(e.morphAttributes)for(const o in e.morphAttributes){const s=e.morphAttributes[o].map(n=>ge(n));r.morphAttributes[o]=s}if(r.morphTargetsRelative=e.morphTargetsRelative??!1,r.boundingBox=new ie,r.boundingBox.min=new I(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),r.boundingBox.max=new I(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),r.boundingSphere=new ve(new I(e.boundingSphere?.center.x,e.boundingSphere?.center.y,e.boundingSphere?.center.z),e.boundingSphere?.radius),e.groups)for(const o of e.groups)r.addGroup(o.start,o.count,o.materialIndex);e.userData&&(r.userData=e.userData),t.geometry=r}for(const t of i.textures){const e=t.texture;let r=null;if(e.isCompressedTexture){const o=e.mipmaps,s=e.image?.width||e.source?.data?.width||-1,n=e.image?.height||e.source?.data?.height||-1;r=new $e(o,s,n,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else r=new N(e.image,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),r.mipmaps=e.mipmaps,r.channel=e.channel,r.source.data=e.source.data,r.flipY=e.flipY,r.premultiplyAlpha=e.premultiplyAlpha,r.unpackAlignment=e.unpackAlignment,r.matrix=new Re(...e.matrix.elements);if(!r){console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");continue}t.texture=r}return i}function ge(i){let t=i;if("isInterleavedBufferAttribute"in i&&i.isInterleavedBufferAttribute){const e=i.data,r=e.array,o=new Ge(r,e.stride);t=new je(o,i.itemSize,r.byteOffset,i.normalized),t.offset=i.offset}else"isBufferAttribute"in i&&i.isBufferAttribute&&(t=new Ne(i.array,i.itemSize,i.normalized),t.usage=i.usage,t.gpuType=i.gpuType,t.updateRanges=i.updateRanges);return t}const ut=F("gltf-progressive-worker"),dt=F("gltf-progressive-reduce-mipmaps"),fe=Symbol("needle-progressive-texture"),$="NEEDLE_progressive";class g{get name(){return $}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e?.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){return this.getAssignedLODInformation(t)?.index??-1}static getMaterialMinMaxLODsCount(t,e){const r=this,o="LODS:minmax",s=t[o];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const l of t)this.getMaterialMinMaxLODsCount(l,e);return t[o]=e,e}if(h==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const l=t;for(const a of Object.keys(l.uniforms)){const u=l.uniforms[a].value;u?.isTexture===!0&&n(u,e)}}else if(t.isMaterial)for(const l of Object.keys(t)){const a=t[l];a?.isTexture===!0&&n(a,e)}else h&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[o]=e,e;function n(l,a){const u=r.getAssignedLODInformation(l);if(u){const f=r.lodInfos.get(u.key);if(f&&f.lods){a.min_count=Math.min(a.min_count,f.lods.length),a.max_count=Math.max(a.max_count,f.lods.length);for(let w=0;w<f.lods.length;w++){const v=f.lods[w];v.width&&(a.lods[w]=a.lods[w]||{min_height:1/0,max_height:0},a.lods[w].min_height=Math.min(a.lods[w].min_height,v.height),a.lods[w].max_height=Math.max(a.lods[w].max_height,v.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const n=t[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let r,o;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&r?.userData?.LODS){const s=r.userData.LODS;if(o=this.lodInfos.get(s.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){if(!t)return Promise.resolve(null);if(t instanceof j||t.isMesh===!0){const r=t.geometry,o=this.getAssignedLODInformation(r);if(!o)return Promise.resolve(null);for(const s of R)s.onBeforeGetLODMesh?.(t,e);return t["LOD:requested level"]=e,g.getOrLoadLOD(r,e).then(s=>{if(Array.isArray(s)){const n=o.index||0;s=s[n]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],s&&r!=s&&(s?.isBufferGeometry?t.geometry=s:h&&console.error("Invalid LOD geometry",s))),s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else h&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const o=new Array;for(const s of r.material){const n=this.assignTextureLOD(s,e);o.push(n)}return Promise.all(o).then(s=>{const n=new Array;for(const l of s)Array.isArray(l)&&n.push(...l);return n})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,o=[],s=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const n=r;for(const l of Object.keys(n.uniforms)){const a=n.uniforms[l].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,l).then(f=>(f&&n.uniforms[l].value!=f&&(n.uniforms[l].value=f,n.uniformsNeedUpdate=!0),f));o.push(u),s.push(l)}}}else for(const n of Object.keys(r)){const l=r[n];if(l?.isTexture===!0){const a=this.assignTextureLODForSlot(l,e,r,n);o.push(a),s.push(n)}}return Promise.all(o).then(n=>{const l=new Array;for(let a=0;a<n.length;a++){const u=n[a],f=s[a];u&&u.isTexture===!0?l.push({material:r,slot:f,texture:u,level:e}):l.push({material:r,slot:f,texture:null,level:e})}return l})}if(t instanceof N||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,o){return t?.isTexture!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):g.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(s?.isTexture===!0){if(s!=t&&r&&o){const n=r[o];if(n&&!h){const l=this.getAssignedLODInformation(n);if(l&&l?.level<e)return h==="verbose"&&console.warn("Assigned texture level is already higher: ",l.level,e,r,n,s),null}if(dt&&s.mipmaps){const l=s.mipmaps.length;s.mipmaps.length=Math.min(s.mipmaps.length,3),l!==s.mipmaps.length&&h&&console.debug(`Reduced mipmap count from ${l} to ${s.mipmaps.length} for ${s.uuid}: ${s.image?.width}x${s.image?.height}.`)}r[o]=s}return s}else h=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}parser;url;constructor(t){const e=t.options.path;h&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}_isLoadingMesh;loadMesh=t=>{if(this._isLoadingMesh)return null;const e=this.parser.json.meshes[t]?.extensions?.[$];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>(this._isLoadingMesh=!1,r&&g.registerMesh(this.url,e.guid,r,e.lods?.length,0,e),r))):null};afterRoot(t){return h&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,r)=>{if(e?.extensions){const o=e?.extensions[$];if(o){if(!o.lods){h&&console.warn("Texture has no LODs",o);return}let s=!1;for(const n of this.parser.associations.keys())n.isTexture===!0&&this.parser.associations.get(n)?.textures===r&&(s=!0,g.registerTexture(this.url,n,o.lods?.length,r,o));s||this.parser.getDependency("texture",r).then(n=>{n&&g.registerTexture(this.url,n,o.lods?.length,r,o)})}}}),this.parser.json.meshes?.forEach((e,r)=>{if(e?.extensions){const o=e?.extensions[$];if(o&&o.lods){for(const s of this.parser.associations.keys())if(s.isMesh){const n=this.parser.associations.get(s);n?.meshes===r&&g.registerMesh(this.url,o.guid,s,o.lods.length,n.primitives,o)}}}}),null}static registerTexture=(t,e,r,o,s)=>{if(!e){h&&console.error("!! gltf-progressive: Called register texture without texture");return}if(h){const l=e.image?.width||e.source?.data?.width||0,a=e.image?.height||e.source?.data?.height||0;console.log(`> gltf-progressive: register texture[${o}] "${e.name||e.uuid}", Current: ${l}x${a}, Max: ${s.lods[0]?.width}x${s.lods[0]?.height}, uuid: ${e.uuid}`,s,e)}e.source&&(e.source[fe]=s);const n=s.guid;g.assignLODInformation(t,e,n,r,o),g.lodInfos.set(n,s),g.lowresCache.set(n,e)};static registerMesh=(t,e,r,o,s,n)=>{const l=r.geometry;if(!l){h&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),h&&console.log("> Progressive: register mesh "+r.name,{index:s,uuid:r.uuid},n,r),g.assignLODInformation(t,l,e,o,s),g.lodInfos.set(e,n);let a=g.lowresCache.get(e);a?a.push(r.geometry):a=[r.geometry],g.lowresCache.set(e,a),o>0&&!z(r)&&rt(r,l);for(const u of R)u.onRegisteredNewMesh?.(r,n)};static lodInfos=new Map;static previouslyLoaded=new Map;static lowresCache=new Map;static workers=[];static _workersIndex=0;static async getOrLoadLOD(t,e){const r=h=="verbose",o=this.getAssignedLODInformation(t);if(!o)return h&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const s=o?.key;let n;if(t.isTexture===!0){const l=t;l.source&&l.source[fe]&&(n=l.source[fe])}if(n||(n=g.lodInfos.get(s)),!n)h&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type,g.lodInfos);else{if(e>0){let u=!1;const f=Array.isArray(n.lods);if(f&&e>=n.lods.length?u=!0:f||(u=!0),u)return this.lowresCache.get(s)}const l=Array.isArray(n.lods)?n.lods[e]?.path:n.lods;if(!l)return h&&!n["missing:uri"]&&(n["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,n)),null;const a=Ze(o.url,l);if(a.endsWith(".glb")||a.endsWith(".gltf")){if(!n.guid)return console.warn("missing pointer for glb/gltf texture",n),null;const u=a+"_"+n.guid,f=await this.queue.slot(a),w=this.previouslyLoaded.get(u);if(w!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${u}`);let p=await w.catch(y=>(console.error(`Error loading LOD ${e} from ${a}
1
+ import{BufferGeometry as V,Mesh as j,Box3 as ie,Vector3 as I,Sphere as ve,CompressedTexture as $e,Texture as N,Matrix3 as Re,InterleavedBuffer as Ge,InterleavedBufferAttribute as je,BufferAttribute as Ne,TextureLoader as Ue,Matrix4 as Le,Clock as Fe,MeshStandardMaterial as We}from"./three-I__hSXzr.min.js";import{DRACOLoader as ze,KTX2Loader as qe,MeshoptDecoder as Ve,GLTFLoader as ae}from"./three-examples-D8zAE_7t.min.js";const Xe="";globalThis.GLTF_PROGRESSIVE_VERSION=Xe,console.debug("[gltf-progressive] version -");let k="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",U="https://cdn.needle.tools/static/three/0.179.1/basis2/";const He=k,Ke=U,_e=new URL(k+"draco_decoder.js");_e.searchParams.append("range","true"),fetch(_e,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(i=>{console.debug(`Failed to fetch remote Draco decoder from ${k} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),k===He&&be("./include/draco/"),U===Ke&&De("./include/ktx2/")}).finally(()=>{Me()});const Ye=()=>({dracoDecoderPath:k,ktx2TranscoderPath:U});function be(i){k=i,P&&P[ue]!=k?(console.debug("Updating Draco decoder path to "+i),P[ue]=k,P.setDecoderPath(k),P.preload()):console.debug("Setting Draco decoder path to "+i)}function De(i){U=i,C&&C.transcoderPath!=U?(console.debug("Updating KTX2 transcoder path to "+i),C.setTranscoderPath(U),C.init()):console.debug("Setting KTX2 transcoder path to "+i)}function ee(i){return Me(),i?C.detectSupport(i):i!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:P,ktx2Loader:C,meshoptDecoder:te}}function le(i){i.dracoLoader||i.setDRACOLoader(P),i.ktx2Loader||i.setKTX2Loader(C),i.meshoptDecoder||i.setMeshoptDecoder(te)}const ue=Symbol("dracoDecoderPath");let P,te,C;function Me(){P||(P=new ze,P[ue]=k,P.setDecoderPath(k),P.setDecoderConfig({type:"js"}),P.preload()),C||(C=new qe,C.setTranscoderPath(U),C.init()),te||(te=Ve)}const de=new WeakMap;function ce(i,t){let e=de.get(i);e?e=Object.assign(e,t):e=t,de.set(i,e)}const Qe=ae.prototype.load;function Je(...i){const t=de.get(this);let e=i[0];const r=new URL(e,window.location.href);if(r.hostname.endsWith("needle.tools")){const o=t?.progressive!==void 0?t.progressive:!0,s=t?.usecase?t.usecase:"default";o?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${s}`:this.requestHeader.Accept=`*/*;usecase=${s}`,e=r.toString()}return i[0]=e,Qe?.call(this,...i)}ae.prototype.load=Je,F("debugprogressive");function F(i){if(typeof window>"u")return!1;const t=new URL(window.location.href).searchParams.get(i);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function Ze(i,t){if(t===void 0||i===void 0||t.startsWith("./")||t.startsWith("http")||t.startsWith("data:")||t.startsWith("blob:"))return t;const e=i.lastIndexOf("/");if(e>=0){const r=i.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}function Oe(){return re!==void 0||(re=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),F("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",re)),re}let re;function Se(){if(typeof window>"u")return!1;const i=new URL(window.location.href),t=i.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(i.hostname);return i.hostname==="127.0.0.1"||t}class et{constructor(t=100,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,window.requestAnimationFrame(this.tick)}_running=new Map;_queue=[];debug=!1;tick=()=>{this.internalUpdate(),setTimeout(this.tick,10)};slot(t){return this.debug&&console.debug(`[PromiseQueue]: Requesting slot for key ${t}, running: ${this._running.size}, waiting: ${this._queue.length}`),new Promise(e=>{this._queue.push({key:t,resolve:e})})}add(t,e){this._running.has(t)||(this._running.set(t,e),e.finally(()=>{this._running.delete(t),this.debug&&console.debug(`[PromiseQueue]: Promise finished now running: ${this._running.size}, waiting: ${this._queue.length}. (finished ${t})`)}),this.debug&&console.debug(`[PromiseQueue]: Added new promise, now running: ${this._running.size}, waiting: ${this._queue.length}. (added ${t})`))}internalUpdate(){const t=this.maxConcurrent-this._running.size;for(let e=0;e<t&&this._queue.length>0;e++){this.debug&&console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);const{key:r,resolve:o}=this._queue.shift();o({use:s=>this.add(r,s)})}}}const tt=typeof window>"u"&&typeof document>"u",he=Symbol("needle:raycast-mesh");function z(i){return i?.[he]instanceof V?i[he]:null}function rt(i,t){if((i.type==="Mesh"||i.type==="SkinnedMesh")&&!z(i)){const e=ot(t);e.userData={isRaycastMesh:!0},i[he]=e}}function st(i=!0){if(i){if(X)return;const t=X=j.prototype.raycast;j.prototype.raycast=function(e,r){const o=this,s=z(o);let n;s&&o.isMesh&&(n=o.geometry,o.geometry=s),t.call(this,e,r),n&&(o.geometry=n)}}else{if(!X)return;j.prototype.raycast=X,X=null}}let X=null;function ot(i){const t=new V;for(const e in i.attributes)t.setAttribute(e,i.getAttribute(e));return t.setIndex(i.getIndex()),t}const R=new Array,h=F("debugprogressive");let H,W=-1;if(h){let i=function(){W+=1,W>=t&&(W=-1),console.log(`Toggle LOD level [${W}]`)},t=6;window.addEventListener("keyup",e=>{e.key==="p"&&i(),e.key==="w"&&(H=!H,console.log(`Toggle wireframe [${H}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(W=r,console.log(`Set LOD level to [${W}]`))})}function Pe(i){if(h&&H!==void 0)if(Array.isArray(i))for(const t of i)Pe(t);else i&&"wireframe"in i&&(i.wireframe=H===!0)}const K=new Array;let nt=0;const it=Oe()?2:10;function at(i){if(K.length<it){const e=K.length;h&&console.warn(`[Worker] Creating new worker #${e}`);const r=ye.createWorker(i||{});return K.push(r),r}const t=nt++%K.length;return K[t]}class ye{constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=r=>{const o=r.data;switch(this._debug&&console.log("[Worker] EVENT",o),o.type){case"loaded-gltf":for(const s of this._running)if(s.url===o.result.url){lt(o.result),s.resolve(o.result);const n=s.url;n.startsWith("blob:")&&URL.revokeObjectURL(n)}}},t.onerror=r=>{console.error("[Worker] Error in gltf-progressive worker:",r)},t.postMessage({type:"init"})}static async createWorker(t){const e=new Worker(URL.createObjectURL(new Blob([`import '${new URL("./loader.worker-C1GG9A7C.js",import.meta.url).toString()}';`],{type:"text/javascript"})),{type:"module"});return new ye(e,t)}_running=[];_webglRenderer=null;async load(t,e){const r=Ye();let o=e?.renderer;o||(this._webglRenderer??=(async()=>{const{WebGLRenderer:l}=await import("./three-I__hSXzr.min.js").then(a=>a.THREE);return new l})(),o=await this._webglRenderer);const s=ee(o).ktx2Loader.workerConfig;t instanceof URL?t=t.toString():t.startsWith("file:")?t=URL.createObjectURL(new Blob([t])):!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")&&(t=new URL(t,window.location.href).toString());const n={type:"load",url:t,dracoDecoderPath:r.dracoDecoderPath,ktx2TranscoderPath:r.ktx2TranscoderPath,ktx2LoaderConfig:s};return this._debug&&console.debug("[Worker] Sending load request",n),this.worker.postMessage(n),new Promise(l=>{this._running.push({url:t.toString(),resolve:l})})}_debug=!1}function lt(i){for(const t of i.geometries){const e=t.geometry,r=new V;if(r.name=e.name||"",e.index){const o=e.index;r.setIndex(ge(o))}for(const o in e.attributes){const s=e.attributes[o],n=ge(s);r.setAttribute(o,n)}if(e.morphAttributes)for(const o in e.morphAttributes){const s=e.morphAttributes[o].map(n=>ge(n));r.morphAttributes[o]=s}if(r.morphTargetsRelative=e.morphTargetsRelative??!1,r.boundingBox=new ie,r.boundingBox.min=new I(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),r.boundingBox.max=new I(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),r.boundingSphere=new ve(new I(e.boundingSphere?.center.x,e.boundingSphere?.center.y,e.boundingSphere?.center.z),e.boundingSphere?.radius),e.groups)for(const o of e.groups)r.addGroup(o.start,o.count,o.materialIndex);e.userData&&(r.userData=e.userData),t.geometry=r}for(const t of i.textures){const e=t.texture;let r=null;if(e.isCompressedTexture){const o=e.mipmaps,s=e.image?.width||e.source?.data?.width||-1,n=e.image?.height||e.source?.data?.height||-1;r=new $e(o,s,n,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else r=new N(e.image,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),r.mipmaps=e.mipmaps,r.channel=e.channel,r.source.data=e.source.data,r.flipY=e.flipY,r.premultiplyAlpha=e.premultiplyAlpha,r.unpackAlignment=e.unpackAlignment,r.matrix=new Re(...e.matrix.elements);if(!r){console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");continue}t.texture=r}return i}function ge(i){let t=i;if("isInterleavedBufferAttribute"in i&&i.isInterleavedBufferAttribute){const e=i.data,r=e.array,o=new Ge(r,e.stride);t=new je(o,i.itemSize,r.byteOffset,i.normalized),t.offset=i.offset}else"isBufferAttribute"in i&&i.isBufferAttribute&&(t=new Ne(i.array,i.itemSize,i.normalized),t.usage=i.usage,t.gpuType=i.gpuType,t.updateRanges=i.updateRanges);return t}const ut=F("gltf-progressive-worker"),dt=F("gltf-progressive-reduce-mipmaps"),fe=Symbol("needle-progressive-texture"),$="NEEDLE_progressive";class g{get name(){return $}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e?.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){return this.getAssignedLODInformation(t)?.index??-1}static getMaterialMinMaxLODsCount(t,e){const r=this,o="LODS:minmax",s=t[o];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const l of t)this.getMaterialMinMaxLODsCount(l,e);return t[o]=e,e}if(h==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const l=t;for(const a of Object.keys(l.uniforms)){const u=l.uniforms[a].value;u?.isTexture===!0&&n(u,e)}}else if(t.isMaterial)for(const l of Object.keys(t)){const a=t[l];a?.isTexture===!0&&n(a,e)}else h&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[o]=e,e;function n(l,a){const u=r.getAssignedLODInformation(l);if(u){const f=r.lodInfos.get(u.key);if(f&&f.lods){a.min_count=Math.min(a.min_count,f.lods.length),a.max_count=Math.max(a.max_count,f.lods.length);for(let w=0;w<f.lods.length;w++){const v=f.lods[w];v.width&&(a.lods[w]=a.lods[w]||{min_height:1/0,max_height:0},a.lods[w].min_height=Math.min(a.lods[w].min_height,v.height),a.lods[w].max_height=Math.max(a.lods[w].max_height,v.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const n=t[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let r,o;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&r?.userData?.LODS){const s=r.userData.LODS;if(o=this.lodInfos.get(s.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){if(!t)return Promise.resolve(null);if(t instanceof j||t.isMesh===!0){const r=t.geometry,o=this.getAssignedLODInformation(r);if(!o)return Promise.resolve(null);for(const s of R)s.onBeforeGetLODMesh?.(t,e);return t["LOD:requested level"]=e,g.getOrLoadLOD(r,e).then(s=>{if(Array.isArray(s)){const n=o.index||0;s=s[n]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],s&&r!=s&&(s?.isBufferGeometry?t.geometry=s:h&&console.error("Invalid LOD geometry",s))),s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else h&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const o=new Array;for(const s of r.material){const n=this.assignTextureLOD(s,e);o.push(n)}return Promise.all(o).then(s=>{const n=new Array;for(const l of s)Array.isArray(l)&&n.push(...l);return n})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,o=[],s=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const n=r;for(const l of Object.keys(n.uniforms)){const a=n.uniforms[l].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,l).then(f=>(f&&n.uniforms[l].value!=f&&(n.uniforms[l].value=f,n.uniformsNeedUpdate=!0),f));o.push(u),s.push(l)}}}else for(const n of Object.keys(r)){const l=r[n];if(l?.isTexture===!0){const a=this.assignTextureLODForSlot(l,e,r,n);o.push(a),s.push(n)}}return Promise.all(o).then(n=>{const l=new Array;for(let a=0;a<n.length;a++){const u=n[a],f=s[a];u&&u.isTexture===!0?l.push({material:r,slot:f,texture:u,level:e}):l.push({material:r,slot:f,texture:null,level:e})}return l})}if(t instanceof N||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,o){return t?.isTexture!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):g.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(s?.isTexture===!0){if(s!=t&&r&&o){const n=r[o];if(n&&!h){const l=this.getAssignedLODInformation(n);if(l&&l?.level<e)return h==="verbose"&&console.warn("Assigned texture level is already higher: ",l.level,e,r,n,s),null}if(dt&&s.mipmaps){const l=s.mipmaps.length;s.mipmaps.length=Math.min(s.mipmaps.length,3),l!==s.mipmaps.length&&h&&console.debug(`Reduced mipmap count from ${l} to ${s.mipmaps.length} for ${s.uuid}: ${s.image?.width}x${s.image?.height}.`)}r[o]=s}return s}else h=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}parser;url;constructor(t){const e=t.options.path;h&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}_isLoadingMesh;loadMesh=t=>{if(this._isLoadingMesh)return null;const e=this.parser.json.meshes[t]?.extensions?.[$];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>(this._isLoadingMesh=!1,r&&g.registerMesh(this.url,e.guid,r,e.lods?.length,0,e),r))):null};afterRoot(t){return h&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,r)=>{if(e?.extensions){const o=e?.extensions[$];if(o){if(!o.lods){h&&console.warn("Texture has no LODs",o);return}let s=!1;for(const n of this.parser.associations.keys())n.isTexture===!0&&this.parser.associations.get(n)?.textures===r&&(s=!0,g.registerTexture(this.url,n,o.lods?.length,r,o));s||this.parser.getDependency("texture",r).then(n=>{n&&g.registerTexture(this.url,n,o.lods?.length,r,o)})}}}),this.parser.json.meshes?.forEach((e,r)=>{if(e?.extensions){const o=e?.extensions[$];if(o&&o.lods){for(const s of this.parser.associations.keys())if(s.isMesh){const n=this.parser.associations.get(s);n?.meshes===r&&g.registerMesh(this.url,o.guid,s,o.lods.length,n.primitives,o)}}}}),null}static registerTexture=(t,e,r,o,s)=>{if(!e){h&&console.error("!! gltf-progressive: Called register texture without texture");return}if(h){const l=e.image?.width||e.source?.data?.width||0,a=e.image?.height||e.source?.data?.height||0;console.log(`> gltf-progressive: register texture[${o}] "${e.name||e.uuid}", Current: ${l}x${a}, Max: ${s.lods[0]?.width}x${s.lods[0]?.height}, uuid: ${e.uuid}`,s,e)}e.source&&(e.source[fe]=s);const n=s.guid;g.assignLODInformation(t,e,n,r,o),g.lodInfos.set(n,s),g.lowresCache.set(n,e)};static registerMesh=(t,e,r,o,s,n)=>{const l=r.geometry;if(!l){h&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),h&&console.log("> Progressive: register mesh "+r.name,{index:s,uuid:r.uuid},n,r),g.assignLODInformation(t,l,e,o,s),g.lodInfos.set(e,n);let a=g.lowresCache.get(e);a?a.push(r.geometry):a=[r.geometry],g.lowresCache.set(e,a),o>0&&!z(r)&&rt(r,l);for(const u of R)u.onRegisteredNewMesh?.(r,n)};static lodInfos=new Map;static previouslyLoaded=new Map;static lowresCache=new Map;static workers=[];static _workersIndex=0;static async getOrLoadLOD(t,e){const r=h=="verbose",o=this.getAssignedLODInformation(t);if(!o)return h&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const s=o?.key;let n;if(t.isTexture===!0){const l=t;l.source&&l.source[fe]&&(n=l.source[fe])}if(n||(n=g.lodInfos.get(s)),!n)h&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type,g.lodInfos);else{if(e>0){let u=!1;const f=Array.isArray(n.lods);if(f&&e>=n.lods.length?u=!0:f||(u=!0),u)return this.lowresCache.get(s)}const l=Array.isArray(n.lods)?n.lods[e]?.path:n.lods;if(!l)return h&&!n["missing:uri"]&&(n["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,n)),null;const a=Ze(o.url,l);if(a.endsWith(".glb")||a.endsWith(".gltf")){if(!n.guid)return console.warn("missing pointer for glb/gltf texture",n),null;const u=a+"_"+n.guid,f=await this.queue.slot(a),w=this.previouslyLoaded.get(u);if(w!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${u}`);let p=await w.catch(y=>(console.error(`Error loading LOD ${e} from ${a}
2
2
  `,y),null)),m=!1;if(p==null||(p instanceof N&&t instanceof N?p.image?.data||p.source?.data?p=this.copySettings(t,p):(m=!0,this.previouslyLoaded.delete(u)):p instanceof V&&t instanceof V&&(p.attributes.position?.array||(m=!0,this.previouslyLoaded.delete(u)))),!m)return p}if(!f.use)return h&&console.log(`LOD ${e} was aborted: ${a}`),null;const v=n,T=new Promise(async(p,m)=>{if(ut){const x=await(await at({})).load(a);if(x.textures.length>0)for(const d of x.textures){let c=d.texture;return g.assignLODInformation(o.url,c,s,e,void 0),t instanceof N&&(c=this.copySettings(t,c)),c&&(c.guid=v.guid),p(c)}if(x.geometries.length>0){const d=new Array;for(const c of x.geometries){const L=c.geometry;g.assignLODInformation(o.url,L,s,e,c.primitiveIndex),d.push(L)}return p(d)}return p(null)}const y=new ae;le(y),h&&(await new Promise(x=>setTimeout(x,1e3)),r&&console.warn("Start loading (delayed) "+a,v.guid));let A=a;if(v&&Array.isArray(v.lods)){const x=v.lods[e];x.hash&&(A+="?v="+x.hash)}const _=await y.loadAsync(A).catch(x=>(console.error(`Error loading LOD ${e} from ${a}
3
3
  `,x),p(null)));if(!_)return p(null);const E=_.parser;r&&console.log("Loading finished "+a,v.guid);let D=0;if(_.parser.json.textures){let x=!1;for(const d of _.parser.json.textures){if(d?.extensions){const c=d?.extensions[$];if(c?.guid&&c.guid===v.guid){x=!0;break}}D++}if(x){let d=await E.getDependency("texture",D);return d&&g.assignLODInformation(o.url,d,s,e,void 0),r&&console.log('change "'+t.name+'" \u2192 "'+d.name+'"',a,D,d,u),t instanceof N&&(d=this.copySettings(t,d)),d&&(d.guid=v.guid),p(d)}else h&&console.warn("Could not find texture with guid",v.guid,_.parser.json)}if(D=0,_.parser.json.meshes){let x=!1;for(const d of _.parser.json.meshes){if(d?.extensions){const c=d?.extensions[$];if(c?.guid&&c.guid===v.guid){x=!0;break}}D++}if(x){const d=await E.getDependency("mesh",D);if(r&&console.log(`Loaded Mesh "${d.name}"`,a,D,d,u),d.isMesh===!0){const c=d.geometry;return g.assignLODInformation(o.url,c,s,e,0),p(c)}else{const c=new Array;for(let L=0;L<d.children.length;L++){const O=d.children[L];if(O.isMesh===!0){const S=O.geometry;g.assignLODInformation(o.url,S,s,e,L),c.push(S)}}return p(c)}}else h&&console.warn("Could not find mesh with guid",v.guid,_.parser.json)}return p(null)});return this.previouslyLoaded.set(u,T),f.use(T),await T}else if(t instanceof N){r&&console.log("Load texture from uri: "+a);const u=await new Ue().loadAsync(a);return u?(u.guid=n.guid,u.flipY=!1,u.needsUpdate=!0,u.colorSpace=t.colorSpace,r&&console.log(n,u)):h&&console.warn("failed loading",a),u}}return null}static maxConcurrent=50;static queue=new et(g.maxConcurrent,{debug:h!=!1});static assignLODInformation(t,e,r,o,s){if(!e)return;e.userData||(e.userData={});const n=new ct(t,r,o,s);e.userData.LODS=n,"source"in e&&typeof e.source=="object"&&(e.source.LODS=n)}static getAssignedLODInformation(t){return t?t.userData?.LODS?t.userData.LODS:"source"in t&&t.source?.LODS?t.source.LODS:null:null}static copySettings(t,e){return e?(h==="verbose"&&console.debug(`Copy texture settings
4
4
  `,t.uuid,`
@@ -1,5 +1,5 @@
1
- import { BufferGeometry as J, Mesh as q, Box3 as ge, Vector3 as A, Sphere as Oe, CompressedTexture as Ge, Texture as E, Matrix3 as Fe, InterleavedBuffer as We, InterleavedBufferAttribute as Ue, BufferAttribute as ze, TextureLoader as Ee, Matrix4 as _e, Clock as Ne, MeshStandardMaterial as qe } from "./three-D9pcFbxc.js";
2
- import { DRACOLoader as Ve, KTX2Loader as Xe, MeshoptDecoder as je, GLTFLoader as xe } from "./three-examples-F0MJj0vr.js";
1
+ import { BufferGeometry as J, Mesh as q, Box3 as ge, Vector3 as A, Sphere as Oe, CompressedTexture as Ge, Texture as E, Matrix3 as Fe, InterleavedBuffer as We, InterleavedBufferAttribute as Ue, BufferAttribute as ze, TextureLoader as Ee, Matrix4 as _e, Clock as Ne, MeshStandardMaterial as qe } from "./three-VvRoMeIN.js";
2
+ import { DRACOLoader as Ve, KTX2Loader as Xe, MeshoptDecoder as je, GLTFLoader as xe } from "./three-examples-BhfOE7NG.js";
3
3
  const Ke = "";
4
4
  globalThis.GLTF_PROGRESSIVE_VERSION = Ke;
5
5
  console.debug("[gltf-progressive] version -");
@@ -208,7 +208,7 @@ class Le {
208
208
  const s = Qe();
209
209
  let n = e?.renderer;
210
210
  n || (this._webglRenderer ??= (async () => {
211
- const { WebGLRenderer: u } = await import("./three-D9pcFbxc.js").then((d) => d.THREE);
211
+ const { WebGLRenderer: u } = await import("./three-VvRoMeIN.js").then((d) => d.THREE);
212
212
  return new u();
213
213
  })(), n = await this._webglRenderer);
214
214
  const l = we(n).ktx2Loader.workerConfig;