@needle-tools/gltf-progressive 1.2.1-alpha → 1.2.1-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,5 +1,5 @@
1
- var ye=Object.defineProperty,ve=(t,e,r)=>e in t?ye(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,d=(t,e,r)=>(ve(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as Le}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Me}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as De}from"three/examples/jsm/loaders/KTX2Loader.js";import{BufferGeometry as z,Mesh as N,Material as _e,Texture as U,TextureLoader as we,Matrix4 as de,Frustum as Oe,Sphere as be,Box3 as he,Vector3 as j}from"three";import{GLTFLoader as Se}from"three/examples/jsm/loaders/GLTFLoader.js";let J="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",se="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(J+"draco_decoder.js",{method:"head"}).catch(t=>{J="./include/draco/",se="./include/ktx2/"});function Te(t){J=t}function Ae(t){se=t}let q,oe,V;function ne(t){q||(q=new Me,q.setDecoderPath(J),q.setDecoderConfig({type:"js"})),V||(V=new De,V.setTranscoderPath(se)),oe||(oe=Le),t?V.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ie(t){t.dracoLoader||t.setDRACOLoader(q),t.ktx2Loader||t.setKTX2Loader(V),t.meshoptDecoder||t.setMeshoptDecoder(oe)}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 Pe(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 Z;function Ee(){return Z!==void 0||(Z=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),Q("debugprogressive")&&console.log("isMobileDevice",Z)),Z}const ae=Symbol("needle:raycast-mesh");function ee(t){return t?.[ae]instanceof z?t[ae]:null}function fe(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ee(t)){const r=Be(e);r.userData={isRaycastMesh:!0},t[ae]=r}}function Ie(t=!0){if(t){if(X)return;const e=X=N.prototype.raycast;N.prototype.raycast=function(r,n){const o=this,s=ee(o);let a;s&&o.isMesh&&(a=o.geometry,o.geometry=s),e.call(this,r,n),a&&(o.geometry=a)}}else{if(!X)return;N.prototype.raycast=X,X=null}}let X=null;function Be(t){const e=new z;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const F=new Array,C="NEEDLE_progressive",v=Q("debugprogressive"),le=Symbol("needle-progressive-texture"),K=new Map,ue=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,K),K.forEach((o,s)=>{for(const a of o.keys){const i=s[a];if(i!=null){if(i.isBufferGeometry===!0){const l=S.getMeshLODInformation(i),c=l?Math.min(e,l.lods.length):0;s["DEBUG:LOD"]=e,S.assignMeshLOD(s,c),l&&(r=Math.max(r,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,S.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,ue&&ue.forEach(s=>{s.name!="BackgroundCubeMaterial"&&s.glyphMap==null&&"wireframe"in s&&(s.wireframe=n)}))})}function ge(t,e,r){var n;if(!v)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(a=>(this._isLoadingMesh=!1,a&&_.registerMesh(this.url,s.guid,a,s.lods.length,void 0,s),a))):null}),v&&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 a of t)this.getMaterialMinMaxLODsCount(a,e);return t[n]=e,e}if(v==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const i of Object.keys(a.uniforms)){const l=a.uniforms[i].value;l?.isTexture===!0&&s(l,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const i=t[a];i?.isTexture===!0&&s(i,e)}return t[n]=e,e;function s(a,i){const l=r.getAssignedLODInformation(a);if(l){const c=r.lodInfos.get(l.key);if(c&&c.lods){i.min_count=Math.min(i.min_count,c.lods.length),i.max_count=Math.max(i.max_count,c.lods.length);for(let f=0;f<c.lods.length;f++){const u=c.lods[f];u.width&&(i.lods[f]=i.lods[f]||{min_height:1/0,max_height:0},i.lods[f].min_height=Math.min(i.lods[f].min_height,u.height),i.lods[f].max_height=Math.max(i.lods[f].max_height,u.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 a=t[s];if(a&&a.isTexture&&this.hasLODLevelAvailable(a,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 F)(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 a=o.index||0;s=s[a]}s&&n!=s&&s instanceof z&&(t.geometry=s,v&&ge(t,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else v&&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 _e||t.isMaterial===!0){const r=t,n=[],o=new Array;if(v&&ue.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const a of Object.keys(s.uniforms)){const i=s.uniforms[a].value;if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,r,a);n.push(l),o.push(a)}}}else for(const s of Object.keys(r)){const a=r[s];if(a?.isTexture===!0){const i=this.assignTextureLODForSlot(a,e,r,s);n.push(i),o.push(s)}}return Promise.all(n).then(s=>{const a=new Array;for(let i=0;i<s.length;i++){const l=s[i],c=o[i];l&&l.isTexture===!0?a.push({material:r,slot:c,texture:l,level:e}):a.push({material:r,slot:c,texture:null,level:e})}return a})}if(t instanceof U||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 a=this.getAssignedLODInformation(s);if(a&&a?.level<e)return v==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,r,s,o),null}r[n]=o}if(v&&n&&r){const s=this.getAssignedLODInformation(t);s&&ge(r,n,s.url)}}return o}else v=="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 v&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.extensions[C];if(s){if(!s.lods){v&&console.warn("Texture has no LODs",s);return}let a=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i).textures===o&&(a=!0,_.registerTexture(this.url,i,s.lods.length,o,s));a||this.parser.getDependency("texture",o).then(i=>{i&&_.registerTexture(this.url,i,s.lods.length,o,s)})}}}),(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 a of this.parser.associations.keys())if(a.isMesh){const i=this.parser.associations.get(a);i.meshes===o&&_.registerMesh(this.url,s.guid,a,s.lods.length,i.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var r,n,o,s,a,i;const l=v=="verbose",c=(n=(r=t.userData).LODS)==null?void 0:n.call(r);if(!c)return null;const f=c?.key;let u;if(t.isTexture===!0){const y=t;y.source&&y.source[le]&&(u=y.source[le])}if(u||(u=_.lodInfos.get(f)),u){if(e>0){let h=!1;const O=Array.isArray(u.lods);if(O&&e>=u.lods.length?h=!0:O||(h=!0),h)return this.lowresCache.get(f)}const y=Array.isArray(u.lods)?(o=u.lods[e])==null?void 0:o.path:u.lods;if(!y)return v&&!u["missing:uri"]&&(u["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,u)),null;const m=Pe(c.url,y);if(m.endsWith(".glb")||m.endsWith(".gltf")){if(!u.guid)return console.warn("missing pointer for glb/gltf texture",u),null;const h=m+"_"+u.guid,O=this.previouslyLoaded.get(h);if(O!==void 0){l&&console.log(`LOD ${e} was already loading/loaded: ${h}`);let b=await O.catch(x=>(console.error(`Error loading LOD ${e} from ${m}
2
- `,x),null)),G=!1;if(b==null||(b instanceof U&&t instanceof U?(s=b.image)!=null&&s.data||(a=b.source)!=null&&a.data?b=this.copySettings(t,b):(G=!0,this.previouslyLoaded.delete(h)):b instanceof z&&t instanceof z&&((i=b.attributes.position)!=null&&i.array||(G=!0,this.previouslyLoaded.delete(h)))),!G)return b}const p=u,P=new Promise(async(b,G)=>{const x=new Se;ie(x),v&&(await new Promise(D=>setTimeout(D,1e3)),l&&console.warn("Start loading (delayed) "+m,p.guid));let L=m;if(p&&Array.isArray(p.lods)){const D=p.lods[e];D.hash&&(L+="?v="+D.hash)}const w=await x.loadAsync(L).catch(D=>(console.error(`Error loading LOD ${e} from ${m}
3
- `,D),null));if(!w)return null;const A=w.parser;l&&console.log("Loading finished "+m,p.guid);let M=0;if(w.parser.json.textures){let D=!1;for(const g of w.parser.json.textures){if(g!=null&&g.extensions){const T=g?.extensions[C];if(T!=null&&T.guid&&T.guid===p.guid){D=!0;break}}M++}if(D){let g=await A.getDependency("texture",M);return g&&_.assignLODInformation(c.url,g,f,e,void 0,void 0),l&&console.log('change "'+t.name+'" \u2192 "'+g.name+'"',m,M,g,h),t instanceof U&&(g=this.copySettings(t,g)),g&&(g.guid=p.guid),b(g)}else v&&console.warn("Could not find texture with guid",p.guid)}if(M=0,w.parser.json.meshes){let D=!1;for(const g of w.parser.json.meshes){if(g!=null&&g.extensions){const T=g?.extensions[C];if(T!=null&&T.guid&&T.guid===p.guid){D=!0;break}}M++}if(D){const g=await A.getDependency("mesh",M),T=p;if(l&&console.log(`Loaded Mesh "${g.name}"`,m,M,g,h),g.isMesh===!0){const B=g.geometry;return _.assignLODInformation(c.url,B,f,e,void 0,T.density),b(B)}else{const B=new Array;for(let k=0;k<g.children.length;k++){const H=g.children[k];if(H instanceof N){const Y=H.geometry;_.assignLODInformation(c.url,Y,f,e,k,T.density),B.push(Y)}}return b(B)}}}return b(null)});return this.previouslyLoaded.set(h,P),await P}else if(t instanceof U){l&&console.log("Load texture from uri: "+m);const h=await new we().loadAsync(m);return h?(h.guid=u.guid,h.flipY=!1,h.needsUpdate=!0,h.colorSpace=t.colorSpace,l&&console.log(u,h)):v&&console.warn("failed loading",m),h}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${f}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,o,s){if(!e)return;e.userData||(e.userData={});const a=new Ce(t,r,n,o,s);e.userData.LODS=()=>a}static getAssignedLODInformation(t){var e,r;return((r=(e=t?.userData)==null?void 0:e.LODS)==null?void 0:r.call(e))||null}static copySettings(t,e){return e=e.clone(),v&&console.warn(`Copying texture settings
1
+ var ve=Object.defineProperty,Le=(t,e,r)=>e in t?ve(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,d=(t,e,r)=>(Le(t,typeof e!="symbol"?e+"":e,r),r);import{BufferGeometry as K,Mesh as $,Material as Me,Texture as W,TextureLoader as De,Matrix4 as ce,Frustum as _e,Sphere as we,Box3 as de,Vector3 as R}from"three";import{GLTFLoader as Oe}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as be}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Se}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as Te}from"three/examples/jsm/loaders/KTX2Loader.js";let Y="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",re="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(Y+"draco_decoder.js",{method:"head"}).catch(t=>{Y="./include/draco/",re="./include/ktx2/"});function Ae(t){Y=t}function Ee(t){re=t}let U,se,z;function ne(t){U||(U=new Se,U.setDecoderPath(Y),U.setDecoderConfig({type:"js"})),z||(z=new Te,z.setTranscoderPath(re)),se||(se=be),t?z.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function oe(t){t.dracoLoader||t.setDRACOLoader(U),t.ktx2Loader||t.setKTX2Loader(z),t.meshoptDecoder||t.setMeshoptDecoder(se)}function J(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Pe(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const o=t.substring(0,r+1);for(;o.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return o+e}return e}let Q;function Ie(){return Q!==void 0||(Q=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),J("debugprogressive")&&console.log("isMobileDevice",Q)),Q}const ie=Symbol("needle:raycast-mesh");function Z(t){return t?.[ie]instanceof K?t[ie]:null}function he(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!Z(t)){const r=Ce(e);r.userData={isRaycastMesh:!0},t[ie]=r}}function Be(t=!0){if(t){if(q)return;const e=q=$.prototype.raycast;$.prototype.raycast=function(r,o){const s=this,n=Z(s);let i;n&&s.isMesh&&(i=s.geometry,s.geometry=n),e.call(this,r,o),i&&(s.geometry=i)}}else{if(!q)return;$.prototype.raycast=q,q=null}}let q=null;function Ce(t){const e=new K;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const k=new Array,I="NEEDLE_progressive",p=J("debugprogressive"),ae=Symbol("needle-progressive-texture"),V=new Map,le=new Set;if(p){let t=function(){e+=1,console.log("Toggle LOD level",e,V),V.forEach((s,n)=>{for(const i of s.keys){const a=n[i];if(a!=null){if(a.isBufferGeometry===!0){const u=O.getMeshLODInformation(a),l=u?Math.min(e,u.lods.length):0;n["DEBUG:LOD"]=e,O.assignMeshLOD(n,l),u&&(r=Math.max(r,u.lods.length-1))}else if(n.isMaterial===!0){n["DEBUG:LOD"]=e,O.assignTextureLOD(n,e);break}}}}),e>=r&&(e=-1)},e=-1,r=2,o=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(o=!o,le&&le.forEach(n=>{n.name!="BackgroundCubeMaterial"&&n.glyphMap==null&&"wireframe"in n&&(n.wireframe=o)}))})}function fe(t,e,r){var o;if(!p)return;V.has(t)||V.set(t,{keys:[],sourceId:r});const s=V.get(t);((o=s?.keys)==null?void 0:o.includes(e))==!1&&s.keys.push(e)}const _=class{constructor(t,e){d(this,"parser"),d(this,"url"),d(this,"_isLoadingMesh"),d(this,"loadMesh",r=>{var o,s;if(this._isLoadingMesh)return null;const n=(s=(o=this.parser.json.meshes[r])==null?void 0:o.extensions)==null?void 0:s[I];return n?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var a;return this._isLoadingMesh=!1,i&&_.registerMesh(this.url,n.guid,i,(a=n.lods)==null?void 0:a.length,void 0,n),i})):null}),p&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return I}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,o="LODS:minmax",s=t[o];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[o]=e,e}if(p==="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&&n(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const a=t[i];a?.isTexture===!0&&n(a,e)}return t[o]=e,e;function n(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 x=0;x<l.lods.length;x++){const c=l.lods[x];c.width&&(a.lods[x]=a.lods[x]||{min_height:1/0,max_height:0},a.lods[x].min_height=Math.min(a.lods[x].min_height,c.height),a.lods[x].max_height=Math.max(a.lods[x].max_height,c.height))}}}}}static hasLODLevelAvailable(t,e){var r;if(Array.isArray(t)){for(const n of t)if(this.hasLODLevelAvailable(n,e))return!0;return!1}if(t.isMaterial===!0){for(const n of Object.keys(t)){const i=t[n];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const n of t.children)if(n.isMesh===!0&&this.hasLODLevelAvailable(n,e))return!0}let o,s;if(t.isMesh?o=t.geometry:(t.isBufferGeometry||t.isTexture)&&(o=t),o&&(r=o?.userData)!=null&&r.LODS){const n=o.userData.LODS;if(s=this.lodInfos.get(n.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof $||t.isMesh===!0){const o=t.geometry,s=this.getAssignedLODInformation(o);if(!s)return Promise.resolve(null);for(const n of k)(r=n.onBeforeGetLODMesh)==null||r.call(n,t,e);return t["LOD:requested level"]=e,_.getOrLoadLOD(o,e).then(n=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(n)){const i=s.index||0;n=n[i]}n&&o!=n&&(n?.isBufferGeometry?(t.geometry=n,p&&fe(t,"geometry",s.url)):p&&console.error("Invalid LOD geometry",n))}return n}).catch(n=>(console.error("Error loading mesh LOD",t,n),null))}else p&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t instanceof Me||t.isMaterial===!0){const r=t,o=[],s=new Array;if(p&&le.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const n=r;for(const i of Object.keys(n.uniforms)){const a=n.uniforms[i].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,i);o.push(u),s.push(i)}}}else for(const n of Object.keys(r)){const i=r[n];if(i?.isTexture===!0){const a=this.assignTextureLODForSlot(i,e,r,n);o.push(a),s.push(n)}}return Promise.all(o).then(n=>{const i=new Array;for(let a=0;a<n.length;a++){const u=n[a],l=s[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,o){return t?.isTexture!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):_.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t){if(r&&o){const n=r[o];if(n){const i=this.getAssignedLODInformation(n);if(i&&i?.level<e)return p==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,n,s),null}r[o]=s}if(p&&o&&r){const n=this.getAssignedLODInformation(t);n&&fe(r,o,n.url)}}return s}else p=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return p&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,s)=>{var n;if(o!=null&&o.extensions){const i=o?.extensions[I];if(i){if(!i.lods){p&&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===s&&(a=!0,_.registerTexture(this.url,u,(n=i.lods)==null?void 0:n.length,s,i));a||this.parser.getDependency("texture",s).then(u=>{var l;u&&_.registerTexture(this.url,u,(l=i.lods)==null?void 0:l.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((o,s)=>{if(o!=null&&o.extensions){const n=o?.extensions[I];if(n&&n.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const a=this.parser.associations.get(i);a.meshes===s&&_.registerMesh(this.url,n.guid,i,n.lods.length,a.primitives,n)}}}}),null}static async getOrLoadLOD(t,e){var r,o,s,n;const i=p=="verbose",a=t.userData.LODS;if(!a)return null;const u=a?.key;let l;if(t.isTexture===!0){const x=t;x.source&&x.source[ae]&&(l=x.source[ae])}if(l||(l=_.lodInfos.get(u)),l){if(e>0){let f=!1;const b=Array.isArray(l.lods);if(b&&e>=l.lods.length?f=!0:b||(f=!0),f)return this.lowresCache.get(u)}const x=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!x)return p&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const c=Pe(a.url,x);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,b=this.previouslyLoaded.get(f);if(b!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${f}`);let m=await b.catch(P=>(console.error(`Error loading LOD ${e} from ${c}
2
+ `,P),null)),w=!1;if(m==null||(m instanceof W&&t instanceof W?(o=m.image)!=null&&o.data||(s=m.source)!=null&&s.data?m=this.copySettings(t,m):(w=!0,this.previouslyLoaded.delete(f)):m instanceof K&&t instanceof K&&((n=m.attributes.position)!=null&&n.array||(w=!0,this.previouslyLoaded.delete(f)))),!w)return m}const g=l,L=new Promise(async(m,w)=>{const P=new Oe;oe(P),p&&(await new Promise(v=>setTimeout(v,1e3)),i&&console.warn("Start loading (delayed) "+c,g.guid));let X=c;if(g&&Array.isArray(g.lods)){const v=g.lods[e];v.hash&&(X+="?v="+v.hash)}const S=await P.loadAsync(X).catch(v=>(console.error(`Error loading LOD ${e} from ${c}
3
+ `,v),null));if(!S)return null;const M=S.parser;i&&console.log("Loading finished "+c,g.guid);let y=0;if(S.parser.json.textures){let v=!1;for(const h of S.parser.json.textures){if(h!=null&&h.extensions){const D=h?.extensions[I];if(D!=null&&D.guid&&D.guid===g.guid){v=!0;break}}y++}if(v){let h=await M.getDependency("texture",y);return h&&_.assignLODInformation(a.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',c,y,h,f),t instanceof W&&(h=this.copySettings(t,h)),h&&(h.guid=g.guid),m(h)}else p&&console.warn("Could not find texture with guid",g.guid,S.parser.json)}if(y=0,S.parser.json.meshes){let v=!1;for(const h of S.parser.json.meshes){if(h!=null&&h.extensions){const D=h?.extensions[I];if(D!=null&&D.guid&&D.guid===g.guid){v=!0;break}}y++}if(v){const h=await M.getDependency("mesh",y),D=g;if(i&&console.log(`Loaded Mesh "${h.name}"`,c,y,h,f),h.isMesh===!0){const A=h.geometry;return _.assignLODInformation(a.url,A,u,e,void 0,D.density),m(A)}else{const A=new Array;for(let C=0;C<h.children.length;C++){const F=h.children[C];if(F.isMesh===!0){const j=F.geometry;_.assignLODInformation(a.url,j,u,e,C,D.density),A.push(j)}}return m(A)}}else p&&console.warn("Could not find mesh with guid",g.guid,S.parser.json)}return m(null)});return this.previouslyLoaded.set(f,L),await L}else if(t instanceof W){i&&console.log("Load texture from uri: "+c);const f=await new De().loadAsync(c);return f?(f.guid=l.guid,f.flipY=!1,f.needsUpdate=!0,f.colorSpace=t.colorSpace,i&&console.log(l,f)):p&&console.warn("failed loading",c),f}}else p&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,o,s,n){if(!e)return;e.userData||(e.userData={});const i=new Re(t,r,o,s,n);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(),p&&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 S=_;d(S,"registerTexture",(t,e,r,n,o)=>{if(v&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,o),!e){v&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[le]=o);const s=o.guid;_.assignLODInformation(t,e,s,r,n,void 0),_.lodInfos.set(s,o),_.lowresCache.set(s,e)}),d(S,"registerMesh",(t,e,r,n,o,s)=>{var a;v&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const i=r.geometry;if(!i){v&&console.warn("gltf-progressive: Register mesh without geometry");return}i.userData||(i.userData={}),_.assignLODInformation(t,i,e,n,o,s.density),_.lodInfos.set(e,s);let l=_.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],_.lowresCache.set(e,l),n>0&&!ee(r)&&fe(r,i);for(const c of F)(a=c.onRegisteredNewMesh)==null||a.call(c,r,s)}),d(S,"lodInfos",new Map),d(S,"previouslyLoaded",new Map),d(S,"lowresCache",new Map);class Ce{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 W=Q("debugprogressive"),Re=Q("noprogressive"),me=Symbol("Needle:LODSManager"),ce=Symbol("Needle:LODState"),$=Symbol("Needle:CurrentLOD"),I={mesh_lod:-1,texture_lod:-1},E=class{constructor(t){d(this,"renderer"),d(this,"projectionScreenMatrix",new de),d(this,"cameraFrustrum",new Oe),d(this,"targetTriangleDensity",2e5),d(this,"updateInterval",0),d(this,"pause",!1),d(this,"_frame",0),d(this,"_originalRender"),d(this,"_sphere",new be),d(this,"_tempBox",new he),d(this,"_tempBox2",new he),d(this,"tempMatrix",new de),d(this,"_tempWorldPosition",new j),d(this,"_tempBoxSize",new j),d(this,"_tempBox2Size",new j),this.renderer=t}static getObjectLODState(t){return t[ce]}static addPlugin(t){F.push(t)}static removePlugin(t){const e=F.indexOf(t);e>=0&&F.splice(e,1)}static get(t){return t[me]?t[me]:new E(t)}get plugins(){return F}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;ne(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 a=this.renderer.renderLists.get(t,0),i=a.opaque;let l=!0;if(i.length===1){const c=i[0].material;(c.name==="EffectMaterial"||c.name==="CopyShader")&&(l=!1)}if(e.parent&&e.parent.type==="CubeCamera"&&(l=!1),l){if(Re||this.updateInterval>0&&n%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const c=this.targetTriangleDensity;for(const u of i){if(u.material&&(((o=u.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=u.geometry)==null?void 0:s.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){W&&(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 y=u.object;(y instanceof N||y.isMesh)&&this.updateLODs(t,e,y,c,n)}const f=a.transparent;for(const u of f){const y=u.object;(y instanceof N||y.isMesh)&&this.updateLODs(t,e,y,c,n)}}}updateLODs(t,e,r,n,o){var s,a;r.userData||(r.userData={});let i=r[ce];if(i||(i=new ke,r[ce]=i),i.frames++<2)return;for(const c of F)(s=c.onBeforeUpdateLOD)==null||s.call(c,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,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 l=I.texture_lod;if(r.material&&l>=0){const c=r["DEBUG:LOD"];c!=null&&(l=c),this.loadProgressiveTextures(r.material,l)}for(const c of F)(a=c.onAfterUpdatedLOD)==null||a.call(c,this.renderer,t,e,r,I);i.lastLodLevel_Mesh=I.mesh_lod,i.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[$]==null||e<t[$])&&(r=!0),r&&(t[$]=e,S.assignTextureLOD(t,e))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[$]!==e){t[$]=e;const r=t.geometry;return S.assignMeshLOD(t,e).then(n=>(n&&t[$]==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 a=10+1;if(W&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const i=S.getMeshLODInformation(e.geometry),l=i?.lods,c=l&&l.length>0,f=S.getMaterialMinMaxLODsCount(e.material),u=f?.min_count!=1/0&&f.min_count>0&&f.max_count>0;if(!c&&!u){o.mesh_lod=0,o.texture_lod=0;return}if(c||(a=0),!((s=this.cameraFrustrum)!=null&&s.intersectsObject(e))){o.mesh_lod=99,o.texture_lod=99;return}let y=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const m=e;m.boundingBox||m.computeBoundingBox(),y=m.boundingBox}if(y&&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 x=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(x)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(y),e.type==="SkinnedMesh"?e.parent&&this._tempBox.applyMatrix4(e.parent.matrixWorld):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&&m.fov>70){const x=this._tempBox.min,L=this._tempBox.max;let w=x.x,A=x.y,M=L.x,D=L.y;const g=2,T=1.5,B=(x.x+L.x)*.5,k=(x.y+L.y)*.5;w=(w-B)*g+B,A=(A-k)*g+k,M=(M-B)*g+B,D=(D-k)*g+k;const H=w<0&&M>0?0:Math.min(Math.abs(x.x),Math.abs(L.x)),Y=A<0&&D>0?0:Math.min(Math.abs(x.y),Math.abs(L.y)),re=Math.max(H,Y);r.lastCentrality=(T-re)*(T-re)*(T-re)}else r.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&h.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),h.x*=m.aspect;const O=t.matrixWorldInverse,p=this._tempBox2;p.copy(y),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(O);const P=p.getSize(this._tempBox2Size),b=Math.max(P.x,P.y);if(Math.max(h.x,h.y)!=0&&b!=0&&(h.z=P.z/Math.max(P.x,P.y)*Math.max(h.x,h.y)),r.lastScreenCoverage=Math.max(h.x,h.y,h.z),r.lastScreenspaceVolume.copy(h),r.lastScreenCoverage*=r.lastCentrality,W&&E.debugDrawLine){const x=this.tempMatrix.copy(this.projectionScreenMatrix);x.invert();const L=E.corner0,w=E.corner1,A=E.corner2,M=E.corner3;L.copy(this._tempBox.min),w.copy(this._tempBox.max),w.x=L.x,A.copy(this._tempBox.max),A.y=L.y,M.copy(this._tempBox.max);const D=(L.z+M.z)*.5;L.z=w.z=A.z=M.z=D,L.applyMatrix4(x),w.applyMatrix4(x),A.applyMatrix4(x),M.applyMatrix4(x),E.debugDrawLine(L,w,255),E.debugDrawLine(L,A,255),E.debugDrawLine(w,M,255),E.debugDrawLine(A,M,255)}let G=999;if(l&&r.lastScreenCoverage>0){for(let x=0;x<l.length;x++)if(l[x].density/r.lastScreenCoverage<n){G=x;break}}G<a&&(a=G)}if(o.mesh_lod=a,u)if(r.lastLodLevel_Texture<0){if(o.texture_lod=f.max_count-1,W){const m=f.lods[f.max_count-1];W&&console.log(`First Texture LOD ${o.texture_lod} (${m.max_height}px) - ${e.name}`)}}else{const m=r.lastScreenCoverage*1.5,h=this.renderer.domElement.clientHeight/window.devicePixelRatio*m;for(let O=f.lods.length-1;O>=0;O--){const p=f.lods[O];if(!(Ee()&&p.max_height>4096)&&p.max_height>h){o.texture_lod=O,o.texture_lod<r.lastLodLevel_Texture&&W&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} (${p.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${h.toFixed(0)}px) - ${e.name}`);break}}}else o.texture_lod=0}};let R=E;d(R,"debugDrawLine"),d(R,"corner0",new j),d(R,"corner1",new j),d(R,"corner2",new j),d(R,"corner3",new j),d(R,"_tempPtInside",new j);class ke{constructor(){d(this,"frames",0),d(this,"lastLodLevel_Mesh",-1),d(this,"lastLodLevel_Texture",-1),d(this,"lastScreenCoverage",0),d(this,"lastScreenspaceVolume",new j),d(this,"lastCentrality",0)}}const pe=Symbol("NEEDLE_mesh_lod"),te=Symbol("NEEDLE_texture_lod");function xe(t){if(!t)return null;let e=null,r=null;for(let n=t;n!=null;n=Object.getPrototypeOf(n)){const o=Object.getOwnPropertySymbols(n),s=o.find(i=>i.toString()=="Symbol(renderer)"),a=o.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=t[s].threeRenderer),!r&&a!=null&&(r=t[a])}if(e){console.log("Adding Needle LODs to modelviewer");const n=R.get(e);if(R.addPlugin(new je(t)),n.enable(),r){const o=r.camera||r.traverse(s=>s.type=="PerspectiveCamera")[0];o&&e.render(r,o)}return()=>{n.disable()}}return null}class je{constructor(e){d(this,"modelviewer"),d(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,r,n,o){this.tryParseMeshLOD(r,o),this.tryParseTextureLOD(r,o)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,r){if(r[te]==!0)return;r[te]=!0;const n=this.tryGetCurrentGLTF(e),o=this.getUrl();if(o&&n&&r.material){let s=function(i){var l,c,f;if(i[te]==!0)return;i[te]=!0,i.userData&&(i.userData.LOD=-1);const u=Object.keys(i);for(let y=0;y<u.length;y++){const m=u[y],h=i[m];if(h?.isTexture===!0){const O=(c=(l=h.userData)==null?void 0:l.associations)==null?void 0:c.textures,p=n.parser.json.textures[O];if(!p){console.warn("Texture data not found for texture index "+O);continue}if((f=p?.extensions)!=null&&f[C]){const P=p.extensions[C];P&&o&&S.registerTexture(o,h,P.lods.length,O,P)}}}};const a=r.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,r){var n,o;if(r[pe]==!0)return;r[pe]=!0;const s=this.getUrl();if(!s)return;const a=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[C];if(a&&s){const i=r.uuid;S.registerMesh(s,i,r,0,a.lods.length,a)}}}function Ge(t,e,r,n){ne(e),ie(r),r.register(s=>new S(s,t));const o=R.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{xe(document.querySelector("model-viewer"))});export{C as EXTENSION_NAME,R as LODsManager,S as NEEDLE_progressive,ie as addDracoAndKTX2Loaders,ne as createLoaders,ee as getRaycastMesh,xe as patchModelViewer,Te as setDracoDecoderLocation,Ae as setKTX2TranscoderLocation,fe as setRaycastMesh,Ge as useNeedleProgressive,Ie 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 O=_;d(O,"registerTexture",(t,e,r,o,s)=>{if(p&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,s),!e){p&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ae]=s);const n=s.guid;_.assignLODInformation(t,e,n,r,o,void 0),_.lodInfos.set(n,s),_.lowresCache.set(n,e)}),d(O,"registerMesh",(t,e,r,o,s,n)=>{var i;p&&console.log("> Progressive: register mesh",s,r.name,n,r.uuid,r);const a=r.geometry;if(!a){p&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),_.assignLODInformation(t,a,e,o,s,n.density),_.lodInfos.set(e,n);let u=_.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],_.lowresCache.set(e,u),o>0&&!Z(r)&&he(r,a);for(const l of k)(i=l.onRegisteredNewMesh)==null||i.call(l,r,n)}),d(O,"lodInfos",new Map),d(O,"previouslyLoaded",new Map),d(O,"lowresCache",new Map);class Re{constructor(e,r,o,s,n){d(this,"url"),d(this,"key"),d(this,"level"),d(this,"index"),d(this,"density"),this.url=e,this.key=r,this.level=o,s!=null&&(this.index=s),n!=null&&(this.density=n)}}const G=J("debugprogressive"),ke=J("noprogressive"),ge=Symbol("Needle:LODSManager"),ue=Symbol("Needle:LODState"),N=Symbol("Needle:CurrentLOD"),E={mesh_lod:-1,texture_lod:-1},T=class{constructor(t){d(this,"renderer"),d(this,"projectionScreenMatrix",new ce),d(this,"cameraFrustrum",new _e),d(this,"targetTriangleDensity",2e5),d(this,"updateInterval",0),d(this,"pause",!1),d(this,"_frame",0),d(this,"_originalRender"),d(this,"_sphere",new we),d(this,"_tempBox",new de),d(this,"_tempBox2",new de),d(this,"tempMatrix",new ce),d(this,"_tempWorldPosition",new R),d(this,"_tempBoxSize",new R),d(this,"_tempBox2Size",new R),this.renderer=t}static getObjectLODState(t){return t[ue]}static addPlugin(t){k.push(t)}static removePlugin(t){const e=k.indexOf(t);e>=0&&k.splice(e,1)}static get(t){return t[ge]?t[ge]:new T(t)}get plugins(){return k}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;ne(this.renderer),this.renderer.render=function(r,o){e.renderer.getRenderTarget()==null&&(t=0,e._frame+=1);const s=e._frame,n=t++;e.onBeforeRender(r,o,n,s),e._originalRender.call(this,r,o),e.onAfterRender(r,o,n,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(t,e,r,o){}onAfterRender(t,e,r,o){var s,n;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(ke||this.updateInterval>0&&o%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&&(((s=c.geometry)==null?void 0:s.type)==="BoxGeometry"||((n=c.geometry)==null?void 0:n.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,o)}const x=i.transparent;for(const c of x){const f=c.object;(f instanceof $||f.isMesh)&&this.updateLODs(t,e,f,l,o)}}}updateLODs(t,e,r,o,s){var n,i;r.userData||(r.userData={});let a=r[ue];if(a||(a=new je,r[ue]=a),a.frames++<2)return;for(const l of k)(n=l.onBeforeUpdateLOD)==null||n.call(l,this.renderer,t,e,r);this.calculateLodLevel(e,r,a,o,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 u=E.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,E);a.lastLodLevel_Mesh=E.mesh_lod,a.lastLodLevel_Texture=E.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const o of t)this.loadProgressiveTextures(o,e);return}let r=!1;(t[N]===void 0||e<t[N])&&(r=!0),r&&(t[N]=e,O.assignTextureLOD(t,e))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[N]!==e){t[N]=e;const r=t.geometry;return O.assignMeshLOD(t,e).then(o=>(o&&t[N]==e&&r!=t.geometry,o))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,o=t.max,s=(r.x+o.x)*.5,n=(r.y+o.y)*.5;return this._tempPtInside.set(s,n,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,o,s){var n;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.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,x=l&&l.length>0,c=O.getMaterialMinMaxLODsCount(e.material),f=c?.min_count!=1/0&&c.min_count>0&&c.max_count>0;if(!x&&!f){s.mesh_lod=0,s.texture_lod=0;return}if(x||(a=!0,i=0),!((n=this.cameraFrustrum)!=null&&n.intersectsObject(e))){s.mesh_lod=99,s.texture_lod=99;return}let b=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const g=e;g.boundingBox||g.computeBoundingBox(),b=g.boundingBox}if(b&&t.isPerspectiveCamera){const g=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 M=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(M)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(b),e.type==="SkinnedMesh"?e.parent&&this._tempBox.applyMatrix4(e.parent.matrixWorld):this._tempBox.applyMatrix4(e.matrixWorld),T.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&g.fov>70){const M=this._tempBox.min,y=this._tempBox.max;let v=M.x,h=M.y,D=y.x,A=y.y;const C=2,F=1.5,j=(M.x+y.x)*.5,H=(M.y+y.y)*.5;v=(v-j)*C+j,h=(h-H)*C+H,D=(D-j)*C+j,A=(A-H)*C+H;const xe=v<0&&D>0?0:Math.min(Math.abs(M.x),Math.abs(y.x)),ye=h<0&&A>0?0:Math.min(Math.abs(M.y),Math.abs(y.y)),te=Math.max(xe,ye);r.lastCentrality=(F-te)*(F-te)*(F-te)}else r.lastCentrality=1;const L=this._tempBox.getSize(this._tempBoxSize);L.multiplyScalar(.5),screen.availHeight>0&&L.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),L.x*=g.aspect;const m=t.matrixWorldInverse,w=this._tempBox2;w.copy(b),w.applyMatrix4(e.matrixWorld),w.applyMatrix4(m);const P=w.getSize(this._tempBox2Size),X=Math.max(P.x,P.y);if(Math.max(L.x,L.y)!=0&&X!=0&&(L.z=P.z/Math.max(P.x,P.y)*Math.max(L.x,L.y)),r.lastScreenCoverage=Math.max(L.x,L.y,L.z),r.lastScreenspaceVolume.copy(L),r.lastScreenCoverage*=r.lastCentrality,G&&T.debugDrawLine){const M=this.tempMatrix.copy(this.projectionScreenMatrix);M.invert();const y=T.corner0,v=T.corner1,h=T.corner2,D=T.corner3;y.copy(this._tempBox.min),v.copy(this._tempBox.max),v.x=y.x,h.copy(this._tempBox.max),h.y=y.y,D.copy(this._tempBox.max);const A=(y.z+D.z)*.5;y.z=v.z=h.z=D.z=A,y.applyMatrix4(M),v.applyMatrix4(M),h.applyMatrix4(M),D.applyMatrix4(M),T.debugDrawLine(y,v,255),T.debugDrawLine(y,h,255),T.debugDrawLine(v,D,255),T.debugDrawLine(h,D,255)}let S=999;if(l&&r.lastScreenCoverage>0){for(let M=0;M<l.length;M++)if(l[M].density/r.lastScreenCoverage<o){S=M;break}}S<i&&(i=S,a=!0)}if(a?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,G&&s.mesh_lod!=r.lastLodLevel_Mesh){const g=l?.[s.mesh_lod];g&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${g.density.toFixed(0)}) - ${e.name}`)}if(f)if(r.lastLodLevel_Texture<0){if(s.texture_lod=c.max_count-1,G){const g=c.lods[c.max_count-1];G&&console.log(`First Texture LOD ${s.texture_lod} (${g.max_height}px) - ${e.name}`)}}else{const g=r.lastScreenCoverage*1.5,L=this.renderer.domElement.clientHeight/window.devicePixelRatio*g;for(let m=c.lods.length-1;m>=0;m--){const w=c.lods[m];if(!(Ie()&&w.max_height>4096)&&w.max_height>L){s.texture_lod=m,s.texture_lod<r.lastLodLevel_Texture&&G&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} (${w.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${L.toFixed(0)}px) - ${e.name}`);break}}}else s.texture_lod=0}};let B=T;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 je{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 me=Symbol("NEEDLE_mesh_lod"),ee=Symbol("NEEDLE_texture_lod");function pe(t){if(!t)return null;let e=null,r=null;for(let o=t;o!=null;o=Object.getPrototypeOf(o)){const s=Object.getOwnPropertySymbols(o),n=s.find(a=>a.toString()=="Symbol(renderer)"),i=s.find(a=>a.toString()=="Symbol(scene)");!e&&n!=null&&(e=t[n].threeRenderer),!r&&i!=null&&(r=t[i])}if(e){const o=B.get(e);if(B.addPlugin(new Ge(t)),o.enable(),r){const s=r.camera||r.traverse(n=>n.type=="PerspectiveCamera")[0];s&&e.render(r,s)}return()=>{o.disable()}}return null}class Ge{constructor(e){d(this,"modelviewer"),d(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,r,o,s){this.tryParseMeshLOD(r,s),this.tryParseTextureLOD(r,s)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,r){if(r[ee]==!0)return;r[ee]=!0;const o=this.tryGetCurrentGLTF(e),s=this.getUrl();if(s&&o&&r.material){let n=function(a){var u,l,x;if(a[ee]==!0)return;a[ee]=!0,a.userData&&(a.userData.LOD=-1);const c=Object.keys(a);for(let f=0;f<c.length;f++){const b=c[f],g=a[b];if(g?.isTexture===!0){const L=(l=(u=g.userData)==null?void 0:u.associations)==null?void 0:l.textures,m=o.parser.json.textures[L];if(!m){console.warn("Texture data not found for texture index "+L);continue}if((x=m?.extensions)!=null&&x[I]){const w=m.extensions[I];w&&s&&O.registerTexture(s,g,w.lods.length,L,w)}}}};const i=r.material;if(Array.isArray(i))for(const a of i)n(a);else n(i)}}tryParseMeshLOD(e,r){var o,s;if(r[me]==!0)return;r[me]=!0;const n=this.getUrl();if(!n)return;const i=(s=(o=r.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[I];if(i&&n){const a=r.uuid;O.registerMesh(n,a,r,0,i.lods.length,i)}}}document.addEventListener("DOMContentLoaded",()=>{pe(document.querySelector("model-viewer"))});function Fe(t,e,r,o){ne(e),oe(r),r.register(n=>new O(n,t));const s=B.get(e);return o?.enableLODsManager!==!1&&s.enable(),s}export{I as EXTENSION_NAME,B as LODsManager,O as NEEDLE_progressive,oe as addDracoAndKTX2Loaders,ne as createLoaders,Z as getRaycastMesh,pe as patchModelViewer,Ae as setDracoDecoderLocation,Ee as setKTX2TranscoderLocation,he as setRaycastMesh,Fe as useNeedleProgressive,Be as useRaycastMeshes};
@@ -1,5 +1,5 @@
1
- "use strict";var xe=Object.defineProperty;var me=(l,e,t)=>e in l?xe(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var c=(l,e,t)=>(me(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Le=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Me=require("three/examples/jsm/loaders/DRACOLoader.js"),De=require("three/examples/jsm/loaders/KTX2Loader.js"),h=require("three"),we=require("three/examples/jsm/loaders/GLTFLoader.js");let Q="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ae="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(Q+"draco_decoder.js",{method:"head"}).catch(l=>{Q="./include/draco/",ae="./include/ktx2/"});function _e(l){Q=l}function Oe(l){ae=l}let X,ie,Y;function le(l){X||(X=new Me.DRACOLoader,X.setDecoderPath(Q),X.setDecoderConfig({type:"js"})),Y||(Y=new De.KTX2Loader,Y.setTranscoderPath(ae)),ie||(ie=Le.MeshoptDecoder),l?Y.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ce(l){l.dracoLoader||l.setDRACOLoader(X),l.ktx2Loader||l.setKTX2Loader(Y),l.meshoptDecoder||l.setMeshoptDecoder(ie)}function Z(l){const t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function ve(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 Se(){return q!==void 0||(q=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),Z("debugprogressive")&&console.log("isMobileDevice",q)),q}const oe=Symbol("needle:raycast-mesh");function j(l){return(l==null?void 0:l[oe])instanceof h.BufferGeometry?l[oe]:null}function he(l,e){if((l.type==="Mesh"||l.type==="SkinnedMesh")&&!j(l)){const r=be(e);r.userData={isRaycastMesh:!0},l[oe]=r}}function Te(l=!0){if(l){if(K)return;const e=K=h.Mesh.prototype.raycast;h.Mesh.prototype.raycast=function(t,r){const i=this,o=j(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;h.Mesh.prototype.raycast=K,K=null}}let K=null;function be(l){const e=new h.BufferGeometry;for(const t in l.attributes)e.setAttribute(t,l.getAttribute(t));return e.setIndex(l.getIndex()),e}const $=new Array,I="NEEDLE_progressive",M=Z("debugprogressive"),re=Symbol("needle-progressive-texture"),H=new Map,ne=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=b.getMeshLODInformation(n),d=a?Math.min(e,a.lods.length):0;o["DEBUG:LOD"]=e,b.assignMeshLOD(o,d),a&&(t=Math.max(t,a.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,b.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,ne&&ne.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=r)}))})}function ue(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 S=class{constructor(e,t){c(this,"parser");c(this,"url");c(this,"_isLoadingMesh");c(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[I];return t?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",e).then(o=>(this._isLoadingMesh=!1,o&&S.registerMesh(this.url,t.guid,o,t.lods.length,void 0,t),o))):null});M&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return I}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 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 f=r.lodInfos.get(d.key);if(f&&f.lods){a.min_count=Math.min(a.min_count,f.lods.length),a.max_count=Math.max(a.max_count,f.lods.length);for(let y=0;y<f.lods.length;y++){const p=f.lods[y];p.width&&(a.lods[y]=a.lods[y]||{min_height:1/0,max_height:0},a.lods[y].min_height=Math.min(a.lods[y].min_height,p.height),a.lods[y].max_height=Math.max(a.lods[y].max_height,p.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 h.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,S.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 instanceof h.BufferGeometry&&(e.geometry=s,M&&ue(e,"geometry",o.url))}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 h.Material||e.isMaterial===!0){const r=e,i=[],o=new Array;if(M&&ne.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],f=o[a];d&&d.isTexture===!0?n.push({material:r,slot:f,texture:d,level:t}):n.push({material:r,slot:f,texture:null,level:t})}return n})}if(e instanceof h.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):S.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&&ue(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)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[I];if(s){if(!s.lods){M&&console.warn("Texture has no LODs",s);return}let n=!1;for(const a of this.parser.associations.keys())a.isTexture===!0&&this.parser.associations.get(a).textures===o&&(n=!0,S.registerTexture(this.url,a,s.lods.length,o,s));n||this.parser.getDependency("texture",o).then(a=>{a&&S.registerTexture(this.url,a,s.lods.length,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[I];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&&S.registerMesh(this.url,s.guid,n,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var n,a,d,f,y,p;const r=M=="verbose",i=(a=(n=e.userData).LODS)==null?void 0:a.call(n);if(!i)return null;const o=i==null?void 0:i.key;let s;if(e.isTexture===!0){const w=e;w.source&&w.source[re]&&(s=w.source[re])}if(s||(s=S.lodInfos.get(o)),s){if(t>0){let x=!1;const g=Array.isArray(s.lods);if(g&&t>=s.lods.length?x=!0:g||(x=!0),x)return this.lowresCache.get(o)}const w=Array.isArray(s.lods)?(d=s.lods[t])==null?void 0:d.path:s.lods;if(!w)return M&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const D=ve(i.url,w);if(D.endsWith(".glb")||D.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const x=D+"_"+s.guid,g=this.previouslyLoaded.get(x);if(g!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${x}`);let A=await g.catch(G=>(console.error(`Error loading LOD ${t} from ${D}
2
- `,G),null)),V=!1;if(A==null||(A instanceof h.Texture&&e instanceof h.Texture?(f=A.image)!=null&&f.data||(y=A.source)!=null&&y.data?A=this.copySettings(e,A):(V=!0,this.previouslyLoaded.delete(x)):A instanceof h.BufferGeometry&&e instanceof h.BufferGeometry&&((p=A.attributes.position)!=null&&p.array||(V=!0,this.previouslyLoaded.delete(x)))),!V)return A}const _=s,B=new Promise(async(A,V)=>{const G=new we.GLTFLoader;ce(G),M&&(await new Promise(L=>setTimeout(L,1e3)),r&&console.warn("Start loading (delayed) "+D,_.guid));let ee=D;if(_&&Array.isArray(_.lods)){const L=_.lods[t];L.hash&&(ee+="?v="+L.hash)}const m=await G.loadAsync(ee).catch(L=>(console.error(`Error loading LOD ${t} from ${D}
3
- `,L),null));if(!m)return null;const O=m.parser;r&&console.log("Loading finished "+D,_.guid);let v=0;if(m.parser.json.textures){let L=!1;for(const u of m.parser.json.textures){if(u!=null&&u.extensions){const T=u==null?void 0:u.extensions[I];if(T!=null&&T.guid&&T.guid===_.guid){L=!0;break}}v++}if(L){let u=await O.getDependency("texture",v);return u&&S.assignLODInformation(i.url,u,o,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+u.name+'"',D,v,u,x),e instanceof h.Texture&&(u=this.copySettings(e,u)),u&&(u.guid=_.guid),A(u)}else M&&console.warn("Could not find texture with guid",_.guid)}if(v=0,m.parser.json.meshes){let L=!1;for(const u of m.parser.json.meshes){if(u!=null&&u.extensions){const T=u==null?void 0:u.extensions[I];if(T!=null&&T.guid&&T.guid===_.guid){L=!0;break}}v++}if(L){const u=await O.getDependency("mesh",v),T=_;if(r&&console.log(`Loaded Mesh "${u.name}"`,D,v,u,x),u.isMesh===!0){const E=u.geometry;return S.assignLODInformation(i.url,E,o,t,void 0,T.density),A(E)}else{const E=new Array;for(let F=0;F<u.children.length;F++){const N=u.children[F];if(N instanceof h.Mesh){const z=N.geometry;S.assignLODInformation(i.url,z,o,t,F,T.density),E.push(z)}}return A(E)}}}return A(null)});return this.previouslyLoaded.set(x,B),await B}else if(e instanceof h.Texture){r&&console.log("Load texture from uri: "+D);const g=await new h.TextureLoader().loadAsync(D);return g?(g.guid=s.guid,g.flipY=!1,g.needsUpdate=!0,g.colorSpace=e.colorSpace,r&&console.log(s,g)):M&&console.warn("failed loading",D),g}}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 Ae(e,r,i,o,s);t.userData.LODS=()=>n}static getAssignedLODInformation(e){var t,r;return((r=(t=e==null?void 0:e.userData)==null?void 0:t.LODS)==null?void 0:r.call(t))||null}static copySettings(e,t){return t=t.clone(),M&&console.warn(`Copying texture settings
1
+ "use strict";var Le=Object.defineProperty;var me=(l,e,t)=>e in l?Le(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var d=(l,e,t)=>(me(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),Me=require("three/examples/jsm/loaders/GLTFLoader.js"),De=require("three/examples/jsm/libs/meshopt_decoder.module.js"),_e=require("three/examples/jsm/loaders/DRACOLoader.js"),we=require("three/examples/jsm/loaders/KTX2Loader.js");let Z="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",le="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(Z+"draco_decoder.js",{method:"head"}).catch(l=>{Z="./include/draco/",le="./include/ktx2/"});function Oe(l){Z=l}function ve(l){le=l}let q,oe,K;function ce(l){q||(q=new _e.DRACOLoader,q.setDecoderPath(Z),q.setDecoderConfig({type:"js"})),K||(K=new we.KTX2Loader,K.setTranscoderPath(le)),oe||(oe=De.MeshoptDecoder),l?K.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function ue(l){l.dracoLoader||l.setDRACOLoader(q),l.ktx2Loader||l.setKTX2Loader(K),l.meshoptDecoder||l.setMeshoptDecoder(oe)}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 Se(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 Te(){return W!==void 0||(W=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),j("debugprogressive")&&console.log("isMobileDevice",W)),W}const ne=Symbol("needle:raycast-mesh");function ee(l){return(l==null?void 0:l[ne])instanceof p.BufferGeometry?l[ne]:null}function ge(l,e){if((l.type==="Mesh"||l.type==="SkinnedMesh")&&!ee(l)){const r=Ae(e);r.userData={isRaycastMesh:!0},l[ne]=r}}function be(l=!0){if(l){if(V)return;const e=V=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(t,r){const i=this,o=ee(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),e.call(this,t,r),s&&(i.geometry=s)}}else{if(!V)return;p.Mesh.prototype.raycast=V,V=null}}let V=null;function Ae(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 F=new Array,E="NEEDLE_progressive",x=j("debugprogressive"),se=Symbol("needle-progressive-texture"),X=new Map,ae=new Set;if(x){let l=function(){e+=1,console.log("Toggle LOD level",e,X),X.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),h=a?Math.min(e,a.lods.length):0;o["DEBUG:LOD"]=e,S.assignMeshLOD(o,h),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,ae&&ae.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=r)}))})}function fe(l,e,t){var i;if(!x)return;X.has(l)||X.set(l,{keys:[],sourceId:t});const r=X.get(l);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const v=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[E];return t?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",e).then(o=>{var s;return this._isLoadingMesh=!1,o&&v.registerMesh(this.url,t.guid,o,(s=t.lods)==null?void 0:s.length,void 0,t),o})):null});x&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return E}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(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",e),e.type==="ShaderMaterial"||e.type==="RawShaderMaterial"){const n=e;for(const a of Object.keys(n.uniforms)){const h=n.uniforms[a].value;(h==null?void 0:h.isTexture)===!0&&s(h,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 h=r.getAssignedLODInformation(n);if(h){const c=r.lodInfos.get(h.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 p.Mesh||e.isMesh===!0){const i=e.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of F)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,v.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,x&&fe(e,"geometry",o.url)):x&&console.error("Invalid LOD geometry",s))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else x&&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(x&&ae.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 h=this.assignTextureLODForSlot(a,t,r,n);i.push(h),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 h=s[a],c=o[a];h&&h.isTexture===!0?n.push({material:r,slot:c,texture:h,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):v.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 x==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,t,r,s,o),null}r[i]=o}if(x&&i&&r){const s=this.getAssignedLODInformation(e);s&&fe(r,i,s.url)}}return o}else x=="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 x&&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[E];if(n){if(!n.lods){x&&console.warn("Texture has no LODs",n);return}let a=!1;for(const h of this.parser.associations.keys())h.isTexture===!0&&this.parser.associations.get(h).textures===o&&(a=!0,v.registerTexture(this.url,h,(s=n.lods)==null?void 0:s.length,o,n));a||this.parser.getDependency("texture",o).then(h=>{var c;h&&v.registerTexture(this.url,h,(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[E];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&&v.registerMesh(this.url,s.guid,n,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var n,a,h,c;const r=x=="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[se]&&(s=L.source[se])}if(s||(s=v.lodInfos.get(o)),s){if(t>0){let y=!1;const m=Array.isArray(s.lods);if(m&&t>=s.lods.length?y=!0:m||(y=!0),y)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 x&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const u=Se(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 y=u+"_"+s.guid,m=this.previouslyLoaded.get(y);if(m!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${y}`);let O=await m.catch(P=>(console.error(`Error loading LOD ${t} from ${u}
2
+ `,P),null)),A=!1;if(O==null||(O instanceof p.Texture&&e instanceof p.Texture?(a=O.image)!=null&&a.data||(h=O.source)!=null&&h.data?O=this.copySettings(e,O):(A=!0,this.previouslyLoaded.delete(y)):O instanceof p.BufferGeometry&&e instanceof p.BufferGeometry&&((c=O.attributes.position)!=null&&c.array||(A=!0,this.previouslyLoaded.delete(y)))),!A)return O}const w=s,_=new Promise(async(O,A)=>{const P=new Me.GLTFLoader;ue(P),x&&(await new Promise(g=>setTimeout(g,1e3)),r&&console.warn("Start loading (delayed) "+u,w.guid));let Y=u;if(w&&Array.isArray(w.lods)){const g=w.lods[t];g.hash&&(Y+="?v="+g.hash)}const k=await P.loadAsync(Y).catch(g=>(console.error(`Error loading LOD ${t} from ${u}
3
+ `,g),null));if(!k)return null;const z=k.parser;r&&console.log("Loading finished "+u,w.guid);let I=0;if(k.parser.json.textures){let g=!1;for(const f of k.parser.json.textures){if(f!=null&&f.extensions){const M=f==null?void 0:f.extensions[E];if(M!=null&&M.guid&&M.guid===w.guid){g=!0;break}}I++}if(g){let f=await z.getDependency("texture",I);return f&&v.assignLODInformation(i.url,f,o,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+f.name+'"',u,I,f,y),e instanceof p.Texture&&(f=this.copySettings(e,f)),f&&(f.guid=w.guid),O(f)}else x&&console.warn("Could not find texture with guid",w.guid,k.parser.json)}if(I=0,k.parser.json.meshes){let g=!1;for(const f of k.parser.json.meshes){if(f!=null&&f.extensions){const M=f==null?void 0:f.extensions[E];if(M!=null&&M.guid&&M.guid===w.guid){g=!0;break}}I++}if(g){const f=await z.getDependency("mesh",I),M=w;if(r&&console.log(`Loaded Mesh "${f.name}"`,u,I,f,y),f.isMesh===!0){const T=f.geometry;return v.assignLODInformation(i.url,T,o,t,void 0,M.density),O(T)}else{const T=new Array;for(let b=0;b<f.children.length;b++){const G=f.children[b];if(G.isMesh===!0){const $=G.geometry;v.assignLODInformation(i.url,$,o,t,b,M.density),T.push($)}}return O(T)}}else x&&console.warn("Could not find mesh with guid",w.guid,k.parser.json)}return O(null)});return this.previouslyLoaded.set(y,_),await _}else if(e instanceof p.Texture){r&&console.log("Load texture from uri: "+u);const m=await new p.TextureLoader().loadAsync(u);return m?(m.guid=s.guid,m.flipY=!1,m.needsUpdate=!0,m.colorSpace=e.colorSpace,r&&console.log(s,m)):x&&console.warn("failed loading",u),m}}else x&&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 Pe(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(),x&&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 b=S;c(b,"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[re]=o);const s=o.guid;S.assignLODInformation(e,t,s,r,i,void 0),S.lodInfos.set(s,o),S.lowresCache.set(s,t)}),c(b,"registerMesh",(e,t,r,i,o,s)=>{var d;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={}),S.assignLODInformation(e,n,t,i,o,s.density),S.lodInfos.set(t,s);let a=S.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],S.lowresCache.set(t,a),i>0&&!j(r)&&he(r,n);for(const f of $)(d=f.onRegisteredNewMesh)==null||d.call(f,r,s)}),c(b,"lodInfos",new Map),c(b,"previouslyLoaded",new Map),c(b,"lowresCache",new Map);class Ae{constructor(e,t,r,i,o){c(this,"url");c(this,"key");c(this,"level");c(this,"index");c(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}const U=Z("debugprogressive"),Pe=Z("noprogressive"),fe=Symbol("Needle:LODSManager"),se=Symbol("Needle:LODState"),W=Symbol("Needle:CurrentLOD"),R={mesh_lod:-1,texture_lod:-1},P=class{constructor(e){c(this,"renderer");c(this,"projectionScreenMatrix",new h.Matrix4);c(this,"cameraFrustrum",new h.Frustum);c(this,"targetTriangleDensity",2e5);c(this,"updateInterval",0);c(this,"pause",!1);c(this,"_frame",0);c(this,"_originalRender");c(this,"_sphere",new h.Sphere);c(this,"_tempBox",new h.Box3);c(this,"_tempBox2",new h.Box3);c(this,"tempMatrix",new h.Matrix4);c(this,"_tempWorldPosition",new h.Vector3);c(this,"_tempBoxSize",new h.Vector3);c(this,"_tempBox2Size",new h.Vector3);this.renderer=e}static getObjectLODState(e){return e[se]}static addPlugin(e){$.push(e)}static removePlugin(e){const t=$.indexOf(e);t>=0&&$.splice(t,1)}static get(e){return e[fe]?e[fe]:new P(e)}get plugins(){return $}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;le(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 f=s[0].material;(f.name==="EffectMaterial"||f.name==="CopyShader")&&(n=!1)}if(t.parent&&t.parent.type==="CubeCamera"&&(n=!1),n){if(Pe||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const f=this.targetTriangleDensity;for(const p of s){if(p.material&&(((a=p.geometry)==null?void 0:a.type)==="BoxGeometry"||((d=p.geometry)==null?void 0:d.type)==="BufferGeometry")&&(p.material.name==="SphericalGaussianBlur"||p.material.name=="BackgroundCubeMaterial"||p.material.name==="CubemapFromEquirect"||p.material.name==="EquirectangularToCubeUV")){U&&(p.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(p.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",p,p.material.name,p.material.type)));continue}switch(p.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const w=p.object;(w instanceof h.Mesh||w.isMesh)&&this.updateLODs(e,t,w,f,i)}const y=o.transparent;for(const p of y){const w=p.object;(w instanceof h.Mesh||w.isMesh)&&this.updateLODs(e,t,w,f,i)}}}updateLODs(e,t,r,i,o){var a,d;r.userData||(r.userData={});let s=r[se];if(s||(s=new Be,r[se]=s),s.frames++<2)return;for(const f of $)(a=f.onBeforeUpdateLOD)==null||a.call(f,this.renderer,e,t,r);this.calculateLodLevel(t,r,s,i,R),R.mesh_lod=Math.round(R.mesh_lod),R.texture_lod=Math.round(R.texture_lod),R.mesh_lod>=0&&this.loadProgressiveMeshes(r,R.mesh_lod);let n=R.texture_lod;if(r.material&&n>=0){const f=r["DEBUG:LOD"];f!=null&&(n=f),this.loadProgressiveTextures(r.material,n)}for(const f of $)(d=f.onAfterUpdatedLOD)==null||d.call(f,this.renderer,e,t,r,R);s.lastLodLevel_Mesh=R.mesh_lod,s.lastLodLevel_Texture=R.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[W]==null||t<e[W])&&(r=!0),r&&(e[W]=t,b.assignTextureLOD(e,t))}loadProgressiveMeshes(e,t){if(!e)return Promise.resolve(null);if(e[W]!==t){e[W]=t;const r=e.geometry;return b.assignMeshLOD(e,t).then(i=>(i&&e[W]==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 D;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;if(U&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const a=b.getMeshLODInformation(t.geometry),d=a==null?void 0:a.lods,f=d&&d.length>0,y=b.getMaterialMinMaxLODsCount(t.material),p=(y==null?void 0:y.min_count)!=1/0&&y.min_count>0&&y.max_count>0;if(!f&&!p){o.mesh_lod=0,o.texture_lod=0;return}if(f||(n=0),!((D=this.cameraFrustrum)!=null&&D.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}let w=t.geometry.boundingBox;if(t.type==="SkinnedMesh"){const x=t;x.boundingBox||x.computeBoundingBox(),w=x.boundingBox}if(w&&e.isPerspectiveCamera){const x=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 m=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(m)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(w),t.type==="SkinnedMesh"?t.parent&&this._tempBox.applyMatrix4(t.parent.matrixWorld):this._tempBox.applyMatrix4(t.matrixWorld),P.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&x.fov>70){const m=this._tempBox.min,O=this._tempBox.max;let v=m.x,L=m.y,u=O.x,T=O.y;const E=2,F=1.5,N=(m.x+O.x)*.5,z=(m.y+O.y)*.5;v=(v-N)*E+N,L=(L-z)*E+z,u=(u-N)*E+N,T=(T-z)*E+z;const pe=v<0&&u>0?0:Math.min(Math.abs(m.x),Math.abs(O.x)),ye=L<0&&T>0?0:Math.min(Math.abs(m.y),Math.abs(O.y)),te=Math.max(pe,ye);r.lastCentrality=(F-te)*(F-te)*(F-te)}else r.lastCentrality=1;const g=this._tempBox.getSize(this._tempBoxSize);g.multiplyScalar(.5),screen.availHeight>0&&g.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),g.x*=x.aspect;const _=e.matrixWorldInverse,B=this._tempBox2;B.copy(w),B.applyMatrix4(t.matrixWorld),B.applyMatrix4(_);const k=B.getSize(this._tempBox2Size),A=Math.max(k.x,k.y);if(Math.max(g.x,g.y)!=0&&A!=0&&(g.z=k.z/Math.max(k.x,k.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,U&&P.debugDrawLine){const m=this.tempMatrix.copy(this.projectionScreenMatrix);m.invert();const O=P.corner0,v=P.corner1,L=P.corner2,u=P.corner3;O.copy(this._tempBox.min),v.copy(this._tempBox.max),v.x=O.x,L.copy(this._tempBox.max),L.y=O.y,u.copy(this._tempBox.max);const T=(O.z+u.z)*.5;O.z=v.z=L.z=u.z=T,O.applyMatrix4(m),v.applyMatrix4(m),L.applyMatrix4(m),u.applyMatrix4(m),P.debugDrawLine(O,v,255),P.debugDrawLine(O,L,255),P.debugDrawLine(v,u,255),P.debugDrawLine(L,u,255)}let G=999;if(d&&r.lastScreenCoverage>0){for(let m=0;m<d.length;m++)if(d[m].density/r.lastScreenCoverage<i){G=m;break}}G<n&&(n=G)}if(o.mesh_lod=n,p)if(r.lastLodLevel_Texture<0){if(o.texture_lod=y.max_count-1,U){const x=y.lods[y.max_count-1];U&&console.log(`First Texture LOD ${o.texture_lod} (${x.max_height}px) - ${t.name}`)}}else{const x=r.lastScreenCoverage*1.5,_=this.renderer.domElement.clientHeight/window.devicePixelRatio*x;for(let B=y.lods.length-1;B>=0;B--){const k=y.lods[B];if(!(Se()&&k.max_height>4096)&&k.max_height>_){o.texture_lod=B,o.texture_lod<r.lastLodLevel_Texture&&U&&console.log(`Texture LOD changed ${r.lastLodLevel_Texture} → ${o.texture_lod} (${k.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${_.toFixed(0)}px) - ${t.name}`);break}}}else o.texture_lod=0}};let C=P;c(C,"debugDrawLine"),c(C,"corner0",new h.Vector3),c(C,"corner1",new h.Vector3),c(C,"corner2",new h.Vector3),c(C,"corner3",new h.Vector3),c(C,"_tempPtInside",new h.Vector3);class Be{constructor(){c(this,"frames",0);c(this,"lastLodLevel_Mesh",-1);c(this,"lastLodLevel_Texture",-1);c(this,"lastScreenCoverage",0);c(this,"lastScreenspaceVolume",new h.Vector3);c(this,"lastCentrality",0)}}const de=Symbol("NEEDLE_mesh_lod"),J=Symbol("NEEDLE_texture_lod");function ge(l){if(!l)return null;let e=null,t=null;for(let r=l;r!=null;r=Object.getPrototypeOf(r)){const i=Object.getOwnPropertySymbols(r),o=i.find(n=>n.toString()=="Symbol(renderer)"),s=i.find(n=>n.toString()=="Symbol(scene)");!e&&o!=null&&(e=l[o].threeRenderer),!t&&s!=null&&(t=l[s])}if(e){console.log("Adding Needle LODs to modelviewer");const r=C.get(e);if(C.addPlugin(new Ce(l)),r.enable(),t){const i=t.camera||t.traverse(o=>o.type=="PerspectiveCamera")[0];i&&e.render(t,i)}return()=>{r.disable()}}return null}class Ce{constructor(e){c(this,"modelviewer");c(this,"_didWarnAboutMissingUrl",!1);this.modelviewer=e}onBeforeUpdateLOD(e,t,r,i){this.tryParseMeshLOD(t,i),this.tryParseTextureLOD(t,i)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[J]==!0)return;t[J]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var d,f,y;if(n[J]==!0)return;n[J]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let p=0;p<a.length;p++){const w=a[p],D=n[w];if((D==null?void 0:D.isTexture)===!0){const x=(f=(d=D.userData)==null?void 0:d.associations)==null?void 0:f.textures,g=r.parser.json.textures[x];if(!g){console.warn("Texture data not found for texture index "+x);continue}if((y=g==null?void 0:g.extensions)!=null&&y[I]){const _=g.extensions[I];_&&i&&b.registerTexture(i,D,_.lods.length,x,_)}}}};const s=t.material;if(Array.isArray(s))for(const n of s)o(n);else o(s)}}tryParseMeshLOD(e,t){var o,s;if(t[de]==!0)return;t[de]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[I];if(i&&r){const n=t.uuid;b.registerMesh(r,n,t,0,i.lods.length,i)}}}function Re(l,e,t,r){le(e),ce(t),t.register(o=>new b(o,l));const i=C.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}document.addEventListener("DOMContentLoaded",()=>{ge(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=I;exports.LODsManager=C;exports.NEEDLE_progressive=b;exports.addDracoAndKTX2Loaders=ce;exports.createLoaders=le;exports.getRaycastMesh=j;exports.patchModelViewer=ge;exports.setDracoDecoderLocation=_e;exports.setKTX2TranscoderLocation=Oe;exports.setRaycastMesh=he;exports.useNeedleProgressive=Re;exports.useRaycastMeshes=Te;
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=v;d(S,"registerTexture",(e,t,r,i,o)=>{if(x&&console.log("> Progressive: register texture",i,t.name,t.uuid,t,o),!t){x&&console.error("gltf-progressive: Register texture without texture");return}t.source&&(t.source[se]=o);const s=o.guid;v.assignLODInformation(e,t,s,r,i,void 0),v.lodInfos.set(s,o),v.lowresCache.set(s,t)}),d(S,"registerMesh",(e,t,r,i,o,s)=>{var h;x&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;if(!n){x&&console.warn("gltf-progressive: Register mesh without geometry");return}n.userData||(n.userData={}),v.assignLODInformation(e,n,t,i,o,s.density),v.lodInfos.set(t,s);let a=v.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],v.lowresCache.set(t,a),i>0&&!ee(r)&&ge(r,n);for(const c of F)(h=c.onRegisteredNewMesh)==null||h.call(c,r,s)}),d(S,"lodInfos",new Map),d(S,"previouslyLoaded",new Map),d(S,"lowresCache",new Map);class Pe{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 N=j("debugprogressive"),Be=j("noprogressive"),de=Symbol("Needle:LODSManager"),ie=Symbol("Needle:LODState"),U=Symbol("Needle:CurrentLOD"),R={mesh_lod:-1,texture_lod:-1},B=class{constructor(e){d(this,"renderer");d(this,"projectionScreenMatrix",new p.Matrix4);d(this,"cameraFrustrum",new p.Frustum);d(this,"targetTriangleDensity",2e5);d(this,"updateInterval",0);d(this,"pause",!1);d(this,"_frame",0);d(this,"_originalRender");d(this,"_sphere",new p.Sphere);d(this,"_tempBox",new p.Box3);d(this,"_tempBox2",new p.Box3);d(this,"tempMatrix",new p.Matrix4);d(this,"_tempWorldPosition",new p.Vector3);d(this,"_tempBoxSize",new p.Vector3);d(this,"_tempBox2Size",new p.Vector3);this.renderer=e}static getObjectLODState(e){return e[ie]}static addPlugin(e){F.push(e)}static removePlugin(e){const t=F.indexOf(e);t>=0&&F.splice(t,1)}static get(e){return e[de]?e[de]:new B(e)}get plugins(){return F}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;ce(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,h;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(Be||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"||((h=u.geometry)==null?void 0:h.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){N&&(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 y=u.object;(y instanceof p.Mesh||y.isMesh)&&this.updateLODs(e,t,y,c,i)}const L=o.transparent;for(const u of L){const y=u.object;(y instanceof p.Mesh||y.isMesh)&&this.updateLODs(e,t,y,c,i)}}}updateLODs(e,t,r,i,o){var a,h;r.userData||(r.userData={});let s=r[ie];if(s||(s=new Ce,r[ie]=s),s.frames++<2)return;for(const c of F)(a=c.onBeforeUpdateLOD)==null||a.call(c,this.renderer,e,t,r);this.calculateLodLevel(t,r,s,i,R),R.mesh_lod=Math.round(R.mesh_lod),R.texture_lod=Math.round(R.texture_lod),R.mesh_lod>=0&&this.loadProgressiveMeshes(r,R.mesh_lod);let n=R.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 F)(h=c.onAfterUpdatedLOD)==null||h.call(c,this.renderer,e,t,r,R);s.lastLodLevel_Mesh=R.mesh_lod,s.lastLodLevel_Texture=R.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 w;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 h=S.getMeshLODInformation(t.geometry),c=h==null?void 0:h.lods,L=c&&c.length>0,u=S.getMaterialMinMaxLODsCount(t.material),y=(u==null?void 0:u.min_count)!=1/0&&u.min_count>0&&u.max_count>0;if(!L&&!y){o.mesh_lod=0,o.texture_lod=0;return}if(L||(a=!0,n=0),!((w=this.cameraFrustrum)!=null&&w.intersectsObject(t))){o.mesh_lod=99,o.texture_lod=99;return}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 g=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(m),t.type==="SkinnedMesh"?t.parent&&this._tempBox.applyMatrix4(t.parent.matrixWorld):this._tempBox.applyMatrix4(t.matrixWorld),B.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 g=this._tempBox.min,f=this._tempBox.max;let M=g.x,T=g.y,b=f.x,G=f.y;const $=2,te=1.5,H=(g.x+f.x)*.5,J=(g.y+f.y)*.5;M=(M-H)*$+H,T=(T-J)*$+J,b=(b-H)*$+H,G=(G-J)*$+J;const ye=M<0&&b>0?0:Math.min(Math.abs(g.x),Math.abs(f.x)),xe=T<0&&G>0?0:Math.min(Math.abs(g.y),Math.abs(f.y)),re=Math.max(ye,xe);r.lastCentrality=(te-re)*(te-re)*(te-re)}else r.lastCentrality=1;const D=this._tempBox.getSize(this._tempBoxSize);D.multiplyScalar(.5),screen.availHeight>0&&D.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),D.x*=_.aspect;const O=e.matrixWorldInverse,A=this._tempBox2;A.copy(m),A.applyMatrix4(t.matrixWorld),A.applyMatrix4(O);const P=A.getSize(this._tempBox2Size),Y=Math.max(P.x,P.y);if(Math.max(D.x,D.y)!=0&&Y!=0&&(D.z=P.z/Math.max(P.x,P.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,N&&B.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const f=B.corner0,M=B.corner1,T=B.corner2,b=B.corner3;f.copy(this._tempBox.min),M.copy(this._tempBox.max),M.x=f.x,T.copy(this._tempBox.max),T.y=f.y,b.copy(this._tempBox.max);const G=(f.z+b.z)*.5;f.z=M.z=T.z=b.z=G,f.applyMatrix4(g),M.applyMatrix4(g),T.applyMatrix4(g),b.applyMatrix4(g),B.debugDrawLine(f,M,255),B.debugDrawLine(f,T,255),B.debugDrawLine(M,b,255),B.debugDrawLine(T,b,255)}let z=999;if(c&&r.lastScreenCoverage>0){for(let g=0;g<c.length;g++)if(c[g].density/r.lastScreenCoverage<i){z=g;break}}z<n&&(n=z,a=!0)}if(a?o.mesh_lod=n:o.mesh_lod=r.lastLodLevel_Mesh,N&&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(y)if(r.lastLodLevel_Texture<0){if(o.texture_lod=u.max_count-1,N){const _=u.lods[u.max_count-1];N&&console.log(`First Texture LOD ${o.texture_lod} (${_.max_height}px) - ${t.name}`)}}else{const _=r.lastScreenCoverage*1.5,O=this.renderer.domElement.clientHeight/window.devicePixelRatio*_;for(let A=u.lods.length-1;A>=0;A--){const P=u.lods[A];if(!(Te()&&P.max_height>4096)&&P.max_height>O){o.texture_lod=A,o.texture_lod<r.lastLodLevel_Texture&&N&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${o.texture_lod} (${P.max_height}px: ${(100*r.lastScreenCoverage).toFixed(2)} % = ${O.toFixed(0)}px) - ${t.name}`);break}}}else o.texture_lod=0}};let C=B;d(C,"debugDrawLine"),d(C,"corner0",new p.Vector3),d(C,"corner1",new p.Vector3),d(C,"corner2",new p.Vector3),d(C,"corner3",new p.Vector3),d(C,"_tempPtInside",new p.Vector3);class Ce{constructor(){d(this,"frames",0);d(this,"lastLodLevel_Mesh",-1);d(this,"lastLodLevel_Texture",-1);d(this,"lastScreenCoverage",0);d(this,"lastScreenspaceVolume",new p.Vector3);d(this,"lastCentrality",0)}}const he=Symbol("NEEDLE_mesh_lod"),Q=Symbol("NEEDLE_texture_lod");function pe(l){if(!l)return null;let e=null,t=null;for(let r=l;r!=null;r=Object.getPrototypeOf(r)){const i=Object.getOwnPropertySymbols(r),o=i.find(n=>n.toString()=="Symbol(renderer)"),s=i.find(n=>n.toString()=="Symbol(scene)");!e&&o!=null&&(e=l[o].threeRenderer),!t&&s!=null&&(t=l[s])}if(e){const r=C.get(e);if(C.addPlugin(new Re(l)),r.enable(),t){const i=t.camera||t.traverse(o=>o.type=="PerspectiveCamera")[0];i&&e.render(t,i)}return()=>{r.disable()}}return null}class Re{constructor(e){d(this,"modelviewer");d(this,"_didWarnAboutMissingUrl",!1);this.modelviewer=e}onBeforeUpdateLOD(e,t,r,i){this.tryParseMeshLOD(t,i),this.tryParseTextureLOD(t,i)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[Q]==!0)return;t[Q]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let o=function(n){var h,c,L;if(n[Q]==!0)return;n[Q]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let u=0;u<a.length;u++){const y=a[u],m=n[y];if((m==null?void 0:m.isTexture)===!0){const w=(c=(h=m.userData)==null?void 0:h.associations)==null?void 0:c.textures,_=r.parser.json.textures[w];if(!_){console.warn("Texture data not found for texture index "+w);continue}if((L=_==null?void 0:_.extensions)!=null&&L[E]){const D=_.extensions[E];D&&i&&S.registerTexture(i,m,D.lods.length,w,D)}}}};const s=t.material;if(Array.isArray(s))for(const n of s)o(n);else o(s)}}tryParseMeshLOD(e,t){var o,s;if(t[he]==!0)return;t[he]=!0;const r=this.getUrl();if(!r)return;const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[E];if(i&&r){const n=t.uuid;S.registerMesh(r,n,t,0,i.lods.length,i)}}}document.addEventListener("DOMContentLoaded",()=>{pe(document.querySelector("model-viewer"))});function Ee(l,e,t,r){ce(e),ue(t),t.register(o=>new S(o,l));const i=C.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}exports.EXTENSION_NAME=E;exports.LODsManager=C;exports.NEEDLE_progressive=S;exports.addDracoAndKTX2Loaders=ue;exports.createLoaders=ce;exports.getRaycastMesh=ee;exports.patchModelViewer=pe;exports.setDracoDecoderLocation=Oe;exports.setKTX2TranscoderLocation=ve;exports.setRaycastMesh=ge;exports.useNeedleProgressive=Ee;exports.useRaycastMeshes=be;
package/lib/extension.js CHANGED
@@ -208,7 +208,7 @@ export class NEEDLE_progressive {
208
208
  }
209
209
  if (lodObject) {
210
210
  if (lodObject?.userData?.LODS) {
211
- const lods = lodObject.userData.LODS();
211
+ const lods = lodObject.userData.LODS;
212
212
  lodInformation = this.lodInfos.get(lods.key);
213
213
  if (level === undefined)
214
214
  return lodInformation != undefined;
@@ -258,12 +258,16 @@ export class NEEDLE_progressive {
258
258
  geo = geo[index];
259
259
  }
260
260
  if (geo && currentGeometry != geo) {
261
+ const isGeometry = geo?.isBufferGeometry;
261
262
  // if (debug == "verbose") console.log("Progressive Mesh " + mesh.name + " loaded", currentGeometry, "→", geo, "\n", mesh)
262
- if (geo instanceof BufferGeometry) {
263
+ if (isGeometry) {
263
264
  mesh.geometry = geo;
264
265
  if (debug)
265
266
  registerDebug(mesh, "geometry", lodinfo.url);
266
267
  }
268
+ else if (debug) {
269
+ console.error("Invalid LOD geometry", geo);
270
+ }
267
271
  }
268
272
  }
269
273
  // this.onProgressiveLoadEnd(info);
@@ -413,7 +417,7 @@ export class NEEDLE_progressive {
413
417
  return this.parser.getDependency("mesh", meshIndex).then(mesh => {
414
418
  this._isLoadingMesh = false;
415
419
  if (mesh) {
416
- NEEDLE_progressive.registerMesh(this.url, ext.guid, mesh, ext.lods.length, undefined, ext);
420
+ NEEDLE_progressive.registerMesh(this.url, ext.guid, mesh, ext.lods?.length, undefined, ext);
417
421
  }
418
422
  return mesh;
419
423
  });
@@ -436,7 +440,7 @@ export class NEEDLE_progressive {
436
440
  const val = this.parser.associations.get(key);
437
441
  if (val.textures === index) {
438
442
  found = true;
439
- NEEDLE_progressive.registerTexture(this.url, key, ext.lods.length, index, ext);
443
+ NEEDLE_progressive.registerTexture(this.url, key, ext.lods?.length, index, ext);
440
444
  }
441
445
  }
442
446
  }
@@ -444,7 +448,7 @@ export class NEEDLE_progressive {
444
448
  if (!found) {
445
449
  this.parser.getDependency("texture", index).then(tex => {
446
450
  if (tex) {
447
- NEEDLE_progressive.registerTexture(this.url, tex, ext.lods.length, index, ext);
451
+ NEEDLE_progressive.registerTexture(this.url, tex, ext.lods?.length, index, ext);
448
452
  }
449
453
  });
450
454
  }
@@ -537,7 +541,7 @@ export class NEEDLE_progressive {
537
541
  static async getOrLoadLOD(current, level) {
538
542
  const debugverbose = debug == "verbose";
539
543
  /** this key is used to lookup the LOD information */
540
- const LOD = current.userData.LODS?.();
544
+ const LOD = current.userData.LODS;
541
545
  if (!LOD) {
542
546
  return null;
543
547
  }
@@ -680,7 +684,7 @@ export class NEEDLE_progressive {
680
684
  return resolve(tex);
681
685
  }
682
686
  else if (debug) {
683
- console.warn("Could not find texture with guid", ext.guid);
687
+ console.warn("Could not find texture with guid", ext.guid, gltf.parser.json);
684
688
  }
685
689
  }
686
690
  index = 0;
@@ -713,7 +717,7 @@ export class NEEDLE_progressive {
713
717
  const geometries = new Array();
714
718
  for (let i = 0; i < mesh.children.length; i++) {
715
719
  const child = mesh.children[i];
716
- if (child instanceof Mesh) {
720
+ if (child.isMesh === true) {
717
721
  const geo = child.geometry;
718
722
  NEEDLE_progressive.assignLODInformation(LOD.url, geo, LODKEY, level, i, meshExt.density);
719
723
  geometries.push(geo);
@@ -722,6 +726,9 @@ export class NEEDLE_progressive {
722
726
  return resolve(geometries);
723
727
  }
724
728
  }
729
+ else if (debug) {
730
+ console.warn("Could not find mesh with guid", ext.guid, gltf.parser.json);
731
+ }
725
732
  }
726
733
  // we could not find a texture or mesh with the given guid
727
734
  return resolve(null);
@@ -762,10 +769,10 @@ export class NEEDLE_progressive {
762
769
  if (!res.userData)
763
770
  res.userData = {};
764
771
  const info = new LODInformation(url, key, level, index, density);
765
- res.userData.LODS = () => info;
772
+ res.userData.LODS = info;
766
773
  }
767
774
  static getAssignedLODInformation(res) {
768
- return res?.userData?.LODS?.() || null;
775
+ return res?.userData?.LODS || null;
769
776
  }
770
777
  // private static readonly _copiedTextures: WeakMap<Texture, Texture> = new Map();
771
778
  static copySettings(source, target) {
package/lib/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { WebGLRenderer } from "three";
2
- import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
3
- import { LODsManager } from "./lods_manager.js";
4
1
  export * from "./extension.js";
5
2
  export * from "./plugins/index.js";
6
3
  export { LODsManager } from "./lods_manager.js";
7
4
  export { setDracoDecoderLocation, setKTX2TranscoderLocation, createLoaders, addDracoAndKTX2Loaders } from "./loaders.js";
8
5
  export * from "./utils.js";
6
+ import { WebGLRenderer } from "three";
7
+ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
8
+ import { LODsManager } from "./lods_manager.js";
9
9
  declare class UseNeedleGLTFProgressive {
10
10
  enableLODsManager?: boolean;
11
11
  }
package/lib/index.js CHANGED
@@ -1,11 +1,16 @@
1
- import { addDracoAndKTX2Loaders, createLoaders } from "./loaders.js";
2
- import { NEEDLE_progressive } from "./extension.js";
3
- import { LODsManager } from "./lods_manager.js";
4
1
  export * from "./extension.js";
5
2
  export * from "./plugins/index.js";
6
3
  export { LODsManager } from "./lods_manager.js";
7
4
  export { setDracoDecoderLocation, setKTX2TranscoderLocation, createLoaders, addDracoAndKTX2Loaders } from "./loaders.js";
8
5
  export * from "./utils.js";
6
+ import { patchModelViewer } from "./plugins/modelviewer.js";
7
+ // Query once for model viewer. If a user does not have model-viewer in their page, this will return null.
8
+ document.addEventListener("DOMContentLoaded", () => {
9
+ patchModelViewer(document.querySelector("model-viewer"));
10
+ });
11
+ import { addDracoAndKTX2Loaders, createLoaders } from "./loaders.js";
12
+ import { NEEDLE_progressive } from "./extension.js";
13
+ import { LODsManager } from "./lods_manager.js";
9
14
  ;
10
15
  /** Use this function to enable progressive loading of gltf models.
11
16
  * @param url The url of the gltf model.
@@ -32,8 +37,3 @@ export function useNeedleProgressive(url, renderer, loader, opts) {
32
37
  }
33
38
  return lod;
34
39
  }
35
- import { patchModelViewer } from "./plugins/modelviewer.js";
36
- // Query once for model viewer. If a user does not have model-viewer in their page, this will return null.
37
- document.addEventListener("DOMContentLoaded", () => {
38
- patchModelViewer(document.querySelector("model-viewer"));
39
- });
@@ -147,6 +147,12 @@ export class LODsManager {
147
147
  if (camera.parent && camera.parent.type === "CubeCamera") {
148
148
  updateLODs = false;
149
149
  }
150
+ else if (_stack >= 1) {
151
+ // don't update LODs if we're e.g. rendering a shadow map
152
+ if (camera.type === "OrthographicCamera") {
153
+ updateLODs = false;
154
+ }
155
+ }
150
156
  if (updateLODs) {
151
157
  if (suppressProgressiveLoading)
152
158
  return;
@@ -256,7 +262,7 @@ export class LODsManager {
256
262
  // Check if the material LOD was already updated to a certain level
257
263
  // We don't use the userData here because we want to re-run assigning textures if the material has been cloned
258
264
  let update = false;
259
- if (material[$currentLOD] == undefined) {
265
+ if (material[$currentLOD] === undefined) {
260
266
  update = true;
261
267
  }
262
268
  else if (level < material[$currentLOD]) {
@@ -332,6 +338,7 @@ export class LODsManager {
332
338
  /** highest LOD level we'd ever expect to be generated */
333
339
  const maxLevel = 10;
334
340
  let mesh_level = maxLevel + 1;
341
+ let mesh_level_calculated = false;
335
342
  if (debugProgressiveLoading && mesh["DEBUG:LOD"] != undefined) {
336
343
  return mesh["DEBUG:LOD"];
337
344
  }
@@ -348,6 +355,7 @@ export class LODsManager {
348
355
  return;
349
356
  }
350
357
  if (!has_mesh_lods) {
358
+ mesh_level_calculated = true;
351
359
  mesh_level = 0;
352
360
  }
353
361
  if (!this.cameraFrustrum?.intersectsObject(mesh)) {
@@ -491,9 +499,24 @@ export class LODsManager {
491
499
  const isLowerLod = expectedLevel < mesh_level;
492
500
  if (isLowerLod) {
493
501
  mesh_level = expectedLevel;
502
+ mesh_level_calculated = true;
503
+ }
504
+ }
505
+ if (mesh_level_calculated) {
506
+ result.mesh_lod = mesh_level;
507
+ }
508
+ else {
509
+ result.mesh_lod = state.lastLodLevel_Mesh;
510
+ }
511
+ if (debugProgressiveLoading) {
512
+ const changed = result.mesh_lod != state.lastLodLevel_Mesh;
513
+ if (changed) {
514
+ const level = mesh_lods?.[result.mesh_lod];
515
+ if (level) {
516
+ console.log(`Mesh LOD changed: ${state.lastLodLevel_Mesh} → ${result.mesh_lod} (${level.density.toFixed(0)}) - ${mesh.name}`);
517
+ }
494
518
  }
495
519
  }
496
- result.mesh_lod = mesh_level;
497
520
  if (has_texture_lods) {
498
521
  // If this is the first time a texture LOD is requested we want to get the highest LOD to not display the minimal resolution that the root glTF contains as long while we wait for loading of e.g. the 8k LOD 0 texture
499
522
  if (state.lastLodLevel_Texture < 0) {
@@ -516,7 +539,7 @@ export class LODsManager {
516
539
  result.texture_lod = i;
517
540
  if (result.texture_lod < state.lastLodLevel_Texture) {
518
541
  if (debugProgressiveLoading)
519
- console.log(`Texture LOD changed ${state.lastLodLevel_Texture} → ${result.texture_lod} (${lod.max_height}px: ${(100 * state.lastScreenCoverage).toFixed(2)} % = ${pixelSizeOnScreen.toFixed(0)}px) - ${mesh.name}`);
542
+ console.log(`Texture LOD changed: ${state.lastLodLevel_Texture} → ${result.texture_lod} (${lod.max_height}px: ${(100 * state.lastScreenCoverage).toFixed(2)} % = ${pixelSizeOnScreen.toFixed(0)}px) - ${mesh.name}`);
520
543
  }
521
544
  break;
522
545
  }
@@ -530,9 +553,6 @@ export class LODsManager {
530
553
  }
531
554
  }
532
555
  }
533
- function lerp(a, b, t) {
534
- return a + (b - a) * t;
535
- }
536
556
  class LOD_state {
537
557
  frames = 0;
538
558
  lastLodLevel_Mesh = -1;
@@ -22,7 +22,6 @@ export function patchModelViewer(modelviewer) {
22
22
  }
23
23
  }
24
24
  if (renderer) {
25
- console.log("Adding Needle LODs to modelviewer");
26
25
  const lod = LODsManager.get(renderer);
27
26
  LODsManager.addPlugin(new RegisterModelviewerDataPlugin(modelviewer));
28
27
  lod.enable();
@@ -30,12 +29,6 @@ export function patchModelViewer(modelviewer) {
30
29
  const camera = scene["camera"] || scene.traverse((o) => o.type == "PerspectiveCamera")[0];
31
30
  if (camera) {
32
31
  renderer.render(scene, camera);
33
- // setTimeout(() => {
34
- // renderer.render(scene, camera);
35
- // }, 100)
36
- // setTimeout(() => {
37
- // renderer.render(scene, camera);
38
- // }, 1200)
39
32
  }
40
33
  }
41
34
  return () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/gltf-progressive",
3
- "version": "1.2.1-alpha",
3
+ "version": "1.2.1-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": {