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

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 _e=Object.defineProperty,we=(t,e,r)=>e in t?_e(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,d=(t,e,r)=>(we(t,typeof e!="symbol"?e+"":e,r),r);import{BufferGeometry as Q,Mesh as $,Material as Oe,Texture as W,TextureLoader as be,Matrix4 as fe,Frustum as Se,Sphere as Te,Box3 as me,Vector3 as R}from"three";import{GLTFLoader as Ae}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as Ee}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Ie}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Pe}from"three/examples/jsm/loaders/KTX2Loader.js";const se="";globalThis.GLTF_PROGRESSIVE_VERSION=se,console.debug(`[gltf-progressive] version ${se}`);let Z="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",oe="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(Z+"draco_decoder.js",{method:"head"}).catch(t=>{Z="./include/draco/",oe="./include/ktx2/"});function Ce(t){Z=t}function Be(t){oe=t}let U,ne,V;function ie(t){U||(U=new Ie,U.setDecoderPath(Z),U.setDecoderConfig({type:"js"})),V||(V=new Pe,V.setTranscoderPath(oe)),ne||(ne=Ee),t?V.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ae(t){t.dracoLoader||t.setDRACOLoader(U),t.ktx2Loader||t.setKTX2Loader(V),t.meshoptDecoder||t.setMeshoptDecoder(ne)}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 Re(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 J;function ke(){return J!==void 0||(J=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),q("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",J)),J}const le=Symbol("needle:raycast-mesh");function ee(t){return t?.[le]instanceof Q?t[le]:null}function pe(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ee(t)){const r=Ge(e);r.userData={isRaycastMesh:!0},t[le]=r}}function je(t=!0){if(t){if(X)return;const e=X=$.prototype.raycast;$.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(!X)return;$.prototype.raycast=X,X=null}}let X=null;function Ge(t){const e=new Q;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const k=new Array,C="NEEDLE_progressive",y=q("debugprogressive"),ue=Symbol("needle-progressive-texture"),K=new Map,ce=new Set;if(y){let t=function(){e+=1,console.log("Toggle LOD level",e,K),K.forEach((o,s)=>{for(const i of o.keys){const a=s[i];if(a!=null){if(a.isBufferGeometry===!0){const u=O.getMeshLODInformation(a),l=u?Math.min(e,u.lods.length):0;s["DEBUG:LOD"]=e,O.assignMeshLOD(s,l),u&&(r=Math.max(r,u.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,O.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,ce&&ce.forEach(s=>{s.name!="BackgroundCubeMaterial"&&s.glyphMap==null&&"wireframe"in s&&(s.wireframe=n)}))})}function xe(t,e,r){var n;if(!y)return;K.has(t)||K.set(t,{keys:[],sourceId:r});const o=K.get(t);((n=o?.keys)==null?void 0:n.includes(e))==!1&&o.keys.push(e)}const _=class{constructor(t,e){d(this,"parser"),d(this,"url"),d(this,"_isLoadingMesh"),d(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[C];return s?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var a;return this._isLoadingMesh=!1,i&&_.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 C}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 u=i.uniforms[a].value;u?.isTexture===!0&&s(u,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 u=r.getAssignedLODInformation(i);if(u){const l=r.lodInfos.get(u.key);if(l&&l.lods){a.min_count=Math.min(a.min_count,l.lods.length),a.max_count=Math.max(a.max_count,l.lods.length);for(let m=0;m<l.lods.length;m++){const c=l.lods[m];c.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,c.height),a.lods[m].max_height=Math.max(a.lods[m].max_height,c.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 $||t.isMesh===!0){const n=t.geometry,o=this.getAssignedLODInformation(n);if(!o)return Promise.resolve(null);for(const s of k)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,_.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&&xe(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 Oe||t.isMaterial===!0){const r=t,n=[],o=new Array;if(y&&ce.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 u=this.assignTextureLODForSlot(a,e,r,i);n.push(u),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 u=s[a],l=o[a];u&&u.isTexture===!0?i.push({material:r,slot:l,texture:u,level:e}):i.push({material:r,slot:l,texture:null,level:e})}return i})}if(t instanceof W||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):_.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&&xe(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[C];if(i){if(!i.lods){y&&console.warn("Texture has no LODs",i);return}let a=!1;for(const u of this.parser.associations.keys())u.isTexture===!0&&this.parser.associations.get(u).textures===o&&(a=!0,_.registerTexture(this.url,u,(s=i.lods)==null?void 0:s.length,o,i));a||this.parser.getDependency("texture",o).then(u=>{var l;u&&_.registerTexture(this.url,u,(l=i.lods)==null?void 0:l.length,o,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.extensions[C];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&&_.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 u=a?.key;let l;if(t.isTexture===!0){const m=t;m.source&&m.source[ue]&&(l=m.source[ue])}if(l||(l=_.lodInfos.get(u)),l){if(e>0){let f=!1;const S=Array.isArray(l.lods);if(S&&e>=l.lods.length?f=!0:S||(f=!0),f)return this.lowresCache.get(u)}const m=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!m)return y&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const c=Re(a.url,m);if(c.endsWith(".glb")||c.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const f=c+"_"+l.guid,S=this.previouslyLoaded.get(f);if(S!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let g=await S.catch(D=>(console.error(`Error loading LOD ${e} from ${c}
2
- `,D),null)),b=!1;if(g==null||(g instanceof W&&t instanceof W?(n=g.image)!=null&&n.data||(o=g.source)!=null&&o.data?g=this.copySettings(t,g):(b=!0,this.previouslyLoaded.delete(f)):g instanceof Q&&t instanceof Q&&((s=g.attributes.position)!=null&&s.array||(b=!0,this.previouslyLoaded.delete(f)))),!b)return g}const M=l,v=new Promise(async(g,b)=>{const D=new Ae;ae(D),y&&(await new Promise(p=>setTimeout(p,1e3)),i&&console.warn("Start loading (delayed) "+c,M.guid));let T=c;if(M&&Array.isArray(M.lods)){const p=M.lods[e];p.hash&&(T+="?v="+p.hash)}const A=await D.loadAsync(T).catch(p=>(console.error(`Error loading LOD ${e} from ${c}
3
- `,p),null));if(!A)return null;const F=A.parser;i&&console.log("Loading finished "+c,M.guid);let x=0;if(A.parser.json.textures){let p=!1;for(const h of A.parser.json.textures){if(h!=null&&h.extensions){const L=h?.extensions[C];if(L!=null&&L.guid&&L.guid===M.guid){p=!0;break}}x++}if(p){let h=await F.getDependency("texture",x);return h&&_.assignLODInformation(a.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',c,x,h,f),t instanceof W&&(h=this.copySettings(t,h)),h&&(h.guid=M.guid),g(h)}else y&&console.warn("Could not find texture with guid",M.guid,A.parser.json)}if(x=0,A.parser.json.meshes){let p=!1;for(const h of A.parser.json.meshes){if(h!=null&&h.extensions){const L=h?.extensions[C];if(L!=null&&L.guid&&L.guid===M.guid){p=!0;break}}x++}if(p){const h=await F.getDependency("mesh",x),L=M;if(i&&console.log(`Loaded Mesh "${h.name}"`,c,x,h,f),h.isMesh===!0){const w=h.geometry;return _.assignLODInformation(a.url,w,u,e,void 0,L.density),g(w)}else{const w=new Array;for(let P=0;P<h.children.length;P++){const j=h.children[P];if(j.isMesh===!0){const N=j.geometry;_.assignLODInformation(a.url,N,u,e,P,L.density),w.push(N)}}return g(w)}}else y&&console.warn("Could not find mesh with guid",M.guid,A.parser.json)}return g(null)});return this.previouslyLoaded.set(f,v),await v}else if(t instanceof W){i&&console.log("Load texture from uri: "+c);const f=await new be().loadAsync(c);return f?(f.guid=l.guid,f.flipY=!1,f.needsUpdate=!0,f.colorSpace=t.colorSpace,i&&console.log(l,f)):y&&console.warn("failed loading",c),f}}else y&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${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 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
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 O=_;d(O,"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[ue]=o);const s=o.guid;_.assignLODInformation(t,e,s,r,n,void 0),_.lodInfos.set(s,o),_.lowresCache.set(s,e)}),d(O,"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={}),_.assignLODInformation(t,a,e,n,o,s.density),_.lodInfos.set(e,s);let u=_.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],_.lowresCache.set(e,u),n>0&&!ee(r)&&pe(r,a);for(const l of k)(i=l.onRegisteredNewMesh)==null||i.call(l,r,s)}),d(O,"lodInfos",new Map),d(O,"previouslyLoaded",new Map),d(O,"lowresCache",new Map);class Fe{constructor(e,r,n,o,s){d(this,"url"),d(this,"key"),d(this,"level"),d(this,"index"),d(this,"density"),this.url=e,this.key=r,this.level=n,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const G=q("debugprogressive"),Ne=q("noprogressive"),de=Symbol("Needle:LODSManager"),he=Symbol("Needle:LODState"),z=Symbol("Needle:CurrentLOD"),I={mesh_lod:-1,texture_lod:-1},E=class{constructor(t,e){d(this,"context"),d(this,"renderer"),d(this,"projectionScreenMatrix",new fe),d(this,"cameraFrustrum",new Se),d(this,"targetTriangleDensity",2e5),d(this,"updateInterval",0),d(this,"pause",!1),d(this,"_frame",0),d(this,"_originalRender"),d(this,"_sphere",new Te),d(this,"_tempBox",new me),d(this,"_tempBox2",new me),d(this,"tempMatrix",new fe),d(this,"_tempWorldPosition",new R),d(this,"_tempBoxSize",new R),d(this,"_tempBox2Size",new R),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[he]}static addPlugin(t){k.push(t)}static removePlugin(t){const e=k.indexOf(t);e>=0&&k.splice(e,1)}static get(t,e){if(t[de])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[de];const r=new E(t,{engine:"unknown",...e});return t[de]=r,r}get plugins(){return k}enable(){if(this._originalRender)return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;this._originalRender=this.renderer.render;const e=this;ie(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 u=!0;if(a.length===1){const l=a[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(u=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(u=!1),u){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 l=this.targetTriangleDensity;for(const c of a){if(c.material&&(((o=c.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=c.geometry)==null?void 0:s.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){G&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}switch(c.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const f=c.object;(f instanceof $||f.isMesh)&&this.updateLODs(t,e,f,l,n)}const m=i.transparent;for(const c of m){const f=c.object;(f instanceof $||f.isMesh)&&this.updateLODs(t,e,f,l,n)}}}updateLODs(t,e,r,n,o){var s,i;r.userData||(r.userData={});let a=r[he];if(a||(a=new $e,r[he]=a),a.frames++<2)return;for(const l of k)(s=l.onBeforeUpdateLOD)==null||s.call(l,this.renderer,t,e,r);this.calculateLodLevel(e,r,a,n,I),I.mesh_lod=Math.round(I.mesh_lod),I.texture_lod=Math.round(I.texture_lod),I.mesh_lod>=0&&this.loadProgressiveMeshes(r,I.mesh_lod);let u=I.texture_lod;if(r.material&&u>=0){const l=r["DEBUG:LOD"];l!=null&&(u=l),this.loadProgressiveTextures(r.material,u)}for(const l of k)(i=l.onAfterUpdatedLOD)==null||i.call(l,this.renderer,t,e,r,I);a.lastLodLevel_Mesh=I.mesh_lod,a.lastLodLevel_Texture=I.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[z]===void 0||e<t[z])&&(r=!0),r&&(t[z]=e,O.assignTextureLOD(t,e))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[z]!==e){t[z]=e;const r=t.geometry;return O.assignMeshLOD(t,e).then(n=>(n&&t[z]==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;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let i=10+1,a=!1;if(G&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=O.getMeshLODInformation(e.geometry),l=u?.lods,m=l&&l.length>0,c=O.getMaterialMinMaxLODsCount(e.material),f=c?.min_count!=1/0&&c.min_count>0&&c.max_count>0;if(!m&&!f){o.mesh_lod=0,o.texture_lod=0;return}if(m||(a=!0,i=0),!((s=this.cameraFrustrum)!=null&&s.intersectsObject(e))){o.mesh_lod=99,o.texture_lod=99;return}const S=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let M=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const v=e;v.boundingBox||v.computeBoundingBox(),M=v.boundingBox}if(M&&t.isPerspectiveCamera){const v=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 x=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(x)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(M),this._tempBox.applyMatrix4(e.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&&v.fov>70){const x=this._tempBox.min,p=this._tempBox.max;let h=x.x,L=x.y,w=p.x,P=p.y;const j=2,N=1.5,H=(x.x+p.x)*.5,Y=(x.y+p.y)*.5;h=(h-H)*j+H,L=(L-Y)*j+Y,w=(w-H)*j+H,P=(P-Y)*j+Y;const Me=h<0&&w>0?0:Math.min(Math.abs(x.x),Math.abs(p.x)),De=L<0&&P>0?0:Math.min(Math.abs(x.y),Math.abs(p.y)),re=Math.max(Me,De);r.lastCentrality=(N-re)*(N-re)*(N-re)}else r.lastCentrality=1;const g=this._tempBox.getSize(this._tempBoxSize);g.multiplyScalar(.5),screen.availHeight>0&&S>0&&g.multiplyScalar(S/screen.availHeight),g.x*=v.aspect;const b=t.matrixWorldInverse,D=this._tempBox2;D.copy(M),D.applyMatrix4(e.matrixWorld),D.applyMatrix4(b);const T=D.getSize(this._tempBox2Size),A=Math.max(T.x,T.y);if(Math.max(g.x,g.y)!=0&&A!=0&&(g.z=T.z/Math.max(T.x,T.y)*Math.max(g.x,g.y)),r.lastScreenCoverage=Math.max(g.x,g.y,g.z),r.lastScreenspaceVolume.copy(g),r.lastScreenCoverage*=r.lastCentrality,G&&E.debugDrawLine){const x=this.tempMatrix.copy(this.projectionScreenMatrix);x.invert();const p=E.corner0,h=E.corner1,L=E.corner2,w=E.corner3;p.copy(this._tempBox.min),h.copy(this._tempBox.max),h.x=p.x,L.copy(this._tempBox.max),L.y=p.y,w.copy(this._tempBox.max);const P=(p.z+w.z)*.5;p.z=h.z=L.z=w.z=P,p.applyMatrix4(x),h.applyMatrix4(x),L.applyMatrix4(x),w.applyMatrix4(x),E.debugDrawLine(p,h,255),E.debugDrawLine(p,L,255),E.debugDrawLine(h,w,255),E.debugDrawLine(L,w,255)}let F=999;if(l&&r.lastScreenCoverage>0){for(let x=0;x<l.length;x++)if(l[x].density/r.lastScreenCoverage<n){F=x;break}}F<i&&(i=F,a=!0)}if(a?o.mesh_lod=i:o.mesh_lod=r.lastLodLevel_Mesh,G&&o.mesh_lod!=r.lastLodLevel_Mesh){const v=l?.[o.mesh_lod];v&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${o.mesh_lod} (${v.density.toFixed(0)}) - ${e.name}`)}if(f)if(r.lastLodLevel_Texture<0){if(o.texture_lod=c.max_count-1,G){const v=c.lods[c.max_count-1];G&&console.log(`First Texture LOD ${o.texture_lod} (${v.max_height}px) - ${e.name}`)}}else{const v=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z,g=r.lastScreenCoverage*2,b=S/window.devicePixelRatio*g;for(let D=c.lods.length-1;D>=0;D--){let T=c.lods[D];if(!(ke()&&T.max_height>4096)&&T.max_height>b){if(o.texture_lod=D,o.texture_lod<r.lastLodLevel_Texture){const A=T.max_height;G&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} = ${A}px
6
- Screensize: ${b.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${v.toFixed(1)}
7
- ${e.name}`)}break}}}else o.texture_lod=0}};let B=E;d(B,"debugDrawLine"),d(B,"corner0",new R),d(B,"corner1",new R),d(B,"corner2",new R),d(B,"corner3",new R),d(B,"_tempPtInside",new R);class $e{constructor(){d(this,"frames",0),d(this,"lastLodLevel_Mesh",-1),d(this,"lastLodLevel_Texture",-1),d(this,"lastScreenCoverage",0),d(this,"lastScreenspaceVolume",new R),d(this,"lastCentrality",0)}}const ye=Symbol("NEEDLE_mesh_lod"),te=Symbol("NEEDLE_texture_lod");function ve(){document.removeEventListener("DOMContentLoaded",ge),document.addEventListener("DOMContentLoaded",ge),ge()}function ge(){document.querySelectorAll("model-viewer").forEach((t,e)=>{ze(t,e)})}const Le=new WeakSet;function ze(t,e){if(!t||Le.has(t))return null;Le.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(m=>m.toString()=="Symbol(renderer)"),u=i.find(m=>m.toString()=="Symbol(scene)"),l=i.find(m=>m.toString()=="Symbol(needsRender)");!r&&a!=null&&(r=t[a].threeRenderer),!n&&u!=null&&(n=t[u]),!o&&l!=null&&(o=t[l])}if(r&&n){console.debug("[gltf-progressive] setup model-viewer");const s=B.get(r,{engine:"model-viewer"});if(B.addPlugin(new We),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 We{constructor(){d(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(u){var l,m,c;if(u[te]==!0)return;u[te]=!0,u.userData&&(u.userData.LOD=-1);const f=Object.keys(u);for(let S=0;S<f.length;S++){const M=f[S],v=u[M];if(v?.isTexture===!0){const g=(m=(l=v.userData)==null?void 0:l.associations)==null?void 0:m.textures;if(g==null)continue;const b=n.parser.json.textures[g];if(!b){console.warn("Texture data not found for texture index "+g);continue}if((c=b?.extensions)!=null&&c[C]){const D=b.extensions[C];D&&s&&O.registerTexture(s,v,D.lods.length,g,D)}}}};const a=r.material;if(Array.isArray(a))for(const u of a)i(u);else i(a)}}tryParseMeshLOD(e,r){var n,o;if(r[ye]==!0)return;r[ye]=!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[C];if(a&&i){const u=r.uuid;O.registerMesh(i,u,r,0,a.lods.length,a)}}}ve();function Ue(t,e,r,n){ie(e),ae(r),r.register(s=>new O(s,t));const o=B.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}export{C as EXTENSION_NAME,B as LODsManager,O as NEEDLE_progressive,se as VERSION,ae as addDracoAndKTX2Loaders,ie as createLoaders,ee as getRaycastMesh,ve as patchModelViewer,Ce as setDracoDecoderLocation,Be as setKTX2TranscoderLocation,pe as setRaycastMesh,Ue as useNeedleProgressive,je as useRaycastMeshes};
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
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};
@@ -1,7 +1,7 @@
1
- "use strict";var we=Object.defineProperty;var _e=(l,e,t)=>e in l?we(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var h=(l,e,t)=>(_e(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),ve=require("three/examples/jsm/loaders/GLTFLoader.js"),Oe=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Se=require("three/examples/jsm/loaders/DRACOLoader.js"),Te=require("three/examples/jsm/loaders/KTX2Loader.js"),fe="";globalThis.GLTF_PROGRESSIVE_VERSION=fe;console.debug(`[gltf-progressive] version ${fe}`);let ee="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",de="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(ee+"draco_decoder.js",{method:"head"}).catch(l=>{ee="./include/draco/",de="./include/ktx2/"});function be(l){ee=l}function Ae(l){de=l}let K,le,X;function he(l){K||(K=new Se.DRACOLoader,K.setDecoderPath(ee),K.setDecoderConfig({type:"js"})),X||(X=new Te.KTX2Loader,X.setTranscoderPath(de)),le||(le=Oe.MeshoptDecoder),l?X.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ge(l){l.dracoLoader||l.setDRACOLoader(K),l.ktx2Loader||l.setKTX2Loader(X),l.meshoptDecoder||l.setMeshoptDecoder(le)}H("debugprogressive");function H(l){const t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function Pe(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 W;function Ce(){return W!==void 0||(W=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),H("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",W)),W}const ce=Symbol("needle:raycast-mesh");function te(l){return(l==null?void 0:l[ce])instanceof p.BufferGeometry?l[ce]:null}function Le(l,e){if((l.type==="Mesh"||l.type==="SkinnedMesh")&&!te(l)){const r=Ee(e);r.userData={isRaycastMesh:!0},l[ce]=r}}function Re(l=!0){if(l){if(q)return;const e=q=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(t,r){const i=this,o=te(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),e.call(this,t,r),s&&(i.geometry=s)}}else{if(!q)return;p.Mesh.prototype.raycast=q,q=null}}let q=null;function Ee(l){const e=new p.BufferGeometry;for(const t in l.attributes)e.setAttribute(t,l.getAttribute(t));return e.setIndex(l.getIndex()),e}const $=new Array,G="NEEDLE_progressive",L=H("debugprogressive"),oe=Symbol("needle-progressive-texture"),Y=new Map,ue=new Set;if(L){let l=function(){e+=1,console.log("Toggle LOD level",e,Y),Y.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n!=null){if(n.isBufferGeometry===!0){const a=v.getMeshLODInformation(n),d=a?Math.min(e,a.lods.length):0;o["DEBUG:LOD"]=e,v.assignMeshLOD(o,d),a&&(t=Math.max(t,a.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,v.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,ue&&ue.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=r)}))})}function pe(l,e,t){var i;if(!L)return;Y.has(l)||Y.set(l,{keys:[],sourceId:t});const r=Y.get(l);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const w=class{constructor(e,t){h(this,"parser");h(this,"url");h(this,"_isLoadingMesh");h(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&&w.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 d=n.uniforms[a].value;(d==null?void 0:d.isTexture)===!0&&s(d,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 d=r.getAssignedLODInformation(n);if(d){const c=r.lodInfos.get(d.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 f=c.lods[m];f.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,f.height),a.lods[m].max_height=Math.max(a.lods[m].max_height,f.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 p.Mesh||e.isMesh===!0){const i=e.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of $)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,w.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&&pe(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 p.Material||e.isMaterial===!0){const r=e,i=[],o=new Array;if(L&&ue.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 d=this.assignTextureLODForSlot(a,t,r,n);i.push(d),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 d=s[a],c=o[a];d&&d.isTexture===!0?n.push({material:r,slot:c,texture:d,level:t}):n.push({material:r,slot:c,texture:null,level:t})}return n})}if(e instanceof p.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):w.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&&pe(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 d of this.parser.associations.keys())d.isTexture===!0&&this.parser.associations.get(d).textures===o&&(a=!0,w.registerTexture(this.url,d,(s=n.lods)==null?void 0:s.length,o,n));a||this.parser.getDependency("texture",o).then(d=>{var c;d&&w.registerTexture(this.url,d,(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&&w.registerMesh(this.url,s.guid,n,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var n,a,d,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=w.lodInfos.get(o)),s){if(t>0){let x=!1;const D=Array.isArray(s.lods);if(D&&t>=s.lods.length?x=!0:D||(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 f=Pe(i.url,m);if(f.endsWith(".glb")||f.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const x=f+"_"+s.guid,D=this.previouslyLoaded.get(x);if(D!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${x}`);let g=await D.catch(R=>(console.error(`Error loading LOD ${t} from ${f}
2
- `,R),null)),V=!1;if(g==null||(g instanceof p.Texture&&e instanceof p.Texture?(a=g.image)!=null&&a.data||(d=g.source)!=null&&d.data?g=this.copySettings(e,g):(V=!0,this.previouslyLoaded.delete(x)):g instanceof p.BufferGeometry&&e instanceof p.BufferGeometry&&((c=g.attributes.position)!=null&&c.array||(V=!0,this.previouslyLoaded.delete(x)))),!V)return g}const M=s,I=new Promise(async(g,V)=>{const R=new ve.GLTFLoader;ge(R),L&&(await new Promise(A=>setTimeout(A,1e3)),r&&console.warn("Start loading (delayed) "+f,M.guid));let b=f;if(M&&Array.isArray(M.lods)){const A=M.lods[t];A.hash&&(b+="?v="+A.hash)}const T=await R.loadAsync(b).catch(A=>(console.error(`Error loading LOD ${t} from ${f}
3
- `,A),null));if(!T)return null;const U=T.parser;r&&console.log("Loading finished "+f,M.guid);let B=0;if(T.parser.json.textures){let A=!1;for(const u of T.parser.json.textures){if(u!=null&&u.extensions){const y=u==null?void 0:u.extensions[G];if(y!=null&&y.guid&&y.guid===M.guid){A=!0;break}}B++}if(A){let u=await U.getDependency("texture",B);return u&&w.assignLODInformation(i.url,u,o,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+u.name+'"',f,B,u,x),e instanceof p.Texture&&(u=this.copySettings(e,u)),u&&(u.guid=M.guid),g(u)}else L&&console.warn("Could not find texture with guid",M.guid,T.parser.json)}if(B=0,T.parser.json.meshes){let A=!1;for(const u of T.parser.json.meshes){if(u!=null&&u.extensions){const y=u==null?void 0:u.extensions[G];if(y!=null&&y.guid&&y.guid===M.guid){A=!0;break}}B++}if(A){const u=await U.getDependency("mesh",B),y=M;if(r&&console.log(`Loaded Mesh "${u.name}"`,f,B,u,x),u.isMesh===!0){const O=u.geometry;return w.assignLODInformation(i.url,O,o,t,void 0,y.density),g(O)}else{const O=new Array;for(let S=0;S<u.children.length;S++){const P=u.children[S];if(P.isMesh===!0){const F=P.geometry;w.assignLODInformation(i.url,F,o,t,S,y.density),O.push(F)}}return g(O)}}else L&&console.warn("Could not find mesh with guid",M.guid,T.parser.json)}return g(null)});return this.previouslyLoaded.set(x,I),await I}else if(e instanceof p.Texture){r&&console.log("Load texture from uri: "+f);const D=await new p.TextureLoader().loadAsync(f);return D?(D.guid=s.guid,D.flipY=!1,D.needsUpdate=!0,D.colorSpace=e.colorSpace,r&&console.log(s,D)):L&&console.warn("failed loading",f),D}}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 Be(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
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
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 v=w;h(v,"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;w.assignLODInformation(e,t,s,r,i,void 0),w.lodInfos.set(s,o),w.lowresCache.set(s,t)}),h(v,"registerMesh",(e,t,r,i,o,s)=>{var d;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={}),w.assignLODInformation(e,n,t,i,o,s.density),w.lodInfos.set(t,s);let a=w.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],w.lowresCache.set(t,a),i>0&&!te(r)&&Le(r,n);for(const c of $)(d=c.onRegisteredNewMesh)==null||d.call(c,r,s)}),h(v,"lodInfos",new Map),h(v,"previouslyLoaded",new Map),h(v,"lowresCache",new Map);class Be{constructor(e,t,r,i,o){h(this,"url");h(this,"key");h(this,"level");h(this,"index");h(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const N=H("debugprogressive"),ke=H("noprogressive"),ie=Symbol("Needle:LODSManager"),ne=Symbol("Needle:LODState"),z=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1},C=class{constructor(e,t){h(this,"context");h(this,"renderer");h(this,"projectionScreenMatrix",new p.Matrix4);h(this,"cameraFrustrum",new p.Frustum);h(this,"targetTriangleDensity",2e5);h(this,"updateInterval",0);h(this,"pause",!1);h(this,"_frame",0);h(this,"_originalRender");h(this,"_sphere",new p.Sphere);h(this,"_tempBox",new p.Box3);h(this,"_tempBox2",new p.Box3);h(this,"tempMatrix",new p.Matrix4);h(this,"_tempWorldPosition",new p.Vector3);h(this,"_tempBoxSize",new p.Vector3);h(this,"_tempBox2Size",new p.Vector3);this.renderer=e,this.context={...t}}static getObjectLODState(e){return e[ne]}static addPlugin(e){$.push(e)}static removePlugin(e){const t=$.indexOf(e);t>=0&&$.splice(t,1)}static get(e,t){if(e[ie])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),e[ie];const r=new C(e,{engine:"unknown",...t});return e[ie]=r,r}get plugins(){return $}enable(){if(this._originalRender)return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let e=0;this._originalRender=this.renderer.render;const t=this;he(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,d;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(ke||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 f of s){if(f.material&&(((a=f.geometry)==null?void 0:a.type)==="BoxGeometry"||((d=f.geometry)==null?void 0:d.type)==="BufferGeometry")&&(f.material.name==="SphericalGaussianBlur"||f.material.name=="BackgroundCubeMaterial"||f.material.name==="CubemapFromEquirect"||f.material.name==="EquirectangularToCubeUV")){N&&(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(f.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",f,f.material.name,f.material.type)));continue}switch(f.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const x=f.object;(x instanceof p.Mesh||x.isMesh)&&this.updateLODs(e,t,x,c,i)}const m=o.transparent;for(const f of m){const x=f.object;(x instanceof p.Mesh||x.isMesh)&&this.updateLODs(e,t,x,c,i)}}}updateLODs(e,t,r,i,o){var a,d;r.userData||(r.userData={});let s=r[ne];if(s||(s=new Ie,r[ne]=s),s.frames++<2)return;for(const c of $)(a=c.onBeforeUpdateLOD)==null||a.call(c,this.renderer,e,t,r);this.calculateLodLevel(t,r,s,i,k),k.mesh_lod=Math.round(k.mesh_lod),k.texture_lod=Math.round(k.texture_lod),k.mesh_lod>=0&&this.loadProgressiveMeshes(r,k.mesh_lod);let n=k.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 $)(d=c.onAfterUpdatedLOD)==null||d.call(c,this.renderer,e,t,r,k);s.lastLodLevel_Mesh=k.mesh_lod,s.lastLodLevel_Texture=k.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[z]===void 0||t<e[z])&&(r=!0),r&&(e[z]=t,v.assignTextureLOD(e,t))}loadProgressiveMeshes(e,t){if(!e)return Promise.resolve(null);if(e[z]!==t){e[z]=t;const r=e.geometry;return v.assignMeshLOD(e,t).then(i=>(i&&e[z]==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 I;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(N&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const d=v.getMeshLODInformation(t.geometry),c=d==null?void 0:d.lods,m=c&&c.length>0,f=v.getMaterialMinMaxLODsCount(t.material),x=(f==null?void 0:f.min_count)!=1/0&&f.min_count>0&&f.max_count>0;if(!m&&!x){o.mesh_lod=0,o.texture_lod=0;return}if(m||(a=!0,n=0),!((I=this.cameraFrustrum)!=null&&I.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}const D=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let M=t.geometry.boundingBox;if(t.type==="SkinnedMesh"){const _=t;_.boundingBox||_.computeBoundingBox(),M=_.boundingBox}if(M&&e.isPerspectiveCamera){const _=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 u=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(u)){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&&_.fov>70){const u=this._tempBox.min,y=this._tempBox.max;let O=u.x,S=u.y,P=y.x,F=y.y;const J=2,re=1.5,Q=(u.x+y.x)*.5,Z=(u.y+y.y)*.5;O=(O-Q)*J+Q,S=(S-Z)*J+Z,P=(P-Q)*J+Q,F=(F-Z)*J+Z;const Me=O<0&&P>0?0:Math.min(Math.abs(u.x),Math.abs(y.x)),De=S<0&&F>0?0:Math.min(Math.abs(u.y),Math.abs(y.y)),se=Math.max(Me,De);r.lastCentrality=(re-se)*(re-se)*(re-se)}else r.lastCentrality=1;const g=this._tempBox.getSize(this._tempBoxSize);g.multiplyScalar(.5),screen.availHeight>0&&D>0&&g.multiplyScalar(D/screen.availHeight),g.x*=_.aspect;const V=e.matrixWorldInverse,R=this._tempBox2;R.copy(M),R.applyMatrix4(t.matrixWorld),R.applyMatrix4(V);const b=R.getSize(this._tempBox2Size),T=Math.max(b.x,b.y);if(Math.max(g.x,g.y)!=0&&T!=0&&(g.z=b.z/Math.max(b.x,b.y)*Math.max(g.x,g.y)),r.lastScreenCoverage=Math.max(g.x,g.y,g.z),r.lastScreenspaceVolume.copy(g),r.lastScreenCoverage*=r.lastCentrality,N&&C.debugDrawLine){const u=this.tempMatrix.copy(this.projectionScreenMatrix);u.invert();const y=C.corner0,O=C.corner1,S=C.corner2,P=C.corner3;y.copy(this._tempBox.min),O.copy(this._tempBox.max),O.x=y.x,S.copy(this._tempBox.max),S.y=y.y,P.copy(this._tempBox.max);const F=(y.z+P.z)*.5;y.z=O.z=S.z=P.z=F,y.applyMatrix4(u),O.applyMatrix4(u),S.applyMatrix4(u),P.applyMatrix4(u),C.debugDrawLine(y,O,255),C.debugDrawLine(y,S,255),C.debugDrawLine(O,P,255),C.debugDrawLine(S,P,255)}let B=999;if(c&&r.lastScreenCoverage>0){for(let u=0;u<c.length;u++)if(c[u].density/r.lastScreenCoverage<i){B=u;break}}B<n&&(n=B,a=!0)}if(a?o.mesh_lod=n:o.mesh_lod=r.lastLodLevel_Mesh,N&&o.mesh_lod!=r.lastLodLevel_Mesh){const g=c==null?void 0:c[o.mesh_lod];g&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${o.mesh_lod} (${g.density.toFixed(0)}) - ${t.name}`)}if(x)if(r.lastLodLevel_Texture<0){if(o.texture_lod=f.max_count-1,N){const _=f.lods[f.max_count-1];N&&console.log(`First Texture LOD ${o.texture_lod} (${_.max_height}px) - ${t.name}`)}}else{const _=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z,g=r.lastScreenCoverage*2,R=D/window.devicePixelRatio*g;for(let b=f.lods.length-1;b>=0;b--){let T=f.lods[b];if(!(Ce()&&T.max_height>4096)&&T.max_height>R){if(o.texture_lod=b,o.texture_lod<r.lastLodLevel_Texture){const U=T.max_height;N&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${o.texture_lod} = ${U}px
6
- Screensize: ${R.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${_.toFixed(1)}
7
- ${t.name}`)}break}}}else o.texture_lod=0}};let E=C;h(E,"debugDrawLine"),h(E,"corner0",new p.Vector3),h(E,"corner1",new p.Vector3),h(E,"corner2",new p.Vector3),h(E,"corner3",new p.Vector3),h(E,"_tempPtInside",new p.Vector3);class Ie{constructor(){h(this,"frames",0);h(this,"lastLodLevel_Mesh",-1);h(this,"lastLodLevel_Texture",-1);h(this,"lastScreenCoverage",0);h(this,"lastScreenspaceVolume",new p.Vector3);h(this,"lastCentrality",0)}}const ye=Symbol("NEEDLE_mesh_lod"),j=Symbol("NEEDLE_texture_lod");function me(){document.removeEventListener("DOMContentLoaded",ae),document.addEventListener("DOMContentLoaded",ae),ae()}function ae(){document.querySelectorAll("model-viewer").forEach((e,t)=>{Ge(e,t)})}const xe=new WeakSet;function Ge(l,e){if(!l||xe.has(l))return null;xe.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)"),d=s.find(c=>c.toString()=="Symbol(needsRender)");!t&&n!=null&&(t=l[n].threeRenderer),!r&&a!=null&&(r=l[a]),!i&&d!=null&&(i=l[d])}if(t&&r){console.debug("[gltf-progressive] setup model-viewer");const o=E.get(t,{engine:"model-viewer"});if(E.addPlugin(new Fe),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 Fe{constructor(){h(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[j]==!0)return;t[j]=!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,f;if(a[j]==!0)return;a[j]=!0,a.userData&&(a.userData.LOD=-1);const d=Object.keys(a);for(let x=0;x<d.length;x++){const D=d[x],M=a[D];if((M==null?void 0:M.isTexture)===!0){const I=(m=(c=M.userData)==null?void 0:c.associations)==null?void 0:m.textures;if(I==null)continue;const _=r.parser.json.textures[I];if(!_){console.warn("Texture data not found for texture index "+I);continue}if((f=_==null?void 0:_.extensions)!=null&&f[G]){const g=_.extensions[G];g&&o&&v.registerTexture(o,M,g.lods.length,I,g)}}}};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[ye]==!0)return;t[ye]=!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;v.registerMesh(i,a,t,0,o.lods.length,o)}}}me();function $e(l,e,t,r){he(e),ge(t),t.register(o=>new v(o,l));const i=E.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}exports.EXTENSION_NAME=G;exports.LODsManager=E;exports.NEEDLE_progressive=v;exports.VERSION=fe;exports.addDracoAndKTX2Loaders=ge;exports.createLoaders=he;exports.getRaycastMesh=te;exports.patchModelViewer=me;exports.setDracoDecoderLocation=be;exports.setKTX2TranscoderLocation=Ae;exports.setRaycastMesh=Le;exports.useNeedleProgressive=$e;exports.useRaycastMeshes=Re;
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
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;
@@ -535,7 +535,10 @@ export class LODsManager {
535
535
  }
536
536
  else {
537
537
  const volume = state.lastScreenspaceVolume.x + state.lastScreenspaceVolume.y + state.lastScreenspaceVolume.z;
538
- const factor = state.lastScreenCoverage * 2;
538
+ let factor = state.lastScreenCoverage * 2;
539
+ if (this.context?.engine === "model-viewer") {
540
+ factor *= 2;
541
+ }
539
542
  const screenSize = canvasHeight / window.devicePixelRatio;
540
543
  const pixelSizeOnScreen = screenSize * factor;
541
544
  for (let i = texture_lods_minmax.lods.length - 1; i >= 0; i--) {
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // replaced at build time
2
- export const version = "1.2.2-alpha.1";
2
+ export const version = "1.2.2-alpha.2";
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.1",
3
+ "version": "1.2.2-alpha.2",
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": {