@needle-tools/gltf-progressive 1.2.2-alpha.2 → 1.2.2-alpha.3

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,7 +1,7 @@
1
- var we=Object.defineProperty,Oe=(t,e,r)=>e in t?we(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(Oe(t,typeof e!="symbol"?e+"":e,r),r);import{BufferGeometry as Z,Mesh as N,Material as be,Texture as z,TextureLoader as Se,Matrix4 as me,Frustum as Te,Sphere as Ee,Box3 as pe,Vector3 as R}from"three";import{GLTFLoader as Ae}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as Ie}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Pe}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Be}from"three/examples/jsm/loaders/KTX2Loader.js";const oe="";globalThis.GLTF_PROGRESSIVE_VERSION=oe,console.debug(`[gltf-progressive] version ${oe}`);let J="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ne="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(J+"draco_decoder.js",{method:"head"}).catch(t=>{J="./include/draco/",ne="./include/ktx2/"});function Ce(t){J=t}function Re(t){ne=t}let U,ie,V;function ae(t){U||(U=new Pe,U.setDecoderPath(J),U.setDecoderConfig({type:"js"})),V||(V=new Be,V.setTranscoderPath(ne)),ie||(ie=Ie),t?V.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function le(t){t.dracoLoader||t.setDRACOLoader(U),t.ktx2Loader||t.setKTX2Loader(V),t.meshoptDecoder||t.setMeshoptDecoder(ie)}q("debugprogressive");function q(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function ke(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let Q;function je(){return Q!==void 0||(Q=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),q("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",Q)),Q}const ue=Symbol("needle:raycast-mesh");function ee(t){return t?.[ue]instanceof Z?t[ue]:null}function xe(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ee(t)){const r=$e(e);r.userData={isRaycastMesh:!0},t[ue]=r}}function Ge(t=!0){if(t){if(K)return;const e=K=N.prototype.raycast;N.prototype.raycast=function(r,n){const o=this,s=ee(o);let i;s&&o.isMesh&&(i=o.geometry,o.geometry=s),e.call(this,r,n),i&&(o.geometry=i)}}else{if(!K)return;N.prototype.raycast=K,K=null}}let K=null;function $e(t){const e=new Z;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const j=new Array,B="NEEDLE_progressive",y=q("debugprogressive"),ce=Symbol("needle-progressive-texture"),X=new Map,de=new Set;if(y){let t=function(){e+=1,console.log("Toggle LOD level",e,X),X.forEach((o,s)=>{for(const i of o.keys){const a=s[i];if(a!=null){if(a.isBufferGeometry===!0){const l=w.getMeshLODInformation(a),u=l?Math.min(e,l.lods.length):0;s["DEBUG:LOD"]=e,w.assignMeshLOD(s,u),l&&(r=Math.max(r,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,w.assignTextureLOD(s,e);break}}}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",o=>{o.key==="p"&&t(),o.key==="w"&&(n=!n,de&&de.forEach(s=>{s.name!="BackgroundCubeMaterial"&&s.glyphMap==null&&"wireframe"in s&&(s.wireframe=n)}))})}function ye(t,e,r){var n;if(!y)return;X.has(t)||X.set(t,{keys:[],sourceId:r});const o=X.get(t);((n=o?.keys)==null?void 0:n.includes(e))==!1&&o.keys.push(e)}const M=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(this,"loadMesh",r=>{var n,o;if(this._isLoadingMesh)return null;const s=(o=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:o[B];return s?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var a;return this._isLoadingMesh=!1,i&&M.registerMesh(this.url,s.guid,i,(a=s.lods)==null?void 0:a.length,void 0,s),i})):null}),y&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return B}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",o=t[n];if(o!=null)return o;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(y==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const a of Object.keys(i.uniforms)){const l=i.uniforms[a].value;l?.isTexture===!0&&s(l,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const a=t[i];a?.isTexture===!0&&s(a,e)}return t[n]=e,e;function s(i,a){const l=r.getAssignedLODInformation(i);if(l){const u=r.lodInfos.get(l.key);if(u&&u.lods){a.min_count=Math.min(a.min_count,u.lods.length),a.max_count=Math.max(a.max_count,u.lods.length);for(let g=0;g<u.lods.length;g++){const h=u.lods[g];h.width&&(a.lods[g]=a.lods[g]||{min_height:1/0,max_height:0},a.lods[g].min_height=Math.min(a.lods[g].min_height,h.height),a.lods[g].max_height=Math.max(a.lods[g].max_height,h.height))}}}}}static hasLODLevelAvailable(t,e){var r;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 n,o;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const s=n.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){var r;if(!t)return Promise.resolve(null);if(t instanceof N||t.isMesh===!0){const n=t.geometry,o=this.getAssignedLODInformation(n);if(!o)return Promise.resolve(null);for(const s of j)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,M.getOrLoadLOD(n,e).then(s=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(s)){const i=o.index||0;s=s[i]}s&&n!=s&&(s?.isBufferGeometry?(t.geometry=s,y&&ye(t,"geometry",o.url)):y&&console.error("Invalid LOD geometry",s))}return s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else y&&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 instanceof be||t.isMaterial===!0){const r=t,n=[],o=new Array;if(y&&de.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const i of Object.keys(s.uniforms)){const a=s.uniforms[i].value;if(a?.isTexture===!0){const l=this.assignTextureLODForSlot(a,e,r,i);n.push(l),o.push(i)}}}else for(const s of Object.keys(r)){const i=r[s];if(i?.isTexture===!0){const a=this.assignTextureLODForSlot(i,e,r,s);n.push(a),o.push(s)}}return Promise.all(n).then(s=>{const i=new Array;for(let a=0;a<s.length;a++){const l=s[a],u=o[a];l&&l.isTexture===!0?i.push({material:r,slot:u,texture:l,level:e}):i.push({material:r,slot:u,texture:null,level:e})}return i})}if(t instanceof z||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):M.getOrLoadLOD(t,e).then(o=>{if(Array.isArray(o))return null;if(o?.isTexture===!0){if(o!=t){if(r&&n){const s=r[n];if(s){const i=this.getAssignedLODInformation(s);if(i&&i?.level<e)return y==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,s,o),null}r[n]=o}if(y&&n&&r){const s=this.getAssignedLODInformation(t);s&&ye(r,n,s.url)}}return o}else y=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(o=>(console.error("Error loading LOD",t,o),null))}afterRoot(t){var e,r;return y&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,o)=>{var s;if(n!=null&&n.extensions){const i=n?.extensions[B];if(i){if(!i.lods){y&&console.warn("Texture has no LODs",i);return}let a=!1;for(const l of this.parser.associations.keys())l.isTexture===!0&&this.parser.associations.get(l).textures===o&&(a=!0,M.registerTexture(this.url,l,(s=i.lods)==null?void 0:s.length,o,i));a||this.parser.getDependency("texture",o).then(l=>{var u;l&&M.registerTexture(this.url,l,(u=i.lods)==null?void 0:u.length,o,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.extensions[B];if(s&&s.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const a=this.parser.associations.get(i);a.meshes===o&&M.registerMesh(this.url,s.guid,i,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var r,n,o,s;const i=y=="verbose",a=t.userData.LODS;if(!a)return null;const l=a?.key;let u;if(t.isTexture===!0){const g=t;g.source&&g.source[ce]&&(u=g.source[ce])}if(u||(u=M.lodInfos.get(l)),u){if(e>0){let f=!1;const S=Array.isArray(u.lods);if(S&&e>=u.lods.length?f=!0:S||(f=!0),f)return this.lowresCache.get(l)}const g=Array.isArray(u.lods)?(r=u.lods[e])==null?void 0:r.path:u.lods;if(!g)return y&&!u["missing:uri"]&&(u["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,u)),null;const h=ke(a.url,g);if(h.endsWith(".glb")||h.endsWith(".gltf")){if(!u.guid)return console.warn("missing pointer for glb/gltf texture",u),null;const f=h+"_"+u.guid,S=this.previouslyLoaded.get(f);if(S!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let m=await S.catch(b=>(console.error(`Error loading LOD ${e} from ${h}
2
- `,b),null)),x=!1;if(m==null||(m instanceof z&&t instanceof z?(n=m.image)!=null&&n.data||(o=m.source)!=null&&o.data?m=this.copySettings(t,m):(x=!0,this.previouslyLoaded.delete(f)):m instanceof Z&&t instanceof Z&&((s=m.attributes.position)!=null&&s.array||(x=!0,this.previouslyLoaded.delete(f)))),!x)return m}const D=u,T=new Promise(async(m,x)=>{const b=new Ae;le(b),y&&(await new Promise(p=>setTimeout(p,1e3)),i&&console.warn("Start loading (delayed) "+h,D.guid));let E=h;if(D&&Array.isArray(D.lods)){const p=D.lods[e];p.hash&&(E+="?v="+p.hash)}const L=await b.loadAsync(E).catch(p=>(console.error(`Error loading LOD ${e} from ${h}
3
- `,p),null));if(!L)return null;const F=L.parser;i&&console.log("Loading finished "+h,D.guid);let I=0;if(L.parser.json.textures){let p=!1;for(const d of L.parser.json.textures){if(d!=null&&d.extensions){const v=d?.extensions[B];if(v!=null&&v.guid&&v.guid===D.guid){p=!0;break}}I++}if(p){let d=await F.getDependency("texture",I);return d&&M.assignLODInformation(a.url,d,l,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+d.name+'"',h,I,d,f),t instanceof z&&(d=this.copySettings(t,d)),d&&(d.guid=D.guid),m(d)}else y&&console.warn("Could not find texture with guid",D.guid,L.parser.json)}if(I=0,L.parser.json.meshes){let p=!1;for(const d of L.parser.json.meshes){if(d!=null&&d.extensions){const v=d?.extensions[B];if(v!=null&&v.guid&&v.guid===D.guid){p=!0;break}}I++}if(p){const d=await F.getDependency("mesh",I),v=D;if(i&&console.log(`Loaded Mesh "${d.name}"`,h,I,d,f),d.isMesh===!0){const _=d.geometry;return M.assignLODInformation(a.url,_,l,e,void 0,v.density),m(_)}else{const _=new Array;for(let O=0;O<d.children.length;O++){const k=d.children[O];if(k.isMesh===!0){const G=k.geometry;M.assignLODInformation(a.url,G,l,e,O,v.density),_.push(G)}}return m(_)}}else y&&console.warn("Could not find mesh with guid",D.guid,L.parser.json)}return m(null)});return this.previouslyLoaded.set(f,T),await T}else if(t instanceof z){i&&console.log("Load texture from uri: "+h);const f=await new Se().loadAsync(h);return f?(f.guid=u.guid,f.flipY=!1,f.needsUpdate=!0,f.colorSpace=t.colorSpace,i&&console.log(u,f)):y&&console.warn("failed loading",h),f}}else y&&console.warn(`Can not load LOD ${e}: no LOD info found for "${l}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,o,s){if(!e)return;e.userData||(e.userData={});const i=new Fe(t,r,n,o,s);e.userData.LODS=i}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e=e.clone(),y&&console.warn(`Copying texture settings
1
+ var we=Object.defineProperty,Oe=(t,e,r)=>e in t?we(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(Oe(t,typeof e!="symbol"?e+"":e,r),r);import{BufferGeometry as Z,Mesh as N,Material as be,Texture as z,TextureLoader as Se,Matrix4 as me,Frustum as Te,Sphere as Ee,Box3 as pe,Vector3 as R}from"three";import{GLTFLoader as Ae}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as Ie}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Pe}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Be}from"three/examples/jsm/loaders/KTX2Loader.js";const oe="";globalThis.GLTF_PROGRESSIVE_VERSION=oe,console.debug(`[gltf-progressive] version ${oe}`);let J="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ne="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(J+"draco_decoder.js",{method:"head"}).catch(t=>{J="./include/draco/",ne="./include/ktx2/"});function Ce(t){J=t}function Re(t){ne=t}let U,ie,V;function ae(t){U||(U=new Pe,U.setDecoderPath(J),U.setDecoderConfig({type:"js"})),V||(V=new Be,V.setTranscoderPath(ne)),ie||(ie=Ie),t?V.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function le(t){t.dracoLoader||t.setDRACOLoader(U),t.ktx2Loader||t.setKTX2Loader(V),t.meshoptDecoder||t.setMeshoptDecoder(ie)}q("debugprogressive");function q(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function ke(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let Q;function je(){return Q!==void 0||(Q=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),q("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",Q)),Q}const ue=Symbol("needle:raycast-mesh");function ee(t){return t?.[ue]instanceof Z?t[ue]:null}function xe(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ee(t)){const r=$e(e);r.userData={isRaycastMesh:!0},t[ue]=r}}function Ge(t=!0){if(t){if(K)return;const e=K=N.prototype.raycast;N.prototype.raycast=function(r,n){const s=this,o=ee(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),e.call(this,r,n),i&&(s.geometry=i)}}else{if(!K)return;N.prototype.raycast=K,K=null}}let K=null;function $e(t){const e=new Z;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const j=new Array,B="NEEDLE_progressive",y=q("debugprogressive"),ce=Symbol("needle-progressive-texture"),X=new Map,de=new Set;if(y){let t=function(){e+=1,console.log("Toggle LOD level",e,X),X.forEach((s,o)=>{for(const i of s.keys){const a=o[i];if(a!=null){if(a.isBufferGeometry===!0){const l=w.getMeshLODInformation(a),u=l?Math.min(e,l.lods.length):0;o["DEBUG:LOD"]=e,w.assignMeshLOD(o,u),l&&(r=Math.max(r,l.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,w.assignTextureLOD(o,e);break}}}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(n=!n,de&&de.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function ye(t,e,r){var n;if(!y)return;X.has(t)||X.set(t,{keys:[],sourceId:r});const s=X.get(t);((n=s?.keys)==null?void 0:n.includes(e))==!1&&s.keys.push(e)}const M=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(this,"loadMesh",r=>{var n,s;if(this._isLoadingMesh)return null;const o=(s=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:s[B];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var a;return this._isLoadingMesh=!1,i&&M.registerMesh(this.url,o.guid,i,(a=o.lods)==null?void 0:a.length,void 0,o),i})):null}),y&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return B}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}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 i of t)this.getMaterialMinMaxLODsCount(i,e);return t[n]=e,e}if(y==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const a of Object.keys(i.uniforms)){const l=i.uniforms[a].value;l?.isTexture===!0&&o(l,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const a=t[i];a?.isTexture===!0&&o(a,e)}return t[n]=e,e;function o(i,a){const l=r.getAssignedLODInformation(i);if(l){const u=r.lodInfos.get(l.key);if(u&&u.lods){a.min_count=Math.min(a.min_count,u.lods.length),a.max_count=Math.max(a.max_count,u.lods.length);for(let f=0;f<u.lods.length;f++){const h=u.lods[f];h.width&&(a.lods[f]=a.lods[f]||{min_height:1/0,max_height:0},a.lods[f].min_height=Math.min(a.lods[f].min_height,h.height),a.lods[f].max_height=Math.max(a.lods[f].max_height,h.height))}}}}}static hasLODLevelAvailable(t,e){var r;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,s;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const o=n.userData.LODS;if(s=this.lodInfos.get(o.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof N||t.isMesh===!0){const n=t.geometry,s=this.getAssignedLODInformation(n);if(!s)return Promise.resolve(null);for(const o of j)(r=o.onBeforeGetLODMesh)==null||r.call(o,t,e);return t["LOD:requested level"]=e,M.getOrLoadLOD(n,e).then(o=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(o)){const i=s.index||0;o=o[i]}o&&n!=o&&(o?.isBufferGeometry?(t.geometry=o,y&&ye(t,"geometry",s.url)):y&&console.error("Invalid LOD geometry",o))}return o}).catch(o=>(console.error("Error loading mesh LOD",t,o),null))}else y&&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 instanceof be||t.isMaterial===!0){const r=t,n=[],s=new Array;if(y&&de.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const o=r;for(const i of Object.keys(o.uniforms)){const a=o.uniforms[i].value;if(a?.isTexture===!0){const l=this.assignTextureLODForSlot(a,e,r,i);n.push(l),s.push(i)}}}else for(const o of Object.keys(r)){const i=r[o];if(i?.isTexture===!0){const a=this.assignTextureLODForSlot(i,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const i=new Array;for(let a=0;a<o.length;a++){const l=o[a],u=s[a];l&&l.isTexture===!0?i.push({material:r,slot:u,texture:l,level:e}):i.push({material:r,slot:u,texture:null,level:e})}return i})}if(t instanceof z||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):M.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t){if(r&&n){const o=r[n];if(o){const i=this.getAssignedLODInformation(o);if(i&&i?.level<e)return y==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,o,s),null}r[n]=s}if(y&&n&&r){const o=this.getAssignedLODInformation(t);o&&ye(r,n,o.url)}}return s}else y=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return y&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,s)=>{var o;if(n!=null&&n.extensions){const i=n?.extensions[B];if(i){if(!i.lods){y&&console.warn("Texture has no LODs",i);return}let a=!1;for(const l of this.parser.associations.keys())l.isTexture===!0&&this.parser.associations.get(l).textures===s&&(a=!0,M.registerTexture(this.url,l,(o=i.lods)==null?void 0:o.length,s,i));a||this.parser.getDependency("texture",s).then(l=>{var u;l&&M.registerTexture(this.url,l,(u=i.lods)==null?void 0:u.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,s)=>{if(n!=null&&n.extensions){const o=n?.extensions[B];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const a=this.parser.associations.get(i);a.meshes===s&&M.registerMesh(this.url,o.guid,i,o.lods.length,a.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var r,n,s,o;const i=y=="verbose",a=t.userData.LODS;if(!a)return null;const l=a?.key;let u;if(t.isTexture===!0){const f=t;f.source&&f.source[ce]&&(u=f.source[ce])}if(u||(u=M.lodInfos.get(l)),u){if(e>0){let g=!1;const S=Array.isArray(u.lods);if(S&&e>=u.lods.length?g=!0:S||(g=!0),g)return this.lowresCache.get(l)}const f=Array.isArray(u.lods)?(r=u.lods[e])==null?void 0:r.path:u.lods;if(!f)return y&&!u["missing:uri"]&&(u["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,u)),null;const h=ke(a.url,f);if(h.endsWith(".glb")||h.endsWith(".gltf")){if(!u.guid)return console.warn("missing pointer for glb/gltf texture",u),null;const g=h+"_"+u.guid,S=this.previouslyLoaded.get(g);if(S!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${g}`);let m=await S.catch(b=>(console.error(`Error loading LOD ${e} from ${h}
2
+ `,b),null)),x=!1;if(m==null||(m instanceof z&&t instanceof z?(n=m.image)!=null&&n.data||(s=m.source)!=null&&s.data?m=this.copySettings(t,m):(x=!0,this.previouslyLoaded.delete(g)):m instanceof Z&&t instanceof Z&&((o=m.attributes.position)!=null&&o.array||(x=!0,this.previouslyLoaded.delete(g)))),!x)return m}const D=u,T=new Promise(async(m,x)=>{const b=new Ae;le(b),y&&(await new Promise(p=>setTimeout(p,1e3)),i&&console.warn("Start loading (delayed) "+h,D.guid));let E=h;if(D&&Array.isArray(D.lods)){const p=D.lods[e];p.hash&&(E+="?v="+p.hash)}const L=await b.loadAsync(E).catch(p=>(console.error(`Error loading LOD ${e} from ${h}
3
+ `,p),null));if(!L)return null;const F=L.parser;i&&console.log("Loading finished "+h,D.guid);let I=0;if(L.parser.json.textures){let p=!1;for(const d of L.parser.json.textures){if(d!=null&&d.extensions){const v=d?.extensions[B];if(v!=null&&v.guid&&v.guid===D.guid){p=!0;break}}I++}if(p){let d=await F.getDependency("texture",I);return d&&M.assignLODInformation(a.url,d,l,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+d.name+'"',h,I,d,g),t instanceof z&&(d=this.copySettings(t,d)),d&&(d.guid=D.guid),m(d)}else y&&console.warn("Could not find texture with guid",D.guid,L.parser.json)}if(I=0,L.parser.json.meshes){let p=!1;for(const d of L.parser.json.meshes){if(d!=null&&d.extensions){const v=d?.extensions[B];if(v!=null&&v.guid&&v.guid===D.guid){p=!0;break}}I++}if(p){const d=await F.getDependency("mesh",I),v=D;if(i&&console.log(`Loaded Mesh "${d.name}"`,h,I,d,g),d.isMesh===!0){const _=d.geometry;return M.assignLODInformation(a.url,_,l,e,void 0,v.density),m(_)}else{const _=new Array;for(let O=0;O<d.children.length;O++){const k=d.children[O];if(k.isMesh===!0){const G=k.geometry;M.assignLODInformation(a.url,G,l,e,O,v.density),_.push(G)}}return m(_)}}else y&&console.warn("Could not find mesh with guid",D.guid,L.parser.json)}return m(null)});return this.previouslyLoaded.set(g,T),await T}else if(t instanceof z){i&&console.log("Load texture from uri: "+h);const g=await new Se().loadAsync(h);return g?(g.guid=u.guid,g.flipY=!1,g.needsUpdate=!0,g.colorSpace=t.colorSpace,i&&console.log(u,g)):y&&console.warn("failed loading",h),g}}else y&&console.warn(`Can not load LOD ${e}: no LOD info found for "${l}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,s,o){if(!e)return;e.userData||(e.userData={});const i=new Fe(t,r,n,s,o);e.userData.LODS=i}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e=e.clone(),y&&console.warn(`Copying texture settings
4
4
  `,t.uuid,`
5
- `,e.uuid),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}};let w=M;c(w,"registerTexture",(t,e,r,n,o)=>{if(y&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,o),!e){y&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ce]=o);const s=o.guid;M.assignLODInformation(t,e,s,r,n,void 0),M.lodInfos.set(s,o),M.lowresCache.set(s,e)}),c(w,"registerMesh",(t,e,r,n,o,s)=>{var i;y&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const a=r.geometry;if(!a){y&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),M.assignLODInformation(t,a,e,n,o,s.density),M.lodInfos.set(e,s);let l=M.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],M.lowresCache.set(e,l),n>0&&!ee(r)&&xe(r,a);for(const u of j)(i=u.onRegisteredNewMesh)==null||i.call(u,r,s)}),c(w,"lodInfos",new Map),c(w,"previouslyLoaded",new Map),c(w,"lowresCache",new Map);class Fe{constructor(e,r,n,o,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const $=q("debugprogressive"),Ne=q("noprogressive"),he=Symbol("Needle:LODSManager"),fe=Symbol("Needle:LODState"),W=Symbol("Needle:CurrentLOD"),P={mesh_lod:-1,texture_lod:-1},A=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new me),c(this,"cameraFrustrum",new Te),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new Ee),c(this,"_tempBox",new pe),c(this,"_tempBox2",new pe),c(this,"tempMatrix",new me),c(this,"_tempWorldPosition",new R),c(this,"_tempBoxSize",new R),c(this,"_tempBox2Size",new R),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[fe]}static addPlugin(t){j.push(t)}static removePlugin(t){const e=j.indexOf(t);e>=0&&j.splice(e,1)}static get(t,e){if(t[he])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[he];const r=new A(t,{engine:"unknown",...e});return t[he]=r,r}get plugins(){return j}enable(){if(this._originalRender)return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;this._originalRender=this.renderer.render;const e=this;ae(this.renderer),this.renderer.render=function(r,n){e.renderer.getRenderTarget()==null&&(t=0,e._frame+=1);const o=e._frame,s=t++;e.onBeforeRender(r,n,s,o),e._originalRender.call(this,r,n),e.onAfterRender(r,n,s,o)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(t,e,r,n){}onAfterRender(t,e,r,n){var o,s;if(this.pause)return;const i=this.renderer.renderLists.get(t,0),a=i.opaque;let l=!0;if(a.length===1){const u=a[0].material;(u.name==="EffectMaterial"||u.name==="CopyShader")&&(l=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(l=!1),l){if(Ne||this.updateInterval>0&&n%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const u=this.targetTriangleDensity;for(const h of a){if(h.material&&(((o=h.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=h.geometry)==null?void 0:s.type)==="BufferGeometry")&&(h.material.name==="SphericalGaussianBlur"||h.material.name=="BackgroundCubeMaterial"||h.material.name==="CubemapFromEquirect"||h.material.name==="EquirectangularToCubeUV")){$&&(h.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(h.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",h,h.material.name,h.material.type)));continue}switch(h.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const f=h.object;(f instanceof N||f.isMesh)&&this.updateLODs(t,e,f,u,n)}const g=i.transparent;for(const h of g){const f=h.object;(f instanceof N||f.isMesh)&&this.updateLODs(t,e,f,u,n)}}}updateLODs(t,e,r,n,o){var s,i;r.userData||(r.userData={});let a=r[fe];if(a||(a=new We,r[fe]=a),a.frames++<2)return;for(const u of j)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,a,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);let l=P.texture_lod;if(r.material&&l>=0){const u=r["DEBUG:LOD"];u!=null&&(l=u),this.loadProgressiveTextures(r.material,l)}for(const u of j)(i=u.onAfterUpdatedLOD)==null||i.call(u,this.renderer,t,e,r,P);a.lastLodLevel_Mesh=P.mesh_lod,a.lastLodLevel_Texture=P.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const n of t)this.loadProgressiveTextures(n,e);return}let r=!1;(t[W]===void 0||e<t[W])&&(r=!0),r&&(t[W]=e,w.assignTextureLOD(t,e))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[W]!==e){t[W]=e;const r=t.geometry;return w.assignMeshLOD(t,e).then(n=>(n&&t[W]==e&&r!=t.geometry,n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,o=(r.x+n.x)*.5,s=(r.y+n.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,o){var s,i;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let a=10+1,l=!1;if($&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=w.getMeshLODInformation(e.geometry),g=u?.lods,h=g&&g.length>0,f=w.getMaterialMinMaxLODsCount(e.material),S=f?.min_count!=1/0&&f.min_count>0&&f.max_count>0;if(!h&&!S){o.mesh_lod=0,o.texture_lod=0;return}if(h||(l=!0,a=0),!((s=this.cameraFrustrum)!=null&&s.intersectsObject(e))){o.mesh_lod=99,o.texture_lod=99;return}const D=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let T=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const m=e;m.boundingBox||m.computeBoundingBox(),T=m.boundingBox}if(T&&t.isPerspectiveCamera){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 p=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(p)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(T),this._tempBox.applyMatrix4(e.matrixWorld),A.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&m.fov>70){const p=this._tempBox.min,d=this._tempBox.max;let v=p.x,_=p.y,O=d.x,k=d.y;const G=2,re=1.5,H=(p.x+d.x)*.5,Y=(p.y+d.y)*.5;v=(v-H)*G+H,_=(_-Y)*G+Y,O=(O-H)*G+H,k=(k-Y)*G+Y;const De=v<0&&O>0?0:Math.min(Math.abs(p.x),Math.abs(d.x)),_e=_<0&&k>0?0:Math.min(Math.abs(p.y),Math.abs(d.y)),se=Math.max(De,_e);r.lastCentrality=(re-se)*(re-se)*(re-se)}else r.lastCentrality=1;const x=this._tempBox.getSize(this._tempBoxSize);x.multiplyScalar(.5),screen.availHeight>0&&D>0&&x.multiplyScalar(D/screen.availHeight),x.x*=m.aspect;const b=t.matrixWorldInverse,E=this._tempBox2;E.copy(T),E.applyMatrix4(e.matrixWorld),E.applyMatrix4(b);const L=E.getSize(this._tempBox2Size),F=Math.max(L.x,L.y);if(Math.max(x.x,x.y)!=0&&F!=0&&(x.z=L.z/Math.max(L.x,L.y)*Math.max(x.x,x.y)),r.lastScreenCoverage=Math.max(x.x,x.y,x.z),r.lastScreenspaceVolume.copy(x),r.lastScreenCoverage*=r.lastCentrality,$&&A.debugDrawLine){const p=this.tempMatrix.copy(this.projectionScreenMatrix);p.invert();const d=A.corner0,v=A.corner1,_=A.corner2,O=A.corner3;d.copy(this._tempBox.min),v.copy(this._tempBox.max),v.x=d.x,_.copy(this._tempBox.max),_.y=d.y,O.copy(this._tempBox.max);const k=(d.z+O.z)*.5;d.z=v.z=_.z=O.z=k,d.applyMatrix4(p),v.applyMatrix4(p),_.applyMatrix4(p),O.applyMatrix4(p),A.debugDrawLine(d,v,255),A.debugDrawLine(d,_,255),A.debugDrawLine(v,O,255),A.debugDrawLine(_,O,255)}let I=999;if(g&&r.lastScreenCoverage>0){for(let p=0;p<g.length;p++)if(g[p].density/r.lastScreenCoverage<n){I=p;break}}I<a&&(a=I,l=!0)}if(l?o.mesh_lod=a:o.mesh_lod=r.lastLodLevel_Mesh,$&&o.mesh_lod!=r.lastLodLevel_Mesh){const m=g?.[o.mesh_lod];m&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${o.mesh_lod} (${m.density.toFixed(0)}) - ${e.name}`)}if(S)if(r.lastLodLevel_Texture<0){if(o.texture_lod=f.max_count-1,$){const m=f.lods[f.max_count-1];$&&console.log(`First Texture LOD ${o.texture_lod} (${m.max_height}px) - ${e.name}`)}}else{const m=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let x=r.lastScreenCoverage*2;((i=this.context)==null?void 0:i.engine)==="model-viewer"&&(x*=2);const b=D/window.devicePixelRatio*x;for(let E=f.lods.length-1;E>=0;E--){let L=f.lods[E];if(!(je()&&L.max_height>4096)&&L.max_height>b){if(o.texture_lod=E,o.texture_lod<r.lastLodLevel_Texture){const F=L.max_height;$&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} = ${F}px
5
+ `,e.uuid),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}};let w=M;c(w,"registerTexture",(t,e,r,n,s)=>{if(y&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,s),!e){y&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ce]=s);const o=s.guid;M.assignLODInformation(t,e,o,r,n,void 0),M.lodInfos.set(o,s),M.lowresCache.set(o,e)}),c(w,"registerMesh",(t,e,r,n,s,o)=>{var i;y&&console.log("> Progressive: register mesh",s,r.name,o,r.uuid,r);const a=r.geometry;if(!a){y&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),M.assignLODInformation(t,a,e,n,s,o.density),M.lodInfos.set(e,o);let l=M.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],M.lowresCache.set(e,l),n>0&&!ee(r)&&xe(r,a);for(const u of j)(i=u.onRegisteredNewMesh)==null||i.call(u,r,o)}),c(w,"lodInfos",new Map),c(w,"previouslyLoaded",new Map),c(w,"lowresCache",new Map);class Fe{constructor(e,r,n,s,o){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,s!=null&&(this.index=s),o!=null&&(this.density=o)}}const $=q("debugprogressive"),Ne=q("noprogressive"),he=Symbol("Needle:LODSManager"),ge=Symbol("Needle:LODState"),W=Symbol("Needle:CurrentLOD"),P={mesh_lod:-1,texture_lod:-1},A=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new me),c(this,"cameraFrustrum",new Te),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_lodchangedlisteners",[]),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new Ee),c(this,"_tempBox",new pe),c(this,"_tempBox2",new pe),c(this,"tempMatrix",new me),c(this,"_tempWorldPosition",new R),c(this,"_tempBoxSize",new R),c(this,"_tempBox2Size",new R),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[ge]}static addPlugin(t){j.push(t)}static removePlugin(t){const e=j.indexOf(t);e>=0&&j.splice(e,1)}static get(t,e){if(t[he])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[he];const r=new A(t,{engine:"unknown",...e});return t[he]=r,r}get plugins(){return j}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}enable(){if(this._originalRender)return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;this._originalRender=this.renderer.render;const e=this;ae(this.renderer),this.renderer.render=function(r,n){e.renderer.getRenderTarget()==null&&(t=0,e._frame+=1);const s=e._frame,o=t++;e.onBeforeRender(r,n,o,s),e._originalRender.call(this,r,n),e.onAfterRender(r,n,o,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(t,e,r,n){}onAfterRender(t,e,r,n){var s,o;if(this.pause)return;const i=this.renderer.renderLists.get(t,0),a=i.opaque;let l=!0;if(a.length===1){const u=a[0].material;(u.name==="EffectMaterial"||u.name==="CopyShader")&&(l=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(l=!1),l){if(Ne||this.updateInterval>0&&n%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const u=this.targetTriangleDensity;for(const h of a){if(h.material&&(((s=h.geometry)==null?void 0:s.type)==="BoxGeometry"||((o=h.geometry)==null?void 0:o.type)==="BufferGeometry")&&(h.material.name==="SphericalGaussianBlur"||h.material.name=="BackgroundCubeMaterial"||h.material.name==="CubemapFromEquirect"||h.material.name==="EquirectangularToCubeUV")){$&&(h.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(h.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",h,h.material.name,h.material.type)));continue}switch(h.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const g=h.object;(g instanceof N||g.isMesh)&&this.updateLODs(t,e,g,u,n)}const f=i.transparent;for(const h of f){const g=h.object;(g instanceof N||g.isMesh)&&this.updateLODs(t,e,g,u,n)}}}updateLODs(t,e,r,n,s){var o,i;r.userData||(r.userData={});let a=r[ge];if(a||(a=new We,r[ge]=a),a.frames++<2)return;for(const u of j)(o=u.onBeforeUpdateLOD)==null||o.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,a,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);let l=P.texture_lod;if(r.material&&l>=0){const u=r["DEBUG:LOD"];u!=null&&(l=u),this.loadProgressiveTextures(r.material,l)}for(const u of j)(i=u.onAfterUpdatedLOD)==null||i.call(u,this.renderer,t,e,r,P);a.lastLodLevel_Mesh=P.mesh_lod,a.lastLodLevel_Texture=P.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const n of t)this.loadProgressiveTextures(n,e);return}let r=!1;(t[W]===void 0||e<t[W])&&(r=!0),r&&(t[W]=e,w.assignTextureLOD(t,e).then(n=>{this._lodchangedlisteners.forEach(s=>s({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[W]!==e){t[W]=e;const r=t.geometry;return w.assignMeshLOD(t,e).then(n=>(n&&t[W]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,s){var o,i;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let a=10+1,l=!1;if($&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=w.getMeshLODInformation(e.geometry),f=u?.lods,h=f&&f.length>0,g=w.getMaterialMinMaxLODsCount(e.material),S=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!h&&!S){s.mesh_lod=0,s.texture_lod=0;return}if(h||(l=!0,a=0),!((o=this.cameraFrustrum)!=null&&o.intersectsObject(e))){s.mesh_lod=99,s.texture_lod=99;return}const D=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let T=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const m=e;m.boundingBox||m.computeBoundingBox(),T=m.boundingBox}if(T&&t.isPerspectiveCamera){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 p=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(p)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(T),this._tempBox.applyMatrix4(e.matrixWorld),A.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.fov>70){const p=this._tempBox.min,d=this._tempBox.max;let v=p.x,_=p.y,O=d.x,k=d.y;const G=2,re=1.5,H=(p.x+d.x)*.5,Y=(p.y+d.y)*.5;v=(v-H)*G+H,_=(_-Y)*G+Y,O=(O-H)*G+H,k=(k-Y)*G+Y;const De=v<0&&O>0?0:Math.min(Math.abs(p.x),Math.abs(d.x)),_e=_<0&&k>0?0:Math.min(Math.abs(p.y),Math.abs(d.y)),se=Math.max(De,_e);r.lastCentrality=(re-se)*(re-se)*(re-se)}else r.lastCentrality=1;const x=this._tempBox.getSize(this._tempBoxSize);x.multiplyScalar(.5),screen.availHeight>0&&D>0&&x.multiplyScalar(D/screen.availHeight),x.x*=m.aspect;const b=t.matrixWorldInverse,E=this._tempBox2;E.copy(T),E.applyMatrix4(e.matrixWorld),E.applyMatrix4(b);const L=E.getSize(this._tempBox2Size),F=Math.max(L.x,L.y);if(Math.max(x.x,x.y)!=0&&F!=0&&(x.z=L.z/Math.max(L.x,L.y)*Math.max(x.x,x.y)),r.lastScreenCoverage=Math.max(x.x,x.y,x.z),r.lastScreenspaceVolume.copy(x),r.lastScreenCoverage*=r.lastCentrality,$&&A.debugDrawLine){const p=this.tempMatrix.copy(this.projectionScreenMatrix);p.invert();const d=A.corner0,v=A.corner1,_=A.corner2,O=A.corner3;d.copy(this._tempBox.min),v.copy(this._tempBox.max),v.x=d.x,_.copy(this._tempBox.max),_.y=d.y,O.copy(this._tempBox.max);const k=(d.z+O.z)*.5;d.z=v.z=_.z=O.z=k,d.applyMatrix4(p),v.applyMatrix4(p),_.applyMatrix4(p),O.applyMatrix4(p),A.debugDrawLine(d,v,255),A.debugDrawLine(d,_,255),A.debugDrawLine(v,O,255),A.debugDrawLine(_,O,255)}let I=999;if(f&&r.lastScreenCoverage>0){for(let p=0;p<f.length;p++)if(f[p].density/r.lastScreenCoverage<n){I=p;break}}I<a&&(a=I,l=!0)}if(l?s.mesh_lod=a:s.mesh_lod=r.lastLodLevel_Mesh,$&&s.mesh_lod!=r.lastLodLevel_Mesh){const m=f?.[s.mesh_lod];m&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${m.density.toFixed(0)}) - ${e.name}`)}if(S)if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,$){const m=g.lods[g.max_count-1];$&&console.log(`First Texture LOD ${s.texture_lod} (${m.max_height}px) - ${e.name}`)}}else{const m=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let x=r.lastScreenCoverage*2;((i=this.context)==null?void 0:i.engine)==="model-viewer"&&(x*=2);const b=D/window.devicePixelRatio*x;for(let E=g.lods.length-1;E>=0;E--){let L=g.lods[E];if(!(je()&&L.max_height>4096)&&L.max_height>b){if(s.texture_lod=E,s.texture_lod<r.lastLodLevel_Texture){const F=L.max_height;$&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${F}px
6
6
  Screensize: ${b.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${m.toFixed(1)}
7
- ${e.name}`)}break}}}else o.texture_lod=0}};let C=A;c(C,"debugDrawLine"),c(C,"corner0",new R),c(C,"corner1",new R),c(C,"corner2",new R),c(C,"corner3",new R),c(C,"_tempPtInside",new R);class We{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new R),c(this,"lastCentrality",0)}}const ve=Symbol("NEEDLE_mesh_lod"),te=Symbol("NEEDLE_texture_lod");function Le(){document.removeEventListener("DOMContentLoaded",ge),document.addEventListener("DOMContentLoaded",ge),ge()}function ge(){document.querySelectorAll("model-viewer").forEach((t,e)=>{ze(t,e)})}const Me=new WeakSet;function ze(t,e){if(!t||Me.has(t))return null;Me.add(t),console.debug("[gltf-progressive] found model-viewer..."+e);let r=null,n=null,o=null;for(let s=t;s!=null;s=Object.getPrototypeOf(s)){const i=Object.getOwnPropertySymbols(s),a=i.find(g=>g.toString()=="Symbol(renderer)"),l=i.find(g=>g.toString()=="Symbol(scene)"),u=i.find(g=>g.toString()=="Symbol(needsRender)");!r&&a!=null&&(r=t[a].threeRenderer),!n&&l!=null&&(n=t[l]),!o&&u!=null&&(o=t[u])}if(r&&n){console.debug("[gltf-progressive] setup model-viewer");const s=C.get(r,{engine:"model-viewer"});if(C.addPlugin(new Ue),s.enable(),n&&o){let i=0,a=setInterval(()=>{if(i++>10){clearInterval(a);return}o?.call(t)},150)}return()=>{s.disable()}}return null}class Ue{constructor(){c(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,r,n,o){this.tryParseMeshLOD(r,o),this.tryParseTextureLOD(r,o)}getUrl(e){if(!e)return null;let r=e.getAttribute("src");return r||(r=e.src),r||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),r}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,r){if(r[te]==!0)return;r[te]=!0;const n=this.tryGetCurrentGLTF(e),o=this.tryGetCurrentModelViewer(e),s=this.getUrl(o);if(s&&n&&r.material){let i=function(l){var u,g,h;if(l[te]==!0)return;l[te]=!0,l.userData&&(l.userData.LOD=-1);const f=Object.keys(l);for(let S=0;S<f.length;S++){const D=f[S],T=l[D];if(T?.isTexture===!0){const m=(g=(u=T.userData)==null?void 0:u.associations)==null?void 0:g.textures;if(m==null)continue;const x=n.parser.json.textures[m];if(!x){console.warn("Texture data not found for texture index "+m);continue}if((h=x?.extensions)!=null&&h[B]){const b=x.extensions[B];b&&s&&w.registerTexture(s,T,b.lods.length,m,b)}}}};const a=r.material;if(Array.isArray(a))for(const l of a)i(l);else i(a)}}tryParseMeshLOD(e,r){var n,o;if(r[ve]==!0)return;r[ve]=!0;const s=this.tryGetCurrentModelViewer(e),i=this.getUrl(s);if(!i)return;const a=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[B];if(a&&i){const l=r.uuid;w.registerMesh(i,l,r,0,a.lods.length,a)}}}Le();function Ve(t,e,r,n){ae(e),le(r),r.register(s=>new w(s,t));const o=C.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}export{B as EXTENSION_NAME,C as LODsManager,w as NEEDLE_progressive,oe as VERSION,le as addDracoAndKTX2Loaders,ae as createLoaders,ee as getRaycastMesh,Le as patchModelViewer,Ce as setDracoDecoderLocation,Re as setKTX2TranscoderLocation,xe as setRaycastMesh,Ve as useNeedleProgressive,Ge as useRaycastMeshes};
7
+ ${e.name}`)}break}}}else s.texture_lod=0}};let C=A;c(C,"debugDrawLine"),c(C,"corner0",new R),c(C,"corner1",new R),c(C,"corner2",new R),c(C,"corner3",new R),c(C,"_tempPtInside",new R);class We{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new R),c(this,"lastCentrality",0)}}const ve=Symbol("NEEDLE_mesh_lod"),te=Symbol("NEEDLE_texture_lod");function Le(){document.removeEventListener("DOMContentLoaded",fe),document.addEventListener("DOMContentLoaded",fe),fe()}function fe(){document.querySelectorAll("model-viewer").forEach((t,e)=>{ze(t,e)})}const Me=new WeakSet;function ze(t,e){if(!t||Me.has(t))return null;Me.add(t),console.debug("[gltf-progressive] found model-viewer..."+e);let r=null,n=null,s=null;for(let o=t;o!=null;o=Object.getPrototypeOf(o)){const i=Object.getOwnPropertySymbols(o),a=i.find(f=>f.toString()=="Symbol(renderer)"),l=i.find(f=>f.toString()=="Symbol(scene)"),u=i.find(f=>f.toString()=="Symbol(needsRender)");!r&&a!=null&&(r=t[a].threeRenderer),!n&&l!=null&&(n=t[l]),!s&&u!=null&&(s=t[u])}if(r&&n){let o=function(){if(s){let a=0,l=setInterval(()=>{if(a++>5){clearInterval(l);return}s?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const i=C.get(r,{engine:"model-viewer"});return C.addPlugin(new Ue),i.enable(),i.addEventListener("changed",()=>{s?.call(t)}),t.addEventListener("model-visibility",a=>{a.detail.visible&&s?.call(t)}),t.addEventListener("load",()=>{o()}),()=>{i.disable()}}return null}class Ue{constructor(){c(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,r,n,s){this.tryParseMeshLOD(r,s),this.tryParseTextureLOD(r,s)}getUrl(e){if(!e)return null;let r=e.getAttribute("src");return r||(r=e.src),r||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),r}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,r){if(r[te]==!0)return;r[te]=!0;const n=this.tryGetCurrentGLTF(e),s=this.tryGetCurrentModelViewer(e),o=this.getUrl(s);if(o&&n&&r.material){let i=function(l){var u,f,h;if(l[te]==!0)return;l[te]=!0,l.userData&&(l.userData.LOD=-1);const g=Object.keys(l);for(let S=0;S<g.length;S++){const D=g[S],T=l[D];if(T?.isTexture===!0){const m=(f=(u=T.userData)==null?void 0:u.associations)==null?void 0:f.textures;if(m==null)continue;const x=n.parser.json.textures[m];if(!x){console.warn("Texture data not found for texture index "+m);continue}if((h=x?.extensions)!=null&&h[B]){const b=x.extensions[B];b&&o&&w.registerTexture(o,T,b.lods.length,m,b)}}}};const a=r.material;if(Array.isArray(a))for(const l of a)i(l);else i(a)}}tryParseMeshLOD(e,r){var n,s;if(r[ve]==!0)return;r[ve]=!0;const o=this.tryGetCurrentModelViewer(e),i=this.getUrl(o);if(!i)return;const a=(s=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[B];if(a&&i){const l=r.uuid;w.registerMesh(i,l,r,0,a.lods.length,a)}}}Le();function Ve(t,e,r,n){ae(e),le(r),r.register(o=>new w(o,t));const s=C.get(e);return n?.enableLODsManager!==!1&&s.enable(),s}export{B as EXTENSION_NAME,C as LODsManager,w as NEEDLE_progressive,oe as VERSION,le as addDracoAndKTX2Loaders,ae as createLoaders,ee as getRaycastMesh,Le as patchModelViewer,Ce as setDracoDecoderLocation,Re as setKTX2TranscoderLocation,xe as setRaycastMesh,Ve as useNeedleProgressive,Ge as useRaycastMeshes};
@@ -1,7 +1,7 @@
1
- "use strict";var _e=Object.defineProperty;var ve=(l,e,t)=>e in l?_e(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var d=(l,e,t)=>(ve(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("three"),Oe=require("three/examples/jsm/loaders/GLTFLoader.js"),Se=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Te=require("three/examples/jsm/loaders/DRACOLoader.js"),be=require("three/examples/jsm/loaders/KTX2Loader.js"),de="";globalThis.GLTF_PROGRESSIVE_VERSION=de;console.debug(`[gltf-progressive] version ${de}`);let te="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",he="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(te+"draco_decoder.js",{method:"head"}).catch(l=>{te="./include/draco/",he="./include/ktx2/"});function Ae(l){te=l}function Pe(l){he=l}let X,ce,Y;function ge(l){X||(X=new Te.DRACOLoader,X.setDecoderPath(te),X.setDecoderConfig({type:"js"})),Y||(Y=new be.KTX2Loader,Y.setTranscoderPath(he)),ce||(ce=Se.MeshoptDecoder),l?Y.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function pe(l){l.dracoLoader||l.setDRACOLoader(X),l.ktx2Loader||l.setKTX2Loader(Y),l.meshoptDecoder||l.setMeshoptDecoder(ce)}J("debugprogressive");function J(l){const t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function Ce(l,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||l===void 0)return e;const t=l.lastIndexOf("/");if(t>=0){const r=l.substring(0,t+1);for(;r.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return r+e}return e}let q;function Re(){return q!==void 0||(q=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),J("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",q)),q}const ue=Symbol("needle:raycast-mesh");function re(l){return(l==null?void 0:l[ue])instanceof g.BufferGeometry?l[ue]:null}function Le(l,e){if((l.type==="Mesh"||l.type==="SkinnedMesh")&&!re(l)){const r=Be(e);r.userData={isRaycastMesh:!0},l[ue]=r}}function Ee(l=!0){if(l){if(K)return;const e=K=g.Mesh.prototype.raycast;g.Mesh.prototype.raycast=function(t,r){const i=this,o=re(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),e.call(this,t,r),s&&(i.geometry=s)}}else{if(!K)return;g.Mesh.prototype.raycast=K,K=null}}let K=null;function Be(l){const e=new g.BufferGeometry;for(const t in l.attributes)e.setAttribute(t,l.getAttribute(t));return e.setIndex(l.getIndex()),e}const V=new Array,G="NEEDLE_progressive",m=J("debugprogressive"),ie=Symbol("needle-progressive-texture"),H=new Map,fe=new Set;if(m){let l=function(){e+=1,console.log("Toggle LOD level",e,H),H.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n!=null){if(n.isBufferGeometry===!0){const a=S.getMeshLODInformation(n),f=a?Math.min(e,a.lods.length):0;o["DEBUG:LOD"]=e,S.assignMeshLOD(o,f),a&&(t=Math.max(t,a.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,S.assignTextureLOD(o,e);break}}}}),e>=t&&(e=-1)},e=-1,t=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&l(),i.key==="w"&&(r=!r,fe&&fe.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=r)}))})}function ye(l,e,t){var i;if(!m)return;H.has(l)||H.set(l,{keys:[],sourceId:t});const r=H.get(l);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const O=class{constructor(e,t){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",e=>{var r,i;if(this._isLoadingMesh)return null;const t=(i=(r=this.parser.json.meshes[e])==null?void 0:r.extensions)==null?void 0:i[G];return t?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",e).then(o=>{var s;return this._isLoadingMesh=!1,o&&O.registerMesh(this.url,t.guid,o,(s=t.lods)==null?void 0:s.length,void 0,t),o})):null});m&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return G}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static getMaterialMinMaxLODsCount(e,t){const r=this,i="LODS:minmax",o=e[i];if(o!=null)return o;if(t||(t={min_count:1/0,max_count:0,lods:[]}),Array.isArray(e)){for(const n of e)this.getMaterialMinMaxLODsCount(n,t);return e[i]=t,t}if(m==="verbose"&&console.log("getMaterialMinMaxLODsCount",e),e.type==="ShaderMaterial"||e.type==="RawShaderMaterial"){const n=e;for(const a of Object.keys(n.uniforms)){const f=n.uniforms[a].value;(f==null?void 0:f.isTexture)===!0&&s(f,t)}}else if(e.isMaterial)for(const n of Object.keys(e)){const a=e[n];(a==null?void 0:a.isTexture)===!0&&s(a,t)}return e[i]=t,t;function s(n,a){const f=r.getAssignedLODInformation(n);if(f){const c=r.lodInfos.get(f.key);if(c&&c.lods){a.min_count=Math.min(a.min_count,c.lods.length),a.max_count=Math.max(a.max_count,c.lods.length);for(let L=0;L<c.lods.length;L++){const u=c.lods[L];u.width&&(a.lods[L]=a.lods[L]||{min_height:1/0,max_height:0},a.lods[L].min_height=Math.min(a.lods[L].min_height,u.height),a.lods[L].max_height=Math.max(a.lods[L].max_height,u.height))}}}}}static hasLODLevelAvailable(e,t){var o;if(Array.isArray(e)){for(const s of e)if(this.hasLODLevelAvailable(s,t))return!0;return!1}if(e.isMaterial===!0){for(const s of Object.keys(e)){const n=e[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,t))return!0}return!1}else if(e.isGroup===!0){for(const s of e.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,t))return!0}let r,i;if(e.isMesh?r=e.geometry:(e.isBufferGeometry||e.isTexture)&&(r=e),r&&(o=r==null?void 0:r.userData)!=null&&o.LODS){const s=r.userData.LODS;if(i=this.lodInfos.get(s.key),t===void 0)return i!=null;if(i)return Array.isArray(i.lods)?t<i.lods.length:t===0}return!1}static assignMeshLOD(e,t){var r;if(!e)return Promise.resolve(null);if(e instanceof g.Mesh||e.isMesh===!0){const i=e.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of V)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,O.getOrLoadLOD(i,t).then(s=>{if(e["LOD:requested level"]===t){if(delete e["LOD:requested level"],Array.isArray(s)){const n=o.index||0;s=s[n]}s&&i!=s&&((s==null?void 0:s.isBufferGeometry)?(e.geometry=s,m&&ye(e,"geometry",o.url)):m&&console.error("Invalid LOD geometry",s))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else m&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",e);return Promise.resolve(null)}static assignTextureLOD(e,t=0){if(!e)return Promise.resolve(null);if(e instanceof g.Material||e.isMaterial===!0){const r=e,i=[],o=new Array;if(m&&fe.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const n of Object.keys(s.uniforms)){const a=s.uniforms[n].value;if((a==null?void 0:a.isTexture)===!0){const f=this.assignTextureLODForSlot(a,t,r,n);i.push(f),o.push(n)}}}else for(const s of Object.keys(r)){const n=r[s];if((n==null?void 0:n.isTexture)===!0){const a=this.assignTextureLODForSlot(n,t,r,s);i.push(a),o.push(s)}}return Promise.all(i).then(s=>{const n=new Array;for(let a=0;a<s.length;a++){const f=s[a],c=o[a];f&&f.isTexture===!0?n.push({material:r,slot:c,texture:f,level:t}):n.push({material:r,slot:c,texture:null,level:t})}return n})}if(e instanceof g.Texture||e.isTexture===!0){const r=e;return this.assignTextureLODForSlot(r,t,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(e,t,r,i){return(e==null?void 0:e.isTexture)!==!0?Promise.resolve(null):i==="glyphMap"?Promise.resolve(e):O.getOrLoadLOD(e,t).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=e){if(r&&i){const s=r[i];if(s){const n=this.getAssignedLODInformation(s);if(n&&(n==null?void 0:n.level)<t)return m==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,t,r,s,o),null}r[i]=o}if(m&&i&&r){const s=this.getAssignedLODInformation(e);s&&ye(r,i,s.url)}}return o}else m=="verbose"&&console.warn("No LOD found for",e,t);return null}).catch(o=>(console.error("Error loading LOD",e,o),null))}afterRoot(e){var t,r;return m&&console.log("AFTER",this.url,e),(t=this.parser.json.textures)==null||t.forEach((i,o)=>{var s;if(i!=null&&i.extensions){const n=i==null?void 0:i.extensions[G];if(n){if(!n.lods){m&&console.warn("Texture has no LODs",n);return}let a=!1;for(const f of this.parser.associations.keys())f.isTexture===!0&&this.parser.associations.get(f).textures===o&&(a=!0,O.registerTexture(this.url,f,(s=n.lods)==null?void 0:s.length,o,n));a||this.parser.getDependency("texture",o).then(f=>{var c;f&&O.registerTexture(this.url,f,(c=n.lods)==null?void 0:c.length,o,n)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[G];if(s&&s.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const a=this.parser.associations.get(n);a.meshes===o&&O.registerMesh(this.url,s.guid,n,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var n,a,f,c;const r=m=="verbose",i=e.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(e.isTexture===!0){const L=e;L.source&&L.source[ie]&&(s=L.source[ie])}if(s||(s=O.lodInfos.get(o)),s){if(t>0){let x=!1;const _=Array.isArray(s.lods);if(_&&t>=s.lods.length?x=!0:_||(x=!0),x)return this.lowresCache.get(o)}const L=Array.isArray(s.lods)?(n=s.lods[t])==null?void 0:n.path:s.lods;if(!L)return m&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const u=Ce(i.url,L);if(u.endsWith(".glb")||u.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const x=u+"_"+s.guid,_=this.previouslyLoaded.get(x);if(_!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${x}`);let y=await _.catch(N=>(console.error(`Error loading LOD ${t} from ${u}
2
- `,N),null)),D=!1;if(y==null||(y instanceof g.Texture&&e instanceof g.Texture?(a=y.image)!=null&&a.data||(f=y.source)!=null&&f.data?y=this.copySettings(e,y):(D=!0,this.previouslyLoaded.delete(x)):y instanceof g.BufferGeometry&&e instanceof g.BufferGeometry&&((c=y.attributes.position)!=null&&c.array||(D=!0,this.previouslyLoaded.delete(x)))),!D)return y}const M=s,B=new Promise(async(y,D)=>{const N=new Oe.GLTFLoader;pe(N),m&&(await new Promise(T=>setTimeout(T,1e3)),r&&console.warn("Start loading (delayed) "+u,M.guid));let k=u;if(M&&Array.isArray(M.lods)){const T=M.lods[t];T.hash&&(k+="?v="+T.hash)}const v=await N.loadAsync(k).catch(T=>(console.error(`Error loading LOD ${t} from ${u}
3
- `,T),null));if(!v)return null;const $=v.parser;r&&console.log("Loading finished "+u,M.guid);let I=0;if(v.parser.json.textures){let T=!1;for(const p of v.parser.json.textures){if(p!=null&&p.extensions){const h=p==null?void 0:p.extensions[G];if(h!=null&&h.guid&&h.guid===M.guid){T=!0;break}}I++}if(T){let p=await $.getDependency("texture",I);return p&&O.assignLODInformation(i.url,p,o,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+p.name+'"',u,I,p,x),e instanceof g.Texture&&(p=this.copySettings(e,p)),p&&(p.guid=M.guid),y(p)}else m&&console.warn("Could not find texture with guid",M.guid,v.parser.json)}if(I=0,v.parser.json.meshes){let T=!1;for(const p of v.parser.json.meshes){if(p!=null&&p.extensions){const h=p==null?void 0:p.extensions[G];if(h!=null&&h.guid&&h.guid===M.guid){T=!0;break}}I++}if(T){const p=await $.getDependency("mesh",I),h=M;if(r&&console.log(`Loaded Mesh "${p.name}"`,u,I,p,x),p.isMesh===!0){const w=p.geometry;return O.assignLODInformation(i.url,w,o,t,void 0,h.density),y(w)}else{const w=new Array;for(let b=0;b<p.children.length;b++){const A=p.children[b];if(A.isMesh===!0){const P=A.geometry;O.assignLODInformation(i.url,P,o,t,b,h.density),w.push(P)}}return y(w)}}else m&&console.warn("Could not find mesh with guid",M.guid,v.parser.json)}return y(null)});return this.previouslyLoaded.set(x,B),await B}else if(e instanceof g.Texture){r&&console.log("Load texture from uri: "+u);const _=await new g.TextureLoader().loadAsync(u);return _?(_.guid=s.guid,_.flipY=!1,_.needsUpdate=!0,_.colorSpace=e.colorSpace,r&&console.log(s,_)):m&&console.warn("failed loading",u),_}}else m&&console.warn(`Can not load LOD ${t}: no LOD info found for "${o}" ${e.name}`,e.type);return null}static assignLODInformation(e,t,r,i,o,s){if(!t)return;t.userData||(t.userData={});const n=new ke(e,r,i,o,s);t.userData.LODS=n}static getAssignedLODInformation(e){var t;return((t=e==null?void 0:e.userData)==null?void 0:t.LODS)||null}static copySettings(e,t){return t=t.clone(),m&&console.warn(`Copying texture settings
1
+ "use strict";var ve=Object.defineProperty;var we=(l,e,t)=>e in l?ve(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var d=(l,e,t)=>(we(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("three"),Oe=require("three/examples/jsm/loaders/GLTFLoader.js"),Se=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Te=require("three/examples/jsm/loaders/DRACOLoader.js"),be=require("three/examples/jsm/loaders/KTX2Loader.js"),fe="";globalThis.GLTF_PROGRESSIVE_VERSION=fe;console.debug(`[gltf-progressive] version ${fe}`);let te="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",he="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(te+"draco_decoder.js",{method:"head"}).catch(l=>{te="./include/draco/",he="./include/ktx2/"});function Ae(l){te=l}function Pe(l){he=l}let X,ce,Y;function ge(l){X||(X=new Te.DRACOLoader,X.setDecoderPath(te),X.setDecoderConfig({type:"js"})),Y||(Y=new be.KTX2Loader,Y.setTranscoderPath(he)),ce||(ce=Se.MeshoptDecoder),l?Y.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function pe(l){l.dracoLoader||l.setDRACOLoader(X),l.ktx2Loader||l.setKTX2Loader(Y),l.meshoptDecoder||l.setMeshoptDecoder(ce)}J("debugprogressive");function J(l){const t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function Ee(l,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||l===void 0)return e;const t=l.lastIndexOf("/");if(t>=0){const r=l.substring(0,t+1);for(;r.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return r+e}return e}let q;function Ce(){return q!==void 0||(q=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),J("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",q)),q}const ue=Symbol("needle:raycast-mesh");function re(l){return(l==null?void 0:l[ue])instanceof g.BufferGeometry?l[ue]:null}function me(l,e){if((l.type==="Mesh"||l.type==="SkinnedMesh")&&!re(l)){const r=Re(e);r.userData={isRaycastMesh:!0},l[ue]=r}}function Be(l=!0){if(l){if(K)return;const e=K=g.Mesh.prototype.raycast;g.Mesh.prototype.raycast=function(t,r){const i=this,o=re(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),e.call(this,t,r),s&&(i.geometry=s)}}else{if(!K)return;g.Mesh.prototype.raycast=K,K=null}}let K=null;function Re(l){const e=new g.BufferGeometry;for(const t in l.attributes)e.setAttribute(t,l.getAttribute(t));return e.setIndex(l.getIndex()),e}const V=new Array,G="NEEDLE_progressive",L=J("debugprogressive"),oe=Symbol("needle-progressive-texture"),H=new Map,de=new Set;if(L){let l=function(){e+=1,console.log("Toggle LOD level",e,H),H.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n!=null){if(n.isBufferGeometry===!0){const a=S.getMeshLODInformation(n),f=a?Math.min(e,a.lods.length):0;o["DEBUG:LOD"]=e,S.assignMeshLOD(o,f),a&&(t=Math.max(t,a.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,S.assignTextureLOD(o,e);break}}}}),e>=t&&(e=-1)},e=-1,t=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&l(),i.key==="w"&&(r=!r,de&&de.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=r)}))})}function ye(l,e,t){var i;if(!L)return;H.has(l)||H.set(l,{keys:[],sourceId:t});const r=H.get(l);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const O=class{constructor(e,t){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",e=>{var r,i;if(this._isLoadingMesh)return null;const t=(i=(r=this.parser.json.meshes[e])==null?void 0:r.extensions)==null?void 0:i[G];return t?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",e).then(o=>{var s;return this._isLoadingMesh=!1,o&&O.registerMesh(this.url,t.guid,o,(s=t.lods)==null?void 0:s.length,void 0,t),o})):null});L&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return G}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static getMaterialMinMaxLODsCount(e,t){const r=this,i="LODS:minmax",o=e[i];if(o!=null)return o;if(t||(t={min_count:1/0,max_count:0,lods:[]}),Array.isArray(e)){for(const n of e)this.getMaterialMinMaxLODsCount(n,t);return e[i]=t,t}if(L==="verbose"&&console.log("getMaterialMinMaxLODsCount",e),e.type==="ShaderMaterial"||e.type==="RawShaderMaterial"){const n=e;for(const a of Object.keys(n.uniforms)){const f=n.uniforms[a].value;(f==null?void 0:f.isTexture)===!0&&s(f,t)}}else if(e.isMaterial)for(const n of Object.keys(e)){const a=e[n];(a==null?void 0:a.isTexture)===!0&&s(a,t)}return e[i]=t,t;function s(n,a){const f=r.getAssignedLODInformation(n);if(f){const c=r.lodInfos.get(f.key);if(c&&c.lods){a.min_count=Math.min(a.min_count,c.lods.length),a.max_count=Math.max(a.max_count,c.lods.length);for(let m=0;m<c.lods.length;m++){const u=c.lods[m];u.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,u.height),a.lods[m].max_height=Math.max(a.lods[m].max_height,u.height))}}}}}static hasLODLevelAvailable(e,t){var o;if(Array.isArray(e)){for(const s of e)if(this.hasLODLevelAvailable(s,t))return!0;return!1}if(e.isMaterial===!0){for(const s of Object.keys(e)){const n=e[s];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,t))return!0}return!1}else if(e.isGroup===!0){for(const s of e.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,t))return!0}let r,i;if(e.isMesh?r=e.geometry:(e.isBufferGeometry||e.isTexture)&&(r=e),r&&(o=r==null?void 0:r.userData)!=null&&o.LODS){const s=r.userData.LODS;if(i=this.lodInfos.get(s.key),t===void 0)return i!=null;if(i)return Array.isArray(i.lods)?t<i.lods.length:t===0}return!1}static assignMeshLOD(e,t){var r;if(!e)return Promise.resolve(null);if(e instanceof g.Mesh||e.isMesh===!0){const i=e.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of V)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,O.getOrLoadLOD(i,t).then(s=>{if(e["LOD:requested level"]===t){if(delete e["LOD:requested level"],Array.isArray(s)){const n=o.index||0;s=s[n]}s&&i!=s&&((s==null?void 0:s.isBufferGeometry)?(e.geometry=s,L&&ye(e,"geometry",o.url)):L&&console.error("Invalid LOD geometry",s))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else L&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",e);return Promise.resolve(null)}static assignTextureLOD(e,t=0){if(!e)return Promise.resolve(null);if(e instanceof g.Material||e.isMaterial===!0){const r=e,i=[],o=new Array;if(L&&de.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const n of Object.keys(s.uniforms)){const a=s.uniforms[n].value;if((a==null?void 0:a.isTexture)===!0){const f=this.assignTextureLODForSlot(a,t,r,n);i.push(f),o.push(n)}}}else for(const s of Object.keys(r)){const n=r[s];if((n==null?void 0:n.isTexture)===!0){const a=this.assignTextureLODForSlot(n,t,r,s);i.push(a),o.push(s)}}return Promise.all(i).then(s=>{const n=new Array;for(let a=0;a<s.length;a++){const f=s[a],c=o[a];f&&f.isTexture===!0?n.push({material:r,slot:c,texture:f,level:t}):n.push({material:r,slot:c,texture:null,level:t})}return n})}if(e instanceof g.Texture||e.isTexture===!0){const r=e;return this.assignTextureLODForSlot(r,t,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(e,t,r,i){return(e==null?void 0:e.isTexture)!==!0?Promise.resolve(null):i==="glyphMap"?Promise.resolve(e):O.getOrLoadLOD(e,t).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=e){if(r&&i){const s=r[i];if(s){const n=this.getAssignedLODInformation(s);if(n&&(n==null?void 0:n.level)<t)return L==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,t,r,s,o),null}r[i]=o}if(L&&i&&r){const s=this.getAssignedLODInformation(e);s&&ye(r,i,s.url)}}return o}else L=="verbose"&&console.warn("No LOD found for",e,t);return null}).catch(o=>(console.error("Error loading LOD",e,o),null))}afterRoot(e){var t,r;return L&&console.log("AFTER",this.url,e),(t=this.parser.json.textures)==null||t.forEach((i,o)=>{var s;if(i!=null&&i.extensions){const n=i==null?void 0:i.extensions[G];if(n){if(!n.lods){L&&console.warn("Texture has no LODs",n);return}let a=!1;for(const f of this.parser.associations.keys())f.isTexture===!0&&this.parser.associations.get(f).textures===o&&(a=!0,O.registerTexture(this.url,f,(s=n.lods)==null?void 0:s.length,o,n));a||this.parser.getDependency("texture",o).then(f=>{var c;f&&O.registerTexture(this.url,f,(c=n.lods)==null?void 0:c.length,o,n)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[G];if(s&&s.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const a=this.parser.associations.get(n);a.meshes===o&&O.registerMesh(this.url,s.guid,n,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var n,a,f,c;const r=L=="verbose",i=e.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(e.isTexture===!0){const m=e;m.source&&m.source[oe]&&(s=m.source[oe])}if(s||(s=O.lodInfos.get(o)),s){if(t>0){let x=!1;const v=Array.isArray(s.lods);if(v&&t>=s.lods.length?x=!0:v||(x=!0),x)return this.lowresCache.get(o)}const m=Array.isArray(s.lods)?(n=s.lods[t])==null?void 0:n.path:s.lods;if(!m)return L&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const u=Ee(i.url,m);if(u.endsWith(".glb")||u.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const x=u+"_"+s.guid,v=this.previouslyLoaded.get(x);if(v!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${x}`);let y=await v.catch(N=>(console.error(`Error loading LOD ${t} from ${u}
2
+ `,N),null)),D=!1;if(y==null||(y instanceof g.Texture&&e instanceof g.Texture?(a=y.image)!=null&&a.data||(f=y.source)!=null&&f.data?y=this.copySettings(e,y):(D=!0,this.previouslyLoaded.delete(x)):y instanceof g.BufferGeometry&&e instanceof g.BufferGeometry&&((c=y.attributes.position)!=null&&c.array||(D=!0,this.previouslyLoaded.delete(x)))),!D)return y}const M=s,R=new Promise(async(y,D)=>{const N=new Oe.GLTFLoader;pe(N),L&&(await new Promise(T=>setTimeout(T,1e3)),r&&console.warn("Start loading (delayed) "+u,M.guid));let k=u;if(M&&Array.isArray(M.lods)){const T=M.lods[t];T.hash&&(k+="?v="+T.hash)}const w=await N.loadAsync(k).catch(T=>(console.error(`Error loading LOD ${t} from ${u}
3
+ `,T),null));if(!w)return null;const $=w.parser;r&&console.log("Loading finished "+u,M.guid);let I=0;if(w.parser.json.textures){let T=!1;for(const p of w.parser.json.textures){if(p!=null&&p.extensions){const h=p==null?void 0:p.extensions[G];if(h!=null&&h.guid&&h.guid===M.guid){T=!0;break}}I++}if(T){let p=await $.getDependency("texture",I);return p&&O.assignLODInformation(i.url,p,o,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+p.name+'"',u,I,p,x),e instanceof g.Texture&&(p=this.copySettings(e,p)),p&&(p.guid=M.guid),y(p)}else L&&console.warn("Could not find texture with guid",M.guid,w.parser.json)}if(I=0,w.parser.json.meshes){let T=!1;for(const p of w.parser.json.meshes){if(p!=null&&p.extensions){const h=p==null?void 0:p.extensions[G];if(h!=null&&h.guid&&h.guid===M.guid){T=!0;break}}I++}if(T){const p=await $.getDependency("mesh",I),h=M;if(r&&console.log(`Loaded Mesh "${p.name}"`,u,I,p,x),p.isMesh===!0){const _=p.geometry;return O.assignLODInformation(i.url,_,o,t,void 0,h.density),y(_)}else{const _=new Array;for(let b=0;b<p.children.length;b++){const A=p.children[b];if(A.isMesh===!0){const P=A.geometry;O.assignLODInformation(i.url,P,o,t,b,h.density),_.push(P)}}return y(_)}}else L&&console.warn("Could not find mesh with guid",M.guid,w.parser.json)}return y(null)});return this.previouslyLoaded.set(x,R),await R}else if(e instanceof g.Texture){r&&console.log("Load texture from uri: "+u);const v=await new g.TextureLoader().loadAsync(u);return v?(v.guid=s.guid,v.flipY=!1,v.needsUpdate=!0,v.colorSpace=e.colorSpace,r&&console.log(s,v)):L&&console.warn("failed loading",u),v}}else L&&console.warn(`Can not load LOD ${t}: no LOD info found for "${o}" ${e.name}`,e.type);return null}static assignLODInformation(e,t,r,i,o,s){if(!t)return;t.userData||(t.userData={});const n=new ke(e,r,i,o,s);t.userData.LODS=n}static getAssignedLODInformation(e){var t;return((t=e==null?void 0:e.userData)==null?void 0:t.LODS)||null}static copySettings(e,t){return t=t.clone(),L&&console.warn(`Copying texture settings
4
4
  `,e.uuid,`
5
- `,t.uuid),t.offset=e.offset,t.repeat=e.repeat,t.colorSpace=e.colorSpace,t.magFilter=e.magFilter,t.minFilter=e.minFilter,t.wrapS=e.wrapS,t.wrapT=e.wrapT,t.flipY=e.flipY,t.anisotropy=e.anisotropy,t.mipmaps||(t.generateMipmaps=e.generateMipmaps),t}};let S=O;d(S,"registerTexture",(e,t,r,i,o)=>{if(m&&console.log("> Progressive: register texture",i,t.name,t.uuid,t,o),!t){m&&console.error("gltf-progressive: Register texture without texture");return}t.source&&(t.source[ie]=o);const s=o.guid;O.assignLODInformation(e,t,s,r,i,void 0),O.lodInfos.set(s,o),O.lowresCache.set(s,t)}),d(S,"registerMesh",(e,t,r,i,o,s)=>{var f;m&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;if(!n){m&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),O.assignLODInformation(e,n,t,i,o,s.density),O.lodInfos.set(t,s);let a=O.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],O.lowresCache.set(t,a),i>0&&!re(r)&&Le(r,n);for(const c of V)(f=c.onRegisteredNewMesh)==null||f.call(c,r,s)}),d(S,"lodInfos",new Map),d(S,"previouslyLoaded",new Map),d(S,"lowresCache",new Map);class ke{constructor(e,t,r,i,o){d(this,"url");d(this,"key");d(this,"level");d(this,"index");d(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const z=J("debugprogressive"),Ie=J("noprogressive"),ne=Symbol("Needle:LODSManager"),ae=Symbol("Needle:LODState"),U=Symbol("Needle:CurrentLOD"),E={mesh_lod:-1,texture_lod:-1},C=class{constructor(e,t){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new g.Matrix4);d(this,"cameraFrustrum",new g.Frustum);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval",0);d(this,"pause",!1);d(this,"_frame",0);d(this,"_originalRender");d(this,"_sphere",new g.Sphere);d(this,"_tempBox",new g.Box3);d(this,"_tempBox2",new g.Box3);d(this,"tempMatrix",new g.Matrix4);d(this,"_tempWorldPosition",new g.Vector3);d(this,"_tempBoxSize",new g.Vector3);d(this,"_tempBox2Size",new g.Vector3);this.renderer=e,this.context={...t}}static getObjectLODState(e){return e[ae]}static addPlugin(e){V.push(e)}static removePlugin(e){const t=V.indexOf(e);t>=0&&V.splice(t,1)}static get(e,t){if(e[ne])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),e[ne];const r=new C(e,{engine:"unknown",...t});return e[ne]=r,r}get plugins(){return V}enable(){if(this._originalRender)return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let e=0;this._originalRender=this.renderer.render;const t=this;ge(this.renderer),this.renderer.render=function(r,i){t.renderer.getRenderTarget()==null&&(e=0,t._frame+=1);const s=t._frame,n=e++;t.onBeforeRender(r,i,n,s),t._originalRender.call(this,r,i),t.onAfterRender(r,i,n,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,i){}onAfterRender(e,t,r,i){var a,f;if(this.pause)return;const o=this.renderer.renderLists.get(e,0),s=o.opaque;let n=!0;if(s.length===1){const c=s[0].material;(c.name==="EffectMaterial"||c.name==="CopyShader")&&(n=!1)}if((t.parent&&t.parent.type==="CubeCamera"||r>=1&&t.type==="OrthographicCamera")&&(n=!1),n){if(Ie||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const c=this.targetTriangleDensity;for(const u of s){if(u.material&&(((a=u.geometry)==null?void 0:a.type)==="BoxGeometry"||((f=u.geometry)==null?void 0:f.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){z&&(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",u,u.material.name,u.material.type)));continue}switch(u.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const x=u.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,c,i)}const L=o.transparent;for(const u of L){const x=u.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,c,i)}}}updateLODs(e,t,r,i,o){var a,f;r.userData||(r.userData={});let s=r[ae];if(s||(s=new Ge,r[ae]=s),s.frames++<2)return;for(const c of V)(a=c.onBeforeUpdateLOD)==null||a.call(c,this.renderer,e,t,r);this.calculateLodLevel(t,r,s,i,E),E.mesh_lod=Math.round(E.mesh_lod),E.texture_lod=Math.round(E.texture_lod),E.mesh_lod>=0&&this.loadProgressiveMeshes(r,E.mesh_lod);let n=E.texture_lod;if(r.material&&n>=0){const c=r["DEBUG:LOD"];c!=null&&(n=c),this.loadProgressiveTextures(r.material,n)}for(const c of V)(f=c.onAfterUpdatedLOD)==null||f.call(c,this.renderer,e,t,r,E);s.lastLodLevel_Mesh=E.mesh_lod,s.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(e,t){if(!e)return;if(Array.isArray(e)){for(const i of e)this.loadProgressiveTextures(i,t);return}let r=!1;(e[U]===void 0||t<e[U])&&(r=!0),r&&(e[U]=t,S.assignTextureLOD(e,t))}loadProgressiveMeshes(e,t){if(!e)return Promise.resolve(null);if(e[U]!==t){e[U]=t;const r=e.geometry;return S.assignMeshLOD(e,t).then(i=>(i&&e[U]==t&&r!=e.geometry,i))}return Promise.resolve(null)}static isInside(e,t){const r=e.min,i=e.max,o=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(t).z<0}calculateLodLevel(e,t,r,i,o){var B,F;if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}let n=10+1,a=!1;if(z&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const f=S.getMeshLODInformation(t.geometry),c=f==null?void 0:f.lods,L=c&&c.length>0,u=S.getMaterialMinMaxLODsCount(t.material),x=(u==null?void 0:u.min_count)!=1/0&&u.min_count>0&&u.max_count>0;if(!L&&!x){o.mesh_lod=0,o.texture_lod=0;return}if(L||(a=!0,n=0),!((B=this.cameraFrustrum)!=null&&B.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}const _=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let M=t.geometry.boundingBox;if(t.type==="SkinnedMesh"){const y=t;y.boundingBox||y.computeBoundingBox(),M=y.boundingBox}if(M&&e.isPerspectiveCamera){const y=e;if(t.geometry.attributes.color&&t.geometry.attributes.color.count<100&&t.geometry.boundingSphere){this._sphere.copy(t.geometry.boundingSphere),this._sphere.applyMatrix4(t.matrixWorld);const h=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(h)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(M),this._tempBox.applyMatrix4(t.matrixWorld),C.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.fov>70){const h=this._tempBox.min,w=this._tempBox.max;let b=h.x,A=h.y,P=w.x,W=w.y;const Q=2,se=1.5,Z=(h.x+w.x)*.5,j=(h.y+w.y)*.5;b=(b-Z)*Q+Z,A=(A-j)*Q+j,P=(P-Z)*Q+Z,W=(W-j)*Q+j;const De=b<0&&P>0?0:Math.min(Math.abs(h.x),Math.abs(w.x)),we=A<0&&W>0?0:Math.min(Math.abs(h.y),Math.abs(w.y)),oe=Math.max(De,we);r.lastCentrality=(se-oe)*(se-oe)*(se-oe)}else r.lastCentrality=1;const D=this._tempBox.getSize(this._tempBoxSize);D.multiplyScalar(.5),screen.availHeight>0&&_>0&&D.multiplyScalar(_/screen.availHeight),D.x*=y.aspect;const N=e.matrixWorldInverse,k=this._tempBox2;k.copy(M),k.applyMatrix4(t.matrixWorld),k.applyMatrix4(N);const v=k.getSize(this._tempBox2Size),$=Math.max(v.x,v.y);if(Math.max(D.x,D.y)!=0&&$!=0&&(D.z=v.z/Math.max(v.x,v.y)*Math.max(D.x,D.y)),r.lastScreenCoverage=Math.max(D.x,D.y,D.z),r.lastScreenspaceVolume.copy(D),r.lastScreenCoverage*=r.lastCentrality,z&&C.debugDrawLine){const h=this.tempMatrix.copy(this.projectionScreenMatrix);h.invert();const w=C.corner0,b=C.corner1,A=C.corner2,P=C.corner3;w.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=w.x,A.copy(this._tempBox.max),A.y=w.y,P.copy(this._tempBox.max);const W=(w.z+P.z)*.5;w.z=b.z=A.z=P.z=W,w.applyMatrix4(h),b.applyMatrix4(h),A.applyMatrix4(h),P.applyMatrix4(h),C.debugDrawLine(w,b,255),C.debugDrawLine(w,A,255),C.debugDrawLine(b,P,255),C.debugDrawLine(A,P,255)}let T=999;if(c&&r.lastScreenCoverage>0){for(let h=0;h<c.length;h++)if(c[h].density/r.lastScreenCoverage<i){T=h;break}}T<n&&(n=T,a=!0)}if(a?o.mesh_lod=n:o.mesh_lod=r.lastLodLevel_Mesh,z&&o.mesh_lod!=r.lastLodLevel_Mesh){const D=c==null?void 0:c[o.mesh_lod];D&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${o.mesh_lod} (${D.density.toFixed(0)}) - ${t.name}`)}if(x)if(r.lastLodLevel_Texture<0){if(o.texture_lod=u.max_count-1,z){const y=u.lods[u.max_count-1];z&&console.log(`First Texture LOD ${o.texture_lod} (${y.max_height}px) - ${t.name}`)}}else{const y=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let D=r.lastScreenCoverage*2;((F=this.context)==null?void 0:F.engine)==="model-viewer"&&(D*=2);const k=_/window.devicePixelRatio*D;for(let v=u.lods.length-1;v>=0;v--){let $=u.lods[v];if(!(Re()&&$.max_height>4096)&&$.max_height>k){if(o.texture_lod=v,o.texture_lod<r.lastLodLevel_Texture){const I=$.max_height;z&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${o.texture_lod} = ${I}px
5
+ `,t.uuid),t.offset=e.offset,t.repeat=e.repeat,t.colorSpace=e.colorSpace,t.magFilter=e.magFilter,t.minFilter=e.minFilter,t.wrapS=e.wrapS,t.wrapT=e.wrapT,t.flipY=e.flipY,t.anisotropy=e.anisotropy,t.mipmaps||(t.generateMipmaps=e.generateMipmaps),t}};let S=O;d(S,"registerTexture",(e,t,r,i,o)=>{if(L&&console.log("> Progressive: register texture",i,t.name,t.uuid,t,o),!t){L&&console.error("gltf-progressive: Register texture without texture");return}t.source&&(t.source[oe]=o);const s=o.guid;O.assignLODInformation(e,t,s,r,i,void 0),O.lodInfos.set(s,o),O.lowresCache.set(s,t)}),d(S,"registerMesh",(e,t,r,i,o,s)=>{var f;L&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;if(!n){L&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),O.assignLODInformation(e,n,t,i,o,s.density),O.lodInfos.set(t,s);let a=O.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],O.lowresCache.set(t,a),i>0&&!re(r)&&me(r,n);for(const c of V)(f=c.onRegisteredNewMesh)==null||f.call(c,r,s)}),d(S,"lodInfos",new Map),d(S,"previouslyLoaded",new Map),d(S,"lowresCache",new Map);class ke{constructor(e,t,r,i,o){d(this,"url");d(this,"key");d(this,"level");d(this,"index");d(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const z=J("debugprogressive"),Ie=J("noprogressive"),ne=Symbol("Needle:LODSManager"),ae=Symbol("Needle:LODState"),U=Symbol("Needle:CurrentLOD"),B={mesh_lod:-1,texture_lod:-1},E=class{constructor(e,t){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new g.Matrix4);d(this,"cameraFrustrum",new g.Frustum);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval",0);d(this,"pause",!1);d(this,"_lodchangedlisteners",[]);d(this,"_frame",0);d(this,"_originalRender");d(this,"_sphere",new g.Sphere);d(this,"_tempBox",new g.Box3);d(this,"_tempBox2",new g.Box3);d(this,"tempMatrix",new g.Matrix4);d(this,"_tempWorldPosition",new g.Vector3);d(this,"_tempBoxSize",new g.Vector3);d(this,"_tempBox2Size",new g.Vector3);this.renderer=e,this.context={...t}}static getObjectLODState(e){return e[ae]}static addPlugin(e){V.push(e)}static removePlugin(e){const t=V.indexOf(e);t>=0&&V.splice(t,1)}static get(e,t){if(e[ne])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),e[ne];const r=new E(e,{engine:"unknown",...t});return e[ne]=r,r}get plugins(){return V}addEventListener(e,t){e==="changed"&&this._lodchangedlisteners.push(t)}enable(){if(this._originalRender)return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let e=0;this._originalRender=this.renderer.render;const t=this;ge(this.renderer),this.renderer.render=function(r,i){t.renderer.getRenderTarget()==null&&(e=0,t._frame+=1);const s=t._frame,n=e++;t.onBeforeRender(r,i,n,s),t._originalRender.call(this,r,i),t.onAfterRender(r,i,n,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,i){}onAfterRender(e,t,r,i){var a,f;if(this.pause)return;const o=this.renderer.renderLists.get(e,0),s=o.opaque;let n=!0;if(s.length===1){const c=s[0].material;(c.name==="EffectMaterial"||c.name==="CopyShader")&&(n=!1)}if((t.parent&&t.parent.type==="CubeCamera"||r>=1&&t.type==="OrthographicCamera")&&(n=!1),n){if(Ie||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const c=this.targetTriangleDensity;for(const u of s){if(u.material&&(((a=u.geometry)==null?void 0:a.type)==="BoxGeometry"||((f=u.geometry)==null?void 0:f.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){z&&(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",u,u.material.name,u.material.type)));continue}switch(u.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const x=u.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,c,i)}const m=o.transparent;for(const u of m){const x=u.object;(x instanceof g.Mesh||x.isMesh)&&this.updateLODs(e,t,x,c,i)}}}updateLODs(e,t,r,i,o){var a,f;r.userData||(r.userData={});let s=r[ae];if(s||(s=new Ge,r[ae]=s),s.frames++<2)return;for(const c of V)(a=c.onBeforeUpdateLOD)==null||a.call(c,this.renderer,e,t,r);this.calculateLodLevel(t,r,s,i,B),B.mesh_lod=Math.round(B.mesh_lod),B.texture_lod=Math.round(B.texture_lod),B.mesh_lod>=0&&this.loadProgressiveMeshes(r,B.mesh_lod);let n=B.texture_lod;if(r.material&&n>=0){const c=r["DEBUG:LOD"];c!=null&&(n=c),this.loadProgressiveTextures(r.material,n)}for(const c of V)(f=c.onAfterUpdatedLOD)==null||f.call(c,this.renderer,e,t,r,B);s.lastLodLevel_Mesh=B.mesh_lod,s.lastLodLevel_Texture=B.texture_lod}loadProgressiveTextures(e,t){if(!e)return;if(Array.isArray(e)){for(const i of e)this.loadProgressiveTextures(i,t);return}let r=!1;(e[U]===void 0||t<e[U])&&(r=!0),r&&(e[U]=t,S.assignTextureLOD(e,t).then(i=>{this._lodchangedlisteners.forEach(o=>o({type:"texture",level:t,object:e}))}))}loadProgressiveMeshes(e,t){if(!e)return Promise.resolve(null);if(e[U]!==t){e[U]=t;const r=e.geometry;return S.assignMeshLOD(e,t).then(i=>(i&&e[U]==t&&r!=e.geometry&&this._lodchangedlisteners.forEach(o=>o({type:"mesh",level:t,object:e})),i))}return Promise.resolve(null)}static isInside(e,t){const r=e.min,i=e.max,o=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(t).z<0}calculateLodLevel(e,t,r,i,o){var R,F;if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}let n=10+1,a=!1;if(z&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const f=S.getMeshLODInformation(t.geometry),c=f==null?void 0:f.lods,m=c&&c.length>0,u=S.getMaterialMinMaxLODsCount(t.material),x=(u==null?void 0:u.min_count)!=1/0&&u.min_count>0&&u.max_count>0;if(!m&&!x){o.mesh_lod=0,o.texture_lod=0;return}if(m||(a=!0,n=0),!((R=this.cameraFrustrum)!=null&&R.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}const v=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let M=t.geometry.boundingBox;if(t.type==="SkinnedMesh"){const y=t;y.boundingBox||y.computeBoundingBox(),M=y.boundingBox}if(M&&e.isPerspectiveCamera){const y=e;if(t.geometry.attributes.color&&t.geometry.attributes.color.count<100&&t.geometry.boundingSphere){this._sphere.copy(t.geometry.boundingSphere),this._sphere.applyMatrix4(t.matrixWorld);const h=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(h)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(M),this._tempBox.applyMatrix4(t.matrixWorld),E.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.fov>70){const h=this._tempBox.min,_=this._tempBox.max;let b=h.x,A=h.y,P=_.x,W=_.y;const Q=2,se=1.5,Z=(h.x+_.x)*.5,j=(h.y+_.y)*.5;b=(b-Z)*Q+Z,A=(A-j)*Q+j,P=(P-Z)*Q+Z,W=(W-j)*Q+j;const De=b<0&&P>0?0:Math.min(Math.abs(h.x),Math.abs(_.x)),_e=A<0&&W>0?0:Math.min(Math.abs(h.y),Math.abs(_.y)),ie=Math.max(De,_e);r.lastCentrality=(se-ie)*(se-ie)*(se-ie)}else r.lastCentrality=1;const D=this._tempBox.getSize(this._tempBoxSize);D.multiplyScalar(.5),screen.availHeight>0&&v>0&&D.multiplyScalar(v/screen.availHeight),D.x*=y.aspect;const N=e.matrixWorldInverse,k=this._tempBox2;k.copy(M),k.applyMatrix4(t.matrixWorld),k.applyMatrix4(N);const w=k.getSize(this._tempBox2Size),$=Math.max(w.x,w.y);if(Math.max(D.x,D.y)!=0&&$!=0&&(D.z=w.z/Math.max(w.x,w.y)*Math.max(D.x,D.y)),r.lastScreenCoverage=Math.max(D.x,D.y,D.z),r.lastScreenspaceVolume.copy(D),r.lastScreenCoverage*=r.lastCentrality,z&&E.debugDrawLine){const h=this.tempMatrix.copy(this.projectionScreenMatrix);h.invert();const _=E.corner0,b=E.corner1,A=E.corner2,P=E.corner3;_.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=_.x,A.copy(this._tempBox.max),A.y=_.y,P.copy(this._tempBox.max);const W=(_.z+P.z)*.5;_.z=b.z=A.z=P.z=W,_.applyMatrix4(h),b.applyMatrix4(h),A.applyMatrix4(h),P.applyMatrix4(h),E.debugDrawLine(_,b,255),E.debugDrawLine(_,A,255),E.debugDrawLine(b,P,255),E.debugDrawLine(A,P,255)}let T=999;if(c&&r.lastScreenCoverage>0){for(let h=0;h<c.length;h++)if(c[h].density/r.lastScreenCoverage<i){T=h;break}}T<n&&(n=T,a=!0)}if(a?o.mesh_lod=n:o.mesh_lod=r.lastLodLevel_Mesh,z&&o.mesh_lod!=r.lastLodLevel_Mesh){const D=c==null?void 0:c[o.mesh_lod];D&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${o.mesh_lod} (${D.density.toFixed(0)}) - ${t.name}`)}if(x)if(r.lastLodLevel_Texture<0){if(o.texture_lod=u.max_count-1,z){const y=u.lods[u.max_count-1];z&&console.log(`First Texture LOD ${o.texture_lod} (${y.max_height}px) - ${t.name}`)}}else{const y=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let D=r.lastScreenCoverage*2;((F=this.context)==null?void 0:F.engine)==="model-viewer"&&(D*=2);const k=v/window.devicePixelRatio*D;for(let w=u.lods.length-1;w>=0;w--){let $=u.lods[w];if(!(Ce()&&$.max_height>4096)&&$.max_height>k){if(o.texture_lod=w,o.texture_lod<r.lastLodLevel_Texture){const I=$.max_height;z&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${o.texture_lod} = ${I}px
6
6
  Screensize: ${k.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${y.toFixed(1)}
7
- ${t.name}`)}break}}}else o.texture_lod=0}};let R=C;d(R,"debugDrawLine"),d(R,"corner0",new g.Vector3),d(R,"corner1",new g.Vector3),d(R,"corner2",new g.Vector3),d(R,"corner3",new g.Vector3),d(R,"_tempPtInside",new g.Vector3);class Ge{constructor(){d(this,"frames",0);d(this,"lastLodLevel_Mesh",-1);d(this,"lastLodLevel_Texture",-1);d(this,"lastScreenCoverage",0);d(this,"lastScreenspaceVolume",new g.Vector3);d(this,"lastCentrality",0)}}const xe=Symbol("NEEDLE_mesh_lod"),ee=Symbol("NEEDLE_texture_lod");function Me(){document.removeEventListener("DOMContentLoaded",le),document.addEventListener("DOMContentLoaded",le),le()}function le(){document.querySelectorAll("model-viewer").forEach((e,t)=>{Fe(e,t)})}const me=new WeakSet;function Fe(l,e){if(!l||me.has(l))return null;me.add(l),console.debug("[gltf-progressive] found model-viewer..."+e);let t=null,r=null,i=null;for(let o=l;o!=null;o=Object.getPrototypeOf(o)){const s=Object.getOwnPropertySymbols(o),n=s.find(c=>c.toString()=="Symbol(renderer)"),a=s.find(c=>c.toString()=="Symbol(scene)"),f=s.find(c=>c.toString()=="Symbol(needsRender)");!t&&n!=null&&(t=l[n].threeRenderer),!r&&a!=null&&(r=l[a]),!i&&f!=null&&(i=l[f])}if(t&&r){console.debug("[gltf-progressive] setup model-viewer");const o=R.get(t,{engine:"model-viewer"});if(R.addPlugin(new $e),o.enable(),r&&i){let s=0,n=setInterval(()=>{if(s++>10){clearInterval(n);return}i==null||i.call(l)},150)}return()=>{o.disable()}}return null}class $e{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,t,r,i){this.tryParseMeshLOD(t,i),this.tryParseTextureLOD(t,i)}getUrl(e){if(!e)return null;let t=e.getAttribute("src");return t||(t=e.src),t||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),t}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,t){if(t[ee]==!0)return;t[ee]=!0;const r=this.tryGetCurrentGLTF(e),i=this.tryGetCurrentModelViewer(e),o=this.getUrl(i);if(o&&r&&t.material){let s=function(a){var c,L,u;if(a[ee]==!0)return;a[ee]=!0,a.userData&&(a.userData.LOD=-1);const f=Object.keys(a);for(let x=0;x<f.length;x++){const _=f[x],M=a[_];if((M==null?void 0:M.isTexture)===!0){const B=(L=(c=M.userData)==null?void 0:c.associations)==null?void 0:L.textures;if(B==null)continue;const F=r.parser.json.textures[B];if(!F){console.warn("Texture data not found for texture index "+B);continue}if((u=F==null?void 0:F.extensions)!=null&&u[G]){const y=F.extensions[G];y&&o&&S.registerTexture(o,M,y.lods.length,B,y)}}}};const n=t.material;if(Array.isArray(n))for(const a of n)s(a);else s(n)}}tryParseMeshLOD(e,t){var s,n;if(t[xe]==!0)return;t[xe]=!0;const r=this.tryGetCurrentModelViewer(e),i=this.getUrl(r);if(!i)return;const o=(n=(s=t.userData)==null?void 0:s.gltfExtensions)==null?void 0:n[G];if(o&&i){const a=t.uuid;S.registerMesh(i,a,t,0,o.lods.length,o)}}}Me();function Ve(l,e,t,r){ge(e),pe(t),t.register(o=>new S(o,l));const i=R.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}exports.EXTENSION_NAME=G;exports.LODsManager=R;exports.NEEDLE_progressive=S;exports.VERSION=de;exports.addDracoAndKTX2Loaders=pe;exports.createLoaders=ge;exports.getRaycastMesh=re;exports.patchModelViewer=Me;exports.setDracoDecoderLocation=Ae;exports.setKTX2TranscoderLocation=Pe;exports.setRaycastMesh=Le;exports.useNeedleProgressive=Ve;exports.useRaycastMeshes=Ee;
7
+ ${t.name}`)}break}}}else o.texture_lod=0}};let C=E;d(C,"debugDrawLine"),d(C,"corner0",new g.Vector3),d(C,"corner1",new g.Vector3),d(C,"corner2",new g.Vector3),d(C,"corner3",new g.Vector3),d(C,"_tempPtInside",new g.Vector3);class Ge{constructor(){d(this,"frames",0);d(this,"lastLodLevel_Mesh",-1);d(this,"lastLodLevel_Texture",-1);d(this,"lastScreenCoverage",0);d(this,"lastScreenspaceVolume",new g.Vector3);d(this,"lastCentrality",0)}}const xe=Symbol("NEEDLE_mesh_lod"),ee=Symbol("NEEDLE_texture_lod");function Me(){document.removeEventListener("DOMContentLoaded",le),document.addEventListener("DOMContentLoaded",le),le()}function le(){document.querySelectorAll("model-viewer").forEach((e,t)=>{Fe(e,t)})}const Le=new WeakSet;function Fe(l,e){if(!l||Le.has(l))return null;Le.add(l),console.debug("[gltf-progressive] found model-viewer..."+e);let t=null,r=null,i=null;for(let o=l;o!=null;o=Object.getPrototypeOf(o)){const s=Object.getOwnPropertySymbols(o),n=s.find(c=>c.toString()=="Symbol(renderer)"),a=s.find(c=>c.toString()=="Symbol(scene)"),f=s.find(c=>c.toString()=="Symbol(needsRender)");!t&&n!=null&&(t=l[n].threeRenderer),!r&&a!=null&&(r=l[a]),!i&&f!=null&&(i=l[f])}if(t&&r){let o=function(){if(i){let n=0,a=setInterval(()=>{if(n++>5){clearInterval(a);return}i==null||i.call(l)},300)}};console.debug("[gltf-progressive] setup model-viewer");const s=C.get(t,{engine:"model-viewer"});return C.addPlugin(new $e),s.enable(),s.addEventListener("changed",()=>{i==null||i.call(l)}),l.addEventListener("model-visibility",n=>{n.detail.visible&&(i==null||i.call(l))}),l.addEventListener("load",()=>{o()}),()=>{s.disable()}}return null}class $e{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,t,r,i){this.tryParseMeshLOD(t,i),this.tryParseTextureLOD(t,i)}getUrl(e){if(!e)return null;let t=e.getAttribute("src");return t||(t=e.src),t||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),t}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,t){if(t[ee]==!0)return;t[ee]=!0;const r=this.tryGetCurrentGLTF(e),i=this.tryGetCurrentModelViewer(e),o=this.getUrl(i);if(o&&r&&t.material){let s=function(a){var c,m,u;if(a[ee]==!0)return;a[ee]=!0,a.userData&&(a.userData.LOD=-1);const f=Object.keys(a);for(let x=0;x<f.length;x++){const v=f[x],M=a[v];if((M==null?void 0:M.isTexture)===!0){const R=(m=(c=M.userData)==null?void 0:c.associations)==null?void 0:m.textures;if(R==null)continue;const F=r.parser.json.textures[R];if(!F){console.warn("Texture data not found for texture index "+R);continue}if((u=F==null?void 0:F.extensions)!=null&&u[G]){const y=F.extensions[G];y&&o&&S.registerTexture(o,M,y.lods.length,R,y)}}}};const n=t.material;if(Array.isArray(n))for(const a of n)s(a);else s(n)}}tryParseMeshLOD(e,t){var s,n;if(t[xe]==!0)return;t[xe]=!0;const r=this.tryGetCurrentModelViewer(e),i=this.getUrl(r);if(!i)return;const o=(n=(s=t.userData)==null?void 0:s.gltfExtensions)==null?void 0:n[G];if(o&&i){const a=t.uuid;S.registerMesh(i,a,t,0,o.lods.length,o)}}}Me();function Ve(l,e,t,r){ge(e),pe(t),t.register(o=>new S(o,l));const i=C.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}exports.EXTENSION_NAME=G;exports.LODsManager=C;exports.NEEDLE_progressive=S;exports.VERSION=fe;exports.addDracoAndKTX2Loaders=pe;exports.createLoaders=ge;exports.getRaycastMesh=re;exports.patchModelViewer=Me;exports.setDracoDecoderLocation=Ae;exports.setKTX2TranscoderLocation=Pe;exports.setRaycastMesh=me;exports.useNeedleProgressive=Ve;exports.useRaycastMeshes=Be;
@@ -1,4 +1,4 @@
1
- import { Frustum, Matrix4, Object3D, Vector3, WebGLRenderer } from "three";
1
+ import { Frustum, Material, Matrix4, Object3D, Texture, Vector3, WebGLRenderer } from "three";
2
2
  import { NEEDLE_progressive_plugin } from "./plugins/plugin.js";
3
3
  export type LODManagerContext = {
4
4
  engine: "three" | "needle-engine" | "model-viewer" | "react-three-fiber" | "unknown";
@@ -7,6 +7,11 @@ export declare type LOD_Results = {
7
7
  mesh_lod: number;
8
8
  texture_lod: number;
9
9
  };
10
+ declare type LODChangedEventListener = (args: {
11
+ type: "mesh" | "texture";
12
+ level: number;
13
+ object: Object3D | Material | Texture;
14
+ }) => void;
10
15
  /**
11
16
  * The LODsManager class is responsible for managing the LODs and progressive assets in the scene. It will automatically update the LODs based on the camera position, screen coverage and mesh density of the objects.
12
17
  * It must be enabled by calling the `enable` method.
@@ -69,6 +74,8 @@ export declare class LODsManager {
69
74
  * If set to true, the LODsManager will not update the LODs.
70
75
  */
71
76
  pause: boolean;
77
+ private readonly _lodchangedlisteners;
78
+ addEventListener(evt: "changed", listener: LODChangedEventListener): void;
72
79
  private constructor();
73
80
  private _frame;
74
81
  private _originalRender?;
@@ -90,6 +90,12 @@ export class LODsManager {
90
90
  * If set to true, the LODsManager will not update the LODs.
91
91
  */
92
92
  pause = false;
93
+ _lodchangedlisteners = [];
94
+ addEventListener(evt, listener) {
95
+ if (evt === "changed") {
96
+ this._lodchangedlisteners.push(listener);
97
+ }
98
+ }
93
99
  // readonly plugins: NEEDLE_progressive_plugin[] = [];
94
100
  constructor(renderer, context) {
95
101
  this.renderer = renderer;
@@ -278,7 +284,9 @@ export class LODsManager {
278
284
  }
279
285
  if (update) {
280
286
  material[$currentLOD] = level;
281
- NEEDLE_progressive.assignTextureLOD(material, level);
287
+ NEEDLE_progressive.assignTextureLOD(material, level).then(_ => {
288
+ this._lodchangedlisteners.forEach(l => l({ type: "texture", level, object: material }));
289
+ });
282
290
  }
283
291
  }
284
292
  /** Load progressive meshes for the given mesh
@@ -295,6 +303,7 @@ export class LODsManager {
295
303
  const originalGeometry = mesh.geometry;
296
304
  return NEEDLE_progressive.assignMeshLOD(mesh, level).then(res => {
297
305
  if (res && mesh[$currentLOD] == level && originalGeometry != mesh.geometry) {
306
+ this._lodchangedlisteners.forEach(l => l({ type: "mesh", level, object: mesh }));
298
307
  // if (this.handles) {
299
308
  // for (const inst of this.handles) {
300
309
  // // if (inst["LOD"] < level) continue;
@@ -49,20 +49,33 @@ function _patchModelViewer(modelviewer, index) {
49
49
  const lod = LODsManager.get(renderer, { engine: "model-viewer" });
50
50
  LODsManager.addPlugin(new RegisterModelviewerDataPlugin());
51
51
  lod.enable();
52
- if (scene) {
53
- /**
54
- * For model viewer to immediately update without interaction we need to trigger a few renders
55
- * We do this so that the LODs are loaded
56
- */
52
+ // Trigger a render when a LOD has changed
53
+ lod.addEventListener("changed", () => {
54
+ needsRender?.call(modelviewer);
55
+ });
56
+ // Trigger a render when the model viewer visibility changes
57
+ modelviewer.addEventListener("model-visibility", (evt) => {
58
+ const visible = evt.detail.visible;
59
+ if (visible)
60
+ needsRender?.call(modelviewer);
61
+ });
62
+ modelviewer.addEventListener("load", () => {
63
+ renderFrames();
64
+ });
65
+ /**
66
+ * For model viewer to immediately update without interaction we need to trigger a few renders
67
+ * We do this so that the LODs are loaded
68
+ */
69
+ function renderFrames() {
57
70
  if (needsRender) {
58
71
  let forcedFrames = 0;
59
72
  let interval = setInterval(() => {
60
- if (forcedFrames++ > 10) {
73
+ if (forcedFrames++ > 5) {
61
74
  clearInterval(interval);
62
75
  return;
63
76
  }
64
77
  needsRender?.call(modelviewer);
65
- }, 150);
78
+ }, 300);
66
79
  }
67
80
  }
68
81
  return () => {
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // replaced at build time
2
- export const version = "1.2.2-alpha.2";
2
+ export const version = "1.2.2-alpha.3";
3
3
  globalThis["GLTF_PROGRESSIVE_VERSION"] = version;
4
4
  console.debug(`[gltf-progressive] version ${version}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/gltf-progressive",
3
- "version": "1.2.2-alpha.2",
3
+ "version": "1.2.2-alpha.3",
4
4
  "description": "three.js support for loading glTF or GLB files that contain progressive loading data",
5
5
  "homepage": "https://needle.tools",
6
6
  "author": {