@needle-tools/gltf-progressive 3.1.0 → 3.1.1-next.1039397

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.
@@ -1,8 +1,8 @@
1
- var Qe=Object.defineProperty,Ye=(t,e,s)=>e in t?Qe(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s,u=(t,e,s)=>(Ye(t,typeof e!="symbol"?e+"":e,s),s),Ee=(t,e,s)=>{if(!e.has(t))throw TypeError("Cannot "+s)},y=(t,e,s)=>(Ee(t,e,"read from private field"),s?s.call(t):e.get(t)),Y=(t,e,s)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,s)},U=(t,e,s,n)=>(Ee(t,e,"write to private field"),n?n.call(t,s):e.set(t,s),s);import{BufferGeometry as ue,Mesh as Z,Texture as se,TextureLoader as Ze,Matrix4 as Ce,Clock as Je,MeshStandardMaterial as et,Sphere as tt,Box3 as ke,Vector3 as W}from"three";import{GLTFLoader as xe}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as st}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as rt}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as nt}from"three/examples/jsm/loaders/KTX2Loader.js";const Be="";globalThis.GLTF_PROGRESSIVE_VERSION=Be,console.debug("[gltf-progressive] version -");let N="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",ee="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const ot=N,it=ee,Ie=new URL(N+"draco_decoder.js");Ie.searchParams.append("range","true"),fetch(Ie,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(t=>{console.debug(`Failed to fetch remote Draco decoder from ${N} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),N===ot&&Ge("./include/draco/"),ee===it&&Re("./include/ktx2/")}).finally(()=>{$e()});function Ge(t){N=t,I&&I[_e]!=N?(console.debug("Updating Draco decoder path to "+t),I[_e]=N,I.setDecoderPath(N),I.preload()):console.debug("Setting Draco decoder path to "+t)}function Re(t){ee=t,R&&R.transcoderPath!=ee?(console.debug("Updating KTX2 transcoder path to "+t),R.setTranscoderPath(ee),R.init()):console.debug("Setting KTX2 transcoder path to "+t)}const _e=Symbol("dracoDecoderPath");let I,de,R;function $e(){I||(I=new rt,I[_e]=N,I.setDecoderPath(N),I.setDecoderConfig({type:"js"}),I.preload()),R||(R=new nt,R.setTranscoderPath(ee),R.init()),de||(de=st)}function Le(t){return $e(),t?R.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:I,ktx2Loader:R,meshoptDecoder:de}}function we(t){t.dracoLoader||t.setDRACOLoader(I),t.ktx2Loader||t.setKTX2Loader(R),t.meshoptDecoder||t.setMeshoptDecoder(de)}const Me=new WeakMap;function be(t,e){let s=Me.get(t);s?s=Object.assign(s,e):s=e,Me.set(t,s)}const je=xe.prototype.load;function at(...t){const e=Me.get(this);let s=t[0];const n=new URL(s,window.location.href);if(n.hostname.endsWith("needle.tools")){const r=e?.progressive!==void 0?e.progressive:!0,o=e!=null&&e.usecase?e.usecase:"default";r?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${o}`:this.requestHeader.Accept=`*/*;usecase=${o}`,s=n.toString()}return t[0]=s,je?.call(this,...t)}xe.prototype.load=at,re("debugprogressive");function re(t){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function lt(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const s=t.lastIndexOf("/");if(s>=0){const n=t.substring(0,s+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let ce;function ut(){return ce!==void 0||(ce=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),re("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ce)),ce}function dt(){if(typeof window>"u")return!1;const t=new URL(window.location.href),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 ct{constructor(e=100,s={}){u(this,"_running",new Map),u(this,"_queue",[]),u(this,"debug",!1),u(this,"tick",()=>{this.internalUpdate(),setTimeout(this.tick,10)}),this.maxConcurrent=e,this.debug=s.debug??!1,window.requestAnimationFrame(this.tick)}slot(e){return this.debug&&console.debug(`[PromiseQueue]: Requesting slot for key ${e}, running: ${this._running.size}, waiting: ${this._queue.length}`),new Promise(s=>{this._queue.push({key:e,resolve:s})})}add(e,s){this._running.has(e)||(this._running.set(e,s),s.finally(()=>{this._running.delete(e),this.debug&&console.debug(`[PromiseQueue]: Promise for key ${e} finished, running: ${this._running.size}, waiting: ${this._queue.length}`)}),this.debug&&console.debug(`[PromiseQueue]: Adding promise for key ${e}, running: ${this._running.size}, waiting: ${this._queue.length}`))}internalUpdate(){const e=this.maxConcurrent-this._running.size;for(let s=0;s<e&&this._queue.length>0;s++){this.debug&&console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);const{key:n,resolve:r}=this._queue.shift();r({use:o=>this.add(n,o)})}}}const ht=typeof window>"u"&&typeof document>"u",De=Symbol("needle:raycast-mesh");function te(t){return t?.[De]instanceof ue?t[De]:null}function Ne(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!te(t)){const s=gt(e);s.userData={isRaycastMesh:!0},t[De]=s}}function Fe(t=!0){if(t){if(ne)return;const e=ne=Z.prototype.raycast;Z.prototype.raycast=function(s,n){const r=this,o=te(r);let i;o&&r.isMesh&&(i=r.geometry,r.geometry=o),e.call(this,s,n),i&&(r.geometry=i)}}else{if(!ne)return;Z.prototype.raycast=ne,ne=null}}let ne=null;function gt(t){const e=new ue;for(const s in t.attributes)e.setAttribute(s,t.getAttribute(s));return e.setIndex(t.getIndex()),e}const q=new Array,m=re("debugprogressive");let he,J=-1;if(m){let t=function(){J+=1,J>=e&&(J=-1),console.log(`Toggle LOD level [${J}]`)},e=6;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(he=!he,console.log(`Toggle wireframe [${he}]`));const n=parseInt(s.key);!isNaN(n)&&n>=0&&(J=n,console.log(`Set LOD level to [${J}]`))})}function Ue(t){if(m)if(Array.isArray(t))for(const e of t)Ue(e);else t&&"wireframe"in t&&(t.wireframe=he===!0)}const F="NEEDLE_progressive",Oe=Symbol("needle-progressive-texture"),M=class{constructor(t,e){u(this,"parser"),u(this,"url"),u(this,"_isLoadingMesh"),u(this,"loadMesh",s=>{var n,r;if(this._isLoadingMesh)return null;const o=(r=(n=this.parser.json.meshes[s])==null?void 0:n.extensions)==null?void 0:r[F];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",s).then(i=>{var l;return this._isLoadingMesh=!1,i&&M.registerMesh(this.url,o.guid,i,(l=o.lods)==null?void 0:l.length,0,o),i})):null}),m&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return F}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){var e;return((e=this.getAssignedLODInformation(t))==null?void 0:e.index)??-1}static getMaterialMinMaxLODsCount(t,e){const s=this,n="LODS:minmax",r=t[n];if(r!=null)return r;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[n]=e,e}if(m==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const l of Object.keys(i.uniforms)){const d=i.uniforms[l].value;d?.isTexture===!0&&o(d,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const l=t[i];l?.isTexture===!0&&o(l,e)}return t[n]=e,e;function o(i,l){const d=s.getAssignedLODInformation(i);if(d){const a=s.lodInfos.get(d.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let g=0;g<a.lods.length;g++){const x=a.lods[g];x.width&&(l.lods[g]=l.lods[g]||{min_height:1/0,max_height:0},l.lods[g].min_height=Math.min(l.lods[g].min_height,x.height),l.lods[g].max_height=Math.max(l.lods[g].max_height,x.height))}}}}}static hasLODLevelAvailable(t,e){var s;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 n,r;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(s=n?.userData)!=null&&s.LODS){const o=n.userData.LODS;if(r=this.lodInfos.get(o.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){var s;if(!t)return Promise.resolve(null);if(t instanceof Z||t.isMesh===!0){const n=t.geometry,r=this.getAssignedLODInformation(n);if(!r)return Promise.resolve(null);for(const o of q)(s=o.onBeforeGetLODMesh)==null||s.call(o,t,e);return t["LOD:requested level"]=e,M.getOrLoadLOD(n,e).then(o=>{if(Array.isArray(o)){const i=r.index||0;o=o[i]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],o&&n!=o&&(o?.isBufferGeometry?t.geometry=o:m&&console.error("Invalid LOD geometry",o))),o}).catch(o=>(console.error("Error loading mesh LOD",t,o),null))}else m&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const s=t;if(Array.isArray(s.material)){const n=new Array;for(const r of s.material){const o=this.assignTextureLOD(r,e);n.push(o)}return Promise.all(n).then(r=>{const o=new Array;for(const i of r)Array.isArray(i)&&o.push(...i);return o})}else return this.assignTextureLOD(s.material,e)}if(t.isMaterial===!0){const s=t,n=[],r=new Array;if(s.uniforms&&(s.isRawShaderMaterial||s.isShaderMaterial===!0)){const o=s;for(const i of Object.keys(o.uniforms)){const l=o.uniforms[i].value;if(l?.isTexture===!0){const d=this.assignTextureLODForSlot(l,e,s,i).then(a=>(a&&o.uniforms[i].value!=a&&(o.uniforms[i].value=a,o.uniformsNeedUpdate=!0),a));n.push(d),r.push(i)}}}else for(const o of Object.keys(s)){const i=s[o];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,s,o);n.push(l),r.push(o)}}return Promise.all(n).then(o=>{const i=new Array;for(let l=0;l<o.length;l++){const d=o[l],a=r[l];d&&d.isTexture===!0?i.push({material:s,slot:a,texture:d,level:e}):i.push({material:s,slot:a,texture:null,level:e})}return i})}if(t instanceof se||t.isTexture===!0){const s=t;return this.assignTextureLODForSlot(s,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,s,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):M.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if(r?.isTexture===!0){if(r!=t&&s&&n){const o=s[n];if(o&&!m){const i=this.getAssignedLODInformation(o);if(i&&i?.level<e)return m==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,s,o,r),null}s[n]=r}return r}else m=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(r=>(console.error("Error loading LOD",t,r),null))}afterRoot(t){var e,s;return m&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,r)=>{var o;if(n!=null&&n.extensions){const i=n?.extensions[F];if(i){if(!i.lods){m&&console.warn("Texture has no LODs",i);return}let l=!1;for(const d of this.parser.associations.keys())if(d.isTexture===!0){const a=this.parser.associations.get(d);a?.textures===r&&(l=!0,M.registerTexture(this.url,d,(o=i.lods)==null?void 0:o.length,r,i))}l||this.parser.getDependency("texture",r).then(d=>{var a;d&&M.registerTexture(this.url,d,(a=i.lods)==null?void 0:a.length,r,i)})}}}),(s=this.parser.json.meshes)==null||s.forEach((n,r)=>{if(n!=null&&n.extensions){const o=n?.extensions[F];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===r&&M.registerMesh(this.url,o.guid,i,o.lods.length,l.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var s,n,r,o;const i=m=="verbose",l=t.userData.LODS;if(!l)return null;const d=l?.key;let a;if(t.isTexture===!0){const g=t;g.source&&g.source[Oe]&&(a=g.source[Oe])}if(a||(a=M.lodInfos.get(d)),a){if(e>0){let p=!1;const L=Array.isArray(a.lods);if(L&&e>=a.lods.length?p=!0:L||(p=!0),p)return this.lowresCache.get(d)}const g=Array.isArray(a.lods)?(s=a.lods[e])==null?void 0:s.path:a.lods;if(!g)return m&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const x=lt(l.url,g);if(x.endsWith(".glb")||x.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const p=x+"_"+a.guid,L=this.previouslyLoaded.get(p);if(L!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let h=await L.catch(T=>(console.error(`Error loading LOD ${e} from ${x}
2
- `,T),null)),v=!1;if(h==null||(h instanceof se&&t instanceof se?(n=h.image)!=null&&n.data||(r=h.source)!=null&&r.data?h=this.copySettings(t,h):(v=!0,this.previouslyLoaded.delete(p)):h instanceof ue&&t instanceof ue&&((o=h.attributes.position)!=null&&o.array||(v=!0,this.previouslyLoaded.delete(p)))),!v)return h}const Q=await this.queue.slot(x);if(!Q.use)return m&&console.log(`LOD ${e} was aborted: ${x}`),null;const w=a,k=new Promise(async(h,v)=>{const T=new xe;we(T),m&&(await new Promise(f=>setTimeout(f,1e3)),i&&console.warn("Start loading (delayed) "+x,w.guid));let G=x;if(w&&Array.isArray(w.lods)){const f=w.lods[e];f.hash&&(G+="?v="+f.hash)}const D=await T.loadAsync(G).catch(f=>(console.error(`Error loading LOD ${e} from ${x}
3
- `,f),h(null)));if(!D)return h(null);const j=D.parser;i&&console.log("Loading finished "+x,w.guid);let O=0;if(D.parser.json.textures){let f=!1;for(const c of D.parser.json.textures){if(c!=null&&c.extensions){const _=c?.extensions[F];if(_!=null&&_.guid&&_.guid===w.guid){f=!0;break}}O++}if(f){let c=await j.getDependency("texture",O);return c&&M.assignLODInformation(l.url,c,d,e,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+c.name+'"',x,O,c,p),t instanceof se&&(c=this.copySettings(t,c)),c&&(c.guid=w.guid),h(c)}else m&&console.warn("Could not find texture with guid",w.guid,D.parser.json)}if(O=0,D.parser.json.meshes){let f=!1;for(const c of D.parser.json.meshes){if(c!=null&&c.extensions){const _=c?.extensions[F];if(_!=null&&_.guid&&_.guid===w.guid){f=!0;break}}O++}if(f){const c=await j.getDependency("mesh",O);if(i&&console.log(`Loaded Mesh "${c.name}"`,x,O,c,p),c.isMesh===!0){const _=c.geometry;return M.assignLODInformation(l.url,_,d,e,0),h(_)}else{const _=new Array;for(let S=0;S<c.children.length;S++){const B=c.children[S];if(B.isMesh===!0){const z=B.geometry;M.assignLODInformation(l.url,z,d,e,S),_.push(z)}}return h(_)}}else m&&console.warn("Could not find mesh with guid",w.guid,D.parser.json)}return h(null)});return this.previouslyLoaded.set(p,k),Q.use(k),await k}else if(t instanceof se){i&&console.log("Load texture from uri: "+x);const p=await new Ze().loadAsync(x);return p?(p.guid=a.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=t.colorSpace,i&&console.log(a,p)):m&&console.warn("failed loading",x),p}}else m&&console.warn(`Can not load LOD ${e}: no LOD info found for "${d}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,s,n,r){if(!e)return;e.userData||(e.userData={});const o=new ft(t,s,n,r);e.userData.LODS=o}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e?(m&&console.warn(`Copy texture settings
1
+ import{BufferGeometry as V,Mesh as N,Box3 as ne,Vector3 as I,Sphere as ve,CompressedTexture as Ne,Texture as j,Matrix3 as je,InterleavedBuffer as Fe,InterleavedBufferAttribute as Ue,BufferAttribute as We,TextureLoader as ze,Matrix4 as Le,Clock as qe,MeshStandardMaterial as Ve}from"three";import{GLTFLoader as ie}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as Xe}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Ke}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as He}from"three/examples/jsm/loaders/KTX2Loader.js";const be="";globalThis.GLTF_PROGRESSIVE_VERSION=be,console.debug("[gltf-progressive] version -");let k="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",F="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ye=k,Qe=F,_e=new URL(k+"draco_decoder.js");_e.searchParams.append("range","true"),fetch(_e,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(i=>{console.debug(`Failed to fetch remote Draco decoder from ${k} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),k===Ye&&De("./include/draco/"),F===Qe&&Me("./include/ktx2/")}).finally(()=>{Oe()});const Je=()=>({dracoDecoderPath:k,ktx2TranscoderPath:F});function De(i){k=i,P&&P[le]!=k?(console.debug("Updating Draco decoder path to "+i),P[le]=k,P.setDecoderPath(k),P.preload()):console.debug("Setting Draco decoder path to "+i)}function Me(i){F=i,C&&C.transcoderPath!=F?(console.debug("Updating KTX2 transcoder path to "+i),C.setTranscoderPath(F),C.init()):console.debug("Setting KTX2 transcoder path to "+i)}function J(i){return Oe(),i?C.detectSupport(i):i!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:P,ktx2Loader:C,meshoptDecoder:Z}}function ae(i){i.dracoLoader||i.setDRACOLoader(P),i.ktx2Loader||i.setKTX2Loader(C),i.meshoptDecoder||i.setMeshoptDecoder(Z)}const le=Symbol("dracoDecoderPath");let P,Z,C;function Oe(){P||(P=new Ke,P[le]=k,P.setDecoderPath(k),P.setDecoderConfig({type:"js"}),P.preload()),C||(C=new He,C.setTranscoderPath(F),C.init()),Z||(Z=Xe)}const ue=new WeakMap;function ce(i,t){let e=ue.get(i);e?e=Object.assign(e,t):e=t,ue.set(i,e)}const Ze=ie.prototype.load;function et(...i){const t=ue.get(this);let e=i[0];const r=new URL(e,window.location.href);if(r.hostname.endsWith("needle.tools")){const o=t?.progressive!==void 0?t.progressive:!0,s=t?.usecase?t.usecase:"default";o?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${s}`:this.requestHeader.Accept=`*/*;usecase=${s}`,e=r.toString()}return i[0]=e,Ze?.call(this,...i)}ie.prototype.load=et,U("debugprogressive");function U(i){if(typeof window>"u")return!1;const t=new URL(window.location.href).searchParams.get(i);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function tt(i,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||i===void 0)return t;const e=i.lastIndexOf("/");if(e>=0){const r=i.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let ee;function Se(){return ee!==void 0||(ee=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),U("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ee)),ee}function Pe(){if(typeof window>"u")return!1;const i=new URL(window.location.href),t=i.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(i.hostname);return i.hostname==="127.0.0.1"||t}class rt{constructor(t=100,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,window.requestAnimationFrame(this.tick)}_running=new Map;_queue=[];debug=!1;tick=()=>{this.internalUpdate(),setTimeout(this.tick,10)};slot(t){return this.debug&&console.debug(`[PromiseQueue]: Requesting slot for key ${t}, running: ${this._running.size}, waiting: ${this._queue.length}`),new Promise(e=>{this._queue.push({key:t,resolve:e})})}add(t,e){this._running.has(t)||(this._running.set(t,e),e.finally(()=>{this._running.delete(t),this.debug&&console.debug(`[PromiseQueue]: Promise finished now running: ${this._running.size}, waiting: ${this._queue.length}. (finished ${t})`)}),this.debug&&console.debug(`[PromiseQueue]: Added new promise, now running: ${this._running.size}, waiting: ${this._queue.length}. (added ${t})`))}internalUpdate(){const t=this.maxConcurrent-this._running.size;for(let e=0;e<t&&this._queue.length>0;e++){this.debug&&console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);const{key:r,resolve:o}=this._queue.shift();o({use:s=>this.add(r,s)})}}}const st=typeof window>"u"&&typeof document>"u",de=Symbol("needle:raycast-mesh");function z(i){return i?.[de]instanceof V?i[de]:null}function Te(i,t){if((i.type==="Mesh"||i.type==="SkinnedMesh")&&!z(i)){const e=ot(t);e.userData={isRaycastMesh:!0},i[de]=e}}function Ae(i=!0){if(i){if(X)return;const t=X=N.prototype.raycast;N.prototype.raycast=function(e,r){const o=this,s=z(o);let n;s&&o.isMesh&&(n=o.geometry,o.geometry=s),t.call(this,e,r),n&&(o.geometry=n)}}else{if(!X)return;N.prototype.raycast=X,X=null}}let X=null;function ot(i){const t=new V;for(const e in i.attributes)t.setAttribute(e,i.getAttribute(e));return t.setIndex(i.getIndex()),t}const R=new Array,h=U("debugprogressive");let te,W=-1;if(h){let i=function(){W+=1,W>=t&&(W=-1),console.log(`Toggle LOD level [${W}]`)},t=6;window.addEventListener("keyup",e=>{e.key==="p"&&i(),e.key==="w"&&(te=!te,console.log(`Toggle wireframe [${te}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(W=r,console.log(`Set LOD level to [${W}]`))})}function Ie(i){if(h)if(Array.isArray(i))for(const t of i)Ie(t);else i&&"wireframe"in i&&(i.wireframe=te===!0)}const K=new Array;let nt=0;const it=Se()?2:10;function at(i){if(K.length<it){const e=K.length;h&&console.warn(`[Worker] Creating new worker #${e}`);const r=ye.createWorker(i||{});return K.push(r),r}const t=nt++%K.length;return K[t]}class ye{constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=r=>{const o=r.data;switch(this._debug&&console.log("[Worker] EVENT",o),o.type){case"loaded-gltf":for(const s of this._running)if(s.url===o.result.url){lt(o.result),s.resolve(o.result);const n=s.url;n.startsWith("blob:")&&URL.revokeObjectURL(n)}}},t.onerror=r=>{console.error("[Worker] Error in gltf-progressive worker:",r)},t.postMessage({type:"init"})}static async createWorker(t){const e=new Worker(new URL("/assets/loader.worker-8olmVOL4.js",import.meta.url),{type:"module"});return new ye(e,t)}_running=[];_webglRenderer=null;async load(t,e){const r=Je();let o=e?.renderer;o||(this._webglRenderer??=(async()=>{const{WebGLRenderer:l}=await import("three");return new l})(),o=await this._webglRenderer);const s=J(o).ktx2Loader.workerConfig;t instanceof URL?t=t.toString():t.startsWith("file:")?t=URL.createObjectURL(new Blob([t])):!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")&&(t=new URL(t,window.location.href).toString());const n={type:"load",url:t,dracoDecoderPath:r.dracoDecoderPath,ktx2TranscoderPath:r.ktx2TranscoderPath,ktx2LoaderConfig:s};return this._debug&&console.debug("[Worker] Sending load request",n),this.worker.postMessage(n),new Promise(l=>{this._running.push({url:t.toString(),resolve:l})})}_debug=!1}function lt(i){for(const t of i.geometries){const e=t.geometry,r=new V;if(r.name=e.name||"",e.index){const o=e.index;r.setIndex(he(o))}for(const o in e.attributes){const s=e.attributes[o],n=he(s);r.setAttribute(o,n)}if(e.morphAttributes)for(const o in e.morphAttributes){const s=e.morphAttributes[o].map(n=>he(n));r.morphAttributes[o]=s}if(r.morphTargetsRelative=e.morphTargetsRelative??!1,r.boundingBox=new ne,r.boundingBox.min=new I(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),r.boundingBox.max=new I(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),r.boundingSphere=new ve(new I(e.boundingSphere?.center.x,e.boundingSphere?.center.y,e.boundingSphere?.center.z),e.boundingSphere?.radius),e.groups)for(const o of e.groups)r.addGroup(o.start,o.count,o.materialIndex);e.userData&&(r.userData=e.userData),t.geometry=r}for(const t of i.textures){const e=t.texture;let r=null;if(e.isCompressedTexture){const o=e.mipmaps,s=e.image?.width||e.source?.data?.width||-1,n=e.image?.height||e.source?.data?.height||-1;r=new Ne(o,s,n,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else r=new j(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 je(...e.matrix.elements);if(!r){console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");continue}t.texture=r}return i}function he(i){let t=i;if("isInterleavedBufferAttribute"in i&&i.isInterleavedBufferAttribute){const e=i.data,r=e.array,o=new Fe(r,e.stride);t=new Ue(o,i.itemSize,r.byteOffset,i.normalized),t.offset=i.offset}else"isBufferAttribute"in i&&i.isBufferAttribute&&(t=new We(i.array,i.itemSize,i.normalized),t.usage=i.usage,t.gpuType=i.gpuType,t.updateRanges=i.updateRanges);return t}const ut=U("gltf-progressive-worker"),ct=U("gltf-progressive-reduce-mipmaps"),ge=Symbol("needle-progressive-texture"),$="NEEDLE_progressive";class g{get name(){return $}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e?.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){return this.getAssignedLODInformation(t)?.index??-1}static getMaterialMinMaxLODsCount(t,e){const r=this,o="LODS:minmax",s=t[o];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const l of t)this.getMaterialMinMaxLODsCount(l,e);return t[o]=e,e}if(h==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const l=t;for(const a of Object.keys(l.uniforms)){const u=l.uniforms[a].value;u?.isTexture===!0&&n(u,e)}}else if(t.isMaterial)for(const l of Object.keys(t)){const a=t[l];a?.isTexture===!0&&n(a,e)}else h&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[o]=e,e;function n(l,a){const u=r.getAssignedLODInformation(l);if(u){const f=r.lodInfos.get(u.key);if(f&&f.lods){a.min_count=Math.min(a.min_count,f.lods.length),a.max_count=Math.max(a.max_count,f.lods.length);for(let w=0;w<f.lods.length;w++){const L=f.lods[w];L.width&&(a.lods[w]=a.lods[w]||{min_height:1/0,max_height:0},a.lods[w].min_height=Math.min(a.lods[w].min_height,L.height),a.lods[w].max_height=Math.max(a.lods[w].max_height,L.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const n=t[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let r,o;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&r?.userData?.LODS){const s=r.userData.LODS;if(o=this.lodInfos.get(s.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){if(!t)return Promise.resolve(null);if(t instanceof N||t.isMesh===!0){const r=t.geometry,o=this.getAssignedLODInformation(r);if(!o)return Promise.resolve(null);for(const s of R)s.onBeforeGetLODMesh?.(t,e);return t["LOD:requested level"]=e,g.getOrLoadLOD(r,e).then(s=>{if(Array.isArray(s)){const n=o.index||0;s=s[n]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],s&&r!=s&&(s?.isBufferGeometry?t.geometry=s:h&&console.error("Invalid LOD geometry",s))),s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else h&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const o=new Array;for(const s of r.material){const n=this.assignTextureLOD(s,e);o.push(n)}return Promise.all(o).then(s=>{const n=new Array;for(const l of s)Array.isArray(l)&&n.push(...l);return n})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,o=[],s=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const n=r;for(const l of Object.keys(n.uniforms)){const a=n.uniforms[l].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,l).then(f=>(f&&n.uniforms[l].value!=f&&(n.uniforms[l].value=f,n.uniformsNeedUpdate=!0),f));o.push(u),s.push(l)}}}else for(const n of Object.keys(r)){const l=r[n];if(l?.isTexture===!0){const a=this.assignTextureLODForSlot(l,e,r,n);o.push(a),s.push(n)}}return Promise.all(o).then(n=>{const l=new Array;for(let a=0;a<n.length;a++){const u=n[a],f=s[a];u&&u.isTexture===!0?l.push({material:r,slot:f,texture:u,level:e}):l.push({material:r,slot:f,texture:null,level:e})}return l})}if(t instanceof j||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,o){return t?.isTexture!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):g.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(s?.isTexture===!0){if(s!=t&&r&&o){const n=r[o];if(n&&!h){const l=this.getAssignedLODInformation(n);if(l&&l?.level<e)return h==="verbose"&&console.warn("Assigned texture level is already higher: ",l.level,e,r,n,s),null}if(ct&&s.mipmaps){const l=s.mipmaps.length;s.mipmaps.length=Math.min(s.mipmaps.length,3),l!==s.mipmaps.length&&h&&console.debug(`Reduced mipmap count from ${l} to ${s.mipmaps.length} for ${s.uuid}: ${s.image?.width}x${s.image?.height}.`)}r[o]=s}return s}else h=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}parser;url;constructor(t,e){h&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}_isLoadingMesh;loadMesh=t=>{if(this._isLoadingMesh)return null;const e=this.parser.json.meshes[t]?.extensions?.[$];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>(this._isLoadingMesh=!1,r&&g.registerMesh(this.url,e.guid,r,e.lods?.length,0,e),r))):null};afterRoot(t){return h&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,r)=>{if(e?.extensions){const o=e?.extensions[$];if(o){if(!o.lods){h&&console.warn("Texture has no LODs",o);return}let s=!1;for(const n of this.parser.associations.keys())n.isTexture===!0&&this.parser.associations.get(n)?.textures===r&&(s=!0,g.registerTexture(this.url,n,o.lods?.length,r,o));s||this.parser.getDependency("texture",r).then(n=>{n&&g.registerTexture(this.url,n,o.lods?.length,r,o)})}}}),this.parser.json.meshes?.forEach((e,r)=>{if(e?.extensions){const o=e?.extensions[$];if(o&&o.lods){for(const s of this.parser.associations.keys())if(s.isMesh){const n=this.parser.associations.get(s);n?.meshes===r&&g.registerMesh(this.url,o.guid,s,o.lods.length,n.primitives,o)}}}}),null}static registerTexture=(t,e,r,o,s)=>{if(!e){h&&console.error("gltf-progressive: Called register texture without texture");return}if(h){const l=e.image?.width||e.source?.data?.width||0,a=e.image?.height||e.source?.data?.height||0;console.log(`> Progressive: register texture[${o}] "${e.name||e.uuid}", Current: ${l}x${a}, Max: ${s.lods[0]?.width}x${s.lods[0]?.height}, uuid: ${e.uuid}`,s,e)}e.source&&(e.source[ge]=s);const n=s.guid;g.assignLODInformation(t,e,n,r,o),g.lodInfos.set(n,s),g.lowresCache.set(n,e)};static registerMesh=(t,e,r,o,s,n)=>{const l=r.geometry;if(!l){h&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),h&&console.log("> Progressive: register mesh "+r.name,{index:s,uuid:r.uuid},n,r),g.assignLODInformation(t,l,e,o,s),g.lodInfos.set(e,n);let a=g.lowresCache.get(e);a?a.push(r.geometry):a=[r.geometry],g.lowresCache.set(e,a),o>0&&!z(r)&&Te(r,l);for(const u of R)u.onRegisteredNewMesh?.(r,n)};static lodInfos=new Map;static previouslyLoaded=new Map;static lowresCache=new Map;static workers=[];static _workersIndex=0;static async getOrLoadLOD(t,e){const r=h=="verbose",o=this.getAssignedLODInformation(t);if(!o)return h&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const s=o?.key;let n;if(t.isTexture===!0){const l=t;l.source&&l.source[ge]&&(n=l.source[ge])}if(n||(n=g.lodInfos.get(s)),n){if(e>0){let u=!1;const f=Array.isArray(n.lods);if(f&&e>=n.lods.length?u=!0:f||(u=!0),u)return this.lowresCache.get(s)}const l=Array.isArray(n.lods)?n.lods[e]?.path:n.lods;if(!l)return h&&!n["missing:uri"]&&(n["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,n)),null;const a=tt(o.url,l);if(a.endsWith(".glb")||a.endsWith(".gltf")){if(!n.guid)return console.warn("missing pointer for glb/gltf texture",n),null;const u=a+"_"+n.guid,f=await this.queue.slot(a),w=this.previouslyLoaded.get(u);if(w!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${u}`);let p=await w.catch(y=>(console.error(`Error loading LOD ${e} from ${a}
2
+ `,y),null)),m=!1;if(p==null||(p instanceof j&&t instanceof j?p.image?.data||p.source?.data?p=this.copySettings(t,p):(m=!0,this.previouslyLoaded.delete(u)):p instanceof V&&t instanceof V&&(p.attributes.position?.array||(m=!0,this.previouslyLoaded.delete(u)))),!m)return p}if(!f.use)return h&&console.log(`LOD ${e} was aborted: ${a}`),null;const L=n,T=new Promise(async(p,m)=>{if(ut){const x=await(await at({})).load(a);if(x.textures.length>0)for(const c of x.textures){let d=c.texture;return g.assignLODInformation(o.url,d,s,e,void 0),t instanceof j&&(d=this.copySettings(t,d)),d&&(d.guid=L.guid),p(d)}if(x.geometries.length>0){const c=new Array;for(const d of x.geometries){const b=d.geometry;g.assignLODInformation(o.url,b,s,e,d.primitiveIndex),c.push(b)}return p(c)}return p(null)}const y=new ie;ae(y),h&&(await new Promise(x=>setTimeout(x,1e3)),r&&console.warn("Start loading (delayed) "+a,L.guid));let A=a;if(L&&Array.isArray(L.lods)){const x=L.lods[e];x.hash&&(A+="?v="+x.hash)}const _=await y.loadAsync(A).catch(x=>(console.error(`Error loading LOD ${e} from ${a}
3
+ `,x),p(null)));if(!_)return p(null);const E=_.parser;r&&console.log("Loading finished "+a,L.guid);let D=0;if(_.parser.json.textures){let x=!1;for(const c of _.parser.json.textures){if(c?.extensions){const d=c?.extensions[$];if(d?.guid&&d.guid===L.guid){x=!0;break}}D++}if(x){let c=await E.getDependency("texture",D);return c&&g.assignLODInformation(o.url,c,s,e,void 0),r&&console.log('change "'+t.name+'" \u2192 "'+c.name+'"',a,D,c,u),t instanceof j&&(c=this.copySettings(t,c)),c&&(c.guid=L.guid),p(c)}else h&&console.warn("Could not find texture with guid",L.guid,_.parser.json)}if(D=0,_.parser.json.meshes){let x=!1;for(const c of _.parser.json.meshes){if(c?.extensions){const d=c?.extensions[$];if(d?.guid&&d.guid===L.guid){x=!0;break}}D++}if(x){const c=await E.getDependency("mesh",D);if(r&&console.log(`Loaded Mesh "${c.name}"`,a,D,c,u),c.isMesh===!0){const d=c.geometry;return g.assignLODInformation(o.url,d,s,e,0),p(d)}else{const d=new Array;for(let b=0;b<c.children.length;b++){const O=c.children[b];if(O.isMesh===!0){const S=O.geometry;g.assignLODInformation(o.url,S,s,e,b),d.push(S)}}return p(d)}}else h&&console.warn("Could not find mesh with guid",L.guid,_.parser.json)}return p(null)});return this.previouslyLoaded.set(u,T),f.use(T),await T}else if(t instanceof j){r&&console.log("Load texture from uri: "+a);const u=await new ze().loadAsync(a);return u?(u.guid=n.guid,u.flipY=!1,u.needsUpdate=!0,u.colorSpace=t.colorSpace,r&&console.log(n,u)):h&&console.warn("failed loading",a),u}}else h&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type);return null}static maxConcurrent=50;static queue=new rt(g.maxConcurrent,{debug:h!=!1});static assignLODInformation(t,e,r,o,s){if(!e)return;e.userData||(e.userData={});const n=new dt(t,r,o,s);e.userData.LODS=n,"source"in e&&typeof e.source=="object"&&(e.source.LODS=n)}static getAssignedLODInformation(t){return t?t.userData?.LODS?t.userData.LODS:"source"in t&&t.source?.LODS?t.source.LODS:null:null}static copySettings(t,e){return e?(h==="verbose"&&console.debug(`Copy texture settings
4
4
  `,t.uuid,`
5
- `,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}};let P=M;u(P,"registerTexture",(t,e,s,n,r)=>{if(m&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,r),!e){m&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Oe]=r);const o=r.guid;M.assignLODInformation(t,e,o,s,n),M.lodInfos.set(o,r),M.lowresCache.set(o,e)}),u(P,"registerMesh",(t,e,s,n,r,o)=>{var i;const l=s.geometry;if(!l){m&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),m&&console.log("> Progressive: register mesh "+s.name,{index:r,uuid:s.uuid},o,s),M.assignLODInformation(t,l,e,n,r),M.lodInfos.set(e,o);let d=M.lowresCache.get(e);d?d.push(s.geometry):d=[s.geometry],M.lowresCache.set(e,d),n>0&&!te(s)&&Ne(s,l);for(const a of q)(i=a.onRegisteredNewMesh)==null||i.call(a,s,o)}),u(P,"lodInfos",new Map),u(P,"previouslyLoaded",new Map),u(P,"lowresCache",new Map),u(P,"queue",new ct(100,{debug:m!=!1}));class ft{constructor(e,s,n,r){u(this,"url"),u(this,"key"),u(this,"level"),u(this,"index"),this.url=e,this.key=s,this.level=n,r!=null&&(this.index=r)}}class ge{constructor(e,s){u(this,"frame_start"),u(this,"frame_capture_end"),u(this,"ready"),u(this,"_resolve"),u(this,"_signal"),u(this,"_resolved",!1),u(this,"_addedCount",0),u(this,"_resolvedCount",0),u(this,"_awaiting",[]),u(this,"_maxPromisesPerObject",1),u(this,"_currentFrame",0),u(this,"_seen",new WeakMap);var n;const r=Math.max(s.frames??2,2);this.frame_start=e,this.frame_capture_end=e+r,this.ready=new Promise(o=>{this._resolve=o}),this.ready.finally(()=>{this._resolved=!0,this._awaiting.length=0}),this._signal=s.signal,(n=this._signal)==null||n.addEventListener("abort",()=>{this.resolveNow()}),this._maxPromisesPerObject=Math.max(1,s.maxPromisesPerObject??1)}get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}update(e){var s;this._currentFrame=e,((s=this._signal)!=null&&s.aborted||this._currentFrame>this.frame_capture_end&&this._awaiting.length===0)&&this.resolveNow()}add(e,s,n){if(this._resolved){m&&console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}if(!(this._currentFrame>this.frame_capture_end)){if(this._maxPromisesPerObject>=1)if(this._seen.has(s)){let r=this._seen.get(s);if(r>=this._maxPromisesPerObject){m&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(s,r+1)}else this._seen.set(s,1);this._awaiting.push(n),this._addedCount++,n.finally(()=>{this._resolvedCount++,this._awaiting.splice(this._awaiting.indexOf(n),1)})}}resolveNow(){var e,s;this._resolved||(s=this._resolve)==null||s.call(this,{awaited_count:this._addedCount,resolved_count:this._resolvedCount,cancelled:((e=this._signal)==null?void 0:e.aborted)??!1})}}u(ge,"addPromise",(t,e,s,n)=>{n.forEach(r=>{r.add(t,e,s)})});const $=re("debugprogressive"),mt=re("noprogressive"),Se=Symbol("Needle:LODSManager"),Pe=Symbol("Needle:LODState"),V=Symbol("Needle:CurrentLOD"),A={mesh_lod:-1,texture_lod:-1};var E,X,Te,K,oe,fe,H;const b=class{constructor(t,e){u(this,"renderer"),u(this,"context"),u(this,"projectionScreenMatrix",new Ce),u(this,"targetTriangleDensity",2e5),u(this,"skinnedMeshAutoUpdateBoundsInterval",30),u(this,"updateInterval","auto"),Y(this,E,1),u(this,"pause",!1),u(this,"manual",!1),u(this,"_newPromiseGroups",[]),u(this,"_promiseGroupIds",0),u(this,"_lodchangedlisteners",[]),Y(this,X,void 0),Y(this,Te,new Je),Y(this,K,0),Y(this,oe,0),Y(this,fe,0),Y(this,H,0),u(this,"_fpsBuffer",[60,60,60,60,60]),u(this,"_sphere",new tt),u(this,"_tempBox",new ke),u(this,"_tempBox2",new ke),u(this,"tempMatrix",new Ce),u(this,"_tempWorldPosition",new W),u(this,"_tempBoxSize",new W),u(this,"_tempBox2Size",new W),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Pe]}static addPlugin(t){q.push(t)}static removePlugin(t){const e=q.indexOf(t);e>=0&&q.splice(e,1)}static get(t,e){if(t[Se])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[Se];const s=new b(t,{engine:"unknown",...e});return t[Se]=s,s}get plugins(){return q}awaitLoading(t){const e=this._promiseGroupIds++,s=new ge(y(this,K),{...t});this._newPromiseGroups.push(s);const n=performance.now();return s.ready.finally(()=>{const r=this._newPromiseGroups.indexOf(s);r>=0&&(this._newPromiseGroups.splice(r,1),dt()&&performance.measure("LODsManager:awaitLoading",{start:n,detail:{id:e,name:t?.name,awaited:s.awaitedCount,resolved:s.resolvedCount}}))}),s.ready}_postprocessPromiseGroups(){if(this._newPromiseGroups.length!==0)for(let t=this._newPromiseGroups.length-1;t>=0;t--)this._newPromiseGroups[t].update(y(this,K))}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const s=this._lodchangedlisteners.indexOf(e);s>=0&&this._lodchangedlisteners.splice(s,1)}}enable(){if(y(this,X))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;U(this,X,this.renderer.render);const e=this;Le(this.renderer),this.renderer.render=function(s,n){const r=e.renderer.getRenderTarget();(r==null||"isXRRenderTarget"in r&&r.isXRRenderTarget)&&(t=0,U(e,K,y(e,K)+1),U(e,oe,y(e,Te).getDelta()),U(e,fe,y(e,fe)+y(e,oe)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/y(e,oe)),U(e,H,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),$&&y(e,K)%200===0&&console.log("FPS",Math.round(y(e,H)),"Interval:",y(e,E)));const o=t++;y(e,X).call(this,s,n),e.onAfterRender(s,n,o)}}disable(){y(this,X)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=y(this,X),U(this,X,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,s){if(this.pause)return;const n=this.renderer.renderLists.get(t,0).opaque;let r=!0;if(n.length===1){const o=n[0].material;(o.name==="EffectMaterial"||o.name==="CopyShader")&&(r=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(r=!1),r){if(mt||(this.updateInterval==="auto"?y(this,H)<40&&y(this,E)<10?(U(this,E,y(this,E)+1),$&&console.warn("\u2193 Reducing LOD updates",y(this,E),y(this,H).toFixed(0))):y(this,H)>=60&&y(this,E)>1&&(U(this,E,y(this,E)-1),$&&console.warn("\u2191 Increasing LOD updates",y(this,E),y(this,H).toFixed(0))):U(this,E,this.updateInterval),y(this,E)>0&&y(this,K)%y(this,E)!=0))return;this.internalUpdate(t,e),this._postprocessPromiseGroups()}}internalUpdate(t,e){var s,n;const r=this.renderer.renderLists.get(t,0),o=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const a of o){if(a.material&&(((s=a.geometry)==null?void 0:s.type)==="BoxGeometry"||((n=a.geometry)==null?void 0:n.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}if($==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const x=Math.random()*16777215,p=new et({color:x});a.object.material=p}const g=a.object;(g instanceof Z||g.isMesh)&&this.updateLODs(t,e,g,i)}const l=r.transparent;for(const a of l){const g=a.object;(g instanceof Z||g.isMesh)&&this.updateLODs(t,e,g,i)}const d=r.transmissive;for(const a of d){const g=a.object;(g instanceof Z||g.isMesh)&&this.updateLODs(t,e,g,i)}}updateLODs(t,e,s,n){var r,o;s.userData||(s.userData={});let i=s[Pe];if(i||(i=new pt,s[Pe]=i),i.frames++<2)return;for(const d of q)(r=d.onBeforeUpdateLOD)==null||r.call(d,this.renderer,t,e,s);const l=b.overrideGlobalLodLevel!==void 0?b.overrideGlobalLodLevel:J;l>=0?(A.mesh_lod=l,A.texture_lod=l):(this.calculateLodLevel(e,s,i,n,A),A.mesh_lod=Math.round(A.mesh_lod),A.texture_lod=Math.round(A.texture_lod)),A.mesh_lod>=0&&this.loadProgressiveMeshes(s,A.mesh_lod),s.material&&A.texture_lod>=0&&this.loadProgressiveTextures(s.material,A.texture_lod),m&&s.material&&!s.isGizmo&&Ue(s.material);for(const d of q)(o=d.onAfterUpdatedLOD)==null||o.call(d,this.renderer,t,e,s,A);i.lastLodLevel_Mesh=A.mesh_lod,i.lastLodLevel_Texture=A.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const r of t)this.loadProgressiveTextures(r,e);return}let s=!1;(t[V]===void 0||e<t[V])&&(s=!0);const n=t["DEBUG:LOD"];if(n!=null&&(s=t[V]!=n,e=n),s){t[V]=e;const r=P.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(i=>i({type:"texture",level:e,object:t}))});ge.addPromise("texture",t,r,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let s=t[V]!==e;const n=t["DEBUG:LOD"];if(n!=null&&(s=t[V]!=n,e=n),s){t[V]=e;const r=t.geometry,o=P.assignMeshLOD(t,e).then(i=>(i&&t[V]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(l=>l({type:"mesh",level:e,object:t})),i));return ge.addPromise("mesh",t,o,this._newPromiseGroups),o}return Promise.resolve(null)}static isInside(t,e){const s=t.min,n=t.max,r=(s.x+n.x)*.5,o=(s.y+n.y)*.5;return this._tempPtInside.set(r,o,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,n,r){var o,i,l;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let d=10+1,a=!1;if($&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const g=(o=P.getMeshLODExtension(e.geometry))==null?void 0:o.lods,x=P.getPrimitiveIndex(e.geometry),p=g&&g.length>0,L=P.getMaterialMinMaxLODsCount(e.material),Q=L?.min_count!=1/0&&L.min_count>0&&L.max_count>0;if(!p&&!Q){r.mesh_lod=0,r.texture_lod=0;return}p||(a=!0,d=0);const w=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let k=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const h=e;if(!h.boundingBox)h.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0){if(!h[b.$skinnedMeshBoundsOffset]){const T=b.skinnedMeshBoundsFrameOffsetCounter++;h[b.$skinnedMeshBoundsOffset]=T}const v=h[b.$skinnedMeshBoundsOffset];if((s.frames+v)%this.skinnedMeshAutoUpdateBoundsInterval===0){const T=te(h),G=h.geometry;T&&(h.geometry=T),h.computeBoundingBox(),h.geometry=G}}k=h.boundingBox}if(k){const h=t;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 f=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(k),this._tempBox.applyMatrix4(e.matrixWorld),h.isPerspectiveCamera&&b.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&h.isPerspectiveCamera&&h.fov>70){const f=this._tempBox.min,c=this._tempBox.max;let _=f.x,S=f.y,B=c.x,z=c.y;const ie=2,ve=1.5,ae=(f.x+c.x)*.5,le=(f.y+c.y)*.5;_=(_-ae)*ie+ae,S=(S-le)*ie+le,B=(B-ae)*ie+ae,z=(z-le)*ie+le;const Ke=_<0&&B>0?0:Math.min(Math.abs(f.x),Math.abs(c.x)),He=S<0&&z>0?0:Math.min(Math.abs(f.y),Math.abs(c.y)),ye=Math.max(Ke,He);s.lastCentrality=(ve-ye)*(ve-ye)*(ve-ye)}else s.lastCentrality=1;const v=this._tempBox.getSize(this._tempBoxSize);v.multiplyScalar(.5),screen.availHeight>0&&w>0&&v.multiplyScalar(w/screen.availHeight),t.isPerspectiveCamera?v.x*=t.aspect:t.isOrthographicCamera;const T=t.matrixWorldInverse,G=this._tempBox2;G.copy(k),G.applyMatrix4(e.matrixWorld),G.applyMatrix4(T);const D=G.getSize(this._tempBox2Size),j=Math.max(D.x,D.y);if(Math.max(v.x,v.y)!=0&&j!=0&&(v.z=D.z/Math.max(D.x,D.y)*Math.max(v.x,v.y)),s.lastScreenCoverage=Math.max(v.x,v.y,v.z),s.lastScreenspaceVolume.copy(v),s.lastScreenCoverage*=s.lastCentrality,$&&b.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const c=b.corner0,_=b.corner1,S=b.corner2,B=b.corner3;c.copy(this._tempBox.min),_.copy(this._tempBox.max),_.x=c.x,S.copy(this._tempBox.max),S.y=c.y,B.copy(this._tempBox.max);const z=(c.z+B.z)*.5;c.z=_.z=S.z=B.z=z,c.applyMatrix4(f),_.applyMatrix4(f),S.applyMatrix4(f),B.applyMatrix4(f),b.debugDrawLine(c,_,255),b.debugDrawLine(c,S,255),b.debugDrawLine(_,B,255),b.debugDrawLine(S,B,255)}let O=999;if(g&&s.lastScreenCoverage>0)for(let f=0;f<g.length;f++){const c=g[f];if((((i=c.densities)==null?void 0:i[x])||c.density||1e-5)/s.lastScreenCoverage<n){O=f;break}}O<d&&(d=O,a=!0)}if(a?r.mesh_lod=d:r.mesh_lod=s.lastLodLevel_Mesh,$&&r.mesh_lod!=s.lastLodLevel_Mesh){const h=g?.[r.mesh_lod];h&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} \u2192 ${r.mesh_lod} (${h.density.toFixed(0)}) - ${e.name}`)}if(Q){const h="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(s.lastLodLevel_Texture<0){if(r.texture_lod=L.max_count-1,$){const v=L.lods[L.max_count-1];$&&console.log(`First Texture LOD ${r.texture_lod} (${v.max_height}px) - ${e.name}`)}}else{const v=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let T=s.lastScreenCoverage*4;((l=this.context)==null?void 0:l.engine)==="model-viewer"&&(T*=1.5);const G=w/window.devicePixelRatio*T;let D=!1;for(let j=L.lods.length-1;j>=0;j--){const O=L.lods[j];if(!(h&&O.max_height>=2048)&&!(ut()&&O.max_height>4096)&&(O.max_height>G||!D&&j===0)){if(D=!0,r.texture_lod=j,r.texture_lod<s.lastLodLevel_Texture){const f=O.max_height;$&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} \u2192 ${r.texture_lod} = ${f}px
6
- Screensize: ${G.toFixed(0)}px, Coverage: ${(100*s.lastScreenCoverage).toFixed(2)}%, Volume ${v.toFixed(1)}
7
- ${e.name}`)}break}}}}else r.texture_lod=0}};let C=b;E=new WeakMap,X=new WeakMap,Te=new WeakMap,K=new WeakMap,oe=new WeakMap,fe=new WeakMap,H=new WeakMap,u(C,"debugDrawLine"),u(C,"overrideGlobalLodLevel"),u(C,"corner0",new W),u(C,"corner1",new W),u(C,"corner2",new W),u(C,"corner3",new W),u(C,"_tempPtInside",new W),u(C,"skinnedMeshBoundsFrameOffsetCounter",0),u(C,"$skinnedMeshBoundsOffset",Symbol("gltf-progressive-skinnedMeshBoundsOffset"));class pt{constructor(){u(this,"frames",0),u(this,"lastLodLevel_Mesh",-1),u(this,"lastLodLevel_Texture",-1),u(this,"lastScreenCoverage",0),u(this,"lastScreenspaceVolume",new W),u(this,"lastCentrality",0)}}const We=Symbol("NEEDLE_mesh_lod"),me=Symbol("NEEDLE_texture_lod");let pe=null;function Ae(){const t=vt();t&&(t.mapURLs(function(e){return ze(),e}),ze(),pe?.disconnect(),pe=new MutationObserver(e=>{e.forEach(s=>{s.addedNodes.forEach(n=>{n instanceof HTMLElement&&n.tagName.toLowerCase()==="model-viewer"&&Ve(n)})})}),pe.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"),Ae()}),null)}function ze(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(t=>{Ve(t)})}const qe=new WeakSet;let yt=0;function Ve(t){if(!t||qe.has(t))return null;qe.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++yt+`
8
- `,t.getAttribute("src"));let e=null,s=null,n=null;for(let r=t;r!=null;r=Object.getPrototypeOf(r)){const o=Object.getOwnPropertySymbols(r),i=o.find(a=>a.toString()=="Symbol(renderer)"),l=o.find(a=>a.toString()=="Symbol(scene)"),d=o.find(a=>a.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!s&&l!=null&&(s=t[l]),!n&&d!=null&&(n=t[d])}if(e&&s){let r=function(){if(n){let i=0,l=setInterval(()=>{if(i++>5){clearInterval(l);return}n?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=C.get(e,{engine:"model-viewer"});return C.addPlugin(new xt),o.enable(),o.addEventListener("changed",()=>{n?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&n?.call(t)}),t.addEventListener("load",()=>{r()}),()=>{o.disable()}}return null}class xt{constructor(){u(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,s,n,r){this.tryParseMeshLOD(s,r),this.tryParseTextureLOD(s,r)}getUrl(e){if(!e)return null;let s=e.getAttribute("src");return s||(s=e.src),s||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),s}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,s){if(s[me]==!0)return;s[me]=!0;const n=this.tryGetCurrentGLTF(e),r=this.tryGetCurrentModelViewer(e),o=this.getUrl(r);if(o&&n&&s.material){let i=function(d){var a,g,x;if(d[me]==!0)return;d[me]=!0,d.userData&&(d.userData.LOD=-1);const p=Object.keys(d);for(let L=0;L<p.length;L++){const Q=p[L],w=d[Q];if(w?.isTexture===!0){const k=(g=(a=w.userData)==null?void 0:a.associations)==null?void 0:g.textures;if(k==null)continue;const h=n.parser.json.textures[k];if(!h){console.warn("Texture data not found for texture index "+k);continue}if((x=h?.extensions)!=null&&x[F]){const v=h.extensions[F];v&&o&&P.registerTexture(o,w,v.lods.length,k,v)}}}};const l=s.material;if(Array.isArray(l))for(const d of l)i(d);else i(l)}}tryParseMeshLOD(e,s){var n,r;if(s[We]==!0)return;s[We]=!0;const o=this.tryGetCurrentModelViewer(e),i=this.getUrl(o);if(!i)return;const l=(r=(n=s.userData)==null?void 0:n.gltfExtensions)==null?void 0:r[F];if(l&&i){const d=s.uuid;P.registerMesh(i,d,s,0,l.lods.length,l)}}}function Xe(t,e,s,n){Le(e),we(s),be(s,{progressive:!0,...n?.hints}),s.register(o=>new P(o,t));const r=C.get(e);return n?.enableLODsManager!==!1&&r.enable(),r}if(Ae(),!ht){const t={gltfProgressive:{useNeedleProgressive:Xe,LODsManager:C,configureLoader:be,getRaycastMesh:te,useRaycastMeshes:Fe}};if(!globalThis.Needle)globalThis.Needle=t;else for(const e in t)globalThis.Needle[e]=t[e]}export{F as EXTENSION_NAME,C as LODsManager,P as NEEDLE_progressive,Be as VERSION,we as addDracoAndKTX2Loaders,be as configureLoader,Le as createLoaders,te as getRaycastMesh,Ae as patchModelViewer,Ne as registerRaycastMesh,Ge as setDracoDecoderLocation,Re as setKTX2TranscoderLocation,Xe as useNeedleProgressive,Fe as useRaycastMeshes};
5
+ `,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 dt{url;key;level;index;constructor(t,e,r,o){this.url=t,this.key=e,this.level=r,o!=null&&(this.index=o)}}class fe{static addPromise=(t,e,r,o)=>{o.forEach(s=>{s.add(t,e,r)})};frame_start;frame_capture_end;ready;_resolve;_signal;get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}_resolved=!1;_addedCount=0;_resolvedCount=0;_awaiting=[];_maxPromisesPerObject=1;constructor(t,e){const r=Math.max(e.frames??2,2);this.frame_start=t,this.frame_capture_end=t+r,this.ready=new Promise(o=>{this._resolve=o}),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._signal?.aborted||this._currentFrame>this.frame_capture_end&&this._awaiting.length===0)&&this.resolveNow()}_seen=new WeakMap;add(t,e,r){if(this._resolved){h&&console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}if(!(this._currentFrame>this.frame_capture_end)){if(this._maxPromisesPerObject>=1)if(this._seen.has(e)){let o=this._seen.get(e);if(o>=this._maxPromisesPerObject){h&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(e,o+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 B=U("debugprogressive"),ht=U("noprogressive"),me=Symbol("Needle:LODSManager"),pe=Symbol("Needle:LODState"),G=Symbol("Needle:CurrentLOD"),M={mesh_lod:-1,texture_lod:-1};class v{static debugDrawLine;static overrideGlobalLodLevel;static getObjectLODState(t){return t[pe]}static addPlugin(t){R.push(t)}static removePlugin(t){const e=R.indexOf(t);e>=0&&R.splice(e,1)}static get(t,e){if(t[me])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[me];const r=new v(t,{engine:"unknown",...e});return t[me]=r,r}renderer;context;projectionScreenMatrix=new Le;get plugins(){return R}targetTriangleDensity=2e5;skinnedMeshAutoUpdateBoundsInterval=30;updateInterval="auto";#e=1;pause=!1;manual=!1;_newPromiseGroups=[];_promiseGroupIds=0;awaitLoading(t){const e=this._promiseGroupIds++,r=new fe(this.#s,{...t});this._newPromiseGroups.push(r);const o=performance.now();return r.ready.finally(()=>{const s=this._newPromiseGroups.indexOf(r);s>=0&&(this._newPromiseGroups.splice(s,1),Pe()&&performance.measure("LODsManager:awaitLoading",{start:o,detail:{id:e,name:t?.name,awaited:r.awaitedCount,resolved:r.resolvedCount}}))}),r.ready}_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){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}constructor(t,e){this.renderer=t,this.context={...e}}#t;#n=new qe;#s=0;#o=0;#i=0;#r=0;_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;J(this.renderer),this.renderer.render=function(r,o){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,e.#s+=1,e.#o=e.#n.getDelta(),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,B&&e.#s%200===0&&console.log("FPS",Math.round(e.#r),"Interval:",e.#e));const n=t++;e.#t.call(this,r,o),e.onAfterRender(r,o,n)}}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 o=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(o.length===1){const n=o[0].material;(n.name==="EffectMaterial"||n.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(ht||(this.updateInterval==="auto"?this.#r<40&&this.#e<10?(this.#e+=1,B&&console.warn("\u2193 Reducing LOD updates",this.#e,this.#r.toFixed(0))):this.#r>=60&&this.#e>1&&(this.#e-=1,B&&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.renderer.renderLists.get(t,0),o=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const s=this.targetTriangleDensity;for(const a of o){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")){B&&(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}if(B==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const f=Math.random()*16777215,w=new Ve({color:f});a.object.material=w}const u=a.object;(u instanceof N||u.isMesh)&&this.updateLODs(t,e,u,s)}const n=r.transparent;for(const a of n){const u=a.object;(u instanceof N||u.isMesh)&&this.updateLODs(t,e,u,s)}const l=r.transmissive;for(const a of l){const u=a.object;(u instanceof N||u.isMesh)&&this.updateLODs(t,e,u,s)}}updateLODs(t,e,r,o){r.userData||(r.userData={});let s=r[pe];if(s||(s=new gt,r[pe]=s),s.frames++<2)return;for(const l of R)l.onBeforeUpdateLOD?.(this.renderer,t,e,r);const n=v.overrideGlobalLodLevel!==void 0?v.overrideGlobalLodLevel:W;n>=0?(M.mesh_lod=n,M.texture_lod=n):(this.calculateLodLevel(e,r,s,o,M),M.mesh_lod=Math.round(M.mesh_lod),M.texture_lod=Math.round(M.texture_lod)),M.mesh_lod>=0&&this.loadProgressiveMeshes(r,M.mesh_lod),r.material&&M.texture_lod>=0&&this.loadProgressiveTextures(r.material,M.texture_lod,n),h&&r.material&&!r.isGizmo&&Ie(r.material);for(const l of R)l.onAfterUpdatedLOD?.(this.renderer,t,e,r,M);s.lastLodLevel_Mesh=M.mesh_lod,s.lastLodLevel_Texture=M.texture_lod}loadProgressiveTextures(t,e,r){if(!t)return;if(Array.isArray(t)){for(const s of t)this.loadProgressiveTextures(s,e);return}let o=!1;if((t[G]===void 0||e<t[G])&&(o=!0),r!==void 0&&r>=0&&(o=t[G]!=r,e=r),o){t[G]=e;const s=g.assignTextureLOD(t,e).then(n=>{this._lodchangedlisteners.forEach(l=>l({type:"texture",level:e,object:t}))});fe.addPromise("texture",t,s,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[G]!==e;const o=t["DEBUG:LOD"];if(o!=null&&(r=t[G]!=o,e=o),r){t[G]=e;const s=t.geometry,n=g.assignMeshLOD(t,e).then(l=>(l&&t[G]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(a=>a({type:"mesh",level:e,object:t})),l));return fe.addPromise("mesh",t,n,this._newPromiseGroups),n}return Promise.resolve(null)}_sphere=new ve;_tempBox=new ne;_tempBox2=new ne;tempMatrix=new Le;_tempWorldPosition=new I;_tempBoxSize=new I;_tempBox2Size=new I;static corner0=new I;static corner1=new I;static corner2=new I;static corner3=new I;static _tempPtInside=new I;static isInside(t,e){const r=t.min,o=t.max,s=(r.x+o.x)*.5,n=(r.y+o.y)*.5;return this._tempPtInside.set(s,n,r.z).applyMatrix4(e).z<0}static skinnedMeshBoundsFrameOffsetCounter=0;static $skinnedMeshBoundsOffset=Symbol("gltf-progressive-skinnedMeshBoundsOffset");calculateLodLevel(t,e,r,o,s){if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let n=11,l=!1;if(B&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=g.getMeshLODExtension(e.geometry)?.lods,u=g.getPrimitiveIndex(e.geometry),f=a&&a.length>0,w=g.getMaterialMinMaxLODsCount(e.material),L=w.min_count!==1/0&&w.min_count>=0&&w.max_count>=0;if(!f&&!L){s.mesh_lod=0,s.texture_lod=0;return}f||(l=!0,n=0);const T=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let p=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const m=e;if(!m.boundingBox)m.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0){if(!m[v.$skinnedMeshBoundsOffset]){const A=v.skinnedMeshBoundsFrameOffsetCounter++;m[v.$skinnedMeshBoundsOffset]=A}const y=m[v.$skinnedMeshBoundsOffset];if((r.frames+y)%this.skinnedMeshAutoUpdateBoundsInterval===0){const A=z(m),_=m.geometry;A&&(m.geometry=A),m.computeBoundingBox(),m.geometry=_}}p=m.boundingBox}if(p){const m=t;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 c=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(c)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(p),this._tempBox.applyMatrix4(e.matrixWorld),m.isPerspectiveCamera&&v.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&m.isPerspectiveCamera&&m.fov>70){const c=this._tempBox.min,d=this._tempBox.max;let b=c.x,O=c.y,S=d.x,q=d.y;const H=2,se=1.5,Y=(c.x+d.x)*.5,Q=(c.y+d.y)*.5;b=(b-Y)*H+Y,O=(O-Q)*H+Q,S=(S-Y)*H+Y,q=(q-Q)*H+Q;const Re=b<0&&S>0?0:Math.min(Math.abs(c.x),Math.abs(d.x)),Ge=O<0&&q>0?0:Math.min(Math.abs(c.y),Math.abs(d.y)),oe=Math.max(Re,Ge);r.lastCentrality=(se-oe)*(se-oe)*(se-oe)}else r.lastCentrality=1;const y=this._tempBox.getSize(this._tempBoxSize);y.multiplyScalar(.5),screen.availHeight>0&&T>0&&y.multiplyScalar(T/screen.availHeight),t.isPerspectiveCamera?y.x*=t.aspect:t.isOrthographicCamera;const A=t.matrixWorldInverse,_=this._tempBox2;_.copy(p),_.applyMatrix4(e.matrixWorld),_.applyMatrix4(A);const E=_.getSize(this._tempBox2Size),D=Math.max(E.x,E.y);if(Math.max(y.x,y.y)!=0&&D!=0&&(y.z=E.z/Math.max(E.x,E.y)*Math.max(y.x,y.y)),r.lastScreenCoverage=Math.max(y.x,y.y,y.z),r.lastScreenspaceVolume.copy(y),r.lastScreenCoverage*=r.lastCentrality,B&&v.debugDrawLine){const c=this.tempMatrix.copy(this.projectionScreenMatrix);c.invert();const d=v.corner0,b=v.corner1,O=v.corner2,S=v.corner3;d.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=d.x,O.copy(this._tempBox.max),O.y=d.y,S.copy(this._tempBox.max);const q=(d.z+S.z)*.5;d.z=b.z=O.z=S.z=q,d.applyMatrix4(c),b.applyMatrix4(c),O.applyMatrix4(c),S.applyMatrix4(c),v.debugDrawLine(d,b,255),v.debugDrawLine(d,O,255),v.debugDrawLine(b,S,255),v.debugDrawLine(O,S,255)}let x=999;if(a&&r.lastScreenCoverage>0)for(let c=0;c<a.length;c++){const d=a[c],b=(d.densities?.[u]||d.density||1e-5)/r.lastScreenCoverage;if(u>0&&Pe()&&!d.densities&&!globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]&&(window["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.")),b<o){x=c;break}}x<n&&(n=x,l=!0)}if(l?s.mesh_lod=n:s.mesh_lod=r.lastLodLevel_Mesh,B&&s.mesh_lod!=r.lastLodLevel_Mesh){const m=a?.[s.mesh_lod];m&&console.debug(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (density: ${m.densities?.[u].toFixed(0)}) | ${e.name}`)}if(L){const m="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=w.max_count-1,B){const y=w.lods[w.max_count-1];B&&console.log(`First Texture LOD ${s.texture_lod} (${y.max_height}px) - ${e.name}`)}}else{const y=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let A=r.lastScreenCoverage*4;this.context?.engine==="model-viewer"&&(A*=1.5);const _=T/window.devicePixelRatio*A;let E=!1;for(let D=w.lods.length-1;D>=0;D--){const x=w.lods[D];if(!(m&&x.max_height>=2048)&&!(Se()&&x.max_height>4096)&&(x.max_height>_||!E&&D===0)){if(E=!0,s.texture_lod=D,B&&s.texture_lod<r.lastLodLevel_Texture){const c=x.max_height;console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${c}px
6
+ Screensize: ${_.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${y.toFixed(1)}
7
+ ${e.name}`)}break}}}}else s.texture_lod=0}}class gt{frames=0;lastLodLevel_Mesh=-1;lastLodLevel_Texture=-1;lastScreenCoverage=0;lastScreenspaceVolume=new I;lastCentrality=0}const Ee=Symbol("NEEDLE_mesh_lod"),re=Symbol("NEEDLE_texture_lod");let xe=null;function we(){const i=ft();i&&(i.mapURLs(function(t){return ke(),t}),ke(),xe?.disconnect(),xe=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Be(r)})})}),xe.observe(document,{childList:!0,subtree:!0}))}function ft(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),we()}),null)}function ke(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(i=>{Be(i)})}const Ce=new WeakSet;let mt=0;function Be(i){if(!i||Ce.has(i))return null;Ce.add(i),console.debug("[gltf-progressive] found new model-viewer..."+ ++mt+`
8
+ `,i.getAttribute("src"));let t=null,e=null,r=null;for(let o=i;o!=null;o=Object.getPrototypeOf(o)){const s=Object.getOwnPropertySymbols(o),n=s.find(u=>u.toString()=="Symbol(renderer)"),l=s.find(u=>u.toString()=="Symbol(scene)"),a=s.find(u=>u.toString()=="Symbol(needsRender)");!t&&n!=null&&(t=i[n].threeRenderer),!e&&l!=null&&(e=i[l]),!r&&a!=null&&(r=i[a])}if(t&&e){let o=function(){if(r){let n=0,l=setInterval(()=>{if(n++>5){clearInterval(l);return}r?.call(i)},300)}};console.debug("[gltf-progressive] setup model-viewer");const s=v.get(t,{engine:"model-viewer"});return v.addPlugin(new pt),s.enable(),s.addEventListener("changed",()=>{r?.call(i)}),i.addEventListener("model-visibility",n=>{n.detail.visible&&r?.call(i)}),i.addEventListener("load",()=>{o()}),()=>{s.disable()}}return null}class pt{_didWarnAboutMissingUrl=!1;onBeforeUpdateLOD(t,e,r,o){this.tryParseMeshLOD(e,o),this.tryParseTextureLOD(e,o)}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[re]==!0)return;e[re]=!0;const r=this.tryGetCurrentGLTF(t),o=this.tryGetCurrentModelViewer(t),s=this.getUrl(o);if(s&&r&&e.material){let n=function(a){if(a[re]==!0)return;a[re]=!0,a.userData&&(a.userData.LOD=-1);const u=Object.keys(a);for(let f=0;f<u.length;f++){const w=u[f],L=a[w];if(L?.isTexture===!0){const T=L.userData?.associations?.textures;if(T==null)continue;const p=r.parser.json.textures[T];if(!p){console.warn("Texture data not found for texture index "+T);continue}if(p?.extensions?.[$]){const m=p.extensions[$];m&&s&&g.registerTexture(s,L,m.lods.length,T,m)}}}};const l=e.material;if(Array.isArray(l))for(const a of l)n(a);else n(l)}}tryParseMeshLOD(t,e){if(e[Ee]==!0)return;e[Ee]=!0;const r=this.tryGetCurrentModelViewer(t),o=this.getUrl(r);if(!o)return;const s=e.userData?.gltfExtensions?.[$];if(s&&o){const n=e.uuid;g.registerMesh(o,n,e,0,s.lods.length,s)}}}function $e(i,t,e,r){J(t),ae(e),ce(e,{progressive:!0,...r?.hints}),e.register(s=>new g(s,i));const o=v.get(t);return r?.enableLODsManager!==!1&&o.enable(),o}if(we(),!st){const i={gltfProgressive:{useNeedleProgressive:$e,LODsManager:v,configureLoader:ce,getRaycastMesh:z,useRaycastMeshes:Ae}};if(!globalThis.Needle)globalThis.Needle=i;else for(const t in i)globalThis.Needle[t]=i[t]}export{$ as EXTENSION_NAME,v as LODsManager,g as NEEDLE_progressive,be as VERSION,ae as addDracoAndKTX2Loaders,ce as configureLoader,J as createLoaders,z as getRaycastMesh,we as patchModelViewer,Te as registerRaycastMesh,De as setDracoDecoderLocation,Me as setKTX2TranscoderLocation,$e as useNeedleProgressive,Ae as useRaycastMeshes};
@@ -1,8 +1,8 @@
1
- "use strict";var je=Object.defineProperty;var He=(o,t,e)=>t in o?je(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e;var u=(o,t,e)=>(He(o,typeof t!="symbol"?t+"":t,e),e),Ee=(o,t,e)=>{if(!t.has(o))throw TypeError("Cannot "+e)};var L=(o,t,e)=>(Ee(o,t,"read from private field"),e?e.call(o):t.get(o)),j=(o,t,e)=>{if(t.has(o))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(o):t.set(o,e)},z=(o,t,e,s)=>(Ee(o,t,"write to private field"),s?s.call(o,e):t.set(o,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("three"),Pe=require("three/examples/jsm/loaders/GLTFLoader.js"),Qe=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Je=require("three/examples/jsm/loaders/DRACOLoader.js"),Ze=require("three/examples/jsm/loaders/KTX2Loader.js"),Re="";globalThis.GLTF_PROGRESSIVE_VERSION=Re;console.debug("[gltf-progressive] version -");let X="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",se="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const et=X,tt=se,Ie=new URL(X+"draco_decoder.js");Ie.searchParams.append("range","true");fetch(Ie,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(o=>{console.debug(`Failed to fetch remote Draco decoder from ${X} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),X===et&&Fe("./include/draco/"),se===tt&&Ne("./include/ktx2/")}).finally(()=>{Ue()});function Fe(o){X=o,I&&I[Oe]!=X?(console.debug("Updating Draco decoder path to "+o),I[Oe]=X,I.setDecoderPath(X),I.preload()):console.debug("Setting Draco decoder path to "+o)}function Ne(o){se=o,U&&U.transcoderPath!=se?(console.debug("Updating KTX2 transcoder path to "+o),U.setTranscoderPath(se),U.init()):console.debug("Setting KTX2 transcoder path to "+o)}const Oe=Symbol("dracoDecoderPath");let I,me,U;function Ue(){I||(I=new Je.DRACOLoader,I[Oe]=X,I.setDecoderPath(X),I.setDecoderConfig({type:"js"}),I.preload()),U||(U=new Ze.KTX2Loader,U.setTranscoderPath(se),U.init()),me||(me=Qe.MeshoptDecoder)}function Te(o){return Ue(),o?U.detectSupport(o):o!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:I,ktx2Loader:U,meshoptDecoder:me}}function Ae(o){o.dracoLoader||o.setDRACOLoader(I),o.ktx2Loader||o.setKTX2Loader(U),o.meshoptDecoder||o.setMeshoptDecoder(me)}const be=new WeakMap;function Ce(o,t){let e=be.get(o);e?e=Object.assign(e,t):e=t,be.set(o,e)}const we=Pe.GLTFLoader.prototype.load;function st(...o){const t=be.get(this);let e=o[0];const s=new URL(e,window.location.href);if(s.hostname.endsWith("needle.tools")){const r=(t==null?void 0:t.progressive)!==void 0?t.progressive:!0,i=t!=null&&t.usecase?t.usecase:"default";r?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${i}`:this.requestHeader.Accept=`*/*;usecase=${i}`,e=s.toString()}return o[0]=e,we==null?void 0:we.call(this,...o)}Pe.GLTFLoader.prototype.load=st;ue("debugprogressive");function ue(o){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(o);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function rt(o,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||o===void 0)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}let oe;function it(){return oe!==void 0||(oe=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ue("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",oe)),oe}function nt(){if(typeof window>"u")return!1;const o=new URL(window.location.href),t=o.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(o.hostname);return o.hostname==="127.0.0.1"||t}class ot{constructor(t=100,e={}){u(this,"_running",new Map);u(this,"_queue",[]);u(this,"debug",!1);u(this,"tick",()=>{this.internalUpdate(),setTimeout(this.tick,10)});this.maxConcurrent=t,this.debug=e.debug??!1,window.requestAnimationFrame(this.tick)}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 for key ${t} finished, running: ${this._running.size}, waiting: ${this._queue.length}`)}),this.debug&&console.debug(`[PromiseQueue]: Adding promise for key ${t}, running: ${this._running.size}, waiting: ${this._queue.length}`))}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:n}=this._queue.shift();n({use:r=>this.add(s,r)})}}}const at=typeof window>"u"&&typeof document>"u",Se=Symbol("needle:raycast-mesh");function ie(o){return(o==null?void 0:o[Se])instanceof y.BufferGeometry?o[Se]:null}function Ve(o,t){if((o.type==="Mesh"||o.type==="SkinnedMesh")&&!ie(o)){const s=lt(t);s.userData={isRaycastMesh:!0},o[Se]=s}}function qe(o=!0){if(o){if(ae)return;const t=ae=y.Mesh.prototype.raycast;y.Mesh.prototype.raycast=function(e,s){const n=this,r=ie(n);let i;r&&n.isMesh&&(i=n.geometry,n.geometry=r),t.call(this,e,s),i&&(n.geometry=i)}}else{if(!ae)return;y.Mesh.prototype.raycast=ae,ae=null}}let ae=null;function lt(o){const t=new y.BufferGeometry;for(const e in o.attributes)t.setAttribute(e,o.getAttribute(e));return t.setIndex(o.getIndex()),t}const Q=new Array,x=ue("debugprogressive");let ge,te=-1;if(x){let o=function(){te+=1,te>=t&&(te=-1),console.log(`Toggle LOD level [${te}]`)},t=6;window.addEventListener("keyup",e=>{e.key==="p"&&o(),e.key==="w"&&(ge=!ge,console.log(`Toggle wireframe [${ge}]`));const s=parseInt(e.key);!isNaN(s)&&s>=0&&(te=s,console.log(`Set LOD level to [${te}]`))})}function ze(o){if(x)if(Array.isArray(o))for(const t of o)ze(t);else o&&"wireframe"in o&&(o.wireframe=ge===!0)}const W="NEEDLE_progressive",Me=Symbol("needle-progressive-texture"),O=class{constructor(t,e){u(this,"parser");u(this,"url");u(this,"_isLoadingMesh");u(this,"loadMesh",t=>{var s,n;if(this._isLoadingMesh)return null;const e=(n=(s=this.parser.json.meshes[t])==null?void 0:s.extensions)==null?void 0:n[W];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>{var i;return this._isLoadingMesh=!1,r&&O.registerMesh(this.url,e.guid,r,(i=e.lods)==null?void 0:i.length,0,e),r})):null});x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return W}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){var s;const e=(s=this.getAssignedLODInformation(t))==null?void 0:s.index;return e??-1}static getMaterialMinMaxLODsCount(t,e){const s=this,n="LODS:minmax",r=t[n];if(r!=null)return r;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const a of t)this.getMaterialMinMaxLODsCount(a,e);return t[n]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const l of Object.keys(a.uniforms)){const c=a.uniforms[l].value;(c==null?void 0:c.isTexture)===!0&&i(c,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const l=t[a];(l==null?void 0:l.isTexture)===!0&&i(l,e)}return t[n]=e,e;function i(a,l){const c=s.getAssignedLODInformation(a);if(c){const d=s.lodInfos.get(c.key);if(d&&d.lods){l.min_count=Math.min(l.min_count,d.lods.length),l.max_count=Math.max(l.max_count,d.lods.length);for(let p=0;p<d.lods.length;p++){const f=d.lods[p];f.width&&(l.lods[p]=l.lods[p]||{min_height:1/0,max_height:0},l.lods[p].min_height=Math.min(l.lods[p].min_height,f.height),l.lods[p].max_height=Math.max(l.lods[p].max_height,f.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const i of t)if(this.hasLODLevelAvailable(i,e))return!0;return!1}if(t.isMaterial===!0){for(const i of Object.keys(t)){const a=t[i];if(a&&a.isTexture&&this.hasLODLevelAvailable(a,e))return!0}return!1}else if(t.isGroup===!0){for(const i of t.children)if(i.isMesh===!0&&this.hasLODLevelAvailable(i,e))return!0}let s,n;if(t.isMesh?s=t.geometry:(t.isBufferGeometry||t.isTexture)&&(s=t),s&&(r=s==null?void 0:s.userData)!=null&&r.LODS){const i=s.userData.LODS;if(n=this.lodInfos.get(i.key),e===void 0)return n!=null;if(n)return Array.isArray(n.lods)?e<n.lods.length:e===0}return!1}static assignMeshLOD(t,e){var s;if(!t)return Promise.resolve(null);if(t instanceof y.Mesh||t.isMesh===!0){const n=t.geometry,r=this.getAssignedLODInformation(n);if(!r)return Promise.resolve(null);for(const i of Q)(s=i.onBeforeGetLODMesh)==null||s.call(i,t,e);return t["LOD:requested level"]=e,O.getOrLoadLOD(n,e).then(i=>{if(Array.isArray(i)){const a=r.index||0;i=i[a]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],i&&n!=i&&((i==null?void 0:i.isBufferGeometry)?t.geometry=i:x&&console.error("Invalid LOD geometry",i))),i}).catch(i=>(console.error("Error loading mesh LOD",t,i),null))}else x&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const s=t;if(Array.isArray(s.material)){const n=new Array;for(const r of s.material){const i=this.assignTextureLOD(r,e);n.push(i)}return Promise.all(n).then(r=>{const i=new Array;for(const a of r)Array.isArray(a)&&i.push(...a);return i})}else return this.assignTextureLOD(s.material,e)}if(t.isMaterial===!0){const s=t,n=[],r=new Array;if(s.uniforms&&(s.isRawShaderMaterial||s.isShaderMaterial===!0)){const i=s;for(const a of Object.keys(i.uniforms)){const l=i.uniforms[a].value;if((l==null?void 0:l.isTexture)===!0){const c=this.assignTextureLODForSlot(l,e,s,a).then(d=>(d&&i.uniforms[a].value!=d&&(i.uniforms[a].value=d,i.uniformsNeedUpdate=!0),d));n.push(c),r.push(a)}}}else for(const i of Object.keys(s)){const a=s[i];if((a==null?void 0:a.isTexture)===!0){const l=this.assignTextureLODForSlot(a,e,s,i);n.push(l),r.push(i)}}return Promise.all(n).then(i=>{const a=new Array;for(let l=0;l<i.length;l++){const c=i[l],d=r[l];c&&c.isTexture===!0?a.push({material:s,slot:d,texture:c,level:e}):a.push({material:s,slot:d,texture:null,level:e})}return a})}if(t instanceof y.Texture||t.isTexture===!0){const s=t;return this.assignTextureLODForSlot(s,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,s,n){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):O.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if((r==null?void 0:r.isTexture)===!0){if(r!=t&&s&&n){const i=s[n];if(i&&!x){const a=this.getAssignedLODInformation(i);if(a&&(a==null?void 0:a.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,s,i,r),null}s[n]=r}return r}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(r=>(console.error("Error loading LOD",t,r),null))}afterRoot(t){var e,s;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,r)=>{var i;if(n!=null&&n.extensions){const a=n==null?void 0:n.extensions[W];if(a){if(!a.lods){x&&console.warn("Texture has no LODs",a);return}let l=!1;for(const c of this.parser.associations.keys())if(c.isTexture===!0){const d=this.parser.associations.get(c);(d==null?void 0:d.textures)===r&&(l=!0,O.registerTexture(this.url,c,(i=a.lods)==null?void 0:i.length,r,a))}l||this.parser.getDependency("texture",r).then(c=>{var d;c&&O.registerTexture(this.url,c,(d=a.lods)==null?void 0:d.length,r,a)})}}}),(s=this.parser.json.meshes)==null||s.forEach((n,r)=>{if(n!=null&&n.extensions){const i=n==null?void 0:n.extensions[W];if(i&&i.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const l=this.parser.associations.get(a);(l==null?void 0:l.meshes)===r&&O.registerMesh(this.url,i.guid,a,i.lods.length,l.primitives,i)}}}}),null}static async getOrLoadLOD(t,e){var a,l,c,d;const s=x=="verbose",n=t.userData.LODS;if(!n)return null;const r=n==null?void 0:n.key;let i;if(t.isTexture===!0){const p=t;p.source&&p.source[Me]&&(i=p.source[Me])}if(i||(i=O.lodInfos.get(r)),i){if(e>0){let M=!1;const D=Array.isArray(i.lods);if(D&&e>=i.lods.length?M=!0:D||(M=!0),M)return this.lowresCache.get(r)}const p=Array.isArray(i.lods)?(a=i.lods[e])==null?void 0:a.path:i.lods;if(!p)return x&&!i["missing:uri"]&&(i["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,i)),null;const f=rt(n.url,p);if(f.endsWith(".glb")||f.endsWith(".gltf")){if(!i.guid)return console.warn("missing pointer for glb/gltf texture",i),null;const M=f+"_"+i.guid,D=this.previouslyLoaded.get(M);if(D!==void 0){s&&console.log(`LOD ${e} was already loading/loaded: ${M}`);let h=await D.catch(G=>(console.error(`Error loading LOD ${e} from ${f}
2
- `,G),null)),_=!1;if(h==null||(h instanceof y.Texture&&t instanceof y.Texture?(l=h.image)!=null&&l.data||(c=h.source)!=null&&c.data?h=this.copySettings(t,h):(_=!0,this.previouslyLoaded.delete(M)):h instanceof y.BufferGeometry&&t instanceof y.BufferGeometry&&((d=h.attributes.position)!=null&&d.array||(_=!0,this.previouslyLoaded.delete(M)))),!_)return h}const C=await this.queue.slot(f);if(!C.use)return x&&console.log(`LOD ${e} was aborted: ${f}`),null;const S=i,F=new Promise(async(h,_)=>{const G=new Pe.GLTFLoader;Ae(G),x&&(await new Promise(v=>setTimeout(v,1e3)),s&&console.warn("Start loading (delayed) "+f,S.guid));let V=f;if(S&&Array.isArray(S.lods)){const v=S.lods[e];v.hash&&(V+="?v="+v.hash)}const P=await G.loadAsync(V).catch(v=>(console.error(`Error loading LOD ${e} from ${f}
3
- `,v),h(null)));if(!P)return h(null);const ee=P.parser;s&&console.log("Loading finished "+f,S.guid);let E=0;if(P.parser.json.textures){let v=!1;for(const m of P.parser.json.textures){if(m!=null&&m.extensions){const g=m==null?void 0:m.extensions[W];if(g!=null&&g.guid&&g.guid===S.guid){v=!0;break}}E++}if(v){let m=await ee.getDependency("texture",E);return m&&O.assignLODInformation(n.url,m,r,e,void 0),s&&console.log('change "'+t.name+'" → "'+m.name+'"',f,E,m,M),t instanceof y.Texture&&(m=this.copySettings(t,m)),m&&(m.guid=S.guid),h(m)}else x&&console.warn("Could not find texture with guid",S.guid,P.parser.json)}if(E=0,P.parser.json.meshes){let v=!1;for(const m of P.parser.json.meshes){if(m!=null&&m.extensions){const g=m==null?void 0:m.extensions[W];if(g!=null&&g.guid&&g.guid===S.guid){v=!0;break}}E++}if(v){const m=await ee.getDependency("mesh",E);if(s&&console.log(`Loaded Mesh "${m.name}"`,f,E,m,M),m.isMesh===!0){const g=m.geometry;return O.assignLODInformation(n.url,g,r,e,0),h(g)}else{const g=new Array;for(let w=0;w<m.children.length;w++){const B=m.children[w];if(B.isMesh===!0){const $=B.geometry;O.assignLODInformation(n.url,$,r,e,w),g.push($)}}return h(g)}}else x&&console.warn("Could not find mesh with guid",S.guid,P.parser.json)}return h(null)});return this.previouslyLoaded.set(M,F),C.use(F),await F}else if(t instanceof y.Texture){s&&console.log("Load texture from uri: "+f);const D=await new y.TextureLoader().loadAsync(f);return D?(D.guid=i.guid,D.flipY=!1,D.needsUpdate=!0,D.colorSpace=t.colorSpace,s&&console.log(i,D)):x&&console.warn("failed loading",f),D}}else x&&console.warn(`Can not load LOD ${e}: no LOD info found for "${r}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,s,n,r){if(!e)return;e.userData||(e.userData={});const i=new ut(t,s,n,r);e.userData.LODS=i}static getAssignedLODInformation(t){var e;return((e=t==null?void 0:t.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e?(x&&console.warn(`Copy texture settings
1
+ "use strict";var Fe=Object.create;var Le=Object.defineProperty;var Ue=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var We=Object.getPrototypeOf,Ne=Object.prototype.hasOwnProperty;var Ve=(o,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Ee(t))!Ne.call(o,n)&&n!==e&&Le(o,n,{get:()=>t[n],enumerable:!(r=Ue(t,n))||r.enumerable});return o};var ze=(o,t,e)=>(e=o!=null?Fe(We(o)):{},Ve(t||!o||!o.__esModule?Le(e,"default",{value:o,enumerable:!0}):e,o));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("three"),pe=require("three/examples/jsm/loaders/GLTFLoader.js"),qe=require("three/examples/jsm/libs/meshopt_decoder.module.js"),je=require("three/examples/jsm/loaders/DRACOLoader.js"),Xe=require("three/examples/jsm/loaders/KTX2Loader.js");var oe=typeof document<"u"?document.currentScript:null;const De="";globalThis.GLTF_PROGRESSIVE_VERSION=De;console.debug("[gltf-progressive] version -");let k="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",V="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ke=k,Ye=V,Oe=new URL(k+"draco_decoder.js");Oe.searchParams.append("range","true");fetch(Oe,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(o=>{console.debug(`Failed to fetch remote Draco decoder from ${k} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),k===Ke&&Se("./include/draco/"),V===Ye&&Te("./include/ktx2/")}).finally(()=>{Pe()});const He=()=>({dracoDecoderPath:k,ktx2TranscoderPath:V});function Se(o){k=o,A&&A[fe]!=k?(console.debug("Updating Draco decoder path to "+o),A[fe]=k,A.setDecoderPath(k),A.preload()):console.debug("Setting Draco decoder path to "+o)}function Te(o){V=o,R&&R.transcoderPath!=V?(console.debug("Updating KTX2 transcoder path to "+o),R.setTranscoderPath(V),R.init()):console.debug("Setting KTX2 transcoder path to "+o)}function re(o){return Pe(),o?R.detectSupport(o):o!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:A,ktx2Loader:R,meshoptDecoder:te}}function me(o){o.dracoLoader||o.setDRACOLoader(A),o.ktx2Loader||o.setKTX2Loader(R),o.meshoptDecoder||o.setMeshoptDecoder(te)}const fe=Symbol("dracoDecoderPath");let A,te,R;function Pe(){A||(A=new je.DRACOLoader,A[fe]=k,A.setDecoderPath(k),A.setDecoderConfig({type:"js"}),A.preload()),R||(R=new Xe.KTX2Loader,R.setTranscoderPath(V),R.init()),te||(te=qe.MeshoptDecoder)}const he=new WeakMap;function ye(o,t){let e=he.get(o);e?e=Object.assign(e,t):e=t,he.set(o,e)}const Qe=pe.GLTFLoader.prototype.load;function Je(...o){const t=he.get(this);let e=o[0];const r=new URL(e,window.location.href);if(r.hostname.endsWith("needle.tools")){const s=t?.progressive!==void 0?t.progressive:!0,i=t?.usecase?t.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${i}`:this.requestHeader.Accept=`*/*;usecase=${i}`,e=r.toString()}return o[0]=e,Qe?.call(this,...o)}pe.GLTFLoader.prototype.load=Je;z("debugprogressive");function z(o){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(o);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Ze(o,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||o===void 0)return t;const e=o.lastIndexOf("/");if(e>=0){const r=o.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let X;function Ae(){return X!==void 0||(X=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),z("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",X)),X}function _e(){if(typeof window>"u")return!1;const o=new URL(window.location.href),t=o.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(o.hostname);return o.hostname==="127.0.0.1"||t}class et{constructor(t=100,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,window.requestAnimationFrame(this.tick)}_running=new Map;_queue=[];debug=!1;tick=()=>{this.internalUpdate(),setTimeout(this.tick,10)};slot(t){return this.debug&&console.debug(`[PromiseQueue]: Requesting slot for key ${t}, running: ${this._running.size}, waiting: ${this._queue.length}`),new Promise(e=>{this._queue.push({key:t,resolve:e})})}add(t,e){this._running.has(t)||(this._running.set(t,e),e.finally(()=>{this._running.delete(t),this.debug&&console.debug(`[PromiseQueue]: Promise finished now running: ${this._running.size}, waiting: ${this._queue.length}. (finished ${t})`)}),this.debug&&console.debug(`[PromiseQueue]: Added new promise, now running: ${this._running.size}, waiting: ${this._queue.length}. (added ${t})`))}internalUpdate(){const t=this.maxConcurrent-this._running.size;for(let e=0;e<t&&this._queue.length>0;e++){this.debug&&console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);const{key:r,resolve:n}=this._queue.shift();n({use:s=>this.add(r,s)})}}}const tt=typeof window>"u"&&typeof document>"u",ge=Symbol("needle:raycast-mesh");function q(o){return o?.[ge]instanceof d.BufferGeometry?o[ge]:null}function Ie(o,t){if((o.type==="Mesh"||o.type==="SkinnedMesh")&&!q(o)){const r=rt(t);r.userData={isRaycastMesh:!0},o[ge]=r}}function Ce(o=!0){if(o){if(K)return;const t=K=d.Mesh.prototype.raycast;d.Mesh.prototype.raycast=function(e,r){const n=this,s=q(n);let i;s&&n.isMesh&&(i=n.geometry,n.geometry=s),t.call(this,e,r),i&&(n.geometry=i)}}else{if(!K)return;d.Mesh.prototype.raycast=K,K=null}}let K=null;function rt(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 E=new Array,p=z("debugprogressive");let ee,N=-1;if(p){let o=function(){N+=1,N>=t&&(N=-1),console.log(`Toggle LOD level [${N}]`)},t=6;window.addEventListener("keyup",e=>{e.key==="p"&&o(),e.key==="w"&&(ee=!ee,console.log(`Toggle wireframe [${ee}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(N=r,console.log(`Set LOD level to [${N}]`))})}function ke(o){if(p)if(Array.isArray(o))for(const t of o)ke(t);else o&&"wireframe"in o&&(o.wireframe=ee===!0)}const Y=new Array;let st=0;const nt=Ae()?2:10;function ot(o){if(Y.length<nt){const r=Y.length;p&&console.warn(`[Worker] Creating new worker #${r}`);const n=xe.createWorker(o||{});return Y.push(n),n}const t=st++%Y.length;return Y[t]}class xe{constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=r=>{const n=r.data;switch(this._debug&&console.log("[Worker] EVENT",n),n.type){case"loaded-gltf":for(const s of this._running)if(s.url===n.result.url){it(n.result),s.resolve(n.result);const i=s.url;i.startsWith("blob:")&&URL.revokeObjectURL(i)}}},t.onerror=r=>{console.error("[Worker] Error in gltf-progressive worker:",r)},t.postMessage({type:"init"})}static async createWorker(t){const e=new Worker(new URL("/assets/loader.worker-8olmVOL4.js",typeof document>"u"?require("url").pathToFileURL(__filename).href:oe&&oe.tagName.toUpperCase()==="SCRIPT"&&oe.src||new URL("gltf-progressive.umd.cjs",document.baseURI).href),{type:"module"});return new xe(e,t)}_running=[];_webglRenderer=null;async load(t,e){const r=He();let n=e?.renderer;n||(this._webglRenderer??=(async()=>{const{WebGLRenderer:u}=await import("three");return new u})(),n=await this._webglRenderer);const l=re(n).ktx2Loader.workerConfig;t instanceof URL?t=t.toString():t.startsWith("file:")?t=URL.createObjectURL(new Blob([t])):!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")&&(t=new URL(t,window.location.href).toString());const a={type:"load",url:t,dracoDecoderPath:r.dracoDecoderPath,ktx2TranscoderPath:r.ktx2TranscoderPath,ktx2LoaderConfig:l};return this._debug&&console.debug("[Worker] Sending load request",a),this.worker.postMessage(a),new Promise(u=>{this._running.push({url:t.toString(),resolve:u})})}_debug=!1}function it(o){for(const t of o.geometries){const e=t.geometry,r=new d.BufferGeometry;if(r.name=e.name||"",e.index){const n=e.index;r.setIndex(ie(n))}for(const n in e.attributes){const s=e.attributes[n],i=ie(s);r.setAttribute(n,i)}if(e.morphAttributes)for(const n in e.morphAttributes){const i=e.morphAttributes[n].map(l=>ie(l));r.morphAttributes[n]=i}if(r.morphTargetsRelative=e.morphTargetsRelative??!1,r.boundingBox=new d.Box3,r.boundingBox.min=new d.Vector3(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),r.boundingBox.max=new d.Vector3(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),r.boundingSphere=new d.Sphere(new d.Vector3(e.boundingSphere?.center.x,e.boundingSphere?.center.y,e.boundingSphere?.center.z),e.boundingSphere?.radius),e.groups)for(const n of e.groups)r.addGroup(n.start,n.count,n.materialIndex);e.userData&&(r.userData=e.userData),t.geometry=r}for(const t of o.textures){const e=t.texture;let r=null;if(e.isCompressedTexture){const n=e.mipmaps,s=e.image?.width||e.source?.data?.width||-1,i=e.image?.height||e.source?.data?.height||-1;r=new d.CompressedTexture(n,s,i,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else r=new d.Texture(e.image,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),r.mipmaps=e.mipmaps,r.channel=e.channel,r.source.data=e.source.data,r.flipY=e.flipY,r.premultiplyAlpha=e.premultiplyAlpha,r.unpackAlignment=e.unpackAlignment,r.matrix=new d.Matrix3(...e.matrix.elements);if(!r){console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");continue}t.texture=r}return o}function ie(o){let t=o;if("isInterleavedBufferAttribute"in o&&o.isInterleavedBufferAttribute){const e=o.data,r=e.array,n=new d.InterleavedBuffer(r,e.stride);t=new d.InterleavedBufferAttribute(n,o.itemSize,r.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 at=z("gltf-progressive-worker"),lt=z("gltf-progressive-reduce-mipmaps"),ae=Symbol("needle-progressive-texture"),$="NEEDLE_progressive";class x{get name(){return $}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e?.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){const e=this.getAssignedLODInformation(t)?.index;return e??-1}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const l of t)this.getMaterialMinMaxLODsCount(l,e);return t[n]=e,e}if(p==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const l=t;for(const a of Object.keys(l.uniforms)){const u=l.uniforms[a].value;u?.isTexture===!0&&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[n]=e,e;function i(l,a){const u=r.getAssignedLODInformation(l);if(u){const f=r.lodInfos.get(u.key);if(f&&f.lods){a.min_count=Math.min(a.min_count,f.lods.length),a.max_count=Math.max(a.max_count,f.lods.length);for(let m=0;m<f.lods.length;m++){const v=f.lods[m];v.width&&(a.lods[m]=a.lods[m]||{min_height:1/0,max_height:0},a.lods[m].min_height=Math.min(a.lods[m].min_height,v.height),a.lods[m].max_height=Math.max(a.lods[m].max_height,v.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const i=t[s];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let r,n;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&r?.userData?.LODS){const s=r.userData.LODS;if(n=this.lodInfos.get(s.key),e===void 0)return n!=null;if(n)return Array.isArray(n.lods)?e<n.lods.length:e===0}return!1}static assignMeshLOD(t,e){if(!t)return Promise.resolve(null);if(t instanceof d.Mesh||t.isMesh===!0){const r=t.geometry,n=this.getAssignedLODInformation(r);if(!n)return Promise.resolve(null);for(const s of E)s.onBeforeGetLODMesh?.(t,e);return t["LOD:requested level"]=e,x.getOrLoadLOD(r,e).then(s=>{if(Array.isArray(s)){const i=n.index||0;s=s[i]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],s&&r!=s&&(s?.isBufferGeometry?t.geometry=s:p&&console.error("Invalid LOD geometry",s))),s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else p&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const i=this.assignTextureLOD(s,e);n.push(i)}return Promise.all(n).then(s=>{const i=new Array;for(const l of s)Array.isArray(l)&&i.push(...l);return i})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,n=[],s=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const i=r;for(const l of Object.keys(i.uniforms)){const a=i.uniforms[l].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,l).then(f=>(f&&i.uniforms[l].value!=f&&(i.uniforms[l].value=f,i.uniformsNeedUpdate=!0),f));n.push(u),s.push(l)}}}else for(const i of Object.keys(r)){const l=r[i];if(l?.isTexture===!0){const a=this.assignTextureLODForSlot(l,e,r,i);n.push(a),s.push(i)}}return Promise.all(n).then(i=>{const l=new Array;for(let a=0;a<i.length;a++){const u=i[a],f=s[a];u&&u.isTexture===!0?l.push({material:r,slot:f,texture:u,level:e}):l.push({material:r,slot:f,texture:null,level:e})}return l})}if(t instanceof d.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):x.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(s?.isTexture===!0){if(s!=t&&r&&n){const i=r[n];if(i&&!p){const l=this.getAssignedLODInformation(i);if(l&&l?.level<e)return p==="verbose"&&console.warn("Assigned texture level is already higher: ",l.level,e,r,i,s),null}if(lt&&s.mipmaps){const l=s.mipmaps.length;s.mipmaps.length=Math.min(s.mipmaps.length,3),l!==s.mipmaps.length&&p&&console.debug(`Reduced mipmap count from ${l} to ${s.mipmaps.length} for ${s.uuid}: ${s.image?.width}x${s.image?.height}.`)}r[n]=s}return s}else p=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}parser;url;constructor(t,e){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?.[$];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>(this._isLoadingMesh=!1,r&&x.registerMesh(this.url,e.guid,r,e.lods?.length,0,e),r))):null};afterRoot(t){return p&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[$];if(n){if(!n.lods){p&&console.warn("Texture has no LODs",n);return}let s=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i)?.textures===r&&(s=!0,x.registerTexture(this.url,i,n.lods?.length,r,n));s||this.parser.getDependency("texture",r).then(i=>{i&&x.registerTexture(this.url,i,n.lods?.length,r,n)})}}}),this.parser.json.meshes?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[$];if(n&&n.lods){for(const s of this.parser.associations.keys())if(s.isMesh){const i=this.parser.associations.get(s);i?.meshes===r&&x.registerMesh(this.url,n.guid,s,n.lods.length,i.primitives,n)}}}}),null}static registerTexture=(t,e,r,n,s)=>{if(!e){p&&console.error("gltf-progressive: Called register texture without texture");return}if(p){const l=e.image?.width||e.source?.data?.width||0,a=e.image?.height||e.source?.data?.height||0;console.log(`> Progressive: register texture[${n}] "${e.name||e.uuid}", Current: ${l}x${a}, Max: ${s.lods[0]?.width}x${s.lods[0]?.height}, uuid: ${e.uuid}`,s,e)}e.source&&(e.source[ae]=s);const i=s.guid;x.assignLODInformation(t,e,i,r,n),x.lodInfos.set(i,s),x.lowresCache.set(i,e)};static registerMesh=(t,e,r,n,s,i)=>{const l=r.geometry;if(!l){p&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),p&&console.log("> Progressive: register mesh "+r.name,{index:s,uuid:r.uuid},i,r),x.assignLODInformation(t,l,e,n,s),x.lodInfos.set(e,i);let a=x.lowresCache.get(e);a?a.push(r.geometry):a=[r.geometry],x.lowresCache.set(e,a),n>0&&!q(r)&&Ie(r,l);for(const u of E)u.onRegisteredNewMesh?.(r,i)};static lodInfos=new Map;static previouslyLoaded=new Map;static lowresCache=new Map;static workers=[];static _workersIndex=0;static async getOrLoadLOD(t,e){const r=p=="verbose",n=this.getAssignedLODInformation(t);if(!n)return p&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const s=n?.key;let i;if(t.isTexture===!0){const a=t;a.source&&a.source[ae]&&(i=a.source[ae])}if(i||(i=x.lodInfos.get(s)),i){if(e>0){let f=!1;const m=Array.isArray(i.lods);if(m&&e>=i.lods.length?f=!0:m||(f=!0),f)return this.lowresCache.get(s)}const a=Array.isArray(i.lods)?i.lods[e]?.path:i.lods;if(!a)return p&&!i["missing:uri"]&&(i["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,i)),null;const u=Ze(n.url,a);if(u.endsWith(".glb")||u.endsWith(".gltf")){if(!i.guid)return console.warn("missing pointer for glb/gltf texture",i),null;const f=u+"_"+i.guid,m=await this.queue.slot(u),v=this.previouslyLoaded.get(f);if(v!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let c=await v.catch(S=>(console.error(`Error loading LOD ${e} from ${u}
2
+ `,S),null)),w=!1;if(c==null||(c instanceof d.Texture&&t instanceof d.Texture?c.image?.data||c.source?.data?c=this.copySettings(t,c):(w=!0,this.previouslyLoaded.delete(f)):c instanceof d.BufferGeometry&&t instanceof d.BufferGeometry&&(c.attributes.position?.array||(w=!0,this.previouslyLoaded.delete(f)))),!w)return c}if(!m.use)return p&&console.log(`LOD ${e} was aborted: ${u}`),null;const M=i,I=new Promise(async(c,w)=>{if(at){const y=await(await ot({})).load(u);if(y.textures.length>0)for(const h of y.textures){let g=h.texture;return x.assignLODInformation(n.url,g,s,e,void 0),t instanceof d.Texture&&(g=this.copySettings(t,g)),g&&(g.guid=M.guid),c(g)}if(y.geometries.length>0){const h=new Array;for(const g of y.geometries){const D=g.geometry;x.assignLODInformation(n.url,D,s,e,g.primitiveIndex),h.push(D)}return c(h)}return c(null)}const S=new pe.GLTFLoader;me(S),p&&(await new Promise(_=>setTimeout(_,1e3)),r&&console.warn("Start loading (delayed) "+u,M.guid));let B=u;if(M&&Array.isArray(M.lods)){const _=M.lods[e];_.hash&&(B+="?v="+_.hash)}const b=await S.loadAsync(B).catch(_=>(console.error(`Error loading LOD ${e} from ${u}
3
+ `,_),c(null)));if(!b)return c(null);const W=b.parser;r&&console.log("Loading finished "+u,M.guid);let T=0;if(b.parser.json.textures){let _=!1;for(const y of b.parser.json.textures){if(y?.extensions){const h=y?.extensions[$];if(h?.guid&&h.guid===M.guid){_=!0;break}}T++}if(_){let y=await W.getDependency("texture",T);return y&&x.assignLODInformation(n.url,y,s,e,void 0),r&&console.log('change "'+t.name+'" → "'+y.name+'"',u,T,y,f),t instanceof d.Texture&&(y=this.copySettings(t,y)),y&&(y.guid=M.guid),c(y)}else p&&console.warn("Could not find texture with guid",M.guid,b.parser.json)}if(T=0,b.parser.json.meshes){let _=!1;for(const y of b.parser.json.meshes){if(y?.extensions){const h=y?.extensions[$];if(h?.guid&&h.guid===M.guid){_=!0;break}}T++}if(_){const y=await W.getDependency("mesh",T);if(r&&console.log(`Loaded Mesh "${y.name}"`,u,T,y,f),y.isMesh===!0){const h=y.geometry;return x.assignLODInformation(n.url,h,s,e,0),c(h)}else{const h=new Array;for(let g=0;g<y.children.length;g++){const D=y.children[g];if(D.isMesh===!0){const O=D.geometry;x.assignLODInformation(n.url,O,s,e,g),h.push(O)}}return c(h)}}else p&&console.warn("Could not find mesh with guid",M.guid,b.parser.json)}return c(null)});return this.previouslyLoaded.set(f,I),m.use(I),await I}else if(t instanceof d.Texture){r&&console.log("Load texture from uri: "+u);const m=await new d.TextureLoader().loadAsync(u);return m?(m.guid=i.guid,m.flipY=!1,m.needsUpdate=!0,m.colorSpace=t.colorSpace,r&&console.log(i,m)):p&&console.warn("failed loading",u),m}}else p&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type);return null}static maxConcurrent=50;static queue=new et(x.maxConcurrent,{debug:p!=!1});static assignLODInformation(t,e,r,n,s){if(!e)return;e.userData||(e.userData={});const i=new ut(t,r,n,s);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
4
4
  `,t.uuid,`
5
- `,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}};let T=O;u(T,"registerTexture",(t,e,s,n,r)=>{if(x&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,r),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Me]=r);const i=r.guid;O.assignLODInformation(t,e,i,s,n),O.lodInfos.set(i,r),O.lowresCache.set(i,e)}),u(T,"registerMesh",(t,e,s,n,r,i)=>{var c;const a=s.geometry;if(!a){x&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),x&&console.log("> Progressive: register mesh "+s.name,{index:r,uuid:s.uuid},i,s),O.assignLODInformation(t,a,e,n,r),O.lodInfos.set(e,i);let l=O.lowresCache.get(e);l?l.push(s.geometry):l=[s.geometry],O.lowresCache.set(e,l),n>0&&!ie(s)&&Ve(s,a);for(const d of Q)(c=d.onRegisteredNewMesh)==null||c.call(d,s,i)}),u(T,"lodInfos",new Map),u(T,"previouslyLoaded",new Map),u(T,"lowresCache",new Map),u(T,"queue",new ot(100,{debug:x!=!1}));class ut{constructor(t,e,s,n){u(this,"url");u(this,"key");u(this,"level");u(this,"index");this.url=t,this.key=e,this.level=s,n!=null&&(this.index=n)}}class pe{constructor(t,e){u(this,"frame_start");u(this,"frame_capture_end");u(this,"ready");u(this,"_resolve");u(this,"_signal");u(this,"_resolved",!1);u(this,"_addedCount",0);u(this,"_resolvedCount",0);u(this,"_awaiting",[]);u(this,"_maxPromisesPerObject",1);u(this,"_currentFrame",0);u(this,"_seen",new WeakMap);var r;const n=Math.max(e.frames??2,2);this.frame_start=t,this.frame_capture_end=t+n,this.ready=new Promise(i=>{this._resolve=i}),this.ready.finally(()=>{this._resolved=!0,this._awaiting.length=0}),this._signal=e.signal,(r=this._signal)==null||r.addEventListener("abort",()=>{this.resolveNow()}),this._maxPromisesPerObject=Math.max(1,e.maxPromisesPerObject??1)}get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}update(t){var e;this._currentFrame=t,((e=this._signal)!=null&&e.aborted||this._currentFrame>this.frame_capture_end&&this._awaiting.length===0)&&this.resolveNow()}add(t,e,s){if(this._resolved){x&&console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}if(!(this._currentFrame>this.frame_capture_end)){if(this._maxPromisesPerObject>=1)if(this._seen.has(e)){let n=this._seen.get(e);if(n>=this._maxPromisesPerObject){x&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(e,n+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(){var t,e;this._resolved||(e=this._resolve)==null||e.call(this,{awaited_count:this._addedCount,resolved_count:this._resolvedCount,cancelled:((t=this._signal)==null?void 0:t.aborted)??!1})}}u(pe,"addPromise",(t,e,s,n)=>{n.forEach(r=>{r.add(t,e,s)})});const N=ue("debugprogressive"),dt=ue("noprogressive"),ve=Symbol("Needle:LODSManager"),De=Symbol("Needle:LODState"),H=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var R,K,ye,J,re,Le,Y;const b=class{constructor(t,e){u(this,"renderer");u(this,"context");u(this,"projectionScreenMatrix",new y.Matrix4);u(this,"targetTriangleDensity",2e5);u(this,"skinnedMeshAutoUpdateBoundsInterval",30);u(this,"updateInterval","auto");j(this,R,1);u(this,"pause",!1);u(this,"manual",!1);u(this,"_newPromiseGroups",[]);u(this,"_promiseGroupIds",0);u(this,"_lodchangedlisteners",[]);j(this,K,void 0);j(this,ye,new y.Clock);j(this,J,0);j(this,re,0);j(this,Le,0);j(this,Y,0);u(this,"_fpsBuffer",[60,60,60,60,60]);u(this,"_sphere",new y.Sphere);u(this,"_tempBox",new y.Box3);u(this,"_tempBox2",new y.Box3);u(this,"tempMatrix",new y.Matrix4);u(this,"_tempWorldPosition",new y.Vector3);u(this,"_tempBoxSize",new y.Vector3);u(this,"_tempBox2Size",new y.Vector3);this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[De]}static addPlugin(t){Q.push(t)}static removePlugin(t){const e=Q.indexOf(t);e>=0&&Q.splice(e,1)}static get(t,e){if(t[ve])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[ve];const s=new b(t,{engine:"unknown",...e});return t[ve]=s,s}get plugins(){return Q}awaitLoading(t){const e=this._promiseGroupIds++,s=new pe(L(this,J),{...t});this._newPromiseGroups.push(s);const n=performance.now();return s.ready.finally(()=>{const r=this._newPromiseGroups.indexOf(s);r>=0&&(this._newPromiseGroups.splice(r,1),nt()&&performance.measure("LODsManager:awaitLoading",{start:n,detail:{id:e,name:t==null?void 0:t.name,awaited:s.awaitedCount,resolved:s.resolvedCount}}))}),s.ready}_postprocessPromiseGroups(){if(this._newPromiseGroups.length!==0)for(let t=this._newPromiseGroups.length-1;t>=0;t--)this._newPromiseGroups[t].update(L(this,J))}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const s=this._lodchangedlisteners.indexOf(e);s>=0&&this._lodchangedlisteners.splice(s,1)}}enable(){if(L(this,K))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;z(this,K,this.renderer.render);const e=this;Te(this.renderer),this.renderer.render=function(s,n){const r=e.renderer.getRenderTarget();(r==null||"isXRRenderTarget"in r&&r.isXRRenderTarget)&&(t=0,z(e,J,L(e,J)+1),z(e,re,L(e,ye).getDelta()),z(e,Le,L(e,Le)+L(e,re)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/L(e,re)),z(e,Y,e._fpsBuffer.reduce((a,l)=>a+l)/e._fpsBuffer.length),N&&L(e,J)%200===0&&console.log("FPS",Math.round(L(e,Y)),"Interval:",L(e,R)));const i=t++;L(e,K).call(this,s,n),e.onAfterRender(s,n,i)}}disable(){L(this,K)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=L(this,K),z(this,K,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,s){if(this.pause)return;const r=this.renderer.renderLists.get(t,0).opaque;let i=!0;if(r.length===1){const a=r[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(dt||(this.updateInterval==="auto"?L(this,Y)<40&&L(this,R)<10?(z(this,R,L(this,R)+1),N&&console.warn("↓ Reducing LOD updates",L(this,R),L(this,Y).toFixed(0))):L(this,Y)>=60&&L(this,R)>1&&(z(this,R,L(this,R)-1),N&&console.warn("↑ Increasing LOD updates",L(this,R),L(this,Y).toFixed(0))):z(this,R,this.updateInterval),L(this,R)>0&&L(this,J)%L(this,R)!=0))return;this.internalUpdate(t,e),this._postprocessPromiseGroups()}}internalUpdate(t,e){var l,c;const s=this.renderer.renderLists.get(t,0),n=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const r=this.targetTriangleDensity;for(const d of n){if(d.material&&(((l=d.geometry)==null?void 0:l.type)==="BoxGeometry"||((c=d.geometry)==null?void 0:c.type)==="BufferGeometry")&&(d.material.name==="SphericalGaussianBlur"||d.material.name=="BackgroundCubeMaterial"||d.material.name==="CubemapFromEquirect"||d.material.name==="EquirectangularToCubeUV")){N&&(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",d,d.material.name,d.material.type)));continue}switch(d.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(N==="color"&&d.material&&!d.object.progressive_debug_color){d.object.progressive_debug_color=!0;const f=Math.random()*16777215,M=new y.MeshStandardMaterial({color:f});d.object.material=M}const p=d.object;(p instanceof y.Mesh||p.isMesh)&&this.updateLODs(t,e,p,r)}const i=s.transparent;for(const d of i){const p=d.object;(p instanceof y.Mesh||p.isMesh)&&this.updateLODs(t,e,p,r)}const a=s.transmissive;for(const d of a){const p=d.object;(p instanceof y.Mesh||p.isMesh)&&this.updateLODs(t,e,p,r)}}updateLODs(t,e,s,n){var a,l;s.userData||(s.userData={});let r=s[De];if(r||(r=new ct,s[De]=r),r.frames++<2)return;for(const c of Q)(a=c.onBeforeUpdateLOD)==null||a.call(c,this.renderer,t,e,s);const i=b.overrideGlobalLodLevel!==void 0?b.overrideGlobalLodLevel:te;i>=0?(k.mesh_lod=i,k.texture_lod=i):(this.calculateLodLevel(e,s,r,n,k),k.mesh_lod=Math.round(k.mesh_lod),k.texture_lod=Math.round(k.texture_lod)),k.mesh_lod>=0&&this.loadProgressiveMeshes(s,k.mesh_lod),s.material&&k.texture_lod>=0&&this.loadProgressiveTextures(s.material,k.texture_lod),x&&s.material&&!s.isGizmo&&ze(s.material);for(const c of Q)(l=c.onAfterUpdatedLOD)==null||l.call(c,this.renderer,t,e,s,k);r.lastLodLevel_Mesh=k.mesh_lod,r.lastLodLevel_Texture=k.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const r of t)this.loadProgressiveTextures(r,e);return}let s=!1;(t[H]===void 0||e<t[H])&&(s=!0);const n=t["DEBUG:LOD"];if(n!=null&&(s=t[H]!=n,e=n),s){t[H]=e;const r=T.assignTextureLOD(t,e).then(i=>{this._lodchangedlisteners.forEach(a=>a({type:"texture",level:e,object:t}))});pe.addPromise("texture",t,r,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let s=t[H]!==e;const n=t["DEBUG:LOD"];if(n!=null&&(s=t[H]!=n,e=n),s){t[H]=e;const r=t.geometry,i=T.assignMeshLOD(t,e).then(a=>(a&&t[H]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(l=>l({type:"mesh",level:e,object:t})),a));return pe.addPromise("mesh",t,i,this._newPromiseGroups),i}return Promise.resolve(null)}static isInside(t,e){const s=t.min,n=t.max,r=(s.x+n.x)*.5,i=(s.y+n.y)*.5;return this._tempPtInside.set(r,i,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,n,r){var S,F,Z;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let a=10+1,l=!1;if(N&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const c=(S=T.getMeshLODExtension(e.geometry))==null?void 0:S.lods,d=T.getPrimitiveIndex(e.geometry),p=c&&c.length>0,f=T.getMaterialMinMaxLODsCount(e.material),M=(f==null?void 0:f.min_count)!=1/0&&f.min_count>0&&f.max_count>0;if(!p&&!M){r.mesh_lod=0,r.texture_lod=0;return}p||(l=!0,a=0);const D=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let C=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const h=e;if(!h.boundingBox)h.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0){if(!h[b.$skinnedMeshBoundsOffset]){const G=b.skinnedMeshBoundsFrameOffsetCounter++;h[b.$skinnedMeshBoundsOffset]=G}const _=h[b.$skinnedMeshBoundsOffset];if((s.frames+_)%this.skinnedMeshAutoUpdateBoundsInterval===0){const G=ie(h),V=h.geometry;G&&(h.geometry=G),h.computeBoundingBox(),h.geometry=V}}C=h.boundingBox}if(C){const h=t;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 g=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(C),this._tempBox.applyMatrix4(e.matrixWorld),h.isPerspectiveCamera&&b.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&h.isPerspectiveCamera&&h.fov>70){const g=this._tempBox.min,w=this._tempBox.max;let B=g.x,$=g.y,q=w.x,ne=w.y;const de=2,xe=1.5,ce=(g.x+w.x)*.5,fe=(g.y+w.y)*.5;B=(B-ce)*de+ce,$=($-fe)*de+fe,q=(q-ce)*de+ce,ne=(ne-fe)*de+fe;const Ke=B<0&&q>0?0:Math.min(Math.abs(g.x),Math.abs(w.x)),Ye=$<0&&ne>0?0:Math.min(Math.abs(g.y),Math.abs(w.y)),_e=Math.max(Ke,Ye);s.lastCentrality=(xe-_e)*(xe-_e)*(xe-_e)}else s.lastCentrality=1;const _=this._tempBox.getSize(this._tempBoxSize);_.multiplyScalar(.5),screen.availHeight>0&&D>0&&_.multiplyScalar(D/screen.availHeight),t.isPerspectiveCamera?_.x*=t.aspect:t.isOrthographicCamera;const G=t.matrixWorldInverse,V=this._tempBox2;V.copy(C),V.applyMatrix4(e.matrixWorld),V.applyMatrix4(G);const P=V.getSize(this._tempBox2Size),ee=Math.max(P.x,P.y);if(Math.max(_.x,_.y)!=0&&ee!=0&&(_.z=P.z/Math.max(P.x,P.y)*Math.max(_.x,_.y)),s.lastScreenCoverage=Math.max(_.x,_.y,_.z),s.lastScreenspaceVolume.copy(_),s.lastScreenCoverage*=s.lastCentrality,N&&b.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const w=b.corner0,B=b.corner1,$=b.corner2,q=b.corner3;w.copy(this._tempBox.min),B.copy(this._tempBox.max),B.x=w.x,$.copy(this._tempBox.max),$.y=w.y,q.copy(this._tempBox.max);const ne=(w.z+q.z)*.5;w.z=B.z=$.z=q.z=ne,w.applyMatrix4(g),B.applyMatrix4(g),$.applyMatrix4(g),q.applyMatrix4(g),b.debugDrawLine(w,B,255),b.debugDrawLine(w,$,255),b.debugDrawLine(B,q,255),b.debugDrawLine($,q,255)}let v=999;if(c&&s.lastScreenCoverage>0)for(let g=0;g<c.length;g++){const w=c[g];if((((F=w.densities)==null?void 0:F[d])||w.density||1e-5)/s.lastScreenCoverage<n){v=g;break}}v<a&&(a=v,l=!0)}if(l?r.mesh_lod=a:r.mesh_lod=s.lastLodLevel_Mesh,N&&r.mesh_lod!=s.lastLodLevel_Mesh){const _=c==null?void 0:c[r.mesh_lod];_&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${r.mesh_lod} (${_.density.toFixed(0)}) - ${e.name}`)}if(M){const h="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(s.lastLodLevel_Texture<0){if(r.texture_lod=f.max_count-1,N){const _=f.lods[f.max_count-1];N&&console.log(`First Texture LOD ${r.texture_lod} (${_.max_height}px) - ${e.name}`)}}else{const _=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let G=s.lastScreenCoverage*4;((Z=this.context)==null?void 0:Z.engine)==="model-viewer"&&(G*=1.5);const P=D/window.devicePixelRatio*G;let ee=!1;for(let E=f.lods.length-1;E>=0;E--){const v=f.lods[E];if(!(h&&v.max_height>=2048)&&!(it()&&v.max_height>4096)&&(v.max_height>P||!ee&&E===0)){if(ee=!0,r.texture_lod=E,r.texture_lod<s.lastLodLevel_Texture){const m=v.max_height;N&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${r.texture_lod} = ${m}px
6
- Screensize: ${P.toFixed(0)}px, Coverage: ${(100*s.lastScreenCoverage).toFixed(2)}%, Volume ${_.toFixed(1)}
7
- ${e.name}`)}break}}}}else r.texture_lod=0}};let A=b;R=new WeakMap,K=new WeakMap,ye=new WeakMap,J=new WeakMap,re=new WeakMap,Le=new WeakMap,Y=new WeakMap,u(A,"debugDrawLine"),u(A,"overrideGlobalLodLevel"),u(A,"corner0",new y.Vector3),u(A,"corner1",new y.Vector3),u(A,"corner2",new y.Vector3),u(A,"corner3",new y.Vector3),u(A,"_tempPtInside",new y.Vector3),u(A,"skinnedMeshBoundsFrameOffsetCounter",0),u(A,"$skinnedMeshBoundsOffset",Symbol("gltf-progressive-skinnedMeshBoundsOffset"));class ct{constructor(){u(this,"frames",0);u(this,"lastLodLevel_Mesh",-1);u(this,"lastLodLevel_Texture",-1);u(this,"lastScreenCoverage",0);u(this,"lastScreenspaceVolume",new y.Vector3);u(this,"lastCentrality",0)}}const Be=Symbol("NEEDLE_mesh_lod"),he=Symbol("NEEDLE_texture_lod");let le=null;function Ge(){const o=ft();o&&(o.mapURLs(function(t){return $e(),t}),$e(),le==null||le.disconnect(),le=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(s=>{s instanceof HTMLElement&&s.tagName.toLowerCase()==="model-viewer"&&We(s)})})}),le.observe(document,{childList:!0,subtree:!0}))}function ft(){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"),Ge()}),null)}function $e(){if(typeof document>"u")return;document.querySelectorAll("model-viewer").forEach(t=>{We(t)})}const ke=new WeakSet;let ht=0;function We(o){if(!o||ke.has(o))return null;ke.add(o),console.debug("[gltf-progressive] found new model-viewer..."+ ++ht+`
8
- `,o.getAttribute("src"));let t=null,e=null,s=null;for(let n=o;n!=null;n=Object.getPrototypeOf(n)){const r=Object.getOwnPropertySymbols(n),i=r.find(c=>c.toString()=="Symbol(renderer)"),a=r.find(c=>c.toString()=="Symbol(scene)"),l=r.find(c=>c.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=o[i].threeRenderer),!e&&a!=null&&(e=o[a]),!s&&l!=null&&(s=o[l])}if(t&&e){let n=function(){if(s){let i=0,a=setInterval(()=>{if(i++>5){clearInterval(a);return}s==null||s.call(o)},300)}};console.debug("[gltf-progressive] setup model-viewer");const r=A.get(t,{engine:"model-viewer"});return A.addPlugin(new gt),r.enable(),r.addEventListener("changed",()=>{s==null||s.call(o)}),o.addEventListener("model-visibility",i=>{i.detail.visible&&(s==null||s.call(o))}),o.addEventListener("load",()=>{n()}),()=>{r.disable()}}return null}class gt{constructor(){u(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(t,e,s,n){this.tryParseMeshLOD(e,n),this.tryParseTextureLOD(e,n)}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[he]==!0)return;e[he]=!0;const s=this.tryGetCurrentGLTF(t),n=this.tryGetCurrentModelViewer(t),r=this.getUrl(n);if(r&&s&&e.material){let i=function(l){var d,p,f;if(l[he]==!0)return;l[he]=!0,l.userData&&(l.userData.LOD=-1);const c=Object.keys(l);for(let M=0;M<c.length;M++){const D=c[M],C=l[D];if((C==null?void 0:C.isTexture)===!0){const S=(p=(d=C.userData)==null?void 0:d.associations)==null?void 0:p.textures;if(S==null)continue;const F=s.parser.json.textures[S];if(!F){console.warn("Texture data not found for texture index "+S);continue}if((f=F==null?void 0:F.extensions)!=null&&f[W]){const Z=F.extensions[W];Z&&r&&T.registerTexture(r,C,Z.lods.length,S,Z)}}}};const a=e.material;if(Array.isArray(a))for(const l of a)i(l);else i(a)}}tryParseMeshLOD(t,e){var i,a;if(e[Be]==!0)return;e[Be]=!0;const s=this.tryGetCurrentModelViewer(t),n=this.getUrl(s);if(!n)return;const r=(a=(i=e.userData)==null?void 0:i.gltfExtensions)==null?void 0:a[W];if(r&&n){const l=e.uuid;T.registerMesh(n,l,e,0,r.lods.length,r)}}}function Xe(o,t,e,s){Te(t),Ae(e),Ce(e,{progressive:!0,...s==null?void 0:s.hints}),e.register(r=>new T(r,o));const n=A.get(t);return(s==null?void 0:s.enableLODsManager)!==!1&&n.enable(),n}Ge();if(!at){const o={gltfProgressive:{useNeedleProgressive:Xe,LODsManager:A,configureLoader:Ce,getRaycastMesh:ie,useRaycastMeshes:qe}};if(!globalThis.Needle)globalThis.Needle=o;else for(const t in o)globalThis.Needle[t]=o[t]}exports.EXTENSION_NAME=W;exports.LODsManager=A;exports.NEEDLE_progressive=T;exports.VERSION=Re;exports.addDracoAndKTX2Loaders=Ae;exports.configureLoader=Ce;exports.createLoaders=Te;exports.getRaycastMesh=ie;exports.patchModelViewer=Ge;exports.registerRaycastMesh=Ve;exports.setDracoDecoderLocation=Fe;exports.setKTX2TranscoderLocation=Ne;exports.useNeedleProgressive=Xe;exports.useRaycastMeshes=qe;
5
+ `,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 ut{url;key;level;index;constructor(t,e,r,n){this.url=t,this.key=e,this.level=r,n!=null&&(this.index=n)}}class le{static addPromise=(t,e,r,n)=>{n.forEach(s=>{s.add(t,e,r)})};frame_start;frame_capture_end;ready;_resolve;_signal;get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}_resolved=!1;_addedCount=0;_resolvedCount=0;_awaiting=[];_maxPromisesPerObject=1;constructor(t,e){const n=Math.max(e.frames??2,2);this.frame_start=t,this.frame_capture_end=t+n,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._signal?.aborted||this._currentFrame>this.frame_capture_end&&this._awaiting.length===0)&&this.resolveNow()}_seen=new WeakMap;add(t,e,r){if(this._resolved){p&&console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}if(!(this._currentFrame>this.frame_capture_end)){if(this._maxPromisesPerObject>=1)if(this._seen.has(e)){let n=this._seen.get(e);if(n>=this._maxPromisesPerObject){p&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(e,n+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 C=z("debugprogressive"),dt=z("noprogressive"),ue=Symbol("Needle:LODSManager"),de=Symbol("Needle:LODState"),U=Symbol("Needle:CurrentLOD"),P={mesh_lod:-1,texture_lod:-1};class L{static debugDrawLine;static overrideGlobalLodLevel;static getObjectLODState(t){return t[de]}static addPlugin(t){E.push(t)}static removePlugin(t){const e=E.indexOf(t);e>=0&&E.splice(e,1)}static get(t,e){if(t[ue])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[ue];const r=new L(t,{engine:"unknown",...e});return t[ue]=r,r}renderer;context;projectionScreenMatrix=new d.Matrix4;get plugins(){return E}targetTriangleDensity=2e5;skinnedMeshAutoUpdateBoundsInterval=30;updateInterval="auto";#e=1;pause=!1;manual=!1;_newPromiseGroups=[];_promiseGroupIds=0;awaitLoading(t){const e=this._promiseGroupIds++,r=new le(this.#s,{...t});this._newPromiseGroups.push(r);const n=performance.now();return r.ready.finally(()=>{const s=this._newPromiseGroups.indexOf(r);s>=0&&(this._newPromiseGroups.splice(s,1),_e()&&performance.measure("LODsManager:awaitLoading",{start:n,detail:{id:e,name:t?.name,awaited:r.awaitedCount,resolved:r.resolvedCount}}))}),r.ready}_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){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}constructor(t,e){this.renderer=t,this.context={...e}}#t;#o=new d.Clock;#s=0;#n=0;#i=0;#r=0;_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;re(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,e.#s+=1,e.#n=e.#o.getDelta(),e.#i+=e.#n,e._fpsBuffer.shift(),e._fpsBuffer.push(1/e.#n),e.#r=e._fpsBuffer.reduce((l,a)=>l+a)/e._fpsBuffer.length,C&&e.#s%200===0&&console.log("FPS",Math.round(e.#r),"Interval:",e.#e));const i=t++;e.#t.call(this,r,n),e.onAfterRender(r,n,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.renderer.renderLists.get(t,0).opaque;let i=!0;if(s.length===1){const l=s[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(dt||(this.updateInterval==="auto"?this.#r<40&&this.#e<10?(this.#e+=1,C&&console.warn("↓ Reducing LOD updates",this.#e,this.#r.toFixed(0))):this.#r>=60&&this.#e>1&&(this.#e-=1,C&&console.warn("↑ 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.renderer.renderLists.get(t,0),n=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const s=this.targetTriangleDensity;for(const a of n){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")){C&&(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}if(C==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const f=Math.random()*16777215,m=new d.MeshStandardMaterial({color:f});a.object.material=m}const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,s)}const i=r.transparent;for(const a of i){const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,s)}const l=r.transmissive;for(const a of l){const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,s)}}updateLODs(t,e,r,n){r.userData||(r.userData={});let s=r[de];if(s||(s=new ct,r[de]=s),s.frames++<2)return;for(const l of E)l.onBeforeUpdateLOD?.(this.renderer,t,e,r);const i=L.overrideGlobalLodLevel!==void 0?L.overrideGlobalLodLevel:N;i>=0?(P.mesh_lod=i,P.texture_lod=i):(this.calculateLodLevel(e,r,s,n,P),P.mesh_lod=Math.round(P.mesh_lod),P.texture_lod=Math.round(P.texture_lod)),P.mesh_lod>=0&&this.loadProgressiveMeshes(r,P.mesh_lod),r.material&&P.texture_lod>=0&&this.loadProgressiveTextures(r.material,P.texture_lod,i),p&&r.material&&!r.isGizmo&&ke(r.material);for(const l of E)l.onAfterUpdatedLOD?.(this.renderer,t,e,r,P);s.lastLodLevel_Mesh=P.mesh_lod,s.lastLodLevel_Texture=P.texture_lod}loadProgressiveTextures(t,e,r){if(!t)return;if(Array.isArray(t)){for(const s of t)this.loadProgressiveTextures(s,e);return}let n=!1;if((t[U]===void 0||e<t[U])&&(n=!0),r!==void 0&&r>=0&&(n=t[U]!=r,e=r),n){t[U]=e;const s=x.assignTextureLOD(t,e).then(i=>{this._lodchangedlisteners.forEach(l=>l({type:"texture",level:e,object:t}))});le.addPromise("texture",t,s,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[U]!==e;const n=t["DEBUG:LOD"];if(n!=null&&(r=t[U]!=n,e=n),r){t[U]=e;const s=t.geometry,i=x.assignMeshLOD(t,e).then(l=>(l&&t[U]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(a=>a({type:"mesh",level:e,object:t})),l));return le.addPromise("mesh",t,i,this._newPromiseGroups),i}return Promise.resolve(null)}_sphere=new d.Sphere;_tempBox=new d.Box3;_tempBox2=new d.Box3;tempMatrix=new d.Matrix4;_tempWorldPosition=new d.Vector3;_tempBoxSize=new d.Vector3;_tempBox2Size=new d.Vector3;static corner0=new d.Vector3;static corner1=new d.Vector3;static corner2=new d.Vector3;static corner3=new d.Vector3;static _tempPtInside=new d.Vector3;static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,i=(r.y+n.y)*.5;return this._tempPtInside.set(s,i,r.z).applyMatrix4(e).z<0}static skinnedMeshBoundsFrameOffsetCounter=0;static $skinnedMeshBoundsOffset=Symbol("gltf-progressive-skinnedMeshBoundsOffset");calculateLodLevel(t,e,r,n,s){if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let l=10+1,a=!1;if(C&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=x.getMeshLODExtension(e.geometry)?.lods,f=x.getPrimitiveIndex(e.geometry),m=u&&u.length>0,v=x.getMaterialMinMaxLODsCount(e.material),M=v.min_count!==1/0&&v.min_count>=0&&v.max_count>=0;if(!m&&!M){s.mesh_lod=0,s.texture_lod=0;return}m||(a=!0,l=0);const I=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let F=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const c=e;if(!c.boundingBox)c.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0){if(!c[L.$skinnedMeshBoundsOffset]){const S=L.skinnedMeshBoundsFrameOffsetCounter++;c[L.$skinnedMeshBoundsOffset]=S}const w=c[L.$skinnedMeshBoundsOffset];if((r.frames+w)%this.skinnedMeshAutoUpdateBoundsInterval===0){const S=q(c),B=c.geometry;S&&(c.geometry=S),c.computeBoundingBox(),c.geometry=B}}F=c.boundingBox}if(F){const c=t;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 h=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(h)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(F),this._tempBox.applyMatrix4(e.matrixWorld),c.isPerspectiveCamera&&L.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&c.isPerspectiveCamera&&c.fov>70){const h=this._tempBox.min,g=this._tempBox.max;let D=h.x,O=h.y,G=g.x,j=g.y;const H=2,se=1.5,Q=(h.x+g.x)*.5,J=(h.y+g.y)*.5;D=(D-Q)*H+Q,O=(O-J)*H+J,G=(G-Q)*H+Q,j=(j-J)*H+J;const Ge=D<0&&G>0?0:Math.min(Math.abs(h.x),Math.abs(g.x)),$e=O<0&&j>0?0:Math.min(Math.abs(h.y),Math.abs(g.y)),ne=Math.max(Ge,$e);r.lastCentrality=(se-ne)*(se-ne)*(se-ne)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&I>0&&w.multiplyScalar(I/screen.availHeight),t.isPerspectiveCamera?w.x*=t.aspect:t.isOrthographicCamera;const S=t.matrixWorldInverse,B=this._tempBox2;B.copy(F),B.applyMatrix4(e.matrixWorld),B.applyMatrix4(S);const b=B.getSize(this._tempBox2Size),W=Math.max(b.x,b.y);if(Math.max(w.x,w.y)!=0&&W!=0&&(w.z=b.z/Math.max(b.x,b.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,C&&L.debugDrawLine){const h=this.tempMatrix.copy(this.projectionScreenMatrix);h.invert();const g=L.corner0,D=L.corner1,O=L.corner2,G=L.corner3;g.copy(this._tempBox.min),D.copy(this._tempBox.max),D.x=g.x,O.copy(this._tempBox.max),O.y=g.y,G.copy(this._tempBox.max);const j=(g.z+G.z)*.5;g.z=D.z=O.z=G.z=j,g.applyMatrix4(h),D.applyMatrix4(h),O.applyMatrix4(h),G.applyMatrix4(h),L.debugDrawLine(g,D,255),L.debugDrawLine(g,O,255),L.debugDrawLine(D,G,255),L.debugDrawLine(O,G,255)}let _=999;if(u&&r.lastScreenCoverage>0)for(let h=0;h<u.length;h++){const g=u[h],O=(g.densities?.[f]||g.density||1e-5)/r.lastScreenCoverage;if(f>0&&_e()&&!g.densities&&!globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]&&(window["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.")),O<n){_=h;break}}_<l&&(l=_,a=!0)}if(a?s.mesh_lod=l:s.mesh_lod=r.lastLodLevel_Mesh,C&&s.mesh_lod!=r.lastLodLevel_Mesh){const w=u?.[s.mesh_lod];w&&console.debug(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${s.mesh_lod} (density: ${w.densities?.[f].toFixed(0)}) | ${e.name}`)}if(M){const c="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=v.max_count-1,C){const w=v.lods[v.max_count-1];C&&console.log(`First Texture LOD ${s.texture_lod} (${w.max_height}px) - ${e.name}`)}}else{const w=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let S=r.lastScreenCoverage*4;this.context?.engine==="model-viewer"&&(S*=1.5);const b=I/window.devicePixelRatio*S;let W=!1;for(let T=v.lods.length-1;T>=0;T--){const _=v.lods[T];if(!(c&&_.max_height>=2048)&&!(Ae()&&_.max_height>4096)&&(_.max_height>b||!W&&T===0)){if(W=!0,s.texture_lod=T,C&&s.texture_lod<r.lastLodLevel_Texture){const y=_.max_height;console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${s.texture_lod} = ${y}px
6
+ Screensize: ${b.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${w.toFixed(1)}
7
+ ${e.name}`)}break}}}}else s.texture_lod=0}}class ct{frames=0;lastLodLevel_Mesh=-1;lastLodLevel_Texture=-1;lastScreenCoverage=0;lastScreenspaceVolume=new d.Vector3;lastCentrality=0}const ve=Symbol("NEEDLE_mesh_lod"),Z=Symbol("NEEDLE_texture_lod");let ce=null;function we(){const o=ft();o&&(o.mapURLs(function(t){return Me(),t}),Me(),ce?.disconnect(),ce=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Re(r)})})}),ce.observe(document,{childList:!0,subtree:!0}))}function ft(){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"),we()}),null)}function Me(){if(typeof document>"u")return;document.querySelectorAll("model-viewer").forEach(t=>{Re(t)})}const be=new WeakSet;let ht=0;function Re(o){if(!o||be.has(o))return null;be.add(o),console.debug("[gltf-progressive] found new model-viewer..."+ ++ht+`
8
+ `,o.getAttribute("src"));let t=null,e=null,r=null;for(let n=o;n!=null;n=Object.getPrototypeOf(n)){const s=Object.getOwnPropertySymbols(n),i=s.find(u=>u.toString()=="Symbol(renderer)"),l=s.find(u=>u.toString()=="Symbol(scene)"),a=s.find(u=>u.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=o[i].threeRenderer),!e&&l!=null&&(e=o[l]),!r&&a!=null&&(r=o[a])}if(t&&e){let n=function(){if(r){let i=0,l=setInterval(()=>{if(i++>5){clearInterval(l);return}r?.call(o)},300)}};console.debug("[gltf-progressive] setup model-viewer");const s=L.get(t,{engine:"model-viewer"});return L.addPlugin(new gt),s.enable(),s.addEventListener("changed",()=>{r?.call(o)}),o.addEventListener("model-visibility",i=>{i.detail.visible&&r?.call(o)}),o.addEventListener("load",()=>{n()}),()=>{s.disable()}}return null}class gt{_didWarnAboutMissingUrl=!1;onBeforeUpdateLOD(t,e,r,n){this.tryParseMeshLOD(e,n),this.tryParseTextureLOD(e,n)}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[Z]==!0)return;e[Z]=!0;const r=this.tryGetCurrentGLTF(t),n=this.tryGetCurrentModelViewer(t),s=this.getUrl(n);if(s&&r&&e.material){let i=function(a){if(a[Z]==!0)return;a[Z]=!0,a.userData&&(a.userData.LOD=-1);const u=Object.keys(a);for(let f=0;f<u.length;f++){const m=u[f],v=a[m];if(v?.isTexture===!0){const M=v.userData?.associations?.textures;if(M==null)continue;const I=r.parser.json.textures[M];if(!I){console.warn("Texture data not found for texture index "+M);continue}if(I?.extensions?.[$]){const F=I.extensions[$];F&&s&&x.registerTexture(s,v,F.lods.length,M,F)}}}};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),n=this.getUrl(r);if(!n)return;const s=e.userData?.gltfExtensions?.[$];if(s&&n){const i=e.uuid;x.registerMesh(n,i,e,0,s.lods.length,s)}}}function Be(o,t,e,r){re(t),me(e),ye(e,{progressive:!0,...r?.hints}),e.register(s=>new x(s,o));const n=L.get(t);return r?.enableLODsManager!==!1&&n.enable(),n}we();if(!tt){const o={gltfProgressive:{useNeedleProgressive:Be,LODsManager:L,configureLoader:ye,getRaycastMesh:q,useRaycastMeshes:Ce}};if(!globalThis.Needle)globalThis.Needle=o;else for(const t in o)globalThis.Needle[t]=o[t]}exports.EXTENSION_NAME=$;exports.LODsManager=L;exports.NEEDLE_progressive=x;exports.VERSION=De;exports.addDracoAndKTX2Loaders=me;exports.configureLoader=ye;exports.createLoaders=re;exports.getRaycastMesh=q;exports.patchModelViewer=we;exports.registerRaycastMesh=Ie;exports.setDracoDecoderLocation=Se;exports.setKTX2TranscoderLocation=Te;exports.useNeedleProgressive=Be;exports.useRaycastMeshes=Ce;
@@ -122,7 +122,10 @@ export declare class NEEDLE_progressive implements GLTFLoaderPlugin {
122
122
  private static readonly previouslyLoaded;
123
123
  /** this contains the geometry/textures that were originally loaded */
124
124
  private static readonly lowresCache;
125
+ private static readonly workers;
126
+ private static _workersIndex;
125
127
  private static getOrLoadLOD;
128
+ private static maxConcurrent;
126
129
  private static queue;
127
130
  private static assignLODInformation;
128
131
  private static getAssignedLODInformation;