@needle-tools/gltf-progressive 1.0.0-alpha.17 → 1.0.0-alpha.19
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 +4 -1
- package/README.md +81 -0
- package/examples/react-three-fiber/favicon.png +0 -0
- package/examples/react-three-fiber/index.html +5 -7
- package/examples/react-three-fiber/package-lock.json +223 -2
- package/examples/react-three-fiber/package.json +2 -1
- package/examples/react-three-fiber/vite.config.js +2 -7
- package/gltf-progressive.js +26 -22
- package/gltf-progressive.min.js +1 -1
- package/gltf-progressive.umd.cjs +2 -2
- package/lib/lods_manager.d.ts +2 -0
- package/lib/lods_manager.js +2 -0
- package/package.json +1 -1
- package/examples/react-three-fiber/dist/assets/index-1558b86e.css +0 -1
- package/examples/react-three-fiber/dist/assets/index-a23e0239.js +0 -4003
- package/examples/react-three-fiber/dist/index.html +0 -28
package/gltf-progressive.min.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
var le=Object.defineProperty,ue=(t,e,r)=>e in t?le(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,c=(t,e,r)=>(ue(t,typeof e!="symbol"?e+"":e,r),r);import{MeshoptDecoder as ce}from"three/examples/jsm/libs/meshopt_decoder.module.js";import{DRACOLoader as de}from"three/examples/jsm/loaders/DRACOLoader.js";import{KTX2Loader as he}from"three/examples/jsm/loaders/KTX2Loader.js";import{BufferGeometry as z,Mesh as U,Material as fe,Texture as k,TextureLoader as ge,Matrix4 as ee,Frustum as me,Sphere as pe,Box3 as te,Vector3 as B}from"three";import{GLTFLoader as ye}from"three/examples/jsm/loaders/GLTFLoader.js";let $="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",V="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch($+"draco_decoder.js",{method:"head"}).catch(t=>{$="./include/draco/",V="./include/ktx2/"});function De(t){$=t}function xe(t){V=t}let G,X,N;function K(t){G||(G=new de,G.setDecoderPath($),G.setDecoderConfig({type:"js"})),N||(N=new he,N.setTranscoderPath(V)),X||(X=ce),t?N.detectSupport(t):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function H(t){t.dracoLoader||t.setDRACOLoader(G),t.ktx2Loader||t.setKTX2Loader(N),t.meshoptDecoder||t.setMeshoptDecoder(X)}function Y(t){const e=new URL(window.location.href).searchParams.get(t);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Le(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}function re(t){var e;return((e=t.userData)==null?void 0:e["needle:raycast-mesh"])instanceof z?t.userData["needle:raycast-mesh"]:null}function se(t,e){(t.type==="Mesh"||t.type==="SkinnedMesh")&&(t.userData||(t.userData={}),t.userData["needle:raycast-mesh"]=e)}const R=new Array,I="NEEDLE_progressive",v=Y("debugprogressive"),J=Symbol("needle-progressive-texture"),F=new Map,Q=new Set;if(v){let t=function(){e+=1,console.log("Toggle LOD level",e,F),F.forEach((o,s)=>{for(const a of o.keys){const i=s[a];if(i.isBufferGeometry===!0){const l=O.getMeshLODInformation(i),d=l?Math.min(e,l.lods.length):0;s["DEBUG:LOD"]=e,O.assignMeshLOD(s,d),l&&(r=Math.max(r,l.lods.length-1))}else if(s.isMaterial===!0){s["DEBUG:LOD"]=e,O.assignTextureLOD(s,e);break}}}),e>=r&&(e=-1)},e=-1,r=2,n=!1;window.addEventListener("keyup",o=>{o.key==="p"&&t(),o.key==="w"&&(n=!n,Q&&Q.forEach(s=>{s.name!="BackgroundCubeMaterial"&&"wireframe"in s&&(s.wireframe=n)}))})}function ne(t,e,r){var n;if(!v)return;F.has(t)||F.set(t,{keys:[],sourceId:r});const o=F.get(t);((n=o?.keys)==null?void 0:n.includes(e))==!1&&o.keys.push(e)}const M=class{constructor(t,e){c(this,"parser"),c(this,"url"),v&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}get name(){return I}static getMeshLODInformation(t){const e=this.getAssignedLODInformation(t);return e!=null&&e.key?this.lodInfos.get(e.key):null}static hasLODLevelAvailable(t,e){var r;if(t.isMaterial===!0){for(const s of Object.keys(t)){const a=t[s];if(a.isTexture&&this.hasLODLevelAvailable(a,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let n,o;if(t.isMesh?n=t.geometry:(t.isBufferGeometry||t.isTexture)&&(n=t),n&&(r=n?.userData)!=null&&r.LODS){const s=n.userData.LODS;if(o=this.lodInfos.get(s.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 U||t.isMesh===!0){const n=t.geometry,o=this.getAssignedLODInformation(n);if(!o)return Promise.resolve(null);for(const s of R)(r=s.onBeforeGetLODMesh)==null||r.call(s,t,e);return t["LOD:requested level"]=e,M.getOrLoadLOD(n,e).then(s=>{if(t["LOD:requested level"]===e){if(delete t["LOD:requested level"],Array.isArray(s)){const a=o.index||0;s=s[a]}s&&n!=s&&s instanceof z&&(t.geometry=s,v&&ne(t,"geometry",o.url))}return s}).catch(s=>(console.error("Error loading mesh LOD",t,s),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 instanceof fe||t.isMaterial===!0){const r=t,n=[],o=new Array;if(v&&Q.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const a of Object.keys(s.uniforms)){const i=s.uniforms[a].value;if(i?.isTexture===!0){const l=this.assignTextureLODForSlot(i,e,r,a);n.push(l),o.push(a)}}}else for(const s of Object.keys(r)){const a=r[s];if(a?.isTexture===!0){const i=this.assignTextureLODForSlot(a,e,r,s);n.push(i),o.push(s)}}return Promise.all(n).then(s=>{const a=new Array;for(let i=0;i<s.length;i++){const l=s[i],d=o[i];l&&l.isTexture===!0?a.push({material:r,slot:d,texture:l,level:e}):a.push({material:r,slot:d,texture:null,level:e})}return a})}if(t instanceof k||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):M.getOrLoadLOD(t,e).then(o=>{if(Array.isArray(o))return null;if(o?.isTexture===!0){if(o!=t&&(r&&n&&(r[n]=o),v&&n&&r)){const s=this.getAssignedLODInformation(t);s&&ne(r,n,s.url)}return o}else v=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(o=>(console.error("Error loading LOD",t,o),null))}afterRoot(t){var e,r;return v&&console.log("AFTER",this.url,t),(e=this.parser.json.textures)==null||e.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.extensions[I];if(s){let a=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i).textures===o&&(a=!0,M.registerTexture(this.url,i,o,s));a||this.parser.getDependency("texture",o).then(i=>{i&&M.registerTexture(this.url,i,o,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((n,o)=>{if(n!=null&&n.extensions){const s=n?.extensions[I];if(s&&s.lods){for(const a of this.parser.associations.keys())if(a.isMesh){const i=this.parser.associations.get(a);i.meshes===o&&M.registerMesh(this.url,s.guid,a,s.lods.length,i.primitives,s)}}}}),null}static async getOrLoadLOD(t,e){var r,n,o;const s=v=="verbose",a=t.userData.LODS;if(!a)return null;const i=a?.key;let l;if(t.isTexture===!0){const d=t;d.source&&d.source[J]&&(l=d.source[J])}if(l||(l=M.lodInfos.get(i)),l){if(e>0){let u=!1;const p=Array.isArray(l.lods);if(p&&e>=l.lods.length?u=!0:p||(u=!0),u)return this.lowresCache.get(i)}const d=Array.isArray(l.lods)?l.lods[e].path:l.lods;if(!d)return v&&!l["missing:uri"]&&(l["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,l)),null;const h=Le(a.url,d);if(h.endsWith(".glb")||h.endsWith(".gltf")){if(!l.guid)return console.warn("missing pointer for glb/gltf texture",l),null;const u=h+"_"+l.guid,p=this.previouslyLoaded.get(u);if(p!==void 0){s&&console.log(`LOD ${e} was already loading/loaded: ${u}`);let y=await p.catch(m=>(console.error(`Error loading LOD ${e} from ${h}
|
|
2
2
|
`,m),null)),g=!1;if(y==null||(y instanceof k&&t instanceof k?(r=y.image)!=null&&r.data||(n=y.source)!=null&&n.data?y=this.copySettings(t,y):(g=!0,this.previouslyLoaded.delete(u)):y instanceof z&&t instanceof z&&((o=y.attributes.position)!=null&&o.array||(g=!0,this.previouslyLoaded.delete(u)))),!g)return y}const D=l,P=new Promise(async(y,g)=>{const m=new ye;H(m),v&&(await new Promise(L=>setTimeout(L,1e3)),s&&console.warn("Start loading (delayed) "+h,D.guid));let b=h;if(D&&Array.isArray(D.lods)){const L=D.lods[e];L.hash&&(b+="?v="+L.hash)}const x=await m.loadAsync(b).catch(L=>(console.error(`Error loading LOD ${e} from ${h}
|
|
3
|
-
`,L),null));if(!x)return null;const S=x.parser;s&&console.log("Loading finished "+h,D.guid);let _=0;if(x.parser.json.textures){let L=!1;for(const f of x.parser.json.textures){if(f!=null&&f.extensions){const w=f?.extensions[I];if(w!=null&&w.guid&&w.guid===D.guid){L=!0;break}}_++}if(L){let f=await S.getDependency("texture",_);return f&&M.assignLODInformation(a.url,f,i,e,void 0,void 0),s&&console.log('change "'+t.name+'" \u2192 "'+f.name+'"',h,_,f,u),t instanceof k&&(f=this.copySettings(t,f)),f&&(f.guid=D.guid),y(f)}else v&&console.warn("Could not find texture with guid",D.guid)}if(_=0,x.parser.json.meshes){let L=!1;for(const f of x.parser.json.meshes){if(f!=null&&f.extensions){const w=f?.extensions[I];if(w!=null&&w.guid&&w.guid===D.guid){L=!0;break}}_++}if(L){const f=await S.getDependency("mesh",_),w=D;if(s&&console.log(`Loaded Mesh "${f.name}"`,h,_,f,u),f.isMesh===!0){const E=f.geometry;return M.assignLODInformation(a.url,E,i,e,void 0,w.density),y(E)}else{const E=new Array;for(let C=0;C<f.children.length;C++){const W=f.children[C];if(W instanceof U){const j=W.geometry;M.assignLODInformation(a.url,j,i,e,C,w.density),E.push(j)}}return y(E)}}}return y(null)});return this.previouslyLoaded.set(u,P),await P}else if(t instanceof k){s&&console.log("Load texture from uri: "+h);const u=await new ge().loadAsync(h);return u?(u.guid=l.guid,u.flipY=!1,u.needsUpdate=!0,u.colorSpace=t.colorSpace,s&&console.log(l,u)):v&&console.warn("failed loading",h),u}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,o,s){if(!e)return;e.userData||(e.userData={});const a=new ve(t,r,n,o,s);e.userData.LODS=a,e.userData.LOD=n}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return this._copiedTextures.get(t)||(e=e.clone(),this._copiedTextures.set(t,e),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.generateMipmaps=t.generateMipmaps,e)}};let O=M;c(O,"registerTexture",(t,e,r,n)=>{v&&console.log("> Progressive: register texture",r,e.name,e.uuid,e,n),e.source&&(e.source[J]=n);const o=n.guid;M.assignLODInformation(t,e,o,0,0,void 0),M.lodInfos.set(o,n),M.lowresCache.set(o,e)}),c(O,"registerMesh",(t,e,r,n,o,s)=>{var a;v&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const i=r.geometry;i.userData||(i.userData={}),M.assignLODInformation(t,i,e,n,o,s.density),M.lodInfos.set(e,s);let l=M.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],M.lowresCache.set(e,l),n>0&&!re(r)&&se(r,i);for(const d of R)(a=d.onRegisteredNewMesh)==null||a.call(d,r,s)}),c(O,"lodInfos",new Map),c(O,"previouslyLoaded",new Map),c(O,"lowresCache",new Map),c(O,"_copiedTextures",new Map);class ve{constructor(e,r,n,o,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const Z=Y("debugprogressive"),Me=Y("noprogressive"),oe=Symbol("Needle:LODSManager"),T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new ee),c(this,"cameraFrustrum",new me),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new pe),c(this,"_tempBox",new te),c(this,"_tempBox2",new te),c(this,"tempMatrix",new ee),c(this,"_tempWorldPosition",new B),c(this,"_tempBoxSize",new B),c(this,"_tempBox2Size",new B),this.renderer=t}static getObjectLODState(t){var e;return(e=t.userData)==null?void 0:e.LOD_state}static addPlugin(t){R.push(t)}static removePlugin(t){const e=R.indexOf(t);e>=0&&R.splice(e,1)}static get(t){return t[oe]?t[oe]:new T(t)}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;K(this.renderer),this.renderer.render=function(r,n){e.renderer.getRenderTarget()==null&&(t=0,e._frame+=1);const o=e._frame,s=t++;e.onBeforeRender(r,n,s,o),e._originalRender.call(this,r,n),e.onAfterRender(r,n,s,o)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(t,e,r,n){}onAfterRender(t,e,r,n){var o,s;if(this.pause)return;const a=this.renderer.renderLists.get(t,0),i=a.opaque;let l=!0;if(i.length===1){const d=i[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(l=!1)}if(l){if(Me||this.updateInterval>0&&n%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=this.targetTriangleDensity;for(const u of i){if(u.material&&(((o=u.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=u.geometry)==null?void 0:s.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){Z&&(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",u,u.material.name,u.material.type)));continue}switch(u.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const p=u.object;(p instanceof U||p.isMesh)&&this.updateLODs(t,e,p,d)}const h=a.transparent;for(const u of h){const p=u.object;(p instanceof U||p.isMesh)&&this.updateLODs(t,e,p,d)}}}updateLODs(t,e,r,n){var o,s;for(const d of R)(o=d.onBeforeUpdateLOD)==null||o.call(d,this.renderer,t,e,r);let a=r.userData.LOD_state;a||(a=new Oe,r.userData.LOD_state=a);let i=this.calculateLodLevel(e,r,a,n);i=Math.round(i),i>=0&&this.loadProgressiveMeshes(r,i);let l=0;if(r.material){const d=r["DEBUG:LOD"];if(d!=null&&(l=d),Array.isArray(r.material))for(const h of r.material)this.loadProgressiveTextures(h,l);else this.loadProgressiveTextures(r.material,l)}for(const d of R)(s=d.onAfterUpdatedLOD)==null||s.call(d,this.renderer,t,e,r,i);a.lastLodLevel=i}loadProgressiveTextures(t,e){return t&&t.userData&&t.userData.LOD!==e?(t.userData.LOD=e,O.assignTextureLOD(t,e)):Promise.resolve(null)}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t.userData||(t.userData={}),t.userData.LOD!==e){t.userData.LOD=e;const r=t.geometry;return O.assignMeshLOD(t,e).then(n=>(n&&t.userData.LOD==e&&r!=t.geometry,n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,o=(r.x+n.x)*.5,s=(r.y+n.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n){var o;if(!e)return-1;let s=10+1;if(t){if(Z&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=O.getMeshLODInformation(e.geometry),i=a?.lods;if(!i||i.length<=0)return 0;if(!((o=this.cameraFrustrum)!=null&&o.intersectsObject(e)))return 99;const l=e.geometry.boundingBox;if(l&&t.isPerspectiveCamera){const d=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const g=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g))return 0}if(this._tempBox.copy(l),this._tempBox.applyMatrix4(e.matrixWorld),T.isInside(this._tempBox,this.projectionScreenMatrix))return 0;if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&d.fov>70){const g=this._tempBox.min,m=this._tempBox.max;let b=g.x,x=g.y,S=m.x,_=m.y;const L=2,f=1.5,w=(g.x+m.x)*.5,E=(g.y+m.y)*.5;b=(b-w)*L+w,x=(x-E)*L+E,S=(S-w)*L+w,_=(_-E)*L+E;const C=b<0&&S>0?0:Math.min(Math.abs(g.x),Math.abs(m.x)),W=x<0&&_>0?0:Math.min(Math.abs(g.y),Math.abs(m.y)),j=Math.max(C,W);r.lastCentrality=(f-j)*(f-j)*(f-j)}else r.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&h.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),h.x*=d.aspect;const u=t.matrixWorldInverse,p=this._tempBox2;p.copy(l),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(u);const D=p.getSize(this._tempBox2Size),P=Math.max(D.x,D.y);if(Math.max(h.x,h.y)!=0&&P!=0&&(h.z=D.z/Math.max(D.x,D.y)*Math.max(h.x,h.y)),r.lastScreenCoverage=Math.max(h.x,h.y,h.z),r.lastScreenspaceVolume.copy(h),r.lastScreenCoverage*=r.lastCentrality,Z&&T.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const m=T.corner0,b=T.corner1,x=T.corner2,S=T.corner3;m.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=m.x,x.copy(this._tempBox.max),x.y=m.y,S.copy(this._tempBox.max);const _=(m.z+S.z)*.5;m.z=b.z=x.z=S.z=_,m.applyMatrix4(g),b.applyMatrix4(g),x.applyMatrix4(g),S.applyMatrix4(g),T.debugDrawLine(m,b,255),T.debugDrawLine(m,x,255),T.debugDrawLine(b,S,255),T.debugDrawLine(x,S,255)}let y=999;if(i&&r.lastScreenCoverage>0){for(let g=0;g<i.length;g++)if(i[g].density/r.lastScreenCoverage<n){y=g;break}}y<s&&(s=y)}}return s}};let A=T;c(A,"debugDrawLine"),c(A,"corner0",new B),c(A,"corner1",new B),c(A,"corner2",new B),c(A,"corner3",new B),c(A,"_tempPtInside",new B);class Oe{constructor(){c(this,"lastLodLevel",0),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new B),c(this,"lastCentrality",0)}}const ie=Symbol("NEEDLE_mesh_lod"),q=Symbol("NEEDLE_texture_lod");function ae(t){if(!t)return null;let e=null,r=null;for(let n=t;n!=null;n=Object.getPrototypeOf(n)){const o=Object.getOwnPropertySymbols(n),s=o.find(i=>i.toString()=="Symbol(renderer)"),a=o.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=t[s].threeRenderer),!r&&a!=null&&(r=t[a])}if(e){console.log("Adding Needle LODs to modelviewer");const n=A.get(e);if(A.addPlugin(new we(t)),n.enable(),r){const o=r.camera||r.traverse(s=>s.type=="PerspectiveCamera")[0];o&&e.render(r,o)}return()=>{n.disable()}}return null}class we{constructor(e){c(this,"modelviewer"),c(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,r,n,o){this.tryParseMeshLOD(r,o),this.tryParseTextureLOD(r,o)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,r){if(r[q]==!0)return;r[q]=!0;const n=this.tryGetCurrentGLTF(e),o=this.getUrl();if(o&&n&&r.material){let s=function(i){var l,d,h;if(i[q]==!0)return;i[q]=!0,i.userData&&(i.userData.LOD=-1);const u=Object.keys(i);for(let p=0;p<u.length;p++){const D=u[p],P=i[D];if(P?.isTexture===!0){const y=(d=(l=P.userData)==null?void 0:l.associations)==null?void 0:d.textures,g=n.parser.json.textures[y];if(!g){console.warn("Texture data not found for texture index "+y);continue}if((h=g?.extensions)!=null&&h[I]){const m=g.extensions[I];m&&o&&O.registerTexture(o,P,m.lods.length,m)}}}};const a=r.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,r){var n,o;if(r[ie]==!0)return;r[ie]=!0;const s=this.getUrl();if(!s)return;const a=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[I];if(a&&s){const i=r.uuid;O.registerMesh(s,i,r,0,a.lods.length,a)}}}function be(t,e,r,n){K(e),H(r),r.register(s=>new O(s,t));const o=A.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{ae(document.querySelector("model-viewer"))});export{I as EXTENSION_NAME,A as LODsManager,O as NEEDLE_progressive,H as addDracoAndKTX2Loaders,K as createLoaders,re as getRaycastMesh,ae as patchModelViewer,De as setDracoDecoderLocation,xe as setKTX2TranscoderLocation,se as setRaycastMesh,be as useNeedleProgressive};
|
|
3
|
+
`,L),null));if(!x)return null;const S=x.parser;s&&console.log("Loading finished "+h,D.guid);let _=0;if(x.parser.json.textures){let L=!1;for(const f of x.parser.json.textures){if(f!=null&&f.extensions){const w=f?.extensions[I];if(w!=null&&w.guid&&w.guid===D.guid){L=!0;break}}_++}if(L){let f=await S.getDependency("texture",_);return f&&M.assignLODInformation(a.url,f,i,e,void 0,void 0),s&&console.log('change "'+t.name+'" \u2192 "'+f.name+'"',h,_,f,u),t instanceof k&&(f=this.copySettings(t,f)),f&&(f.guid=D.guid),y(f)}else v&&console.warn("Could not find texture with guid",D.guid)}if(_=0,x.parser.json.meshes){let L=!1;for(const f of x.parser.json.meshes){if(f!=null&&f.extensions){const w=f?.extensions[I];if(w!=null&&w.guid&&w.guid===D.guid){L=!0;break}}_++}if(L){const f=await S.getDependency("mesh",_),w=D;if(s&&console.log(`Loaded Mesh "${f.name}"`,h,_,f,u),f.isMesh===!0){const E=f.geometry;return M.assignLODInformation(a.url,E,i,e,void 0,w.density),y(E)}else{const E=new Array;for(let C=0;C<f.children.length;C++){const W=f.children[C];if(W instanceof U){const j=W.geometry;M.assignLODInformation(a.url,j,i,e,C,w.density),E.push(j)}}return y(E)}}}return y(null)});return this.previouslyLoaded.set(u,P),await P}else if(t instanceof k){s&&console.log("Load texture from uri: "+h);const u=await new ge().loadAsync(h);return u?(u.guid=l.guid,u.flipY=!1,u.needsUpdate=!0,u.colorSpace=t.colorSpace,s&&console.log(l,u)):v&&console.warn("failed loading",h),u}}else v&&console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${t.name}`,t.type);return null}static assignLODInformation(t,e,r,n,o,s){if(!e)return;e.userData||(e.userData={});const a=new ve(t,r,n,o,s);e.userData.LODS=a,e.userData.LOD=n}static getAssignedLODInformation(t){var e;return((e=t?.userData)==null?void 0:e.LODS)||null}static copySettings(t,e){return this._copiedTextures.get(t)||(e=e.clone(),this._copiedTextures.set(t,e),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.generateMipmaps=t.generateMipmaps,e)}};let O=M;c(O,"registerTexture",(t,e,r,n)=>{v&&console.log("> Progressive: register texture",r,e.name,e.uuid,e,n),e.source&&(e.source[J]=n);const o=n.guid;M.assignLODInformation(t,e,o,0,0,void 0),M.lodInfos.set(o,n),M.lowresCache.set(o,e)}),c(O,"registerMesh",(t,e,r,n,o,s)=>{var a;v&&console.log("> Progressive: register mesh",o,r.name,s,r.uuid,r);const i=r.geometry;i.userData||(i.userData={}),M.assignLODInformation(t,i,e,n,o,s.density),M.lodInfos.set(e,s);let l=M.lowresCache.get(e);l?l.push(r.geometry):l=[r.geometry],M.lowresCache.set(e,l),n>0&&!re(r)&&se(r,i);for(const d of R)(a=d.onRegisteredNewMesh)==null||a.call(d,r,s)}),c(O,"lodInfos",new Map),c(O,"previouslyLoaded",new Map),c(O,"lowresCache",new Map),c(O,"_copiedTextures",new Map);class ve{constructor(e,r,n,o,s){c(this,"url"),c(this,"key"),c(this,"level"),c(this,"index"),c(this,"density"),this.url=e,this.key=r,this.level=n,o!=null&&(this.index=o),s!=null&&(this.density=s)}}const Z=Y("debugprogressive"),Me=Y("noprogressive"),oe=Symbol("Needle:LODSManager"),T=class{constructor(t){c(this,"renderer"),c(this,"projectionScreenMatrix",new ee),c(this,"cameraFrustrum",new me),c(this,"targetTriangleDensity",2e5),c(this,"updateInterval",0),c(this,"pause",!1),c(this,"_frame",0),c(this,"_originalRender"),c(this,"_sphere",new pe),c(this,"_tempBox",new te),c(this,"_tempBox2",new te),c(this,"tempMatrix",new ee),c(this,"_tempWorldPosition",new B),c(this,"_tempBoxSize",new B),c(this,"_tempBox2Size",new B),this.renderer=t}static getObjectLODState(t){var e;return(e=t.userData)==null?void 0:e.LOD_state}static addPlugin(t){R.push(t)}static removePlugin(t){const e=R.indexOf(t);e>=0&&R.splice(e,1)}static get(t){return t[oe]?t[oe]:new T(t)}get plugins(){return R}enable(){if(this._originalRender)return;let t=0;this._originalRender=this.renderer.render;const e=this;K(this.renderer),this.renderer.render=function(r,n){e.renderer.getRenderTarget()==null&&(t=0,e._frame+=1);const o=e._frame,s=t++;e.onBeforeRender(r,n,s,o),e._originalRender.call(this,r,n),e.onAfterRender(r,n,s,o)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(t,e,r,n){}onAfterRender(t,e,r,n){var o,s;if(this.pause)return;const a=this.renderer.renderLists.get(t,0),i=a.opaque;let l=!0;if(i.length===1){const d=i[0].material;(d.name==="EffectMaterial"||d.name==="CopyShader")&&(l=!1)}if(l){if(Me||this.updateInterval>0&&n%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const d=this.targetTriangleDensity;for(const u of i){if(u.material&&(((o=u.geometry)==null?void 0:o.type)==="BoxGeometry"||((s=u.geometry)==null?void 0:s.type)==="BufferGeometry")&&(u.material.name==="SphericalGaussianBlur"||u.material.name=="BackgroundCubeMaterial"||u.material.name==="CubemapFromEquirect"||u.material.name==="EquirectangularToCubeUV")){Z&&(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(u.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",u,u.material.name,u.material.type)));continue}switch(u.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const p=u.object;(p instanceof U||p.isMesh)&&this.updateLODs(t,e,p,d)}const h=a.transparent;for(const u of h){const p=u.object;(p instanceof U||p.isMesh)&&this.updateLODs(t,e,p,d)}}}updateLODs(t,e,r,n){var o,s;for(const d of R)(o=d.onBeforeUpdateLOD)==null||o.call(d,this.renderer,t,e,r);let a=r.userData.LOD_state;a||(a=new Oe,r.userData.LOD_state=a);let i=this.calculateLodLevel(e,r,a,n);i=Math.round(i),i>=0&&this.loadProgressiveMeshes(r,i);let l=0;if(r.material){const d=r["DEBUG:LOD"];if(d!=null&&(l=d),Array.isArray(r.material))for(const h of r.material)this.loadProgressiveTextures(h,l);else this.loadProgressiveTextures(r.material,l)}for(const d of R)(s=d.onAfterUpdatedLOD)==null||s.call(d,this.renderer,t,e,r,i);a.lastLodLevel=i}loadProgressiveTextures(t,e){return t&&t.userData&&t.userData.LOD!==e?(t.userData.LOD=e,O.assignTextureLOD(t,e)):Promise.resolve(null)}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);if(t.userData||(t.userData={}),t.userData.LOD!==e){t.userData.LOD=e;const r=t.geometry;return O.assignMeshLOD(t,e).then(n=>(n&&t.userData.LOD==e&&r!=t.geometry,n))}return Promise.resolve(null)}static isInside(t,e){const r=t.min,n=t.max,o=(r.x+n.x)*.5,s=(r.y+n.y)*.5;return this._tempPtInside.set(o,s,r.z).applyMatrix4(e).z<0}calculateLodLevel(t,e,r,n){var o;if(!e)return-1;let s=10+1;if(t){if(Z&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=O.getMeshLODInformation(e.geometry),i=a?.lods;if(!i||i.length<=0)return 0;if(!((o=this.cameraFrustrum)!=null&&o.intersectsObject(e)))return 99;const l=e.geometry.boundingBox;if(l&&t.isPerspectiveCamera){const d=t;if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const g=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(g))return 0}if(this._tempBox.copy(l),this._tempBox.applyMatrix4(e.matrixWorld),T.isInside(this._tempBox,this.projectionScreenMatrix))return 0;if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&d.fov>70){const g=this._tempBox.min,m=this._tempBox.max;let b=g.x,x=g.y,S=m.x,_=m.y;const L=2,f=1.5,w=(g.x+m.x)*.5,E=(g.y+m.y)*.5;b=(b-w)*L+w,x=(x-E)*L+E,S=(S-w)*L+w,_=(_-E)*L+E;const C=b<0&&S>0?0:Math.min(Math.abs(g.x),Math.abs(m.x)),W=x<0&&_>0?0:Math.min(Math.abs(g.y),Math.abs(m.y)),j=Math.max(C,W);r.lastCentrality=(f-j)*(f-j)*(f-j)}else r.lastCentrality=1;const h=this._tempBox.getSize(this._tempBoxSize);h.multiplyScalar(.5),screen.availHeight>0&&h.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),h.x*=d.aspect;const u=t.matrixWorldInverse,p=this._tempBox2;p.copy(l),p.applyMatrix4(e.matrixWorld),p.applyMatrix4(u);const D=p.getSize(this._tempBox2Size),P=Math.max(D.x,D.y);if(Math.max(h.x,h.y)!=0&&P!=0&&(h.z=D.z/Math.max(D.x,D.y)*Math.max(h.x,h.y)),r.lastScreenCoverage=Math.max(h.x,h.y,h.z),r.lastScreenspaceVolume.copy(h),r.lastScreenCoverage*=r.lastCentrality,Z&&T.debugDrawLine){const g=this.tempMatrix.copy(this.projectionScreenMatrix);g.invert();const m=T.corner0,b=T.corner1,x=T.corner2,S=T.corner3;m.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=m.x,x.copy(this._tempBox.max),x.y=m.y,S.copy(this._tempBox.max);const _=(m.z+S.z)*.5;m.z=b.z=x.z=S.z=_,m.applyMatrix4(g),b.applyMatrix4(g),x.applyMatrix4(g),S.applyMatrix4(g),T.debugDrawLine(m,b,255),T.debugDrawLine(m,x,255),T.debugDrawLine(b,S,255),T.debugDrawLine(x,S,255)}let y=999;if(i&&r.lastScreenCoverage>0){for(let g=0;g<i.length;g++)if(i[g].density/r.lastScreenCoverage<n){y=g;break}}y<s&&(s=y)}}return s}};let A=T;c(A,"debugDrawLine"),c(A,"corner0",new B),c(A,"corner1",new B),c(A,"corner2",new B),c(A,"corner3",new B),c(A,"_tempPtInside",new B);class Oe{constructor(){c(this,"lastLodLevel",0),c(this,"lastScreenCoverage",0),c(this,"lastScreenspaceVolume",new B),c(this,"lastCentrality",0)}}const ie=Symbol("NEEDLE_mesh_lod"),q=Symbol("NEEDLE_texture_lod");function ae(t){if(!t)return null;let e=null,r=null;for(let n=t;n!=null;n=Object.getPrototypeOf(n)){const o=Object.getOwnPropertySymbols(n),s=o.find(i=>i.toString()=="Symbol(renderer)"),a=o.find(i=>i.toString()=="Symbol(scene)");!e&&s!=null&&(e=t[s].threeRenderer),!r&&a!=null&&(r=t[a])}if(e){console.log("Adding Needle LODs to modelviewer");const n=A.get(e);if(A.addPlugin(new we(t)),n.enable(),r){const o=r.camera||r.traverse(s=>s.type=="PerspectiveCamera")[0];o&&e.render(r,o)}return()=>{n.disable()}}return null}class we{constructor(e){c(this,"modelviewer"),c(this,"_didWarnAboutMissingUrl",!1),this.modelviewer=e}onBeforeUpdateLOD(e,r,n,o){this.tryParseMeshLOD(r,o),this.tryParseTextureLOD(r,o)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,r){if(r[q]==!0)return;r[q]=!0;const n=this.tryGetCurrentGLTF(e),o=this.getUrl();if(o&&n&&r.material){let s=function(i){var l,d,h;if(i[q]==!0)return;i[q]=!0,i.userData&&(i.userData.LOD=-1);const u=Object.keys(i);for(let p=0;p<u.length;p++){const D=u[p],P=i[D];if(P?.isTexture===!0){const y=(d=(l=P.userData)==null?void 0:l.associations)==null?void 0:d.textures,g=n.parser.json.textures[y];if(!g){console.warn("Texture data not found for texture index "+y);continue}if((h=g?.extensions)!=null&&h[I]){const m=g.extensions[I];m&&o&&O.registerTexture(o,P,m.lods.length,m)}}}};const a=r.material;if(Array.isArray(a))for(const i of a)s(i);else s(a)}}tryParseMeshLOD(e,r){var n,o;if(r[ie]==!0)return;r[ie]=!0;const s=this.getUrl();if(!s)return;const a=(o=(n=r.userData)==null?void 0:n.gltfExtensions)==null?void 0:o[I];if(a&&s){const i=r.uuid;O.registerMesh(s,i,r,0,a.lods.length,a)}}}function be(t,e,r,n){K(e),H(r),r.register(s=>new O(s,t));const o=A.get(e);return n?.enableLODsManager!==!1&&o.enable(),o}document.addEventListener("DOMContentLoaded",()=>{ae(document.querySelector("model-viewer"))});export{I as EXTENSION_NAME,A as LODsManager,O as NEEDLE_progressive,H as addDracoAndKTX2Loaders,K as createLoaders,re as getRaycastMesh,ae as patchModelViewer,De as setDracoDecoderLocation,xe as setKTX2TranscoderLocation,se as setRaycastMesh,be as useNeedleProgressive};
|
package/gltf-progressive.umd.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var ae=Object.defineProperty;var le=(a,e,t)=>e in a?ae(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var u=(a,e,t)=>(le(a,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ce=require("three/examples/jsm/libs/meshopt_decoder.module.js"),ue=require("three/examples/jsm/loaders/DRACOLoader.js"),fe=require("three/examples/jsm/loaders/KTX2Loader.js"),g=require("three"),de=require("three/examples/jsm/loaders/GLTFLoader.js");let q="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",J="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(q+"draco_decoder.js",{method:"head"}).catch(a=>{q="./include/draco/",J="./include/ktx2/"});function ge(a){q=a}function he(a){J=a}let N,Y,U;function Q(a){N||(N=new ue.DRACOLoader,N.setDecoderPath(q),N.setDecoderConfig({type:"js"})),U||(U=new fe.KTX2Loader,U.setTranscoderPath(J)),Y||(Y=ce.MeshoptDecoder),a?U.detectSupport(a):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function Z(a){a.dracoLoader||a.setDRACOLoader(N),a.ktx2Loader||a.setKTX2Loader(U),a.meshoptDecoder||a.setMeshoptDecoder(Y)}function j(a){const t=new URL(window.location.href).searchParams.get(a);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function pe(a,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||a===void 0)return e;const t=a.lastIndexOf("/");if(t>=0){const r=a.substring(0,t+1);for(;r.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return r+e}return e}function se(a){var e;return((e=a.userData)==null?void 0:e["needle:raycast-mesh"])instanceof g.BufferGeometry?a.userData["needle:raycast-mesh"]:null}function ie(a,e){(a.type==="Mesh"||a.type==="SkinnedMesh")&&(a.userData||(a.userData={}),a.userData["needle:raycast-mesh"]=e)}const
|
|
1
|
+
"use strict";var ae=Object.defineProperty;var le=(a,e,t)=>e in a?ae(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var u=(a,e,t)=>(le(a,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ce=require("three/examples/jsm/libs/meshopt_decoder.module.js"),ue=require("three/examples/jsm/loaders/DRACOLoader.js"),fe=require("three/examples/jsm/loaders/KTX2Loader.js"),g=require("three"),de=require("three/examples/jsm/loaders/GLTFLoader.js");let q="https://www.gstatic.com/draco/versioned/decoders/1.4.1/",J="https://www.gstatic.com/basis-universal/versioned/2021-04-15-ba1c3e4/";fetch(q+"draco_decoder.js",{method:"head"}).catch(a=>{q="./include/draco/",J="./include/ktx2/"});function ge(a){q=a}function he(a){J=a}let N,Y,U;function Q(a){N||(N=new ue.DRACOLoader,N.setDecoderPath(q),N.setDecoderConfig({type:"js"})),U||(U=new fe.KTX2Loader,U.setTranscoderPath(J)),Y||(Y=ce.MeshoptDecoder),a?U.detectSupport(a):console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures will probably fail")}function Z(a){a.dracoLoader||a.setDRACOLoader(N),a.ktx2Loader||a.setKTX2Loader(U),a.meshoptDecoder||a.setMeshoptDecoder(Y)}function j(a){const t=new URL(window.location.href).searchParams.get(a);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function pe(a,e){if(e===void 0||e.startsWith("./")||e.startsWith("http")||a===void 0)return e;const t=a.lastIndexOf("/");if(t>=0){const r=a.substring(0,t+1);for(;r.endsWith("/")&&e.startsWith("/");)e=e.substring(1);return r+e}return e}function se(a){var e;return((e=a.userData)==null?void 0:e["needle:raycast-mesh"])instanceof g.BufferGeometry?a.userData["needle:raycast-mesh"]:null}function ie(a,e){(a.type==="Mesh"||a.type==="SkinnedMesh")&&(a.userData||(a.userData={}),a.userData["needle:raycast-mesh"]=e)}const G=new Array,R="NEEDLE_progressive",T=j("debugprogressive"),$=Symbol("needle-progressive-texture"),z=new Map,H=new Set;if(T){let a=function(){e+=1,console.log("Toggle LOD level",e,z),z.forEach((i,n)=>{for(const s of i.keys){const o=n[s];if(o.isBufferGeometry===!0){const l=v.getMeshLODInformation(o),h=l?Math.min(e,l.lods.length):0;n["DEBUG:LOD"]=e,v.assignMeshLOD(n,h),l&&(t=Math.max(t,l.lods.length-1))}else if(n.isMaterial===!0){n["DEBUG:LOD"]=e,v.assignTextureLOD(n,e);break}}}),e>=t&&(e=-1)},e=-1,t=2,r=!1;window.addEventListener("keyup",i=>{i.key==="p"&&a(),i.key==="w"&&(r=!r,H&&H.forEach(n=>{n.name!="BackgroundCubeMaterial"&&"wireframe"in n&&(n.wireframe=r)}))})}function ee(a,e,t){var i;if(!T)return;z.has(a)||z.set(a,{keys:[],sourceId:t});const r=z.get(a);((i=r==null?void 0:r.keys)==null?void 0:i.includes(e))==!1&&r.keys.push(e)}const O=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 R}static getMeshLODInformation(e){const t=this.getAssignedLODInformation(e);return t!=null&&t.key?this.lodInfos.get(t.key):null}static hasLODLevelAvailable(e,t){var n;if(e.isMaterial===!0){for(const s of Object.keys(e)){const o=e[s];if(o.isTexture&&this.hasLODLevelAvailable(o,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&&(n=r==null?void 0:r.userData)!=null&&n.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 g.Mesh||e.isMesh===!0){const i=e.geometry,n=this.getAssignedLODInformation(i);if(!n)return Promise.resolve(null);for(const s of G)(r=s.onBeforeGetLODMesh)==null||r.call(s,e,t);return e["LOD:requested level"]=t,O.getOrLoadLOD(i,t).then(s=>{if(e["LOD:requested level"]===t){if(delete e["LOD:requested level"],Array.isArray(s)){const o=n.index||0;s=s[o]}s&&i!=s&&s instanceof g.BufferGeometry&&(e.geometry=s,T&&ee(e,"geometry",n.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 g.Material||e.isMaterial===!0){const r=e,i=[],n=new Array;if(T&&H.add(r),r.uniforms&&r.isRawShaderMaterial||r.isShaderMaterial===!0){const s=r;for(const o of Object.keys(s.uniforms)){const l=s.uniforms[o].value;if((l==null?void 0:l.isTexture)===!0){const h=this.assignTextureLODForSlot(l,t,r,o);i.push(h),n.push(o)}}}else for(const s of Object.keys(r)){const o=r[s];if((o==null?void 0:o.isTexture)===!0){const l=this.assignTextureLODForSlot(o,t,r,s);i.push(l),n.push(s)}}return Promise.all(i).then(s=>{const o=new Array;for(let l=0;l<s.length;l++){const h=s[l],f=n[l];h&&h.isTexture===!0?o.push({material:r,slot:f,texture:h,level:t}):o.push({material:r,slot:f,texture:null,level:t})}return o})}if(e instanceof g.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):O.getOrLoadLOD(e,t).then(n=>{if(Array.isArray(n))return null;if((n==null?void 0:n.isTexture)===!0){if(n!=e&&(r&&i&&(r[i]=n),T&&i&&r)){const s=this.getAssignedLODInformation(e);s&&ee(r,i,s.url)}return n}else T=="verbose"&&console.warn("No LOD found for",e,t);return null}).catch(n=>(console.error("Error loading LOD",e,n),null))}afterRoot(e){var t,r;return T&&console.log("AFTER",this.url,e),(t=this.parser.json.textures)==null||t.forEach((i,n)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[R];if(s){let o=!1;for(const l of this.parser.associations.keys())l.isTexture===!0&&this.parser.associations.get(l).textures===n&&(o=!0,O.registerTexture(this.url,l,n,s));o||this.parser.getDependency("texture",n).then(l=>{l&&O.registerTexture(this.url,l,n,s)})}}}),(r=this.parser.json.meshes)==null||r.forEach((i,n)=>{if(i!=null&&i.extensions){const s=i==null?void 0:i.extensions[R];if(s&&s.lods){for(const o of this.parser.associations.keys())if(o.isMesh){const l=this.parser.associations.get(o);l.meshes===n&&O.registerMesh(this.url,s.guid,o,s.lods.length,l.primitives,s)}}}}),null}static async getOrLoadLOD(e,t){var o,l,h;const r=T=="verbose",i=e.userData.LODS;if(!i)return null;const n=i==null?void 0:i.key;let s;if(e.isTexture===!0){const f=e;f.source&&f.source[$]&&(s=f.source[$])}if(s||(s=O.lodInfos.get(n)),s){if(t>0){let c=!1;const p=Array.isArray(s.lods);if(p&&t>=s.lods.length?c=!0:p||(c=!0),c)return this.lowresCache.get(n)}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 y=pe(i.url,f);if(y.endsWith(".glb")||y.endsWith(".gltf")){if(!s.guid)return console.warn("missing pointer for glb/gltf texture",s),null;const c=y+"_"+s.guid,p=this.previouslyLoaded.get(c);if(p!==void 0){r&&console.log(`LOD ${t} was already loading/loaded: ${c}`);let M=await p.catch(F=>(console.error(`Error loading LOD ${t} from ${y}
|
|
2
2
|
`,F),null)),k=!1;if(M==null||(M instanceof g.Texture&&e instanceof g.Texture?(o=M.image)!=null&&o.data||(l=M.source)!=null&&l.data?M=this.copySettings(e,M):(k=!0,this.previouslyLoaded.delete(c)):M instanceof g.BufferGeometry&&e instanceof g.BufferGeometry&&((h=M.attributes.position)!=null&&h.array||(k=!0,this.previouslyLoaded.delete(c)))),!k)return M}const D=s,b=new Promise(async(M,k)=>{const F=new de.GLTFLoader;Z(F),T&&(await new Promise(L=>setTimeout(L,1e3)),r&&console.warn("Start loading (delayed) "+y,D.guid));let x=y;if(D&&Array.isArray(D.lods)){const L=D.lods[t];L.hash&&(x+="?v="+L.hash)}const m=await F.loadAsync(x).catch(L=>(console.error(`Error loading LOD ${t} from ${y}
|
|
3
|
-
`,L),null));if(!m)return null;const P=m.parser;r&&console.log("Loading finished "+y,D.guid);let w=0;if(m.parser.json.textures){let L=!1;for(const d of m.parser.json.textures){if(d!=null&&d.extensions){const S=d==null?void 0:d.extensions[R];if(S!=null&&S.guid&&S.guid===D.guid){L=!0;break}}w++}if(L){let d=await P.getDependency("texture",w);return d&&O.assignLODInformation(i.url,d,n,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+d.name+'"',y,w,d,c),e instanceof g.Texture&&(d=this.copySettings(e,d)),d&&(d.guid=D.guid),M(d)}else T&&console.warn("Could not find texture with guid",D.guid)}if(w=0,m.parser.json.meshes){let L=!1;for(const d of m.parser.json.meshes){if(d!=null&&d.extensions){const S=d==null?void 0:d.extensions[R];if(S!=null&&S.guid&&S.guid===D.guid){L=!0;break}}w++}if(L){const d=await P.getDependency("mesh",w),S=D;if(r&&console.log(`Loaded Mesh "${d.name}"`,y,w,d,c),d.isMesh===!0){const B=d.geometry;return O.assignLODInformation(i.url,B,n,t,void 0,S.density),M(B)}else{const B=new Array;for(let E=0;E<d.children.length;E++){const G=d.children[E];if(G instanceof g.Mesh){const W=G.geometry;O.assignLODInformation(i.url,W,n,t,E,S.density),B.push(W)}}return M(B)}}}return M(null)});return this.previouslyLoaded.set(c,b),await b}else if(e instanceof g.Texture){r&&console.log("Load texture from uri: "+y);const p=await new g.TextureLoader().loadAsync(y);return p?(p.guid=s.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=e.colorSpace,r&&console.log(s,p)):T&&console.warn("failed loading",y),p}}else T&&console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`,e.type);return null}static assignLODInformation(e,t,r,i,n,s){if(!t)return;t.userData||(t.userData={});const o=new ye(e,r,i,n,s);t.userData.LODS=o,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.magFilter=e.magFilter,t.minFilter=e.minFilter,t.wrapS=e.wrapS,t.wrapT=e.wrapT,t.flipY=e.flipY,t.anisotropy=e.anisotropy,t.generateMipmaps=e.generateMipmaps,t)}};let v=O;u(v,"registerTexture",(e,t,r,i)=>{T&&console.log("> Progressive: register texture",r,t.name,t.uuid,t,i),t.source&&(t.source[$]=i);const n=i.guid;O.assignLODInformation(e,t,n,0,0,void 0),O.lodInfos.set(n,i),O.lowresCache.set(n,t)}),u(v,"registerMesh",(e,t,r,i,n,s)=>{var h;T&&console.log("> Progressive: register mesh",n,r.name,s,r.uuid,r);const o=r.geometry;o.userData||(o.userData={}),O.assignLODInformation(e,o,t,i,n,s.density),O.lodInfos.set(t,s);let l=O.lowresCache.get(t);l?l.push(r.geometry):l=[r.geometry],O.lowresCache.set(t,l),i>0&&!se(r)&&ie(r,o);for(const f of I)(h=f.onRegisteredNewMesh)==null||h.call(f,r,s)}),u(v,"lodInfos",new Map),u(v,"previouslyLoaded",new Map),u(v,"lowresCache",new Map),u(v,"_copiedTextures",new Map);class ye{constructor(e,t,r,i,n){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),n!=null&&(this.density=n)}}const K=j("debugprogressive"),me=j("noprogressive"),te=Symbol("Needle:LODSManager"),A=class{constructor(e){u(this,"renderer");u(this,"projectionScreenMatrix",new g.Matrix4);u(this,"cameraFrustrum",new g.Frustum);u(this,"targetTriangleDensity",2e5);u(this,"updateInterval",0);u(this,"pause",!1);u(this,"_frame",0);u(this,"_originalRender");u(this,"_sphere",new g.Sphere);u(this,"_tempBox",new g.Box3);u(this,"_tempBox2",new g.Box3);u(this,"tempMatrix",new g.Matrix4);u(this,"_tempWorldPosition",new g.Vector3);u(this,"_tempBoxSize",new g.Vector3);u(this,"_tempBox2Size",new g.Vector3);this.renderer=e}static getObjectLODState(e){var t;return(t=e.userData)==null?void 0:t.LOD_state}static addPlugin(e){I.push(e)}static removePlugin(e){const t=I.indexOf(e);t>=0&&I.splice(t,1)}static get(e){return e[te]?e[te]:new A(e)}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;Q(this.renderer),this.renderer.render=function(r,i){t.renderer.getRenderTarget()==null&&(e=0,t._frame+=1);const s=t._frame,o=e++;t.onBeforeRender(r,i,o,s),t._originalRender.call(this,r,i),t.onAfterRender(r,i,o,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,i){}onAfterRender(e,t,r,i){var l,h;if(this.pause)return;const n=this.renderer.renderLists.get(e,0),s=n.opaque;let o=!0;if(s.length===1){const f=s[0].material;(f.name==="EffectMaterial"||f.name==="CopyShader")&&(o=!1)}if(o){if(me||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const f=this.targetTriangleDensity;for(const c of s){if(c.material&&(((l=c.geometry)==null?void 0:l.type)==="BoxGeometry"||((h=c.geometry)==null?void 0:h.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){K&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}switch(c.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const p=c.object;(p instanceof g.Mesh||p.isMesh)&&this.updateLODs(e,t,p,f)}const y=n.transparent;for(const c of y){const p=c.object;(p instanceof g.Mesh||p.isMesh)&&this.updateLODs(e,t,p,f)}}}updateLODs(e,t,r,i){var l,h;for(const f of I)(l=f.onBeforeUpdateLOD)==null||l.call(f,this.renderer,e,t,r);let n=r.userData.LOD_state;n||(n=new Le,r.userData.LOD_state=n);let s=this.calculateLodLevel(t,r,n,i);s=Math.round(s),s>=0&&this.loadProgressiveMeshes(r,s);let o=0;if(r.material){const f=r["DEBUG:LOD"];if(f!=null&&(o=f),Array.isArray(r.material))for(const y of r.material)this.loadProgressiveTextures(y,o);else this.loadProgressiveTextures(r.material,o)}for(const f of I)(h=f.onAfterUpdatedLOD)==null||h.call(f,this.renderer,e,t,r,s);n.lastLodLevel=s}loadProgressiveTextures(e,t){return e&&e.userData&&e.userData.LOD!==t?(e.userData.LOD=t,v.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 v.assignMeshLOD(e,t).then(i=>(i&&e.userData.LOD==t&&r!=e.geometry,i))}return Promise.resolve(null)}static isInside(e,t){const r=e.min,i=e.max,n=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(n,s,r.z).applyMatrix4(t).z<0}calculateLodLevel(e,t,r,i){var o;if(!t)return-1;let s=10+1;if(e){if(K&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const l=v.getMeshLODInformation(t.geometry),h=l==null?void 0:l.lods;if(!h||h.length<=0)return 0;if(!((o=this.cameraFrustrum)!=null&&o.intersectsObject(t)))return 99;const f=t.geometry.boundingBox;if(f&&e.isPerspectiveCamera){const y=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 x=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(x))return 0}if(this._tempBox.copy(f),this._tempBox.applyMatrix4(t.matrixWorld),A.isInside(this._tempBox,this.projectionScreenMatrix))return 0;if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.fov>70){const x=this._tempBox.min,m=this._tempBox.max;let P=x.x,w=x.y,L=m.x,d=m.y;const S=2,B=1.5,E=(x.x+m.x)*.5,G=(x.y+m.y)*.5;P=(P-E)*S+E,w=(w-G)*S+G,L=(L-E)*S+E,d=(d-G)*S+G;const W=P<0&&L>0?0:Math.min(Math.abs(x.x),Math.abs(m.x)),oe=w<0&&d>0?0:Math.min(Math.abs(x.y),Math.abs(m.y)),X=Math.max(W,oe);r.lastCentrality=(B-X)*(B-X)*(B-X)}else r.lastCentrality=1;const c=this._tempBox.getSize(this._tempBoxSize);c.multiplyScalar(.5),screen.availHeight>0&&c.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),c.x*=y.aspect;const p=e.matrixWorldInverse,D=this._tempBox2;D.copy(f),D.applyMatrix4(t.matrixWorld),D.applyMatrix4(p);const b=D.getSize(this._tempBox2Size),C=Math.max(b.x,b.y);if(Math.max(c.x,c.y)!=0&&C!=0&&(c.z=b.z/Math.max(b.x,b.y)*Math.max(c.x,c.y)),r.lastScreenCoverage=Math.max(c.x,c.y,c.z),r.lastScreenspaceVolume.copy(c),r.lastScreenCoverage*=r.lastCentrality,K&&A.debugDrawLine){const x=this.tempMatrix.copy(this.projectionScreenMatrix);x.invert();const m=A.corner0,P=A.corner1,w=A.corner2,L=A.corner3;m.copy(this._tempBox.min),P.copy(this._tempBox.max),P.x=m.x,w.copy(this._tempBox.max),w.y=m.y,L.copy(this._tempBox.max);const d=(m.z+L.z)*.5;m.z=P.z=w.z=L.z=d,m.applyMatrix4(x),P.applyMatrix4(x),w.applyMatrix4(x),L.applyMatrix4(x),A.debugDrawLine(m,P,255),A.debugDrawLine(m,w,255),A.debugDrawLine(P,L,255),A.debugDrawLine(w,L,255)}let k=999;if(h&&r.lastScreenCoverage>0){for(let x=0;x<h.length;x++)if(h[x].density/r.lastScreenCoverage<i){k=x;break}}k<s&&(s=k)}}return s}};let _=A;u(_,"debugDrawLine"),u(_,"corner0",new g.Vector3),u(_,"corner1",new g.Vector3),u(_,"corner2",new g.Vector3),u(_,"corner3",new g.Vector3),u(_,"_tempPtInside",new g.Vector3);class Le{constructor(){u(this,"lastLodLevel",0);u(this,"lastScreenCoverage",0);u(this,"lastScreenspaceVolume",new g.Vector3);u(this,"lastCentrality",0)}}const re=Symbol("NEEDLE_mesh_lod"),V=Symbol("NEEDLE_texture_lod");function ne(a){if(!a)return null;let e=null,t=null;for(let r=a;r!=null;r=Object.getPrototypeOf(r)){const i=Object.getOwnPropertySymbols(r),n=i.find(o=>o.toString()=="Symbol(renderer)"),s=i.find(o=>o.toString()=="Symbol(scene)");!e&&n!=null&&(e=a[n].threeRenderer),!t&&s!=null&&(t=a[s])}if(e){console.log("Adding Needle LODs to modelviewer");const r=_.get(e);if(_.addPlugin(new De(a)),r.enable(),t){const i=t.camera||t.traverse(n=>n.type=="PerspectiveCamera")[0];i&&e.render(t,i)}return()=>{r.disable()}}return null}class De{constructor(e){u(this,"modelviewer");u(this,"_didWarnAboutMissingUrl",!1);this.modelviewer=e}onBeforeUpdateLOD(e,t,r,i){this.tryParseMeshLOD(t,i),this.tryParseTextureLOD(t,i)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[V]==!0)return;t[V]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let n=function(o){var h,f,y;if(o[V]==!0)return;o[V]=!0,o.userData&&(o.userData.LOD=-1);const l=Object.keys(o);for(let c=0;c<l.length;c++){const p=l[c],D=o[p];if((D==null?void 0:D.isTexture)===!0){const b=(f=(h=D.userData)==null?void 0:h.associations)==null?void 0:f.textures,C=r.parser.json.textures[b];if(!C){console.warn("Texture data not found for texture index "+b);continue}if((y=C==null?void 0:C.extensions)!=null&&y[R]){const M=C.extensions[R];M&&i&&v.registerTexture(i,D,M.lods.length,M)}}}};const s=t.material;if(Array.isArray(s))for(const o of s)n(o);else n(s)}}tryParseMeshLOD(e,t){var n,s;if(t[re]==!0)return;t[re]=!0;const r=this.getUrl();if(!r)return;const i=(s=(n=t.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[R];if(i&&r){const o=t.uuid;v.registerMesh(r,o,t,0,i.lods.length,i)}}}function xe(a,e,t,r){Q(e),Z(t),t.register(n=>new v(n,a));const i=_.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}document.addEventListener("DOMContentLoaded",()=>{ne(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=R;exports.LODsManager=_;exports.NEEDLE_progressive=v;exports.addDracoAndKTX2Loaders=Z;exports.createLoaders=Q;exports.getRaycastMesh=se;exports.patchModelViewer=ne;exports.setDracoDecoderLocation=ge;exports.setKTX2TranscoderLocation=he;exports.setRaycastMesh=ie;exports.useNeedleProgressive=xe;
|
|
3
|
+
`,L),null));if(!m)return null;const P=m.parser;r&&console.log("Loading finished "+y,D.guid);let w=0;if(m.parser.json.textures){let L=!1;for(const d of m.parser.json.textures){if(d!=null&&d.extensions){const S=d==null?void 0:d.extensions[R];if(S!=null&&S.guid&&S.guid===D.guid){L=!0;break}}w++}if(L){let d=await P.getDependency("texture",w);return d&&O.assignLODInformation(i.url,d,n,t,void 0,void 0),r&&console.log('change "'+e.name+'" → "'+d.name+'"',y,w,d,c),e instanceof g.Texture&&(d=this.copySettings(e,d)),d&&(d.guid=D.guid),M(d)}else T&&console.warn("Could not find texture with guid",D.guid)}if(w=0,m.parser.json.meshes){let L=!1;for(const d of m.parser.json.meshes){if(d!=null&&d.extensions){const S=d==null?void 0:d.extensions[R];if(S!=null&&S.guid&&S.guid===D.guid){L=!0;break}}w++}if(L){const d=await P.getDependency("mesh",w),S=D;if(r&&console.log(`Loaded Mesh "${d.name}"`,y,w,d,c),d.isMesh===!0){const B=d.geometry;return O.assignLODInformation(i.url,B,n,t,void 0,S.density),M(B)}else{const B=new Array;for(let E=0;E<d.children.length;E++){const I=d.children[E];if(I instanceof g.Mesh){const W=I.geometry;O.assignLODInformation(i.url,W,n,t,E,S.density),B.push(W)}}return M(B)}}}return M(null)});return this.previouslyLoaded.set(c,b),await b}else if(e instanceof g.Texture){r&&console.log("Load texture from uri: "+y);const p=await new g.TextureLoader().loadAsync(y);return p?(p.guid=s.guid,p.flipY=!1,p.needsUpdate=!0,p.colorSpace=e.colorSpace,r&&console.log(s,p)):T&&console.warn("failed loading",y),p}}else T&&console.warn(`Can not load LOD ${t}: no LOD info found for "${n}" ${e.name}`,e.type);return null}static assignLODInformation(e,t,r,i,n,s){if(!t)return;t.userData||(t.userData={});const o=new ye(e,r,i,n,s);t.userData.LODS=o,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.magFilter=e.magFilter,t.minFilter=e.minFilter,t.wrapS=e.wrapS,t.wrapT=e.wrapT,t.flipY=e.flipY,t.anisotropy=e.anisotropy,t.generateMipmaps=e.generateMipmaps,t)}};let v=O;u(v,"registerTexture",(e,t,r,i)=>{T&&console.log("> Progressive: register texture",r,t.name,t.uuid,t,i),t.source&&(t.source[$]=i);const n=i.guid;O.assignLODInformation(e,t,n,0,0,void 0),O.lodInfos.set(n,i),O.lowresCache.set(n,t)}),u(v,"registerMesh",(e,t,r,i,n,s)=>{var h;T&&console.log("> Progressive: register mesh",n,r.name,s,r.uuid,r);const o=r.geometry;o.userData||(o.userData={}),O.assignLODInformation(e,o,t,i,n,s.density),O.lodInfos.set(t,s);let l=O.lowresCache.get(t);l?l.push(r.geometry):l=[r.geometry],O.lowresCache.set(t,l),i>0&&!se(r)&&ie(r,o);for(const f of G)(h=f.onRegisteredNewMesh)==null||h.call(f,r,s)}),u(v,"lodInfos",new Map),u(v,"previouslyLoaded",new Map),u(v,"lowresCache",new Map),u(v,"_copiedTextures",new Map);class ye{constructor(e,t,r,i,n){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),n!=null&&(this.density=n)}}const K=j("debugprogressive"),me=j("noprogressive"),te=Symbol("Needle:LODSManager"),A=class{constructor(e){u(this,"renderer");u(this,"projectionScreenMatrix",new g.Matrix4);u(this,"cameraFrustrum",new g.Frustum);u(this,"targetTriangleDensity",2e5);u(this,"updateInterval",0);u(this,"pause",!1);u(this,"_frame",0);u(this,"_originalRender");u(this,"_sphere",new g.Sphere);u(this,"_tempBox",new g.Box3);u(this,"_tempBox2",new g.Box3);u(this,"tempMatrix",new g.Matrix4);u(this,"_tempWorldPosition",new g.Vector3);u(this,"_tempBoxSize",new g.Vector3);u(this,"_tempBox2Size",new g.Vector3);this.renderer=e}static getObjectLODState(e){var t;return(t=e.userData)==null?void 0:t.LOD_state}static addPlugin(e){G.push(e)}static removePlugin(e){const t=G.indexOf(e);t>=0&&G.splice(t,1)}static get(e){return e[te]?e[te]:new A(e)}get plugins(){return G}enable(){if(this._originalRender)return;let e=0;this._originalRender=this.renderer.render;const t=this;Q(this.renderer),this.renderer.render=function(r,i){t.renderer.getRenderTarget()==null&&(e=0,t._frame+=1);const s=t._frame,o=e++;t.onBeforeRender(r,i,o,s),t._originalRender.call(this,r,i),t.onAfterRender(r,i,o,s)}}disable(){this._originalRender&&(this.renderer.render=this._originalRender,this._originalRender=void 0)}onBeforeRender(e,t,r,i){}onAfterRender(e,t,r,i){var l,h;if(this.pause)return;const n=this.renderer.renderLists.get(e,0),s=n.opaque;let o=!0;if(s.length===1){const f=s[0].material;(f.name==="EffectMaterial"||f.name==="CopyShader")&&(o=!1)}if(o){if(me||this.updateInterval>0&&i%this.updateInterval!=0)return;this.projectionScreenMatrix.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this.cameraFrustrum.setFromProjectionMatrix(this.projectionScreenMatrix,this.renderer.coordinateSystem);const f=this.targetTriangleDensity;for(const c of s){if(c.material&&(((l=c.geometry)==null?void 0:l.type)==="BoxGeometry"||((h=c.geometry)==null?void 0:h.type)==="BufferGeometry")&&(c.material.name==="SphericalGaussianBlur"||c.material.name=="BackgroundCubeMaterial"||c.material.name==="CubemapFromEquirect"||c.material.name==="EquirectangularToCubeUV")){K&&(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(c.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",c,c.material.name,c.material.type)));continue}switch(c.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const p=c.object;(p instanceof g.Mesh||p.isMesh)&&this.updateLODs(e,t,p,f)}const y=n.transparent;for(const c of y){const p=c.object;(p instanceof g.Mesh||p.isMesh)&&this.updateLODs(e,t,p,f)}}}updateLODs(e,t,r,i){var l,h;for(const f of G)(l=f.onBeforeUpdateLOD)==null||l.call(f,this.renderer,e,t,r);let n=r.userData.LOD_state;n||(n=new Le,r.userData.LOD_state=n);let s=this.calculateLodLevel(t,r,n,i);s=Math.round(s),s>=0&&this.loadProgressiveMeshes(r,s);let o=0;if(r.material){const f=r["DEBUG:LOD"];if(f!=null&&(o=f),Array.isArray(r.material))for(const y of r.material)this.loadProgressiveTextures(y,o);else this.loadProgressiveTextures(r.material,o)}for(const f of G)(h=f.onAfterUpdatedLOD)==null||h.call(f,this.renderer,e,t,r,s);n.lastLodLevel=s}loadProgressiveTextures(e,t){return e&&e.userData&&e.userData.LOD!==t?(e.userData.LOD=t,v.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 v.assignMeshLOD(e,t).then(i=>(i&&e.userData.LOD==t&&r!=e.geometry,i))}return Promise.resolve(null)}static isInside(e,t){const r=e.min,i=e.max,n=(r.x+i.x)*.5,s=(r.y+i.y)*.5;return this._tempPtInside.set(n,s,r.z).applyMatrix4(t).z<0}calculateLodLevel(e,t,r,i){var o;if(!t)return-1;let s=10+1;if(e){if(K&&t["DEBUG:LOD"]!=null)return t["DEBUG:LOD"];const l=v.getMeshLODInformation(t.geometry),h=l==null?void 0:l.lods;if(!h||h.length<=0)return 0;if(!((o=this.cameraFrustrum)!=null&&o.intersectsObject(t)))return 99;const f=t.geometry.boundingBox;if(f&&e.isPerspectiveCamera){const y=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 x=e.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(x))return 0}if(this._tempBox.copy(f),this._tempBox.applyMatrix4(t.matrixWorld),A.isInside(this._tempBox,this.projectionScreenMatrix))return 0;if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&y.fov>70){const x=this._tempBox.min,m=this._tempBox.max;let P=x.x,w=x.y,L=m.x,d=m.y;const S=2,B=1.5,E=(x.x+m.x)*.5,I=(x.y+m.y)*.5;P=(P-E)*S+E,w=(w-I)*S+I,L=(L-E)*S+E,d=(d-I)*S+I;const W=P<0&&L>0?0:Math.min(Math.abs(x.x),Math.abs(m.x)),oe=w<0&&d>0?0:Math.min(Math.abs(x.y),Math.abs(m.y)),X=Math.max(W,oe);r.lastCentrality=(B-X)*(B-X)*(B-X)}else r.lastCentrality=1;const c=this._tempBox.getSize(this._tempBoxSize);c.multiplyScalar(.5),screen.availHeight>0&&c.multiplyScalar(this.renderer.domElement.clientHeight/screen.availHeight),c.x*=y.aspect;const p=e.matrixWorldInverse,D=this._tempBox2;D.copy(f),D.applyMatrix4(t.matrixWorld),D.applyMatrix4(p);const b=D.getSize(this._tempBox2Size),C=Math.max(b.x,b.y);if(Math.max(c.x,c.y)!=0&&C!=0&&(c.z=b.z/Math.max(b.x,b.y)*Math.max(c.x,c.y)),r.lastScreenCoverage=Math.max(c.x,c.y,c.z),r.lastScreenspaceVolume.copy(c),r.lastScreenCoverage*=r.lastCentrality,K&&A.debugDrawLine){const x=this.tempMatrix.copy(this.projectionScreenMatrix);x.invert();const m=A.corner0,P=A.corner1,w=A.corner2,L=A.corner3;m.copy(this._tempBox.min),P.copy(this._tempBox.max),P.x=m.x,w.copy(this._tempBox.max),w.y=m.y,L.copy(this._tempBox.max);const d=(m.z+L.z)*.5;m.z=P.z=w.z=L.z=d,m.applyMatrix4(x),P.applyMatrix4(x),w.applyMatrix4(x),L.applyMatrix4(x),A.debugDrawLine(m,P,255),A.debugDrawLine(m,w,255),A.debugDrawLine(P,L,255),A.debugDrawLine(w,L,255)}let k=999;if(h&&r.lastScreenCoverage>0){for(let x=0;x<h.length;x++)if(h[x].density/r.lastScreenCoverage<i){k=x;break}}k<s&&(s=k)}}return s}};let _=A;u(_,"debugDrawLine"),u(_,"corner0",new g.Vector3),u(_,"corner1",new g.Vector3),u(_,"corner2",new g.Vector3),u(_,"corner3",new g.Vector3),u(_,"_tempPtInside",new g.Vector3);class Le{constructor(){u(this,"lastLodLevel",0);u(this,"lastScreenCoverage",0);u(this,"lastScreenspaceVolume",new g.Vector3);u(this,"lastCentrality",0)}}const re=Symbol("NEEDLE_mesh_lod"),V=Symbol("NEEDLE_texture_lod");function ne(a){if(!a)return null;let e=null,t=null;for(let r=a;r!=null;r=Object.getPrototypeOf(r)){const i=Object.getOwnPropertySymbols(r),n=i.find(o=>o.toString()=="Symbol(renderer)"),s=i.find(o=>o.toString()=="Symbol(scene)");!e&&n!=null&&(e=a[n].threeRenderer),!t&&s!=null&&(t=a[s])}if(e){console.log("Adding Needle LODs to modelviewer");const r=_.get(e);if(_.addPlugin(new De(a)),r.enable(),t){const i=t.camera||t.traverse(n=>n.type=="PerspectiveCamera")[0];i&&e.render(t,i)}return()=>{r.disable()}}return null}class De{constructor(e){u(this,"modelviewer");u(this,"_didWarnAboutMissingUrl",!1);this.modelviewer=e}onBeforeUpdateLOD(e,t,r,i){this.tryParseMeshLOD(t,i),this.tryParseTextureLOD(t,i)}getUrl(){let e=this.modelviewer.getAttribute("src");return e||(e=this.modelviewer.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",this.modelviewer),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(e){return e._currentGLTF}tryParseTextureLOD(e,t){if(t[V]==!0)return;t[V]=!0;const r=this.tryGetCurrentGLTF(e),i=this.getUrl();if(i&&r&&t.material){let n=function(o){var h,f,y;if(o[V]==!0)return;o[V]=!0,o.userData&&(o.userData.LOD=-1);const l=Object.keys(o);for(let c=0;c<l.length;c++){const p=l[c],D=o[p];if((D==null?void 0:D.isTexture)===!0){const b=(f=(h=D.userData)==null?void 0:h.associations)==null?void 0:f.textures,C=r.parser.json.textures[b];if(!C){console.warn("Texture data not found for texture index "+b);continue}if((y=C==null?void 0:C.extensions)!=null&&y[R]){const M=C.extensions[R];M&&i&&v.registerTexture(i,D,M.lods.length,M)}}}};const s=t.material;if(Array.isArray(s))for(const o of s)n(o);else n(s)}}tryParseMeshLOD(e,t){var n,s;if(t[re]==!0)return;t[re]=!0;const r=this.getUrl();if(!r)return;const i=(s=(n=t.userData)==null?void 0:n.gltfExtensions)==null?void 0:s[R];if(i&&r){const o=t.uuid;v.registerMesh(r,o,t,0,i.lods.length,i)}}}function xe(a,e,t,r){Q(e),Z(t),t.register(n=>new v(n,a));const i=_.get(e);return(r==null?void 0:r.enableLODsManager)!==!1&&i.enable(),i}document.addEventListener("DOMContentLoaded",()=>{ne(document.querySelector("model-viewer"))});exports.EXTENSION_NAME=R;exports.LODsManager=_;exports.NEEDLE_progressive=v;exports.addDracoAndKTX2Loaders=Z;exports.createLoaders=Q;exports.getRaycastMesh=se;exports.patchModelViewer=ne;exports.setDracoDecoderLocation=ge;exports.setKTX2TranscoderLocation=he;exports.setRaycastMesh=ie;exports.useNeedleProgressive=xe;
|
package/lib/lods_manager.d.ts
CHANGED
|
@@ -46,6 +46,8 @@ export declare class LODsManager {
|
|
|
46
46
|
readonly renderer: WebGLRenderer;
|
|
47
47
|
readonly projectionScreenMatrix: Matrix4;
|
|
48
48
|
readonly cameraFrustrum: Frustum;
|
|
49
|
+
/** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
|
|
50
|
+
get plugins(): NEEDLE_progressive_plugin[];
|
|
49
51
|
/**
|
|
50
52
|
* The target triangle density is the desired max amount of triangles on screen when the mesh is filling the screen.
|
|
51
53
|
* @default 200_000
|
package/lib/lods_manager.js
CHANGED
|
@@ -66,6 +66,8 @@ export class LODsManager {
|
|
|
66
66
|
renderer;
|
|
67
67
|
projectionScreenMatrix = new Matrix4();
|
|
68
68
|
cameraFrustrum = new Frustum();
|
|
69
|
+
/** @deprecated use static `LODsManager.addPlugin()` method. This getter will be removed in later versions */
|
|
70
|
+
get plugins() { return plugins; }
|
|
69
71
|
/**
|
|
70
72
|
* The target triangle density is the desired max amount of triangles on screen when the mesh is filling the screen.
|
|
71
73
|
* @default 200_000
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
*{box-sizing:border-box}html,body,#root{width:100%;height:100%;margin:0;padding:0}body{background:#f0f0f0}
|