@needle-tools/gltf-progressive 3.0.0 → 3.0.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 +2 -1
- package/gltf-progressive.js +602 -494
- 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_manager.d.ts → lods.manager.d.ts} +15 -3
- package/lib/{lods_manager.js → lods.manager.js} +40 -11
- package/lib/lods.promise.d.ts +61 -0
- package/lib/lods.promise.js +101 -0
- 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,s)=>e in t?Ye(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s,u=(t,e,s)=>(Je(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)),Y=(t,e,s)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,s)},U=(t,e,s,o)=>(Ee(t,e,"write to private field"),o?o.call(t,s):e.set(t,s),s);import{BufferGeometry as ue,Mesh as J,Texture as se,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 ye}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as st}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as rt}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as ot}from"three/examples/jsm/loaders/KTX2Loader.js";const ke="";globalThis.GLTF_PROGRESSIVE_VERSION=ke,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 it=$,nt=Z,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"})`),$===it&&Ge("./include/draco/"),Z===nt&&Re("./include/ktx2/")}).finally(()=>{je()});function Ge(t){$=t,k&&k[Le]!=$?(console.debug("Updating Draco decoder path to "+t),k[Le]=$,k.setDecoderPath($),k.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 k,de,j;function je(){k||(k=new rt,k[Le]=$,k.setDecoderPath($),k.setDecoderConfig({type:"js"}),k.preload()),j||(j=new ot,j.setTranscoderPath(Z),j.init()),de||(de=st)}function _e(t){return je(),t?j.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:k,ktx2Loader:j,meshoptDecoder:de}}function we(t){t.dracoLoader||t.setDRACOLoader(k),t.ktx2Loader||t.setKTX2Loader(j),t.meshoptDecoder||t.setMeshoptDecoder(de)}const Me=new WeakMap;function De(t,e){let s=Me.get(t);s?s=Object.assign(s,e):s=e,Me.set(t,s)}const Ne=ye.prototype.load;function at(...t){const e=Me.get(this);let s=t[0];const o=new URL(s,window.location.href);if(o.hostname.endsWith("needle.tools")){const r=e?.progressive!==void 0?e.progressive:!0,i=e!=null&&e.usecase?e.usecase:"default";r?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${i}`:this.requestHeader.Accept=`*/*;usecase=${i}`,s=o.toString()}return t[0]=s,Ne?.call(this,...t)}ye.prototype.load=at,re("debugprogressive");function re(t){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function lt(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const s=t.lastIndexOf("/");if(s>=0){const o=t.substring(0,s+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),re("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ce)),ce}function dt(){if(typeof window>"u")return!1;const t=new URL(window.location.href),e=t.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(t.hostname);return t.hostname==="127.0.0.1"||e}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 s=ht(e);s.userData={isRaycastMesh:!0},t[be]=s}}function We(t=!0){if(t){if(oe)return;const e=oe=J.prototype.raycast;J.prototype.raycast=function(s,o){const r=this,i=ee(r);let n;i&&r.isMesh&&(n=r.geometry,r.geometry=i),e.call(this,s,o),n&&(r.geometry=n)}}else{if(!oe)return;J.prototype.raycast=oe,oe=null}}let oe=null;function ht(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,x=re("debugprogressive");let he,Q=-1;if(x){let t=function(){Q+=1,Q>=e&&(Q=-1),console.log(`Toggle LOD level [${Q}]`)},e=6;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(he=!he,console.log(`Toggle wireframe [${he}]`));const o=parseInt(s.key);!isNaN(o)&&o>=0&&(Q=o,console.log(`Set LOD level to [${Q}]`))})}function Fe(t){if(x)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){u(this,"parser"),u(this,"url"),u(this,"_isLoadingMesh"),u(this,"loadMesh",s=>{var o,r;if(this._isLoadingMesh)return null;const i=(r=(o=this.parser.json.meshes[s])==null?void 0:o.extensions)==null?void 0:r[W];return i?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",s).then(n=>{var l;return this._isLoadingMesh=!1,n&&M.registerMesh(this.url,i.guid,n,(l=i.lods)==null?void 0:l.length,0,i),n})):null}),x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return W}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){var e;return((e=this.getAssignedLODInformation(t))==null?void 0:e.index)??-1}static getMaterialMinMaxLODsCount(t,e){const s=this,o="LODS:minmax",r=t[o];if(r!=null)return r;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const n of t)this.getMaterialMinMaxLODsCount(n,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const n=t;for(const l of Object.keys(n.uniforms)){const d=n.uniforms[l].value;d?.isTexture===!0&&i(d,e)}}else if(t.isMaterial)for(const n of Object.keys(t)){const l=t[n];l?.isTexture===!0&&i(l,e)}return t[o]=e,e;function i(n,l){const d=s.getAssignedLODInformation(n);if(d){const a=s.lodInfos.get(d.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let 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 s;if(Array.isArray(t)){for(const i of t)if(this.hasLODLevelAvailable(i,e))return!0;return!1}if(t.isMaterial===!0){for(const i of Object.keys(t)){const n=t[i];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,e))return!0}return!1}else if(t.isGroup===!0){for(const i of t.children)if(i.isMesh===!0&&this.hasLODLevelAvailable(i,e))return!0}let o,r;if(t.isMesh?o=t.geometry:(t.isBufferGeometry||t.isTexture)&&(o=t),o&&(s=o?.userData)!=null&&s.LODS){const i=o.userData.LODS;if(r=this.lodInfos.get(i.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 J||t.isMesh===!0){const o=t.geometry,r=this.getAssignedLODInformation(o);if(!r)return Promise.resolve(null);for(const i of V)(s=i.onBeforeGetLODMesh)==null||s.call(i,t,e);return t["LOD:requested level"]=e,M.getOrLoadLOD(o,e).then(i=>{if(Array.isArray(i)){const n=r.index||0;i=i[n]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],i&&o!=i&&(i?.isBufferGeometry?t.geometry=i:x&&console.error("Invalid LOD geometry",i))),i}).catch(i=>(console.error("Error loading mesh LOD",t,i),null))}else x&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const s=t;if(Array.isArray(s.material)){const o=new Array;for(const r of s.material){const i=this.assignTextureLOD(r,e);o.push(i)}return Promise.all(o).then(r=>{const i=new Array;for(const n of r)Array.isArray(n)&&i.push(...n);return i})}else return this.assignTextureLOD(s.material,e)}if(t.isMaterial===!0){const s=t,o=[],r=new Array;if(s.uniforms&&(s.isRawShaderMaterial||s.isShaderMaterial===!0)){const i=s;for(const n of Object.keys(i.uniforms)){const l=i.uniforms[n].value;if(l?.isTexture===!0){const d=this.assignTextureLODForSlot(l,e,s,n).then(a=>(a&&i.uniforms[n].value!=a&&(i.uniforms[n].value=a,i.uniformsNeedUpdate=!0),a));o.push(d),r.push(n)}}}else for(const i of Object.keys(s)){const n=s[i];if(n?.isTexture===!0){const l=this.assignTextureLODForSlot(n,e,s,i);o.push(l),r.push(i)}}return Promise.all(o).then(i=>{const n=new Array;for(let l=0;l<i.length;l++){const d=i[l],a=r[l];d&&d.isTexture===!0?n.push({material:s,slot:a,texture:d,level:e}):n.push({material:s,slot:a,texture:null,level:e})}return n})}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,o){return t?.isTexture!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):M.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if(r?.isTexture===!0){if(r!=t&&s&&o){const i=s[o];if(i&&!x){const n=this.getAssignedLODInformation(i);if(n&&n?.level<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,e,s,i,r),null}s[o]=r}return r}else x=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(r=>(console.error("Error loading LOD",t,r),null))}afterRoot(t){var e,s;return x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,r)=>{var i;if(o!=null&&o.extensions){const n=o?.extensions[W];if(n){if(!n.lods){x&&console.warn("Texture has no LODs",n);return}let l=!1;for(const d of this.parser.associations.keys())if(d.isTexture===!0){const a=this.parser.associations.get(d);a?.textures===r&&(l=!0,M.registerTexture(this.url,d,(i=n.lods)==null?void 0:i.length,r,n))}l||this.parser.getDependency("texture",r).then(d=>{var a;d&&M.registerTexture(this.url,d,(a=n.lods)==null?void 0:a.length,r,n)})}}}),(s=this.parser.json.meshes)==null||s.forEach((o,r)=>{if(o!=null&&o.extensions){const i=o?.extensions[W];if(i&&i.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const l=this.parser.associations.get(n);l?.meshes===r&&M.registerMesh(this.url,i.guid,n,i.lods.length,l.primitives,i)}}}}),null}static async getOrLoadLOD(t,e){var s,o,r,i;const n=x=="verbose",l=t.userData.LODS;if(!l)return null;const d=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(d)),a){if(e>0){let m=!1;const w=Array.isArray(a.lods);if(w&&e>=a.lods.length?m=!0:w||(m=!0),m)return this.lowresCache.get(d)}const h=Array.isArray(a.lods)?(s=a.lods[e])==null?void 0:s.path:a.lods;if(!h)return x&&!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,w=this.previouslyLoaded.get(m);if(w!==void 0){n&&console.log(`LOD ${e} was already loading/loaded: ${m}`);let L=await w.catch(f=>(console.error(`Error loading LOD ${e} from ${y}
|
|
2
|
+
`,f),null)),p=!1;if(L==null||(L instanceof se&&t instanceof se?(o=L.image)!=null&&o.data||(r=L.source)!=null&&r.data?L=this.copySettings(t,L):(p=!0,this.previouslyLoaded.delete(m)):L instanceof ue&&t instanceof ue&&((i=L.attributes.position)!=null&&i.array||(p=!0,this.previouslyLoaded.delete(m)))),!p)return L}const b=a,G=new Promise(async(L,p)=>{const f=new ye;we(f),x&&(await new Promise(_=>setTimeout(_,1e3)),n&&console.warn("Start loading (delayed) "+y,b.guid));let F=y;if(b&&Array.isArray(b.lods)){const _=b.lods[e];_.hash&&(F+="?v="+_.hash)}const D=await f.loadAsync(F).catch(_=>(console.error(`Error loading LOD ${e} from ${y}
|
|
3
|
+
`,_),null));if(!D)return null;const R=D.parser;n&&console.log("Loading finished "+y,b.guid);let O=0;if(D.parser.json.textures){let _=!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){_=!0;break}}O++}if(_){let c=await R.getDependency("texture",O);return c&&M.assignLODInformation(l.url,c,d,e,void 0),n&&console.log('change "'+t.name+'" \u2192 "'+c.name+'"',y,O,c,m),t instanceof se&&(c=this.copySettings(t,c)),c&&(c.guid=b.guid),L(c)}else x&&console.warn("Could not find texture with guid",b.guid,D.parser.json)}if(O=0,D.parser.json.meshes){let _=!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){_=!0;break}}O++}if(_){const c=await R.getDependency("mesh",O);if(n&&console.log(`Loaded Mesh "${c.name}"`,y,O,c,m),c.isMesh===!0){const g=c.geometry;return M.assignLODInformation(l.url,g,d,e,0),L(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,d,e,S),g.push(I)}}return L(g)}}else x&&console.warn("Could not find mesh with guid",b.guid,D.parser.json)}return L(null)});return this.previouslyLoaded.set(m,G),await G}else if(t instanceof se){n&&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,n&&console.log(a,m)):x&&console.warn("failed loading",y),m}}else x&&console.warn(`Can not load LOD ${e}: no LOD info found for "${d}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,s,o,r){if(!e)return;e.userData||(e.userData={});const i=new gt(t,s,o,r);e.userData.LODS=i}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e?(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 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 r.texture_lod=0}};let
|
|
8
|
-
`,t.getAttribute("src"));let e=null,s=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 P=M;u(P,"registerTexture",(t,e,s,o,r)=>{if(x&&console.log("> Progressive: register texture",o,e.name,e.uuid,e,r),!e){x&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[Oe]=r);const i=r.guid;M.assignLODInformation(t,e,i,s,o),M.lodInfos.set(i,r),M.lowresCache.set(i,e)}),u(P,"registerMesh",(t,e,s,o,r,i)=>{var n;const l=s.geometry;if(!l){x&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),x&&console.log("> Progressive: register mesh "+s.name,{index:r,uuid:s.uuid},i,s),M.assignLODInformation(t,l,e,o,r),M.lodInfos.set(e,i);let d=M.lowresCache.get(e);d?d.push(s.geometry):d=[s.geometry],M.lowresCache.set(e,d),o>0&&!ee(s)&&$e(s,l);for(const a of V)(n=a.onRegisteredNewMesh)==null||n.call(a,s,i)}),u(P,"lodInfos",new Map),u(P,"previouslyLoaded",new Map),u(P,"lowresCache",new Map);class gt{constructor(e,s,o,r){u(this,"url"),u(this,"key"),u(this,"level"),u(this,"index"),this.url=e,this.key=s,this.level=o,r!=null&&(this.index=r)}}class ge{constructor(e,s){u(this,"frame_start"),u(this,"frame_capture_end"),u(this,"ready"),u(this,"_resolve"),u(this,"_signal"),u(this,"_resolved",!1),u(this,"_addedCount",0),u(this,"_resolvedCount",0),u(this,"_awaiting",[]),u(this,"_maxPromisesPerObject",1),u(this,"_currentFrame",0),u(this,"_seen",new WeakMap);var o;const r=Math.max(s.frames??2,2);this.frame_start=e,this.frame_capture_end=e+r,this.ready=new Promise(i=>{this._resolve=i}),this.ready.finally(()=>{this._resolved=!0,this._awaiting.length=0}),this._signal=s.signal,(o=this._signal)==null||o.addEventListener("abort",()=>{this.resolveNow()}),this._maxPromisesPerObject=Math.max(1,s.maxPromisesPerObject??1)}get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}update(e){var s;this._currentFrame=e,((s=this._signal)!=null&&s.aborted||this._currentFrame>this.frame_capture_end&&this._awaiting.length===0)&&this.resolveNow()}add(e,s,o){if(this._resolved){x&&console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}if(!(this._currentFrame>this.frame_capture_end)){if(this._maxPromisesPerObject>=1)if(this._seen.has(s)){let r=this._seen.get(s);if(r>=this._maxPromisesPerObject){x&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(s,r+1)}else this._seen.set(s,1);this._awaiting.push(o),this._addedCount++,o.finally(()=>{this._resolvedCount++,this._awaiting.splice(this._awaiting.indexOf(o),1)})}}resolveNow(){var e,s;this._resolved||(s=this._resolve)==null||s.call(this,{awaited_count:this._addedCount,resolved_count:this._resolvedCount,cancelled:((e=this._signal)==null?void 0:e.aborted)??!1})}}u(ge,"addPromise",(t,e,s,o)=>{o.forEach(r=>{r.add(t,e,s)})});const N=re("debugprogressive"),ft=re("noprogressive"),Se=Symbol("Needle:LODSManager"),Pe=Symbol("Needle:LODState"),q=Symbol("Needle:CurrentLOD"),T={mesh_lod:-1,texture_lod:-1};var A,X,Te,K,ie,fe,H;const E=class{constructor(t,e){u(this,"renderer"),u(this,"context"),u(this,"projectionScreenMatrix",new Ce),u(this,"targetTriangleDensity",2e5),u(this,"skinnedMeshAutoUpdateBoundsInterval",30),u(this,"updateInterval","auto"),Y(this,A,1),u(this,"pause",!1),u(this,"manual",!1),u(this,"_newPromiseGroups",[]),u(this,"_promiseGroupIds",0),u(this,"_lodchangedlisteners",[]),Y(this,X,void 0),Y(this,Te,new Ze),Y(this,K,0),Y(this,ie,0),Y(this,fe,0),Y(this,H,0),u(this,"_fpsBuffer",[60,60,60,60,60]),u(this,"_sphere",new tt),u(this,"_tempBox",new Ie),u(this,"_tempBox2",new Ie),u(this,"tempMatrix",new Ce),u(this,"_tempWorldPosition",new z),u(this,"_tempBoxSize",new z),u(this,"_tempBox2Size",new z),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Pe]}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 s=new E(t,{engine:"unknown",...e});return t[Se]=s,s}get plugins(){return V}awaitLoading(t){const e=this._promiseGroupIds++,s=new ge(v(this,K),{...t});this._newPromiseGroups.push(s);const o=performance.now();return s.ready.finally(()=>{const r=this._newPromiseGroups.indexOf(s);r>=0&&(this._newPromiseGroups.splice(r,1),dt()&&performance.measure("LODsManager:awaitLoading",{start:o,detail:{id:e,name:t?.name,awaited:s.awaitedCount,resolved:s.resolvedCount}}))}),s.ready}_postprocessPromiseGroups(){if(this._newPromiseGroups.length!==0)for(let t=this._newPromiseGroups.length-1;t>=0;t--)this._newPromiseGroups[t].update(v(this,K))}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const s=this._lodchangedlisteners.indexOf(e);s>=0&&this._lodchangedlisteners.splice(s,1)}}enable(){if(v(this,X))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;U(this,X,this.renderer.render);const e=this;_e(this.renderer),this.renderer.render=function(s,o){const r=e.renderer.getRenderTarget();(r==null||"isXRRenderTarget"in r&&r.isXRRenderTarget)&&(t=0,U(e,K,v(e,K)+1),U(e,ie,v(e,Te).getDelta()),U(e,fe,v(e,fe)+v(e,ie)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/v(e,ie)),U(e,H,e._fpsBuffer.reduce((n,l)=>n+l)/e._fpsBuffer.length),N&&v(e,K)%200===0&&console.log("FPS",Math.round(v(e,H)),"Interval:",v(e,A)));const i=t++;v(e,X).call(this,s,o),e.onAfterRender(s,o,i)}}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,s){if(this.pause)return;const o=this.renderer.renderLists.get(t,0).opaque;let r=!0;if(o.length===1){const i=o[0].material;(i.name==="EffectMaterial"||i.name==="CopyShader")&&(r=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(r=!1),r){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 s,o;const r=this.renderer.renderLists.get(t,0),i=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const n=this.targetTriangleDensity;for(const a of i){if(a.material&&(((s=a.geometry)==null?void 0:s.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,n)}const l=r.transparent;for(const a of l){const h=a.object;(h instanceof J||h.isMesh)&&this.updateLODs(t,e,h,n)}const d=r.transmissive;for(const a of d){const h=a.object;(h instanceof J||h.isMesh)&&this.updateLODs(t,e,h,n)}}updateLODs(t,e,s,o){var r,i;s.userData||(s.userData={});let n=s[Pe];if(n||(n=new mt,s[Pe]=n),n.frames++<2)return;for(const d of V)(r=d.onBeforeUpdateLOD)==null||r.call(d,this.renderer,t,e,s);const l=E.overrideGlobalLodLevel!==void 0?E.overrideGlobalLodLevel:Q;l>=0?(T.mesh_lod=l,T.texture_lod=l):(this.calculateLodLevel(e,s,n,o,T),T.mesh_lod=Math.round(T.mesh_lod),T.texture_lod=Math.round(T.texture_lod)),T.mesh_lod>=0&&this.loadProgressiveMeshes(s,T.mesh_lod),s.material&&T.texture_lod>=0&&this.loadProgressiveTextures(s.material,T.texture_lod),x&&s.material&&!s.isGizmo&&Fe(s.material);for(const d of V)(i=d.onAfterUpdatedLOD)==null||i.call(d,this.renderer,t,e,s,T);n.lastLodLevel_Mesh=T.mesh_lod,n.lastLodLevel_Texture=T.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 o=t["DEBUG:LOD"];if(o!=null&&(s=t[q]!=o,e=o),s){t[q]=e;const r=P.assignTextureLOD(t,e).then(i=>{this._lodchangedlisteners.forEach(n=>n({type:"texture",level:e,object:t}))});ge.addPromise("texture",t,r,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let s=t[q]!==e;const o=t["DEBUG:LOD"];if(o!=null&&(s=t[q]!=o,e=o),s){t[q]=e;const r=t.geometry,i=P.assignMeshLOD(t,e).then(n=>(n&&t[q]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(l=>l({type:"mesh",level:e,object:t})),n));return ge.addPromise("mesh",t,i,this._newPromiseGroups),i}return Promise.resolve(null)}static isInside(t,e){const s=t.min,o=t.max,r=(s.x+o.x)*.5,i=(s.y+o.y)*.5;return this._tempPtInside.set(r,i,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,o,r){var i,n,l;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let d=10+1,a=!1;if(N&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const h=(i=P.getMeshLODExtension(e.geometry))==null?void 0:i.lods,y=P.getPrimitiveIndex(e.geometry),m=h&&h.length>0,w=P.getMaterialMinMaxLODsCount(e.material),b=w?.min_count!=1/0&&w.min_count>0&&w.max_count>0;if(!m&&!b){r.mesh_lod=0,r.texture_lod=0;return}m||(a=!0,d=0);const G=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let L=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=ee(p),F=p.geometry;f&&(p.geometry=f),p.computeBoundingBox(),p.geometry=F}L=p.boundingBox}if(L){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(L),this._tempBox.applyMatrix4(e.matrixWorld),p.isPerspectiveCamera&&E.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,C=c.y,I=g.x,te=g.y;const ne=2,ve=1.5,ae=(c.x+g.x)*.5,le=(c.y+g.y)*.5;S=(S-ae)*ne+ae,C=(C-le)*ne+le,I=(I-ae)*ne+ae,te=(te-le)*ne+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)),xe=Math.max(Ke,He);s.lastCentrality=(ve-xe)*(ve-xe)*(ve-xe)}else s.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(L),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)),s.lastScreenCoverage=Math.max(f.x,f.y,f.z),s.lastScreenspaceVolume.copy(f),s.lastScreenCoverage*=s.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 _=999;if(h&&s.lastScreenCoverage>0)for(let c=0;c<h.length;c++){const g=h[c];if((((n=g.densities)==null?void 0:n[y])||g.density||1e-5)/s.lastScreenCoverage<o){_=c;break}}_<d&&(d=_,a=!0)}if(a?r.mesh_lod=d: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=w.max_count-1,N){const f=w.lods[w.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 F=s.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=w.lods.length-1;O>=0;O--){const _=w.lods[O];if(!(p&&_.max_height>=2048)&&!(ut()&&_.max_height>4096)&&(_.max_height>D||!R&&O===0)){if(R=!0,r.texture_lod=O,r.texture_lod<s.lastLodLevel_Texture){const c=_.max_height;N&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} \u2192 ${r.texture_lod} = ${c}px
|
|
6
|
+
Screensize: ${D.toFixed(0)}px, Coverage: ${(100*s.lastScreenCoverage).toFixed(2)}%, Volume ${f.toFixed(1)}
|
|
7
|
+
${e.name}`)}break}}}}else r.texture_lod=0}};let B=E;A=new WeakMap,X=new WeakMap,Te=new WeakMap,K=new WeakMap,ie=new WeakMap,fe=new WeakMap,H=new WeakMap,u(B,"debugDrawLine"),u(B,"overrideGlobalLodLevel"),u(B,"corner0",new z),u(B,"corner1",new z),u(B,"corner2",new z),u(B,"corner3",new z),u(B,"_tempPtInside",new z);class mt{constructor(){u(this,"frames",0),u(this,"lastLodLevel_Mesh",-1),u(this,"lastLodLevel_Texture",-1),u(this,"lastScreenCoverage",0),u(this,"lastScreenspaceVolume",new z),u(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(s=>{s.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,s=null,o=null;for(let r=t;r!=null;r=Object.getPrototypeOf(r)){const i=Object.getOwnPropertySymbols(r),n=i.find(a=>a.toString()=="Symbol(renderer)"),l=i.find(a=>a.toString()=="Symbol(scene)"),d=i.find(a=>a.toString()=="Symbol(needsRender)");!e&&n!=null&&(e=t[n].threeRenderer),!s&&l!=null&&(s=t[l]),!o&&d!=null&&(o=t[d])}if(e&&s){let r=function(){if(o){let n=0,l=setInterval(()=>{if(n++>5){clearInterval(l);return}o?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const i=B.get(e,{engine:"model-viewer"});return B.addPlugin(new xt),i.enable(),i.addEventListener("changed",()=>{o?.call(t)}),t.addEventListener("model-visibility",n=>{n.detail.visible&&o?.call(t)}),t.addEventListener("load",()=>{r()}),()=>{i.disable()}}return null}class xt{constructor(){u(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(e,s,o,r){this.tryParseMeshLOD(s,r),this.tryParseTextureLOD(s,r)}getUrl(e){if(!e)return null;let s=e.getAttribute("src");return s||(s=e.src),s||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),s}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,s){if(s[me]==!0)return;s[me]=!0;const o=this.tryGetCurrentGLTF(e),r=this.tryGetCurrentModelViewer(e),i=this.getUrl(r);if(i&&o&&s.material){let n=function(d){var a,h,y;if(d[me]==!0)return;d[me]=!0,d.userData&&(d.userData.LOD=-1);const m=Object.keys(d);for(let w=0;w<m.length;w++){const b=m[w],G=d[b];if(G?.isTexture===!0){const L=(h=(a=G.userData)==null?void 0:a.associations)==null?void 0:h.textures;if(L==null)continue;const p=o.parser.json.textures[L];if(!p){console.warn("Texture data not found for texture index "+L);continue}if((y=p?.extensions)!=null&&y[W]){const f=p.extensions[W];f&&i&&P.registerTexture(i,G,f.lods.length,L,f)}}}};const l=s.material;if(Array.isArray(l))for(const d of l)n(d);else n(l)}}tryParseMeshLOD(e,s){var o,r;if(s[Ue]==!0)return;s[Ue]=!0;const i=this.tryGetCurrentModelViewer(e),n=this.getUrl(i);if(!n)return;const l=(r=(o=s.userData)==null?void 0:o.gltfExtensions)==null?void 0:r[W];if(l&&n){const d=s.uuid;P.registerMesh(n,d,s,0,l.lods.length,l)}}}function Xe(t,e,s,o){_e(e),we(s),De(s,{progressive:!0,...o?.hints}),s.register(i=>new P(i,t));const r=B.get(e);return o?.enableLODsManager!==!1&&r.enable(),r}if(Ae(),!ct){const t={gltfProgressive:{useNeedleProgressive:Xe,LODsManager:B,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,B as LODsManager,P as NEEDLE_progressive,ke as VERSION,we as addDracoAndKTX2Loaders,De as configureLoader,_e 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
|
-
`,y),null)),
|
|
3
|
-
`,b),null));if(!
|
|
1
|
+
"use strict";var je=Object.defineProperty;var He=(n,t,e)=>t in n?je(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var c=(n,t,e)=>(He(n,typeof t!="symbol"?t+"":t,e),e),Ge=(n,t,e)=>{if(!t.has(n))throw TypeError("Cannot "+e)};var m=(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,s)=>(Ge(n,t,"write to private field"),s?s.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/",se="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const et=X,tt=se,Fe=new URL(X+"draco_decoder.js");Fe.searchParams.append("range","true");fetch(Fe,{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&&$e("./include/draco/"),se===tt&&Ne("./include/ktx2/")}).finally(()=>{Ue()});function $e(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){se=n,U&&U.transcoderPath!=se?(console.debug("Updating KTX2 transcoder path to "+n),U.setTranscoderPath(se),U.init()):console.debug("Setting KTX2 transcoder path to "+n)}const Oe=Symbol("dracoDecoderPath");let I,me,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(se),U.init()),me||(me=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:me}}function Ae(n){n.dracoLoader||n.setDRACOLoader(I),n.ktx2Loader||n.setKTX2Loader(U),n.meshoptDecoder||n.setMeshoptDecoder(me)}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 st(...n){const t=be.get(this);let e=n[0];const s=new URL(e,window.location.href);if(s.hostname.endsWith("needle.tools")){const r=(t==null?void 0:t.progressive)!==void 0?t.progressive:!0,o=t!=null&&t.usecase?t.usecase:"default";r?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${o}`:this.requestHeader.Accept=`*/*;usecase=${o}`,e=s.toString()}return n[0]=e,we==null?void 0:we.call(this,...n)}Te.GLTFLoader.prototype.load=st;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 s=n.substring(0,e+1);for(;s.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return s+t}return t}let ne;function ot(){return ne!==void 0||(ne=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ce("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 s=at(t);s.userData={isRaycastMesh:!0},n[Se]=s}}function ze(n=!0){if(n){if(ae)return;const t=ae=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,s){const i=this,r=oe(i);let o;r&&i.isMesh&&(o=i.geometry,i.geometry=r),t.call(this,e,s),o&&(i.geometry=o)}}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,L=ce("debugprogressive");let ge,te=-1;if(L){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 s=parseInt(e.key);!isNaN(s)&&s>=0&&(te=s,console.log(`Set LOD level to [${te}]`))})}function We(n){if(L)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){c(this,"parser");c(this,"url");c(this,"_isLoadingMesh");c(this,"loadMesh",t=>{var s,i;if(this._isLoadingMesh)return null;const e=(i=(s=this.parser.json.meshes[t])==null?void 0:s.extensions)==null?void 0:i[q];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>{var o;return this._isLoadingMesh=!1,r&&S.registerMesh(this.url,e.guid,r,(o=e.lods)==null?void 0:o.length,0,e),r})):null});L&&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 s;const e=(s=this.getAssignedLODInformation(t))==null?void 0:s.index;return e??-1}static getMaterialMinMaxLODsCount(t,e){const s=this,i="LODS:minmax",r=t[i];if(r!=null)return r;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const a of t)this.getMaterialMinMaxLODsCount(a,e);return t[i]=e,e}if(L==="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&&o(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const l=t[a];(l==null?void 0:l.isTexture)===!0&&o(l,e)}return t[i]=e,e;function o(a,l){const u=s.getAssignedLODInformation(a);if(u){const d=s.lodInfos.get(u.key);if(d&&d.lods){l.min_count=Math.min(l.min_count,d.lods.length),l.max_count=Math.max(l.max_count,d.lods.length);for(let h=0;h<d.lods.length;h++){const g=d.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 r;if(Array.isArray(t)){for(const o of t)if(this.hasLODLevelAvailable(o,e))return!0;return!1}if(t.isMaterial===!0){for(const o of Object.keys(t)){const a=t[o];if(a&&a.isTexture&&this.hasLODLevelAvailable(a,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 s,i;if(t.isMesh?s=t.geometry:(t.isBufferGeometry||t.isTexture)&&(s=t),s&&(r=s==null?void 0:s.userData)!=null&&r.LODS){const o=s.userData.LODS;if(i=this.lodInfos.get(o.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 s;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const i=t.geometry,r=this.getAssignedLODInformation(i);if(!r)return Promise.resolve(null);for(const o of Z)(s=o.onBeforeGetLODMesh)==null||s.call(o,t,e);return t["LOD:requested level"]=e,S.getOrLoadLOD(i,e).then(o=>{if(Array.isArray(o)){const a=r.index||0;o=o[a]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],o&&i!=o&&((o==null?void 0: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 i=new Array;for(const r of s.material){const o=this.assignTextureLOD(r,e);i.push(o)}return Promise.all(i).then(r=>{const o=new Array;for(const a of r)Array.isArray(a)&&o.push(...a);return o})}else return this.assignTextureLOD(s.material,e)}if(t.isMaterial===!0){const s=t,i=[],r=new Array;if(s.uniforms&&(s.isRawShaderMaterial||s.isShaderMaterial===!0)){const o=s;for(const a of Object.keys(o.uniforms)){const l=o.uniforms[a].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,s,a).then(d=>(d&&o.uniforms[a].value!=d&&(o.uniforms[a].value=d,o.uniformsNeedUpdate=!0),d));i.push(u),r.push(a)}}}else for(const o of Object.keys(s)){const a=s[o];if((a==null?void 0:a.isTexture)===!0){const l=this.assignTextureLODForSlot(a,e,s,o);i.push(l),r.push(o)}}return Promise.all(i).then(o=>{const a=new Array;for(let l=0;l<o.length;l++){const u=o[l],d=r[l];u&&u.isTexture===!0?a.push({material:s,slot:d,texture:u,level:e}):a.push({material:s,slot:d,texture:null,level:e})}return a})}if(t instanceof p.Texture||t.isTexture===!0){const s=t;return this.assignTextureLODForSlot(s,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,s,i){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):i==="glyphMap"?Promise.resolve(t):S.getOrLoadLOD(t,e).then(r=>{if(Array.isArray(r))return null;if((r==null?void 0:r.isTexture)===!0){if(r!=t&&s&&i){const o=s[i];if(o&&!L){const a=this.getAssignedLODInformation(o);if(a&&(a==null?void 0:a.level)<e)return L==="verbose"&&console.warn("Assigned texture level is already higher: ",a.level,e,s,o,r),null}s[i]=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((i,r)=>{var o;if(i!=null&&i.extensions){const a=i==null?void 0:i.extensions[q];if(a){if(!a.lods){L&&console.warn("Texture has no LODs",a);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const d=this.parser.associations.get(u);(d==null?void 0:d.textures)===r&&(l=!0,S.registerTexture(this.url,u,(o=a.lods)==null?void 0:o.length,r,a))}l||this.parser.getDependency("texture",r).then(u=>{var d;u&&S.registerTexture(this.url,u,(d=a.lods)==null?void 0:d.length,r,a)})}}}),(s=this.parser.json.meshes)==null||s.forEach((i,r)=>{if(i!=null&&i.extensions){const o=i==null?void 0:i.extensions[q];if(o&&o.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const l=this.parser.associations.get(a);(l==null?void 0:l.meshes)===r&&S.registerMesh(this.url,o.guid,a,o.lods.length,l.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var a,l,u,d;const s=L=="verbose",i=t.userData.LODS;if(!i)return null;const r=i==null?void 0:i.key;let o;if(t.isTexture===!0){const h=t;h.source&&h.source[ve]&&(o=h.source[ve])}if(o||(o=S.lodInfos.get(r)),o){if(e>0){let w=!1;const O=Array.isArray(o.lods);if(O&&e>=o.lods.length?w=!0:O||(w=!0),w)return this.lowresCache.get(r)}const h=Array.isArray(o.lods)?(a=o.lods[e])==null?void 0:a.path:o.lods;if(!h)return L&&!o["missing:uri"]&&(o["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,o)),null;const g=rt(i.url,h);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!o.guid)return console.warn("missing pointer for glb/gltf texture",o),null;const w=g+"_"+o.guid,O=this.previouslyLoaded.get(w);if(O!==void 0){s&&console.log(`LOD ${e} was already loading/loaded: ${w}`);let v=await O.catch(y=>(console.error(`Error loading LOD ${e} from ${g}
|
|
2
|
+
`,y),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&&((d=v.attributes.position)!=null&&d.array||(D=!0,this.previouslyLoaded.delete(w)))),!D)return v}const _=o,V=new Promise(async(v,D)=>{const y=new Te.GLTFLoader;Ae(y),L&&(await new Promise(b=>setTimeout(b,1e3)),s&&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 y.loadAsync(Y).catch(b=>(console.error(`Error loading LOD ${e} from ${g}
|
|
3
|
+
`,b),null));if(!C)return null;const F=C.parser;s&&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 F.getDependency("texture",k);return f&&S.assignLODInformation(i.url,f,r,e,void 0),s&&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 L&&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 F.getDependency("mesh",k);if(s&&console.log(`Loaded Mesh "${f.name}"`,g,k,f,w),f.isMesh===!0){const T=f.geometry;return S.assignLODInformation(i.url,T,r,e,0),v(T)}else{const T=new Array;for(let x=0;x<f.children.length;x++){const M=f.children[x];if(M.isMesh===!0){const E=M.geometry;S.assignLODInformation(i.url,E,r,e,x),T.push(E)}}return v(T)}}else L&&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){s&&console.log("Load texture from uri: "+g);const O=await new p.TextureLoader().loadAsync(g);return O?(O.guid=o.guid,O.flipY=!1,O.needsUpdate=!0,O.colorSpace=t.colorSpace,s&&console.log(o,O)):L&&console.warn("failed loading",g),O}}else L&&console.warn(`Can not load LOD ${e}: no LOD info found for "${r}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,s,i,r){if(!e)return;e.userData||(e.userData={});const o=new lt(t,s,i,r);e.userData.LODS=o}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?(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 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: ${
|
|
7
|
-
${e.name}`)}break}}}}else
|
|
8
|
-
`,n.getAttribute("src"));let t=null,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 P=S;c(P,"registerTexture",(t,e,s,i,r)=>{if(L&&console.log("> Progressive: register texture",i,e.name,e.uuid,e,r),!e){L&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ve]=r);const o=r.guid;S.assignLODInformation(t,e,o,s,i),S.lodInfos.set(o,r),S.lowresCache.set(o,e)}),c(P,"registerMesh",(t,e,s,i,r,o)=>{var u;const a=s.geometry;if(!a){L&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),L&&console.log("> Progressive: register mesh "+s.name,{index:r,uuid:s.uuid},o,s),S.assignLODInformation(t,a,e,i,r),S.lodInfos.set(e,o);let l=S.lowresCache.get(e);l?l.push(s.geometry):l=[s.geometry],S.lowresCache.set(e,l),i>0&&!oe(s)&&Ve(s,a);for(const d of Z)(u=d.onRegisteredNewMesh)==null||u.call(d,s,o)}),c(P,"lodInfos",new Map),c(P,"previouslyLoaded",new Map),c(P,"lowresCache",new Map);class lt{constructor(t,e,s,i){c(this,"url");c(this,"key");c(this,"level");c(this,"index");this.url=t,this.key=e,this.level=s,i!=null&&(this.index=i)}}class pe{constructor(t,e){c(this,"frame_start");c(this,"frame_capture_end");c(this,"ready");c(this,"_resolve");c(this,"_signal");c(this,"_resolved",!1);c(this,"_addedCount",0);c(this,"_resolvedCount",0);c(this,"_awaiting",[]);c(this,"_maxPromisesPerObject",1);c(this,"_currentFrame",0);c(this,"_seen",new WeakMap);var r;const i=Math.max(e.frames??2,2);this.frame_start=t,this.frame_capture_end=t+i,this.ready=new Promise(o=>{this._resolve=o}),this.ready.finally(()=>{this._resolved=!0,this._awaiting.length=0}),this._signal=e.signal,(r=this._signal)==null||r.addEventListener("abort",()=>{this.resolveNow()}),this._maxPromisesPerObject=Math.max(1,e.maxPromisesPerObject??1)}get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}update(t){var e;this._currentFrame=t,((e=this._signal)!=null&&e.aborted||this._currentFrame>this.frame_capture_end&&this._awaiting.length===0)&&this.resolveNow()}add(t,e,s){if(this._resolved){L&&console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}if(!(this._currentFrame>this.frame_capture_end)){if(this._maxPromisesPerObject>=1)if(this._seen.has(e)){let i=this._seen.get(e);if(i>=this._maxPromisesPerObject){L&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(e,i+1)}else this._seen.set(e,1);this._awaiting.push(s),this._addedCount++,s.finally(()=>{this._resolvedCount++,this._awaiting.splice(this._awaiting.indexOf(s),1)})}}resolveNow(){var t,e;this._resolved||(e=this._resolve)==null||e.call(this,{awaited_count:this._addedCount,resolved_count:this._resolvedCount,cancelled:((t=this._signal)==null?void 0:t.aborted)??!1})}}c(pe,"addPromise",(t,e,s,i)=>{i.forEach(r=>{r.add(t,e,s)})});const N=ce("debugprogressive"),ct=ce("noprogressive"),Me=Symbol("Needle:LODSManager"),De=Symbol("Needle:LODState"),Q=Symbol("Needle:CurrentLOD"),G={mesh_lod:-1,texture_lod:-1};var R,j,ye,ee,re,Le,H;const A=class{constructor(t,e){c(this,"renderer");c(this,"context");c(this,"projectionScreenMatrix",new p.Matrix4);c(this,"targetTriangleDensity",2e5);c(this,"skinnedMeshAutoUpdateBoundsInterval",30);c(this,"updateInterval","auto");J(this,R,1);c(this,"pause",!1);c(this,"manual",!1);c(this,"_newPromiseGroups",[]);c(this,"_promiseGroupIds",0);c(this,"_lodchangedlisteners",[]);J(this,j,void 0);J(this,ye,new p.Clock);J(this,ee,0);J(this,re,0);J(this,Le,0);J(this,H,0);c(this,"_fpsBuffer",[60,60,60,60,60]);c(this,"_sphere",new p.Sphere);c(this,"_tempBox",new p.Box3);c(this,"_tempBox2",new p.Box3);c(this,"tempMatrix",new p.Matrix4);c(this,"_tempWorldPosition",new p.Vector3);c(this,"_tempBoxSize",new p.Vector3);c(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 s=new A(t,{engine:"unknown",...e});return t[Me]=s,s}get plugins(){return Z}awaitLoading(t){const e=this._promiseGroupIds++,s=new pe(m(this,ee),{...t});this._newPromiseGroups.push(s);const i=performance.now();return s.ready.finally(()=>{const r=this._newPromiseGroups.indexOf(s);r>=0&&(this._newPromiseGroups.splice(r,1),it()&&performance.measure("LODsManager:awaitLoading",{start:i,detail:{id:e,name:t==null?void 0:t.name,awaited:s.awaitedCount,resolved:s.resolvedCount}}))}),s.ready}_postprocessPromiseGroups(){if(this._newPromiseGroups.length!==0)for(let t=this._newPromiseGroups.length-1;t>=0;t--)this._newPromiseGroups[t].update(m(this,ee))}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(m(this,j))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;W(this,j,this.renderer.render);const e=this;Pe(this.renderer),this.renderer.render=function(s,i){const r=e.renderer.getRenderTarget();(r==null||"isXRRenderTarget"in r&&r.isXRRenderTarget)&&(t=0,W(e,ee,m(e,ee)+1),W(e,re,m(e,ye).getDelta()),W(e,Le,m(e,Le)+m(e,re)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/m(e,re)),W(e,H,e._fpsBuffer.reduce((a,l)=>a+l)/e._fpsBuffer.length),N&&m(e,ee)%200===0&&console.log("FPS",Math.round(m(e,H)),"Interval:",m(e,R)));const o=t++;m(e,j).call(this,s,i),e.onAfterRender(s,i,o)}}disable(){m(this,j)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=m(this,j),W(this,j,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,s){if(this.pause)return;const r=this.renderer.renderLists.get(t,0).opaque;let o=!0;if(r.length===1){const a=r[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(o=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(o=!1),o){if(ct||(this.updateInterval==="auto"?m(this,H)<40&&m(this,R)<10?(W(this,R,m(this,R)+1),N&&console.warn("↓ Reducing LOD updates",m(this,R),m(this,H).toFixed(0))):m(this,H)>=60&&m(this,R)>1&&(W(this,R,m(this,R)-1),N&&console.warn("↑ Increasing LOD updates",m(this,R),m(this,H).toFixed(0))):W(this,R,this.updateInterval),m(this,R)>0&&m(this,ee)%m(this,R)!=0))return;this.internalUpdate(t,e),this._postprocessPromiseGroups()}}internalUpdate(t,e){var l,u;const s=this.renderer.renderLists.get(t,0),i=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const r=this.targetTriangleDensity;for(const d of i){if(d.material&&(((l=d.geometry)==null?void 0:l.type)==="BoxGeometry"||((u=d.geometry)==null?void 0:u.type)==="BufferGeometry")&&(d.material.name==="SphericalGaussianBlur"||d.material.name=="BackgroundCubeMaterial"||d.material.name==="CubemapFromEquirect"||d.material.name==="EquirectangularToCubeUV")){N&&(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(d.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",d,d.material.name,d.material.type)));continue}switch(d.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(N==="color"&&d.material&&!d.object.progressive_debug_color){d.object.progressive_debug_color=!0;const g=Math.random()*16777215,w=new p.MeshStandardMaterial({color:g});d.object.material=w}const h=d.object;(h instanceof p.Mesh||h.isMesh)&&this.updateLODs(t,e,h,r)}const o=s.transparent;for(const d of o){const h=d.object;(h instanceof p.Mesh||h.isMesh)&&this.updateLODs(t,e,h,r)}const a=s.transmissive;for(const d of a){const h=d.object;(h instanceof p.Mesh||h.isMesh)&&this.updateLODs(t,e,h,r)}}updateLODs(t,e,s,i){var a,l;s.userData||(s.userData={});let r=s[De];if(r||(r=new dt,s[De]=r),r.frames++<2)return;for(const u of Z)(a=u.onBeforeUpdateLOD)==null||a.call(u,this.renderer,t,e,s);const o=A.overrideGlobalLodLevel!==void 0?A.overrideGlobalLodLevel:te;o>=0?(G.mesh_lod=o,G.texture_lod=o):(this.calculateLodLevel(e,s,r,i,G),G.mesh_lod=Math.round(G.mesh_lod),G.texture_lod=Math.round(G.texture_lod)),G.mesh_lod>=0&&this.loadProgressiveMeshes(s,G.mesh_lod),s.material&&G.texture_lod>=0&&this.loadProgressiveTextures(s.material,G.texture_lod),L&&s.material&&!s.isGizmo&&We(s.material);for(const u of Z)(l=u.onAfterUpdatedLOD)==null||l.call(u,this.renderer,t,e,s,G);r.lastLodLevel_Mesh=G.mesh_lod,r.lastLodLevel_Texture=G.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 i=t["DEBUG:LOD"];if(i!=null&&(s=t[Q]!=i,e=i),s){t[Q]=e;const r=P.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(a=>a({type:"texture",level:e,object:t}))});pe.addPromise("texture",t,r,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let s=t[Q]!==e;const i=t["DEBUG:LOD"];if(i!=null&&(s=t[Q]!=i,e=i),s){t[Q]=e;const r=t.geometry,o=P.assignMeshLOD(t,e).then(a=>(a&&t[Q]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(l=>l({type:"mesh",level:e,object:t})),a));return pe.addPromise("mesh",t,o,this._newPromiseGroups),o}return Promise.resolve(null)}static isInside(t,e){const s=t.min,i=t.max,r=(s.x+i.x)*.5,o=(s.y+i.y)*.5;return this._tempPtInside.set(r,o,s.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,s,i,r){var V,K,v;if(!e){r.mesh_lod=-1,r.texture_lod=-1;return}if(!t){r.mesh_lod=-1,r.texture_lod=-1;return}let a=10+1,l=!1;if(N&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=(V=P.getMeshLODExtension(e.geometry))==null?void 0:V.lods,d=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){r.mesh_lod=0,r.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&&s.frames%this.skinnedMeshAutoUpdateBoundsInterval===0){const y=oe(D),Y=D.geometry;y&&(D.geometry=y),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 x=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(x)){r.mesh_lod=0,r.texture_lod=0;return}}if(this._tempBox.copy(_),this._tempBox.applyMatrix4(e.matrixWorld),D.isPerspectiveCamera&&A.isInside(this._tempBox,this.projectionScreenMatrix)){r.mesh_lod=0,r.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&D.isPerspectiveCamera&&D.fov>70){const x=this._tempBox.min,M=this._tempBox.max;let E=x.x,$=x.y,z=M.x,ie=M.y;const de=2,xe=1.5,ue=(x.x+M.x)*.5,fe=(x.y+M.y)*.5;E=(E-ue)*de+ue,$=($-fe)*de+fe,z=(z-ue)*de+ue,ie=(ie-fe)*de+fe;const Ke=E<0&&z>0?0:Math.min(Math.abs(x.x),Math.abs(M.x)),Ye=$<0&&ie>0?0:Math.min(Math.abs(x.y),Math.abs(M.y)),_e=Math.max(Ke,Ye);s.lastCentrality=(xe-_e)*(xe-_e)*(xe-_e)}else s.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,C=this._tempBox2;C.copy(_),C.applyMatrix4(e.matrixWorld),C.applyMatrix4(Y);const F=C.getSize(this._tempBox2Size),k=Math.max(F.x,F.y);if(Math.max(y.x,y.y)!=0&&k!=0&&(y.z=F.z/Math.max(F.x,F.y)*Math.max(y.x,y.y)),s.lastScreenCoverage=Math.max(y.x,y.y,y.z),s.lastScreenspaceVolume.copy(y),s.lastScreenCoverage*=s.lastCentrality,N&&A.debugDrawLine){const x=this.tempMatrix.copy(this.projectionScreenMatrix);x.invert();const M=A.corner0,E=A.corner1,$=A.corner2,z=A.corner3;M.copy(this._tempBox.min),E.copy(this._tempBox.max),E.x=M.x,$.copy(this._tempBox.max),$.y=M.y,z.copy(this._tempBox.max);const ie=(M.z+z.z)*.5;M.z=E.z=$.z=z.z=ie,M.applyMatrix4(x),E.applyMatrix4(x),$.applyMatrix4(x),z.applyMatrix4(x),A.debugDrawLine(M,E,255),A.debugDrawLine(M,$,255),A.debugDrawLine(E,z,255),A.debugDrawLine($,z,255)}let f=999;if(u&&s.lastScreenCoverage>0)for(let x=0;x<u.length;x++){const M=u[x];if((((K=M.densities)==null?void 0:K[d])||M.density||1e-5)/s.lastScreenCoverage<i){f=x;break}}f<a&&(a=f,l=!0)}if(l?r.mesh_lod=a:r.mesh_lod=s.lastLodLevel_Mesh,N&&r.mesh_lod!=s.lastLodLevel_Mesh){const y=u==null?void 0:u[r.mesh_lod];y&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${r.mesh_lod} (${y.density.toFixed(0)}) - ${e.name}`)}if(w){const D="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(s.lastLodLevel_Texture<0){if(r.texture_lod=g.max_count-1,N){const y=g.lods[g.max_count-1];N&&console.log(`First Texture LOD ${r.texture_lod} (${y.max_height}px) - ${e.name}`)}}else{const y=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let Y=s.lastScreenCoverage*4;((v=this.context)==null?void 0:v.engine)==="model-viewer"&&(Y*=1.5);const F=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>F||!k&&b===0)){if(k=!0,r.texture_lod=b,r.texture_lod<s.lastLodLevel_Texture){const T=f.max_height;N&&console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${r.texture_lod} = ${T}px
|
|
6
|
+
Screensize: ${F.toFixed(0)}px, Coverage: ${(100*s.lastScreenCoverage).toFixed(2)}%, Volume ${y.toFixed(1)}
|
|
7
|
+
${e.name}`)}break}}}}else r.texture_lod=0}};let B=A;R=new WeakMap,j=new WeakMap,ye=new WeakMap,ee=new WeakMap,re=new WeakMap,Le=new WeakMap,H=new WeakMap,c(B,"debugDrawLine"),c(B,"overrideGlobalLodLevel"),c(B,"corner0",new p.Vector3),c(B,"corner1",new p.Vector3),c(B,"corner2",new p.Vector3),c(B,"corner3",new p.Vector3),c(B,"_tempPtInside",new p.Vector3);class dt{constructor(){c(this,"frames",0);c(this,"lastLodLevel_Mesh",-1);c(this,"lastLodLevel_Texture",-1);c(this,"lastScreenCoverage",0);c(this,"lastScreenspaceVolume",new p.Vector3);c(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(s=>{s instanceof HTMLElement&&s.tagName.toLowerCase()==="model-viewer"&&qe(s)})})}),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,s=null;for(let i=n;i!=null;i=Object.getPrototypeOf(i)){const r=Object.getOwnPropertySymbols(i),o=r.find(u=>u.toString()=="Symbol(renderer)"),a=r.find(u=>u.toString()=="Symbol(scene)"),l=r.find(u=>u.toString()=="Symbol(needsRender)");!t&&o!=null&&(t=n[o].threeRenderer),!e&&a!=null&&(e=n[a]),!s&&l!=null&&(s=n[l])}if(t&&e){let i=function(){if(s){let o=0,a=setInterval(()=>{if(o++>5){clearInterval(a);return}s==null||s.call(n)},300)}};console.debug("[gltf-progressive] setup model-viewer");const r=B.get(t,{engine:"model-viewer"});return B.addPlugin(new ht),r.enable(),r.addEventListener("changed",()=>{s==null||s.call(n)}),n.addEventListener("model-visibility",o=>{o.detail.visible&&(s==null||s.call(n))}),n.addEventListener("load",()=>{i()}),()=>{r.disable()}}return null}class ht{constructor(){c(this,"_didWarnAboutMissingUrl",!1)}onBeforeUpdateLOD(t,e,s,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 s=this.tryGetCurrentGLTF(t),i=this.tryGetCurrentModelViewer(t),r=this.getUrl(i);if(r&&s&&e.material){let o=function(l){var d,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=(d=_.userData)==null?void 0:d.associations)==null?void 0:h.textures;if(V==null)continue;const K=s.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&&r&&P.registerTexture(r,_,v.lods.length,V,v)}}}};const a=e.material;if(Array.isArray(a))for(const l of a)o(l);else o(a)}}tryParseMeshLOD(t,e){var o,a;if(e[Be]==!0)return;e[Be]=!0;const s=this.tryGetCurrentModelViewer(t),i=this.getUrl(s);if(!i)return;const r=(a=(o=e.userData)==null?void 0:o.gltfExtensions)==null?void 0:a[q];if(r&&i){const l=e.uuid;P.registerMesh(i,l,e,0,r.lods.length,r)}}}function Xe(n,t,e,s){Pe(t),Ae(e),Ce(e,{progressive:!0,...s==null?void 0:s.hints}),e.register(r=>new P(r,n));const i=B.get(t);return(s==null?void 0:s.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=$e;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.
|
|
@@ -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.promise.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;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Box3, Clock, Matrix4, Mesh, MeshStandardMaterial, Sphere, Vector3 } from "three";
|
|
2
2
|
import { NEEDLE_progressive } from "./extension.js";
|
|
3
3
|
import { createLoaders } from "./loaders.js";
|
|
4
|
-
import { getParam, isMobileDevice } from "./utils.internal.js";
|
|
4
|
+
import { getParam, isDevelopmentServer, isMobileDevice } from "./utils.internal.js";
|
|
5
5
|
import { plugins } from "./plugins/plugin.js";
|
|
6
6
|
import { getRaycastMesh } from "./utils.js";
|
|
7
7
|
import { applyDebugSettings, debug, debug_OverrideLodLevel } from "./lods.debug.js";
|
|
8
|
+
import { PromiseGroup } from "./lods.promise.js";
|
|
8
9
|
const debugProgressiveLoading = getParam("debugprogressive");
|
|
9
10
|
const suppressProgressiveLoading = getParam("noprogressive");
|
|
10
11
|
const $lodsManager = Symbol("Needle:LODSManager");
|
|
@@ -78,8 +79,8 @@ export class LODsManager {
|
|
|
78
79
|
renderer[$lodsManager] = lodsManager;
|
|
79
80
|
return lodsManager;
|
|
80
81
|
}
|
|
81
|
-
context;
|
|
82
82
|
renderer;
|
|
83
|
+
context;
|
|
83
84
|
projectionScreenMatrix = new Matrix4();
|
|
84
85
|
/** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
|
|
85
86
|
get plugins() { return plugins; }
|
|
@@ -111,6 +112,37 @@ export class LODsManager {
|
|
|
111
112
|
* @default false
|
|
112
113
|
*/
|
|
113
114
|
manual = false;
|
|
115
|
+
_newPromiseGroups = [];
|
|
116
|
+
_promiseGroupIds = 0;
|
|
117
|
+
/**
|
|
118
|
+
* Call to await LODs loading during the next render cycle.
|
|
119
|
+
*/
|
|
120
|
+
awaitLoading(opts) {
|
|
121
|
+
const id = this._promiseGroupIds++;
|
|
122
|
+
const newGroup = new PromiseGroup(this.#frame, { ...opts, });
|
|
123
|
+
this._newPromiseGroups.push(newGroup);
|
|
124
|
+
const start = performance.now();
|
|
125
|
+
newGroup.ready.finally(() => {
|
|
126
|
+
const index = this._newPromiseGroups.indexOf(newGroup);
|
|
127
|
+
if (index >= 0) {
|
|
128
|
+
this._newPromiseGroups.splice(index, 1);
|
|
129
|
+
if (isDevelopmentServer())
|
|
130
|
+
performance.measure("LODsManager:awaitLoading", {
|
|
131
|
+
start,
|
|
132
|
+
detail: { id, name: opts?.name, awaited: newGroup.awaitedCount, resolved: newGroup.resolvedCount }
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return newGroup.ready;
|
|
137
|
+
}
|
|
138
|
+
_postprocessPromiseGroups() {
|
|
139
|
+
if (this._newPromiseGroups.length === 0)
|
|
140
|
+
return;
|
|
141
|
+
for (let i = this._newPromiseGroups.length - 1; i >= 0; i--) {
|
|
142
|
+
const group = this._newPromiseGroups[i];
|
|
143
|
+
group.update(this.#frame);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
114
146
|
_lodchangedlisteners = [];
|
|
115
147
|
addEventListener(evt, listener) {
|
|
116
148
|
if (evt === "changed") {
|
|
@@ -232,6 +264,7 @@ export class LODsManager {
|
|
|
232
264
|
return;
|
|
233
265
|
}
|
|
234
266
|
this.internalUpdate(scene, camera);
|
|
267
|
+
this._postprocessPromiseGroups();
|
|
235
268
|
}
|
|
236
269
|
}
|
|
237
270
|
/**
|
|
@@ -368,9 +401,10 @@ export class LODsManager {
|
|
|
368
401
|
}
|
|
369
402
|
if (update) {
|
|
370
403
|
material[$currentLOD] = level;
|
|
371
|
-
NEEDLE_progressive.assignTextureLOD(material, level).then(_ => {
|
|
404
|
+
const promise = NEEDLE_progressive.assignTextureLOD(material, level).then(_ => {
|
|
372
405
|
this._lodchangedlisteners.forEach(l => l({ type: "texture", level, object: material }));
|
|
373
406
|
});
|
|
407
|
+
PromiseGroup.addPromise("texture", material, promise, this._newPromiseGroups);
|
|
374
408
|
}
|
|
375
409
|
}
|
|
376
410
|
/** Load progressive meshes for the given mesh
|
|
@@ -391,19 +425,14 @@ export class LODsManager {
|
|
|
391
425
|
if (update) {
|
|
392
426
|
mesh[$currentLOD] = level;
|
|
393
427
|
const originalGeometry = mesh.geometry;
|
|
394
|
-
|
|
428
|
+
const promise = NEEDLE_progressive.assignMeshLOD(mesh, level).then(res => {
|
|
395
429
|
if (res && mesh[$currentLOD] == level && originalGeometry != mesh.geometry) {
|
|
396
430
|
this._lodchangedlisteners.forEach(l => l({ type: "mesh", level, object: mesh }));
|
|
397
|
-
// if (this.handles) {
|
|
398
|
-
// for (const inst of this.handles) {
|
|
399
|
-
// // if (inst["LOD"] < level) continue;
|
|
400
|
-
// // inst["LOD"] = level;
|
|
401
|
-
// inst.setGeometry(mesh.geometry);
|
|
402
|
-
// }
|
|
403
|
-
// }
|
|
404
431
|
}
|
|
405
432
|
return res;
|
|
406
433
|
});
|
|
434
|
+
PromiseGroup.addPromise("mesh", mesh, promise, this._newPromiseGroups);
|
|
435
|
+
return promise;
|
|
407
436
|
}
|
|
408
437
|
return Promise.resolve(null);
|
|
409
438
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
type PromiseType = "texture" | "mesh";
|
|
2
|
+
export type PromiseGroupOptions = {
|
|
3
|
+
/** Name for debugging purposes */
|
|
4
|
+
name?: string;
|
|
5
|
+
/** Define many frames new LOD promises will be captured and awaited. The group will resolve after all promises captured during this time have resolved (or when the abort signal is triggered).
|
|
6
|
+
* @default 2 frames, which means the group will capture promises for 2 frames before resolving.
|
|
7
|
+
*/
|
|
8
|
+
frames?: number;
|
|
9
|
+
/** An optional signal to abort the promise */
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
/**
|
|
12
|
+
* If set to true, the group will only await one promise per object.
|
|
13
|
+
* @default 1
|
|
14
|
+
*/
|
|
15
|
+
maxPromisesPerObject?: number;
|
|
16
|
+
};
|
|
17
|
+
type PromiseGroupResolveResult = {
|
|
18
|
+
/**
|
|
19
|
+
* `true` if the group was cancelled, `false` if it was resolved normally.
|
|
20
|
+
*/
|
|
21
|
+
cancelled: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The number of promises that started to being awaited
|
|
24
|
+
*/
|
|
25
|
+
awaited_count: number;
|
|
26
|
+
/**
|
|
27
|
+
* The number of promises that were resolved
|
|
28
|
+
*/
|
|
29
|
+
resolved_count: number;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* A group of promises that can be awaited together.
|
|
33
|
+
* This is used for awaiting LOD
|
|
34
|
+
*/
|
|
35
|
+
export declare class PromiseGroup {
|
|
36
|
+
static readonly addPromise: (type: PromiseType, object: object, promise: Promise<any>, groups: PromiseGroup[]) => void;
|
|
37
|
+
readonly frame_start: number;
|
|
38
|
+
readonly frame_capture_end: number;
|
|
39
|
+
readonly ready: Promise<PromiseGroupResolveResult>;
|
|
40
|
+
private _resolve;
|
|
41
|
+
private readonly _signal?;
|
|
42
|
+
/**
|
|
43
|
+
* The number of promises that have been added to this group so far.
|
|
44
|
+
*/
|
|
45
|
+
get awaitedCount(): number;
|
|
46
|
+
get resolvedCount(): number;
|
|
47
|
+
get currentlyAwaiting(): number;
|
|
48
|
+
private _resolved;
|
|
49
|
+
private _addedCount;
|
|
50
|
+
private _resolvedCount;
|
|
51
|
+
/** These promises are currently being awaited */
|
|
52
|
+
private readonly _awaiting;
|
|
53
|
+
private _maxPromisesPerObject;
|
|
54
|
+
constructor(frame: number, options: PromiseGroupOptions);
|
|
55
|
+
private _currentFrame;
|
|
56
|
+
update(frame: number): void;
|
|
57
|
+
private readonly _seen;
|
|
58
|
+
private add;
|
|
59
|
+
private resolveNow;
|
|
60
|
+
}
|
|
61
|
+
export {};
|