@needle-tools/engine 4.4.0-alpha.3 → 4.4.0-alpha.4
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 +3 -0
- package/dist/gltf-progressive.js +54 -54
- package/dist/gltf-progressive.light.js +54 -54
- package/dist/gltf-progressive.light.min.js +7 -7
- package/dist/gltf-progressive.min.js +7 -7
- package/dist/needle-engine.bundle.js +6134 -6132
- package/dist/needle-engine.bundle.light.js +6137 -6135
- package/dist/needle-engine.bundle.light.min.js +130 -130
- package/dist/needle-engine.bundle.light.umd.cjs +2 -2
- package/dist/needle-engine.bundle.min.js +130 -130
- package/dist/needle-engine.bundle.umd.cjs +2 -2
- package/dist/needle-engine.d.ts +9 -9
- package/dist/needle-engine.js +511 -511
- package/dist/needle-engine.light.d.ts +9 -9
- package/dist/needle-engine.light.js +511 -511
- package/dist/needle-engine.light.min.js +1 -1
- package/dist/needle-engine.min.js +1 -1
- package/dist/postprocessing.js +38 -38
- package/dist/postprocessing.light.js +38 -38
- package/dist/postprocessing.light.min.js +2 -2
- package/dist/postprocessing.min.js +2 -2
- package/dist/three-examples.js +1205 -1205
- package/dist/three-examples.light.js +1205 -1205
- package/dist/three-examples.light.min.js +15 -15
- package/dist/three-examples.min.js +15 -15
- package/dist/three-mesh-ui.js +9 -9
- package/dist/three-mesh-ui.light.js +9 -9
- package/dist/three-mesh-ui.light.min.js +9 -9
- package/dist/three-mesh-ui.min.js +9 -9
- package/dist/three.js +238 -238
- package/dist/three.light.js +238 -238
- package/dist/three.light.min.js +24 -24
- package/dist/three.min.js +24 -24
- package/dist/vendor.js +24 -24
- package/dist/vendor.light.js +24 -24
- package/dist/vendor.light.min.js +2 -2
- package/dist/vendor.min.js +2 -2
- package/lib/engine-components/postprocessing/PostProcessingHandler.js +6 -2
- package/lib/engine-components/postprocessing/PostProcessingHandler.js.map +1 -1
- package/package.json +1 -1
- package/src/engine-components/postprocessing/PostProcessingHandler.ts +7 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{B as le,M as H,T as ee,a as Ue,V as $,b as Oe,S as Fe,c as Se,d as ze,C as Ve}from"./three.light.min.js";import{D as qe,K as Ke,G as fe,M as He}from"./three-examples.light.min.js";const Xe="";globalThis.GLTF_PROGRESSIVE_VERSION=Xe,console.debug("[gltf-progressive] version -");let G="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",J="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ye=G,Je=J,Te=new URL(G+"draco_decoder.js");Te.searchParams.append("range","true"),fetch(Te,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(t=>{console.debug(`Failed to fetch remote Draco decoder from ${G} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),G===Ye&&Ee("./include/draco/"),J===Je&&Ae("./include/ktx2/")}).finally(()=>{Pe()});function Ee(t){G=t,A&&A[me]!=G?(console.debug("Updating Draco decoder path to "+t),A[me]=G,A.setDecoderPath(G),A.preload()):console.debug("Setting Draco decoder path to "+t)}function Ae(t){J=t,C&&C.transcoderPath!=J?(console.debug("Updating KTX2 transcoder path to "+t),C.setTranscoderPath(J),C.init()):console.debug("Setting KTX2 transcoder path to "+t)}const me=Symbol("dracoDecoderPath");let A,ae,C;function Pe(){A||(A=new qe,A[me]=G,A.setDecoderPath(G),A.setDecoderConfig({type:"js"}),A.preload()),C||(C=new Ke,C.setTranscoderPath(J),C.init()),ae||(ae=He)}function pe(t){return Pe(),t?C.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:A,ktx2Loader:C,meshoptDecoder:ae}}function ve(t){t.dracoLoader||t.setDRACOLoader(A),t.ktx2Loader||t.setKTX2Loader(C),t.meshoptDecoder||t.setMeshoptDecoder(ae)}const ye=new WeakMap;function xe(t,e){let r=ye.get(t);r?r=Object.assign(r,e):r=e,ye.set(t,r)}const Be=fe.prototype.load;function Qe(...t){const e=ye.get(this);let r=t[0];const n=new URL(r,window.location.href);if(n.hostname.endsWith("needle.tools")){const s=e?.progressive!==void 0?e.progressive:!0,o=e!=null&&e.usecase?e.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${o}`:this.requestHeader.Accept=`*/*;usecase=${o}`,r=n.toString()}return t[0]=r,Be?.call(this,...t)}fe.prototype.load=Qe,te("debugprogressive");function te(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 Ze(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let ue;function et(){return ue!==void 0||(ue=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),te("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ue)),ue}const tt=typeof window>"u"&&typeof document>"u",Le=Symbol("needle:raycast-mesh");function Q(t){return t?.[Le]instanceof le?t[Le]:null}function rt(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!Q(t)){const r=ot(e);r.userData={isRaycastMesh:!0},t[Le]=r}}function st(t=!0){if(t){if(re)return;const e=re=H.prototype.raycast;H.prototype.raycast=function(r,n){const s=this,o=Q(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),e.call(this,r,n),i&&(s.geometry=i)}}else{if(!re)return;H.prototype.raycast=re,re=null}}let re=null;function ot(t){const e=new le;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const F=new Array,N="NEEDLE_progressive",v=te("debugprogressive"),De=Symbol("needle-progressive-texture"),se=new Map,we=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,se),se.forEach((s,o)=>{for(const i of s.keys){const a=o[i];if(a!=null)if(a.isBufferGeometry===!0){const u=S.getMeshLODInformation(a),l=u?Math.min(e,u.lods.length):0;o["DEBUG:LOD"]=l,u&&(r=Math.max(r,u.lods.length-1))}else o.isMaterial===!0&&(o["DEBUG:LOD"]=e)}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(n=!n,we&&we.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function Ie(t,e,r){var n;if(!v)return;se.has(t)||se.set(t,{keys:[],sourceId:r});const s=se.get(t);((n=s?.keys)==null?void 0:n.includes(e))==!1&&s.keys.push(e)}const w=class{constructor(t,e){this.loadMesh=r=>{var n,s;if(this._isLoadingMesh)return null;const o=(s=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:s[N];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var a;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,o.guid,i,(a=o.lods)==null?void 0:a.length,void 0,o),i})):null},v&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return N}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[n]=e,e}if(v==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const a of Object.keys(i.uniforms)){const u=i.uniforms[a].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const a=t[i];a?.isTexture===!0&&o(a,e)}return t[n]=e,e;function o(i,a){const u=r.getAssignedLODInformation(i);if(u){const l=r.lodInfos.get(u.key);if(l&&l.lods){a.min_count=Math.min(a.min_count,l.lods.length),a.max_count=Math.max(a.max_count,l.lods.length);for(let h=0;h<l.lods.length;h++){const g=l.lods[h];g.width&&(a.lods[h]=a.lods[h]||{min_height:1/0,max_height:0},a.lods[h].min_height=Math.min(a.lods[h].min_height,g.height),a.lods[h].max_height=Math.max(a.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 i=t[o];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const o of t.children)if(o.isMesh===!0&&this.hasLODLevelAvailable(o,e))return!0}let n,s;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const o=n.userData.LODS;if(s=this.lodInfos.get(o.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof H||t.isMesh===!0){const n=t.geometry,s=this.getAssignedLODInformation(n);if(!s)return Promise.resolve(null);for(const o of F)(r=o.onBeforeGetLODMesh)==null||r.call(o,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(n,e).then(o=>{if(Array.isArray(o)){const i=s.index||0;o=o[i]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],o&&n!=o&&(o?.isBufferGeometry?(t.geometry=o,v&&Ie(t,"geometry",s.url)):v&&console.error("Invalid LOD geometry",o))),o}).catch(o=>(console.error("Error loading mesh LOD",t,o),null))}else v&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const o=this.assignTextureLOD(s,e);n.push(o)}return Promise.all(n).then(s=>{const o=new Array;for(const i of s)Array.isArray(i)&&o.push(...i);return o})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,n=[],s=new Array;if(v&&we.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const i of Object.keys(o.uniforms)){const a=o.uniforms[i].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,i).then(l=>(l&&o.uniforms[i].value!=l&&(o.uniforms[i].value=l,o.uniformsNeedUpdate=!0),l));n.push(u),s.push(i)}}}else for(const o of Object.keys(r)){const i=r[o];if(i?.isTexture===!0){const a=this.assignTextureLODForSlot(i,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const i=new Array;for(let a=0;a<o.length;a++){const u=o[a],l=s[a];u&&u.isTexture===!0?i.push({material:r,slot:l,texture:u,level:e}):i.push({material:r,slot:l,texture:null,level:e})}return i})}if(t instanceof ee||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t){if(r&&n){const o=r[n];if(o&&!v){const i=this.getAssignedLODInformation(o);if(i&&i?.level<e)return v==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,o,s),null}r[n]=s}if(v&&n&&r){const o=this.getAssignedLODInformation(t);o?Ie(r,n,o.url):console.warn("No LOD info for texture",t)}}return s}else v=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return v&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,s)=>{var o;if(n!=null&&n.extensions){const i=n?.extensions[N];if(i){if(!i.lods){v&&console.warn("Texture has no LODs",i);return}let a=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const l=this.parser.associations.get(u);l?.textures===s&&(a=!0,w.registerTexture(this.url,u,(o=i.lods)==null?void 0:o.length,s,i))}a||this.parser.getDependency("texture",s).then(u=>{var l;u&&w.registerTexture(this.url,u,(l=i.lods)==null?void 0:l.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,s)=>{if(n!=null&&n.extensions){const o=n?.extensions[N];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const a=this.parser.associations.get(i);a?.meshes===s&&w.registerMesh(this.url,o.guid,i,o.lods.length,a.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var r,n,s,o;const i=v=="verbose",a=t.userData.LODS;if(!a)return null;const u=a?.key;let l;if(t.isTexture===!0){const h=t;h.source&&h.source[De]&&(l=h.source[De])}if(l||(l=w.lodInfos.get(u)),l){if(e>0){let p=!1;const E=Array.isArray(l.lods);if(E&&e>=l.lods.length?p=!0:E||(p=!0),p)return this.lowresCache.get(u)}const h=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!h)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const g=Ze(a.url,h);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const p=g+"_"+l.guid,E=this.previouslyLoaded.get(p);if(E!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let c=await E.catch(b=>(console.error(`Error loading LOD ${e} from ${g}
|
|
2
|
-
`,
|
|
3
|
-
`,m),null));if(!
|
|
1
|
+
import{BufferGeometry as ae,Mesh as K,Texture as ee,TextureLoader as Ue,Vector3 as $,Matrix4 as be,Sphere as Fe,Box3 as Se,MeshStandardMaterial as ze,Clock as Ve}from"./three.light.min.js";import{DRACOLoader as qe,KTX2Loader as Xe,GLTFLoader as fe,MeshoptDecoder as Ke}from"./three-examples.light.min.js";const He="";globalThis.GLTF_PROGRESSIVE_VERSION=He,console.debug("[gltf-progressive] version -");let G="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",J="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ye=G,Je=J,Te=new URL(G+"draco_decoder.js");Te.searchParams.append("range","true"),fetch(Te,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(t=>{console.debug(`Failed to fetch remote Draco decoder from ${G} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),G===Ye&&Ee("./include/draco/"),J===Je&&Ae("./include/ktx2/")}).finally(()=>{Pe()});function Ee(t){G=t,A&&A[me]!=G?(console.debug("Updating Draco decoder path to "+t),A[me]=G,A.setDecoderPath(G),A.preload()):console.debug("Setting Draco decoder path to "+t)}function Ae(t){J=t,C&&C.transcoderPath!=J?(console.debug("Updating KTX2 transcoder path to "+t),C.setTranscoderPath(J),C.init()):console.debug("Setting KTX2 transcoder path to "+t)}const me=Symbol("dracoDecoderPath");let A,le,C;function Pe(){A||(A=new qe,A[me]=G,A.setDecoderPath(G),A.setDecoderConfig({type:"js"}),A.preload()),C||(C=new Xe,C.setTranscoderPath(J),C.init()),le||(le=Ke)}function pe(t){return Pe(),t?C.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:A,ktx2Loader:C,meshoptDecoder:le}}function ve(t){t.dracoLoader||t.setDRACOLoader(A),t.ktx2Loader||t.setKTX2Loader(C),t.meshoptDecoder||t.setMeshoptDecoder(le)}const xe=new WeakMap;function ye(t,e){let r=xe.get(t);r?r=Object.assign(r,e):r=e,xe.set(t,r)}const Be=fe.prototype.load;function Qe(...t){const e=xe.get(this);let r=t[0];const n=new URL(r,window.location.href);if(n.hostname.endsWith("needle.tools")){const s=e?.progressive!==void 0?e.progressive:!0,o=e!=null&&e.usecase?e.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${o}`:this.requestHeader.Accept=`*/*;usecase=${o}`,r=n.toString()}return t[0]=r,Be?.call(this,...t)}fe.prototype.load=Qe,te("debugprogressive");function te(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 Ze(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let ue;function et(){return ue!==void 0||(ue=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),te("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ue)),ue}const tt=typeof window>"u"&&typeof document>"u",Le=Symbol("needle:raycast-mesh");function Q(t){return t?.[Le]instanceof ae?t[Le]:null}function rt(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!Q(t)){const r=ot(e);r.userData={isRaycastMesh:!0},t[Le]=r}}function st(t=!0){if(t){if(re)return;const e=re=K.prototype.raycast;K.prototype.raycast=function(r,n){const s=this,o=Q(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),e.call(this,r,n),i&&(s.geometry=i)}}else{if(!re)return;K.prototype.raycast=re,re=null}}let re=null;function ot(t){const e=new ae;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const F=new Array,N="NEEDLE_progressive",v=te("debugprogressive"),De=Symbol("needle-progressive-texture"),se=new Map,Me=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,se),se.forEach((s,o)=>{for(const i of s.keys){const l=o[i];if(l!=null)if(l.isBufferGeometry===!0){const u=S.getMeshLODInformation(l),a=u?Math.min(e,u.lods.length):0;o["DEBUG:LOD"]=a,u&&(r=Math.max(r,u.lods.length-1))}else o.isMaterial===!0&&(o["DEBUG:LOD"]=e)}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(n=!n,Me&&Me.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function Ie(t,e,r){var n;if(!v)return;se.has(t)||se.set(t,{keys:[],sourceId:r});const s=se.get(t);((n=s?.keys)==null?void 0:n.includes(e))==!1&&s.keys.push(e)}const M=class{constructor(t,e){this.loadMesh=r=>{var n,s;if(this._isLoadingMesh)return null;const o=(s=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:s[N];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var l;return this._isLoadingMesh=!1,i&&M.registerMesh(this.url,o.guid,i,(l=o.lods)==null?void 0:l.length,void 0,o),i})):null},v&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return N}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[n]=e,e}if(v==="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=r.getAssignedLODInformation(i);if(u){const a=r.lodInfos.get(u.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let h=0;h<a.lods.length;h++){const g=a.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 i=t[o];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const o of t.children)if(o.isMesh===!0&&this.hasLODLevelAvailable(o,e))return!0}let n,s;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const o=n.userData.LODS;if(s=this.lodInfos.get(o.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof K||t.isMesh===!0){const n=t.geometry,s=this.getAssignedLODInformation(n);if(!s)return Promise.resolve(null);for(const o of F)(r=o.onBeforeGetLODMesh)==null||r.call(o,t,e);return t["LOD:requested level"]=e,M.getOrLoadLOD(n,e).then(o=>{if(Array.isArray(o)){const i=s.index||0;o=o[i]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],o&&n!=o&&(o?.isBufferGeometry?(t.geometry=o,v&&Ie(t,"geometry",s.url)):v&&console.error("Invalid LOD geometry",o))),o}).catch(o=>(console.error("Error loading mesh LOD",t,o),null))}else v&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const o=this.assignTextureLOD(s,e);n.push(o)}return Promise.all(n).then(s=>{const o=new Array;for(const i of s)Array.isArray(i)&&o.push(...i);return o})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,n=[],s=new Array;if(v&&Me.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const i of Object.keys(o.uniforms)){const l=o.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,r,i).then(a=>(a&&o.uniforms[i].value!=a&&(o.uniforms[i].value=a,o.uniformsNeedUpdate=!0),a));n.push(u),s.push(i)}}}else for(const o of Object.keys(r)){const i=r[o];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,r,o);n.push(l),s.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=s[l];u&&u.isTexture===!0?i.push({material:r,slot:a,texture:u,level:e}):i.push({material:r,slot:a,texture:null,level:e})}return i})}if(t instanceof ee||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):M.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t){if(r&&n){const o=r[n];if(o&&!v){const i=this.getAssignedLODInformation(o);if(i&&i?.level<e)return v==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,o,s),null}r[n]=s}if(v&&n&&r){const o=this.getAssignedLODInformation(t);o?Ie(r,n,o.url):console.warn("No LOD info for texture",t)}}return s}else v=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return v&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,s)=>{var o;if(n!=null&&n.extensions){const i=n?.extensions[N];if(i){if(!i.lods){v&&console.warn("Texture has no LODs",i);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const a=this.parser.associations.get(u);a?.textures===s&&(l=!0,M.registerTexture(this.url,u,(o=i.lods)==null?void 0:o.length,s,i))}l||this.parser.getDependency("texture",s).then(u=>{var a;u&&M.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,s)=>{if(n!=null&&n.extensions){const o=n?.extensions[N];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===s&&M.registerMesh(this.url,o.guid,i,o.lods.length,l.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var r,n,s,o;const i=v=="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[De]&&(a=h.source[De])}if(a||(a=M.lodInfos.get(u)),a){if(e>0){let p=!1;const E=Array.isArray(a.lods);if(E&&e>=a.lods.length?p=!0:E||(p=!0),p)return this.lowresCache.get(u)}const h=Array.isArray(a.lods)?(r=a.lods[e])==null?void 0:r.path:a.lods;if(!h)return v&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const g=Ze(l.url,h);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const p=g+"_"+a.guid,E=this.previouslyLoaded.get(p);if(E!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let c=await E.catch(_=>(console.error(`Error loading LOD ${e} from ${g}
|
|
2
|
+
`,_),null)),w=!1;if(c==null||(c instanceof ee&&t instanceof ee?(n=c.image)!=null&&n.data||(s=c.source)!=null&&s.data?c=this.copySettings(t,c):(w=!0,this.previouslyLoaded.delete(p)):c instanceof ae&&t instanceof ae&&((o=c.attributes.position)!=null&&o.array||(w=!0,this.previouslyLoaded.delete(p)))),!w)return c}const D=a,x=new Promise(async(c,w)=>{const _=new fe;ve(_),v&&(await new Promise(m=>setTimeout(m,1e3)),i&&console.warn("Start loading (delayed) "+g,D.guid));let B=g;if(D&&Array.isArray(D.lods)){const m=D.lods[e];m.hash&&(B+="?v="+m.hash)}const O=await _.loadAsync(B).catch(m=>(console.error(`Error loading LOD ${e} from ${g}
|
|
3
|
+
`,m),null));if(!O)return null;const I=O.parser;i&&console.log("Loading finished "+g,D.guid);let f=0;if(O.parser.json.textures){let m=!1;for(const d of O.parser.json.textures){if(d!=null&&d.extensions){const L=d?.extensions[N];if(L!=null&&L.guid&&L.guid===D.guid){m=!0;break}}f++}if(m){let d=await I.getDependency("texture",f);return d&&M.assignLODInformation(l.url,d,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+d.name+'"',g,f,d,p),t instanceof ee&&(d=this.copySettings(t,d)),d&&(d.guid=D.guid),c(d)}else v&&console.warn("Could not find texture with guid",D.guid,O.parser.json)}if(f=0,O.parser.json.meshes){let m=!1;for(const d of O.parser.json.meshes){if(d!=null&&d.extensions){const L=d?.extensions[N];if(L!=null&&L.guid&&L.guid===D.guid){m=!0;break}}f++}if(m){const d=await I.getDependency("mesh",f),L=D;if(i&&console.log(`Loaded Mesh "${d.name}"`,g,f,d,p),d.isMesh===!0){const b=d.geometry;return M.assignLODInformation(l.url,b,u,e,void 0,L.density),c(b)}else{const b=new Array;for(let j=0;j<d.children.length;j++){const X=d.children[j];if(X.isMesh===!0){const Y=X.geometry;M.assignLODInformation(l.url,Y,u,e,j,L.density),b.push(Y)}}return c(b)}}else v&&console.warn("Could not find mesh with guid",D.guid,O.parser.json)}return c(null)});return this.previouslyLoaded.set(p,x),await x}else if(t instanceof ee){i&&console.log("Load texture from uri: "+g);const p=await new Ue().loadAsync(g);return p?(p.guid=a.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=t.colorSpace,i&&console.log(a,p)):v&&console.warn("failed loading",g),p}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,s,o){if(!e)return;e.userData||(e.userData={});const i=new nt(t,r,n,s,o);e.userData.LODS=i}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e?(v&&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 S=w;S.registerTexture=(t,e,r,n,s)=>{if(v&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,s),!e){v&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[De]=s);const o=s.guid;w.assignLODInformation(t,e,o,r,n,void 0),w.lodInfos.set(o,s),w.lowresCache.set(o,e)},S.registerMesh=(t,e,r,n,s,o)=>{var i;v&&console.log("> Progressive: register mesh",s,r.name,o,r.uuid,r);const a=r.geometry;if(!a){v&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),w.assignLODInformation(t,a,e,n,s,o.density),w.lodInfos.set(e,o);let u=w.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],w.lowresCache.set(e,u),n>0&&!Q(r)&&rt(r,a);for(const l of F)(i=l.onRegisteredNewMesh)==null||i.call(l,r,o)},S.lodInfos=new Map,S.previouslyLoaded=new Map,S.lowresCache=new Map;class nt{constructor(e,r,n,s,o){this.url=e,this.key=r,this.level=n,s!=null&&(this.index=s),o!=null&&(this.density=o)}}var Ce=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},x=(t,e,r)=>(Ce(t,e,"read from private field"),r?r.call(t):e.get(t)),X=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},U=(t,e,r,n)=>(Ce(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r),T,z,Me,Z,oe,ce,V;const k=te("debugprogressive"),it=te("noprogressive"),be=Symbol("Needle:LODSManager"),_e=Symbol("Needle:LODState"),q=Symbol("Needle:CurrentLOD"),R={mesh_lod:-1,texture_lod:-1},P=class{constructor(t,e){this.projectionScreenMatrix=new Oe,this.targetTriangleDensity=2e5,this.updateInterval="auto",X(this,T,1),this.pause=!1,this.manual=!1,this._lodchangedlisteners=[],X(this,z,void 0),X(this,Me,new Ve),X(this,Z,0),X(this,oe,0),X(this,ce,0),X(this,V,0),this._fpsBuffer=[60,60,60,60,60],this._sphere=new Fe,this._tempBox=new Se,this._tempBox2=new Se,this.tempMatrix=new Oe,this._tempWorldPosition=new $,this._tempBoxSize=new $,this._tempBox2Size=new $,this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[_e]}static addPlugin(t){F.push(t)}static removePlugin(t){const e=F.indexOf(t);e>=0&&F.splice(e,1)}static get(t,e){if(t[be])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[be];const r=new P(t,{engine:"unknown",...e});return t[be]=r,r}get plugins(){return F}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(x(this,z))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;U(this,z,this.renderer.render);const e=this;pe(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,U(e,Z,x(e,Z)+1),U(e,oe,x(e,Me).getDelta()),U(e,ce,x(e,ce)+x(e,oe)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,oe)),U(e,V,e._fpsBuffer.reduce((i,a)=>i+a)/e._fpsBuffer.length),k&&x(e,Z)%200===0&&console.log("FPS",Math.round(x(e,V)),"Interval:",x(e,T)));const o=t++;x(e,z).call(this,r,n),e.onAfterRender(r,n,o)}}disable(){x(this,z)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=x(this,z),U(this,z,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const n=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(n.length===1){const o=n[0].material;(o.name==="EffectMaterial"||o.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(it||(this.updateInterval==="auto"?x(this,V)<40&&x(this,T)<10?(U(this,T,x(this,T)+1),k&&console.warn("\u2193 Reducing LOD updates",x(this,T),x(this,V).toFixed(0))):x(this,V)>=60&&x(this,T)>1&&(U(this,T,x(this,T)-1),k&&console.warn("\u2191 Increasing LOD updates",x(this,T),x(this,V).toFixed(0))):U(this,T,this.updateInterval),x(this,T)>0&&x(this,Z)%x(this,T)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var r,n;const s=this.renderer.renderLists.get(t,0),o=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const l of o){if(l.material&&(((r=l.geometry)==null?void 0:r.type)==="BoxGeometry"||((n=l.geometry)==null?void 0:n.type)==="BufferGeometry")&&(l.material.name==="SphericalGaussianBlur"||l.material.name=="BackgroundCubeMaterial"||l.material.name==="CubemapFromEquirect"||l.material.name==="EquirectangularToCubeUV")){k&&(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",l,l.material.name,l.material.type)));continue}switch(l.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(k==="color"&&l.material&&!l.object.progressive_debug_color){l.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new ze({color:g});l.object.material=p}const h=l.object;(h instanceof H||h.isMesh)&&this.updateLODs(t,e,h,i)}const a=s.transparent;for(const l of a){const h=l.object;(h instanceof H||h.isMesh)&&this.updateLODs(t,e,h,i)}const u=s.transmissive;for(const l of u){const h=l.object;(h instanceof H||h.isMesh)&&this.updateLODs(t,e,h,i)}}updateLODs(t,e,r,n){var s,o;r.userData||(r.userData={});let i=r[_e];if(i||(i=new lt,r[_e]=i),i.frames++<2)return;for(const u of F)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,R),R.mesh_lod=Math.round(R.mesh_lod),R.texture_lod=Math.round(R.texture_lod),R.mesh_lod>=0&&this.loadProgressiveMeshes(r,R.mesh_lod);let a=R.texture_lod;r.material&&a>=0&&this.loadProgressiveTextures(r.material,a);for(const u of F)(o=u.onAfterUpdatedLOD)==null||o.call(u,this.renderer,t,e,r,R);i.lastLodLevel_Mesh=R.mesh_lod,i.lastLodLevel_Texture=R.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const s of t)this.loadProgressiveTextures(s,e);return}let r=!1;(t[q]===void 0||e<t[q])&&(r=!0);const n=t["DEBUG:LOD"];n!=null&&(r=t[q]!=n,e=n),r&&(t[q]=e,S.assignTextureLOD(t,e).then(s=>{this._lodchangedlisteners.forEach(o=>o({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[q]!==e;const n=t["DEBUG:LOD"];if(n!=null&&(r=t[q]!=n,e=n),r){t[q]=e;const s=t.geometry;return S.assignMeshLOD(t,e).then(o=>(o&&t[q]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(i=>i({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,s){var o;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let i=10+1,a=!1;if(k&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),l=u?.lods,h=l&&l.length>0,g=S.getMaterialMinMaxLODsCount(e.material),p=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!h&&!p){s.mesh_lod=0,s.texture_lod=0;return}h||(a=!0,i=0);const E=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const y=e;if(!y.boundingBox)y.computeBoundingBox();else if(r.frames%30===0){const c=Q(y),M=y.geometry;c&&(y.geometry=c),y.computeBoundingBox(),y.geometry=M}D=y.boundingBox}if(D){const y=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 f=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),y.isPerspectiveCamera&&P.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.isPerspectiveCamera&&y.fov>70){const f=this._tempBox.min,m=this._tempBox.max;let d=f.x,L=f.y,O=m.x,j=m.y;const K=2,Y=1.5,ne=(f.x+m.x)*.5,ie=(f.y+m.y)*.5;d=(d-ne)*K+ne,L=(L-ie)*K+ie,O=(O-ne)*K+ne,j=(j-ie)*K+ie;const $e=d<0&&O>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),Ne=L<0&&j>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),ge=Math.max($e,Ne);r.lastCentrality=(Y-ge)*(Y-ge)*(Y-ge)}else r.lastCentrality=1;const c=this._tempBox.getSize(this._tempBoxSize);c.multiplyScalar(.5),screen.availHeight>0&&E>0&&c.multiplyScalar(E/screen.availHeight),t.isPerspectiveCamera?c.x*=t.aspect:t.isOrthographicCamera;const M=t.matrixWorldInverse,b=this._tempBox2;b.copy(D),b.applyMatrix4(e.matrixWorld),b.applyMatrix4(M);const B=b.getSize(this._tempBox2Size),_=Math.max(B.x,B.y);if(Math.max(c.x,c.y)!=0&&_!=0&&(c.z=B.z/Math.max(B.x,B.y)*Math.max(c.x,c.y)),r.lastScreenCoverage=Math.max(c.x,c.y,c.z),r.lastScreenspaceVolume.copy(c),r.lastScreenCoverage*=r.lastCentrality,k&&P.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const m=P.corner0,d=P.corner1,L=P.corner2,O=P.corner3;m.copy(this._tempBox.min),d.copy(this._tempBox.max),d.x=m.x,L.copy(this._tempBox.max),L.y=m.y,O.copy(this._tempBox.max);const j=(m.z+O.z)*.5;m.z=d.z=L.z=O.z=j,m.applyMatrix4(f),d.applyMatrix4(f),L.applyMatrix4(f),O.applyMatrix4(f),P.debugDrawLine(m,d,255),P.debugDrawLine(m,L,255),P.debugDrawLine(d,O,255),P.debugDrawLine(L,O,255)}let I=999;if(l&&r.lastScreenCoverage>0){for(let f=0;f<l.length;f++)if(l[f].density/r.lastScreenCoverage<n){I=f;break}}I<i&&(i=I,a=!0)}if(a?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,k&&s.mesh_lod!=r.lastLodLevel_Mesh){const y=l?.[s.mesh_lod];y&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${y.density.toFixed(0)}) - ${e.name}`)}if(p){const y="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,k){const c=g.lods[g.max_count-1];k&&console.log(`First Texture LOD ${s.texture_lod} (${c.max_height}px) - ${e.name}`)}}else{const c=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let M=r.lastScreenCoverage*4;((o=this.context)==null?void 0:o.engine)==="model-viewer"&&(M*=1.5);const b=E/window.devicePixelRatio*M;let B=!1;for(let _=g.lods.length-1;_>=0;_--){let I=g.lods[_];if(!(y&&I.max_height>=2048)&&!(et()&&I.max_height>4096)&&(I.max_height>b||!B&&_===0)){if(B=!0,s.texture_lod=_,s.texture_lod<r.lastLodLevel_Texture){const f=I.max_height;k&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${f}px
|
|
6
|
-
Screensize: ${
|
|
7
|
-
${e.name}`)}break}}}}else s.texture_lod=0}};let W=P;T=new WeakMap,z=new WeakMap,
|
|
8
|
-
`,t.getAttribute("src"));let e=null,r=null,n=null;for(let s=t;s!=null;s=Object.getPrototypeOf(s)){const o=Object.getOwnPropertySymbols(s),i=o.find(
|
|
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 S=M;S.registerTexture=(t,e,r,n,s)=>{if(v&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,s),!e){v&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[De]=s);const o=s.guid;M.assignLODInformation(t,e,o,r,n,void 0),M.lodInfos.set(o,s),M.lowresCache.set(o,e)},S.registerMesh=(t,e,r,n,s,o)=>{var i;v&&console.log("> Progressive: register mesh",s,r.name,o,r.uuid,r);const l=r.geometry;if(!l){v&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),M.assignLODInformation(t,l,e,n,s,o.density),M.lodInfos.set(e,o);let u=M.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],M.lowresCache.set(e,u),n>0&&!Q(r)&&rt(r,l);for(const a of F)(i=a.onRegisteredNewMesh)==null||i.call(a,r,o)},S.lodInfos=new Map,S.previouslyLoaded=new Map,S.lowresCache=new Map;class nt{constructor(e,r,n,s,o){this.url=e,this.key=r,this.level=n,s!=null&&(this.index=s),o!=null&&(this.density=o)}}var Ce=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},y=(t,e,r)=>(Ce(t,e,"read from private field"),r?r.call(t):e.get(t)),H=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},U=(t,e,r,n)=>(Ce(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r),T,z,we,Z,oe,ce,V;const k=te("debugprogressive"),it=te("noprogressive"),_e=Symbol("Needle:LODSManager"),Oe=Symbol("Needle:LODState"),q=Symbol("Needle:CurrentLOD"),R={mesh_lod:-1,texture_lod:-1},P=class{constructor(t,e){this.projectionScreenMatrix=new be,this.targetTriangleDensity=2e5,this.updateInterval="auto",H(this,T,1),this.pause=!1,this.manual=!1,this._lodchangedlisteners=[],H(this,z,void 0),H(this,we,new Ve),H(this,Z,0),H(this,oe,0),H(this,ce,0),H(this,V,0),this._fpsBuffer=[60,60,60,60,60],this._sphere=new Fe,this._tempBox=new Se,this._tempBox2=new Se,this.tempMatrix=new be,this._tempWorldPosition=new $,this._tempBoxSize=new $,this._tempBox2Size=new $,this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Oe]}static addPlugin(t){F.push(t)}static removePlugin(t){const e=F.indexOf(t);e>=0&&F.splice(e,1)}static get(t,e){if(t[_e])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[_e];const r=new P(t,{engine:"unknown",...e});return t[_e]=r,r}get plugins(){return F}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(y(this,z))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;U(this,z,this.renderer.render);const e=this;pe(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,U(e,Z,y(e,Z)+1),U(e,oe,y(e,we).getDelta()),U(e,ce,y(e,ce)+y(e,oe)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/y(e,oe)),U(e,V,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),k&&y(e,Z)%200===0&&console.log("FPS",Math.round(y(e,V)),"Interval:",y(e,T)));const o=t++;y(e,z).call(this,r,n),e.onAfterRender(r,n,o)}}disable(){y(this,z)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=y(this,z),U(this,z,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const n=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(n.length===1){const o=n[0].material;(o.name==="EffectMaterial"||o.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(it||(this.updateInterval==="auto"?y(this,V)<40&&y(this,T)<10?(U(this,T,y(this,T)+1),k&&console.warn("\u2193 Reducing LOD updates",y(this,T),y(this,V).toFixed(0))):y(this,V)>=60&&y(this,T)>1&&(U(this,T,y(this,T)-1),k&&console.warn("\u2191 Increasing LOD updates",y(this,T),y(this,V).toFixed(0))):U(this,T,this.updateInterval),y(this,T)>0&&y(this,Z)%y(this,T)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var r,n;const s=this.renderer.renderLists.get(t,0),o=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const a of o){if(a.material&&(((r=a.geometry)==null?void 0:r.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")){k&&(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(k==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new ze({color:g});a.object.material=p}const h=a.object;(h instanceof K||h.isMesh)&&this.updateLODs(t,e,h,i)}const l=s.transparent;for(const a of l){const h=a.object;(h instanceof K||h.isMesh)&&this.updateLODs(t,e,h,i)}const u=s.transmissive;for(const a of u){const h=a.object;(h instanceof K||h.isMesh)&&this.updateLODs(t,e,h,i)}}updateLODs(t,e,r,n){var s,o;r.userData||(r.userData={});let i=r[Oe];if(i||(i=new at,r[Oe]=i),i.frames++<2)return;for(const u of F)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,R),R.mesh_lod=Math.round(R.mesh_lod),R.texture_lod=Math.round(R.texture_lod),R.mesh_lod>=0&&this.loadProgressiveMeshes(r,R.mesh_lod);let l=R.texture_lod;r.material&&l>=0&&this.loadProgressiveTextures(r.material,l);for(const u of F)(o=u.onAfterUpdatedLOD)==null||o.call(u,this.renderer,t,e,r,R);i.lastLodLevel_Mesh=R.mesh_lod,i.lastLodLevel_Texture=R.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const s of t)this.loadProgressiveTextures(s,e);return}let r=!1;(t[q]===void 0||e<t[q])&&(r=!0);const n=t["DEBUG:LOD"];n!=null&&(r=t[q]!=n,e=n),r&&(t[q]=e,S.assignTextureLOD(t,e).then(s=>{this._lodchangedlisteners.forEach(o=>o({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[q]!==e;const n=t["DEBUG:LOD"];if(n!=null&&(r=t[q]!=n,e=n),r){t[q]=e;const s=t.geometry;return S.assignMeshLOD(t,e).then(o=>(o&&t[q]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(i=>i({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,s){var o;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let i=10+1,l=!1;if(k&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),a=u?.lods,h=a&&a.length>0,g=S.getMaterialMinMaxLODsCount(e.material),p=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!h&&!p){s.mesh_lod=0,s.texture_lod=0;return}h||(l=!0,i=0);const E=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const x=e;if(!x.boundingBox)x.computeBoundingBox();else if(r.frames%30===0){const c=Q(x),w=x.geometry;c&&(x.geometry=c),x.computeBoundingBox(),x.geometry=w}D=x.boundingBox}if(D){const x=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 f=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),x.isPerspectiveCamera&&P.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&x.isPerspectiveCamera&&x.fov>70){const f=this._tempBox.min,m=this._tempBox.max;let d=f.x,L=f.y,b=m.x,j=m.y;const X=2,Y=1.5,ne=(f.x+m.x)*.5,ie=(f.y+m.y)*.5;d=(d-ne)*X+ne,L=(L-ie)*X+ie,b=(b-ne)*X+ne,j=(j-ie)*X+ie;const $e=d<0&&b>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),Ne=L<0&&j>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),ge=Math.max($e,Ne);r.lastCentrality=(Y-ge)*(Y-ge)*(Y-ge)}else r.lastCentrality=1;const c=this._tempBox.getSize(this._tempBoxSize);c.multiplyScalar(.5),screen.availHeight>0&&E>0&&c.multiplyScalar(E/screen.availHeight),t.isPerspectiveCamera?c.x*=t.aspect:t.isOrthographicCamera;const w=t.matrixWorldInverse,_=this._tempBox2;_.copy(D),_.applyMatrix4(e.matrixWorld),_.applyMatrix4(w);const B=_.getSize(this._tempBox2Size),O=Math.max(B.x,B.y);if(Math.max(c.x,c.y)!=0&&O!=0&&(c.z=B.z/Math.max(B.x,B.y)*Math.max(c.x,c.y)),r.lastScreenCoverage=Math.max(c.x,c.y,c.z),r.lastScreenspaceVolume.copy(c),r.lastScreenCoverage*=r.lastCentrality,k&&P.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const m=P.corner0,d=P.corner1,L=P.corner2,b=P.corner3;m.copy(this._tempBox.min),d.copy(this._tempBox.max),d.x=m.x,L.copy(this._tempBox.max),L.y=m.y,b.copy(this._tempBox.max);const j=(m.z+b.z)*.5;m.z=d.z=L.z=b.z=j,m.applyMatrix4(f),d.applyMatrix4(f),L.applyMatrix4(f),b.applyMatrix4(f),P.debugDrawLine(m,d,255),P.debugDrawLine(m,L,255),P.debugDrawLine(d,b,255),P.debugDrawLine(L,b,255)}let I=999;if(a&&r.lastScreenCoverage>0){for(let f=0;f<a.length;f++)if(a[f].density/r.lastScreenCoverage<n){I=f;break}}I<i&&(i=I,l=!0)}if(l?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,k&&s.mesh_lod!=r.lastLodLevel_Mesh){const x=a?.[s.mesh_lod];x&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${x.density.toFixed(0)}) - ${e.name}`)}if(p){const x="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,k){const c=g.lods[g.max_count-1];k&&console.log(`First Texture LOD ${s.texture_lod} (${c.max_height}px) - ${e.name}`)}}else{const c=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let w=r.lastScreenCoverage*4;((o=this.context)==null?void 0:o.engine)==="model-viewer"&&(w*=1.5);const _=E/window.devicePixelRatio*w;let B=!1;for(let O=g.lods.length-1;O>=0;O--){let I=g.lods[O];if(!(x&&I.max_height>=2048)&&!(et()&&I.max_height>4096)&&(I.max_height>_||!B&&O===0)){if(B=!0,s.texture_lod=O,s.texture_lod<r.lastLodLevel_Texture){const f=I.max_height;k&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${f}px
|
|
6
|
+
Screensize: ${_.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${c.toFixed(1)}
|
|
7
|
+
${e.name}`)}break}}}}else s.texture_lod=0}};let W=P;T=new WeakMap,z=new WeakMap,we=new WeakMap,Z=new WeakMap,oe=new WeakMap,ce=new WeakMap,V=new WeakMap,W.corner0=new $,W.corner1=new $,W.corner2=new $,W.corner3=new $,W._tempPtInside=new $;class at{constructor(){this.frames=0,this.lastLodLevel_Mesh=-1,this.lastLodLevel_Texture=-1,this.lastScreenCoverage=0,this.lastScreenspaceVolume=new $,this.lastCentrality=0}}const ke=Symbol("NEEDLE_mesh_lod"),de=Symbol("NEEDLE_texture_lod");let he=null;function Re(){const t=lt();t&&(t.mapURLs(function(e){return je(),e}),je(),he?.disconnect(),he=new MutationObserver(e=>{e.forEach(r=>{r.addedNodes.forEach(n=>{n instanceof HTMLElement&&n.tagName.toLowerCase()==="model-viewer"&&We(n)})})}),he.observe(document,{childList:!0,subtree:!0}))}function lt(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Re()}),null)}function je(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(t=>{We(t)})}const Ge=new WeakSet;let ut=0;function We(t){if(!t||Ge.has(t))return null;Ge.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++ut+`
|
|
8
|
+
`,t.getAttribute("src"));let e=null,r=null,n=null;for(let s=t;s!=null;s=Object.getPrototypeOf(s)){const o=Object.getOwnPropertySymbols(s),i=o.find(a=>a.toString()=="Symbol(renderer)"),l=o.find(a=>a.toString()=="Symbol(scene)"),u=o.find(a=>a.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&l!=null&&(r=t[l]),!n&&u!=null&&(n=t[u])}if(e&&r){let s=function(){if(n){let i=0,l=setInterval(()=>{if(i++>5){clearInterval(l);return}n?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=W.get(e,{engine:"model-viewer"});return W.addPlugin(new ct),o.enable(),o.addEventListener("changed",()=>{n?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&n?.call(t)}),t.addEventListener("load",()=>{s()}),()=>{o.disable()}}return null}class ct{constructor(){this._didWarnAboutMissingUrl=!1}onBeforeUpdateLOD(e,r,n,s){this.tryParseMeshLOD(r,s),this.tryParseTextureLOD(r,s)}getUrl(e){if(!e)return null;let r=e.getAttribute("src");return r||(r=e.src),r||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),r}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,r){if(r[de]==!0)return;r[de]=!0;const n=this.tryGetCurrentGLTF(e),s=this.tryGetCurrentModelViewer(e),o=this.getUrl(s);if(o&&n&&r.material){let i=function(u){var a,h,g;if(u[de]==!0)return;u[de]=!0,u.userData&&(u.userData.LOD=-1);const p=Object.keys(u);for(let E=0;E<p.length;E++){const D=p[E],x=u[D];if(x?.isTexture===!0){const c=(h=(a=x.userData)==null?void 0:a.associations)==null?void 0:h.textures;if(c==null)continue;const w=n.parser.json.textures[c];if(!w){console.warn("Texture data not found for texture index "+c);continue}if((g=w?.extensions)!=null&&g[N]){const _=w.extensions[N];_&&o&&S.registerTexture(o,x,_.lods.length,c,_)}}}};const l=r.material;if(Array.isArray(l))for(const u of l)i(u);else i(l)}}tryParseMeshLOD(e,r){var n,s;if(r[ke]==!0)return;r[ke]=!0;const o=this.tryGetCurrentModelViewer(e),i=this.getUrl(o);if(!i)return;const l=(s=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[N];if(l&&i){const u=r.uuid;S.registerMesh(i,u,r,0,l.lods.length,l)}}}function dt(t,e,r,n){pe(e),ve(r),ye(r,{progressive:!0,...n?.hints}),r.register(o=>new S(o,t));const s=W.get(e);return n?.enableLODsManager!==!1&&s.enable(),s}if(Re(),!tt){const t={gltfProgressive:{useNeedleProgressive:dt,LODsManager:W,configureLoader:ye,getRaycastMesh:Q,useRaycastMeshes:st}};if(!globalThis.Needle)globalThis.Needle=t;else for(const e in t)globalThis.Needle[e]=t[e]}export{W as LODsManager,S as NEEDLE_progressive,ve as addDracoAndKTX2Loaders,ye as configureLoader,pe as createLoaders,Q as getRaycastMesh,Ee as setDracoDecoderLocation,Ae as setKTX2TranscoderLocation};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{B as le,M as H,T as ee,a as Ue,V as $,b as Oe,S as Fe,c as Se,d as ze,C as Ve}from"./three.min.js";import{D as qe,K as Ke,G as fe,M as He}from"./three-examples.min.js";const Xe="";globalThis.GLTF_PROGRESSIVE_VERSION=Xe,console.debug("[gltf-progressive] version -");let G="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",J="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ye=G,Je=J,Te=new URL(G+"draco_decoder.js");Te.searchParams.append("range","true"),fetch(Te,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(t=>{console.debug(`Failed to fetch remote Draco decoder from ${G} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),G===Ye&&Ee("./include/draco/"),J===Je&&Ae("./include/ktx2/")}).finally(()=>{Pe()});function Ee(t){G=t,A&&A[me]!=G?(console.debug("Updating Draco decoder path to "+t),A[me]=G,A.setDecoderPath(G),A.preload()):console.debug("Setting Draco decoder path to "+t)}function Ae(t){J=t,C&&C.transcoderPath!=J?(console.debug("Updating KTX2 transcoder path to "+t),C.setTranscoderPath(J),C.init()):console.debug("Setting KTX2 transcoder path to "+t)}const me=Symbol("dracoDecoderPath");let A,ae,C;function Pe(){A||(A=new qe,A[me]=G,A.setDecoderPath(G),A.setDecoderConfig({type:"js"}),A.preload()),C||(C=new Ke,C.setTranscoderPath(J),C.init()),ae||(ae=He)}function pe(t){return Pe(),t?C.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:A,ktx2Loader:C,meshoptDecoder:ae}}function ve(t){t.dracoLoader||t.setDRACOLoader(A),t.ktx2Loader||t.setKTX2Loader(C),t.meshoptDecoder||t.setMeshoptDecoder(ae)}const ye=new WeakMap;function xe(t,e){let r=ye.get(t);r?r=Object.assign(r,e):r=e,ye.set(t,r)}const Be=fe.prototype.load;function Qe(...t){const e=ye.get(this);let r=t[0];const n=new URL(r,window.location.href);if(n.hostname.endsWith("needle.tools")){const s=e?.progressive!==void 0?e.progressive:!0,o=e!=null&&e.usecase?e.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${o}`:this.requestHeader.Accept=`*/*;usecase=${o}`,r=n.toString()}return t[0]=r,Be?.call(this,...t)}fe.prototype.load=Qe,te("debugprogressive");function te(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 Ze(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let ue;function et(){return ue!==void 0||(ue=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),te("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ue)),ue}const tt=typeof window>"u"&&typeof document>"u",Le=Symbol("needle:raycast-mesh");function Q(t){return t?.[Le]instanceof le?t[Le]:null}function rt(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!Q(t)){const r=ot(e);r.userData={isRaycastMesh:!0},t[Le]=r}}function st(t=!0){if(t){if(re)return;const e=re=H.prototype.raycast;H.prototype.raycast=function(r,n){const s=this,o=Q(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),e.call(this,r,n),i&&(s.geometry=i)}}else{if(!re)return;H.prototype.raycast=re,re=null}}let re=null;function ot(t){const e=new le;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const F=new Array,N="NEEDLE_progressive",v=te("debugprogressive"),De=Symbol("needle-progressive-texture"),se=new Map,we=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,se),se.forEach((s,o)=>{for(const i of s.keys){const a=o[i];if(a!=null)if(a.isBufferGeometry===!0){const u=S.getMeshLODInformation(a),l=u?Math.min(e,u.lods.length):0;o["DEBUG:LOD"]=l,u&&(r=Math.max(r,u.lods.length-1))}else o.isMaterial===!0&&(o["DEBUG:LOD"]=e)}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(n=!n,we&&we.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function Ie(t,e,r){var n;if(!v)return;se.has(t)||se.set(t,{keys:[],sourceId:r});const s=se.get(t);((n=s?.keys)==null?void 0:n.includes(e))==!1&&s.keys.push(e)}const w=class{constructor(t,e){this.loadMesh=r=>{var n,s;if(this._isLoadingMesh)return null;const o=(s=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:s[N];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var a;return this._isLoadingMesh=!1,i&&w.registerMesh(this.url,o.guid,i,(a=o.lods)==null?void 0:a.length,void 0,o),i})):null},v&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return N}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[n]=e,e}if(v==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const a of Object.keys(i.uniforms)){const u=i.uniforms[a].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const i of Object.keys(t)){const a=t[i];a?.isTexture===!0&&o(a,e)}return t[n]=e,e;function o(i,a){const u=r.getAssignedLODInformation(i);if(u){const l=r.lodInfos.get(u.key);if(l&&l.lods){a.min_count=Math.min(a.min_count,l.lods.length),a.max_count=Math.max(a.max_count,l.lods.length);for(let h=0;h<l.lods.length;h++){const g=l.lods[h];g.width&&(a.lods[h]=a.lods[h]||{min_height:1/0,max_height:0},a.lods[h].min_height=Math.min(a.lods[h].min_height,g.height),a.lods[h].max_height=Math.max(a.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 i=t[o];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const o of t.children)if(o.isMesh===!0&&this.hasLODLevelAvailable(o,e))return!0}let n,s;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const o=n.userData.LODS;if(s=this.lodInfos.get(o.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof H||t.isMesh===!0){const n=t.geometry,s=this.getAssignedLODInformation(n);if(!s)return Promise.resolve(null);for(const o of F)(r=o.onBeforeGetLODMesh)==null||r.call(o,t,e);return t["LOD:requested level"]=e,w.getOrLoadLOD(n,e).then(o=>{if(Array.isArray(o)){const i=s.index||0;o=o[i]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],o&&n!=o&&(o?.isBufferGeometry?(t.geometry=o,v&&Ie(t,"geometry",s.url)):v&&console.error("Invalid LOD geometry",o))),o}).catch(o=>(console.error("Error loading mesh LOD",t,o),null))}else v&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const o=this.assignTextureLOD(s,e);n.push(o)}return Promise.all(n).then(s=>{const o=new Array;for(const i of s)Array.isArray(i)&&o.push(...i);return o})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,n=[],s=new Array;if(v&&we.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const i of Object.keys(o.uniforms)){const a=o.uniforms[i].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,i).then(l=>(l&&o.uniforms[i].value!=l&&(o.uniforms[i].value=l,o.uniformsNeedUpdate=!0),l));n.push(u),s.push(i)}}}else for(const o of Object.keys(r)){const i=r[o];if(i?.isTexture===!0){const a=this.assignTextureLODForSlot(i,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const i=new Array;for(let a=0;a<o.length;a++){const u=o[a],l=s[a];u&&u.isTexture===!0?i.push({material:r,slot:l,texture:u,level:e}):i.push({material:r,slot:l,texture:null,level:e})}return i})}if(t instanceof ee||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):w.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t){if(r&&n){const o=r[n];if(o&&!v){const i=this.getAssignedLODInformation(o);if(i&&i?.level<e)return v==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,o,s),null}r[n]=s}if(v&&n&&r){const o=this.getAssignedLODInformation(t);o?Ie(r,n,o.url):console.warn("No LOD info for texture",t)}}return s}else v=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return v&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,s)=>{var o;if(n!=null&&n.extensions){const i=n?.extensions[N];if(i){if(!i.lods){v&&console.warn("Texture has no LODs",i);return}let a=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const l=this.parser.associations.get(u);l?.textures===s&&(a=!0,w.registerTexture(this.url,u,(o=i.lods)==null?void 0:o.length,s,i))}a||this.parser.getDependency("texture",s).then(u=>{var l;u&&w.registerTexture(this.url,u,(l=i.lods)==null?void 0:l.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,s)=>{if(n!=null&&n.extensions){const o=n?.extensions[N];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const a=this.parser.associations.get(i);a?.meshes===s&&w.registerMesh(this.url,o.guid,i,o.lods.length,a.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var r,n,s,o;const i=v=="verbose",a=t.userData.LODS;if(!a)return null;const u=a?.key;let l;if(t.isTexture===!0){const h=t;h.source&&h.source[De]&&(l=h.source[De])}if(l||(l=w.lodInfos.get(u)),l){if(e>0){let p=!1;const E=Array.isArray(l.lods);if(E&&e>=l.lods.length?p=!0:E||(p=!0),p)return this.lowresCache.get(u)}const h=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!h)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const g=Ze(a.url,h);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const p=g+"_"+l.guid,E=this.previouslyLoaded.get(p);if(E!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let c=await E.catch(b=>(console.error(`Error loading LOD ${e} from ${g}
|
|
2
|
-
`,
|
|
3
|
-
`,m),null));if(!
|
|
1
|
+
import{BufferGeometry as ae,Mesh as K,Texture as ee,TextureLoader as Ue,Vector3 as $,Matrix4 as be,Sphere as Fe,Box3 as Se,MeshStandardMaterial as ze,Clock as Ve}from"./three.min.js";import{DRACOLoader as qe,KTX2Loader as Xe,GLTFLoader as fe,MeshoptDecoder as Ke}from"./three-examples.min.js";const He="";globalThis.GLTF_PROGRESSIVE_VERSION=He,console.debug("[gltf-progressive] version -");let G="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",J="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ye=G,Je=J,Te=new URL(G+"draco_decoder.js");Te.searchParams.append("range","true"),fetch(Te,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(t=>{console.debug(`Failed to fetch remote Draco decoder from ${G} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),G===Ye&&Ee("./include/draco/"),J===Je&&Ae("./include/ktx2/")}).finally(()=>{Pe()});function Ee(t){G=t,A&&A[me]!=G?(console.debug("Updating Draco decoder path to "+t),A[me]=G,A.setDecoderPath(G),A.preload()):console.debug("Setting Draco decoder path to "+t)}function Ae(t){J=t,C&&C.transcoderPath!=J?(console.debug("Updating KTX2 transcoder path to "+t),C.setTranscoderPath(J),C.init()):console.debug("Setting KTX2 transcoder path to "+t)}const me=Symbol("dracoDecoderPath");let A,le,C;function Pe(){A||(A=new qe,A[me]=G,A.setDecoderPath(G),A.setDecoderConfig({type:"js"}),A.preload()),C||(C=new Xe,C.setTranscoderPath(J),C.init()),le||(le=Ke)}function pe(t){return Pe(),t?C.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:A,ktx2Loader:C,meshoptDecoder:le}}function ve(t){t.dracoLoader||t.setDRACOLoader(A),t.ktx2Loader||t.setKTX2Loader(C),t.meshoptDecoder||t.setMeshoptDecoder(le)}const xe=new WeakMap;function ye(t,e){let r=xe.get(t);r?r=Object.assign(r,e):r=e,xe.set(t,r)}const Be=fe.prototype.load;function Qe(...t){const e=xe.get(this);let r=t[0];const n=new URL(r,window.location.href);if(n.hostname.endsWith("needle.tools")){const s=e?.progressive!==void 0?e.progressive:!0,o=e!=null&&e.usecase?e.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${o}`:this.requestHeader.Accept=`*/*;usecase=${o}`,r=n.toString()}return t[0]=r,Be?.call(this,...t)}fe.prototype.load=Qe,te("debugprogressive");function te(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 Ze(t,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||t===void 0)return e;const r=t.lastIndexOf("/");if(r>=0){const n=t.substring(0,r+1);for(;n.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return n+e}return e}let ue;function et(){return ue!==void 0||(ue=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),te("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ue)),ue}const tt=typeof window>"u"&&typeof document>"u",Le=Symbol("needle:raycast-mesh");function Q(t){return t?.[Le]instanceof ae?t[Le]:null}function rt(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!Q(t)){const r=ot(e);r.userData={isRaycastMesh:!0},t[Le]=r}}function st(t=!0){if(t){if(re)return;const e=re=K.prototype.raycast;K.prototype.raycast=function(r,n){const s=this,o=Q(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),e.call(this,r,n),i&&(s.geometry=i)}}else{if(!re)return;K.prototype.raycast=re,re=null}}let re=null;function ot(t){const e=new ae;for(const r in t.attributes)e.setAttribute(r,t.getAttribute(r));return e.setIndex(t.getIndex()),e}const F=new Array,N="NEEDLE_progressive",v=te("debugprogressive"),De=Symbol("needle-progressive-texture"),se=new Map,Me=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,se),se.forEach((s,o)=>{for(const i of s.keys){const l=o[i];if(l!=null)if(l.isBufferGeometry===!0){const u=S.getMeshLODInformation(l),a=u?Math.min(e,u.lods.length):0;o["DEBUG:LOD"]=a,u&&(r=Math.max(r,u.lods.length-1))}else o.isMaterial===!0&&(o["DEBUG:LOD"]=e)}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(n=!n,Me&&Me.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function Ie(t,e,r){var n;if(!v)return;se.has(t)||se.set(t,{keys:[],sourceId:r});const s=se.get(t);((n=s?.keys)==null?void 0:n.includes(e))==!1&&s.keys.push(e)}const M=class{constructor(t,e){this.loadMesh=r=>{var n,s;if(this._isLoadingMesh)return null;const o=(s=(n=this.parser.json.meshes[r])==null?void 0:n.extensions)==null?void 0:s[N];return o?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",r).then(i=>{var l;return this._isLoadingMesh=!1,i&&M.registerMesh(this.url,o.guid,i,(l=o.lods)==null?void 0:l.length,void 0,o),i})):null},v&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return N}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const i of t)this.getMaterialMinMaxLODsCount(i,e);return t[n]=e,e}if(v==="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=r.getAssignedLODInformation(i);if(u){const a=r.lodInfos.get(u.key);if(a&&a.lods){l.min_count=Math.min(l.min_count,a.lods.length),l.max_count=Math.max(l.max_count,a.lods.length);for(let h=0;h<a.lods.length;h++){const g=a.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 i=t[o];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const o of t.children)if(o.isMesh===!0&&this.hasLODLevelAvailable(o,e))return!0}let n,s;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const o=n.userData.LODS;if(s=this.lodInfos.get(o.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof K||t.isMesh===!0){const n=t.geometry,s=this.getAssignedLODInformation(n);if(!s)return Promise.resolve(null);for(const o of F)(r=o.onBeforeGetLODMesh)==null||r.call(o,t,e);return t["LOD:requested level"]=e,M.getOrLoadLOD(n,e).then(o=>{if(Array.isArray(o)){const i=s.index||0;o=o[i]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],o&&n!=o&&(o?.isBufferGeometry?(t.geometry=o,v&&Ie(t,"geometry",s.url)):v&&console.error("Invalid LOD geometry",o))),o}).catch(o=>(console.error("Error loading mesh LOD",t,o),null))}else v&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const o=this.assignTextureLOD(s,e);n.push(o)}return Promise.all(n).then(s=>{const o=new Array;for(const i of s)Array.isArray(i)&&o.push(...i);return o})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,n=[],s=new Array;if(v&&Me.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const i of Object.keys(o.uniforms)){const l=o.uniforms[i].value;if(l?.isTexture===!0){const u=this.assignTextureLODForSlot(l,e,r,i).then(a=>(a&&o.uniforms[i].value!=a&&(o.uniforms[i].value=a,o.uniformsNeedUpdate=!0),a));n.push(u),s.push(i)}}}else for(const o of Object.keys(r)){const i=r[o];if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,r,o);n.push(l),s.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=s[l];u&&u.isTexture===!0?i.push({material:r,slot:a,texture:u,level:e}):i.push({material:r,slot:a,texture:null,level:e})}return i})}if(t instanceof ee||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):M.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if(s?.isTexture===!0){if(s!=t){if(r&&n){const o=r[n];if(o&&!v){const i=this.getAssignedLODInformation(o);if(i&&i?.level<e)return v==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,o,s),null}r[n]=s}if(v&&n&&r){const o=this.getAssignedLODInformation(t);o?Ie(r,n,o.url):console.warn("No LOD info for texture",t)}}return s}else v=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}afterRoot(t){var e,r;return v&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,s)=>{var o;if(n!=null&&n.extensions){const i=n?.extensions[N];if(i){if(!i.lods){v&&console.warn("Texture has no LODs",i);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const a=this.parser.associations.get(u);a?.textures===s&&(l=!0,M.registerTexture(this.url,u,(o=i.lods)==null?void 0:o.length,s,i))}l||this.parser.getDependency("texture",s).then(u=>{var a;u&&M.registerTexture(this.url,u,(a=i.lods)==null?void 0:a.length,s,i)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,s)=>{if(n!=null&&n.extensions){const o=n?.extensions[N];if(o&&o.lods){for(const i of this.parser.associations.keys())if(i.isMesh){const l=this.parser.associations.get(i);l?.meshes===s&&M.registerMesh(this.url,o.guid,i,o.lods.length,l.primitives,o)}}}}),null}static async getOrLoadLOD(t,e){var r,n,s,o;const i=v=="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[De]&&(a=h.source[De])}if(a||(a=M.lodInfos.get(u)),a){if(e>0){let p=!1;const E=Array.isArray(a.lods);if(E&&e>=a.lods.length?p=!0:E||(p=!0),p)return this.lowresCache.get(u)}const h=Array.isArray(a.lods)?(r=a.lods[e])==null?void 0:r.path:a.lods;if(!h)return v&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const g=Ze(l.url,h);if(g.endsWith(".glb")||g.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const p=g+"_"+a.guid,E=this.previouslyLoaded.get(p);if(E!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let c=await E.catch(_=>(console.error(`Error loading LOD ${e} from ${g}
|
|
2
|
+
`,_),null)),w=!1;if(c==null||(c instanceof ee&&t instanceof ee?(n=c.image)!=null&&n.data||(s=c.source)!=null&&s.data?c=this.copySettings(t,c):(w=!0,this.previouslyLoaded.delete(p)):c instanceof ae&&t instanceof ae&&((o=c.attributes.position)!=null&&o.array||(w=!0,this.previouslyLoaded.delete(p)))),!w)return c}const D=a,x=new Promise(async(c,w)=>{const _=new fe;ve(_),v&&(await new Promise(m=>setTimeout(m,1e3)),i&&console.warn("Start loading (delayed) "+g,D.guid));let B=g;if(D&&Array.isArray(D.lods)){const m=D.lods[e];m.hash&&(B+="?v="+m.hash)}const O=await _.loadAsync(B).catch(m=>(console.error(`Error loading LOD ${e} from ${g}
|
|
3
|
+
`,m),null));if(!O)return null;const I=O.parser;i&&console.log("Loading finished "+g,D.guid);let f=0;if(O.parser.json.textures){let m=!1;for(const d of O.parser.json.textures){if(d!=null&&d.extensions){const L=d?.extensions[N];if(L!=null&&L.guid&&L.guid===D.guid){m=!0;break}}f++}if(m){let d=await I.getDependency("texture",f);return d&&M.assignLODInformation(l.url,d,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+d.name+'"',g,f,d,p),t instanceof ee&&(d=this.copySettings(t,d)),d&&(d.guid=D.guid),c(d)}else v&&console.warn("Could not find texture with guid",D.guid,O.parser.json)}if(f=0,O.parser.json.meshes){let m=!1;for(const d of O.parser.json.meshes){if(d!=null&&d.extensions){const L=d?.extensions[N];if(L!=null&&L.guid&&L.guid===D.guid){m=!0;break}}f++}if(m){const d=await I.getDependency("mesh",f),L=D;if(i&&console.log(`Loaded Mesh "${d.name}"`,g,f,d,p),d.isMesh===!0){const b=d.geometry;return M.assignLODInformation(l.url,b,u,e,void 0,L.density),c(b)}else{const b=new Array;for(let j=0;j<d.children.length;j++){const X=d.children[j];if(X.isMesh===!0){const Y=X.geometry;M.assignLODInformation(l.url,Y,u,e,j,L.density),b.push(Y)}}return c(b)}}else v&&console.warn("Could not find mesh with guid",D.guid,O.parser.json)}return c(null)});return this.previouslyLoaded.set(p,x),await x}else if(t instanceof ee){i&&console.log("Load texture from uri: "+g);const p=await new Ue().loadAsync(g);return p?(p.guid=a.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=t.colorSpace,i&&console.log(a,p)):v&&console.warn("failed loading",g),p}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${u}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,s,o){if(!e)return;e.userData||(e.userData={});const i=new nt(t,r,n,s,o);e.userData.LODS=i}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e?(v&&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 S=w;S.registerTexture=(t,e,r,n,s)=>{if(v&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,s),!e){v&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[De]=s);const o=s.guid;w.assignLODInformation(t,e,o,r,n,void 0),w.lodInfos.set(o,s),w.lowresCache.set(o,e)},S.registerMesh=(t,e,r,n,s,o)=>{var i;v&&console.log("> Progressive: register mesh",s,r.name,o,r.uuid,r);const a=r.geometry;if(!a){v&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),w.assignLODInformation(t,a,e,n,s,o.density),w.lodInfos.set(e,o);let u=w.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],w.lowresCache.set(e,u),n>0&&!Q(r)&&rt(r,a);for(const l of F)(i=l.onRegisteredNewMesh)==null||i.call(l,r,o)},S.lodInfos=new Map,S.previouslyLoaded=new Map,S.lowresCache=new Map;class nt{constructor(e,r,n,s,o){this.url=e,this.key=r,this.level=n,s!=null&&(this.index=s),o!=null&&(this.density=o)}}var Ce=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},x=(t,e,r)=>(Ce(t,e,"read from private field"),r?r.call(t):e.get(t)),X=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},U=(t,e,r,n)=>(Ce(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r),T,z,Me,Z,oe,ce,V;const k=te("debugprogressive"),it=te("noprogressive"),be=Symbol("Needle:LODSManager"),_e=Symbol("Needle:LODState"),q=Symbol("Needle:CurrentLOD"),R={mesh_lod:-1,texture_lod:-1},P=class{constructor(t,e){this.projectionScreenMatrix=new Oe,this.targetTriangleDensity=2e5,this.updateInterval="auto",X(this,T,1),this.pause=!1,this.manual=!1,this._lodchangedlisteners=[],X(this,z,void 0),X(this,Me,new Ve),X(this,Z,0),X(this,oe,0),X(this,ce,0),X(this,V,0),this._fpsBuffer=[60,60,60,60,60],this._sphere=new Fe,this._tempBox=new Se,this._tempBox2=new Se,this.tempMatrix=new Oe,this._tempWorldPosition=new $,this._tempBoxSize=new $,this._tempBox2Size=new $,this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[_e]}static addPlugin(t){F.push(t)}static removePlugin(t){const e=F.indexOf(t);e>=0&&F.splice(e,1)}static get(t,e){if(t[be])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[be];const r=new P(t,{engine:"unknown",...e});return t[be]=r,r}get plugins(){return F}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(x(this,z))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;U(this,z,this.renderer.render);const e=this;pe(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,U(e,Z,x(e,Z)+1),U(e,oe,x(e,Me).getDelta()),U(e,ce,x(e,ce)+x(e,oe)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,oe)),U(e,V,e._fpsBuffer.reduce((i,a)=>i+a)/e._fpsBuffer.length),k&&x(e,Z)%200===0&&console.log("FPS",Math.round(x(e,V)),"Interval:",x(e,T)));const o=t++;x(e,z).call(this,r,n),e.onAfterRender(r,n,o)}}disable(){x(this,z)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=x(this,z),U(this,z,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const n=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(n.length===1){const o=n[0].material;(o.name==="EffectMaterial"||o.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(it||(this.updateInterval==="auto"?x(this,V)<40&&x(this,T)<10?(U(this,T,x(this,T)+1),k&&console.warn("\u2193 Reducing LOD updates",x(this,T),x(this,V).toFixed(0))):x(this,V)>=60&&x(this,T)>1&&(U(this,T,x(this,T)-1),k&&console.warn("\u2191 Increasing LOD updates",x(this,T),x(this,V).toFixed(0))):U(this,T,this.updateInterval),x(this,T)>0&&x(this,Z)%x(this,T)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var r,n;const s=this.renderer.renderLists.get(t,0),o=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const l of o){if(l.material&&(((r=l.geometry)==null?void 0:r.type)==="BoxGeometry"||((n=l.geometry)==null?void 0:n.type)==="BufferGeometry")&&(l.material.name==="SphericalGaussianBlur"||l.material.name=="BackgroundCubeMaterial"||l.material.name==="CubemapFromEquirect"||l.material.name==="EquirectangularToCubeUV")){k&&(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",l,l.material.name,l.material.type)));continue}switch(l.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(k==="color"&&l.material&&!l.object.progressive_debug_color){l.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new ze({color:g});l.object.material=p}const h=l.object;(h instanceof H||h.isMesh)&&this.updateLODs(t,e,h,i)}const a=s.transparent;for(const l of a){const h=l.object;(h instanceof H||h.isMesh)&&this.updateLODs(t,e,h,i)}const u=s.transmissive;for(const l of u){const h=l.object;(h instanceof H||h.isMesh)&&this.updateLODs(t,e,h,i)}}updateLODs(t,e,r,n){var s,o;r.userData||(r.userData={});let i=r[_e];if(i||(i=new lt,r[_e]=i),i.frames++<2)return;for(const u of F)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,R),R.mesh_lod=Math.round(R.mesh_lod),R.texture_lod=Math.round(R.texture_lod),R.mesh_lod>=0&&this.loadProgressiveMeshes(r,R.mesh_lod);let a=R.texture_lod;r.material&&a>=0&&this.loadProgressiveTextures(r.material,a);for(const u of F)(o=u.onAfterUpdatedLOD)==null||o.call(u,this.renderer,t,e,r,R);i.lastLodLevel_Mesh=R.mesh_lod,i.lastLodLevel_Texture=R.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const s of t)this.loadProgressiveTextures(s,e);return}let r=!1;(t[q]===void 0||e<t[q])&&(r=!0);const n=t["DEBUG:LOD"];n!=null&&(r=t[q]!=n,e=n),r&&(t[q]=e,S.assignTextureLOD(t,e).then(s=>{this._lodchangedlisteners.forEach(o=>o({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[q]!==e;const n=t["DEBUG:LOD"];if(n!=null&&(r=t[q]!=n,e=n),r){t[q]=e;const s=t.geometry;return S.assignMeshLOD(t,e).then(o=>(o&&t[q]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(i=>i({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,s){var o;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let i=10+1,a=!1;if(k&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),l=u?.lods,h=l&&l.length>0,g=S.getMaterialMinMaxLODsCount(e.material),p=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!h&&!p){s.mesh_lod=0,s.texture_lod=0;return}h||(a=!0,i=0);const E=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const y=e;if(!y.boundingBox)y.computeBoundingBox();else if(r.frames%30===0){const c=Q(y),M=y.geometry;c&&(y.geometry=c),y.computeBoundingBox(),y.geometry=M}D=y.boundingBox}if(D){const y=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 f=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),y.isPerspectiveCamera&&P.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.isPerspectiveCamera&&y.fov>70){const f=this._tempBox.min,m=this._tempBox.max;let d=f.x,L=f.y,O=m.x,j=m.y;const K=2,Y=1.5,ne=(f.x+m.x)*.5,ie=(f.y+m.y)*.5;d=(d-ne)*K+ne,L=(L-ie)*K+ie,O=(O-ne)*K+ne,j=(j-ie)*K+ie;const $e=d<0&&O>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),Ne=L<0&&j>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),ge=Math.max($e,Ne);r.lastCentrality=(Y-ge)*(Y-ge)*(Y-ge)}else r.lastCentrality=1;const c=this._tempBox.getSize(this._tempBoxSize);c.multiplyScalar(.5),screen.availHeight>0&&E>0&&c.multiplyScalar(E/screen.availHeight),t.isPerspectiveCamera?c.x*=t.aspect:t.isOrthographicCamera;const M=t.matrixWorldInverse,b=this._tempBox2;b.copy(D),b.applyMatrix4(e.matrixWorld),b.applyMatrix4(M);const B=b.getSize(this._tempBox2Size),_=Math.max(B.x,B.y);if(Math.max(c.x,c.y)!=0&&_!=0&&(c.z=B.z/Math.max(B.x,B.y)*Math.max(c.x,c.y)),r.lastScreenCoverage=Math.max(c.x,c.y,c.z),r.lastScreenspaceVolume.copy(c),r.lastScreenCoverage*=r.lastCentrality,k&&P.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const m=P.corner0,d=P.corner1,L=P.corner2,O=P.corner3;m.copy(this._tempBox.min),d.copy(this._tempBox.max),d.x=m.x,L.copy(this._tempBox.max),L.y=m.y,O.copy(this._tempBox.max);const j=(m.z+O.z)*.5;m.z=d.z=L.z=O.z=j,m.applyMatrix4(f),d.applyMatrix4(f),L.applyMatrix4(f),O.applyMatrix4(f),P.debugDrawLine(m,d,255),P.debugDrawLine(m,L,255),P.debugDrawLine(d,O,255),P.debugDrawLine(L,O,255)}let I=999;if(l&&r.lastScreenCoverage>0){for(let f=0;f<l.length;f++)if(l[f].density/r.lastScreenCoverage<n){I=f;break}}I<i&&(i=I,a=!0)}if(a?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,k&&s.mesh_lod!=r.lastLodLevel_Mesh){const y=l?.[s.mesh_lod];y&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${y.density.toFixed(0)}) - ${e.name}`)}if(p){const y="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,k){const c=g.lods[g.max_count-1];k&&console.log(`First Texture LOD ${s.texture_lod} (${c.max_height}px) - ${e.name}`)}}else{const c=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let M=r.lastScreenCoverage*4;((o=this.context)==null?void 0:o.engine)==="model-viewer"&&(M*=1.5);const b=E/window.devicePixelRatio*M;let B=!1;for(let _=g.lods.length-1;_>=0;_--){let I=g.lods[_];if(!(y&&I.max_height>=2048)&&!(et()&&I.max_height>4096)&&(I.max_height>b||!B&&_===0)){if(B=!0,s.texture_lod=_,s.texture_lod<r.lastLodLevel_Texture){const f=I.max_height;k&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${f}px
|
|
6
|
-
Screensize: ${
|
|
7
|
-
${e.name}`)}break}}}}else s.texture_lod=0}};let W=P;T=new WeakMap,z=new WeakMap,
|
|
8
|
-
`,t.getAttribute("src"));let e=null,r=null,n=null;for(let s=t;s!=null;s=Object.getPrototypeOf(s)){const o=Object.getOwnPropertySymbols(s),i=o.find(
|
|
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 S=M;S.registerTexture=(t,e,r,n,s)=>{if(v&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,s),!e){v&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[De]=s);const o=s.guid;M.assignLODInformation(t,e,o,r,n,void 0),M.lodInfos.set(o,s),M.lowresCache.set(o,e)},S.registerMesh=(t,e,r,n,s,o)=>{var i;v&&console.log("> Progressive: register mesh",s,r.name,o,r.uuid,r);const l=r.geometry;if(!l){v&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),M.assignLODInformation(t,l,e,n,s,o.density),M.lodInfos.set(e,o);let u=M.lowresCache.get(e);u?u.push(r.geometry):u=[r.geometry],M.lowresCache.set(e,u),n>0&&!Q(r)&&rt(r,l);for(const a of F)(i=a.onRegisteredNewMesh)==null||i.call(a,r,o)},S.lodInfos=new Map,S.previouslyLoaded=new Map,S.lowresCache=new Map;class nt{constructor(e,r,n,s,o){this.url=e,this.key=r,this.level=n,s!=null&&(this.index=s),o!=null&&(this.density=o)}}var Ce=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},y=(t,e,r)=>(Ce(t,e,"read from private field"),r?r.call(t):e.get(t)),H=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},U=(t,e,r,n)=>(Ce(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r),T,z,we,Z,oe,ce,V;const k=te("debugprogressive"),it=te("noprogressive"),_e=Symbol("Needle:LODSManager"),Oe=Symbol("Needle:LODState"),q=Symbol("Needle:CurrentLOD"),R={mesh_lod:-1,texture_lod:-1},P=class{constructor(t,e){this.projectionScreenMatrix=new be,this.targetTriangleDensity=2e5,this.updateInterval="auto",H(this,T,1),this.pause=!1,this.manual=!1,this._lodchangedlisteners=[],H(this,z,void 0),H(this,we,new Ve),H(this,Z,0),H(this,oe,0),H(this,ce,0),H(this,V,0),this._fpsBuffer=[60,60,60,60,60],this._sphere=new Fe,this._tempBox=new Se,this._tempBox2=new Se,this.tempMatrix=new be,this._tempWorldPosition=new $,this._tempBoxSize=new $,this._tempBox2Size=new $,this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[Oe]}static addPlugin(t){F.push(t)}static removePlugin(t){const e=F.indexOf(t);e>=0&&F.splice(e,1)}static get(t,e){if(t[_e])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[_e];const r=new P(t,{engine:"unknown",...e});return t[_e]=r,r}get plugins(){return F}addEventListener(t,e){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}enable(){if(y(this,z))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;U(this,z,this.renderer.render);const e=this;pe(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,U(e,Z,y(e,Z)+1),U(e,oe,y(e,we).getDelta()),U(e,ce,y(e,ce)+y(e,oe)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/y(e,oe)),U(e,V,e._fpsBuffer.reduce((i,l)=>i+l)/e._fpsBuffer.length),k&&y(e,Z)%200===0&&console.log("FPS",Math.round(y(e,V)),"Interval:",y(e,T)));const o=t++;y(e,z).call(this,r,n),e.onAfterRender(r,n,o)}}disable(){y(this,z)&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=y(this,z),U(this,z,void 0))}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const n=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(n.length===1){const o=n[0].material;(o.name==="EffectMaterial"||o.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(it||(this.updateInterval==="auto"?y(this,V)<40&&y(this,T)<10?(U(this,T,y(this,T)+1),k&&console.warn("\u2193 Reducing LOD updates",y(this,T),y(this,V).toFixed(0))):y(this,V)>=60&&y(this,T)>1&&(U(this,T,y(this,T)-1),k&&console.warn("\u2191 Increasing LOD updates",y(this,T),y(this,V).toFixed(0))):U(this,T,this.updateInterval),y(this,T)>0&&y(this,Z)%y(this,T)!=0))return;this.internalUpdate(t,e)}}internalUpdate(t,e){var r,n;const s=this.renderer.renderLists.get(t,0),o=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const i=this.targetTriangleDensity;for(const a of o){if(a.material&&(((r=a.geometry)==null?void 0:r.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")){k&&(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(k==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new ze({color:g});a.object.material=p}const h=a.object;(h instanceof K||h.isMesh)&&this.updateLODs(t,e,h,i)}const l=s.transparent;for(const a of l){const h=a.object;(h instanceof K||h.isMesh)&&this.updateLODs(t,e,h,i)}const u=s.transmissive;for(const a of u){const h=a.object;(h instanceof K||h.isMesh)&&this.updateLODs(t,e,h,i)}}updateLODs(t,e,r,n){var s,o;r.userData||(r.userData={});let i=r[Oe];if(i||(i=new at,r[Oe]=i),i.frames++<2)return;for(const u of F)(s=u.onBeforeUpdateLOD)==null||s.call(u,this.renderer,t,e,r);this.calculateLodLevel(e,r,i,n,R),R.mesh_lod=Math.round(R.mesh_lod),R.texture_lod=Math.round(R.texture_lod),R.mesh_lod>=0&&this.loadProgressiveMeshes(r,R.mesh_lod);let l=R.texture_lod;r.material&&l>=0&&this.loadProgressiveTextures(r.material,l);for(const u of F)(o=u.onAfterUpdatedLOD)==null||o.call(u,this.renderer,t,e,r,R);i.lastLodLevel_Mesh=R.mesh_lod,i.lastLodLevel_Texture=R.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const s of t)this.loadProgressiveTextures(s,e);return}let r=!1;(t[q]===void 0||e<t[q])&&(r=!0);const n=t["DEBUG:LOD"];n!=null&&(r=t[q]!=n,e=n),r&&(t[q]=e,S.assignTextureLOD(t,e).then(s=>{this._lodchangedlisteners.forEach(o=>o({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[q]!==e;const n=t["DEBUG:LOD"];if(n!=null&&(r=t[q]!=n,e=n),r){t[q]=e;const s=t.geometry;return S.assignMeshLOD(t,e).then(o=>(o&&t[q]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(i=>i({type:"mesh",level:e,object:t})),o))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n,s){var o;if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let i=10+1,l=!1;if(k&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),a=u?.lods,h=a&&a.length>0,g=S.getMaterialMinMaxLODsCount(e.material),p=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!h&&!p){s.mesh_lod=0,s.texture_lod=0;return}h||(l=!0,i=0);const E=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const x=e;if(!x.boundingBox)x.computeBoundingBox();else if(r.frames%30===0){const c=Q(x),w=x.geometry;c&&(x.geometry=c),x.computeBoundingBox(),x.geometry=w}D=x.boundingBox}if(D){const x=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 f=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(f)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),x.isPerspectiveCamera&&P.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&x.isPerspectiveCamera&&x.fov>70){const f=this._tempBox.min,m=this._tempBox.max;let d=f.x,L=f.y,b=m.x,j=m.y;const X=2,Y=1.5,ne=(f.x+m.x)*.5,ie=(f.y+m.y)*.5;d=(d-ne)*X+ne,L=(L-ie)*X+ie,b=(b-ne)*X+ne,j=(j-ie)*X+ie;const $e=d<0&&b>0?0:Math.min(Math.abs(f.x),Math.abs(m.x)),Ne=L<0&&j>0?0:Math.min(Math.abs(f.y),Math.abs(m.y)),ge=Math.max($e,Ne);r.lastCentrality=(Y-ge)*(Y-ge)*(Y-ge)}else r.lastCentrality=1;const c=this._tempBox.getSize(this._tempBoxSize);c.multiplyScalar(.5),screen.availHeight>0&&E>0&&c.multiplyScalar(E/screen.availHeight),t.isPerspectiveCamera?c.x*=t.aspect:t.isOrthographicCamera;const w=t.matrixWorldInverse,_=this._tempBox2;_.copy(D),_.applyMatrix4(e.matrixWorld),_.applyMatrix4(w);const B=_.getSize(this._tempBox2Size),O=Math.max(B.x,B.y);if(Math.max(c.x,c.y)!=0&&O!=0&&(c.z=B.z/Math.max(B.x,B.y)*Math.max(c.x,c.y)),r.lastScreenCoverage=Math.max(c.x,c.y,c.z),r.lastScreenspaceVolume.copy(c),r.lastScreenCoverage*=r.lastCentrality,k&&P.debugDrawLine){const f=this.tempMatrix.copy(this.projectionScreenMatrix);f.invert();const m=P.corner0,d=P.corner1,L=P.corner2,b=P.corner3;m.copy(this._tempBox.min),d.copy(this._tempBox.max),d.x=m.x,L.copy(this._tempBox.max),L.y=m.y,b.copy(this._tempBox.max);const j=(m.z+b.z)*.5;m.z=d.z=L.z=b.z=j,m.applyMatrix4(f),d.applyMatrix4(f),L.applyMatrix4(f),b.applyMatrix4(f),P.debugDrawLine(m,d,255),P.debugDrawLine(m,L,255),P.debugDrawLine(d,b,255),P.debugDrawLine(L,b,255)}let I=999;if(a&&r.lastScreenCoverage>0){for(let f=0;f<a.length;f++)if(a[f].density/r.lastScreenCoverage<n){I=f;break}}I<i&&(i=I,l=!0)}if(l?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,k&&s.mesh_lod!=r.lastLodLevel_Mesh){const x=a?.[s.mesh_lod];x&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${x.density.toFixed(0)}) - ${e.name}`)}if(p){const x="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,k){const c=g.lods[g.max_count-1];k&&console.log(`First Texture LOD ${s.texture_lod} (${c.max_height}px) - ${e.name}`)}}else{const c=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let w=r.lastScreenCoverage*4;((o=this.context)==null?void 0:o.engine)==="model-viewer"&&(w*=1.5);const _=E/window.devicePixelRatio*w;let B=!1;for(let O=g.lods.length-1;O>=0;O--){let I=g.lods[O];if(!(x&&I.max_height>=2048)&&!(et()&&I.max_height>4096)&&(I.max_height>_||!B&&O===0)){if(B=!0,s.texture_lod=O,s.texture_lod<r.lastLodLevel_Texture){const f=I.max_height;k&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${f}px
|
|
6
|
+
Screensize: ${_.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${c.toFixed(1)}
|
|
7
|
+
${e.name}`)}break}}}}else s.texture_lod=0}};let W=P;T=new WeakMap,z=new WeakMap,we=new WeakMap,Z=new WeakMap,oe=new WeakMap,ce=new WeakMap,V=new WeakMap,W.corner0=new $,W.corner1=new $,W.corner2=new $,W.corner3=new $,W._tempPtInside=new $;class at{constructor(){this.frames=0,this.lastLodLevel_Mesh=-1,this.lastLodLevel_Texture=-1,this.lastScreenCoverage=0,this.lastScreenspaceVolume=new $,this.lastCentrality=0}}const ke=Symbol("NEEDLE_mesh_lod"),de=Symbol("NEEDLE_texture_lod");let he=null;function Re(){const t=lt();t&&(t.mapURLs(function(e){return je(),e}),je(),he?.disconnect(),he=new MutationObserver(e=>{e.forEach(r=>{r.addedNodes.forEach(n=>{n instanceof HTMLElement&&n.tagName.toLowerCase()==="model-viewer"&&We(n)})})}),he.observe(document,{childList:!0,subtree:!0}))}function lt(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Re()}),null)}function je(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(t=>{We(t)})}const Ge=new WeakSet;let ut=0;function We(t){if(!t||Ge.has(t))return null;Ge.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++ut+`
|
|
8
|
+
`,t.getAttribute("src"));let e=null,r=null,n=null;for(let s=t;s!=null;s=Object.getPrototypeOf(s)){const o=Object.getOwnPropertySymbols(s),i=o.find(a=>a.toString()=="Symbol(renderer)"),l=o.find(a=>a.toString()=="Symbol(scene)"),u=o.find(a=>a.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&l!=null&&(r=t[l]),!n&&u!=null&&(n=t[u])}if(e&&r){let s=function(){if(n){let i=0,l=setInterval(()=>{if(i++>5){clearInterval(l);return}n?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=W.get(e,{engine:"model-viewer"});return W.addPlugin(new ct),o.enable(),o.addEventListener("changed",()=>{n?.call(t)}),t.addEventListener("model-visibility",i=>{i.detail.visible&&n?.call(t)}),t.addEventListener("load",()=>{s()}),()=>{o.disable()}}return null}class ct{constructor(){this._didWarnAboutMissingUrl=!1}onBeforeUpdateLOD(e,r,n,s){this.tryParseMeshLOD(r,s),this.tryParseTextureLOD(r,s)}getUrl(e){if(!e)return null;let r=e.getAttribute("src");return r||(r=e.src),r||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",e),this._didWarnAboutMissingUrl=!0),r}tryGetCurrentGLTF(e){return e._currentGLTF}tryGetCurrentModelViewer(e){return e.element}tryParseTextureLOD(e,r){if(r[de]==!0)return;r[de]=!0;const n=this.tryGetCurrentGLTF(e),s=this.tryGetCurrentModelViewer(e),o=this.getUrl(s);if(o&&n&&r.material){let i=function(u){var a,h,g;if(u[de]==!0)return;u[de]=!0,u.userData&&(u.userData.LOD=-1);const p=Object.keys(u);for(let E=0;E<p.length;E++){const D=p[E],x=u[D];if(x?.isTexture===!0){const c=(h=(a=x.userData)==null?void 0:a.associations)==null?void 0:h.textures;if(c==null)continue;const w=n.parser.json.textures[c];if(!w){console.warn("Texture data not found for texture index "+c);continue}if((g=w?.extensions)!=null&&g[N]){const _=w.extensions[N];_&&o&&S.registerTexture(o,x,_.lods.length,c,_)}}}};const l=r.material;if(Array.isArray(l))for(const u of l)i(u);else i(l)}}tryParseMeshLOD(e,r){var n,s;if(r[ke]==!0)return;r[ke]=!0;const o=this.tryGetCurrentModelViewer(e),i=this.getUrl(o);if(!i)return;const l=(s=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[N];if(l&&i){const u=r.uuid;S.registerMesh(i,u,r,0,l.lods.length,l)}}}function dt(t,e,r,n){pe(e),ve(r),ye(r,{progressive:!0,...n?.hints}),r.register(o=>new S(o,t));const s=W.get(e);return n?.enableLODsManager!==!1&&s.enable(),s}if(Re(),!tt){const t={gltfProgressive:{useNeedleProgressive:dt,LODsManager:W,configureLoader:ye,getRaycastMesh:Q,useRaycastMeshes:st}};if(!globalThis.Needle)globalThis.Needle=t;else for(const e in t)globalThis.Needle[e]=t[e]}export{W as LODsManager,S as NEEDLE_progressive,ve as addDracoAndKTX2Loaders,ye as configureLoader,pe as createLoaders,Q as getRaycastMesh,Ee as setDracoDecoderLocation,Ae as setKTX2TranscoderLocation};
|