@needle-tools/gltf-progressive 1.0.0-alpha.4 → 1.0.0-alpha.6
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 -1
- package/{dist/@needle-tools-gltf-progressive.js → gltf-progressive.js} +87 -69
- package/gltf-progressive.min.js +3 -0
- package/gltf-progressive.umd.cjs +3 -0
- package/lib/extension.d.ts +109 -109
- package/lib/extension.js +672 -672
- package/lib/extension.js.map +1 -1
- package/lib/index.d.ts +26 -10
- package/lib/index.js +37 -21
- package/lib/index.js.map +1 -1
- package/lib/loaders.d.ts +4 -4
- package/lib/loaders.js +35 -35
- package/lib/loaders.js.map +1 -1
- package/lib/lods_manager.d.ts +69 -51
- package/lib/lods_manager.js +354 -336
- package/lib/lods_manager.js.map +1 -1
- package/lib/plugins/index.d.ts +2 -2
- package/lib/plugins/index.js +2 -2
- package/lib/plugins/modelviewer.d.ts +4 -15
- package/lib/plugins/modelviewer.js +125 -102
- package/lib/plugins/modelviewer.js.map +1 -1
- package/lib/plugins/plugin.d.ts +24 -14
- package/lib/plugins/plugin.js +11 -4
- package/lib/plugins/plugin.js.map +1 -1
- package/lib/utils.d.ts +2 -2
- package/lib/utils.js +36 -36
- package/lib/utils.js.map +1 -1
- package/package.json +18 -3
- package/dist/@needle-tools-gltf-progressive.min.js +0 -3
- package/dist/@needle-tools-gltf-progressive.umd.cjs +0 -3
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
"use strict";var re=Object.defineProperty;var se=(l,e,t)=>e in l?re(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var u=(l,e,t)=>(se(l,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("three"),ie=require("three/examples/jsm/loaders/GLTFLoader.js"),oe=require("three/examples/jsm/libs/meshopt_decoder.module.js"),ne=require("three/examples/jsm/loaders/DRACOLoader.js"),ae=require("three/examples/jsm/loaders/KTX2Loader.js");let le="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",ue="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/",z,$,I;function Z(l){z||(z=new ne.DRACOLoader,z.setDecoderPath(le),z.setDecoderConfig({type:"js"})),I||(I=new ae.KTX2Loader,I.setTranscoderPath(ue)),$||($=oe.MeshoptDecoder),l?I.detectSupport(l):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function j(l){l.dracoLoader||l.setDRACOLoader(z),l.ktx2Loader||l.setKTX2Loader(I),l.meshoptDecoder||l.setMeshoptDecoder($)}function Y(l){let t=new URL(window.location.href).searchParams.get(l);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function ce(l,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||l===void 0)return e;const t=l.lastIndexOf("/");if(t>=0){const r=l.substring(0,t+1);for(;r.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return r+e}return e}const X=new Array;function fe(l){X.push(l)}const C="NEEDLE_progressive",T=Y("debugprogressive"),V=Symbol("needle-progressive-texture"),U=new Map,K=new Set;if(T){let l=function(){e+=1,console.log("Toggle LOD level",e,U),U.forEach((i,o)=>{for(const s of i.keys){const n=o[s];if(n.isBufferGeometry===!0){const a=O.getMeshLODInformation(n),d=a?Math.min(e,a.lods.length):0;o["DEBUG:LOD"]=d,O.assignMeshLOD(o,d),a&&(t=Math.max(t,a.lods.length-1))}else if(o.isMaterial===!0){o["DEBUG:LOD"]=e,O.assignTextureLOD(o,e);break}}}),e>=t&&(e=-1)},e=-1,t=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&l(),i.key==="w"&&(r=!r,K&&K.forEach(o=>{o.name!="BackgroundCubeMaterial"&&"wireframe"in o&&(o.wireframe=r)}))})}function H(l,e,t){var i;if(!T)return;U.has(l)||U.set(l,{keys:[],sourceId:t});const r=U.get(l);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const S=class{constructor(e,t){u(this,"parser");u(this,"url");T&&console.log("Progressive extension registered for",t),this.parser=e,this.url=t}get name(){return C}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static hasLODLevelAvailable(e,t){var o;if(e.isMaterial===!0){for(const s of Object.keys(e)){const n=e[s];if(n.isTexture&&this.hasLODLevelAvailable(n,t))return!0}return!1}else if(e.isGroup===!0){for(const s of e.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,t))return!0}let r,i;if(e.isMesh?r=e.geometry:(e.isBufferGeometry||e.isTexture)&&(r=e),r&&(o=r==null?void 0:r.userData)!=null&&o.LODS){const s=r.userData.LODS;if(i=this.lodInfos.get(s.key),t===void 0)return i!=null;if(i)return Array.isArray(i.lods)?t<i.lods.length:t===0}return!1}static assignMeshLOD(e,t){var r;if(!e)return Promise.resolve(null);if(e instanceof h.Mesh||e.isMesh===!0){const i=e.geometry,o=this.getAssignedLODInformation(i);if(!o)return Promise.resolve(null);for(const s of X)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,S.getOrLoadLOD(i,t).then(s=>{if(e["LOD:requested level"]===t){if(delete e["LOD:requested level"],Array.isArray(s)){const n=o.index||0;s=s[n]}s&&i!=s&&s instanceof h.BufferGeometry&&(e.geometry=s,T&&H(e,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",e,s),null))}else T&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",e);return Promise.resolve(null)}static assignTextureLOD(e,t=0){if(!e)return Promise.resolve(null);if(e instanceof h.Material||e.isMaterial===!0){const r=e,i=[],o=new Array;if(T&&K.add(r),r instanceof h.RawShaderMaterial)for(const s of Object.keys(r.uniforms)){const n=r.uniforms[s].value;if((n==null?void 0:n.isTexture)===!0){const a=this.assignTextureLODForSlot(n,t,r,s);i.push(a),o.push(s)}}else for(const s of Object.keys(r)){const n=r[s];if((n==null?void 0:n.isTexture)===!0){const a=this.assignTextureLODForSlot(n,t,r,s);i.push(a),o.push(s)}}return Promise.all(i).then(s=>{const n=new Array;for(let a=0;a<s.length;a++){const d=s[a],f=o[a];d&&d.isTexture===!0?n.push({material:r,slot:f,texture:d,level:t}):n.push({material:r,slot:f,texture:null,level:t})}return n})}if(e instanceof h.Texture||e.isTexture===!0){const r=e;return this.assignTextureLODForSlot(r,t,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(e,t,r,i){return(e==null?void 0:e.isTexture)!==!0?Promise.resolve(null):S.getOrLoadLOD(e,t).then(o=>{if(Array.isArray(o))return null;if((o==null?void 0:o.isTexture)===!0){if(o!=e&&(r&&i&&(r[i]=o),T&&i&&r)){const s=this.getAssignedLODInformation(e);s&&H(r,i,s.url)}return o}else T=="verbose"&&console.warn("No LOD found for",e,t);return null}).catch(o=>(console.error("Error loading LOD",e,o),null))}afterRoot(e){var t,r;return T&&console.log("AFTER",this.url,e),(t=this.parser.json.textures)==null||t.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[C];if(s){let n=!1;for(const a of this.parser.associations.keys())a.isTexture===!0&&this.parser.associations.get(a).textures===o&&(n=!0,S.registerTexture(this.url,a,o,s));n||this.parser.getDependency("texture",o).then(a=>{a&&S.registerTexture(this.url,a,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,o)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[C];if(s&&s.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const a=this.parser.associations.get(n);a.meshes===o&&S.registerMesh(this.url,n.uuid,n,s.lods.length,a.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var n,a,d;const r=T=="verbose",i=e.userData.LODS;if(!i)return null;const o=i==null?void 0:i.key;let s;if(e.isTexture===!0){const f=e;f.source&&f.source[V]&&(s=f.source[V])}if(s||(s=S.lodInfos.get(o)),s){if(t>0){let g=!1;const v=Array.isArray(s.lods);if(v&&t>=s.lods.length?g=!0:v||(g=!0),g)return this.lowresCache.get(o)}const f=Array.isArray(s.lods)?s.lods[t].path:s.lods;if(!f)return T&&!s["missing:uri"]&&(s["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+t,s)),null;const D=ce(i.url,f);if(D.endsWith(".glb")||D.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const g=D+"_"+s.guid,v=this.previouslyLoaded.get(g);if(v!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${g}`);let m=await v.catch(F=>(console.error(`Error loading LOD ${t} from ${D}
|
|
2
|
-
`,F),null)),R=!1;if(m==null||(m instanceof h.Texture&&e instanceof h.Texture?(n=m.image)!=null&&n.data||(a=m.source)!=null&&a.data?m=this.copySettings(e,m):(R=!0,this.previouslyLoaded.delete(g)):m instanceof h.BufferGeometry&&e instanceof h.BufferGeometry&&((d=m.attributes.position)!=null&&d.array||(R=!0,this.previouslyLoaded.delete(g)))),!R)return m}const x=s,b=new Promise(async(m,R)=>{const F=new ie.GLTFLoader;j(F),T&&(await new Promise(y=>setTimeout(y,1e3)),r&&console.warn("Start loading (delayed) "+D,x.guid));let L=D;if(x&&Array.isArray(x.lods)){const y=x.lods[t];y.hash&&(L+="?v="+y.hash)}const p=await F.loadAsync(L).catch(y=>(console.error(`Error loading LOD ${t} from ${D}
|
|
3
|
-
`,y),null));if(!p)return null;const P=p.parser;r&&console.log("Loading finished "+D,x.guid);let w=0;if(p.parser.json.textures){let y=!1;for(const c of p.parser.json.textures){if(c!=null&&c.extensions){const M=c==null?void 0:c.extensions[C];if(M!=null&&M.guid&&M.guid===x.guid){y=!0;break}}w++}if(y){let c=await P.getDependency("texture",w);return r&&console.log('change "'+e.name+'" → "'+c.name+'"',D,w,c,g),e instanceof h.Texture&&(c=this.copySettings(e,c)),c&&(c.guid=x.guid),m(c)}}if(w=0,p.parser.json.meshes){let y=!1;for(const c of p.parser.json.meshes){if(c!=null&&c.extensions){const M=c==null?void 0:c.extensions[C];if(M!=null&&M.guid&&M.guid===x.guid){y=!0;break}}w++}if(y){const c=await P.getDependency("mesh",w),M=x;if(r&&console.log(`Loaded Mesh "${c.name}"`,D,w,c,g),c.isMesh===!0){const B=c.geometry;return S.assignLODInformation(i.url,B,o,t,void 0,M.density),m(B)}else{const B=new Array;for(let k=0;k<c.children.length;k++){const E=c.children[k];if(E instanceof h.Mesh){const N=E.geometry;S.assignLODInformation(i.url,N,o,t,k,M.density),B.push(N)}}return m(B)}}}return m(null)});return this.previouslyLoaded.set(g,b),await b}else if(e instanceof h.Texture){r&&console.log("Load texture from uri: "+D);const v=await new h.TextureLoader().loadAsync(D);return v?(v.guid=s.guid,v.flipY=!1,v.needsUpdate=!0,v.colorSpace=e.colorSpace,r&&console.log(s,v)):T&&console.warn("failed loading",D),v}}else T&&console.warn(`Can not load LOD ${t}: no LOD info found for "${o}" ${e.name}`,e.type);return null}static assignLODInformation(e,t,r,i,o,s){if(!t)return;t.userData||(t.userData={});const n=new de(e,r,i,o,s);t.userData.LODS=n,t.userData.LOD=i}static getAssignedLODInformation(e){var t;return((t=e==null?void 0:e.userData)==null?void 0:t.LODS)||null}static copySettings(e,t){const r=this._copiedTextures.get(e);return r||(t=t.clone(),this._copiedTextures.set(e,t),t.offset=e.offset,t.repeat=e.repeat,t.colorSpace=e.colorSpace,t)}};let O=S;u(O,"registerTexture",(e,t,r,i)=>{T&&console.log("> Progressive: register texture",r,t.name,t.uuid,t,i),t.source&&(t.source[V]=i);const o=t.uuid;S.assignLODInformation(e,t,o,0,0,void 0),S.lodInfos.set(o,i),S.lowresCache.set(o,t)}),u(O,"registerMesh",(e,t,r,i,o,s)=>{var d;T&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const n=r.geometry;n.userData||(n.userData={}),S.assignLODInformation(e,n,t,i,o,s.density),S.lodInfos.set(t,s);let a=S.lowresCache.get(t);a?a.push(r.geometry):a=[r.geometry],S.lowresCache.set(t,a);for(const f of X)(d=f.onRegisteredNewMesh)==null||d.call(f,r,s)}),u(O,"lodInfos",new Map),u(O,"previouslyLoaded",new Map),u(O,"lowresCache",new Map),u(O,"_copiedTextures",new Map);class de{constructor(e,t,r,i,o){u(this,"url");u(this,"key");u(this,"level");u(this,"index");u(this,"density");this.url=e,this.key=t,this.level=r,i!=null&&(this.index=i),o!=null&&(this.density=o)}}let J=Y("debugprogressive");const ge=Y("noprogressive"),A=class{constructor(e){u(this,"renderer");u(this,"projectionScreenMatrix",new h.Matrix4);u(this,"cameraFrustrum",new h.Frustum);u(this,"updateInterval",0);u(this,"pause",!1);u(this,"plugins",[]);u(this,"_originalRender");u(this,"_sphere",new h.Sphere);u(this,"_tempBox",new h.Box3);u(this,"tempMatrix",new h.Matrix4);u(this,"_tempWorldPosition",new h.Vector3);u(this,"_tempBoxSize",new h.Vector3);u(this,"_tempBox2Size",new h.Vector3);this.renderer=e}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;let r=0;Z(this.renderer),this.renderer.render=function(i,o){const s=r++,n=e++;t.onBeforeRender(i,o,n,s),t._originalRender.call(this,i,o),t.onAfterRender(i,o,n,s),e--}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,i){}onAfterRender(e,t,r,i){if(ge||this.pause||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const o=1e5,n=this.renderer.renderLists.get(e,r).opaque;for(const a of n){const d=a.object;(d instanceof h.Mesh||d.isMesh)&&this.updateLODs(e,t,d,o)}}static getObjectLODState(e){var t;return(t=e.userData)==null?void 0:t.LOD_state}updateLODs(e,t,r,i){var a,d;for(const f of this.plugins)(a=f.onBeforeUpdateLOD)==null||a.call(f,this.renderer,e,t,r);let o=r.userData.LOD_state;o||(o=new he,r.userData.LOD_state=o);let s=this.calculateLodLevel(t,r,o,i);s=Math.round(s),s>=0&&this.loadProgressiveMeshes(r,s);let n=0;if(r.material){const f=r["DEBUG:LOD"];if(f!=null&&(n=f),Array.isArray(r.material))for(const D of r.material)this.loadProgressiveTextures(D,n);else this.loadProgressiveTextures(r.material,n)}for(const f of this.plugins)(d=f.onAfterUpdatedLOD)==null||d.call(f,this.renderer,e,t,r,s);o.lastLodLevel=s}loadProgressiveTextures(e,t){return e&&e.userData&&e.userData.LOD!==t?(e.userData.LOD=t,O.assignTextureLOD(e,t)):Promise.resolve(null)}loadProgressiveMeshes(e,t){if(!e)return Promise.resolve(null);if(e.userData||(e.userData={}),e.userData.LOD!==t){e.userData.LOD=t;const r=e.geometry;return O.assignMeshLOD(e,t).then(i=>(i&&e.userData.LOD==t&&r!=e.geometry,i))}return Promise.resolve(null)}calculateLodLevel(e,t,r,i){var n;if(!t)return-1;let s=10+1;if(e){if(J&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const a=O.getMeshLODInformation(t.geometry),d=a==null?void 0:a.lods;if(!d||d.length<=0||!((n=this.cameraFrustrum)!=null&&n.intersectsObject(t)))return 99;const f=t.geometry.boundingBox;if(f&&e.isPerspectiveCamera){const D=e;if(t.geometry.attributes.color&&t.geometry.attributes.color.count<100&&t.geometry.boundingSphere){this._sphere.copy(t.geometry.boundingSphere),this._sphere.applyMatrix4(t.matrixWorld);const L=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(L))return 0}if(this._tempBox.copy(f),this._tempBox.applyMatrix4(t.matrixWorld),this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&D.fov>70){const L=this._tempBox.min,p=this._tempBox.max;let P=L.x,w=L.y,y=p.x,c=p.y;const M=2,B=1.5,k=(L.x+p.x)*.5,E=(L.y+p.y)*.5;P=(P-k)*M+k,w=(w-E)*M+E,y=(y-k)*M+k,c=(c-E)*M+E;const N=P<0&&y>0?0:Math.min(Math.abs(L.x),Math.abs(p.x)),te=w<0&&c>0?0:Math.min(Math.abs(L.y),Math.abs(p.y)),q=Math.max(N,te);r.lastCentrality=(B-q)*(B-q)*(B-q)}else r.lastCentrality=1;const g=this._tempBox.getSize(this._tempBoxSize);g.multiplyScalar(.5),screen.availHeight>0&&g.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),g.x*=D.aspect;const v=e.matrixWorldInverse,x=new h.Box3;x.copy(f),x.applyMatrix4(t.matrixWorld),x.applyMatrix4(v);const b=x.getSize(this._tempBox2Size),G=Math.max(b.x,b.y);if(Math.max(g.x,g.y)!=0&&G!=0&&(g.z=b.z/Math.max(b.x,b.y)*Math.max(g.x,g.y)),r.lastScreenCoverage=Math.max(g.x,g.y,g.z),r.lastScreenspaceVolume.copy(g),r.lastScreenCoverage*=r.lastCentrality,J&&A.debugDrawLine){const L=this.tempMatrix.copy(this.projectionScreenMatrix);L.invert();const p=A.corner0,P=A.corner1,w=A.corner2,y=A.corner3;p.copy(this._tempBox.min),P.copy(this._tempBox.max),P.x=p.x,w.copy(this._tempBox.max),w.y=p.y,y.copy(this._tempBox.max);const c=(p.z+y.z)*.5;p.z=P.z=w.z=y.z=c,p.applyMatrix4(L),P.applyMatrix4(L),w.applyMatrix4(L),y.applyMatrix4(L),A.debugDrawLine(p,P,255),A.debugDrawLine(p,w,255),A.debugDrawLine(P,y,255),A.debugDrawLine(w,y,255)}let R=999;if(d&&r.lastScreenCoverage>0){for(let L=0;L<d.length;L++)if(d[L].density/r.lastScreenCoverage<i){R=L;break}}R<s&&(s=R)}}return s}};let _=A;u(_,"corner0",new h.Vector3),u(_,"corner1",new h.Vector3),u(_,"corner2",new h.Vector3),u(_,"corner3",new h.Vector3),u(_,"debugDrawLine");class he{constructor(){u(this,"lastLodLevel",0);u(this,"lastScreenCoverage",0);u(this,"lastScreenspaceVolume",new h.Vector3);u(this,"lastCentrality",0)}}const Q=Symbol("NEEDLE_mesh_lod"),W=Symbol("NEEDLE_texture_lod");function ee(){const l=document.querySelector("model-viewer");if(!l)return;let e=null;for(let t=l;t!=null;t=Object.getPrototypeOf(t)){const i=Object.getOwnPropertySymbols(t).find(o=>o.toString()=="Symbol(renderer)");!e&&i!=null&&(e=l[i].threeRenderer)}if(e){console.log("Adding Needle LODs to modelviewer");const t=new _(e);t.plugins.push(new pe(l)),t.enable()}}class pe{constructor(e){u(this,"modelviewer");this.modelviewer=e}onBeforeUpdateLOD(e,t,r,i){this.tryParseMeshLOD(t,i),this.tryParseTextureLOD(t,i)}getUrl(){return this.modelviewer.getAttribute("src")}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[W]==!0)return;t[W]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(!i){console.error("No url found in modelviewer");return}if(r&&t.material){let o=function(n){var d,f,D;if(n[W]==!0)return;n[W]=!0,n.userData&&(n.userData.LOD=-1);const a=Object.keys(n);for(let g=0;g<a.length;g++){const v=a[g],x=n[v];if((x==null?void 0:x.isTexture)===!0){const b=(f=(d=x.userData)==null?void 0:d.associations)==null?void 0:f.textures,G=r.parser.json.textures[b];if((D=G.extensions)!=null&&D[C]){const m=G.extensions[C];m&&i&&O.registerTexture(i,x,m.lods.length,m)}}}};const s=t.material;if(Array.isArray(s))for(const n of s)o(n);else o(s)}}tryParseMeshLOD(e,t){var o,s;if(t[Q]==!0)return;t[Q]=!0;const r=this.getUrl();if(!r){console.error("No url found in modelviewer");return}const i=(s=(o=t.userData)==null?void 0:o.gltfExtensions)==null?void 0:s[C];if(i&&r){const n=t.uuid;O.registerMesh(r,n,t,0,i.lods.length,i)}}}function ye(l,e,t){Z(e),j(t),t.register(i=>new O(i,l));const r=new _(e);return r.enable(),r}document.addEventListener("DOMContentLoaded",()=>{ee()});exports.EXTENSION_NAME=C;exports.LODsManager=_;exports.NEEDLE_progressive=O;exports.patchModelViewer=ee;exports.registerPlugin=fe;exports.useNeedleGLTFProgressive=ye;
|