@needle-tools/gltf-progressive 2.1.6-next.fa4044e → 3.0.0-alpha.1
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.
- package/CHANGELOG.md +6 -0
- package/gltf-progressive.js +571 -477
- package/gltf-progressive.min.js +7 -7
- package/gltf-progressive.umd.cjs +7 -7
- package/lib/index.d.ts +2 -2
- package/lib/index.js +2 -2
- package/lib/lods.loading.d.ts +50 -0
- package/lib/lods.loading.js +82 -0
- package/lib/{lods_manager.d.ts → lods.manager.d.ts} +15 -3
- package/lib/{lods_manager.js → lods.manager.js} +40 -11
- package/lib/plugins/modelviewer.js +1 -1
- package/lib/utils.internal.d.ts +1 -0
- package/lib/utils.internal.js +8 -0
- package/lib/version.js +1 -1
- package/package.json +2 -2
package/gltf-progressive.min.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var He=Object.defineProperty,Ye=(t,e,s)=>e in t?He(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s,d=(t,e,s)=>(Ye(t,typeof e!="symbol"?e+"":e,s),s),Ee=(t,e,s)=>{if(!e.has(t))throw TypeError("Cannot "+s)},v=(t,e,s)=>(Ee(t,e,"read from private field"),s?s.call(t):e.get(t)),H=(t,e,s)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,s)},F=(t,e,s,n)=>(Ee(t,e,"write to private field"),n?n.call(t,s):e.set(t,s),s);import{BufferGeometry as ue,Mesh as Y,Texture as se,TextureLoader as Je,Matrix4 as Pe,Clock as Qe,MeshStandardMaterial as Ze,Sphere as et,Box3 as Ie,Vector3 as z}from"three";import{GLTFLoader as xe}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as tt}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as st}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as rt}from"three/examples/jsm/loaders/KTX2Loader.js";const Ce="";globalThis.GLTF_PROGRESSIVE_VERSION=Ce,console.debug("[gltf-progressive] version -");let $="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",Q="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const ot=$,nt=Q,Be=new URL($+"draco_decoder.js");Be.searchParams.append("range","true"),fetch(Be,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(t=>{console.debug(`Failed to fetch remote Draco decoder from ${$} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),$===ot&&ke("./include/draco/"),Q===nt&&Re("./include/ktx2/")}).finally(()=>{je()});function ke(t){$=t,B&&B[ye]!=$?(console.debug("Updating Draco decoder path to "+t),B[ye]=$,B.setDecoderPath($),B.preload()):console.debug("Setting Draco decoder path to "+t)}function Re(t){Q=t,G&&G.transcoderPath!=Q?(console.debug("Updating KTX2 transcoder path to "+t),G.setTranscoderPath(Q),G.init()):console.debug("Setting KTX2 transcoder path to "+t)}const ye=Symbol("dracoDecoderPath");let B,ce,G;function je(){B||(B=new st,B[ye]=$,B.setDecoderPath($),B.setDecoderConfig({type:"js"}),B.preload()),G||(G=new rt,G.setTranscoderPath(Q),G.init()),ce||(ce=tt)}function Le(t){return je(),t?G.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:B,ktx2Loader:G,meshoptDecoder:ce}}function De(t){t.dracoLoader||t.setDRACOLoader(B),t.ktx2Loader||t.setKTX2Loader(G),t.meshoptDecoder||t.setMeshoptDecoder(ce)}const Me=new WeakMap;function we(t,e){let s=Me.get(t);s?s=Object.assign(s,e):s=e,Me.set(t,s)}const Ge=xe.prototype.load;function it(...t){const e=Me.get(this);let s=t[0];const n=new URL(s,window.location.href);if(n.hostname.endsWith("needle.tools")){const r=e?.progressive!==void 0?e.progressive:!0,o=e!=null&&e.usecase?e.usecase:"default";r?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${o}`:this.requestHeader.Accept=`*/*;usecase=${o}`,s=n.toString()}return t[0]=s,Ge?.call(this,...t)}xe.prototype.load=it,re("debugprogressive");function re(t){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function at(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const s=t.lastIndexOf("/");if(s>=0){const n=t.substring(0,s+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let de;function lt(){return de!==void 0||(de=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),re("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",de)),de}const ut=typeof window>"u"&&typeof document>"u",_e=Symbol("needle:raycast-mesh");function Z(t){return t?.[_e]instanceof ue?t[_e]:null}function Ne(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!Z(t)){const s=ct(e);s.userData={isRaycastMesh:!0},t[_e]=s}}function $e(t=!0){if(t){if(oe)return;const e=oe=Y.prototype.raycast;Y.prototype.raycast=function(s,n){const r=this,o=Z(r);let i;o&&r.isMesh&&(i=r.geometry,r.geometry=o),e.call(this,s,n),i&&(r.geometry=i)}}else{if(!oe)return;Y.prototype.raycast=oe,oe=null}}let oe=null;function ct(t){const e=new ue;for(const s in t.attributes)e.setAttribute(s,t.getAttribute(s));return e.setIndex(t.getIndex()),e}const V=new Array,L=re("debugprogressive");let he,J=-1;if(L){let t=function(){J+=1,J>=e&&(J=-1),console.log(`Toggle LOD level [${J}]`)},e=6;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(he=!he,console.log(`Toggle wireframe [${he}]`));const n=parseInt(s.key);!isNaN(n)&&n>=0&&(J=n,console.log(`Set LOD level to [${J}]`))})}function We(t){if(L)if(Array.isArray(t))for(const e of t)We(e);else t&&"wireframe"in t&&(t.wireframe=he===!0)}const W="NEEDLE_progressive",be=Symbol("needle-progressive-texture"),w=class{constructor(t,e){d(this,"parser"),d(this,"url"),d(this,"_isLoadingMesh"),d(this,"loadMesh",s=>{var n,r;if(this._isLoadingMesh)return null;const o=(r=(n=this.parser.json.meshes[s])==null?void 0:n.extensions)==null?void 0:r[W];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",s).then(i=>{var l;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,o.guid,i,(l=o.lods)==null?void 0:l.length,0,o),i})):null}),L&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return W}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){var e;return((e=this.getAssignedLODInformation(t))==null?void 0:e.index)??-1}static getMaterialMinMaxLODsCount(t,e){const s=this,n="LODS:minmax",r=t[n];if(r!=null)return r;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[n]=e,e}if(L==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const l of Object.keys(i.uniforms)){const u=i.uniforms[l].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const l=t[i];l?.isTexture===!0&&o(l,e)}return t[n]=e,e;function o(i,l){const u=s.getAssignedLODInformation(i);if(u){const a=s.lodInfos.get(u.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let h=0;h<a.lods.length;h++){const x=a.lods[h];x.width&&(l.lods[h]=l.lods[h]||{min_height:1/0,max_height:0},l.lods[h].min_height=Math.min(l.lods[h].min_height,x.height),l.lods[h].max_height=Math.max(l.lods[h].max_height,x.height))}}}}}static hasLODLevelAvailable(t,e){var s;if(Array.isArray(t)){for(const o of t)if(this.hasLODLevelAvailable(o,e))return!0;return!1}if(t.isMaterial===!0){for(const o of Object.keys(t)){const i=t[o];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const o of t.children)if(o.isMesh===!0&&this.hasLODLevelAvailable(o,e))return!0}let n,r;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(s=n?.userData)!=null&&s.LODS){const o=n.userData.LODS;if(r=this.lodInfos.get(o.key),e===void 0)return r!=null;if(r)return Array.isArray(r.lods)?e<r.lods.length:e===0}return!1}static assignMeshLOD(t,e){var s;if(!t)return Promise.resolve(null);if(t instanceof Y||t.isMesh===!0){const n=t.geometry,r=this.getAssignedLODInformation(n);if(!r)return Promise.resolve(null);for(const o of V)(s=o.onBeforeGetLODMesh)==null||s.call(o,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(n,e).then(o=>{if(Array.isArray(o)){const i=r.index||0;o=o[i]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],o&&n!=o&&(o?.isBufferGeometry?t.geometry=o:L&&console.error("Invalid LOD geometry",o))),o}).catch(o=>(console.error("Error loading mesh LOD",t,o),null))}else L&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const s=t;if(Array.isArray(s.material)){const n=new Array;for(const r of s.material){const o=this.assignTextureLOD(r,e);n.push(o)}return Promise.all(n).then(r=>{const o=new Array;for(const i of r)Array.isArray(i)&&o.push(...i);return o})}else return this.assignTextureLOD(s.material,e)}if(t.isMaterial===!0){const s=t,n=[],r=new Array;if(s.uniforms&&(s.isRawShaderMaterial||s.isShaderMaterial===!0)){const o=s;for(const i of Object.keys(o.uniforms)){const l=o.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,s,i).then(a=>(a&&o.uniforms[i].value!=a&&(o.uniforms[i].value=a,o.uniformsNeedUpdate=!0),a));n.push(u),r.push(i)}}}else for(const o of Object.keys(s)){const i=s[o];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,s,o);n.push(l),r.push(o)}}return Promise.all(n).then(o=>{const i=new Array;for(let l=0;l<o.length;l++){const u=o[l],a=r[l];u&&u.isTexture===!0?i.push({material:s,slot:a,texture:u,level:e}):i.push({material:s,slot:a,texture:null,level:e})}return i})}if(t instanceof se||t.isTexture===!0){const s=t;return this.assignTextureLODForSlot(s,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,s,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if(r?.isTexture===!0){if(r!=t&&s&&n){const o=s[n];if(o&&!L){const i=this.getAssignedLODInformation(o);if(i&&i?.level<e)return L==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,s,o,r),null}s[n]=r}return r}else L=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(r=>(console.error("Error loading LOD",t,r),null))}afterRoot(t){var e,s;return L&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,r)=>{var o;if(n!=null&&n.extensions){const i=n?.extensions[W];if(i){if(!i.lods){L&&console.warn("Texture has no LODs",i);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const a=this.parser.associations.get(u);a?.textures===r&&(l=!0,w.registerTexture(this.url,u,(o=i.lods)==null?void 0:o.length,r,i))}l||this.parser.getDependency("texture",r).then(u=>{var a;u&&w.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,r,i)})}}}),(s=this.parser.json.meshes)==null||s.forEach((n,r)=>{if(n!=null&&n.extensions){const o=n?.extensions[W];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===r&&w.registerMesh(this.url,o.guid,i,o.lods.length,l.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var s,n,r,o;const i=L=="verbose",l=t.userData.LODS;if(!l)return null;const u=l?.key;let a;if(t.isTexture===!0){const h=t;h.source&&h.source[be]&&(a=h.source[be])}if(a||(a=w.lodInfos.get(u)),a){if(e>0){let m=!1;const M=Array.isArray(a.lods);if(M&&e>=a.lods.length?m=!0:M||(m=!0),m)return this.lowresCache.get(u)}const h=Array.isArray(a.lods)?(s=a.lods[e])==null?void 0:s.path:a.lods;if(!h)return L&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const x=at(l.url,h);if(x.endsWith(".glb")||x.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const m=x+"_"+a.guid,M=this.previouslyLoaded.get(m);if(M!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${m}`);let y=await M.catch(f=>(console.error(`Error loading LOD ${e} from ${x}
|
|
2
|
-
`,f),null)),p=!1;if(
|
|
3
|
-
`,
|
|
1
|
+
var Ye=Object.defineProperty,Je=(t,e,r)=>e in t?Ye(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,d=(t,e,r)=>(Je(t,typeof e!="symbol"?e+"":e,r),r),Ee=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},v=(t,e,r)=>(Ee(t,e,"read from private field"),r?r.call(t):e.get(t)),Y=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},U=(t,e,r,o)=>(Ee(t,e,"write to private field"),o?o.call(t,r):e.set(t,r),r);import{BufferGeometry as ue,Mesh as J,Texture as re,TextureLoader as Qe,Matrix4 as Ce,Clock as Ze,MeshStandardMaterial as et,Sphere as tt,Box3 as Ie,Vector3 as z}from"three";import{GLTFLoader as xe}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as rt}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as st}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as ot}from"three/examples/jsm/loaders/KTX2Loader.js";const Be="";globalThis.GLTF_PROGRESSIVE_VERSION=Be,console.debug("[gltf-progressive] version -");let $="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",Z="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const nt=$,it=Z,ke=new URL($+"draco_decoder.js");ke.searchParams.append("range","true"),fetch(ke,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(t=>{console.debug(`Failed to fetch remote Draco decoder from ${$} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),$===nt&&Ge("./include/draco/"),Z===it&&Re("./include/ktx2/")}).finally(()=>{je()});function Ge(t){$=t,B&&B[Le]!=$?(console.debug("Updating Draco decoder path to "+t),B[Le]=$,B.setDecoderPath($),B.preload()):console.debug("Setting Draco decoder path to "+t)}function Re(t){Z=t,j&&j.transcoderPath!=Z?(console.debug("Updating KTX2 transcoder path to "+t),j.setTranscoderPath(Z),j.init()):console.debug("Setting KTX2 transcoder path to "+t)}const Le=Symbol("dracoDecoderPath");let B,de,j;function je(){B||(B=new st,B[Le]=$,B.setDecoderPath($),B.setDecoderConfig({type:"js"}),B.preload()),j||(j=new ot,j.setTranscoderPath(Z),j.init()),de||(de=rt)}function we(t){return je(),t?j.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:B,ktx2Loader:j,meshoptDecoder:de}}function _e(t){t.dracoLoader||t.setDRACOLoader(B),t.ktx2Loader||t.setKTX2Loader(j),t.meshoptDecoder||t.setMeshoptDecoder(de)}const Me=new WeakMap;function De(t,e){let r=Me.get(t);r?r=Object.assign(r,e):r=e,Me.set(t,r)}const Ne=xe.prototype.load;function at(...t){const e=Me.get(this);let r=t[0];const o=new URL(r,window.location.href);if(o.hostname.endsWith("needle.tools")){const s=e?.progressive!==void 0?e.progressive:!0,n=e!=null&&e.usecase?e.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${n}`:this.requestHeader.Accept=`*/*;usecase=${n}`,r=o.toString()}return t[0]=r,Ne?.call(this,...t)}xe.prototype.load=at,se("debugprogressive");function se(t){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function lt(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const 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 ce;function ut(){return ce!==void 0||(ce=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),se("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ce)),ce}function dt(){if(typeof window>"u")return!1;const t=new URL(window.location.href),e=t.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(t.hostname);return t.hostname==="127.0.0.1"||e}const ct=typeof window>"u"&&typeof document>"u",be=Symbol("needle:raycast-mesh");function ee(t){return t?.[be]instanceof ue?t[be]:null}function $e(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!ee(t)){const r=ht(e);r.userData={isRaycastMesh:!0},t[be]=r}}function We(t=!0){if(t){if(oe)return;const e=oe=J.prototype.raycast;J.prototype.raycast=function(r,o){const s=this,n=ee(s);let i;n&&s.isMesh&&(i=s.geometry,s.geometry=n),e.call(this,r,o),i&&(s.geometry=i)}}else{if(!oe)return;J.prototype.raycast=oe,oe=null}}let oe=null;function ht(t){const e=new ue;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const V=new Array,L=se("debugprogressive");let he,Q=-1;if(L){let t=function(){Q+=1,Q>=e&&(Q=-1),console.log(`Toggle LOD level [${Q}]`)},e=6;window.addEventListener("keyup",r=>{r.key==="p"&&t(),r.key==="w"&&(he=!he,console.log(`Toggle wireframe [${he}]`));const o=parseInt(r.key);!isNaN(o)&&o>=0&&(Q=o,console.log(`Set LOD level to [${Q}]`))})}function Fe(t){if(L)if(Array.isArray(t))for(const e of t)Fe(e);else t&&"wireframe"in t&&(t.wireframe=he===!0)}const W="NEEDLE_progressive",Oe=Symbol("needle-progressive-texture"),M=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[W];return n?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var l;return this._isLoadingMesh=!1,i&&M.registerMesh(this.url,n.guid,i,(l=n.lods)==null?void 0:l.length,0,n),i})):null}),L&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return W}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){var e;return((e=this.getAssignedLODInformation(t))==null?void 0:e.index)??-1}static getMaterialMinMaxLODsCount(t,e){const r=this,o="LODS:minmax",s=t[o];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[o]=e,e}if(L==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const l of Object.keys(i.uniforms)){const u=i.uniforms[l].value;u?.isTexture===!0&&n(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const l=t[i];l?.isTexture===!0&&n(l,e)}return t[o]=e,e;function n(i,l){const u=r.getAssignedLODInformation(i);if(u){const a=r.lodInfos.get(u.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let h=0;h<a.lods.length;h++){const y=a.lods[h];y.width&&(l.lods[h]=l.lods[h]||{min_height:1/0,max_height:0},l.lods[h].min_height=Math.min(l.lods[h].min_height,y.height),l.lods[h].max_height=Math.max(l.lods[h].max_height,y.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 J||t.isMesh===!0){const o=t.geometry,s=this.getAssignedLODInformation(o);if(!s)return Promise.resolve(null);for(const n of V)(r=n.onBeforeGetLODMesh)==null||r.call(n,t,e);return t["LOD:requested level"]=e,M.getOrLoadLOD(o,e).then(n=>{if(Array.isArray(n)){const i=s.index||0;n=n[i]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],n&&o!=n&&(n?.isBufferGeometry?t.geometry=n:L&&console.error("Invalid LOD geometry",n))),n}).catch(n=>(console.error("Error loading mesh LOD",t,n),null))}else L&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const o=new Array;for(const s of r.material){const n=this.assignTextureLOD(s,e);o.push(n)}return Promise.all(o).then(s=>{const n=new Array;for(const i of s)Array.isArray(i)&&n.push(...i);return n})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,o=[],s=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const n=r;for(const i of Object.keys(n.uniforms)){const l=n.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,r,i).then(a=>(a&&n.uniforms[i].value!=a&&(n.uniforms[i].value=a,n.uniformsNeedUpdate=!0),a));o.push(u),s.push(i)}}}else for(const n of Object.keys(r)){const i=r[n];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,r,n);o.push(l),s.push(n)}}return Promise.all(o).then(n=>{const i=new Array;for(let l=0;l<n.length;l++){const u=n[l],a=s[l];u&&u.isTexture===!0?i.push({material:r,slot:a,texture:u,level:e}):i.push({material:r,slot:a,texture:null,level:e})}return i})}if(t instanceof re||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):M.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t&&r&&o){const n=r[o];if(n&&!L){const i=this.getAssignedLODInformation(n);if(i&&i?.level<e)return L==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,n,s),null}r[o]=s}return s}else L=="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 L&&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[W];if(i){if(!i.lods){L&&console.warn("Texture has no LODs",i);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const a=this.parser.associations.get(u);a?.textures===s&&(l=!0,M.registerTexture(this.url,u,(n=i.lods)==null?void 0:n.length,s,i))}l||this.parser.getDependency("texture",s).then(u=>{var a;u&&M.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((o,s)=>{if(o!=null&&o.extensions){const n=o?.extensions[W];if(n&&n.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===s&&M.registerMesh(this.url,n.guid,i,n.lods.length,l.primitives,n)}}}}),null}static async getOrLoadLOD(t,e){var r,o,s,n;const i=L=="verbose",l=t.userData.LODS;if(!l)return null;const u=l?.key;let a;if(t.isTexture===!0){const h=t;h.source&&h.source[Oe]&&(a=h.source[Oe])}if(a||(a=M.lodInfos.get(u)),a){if(e>0){let m=!1;const _=Array.isArray(a.lods);if(_&&e>=a.lods.length?m=!0:_||(m=!0),m)return this.lowresCache.get(u)}const h=Array.isArray(a.lods)?(r=a.lods[e])==null?void 0:r.path:a.lods;if(!h)return L&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const y=lt(l.url,h);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const m=y+"_"+a.guid,_=this.previouslyLoaded.get(m);if(_!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${m}`);let x=await _.catch(f=>(console.error(`Error loading LOD ${e} from ${y}
|
|
2
|
+
`,f),null)),p=!1;if(x==null||(x instanceof re&&t instanceof re?(o=x.image)!=null&&o.data||(s=x.source)!=null&&s.data?x=this.copySettings(t,x):(p=!0,this.previouslyLoaded.delete(m)):x instanceof ue&&t instanceof ue&&((n=x.attributes.position)!=null&&n.array||(p=!0,this.previouslyLoaded.delete(m)))),!p)return x}const b=a,G=new Promise(async(x,p)=>{const f=new xe;_e(f),L&&(await new Promise(w=>setTimeout(w,1e3)),i&&console.warn("Start loading (delayed) "+y,b.guid));let F=y;if(b&&Array.isArray(b.lods)){const w=b.lods[e];w.hash&&(F+="?v="+w.hash)}const D=await f.loadAsync(F).catch(w=>(console.error(`Error loading LOD ${e} from ${y}
|
|
3
|
+
`,w),null));if(!D)return null;const R=D.parser;i&&console.log("Loading finished "+y,b.guid);let O=0;if(D.parser.json.textures){let w=!1;for(const c of D.parser.json.textures){if(c!=null&&c.extensions){const g=c?.extensions[W];if(g!=null&&g.guid&&g.guid===b.guid){w=!0;break}}O++}if(w){let c=await R.getDependency("texture",O);return c&&M.assignLODInformation(l.url,c,u,e,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+c.name+'"',y,O,c,m),t instanceof re&&(c=this.copySettings(t,c)),c&&(c.guid=b.guid),x(c)}else L&&console.warn("Could not find texture with guid",b.guid,D.parser.json)}if(O=0,D.parser.json.meshes){let w=!1;for(const c of D.parser.json.meshes){if(c!=null&&c.extensions){const g=c?.extensions[W];if(g!=null&&g.guid&&g.guid===b.guid){w=!0;break}}O++}if(w){const c=await R.getDependency("mesh",O);if(i&&console.log(`Loaded Mesh "${c.name}"`,y,O,c,m),c.isMesh===!0){const g=c.geometry;return M.assignLODInformation(l.url,g,u,e,0),x(g)}else{const g=new Array;for(let S=0;S<c.children.length;S++){const C=c.children[S];if(C.isMesh===!0){const I=C.geometry;M.assignLODInformation(l.url,I,u,e,S),g.push(I)}}return x(g)}}else L&&console.warn("Could not find mesh with guid",b.guid,D.parser.json)}return x(null)});return this.previouslyLoaded.set(m,G),await G}else if(t instanceof re){i&&console.log("Load texture from uri: "+y);const m=await new Qe().loadAsync(y);return m?(m.guid=a.guid,m.flipY=!1,m.needsUpdate=!0,m.colorSpace=t.colorSpace,i&&console.log(a,m)):L&&console.warn("failed loading",y),m}}else L&&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){if(!e)return;e.userData||(e.userData={});const n=new gt(t,r,o,s);e.userData.LODS=n}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e?(L&&console.warn(`Copy texture settings
|
|
4
4
|
`,t.uuid,`
|
|
5
|
-
`,e.uuid),e=e.clone(),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e):t}};let T=w;d(T,"registerTexture",(t,e,s,n,r)=>{if(L&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,r),!e){L&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[be]=r);const o=r.guid;w.assignLODInformation(t,e,o,s,n),w.lodInfos.set(o,r),w.lowresCache.set(o,e)}),d(T,"registerMesh",(t,e,s,n,r,o)=>{var i;const l=s.geometry;if(!l){L&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),L&&console.log("> Progressive: register mesh "+s.name,{index:r,uuid:s.uuid},o,s),w.assignLODInformation(t,l,e,n,r),w.lodInfos.set(e,o);let u=w.lowresCache.get(e);u?u.push(s.geometry):u=[s.geometry],w.lowresCache.set(e,u),n>0&&!Z(s)&&Ne(s,l);for(const a of V)(i=a.onRegisteredNewMesh)==null||i.call(a,s,o)}),d(T,"lodInfos",new Map),d(T,"previouslyLoaded",new Map),d(T,"lowresCache",new Map);class dt{constructor(e,s,n,r){d(this,"url"),d(this,"key"),d(this,"level"),d(this,"index"),this.url=e,this.key=s,this.level=n,r!=null&&(this.index=r)}}const N=re("debugprogressive"),ht=re("noprogressive"),Oe=Symbol("Needle:LODSManager"),Se=Symbol("Needle:LODState"),q=Symbol("Needle:CurrentLOD"),A={mesh_lod:-1,texture_lod:-1};var E,X,Te,ee,ne,ge,K;const P=class{constructor(t,e){d(this,"context"),d(this,"renderer"),d(this,"projectionScreenMatrix",new Pe),d(this,"targetTriangleDensity",2e5),d(this,"skinnedMeshAutoUpdateBoundsInterval",30),d(this,"updateInterval","auto"),H(this,E,1),d(this,"pause",!1),d(this,"manual",!1),d(this,"_lodchangedlisteners",[]),H(this,X,void 0),H(this,Te,new Qe),H(this,ee,0),H(this,ne,0),H(this,ge,0),H(this,K,0),d(this,"_fpsBuffer",[60,60,60,60,60]),d(this,"_sphere",new et),d(this,"_tempBox",new Ie),d(this,"_tempBox2",new Ie),d(this,"tempMatrix",new Pe),d(this,"_tempWorldPosition",new z),d(this,"_tempBoxSize",new z),d(this,"_tempBox2Size",new z),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Se]}static addPlugin(t){V.push(t)}static removePlugin(t){const e=V.indexOf(t);e>=0&&V.splice(e,1)}static get(t,e){if(t[Oe])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[Oe];const s=new P(t,{engine:"unknown",...e});return t[Oe]=s,s}get plugins(){return V}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const s=this._lodchangedlisteners.indexOf(e);s>=0&&this._lodchangedlisteners.splice(s,1)}}enable(){if(v(this,X))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;F(this,X,this.renderer.render);const e=this;Le(this.renderer),this.renderer.render=function(s,n){const r=e.renderer.getRenderTarget();(r==null||"isXRRenderTarget"in r&&r.isXRRenderTarget)&&(t=0,F(e,ee,v(e,ee)+1),F(e,ne,v(e,Te).getDelta()),F(e,ge,v(e,ge)+v(e,ne)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/v(e,ne)),F(e,K,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),N&&v(e,ee)%200===0&&console.log("FPS",Math.round(v(e,K)),"Interval:",v(e,E)));const o=t++;v(e,X).call(this,s,n),e.onAfterRender(s,n,o)}}disable(){v(this,X)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=v(this,X),F(this,X,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,s){if(this.pause)return;const n=this.renderer.renderLists.get(t,0).opaque;let r=!0;if(n.length===1){const o=n[0].material;(o.name==="EffectMaterial"||o.name==="CopyShader")&&(r=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(r=!1),r){if(ht||(this.updateInterval==="auto"?v(this,K)<40&&v(this,E)<10?(F(this,E,v(this,E)+1),N&&console.warn("\u2193 Reducing LOD updates",v(this,E),v(this,K).toFixed(0))):v(this,K)>=60&&v(this,E)>1&&(F(this,E,v(this,E)-1),N&&console.warn("\u2191 Increasing LOD updates",v(this,E),v(this,K).toFixed(0))):F(this,E,this.updateInterval),v(this,E)>0&&v(this,ee)%v(this,E)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var s,n;const r=this.renderer.renderLists.get(t,0),o=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const a of o){if(a.material&&(((s=a.geometry)==null?void 0:s.type)==="BoxGeometry"||((n=a.geometry)==null?void 0:n.type)==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){N&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(N==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const x=Math.random()*16777215,m=new Ze({color:x});a.object.material=m}const h=a.object;(h instanceof Y||h.isMesh)&&this.updateLODs(t,e,h,i)}const l=r.transparent;for(const a of l){const h=a.object;(h instanceof Y||h.isMesh)&&this.updateLODs(t,e,h,i)}const u=r.transmissive;for(const a of u){const h=a.object;(h instanceof Y||h.isMesh)&&this.updateLODs(t,e,h,i)}}updateLODs(t,e,s,n){var r,o;s.userData||(s.userData={});let i=s[Se];if(i||(i=new gt,s[Se]=i),i.frames++<2)return;for(const u of V)(r=u.onBeforeUpdateLOD)==null||r.call(u,this.renderer,t,e,s);const l=P.overrideGlobalLodLevel!==void 0?P.overrideGlobalLodLevel:J;l>=0?(A.mesh_lod=l,A.texture_lod=l):(this.calculateLodLevel(e,s,i,n,A),A.mesh_lod=Math.round(A.mesh_lod),A.texture_lod=Math.round(A.texture_lod)),A.mesh_lod>=0&&this.loadProgressiveMeshes(s,A.mesh_lod),s.material&&A.texture_lod>=0&&this.loadProgressiveTextures(s.material,A.texture_lod),L&&s.material&&!s.isGizmo&&We(s.material);for(const u of V)(o=u.onAfterUpdatedLOD)==null||o.call(u,this.renderer,t,e,s,A);i.lastLodLevel_Mesh=A.mesh_lod,i.lastLodLevel_Texture=A.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const r of t)this.loadProgressiveTextures(r,e);return}let s=!1;(t[q]===void 0||e<t[q])&&(s=!0);const n=t["DEBUG:LOD"];n!=null&&(s=t[q]!=n,e=n),s&&(t[q]=e,T.assignTextureLOD(t,e).then(r=>{this._lodchangedlisteners.forEach(o=>o({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let s=t[q]!==e;const n=t["DEBUG:LOD"];if(n!=null&&(s=t[q]!=n,e=n),s){t[q]=e;const r=t.geometry;return T.assignMeshLOD(t,e).then(o=>(o&&t[q]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(i=>i({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const s=t.min,n=t.max,r=(s.x+n.x)*.5,o=(s.y+n.y)*.5;return this._tempPtInside.set(r,o,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,n,r){var o,i,l;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let u=10+1,a=!1;if(N&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const h=(o=T.getMeshLODExtension(e.geometry))==null?void 0:o.lods,x=T.getPrimitiveIndex(e.geometry),m=h&&h.length>0,M=T.getMaterialMinMaxLODsCount(e.material),b=M?.min_count!=1/0&&M.min_count>0&&M.max_count>0;if(!m&&!b){r.mesh_lod=0,r.texture_lod=0;return}m||(a=!0,u=0);const R=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let y=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const p=e;if(!p.boundingBox)p.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0&&s.frames%this.skinnedMeshAutoUpdateBoundsInterval===0){const f=Z(p),U=p.geometry;f&&(p.geometry=f),p.computeBoundingBox(),p.geometry=U}y=p.boundingBox}if(y){const p=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const c=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(c)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(y),this._tempBox.applyMatrix4(e.matrixWorld),p.isPerspectiveCamera&&P.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&p.isPerspectiveCamera&&p.fov>70){const c=this._tempBox.min,g=this._tempBox.max;let S=c.x,I=c.y,C=g.x,te=g.y;const ie=2,pe=1.5,ae=(c.x+g.x)*.5,le=(c.y+g.y)*.5;S=(S-ae)*ie+ae,I=(I-le)*ie+le,C=(C-ae)*ie+ae,te=(te-le)*ie+le;const Xe=S<0&&C>0?0:Math.min(Math.abs(c.x),Math.abs(g.x)),Ke=I<0&&te>0?0:Math.min(Math.abs(c.y),Math.abs(g.y)),ve=Math.max(Xe,Ke);s.lastCentrality=(pe-ve)*(pe-ve)*(pe-ve)}else s.lastCentrality=1;const f=this._tempBox.getSize(this._tempBoxSize);f.multiplyScalar(.5),screen.availHeight>0&&R>0&&f.multiplyScalar(R/screen.availHeight),t.isPerspectiveCamera?f.x*=t.aspect:t.isOrthographicCamera;const U=t.matrixWorldInverse,_=this._tempBox2;_.copy(y),_.applyMatrix4(e.matrixWorld),_.applyMatrix4(U);const j=_.getSize(this._tempBox2Size),O=Math.max(j.x,j.y);if(Math.max(f.x,f.y)!=0&&O!=0&&(f.z=j.z/Math.max(j.x,j.y)*Math.max(f.x,f.y)),s.lastScreenCoverage=Math.max(f.x,f.y,f.z),s.lastScreenspaceVolume.copy(f),s.lastScreenCoverage*=s.lastCentrality,N&&P.debugDrawLine){const c=this.tempMatrix.copy(this.projectionScreenMatrix);c.invert();const g=P.corner0,S=P.corner1,I=P.corner2,C=P.corner3;g.copy(this._tempBox.min),S.copy(this._tempBox.max),S.x=g.x,I.copy(this._tempBox.max),I.y=g.y,C.copy(this._tempBox.max);const te=(g.z+C.z)*.5;g.z=S.z=I.z=C.z=te,g.applyMatrix4(c),S.applyMatrix4(c),I.applyMatrix4(c),C.applyMatrix4(c),P.debugDrawLine(g,S,255),P.debugDrawLine(g,I,255),P.debugDrawLine(S,C,255),P.debugDrawLine(I,C,255)}let D=999;if(h&&s.lastScreenCoverage>0)for(let c=0;c<h.length;c++){const g=h[c];if((((i=g.densities)==null?void 0:i[x])||g.density||1e-5)/s.lastScreenCoverage<n){D=c;break}}D<u&&(u=D,a=!0)}if(a?r.mesh_lod=u:r.mesh_lod=s.lastLodLevel_Mesh,N&&r.mesh_lod!=s.lastLodLevel_Mesh){const p=h?.[r.mesh_lod];p&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} \u2192 ${r.mesh_lod} (${p.density.toFixed(0)}) - ${e.name}`)}if(b){const p="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(s.lastLodLevel_Texture<0){if(r.texture_lod=M.max_count-1,N){const f=M.lods[M.max_count-1];N&&console.log(`First Texture LOD ${r.texture_lod} (${f.max_height}px) - ${e.name}`)}}else{const f=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let U=s.lastScreenCoverage*4;((l=this.context)==null?void 0:l.engine)==="model-viewer"&&(U*=1.5);const _=R/window.devicePixelRatio*U;let j=!1;for(let O=M.lods.length-1;O>=0;O--){const D=M.lods[O];if(!(p&&D.max_height>=2048)&&!(lt()&&D.max_height>4096)&&(D.max_height>_||!j&&O===0)){if(j=!0,r.texture_lod=O,r.texture_lod<s.lastLodLevel_Texture){const c=D.max_height;N&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} \u2192 ${r.texture_lod} = ${c}px
|
|
6
|
-
Screensize: ${
|
|
7
|
-
${e.name}`)}break}}}}else
|
|
8
|
-
`,t.getAttribute("src"));let e=null,
|
|
5
|
+
`,e.uuid),e=e.clone(),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e):t}};let T=M;d(T,"registerTexture",(t,e,r,o,s)=>{if(L&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,s),!e){L&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Oe]=s);const n=s.guid;M.assignLODInformation(t,e,n,r,o),M.lodInfos.set(n,s),M.lowresCache.set(n,e)}),d(T,"registerMesh",(t,e,r,o,s,n)=>{var i;const l=r.geometry;if(!l){L&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),L&&console.log("> Progressive: register mesh "+r.name,{index:s,uuid:r.uuid},n,r),M.assignLODInformation(t,l,e,o,s),M.lodInfos.set(e,n);let u=M.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],M.lowresCache.set(e,u),o>0&&!ee(r)&&$e(r,l);for(const a of V)(i=a.onRegisteredNewMesh)==null||i.call(a,r,n)}),d(T,"lodInfos",new Map),d(T,"previouslyLoaded",new Map),d(T,"lowresCache",new Map);class gt{constructor(e,r,o,s){d(this,"url"),d(this,"key"),d(this,"level"),d(this,"index"),this.url=e,this.key=r,this.level=o,s!=null&&(this.index=s)}}class ge{constructor(e,r){d(this,"frame_start"),d(this,"frame_capture_end"),d(this,"ready"),d(this,"_resolve"),d(this,"_signal"),d(this,"_resolved",!1),d(this,"_addedCount",0),d(this,"_resolvedCount",0),d(this,"_awaiting",[]),d(this,"_currentFrame",0);var o;const s=e===0?2:1,n=Math.max(r.frames??s,s);this.frame_start=e,this.frame_capture_end=e+n,this.ready=new Promise(i=>{this._resolve=i}),this.ready.finally(()=>{this._resolved=!0,this._awaiting.length=0}),this._signal=r.signal,(o=this._signal)==null||o.addEventListener("abort",()=>{this.resolveNow()})}get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}update(e){var r;this._currentFrame=e,((r=this._signal)!=null&&r.aborted||this._currentFrame>this.frame_capture_end&&this._awaiting.length===0)&&this.resolveNow()}add(e,r){if(this._resolved){console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}this._currentFrame>this.frame_capture_end||(this._awaiting.push(r),this._addedCount++,r.finally(()=>{this._resolvedCount++,this._awaiting.splice(this._awaiting.indexOf(r),1)}))}resolveNow(){var e,r;this._resolved||(r=this._resolve)==null||r.call(this,{awaited_count:this._addedCount,resolved_count:this._resolvedCount,cancelled:((e=this._signal)==null?void 0:e.aborted)??!1})}}d(ge,"addPromise",(t,e,r)=>{r.forEach(o=>{o.add(t,e)})});const N=se("debugprogressive"),ft=se("noprogressive"),Se=Symbol("Needle:LODSManager"),Te=Symbol("Needle:LODState"),q=Symbol("Needle:CurrentLOD"),P={mesh_lod:-1,texture_lod:-1};var A,X,Pe,K,ne,fe,H;const E=class{constructor(t,e){d(this,"renderer"),d(this,"context"),d(this,"projectionScreenMatrix",new Ce),d(this,"targetTriangleDensity",2e5),d(this,"skinnedMeshAutoUpdateBoundsInterval",30),d(this,"updateInterval","auto"),Y(this,A,1),d(this,"pause",!1),d(this,"manual",!1),d(this,"_newPromiseGroups",[]),d(this,"_promiseGroupIds",0),d(this,"_lodchangedlisteners",[]),Y(this,X,void 0),Y(this,Pe,new Ze),Y(this,K,0),Y(this,ne,0),Y(this,fe,0),Y(this,H,0),d(this,"_fpsBuffer",[60,60,60,60,60]),d(this,"_sphere",new tt),d(this,"_tempBox",new Ie),d(this,"_tempBox2",new Ie),d(this,"tempMatrix",new Ce),d(this,"_tempWorldPosition",new z),d(this,"_tempBoxSize",new z),d(this,"_tempBox2Size",new z),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Te]}static addPlugin(t){V.push(t)}static removePlugin(t){const e=V.indexOf(t);e>=0&&V.splice(e,1)}static get(t,e){if(t[Se])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[Se];const r=new E(t,{engine:"unknown",...e});return t[Se]=r,r}get plugins(){return V}awaitLoading(t){const e=this._promiseGroupIds++,r=new ge(v(this,K),{...t});this._newPromiseGroups.push(r);const o=performance.now();return r.ready.finally(()=>{const s=this._newPromiseGroups.indexOf(r);s>=0&&(this._newPromiseGroups.splice(s,1),dt()&&performance.measure("LODsManager:awaitLoading",{start:o,detail:{id:e,name:t?.name,awaited:r.awaitedCount,resolved:r.resolvedCount}}))}),r.ready}_postprocessPromiseGroups(){if(this._newPromiseGroups.length!==0)for(let t=this._newPromiseGroups.length-1;t>=0;t--)this._newPromiseGroups[t].update(v(this,K))}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(v(this,X))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;U(this,X,this.renderer.render);const e=this;we(this.renderer),this.renderer.render=function(r,o){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,U(e,K,v(e,K)+1),U(e,ne,v(e,Pe).getDelta()),U(e,fe,v(e,fe)+v(e,ne)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/v(e,ne)),U(e,H,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),N&&v(e,K)%200===0&&console.log("FPS",Math.round(v(e,H)),"Interval:",v(e,A)));const n=t++;v(e,X).call(this,r,o),e.onAfterRender(r,o,n)}}disable(){v(this,X)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=v(this,X),U(this,X,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const o=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(o.length===1){const n=o[0].material;(n.name==="EffectMaterial"||n.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(ft||(this.updateInterval==="auto"?v(this,H)<40&&v(this,A)<10?(U(this,A,v(this,A)+1),N&&console.warn("\u2193 Reducing LOD updates",v(this,A),v(this,H).toFixed(0))):v(this,H)>=60&&v(this,A)>1&&(U(this,A,v(this,A)-1),N&&console.warn("\u2191 Increasing LOD updates",v(this,A),v(this,H).toFixed(0))):U(this,A,this.updateInterval),v(this,A)>0&&v(this,K)%v(this,A)!=0))return;this.internalUpdate(t,e),this._postprocessPromiseGroups()}}internalUpdate(t,e){var r,o;const s=this.renderer.renderLists.get(t,0),n=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const a of n){if(a.material&&(((r=a.geometry)==null?void 0:r.type)==="BoxGeometry"||((o=a.geometry)==null?void 0:o.type)==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){N&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(N==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const y=Math.random()*16777215,m=new et({color:y});a.object.material=m}const h=a.object;(h instanceof J||h.isMesh)&&this.updateLODs(t,e,h,i)}const l=s.transparent;for(const a of l){const h=a.object;(h instanceof J||h.isMesh)&&this.updateLODs(t,e,h,i)}const u=s.transmissive;for(const a of u){const h=a.object;(h instanceof J||h.isMesh)&&this.updateLODs(t,e,h,i)}}updateLODs(t,e,r,o){var s,n;r.userData||(r.userData={});let i=r[Te];if(i||(i=new mt,r[Te]=i),i.frames++<2)return;for(const u of V)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);const l=E.overrideGlobalLodLevel!==void 0?E.overrideGlobalLodLevel:Q;l>=0?(P.mesh_lod=l,P.texture_lod=l):(this.calculateLodLevel(e,r,i,o,P),P.mesh_lod=Math.round(P.mesh_lod),P.texture_lod=Math.round(P.texture_lod)),P.mesh_lod>=0&&this.loadProgressiveMeshes(r,P.mesh_lod),r.material&&P.texture_lod>=0&&this.loadProgressiveTextures(r.material,P.texture_lod),L&&r.material&&!r.isGizmo&&Fe(r.material);for(const u of V)(n=u.onAfterUpdatedLOD)==null||n.call(u,this.renderer,t,e,r,P);i.lastLodLevel_Mesh=P.mesh_lod,i.lastLodLevel_Texture=P.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const s of t)this.loadProgressiveTextures(s,e);return}let r=!1;(t[q]===void 0||e<t[q])&&(r=!0);const o=t["DEBUG:LOD"];if(o!=null&&(r=t[q]!=o,e=o),r){t[q]=e;const s=T.assignTextureLOD(t,e).then(n=>{this._lodchangedlisteners.forEach(i=>i({type:"texture",level:e,object:t}))});ge.addPromise("texture",s,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[q]!==e;const o=t["DEBUG:LOD"];if(o!=null&&(r=t[q]!=o,e=o),r){t[q]=e;const s=t.geometry,n=T.assignMeshLOD(t,e).then(i=>(i&&t[q]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(l=>l({type:"mesh",level:e,object:t})),i));return ge.addPromise("mesh",n,this._newPromiseGroups),n}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,i,l;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let u=10+1,a=!1;if(N&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const h=(n=T.getMeshLODExtension(e.geometry))==null?void 0:n.lods,y=T.getPrimitiveIndex(e.geometry),m=h&&h.length>0,_=T.getMaterialMinMaxLODsCount(e.material),b=_?.min_count!=1/0&&_.min_count>0&&_.max_count>0;if(!m&&!b){s.mesh_lod=0,s.texture_lod=0;return}m||(a=!0,u=0);const G=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let x=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const p=e;if(!p.boundingBox)p.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0&&r.frames%this.skinnedMeshAutoUpdateBoundsInterval===0){const f=ee(p),F=p.geometry;f&&(p.geometry=f),p.computeBoundingBox(),p.geometry=F}x=p.boundingBox}if(x){const p=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const c=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(c)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(x),this._tempBox.applyMatrix4(e.matrixWorld),p.isPerspectiveCamera&&E.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&p.isPerspectiveCamera&&p.fov>70){const c=this._tempBox.min,g=this._tempBox.max;let S=c.x,C=c.y,I=g.x,te=g.y;const ie=2,ve=1.5,ae=(c.x+g.x)*.5,le=(c.y+g.y)*.5;S=(S-ae)*ie+ae,C=(C-le)*ie+le,I=(I-ae)*ie+ae,te=(te-le)*ie+le;const Ke=S<0&&I>0?0:Math.min(Math.abs(c.x),Math.abs(g.x)),He=C<0&&te>0?0:Math.min(Math.abs(c.y),Math.abs(g.y)),ye=Math.max(Ke,He);r.lastCentrality=(ve-ye)*(ve-ye)*(ve-ye)}else r.lastCentrality=1;const f=this._tempBox.getSize(this._tempBoxSize);f.multiplyScalar(.5),screen.availHeight>0&&G>0&&f.multiplyScalar(G/screen.availHeight),t.isPerspectiveCamera?f.x*=t.aspect:t.isOrthographicCamera;const F=t.matrixWorldInverse,D=this._tempBox2;D.copy(x),D.applyMatrix4(e.matrixWorld),D.applyMatrix4(F);const R=D.getSize(this._tempBox2Size),O=Math.max(R.x,R.y);if(Math.max(f.x,f.y)!=0&&O!=0&&(f.z=R.z/Math.max(R.x,R.y)*Math.max(f.x,f.y)),r.lastScreenCoverage=Math.max(f.x,f.y,f.z),r.lastScreenspaceVolume.copy(f),r.lastScreenCoverage*=r.lastCentrality,N&&E.debugDrawLine){const c=this.tempMatrix.copy(this.projectionScreenMatrix);c.invert();const g=E.corner0,S=E.corner1,C=E.corner2,I=E.corner3;g.copy(this._tempBox.min),S.copy(this._tempBox.max),S.x=g.x,C.copy(this._tempBox.max),C.y=g.y,I.copy(this._tempBox.max);const te=(g.z+I.z)*.5;g.z=S.z=C.z=I.z=te,g.applyMatrix4(c),S.applyMatrix4(c),C.applyMatrix4(c),I.applyMatrix4(c),E.debugDrawLine(g,S,255),E.debugDrawLine(g,C,255),E.debugDrawLine(S,I,255),E.debugDrawLine(C,I,255)}let w=999;if(h&&r.lastScreenCoverage>0)for(let c=0;c<h.length;c++){const g=h[c];if((((i=g.densities)==null?void 0:i[y])||g.density||1e-5)/r.lastScreenCoverage<o){w=c;break}}w<u&&(u=w,a=!0)}if(a?s.mesh_lod=u:s.mesh_lod=r.lastLodLevel_Mesh,N&&s.mesh_lod!=r.lastLodLevel_Mesh){const p=h?.[s.mesh_lod];p&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${p.density.toFixed(0)}) - ${e.name}`)}if(b){const p="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=_.max_count-1,N){const f=_.lods[_.max_count-1];N&&console.log(`First Texture LOD ${s.texture_lod} (${f.max_height}px) - ${e.name}`)}}else{const f=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let F=r.lastScreenCoverage*4;((l=this.context)==null?void 0:l.engine)==="model-viewer"&&(F*=1.5);const D=G/window.devicePixelRatio*F;let R=!1;for(let O=_.lods.length-1;O>=0;O--){const w=_.lods[O];if(!(p&&w.max_height>=2048)&&!(ut()&&w.max_height>4096)&&(w.max_height>D||!R&&O===0)){if(R=!0,s.texture_lod=O,s.texture_lod<r.lastLodLevel_Texture){const c=w.max_height;N&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${c}px
|
|
6
|
+
Screensize: ${D.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${f.toFixed(1)}
|
|
7
|
+
${e.name}`)}break}}}}else s.texture_lod=0}};let k=E;A=new WeakMap,X=new WeakMap,Pe=new WeakMap,K=new WeakMap,ne=new WeakMap,fe=new WeakMap,H=new WeakMap,d(k,"debugDrawLine"),d(k,"overrideGlobalLodLevel"),d(k,"corner0",new z),d(k,"corner1",new z),d(k,"corner2",new z),d(k,"corner3",new z),d(k,"_tempPtInside",new z);class mt{constructor(){d(this,"frames",0),d(this,"lastLodLevel_Mesh",-1),d(this,"lastLodLevel_Texture",-1),d(this,"lastScreenCoverage",0),d(this,"lastScreenspaceVolume",new z),d(this,"lastCentrality",0)}}const Ue=Symbol("NEEDLE_mesh_lod"),me=Symbol("NEEDLE_texture_lod");let pe=null;function Ae(){const t=pt();t&&(t.mapURLs(function(e){return ze(),e}),ze(),pe?.disconnect(),pe=new MutationObserver(e=>{e.forEach(r=>{r.addedNodes.forEach(o=>{o instanceof HTMLElement&&o.tagName.toLowerCase()==="model-viewer"&&qe(o)})})}),pe.observe(document,{childList:!0,subtree:!0}))}function pt(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Ae()}),null)}function ze(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(t=>{qe(t)})}const Ve=new WeakSet;let vt=0;function qe(t){if(!t||Ve.has(t))return null;Ve.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++vt+`
|
|
8
|
+
`,t.getAttribute("src"));let e=null,r=null,o=null;for(let s=t;s!=null;s=Object.getPrototypeOf(s)){const n=Object.getOwnPropertySymbols(s),i=n.find(a=>a.toString()=="Symbol(renderer)"),l=n.find(a=>a.toString()=="Symbol(scene)"),u=n.find(a=>a.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&l!=null&&(r=t[l]),!o&&u!=null&&(o=t[u])}if(e&&r){let s=function(){if(o){let i=0,l=setInterval(()=>{if(i++>5){clearInterval(l);return}o?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const n=k.get(e,{engine:"model-viewer"});return k.addPlugin(new yt),n.enable(),n.addEventListener("changed",()=>{o?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&o?.call(t)}),t.addEventListener("load",()=>{s()}),()=>{n.disable()}}return null}class yt{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,r,o,s){this.tryParseMeshLOD(r,s),this.tryParseTextureLOD(r,s)}getUrl(e){if(!e)return null;let r=e.getAttribute("src");return r||(r=e.src),r||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),r}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,r){if(r[me]==!0)return;r[me]=!0;const o=this.tryGetCurrentGLTF(e),s=this.tryGetCurrentModelViewer(e),n=this.getUrl(s);if(n&&o&&r.material){let i=function(u){var a,h,y;if(u[me]==!0)return;u[me]=!0,u.userData&&(u.userData.LOD=-1);const m=Object.keys(u);for(let _=0;_<m.length;_++){const b=m[_],G=u[b];if(G?.isTexture===!0){const x=(h=(a=G.userData)==null?void 0:a.associations)==null?void 0:h.textures;if(x==null)continue;const p=o.parser.json.textures[x];if(!p){console.warn("Texture data not found for texture index "+x);continue}if((y=p?.extensions)!=null&&y[W]){const f=p.extensions[W];f&&n&&T.registerTexture(n,G,f.lods.length,x,f)}}}};const l=r.material;if(Array.isArray(l))for(const u of l)i(u);else i(l)}}tryParseMeshLOD(e,r){var o,s;if(r[Ue]==!0)return;r[Ue]=!0;const n=this.tryGetCurrentModelViewer(e),i=this.getUrl(n);if(!i)return;const l=(s=(o=r.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[W];if(l&&i){const u=r.uuid;T.registerMesh(i,u,r,0,l.lods.length,l)}}}function Xe(t,e,r,o){we(e),_e(r),De(r,{progressive:!0,...o?.hints}),r.register(n=>new T(n,t));const s=k.get(e);return o?.enableLODsManager!==!1&&s.enable(),s}if(Ae(),!ct){const t={gltfProgressive:{useNeedleProgressive:Xe,LODsManager:k,configureLoader:De,getRaycastMesh:ee,useRaycastMeshes:We}};if(!globalThis.Needle)globalThis.Needle=t;else for(const e in t)globalThis.Needle[e]=t[e]}export{W as EXTENSION_NAME,k as LODsManager,T as NEEDLE_progressive,Be as VERSION,_e as addDracoAndKTX2Loaders,De as configureLoader,we as createLoaders,ee as getRaycastMesh,Ae as patchModelViewer,$e as registerRaycastMesh,Ge as setDracoDecoderLocation,Re as setKTX2TranscoderLocation,Xe as useNeedleProgressive,We as useRaycastMeshes};
|
package/gltf-progressive.umd.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"use strict";var Ye=Object.defineProperty;var He=(n,t,e)=>t in n?Ye(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var d=(n,t,e)=>(He(n,typeof t!="symbol"?t+"":t,e),e),Ce=(n,t,e)=>{if(!t.has(n))throw TypeError("Cannot "+e)};var L=(n,t,e)=>(Ce(n,t,"read from private field"),e?e.call(n):t.get(n)),J=(n,t,e)=>{if(t.has(n))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(n):t.set(n,e)},W=(n,t,e,r)=>(Ce(n,t,"write to private field"),r?r.call(n,e):t.set(n,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),Se=require("three/examples/jsm/loaders/GLTFLoader.js"),je=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Je=require("three/examples/jsm/loaders/DRACOLoader.js"),Qe=require("three/examples/jsm/loaders/KTX2Loader.js"),Ge="";globalThis.GLTF_PROGRESSIVE_VERSION=Ge;console.debug("[gltf-progressive] version -");let X="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",te="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ze=X,et=te,ke=new URL(X+"draco_decoder.js");ke.searchParams.append("range","true");fetch(ke,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(n=>{console.debug(`Failed to fetch remote Draco decoder from ${X} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),X===Ze&&$e("./include/draco/"),te===et&&Fe("./include/ktx2/")}).finally(()=>{Ne()});function $e(n){X=n,G&&G[_e]!=X?(console.debug("Updating Draco decoder path to "+n),G[_e]=X,G.setDecoderPath(X),G.preload()):console.debug("Setting Draco decoder path to "+n)}function Fe(n){te=n,U&&U.transcoderPath!=te?(console.debug("Updating KTX2 transcoder path to "+n),U.setTranscoderPath(te),U.init()):console.debug("Setting KTX2 transcoder path to "+n)}const _e=Symbol("dracoDecoderPath");let G,pe,U;function Ne(){G||(G=new Je.DRACOLoader,G[_e]=X,G.setDecoderPath(X),G.setDecoderConfig({type:"js"}),G.preload()),U||(U=new Qe.KTX2Loader,U.setTranscoderPath(te),U.init()),pe||(pe=je.MeshoptDecoder)}function Te(n){return Ne(),n?U.detectSupport(n):n!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:G,ktx2Loader:U,meshoptDecoder:pe}}function Ae(n){n.dracoLoader||n.setDRACOLoader(G),n.ktx2Loader||n.setKTX2Loader(U),n.meshoptDecoder||n.setMeshoptDecoder(pe)}const Oe=new WeakMap;function Pe(n,t){let e=Oe.get(n);e?e=Object.assign(e,t):e=t,Oe.set(n,e)}const Me=Se.GLTFLoader.prototype.load;function tt(...n){const t=Oe.get(this);let e=n[0];const r=new URL(e,window.location.href);if(r.hostname.endsWith("needle.tools")){const o=(t==null?void 0:t.progressive)!==void 0?t.progressive:!0,s=t!=null&&t.usecase?t.usecase:"default";o?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${s}`:this.requestHeader.Accept=`*/*;usecase=${s}`,e=r.toString()}return n[0]=e,Me==null?void 0:Me.call(this,...n)}Se.GLTFLoader.prototype.load=tt;ce("debugprogressive");function ce(n){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(n);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function rt(n,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||n===void 0)return t;const e=n.lastIndexOf("/");if(e>=0){const r=n.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let ne;function st(){return ne!==void 0||(ne=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ce("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ne)),ne}const ot=typeof window>"u"&&typeof document>"u",be=Symbol("needle:raycast-mesh");function oe(n){return(n==null?void 0:n[be])instanceof p.BufferGeometry?n[be]:null}function Ue(n,t){if((n.type==="Mesh"||n.type==="SkinnedMesh")&&!oe(n)){const r=it(t);r.userData={isRaycastMesh:!0},n[be]=r}}function Ve(n=!0){if(n){if(ae)return;const t=ae=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,r){const i=this,o=oe(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),t.call(this,e,r),s&&(i.geometry=s)}}else{if(!ae)return;p.Mesh.prototype.raycast=ae,ae=null}}let ae=null;function it(n){const t=new p.BufferGeometry;for(const e in n.attributes)t.setAttribute(e,n.getAttribute(e));return t.setIndex(n.getIndex()),t}const Z=new Array,x=ce("debugprogressive");let ge,ee=-1;if(x){let n=function(){ee+=1,ee>=t&&(ee=-1),console.log(`Toggle LOD level [${ee}]`)},t=6;window.addEventListener("keyup",e=>{e.key==="p"&&n(),e.key==="w"&&(ge=!ge,console.log(`Toggle wireframe [${ge}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(ee=r,console.log(`Set LOD level to [${ee}]`))})}function ze(n){if(x)if(Array.isArray(n))for(const t of n)ze(t);else n&&"wireframe"in n&&(n.wireframe=ge===!0)}const q="NEEDLE_progressive",De=Symbol("needle-progressive-texture"),S=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var r,i;if(this._isLoadingMesh)return null;const e=(i=(r=this.parser.json.meshes[t])==null?void 0:r.extensions)==null?void 0:i[q];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(o=>{var s;return this._isLoadingMesh=!1,o&&S.registerMesh(this.url,e.guid,o,(s=e.lods)==null?void 0:s.length,0,e),o})):null});x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return q}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){var r;const e=(r=this.getAssignedLODInformation(t))==null?void 0:r.index;return e??-1}static getMaterialMinMaxLODsCount(t,e){const r=this,i="LODS:minmax",o=t[i];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[i]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const l of Object.keys(a.uniforms)){const u=a.uniforms[l].value;(u==null?void 0:u.isTexture)===!0&&s(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const l=t[a];(l==null?void 0:l.isTexture)===!0&&s(l,e)}return t[i]=e,e;function s(a,l){const u=r.getAssignedLODInformation(a);if(u){const c=r.lodInfos.get(u.key);if(c&&c.lods){l.min_count=Math.min(l.min_count,c.lods.length),l.max_count=Math.max(l.max_count,c.lods.length);for(let h=0;h<c.lods.length;h++){const g=c.lods[h];g.width&&(l.lods[h]=l.lods[h]||{min_height:1/0,max_height:0},l.lods[h].min_height=Math.min(l.lods[h].min_height,g.height),l.lods[h].max_height=Math.max(l.lods[h].max_height,g.height))}}}}}static hasLODLevelAvailable(t,e){var o;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 r,i;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&(o=r==null?void 0:r.userData)!=null&&o.LODS){const s=r.userData.LODS;if(i=this.lodInfos.get(s.key),e===void 0)return i!=null;if(i)return Array.isArray(i.lods)?e<i.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const i=t.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of Z)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,S.getOrLoadLOD(i,e).then(s=>{if(Array.isArray(s)){const a=o.index||0;s=s[a]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],s&&i!=s&&((s==null?void 0:s.isBufferGeometry)?t.geometry=s:x&&console.error("Invalid LOD geometry",s))),s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else x&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const i=new Array;for(const o of r.material){const s=this.assignTextureLOD(o,e);i.push(s)}return Promise.all(i).then(o=>{const s=new Array;for(const a of o)Array.isArray(a)&&s.push(...a);return s})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,i=[],o=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const s=r;for(const a of Object.keys(s.uniforms)){const l=s.uniforms[a].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,r,a).then(c=>(c&&s.uniforms[a].value!=c&&(s.uniforms[a].value=c,s.uniformsNeedUpdate=!0),c));i.push(u),o.push(a)}}}else for(const s of Object.keys(r)){const a=r[s];if((a==null?void 0:a.isTexture)===!0){const l=this.assignTextureLODForSlot(a,e,r,s);i.push(l),o.push(s)}}return Promise.all(i).then(s=>{const a=new Array;for(let l=0;l<s.length;l++){const u=s[l],c=o[l];u&&u.isTexture===!0?a.push({material:r,slot:c,texture:u,level:e}):a.push({material:r,slot:c,texture:null,level:e})}return a})}if(t instanceof p.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,i){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):i==="glyphMap"?Promise.resolve(t):S.getOrLoadLOD(t,e).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=t&&r&&i){const s=r[i];if(s&&!x){const a=this.getAssignedLODInformation(s);if(a&&(a==null?void 0:a.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,r,s,o),null}r[i]=o}return o}else x=="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 x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((i,o)=>{var s;if(i!=null&&i.extensions){const a=i==null?void 0:i.extensions[q];if(a){if(!a.lods){x&&console.warn("Texture has no LODs",a);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const c=this.parser.associations.get(u);(c==null?void 0:c.textures)===o&&(l=!0,S.registerTexture(this.url,u,(s=a.lods)==null?void 0:s.length,o,a))}l||this.parser.getDependency("texture",o).then(u=>{var c;u&&S.registerTexture(this.url,u,(c=a.lods)==null?void 0:c.length,o,a)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[q];if(s&&s.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const l=this.parser.associations.get(a);(l==null?void 0:l.meshes)===o&&S.registerMesh(this.url,s.guid,a,s.lods.length,l.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var a,l,u,c;const r=x=="verbose",i=t.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(t.isTexture===!0){const h=t;h.source&&h.source[De]&&(s=h.source[De])}if(s||(s=S.lodInfos.get(o)),s){if(e>0){let D=!1;const O=Array.isArray(s.lods);if(O&&e>=s.lods.length?D=!0:O||(D=!0),D)return this.lowresCache.get(o)}const h=Array.isArray(s.lods)?(a=s.lods[e])==null?void 0:a.path:s.lods;if(!h)return x&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,s)),null;const g=rt(i.url,h);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const D=g+"_"+s.guid,O=this.previouslyLoaded.get(D);if(O!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${D}`);let v=await O.catch(y=>(console.error(`Error loading LOD ${e} from ${g}
|
|
2
|
-
`,
|
|
3
|
-
`,b),null));if(!
|
|
1
|
+
"use strict";var He=Object.defineProperty;var je=(n,t,e)=>t in n?He(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var d=(n,t,e)=>(je(n,typeof t!="symbol"?t+"":t,e),e),Ge=(n,t,e)=>{if(!t.has(n))throw TypeError("Cannot "+e)};var y=(n,t,e)=>(Ge(n,t,"read from private field"),e?e.call(n):t.get(n)),J=(n,t,e)=>{if(t.has(n))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(n):t.set(n,e)},W=(n,t,e,r)=>(Ge(n,t,"write to private field"),r?r.call(n,e):t.set(n,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),Te=require("three/examples/jsm/loaders/GLTFLoader.js"),Je=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Qe=require("three/examples/jsm/loaders/DRACOLoader.js"),Ze=require("three/examples/jsm/loaders/KTX2Loader.js"),ke="";globalThis.GLTF_PROGRESSIVE_VERSION=ke;console.debug("[gltf-progressive] version -");let X="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",re="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const et=X,tt=re,$e=new URL(X+"draco_decoder.js");$e.searchParams.append("range","true");fetch($e,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(n=>{console.debug(`Failed to fetch remote Draco decoder from ${X} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),X===et&&Fe("./include/draco/"),re===tt&&Ne("./include/ktx2/")}).finally(()=>{Ue()});function Fe(n){X=n,I&&I[Oe]!=X?(console.debug("Updating Draco decoder path to "+n),I[Oe]=X,I.setDecoderPath(X),I.preload()):console.debug("Setting Draco decoder path to "+n)}function Ne(n){re=n,U&&U.transcoderPath!=re?(console.debug("Updating KTX2 transcoder path to "+n),U.setTranscoderPath(re),U.init()):console.debug("Setting KTX2 transcoder path to "+n)}const Oe=Symbol("dracoDecoderPath");let I,ye,U;function Ue(){I||(I=new Qe.DRACOLoader,I[Oe]=X,I.setDecoderPath(X),I.setDecoderConfig({type:"js"}),I.preload()),U||(U=new Ze.KTX2Loader,U.setTranscoderPath(re),U.init()),ye||(ye=Je.MeshoptDecoder)}function Pe(n){return Ue(),n?U.detectSupport(n):n!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:I,ktx2Loader:U,meshoptDecoder:ye}}function Ae(n){n.dracoLoader||n.setDRACOLoader(I),n.ktx2Loader||n.setKTX2Loader(U),n.meshoptDecoder||n.setMeshoptDecoder(ye)}const be=new WeakMap;function Ce(n,t){let e=be.get(n);e?e=Object.assign(e,t):e=t,be.set(n,e)}const we=Te.GLTFLoader.prototype.load;function rt(...n){const t=be.get(this);let e=n[0];const r=new URL(e,window.location.href);if(r.hostname.endsWith("needle.tools")){const o=(t==null?void 0:t.progressive)!==void 0?t.progressive:!0,s=t!=null&&t.usecase?t.usecase:"default";o?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${s}`:this.requestHeader.Accept=`*/*;usecase=${s}`,e=r.toString()}return n[0]=e,we==null?void 0:we.call(this,...n)}Te.GLTFLoader.prototype.load=rt;de("debugprogressive");function de(n){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(n);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function st(n,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||n===void 0)return t;const e=n.lastIndexOf("/");if(e>=0){const r=n.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let ne;function ot(){return ne!==void 0||(ne=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),de("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ne)),ne}function it(){if(typeof window>"u")return!1;const n=new URL(window.location.href),t=n.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(n.hostname);return n.hostname==="127.0.0.1"||t}const nt=typeof window>"u"&&typeof document>"u",Se=Symbol("needle:raycast-mesh");function oe(n){return(n==null?void 0:n[Se])instanceof p.BufferGeometry?n[Se]:null}function Ve(n,t){if((n.type==="Mesh"||n.type==="SkinnedMesh")&&!oe(n)){const r=at(t);r.userData={isRaycastMesh:!0},n[Se]=r}}function ze(n=!0){if(n){if(ae)return;const t=ae=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,r){const i=this,o=oe(i);let s;o&&i.isMesh&&(s=i.geometry,i.geometry=o),t.call(this,e,r),s&&(i.geometry=s)}}else{if(!ae)return;p.Mesh.prototype.raycast=ae,ae=null}}let ae=null;function at(n){const t=new p.BufferGeometry;for(const e in n.attributes)t.setAttribute(e,n.getAttribute(e));return t.setIndex(n.getIndex()),t}const Z=new Array,x=de("debugprogressive");let ge,te=-1;if(x){let n=function(){te+=1,te>=t&&(te=-1),console.log(`Toggle LOD level [${te}]`)},t=6;window.addEventListener("keyup",e=>{e.key==="p"&&n(),e.key==="w"&&(ge=!ge,console.log(`Toggle wireframe [${ge}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(te=r,console.log(`Set LOD level to [${te}]`))})}function We(n){if(x)if(Array.isArray(n))for(const t of n)We(t);else n&&"wireframe"in n&&(n.wireframe=ge===!0)}const q="NEEDLE_progressive",ve=Symbol("needle-progressive-texture"),S=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var r,i;if(this._isLoadingMesh)return null;const e=(i=(r=this.parser.json.meshes[t])==null?void 0:r.extensions)==null?void 0:i[q];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(o=>{var s;return this._isLoadingMesh=!1,o&&S.registerMesh(this.url,e.guid,o,(s=e.lods)==null?void 0:s.length,0,e),o})):null});x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return q}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){var r;const e=(r=this.getAssignedLODInformation(t))==null?void 0:r.index;return e??-1}static getMaterialMinMaxLODsCount(t,e){const r=this,i="LODS:minmax",o=t[i];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[i]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const l of Object.keys(a.uniforms)){const u=a.uniforms[l].value;(u==null?void 0:u.isTexture)===!0&&s(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const l=t[a];(l==null?void 0:l.isTexture)===!0&&s(l,e)}return t[i]=e,e;function s(a,l){const u=r.getAssignedLODInformation(a);if(u){const c=r.lodInfos.get(u.key);if(c&&c.lods){l.min_count=Math.min(l.min_count,c.lods.length),l.max_count=Math.max(l.max_count,c.lods.length);for(let h=0;h<c.lods.length;h++){const g=c.lods[h];g.width&&(l.lods[h]=l.lods[h]||{min_height:1/0,max_height:0},l.lods[h].min_height=Math.min(l.lods[h].min_height,g.height),l.lods[h].max_height=Math.max(l.lods[h].max_height,g.height))}}}}}static hasLODLevelAvailable(t,e){var o;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 r,i;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&(o=r==null?void 0:r.userData)!=null&&o.LODS){const s=r.userData.LODS;if(i=this.lodInfos.get(s.key),e===void 0)return i!=null;if(i)return Array.isArray(i.lods)?e<i.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const i=t.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of Z)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,S.getOrLoadLOD(i,e).then(s=>{if(Array.isArray(s)){const a=o.index||0;s=s[a]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],s&&i!=s&&((s==null?void 0:s.isBufferGeometry)?t.geometry=s:x&&console.error("Invalid LOD geometry",s))),s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else x&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const i=new Array;for(const o of r.material){const s=this.assignTextureLOD(o,e);i.push(s)}return Promise.all(i).then(o=>{const s=new Array;for(const a of o)Array.isArray(a)&&s.push(...a);return s})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,i=[],o=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const s=r;for(const a of Object.keys(s.uniforms)){const l=s.uniforms[a].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,r,a).then(c=>(c&&s.uniforms[a].value!=c&&(s.uniforms[a].value=c,s.uniformsNeedUpdate=!0),c));i.push(u),o.push(a)}}}else for(const s of Object.keys(r)){const a=r[s];if((a==null?void 0:a.isTexture)===!0){const l=this.assignTextureLODForSlot(a,e,r,s);i.push(l),o.push(s)}}return Promise.all(i).then(s=>{const a=new Array;for(let l=0;l<s.length;l++){const u=s[l],c=o[l];u&&u.isTexture===!0?a.push({material:r,slot:c,texture:u,level:e}):a.push({material:r,slot:c,texture:null,level:e})}return a})}if(t instanceof p.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,i){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):i==="glyphMap"?Promise.resolve(t):S.getOrLoadLOD(t,e).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=t&&r&&i){const s=r[i];if(s&&!x){const a=this.getAssignedLODInformation(s);if(a&&(a==null?void 0:a.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,r,s,o),null}r[i]=o}return o}else x=="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 x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((i,o)=>{var s;if(i!=null&&i.extensions){const a=i==null?void 0:i.extensions[q];if(a){if(!a.lods){x&&console.warn("Texture has no LODs",a);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const c=this.parser.associations.get(u);(c==null?void 0:c.textures)===o&&(l=!0,S.registerTexture(this.url,u,(s=a.lods)==null?void 0:s.length,o,a))}l||this.parser.getDependency("texture",o).then(u=>{var c;u&&S.registerTexture(this.url,u,(c=a.lods)==null?void 0:c.length,o,a)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[q];if(s&&s.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const l=this.parser.associations.get(a);(l==null?void 0:l.meshes)===o&&S.registerMesh(this.url,s.guid,a,s.lods.length,l.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var a,l,u,c;const r=x=="verbose",i=t.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(t.isTexture===!0){const h=t;h.source&&h.source[ve]&&(s=h.source[ve])}if(s||(s=S.lodInfos.get(o)),s){if(e>0){let w=!1;const O=Array.isArray(s.lods);if(O&&e>=s.lods.length?w=!0:O||(w=!0),w)return this.lowresCache.get(o)}const h=Array.isArray(s.lods)?(a=s.lods[e])==null?void 0:a.path:s.lods;if(!h)return x&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,s)),null;const g=st(i.url,h);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const w=g+"_"+s.guid,O=this.previouslyLoaded.get(w);if(O!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${w}`);let v=await O.catch(m=>(console.error(`Error loading LOD ${e} from ${g}
|
|
2
|
+
`,m),null)),D=!1;if(v==null||(v instanceof p.Texture&&t instanceof p.Texture?(l=v.image)!=null&&l.data||(u=v.source)!=null&&u.data?v=this.copySettings(t,v):(D=!0,this.previouslyLoaded.delete(w)):v instanceof p.BufferGeometry&&t instanceof p.BufferGeometry&&((c=v.attributes.position)!=null&&c.array||(D=!0,this.previouslyLoaded.delete(w)))),!D)return v}const _=s,V=new Promise(async(v,D)=>{const m=new Te.GLTFLoader;Ae(m),x&&(await new Promise(b=>setTimeout(b,1e3)),r&&console.warn("Start loading (delayed) "+g,_.guid));let Y=g;if(_&&Array.isArray(_.lods)){const b=_.lods[e];b.hash&&(Y+="?v="+b.hash)}const C=await m.loadAsync(Y).catch(b=>(console.error(`Error loading LOD ${e} from ${g}
|
|
3
|
+
`,b),null));if(!C)return null;const $=C.parser;r&&console.log("Loading finished "+g,_.guid);let k=0;if(C.parser.json.textures){let b=!1;for(const f of C.parser.json.textures){if(f!=null&&f.extensions){const T=f==null?void 0:f.extensions[q];if(T!=null&&T.guid&&T.guid===_.guid){b=!0;break}}k++}if(b){let f=await $.getDependency("texture",k);return f&&S.assignLODInformation(i.url,f,o,e,void 0),r&&console.log('change "'+t.name+'" → "'+f.name+'"',g,k,f,w),t instanceof p.Texture&&(f=this.copySettings(t,f)),f&&(f.guid=_.guid),v(f)}else x&&console.warn("Could not find texture with guid",_.guid,C.parser.json)}if(k=0,C.parser.json.meshes){let b=!1;for(const f of C.parser.json.meshes){if(f!=null&&f.extensions){const T=f==null?void 0:f.extensions[q];if(T!=null&&T.guid&&T.guid===_.guid){b=!0;break}}k++}if(b){const f=await $.getDependency("mesh",k);if(r&&console.log(`Loaded Mesh "${f.name}"`,g,k,f,w),f.isMesh===!0){const T=f.geometry;return S.assignLODInformation(i.url,T,o,e,0),v(T)}else{const T=new Array;for(let L=0;L<f.children.length;L++){const M=f.children[L];if(M.isMesh===!0){const E=M.geometry;S.assignLODInformation(i.url,E,o,e,L),T.push(E)}}return v(T)}}else x&&console.warn("Could not find mesh with guid",_.guid,C.parser.json)}return v(null)});return this.previouslyLoaded.set(w,V),await V}else if(t instanceof p.Texture){r&&console.log("Load texture from uri: "+g);const O=await new p.TextureLoader().loadAsync(g);return O?(O.guid=s.guid,O.flipY=!1,O.needsUpdate=!0,O.colorSpace=t.colorSpace,r&&console.log(s,O)):x&&console.warn("failed loading",g),O}}else x&&console.warn(`Can not load LOD ${e}: no LOD info found for "${o}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,i,o){if(!e)return;e.userData||(e.userData={});const s=new lt(t,r,i,o);e.userData.LODS=s}static getAssignedLODInformation(t){var e;return((e=t==null?void 0:t.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e?(x&&console.warn(`Copy texture settings
|
|
4
4
|
`,t.uuid,`
|
|
5
|
-
`,e.uuid),e=e.clone(),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e):t}};let A=S;d(A,"registerTexture",(t,e,r,i,o)=>{if(x&&console.log("> Progressive: register texture",i,e.name,e.uuid,e,o),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[De]=o);const s=o.guid;S.assignLODInformation(t,e,s,r,i),S.lodInfos.set(s,o),S.lowresCache.set(s,e)}),d(A,"registerMesh",(t,e,r,i,o,s)=>{var u;const a=r.geometry;if(!a){x&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),x&&console.log("> Progressive: register mesh "+r.name,{index:o,uuid:r.uuid},s,r),S.assignLODInformation(t,a,e,i,o),S.lodInfos.set(e,s);let l=S.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],S.lowresCache.set(e,l),i>0&&!oe(r)&&Ue(r,a);for(const c of Z)(u=c.onRegisteredNewMesh)==null||u.call(c,r,s)}),d(A,"lodInfos",new Map),d(A,"previouslyLoaded",new Map),d(A,"lowresCache",new Map);class nt{constructor(t,e,r,i){d(this,"url");d(this,"key");d(this,"level");d(this,"index");this.url=t,this.key=e,this.level=r,i!=null&&(this.index=i)}}const N=ce("debugprogressive"),at=ce("noprogressive"),ve=Symbol("Needle:LODSManager"),we=Symbol("Needle:LODState"),Q=Symbol("Needle:CurrentLOD"),B={mesh_lod:-1,texture_lod:-1};var I,H,ye,re,se,Le,j;const P=class{constructor(t,e){d(this,"context");d(this,"renderer");d(this,"projectionScreenMatrix",new p.Matrix4);d(this,"targetTriangleDensity",2e5);d(this,"skinnedMeshAutoUpdateBoundsInterval",30);d(this,"updateInterval","auto");J(this,I,1);d(this,"pause",!1);d(this,"manual",!1);d(this,"_lodchangedlisteners",[]);J(this,H,void 0);J(this,ye,new p.Clock);J(this,re,0);J(this,se,0);J(this,Le,0);J(this,j,0);d(this,"_fpsBuffer",[60,60,60,60,60]);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=t,this.context={...e}}static getObjectLODState(t){return t[we]}static addPlugin(t){Z.push(t)}static removePlugin(t){const e=Z.indexOf(t);e>=0&&Z.splice(e,1)}static get(t,e){if(t[ve])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[ve];const r=new P(t,{engine:"unknown",...e});return t[ve]=r,r}get plugins(){return Z}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(L(this,H))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;W(this,H,this.renderer.render);const e=this;Te(this.renderer),this.renderer.render=function(r,i){const o=e.renderer.getRenderTarget();(o==null||"isXRRenderTarget"in o&&o.isXRRenderTarget)&&(t=0,W(e,re,L(e,re)+1),W(e,se,L(e,ye).getDelta()),W(e,Le,L(e,Le)+L(e,se)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/L(e,se)),W(e,j,e._fpsBuffer.reduce((a,l)=>a+l)/e._fpsBuffer.length),N&&L(e,re)%200===0&&console.log("FPS",Math.round(L(e,j)),"Interval:",L(e,I)));const s=t++;L(e,H).call(this,r,i),e.onAfterRender(r,i,s)}}disable(){L(this,H)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=L(this,H),W(this,H,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const o=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(o.length===1){const a=o[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(at||(this.updateInterval==="auto"?L(this,j)<40&&L(this,I)<10?(W(this,I,L(this,I)+1),N&&console.warn("↓ Reducing LOD updates",L(this,I),L(this,j).toFixed(0))):L(this,j)>=60&&L(this,I)>1&&(W(this,I,L(this,I)-1),N&&console.warn("↑ Increasing LOD updates",L(this,I),L(this,j).toFixed(0))):W(this,I,this.updateInterval),L(this,I)>0&&L(this,re)%L(this,I)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var l,u;const r=this.renderer.renderLists.get(t,0),i=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const o=this.targetTriangleDensity;for(const c of i){if(c.material&&(((l=c.geometry)==null?void 0:l.type)==="BoxGeometry"||((u=c.geometry)==null?void 0:u.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){N&&(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}if(N==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const g=Math.random()*16777215,D=new p.MeshStandardMaterial({color:g});c.object.material=D}const h=c.object;(h instanceof p.Mesh||h.isMesh)&&this.updateLODs(t,e,h,o)}const s=r.transparent;for(const c of s){const h=c.object;(h instanceof p.Mesh||h.isMesh)&&this.updateLODs(t,e,h,o)}const a=r.transmissive;for(const c of a){const h=c.object;(h instanceof p.Mesh||h.isMesh)&&this.updateLODs(t,e,h,o)}}updateLODs(t,e,r,i){var a,l;r.userData||(r.userData={});let o=r[we];if(o||(o=new lt,r[we]=o),o.frames++<2)return;for(const u of Z)(a=u.onBeforeUpdateLOD)==null||a.call(u,this.renderer,t,e,r);const s=P.overrideGlobalLodLevel!==void 0?P.overrideGlobalLodLevel:ee;s>=0?(B.mesh_lod=s,B.texture_lod=s):(this.calculateLodLevel(e,r,o,i,B),B.mesh_lod=Math.round(B.mesh_lod),B.texture_lod=Math.round(B.texture_lod)),B.mesh_lod>=0&&this.loadProgressiveMeshes(r,B.mesh_lod),r.material&&B.texture_lod>=0&&this.loadProgressiveTextures(r.material,B.texture_lod),x&&r.material&&!r.isGizmo&&ze(r.material);for(const u of Z)(l=u.onAfterUpdatedLOD)==null||l.call(u,this.renderer,t,e,r,B);o.lastLodLevel_Mesh=B.mesh_lod,o.lastLodLevel_Texture=B.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[Q]===void 0||e<t[Q])&&(r=!0);const i=t["DEBUG:LOD"];i!=null&&(r=t[Q]!=i,e=i),r&&(t[Q]=e,A.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(s=>s({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[Q]!==e;const i=t["DEBUG:LOD"];if(i!=null&&(r=t[Q]!=i,e=i),r){t[Q]=e;const o=t.geometry;return A.assignMeshLOD(t,e).then(s=>(s&&t[Q]==e&&o!=t.geometry&&this._lodchangedlisteners.forEach(a=>a({type:"mesh",level:e,object:t})),s))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,i=t.max,o=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,i,o){var V,K,v;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let a=10+1,l=!1;if(N&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=(V=A.getMeshLODExtension(e.geometry))==null?void 0:V.lods,c=A.getPrimitiveIndex(e.geometry),h=u&&u.length>0,g=A.getMaterialMinMaxLODsCount(e.material),D=(g==null?void 0:g.min_count)!=1/0&&g.min_count>0&&g.max_count>0;if(!h&&!D){o.mesh_lod=0,o.texture_lod=0;return}h||(l=!0,a=0);const O=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let M=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const _=e;if(!_.boundingBox)_.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0&&r.frames%this.skinnedMeshAutoUpdateBoundsInterval===0){const y=oe(_),Y=_.geometry;y&&(_.geometry=y),_.computeBoundingBox(),_.geometry=Y}M=_.boundingBox}if(M){const _=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)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(M),this._tempBox.applyMatrix4(e.matrixWorld),_.isPerspectiveCamera&&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&&_.isPerspectiveCamera&&_.fov>70){const m=this._tempBox.min,w=this._tempBox.max;let C=m.x,F=m.y,z=w.x,ie=w.y;const ue=2,me=1.5,de=(m.x+w.x)*.5,fe=(m.y+w.y)*.5;C=(C-de)*ue+de,F=(F-fe)*ue+fe,z=(z-de)*ue+de,ie=(ie-fe)*ue+fe;const Xe=C<0&&z>0?0:Math.min(Math.abs(m.x),Math.abs(w.x)),Ke=F<0&&ie>0?0:Math.min(Math.abs(m.y),Math.abs(w.y)),xe=Math.max(Xe,Ke);r.lastCentrality=(me-xe)*(me-xe)*(me-xe)}else r.lastCentrality=1;const y=this._tempBox.getSize(this._tempBoxSize);y.multiplyScalar(.5),screen.availHeight>0&&O>0&&y.multiplyScalar(O/screen.availHeight),t.isPerspectiveCamera?y.x*=t.aspect:t.isOrthographicCamera;const Y=t.matrixWorldInverse,E=this._tempBox2;E.copy(M),E.applyMatrix4(e.matrixWorld),E.applyMatrix4(Y);const $=E.getSize(this._tempBox2Size),k=Math.max($.x,$.y);if(Math.max(y.x,y.y)!=0&&k!=0&&(y.z=$.z/Math.max($.x,$.y)*Math.max(y.x,y.y)),r.lastScreenCoverage=Math.max(y.x,y.y,y.z),r.lastScreenspaceVolume.copy(y),r.lastScreenCoverage*=r.lastCentrality,N&&P.debugDrawLine){const m=this.tempMatrix.copy(this.projectionScreenMatrix);m.invert();const w=P.corner0,C=P.corner1,F=P.corner2,z=P.corner3;w.copy(this._tempBox.min),C.copy(this._tempBox.max),C.x=w.x,F.copy(this._tempBox.max),F.y=w.y,z.copy(this._tempBox.max);const ie=(w.z+z.z)*.5;w.z=C.z=F.z=z.z=ie,w.applyMatrix4(m),C.applyMatrix4(m),F.applyMatrix4(m),z.applyMatrix4(m),P.debugDrawLine(w,C,255),P.debugDrawLine(w,F,255),P.debugDrawLine(C,z,255),P.debugDrawLine(F,z,255)}let f=999;if(u&&r.lastScreenCoverage>0)for(let m=0;m<u.length;m++){const w=u[m];if((((K=w.densities)==null?void 0:K[c])||w.density||1e-5)/r.lastScreenCoverage<i){f=m;break}}f<a&&(a=f,l=!0)}if(l?o.mesh_lod=a:o.mesh_lod=r.lastLodLevel_Mesh,N&&o.mesh_lod!=r.lastLodLevel_Mesh){const y=u==null?void 0:u[o.mesh_lod];y&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${o.mesh_lod} (${y.density.toFixed(0)}) - ${e.name}`)}if(D){const _="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(o.texture_lod=g.max_count-1,N){const y=g.lods[g.max_count-1];N&&console.log(`First Texture LOD ${o.texture_lod} (${y.max_height}px) - ${e.name}`)}}else{const y=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let Y=r.lastScreenCoverage*4;((v=this.context)==null?void 0:v.engine)==="model-viewer"&&(Y*=1.5);const $=O/window.devicePixelRatio*Y;let k=!1;for(let b=g.lods.length-1;b>=0;b--){const f=g.lods[b];if(!(_&&f.max_height>=2048)&&!(st()&&f.max_height>4096)&&(f.max_height>$||!k&&b===0)){if(k=!0,o.texture_lod=b,o.texture_lod<r.lastLodLevel_Texture){const T=f.max_height;N&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${o.texture_lod} = ${T}px
|
|
6
|
-
Screensize: ${$.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${
|
|
7
|
-
${e.name}`)}break}}}}else o.texture_lod=0}};let
|
|
8
|
-
`,n.getAttribute("src"));let t=null,e=null,r=null;for(let i=n;i!=null;i=Object.getPrototypeOf(i)){const o=Object.getOwnPropertySymbols(i),s=o.find(u=>u.toString()=="Symbol(renderer)"),a=o.find(u=>u.toString()=="Symbol(scene)"),l=o.find(u=>u.toString()=="Symbol(needsRender)");!t&&s!=null&&(t=n[s].threeRenderer),!e&&a!=null&&(e=n[a]),!r&&l!=null&&(r=n[l])}if(t&&e){let i=function(){if(r){let s=0,a=setInterval(()=>{if(s++>5){clearInterval(a);return}r==null||r.call(n)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=
|
|
5
|
+
`,e.uuid),e=e.clone(),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e):t}};let P=S;d(P,"registerTexture",(t,e,r,i,o)=>{if(x&&console.log("> Progressive: register texture",i,e.name,e.uuid,e,o),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ve]=o);const s=o.guid;S.assignLODInformation(t,e,s,r,i),S.lodInfos.set(s,o),S.lowresCache.set(s,e)}),d(P,"registerMesh",(t,e,r,i,o,s)=>{var u;const a=r.geometry;if(!a){x&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),x&&console.log("> Progressive: register mesh "+r.name,{index:o,uuid:r.uuid},s,r),S.assignLODInformation(t,a,e,i,o),S.lodInfos.set(e,s);let l=S.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],S.lowresCache.set(e,l),i>0&&!oe(r)&&Ve(r,a);for(const c of Z)(u=c.onRegisteredNewMesh)==null||u.call(c,r,s)}),d(P,"lodInfos",new Map),d(P,"previouslyLoaded",new Map),d(P,"lowresCache",new Map);class lt{constructor(t,e,r,i){d(this,"url");d(this,"key");d(this,"level");d(this,"index");this.url=t,this.key=e,this.level=r,i!=null&&(this.index=i)}}class pe{constructor(t,e){d(this,"frame_start");d(this,"frame_capture_end");d(this,"ready");d(this,"_resolve");d(this,"_signal");d(this,"_resolved",!1);d(this,"_addedCount",0);d(this,"_resolvedCount",0);d(this,"_awaiting",[]);d(this,"_currentFrame",0);var o;const r=t===0?2:1,i=Math.max(e.frames??r,r);this.frame_start=t,this.frame_capture_end=t+i,this.ready=new Promise(s=>{this._resolve=s}),this.ready.finally(()=>{this._resolved=!0,this._awaiting.length=0}),this._signal=e.signal,(o=this._signal)==null||o.addEventListener("abort",()=>{this.resolveNow()})}get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}update(t){var e;this._currentFrame=t,((e=this._signal)!=null&&e.aborted||this._currentFrame>this.frame_capture_end&&this._awaiting.length===0)&&this.resolveNow()}add(t,e){if(this._resolved){console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}this._currentFrame>this.frame_capture_end||(this._awaiting.push(e),this._addedCount++,e.finally(()=>{this._resolvedCount++,this._awaiting.splice(this._awaiting.indexOf(e),1)}))}resolveNow(){var t,e;this._resolved||(e=this._resolve)==null||e.call(this,{awaited_count:this._addedCount,resolved_count:this._resolvedCount,cancelled:((t=this._signal)==null?void 0:t.aborted)??!1})}}d(pe,"addPromise",(t,e,r)=>{r.forEach(i=>{i.add(t,e)})});const N=de("debugprogressive"),dt=de("noprogressive"),Me=Symbol("Needle:LODSManager"),De=Symbol("Needle:LODState"),Q=Symbol("Needle:CurrentLOD"),G={mesh_lod:-1,texture_lod:-1};var R,H,me,ee,se,Le,j;const A=class{constructor(t,e){d(this,"renderer");d(this,"context");d(this,"projectionScreenMatrix",new p.Matrix4);d(this,"targetTriangleDensity",2e5);d(this,"skinnedMeshAutoUpdateBoundsInterval",30);d(this,"updateInterval","auto");J(this,R,1);d(this,"pause",!1);d(this,"manual",!1);d(this,"_newPromiseGroups",[]);d(this,"_promiseGroupIds",0);d(this,"_lodchangedlisteners",[]);J(this,H,void 0);J(this,me,new p.Clock);J(this,ee,0);J(this,se,0);J(this,Le,0);J(this,j,0);d(this,"_fpsBuffer",[60,60,60,60,60]);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=t,this.context={...e}}static getObjectLODState(t){return t[De]}static addPlugin(t){Z.push(t)}static removePlugin(t){const e=Z.indexOf(t);e>=0&&Z.splice(e,1)}static get(t,e){if(t[Me])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[Me];const r=new A(t,{engine:"unknown",...e});return t[Me]=r,r}get plugins(){return Z}awaitLoading(t){const e=this._promiseGroupIds++,r=new pe(y(this,ee),{...t});this._newPromiseGroups.push(r);const i=performance.now();return r.ready.finally(()=>{const o=this._newPromiseGroups.indexOf(r);o>=0&&(this._newPromiseGroups.splice(o,1),it()&&performance.measure("LODsManager:awaitLoading",{start:i,detail:{id:e,name:t==null?void 0:t.name,awaited:r.awaitedCount,resolved:r.resolvedCount}}))}),r.ready}_postprocessPromiseGroups(){if(this._newPromiseGroups.length!==0)for(let t=this._newPromiseGroups.length-1;t>=0;t--)this._newPromiseGroups[t].update(y(this,ee))}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(y(this,H))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;W(this,H,this.renderer.render);const e=this;Pe(this.renderer),this.renderer.render=function(r,i){const o=e.renderer.getRenderTarget();(o==null||"isXRRenderTarget"in o&&o.isXRRenderTarget)&&(t=0,W(e,ee,y(e,ee)+1),W(e,se,y(e,me).getDelta()),W(e,Le,y(e,Le)+y(e,se)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/y(e,se)),W(e,j,e._fpsBuffer.reduce((a,l)=>a+l)/e._fpsBuffer.length),N&&y(e,ee)%200===0&&console.log("FPS",Math.round(y(e,j)),"Interval:",y(e,R)));const s=t++;y(e,H).call(this,r,i),e.onAfterRender(r,i,s)}}disable(){y(this,H)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=y(this,H),W(this,H,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const o=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(o.length===1){const a=o[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(dt||(this.updateInterval==="auto"?y(this,j)<40&&y(this,R)<10?(W(this,R,y(this,R)+1),N&&console.warn("↓ Reducing LOD updates",y(this,R),y(this,j).toFixed(0))):y(this,j)>=60&&y(this,R)>1&&(W(this,R,y(this,R)-1),N&&console.warn("↑ Increasing LOD updates",y(this,R),y(this,j).toFixed(0))):W(this,R,this.updateInterval),y(this,R)>0&&y(this,ee)%y(this,R)!=0))return;this.internalUpdate(t,e),this._postprocessPromiseGroups()}}internalUpdate(t,e){var l,u;const r=this.renderer.renderLists.get(t,0),i=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const o=this.targetTriangleDensity;for(const c of i){if(c.material&&(((l=c.geometry)==null?void 0:l.type)==="BoxGeometry"||((u=c.geometry)==null?void 0:u.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){N&&(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}if(N==="color"&&c.material&&!c.object.progressive_debug_color){c.object.progressive_debug_color=!0;const g=Math.random()*16777215,w=new p.MeshStandardMaterial({color:g});c.object.material=w}const h=c.object;(h instanceof p.Mesh||h.isMesh)&&this.updateLODs(t,e,h,o)}const s=r.transparent;for(const c of s){const h=c.object;(h instanceof p.Mesh||h.isMesh)&&this.updateLODs(t,e,h,o)}const a=r.transmissive;for(const c of a){const h=c.object;(h instanceof p.Mesh||h.isMesh)&&this.updateLODs(t,e,h,o)}}updateLODs(t,e,r,i){var a,l;r.userData||(r.userData={});let o=r[De];if(o||(o=new ct,r[De]=o),o.frames++<2)return;for(const u of Z)(a=u.onBeforeUpdateLOD)==null||a.call(u,this.renderer,t,e,r);const s=A.overrideGlobalLodLevel!==void 0?A.overrideGlobalLodLevel:te;s>=0?(G.mesh_lod=s,G.texture_lod=s):(this.calculateLodLevel(e,r,o,i,G),G.mesh_lod=Math.round(G.mesh_lod),G.texture_lod=Math.round(G.texture_lod)),G.mesh_lod>=0&&this.loadProgressiveMeshes(r,G.mesh_lod),r.material&&G.texture_lod>=0&&this.loadProgressiveTextures(r.material,G.texture_lod),x&&r.material&&!r.isGizmo&&We(r.material);for(const u of Z)(l=u.onAfterUpdatedLOD)==null||l.call(u,this.renderer,t,e,r,G);o.lastLodLevel_Mesh=G.mesh_lod,o.lastLodLevel_Texture=G.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[Q]===void 0||e<t[Q])&&(r=!0);const i=t["DEBUG:LOD"];if(i!=null&&(r=t[Q]!=i,e=i),r){t[Q]=e;const o=P.assignTextureLOD(t,e).then(s=>{this._lodchangedlisteners.forEach(a=>a({type:"texture",level:e,object:t}))});pe.addPromise("texture",o,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[Q]!==e;const i=t["DEBUG:LOD"];if(i!=null&&(r=t[Q]!=i,e=i),r){t[Q]=e;const o=t.geometry,s=P.assignMeshLOD(t,e).then(a=>(a&&t[Q]==e&&o!=t.geometry&&this._lodchangedlisteners.forEach(l=>l({type:"mesh",level:e,object:t})),a));return pe.addPromise("mesh",s,this._newPromiseGroups),s}return Promise.resolve(null)}static isInside(t,e){const r=t.min,i=t.max,o=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,i,o){var V,K,v;if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let a=10+1,l=!1;if(N&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=(V=P.getMeshLODExtension(e.geometry))==null?void 0:V.lods,c=P.getPrimitiveIndex(e.geometry),h=u&&u.length>0,g=P.getMaterialMinMaxLODsCount(e.material),w=(g==null?void 0:g.min_count)!=1/0&&g.min_count>0&&g.max_count>0;if(!h&&!w){o.mesh_lod=0,o.texture_lod=0;return}h||(l=!0,a=0);const O=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let _=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const D=e;if(!D.boundingBox)D.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0&&r.frames%this.skinnedMeshAutoUpdateBoundsInterval===0){const m=oe(D),Y=D.geometry;m&&(D.geometry=m),D.computeBoundingBox(),D.geometry=Y}_=D.boundingBox}if(_){const D=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 L=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(L)){o.mesh_lod=0,o.texture_lod=0;return}}if(this._tempBox.copy(_),this._tempBox.applyMatrix4(e.matrixWorld),D.isPerspectiveCamera&&A.isInside(this._tempBox,this.projectionScreenMatrix)){o.mesh_lod=0,o.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&D.isPerspectiveCamera&&D.fov>70){const L=this._tempBox.min,M=this._tempBox.max;let E=L.x,F=L.y,z=M.x,ie=M.y;const ce=2,xe=1.5,ue=(L.x+M.x)*.5,fe=(L.y+M.y)*.5;E=(E-ue)*ce+ue,F=(F-fe)*ce+fe,z=(z-ue)*ce+ue,ie=(ie-fe)*ce+fe;const Ke=E<0&&z>0?0:Math.min(Math.abs(L.x),Math.abs(M.x)),Ye=F<0&&ie>0?0:Math.min(Math.abs(L.y),Math.abs(M.y)),_e=Math.max(Ke,Ye);r.lastCentrality=(xe-_e)*(xe-_e)*(xe-_e)}else r.lastCentrality=1;const m=this._tempBox.getSize(this._tempBoxSize);m.multiplyScalar(.5),screen.availHeight>0&&O>0&&m.multiplyScalar(O/screen.availHeight),t.isPerspectiveCamera?m.x*=t.aspect:t.isOrthographicCamera;const Y=t.matrixWorldInverse,C=this._tempBox2;C.copy(_),C.applyMatrix4(e.matrixWorld),C.applyMatrix4(Y);const $=C.getSize(this._tempBox2Size),k=Math.max($.x,$.y);if(Math.max(m.x,m.y)!=0&&k!=0&&(m.z=$.z/Math.max($.x,$.y)*Math.max(m.x,m.y)),r.lastScreenCoverage=Math.max(m.x,m.y,m.z),r.lastScreenspaceVolume.copy(m),r.lastScreenCoverage*=r.lastCentrality,N&&A.debugDrawLine){const L=this.tempMatrix.copy(this.projectionScreenMatrix);L.invert();const M=A.corner0,E=A.corner1,F=A.corner2,z=A.corner3;M.copy(this._tempBox.min),E.copy(this._tempBox.max),E.x=M.x,F.copy(this._tempBox.max),F.y=M.y,z.copy(this._tempBox.max);const ie=(M.z+z.z)*.5;M.z=E.z=F.z=z.z=ie,M.applyMatrix4(L),E.applyMatrix4(L),F.applyMatrix4(L),z.applyMatrix4(L),A.debugDrawLine(M,E,255),A.debugDrawLine(M,F,255),A.debugDrawLine(E,z,255),A.debugDrawLine(F,z,255)}let f=999;if(u&&r.lastScreenCoverage>0)for(let L=0;L<u.length;L++){const M=u[L];if((((K=M.densities)==null?void 0:K[c])||M.density||1e-5)/r.lastScreenCoverage<i){f=L;break}}f<a&&(a=f,l=!0)}if(l?o.mesh_lod=a:o.mesh_lod=r.lastLodLevel_Mesh,N&&o.mesh_lod!=r.lastLodLevel_Mesh){const m=u==null?void 0:u[o.mesh_lod];m&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${o.mesh_lod} (${m.density.toFixed(0)}) - ${e.name}`)}if(w){const D="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(o.texture_lod=g.max_count-1,N){const m=g.lods[g.max_count-1];N&&console.log(`First Texture LOD ${o.texture_lod} (${m.max_height}px) - ${e.name}`)}}else{const m=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let Y=r.lastScreenCoverage*4;((v=this.context)==null?void 0:v.engine)==="model-viewer"&&(Y*=1.5);const $=O/window.devicePixelRatio*Y;let k=!1;for(let b=g.lods.length-1;b>=0;b--){const f=g.lods[b];if(!(D&&f.max_height>=2048)&&!(ot()&&f.max_height>4096)&&(f.max_height>$||!k&&b===0)){if(k=!0,o.texture_lod=b,o.texture_lod<r.lastLodLevel_Texture){const T=f.max_height;N&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${o.texture_lod} = ${T}px
|
|
6
|
+
Screensize: ${$.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${m.toFixed(1)}
|
|
7
|
+
${e.name}`)}break}}}}else o.texture_lod=0}};let B=A;R=new WeakMap,H=new WeakMap,me=new WeakMap,ee=new WeakMap,se=new WeakMap,Le=new WeakMap,j=new WeakMap,d(B,"debugDrawLine"),d(B,"overrideGlobalLodLevel"),d(B,"corner0",new p.Vector3),d(B,"corner1",new p.Vector3),d(B,"corner2",new p.Vector3),d(B,"corner3",new p.Vector3),d(B,"_tempPtInside",new p.Vector3);class ct{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 Be=Symbol("NEEDLE_mesh_lod"),he=Symbol("NEEDLE_texture_lod");let le=null;function Ee(){const n=ut();n&&(n.mapURLs(function(t){return Re(),t}),Re(),le==null||le.disconnect(),le=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&qe(r)})})}),le.observe(document,{childList:!0,subtree:!0}))}function ut(){if(typeof customElements>"u")return null;const n=customElements.get("model-viewer");return n||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Ee()}),null)}function Re(){if(typeof document>"u")return;document.querySelectorAll("model-viewer").forEach(t=>{qe(t)})}const Ie=new WeakSet;let ft=0;function qe(n){if(!n||Ie.has(n))return null;Ie.add(n),console.debug("[gltf-progressive] found new model-viewer..."+ ++ft+`
|
|
8
|
+
`,n.getAttribute("src"));let t=null,e=null,r=null;for(let i=n;i!=null;i=Object.getPrototypeOf(i)){const o=Object.getOwnPropertySymbols(i),s=o.find(u=>u.toString()=="Symbol(renderer)"),a=o.find(u=>u.toString()=="Symbol(scene)"),l=o.find(u=>u.toString()=="Symbol(needsRender)");!t&&s!=null&&(t=n[s].threeRenderer),!e&&a!=null&&(e=n[a]),!r&&l!=null&&(r=n[l])}if(t&&e){let i=function(){if(r){let s=0,a=setInterval(()=>{if(s++>5){clearInterval(a);return}r==null||r.call(n)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=B.get(t,{engine:"model-viewer"});return B.addPlugin(new ht),o.enable(),o.addEventListener("changed",()=>{r==null||r.call(n)}),n.addEventListener("model-visibility",s=>{s.detail.visible&&(r==null||r.call(n))}),n.addEventListener("load",()=>{i()}),()=>{o.disable()}}return null}class ht{constructor(){d(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(t,e,r,i){this.tryParseMeshLOD(e,i),this.tryParseTextureLOD(e,i)}getUrl(t){if(!t)return null;let e=t.getAttribute("src");return e||(e=t.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",t),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(t){return t._currentGLTF}tryGetCurrentModelViewer(t){return t.element}tryParseTextureLOD(t,e){if(e[he]==!0)return;e[he]=!0;const r=this.tryGetCurrentGLTF(t),i=this.tryGetCurrentModelViewer(t),o=this.getUrl(i);if(o&&r&&e.material){let s=function(l){var c,h,g;if(l[he]==!0)return;l[he]=!0,l.userData&&(l.userData.LOD=-1);const u=Object.keys(l);for(let w=0;w<u.length;w++){const O=u[w],_=l[O];if((_==null?void 0:_.isTexture)===!0){const V=(h=(c=_.userData)==null?void 0:c.associations)==null?void 0:h.textures;if(V==null)continue;const K=r.parser.json.textures[V];if(!K){console.warn("Texture data not found for texture index "+V);continue}if((g=K==null?void 0:K.extensions)!=null&&g[q]){const v=K.extensions[q];v&&o&&P.registerTexture(o,_,v.lods.length,V,v)}}}};const a=e.material;if(Array.isArray(a))for(const l of a)s(l);else s(a)}}tryParseMeshLOD(t,e){var s,a;if(e[Be]==!0)return;e[Be]=!0;const r=this.tryGetCurrentModelViewer(t),i=this.getUrl(r);if(!i)return;const o=(a=(s=e.userData)==null?void 0:s.gltfExtensions)==null?void 0:a[q];if(o&&i){const l=e.uuid;P.registerMesh(i,l,e,0,o.lods.length,o)}}}function Xe(n,t,e,r){Pe(t),Ae(e),Ce(e,{progressive:!0,...r==null?void 0:r.hints}),e.register(o=>new P(o,n));const i=B.get(t);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}Ee();if(!nt){const n={gltfProgressive:{useNeedleProgressive:Xe,LODsManager:B,configureLoader:Ce,getRaycastMesh:oe,useRaycastMeshes:ze}};if(!globalThis.Needle)globalThis.Needle=n;else for(const t in n)globalThis.Needle[t]=n[t]}exports.EXTENSION_NAME=q;exports.LODsManager=B;exports.NEEDLE_progressive=P;exports.VERSION=ke;exports.addDracoAndKTX2Loaders=Ae;exports.configureLoader=Ce;exports.createLoaders=Pe;exports.getRaycastMesh=oe;exports.patchModelViewer=Ee;exports.registerRaycastMesh=Ve;exports.setDracoDecoderLocation=Fe;exports.setKTX2TranscoderLocation=Ne;exports.useNeedleProgressive=Xe;exports.useRaycastMeshes=ze;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export { version as VERSION } from "./version.js";
|
|
2
2
|
export * from "./extension.js";
|
|
3
3
|
export * from "./plugins/index.js";
|
|
4
|
-
export { LODsManager, type LOD_Results } from "./
|
|
4
|
+
export { LODsManager, type LOD_Results } from "./lods.manager.js";
|
|
5
5
|
export { setDracoDecoderLocation, setKTX2TranscoderLocation, createLoaders, addDracoAndKTX2Loaders, configureLoader } from "./loaders.js";
|
|
6
6
|
export { getRaycastMesh, registerRaycastMesh, useRaycastMeshes } from "./utils.js";
|
|
7
7
|
import { WebGLRenderer } from "three";
|
|
8
8
|
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
9
9
|
import { SmartLoadingHints } from "./loaders.js";
|
|
10
|
-
import { LODsManager } from "./
|
|
10
|
+
import { LODsManager } from "./lods.manager.js";
|
|
11
11
|
declare type UseNeedleGLTFProgressiveOptions = {
|
|
12
12
|
/**
|
|
13
13
|
* When set to true the LODs manager will automatically be enabled
|
package/lib/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export { version as VERSION } from "./version.js";
|
|
2
2
|
export * from "./extension.js";
|
|
3
3
|
export * from "./plugins/index.js";
|
|
4
|
-
export { LODsManager } from "./
|
|
4
|
+
export { LODsManager } from "./lods.manager.js";
|
|
5
5
|
export { setDracoDecoderLocation, setKTX2TranscoderLocation, createLoaders, addDracoAndKTX2Loaders, configureLoader } from "./loaders.js";
|
|
6
6
|
export { getRaycastMesh, registerRaycastMesh, useRaycastMeshes } from "./utils.js";
|
|
7
7
|
import { addDracoAndKTX2Loaders, configureLoader, createLoaders } from "./loaders.js";
|
|
8
8
|
import { NEEDLE_progressive } from "./extension.js";
|
|
9
|
-
import { LODsManager } from "./
|
|
9
|
+
import { LODsManager } from "./lods.manager.js";
|
|
10
10
|
/** Use this function to enable progressive loading of gltf models.
|
|
11
11
|
* @param url The url of the gltf model.
|
|
12
12
|
* @param renderer The renderer of the scene.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
type PromiseType = "texture" | "mesh";
|
|
2
|
+
export type PromiseGroupOptions = {
|
|
3
|
+
name?: string;
|
|
4
|
+
/** How many renderer frames can requests be captured to be awaited */
|
|
5
|
+
frames?: number;
|
|
6
|
+
signal?: AbortSignal;
|
|
7
|
+
};
|
|
8
|
+
type PromiseGroupResolveResult = {
|
|
9
|
+
/**
|
|
10
|
+
* `true` if the group was cancelled, `false` if it was resolved normally.
|
|
11
|
+
*/
|
|
12
|
+
cancelled: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* The number of promises that started to being awaited
|
|
15
|
+
*/
|
|
16
|
+
awaited_count: number;
|
|
17
|
+
/**
|
|
18
|
+
* The number of promises that were resolved
|
|
19
|
+
*/
|
|
20
|
+
resolved_count: number;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* A group of promises that can be awaited together.
|
|
24
|
+
* This is used for awaiting LOD
|
|
25
|
+
*/
|
|
26
|
+
export declare class PromiseGroup {
|
|
27
|
+
static readonly addPromise: (type: PromiseType, promise: Promise<any>, groups: PromiseGroup[]) => void;
|
|
28
|
+
readonly frame_start: number;
|
|
29
|
+
readonly frame_capture_end: number;
|
|
30
|
+
readonly ready: Promise<PromiseGroupResolveResult>;
|
|
31
|
+
private _resolve;
|
|
32
|
+
private readonly _signal?;
|
|
33
|
+
/**
|
|
34
|
+
* The number of promises that have been added to this group so far.
|
|
35
|
+
*/
|
|
36
|
+
get awaitedCount(): number;
|
|
37
|
+
get resolvedCount(): number;
|
|
38
|
+
get currentlyAwaiting(): number;
|
|
39
|
+
private _resolved;
|
|
40
|
+
private _addedCount;
|
|
41
|
+
private _resolvedCount;
|
|
42
|
+
/** These promises are currently being awaited */
|
|
43
|
+
private readonly _awaiting;
|
|
44
|
+
constructor(frame: number, options: PromiseGroupOptions);
|
|
45
|
+
private _currentFrame;
|
|
46
|
+
update(frame: number): void;
|
|
47
|
+
private add;
|
|
48
|
+
private resolveNow;
|
|
49
|
+
}
|
|
50
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A group of promises that can be awaited together.
|
|
3
|
+
* This is used for awaiting LOD
|
|
4
|
+
*/
|
|
5
|
+
export class PromiseGroup {
|
|
6
|
+
static addPromise = (type, promise, groups) => {
|
|
7
|
+
groups.forEach(group => {
|
|
8
|
+
group.add(type, promise);
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
frame_start;
|
|
12
|
+
frame_capture_end;
|
|
13
|
+
ready;
|
|
14
|
+
_resolve;
|
|
15
|
+
_signal;
|
|
16
|
+
/**
|
|
17
|
+
* The number of promises that have been added to this group so far.
|
|
18
|
+
*/
|
|
19
|
+
get awaitedCount() {
|
|
20
|
+
return this._addedCount;
|
|
21
|
+
}
|
|
22
|
+
get resolvedCount() {
|
|
23
|
+
return this._resolvedCount;
|
|
24
|
+
}
|
|
25
|
+
get currentlyAwaiting() {
|
|
26
|
+
return this._awaiting.length;
|
|
27
|
+
}
|
|
28
|
+
_resolved = false;
|
|
29
|
+
_addedCount = 0;
|
|
30
|
+
_resolvedCount = 0;
|
|
31
|
+
/** These promises are currently being awaited */
|
|
32
|
+
_awaiting = [];
|
|
33
|
+
constructor(frame, options) {
|
|
34
|
+
const minFrames = frame === 0 ? 2 : 1; // if we are at frame 0, we need at least 2 frames to capture
|
|
35
|
+
const framesToCapture = Math.max(options.frames ?? minFrames, minFrames); // default to 2 frames and make sure it's at least 2 frames
|
|
36
|
+
this.frame_start = frame;
|
|
37
|
+
this.frame_capture_end = frame + framesToCapture;
|
|
38
|
+
this.ready = new Promise((resolve) => {
|
|
39
|
+
this._resolve = resolve;
|
|
40
|
+
});
|
|
41
|
+
this.ready.finally(() => {
|
|
42
|
+
this._resolved = true;
|
|
43
|
+
this._awaiting.length = 0;
|
|
44
|
+
});
|
|
45
|
+
this._signal = options.signal;
|
|
46
|
+
this._signal?.addEventListener("abort", () => {
|
|
47
|
+
this.resolveNow();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
_currentFrame = 0;
|
|
51
|
+
update(frame) {
|
|
52
|
+
this._currentFrame = frame;
|
|
53
|
+
// If we've passes the frame capture end frame and didn't add any promises, we resolve immediately
|
|
54
|
+
if (this._signal?.aborted || (this._currentFrame > this.frame_capture_end && this._awaiting.length === 0)) {
|
|
55
|
+
this.resolveNow();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
add(_type, promise) {
|
|
59
|
+
if (this._resolved) {
|
|
60
|
+
console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (this._currentFrame > this.frame_capture_end) {
|
|
64
|
+
return; // we are not capturing any more promises
|
|
65
|
+
}
|
|
66
|
+
this._awaiting.push(promise);
|
|
67
|
+
this._addedCount++;
|
|
68
|
+
promise.finally(() => {
|
|
69
|
+
this._resolvedCount++;
|
|
70
|
+
this._awaiting.splice(this._awaiting.indexOf(promise), 1);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
resolveNow() {
|
|
74
|
+
if (this._resolved)
|
|
75
|
+
return;
|
|
76
|
+
this._resolve?.({
|
|
77
|
+
awaited_count: this._addedCount,
|
|
78
|
+
resolved_count: this._resolvedCount,
|
|
79
|
+
cancelled: this._signal?.aborted ?? false,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Camera, Material,
|
|
1
|
+
import { Camera, Material, Object3D, Scene, Texture, Vector3, WebGLRenderer } from "three";
|
|
2
2
|
import { NEEDLE_progressive_plugin } from "./plugins/plugin.js";
|
|
3
|
+
import { PromiseGroupOptions } from "./lods.loading.js";
|
|
3
4
|
export type LODManagerContext = {
|
|
4
5
|
engine: "three" | "needle-engine" | "model-viewer" | "react-three-fiber" | "unknown";
|
|
5
6
|
};
|
|
@@ -61,9 +62,9 @@ export declare class LODsManager {
|
|
|
61
62
|
* @returns The LODsManager instance.
|
|
62
63
|
*/
|
|
63
64
|
static get(renderer: WebGLRenderer, context?: LODManagerContext): LODsManager;
|
|
64
|
-
private readonly context;
|
|
65
65
|
readonly renderer: WebGLRenderer;
|
|
66
|
-
readonly
|
|
66
|
+
private readonly context;
|
|
67
|
+
private readonly projectionScreenMatrix;
|
|
67
68
|
/** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
|
|
68
69
|
get plugins(): NEEDLE_progressive_plugin[];
|
|
69
70
|
/**
|
|
@@ -93,6 +94,17 @@ export declare class LODsManager {
|
|
|
93
94
|
* @default false
|
|
94
95
|
*/
|
|
95
96
|
manual: boolean;
|
|
97
|
+
private readonly _newPromiseGroups;
|
|
98
|
+
private _promiseGroupIds;
|
|
99
|
+
/**
|
|
100
|
+
* Call to await LODs loading during the next render cycle.
|
|
101
|
+
*/
|
|
102
|
+
awaitLoading(opts?: PromiseGroupOptions): Promise<{
|
|
103
|
+
cancelled: boolean;
|
|
104
|
+
awaited_count: number;
|
|
105
|
+
resolved_count: number;
|
|
106
|
+
}>;
|
|
107
|
+
private _postprocessPromiseGroups;
|
|
96
108
|
private readonly _lodchangedlisteners;
|
|
97
109
|
addEventListener(evt: "changed", listener: LODChangedEventListener): void;
|
|
98
110
|
removeEventListener(evt: "changed", listener: LODChangedEventListener): void;
|