@needle-tools/gltf-progressive 1.2.11 → 1.2.13
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 +163 -156
- package/README.md +131 -125
- package/examples/modelviewer-multiple.html +124 -124
- package/examples/modelviewer.html +32 -32
- package/examples/react-three-fiber/.prettierrc +9 -9
- package/examples/react-three-fiber/index.html +23 -23
- package/examples/react-three-fiber/package-lock.json +4023 -4023
- package/examples/react-three-fiber/package.json +34 -34
- package/examples/react-three-fiber/tsconfig.json +21 -21
- package/examples/react-three-fiber/vite.config.js +38 -38
- package/examples/threejs/index.html +50 -50
- package/examples/threejs/main.js +181 -181
- package/gltf-progressive.js +17 -7
- package/gltf-progressive.min.js +5 -5
- package/gltf-progressive.umd.cjs +1 -1
- package/lib/extension.d.ts +3 -1
- package/lib/extension.js +22 -7
- package/lib/loaders.d.ts +2 -2
- package/lib/version.js +1 -1
- package/package.json +1 -1
package/gltf-progressive.js
CHANGED
|
@@ -258,16 +258,26 @@ const v = class {
|
|
|
258
258
|
x && console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh", t);
|
|
259
259
|
return Promise.resolve(null);
|
|
260
260
|
}
|
|
261
|
-
/** Load a different resolution of a texture (if available)
|
|
262
|
-
* @param context the context
|
|
263
|
-
* @param source the sourceid of the file from which the texture is loaded (this is usually the component's sourceId)
|
|
264
|
-
* @param materialOrTexture the material or texture to load the LOD for (if passing in a material all textures in the material will be loaded)
|
|
265
|
-
* @param level the level of detail to load (0 is the highest resolution) - currently only 0 is supported
|
|
266
|
-
* @returns a promise that resolves to the material or texture with the requested LOD level
|
|
267
|
-
*/
|
|
268
261
|
static assignTextureLOD(t, e = 0) {
|
|
269
262
|
if (!t)
|
|
270
263
|
return Promise.resolve(null);
|
|
264
|
+
if (t.isMesh === !0) {
|
|
265
|
+
const s = t;
|
|
266
|
+
if (Array.isArray(s.material)) {
|
|
267
|
+
const n = new Array();
|
|
268
|
+
for (const r of s.material) {
|
|
269
|
+
const i = this.assignTextureLOD(r, e);
|
|
270
|
+
n.push(i);
|
|
271
|
+
}
|
|
272
|
+
return Promise.all(n).then((r) => {
|
|
273
|
+
const i = new Array();
|
|
274
|
+
for (const o of r)
|
|
275
|
+
Array.isArray(o) && i.push(...o);
|
|
276
|
+
return i;
|
|
277
|
+
});
|
|
278
|
+
} else
|
|
279
|
+
return this.assignTextureLOD(s.material, e);
|
|
280
|
+
}
|
|
271
281
|
if (t instanceof ze || t.isMaterial === !0) {
|
|
272
282
|
const s = t, n = [], r = new Array();
|
|
273
283
|
if (x && Oe.add(s), s.uniforms && (s.isRawShaderMaterial || s.isShaderMaterial === !0)) {
|
package/gltf-progressive.min.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var Re=Object.defineProperty,je=(t,e,r)=>e in t?Re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(je(t,typeof e!="symbol"?e+"":e,r),r),Oe=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},x=(t,e,r)=>(Oe(t,e,"read from private field"),r?r.call(t):e.get(t)),V=(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)},G=(t,e,r,n)=>(Oe(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r);import{BufferGeometry as ae,Mesh as q,Material as Ge,Texture as Z,TextureLoader as Ne,Matrix4 as be,Clock as We,MeshStandardMaterial as Fe,Sphere as $e,Box3 as Se,Vector3 as N}from"three";import{GLTFLoader as Ue}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as ze}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Ve}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as qe}from"three/examples/jsm/loaders/KTX2Loader.js";const me="";globalThis.GLTF_PROGRESSIVE_VERSION=me,console.debug(`[gltf-progressive] version ${me}`);let K="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",ee="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Xe=K,Ke=ee;fetch(K+"draco_decoder.js",{method:"head"}).catch(t=>{K===Xe&&(K="./include/draco/"),ee===Ke&&(ee="./include/ktx2/")});function He(t){K=t}function Ye(t){ee=t}let H,ue,Y;function pe(t){return H||(H=new Ve,H.setDecoderPath(K),H.setDecoderConfig({type:"js"})),Y||(Y=new qe,Y.setTranscoderPath(ee)),ue||(ue=ze),t?Y.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:H,ktx2Loader:Y,meshoptDecoder:ue}}function ve(t){t.dracoLoader||t.setDRACOLoader(H),t.ktx2Loader||t.setKTX2Loader(Y),t.meshoptDecoder||t.setMeshoptDecoder(ue)}te("debugprogressive");function te(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Je(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 ce;function Qe(){return ce!==void 0||(ce=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),te("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ce)),ce}const xe=Symbol("needle:raycast-mesh");function re(t){return t?.[xe]instanceof ae?t[xe]:null}function Te(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!re(t)){const r=et(e);r.userData={isRaycastMesh:!0},t[xe]=r}}function Ze(t=!0){if(t){if(se)return;const e=se=q.prototype.raycast;q.prototype.raycast=function(r,n){const s=this,o=re(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),e.call(this,r,n),i&&(s.geometry=i)}}else{if(!se)return;q.prototype.raycast=se,se=null}}let se=null;function et(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,R="NEEDLE_progressive",y=te("debugprogressive"),ye=Symbol("needle-progressive-texture"),oe=new Map,Le=new Set;if(y){let t=function(){e+=1,console.log("Toggle LOD level",e,oe),oe.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"]=e,S.assignMeshLOD(o,l),u&&(r=Math.max(r,u.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,S.assignTextureLOD(o,e);break}}}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(n=!n,Le&&Le.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function Ee(t,e,r){var n;if(!y)return;oe.has(t)||oe.set(t,{keys:[],sourceId:r});const s=oe.get(t);((n=s?.keys)==null?void 0:n.includes(e))==!1&&s.keys.push(e)}const w=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(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[R];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}),y&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return R}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(y==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const i=t;for(const a of Object.keys(i.uniforms)){const u=i.uniforms[a].value;u?.isTexture===!0&&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 f=0;f<l.lods.length;f++){const g=l.lods[f];g.width&&(a.lods[f]=a.lods[f]||{min_height:1/0,max_height:0},a.lods[f].min_height=Math.min(a.lods[f].min_height,g.height),a.lods[f].max_height=Math.max(a.lods[f].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 q||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(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(o)){const i=s.index||0;o=o[i]}o&&n!=o&&(o?.isBufferGeometry?(t.geometry=o,y&&Ee(t,"geometry",s.url)):y&&console.error("Invalid LOD geometry",o))}return o}).catch(o=>(console.error("Error loading mesh LOD",t,o),null))}else y&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t instanceof Ge||t.isMaterial===!0){const r=t,n=[],s=new Array;if(y&&Le.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 Z||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):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){const i=this.getAssignedLODInformation(o);if(i&&i?.level<e)return y==="verbose"&&console.warn("Assigned texture level is already higher: ",i.level,e,r,o,s),null}r[n]=s}if(y&&n&&r){const o=this.getAssignedLODInformation(t);o&&Ee(r,n,o.url)}}return s}else y=="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 y&&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[R];if(i){if(!i.lods){y&&console.warn("Texture has no LODs",i);return}let a=!1;for(const u of this.parser.associations.keys())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[R];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=y=="verbose",a=t.userData.LODS;if(!a)return null;const u=a?.key;let l;if(t.isTexture===!0){const f=t;f.source&&f.source[ye]&&(l=f.source[ye])}if(l||(l=w.lodInfos.get(u)),l){if(e>0){let p=!1;const A=Array.isArray(l.lods);if(A&&e>=l.lods.length?p=!0:A||(p=!0),p)return this.lowresCache.get(u)}const f=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!f)return y&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const g=Je(a.url,f);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,A=this.previouslyLoaded.get(p);if(A!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let d=await A.catch(O=>(console.error(`Error loading LOD ${e} from ${g}
|
|
2
|
-
`,O),null)),_=!1;if(d==null||(d instanceof Z&&t instanceof Z?(n=d.image)!=null&&n.data||(s=d.source)!=null&&s.data?d=this.copySettings(t,d):(_=!0,this.previouslyLoaded.delete(p)):d instanceof ae&&t instanceof ae&&((o=d.attributes.position)!=null&&o.array||(_=!0,this.previouslyLoaded.delete(p)))),!_)return d}const D=l,L=new Promise(async(d,_)=>{const O=new Ue;
|
|
3
|
-
`,m),null));if(!T)return null;const W=T.parser;i&&console.log("Loading finished "+g,D.guid);let
|
|
1
|
+
var Re=Object.defineProperty,je=(t,e,r)=>e in t?Re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(je(t,typeof e!="symbol"?e+"":e,r),r),Oe=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)},x=(t,e,r)=>(Oe(t,e,"read from private field"),r?r.call(t):e.get(t)),V=(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)},G=(t,e,r,n)=>(Oe(t,e,"write to private field"),n?n.call(t,r):e.set(t,r),r);import{BufferGeometry as ae,Mesh as q,Material as Ge,Texture as Z,TextureLoader as Ne,Matrix4 as be,Clock as We,MeshStandardMaterial as Fe,Sphere as $e,Box3 as Se,Vector3 as N}from"three";import{GLTFLoader as Ue}from"three/examples/jsm/loaders/GLTFLoader.js";import{MeshoptDecoder as ze}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as Ve}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as qe}from"three/examples/jsm/loaders/KTX2Loader.js";const me="";globalThis.GLTF_PROGRESSIVE_VERSION=me,console.debug(`[gltf-progressive] version ${me}`);let K="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",ee="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Xe=K,Ke=ee;fetch(K+"draco_decoder.js",{method:"head"}).catch(t=>{K===Xe&&(K="./include/draco/"),ee===Ke&&(ee="./include/ktx2/")});function He(t){K=t}function Ye(t){ee=t}let H,ue,Y;function pe(t){return H||(H=new Ve,H.setDecoderPath(K),H.setDecoderConfig({type:"js"})),Y||(Y=new qe,Y.setTranscoderPath(ee)),ue||(ue=ze),t?Y.detectSupport(t):t!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:H,ktx2Loader:Y,meshoptDecoder:ue}}function ye(t){t.dracoLoader||t.setDRACOLoader(H),t.ktx2Loader||t.setKTX2Loader(Y),t.meshoptDecoder||t.setMeshoptDecoder(ue)}te("debugprogressive");function te(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Je(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 ce;function Qe(){return ce!==void 0||(ce=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),te("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ce)),ce}const xe=Symbol("needle:raycast-mesh");function re(t){return t?.[xe]instanceof ae?t[xe]:null}function Te(t,e){if((t.type==="Mesh"||t.type==="SkinnedMesh")&&!re(t)){const r=et(e);r.userData={isRaycastMesh:!0},t[xe]=r}}function Ze(t=!0){if(t){if(se)return;const e=se=q.prototype.raycast;q.prototype.raycast=function(r,n){const s=this,o=re(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),e.call(this,r,n),i&&(s.geometry=i)}}else{if(!se)return;q.prototype.raycast=se,se=null}}let se=null;function et(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,R="NEEDLE_progressive",v=te("debugprogressive"),ve=Symbol("needle-progressive-texture"),oe=new Map,Le=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,oe),oe.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"]=e,S.assignMeshLOD(o,l),u&&(r=Math.max(r,u.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,S.assignTextureLOD(o,e);break}}}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",s=>{s.key==="p"&&t(),s.key==="w"&&(n=!n,Le&&Le.forEach(o=>{o.name!="BackgroundCubeMaterial"&&o.glyphMap==null&&"wireframe"in o&&(o.wireframe=n)}))})}function Ee(t,e,r){var n;if(!v)return;oe.has(t)||oe.set(t,{keys:[],sourceId:r});const s=oe.get(t);((n=s?.keys)==null?void 0:n.includes(e))==!1&&s.keys.push(e)}const w=class{constructor(t,e){c(this,"parser"),c(this,"url"),c(this,"_isLoadingMesh"),c(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[R];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 R}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 f=0;f<l.lods.length;f++){const g=l.lods[f];g.width&&(a.lods[f]=a.lods[f]||{min_height:1/0,max_height:0},a.lods[f].min_height=Math.min(a.lods[f].min_height,g.height),a.lods[f].max_height=Math.max(a.lods[f].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 q||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(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(o)){const i=s.index||0;o=o[i]}o&&n!=o&&(o?.isBufferGeometry?(t.geometry=o,v&&Ee(t,"geometry",s.url)):v&&console.error("Invalid LOD geometry",o))}return 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 instanceof Ge||t.isMaterial===!0){const r=t,n=[],s=new Array;if(v&&Le.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 Z||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):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){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&&Ee(r,n,o.url)}}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[R];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[R];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 f=t;f.source&&f.source[ve]&&(l=f.source[ve])}if(l||(l=w.lodInfos.get(u)),l){if(e>0){let p=!1;const A=Array.isArray(l.lods);if(A&&e>=l.lods.length?p=!0:A||(p=!0),p)return this.lowresCache.get(u)}const f=Array.isArray(l.lods)?(r=l.lods[e])==null?void 0:r.path:l.lods;if(!f)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const g=Je(a.url,f);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,A=this.previouslyLoaded.get(p);if(A!==void 0){i&&console.log(`LOD ${e} was already loading/loaded: ${p}`);let d=await A.catch(O=>(console.error(`Error loading LOD ${e} from ${g}
|
|
2
|
+
`,O),null)),_=!1;if(d==null||(d instanceof Z&&t instanceof Z?(n=d.image)!=null&&n.data||(s=d.source)!=null&&s.data?d=this.copySettings(t,d):(_=!0,this.previouslyLoaded.delete(p)):d instanceof ae&&t instanceof ae&&((o=d.attributes.position)!=null&&o.array||(_=!0,this.previouslyLoaded.delete(p)))),!_)return d}const D=l,L=new Promise(async(d,_)=>{const O=new Ue;ye(O),v&&(await new Promise(m=>setTimeout(m,1e3)),i&&console.warn("Start loading (delayed) "+g,D.guid));let I=g;if(D&&Array.isArray(D.lods)){const m=D.lods[e];m.hash&&(I+="?v="+m.hash)}const T=await O.loadAsync(I).catch(m=>(console.error(`Error loading LOD ${e} from ${g}
|
|
3
|
+
`,m),null));if(!T)return null;const W=T.parser;i&&console.log("Loading finished "+g,D.guid);let y=0;if(T.parser.json.textures){let m=!1;for(const h of T.parser.json.textures){if(h!=null&&h.extensions){const M=h?.extensions[R];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}y++}if(m){let h=await W.getDependency("texture",y);return h&&w.assignLODInformation(a.url,h,u,e,void 0,void 0),i&&console.log('change "'+t.name+'" \u2192 "'+h.name+'"',g,y,h,p),t instanceof Z&&(h=this.copySettings(t,h)),h&&(h.guid=D.guid),d(h)}else v&&console.warn("Could not find texture with guid",D.guid,T.parser.json)}if(y=0,T.parser.json.meshes){let m=!1;for(const h of T.parser.json.meshes){if(h!=null&&h.extensions){const M=h?.extensions[R];if(M!=null&&M.guid&&M.guid===D.guid){m=!0;break}}y++}if(m){const h=await W.getDependency("mesh",y),M=D;if(i&&console.log(`Loaded Mesh "${h.name}"`,g,y,h,p),h.isMesh===!0){const b=h.geometry;return w.assignLODInformation(a.url,b,u,e,void 0,M.density),d(b)}else{const b=new Array;for(let C=0;C<h.children.length;C++){const z=h.children[C];if(z.isMesh===!0){const X=z.geometry;w.assignLODInformation(a.url,X,u,e,C,M.density),b.push(X)}}return d(b)}}else v&&console.warn("Could not find mesh with guid",D.guid,T.parser.json)}return d(null)});return this.previouslyLoaded.set(p,L),await L}else if(t instanceof Z){i&&console.log("Load texture from uri: "+g);const p=await new Ne().loadAsync(g);return p?(p.guid=l.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=t.colorSpace,i&&console.log(l,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 tt(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=e.clone(),v&&console.warn(`Copying texture settings
|
|
4
4
|
`,t.uuid,`
|
|
5
|
-
`,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let S=w;c(S,"registerTexture",(t,e,r,n,s)=>{if(y&&console.log("> Progressive: register texture",n,e.name,e.uuid,e,s),!e){y&&console.error("gltf-progressive: Register texture without texture");return}e.source&&(e.source[ye]=s);const o=s.guid;w.assignLODInformation(t,e,o,r,n,void 0),w.lodInfos.set(o,s),w.lowresCache.set(o,e)}),c(S,"registerMesh",(t,e,r,n,s,o)=>{var i;y&&console.log("> Progressive: register mesh",s,r.name,o,r.uuid,r);const a=r.geometry;if(!a){y&&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&&!re(r)&&Te(r,a);for(const l of F)(i=l.onRegisteredNewMesh)==null||i.call(l,r,o)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class tt{constructor(e,r,n,s,o){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,s!=null&&(this.index=s),o!=null&&(this.density=o)}}const P=te("debugprogressive"),rt=te("noprogressive"),Me=Symbol("Needle:LODSManager"),De=Symbol("Needle:LODState"),J=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var E,$,we,Q,ne,de,U;const B=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new be),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval","auto"),V(this,E,1),c(this,"pause",!1),c(this,"manual",!1),c(this,"_lodchangedlisteners",[]),V(this,$,void 0),V(this,we,new We),V(this,Q,0),V(this,ne,0),V(this,de,0),V(this,U,0),c(this,"_fpsBuffer",[60,60,60,60,60]),c(this,"_sphere",new $e),c(this,"_tempBox",new Se),c(this,"_tempBox2",new Se),c(this,"tempMatrix",new be),c(this,"_tempWorldPosition",new N),c(this,"_tempBoxSize",new N),c(this,"_tempBox2Size",new N),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[De]}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[Me])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[Me];const r=new B(t,{engine:"unknown",...e});return t[Me]=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,$))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,$,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,G(e,Q,x(e,Q)+1),G(e,ne,x(e,we).getDelta()),G(e,de,x(e,de)+x(e,ne)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,ne)),G(e,U,e._fpsBuffer.reduce((i,a)=>i+a)/e._fpsBuffer.length),P&&x(e,Q)%200===0&&console.log("FPS",Math.round(x(e,U)),"Interval:",x(e,E)));const o=t++;x(e,$).call(this,r,n),e.onAfterRender(r,n,o)}}disable(){x(this,$)&&(this.renderer.render=x(this,$),G(this,$,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(rt||(this.updateInterval==="auto"?x(this,U)<40&&x(this,E)<10?(G(this,E,x(this,E)+1),P&&console.warn("\u2193 Reducing LOD updates",x(this,E),x(this,U).toFixed(0))):x(this,U)>=60&&x(this,E)>1&&(G(this,E,x(this,E)-1),P&&console.warn("\u2191 Increasing LOD updates",x(this,E),x(this,U).toFixed(0))):G(this,E,this.updateInterval),x(this,E)>0&&x(this,Q)%x(this,E)!=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")){P&&(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(P==="color"&&l.material&&!l.object.progressive_debug_color){l.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new Fe({color:g});l.object.material=p}const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const a=s.transparent;for(const l of a){const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const u=s.transmissive;for(const l of u){const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}}updateLODs(t,e,r,n){var s,o;r.userData||(r.userData={});let i=r[De];if(i||(i=new st,r[De]=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,k),k.mesh_lod=Math.round(k.mesh_lod),k.texture_lod=Math.round(k.texture_lod),k.mesh_lod>=0&&this.loadProgressiveMeshes(r,k.mesh_lod);let a=k.texture_lod;if(r.material&&a>=0){const u=r["DEBUG:LOD"];u!=null&&(a=u),this.loadProgressiveTextures(r.material,a)}for(const u of F)(o=u.onAfterUpdatedLOD)==null||o.call(u,this.renderer,t,e,r,k);i.lastLodLevel_Mesh=k.mesh_lod,i.lastLodLevel_Texture=k.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const n of t)this.loadProgressiveTextures(n,e);return}let r=!1;(t[J]===void 0||e<t[J])&&(r=!0),r&&(t[J]=e,S.assignTextureLOD(t,e).then(n=>{this._lodchangedlisteners.forEach(s=>s({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[J]!==e){t[J]=e;const r=t.geometry;return S.assignMeshLOD(t,e).then(n=>(n&&t[J]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),n))}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(P&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),l=u?.lods,f=l&&l.length>0,g=S.getMaterialMinMaxLODsCount(e.material),p=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!f&&!p){s.mesh_lod=0,s.texture_lod=0;return}f||(a=!0,i=0);const A=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const L=e;if(!L.boundingBox)L.computeBoundingBox();else if(r.frames%30===0){const d=re(L),_=L.geometry;d&&(L.geometry=d),L.computeBoundingBox(),L.geometry=_}D=L.boundingBox}if(D&&t.isPerspectiveCamera){const L=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 v=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(v)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),B.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&L.fov>70){const v=this._tempBox.min,m=this._tempBox.max;let h=v.x,M=v.y,b=m.x,C=m.y;const z=2,X=1.5,ie=(v.x+m.x)*.5,le=(v.y+m.y)*.5;h=(h-ie)*z+ie,M=(M-le)*z+le,b=(b-ie)*z+ie,C=(C-le)*z+le;const ke=h<0&&b>0?0:Math.min(Math.abs(v.x),Math.abs(m.x)),Ce=M<0&&C>0?0:Math.min(Math.abs(v.y),Math.abs(m.y)),ge=Math.max(ke,Ce);r.lastCentrality=(X-ge)*(X-ge)*(X-ge)}else r.lastCentrality=1;const d=this._tempBox.getSize(this._tempBoxSize);d.multiplyScalar(.5),screen.availHeight>0&&A>0&&d.multiplyScalar(A/screen.availHeight),d.x*=L.aspect;const _=t.matrixWorldInverse,O=this._tempBox2;O.copy(D),O.applyMatrix4(e.matrixWorld),O.applyMatrix4(_);const I=O.getSize(this._tempBox2Size),T=Math.max(I.x,I.y);if(Math.max(d.x,d.y)!=0&&T!=0&&(d.z=I.z/Math.max(I.x,I.y)*Math.max(d.x,d.y)),r.lastScreenCoverage=Math.max(d.x,d.y,d.z),r.lastScreenspaceVolume.copy(d),r.lastScreenCoverage*=r.lastCentrality,P&&B.debugDrawLine){const v=this.tempMatrix.copy(this.projectionScreenMatrix);v.invert();const m=B.corner0,h=B.corner1,M=B.corner2,b=B.corner3;m.copy(this._tempBox.min),h.copy(this._tempBox.max),h.x=m.x,M.copy(this._tempBox.max),M.y=m.y,b.copy(this._tempBox.max);const C=(m.z+b.z)*.5;m.z=h.z=M.z=b.z=C,m.applyMatrix4(v),h.applyMatrix4(v),M.applyMatrix4(v),b.applyMatrix4(v),B.debugDrawLine(m,h,255),B.debugDrawLine(m,M,255),B.debugDrawLine(h,b,255),B.debugDrawLine(M,b,255)}let W=999;if(l&&r.lastScreenCoverage>0){for(let v=0;v<l.length;v++)if(l[v].density/r.lastScreenCoverage<n){W=v;break}}W<i&&(i=W,a=!0)}if(a?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,P&&s.mesh_lod!=r.lastLodLevel_Mesh){const L=l?.[s.mesh_lod];L&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${L.density.toFixed(0)}) - ${e.name}`)}if(p){const L="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,P){const d=g.lods[g.max_count-1];P&&console.log(`First Texture LOD ${s.texture_lod} (${d.max_height}px) - ${e.name}`)}}else{const d=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let _=r.lastScreenCoverage*2;((o=this.context)==null?void 0:o.engine)==="model-viewer"&&(_*=2);const O=A/window.devicePixelRatio*_;for(let I=g.lods.length-1;I>=0;I--){let T=g.lods[I];if(!(L&&T.max_height>=2048)&&!(Qe()&&T.max_height>4096)&&T.max_height>O){if(s.texture_lod=I,s.texture_lod<r.lastLodLevel_Texture){const W=T.max_height;P&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${W}px
|
|
5
|
+
`,e.uuid),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e}};let S=w;c(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[ve]=s);const o=s.guid;w.assignLODInformation(t,e,o,r,n,void 0),w.lodInfos.set(o,s),w.lowresCache.set(o,e)}),c(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&&!re(r)&&Te(r,a);for(const l of F)(i=l.onRegisteredNewMesh)==null||i.call(l,r,o)}),c(S,"lodInfos",new Map),c(S,"previouslyLoaded",new Map),c(S,"lowresCache",new Map);class tt{constructor(e,r,n,s,o){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,s!=null&&(this.index=s),o!=null&&(this.density=o)}}const P=te("debugprogressive"),rt=te("noprogressive"),Me=Symbol("Needle:LODSManager"),De=Symbol("Needle:LODState"),J=Symbol("Needle:CurrentLOD"),k={mesh_lod:-1,texture_lod:-1};var E,$,we,Q,ne,de,U;const B=class{constructor(t,e){c(this,"context"),c(this,"renderer"),c(this,"projectionScreenMatrix",new be),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval","auto"),V(this,E,1),c(this,"pause",!1),c(this,"manual",!1),c(this,"_lodchangedlisteners",[]),V(this,$,void 0),V(this,we,new We),V(this,Q,0),V(this,ne,0),V(this,de,0),V(this,U,0),c(this,"_fpsBuffer",[60,60,60,60,60]),c(this,"_sphere",new $e),c(this,"_tempBox",new Se),c(this,"_tempBox2",new Se),c(this,"tempMatrix",new be),c(this,"_tempWorldPosition",new N),c(this,"_tempBoxSize",new N),c(this,"_tempBox2Size",new N),this.renderer=t,this.context={...e}}static getObjectLODState(t){return t[De]}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[Me])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[Me];const r=new B(t,{engine:"unknown",...e});return t[Me]=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,$))return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;G(this,$,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,G(e,Q,x(e,Q)+1),G(e,ne,x(e,we).getDelta()),G(e,de,x(e,de)+x(e,ne)),e._fpsBuffer.shift(),e._fpsBuffer.push(1/x(e,ne)),G(e,U,e._fpsBuffer.reduce((i,a)=>i+a)/e._fpsBuffer.length),P&&x(e,Q)%200===0&&console.log("FPS",Math.round(x(e,U)),"Interval:",x(e,E)));const o=t++;x(e,$).call(this,r,n),e.onAfterRender(r,n,o)}}disable(){x(this,$)&&(this.renderer.render=x(this,$),G(this,$,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(rt||(this.updateInterval==="auto"?x(this,U)<40&&x(this,E)<10?(G(this,E,x(this,E)+1),P&&console.warn("\u2193 Reducing LOD updates",x(this,E),x(this,U).toFixed(0))):x(this,U)>=60&&x(this,E)>1&&(G(this,E,x(this,E)-1),P&&console.warn("\u2191 Increasing LOD updates",x(this,E),x(this,U).toFixed(0))):G(this,E,this.updateInterval),x(this,E)>0&&x(this,Q)%x(this,E)!=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")){P&&(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(P==="color"&&l.material&&!l.object.progressive_debug_color){l.object.progressive_debug_color=!0;const g=Math.random()*16777215,p=new Fe({color:g});l.object.material=p}const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const a=s.transparent;for(const l of a){const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}const u=s.transmissive;for(const l of u){const f=l.object;(f instanceof q||f.isMesh)&&this.updateLODs(t,e,f,i)}}updateLODs(t,e,r,n){var s,o;r.userData||(r.userData={});let i=r[De];if(i||(i=new st,r[De]=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,k),k.mesh_lod=Math.round(k.mesh_lod),k.texture_lod=Math.round(k.texture_lod),k.mesh_lod>=0&&this.loadProgressiveMeshes(r,k.mesh_lod);let a=k.texture_lod;if(r.material&&a>=0){const u=r["DEBUG:LOD"];u!=null&&(a=u),this.loadProgressiveTextures(r.material,a)}for(const u of F)(o=u.onAfterUpdatedLOD)==null||o.call(u,this.renderer,t,e,r,k);i.lastLodLevel_Mesh=k.mesh_lod,i.lastLodLevel_Texture=k.texture_lod}loadProgressiveTextures(t,e){if(!t)return;if(Array.isArray(t)){for(const n of t)this.loadProgressiveTextures(n,e);return}let r=!1;(t[J]===void 0||e<t[J])&&(r=!0),r&&(t[J]=e,S.assignTextureLOD(t,e).then(n=>{this._lodchangedlisteners.forEach(s=>s({type:"texture",level:e,object:t}))}))}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t[J]!==e){t[J]=e;const r=t.geometry;return S.assignMeshLOD(t,e).then(n=>(n&&t[J]==e&&r!=t.geometry&&this._lodchangedlisteners.forEach(s=>s({type:"mesh",level:e,object:t})),n))}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(P&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=S.getMeshLODInformation(e.geometry),l=u?.lods,f=l&&l.length>0,g=S.getMaterialMinMaxLODsCount(e.material),p=g?.min_count!=1/0&&g.min_count>0&&g.max_count>0;if(!f&&!p){s.mesh_lod=0,s.texture_lod=0;return}f||(a=!0,i=0);const A=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let D=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const L=e;if(!L.boundingBox)L.computeBoundingBox();else if(r.frames%30===0){const d=re(L),_=L.geometry;d&&(L.geometry=d),L.computeBoundingBox(),L.geometry=_}D=L.boundingBox}if(D&&t.isPerspectiveCamera){const L=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 y=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(y)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(D),this._tempBox.applyMatrix4(e.matrixWorld),B.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&L.fov>70){const y=this._tempBox.min,m=this._tempBox.max;let h=y.x,M=y.y,b=m.x,C=m.y;const z=2,X=1.5,ie=(y.x+m.x)*.5,le=(y.y+m.y)*.5;h=(h-ie)*z+ie,M=(M-le)*z+le,b=(b-ie)*z+ie,C=(C-le)*z+le;const ke=h<0&&b>0?0:Math.min(Math.abs(y.x),Math.abs(m.x)),Ce=M<0&&C>0?0:Math.min(Math.abs(y.y),Math.abs(m.y)),ge=Math.max(ke,Ce);r.lastCentrality=(X-ge)*(X-ge)*(X-ge)}else r.lastCentrality=1;const d=this._tempBox.getSize(this._tempBoxSize);d.multiplyScalar(.5),screen.availHeight>0&&A>0&&d.multiplyScalar(A/screen.availHeight),d.x*=L.aspect;const _=t.matrixWorldInverse,O=this._tempBox2;O.copy(D),O.applyMatrix4(e.matrixWorld),O.applyMatrix4(_);const I=O.getSize(this._tempBox2Size),T=Math.max(I.x,I.y);if(Math.max(d.x,d.y)!=0&&T!=0&&(d.z=I.z/Math.max(I.x,I.y)*Math.max(d.x,d.y)),r.lastScreenCoverage=Math.max(d.x,d.y,d.z),r.lastScreenspaceVolume.copy(d),r.lastScreenCoverage*=r.lastCentrality,P&&B.debugDrawLine){const y=this.tempMatrix.copy(this.projectionScreenMatrix);y.invert();const m=B.corner0,h=B.corner1,M=B.corner2,b=B.corner3;m.copy(this._tempBox.min),h.copy(this._tempBox.max),h.x=m.x,M.copy(this._tempBox.max),M.y=m.y,b.copy(this._tempBox.max);const C=(m.z+b.z)*.5;m.z=h.z=M.z=b.z=C,m.applyMatrix4(y),h.applyMatrix4(y),M.applyMatrix4(y),b.applyMatrix4(y),B.debugDrawLine(m,h,255),B.debugDrawLine(m,M,255),B.debugDrawLine(h,b,255),B.debugDrawLine(M,b,255)}let W=999;if(l&&r.lastScreenCoverage>0){for(let y=0;y<l.length;y++)if(l[y].density/r.lastScreenCoverage<n){W=y;break}}W<i&&(i=W,a=!0)}if(a?s.mesh_lod=i:s.mesh_lod=r.lastLodLevel_Mesh,P&&s.mesh_lod!=r.lastLodLevel_Mesh){const L=l?.[s.mesh_lod];L&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (${L.density.toFixed(0)}) - ${e.name}`)}if(p){const L="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=g.max_count-1,P){const d=g.lods[g.max_count-1];P&&console.log(`First Texture LOD ${s.texture_lod} (${d.max_height}px) - ${e.name}`)}}else{const d=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let _=r.lastScreenCoverage*2;((o=this.context)==null?void 0:o.engine)==="model-viewer"&&(_*=2);const O=A/window.devicePixelRatio*_;for(let I=g.lods.length-1;I>=0;I--){let T=g.lods[I];if(!(L&&T.max_height>=2048)&&!(Qe()&&T.max_height>4096)&&T.max_height>O){if(s.texture_lod=I,s.texture_lod<r.lastLodLevel_Texture){const W=T.max_height;P&&console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${W}px
|
|
6
6
|
Screensize: ${O.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${d.toFixed(1)}
|
|
7
7
|
${e.name}`)}break}}}}else s.texture_lod=0}};let j=B;E=new WeakMap,$=new WeakMap,we=new WeakMap,Q=new WeakMap,ne=new WeakMap,de=new WeakMap,U=new WeakMap,c(j,"debugDrawLine"),c(j,"corner0",new N),c(j,"corner1",new N),c(j,"corner2",new N),c(j,"corner3",new N),c(j,"_tempPtInside",new N);class st{constructor(){c(this,"frames",0),c(this,"lastLodLevel_Mesh",-1),c(this,"lastLodLevel_Texture",-1),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new N),c(this,"lastCentrality",0)}}const Ae=Symbol("NEEDLE_mesh_lod"),he=Symbol("NEEDLE_texture_lod");let fe=null;function _e(){const t=ot();t&&(t.mapURLs(function(e){return Ie(),e}),Ie(),fe?.disconnect(),fe=new MutationObserver(e=>{e.forEach(r=>{r.addedNodes.forEach(n=>{n instanceof HTMLElement&&n.tagName.toLowerCase()==="model-viewer"&&Pe(n)})})}),fe.observe(document,{childList:!0,subtree:!0}))}function ot(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),_e()}),null)}function Ie(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(t=>{Pe(t)})}const Be=new WeakSet;let nt=0;function Pe(t){if(!t||Be.has(t))return null;Be.add(t),console.debug("[gltf-progressive] found new model-viewer..."+ ++nt+`
|
|
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(l=>l.toString()=="Symbol(renderer)"),a=o.find(l=>l.toString()=="Symbol(scene)"),u=o.find(l=>l.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&a!=null&&(r=t[a]),!n&&u!=null&&(n=t[u])}if(e&&r){let s=function(){if(n){let i=0,a=setInterval(()=>{if(i++>5){clearInterval(a);return}n?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=j.get(e,{engine:"model-viewer"});return j.addPlugin(new it),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 it{constructor(){c(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[he]==!0)return;r[he]=!0;const n=this.tryGetCurrentGLTF(e),s=this.tryGetCurrentModelViewer(e),o=this.getUrl(s);if(o&&n&&r.material){let i=function(u){var l,f,g;if(u[he]==!0)return;u[he]=!0,u.userData&&(u.userData.LOD=-1);const p=Object.keys(u);for(let A=0;A<p.length;A++){const D=p[A],L=u[D];if(L?.isTexture===!0){const d=(f=(l=L.userData)==null?void 0:l.associations)==null?void 0:f.textures;if(d==null)continue;const _=n.parser.json.textures[d];if(!_){console.warn("Texture data not found for texture index "+d);continue}if((g=_?.extensions)!=null&&g[R]){const O=_.extensions[R];O&&o&&S.registerTexture(o,L,O.lods.length,d,O)}}}};const a=r.material;if(Array.isArray(a))for(const u of a)i(u);else i(a)}}tryParseMeshLOD(e,r){var n,s;if(r[Ae]==!0)return;r[Ae]=!0;const o=this.tryGetCurrentModelViewer(e),i=this.getUrl(o);if(!i)return;const a=(s=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[R];if(a&&i){const u=r.uuid;S.registerMesh(i,u,r,0,a.lods.length,a)}}}function lt(t,e,r,n){pe(e),
|
|
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(l=>l.toString()=="Symbol(renderer)"),a=o.find(l=>l.toString()=="Symbol(scene)"),u=o.find(l=>l.toString()=="Symbol(needsRender)");!e&&i!=null&&(e=t[i].threeRenderer),!r&&a!=null&&(r=t[a]),!n&&u!=null&&(n=t[u])}if(e&&r){let s=function(){if(n){let i=0,a=setInterval(()=>{if(i++>5){clearInterval(a);return}n?.call(t)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=j.get(e,{engine:"model-viewer"});return j.addPlugin(new it),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 it{constructor(){c(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[he]==!0)return;r[he]=!0;const n=this.tryGetCurrentGLTF(e),s=this.tryGetCurrentModelViewer(e),o=this.getUrl(s);if(o&&n&&r.material){let i=function(u){var l,f,g;if(u[he]==!0)return;u[he]=!0,u.userData&&(u.userData.LOD=-1);const p=Object.keys(u);for(let A=0;A<p.length;A++){const D=p[A],L=u[D];if(L?.isTexture===!0){const d=(f=(l=L.userData)==null?void 0:l.associations)==null?void 0:f.textures;if(d==null)continue;const _=n.parser.json.textures[d];if(!_){console.warn("Texture data not found for texture index "+d);continue}if((g=_?.extensions)!=null&&g[R]){const O=_.extensions[R];O&&o&&S.registerTexture(o,L,O.lods.length,d,O)}}}};const a=r.material;if(Array.isArray(a))for(const u of a)i(u);else i(a)}}tryParseMeshLOD(e,r){var n,s;if(r[Ae]==!0)return;r[Ae]=!0;const o=this.tryGetCurrentModelViewer(e),i=this.getUrl(o);if(!i)return;const a=(s=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[R];if(a&&i){const u=r.uuid;S.registerMesh(i,u,r,0,a.lods.length,a)}}}function lt(t,e,r,n){pe(e),ye(r),r.register(o=>new S(o,t));const s=j.get(e);return n?.enableLODsManager!==!1&&s.enable(),s}_e();export{R as EXTENSION_NAME,j as LODsManager,S as NEEDLE_progressive,me as VERSION,ye as addDracoAndKTX2Loaders,pe as createLoaders,re as getRaycastMesh,_e as patchModelViewer,Te as registerRaycastMesh,He as setDracoDecoderLocation,Ye as setKTX2TranscoderLocation,lt as useNeedleProgressive,Ze as useRaycastMeshes};
|
package/gltf-progressive.umd.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var Re=Object.defineProperty;var ke=(a,t,e)=>t in a?Re(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var d=(a,t,e)=>(ke(a,typeof t!="symbol"?t+"":t,e),e),Se=(a,t,e)=>{if(!t.has(a))throw TypeError("Cannot "+e)};var L=(a,t,e)=>(Se(a,t,"read from private field"),e?e.call(a):t.get(a)),K=(a,t,e)=>{if(t.has(a))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(a):t.set(a,e)},N=(a,t,e,r)=>(Se(a,t,"write to private field"),r?r.call(a,e):t.set(a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),Ge=require("three/examples/jsm/loaders/GLTFLoader.js"),Ve=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Fe=require("three/examples/jsm/loaders/DRACOLoader.js"),$e=require("three/examples/jsm/loaders/KTX2Loader.js"),we="";globalThis.GLTF_PROGRESSIVE_VERSION=we;console.debug(`[gltf-progressive] version ${we}`);let Z="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",oe="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ne=Z,Ue=oe;fetch(Z+"draco_decoder.js",{method:"head"}).catch(a=>{Z===Ne&&(Z="./include/draco/"),oe===Ue&&(oe="./include/ktx2/")});function ze(a){Z=a}function We(a){oe=a}let J,de,Q;function ve(a){return J||(J=new Fe.DRACOLoader,J.setDecoderPath(Z),J.setDecoderConfig({type:"js"})),Q||(Q=new $e.KTX2Loader,Q.setTranscoderPath(oe)),de||(de=Ve.MeshoptDecoder),a?Q.detectSupport(a):a!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:J,ktx2Loader:Q,meshoptDecoder:de}}function _e(a){a.dracoLoader||a.setDRACOLoader(J),a.ktx2Loader||a.setKTX2Loader(Q),a.meshoptDecoder||a.setMeshoptDecoder(de)}ne("debugprogressive");function ne(a){const e=new URL(window.location.href).searchParams.get(a);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function qe(a,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||a===void 0)return t;const e=a.lastIndexOf("/");if(e>=0){const r=a.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let te;function Xe(){return te!==void 0||(te=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ne("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",te)),te}const Me=Symbol("needle:raycast-mesh");function ae(a){return(a==null?void 0:a[Me])instanceof p.BufferGeometry?a[Me]:null}function Pe(a,t){if((a.type==="Mesh"||a.type==="SkinnedMesh")&&!ae(a)){const r=Ye(t);r.userData={isRaycastMesh:!0},a[Me]=r}}function Ke(a=!0){if(a){if(re)return;const t=re=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,r){const o=this,s=ae(o);let i;s&&o.isMesh&&(i=o.geometry,o.geometry=s),t.call(this,e,r),i&&(o.geometry=i)}}else{if(!re)return;p.Mesh.prototype.raycast=re,re=null}}let re=null;function Ye(a){const t=new p.BufferGeometry;for(const e in a.attributes)t.setAttribute(e,a.getAttribute(e));return t.setIndex(a.getIndex()),t}const Y=new Array,U="NEEDLE_progressive",x=ne("debugprogressive"),me=Symbol("needle-progressive-texture"),ie=new Map,De=new Set;if(x){let a=function(){t+=1,console.log("Toggle LOD level",t,ie),ie.forEach((o,s)=>{for(const i of o.keys){const n=s[i];if(n!=null){if(n.isBufferGeometry===!0){const l=O.getMeshLODInformation(n),u=l?Math.min(t,l.lods.length):0;s["DEBUG:LOD"]=t,O.assignMeshLOD(s,u),l&&(e=Math.max(e,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=t,O.assignTextureLOD(s,t);break}}}}),t>=e&&(t=-1)},t=-1,e=2,r=!1;window.addEventListener("keyup",o=>{o.key==="p"&&a(),o.key==="w"&&(r=!r,De&&De.forEach(s=>{s.name!="BackgroundCubeMaterial"&&s.glyphMap==null&&"wireframe"in s&&(s.wireframe=r)}))})}function be(a,t,e){var o;if(!x)return;ie.has(a)||ie.set(a,{keys:[],sourceId:e});const r=ie.get(a);((o=r==null?void 0:r.keys)==null?void 0:o.includes(t))==!1&&r.keys.push(t)}const _=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var r,o;if(this._isLoadingMesh)return null;const e=(o=(r=this.parser.json.meshes[t])==null?void 0:r.extensions)==null?void 0:o[U];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(s=>{var i;return this._isLoadingMesh=!1,s&&_.registerMesh(this.url,e.guid,s,(i=e.lods)==null?void 0:i.length,void 0,e),s})):null});x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return U}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,o="LODS:minmax",s=t[o];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const n of t)this.getMaterialMinMaxLODsCount(n,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const n=t;for(const l of Object.keys(n.uniforms)){const u=n.uniforms[l].value;(u==null?void 0:u.isTexture)===!0&&i(u,e)}}else if(t.isMaterial)for(const n of Object.keys(t)){const l=t[n];(l==null?void 0:l.isTexture)===!0&&i(l,e)}return t[o]=e,e;function i(n,l){const u=r.getAssignedLODInformation(n);if(u){const c=r.lodInfos.get(u.key);if(c&&c.lods){l.min_count=Math.min(l.min_count,c.lods.length),l.max_count=Math.max(l.max_count,c.lods.length);for(let g=0;g<c.lods.length;g++){const y=c.lods[g];y.width&&(l.lods[g]=l.lods[g]||{min_height:1/0,max_height:0},l.lods[g].min_height=Math.min(l.lods[g].min_height,y.height),l.lods[g].max_height=Math.max(l.lods[g].max_height,y.height))}}}}}static hasLODLevelAvailable(t,e){var s;if(Array.isArray(t)){for(const i of t)if(this.hasLODLevelAvailable(i,e))return!0;return!1}if(t.isMaterial===!0){for(const i of Object.keys(t)){const n=t[i];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,e))return!0}return!1}else if(t.isGroup===!0){for(const i of t.children)if(i.isMesh===!0&&this.hasLODLevelAvailable(i,e))return!0}let r,o;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&(s=r==null?void 0:r.userData)!=null&&s.LODS){const i=r.userData.LODS;if(o=this.lodInfos.get(i.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const o=t.geometry,s=this.getAssignedLODInformation(o);if(!s)return Promise.resolve(null);for(const i of Y)(r=i.onBeforeGetLODMesh)==null||r.call(i,t,e);return t["LOD:requested level"]=e,_.getOrLoadLOD(o,e).then(i=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(i)){const n=s.index||0;i=i[n]}i&&o!=i&&((i==null?void 0:i.isBufferGeometry)?(t.geometry=i,x&&be(t,"geometry",s.url)):x&&console.error("Invalid LOD geometry",i))}return i}).catch(i=>(console.error("Error loading mesh LOD",t,i),null))}else x&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t instanceof p.Material||t.isMaterial===!0){const r=t,o=[],s=new Array;if(x&&De.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const i=r;for(const n of Object.keys(i.uniforms)){const l=i.uniforms[n].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,r,n).then(c=>(c&&i.uniforms[n].value!=c&&(i.uniforms[n].value=c,i.uniformsNeedUpdate=!0),c));o.push(u),s.push(n)}}}else for(const i of Object.keys(r)){const n=r[i];if((n==null?void 0:n.isTexture)===!0){const l=this.assignTextureLODForSlot(n,e,r,i);o.push(l),s.push(i)}}return Promise.all(o).then(i=>{const n=new Array;for(let l=0;l<i.length;l++){const u=i[l],c=s[l];u&&u.isTexture===!0?n.push({material:r,slot:c,texture:u,level:e}):n.push({material:r,slot:c,texture:null,level:e})}return n})}if(t instanceof p.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,o){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):_.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if((s==null?void 0:s.isTexture)===!0){if(s!=t){if(r&&o){const i=r[o];if(i){const n=this.getAssignedLODInformation(i);if(n&&(n==null?void 0:n.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,e,r,i,s),null}r[o]=s}if(x&&o&&r){const i=this.getAssignedLODInformation(t);i&&be(r,o,i.url)}}return s}else x=="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 x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,s)=>{var i;if(o!=null&&o.extensions){const n=o==null?void 0:o.extensions[U];if(n){if(!n.lods){x&&console.warn("Texture has no LODs",n);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const c=this.parser.associations.get(u);(c==null?void 0:c.textures)===s&&(l=!0,_.registerTexture(this.url,u,(i=n.lods)==null?void 0:i.length,s,n))}l||this.parser.getDependency("texture",s).then(u=>{var c;u&&_.registerTexture(this.url,u,(c=n.lods)==null?void 0:c.length,s,n)})}}}),(r=this.parser.json.meshes)==null||r.forEach((o,s)=>{if(o!=null&&o.extensions){const i=o==null?void 0:o.extensions[U];if(i&&i.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const l=this.parser.associations.get(n);(l==null?void 0:l.meshes)===s&&_.registerMesh(this.url,i.guid,n,i.lods.length,l.primitives,i)}}}}),null}static async getOrLoadLOD(t,e){var n,l,u,c;const r=x=="verbose",o=t.userData.LODS;if(!o)return null;const s=o==null?void 0:o.key;let i;if(t.isTexture===!0){const g=t;g.source&&g.source[me]&&(i=g.source[me])}if(i||(i=_.lodInfos.get(s)),i){if(e>0){let D=!1;const v=Array.isArray(i.lods);if(v&&e>=i.lods.length?D=!0:v||(D=!0),D)return this.lowresCache.get(s)}const g=Array.isArray(i.lods)?(n=i.lods[e])==null?void 0:n.path:i.lods;if(!g)return x&&!i["missing:uri"]&&(i["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,i)),null;const y=qe(o.url,g);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!i.guid)return console.warn("missing pointer for glb/gltf texture",i),null;const D=y+"_"+i.guid,v=this.previouslyLoaded.get(D);if(v!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${D}`);let h=await v.catch($=>(console.error(`Error loading LOD ${e} from ${y}
|
|
1
|
+
"use strict";var Re=Object.defineProperty;var ke=(a,t,e)=>t in a?Re(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var d=(a,t,e)=>(ke(a,typeof t!="symbol"?t+"":t,e),e),Se=(a,t,e)=>{if(!t.has(a))throw TypeError("Cannot "+e)};var L=(a,t,e)=>(Se(a,t,"read from private field"),e?e.call(a):t.get(a)),K=(a,t,e)=>{if(t.has(a))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(a):t.set(a,e)},N=(a,t,e,r)=>(Se(a,t,"write to private field"),r?r.call(a,e):t.set(a,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("three"),Ge=require("three/examples/jsm/loaders/GLTFLoader.js"),Ve=require("three/examples/jsm/libs/meshopt_decoder.module.js"),Fe=require("three/examples/jsm/loaders/DRACOLoader.js"),$e=require("three/examples/jsm/loaders/KTX2Loader.js"),we="";globalThis.GLTF_PROGRESSIVE_VERSION=we;console.debug(`[gltf-progressive] version ${we}`);let Z="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",oe="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";const Ne=Z,Ue=oe;fetch(Z+"draco_decoder.js",{method:"head"}).catch(a=>{Z===Ne&&(Z="./include/draco/"),oe===Ue&&(oe="./include/ktx2/")});function ze(a){Z=a}function We(a){oe=a}let J,de,Q;function ve(a){return J||(J=new Fe.DRACOLoader,J.setDecoderPath(Z),J.setDecoderConfig({type:"js"})),Q||(Q=new $e.KTX2Loader,Q.setTranscoderPath(oe)),de||(de=Ve.MeshoptDecoder),a?Q.detectSupport(a):a!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:J,ktx2Loader:Q,meshoptDecoder:de}}function _e(a){a.dracoLoader||a.setDRACOLoader(J),a.ktx2Loader||a.setKTX2Loader(Q),a.meshoptDecoder||a.setMeshoptDecoder(de)}ne("debugprogressive");function ne(a){const e=new URL(window.location.href).searchParams.get(a);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function qe(a,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||a===void 0)return t;const e=a.lastIndexOf("/");if(e>=0){const r=a.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let te;function Xe(){return te!==void 0||(te=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),ne("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",te)),te}const Me=Symbol("needle:raycast-mesh");function ae(a){return(a==null?void 0:a[Me])instanceof p.BufferGeometry?a[Me]:null}function Pe(a,t){if((a.type==="Mesh"||a.type==="SkinnedMesh")&&!ae(a)){const r=Ye(t);r.userData={isRaycastMesh:!0},a[Me]=r}}function Ke(a=!0){if(a){if(re)return;const t=re=p.Mesh.prototype.raycast;p.Mesh.prototype.raycast=function(e,r){const o=this,s=ae(o);let i;s&&o.isMesh&&(i=o.geometry,o.geometry=s),t.call(this,e,r),i&&(o.geometry=i)}}else{if(!re)return;p.Mesh.prototype.raycast=re,re=null}}let re=null;function Ye(a){const t=new p.BufferGeometry;for(const e in a.attributes)t.setAttribute(e,a.getAttribute(e));return t.setIndex(a.getIndex()),t}const Y=new Array,U="NEEDLE_progressive",x=ne("debugprogressive"),me=Symbol("needle-progressive-texture"),ie=new Map,De=new Set;if(x){let a=function(){t+=1,console.log("Toggle LOD level",t,ie),ie.forEach((o,s)=>{for(const i of o.keys){const n=s[i];if(n!=null){if(n.isBufferGeometry===!0){const l=O.getMeshLODInformation(n),u=l?Math.min(t,l.lods.length):0;s["DEBUG:LOD"]=t,O.assignMeshLOD(s,u),l&&(e=Math.max(e,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=t,O.assignTextureLOD(s,t);break}}}}),t>=e&&(t=-1)},t=-1,e=2,r=!1;window.addEventListener("keyup",o=>{o.key==="p"&&a(),o.key==="w"&&(r=!r,De&&De.forEach(s=>{s.name!="BackgroundCubeMaterial"&&s.glyphMap==null&&"wireframe"in s&&(s.wireframe=r)}))})}function be(a,t,e){var o;if(!x)return;ie.has(a)||ie.set(a,{keys:[],sourceId:e});const r=ie.get(a);((o=r==null?void 0:r.keys)==null?void 0:o.includes(t))==!1&&r.keys.push(t)}const _=class{constructor(t,e){d(this,"parser");d(this,"url");d(this,"_isLoadingMesh");d(this,"loadMesh",t=>{var r,o;if(this._isLoadingMesh)return null;const e=(o=(r=this.parser.json.meshes[t])==null?void 0:r.extensions)==null?void 0:o[U];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(s=>{var i;return this._isLoadingMesh=!1,s&&_.registerMesh(this.url,e.guid,s,(i=e.lods)==null?void 0:i.length,void 0,e),s})):null});x&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return U}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static getMaterialMinMaxLODsCount(t,e){const r=this,o="LODS:minmax",s=t[o];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const n of t)this.getMaterialMinMaxLODsCount(n,e);return t[o]=e,e}if(x==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const n=t;for(const l of Object.keys(n.uniforms)){const u=n.uniforms[l].value;(u==null?void 0:u.isTexture)===!0&&i(u,e)}}else if(t.isMaterial)for(const n of Object.keys(t)){const l=t[n];(l==null?void 0:l.isTexture)===!0&&i(l,e)}return t[o]=e,e;function i(n,l){const u=r.getAssignedLODInformation(n);if(u){const c=r.lodInfos.get(u.key);if(c&&c.lods){l.min_count=Math.min(l.min_count,c.lods.length),l.max_count=Math.max(l.max_count,c.lods.length);for(let g=0;g<c.lods.length;g++){const y=c.lods[g];y.width&&(l.lods[g]=l.lods[g]||{min_height:1/0,max_height:0},l.lods[g].min_height=Math.min(l.lods[g].min_height,y.height),l.lods[g].max_height=Math.max(l.lods[g].max_height,y.height))}}}}}static hasLODLevelAvailable(t,e){var s;if(Array.isArray(t)){for(const i of t)if(this.hasLODLevelAvailable(i,e))return!0;return!1}if(t.isMaterial===!0){for(const i of Object.keys(t)){const n=t[i];if(n&&n.isTexture&&this.hasLODLevelAvailable(n,e))return!0}return!1}else if(t.isGroup===!0){for(const i of t.children)if(i.isMesh===!0&&this.hasLODLevelAvailable(i,e))return!0}let r,o;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&(s=r==null?void 0:r.userData)!=null&&s.LODS){const i=r.userData.LODS;if(o=this.lodInfos.get(i.key),e===void 0)return o!=null;if(o)return Array.isArray(o.lods)?e<o.lods.length:e===0}return!1}static assignMeshLOD(t,e){var r;if(!t)return Promise.resolve(null);if(t instanceof p.Mesh||t.isMesh===!0){const o=t.geometry,s=this.getAssignedLODInformation(o);if(!s)return Promise.resolve(null);for(const i of Y)(r=i.onBeforeGetLODMesh)==null||r.call(i,t,e);return t["LOD:requested level"]=e,_.getOrLoadLOD(o,e).then(i=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(i)){const n=s.index||0;i=i[n]}i&&o!=i&&((i==null?void 0:i.isBufferGeometry)?(t.geometry=i,x&&be(t,"geometry",s.url)):x&&console.error("Invalid LOD geometry",i))}return i}).catch(i=>(console.error("Error loading mesh LOD",t,i),null))}else x&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const o=new Array;for(const s of r.material){const i=this.assignTextureLOD(s,e);o.push(i)}return Promise.all(o).then(s=>{const i=new Array;for(const n of s)Array.isArray(n)&&i.push(...n);return i})}else return this.assignTextureLOD(r.material,e)}if(t instanceof p.Material||t.isMaterial===!0){const r=t,o=[],s=new Array;if(x&&De.add(r),r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const i=r;for(const n of Object.keys(i.uniforms)){const l=i.uniforms[n].value;if((l==null?void 0:l.isTexture)===!0){const u=this.assignTextureLODForSlot(l,e,r,n).then(c=>(c&&i.uniforms[n].value!=c&&(i.uniforms[n].value=c,i.uniformsNeedUpdate=!0),c));o.push(u),s.push(n)}}}else for(const i of Object.keys(r)){const n=r[i];if((n==null?void 0:n.isTexture)===!0){const l=this.assignTextureLODForSlot(n,e,r,i);o.push(l),s.push(i)}}return Promise.all(o).then(i=>{const n=new Array;for(let l=0;l<i.length;l++){const u=i[l],c=s[l];u&&u.isTexture===!0?n.push({material:r,slot:c,texture:u,level:e}):n.push({material:r,slot:c,texture:null,level:e})}return n})}if(t instanceof p.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,o){return(t==null?void 0:t.isTexture)!==!0?Promise.resolve(null):o==="glyphMap"?Promise.resolve(t):_.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return null;if((s==null?void 0:s.isTexture)===!0){if(s!=t){if(r&&o){const i=r[o];if(i){const n=this.getAssignedLODInformation(i);if(n&&(n==null?void 0:n.level)<e)return x==="verbose"&&console.warn("Assigned texture level is already higher: ",n.level,e,r,i,s),null}r[o]=s}if(x&&o&&r){const i=this.getAssignedLODInformation(t);i&&be(r,o,i.url)}}return s}else x=="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 x&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((o,s)=>{var i;if(o!=null&&o.extensions){const n=o==null?void 0:o.extensions[U];if(n){if(!n.lods){x&&console.warn("Texture has no LODs",n);return}let l=!1;for(const u of this.parser.associations.keys())if(u.isTexture===!0){const c=this.parser.associations.get(u);(c==null?void 0:c.textures)===s&&(l=!0,_.registerTexture(this.url,u,(i=n.lods)==null?void 0:i.length,s,n))}l||this.parser.getDependency("texture",s).then(u=>{var c;u&&_.registerTexture(this.url,u,(c=n.lods)==null?void 0:c.length,s,n)})}}}),(r=this.parser.json.meshes)==null||r.forEach((o,s)=>{if(o!=null&&o.extensions){const i=o==null?void 0:o.extensions[U];if(i&&i.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const l=this.parser.associations.get(n);(l==null?void 0:l.meshes)===s&&_.registerMesh(this.url,i.guid,n,i.lods.length,l.primitives,i)}}}}),null}static async getOrLoadLOD(t,e){var n,l,u,c;const r=x=="verbose",o=t.userData.LODS;if(!o)return null;const s=o==null?void 0:o.key;let i;if(t.isTexture===!0){const g=t;g.source&&g.source[me]&&(i=g.source[me])}if(i||(i=_.lodInfos.get(s)),i){if(e>0){let D=!1;const v=Array.isArray(i.lods);if(v&&e>=i.lods.length?D=!0:v||(D=!0),D)return this.lowresCache.get(s)}const g=Array.isArray(i.lods)?(n=i.lods[e])==null?void 0:n.path:i.lods;if(!g)return x&&!i["missing:uri"]&&(i["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,i)),null;const y=qe(o.url,g);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!i.guid)return console.warn("missing pointer for glb/gltf texture",i),null;const D=y+"_"+i.guid,v=this.previouslyLoaded.get(D);if(v!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${D}`);let h=await v.catch($=>(console.error(`Error loading LOD ${e} from ${y}
|
|
2
2
|
`,$),null)),R=!1;if(h==null||(h instanceof p.Texture&&t instanceof p.Texture?(l=h.image)!=null&&l.data||(u=h.source)!=null&&u.data?h=this.copySettings(t,h):(R=!0,this.previouslyLoaded.delete(D)):h instanceof p.BufferGeometry&&t instanceof p.BufferGeometry&&((c=h.attributes.position)!=null&&c.array||(R=!0,this.previouslyLoaded.delete(D)))),!R)return h}const M=i,F=new Promise(async(h,R)=>{const $=new Ge.GLTFLoader;_e($),x&&(await new Promise(E=>setTimeout(E,1e3)),r&&console.warn("Start loading (delayed) "+y,M.guid));let k=y;if(M&&Array.isArray(M.lods)){const E=M.lods[e];E.hash&&(k+="?v="+E.hash)}const b=await $.loadAsync(k).catch(E=>(console.error(`Error loading LOD ${e} from ${y}
|
|
3
3
|
`,E),null));if(!b)return null;const q=b.parser;r&&console.log("Loading finished "+y,M.guid);let A=0;if(b.parser.json.textures){let E=!1;for(const f of b.parser.json.textures){if(f!=null&&f.extensions){const m=f==null?void 0:f.extensions[U];if(m!=null&&m.guid&&m.guid===M.guid){E=!0;break}}A++}if(E){let f=await q.getDependency("texture",A);return f&&_.assignLODInformation(o.url,f,s,e,void 0,void 0),r&&console.log('change "'+t.name+'" → "'+f.name+'"',y,A,f,D),t instanceof p.Texture&&(f=this.copySettings(t,f)),f&&(f.guid=M.guid),h(f)}else x&&console.warn("Could not find texture with guid",M.guid,b.parser.json)}if(A=0,b.parser.json.meshes){let E=!1;for(const f of b.parser.json.meshes){if(f!=null&&f.extensions){const m=f==null?void 0:f.extensions[U];if(m!=null&&m.guid&&m.guid===M.guid){E=!0;break}}A++}if(E){const f=await q.getDependency("mesh",A),m=M;if(r&&console.log(`Loaded Mesh "${f.name}"`,y,A,f,D),f.isMesh===!0){const S=f.geometry;return _.assignLODInformation(o.url,S,s,e,void 0,m.density),h(S)}else{const S=new Array;for(let T=0;T<f.children.length;T++){const P=f.children[T];if(P.isMesh===!0){const X=P.geometry;_.assignLODInformation(o.url,X,s,e,T,m.density),S.push(X)}}return h(S)}}else x&&console.warn("Could not find mesh with guid",M.guid,b.parser.json)}return h(null)});return this.previouslyLoaded.set(D,F),await F}else if(t instanceof p.Texture){r&&console.log("Load texture from uri: "+y);const v=await new p.TextureLoader().loadAsync(y);return v?(v.guid=i.guid,v.flipY=!1,v.needsUpdate=!0,v.colorSpace=t.colorSpace,r&&console.log(i,v)):x&&console.warn("failed loading",y),v}}else x&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,o,s,i){if(!e)return;e.userData||(e.userData={});const n=new He(t,r,o,s,i);e.userData.LODS=n}static getAssignedLODInformation(t){var e;return((e=t==null?void 0:t.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return e=e.clone(),x&&console.warn(`Copying texture settings
|
|
4
4
|
`,t.uuid,`
|
package/lib/extension.d.ts
CHANGED
|
@@ -94,7 +94,9 @@ export declare class NEEDLE_progressive implements GLTFLoaderPlugin {
|
|
|
94
94
|
* @param level the level of detail to load (0 is the highest resolution) - currently only 0 is supported
|
|
95
95
|
* @returns a promise that resolves to the material or texture with the requested LOD level
|
|
96
96
|
*/
|
|
97
|
-
static assignTextureLOD(materialOrTexture: Material
|
|
97
|
+
static assignTextureLOD(materialOrTexture: Material, level: number): Promise<Array<ProgressiveMaterialTextureLoadingResult> | null>;
|
|
98
|
+
static assignTextureLOD(materialOrTexture: Mesh, level: number): Promise<Array<ProgressiveMaterialTextureLoadingResult> | null>;
|
|
99
|
+
static assignTextureLOD(materialOrTexture: Texture, level: number): Promise<Texture | null>;
|
|
98
100
|
private static assignTextureLODForSlot;
|
|
99
101
|
private readonly parser;
|
|
100
102
|
private readonly url;
|
package/lib/extension.js
CHANGED
|
@@ -283,16 +283,31 @@ export class NEEDLE_progressive {
|
|
|
283
283
|
}
|
|
284
284
|
return Promise.resolve(null);
|
|
285
285
|
}
|
|
286
|
-
/** Load a different resolution of a texture (if available)
|
|
287
|
-
* @param context the context
|
|
288
|
-
* @param source the sourceid of the file from which the texture is loaded (this is usually the component's sourceId)
|
|
289
|
-
* @param materialOrTexture the material or texture to load the LOD for (if passing in a material all textures in the material will be loaded)
|
|
290
|
-
* @param level the level of detail to load (0 is the highest resolution) - currently only 0 is supported
|
|
291
|
-
* @returns a promise that resolves to the material or texture with the requested LOD level
|
|
292
|
-
*/
|
|
293
286
|
static assignTextureLOD(materialOrTexture, level = 0) {
|
|
294
287
|
if (!materialOrTexture)
|
|
295
288
|
return Promise.resolve(null);
|
|
289
|
+
if (materialOrTexture.isMesh === true) {
|
|
290
|
+
const mesh = materialOrTexture;
|
|
291
|
+
if (Array.isArray(mesh.material)) {
|
|
292
|
+
const arr = new Array();
|
|
293
|
+
for (const mat of mesh.material) {
|
|
294
|
+
const promise = this.assignTextureLOD(mat, level);
|
|
295
|
+
arr.push(promise);
|
|
296
|
+
}
|
|
297
|
+
return Promise.all(arr).then(res => {
|
|
298
|
+
const textures = new Array();
|
|
299
|
+
for (const tex of res) {
|
|
300
|
+
if (Array.isArray(tex)) {
|
|
301
|
+
textures.push(...tex);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return textures;
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
return this.assignTextureLOD(mesh.material, level);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
296
311
|
if (materialOrTexture instanceof Material || materialOrTexture.isMaterial === true) {
|
|
297
312
|
const material = materialOrTexture;
|
|
298
313
|
const promises = [];
|
package/lib/loaders.d.ts
CHANGED
|
@@ -23,10 +23,10 @@ export declare function createLoaders(renderer: WebGLRenderer | null): {
|
|
|
23
23
|
meshoptDecoder: {
|
|
24
24
|
supported: boolean;
|
|
25
25
|
ready: Promise<void>;
|
|
26
|
-
decodeVertexBuffer: (target: Uint8Array, count: number, size: number, source: Uint8Array, filter?: string) => void;
|
|
26
|
+
decodeVertexBuffer: (target: Uint8Array, count: number, size: number, source: Uint8Array, filter?: string | undefined) => void;
|
|
27
27
|
decodeIndexBuffer: (target: Uint8Array, count: number, size: number, source: Uint8Array) => void;
|
|
28
28
|
decodeIndexSequence: (target: Uint8Array, count: number, size: number, source: Uint8Array) => void;
|
|
29
|
-
decodeGltfBuffer: (target: Uint8Array, count: number, size: number, source: Uint8Array, mode: string, filter?: string) => void;
|
|
29
|
+
decodeGltfBuffer: (target: Uint8Array, count: number, size: number, source: Uint8Array, mode: string, filter?: string | undefined) => void;
|
|
30
30
|
};
|
|
31
31
|
};
|
|
32
32
|
export declare function addDracoAndKTX2Loaders(loader: GLTFLoader): void;
|
package/lib/version.js
CHANGED
package/package.json
CHANGED