@needle-tools/engine 6.0.0-alpha.5 → 6.0.0-alpha.7

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 (84) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/gltf-progressive-CRdzVlSY.umd.cjs +10 -0
  3. package/dist/gltf-progressive-OBdIERAY.min.js +10 -0
  4. package/dist/{gltf-progressive-B7lOWdLe.js → gltf-progressive-ZuAsp3FE.js} +237 -231
  5. package/dist/{materialx-CTPhpPxI.min.js → materialx-Bd0NThHa.min.js} +1 -1
  6. package/dist/{materialx-BwYvA-4x.umd.cjs → materialx-Clep-Dc8.umd.cjs} +2 -2
  7. package/dist/{materialx-B3qY8vPU.js → materialx-m9EM4lhZ.js} +1 -1
  8. package/dist/{needle-engine.bundle-_kAszB-k.min.js → needle-engine.bundle-B2_-yVCX.min.js} +148 -148
  9. package/dist/{needle-engine.bundle-D3nBMgfk.umd.cjs → needle-engine.bundle-BOs3iHUC.umd.cjs} +147 -147
  10. package/dist/{needle-engine.bundle-4xlWxOTF.js → needle-engine.bundle-hBHg3HuX.js} +7092 -7023
  11. package/dist/needle-engine.d.ts +49 -28
  12. package/dist/needle-engine.js +604 -603
  13. package/dist/needle-engine.min.js +1 -1
  14. package/dist/needle-engine.umd.cjs +1 -1
  15. package/dist/{vendor-BJviq-Oq.umd.cjs → vendor-Bb_SUKxZ.umd.cjs} +92 -92
  16. package/dist/{vendor-CdNldo8c.min.js → vendor-D1vc0sOe.min.js} +100 -100
  17. package/dist/{vendor-BQUQwut5.js → vendor-ipoLrKAE.js} +3466 -3320
  18. package/lib/engine/api.d.ts +2 -1
  19. package/lib/engine/api.js +2 -1
  20. package/lib/engine/api.js.map +1 -1
  21. package/lib/engine/engine_context.d.ts +2 -0
  22. package/lib/engine/engine_context.js +14 -0
  23. package/lib/engine/engine_context.js.map +1 -1
  24. package/lib/engine/engine_init.js +2 -2
  25. package/lib/engine/engine_init.js.map +1 -1
  26. package/lib/engine/engine_license.d.ts +7 -7
  27. package/lib/engine/engine_license.js +73 -73
  28. package/lib/engine/engine_license.js.map +1 -1
  29. package/lib/engine/engine_loaders.gltf.d.ts +3 -1
  30. package/lib/engine/engine_loaders.gltf.js +6 -1
  31. package/lib/engine/engine_loaders.gltf.js.map +1 -1
  32. package/lib/engine/engine_networking_blob.js +3 -3
  33. package/lib/engine/engine_networking_blob.js.map +1 -1
  34. package/lib/engine/engine_physics.d.ts +2 -0
  35. package/lib/engine/engine_physics.js +23 -1
  36. package/lib/engine/engine_physics.js.map +1 -1
  37. package/lib/engine/engine_utils_qrcode.js +2 -2
  38. package/lib/engine/engine_utils_qrcode.js.map +1 -1
  39. package/lib/engine/project-document/engine_document_extensions.d.ts +16 -0
  40. package/lib/engine/project-document/engine_document_extensions.js +29 -0
  41. package/lib/engine/project-document/engine_document_extensions.js.map +1 -0
  42. package/lib/engine/project-document/engine_document_runtime.js +1 -1
  43. package/lib/engine/project-document/engine_document_runtime.js.map +1 -1
  44. package/lib/engine/project-document/engine_project_document.js +39 -3
  45. package/lib/engine/project-document/engine_project_document.js.map +1 -1
  46. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
  47. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  48. package/lib/engine/webcomponents/needle menu/needle-menu.js +5 -5
  49. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  50. package/lib/engine/webcomponents/needle-engine.js +2 -2
  51. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  52. package/lib/engine/webcomponents/needle-engine.loading.js +2 -2
  53. package/lib/engine/xr/TempXRContext.js +2 -2
  54. package/lib/engine/xr/TempXRContext.js.map +1 -1
  55. package/lib/engine-components/Renderer.d.ts +1 -1
  56. package/lib/engine-components/Renderer.js +2 -11
  57. package/lib/engine-components/Renderer.js.map +1 -1
  58. package/lib/engine-components/export/usdz/USDZExporter.js +4 -4
  59. package/package.json +4 -4
  60. package/plugins/common/license.js +4 -4
  61. package/plugins/license/cli.js +7 -4
  62. package/plugins/vite/build-pipeline.js +6 -1
  63. package/plugins/vite/license.js +4 -4
  64. package/plugins/vite/logger.client.js +21 -8
  65. package/src/engine/api.ts +2 -1
  66. package/src/engine/engine_context.ts +11 -0
  67. package/src/engine/engine_init.ts +2 -2
  68. package/src/engine/engine_license.ts +70 -70
  69. package/src/engine/engine_loaders.gltf.ts +8 -2
  70. package/src/engine/engine_networking_blob.ts +3 -3
  71. package/src/engine/engine_physics.ts +22 -1
  72. package/src/engine/engine_utils_qrcode.ts +2 -2
  73. package/src/engine/project-document/engine_document_extensions.ts +39 -0
  74. package/src/engine/project-document/engine_document_runtime.ts +1 -1
  75. package/src/engine/project-document/engine_project_document.ts +46 -3
  76. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
  77. package/src/engine/webcomponents/needle menu/needle-menu.ts +5 -5
  78. package/src/engine/webcomponents/needle-engine.loading.ts +2 -2
  79. package/src/engine/webcomponents/needle-engine.ts +2 -2
  80. package/src/engine/xr/TempXRContext.ts +2 -2
  81. package/src/engine-components/Renderer.ts +4 -13
  82. package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
  83. package/dist/gltf-progressive-BpT9M5Mt.umd.cjs +0 -10
  84. package/dist/gltf-progressive-D0rzvhNG.min.js +0 -10
package/CHANGELOG.md CHANGED
@@ -4,6 +4,15 @@ 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
+ ## [6.0.0-alpha.7] - 2026-10-12
8
+
9
+ - Closing the final engine scene releases shared BVH and glTF decoder workers. Opening another scene starts fresh workers when needed.
10
+ - Project documents saved with legacy `namePath` addresses continue to load with the updated addressing dependency.
11
+
12
+ ## [6.0.0-alpha.6] - 2026-10-06
13
+
14
+ - Morph target animations now work reliably on shared meshes with multiple materials.
15
+
7
16
  ## [6.0.0-alpha.5] - 2026-10-05
8
17
 
9
18
  - Added initial support for using Needle Engine with Angular.
@@ -0,0 +1,10 @@
1
+ "use strict";const d=require("./three-core.umd.cjs"),Z=require("./three-examples.umd.cjs");var ce=typeof document<"u"?document.currentScript:null;const Ne="";globalThis.GLTF_PROGRESSIVE_VERSION=Ne;console.debug("[gltf-progressive] version -");let B="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",K="https://cdn.needle.tools/static/three/0.179.1/basis2/";const Xe=B,je=K;if(typeof window<"u"){const o=new URL(B+"draco_decoder.js");o.searchParams.append("range","true"),fetch(o,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(t=>{console.debug(`Failed to fetch remote Draco decoder from ${B} (offline: ${navigator.onLine})`),B===Xe&&$e("./include/draco/"),K===je&&Be("./include/ktx2/")}).finally(()=>{_e&&Te()})}const Ke=()=>({dracoDecoderPath:B,ktx2TranscoderPath:K});function $e(o){B=o,P&&P[ye]!=B?(console.debug("Updating Draco decoder path to "+o),P[ye]=B,P.setDecoderPath(B),P.preload()):console.debug("Setting Draco decoder path to "+o)}function Be(o){K=o,$&&$.transcoderPath!=K?(console.debug("Updating KTX2 transcoder path to "+o),$.setTranscoderPath(K),$.init()):console.debug("Setting KTX2 transcoder path to "+o)}function ue(o){_e=!0;const t=Te();return o?t.ktx2Loader.detectSupport(o):o!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),t}function He(){_e=!1,P?.dispose(),$?.dispose(),P=void 0,$=void 0}function Me(o){const{dracoLoader:t,ktx2Loader:e,meshoptDecoder:s}=Te();o.dracoLoader||o.setDRACOLoader(t),o.ktx2Loader||o.setKTX2Loader(e),o.meshoptDecoder||o.setMeshoptDecoder(s)}const ye=Symbol("dracoDecoderPath");let _e=!0,P,de,$;function Te(){return P||(P=new Z.DRACOLoader,P[ye]=B,P.setDecoderPath(B),P.preload()),$||($=new Z.KTX2Loader,$.setTranscoderPath(K),$.init()),de||(de=Z.MeshoptDecoder),{dracoLoader:P,ktx2Loader:$,meshoptDecoder:de}}const Le=new WeakMap;function Oe(o,t){let e=Le.get(o);e?e=Object.assign(e,t):e=t,Le.set(o,e)}const Ye=Z.GLTFLoader.prototype.load;function Qe(...o){const t=Le.get(this);let e=o[0];const s=Je(e);if(s?.hostname.endsWith("needle.tools")){const n=t?.progressive!==void 0?t.progressive:!0,i=t?.usecase?t.usecase:"default";n?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${i}`:this.requestHeader.Accept=`*/*;usecase=${i}`,e=s.toString()}return o[0]=e,Ye?.call(this,...o)}Z.GLTFLoader.prototype.load=Qe;function Je(o){try{if(o instanceof URL)return o;const t=globalThis.location?.href;return t?new URL(o,t):new URL(o)}catch{return null}}function Re(o){return o!=null&&o.data!=null}function we(o){const t=o.source?.data;return t!=null&&typeof t=="object"?t:null}function Ze(o){const t=o.image;return t!=null&&typeof t=="object"?t:null}function De(o){const t=Ze(o),e=we(o);return{width:t?.width||e?.width||0,height:t?.height||e?.height||0}}E("debugprogressive");function E(o){const t=globalThis.location?.href;if(!t)return!1;const s=new URL(t).searchParams.get(o);return s==null||s==="0"||s==="false"?!1:s===""?!0:s}function et(o,t){if(t===void 0||o===void 0||t.startsWith("./")||t.startsWith("http")||t.startsWith("data:")||t.startsWith("blob:"))return t;const e=o.lastIndexOf("/");if(e>=0){const s=o.substring(0,e+1);for(;s.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return s+t}return t}function be(){if(te!==void 0)return te;const o=globalThis.navigator?.userAgent||"";return te=/iPhone|iPad|iPod|Android|IEMobile/i.test(o),E("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",te),te}let te;function qe(){const o=globalThis.location?.href;if(!o)return!1;const t=new URL(o),e=t.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(t.hostname);return t.hostname==="127.0.0.1"||e}class tt{constructor(t,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,setTimeout(this.tick,0)}maxConcurrent;_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:s,resolve:r}=this._queue.shift();r({use:n=>this.add(s,n)})}}}function st(o){const t=o.image,e=t?.width??0,s=t?.height??0,r=t?.depth??1,n=Math.floor(Math.log2(Math.max(e,s,r)))+1,i=rt(o);return e*s*r*i*(1-Math.pow(.25,n))/(1-.25)}function rt(o){let t=4;const e=o.format;e===d.RedFormat||e===d.RedIntegerFormat?t=1:e===d.RGFormat||e===d.RGIntegerFormat?t=2:e===d.RGBFormat||e===1029?t=3:(e===d.RGBAFormat||e===d.RGBAIntegerFormat)&&(t=4);let s=1;const r=o.type;return r===1009||r===1010?s=1:r===1011||r===1012?s=2:r===1013||r===1014||r===1015?s=4:r===1016&&(s=2),t*s}const nt=typeof window>"u"&&typeof document>"u",ve=Symbol("needle:raycast-mesh");function ee(o){return o?.[ve]instanceof d.BufferGeometry?o[ve]:null}function ot(o,t){if((o.type==="Mesh"||o.type==="SkinnedMesh")&&!ee(o)){const s=at(t);s.userData={isRaycastMesh:!0},o[ve]=s}}function it(o=!0){if(o){if(se)return;const t=se=d.Mesh.prototype.raycast;d.Mesh.prototype.raycast=function(e,s){const r=this,n=ee(r);let i;n&&r.isMesh&&(i=r.geometry,r.geometry=n),t.call(this,e,s),i&&(r.geometry=i)}}else{if(!se)return;d.Mesh.prototype.raycast=se,se=null}}let se=null;function at(o){const t=new d.BufferGeometry;for(const e in o.attributes)t.setAttribute(e,o.getAttribute(e));return t.setIndex(o.getIndex()),t}const W=new Array,p=E("debugprogressive");let oe,X=-1;if(p&&typeof window<"u"){let o=function(){X+=1,X>=t&&(X=-1),console.log(`Toggle LOD level [${X}]`)};const t=6;window.addEventListener("keyup",e=>{e.key==="p"&&o(),e.key==="w"&&(oe=!oe,console.log(`Toggle wireframe [${oe}]`));const s=parseInt(e.key);!isNaN(s)&&s>=0&&(X=s,console.log(`Set LOD level to [${X}]`))})}function We(o){if(p&&oe!==void 0)if(Array.isArray(o))for(const t of o)We(t);else o&&"wireframe"in o&&(o.wireframe=oe===!0)}const re=new Array;let lt=0;const ut=be()?2:10;function ct(o){if(re.length<ut){const s=re.length;p&&console.warn(`[Worker] Creating new worker #${s}`);const r=Se.createWorker(o||{});return re.push(r),r}const t=lt++%re.length;return re[t]}class Se{constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=s=>{const r=s.data;switch(this._debug&&console.log("[Worker] EVENT",r),r.type){case"loaded-gltf":for(const n of this._running)if(n.url===r.result.url){dt(r.result),n.resolve(r.result);const i=n.url;i.startsWith("blob:")&&URL.revokeObjectURL(i)}}},t.onerror=s=>{console.error("[Worker] Error in gltf-progressive worker:",s)},t.postMessage({type:"init"})}worker;static async createWorker(t){const e=new Worker(new URL("/gltf-progressive.worker-DvoMaVdx.js",typeof document>"u"?require("url").pathToFileURL(__filename).href:ce&&ce.tagName.toUpperCase()==="SCRIPT"&&ce.src||new URL("gltf-progressive-CRdzVlSY.umd.cjs",document.baseURI).href),{type:"module"});return new Se(e,t)}_running=[];_webglRenderer=null;async load(t,e){const s=Ke();let r=e?.renderer;r||(this._webglRenderer??=(async()=>{const{WebGLRenderer:u}=await Promise.resolve().then(()=>require("./three-core.umd.cjs")).then(h=>h.THREE);return new u})(),r=await this._webglRenderer);const l=ue(r).ktx2Loader.workerConfig;if(t instanceof URL)t=t.toString();else if(t.startsWith("file:"))t=URL.createObjectURL(new Blob([t]));else if(!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")){const u=globalThis.location?.href;u&&(t=new URL(t,u).toString())}const a={type:"load",url:t,dracoDecoderPath:s.dracoDecoderPath,ktx2TranscoderPath:s.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 dt(o){for(const t of o.geometries){const e=t.geometry,s=new d.BufferGeometry;if(s.name=e.name||"",e.index){const r=e.index;s.setIndex(fe(r))}for(const r in e.attributes){const n=e.attributes[r],i=fe(n);s.setAttribute(r,i)}if(e.morphAttributes)for(const r in e.morphAttributes){const i=e.morphAttributes[r].map(l=>fe(l));s.morphAttributes[r]=i}if(s.morphTargetsRelative=e.morphTargetsRelative??!1,s.boundingBox=new d.Box3,s.boundingBox.min=new d.Vector3(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),s.boundingBox.max=new d.Vector3(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),s.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 r of e.groups)s.addGroup(r.start,r.count,r.materialIndex);e.userData&&(s.userData=e.userData),t.geometry=s}for(const t of o.textures){const e=t.texture;let s=null;if(e.isCompressedTexture){const r=e.mipmaps,{width:n,height:i}=De(e);s=new d.CompressedTexture(r,n,i,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else s=new d.Texture(e.image,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),s.mipmaps=e.mipmaps,s.channel=e.channel,s.source.data=e.source.data,s.flipY=e.flipY,s.premultiplyAlpha=e.premultiplyAlpha,s.unpackAlignment=e.unpackAlignment,s.matrix=new d.Matrix3(...e.matrix.elements);if(!s){console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");continue}t.texture=s}return o}function fe(o){let t=o;if("isInterleavedBufferAttribute"in o&&o.isInterleavedBufferAttribute){const e=o.data,s=e.array,r=new d.InterleavedBuffer(s,e.stride);t=new d.InterleavedBufferAttribute(r,o.itemSize,s.byteOffset,o.normalized),t.offset=o.offset}else"isBufferAttribute"in o&&o.isBufferAttribute&&(t=new d.BufferAttribute(o.array,o.itemSize,o.normalized),t.usage=o.usage,t.gpuType=o.gpuType,t.updateRanges=o.updateRanges);return t}const ft=E("gltf-progressive-worker");E("gltf-progressive-reduce-mipmaps");const ne=E("gltf-progressive-gc"),he=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 s=this,r="LODS:minmax",n=t[r];if(n!=null)return n;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[r]=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&&i(u,e)}}else if(t.isMaterial)for(const l of Object.keys(t)){const a=t[l];a?.isTexture===!0&&i(a,e)}else p&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[r]=e,e;function i(l,a){const u=s.getAssignedLODInformation(l);if(u){const h=s.lodInfos.get(u.key);if(h&&h.lods){a.min_count=Math.min(a.min_count,h.lods.length),a.max_count=Math.max(a.max_count,h.lods.length);for(let c=0;c<h.lods.length;c++){const f=h.lods[c];f.width&&(a.lods[c]=a.lods[c]||{min_height:1/0,max_height:0},a.lods[c].min_height=Math.min(a.lods[c].min_height,f.height),a.lods[c].max_height=Math.max(a.lods[c].max_height,f.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const n of t)if(this.hasLODLevelAvailable(n,e))return!0;return!1}if(t.isMaterial===!0){for(const n of Object.keys(t)){const i=t[n];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const n of t.children)if(n.isMesh===!0&&this.hasLODLevelAvailable(n,e))return!0}let s,r;if(t.isMesh?s=t.geometry:(t.isBufferGeometry||t.isTexture)&&(s=t),s&&s?.userData?.LODS){const n=s.userData.LODS;if(r=this.lodInfos.get(n.key),e===void 0)return r!=null;if(r)return Array.isArray(r.lods)?e<r.lods.length:e===0}return!1}static assignMeshLOD(t,e,s){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 l of W)l.onBeforeGetLODMesh?.(t,e);t["LOD:requested level"]=e;const i=()=>t["LOD:requested level"]===e||this.shouldApplyStaleMeshLOD(t,e);return m.getOrLoadLOD(r,e,{isCurrent:i}).then(l=>{if(Array.isArray(l)){const u=n.index||0;l=l[u]}const a=t["LOD:requested level"]===e;return(a||this.shouldApplyStaleMeshLOD(t,e))&&(a&&delete t["LOD:requested level"],l&&r!=l&&(l?.isBufferGeometry?typeof s?.apply=="function"?s.apply(l,e,t):s?.apply!==!1&&(t.geometry=l):p&&console.error("Invalid LOD geometry",l))),l}).catch(l=>(console.error("Error loading mesh LOD",t,l),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,s){if(!t)return Promise.resolve(null);const r=s?.force===!0;if(t.isMesh===!0){const n=t;if(Array.isArray(n.material)){const i=new Array;for(const l of n.material){const a=this.assignTextureLOD(l,e,s);i.push(a)}return Promise.all(i).then(l=>{const a=new Array;for(const u of l)Array.isArray(u)&&a.push(...u);return a})}else return this.assignTextureLOD(n.material,e,s)}if(t.isMaterial===!0){const n=t,i=[],l=new Array;if(this.trackCurrentMaterialTextureSlots(n),n.uniforms&&(n.isRawShaderMaterial||n.isShaderMaterial===!0)){const a=n;for(const u of Object.keys(a.uniforms)){const h=a.uniforms[u].value;if(h?.isTexture===!0){const c=this.assignTextureLODForSlot(h,e,n,u,r).then(f=>(f&&a.uniforms[u].value!=f&&(a.uniforms[u].value=f,a.uniformsNeedUpdate=!0),f));i.push(c),l.push(u)}}}else for(const a of Object.keys(n)){const u=n[a];if(u?.isTexture===!0){const h=this.assignTextureLODForSlot(u,e,n,a,r);i.push(h),l.push(a)}}return Promise.all(i).then(a=>{const u=new Array;for(let h=0;h<a.length;h++){const c=a[h],f=l[h];c&&c.isTexture===!0?u.push({material:n,slot:f,texture:c,level:e}):u.push({material:n,slot:f,texture:null,level:e})}return u})}if(t instanceof d.Texture||t.isTexture===!0){const n=t;return this.assignTextureLODForSlot(n,e,null,null,r)}return Promise.resolve(null)}static set maxConcurrentLoadingTasks(t){m.queue.maxConcurrent=t}static get maxConcurrentLoadingTasks(){return m.queue.maxConcurrent}static assignTextureLODForSlot(t,e,s,r,n){if(t?.isTexture!==!0)return Promise.resolve(null);if(r==="glyphMap")return Promise.resolve(t);const i=this.getAssignedLODInformation(t);if(i&&(i.level===e||!n&&i.level<e))return Promise.resolve(t);if(s&&r){const c=this.getPendingTextureSlotRequest(s,r);if(c&&c.level===e&&c.force===n)return c.promise}const l=s&&r?this.nextTextureSlotRequestId(s,r,e,n):0,a=()=>!s||!r||this.getLatestTextureSlotRequest(s,r)?.id===l,u=()=>a()||this.shouldApplyStaleTextureSlotLOD(s,r,e,n),h=m.getOrLoadLOD(t,e,{isCurrent:u}).then(c=>{if(!a()&&!this.shouldApplyStaleTextureSlotLOD(s,r,e,n))return null;if(Array.isArray(c))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(c?.isTexture===!0){if(c!=t&&s&&r){const f=this.getMaterialTextureSlot(s,r)??t;if(f&&!n){const g=this.getAssignedLODInformation(f);if(g&&g?.level<e)return p==="verbose"&&console.warn("Assigned texture level is already higher: ",g.level,e,s,f,c),null}this.assignTrackedTextureSlot(s,r,c)}return c}else p=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(c=>(console.error("Error loading LOD",t,c),null));return s&&r&&this.setPendingTextureSlotRequest(s,r,e,n,l,h),h}static trackedTextureSlots=new WeakMap;static pendingTextureSlotRequests=new WeakMap;static latestTextureSlotRequests=new WeakMap;static textureSlotRequestId=0;static trackCurrentMaterialTextureSlots(t){if(t.uniforms&&(t.isRawShaderMaterial||t.isShaderMaterial===!0)){const e=t;for(const s of Object.keys(e.uniforms)){const r=e.uniforms[s].value;r?.isTexture===!0&&this.ensureTrackedTextureSlot(t,s,r)}return}for(const e of Object.keys(t)){const s=t[e];s?.isTexture===!0&&this.ensureTrackedTextureSlot(t,e,s)}}static getPendingTextureSlotRequest(t,e){return this.pendingTextureSlotRequests.get(t)?.get(e)}static nextTextureSlotRequestId(t,e,s,r){let n=this.latestTextureSlotRequests.get(t);n||(n=new Map,this.latestTextureSlotRequests.set(t,n));const i=++this.textureSlotRequestId;return n.set(e,{id:i,level:s,force:r}),i}static getLatestTextureSlotRequest(t,e){return this.latestTextureSlotRequests.get(t)?.get(e)}static shouldApplyStaleTextureSlotLOD(t,e,s,r){if(!t||!e)return!1;const n=this.getLatestTextureSlotRequest(t,e),i=this.getMaterialTextureSlot(t,e),l=this.getAssignedLODInformation(i)?.level??1/0;return s>=l?!1:r?n?s>=n.level:!1:!0}static shouldApplyStaleMeshLOD(t,e){const s=t["LOD:requested level"];if(typeof s!="number")return!1;const r=this.getAssignedLODInformation(t.geometry)?.level??1/0;return e<r&&e>=s}static setPendingTextureSlotRequest(t,e,s,r,n,i){let l=this.pendingTextureSlotRequests.get(t);l||(l=new Map,this.pendingTextureSlotRequests.set(t,l));const a={level:s,force:r,id:n,promise:i};l.set(e,a),i.finally(()=>{l.get(e)?.id===n&&l.delete(e)})}static getMaterialTextureSlot(t,e){const r=t.uniforms?.[e];if(r?.value?.isTexture===!0)return r.value;const n=t[e];return n?.isTexture===!0?n:null}static setMaterialTextureSlot(t,e,s){const n=t.uniforms?.[e];if(n?.value?.isTexture===!0){n.value=s,t.uniformsNeedUpdate=!0;return}t[e]=s}static assignTrackedTextureSlot(t,e,s){let r=this.trackedTextureSlots.get(t);r||(r=new Map,this.trackedTextureSlots.set(t,r));const n=this.getMaterialTextureSlot(t,e);let i=r.get(e);!i&&n?i=this.ensureTrackedTextureSlot(t,e,n):i&&n&&i!==n&&(this.releaseTrackedTextureSlot(t,e,i),i=this.ensureTrackedTextureSlot(t,e,n)),!(i===s&&n===s)&&(i&&i!==s&&this.releaseTrackedTextureSlot(t,e,i),i!==s&&(this.trackTextureUsage(s),r.set(e,s)),n!==s&&this.setMaterialTextureSlot(t,e,s))}static ensureTrackedTextureSlot(t,e,s){let r=this.trackedTextureSlots.get(t);r||(r=new Map,this.trackedTextureSlots.set(t,r));const n=r.get(e);return n===s?n:(n&&this.releaseTrackedTextureSlot(t,e,n),this.trackTextureUsage(s),r.set(e,s),s)}static releaseTrackedTextureSlot(t,e,s){const r=this.trackedTextureSlots.get(t);if(r?.get(e)===s&&r.delete(e),this.untrackTextureUsage(s)&&(p||ne)){const i=this.getAssignedLODInformation(s);console.log(`[gltf-progressive] Disposed old texture LOD ${i?.level??"?"} for ${t.name||t.type}.${e}`,s.uuid)}}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(s=>(this._isLoadingMesh=!1,s&&m.registerMesh(this.url,e.guid,s,e.lods?.length,0,e),s))):null};afterRoot(t){return p&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,s)=>{if(e?.extensions){const r=e?.extensions[F];if(r){if(!r.lods){p&&console.warn("Texture has no LODs",r);return}let n=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i)?.textures===s&&(n=!0,m.registerTexture(this.url,i,r.lods?.length,s,r));n||this.parser.getDependency("texture",s).then(i=>{i&&m.registerTexture(this.url,i,r.lods?.length,s,r)})}}}),this.parser.json.meshes?.forEach((e,s)=>{if(e?.extensions){const r=e?.extensions[F];if(r&&r.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const i=this.parser.associations.get(n);i?.meshes===s&&m.registerMesh(this.url,r.guid,n,r.lods.length,i.primitives,r)}}}}),null}static registerTexture=(t,e,s,r,n)=>{if(!e){p&&console.error("!! gltf-progressive: Called register texture without texture");return}if(p){const{width:l,height:a}=De(e);console.log(`> gltf-progressive: register texture[${r}] "${e.name||e.uuid}", Current: ${l}x${a}, Max: ${n.lods[0]?.width}x${n.lods[0]?.height}, uuid: ${e.uuid}`,n,e)}e.source&&(e.source[he]=n);const i=n.guid;m.assignLODInformation(t,e,i,s,r),m.lodInfos.set(i,n),m.lowresCache.set(i,new WeakRef(e))};static registerMesh=(t,e,s,r,n,i)=>{const l=s.geometry;if(!l){p&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),p&&console.log("> Progressive: register mesh "+s.name,{index:n,uuid:s.uuid},i,s),m.assignLODInformation(t,l,e,r,n),m.lodInfos.set(e,i);let u=m.lowresCache.get(e)?.deref();u?u.push(s.geometry):u=[s.geometry],m.lowresCache.set(e,new WeakRef(u)),r>0&&!ee(s)&&ot(s,l);for(const h of W)h.onRegisteredNewMesh?.(s,i)};static dispose(t){if(t){this.lodInfos.delete(t);const e=this.lowresCache.get(t);if(e){const s=e.deref();if(s){if(s.isTexture){const r=s;this.textureRefCounts.delete(r.uuid),r.dispose()}else if(Array.isArray(s))for(const r of s)r.dispose()}this.lowresCache.delete(t)}for(const[s,r]of this.cache)s.includes(t)&&(this._disposeCacheEntry(r),this.cache.delete(s))}else{this.cacheGeneration++,this.lodInfos.clear();for(const[,e]of this.lowresCache){const s=e.deref();if(s){if(s.isTexture){const r=s;this.textureRefCounts.delete(r.uuid),r.dispose()}else if(Array.isArray(s))for(const r of s)r.dispose()}}this.lowresCache.clear();for(const[,e]of this.cache)this._disposeCacheEntry(e);this.cache.clear(),this.textureRefCounts.clear(),this.trackedTextureSlots=new WeakMap,this.pendingTextureSlotRequests=new WeakMap,this.latestTextureSlotRequests=new WeakMap,this.textureSlotRequestId=0}}static _disposeCacheEntry(t){if(t instanceof WeakRef){const e=t.deref();e&&(e.isTexture&&this.textureRefCounts.delete(e.uuid),e.dispose())}else this.disposedRequests.add(t),t.then(e=>{if(e)if(Array.isArray(e))for(const s of e)s.dispose();else e.isTexture&&this.textureRefCounts.delete(e.uuid),e.dispose()}).catch(()=>{})}static lodInfos=new Map;static cache=new Map;static lowresCache=new Map;static textureRefCounts=new Map;static _resourceRegistry=new FinalizationRegistry(t=>{const e=m.cache.get(t);(p||ne)&&console.debug(`[gltf-progressive] Memory: Resource GC'd
2
+ ${t}`),e instanceof WeakRef&&(e.deref()||(m.cache.delete(t),(p||ne)&&console.log("[gltf-progressive] ↪ Cache entry deleted (GC)")))});static trackTextureUsage(t){const e=t.uuid,s=this.textureRefCounts.get(e)||0;this.textureRefCounts.set(e,s+1),p==="verbose"&&console.log(`[gltf-progressive] Track texture ${e}, refCount: ${s} → ${s+1}`)}static untrackTextureUsage(t){const e=t.uuid,s=this.textureRefCounts.get(e);if(!s)return(p==="verbose"||ne)&&n("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)",0),t.dispose(),!0;const r=s-1;if(r<=0)return this.textureRefCounts.delete(e),(p||ne)&&n("[gltf-progressive] Memory: Dispose texture",r),t.dispose(),!0;return this.textureRefCounts.set(e,r),p==="verbose"&&n("[gltf-progressive] Memory: Untrack texture",r),!1;function n(i,l){const{width:a,height:u}=De(t),h=a&&u?`${a}x${u}`:"N/A";let c="N/A";a&&u&&(c=`~${(st(t)/(1024*1024)).toFixed(2)} MB`),console.log(`${i} — ${t.name} ${h} (${c}), refCount: ${s} → ${l}
3
+ ${e}`)}}static workers=[];static cacheGeneration=0;static disposedRequests=new WeakSet;static _workersIndex=0;static async getOrLoadLOD(t,e,s){const r=this.cacheGeneration,n=p=="verbose",i=this.getAssignedLODInformation(t);if(!i)return p&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const l=i?.key;let a;if(t.isTexture===!0){const h=t;h.source&&h.source[he]&&(a=h.source[he])}if(a||(a=m.lodInfos.get(l)),!a)p&&console.warn(`Can not load LOD ${e}: no LOD info found for "${l}" ${t.name}`,t.type,m.lodInfos);else{if(e>0){let f=!1;const g=Array.isArray(a.lods);if(g&&e>=a.lods.length?f=!0:g||(f=!0),f){const M=this.lowresCache.get(l);if(M){const w=M.deref();if(w)return w;this.lowresCache.delete(l),p&&console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${l}`)}return null}}const h=Array.isArray(a.lods)?a.lods[e]?.path:a.lods;if(!h)return p&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const c=et(i.url,h);if(c.endsWith(".glb")||c.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const f=c+"_"+a.guid,g=await this.tryResolveLODCacheEntry(this.cache.get(f),f,c,t,e,n);if(r!==this.cacheGeneration)return null;if(g.found)return g.value;if(s?.isCurrent?.()===!1)return n&&console.log(`Skipping stale LOD ${e} request before queue: ${c}`),null;const M=await this.queue.slot(c);if(r!==this.cacheGeneration)return null;if(s?.isCurrent?.()===!1)return n&&console.log(`Skipping stale LOD ${e} request after queue: ${c}`),null;const w=await this.tryResolveLODCacheEntry(this.cache.get(f),f,c,t,e,n);if(r!==this.cacheGeneration)return null;if(w.found)return w.value;const L=this.cache.get(f);if(L!==void 0){const y=await this.tryResolveLODCacheEntry(L,f,c,t,e,n);if(r!==this.cacheGeneration)return null;if(y.found)return y.value}if(!M.use)return p&&console.log(`LOD ${e} was aborted: ${c}`),null;const D=a,_=new Promise(async(y,S)=>{if(ft){const x=await(await ct({})).load(c);if(x.textures.length>0)for(const v of x.textures){let R=v.texture;return m.assignLODInformation(i.url,R,l,e,void 0),t instanceof d.Texture&&(R=this.copySettings(t,R)),R&&(R.guid=D.guid),y(R)}if(x.geometries.length>0){const v=new Array;for(const R of x.geometries){const N=R.geometry;m.assignLODInformation(i.url,N,l,e,R.primitiveIndex),v.push(N)}return y(v)}return y(null)}const I=new Z.GLTFLoader;Me(I),p&&(await new Promise(O=>setTimeout(O,1e3)),n&&console.warn("Start loading (delayed) "+c,D.guid));let k=c;if(D&&Array.isArray(D.lods)){const O=D.lods[e];O.hash&&(k+="?v="+O.hash)}const T=await I.loadAsync(k).catch(O=>(console.error(`Error loading LOD ${e} from ${c}
4
+ `,O),y(null)));if(!T)return y(null);const U=T.parser;n&&console.log("Loading finished "+c,D.guid);let A=0;if(T.parser.json.textures){let O=!1;for(const x of T.parser.json.textures){if(x?.extensions){const v=x?.extensions[F];if(v?.guid&&v.guid===D.guid){O=!0;break}}A++}if(O){let x=await U.getDependency("texture",A);return x&&m.assignLODInformation(i.url,x,l,e,void 0),n&&console.log('change "'+t.name+'" → "'+x.name+'"',c,A,x,f),t instanceof d.Texture&&(x=this.copySettings(t,x)),x&&(x.guid=D.guid),y(x)}else p&&console.warn("Could not find texture with guid",D.guid,T.parser.json)}if(A=0,T.parser.json.meshes){let O=!1;for(const x of T.parser.json.meshes){if(x?.extensions){const v=x?.extensions[F];if(v?.guid&&v.guid===D.guid){O=!0;break}}A++}if(O){const x=await U.getDependency("mesh",A);if(n&&console.log(`Loaded Mesh "${x.name}"`,c,A,x,f),x.isMesh===!0){const v=x.geometry;return m.assignLODInformation(i.url,v,l,e,0),y(v)}else{const v=new Array;for(let R=0;R<x.children.length;R++){const N=x.children[R];if(N.isMesh===!0){const H=N.geometry;m.assignLODInformation(i.url,H,l,e,R),v.push(H)}}return y(v)}}else p&&console.warn("Could not find mesh with guid",D.guid,T.parser.json)}return y(null)});this.cache.set(f,_),M.use(_);const b=await _;return r!==this.cacheGeneration||this.cache.get(f)!==_?null:(b!=null?b instanceof d.Texture?(this.cache.set(f,new WeakRef(b)),m._resourceRegistry.register(b,f)):Array.isArray(b)?this.cache.set(f,Promise.resolve(b)):this.cache.set(f,Promise.resolve(b)):this.cache.set(f,Promise.resolve(null)),b)}else if(t instanceof d.Texture){if(s?.isCurrent?.()===!1)return n&&console.log(`Skipping stale texture LOD ${e} request: ${c}`),null;n&&console.log("Load texture from uri: "+c);const g=await new d.TextureLoader().loadAsync(c);return r!==this.cacheGeneration||s?.isCurrent?.()===!1?(g?.dispose(),null):(g?(g.guid=a.guid,g.flipY=!1,g.needsUpdate=!0,g.colorSpace=t.colorSpace,n&&console.log(a,g)):p&&console.warn("failed loading",c),g)}}return null}static async tryResolveLODCacheEntry(t,e,s,r,n,i){if(t===void 0)return{found:!1};if(i&&console.log(`LOD ${n} was already loading/loaded: ${e}`),t instanceof WeakRef){const u=t.deref();if(u){let h=u,c=!1;if(h instanceof d.Texture&&r instanceof d.Texture?Re(h.image)||we(h)?h=this.copySettings(r,h):c=!0:h instanceof d.BufferGeometry&&r instanceof d.BufferGeometry&&(h.attributes.position?.array||(c=!0)),!c)return{found:!0,value:h}}return this.cache.delete(e),p&&console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${e}`),{found:!1}}let l=await t.catch(u=>(console.error(`Error loading LOD ${n} from ${s}
5
+ `,u),null));if(this.disposedRequests.has(t))return{found:!0,value:null};let a=!1;return l==null||(l instanceof d.Texture&&r instanceof d.Texture?Re(l.image)||we(l)?l=this.copySettings(r,l):(a=!0,this.cache.delete(e)):l instanceof d.BufferGeometry&&r instanceof d.BufferGeometry&&(l.attributes.position?.array||(a=!0,this.cache.delete(e)))),a?{found:!1}:{found:!0,value:l}}static _queue;static get queue(){return this._queue??=new tt(be()?20:50,{debug:p!=!1})}static assignLODInformation(t,e,s,r,n){if(!e)return;e.userData||(e.userData={});const i=new ht(t,s,r,n);e.userData.LODS=i,"source"in e&&typeof e.source=="object"&&(e.source.LODS=i)}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
6
+ `,t.uuid,`
7
+ `,e.uuid),e=e.clone(),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e):t}}class ht{url;key;level;index;constructor(t,e,s,r){this.url=t,this.key=e,this.level=s,r!=null&&(this.index=r)}}class ae{static addPromise=(t,e,s,r)=>{r.forEach(n=>{n.add(t,e,s)})};ready;get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}_resolve;_signal;_frame_start;_frames_to_capture;_resolved=!1;_addedCount=0;_resolvedCount=0;_awaiting=[];_maxPromisesPerObject=1;constructor(t,e){const r=Math.max(e.frames??2,2);this._frame_start=e.waitForFirstCapture?void 0:t,this._frames_to_capture=r,this.ready=new Promise(n=>{this._resolve=n}),this.ready.finally(()=>{this._resolved=!0,this._awaiting.length=0}),this._signal=e.signal,this._signal?.addEventListener("abort",()=>{this.resolveNow()}),this._maxPromisesPerObject=Math.max(1,e.maxPromisesPerObject??1)}_currentFrame=0;update(t){this._currentFrame=t,this._frame_start===void 0&&this._addedCount>0&&(this._frame_start=t),(this._signal?.aborted||this._awaiting.length===0&&this._frame_start!==void 0&&t>this._frame_start+this._frames_to_capture)&&this.resolveNow()}_seen=new WeakMap;add(t,e,s){if(this._resolved){p&&console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}if(!(this._frame_start!==void 0&&this._currentFrame>this._frame_start+this._frames_to_capture)){if(this._maxPromisesPerObject>=1)if(this._seen.has(e)){const r=this._seen.get(e);if(r>=this._maxPromisesPerObject){p&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(e,r+1)}else this._seen.set(e,1);this._awaiting.push(s),this._addedCount++,s.finally(()=>{this._resolvedCount++,this._awaiting.splice(this._awaiting.indexOf(s),1)})}}resolveNow(){this._resolved||this._resolve?.({awaited_count:this._addedCount,resolved_count:this._resolvedCount,cancelled:this._signal?.aborted??!1})}}const G=E("debugprogressive"),gt=G==="colors",pt=E("noprogressive"),ge=Symbol("Needle:LODSManager"),pe=Symbol("Needle:LODState"),V=Symbol("Needle:CurrentLOD"),Ce=d.THREE,C={mesh_lod:-1,texture_lod:-1},mt=new d.Color,Pe=[3526751,11065402,15978811,15897394,15749691,11032304,4827122,3332036,16739229,7306743,14053330,3516499,12035359,14703919,3963096,42662,14100029,8344319,4633680,16229681,3120096,12076434,9083434,2060171,15751837,10182117,48121,62932,16704576,15817653,5083278,5592405];function xt(){const o=Ce.Timer||Ce.Clock;return new o}const me=new d.Box3,z=new d.Box3,ke=new d.Box3,yt=new d.Vector3,Lt=new d.Vector3,wt=new d.Matrix4,q=new d.Vector3,Y=new d.Vector3,Q=new d.Vector3,J=new d.Vector3;function Dt(o,t){const e=o.min,s=o.max,r=(e.x+s.x)*.5,n=(e.y+s.y)*.5;return q.set(r,n,e.z).applyMatrix4(t).z<0}function Fe(o){const{geometry:t,matrixWorld:e,camera:s,projectionScreenMatrix:r,desiredDensity:n,canvasHeight:i=0,currentLevel:l=-1,xrEnabled:a=!1,debugDrawLine:u,warnMissingPrimitiveDensities:h=!1}=o,c=m.getMeshLODExtension(t)?.lods,f=m.getPrimitiveIndex(t),g=o.target??{level:l,primitiveIndex:f,screenCoverage:0,screenspaceVolume:new d.Vector3,centrality:1};g.level=l,g.primitiveIndex=f,g.screenCoverage=0,g.screenspaceVolume.set(0,0,0),g.centrality=1;let M=o.boundingBox??t.boundingBox;if(M||(t.computeBoundingBox(),M=t.boundingBox),!M)return g;if(me.copy(M).applyMatrix4(e),s.isPerspectiveCamera&&Dt(me,r))return g.level=0,g.screenCoverage=1/0,g.screenspaceVolume.set(1/0,1/0,1/0),g;if(z.copy(me).applyMatrix4(r),a&&s.isPerspectiveCamera&&s.fov>70){const y=z.min,S=z.max;let I=y.x,k=y.y,T=S.x,U=S.y;const A=2,O=1.5,x=(y.x+S.x)*.5,v=(y.y+S.y)*.5;I=(I-x)*A+x,k=(k-v)*A+v,T=(T-x)*A+x,U=(U-v)*A+v;const R=I<0&&T>0?0:Math.min(Math.abs(y.x),Math.abs(S.x)),N=k<0&&U>0?0:Math.min(Math.abs(y.y),Math.abs(S.y)),H=Math.max(R,N);g.centrality=(O-H)*(O-H)*(O-H)}const w=z.getSize(yt);w.multiplyScalar(.5),globalThis.screen?.availHeight>0&&i>0&&w.multiplyScalar(i/globalThis.screen.availHeight),s.isPerspectiveCamera&&(w.x*=s.aspect),ke.copy(M).applyMatrix4(e).applyMatrix4(s.matrixWorldInverse);const L=ke.getSize(Lt),D=Math.max(w.x,w.y),_=Math.max(L.x,L.y);D!==0&&_!==0&&(w.z=L.z/_*D);const b=Math.max(w.x,w.y,w.z)*g.centrality;if(g.screenCoverage=b,g.screenspaceVolume.copy(w),b<=0)return g;if(u){const y=wt.copy(r);y.invert(),q.copy(z.min),Y.copy(z.max),Y.x=q.x,Q.copy(z.max),Q.y=q.y,J.copy(z.max);const S=(q.z+J.z)*.5;q.z=Y.z=Q.z=J.z=S,q.applyMatrix4(y),Y.applyMatrix4(y),Q.applyMatrix4(y),J.applyMatrix4(y),u(q,Y,255),u(q,Q,255),u(Y,J,255),u(Q,J,255)}if(c?.length)for(let y=0;y<c.length;y++){const S=c[y],I=S.densities?.[f]||S.density||1e-5;if(f>0&&h&&qe()&&!S.densities&&!globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]&&(globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]=!0,console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")),I/b<n){g.level=y;break}}return g}let ie=class j{static debugDrawLine;static getObjectLODState(t){return t[pe]}static addPlugin(t){W.push(t)}static removePlugin(t){const e=W.indexOf(t);e>=0&&W.splice(e,1)}static getPlugins(){return W}static get(t,e){if(t[ge])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[ge];const s=new j(t,{engine:"unknown",...e});return t[ge]=s,s}renderer;context;projectionScreenMatrix=new d.Matrix4;get plugins(){return W}overrideLodLevel=void 0;targetTriangleDensity=2e5;skinnedMeshAutoUpdateBoundsInterval=30;updateInterval="auto";#e=1;pause=!1;manual=!1;_newPromiseGroups=[];_promiseGroupIds=0;awaitLoading(t){const e=this._promiseGroupIds++,s=new ae(this.#r,{...t});this._newPromiseGroups.push(s);const r=performance.now();return s.ready.finally(()=>{const n=this._newPromiseGroups.indexOf(s);n>=0&&(this._newPromiseGroups.splice(n,1),qe()&&performance.measure("LODsManager:awaitLoading",{start:r,detail:{id:e,name:t?.name,awaited:s.awaitedCount,resolved:s.resolvedCount}}))}),s.ready}trackLoadingPromise(t,e,s){return ae.addPromise(t,e,s,this._newPromiseGroups),s}_postprocessPromiseGroups(){if(this._newPromiseGroups.length!==0)for(let t=this._newPromiseGroups.length-1;t>=0;t--)this._newPromiseGroups[t].update(this.#r)}_lodchangedlisteners=[];addEventListener(t,e){return t==="changed"?(this._lodchangedlisteners.push(e),()=>{this.removeEventListener(t,e)}):()=>{}}removeEventListener(t,e){let s=!1;if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&(this._lodchangedlisteners.splice(r,1),s=!0)}return s}constructor(t,e){this.renderer=t,this.context={...e}}#t;#r=0;#n=0;#i=0;#s=0;#o=xt();_fpsBuffer=[60,60,60,60,60];enable(){if(this.#t)return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;this.#t=this.renderer.render;const e=this;ue(this.renderer),this.renderer.render=function(s,r){const n=e.renderer.getRenderTarget();(n==null||"isXRRenderTarget"in n&&n.isXRRenderTarget)&&(t=0,e.#r+=1,e.#o.update?.(),e.#n=Math.max(e.#o.getDelta(),1/1e3),e.#i+=e.#n,e._fpsBuffer.shift(),e._fpsBuffer.push(1/e.#n),e.#s=e._fpsBuffer.reduce((l,a)=>l+a)/e._fpsBuffer.length,G&&e.#r%200===0&&console.log("FPS",Math.round(e.#s),"Interval:",e.#e));const i=t++;e.#t.call(this,s,r),e.onAfterRender(s,r,i)}}disable(){this.#t&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=this.#t,this.#t=void 0)}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,s){if(this.pause)return;const r=this.getRenderList(t,e,s);if(!r)return;const n=r.opaque;let i=!0;if(n.length===1){const l=n[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(pt||(this.updateInterval==="auto"?this.#s<40&&this.#e<10?(this.#e+=1,G&&console.warn("↓ Reducing LOD updates",this.#e,this.#s.toFixed(0))):this.#s>=60&&this.#e>1&&(this.#e-=1,G&&console.warn("↑ Increasing LOD updates",this.#e,this.#s.toFixed(0))):this.#e=this.updateInterval,this.#e>0&&this.#r%this.#e!=0))return;this.internalUpdate(t,e),this._postprocessPromiseGroups()}}internalUpdate(t,e){const s=this.getRenderList(t,e,0);if(!s)return;const r=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const n=this.targetTriangleDensity;for(const a of r){if(a.material&&(a.geometry?.type==="BoxGeometry"||a.geometry?.type==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){G&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,n)}const i=s.transparent;for(const a of i){const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,n)}const l=s.transmissive;for(const a of l){const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,n)}}getRenderList(t,e,s){const r=this.renderer;let n=null;if(r.isWebGPURenderer===!0){const i=r._renderLists;if(!i)return null;n=i.get(t,e)}else if(r.isWebGLRenderer===!0){const i=r.renderLists;if(!i)return null;n=i.get(t,s)}return n?{opaque:n.opaque||[],transparent:n.transparent||[],transmissive:n.transmissive||n.transparentDoublePass||[],transparentDoublePass:n.transparentDoublePass||[]}:null}updateLODs(t,e,s,r){s.userData||(s.userData={});let n=s[pe];if(n||(n=new vt,s[pe]=n),n.frames++<2)return;for(const l of W)l.onBeforeUpdateLOD?.(this.renderer,t,e,s);const i=this.overrideLodLevel!==void 0?this.overrideLodLevel:X;i>=0?(C.mesh_lod=i,C.texture_lod=i):(this.calculateLodLevel(e,s,n,r,C),C.mesh_lod=Math.round(C.mesh_lod),C.texture_lod=Math.round(C.texture_lod)),C.mesh_lod>=0&&this.loadProgressiveMeshes(s,C.mesh_lod),s.material&&C.texture_lod>=0&&this.loadProgressiveTextures(s.material,C.texture_lod,i),p&&s.material&&!s.isGizmo&&We(s.material),gt&&s.material&&!s.isGizmo&&!s.isBatchedMesh&&Ue(s.material,C.mesh_lod);for(const l of W)l.onAfterUpdatedLOD?.(this.renderer,t,e,s,C);n.lastLodLevel_Mesh=C.mesh_lod,n.lastLodLevel_Texture=C.texture_lod}loadProgressiveTextures(t,e,s){if(!t)return;if(Array.isArray(t)){for(const i of t)this.loadProgressiveTextures(i,e,s);return}let r=!1;(t[V]===void 0||e<t[V])&&(r=!0);const n=s!==void 0&&s>=0;if(n&&(r=t[V]!=s,e=s),r){t[V]=e;const i=n?{force:!0}:void 0,l=m.assignTextureLOD(t,e,i).then(a=>{this._lodchangedlisteners.forEach(u=>u({type:"texture",level:e,object:t}))});ae.addPromise("texture",t,l,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let s=t[V]!==e;const r=t["DEBUG:LOD"];if(r!=null&&(s=t[V]!=r,e=r),s){t[V]=e;const n=t.geometry,i=m.assignMeshLOD(t,e).then(l=>(l&&t[V]==e&&n!=t.geometry&&this._lodchangedlisteners.forEach(a=>a({type:"mesh",level:e,object:t})),l));return ae.addPromise("mesh",t,i,this._newPromiseGroups),i}return Promise.resolve(null)}_sphere=new d.Sphere;_tempWorldPosition=new d.Vector3;static skinnedMeshBoundsFrameOffsetCounter=0;static $skinnedMeshBoundsOffset=Symbol("gltf-progressive-skinnedMeshBoundsOffset");calculateLodLevel(t,e,s,r,n){if(!e){n.mesh_lod=-1,n.texture_lod=-1;return}if(!t){n.mesh_lod=-1,n.texture_lod=-1;return}let l=10+1,a=!1;if(G&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=m.getMeshLODExtension(e.geometry)?.lods,h=m.getPrimitiveIndex(e.geometry),c=u&&u.length>0,f=m.getMaterialMinMaxLODsCount(e.material),g=f.min_count!==1/0&&f.min_count>=0&&f.max_count>=0;if(!c&&!g){n.mesh_lod=0,n.texture_lod=0;return}c||(a=!0,l=0);const M=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let w=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const L=e;if(!L.boundingBox)L.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0){if(!L[j.$skinnedMeshBoundsOffset]){const _=j.skinnedMeshBoundsFrameOffsetCounter++;L[j.$skinnedMeshBoundsOffset]=_}const D=L[j.$skinnedMeshBoundsOffset];if((s.frames+D)%this.skinnedMeshAutoUpdateBoundsInterval===0){const _=ee(L),b=L.geometry;_&&(L.geometry=_),L.computeBoundingBox(),L.geometry=b}}w=L.boundingBox}if(w){if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const _=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(_)){n.mesh_lod=0,n.texture_lod=0;return}}const L=Fe({geometry:e.geometry,matrixWorld:e.matrixWorld,camera:t,projectionScreenMatrix:this.projectionScreenMatrix,desiredDensity:r,canvasHeight:M,currentLevel:s.lastLodLevel_Mesh,boundingBox:w,xrEnabled:this.renderer.xr.enabled,debugDrawLine:G?j.debugDrawLine:void 0,warnMissingPrimitiveDensities:!0});if(s.lastCentrality=L.centrality,s.lastScreenCoverage=L.screenCoverage,s.lastScreenspaceVolume.copy(L.screenspaceVolume),L.screenCoverage===1/0){n.mesh_lod=0,n.texture_lod=0;return}L.level>=0&&L.level<l&&(l=L.level,a=!0)}if(a?n.mesh_lod=l:n.mesh_lod=s.lastLodLevel_Mesh,G&&n.mesh_lod!=s.lastLodLevel_Mesh){const D=u?.[n.mesh_lod];D&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${n.mesh_lod} (density: ${D.densities?.[h].toFixed(0)}) | ${e.name}`)}if(g){const L="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(s.lastLodLevel_Texture<0){if(n.texture_lod=f.max_count-1,G){const D=f.lods[f.max_count-1];G&&console.log(`First Texture LOD ${n.texture_lod} (${D.max_height}px) - ${e.name}`)}}else{const D=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let _=s.lastScreenCoverage*4;this.context?.engine==="model-viewer"&&(_*=1.5);const b=this.renderer.getPixelRatio?.()||globalThis.devicePixelRatio||1,S=M/b*_;let I=!1;for(let k=f.lods.length-1;k>=0;k--){const T=f.lods[k];if(!(L&&T.max_height>=2048)&&!(be()&&T.max_height>4096)&&(T.max_height>S||!I&&k===0)){if(I=!0,n.texture_lod=k,G&&n.texture_lod<s.lastLodLevel_Texture){const U=T.max_height;console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${n.texture_lod} = ${U}px
8
+ Screensize: ${S.toFixed(0)}px, Coverage: ${(100*s.lastScreenCoverage).toFixed(2)}%, Volume ${D.toFixed(1)}
9
+ ${e.name}`)}break}}}}else n.texture_lod=0}};class vt{frames=0;lastLodLevel_Mesh=-1;lastLodLevel_Texture=-1;lastScreenCoverage=0;lastScreenspaceVolume=new d.Vector3;lastCentrality=0}function Ue(o,t){if(!(t<0)){if(Array.isArray(o)){for(const e of o)Ue(e,t);return}"color"in o&&o.color instanceof d.Color&&(o.color.copy(Ve(t,mt)),o.needsUpdate=!0)}}function Ve(o,t){const e=Math.max(0,Math.min(Pe.length-1,Math.floor(o)));return t.setHex(Pe[e])}const Ae=Symbol("NEEDLE_mesh_lod"),le=Symbol("NEEDLE_texture_lod");let xe=null;function ze(){const o=Mt();o&&(o.mapURLs(function(t){return Ie(),t}),Ie(),xe?.disconnect(),xe=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(s=>{s instanceof HTMLElement&&s.tagName.toLowerCase()==="model-viewer"&&Ee(s)})})}),xe.observe(document,{childList:!0,subtree:!0}))}function Mt(){if(typeof customElements>"u")return null;const o=customElements.get("model-viewer");return o||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),ze()}),null)}function Ie(){if(typeof document>"u")return;document.querySelectorAll("model-viewer").forEach(t=>{Ee(t)})}const Ge=new WeakSet;let _t=0;function Ee(o){if(!o||Ge.has(o))return null;Ge.add(o),console.debug("[gltf-progressive] found new model-viewer..."+ ++_t+`
10
+ `,o.getAttribute("src"));let t=null,e=null,s=null;for(let r=o;r!=null;r=Object.getPrototypeOf(r)){const n=Object.getOwnPropertySymbols(r),i=n.find(u=>u.toString()=="Symbol(renderer)"),l=n.find(u=>u.toString()=="Symbol(scene)"),a=n.find(u=>u.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=o[i].threeRenderer),!e&&l!=null&&(e=o[l]),!s&&a!=null&&(s=o[a])}if(t&&e){let r=function(){if(s){let i=0;const l=setInterval(()=>{if(i++>5){clearInterval(l);return}s?.call(o)},300)}};console.debug("[gltf-progressive] setup model-viewer");const n=ie.get(t,{engine:"model-viewer"});return ie.addPlugin(new Tt),n.enable(),n.addEventListener("changed",()=>{s?.call(o)}),o.addEventListener("model-visibility",i=>{i.detail.visible&&s?.call(o)}),o.addEventListener("load",()=>{r()}),()=>{n.disable()}}return null}class Tt{_didWarnAboutMissingUrl=!1;onBeforeUpdateLOD(t,e,s,r){this.tryParseMeshLOD(e,r),this.tryParseTextureLOD(e,r)}getUrl(t){if(!t)return null;let e=t.getAttribute("src");return e||(e=t.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",t),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(t){return t._currentGLTF}tryGetCurrentModelViewer(t){return t.element}tryParseTextureLOD(t,e){if(e[le]==!0)return;e[le]=!0;const s=this.tryGetCurrentGLTF(t),r=this.tryGetCurrentModelViewer(t),n=this.getUrl(r);if(n&&s&&e.material){let i=function(a){if(a[le]==!0)return;a[le]=!0,a.userData&&(a.userData.LOD=-1);const u=Object.keys(a);for(let h=0;h<u.length;h++){const c=u[h],f=a[c];if(f?.isTexture===!0){const g=f.userData?.associations?.textures;if(g==null)continue;const M=s.parser.json.textures[g];if(!M){console.warn("Texture data not found for texture index "+g);continue}if(M?.extensions?.[F]){const w=M.extensions[F];w&&n&&m.registerTexture(n,f,w.lods.length,g,w)}}}};const l=e.material;if(Array.isArray(l))for(const a of l)i(a);else i(l)}}tryParseMeshLOD(t,e){if(e[Ae]==!0)return;e[Ae]=!0;const s=this.tryGetCurrentModelViewer(t),r=this.getUrl(s);if(!r)return;const n=e.userData?.gltfExtensions?.[F];if(n&&r){const i=e.uuid;m.registerMesh(r,i,e,0,n.lods.length,n)}}}function Ot(...o){let t,e,s,r;switch(o.length){case 2:[s,e]=o,r={};break;case 3:[s,e,r]=o;break;case 4:[t,e,s,r]=o;break;default:throw new Error("Invalid arguments")}ue(e),Me(s),Oe(s,{progressive:!0,...r?.hints}),s.register(i=>new m(i));const n=ie.get(e);return r?.enableLODsManager!==!1&&n.enable(),n}ze();if(!nt){const o={gltfProgressive:{useNeedleProgressive:Ot,LODsManager:ie,configureLoader:Oe,getRaycastMesh:ee,useRaycastMeshes:it}};if(!globalThis.Needle)globalThis.Needle=o;else for(const t in o)globalThis.Needle[t]=o[t]}exports.LODsManager=ie;exports.NEEDLE_progressive=m;exports.addDracoAndKTX2Loaders=Me;exports.calculateMeshLODLevel=Fe;exports.configureLoader=Oe;exports.createLoaders=ue;exports.disposeLoaders=He;exports.getLODColor=Ve;exports.getRaycastMesh=ee;exports.setDracoDecoderLocation=$e;exports.setKTX2TranscoderLocation=Be;
@@ -0,0 +1,10 @@
1
+ import{RedFormat as Ye,RedIntegerFormat as Je,RGFormat as Ze,RGIntegerFormat as et,RGBFormat as tt,RGBAFormat as rt,RGBAIntegerFormat as st,BufferGeometry as N,Mesh as z,Box3 as le,Vector3 as C,Sphere as Ce,CompressedTexture as ot,Texture as G,Matrix3 as nt,InterleavedBuffer as it,InterleavedBufferAttribute as at,BufferAttribute as lt,TextureLoader as ut,Matrix4 as Ae,THREE as ct,Color as Ie}from"./three-core.min.js";import{DRACOLoader as dt,KTX2Loader as ht,MeshoptDecoder as gt,GLTFLoader as ge}from"./three-examples.min.js";const ft="";globalThis.GLTF_PROGRESSIVE_VERSION=ft,console.debug("[gltf-progressive] version -");let I="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",V="https://cdn.needle.tools/static/three/0.179.1/basis2/";const mt=I,pt=V;if(typeof window<"u"){const n=new URL(I+"draco_decoder.js");n.searchParams.append("range","true"),fetch(n,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(t=>{console.debug(`Failed to fetch remote Draco decoder from ${I} (offline: ${navigator.onLine})`),I===mt&&Ee("./include/draco/"),V===pt&&$e("./include/ktx2/")}).finally(()=>{pe&&ye()})}const xt=()=>({dracoDecoderPath:I,ktx2TranscoderPath:V});function Ee(n){I=n,R&&R[me]!=I?(console.debug("Updating Draco decoder path to "+n),R[me]=I,R.setDecoderPath(I),R.preload()):console.debug("Setting Draco decoder path to "+n)}function $e(n){V=n,E&&E.transcoderPath!=V?(console.debug("Updating KTX2 transcoder path to "+n),E.setTranscoderPath(V),E.init()):console.debug("Setting KTX2 transcoder path to "+n)}function ue(n){pe=!0;const t=ye();return n?t.ktx2Loader.detectSupport(n):n!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),t}function yt(){pe=!1,R?.dispose(),E?.dispose(),R=void 0,E=void 0}function fe(n){const{dracoLoader:t,ktx2Loader:e,meshoptDecoder:r}=ye();n.dracoLoader||n.setDRACOLoader(t),n.ktx2Loader||n.setKTX2Loader(e),n.meshoptDecoder||n.setMeshoptDecoder(r)}const me=Symbol("dracoDecoderPath");let pe=!0,R,xe,E;function ye(){return R||(R=new dt,R[me]=I,R.setDecoderPath(I),R.preload()),E||(E=new ht,E.setTranscoderPath(V),E.init()),xe||(xe=gt),{dracoLoader:R,ktx2Loader:E,meshoptDecoder:xe}}const ve=new WeakMap;function we(n,t){let e=ve.get(n);e?e=Object.assign(e,t):e=t,ve.set(n,e)}const vt=ge.prototype.load;function wt(...n){const t=ve.get(this);let e=n[0];const r=Lt(e);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 n[0]=e,vt?.call(this,...n)}ge.prototype.load=wt;function Lt(n){try{if(n instanceof URL)return n;const t=globalThis.location?.href;return t?new URL(n,t):new URL(n)}catch{return null}}function Ge(n){return n!=null&&n.data!=null}function Le(n){const t=n.source?.data;return t!=null&&typeof t=="object"?t:null}function bt(n){const t=n.image;return t!=null&&typeof t=="object"?t:null}function be(n){const t=bt(n),e=Le(n);return{width:t?.width||e?.width||0,height:t?.height||e?.height||0}}U("debugprogressive");function U(n){const t=globalThis.location?.href;if(!t)return!1;const e=new URL(t).searchParams.get(n);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Mt(n,t){if(t===void 0||n===void 0||t.startsWith("./")||t.startsWith("http")||t.startsWith("data:")||t.startsWith("blob:"))return t;const e=n.lastIndexOf("/");if(e>=0){const r=n.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}function Me(){if(ee!==void 0)return ee;const n=globalThis.navigator?.userAgent||"";return ee=/iPhone|iPad|iPod|Android|IEMobile/i.test(n),U("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ee),ee}let ee;function Be(){const n=globalThis.location?.href;if(!n)return!1;const t=new URL(n),e=t.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(t.hostname);return t.hostname==="127.0.0.1"||e}class Dt{constructor(t,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,setTimeout(this.tick,0)}maxConcurrent;_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:s}=this._queue.shift();s({use:o=>this.add(r,o)})}}}function _t(n){const t=n.image,e=t?.width??0,r=t?.height??0,s=t?.depth??1,o=Math.floor(Math.log2(Math.max(e,r,s)))+1,i=Tt(n);return e*r*s*i*(1-Math.pow(.25,o))/(1-.25)}function Tt(n){let t=4;const e=n.format;e===Ye||e===Je?t=1:e===Ze||e===et?t=2:e===tt||e===1029?t=3:(e===rt||e===st)&&(t=4);let r=1;const s=n.type;return s===1009||s===1010?r=1:s===1011||s===1012?r=2:s===1013||s===1014||s===1015?r=4:s===1016&&(r=2),t*r}const St=typeof window>"u"&&typeof document>"u",De=Symbol("needle:raycast-mesh");function Q(n){return n?.[De]instanceof N?n[De]:null}function Ot(n,t){if((n.type==="Mesh"||n.type==="SkinnedMesh")&&!Q(n)){const e=Rt(t);e.userData={isRaycastMesh:!0},n[De]=e}}function kt(n=!0){if(n){if(te)return;const t=te=z.prototype.raycast;z.prototype.raycast=function(e,r){const s=this,o=Q(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),t.call(this,e,r),i&&(s.geometry=i)}}else{if(!te)return;z.prototype.raycast=te,te=null}}let te=null;function Rt(n){const t=new N;for(const e in n.attributes)t.setAttribute(e,n.getAttribute(e));return t.setIndex(n.getIndex()),t}const B=new Array,g=U("debugprogressive");let re,H=-1;if(g&&typeof window<"u"){let n=function(){H+=1,H>=t&&(H=-1),console.log(`Toggle LOD level [${H}]`)};window.addEventListener("keyup",e=>{e.key==="p"&&n(),e.key==="w"&&(re=!re,console.log(`Toggle wireframe [${re}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(H=r,console.log(`Set LOD level to [${H}]`))})}function qe(n){if(g&&re!==void 0)if(Array.isArray(n))for(const t of n)qe(t);else n&&"wireframe"in n&&(n.wireframe=re===!0)}const se=new Array;let Pt=0;const Ct=Me()?2:10;function At(n){if(se.length<Ct){const e=se.length;g&&console.warn(`[Worker] Creating new worker #${e}`);const r=Pe.createWorker(n||{});return se.push(r),r}const t=Pt++%se.length;return se[t]}class Pe{constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=r=>{const s=r.data;switch(this._debug&&console.log("[Worker] EVENT",s),s.type){case"loaded-gltf":for(const o of this._running)if(o.url===s.result.url){It(s.result),o.resolve(s.result);const i=o.url;i.startsWith("blob:")&&URL.revokeObjectURL(i)}}},t.onerror=r=>{console.error("[Worker] Error in gltf-progressive worker:",r)},t.postMessage({type:"init"})}worker;static async createWorker(t){const e=new Worker(URL.createObjectURL(new Blob([`import '${new URL("./gltf-progressive.worker-DvoMaVdx.js",import.meta.url).toString()}';`],{type:"text/javascript"})),{type:"module"});return new Pe(e,t)}_running=[];_webglRenderer=null;async load(t,e){const r=xt();let s=e?.renderer;s||(this._webglRenderer??=(async()=>{const{WebGLRenderer:l}=await import("./three-core.min.js").then(a=>a.THREE);return new l})(),s=await this._webglRenderer);const o=ue(s).ktx2Loader.workerConfig;if(t instanceof URL)t=t.toString();else if(t.startsWith("file:"))t=URL.createObjectURL(new Blob([t]));else if(!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")){const l=globalThis.location?.href;l&&(t=new URL(t,l).toString())}const i={type:"load",url:t,dracoDecoderPath:r.dracoDecoderPath,ktx2TranscoderPath:r.ktx2TranscoderPath,ktx2LoaderConfig:o};return this._debug&&console.debug("[Worker] Sending load request",i),this.worker.postMessage(i),new Promise(l=>{this._running.push({url:t.toString(),resolve:l})})}_debug=!1}function It(n){for(const t of n.geometries){const e=t.geometry,r=new N;if(r.name=e.name||"",e.index){const s=e.index;r.setIndex(_e(s))}for(const s in e.attributes){const o=e.attributes[s],i=_e(o);r.setAttribute(s,i)}if(e.morphAttributes)for(const s in e.morphAttributes){const o=e.morphAttributes[s].map(i=>_e(i));r.morphAttributes[s]=o}if(r.morphTargetsRelative=e.morphTargetsRelative??!1,r.boundingBox=new le,r.boundingBox.min=new C(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),r.boundingBox.max=new C(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),r.boundingSphere=new Ce(new C(e.boundingSphere?.center.x,e.boundingSphere?.center.y,e.boundingSphere?.center.z),e.boundingSphere?.radius),e.groups)for(const s of e.groups)r.addGroup(s.start,s.count,s.materialIndex);e.userData&&(r.userData=e.userData),t.geometry=r}for(const t of n.textures){const e=t.texture;let r=null;if(e.isCompressedTexture){const s=e.mipmaps,{width:o,height:i}=be(e);r=new ot(s,o,i,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else r=new G(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 nt(...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 n}function _e(n){let t=n;if("isInterleavedBufferAttribute"in n&&n.isInterleavedBufferAttribute){const e=n.data,r=e.array,s=new it(r,e.stride);t=new at(s,n.itemSize,r.byteOffset,n.normalized),t.offset=n.offset}else"isBufferAttribute"in n&&n.isBufferAttribute&&(t=new lt(n.array,n.itemSize,n.normalized),t.usage=n.usage,t.gpuType=n.gpuType,t.updateRanges=n.updateRanges);return t}const Et=U("gltf-progressive-worker");U("gltf-progressive-reduce-mipmaps");const oe=U("gltf-progressive-gc"),Te=Symbol("needle-progressive-texture"),q="NEEDLE_progressive";class f{get name(){return q}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,s="LODS:minmax",o=t[s];if(o!=null)return o;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[s]=e,e}if(g==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const l=t;for(const a of Object.keys(l.uniforms)){const c=l.uniforms[a].value;c?.isTexture===!0&&i(c,e)}}else if(t.isMaterial)for(const l of Object.keys(t)){const a=t[l];a?.isTexture===!0&&i(a,e)}else g&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[s]=e,e;function i(l,a){const c=r.getAssignedLODInformation(l);if(c){const d=r.lodInfos.get(c.key);if(d&&d.lods){a.min_count=Math.min(a.min_count,d.lods.length),a.max_count=Math.max(a.max_count,d.lods.length);for(let u=0;u<d.lods.length;u++){const p=d.lods[u];p.width&&(a.lods[u]=a.lods[u]||{min_height:1/0,max_height:0},a.lods[u].min_height=Math.min(a.lods[u].min_height,p.height),a.lods[u].max_height=Math.max(a.lods[u].max_height,p.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const o of t)if(this.hasLODLevelAvailable(o,e))return!0;return!1}if(t.isMaterial===!0){for(const o of Object.keys(t)){const i=t[o];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const o of t.children)if(o.isMesh===!0&&this.hasLODLevelAvailable(o,e))return!0}let r,s;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&r?.userData?.LODS){const o=r.userData.LODS;if(s=this.lodInfos.get(o.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e,r){if(!t)return Promise.resolve(null);if(t instanceof z||t.isMesh===!0){const s=t.geometry,o=this.getAssignedLODInformation(s);if(!o)return Promise.resolve(null);for(const l of B)l.onBeforeGetLODMesh?.(t,e);t["LOD:requested level"]=e;const i=()=>t["LOD:requested level"]===e||this.shouldApplyStaleMeshLOD(t,e);return f.getOrLoadLOD(s,e,{isCurrent:i}).then(l=>{if(Array.isArray(l)){const c=o.index||0;l=l[c]}const a=t["LOD:requested level"]===e;return(a||this.shouldApplyStaleMeshLOD(t,e))&&(a&&delete t["LOD:requested level"],l&&s!=l&&(l?.isBufferGeometry?typeof r?.apply=="function"?r.apply(l,e,t):r?.apply!==!1&&(t.geometry=l):g&&console.error("Invalid LOD geometry",l))),l}).catch(l=>(console.error("Error loading mesh LOD",t,l),null))}else g&&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,r){if(!t)return Promise.resolve(null);const s=r?.force===!0;if(t.isMesh===!0){const o=t;if(Array.isArray(o.material)){const i=new Array;for(const l of o.material){const a=this.assignTextureLOD(l,e,r);i.push(a)}return Promise.all(i).then(l=>{const a=new Array;for(const c of l)Array.isArray(c)&&a.push(...c);return a})}else return this.assignTextureLOD(o.material,e,r)}if(t.isMaterial===!0){const o=t,i=[],l=new Array;if(this.trackCurrentMaterialTextureSlots(o),o.uniforms&&(o.isRawShaderMaterial||o.isShaderMaterial===!0)){const a=o;for(const c of Object.keys(a.uniforms)){const d=a.uniforms[c].value;if(d?.isTexture===!0){const u=this.assignTextureLODForSlot(d,e,o,c,s).then(p=>(p&&a.uniforms[c].value!=p&&(a.uniforms[c].value=p,a.uniformsNeedUpdate=!0),p));i.push(u),l.push(c)}}}else for(const a of Object.keys(o)){const c=o[a];if(c?.isTexture===!0){const d=this.assignTextureLODForSlot(c,e,o,a,s);i.push(d),l.push(a)}}return Promise.all(i).then(a=>{const c=new Array;for(let d=0;d<a.length;d++){const u=a[d],p=l[d];u&&u.isTexture===!0?c.push({material:o,slot:p,texture:u,level:e}):c.push({material:o,slot:p,texture:null,level:e})}return c})}if(t instanceof G||t.isTexture===!0){const o=t;return this.assignTextureLODForSlot(o,e,null,null,s)}return Promise.resolve(null)}static set maxConcurrentLoadingTasks(t){f.queue.maxConcurrent=t}static get maxConcurrentLoadingTasks(){return f.queue.maxConcurrent}static assignTextureLODForSlot(t,e,r,s,o){if(t?.isTexture!==!0)return Promise.resolve(null);if(s==="glyphMap")return Promise.resolve(t);const i=this.getAssignedLODInformation(t);if(i&&(i.level===e||!o&&i.level<e))return Promise.resolve(t);if(r&&s){const u=this.getPendingTextureSlotRequest(r,s);if(u&&u.level===e&&u.force===o)return u.promise}const l=r&&s?this.nextTextureSlotRequestId(r,s,e,o):0,a=()=>!r||!s||this.getLatestTextureSlotRequest(r,s)?.id===l,c=()=>a()||this.shouldApplyStaleTextureSlotLOD(r,s,e,o),d=f.getOrLoadLOD(t,e,{isCurrent:c}).then(u=>{if(!a()&&!this.shouldApplyStaleTextureSlotLOD(r,s,e,o))return null;if(Array.isArray(u))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(u?.isTexture===!0){if(u!=t&&r&&s){const p=this.getMaterialTextureSlot(r,s)??t;if(p&&!o){const m=this.getAssignedLODInformation(p);if(m&&m?.level<e)return g==="verbose"&&console.warn("Assigned texture level is already higher: ",m.level,e,r,p,u),null}this.assignTrackedTextureSlot(r,s,u)}return u}else g=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(u=>(console.error("Error loading LOD",t,u),null));return r&&s&&this.setPendingTextureSlotRequest(r,s,e,o,l,d),d}static trackedTextureSlots=new WeakMap;static pendingTextureSlotRequests=new WeakMap;static latestTextureSlotRequests=new WeakMap;static textureSlotRequestId=0;static trackCurrentMaterialTextureSlots(t){if(t.uniforms&&(t.isRawShaderMaterial||t.isShaderMaterial===!0)){const e=t;for(const r of Object.keys(e.uniforms)){const s=e.uniforms[r].value;s?.isTexture===!0&&this.ensureTrackedTextureSlot(t,r,s)}return}for(const e of Object.keys(t)){const r=t[e];r?.isTexture===!0&&this.ensureTrackedTextureSlot(t,e,r)}}static getPendingTextureSlotRequest(t,e){return this.pendingTextureSlotRequests.get(t)?.get(e)}static nextTextureSlotRequestId(t,e,r,s){let o=this.latestTextureSlotRequests.get(t);o||(o=new Map,this.latestTextureSlotRequests.set(t,o));const i=++this.textureSlotRequestId;return o.set(e,{id:i,level:r,force:s}),i}static getLatestTextureSlotRequest(t,e){return this.latestTextureSlotRequests.get(t)?.get(e)}static shouldApplyStaleTextureSlotLOD(t,e,r,s){if(!t||!e)return!1;const o=this.getLatestTextureSlotRequest(t,e),i=this.getMaterialTextureSlot(t,e),l=this.getAssignedLODInformation(i)?.level??1/0;return r>=l?!1:s?o?r>=o.level:!1:!0}static shouldApplyStaleMeshLOD(t,e){const r=t["LOD:requested level"];if(typeof r!="number")return!1;const s=this.getAssignedLODInformation(t.geometry)?.level??1/0;return e<s&&e>=r}static setPendingTextureSlotRequest(t,e,r,s,o,i){let l=this.pendingTextureSlotRequests.get(t);l||(l=new Map,this.pendingTextureSlotRequests.set(t,l));const a={level:r,force:s,id:o,promise:i};l.set(e,a),i.finally(()=>{l.get(e)?.id===o&&l.delete(e)})}static getMaterialTextureSlot(t,e){const r=t.uniforms?.[e];if(r?.value?.isTexture===!0)return r.value;const s=t[e];return s?.isTexture===!0?s:null}static setMaterialTextureSlot(t,e,r){const s=t.uniforms?.[e];if(s?.value?.isTexture===!0){s.value=r,t.uniformsNeedUpdate=!0;return}t[e]=r}static assignTrackedTextureSlot(t,e,r){let s=this.trackedTextureSlots.get(t);s||(s=new Map,this.trackedTextureSlots.set(t,s));const o=this.getMaterialTextureSlot(t,e);let i=s.get(e);!i&&o?i=this.ensureTrackedTextureSlot(t,e,o):i&&o&&i!==o&&(this.releaseTrackedTextureSlot(t,e,i),i=this.ensureTrackedTextureSlot(t,e,o)),!(i===r&&o===r)&&(i&&i!==r&&this.releaseTrackedTextureSlot(t,e,i),i!==r&&(this.trackTextureUsage(r),s.set(e,r)),o!==r&&this.setMaterialTextureSlot(t,e,r))}static ensureTrackedTextureSlot(t,e,r){let s=this.trackedTextureSlots.get(t);s||(s=new Map,this.trackedTextureSlots.set(t,s));const o=s.get(e);return o===r?o:(o&&this.releaseTrackedTextureSlot(t,e,o),this.trackTextureUsage(r),s.set(e,r),r)}static releaseTrackedTextureSlot(t,e,r){const s=this.trackedTextureSlots.get(t);if(s?.get(e)===r&&s.delete(e),this.untrackTextureUsage(r)&&(g||oe)){const o=this.getAssignedLODInformation(r);console.log(`[gltf-progressive] Disposed old texture LOD ${o?.level??"?"} for ${t.name||t.type}.${e}`,r.uuid)}}parser;url;constructor(t){const e=t.options.path;g&&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?.[q];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>(this._isLoadingMesh=!1,r&&f.registerMesh(this.url,e.guid,r,e.lods?.length,0,e),r))):null};afterRoot(t){return g&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,r)=>{if(e?.extensions){const s=e?.extensions[q];if(s){if(!s.lods){g&&console.warn("Texture has no LODs",s);return}let o=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i)?.textures===r&&(o=!0,f.registerTexture(this.url,i,s.lods?.length,r,s));o||this.parser.getDependency("texture",r).then(i=>{i&&f.registerTexture(this.url,i,s.lods?.length,r,s)})}}}),this.parser.json.meshes?.forEach((e,r)=>{if(e?.extensions){const s=e?.extensions[q];if(s&&s.lods){for(const o of this.parser.associations.keys())if(o.isMesh){const i=this.parser.associations.get(o);i?.meshes===r&&f.registerMesh(this.url,s.guid,o,s.lods.length,i.primitives,s)}}}}),null}static registerTexture=(t,e,r,s,o)=>{if(!e){g&&console.error("!! gltf-progressive: Called register texture without texture");return}if(g){const{width:l,height:a}=be(e);console.log(`> gltf-progressive: register texture[${s}] "${e.name||e.uuid}", Current: ${l}x${a}, Max: ${o.lods[0]?.width}x${o.lods[0]?.height}, uuid: ${e.uuid}`,o,e)}e.source&&(e.source[Te]=o);const i=o.guid;f.assignLODInformation(t,e,i,r,s),f.lodInfos.set(i,o),f.lowresCache.set(i,new WeakRef(e))};static registerMesh=(t,e,r,s,o,i)=>{const l=r.geometry;if(!l){g&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),g&&console.log("> Progressive: register mesh "+r.name,{index:o,uuid:r.uuid},i,r),f.assignLODInformation(t,l,e,s,o),f.lodInfos.set(e,i);let a=f.lowresCache.get(e)?.deref();a?a.push(r.geometry):a=[r.geometry],f.lowresCache.set(e,new WeakRef(a)),s>0&&!Q(r)&&Ot(r,l);for(const c of B)c.onRegisteredNewMesh?.(r,i)};static dispose(t){if(t){this.lodInfos.delete(t);const e=this.lowresCache.get(t);if(e){const r=e.deref();if(r){if(r.isTexture){const s=r;this.textureRefCounts.delete(s.uuid),s.dispose()}else if(Array.isArray(r))for(const s of r)s.dispose()}this.lowresCache.delete(t)}for(const[r,s]of this.cache)r.includes(t)&&(this._disposeCacheEntry(s),this.cache.delete(r))}else{this.cacheGeneration++,this.lodInfos.clear();for(const[,e]of this.lowresCache){const r=e.deref();if(r){if(r.isTexture){const s=r;this.textureRefCounts.delete(s.uuid),s.dispose()}else if(Array.isArray(r))for(const s of r)s.dispose()}}this.lowresCache.clear();for(const[,e]of this.cache)this._disposeCacheEntry(e);this.cache.clear(),this.textureRefCounts.clear(),this.trackedTextureSlots=new WeakMap,this.pendingTextureSlotRequests=new WeakMap,this.latestTextureSlotRequests=new WeakMap,this.textureSlotRequestId=0}}static _disposeCacheEntry(t){if(t instanceof WeakRef){const e=t.deref();e&&(e.isTexture&&this.textureRefCounts.delete(e.uuid),e.dispose())}else this.disposedRequests.add(t),t.then(e=>{if(e)if(Array.isArray(e))for(const r of e)r.dispose();else e.isTexture&&this.textureRefCounts.delete(e.uuid),e.dispose()}).catch(()=>{})}static lodInfos=new Map;static cache=new Map;static lowresCache=new Map;static textureRefCounts=new Map;static _resourceRegistry=new FinalizationRegistry(t=>{const e=f.cache.get(t);(g||oe)&&console.debug(`[gltf-progressive] Memory: Resource GC'd
2
+ ${t}`),e instanceof WeakRef&&(e.deref()||(f.cache.delete(t),(g||oe)&&console.log("[gltf-progressive] \u21AA Cache entry deleted (GC)")))});static trackTextureUsage(t){const e=t.uuid,r=this.textureRefCounts.get(e)||0;this.textureRefCounts.set(e,r+1),g==="verbose"&&console.log(`[gltf-progressive] Track texture ${e}, refCount: ${r} \u2192 ${r+1}`)}static untrackTextureUsage(t){const e=t.uuid,r=this.textureRefCounts.get(e);if(!r)return(g==="verbose"||oe)&&o("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)",0),t.dispose(),!0;const s=r-1;if(s<=0)return this.textureRefCounts.delete(e),(g||oe)&&o("[gltf-progressive] Memory: Dispose texture",s),t.dispose(),!0;return this.textureRefCounts.set(e,s),g==="verbose"&&o("[gltf-progressive] Memory: Untrack texture",s),!1;function o(i,l){const{width:a,height:c}=be(t),d=a&&c?`${a}x${c}`:"N/A";let u="N/A";a&&c&&(u=`~${(_t(t)/(1024*1024)).toFixed(2)} MB`),console.log(`${i} \u2014 ${t.name} ${d} (${u}), refCount: ${r} \u2192 ${l}
3
+ ${e}`)}}static workers=[];static cacheGeneration=0;static disposedRequests=new WeakSet;static _workersIndex=0;static async getOrLoadLOD(t,e,r){const s=this.cacheGeneration,o=g=="verbose",i=this.getAssignedLODInformation(t);if(!i)return g&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const l=i?.key;let a;if(t.isTexture===!0){const c=t;c.source&&c.source[Te]&&(a=c.source[Te])}if(a||(a=f.lodInfos.get(l)),!a)g&&console.warn(`Can not load LOD ${e}: no LOD info found for "${l}" ${t.name}`,t.type,f.lodInfos);else{if(e>0){let u=!1;const p=Array.isArray(a.lods);if(p&&e>=a.lods.length?u=!0:p||(u=!0),u){const m=this.lowresCache.get(l);if(m){const M=m.deref();if(M)return M;this.lowresCache.delete(l),g&&console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${l}`)}return null}}const c=Array.isArray(a.lods)?a.lods[e]?.path:a.lods;if(!c)return g&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const d=Mt(i.url,c);if(d.endsWith(".glb")||d.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const u=d+"_"+a.guid,p=await this.tryResolveLODCacheEntry(this.cache.get(u),u,d,t,e,o);if(s!==this.cacheGeneration)return null;if(p.found)return p.value;if(r?.isCurrent?.()===!1)return o&&console.log(`Skipping stale LOD ${e} request before queue: ${d}`),null;const m=await this.queue.slot(d);if(s!==this.cacheGeneration)return null;if(r?.isCurrent?.()===!1)return o&&console.log(`Skipping stale LOD ${e} request after queue: ${d}`),null;const M=await this.tryResolveLODCacheEntry(this.cache.get(u),u,d,t,e,o);if(s!==this.cacheGeneration)return null;if(M.found)return M.value;const h=this.cache.get(u);if(h!==void 0){const D=await this.tryResolveLODCacheEntry(h,u,d,t,e,o);if(s!==this.cacheGeneration)return null;if(D.found)return D.value}if(!m.use)return g&&console.log(`LOD ${e} was aborted: ${d}`),null;const v=a,_=new Promise(async(D,L)=>{if(Et){const w=await(await At({})).load(d);if(w.textures.length>0)for(const x of w.textures){let y=x.texture;return f.assignLODInformation(i.url,y,l,e,void 0),t instanceof G&&(y=this.copySettings(t,y)),y&&(y.guid=v.guid),D(y)}if(w.geometries.length>0){const x=new Array;for(const y of w.geometries){const P=y.geometry;f.assignLODInformation(i.url,P,l,e,y.primitiveIndex),x.push(P)}return D(x)}return D(null)}const b=new ge;fe(b),g&&(await new Promise(w=>setTimeout(w,1e3)),o&&console.warn("Start loading (delayed) "+d,v.guid));let k=d;if(v&&Array.isArray(v.lods)){const w=v.lods[e];w.hash&&(k+="?v="+w.hash)}const O=await b.loadAsync(k).catch(w=>(console.error(`Error loading LOD ${e} from ${d}
4
+ `,w),D(null)));if(!O)return D(null);const K=O.parser;o&&console.log("Loading finished "+d,v.guid);let A=0;if(O.parser.json.textures){let w=!1;for(const x of O.parser.json.textures){if(x?.extensions){const y=x?.extensions[q];if(y?.guid&&y.guid===v.guid){w=!0;break}}A++}if(w){let x=await K.getDependency("texture",A);return x&&f.assignLODInformation(i.url,x,l,e,void 0),o&&console.log('change "'+t.name+'" \u2192 "'+x.name+'"',d,A,x,u),t instanceof G&&(x=this.copySettings(t,x)),x&&(x.guid=v.guid),D(x)}else g&&console.warn("Could not find texture with guid",v.guid,O.parser.json)}if(A=0,O.parser.json.meshes){let w=!1;for(const x of O.parser.json.meshes){if(x?.extensions){const y=x?.extensions[q];if(y?.guid&&y.guid===v.guid){w=!0;break}}A++}if(w){const x=await K.getDependency("mesh",A);if(o&&console.log(`Loaded Mesh "${x.name}"`,d,A,x,u),x.isMesh===!0){const y=x.geometry;return f.assignLODInformation(i.url,y,l,e,0),D(y)}else{const y=new Array;for(let P=0;P<x.children.length;P++){const ie=x.children[P];if(ie.isMesh===!0){const ae=ie.geometry;f.assignLODInformation(i.url,ae,l,e,P),y.push(ae)}}return D(y)}}else g&&console.warn("Could not find mesh with guid",v.guid,O.parser.json)}return D(null)});this.cache.set(u,_),m.use(_);const T=await _;return s!==this.cacheGeneration||this.cache.get(u)!==_?null:(T!=null?T instanceof G?(this.cache.set(u,new WeakRef(T)),f._resourceRegistry.register(T,u)):Array.isArray(T)?this.cache.set(u,Promise.resolve(T)):this.cache.set(u,Promise.resolve(T)):this.cache.set(u,Promise.resolve(null)),T)}else if(t instanceof G){if(r?.isCurrent?.()===!1)return o&&console.log(`Skipping stale texture LOD ${e} request: ${d}`),null;o&&console.log("Load texture from uri: "+d);const u=await new ut().loadAsync(d);return s!==this.cacheGeneration||r?.isCurrent?.()===!1?(u?.dispose(),null):(u?(u.guid=a.guid,u.flipY=!1,u.needsUpdate=!0,u.colorSpace=t.colorSpace,o&&console.log(a,u)):g&&console.warn("failed loading",d),u)}}return null}static async tryResolveLODCacheEntry(t,e,r,s,o,i){if(t===void 0)return{found:!1};if(i&&console.log(`LOD ${o} was already loading/loaded: ${e}`),t instanceof WeakRef){const c=t.deref();if(c){let d=c,u=!1;if(d instanceof G&&s instanceof G?Ge(d.image)||Le(d)?d=this.copySettings(s,d):u=!0:d instanceof N&&s instanceof N&&(d.attributes.position?.array||(u=!0)),!u)return{found:!0,value:d}}return this.cache.delete(e),g&&console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${e}`),{found:!1}}let l=await t.catch(c=>(console.error(`Error loading LOD ${o} from ${r}
5
+ `,c),null));if(this.disposedRequests.has(t))return{found:!0,value:null};let a=!1;return l==null||(l instanceof G&&s instanceof G?Ge(l.image)||Le(l)?l=this.copySettings(s,l):(a=!0,this.cache.delete(e)):l instanceof N&&s instanceof N&&(l.attributes.position?.array||(a=!0,this.cache.delete(e)))),a?{found:!1}:{found:!0,value:l}}static _queue;static get queue(){return this._queue??=new Dt(Me()?20:50,{debug:g!=!1})}static assignLODInformation(t,e,r,s,o){if(!e)return;e.userData||(e.userData={});const i=new $t(t,r,s,o);e.userData.LODS=i,"source"in e&&typeof e.source=="object"&&(e.source.LODS=i)}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?(g==="verbose"&&console.debug(`Copy texture settings
6
+ `,t.uuid,`
7
+ `,e.uuid),e=e.clone(),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e):t}}class $t{url;key;level;index;constructor(t,e,r,s){this.url=t,this.key=e,this.level=r,s!=null&&(this.index=s)}}class ce{static addPromise=(t,e,r,s)=>{s.forEach(o=>{o.add(t,e,r)})};ready;get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}_resolve;_signal;_frame_start;_frames_to_capture;_resolved=!1;_addedCount=0;_resolvedCount=0;_awaiting=[];_maxPromisesPerObject=1;constructor(t,e){const r=Math.max(e.frames??2,2);this._frame_start=e.waitForFirstCapture?void 0:t,this._frames_to_capture=r,this.ready=new Promise(s=>{this._resolve=s}),this.ready.finally(()=>{this._resolved=!0,this._awaiting.length=0}),this._signal=e.signal,this._signal?.addEventListener("abort",()=>{this.resolveNow()}),this._maxPromisesPerObject=Math.max(1,e.maxPromisesPerObject??1)}_currentFrame=0;update(t){this._currentFrame=t,this._frame_start===void 0&&this._addedCount>0&&(this._frame_start=t),(this._signal?.aborted||this._awaiting.length===0&&this._frame_start!==void 0&&t>this._frame_start+this._frames_to_capture)&&this.resolveNow()}_seen=new WeakMap;add(t,e,r){if(this._resolved){g&&console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}if(!(this._frame_start!==void 0&&this._currentFrame>this._frame_start+this._frames_to_capture)){if(this._maxPromisesPerObject>=1)if(this._seen.has(e)){const s=this._seen.get(e);if(s>=this._maxPromisesPerObject){g&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(e,s+1)}else this._seen.set(e,1);this._awaiting.push(r),this._addedCount++,r.finally(()=>{this._resolvedCount++,this._awaiting.splice(this._awaiting.indexOf(r),1)})}}resolveNow(){this._resolved||this._resolve?.({awaited_count:this._addedCount,resolved_count:this._resolvedCount,cancelled:this._signal?.aborted??!1})}}const $=U("debugprogressive"),Gt=$==="colors",Bt=U("noprogressive"),Se=Symbol("Needle:LODSManager"),Oe=Symbol("Needle:LODState"),j=Symbol("Needle:CurrentLOD"),We=ct,S={mesh_lod:-1,texture_lod:-1},qt=new Ie,Ue=[3526751,11065402,15978811,15897394,15749691,11032304,4827122,3332036,16739229,7306743,14053330,3516499,12035359,14703919,3963096,42662,14100029,8344319,4633680,16229681,3120096,12076434,9083434,2060171,15751837,10182117,48121,62932,16704576,15817653,5083278,5592405];function Wt(){const n=We.Timer||We.Clock;return new n}const ke=new le,F=new le,je=new le,Ut=new C,jt=new C,Ft=new Ae,W=new C,Y=new C,J=new C,Z=new C;function Nt(n,t){const e=n.min,r=n.max,s=(e.x+r.x)*.5,o=(e.y+r.y)*.5;return W.set(s,o,e.z).applyMatrix4(t).z<0}function Fe(n){const{geometry:t,matrixWorld:e,camera:r,projectionScreenMatrix:s,desiredDensity:o,canvasHeight:i=0,currentLevel:l=-1,xrEnabled:a=!1,debugDrawLine:c,warnMissingPrimitiveDensities:d=!1}=n,u=f.getMeshLODExtension(t)?.lods,p=f.getPrimitiveIndex(t),m=n.target??{level:l,primitiveIndex:p,screenCoverage:0,screenspaceVolume:new C,centrality:1};m.level=l,m.primitiveIndex=p,m.screenCoverage=0,m.screenspaceVolume.set(0,0,0),m.centrality=1;let M=n.boundingBox??t.boundingBox;if(M||(t.computeBoundingBox(),M=t.boundingBox),!M)return m;if(ke.copy(M).applyMatrix4(e),r.isPerspectiveCamera&&Nt(ke,s))return m.level=0,m.screenCoverage=1/0,m.screenspaceVolume.set(1/0,1/0,1/0),m;if(F.copy(ke).applyMatrix4(s),a&&r.isPerspectiveCamera&&r.fov>70){const L=F.min,b=F.max;let k=L.x,O=L.y,K=b.x,A=b.y;const w=2,x=1.5,y=(L.x+b.x)*.5,P=(L.y+b.y)*.5;k=(k-y)*w+y,O=(O-P)*w+P,K=(K-y)*w+y,A=(A-P)*w+P;const ie=k<0&&K>0?0:Math.min(Math.abs(L.x),Math.abs(b.x)),ae=O<0&&A>0?0:Math.min(Math.abs(L.y),Math.abs(b.y)),he=Math.max(ie,ae);m.centrality=(x-he)*(x-he)*(x-he)}const h=F.getSize(Ut);h.multiplyScalar(.5),globalThis.screen?.availHeight>0&&i>0&&h.multiplyScalar(i/globalThis.screen.availHeight),r.isPerspectiveCamera&&(h.x*=r.aspect),je.copy(M).applyMatrix4(e).applyMatrix4(r.matrixWorldInverse);const v=je.getSize(jt),_=Math.max(h.x,h.y),T=Math.max(v.x,v.y);_!==0&&T!==0&&(h.z=v.z/T*_);const D=Math.max(h.x,h.y,h.z)*m.centrality;if(m.screenCoverage=D,m.screenspaceVolume.copy(h),D<=0)return m;if(c){const L=Ft.copy(s);L.invert(),W.copy(F.min),Y.copy(F.max),Y.x=W.x,J.copy(F.max),J.y=W.y,Z.copy(F.max);const b=(W.z+Z.z)*.5;W.z=Y.z=J.z=Z.z=b,W.applyMatrix4(L),Y.applyMatrix4(L),J.applyMatrix4(L),Z.applyMatrix4(L),c(W,Y,255),c(W,J,255),c(Y,Z,255),c(J,Z,255)}if(u?.length)for(let L=0;L<u.length;L++){const b=u[L],k=b.densities?.[p]||b.density||1e-5;if(p>0&&d&&Be()&&!b.densities&&!globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]&&(globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]=!0,console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")),k/D<o){m.level=L;break}}return m}let ne=class X{static debugDrawLine;static getObjectLODState(t){return t[Oe]}static addPlugin(t){B.push(t)}static removePlugin(t){const e=B.indexOf(t);e>=0&&B.splice(e,1)}static getPlugins(){return B}static get(t,e){if(t[Se])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[Se];const r=new X(t,{engine:"unknown",...e});return t[Se]=r,r}renderer;context;projectionScreenMatrix=new Ae;get plugins(){return B}overrideLodLevel=void 0;targetTriangleDensity=2e5;skinnedMeshAutoUpdateBoundsInterval=30;updateInterval="auto";#e=1;pause=!1;manual=!1;_newPromiseGroups=[];_promiseGroupIds=0;awaitLoading(t){const e=this._promiseGroupIds++,r=new ce(this.#s,{...t});this._newPromiseGroups.push(r);const s=performance.now();return r.ready.finally(()=>{const o=this._newPromiseGroups.indexOf(r);o>=0&&(this._newPromiseGroups.splice(o,1),Be()&&performance.measure("LODsManager:awaitLoading",{start:s,detail:{id:e,name:t?.name,awaited:r.awaitedCount,resolved:r.resolvedCount}}))}),r.ready}trackLoadingPromise(t,e,r){return ce.addPromise(t,e,r,this._newPromiseGroups),r}_postprocessPromiseGroups(){if(this._newPromiseGroups.length!==0)for(let t=this._newPromiseGroups.length-1;t>=0;t--)this._newPromiseGroups[t].update(this.#s)}_lodchangedlisteners=[];addEventListener(t,e){return t==="changed"?(this._lodchangedlisteners.push(e),()=>{this.removeEventListener(t,e)}):()=>{}}removeEventListener(t,e){let r=!1;if(t==="changed"){const s=this._lodchangedlisteners.indexOf(e);s>=0&&(this._lodchangedlisteners.splice(s,1),r=!0)}return r}constructor(t,e){this.renderer=t,this.context={...e}}#t;#s=0;#o=0;#i=0;#r=0;#n=Wt();_fpsBuffer=[60,60,60,60,60];enable(){if(this.#t)return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;this.#t=this.renderer.render;const e=this;ue(this.renderer),this.renderer.render=function(r,s){const o=e.renderer.getRenderTarget();(o==null||"isXRRenderTarget"in o&&o.isXRRenderTarget)&&(t=0,e.#s+=1,e.#n.update?.(),e.#o=Math.max(e.#n.getDelta(),1/1e3),e.#i+=e.#o,e._fpsBuffer.shift(),e._fpsBuffer.push(1/e.#o),e.#r=e._fpsBuffer.reduce((l,a)=>l+a)/e._fpsBuffer.length,$&&e.#s%200===0&&console.log("FPS",Math.round(e.#r),"Interval:",e.#e));const i=t++;e.#t.call(this,r,s),e.onAfterRender(r,s,i)}}disable(){this.#t&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=this.#t,this.#t=void 0)}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const s=this.getRenderList(t,e,r);if(!s)return;const o=s.opaque;let i=!0;if(o.length===1){const l=o[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(Bt||(this.updateInterval==="auto"?this.#r<40&&this.#e<10?(this.#e+=1,$&&console.warn("\u2193 Reducing LOD updates",this.#e,this.#r.toFixed(0))):this.#r>=60&&this.#e>1&&(this.#e-=1,$&&console.warn("\u2191 Increasing LOD updates",this.#e,this.#r.toFixed(0))):this.#e=this.updateInterval,this.#e>0&&this.#s%this.#e!=0))return;this.internalUpdate(t,e),this._postprocessPromiseGroups()}}internalUpdate(t,e){const r=this.getRenderList(t,e,0);if(!r)return;const s=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const o=this.targetTriangleDensity;for(const a of s){if(a.material&&(a.geometry?.type==="BoxGeometry"||a.geometry?.type==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){$&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const c=a.object;(c instanceof z||c.isMesh)&&this.updateLODs(t,e,c,o)}const i=r.transparent;for(const a of i){const c=a.object;(c instanceof z||c.isMesh)&&this.updateLODs(t,e,c,o)}const l=r.transmissive;for(const a of l){const c=a.object;(c instanceof z||c.isMesh)&&this.updateLODs(t,e,c,o)}}getRenderList(t,e,r){const s=this.renderer;let o=null;if(s.isWebGPURenderer===!0){const i=s._renderLists;if(!i)return null;o=i.get(t,e)}else if(s.isWebGLRenderer===!0){const i=s.renderLists;if(!i)return null;o=i.get(t,r)}return o?{opaque:o.opaque||[],transparent:o.transparent||[],transmissive:o.transmissive||o.transparentDoublePass||[],transparentDoublePass:o.transparentDoublePass||[]}:null}updateLODs(t,e,r,s){r.userData||(r.userData={});let o=r[Oe];if(o||(o=new zt,r[Oe]=o),o.frames++<2)return;for(const l of B)l.onBeforeUpdateLOD?.(this.renderer,t,e,r);const i=this.overrideLodLevel!==void 0?this.overrideLodLevel:H;i>=0?(S.mesh_lod=i,S.texture_lod=i):(this.calculateLodLevel(e,r,o,s,S),S.mesh_lod=Math.round(S.mesh_lod),S.texture_lod=Math.round(S.texture_lod)),S.mesh_lod>=0&&this.loadProgressiveMeshes(r,S.mesh_lod),r.material&&S.texture_lod>=0&&this.loadProgressiveTextures(r.material,S.texture_lod,i),g&&r.material&&!r.isGizmo&&qe(r.material),Gt&&r.material&&!r.isGizmo&&!r.isBatchedMesh&&Ne(r.material,S.mesh_lod);for(const l of B)l.onAfterUpdatedLOD?.(this.renderer,t,e,r,S);o.lastLodLevel_Mesh=S.mesh_lod,o.lastLodLevel_Texture=S.texture_lod}loadProgressiveTextures(t,e,r){if(!t)return;if(Array.isArray(t)){for(const i of t)this.loadProgressiveTextures(i,e,r);return}let s=!1;(t[j]===void 0||e<t[j])&&(s=!0);const o=r!==void 0&&r>=0;if(o&&(s=t[j]!=r,e=r),s){t[j]=e;const i=o?{force:!0}:void 0,l=f.assignTextureLOD(t,e,i).then(a=>{this._lodchangedlisteners.forEach(c=>c({type:"texture",level:e,object:t}))});ce.addPromise("texture",t,l,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[j]!==e;const s=t["DEBUG:LOD"];if(s!=null&&(r=t[j]!=s,e=s),r){t[j]=e;const o=t.geometry,i=f.assignMeshLOD(t,e).then(l=>(l&&t[j]==e&&o!=t.geometry&&this._lodchangedlisteners.forEach(a=>a({type:"mesh",level:e,object:t})),l));return ce.addPromise("mesh",t,i,this._newPromiseGroups),i}return Promise.resolve(null)}_sphere=new Ce;_tempWorldPosition=new C;static skinnedMeshBoundsFrameOffsetCounter=0;static $skinnedMeshBoundsOffset=Symbol("gltf-progressive-skinnedMeshBoundsOffset");calculateLodLevel(t,e,r,s,o){if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let i=10+1,l=!1;if($&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=f.getMeshLODExtension(e.geometry)?.lods,c=f.getPrimitiveIndex(e.geometry),d=a&&a.length>0,u=f.getMaterialMinMaxLODsCount(e.material),p=u.min_count!==1/0&&u.min_count>=0&&u.max_count>=0;if(!d&&!p){o.mesh_lod=0,o.texture_lod=0;return}d||(l=!0,i=0);const m=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let M=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const h=e;if(!h.boundingBox)h.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0){if(!h[X.$skinnedMeshBoundsOffset]){const _=X.skinnedMeshBoundsFrameOffsetCounter++;h[X.$skinnedMeshBoundsOffset]=_}const v=h[X.$skinnedMeshBoundsOffset];if((r.frames+v)%this.skinnedMeshAutoUpdateBoundsInterval===0){const _=Q(h),T=h.geometry;_&&(h.geometry=_),h.computeBoundingBox(),h.geometry=T}}M=h.boundingBox}if(M){if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const v=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(v)){o.mesh_lod=0,o.texture_lod=0;return}}const h=Fe({geometry:e.geometry,matrixWorld:e.matrixWorld,camera:t,projectionScreenMatrix:this.projectionScreenMatrix,desiredDensity:s,canvasHeight:m,currentLevel:r.lastLodLevel_Mesh,boundingBox:M,xrEnabled:this.renderer.xr.enabled,debugDrawLine:$?X.debugDrawLine:void 0,warnMissingPrimitiveDensities:!0});if(r.lastCentrality=h.centrality,r.lastScreenCoverage=h.screenCoverage,r.lastScreenspaceVolume.copy(h.screenspaceVolume),h.screenCoverage===1/0){o.mesh_lod=0,o.texture_lod=0;return}h.level>=0&&h.level<i&&(i=h.level,l=!0)}if(l?o.mesh_lod=i:o.mesh_lod=r.lastLodLevel_Mesh,$&&o.mesh_lod!=r.lastLodLevel_Mesh){const h=a?.[o.mesh_lod];h&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${o.mesh_lod} (density: ${h.densities?.[c].toFixed(0)}) | ${e.name}`)}if(p){const h="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(o.texture_lod=u.max_count-1,$){const v=u.lods[u.max_count-1];$&&console.log(`First Texture LOD ${o.texture_lod} (${v.max_height}px) - ${e.name}`)}}else{const v=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let _=r.lastScreenCoverage*4;this.context?.engine==="model-viewer"&&(_*=1.5);const T=this.renderer.getPixelRatio?.()||globalThis.devicePixelRatio||1,D=m/T*_;let L=!1;for(let b=u.lods.length-1;b>=0;b--){const k=u.lods[b];if(!(h&&k.max_height>=2048)&&!(Me()&&k.max_height>4096)&&(k.max_height>D||!L&&b===0)){if(L=!0,o.texture_lod=b,$&&o.texture_lod<r.lastLodLevel_Texture){const O=k.max_height;console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} = ${O}px
8
+ Screensize: ${D.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${v.toFixed(1)}
9
+ ${e.name}`)}break}}}}else o.texture_lod=0}};class zt{frames=0;lastLodLevel_Mesh=-1;lastLodLevel_Texture=-1;lastScreenCoverage=0;lastScreenspaceVolume=new C;lastCentrality=0}function Ne(n,t){if(!(t<0)){if(Array.isArray(n)){for(const e of n)Ne(e,t);return}"color"in n&&n.color instanceof Ie&&(n.color.copy(ze(t,qt)),n.needsUpdate=!0)}}function ze(n,t){const e=Math.max(0,Math.min(Ue.length-1,Math.floor(n)));return t.setHex(Ue[e])}const Ve=Symbol("NEEDLE_mesh_lod"),de=Symbol("NEEDLE_texture_lod");let Re=null;function He(){const n=Vt();n&&(n.mapURLs(function(t){return Xe(),t}),Xe(),Re?.disconnect(),Re=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Qe(r)})})}),Re.observe(document,{childList:!0,subtree:!0}))}function Vt(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),He()}),null)}function Xe(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(n=>{Qe(n)})}const Ke=new WeakSet;let Ht=0;function Qe(n){if(!n||Ke.has(n))return null;Ke.add(n),console.debug("[gltf-progressive] found new model-viewer..."+ ++Ht+`
10
+ `,n.getAttribute("src"));let t=null,e=null,r=null;for(let s=n;s!=null;s=Object.getPrototypeOf(s)){const o=Object.getOwnPropertySymbols(s),i=o.find(c=>c.toString()=="Symbol(renderer)"),l=o.find(c=>c.toString()=="Symbol(scene)"),a=o.find(c=>c.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=n[i].threeRenderer),!e&&l!=null&&(e=n[l]),!r&&a!=null&&(r=n[a])}if(t&&e){let s=function(){if(r){let i=0;const l=setInterval(()=>{if(i++>5){clearInterval(l);return}r?.call(n)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=ne.get(t,{engine:"model-viewer"});return ne.addPlugin(new Xt),o.enable(),o.addEventListener("changed",()=>{r?.call(n)}),n.addEventListener("model-visibility",i=>{i.detail.visible&&r?.call(n)}),n.addEventListener("load",()=>{s()}),()=>{o.disable()}}return null}class Xt{_didWarnAboutMissingUrl=!1;onBeforeUpdateLOD(t,e,r,s){this.tryParseMeshLOD(e,s),this.tryParseTextureLOD(e,s)}getUrl(t){if(!t)return null;let e=t.getAttribute("src");return e||(e=t.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",t),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(t){return t._currentGLTF}tryGetCurrentModelViewer(t){return t.element}tryParseTextureLOD(t,e){if(e[de]==!0)return;e[de]=!0;const r=this.tryGetCurrentGLTF(t),s=this.tryGetCurrentModelViewer(t),o=this.getUrl(s);if(o&&r&&e.material){let i=function(a){if(a[de]==!0)return;a[de]=!0,a.userData&&(a.userData.LOD=-1);const c=Object.keys(a);for(let d=0;d<c.length;d++){const u=c[d],p=a[u];if(p?.isTexture===!0){const m=p.userData?.associations?.textures;if(m==null)continue;const M=r.parser.json.textures[m];if(!M){console.warn("Texture data not found for texture index "+m);continue}if(M?.extensions?.[q]){const h=M.extensions[q];h&&o&&f.registerTexture(o,p,h.lods.length,m,h)}}}};const l=e.material;if(Array.isArray(l))for(const a of l)i(a);else i(l)}}tryParseMeshLOD(t,e){if(e[Ve]==!0)return;e[Ve]=!0;const r=this.tryGetCurrentModelViewer(t),s=this.getUrl(r);if(!s)return;const o=e.userData?.gltfExtensions?.[q];if(o&&s){const i=e.uuid;f.registerMesh(s,i,e,0,o.lods.length,o)}}}function Kt(...n){let t,e,r,s;switch(n.length){case 2:[r,e]=n,s={};break;case 3:[r,e,s]=n;break;case 4:[t,e,r,s]=n;break;default:throw new Error("Invalid arguments")}ue(e),fe(r),we(r,{progressive:!0,...s?.hints}),r.register(i=>new f(i));const o=ne.get(e);return s?.enableLODsManager!==!1&&o.enable(),o}if(He(),!St){const n={gltfProgressive:{useNeedleProgressive:Kt,LODsManager:ne,configureLoader:we,getRaycastMesh:Q,useRaycastMeshes:kt}};if(!globalThis.Needle)globalThis.Needle=n;else for(const t in n)globalThis.Needle[t]=n[t]}export{ne as LODsManager,f as NEEDLE_progressive,fe as addDracoAndKTX2Loaders,Fe as calculateMeshLODLevel,we as configureLoader,ue as createLoaders,yt as disposeLoaders,ze as getLODColor,Q as getRaycastMesh,Ee as setDracoDecoderLocation,$e as setKTX2TranscoderLocation};