@gltf-transform/functions
Advanced tools
Comparing version 3.1.1 to 3.1.2
@@ -1,2 +0,2 @@ | ||
import{Primitive as e,PropertyType as t,Document as n,getBounds as r,Scene as o,PrimitiveTarget as s,MathUtils as i,BufferUtils as a,Root as c,AnimationChannel as l,Texture as g,TextureInfo as u,ExtensionProperty as f,ImageUtils as p,ComponentTypeToTypedArray as m,Material as d,TextureChannel as h,Node as A,Accessor as y,AnimationSampler as T,uuid as E}from"@gltf-transform/core";import{getPixels as S,savePixels as I}from"ndarray-pixels";import{KHRMeshQuantization as M,KHRDracoMeshCompression as w,EXTMeshGPUInstancing as b,EXTMeshoptCompression as N,KHRMaterialsIOR as R,KHRMaterialsSpecular as C,KHRMaterialsPBRSpecularGlossiness as O,EXTTextureWebP as v,EXTTextureAVIF as P,KHRMaterialsUnlit as $}from"@gltf-transform/extensions";import{read as x,KHR_DF_MODEL_ETC1S as z,KHR_DF_MODEL_UASTC as L}from"ktx-parse";import q from"ndarray";import{lanczos3 as _,lanczos2 as k}from"ndarray-lanczos";function G(){return(G=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function F(e,t){return Object.defineProperty(t,"name",{value:e}),t}function B(e,t,n){return!!e&&e.stack.lastIndexOf(t)<e.stack.lastIndexOf(n)}async function U(e,t,n){if(!e)return null;const r=e.getImage();if(!r)return null;const o=await S(r,e.getMimeType());for(let e=0;e<o.shape[0];++e)for(let t=0;t<o.shape[1];++t)n(o,e,t);const s=await I(o,"image/png");return t.setImage(s).setMimeType("image/png")}function W(t){const n=t.getIndices(),r=t.getAttribute("POSITION");switch(t.getMode()){case e.Mode.POINTS:return r.getCount();case e.Mode.LINES:return n?n.getCount()/2:r.getCount()/2;case e.Mode.LINE_LOOP:return r.getCount();case e.Mode.LINE_STRIP:return r.getCount()-1;case e.Mode.TRIANGLES:return n?n.getCount()/3:r.getCount()/3;case e.Mode.TRIANGLE_STRIP:case e.Mode.TRIANGLE_FAN:return r.getCount()-2;default:throw new Error("Unexpected mode: "+t.getMode())}}class H{constructor(){this._map=new Map}get size(){return this._map.size}has(e){return this._map.has(e)}add(e,t){let n=this._map.get(e);return n||(n=new Set,this._map.set(e,n)),n.add(t),this}get(e){return this._map.get(e)||new Set}keys(){return this._map.keys()}}function j(e,t=2){if(0===e)return"0 Bytes";const n=t<0?0:t,r=Math.floor(Math.log(e)/Math.log(1e3));return parseFloat((e/Math.pow(1e3,r)).toFixed(n))+" "+["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"][r]}function D(e){return e.toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}function V(e,t){return`${D(e)} → ${D(t)} (${function(e,t,n=2){return(e>t?"–":"+")+(Math.abs(e-t)/e*100).toFixed(n)+"%"}(e,t)})`}function X(e){const t=[];for(const n of e.listAttributes())t.push(n);for(const n of e.listTargets())for(const e of n.listAttributes())t.push(e);return Array.from(new Set(t))}function K(e,t,n){e.swap(t,n);for(const r of e.listTargets())r.swap(t,n)}function J(e,t,n){const r=e.getElementSize(),o=e.getCount(),s=e.getArray(),i=s.slice(0,n*r);for(let e=0;e<o;e++)for(let n=0;n<r;n++)i[t[e]*r+n]=s[e*r+n];e.setArray(i)}function Z(e,t=e){const n=t<=65534?new Uint16Array(e):new Uint32Array(e);for(let e=0;e<n.length;e++)n[e]=e;return n}function Q(e){const t=n.fromGraph(e.getGraph()),r=e.getMaterial();return`${t.getRoot().listMaterials().indexOf(r)}|${e.getMode()}|${!!e.getIndices()}|${e.listSemantics().sort().map(t=>{const n=e.getAttribute(t);return`${t}:${n.getElementSize()}:${n.getComponentType()}`}).join("+")}|${e.listTargets().map(t=>t.listSemantics().sort().map(t=>{const n=e.getAttribute(t);return`${t}:${n.getElementSize()}:${n.getComponentType()}`}).join("+")).join("~")}`}const Y={pivot:"center"};function ee(e=Y){const t=G({},Y,e);return F("center",e=>{const n=e.getLogger(),o=e.getRoot(),s=o.listAnimations().length>0||o.listSkins().length>0;e.getRoot().listScenes().forEach((i,a)=>{let c;if(n.debug(`center: Scene ${a+1} / ${o.listScenes().length}.`),"string"==typeof t.pivot){const e=r(i);c=[(e.max[0]-e.min[0])/2+e.min[0],(e.max[1]-e.min[1])/2+e.min[1],(e.max[2]-e.min[2])/2+e.min[2]],"above"===t.pivot&&(c[1]=e.max[1]),"below"===t.pivot&&(c[1]=e.min[1])}else c=t.pivot;n.debug(`center: Pivot "${c.join(", ")}".`);const l=[-1*c[0],-1*c[1],-1*c[2]];if(s){n.debug("center: Model contains animation or skin. Adding a wrapper node.");const t=e.createNode("Pivot").setTranslation(l);i.listChildren().forEach(e=>t.addChild(e)),i.addChild(t)}else n.debug("center: Skipping wrapper, offsetting all root nodes."),i.listChildren().forEach(e=>{const t=e.getTranslation();e.setTranslation([t[0]+l[0],t[1]+l[1],t[2]+l[2]])})}),n.debug("center: Complete.")})}function te(e){const t=new Set;let n,r=e;for(;n=r.getParentNode();){if(t.has(n))throw new Error("Circular dependency in scene graph.");t.add(n),r=n}return r.listParents().filter(e=>e instanceof o)}function ne(e){const t=te(e),n=e.getParentNode();if(!n)return e;e.setMatrix(e.getWorldMatrix()),n.removeChild(e);for(const n of t)n.addChild(e);return e}var re="undefined"!=typeof Float32Array?Float32Array:Array;function oe(e,t){var n=t[0],r=t[1],o=t[2],s=t[3],i=t[4],a=t[5],c=t[6],l=t[7],g=t[8],u=t[9],f=t[10],p=t[11],m=t[12],d=t[13],h=t[14],A=t[15],y=n*a-r*i,T=n*c-o*i,E=n*l-s*i,S=r*c-o*a,I=r*l-s*a,M=o*l-s*c,w=g*d-u*m,b=g*h-f*m,N=g*A-p*m,R=u*h-f*d,C=u*A-p*d,O=f*A-p*h,v=y*O-T*C+E*R+S*N-I*b+M*w;return v?(e[0]=(a*O-c*C+l*R)*(v=1/v),e[1]=(o*C-r*O-s*R)*v,e[2]=(d*M-h*I+A*S)*v,e[3]=(f*I-u*M-p*S)*v,e[4]=(c*N-i*O-l*b)*v,e[5]=(n*O-o*N+s*b)*v,e[6]=(h*E-m*M-A*T)*v,e[7]=(g*M-f*E+p*T)*v,e[8]=(i*C-a*N+l*w)*v,e[9]=(r*N-n*C-s*w)*v,e[10]=(m*I-d*E+A*y)*v,e[11]=(u*E-g*I-p*y)*v,e[12]=(a*b-i*R-c*w)*v,e[13]=(n*R-r*b+o*w)*v,e[14]=(d*T-m*S-h*y)*v,e[15]=(g*S-u*T+f*y)*v,e):null}function se(e,t,n){var r=t[0],o=t[1],s=t[2],i=t[3],a=t[4],c=t[5],l=t[6],g=t[7],u=t[8],f=t[9],p=t[10],m=t[11],d=t[12],h=t[13],A=t[14],y=t[15],T=n[0],E=n[1],S=n[2],I=n[3];return e[0]=T*r+E*a+S*u+I*d,e[1]=T*o+E*c+S*f+I*h,e[2]=T*s+E*l+S*p+I*A,e[3]=T*i+E*g+S*m+I*y,e[4]=(T=n[4])*r+(E=n[5])*a+(S=n[6])*u+(I=n[7])*d,e[5]=T*o+E*c+S*f+I*h,e[6]=T*s+E*l+S*p+I*A,e[7]=T*i+E*g+S*m+I*y,e[8]=(T=n[8])*r+(E=n[9])*a+(S=n[10])*u+(I=n[11])*d,e[9]=T*o+E*c+S*f+I*h,e[10]=T*s+E*l+S*p+I*A,e[11]=T*i+E*g+S*m+I*y,e[12]=(T=n[12])*r+(E=n[13])*a+(S=n[14])*u+(I=n[15])*d,e[13]=T*o+E*c+S*f+I*h,e[14]=T*s+E*l+S*p+I*A,e[15]=T*i+E*g+S*m+I*y,e}function ie(){var e=new re(9);return re!=Float32Array&&(e[1]=0,e[2]=0,e[3]=0,e[5]=0,e[6]=0,e[7]=0),e[0]=1,e[4]=1,e[8]=1,e}function ae(){var e=new re(3);return re!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0),e}function ce(e,t,n){var r=new re(3);return r[0]=e,r[1]=t,r[2]=n,r}function le(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e[2]=Math.min(t[2],n[2]),e}function ge(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e[2]=Math.max(t[2],n[2]),e}function ue(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e[2]=t[2]*n,e}function fe(e,t){var n=t[0],r=t[1],o=t[2],s=n*n+r*r+o*o;return s>0&&(s=1/Math.sqrt(s)),e[0]=t[0]*s,e[1]=t[1]*s,e[2]=t[2]*s,e}function pe(e,t,n){var r=t[0],o=t[1],s=t[2],i=n[3]*r+n[7]*o+n[11]*s+n[15];return e[0]=(n[0]*r+n[4]*o+n[8]*s+n[12])/(i=i||1),e[1]=(n[1]*r+n[5]*o+n[9]*s+n[13])/i,e[2]=(n[2]*r+n[6]*o+n[10]*s+n[14])/i,e}function me(e,t,n){var r=t[0],o=t[1],s=t[2];return e[0]=r*n[0]+o*n[3]+s*n[6],e[1]=r*n[1]+o*n[4]+s*n[7],e[2]=r*n[2]+o*n[5]+s*n[8],e}function de(){var e=new re(4);return re!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0,e[3]=0),e}function he(e,t,n=new Set){var r;const o=e.getAttribute("POSITION"),s=(null==(r=e.getIndices())?void 0:r.getArray())||Z(o.getCount());o&&Ae(t,o,s,new Set(n));const i=e.getAttribute("NORMAL");i&&ye(t,i,s,new Set(n));const a=e.getAttribute("TANGENT");a&&Te(t,a,s,new Set(n));for(const r of e.listTargets()){const e=r.getAttribute("POSITION");e&&Ae(t,e,s,new Set(n));const o=r.getAttribute("NORMAL");o&&ye(t,o,s,new Set(n));const i=r.getAttribute("TANGENT");i&&Te(t,i,s,new Set(n))}for(let e=0;e<s.length;e++)n.add(s[e])}function Ae(e,t,n,r){const o=new Float32Array(3*t.getCount()),s=t.getElementSize();for(let e=0,n=[],r=t.getCount();e<r;e++)o.set(t.getElement(e,n),e*s);const i=ae();for(let s=0;s<n.length;s++){const a=n[s];r.has(a)||(t.getElement(a,i),pe(i,i,e),o.set(i,3*a),r.add(a))}t.setArray(o).setNormalized(!1)}function ye(e,t,n,r){const o=ie();var s,i;(s=o)[0]=(i=e)[0],s[1]=i[1],s[2]=i[2],s[3]=i[4],s[4]=i[5],s[5]=i[6],s[6]=i[8],s[7]=i[9],s[8]=i[10],function(e,t){var n=t[0],r=t[1],o=t[2],s=t[3],i=t[4],a=t[5],c=t[6],l=t[7],g=t[8],u=g*i-a*l,f=-g*s+a*c,p=l*s-i*c,m=n*u+r*f+o*p;m&&(e[0]=u*(m=1/m),e[1]=(-g*r+o*l)*m,e[2]=(a*r-o*i)*m,e[3]=f*m,e[4]=(g*n-o*c)*m,e[5]=(-a*n+o*s)*m,e[6]=p*m,e[7]=(-l*n+r*c)*m,e[8]=(i*n-r*s)*m)}(o,o),function(e,t){if(e===t){var n=t[1],r=t[2],o=t[5];e[1]=t[3],e[2]=t[6],e[3]=n,e[5]=t[7],e[6]=r,e[7]=o}else e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8]}(o,o);const a=ae();for(let e=0;e<n.length;e++){const s=n[e];r.has(s)||(t.getElement(s,a),me(a,a,o),fe(a,a),t.setElement(s,a),r.add(s))}}function Te(e,t,n,r){const o=ae(),s=de();for(let i=0;i<n.length;i++){const a=n[i];if(r.has(a))continue;t.getElement(a,s);const[c,l,g]=s;o[0]=e[0]*c+e[4]*l+e[8]*g,o[1]=e[1]*c+e[5]*l+e[9]*g,o[2]=e[2]*c+e[6]*l+e[10]*g,fe(o,o),s[0]=o[0],s[1]=o[1],s[2]=o[2],t.setElement(a,s),r.add(a)}}function Ee(n,r,o=!1,i){for(const e of n.listPrimitives())if(e.listParents().some(e=>e.propertyType===t.MESH&&e!==n)){const t=e.clone();n.swap(e,t);for(const e of t.listTargets()){const n=e.clone();t.swap(e,n)}}if(!o){const t=new Set([...n.listPrimitives(),...n.listPrimitives().flatMap(e=>e.listTargets())]),r=new Map;for(const o of n.listPrimitives())for(const n of X(o))n.listParents().some(n=>(n instanceof e||n instanceof s)&&!t.has(n))&&!r.has(n)&&r.set(n,n.clone());for(const e of t)for(const[t,n]of r)e.swap(t,n)}i=i||new Set;for(const e of n.listPrimitives())he(e,r,i)}Math.hypot||(Math.hypot=function(){for(var e=0,t=arguments.length;t--;)e+=arguments[t]*arguments[t];return Math.sqrt(e)}),ae(),de();const Se=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];function Ie(e){const t=e.getMesh(),n=e.getMatrix();t&&!i.eq(n,Se)&&Ee(t,n);for(const t of e.listChildren()){const e=t.getMatrix();se(e,e,n),t.setMatrix(e)}return e.setMatrix(Se)}const Me="colorspace";function we(e){return F(Me,t=>{const n=t.getLogger();if("linear"===e.inputEncoding)return void n.info(`${Me}: Vertex colors already linear. Skipping conversion.`);if("sRGB"!==e.inputEncoding)return void n.error(`${Me}: Unknown input encoding "${e.inputEncoding}" – should be "sRGB" or "linear". Skipping conversion.`);const r=new Set;function o(e){return e<.04045?.0773993808*e:Math.pow(.9478672986*e+.0521327014,2.4)}function s(e){const t=[0,0,0];let n;for(let s=0;n=e.getAttribute(`COLOR_${s}`);s++)if(!r.has(n)){for(let e=0;e<n.getCount();e++)n.getElement(e,t),t[0]=o(t[0]),t[1]=o(t[1]),t[2]=o(t[2]),n.setElement(e,t);r.add(n)}}t.getRoot().listMeshes().forEach(e=>e.listPrimitives().forEach(s)),n.debug(`${Me}: Complete.`)})}const be={propertyTypes:[t.ACCESSOR,t.MESH,t.TEXTURE,t.MATERIAL]},Ne=function(e=be){const n=G({},be,e),r=new Set(n.propertyTypes);for(const e of n.propertyTypes)if(!be.propertyTypes.includes(e))throw new Error(`dedup: Unsupported deduplication on type "${e}".`);return F("dedup",e=>{const n=e.getLogger();r.has(t.ACCESSOR)&&function(e,t){const n=new Set,r=new Set,o=new Set,s=new Set,i=t.getRoot().listMeshes();i.forEach(e=>{e.listPrimitives().forEach(e=>{e.listAttributes().forEach(e=>r.add(e));const t=e.getIndices();t&&n.add(t)})});for(const e of t.getRoot().listAnimations())for(const t of e.listSamplers()){const e=t.getInput(),n=t.getOutput();e&&o.add(e),n&&s.add(n)}function c(e){const t=new Map;for(let n=0;n<e.length;n++){const r=e[n],o=a.toView(r.getArray());if(!t.has(r))for(let n=0;n<e.length;n++){const s=e[n];r!==s&&(t.has(s)||r.getType()===s.getType()&&r.getComponentType()===s.getComponentType()&&r.getCount()===s.getCount()&&r.getNormalized()===s.getNormalized()&&a.equals(o,a.toView(s.getArray()))&&t.set(s,r))}}return t}const l=c(Array.from(n));e.debug(`dedup: Found ${l.size} duplicates among ${n.size} indices.`);const g=c(Array.from(r));e.debug(`dedup: Found ${g.size} duplicates among ${r.size} attributes.`);const u=c(Array.from(o)),f=c(Array.from(s));e.debug(`dedup: Found ${u.size+f.size} duplicates among ${o.size+s.size} animation accessors.`),i.forEach(e=>{e.listPrimitives().forEach(e=>{e.listAttributes().forEach(t=>{g.has(t)&&e.swap(t,g.get(t))});const t=e.getIndices();t&&l.has(t)&&e.swap(t,l.get(t))})}),Array.from(l.keys()).forEach(e=>e.dispose()),Array.from(g.keys()).forEach(e=>e.dispose());for(const e of t.getRoot().listAnimations())for(const t of e.listSamplers()){const e=t.getInput(),n=t.getOutput();e&&u.has(e)&&t.swap(e,u.get(e)),n&&f.has(n)&&t.swap(n,f.get(n))}Array.from(u.keys()).forEach(e=>e.dispose()),Array.from(f.keys()).forEach(e=>e.dispose())}(n,e),r.has(t.TEXTURE)&&function(e,t){const n=t.getRoot(),r=n.listTextures(),o=new Map;for(let e=0;e<r.length;e++){const t=r[e],n=t.getImage();if(!o.has(t))for(let e=0;e<r.length;e++){const s=r[e],i=s.getImage();if(t===s)continue;if(o.has(s))continue;if(t.getMimeType()!==s.getMimeType())continue;const c=t.getSize(),l=s.getSize();c&&l&&c[0]===l[0]&&c[1]===l[1]&&n&&i&&a.equals(n,i)&&o.set(s,t)}}e.debug(`dedup: Found ${o.size} duplicates among ${n.listTextures().length} textures.`),Array.from(o.entries()).forEach(([e,t])=>{e.listParents().forEach(n=>{n instanceof c||n.swap(e,t)}),e.dispose()})}(n,e),r.has(t.MATERIAL)&&function(e,t){const n=t.getRoot(),r=n.listMaterials(),o=new Map,s=new Set(["name"]);for(let e=0;e<r.length;e++){const t=r[e];if(!o.has(t))for(let e=0;e<r.length;e++){const n=r[e];t!==n&&(o.has(n)||t.equals(n,s)&&o.set(n,t))}}e.debug(`dedup: Found ${o.size} duplicates among ${n.listMaterials().length} materials.`),Array.from(o.entries()).forEach(([e,t])=>{e.listParents().forEach(n=>{n instanceof c||n.swap(e,t)}),e.dispose()})}(n,e),r.has(t.MESH)&&function(e,n){const r=n.getRoot(),o=new Map;r.listAccessors().forEach((e,t)=>o.set(e,t)),r.listMaterials().forEach((e,t)=>o.set(e,t));const s=r.listMeshes().length,i=new Map;for(const e of r.listMeshes()){const n=[];for(const t of e.listPrimitives())n.push(Re(t,o));const r=n.join(";");if(i.has(r)){const n=i.get(r);e.listParents().forEach(r=>{r.propertyType!==t.ROOT&&r.swap(e,n)}),e.dispose()}else i.set(r,e)}e.debug(`dedup: Found ${s-i.size} duplicates among ${s} meshes.`)}(n,e),n.debug("dedup: Complete.")})};function Re(t,n){const r=[];for(const e of t.listSemantics()){const o=t.getAttribute(e);r.push(e+":"+n.get(o))}if(t instanceof e){const e=t.getIndices();e&&r.push("indices:"+n.get(e));const o=t.getMaterial();o&&r.push("material:"+n.get(o)),r.push("mode:"+t.getMode());for(const e of t.listTargets())r.push("target:"+Re(e,n))}return r.join(",")}const Ce={pattern:/^((?!JOINTS_).)*$/};function Oe(e=Ce){const t=G({},Ce,e);return F("dequantize",e=>{const n=e.getLogger();for(const n of e.getRoot().listMeshes())for(const e of n.listPrimitives())ve(e,t);e.createExtension(M).dispose(),n.debug("dequantize: Complete.")})}function ve(e,t){for(const n of e.listSemantics())Pe(n,e.getAttribute(n),t);for(const n of e.listTargets())for(const e of n.listSemantics())Pe(e,n.getAttribute(e),t)}function Pe(e,t,n){if(!t.getArray())return;if(!n.pattern.test(e))return;if(t.getComponentSize()>=4)return;const r=t.getArray(),o=new Float32Array(r.length);for(let e=0,n=t.getCount(),s=[];e<n;e++)s=t.getElement(e,s),t.setArray(o).setElement(e,s).setArray(r);t.setArray(o).setNormalized(!1)}const $e={method:"edgebreaker",encodeSpeed:5,decodeSpeed:5,quantizePosition:14,quantizeNormal:10,quantizeColor:8,quantizeTexcoord:12,quantizeGeneric:12,quantizationVolume:"mesh"},xe=(e=$e)=>{const t=G({},$e,e);return F("draco",e=>{e.createExtension(w).setRequired(!0).setEncoderOptions({method:"edgebreaker"===t.method?w.EncoderMethod.EDGEBREAKER:w.EncoderMethod.SEQUENTIAL,encodeSpeed:t.encodeSpeed,decodeSpeed:t.decodeSpeed,quantizationBits:{POSITION:t.quantizePosition,NORMAL:t.quantizeNormal,COLOR:t.quantizeColor,TEX_COORD:t.quantizeTexcoord,GENERIC:t.quantizeGeneric},quantizationVolume:t.quantizationVolume})})},ze={propertyTypes:[t.NODE,t.SKIN,t.MESH,t.CAMERA,t.PRIMITIVE,t.PRIMITIVE_TARGET,t.ANIMATION,t.MATERIAL,t.TEXTURE,t.ACCESSOR,t.BUFFER],keepLeaves:!1,keepAttributes:!0},Le=function(e=ze){const n=G({},ze,e),r=new Set(n.propertyTypes);return F("prune",e=>{const s=e.getLogger(),i=e.getRoot(),a=e.getGraph(),g={};if(r.has(t.MESH))for(const e of i.listMeshes())e.listPrimitives().length>0||(e.dispose(),m(e));if(r.has(t.NODE)&&!n.keepLeaves&&i.listScenes().forEach(function e(n){if(n.listChildren().forEach(e),n instanceof o)return;const r=a.listParentEdges(n).some(e=>{const n=e.getParent().propertyType;return n!==t.ROOT&&n!==t.SCENE&&n!==t.NODE});0!==a.listChildren(n).length||r||(n.dispose(),m(n))}),r.has(t.NODE)&&i.listNodes().forEach(u),r.has(t.SKIN)&&i.listSkins().forEach(u),r.has(t.MESH)&&i.listMeshes().forEach(u),r.has(t.CAMERA)&&i.listCameras().forEach(u),r.has(t.PRIMITIVE)&&f(a,t.PRIMITIVE),r.has(t.PRIMITIVE_TARGET)&&f(a,t.PRIMITIVE_TARGET),!n.keepAttributes&&r.has(t.ACCESSOR))for(const t of i.listMeshes())for(const n of t.listPrimitives()){const t=_e(e,n.getMaterial()),r=qe(n,t);p(n,r),n.listTargets().forEach(e=>p(e,r))}if(r.has(t.ANIMATION))for(const e of i.listAnimations()){for(const t of e.listChannels())t.getTargetNode()||(t.dispose(),m(t));if(e.listChannels().length)e.listSamplers().forEach(u);else{const t=e.listSamplers();u(e),t.forEach(u)}}if(r.has(t.MATERIAL)&&i.listMaterials().forEach(u),r.has(t.TEXTURE)&&i.listTextures().forEach(u),r.has(t.ACCESSOR)&&i.listAccessors().forEach(u),r.has(t.BUFFER)&&i.listBuffers().forEach(u),Object.keys(g).length){const e=Object.keys(g).map(e=>`${e} (${g[e]})`).join(", ");s.info(`prune: Removed types... ${e}`)}else s.info("prune: No unused properties found.");function u(e){e.listParents().filter(e=>!(e instanceof c||e instanceof l)).length||(e.dispose(),m(e))}function f(e,t){e.listEdges().map(e=>e.getParent()).filter(e=>e.propertyType===t).forEach(u)}function p(e,t){for(const n of t)e.setAttribute(n,null)}function m(e){g[e.propertyType]=g[e.propertyType]||0,g[e.propertyType]++}s.debug("prune: Complete.")})};function qe(e,t){const n=[];for(const r of e.listSemantics())"TANGENT"!==r||t.has(r)?(r.startsWith("TEXCOORD_")&&!t.has(r)||r.startsWith("COLOR_")&&"COLOR_0"!==r)&&n.push(r):n.push(r);return n}function _e(e,t,n=new Set){if(!t)return n;const r=e.getGraph().listChildEdges(t),o=new Set;for(const e of r)e.getChild()instanceof g&&o.add(e.getName());for(const t of r){const r=t.getName(),s=t.getChild();s instanceof u&&o.has(r.replace(/Info$/,""))&&n.add(`TEXCOORD_${s.getTexCoord()}`),s instanceof g&&r.match(/normalTexture/i)&&n.add("TANGENT"),s instanceof f&&_e(e,s,n)}return n}const ke={};function Ge(e=ke){return G({},ke,e),F("flatten",async e=>{const n=e.getRoot(),r=e.getLogger(),o=new Set;for(const e of n.listSkins())for(const t of e.listJoints())o.add(t);const s=new Set;for(const e of n.listAnimations())for(const t of e.listChannels()){const e=t.getTargetNode();e&&s.add(e)}const i=new Set,a=new Set;for(const e of n.listScenes())e.traverse(e=>{const t=e.getParentNode();t&&((o.has(t)||i.has(t))&&i.add(e),(s.has(t)||a.has(t))&&a.add(e))});for(const e of n.listScenes())e.traverse(e=>{s.has(e)||i.has(e)||a.has(e)||ne(e)});s.size&&r.debug("flatten: Flattening node hierarchies with TRS animation not yet supported."),await e.transform(Le({propertyTypes:[t.NODE],keepLeaves:!1})),r.debug("flatten: Complete.")})}function Fe(e){return te(e)[0]||null}function Be(e){return{scenes:Ue(e),meshes:We(e),materials:He(e),textures:je(e),animations:De(e)}}function Ue(e){return{properties:e.getRoot().listScenes().map(e=>{const t=e.listChildren()[0],n=r(e);return{name:e.getName(),rootName:t?t.getName():"",bboxMin:Ke(n.min),bboxMax:Ke(n.max)}})}}function We(e){return{properties:e.getRoot().listMeshes().map(e=>{const n=e.listParents().filter(e=>e.propertyType!==t.ROOT).length;let r=0,o=0;const s=new Set,i=new Set,a=new Set;e.listPrimitives().forEach(e=>{for(const t of e.listSemantics()){const n=e.getAttribute(t);s.add(t+":"+Je(n)),a.add(n)}for(const t of e.listTargets())t.listAttributes().forEach(e=>a.add(e));const t=e.getIndices();t&&(i.add(Je(t)),a.add(t)),o+=e.listAttributes()[0].getCount(),r+=W(e)});let c=0;Array.from(a).forEach(e=>c+=e.getArray().byteLength);const l=e.listPrimitives().map(e=>Ve[e.getMode()]);return{name:e.getName(),mode:Array.from(new Set(l)),primitives:e.listPrimitives().length,glPrimitives:r,vertices:o,indices:Array.from(i).sort(),attributes:Array.from(s).sort(),instances:n,size:c}})}}function He(e){return{properties:e.getRoot().listMaterials().map(n=>{const r=n.listParents().filter(e=>e.propertyType!==t.ROOT).length,o=new Set(n.listExtensions()),s=e.getGraph().listEdges().filter(e=>{const t=e.getChild(),r=e.getParent();return t instanceof g&&r===n||!!(t instanceof g&&r instanceof f&&o.has(r))}).map(e=>e.getName());return{name:n.getName(),instances:r,textures:s,alphaMode:n.getAlphaMode(),doubleSided:n.getDoubleSided()}})}}function je(e){return{properties:e.getRoot().listTextures().map(n=>{const r=n.listParents().filter(e=>e.propertyType!==t.ROOT).length,o=e.getGraph().listParentEdges(n).filter(e=>e.getParent().propertyType!==t.ROOT).map(e=>e.getName()),s=p.getSize(n.getImage(),n.getMimeType());let i="";if("image/ktx2"===n.getMimeType()){const e=x(n.getImage()).dataFormatDescriptor[0];e.colorModel===z?i="ETC1S":e.colorModel===L&&(i="UASTC")}return{name:n.getName(),uri:n.getURI(),slots:Array.from(new Set(o)),instances:r,mimeType:n.getMimeType(),compression:i,resolution:s?s.join("x"):"",size:n.getImage().byteLength,gpuSize:p.getVRAMByteLength(n.getImage(),n.getMimeType())}})}}function De(e){return{properties:e.getRoot().listAnimations().map(e=>{let t=Infinity,n=-Infinity;e.listSamplers().forEach(e=>{const r=e.getInput();r&&(t=Math.min(t,r.getMin([])[0]),n=Math.max(n,r.getMax([])[0]))});let r=0,o=0;const s=new Set;return e.listSamplers().forEach(e=>{const t=e.getInput(),n=e.getOutput();t&&(o+=t.getCount(),s.add(t),n&&s.add(n))}),Array.from(s).forEach(e=>{r+=e.getArray().byteLength}),{name:e.getName(),channels:e.listChannels().length,samplers:e.listSamplers().length,duration:Math.round(1e3*(n-t))/1e3,keyframes:o,size:r}})}}const Ve=["POINTS","LINES","LINE_LOOP","LINE_STRIP","TRIANGLES","TRIANGLE_STRIP","TRIANGLE_FAN"],Xe={Float32Array:"f32",Uint32Array:"u32",Uint16Array:"u16",Uint8Array:"u8",Int32Array:"i32",Int16Array:"i16",Int8Array:"i8"};function Ke(e){for(let t=0;t<e.length;t++)e[t].toFixed&&(e[t]=Number(e[t].toFixed(5)));return e}function Je(e){const t=e.getArray();return(Xe[t.constructor.name]||"?")+(e.getNormalized()?"_norm":"")}const Ze={min:2};function Qe(e=Ze){const t=G({},Ze,e);return F("instance",e=>{const n=e.getLogger(),r=e.getRoot(),o=e.createExtension(b);if(r.listAnimations().length)return n.warn("instance: Instancing is not currently supported for animated models."),void n.debug("instance: Complete.");let s=0,a=0;for(const c of r.listScenes()){const r=new Map;c.traverse(e=>{const t=e.getMesh();t&&r.set(t,(r.get(t)||new Set).add(e))});const l=[];for(const g of Array.from(r.keys())){const u=Array.from(r.get(g));if(u.length<t.min)continue;if(u.some(e=>e.getSkin()))continue;const f=et(e,o,g,u.length),p=f.getAttribute("TRANSLATION"),m=f.getAttribute("ROTATION"),d=f.getAttribute("SCALE"),h=e.createNode().setMesh(g).setExtension("EXT_mesh_gpu_instancing",f);c.addChild(h);let A=!1,y=!1,T=!1;for(let e=0;e<u.length;e++){let t,n,r;const o=u[e];p.setElement(e,t=o.getWorldTranslation()),m.setElement(e,n=o.getWorldRotation()),d.setElement(e,r=o.getWorldScale()),i.eq(t,[0,0,0])||(A=!0),i.eq(n,[0,0,0,1])||(y=!0),i.eq(r,[1,1,1])||(T=!0),o.setMesh(null),l.push(o)}A||p.dispose(),y||m.dispose(),T||d.dispose(),Ye(l,n),s++,a+=u.length}}n.info(s>0?`instance: Created ${s} batches, with ${a} total instances.`:`instance: No meshes with ≥${t.min} parent nodes were found.`),0===o.listProperties().length&&o.dispose(),n.debug("instance: Complete.")})}function Ye(e,t){let n,r=0;for(;n=e.pop();){if(n.listChildren().length||n.getCamera()||n.getMesh()||n.getSkin()||n.listExtensions().length)continue;const t=n.getParentNode();t&&e.push(t),n.dispose(),r++}t.debug(`instance: Removed ${r} unused nodes.`)}function et(e,t,n,r){const o=n.listPrimitives()[0].getAttribute("POSITION").getBuffer(),s=e.createAccessor().setType("VEC3").setArray(new Float32Array(3*r)).setBuffer(o),i=e.createAccessor().setType("VEC4").setArray(new Float32Array(4*r)).setBuffer(o),a=e.createAccessor().setType("VEC3").setArray(new Float32Array(3*r)).setBuffer(o);return t.createInstancedMesh().setAttribute("TRANSLATION",s).setAttribute("ROTATION",i).setAttribute("SCALE",a)}const tt={skipValidation:!1};function nt(e,t={}){t=G({},tt,t);const r=e[0],o=n.fromGraph(r.getGraph());if(!t.skipValidation&&new Set(e.map(Q)).size>1)throw new Error("Requires ≥2 Primitives, sharing the same Material and Mode, with compatible vertex attributes and indices.");const s=[],i=[];let a=0,c=0;for(const t of e){const e=rt(t),n=[];for(let t=0;t<e.length;t++){const r=e[t];void 0===n[r]&&(n[r]=a++),c++}s.push(new Uint32Array(n)),i.push(e)}const l=o.createPrimitive().setMode(r.getMode()).setMaterial(r.getMaterial());for(const e of r.listSemantics()){const t=r.getAttribute(e),n=m[t.getComponentType()],s=o.createAccessor().setType(t.getType()).setBuffer(t.getBuffer()).setNormalized(t.getNormalized()).setArray(new n(a*t.getElementSize()));l.setAttribute(e,s)}const g=(r.getIndices()?Z(a):null)&&o.createAccessor().setBuffer(r.getIndices().getBuffer()).setArray(Z(c,a));l.setIndices(g);let u=0;for(let t=0;t<s.length;t++){const n=e[t],r=s[t],o=i[t],a=u;let c=a;for(const e of l.listSemantics()){const t=n.getAttribute(e),s=l.getAttribute(e),i=[];c=a;for(let e=0;e<o.length;e++){const n=o[e];t.getElement(n,i),s.setElement(r[n],i),g&&g.setScalar(c++,r[n])}}u=c}return l}function rt(e){const t=e.getIndices();return t?t.getArray():Z(e.getAttribute("POSITION").getCount())}const{ROOT:ot,NODE:st,MESH:it,PRIMITIVE:at,ACCESSOR:ct}=t,lt=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],gt={keepMeshes:!1,keepNamed:!1};function ut(e=gt){const t=G({},gt,e);return F("join",async e=>{const n=e.getRoot(),r=e.getLogger();for(const r of n.listScenes())ft(e,r,t),r.traverse(n=>ft(e,n,t));await e.transform(Le({propertyTypes:[st,it,at,ct],keepLeaves:!1,keepAttributes:!0})),r.debug("join: Complete.")})}function ft(e,n,r){const o=e.getLogger(),s={},i=n.listChildren();for(let e=0;e<i.length;e++){const t=i[e];if(t.listParents().some(e=>e instanceof l))continue;const n=t.getMesh();if(n&&!t.getExtension("EXT_mesh_gpu_instancing")&&!t.getSkin())for(const o of n.listPrimitives()){if(o.listTargets().length>0)continue;const i=o.getMaterial();if(i&&i.getExtension("KHR_materials_volume"))continue;let a=Q(o);const c=n.getName()||t.getName();(r.keepMeshes||r.keepNamed&&c)&&(a+=`|${e}`),a in s||(s[a]={prims:[],primMeshes:[],primNodes:[],dstNode:t,dstMesh:void 0});const l=s[a];l.prims.push(o),l.primNodes.push(t)}}const a=Object.values(s).filter(({prims:e})=>e.length>1),c=new Set(a.flatMap(e=>e.primNodes));for(const e of c){const t=e.getMesh();t.listParents().some(t=>t.propertyType!==ot&&e!==t)&&e.setMesh(t.clone())}for(const e of a){const{dstNode:t,primNodes:n}=e;e.dstMesh=t.getMesh(),e.primMeshes=n.map(e=>e.getMesh())}for(const e of a){const{prims:n,primNodes:r,primMeshes:s,dstNode:i,dstMesh:a}=e,c=i.getMatrix();for(let e=0;e<n.length;e++){const o=r[e];let a=n[e];s[e].removePrimitive(a),(a.listParents().some(e=>e.propertyType!==t.ROOT)||mt(a))&&(a=n[e]=pt(n[e])),o!==i&&(se(lt,oe(lt,c),o.getMatrix()),he(a,lt))}const l=nt(n),g=l.listAttributes()[0].getCount();a.addPrimitive(l),o.debug(`join: Joined Primitives (${n.length}) containing ${D(g)} vertices under Node "${i.getName()}".`)}}function pt(e){const t=e.clone();for(const e of t.listSemantics())t.setAttribute(e,t.getAttribute(e).clone());const n=t.getIndices();return n&&t.setIndices(n.clone()),t}function mt(e){for(const t of e.listAttributes())for(const n of t.listParents())if(n!==e&&n.propertyType!==ot)return!0;return!1}function dt(e){const t=ht(e),n=[];return t&h.R&&n.push(h.R),t&h.G&&n.push(h.G),t&h.B&&n.push(h.B),t&h.A&&n.push(h.A),n}function ht(e){const r=n.fromGraph(e.getGraph());let o=0;for(const n of r.getGraph().listParentEdges(e)){const e=n.getParent();let{channels:s}=n.getAttributes();s&&"baseColorTexture"===n.getName()&&e instanceof d&&e.getAlphaMode()===d.AlphaMode.OPAQUE&&(s&=~h.A),s?o|=s:e.propertyType!==t.ROOT&&r.getLogger().warn(`Missing attribute ".channels" on edge, "${n.getName()}".`)}return o}function At(e){const t=e.getGraph(),n=[];for(const r of t.listParentEdges(e)){const e=r.getParent(),o=r.getName()+"Info";for(const r of t.listChildEdges(e)){const e=r.getChild();e instanceof u&&r.getName()===o&&n.push(e)}}return n}function yt(e){const t=n.fromGraph(e.getGraph()).getRoot(),r=e.getGraph().listParentEdges(e).filter(e=>e.getParent()!==t).map(e=>e.getName());return Array.from(new Set(r))}const Tt={target:"size"};function Et(n){const r=G({},Tt,n),o=r.encoder;if(!o)throw new Error('reorder: encoder dependency required — install "meshoptimizer".');return F("reorder",async n=>{const s=n.getLogger();await o.ready;const i=St(n);for(const t of i.indicesToAttributes.keys()){const n=t.clone();let s=n.getArray().slice();s instanceof Uint32Array||(s=new Uint32Array(s));const[a,c]=o.reorderMesh(s,i.indicesToMode.get(t)===e.Mode.TRIANGLES,"size"===r.target);n.setArray(c<=65534?new Uint16Array(s):s);for(const e of i.indicesToAttributes.get(t)){const r=e.clone();J(r,a,c);for(const o of i.attributesToPrimitives.get(e))if(o.getIndices()===t&&o.swap(t,n),o.getIndices()===n){o.swap(e,r);for(const t of o.listTargets())t.swap(e,r)}}}await n.transform(Le({propertyTypes:[t.ACCESSOR]})),i.indicesToAttributes.size?s.debug("reorder: Complete."):s.warn("reorder: No qualifying primitives found; may need to weld first.")})}function St(e){const t=new H,n=new Map,r=new H;for(const o of e.getRoot().listMeshes())for(const e of o.listPrimitives()){const o=e.getIndices();if(o){n.set(o,e.getMode());for(const n of X(e))t.add(o,n),r.add(n,e)}}return{indicesToAttributes:t,indicesToMode:n,attributesToPrimitives:r}}function It(e,t=Infinity){if(Number.isFinite(t)&&t%4||t<=0)throw new Error("Limit must be positive multiple of four.");const n=e.getAttribute("POSITION").getCount(),r=e.listSemantics().filter(e=>e.startsWith("WEIGHTS_")).length,o=new Uint16Array(4*r),s=new Float32Array(4*r),a=new Float32Array(4*r),c=new Uint32Array(4*r),l=new Uint32Array(4*r);for(let t=0;t<n;t++){Mt(e,t,"WEIGHTS",s),Mt(e,t,"JOINTS",c);for(let e=0;e<4*r;e++)o[e]=e;o.sort((e,t)=>s[e]>s[t]?-1:1);for(let e=0;e<o.length;e++)a[e]=s[o[e]],l[e]=c[o[e]];wt(e,t,"WEIGHTS",a),wt(e,t,"JOINTS",l)}for(let n=r;4*n>t;n--){const t=e.getAttribute("WEIGHTS_"+(n-1)),r=e.getAttribute("JOINTS_"+(n-1));e.setAttribute("WEIGHTS_"+(n-1),null),e.setAttribute("JOINTS_"+(n-1),null),1===t.listParents().length&&t.dispose(),1===r.listParents().length&&r.dispose()}!function(e){if(!function(e){const t=e.listSemantics().filter(e=>e.startsWith("WEIGHTS_")).map(t=>e.getAttribute(t)),n=t.map(e=>e.getNormalized()),r=t.map(e=>e.getComponentType());return 1===new Set(n).size&&1===new Set(r).size}(e))return;const t=e.getAttribute("POSITION").getCount(),n=e.listSemantics().filter(e=>e.startsWith("WEIGHTS_")).length,r=e.getAttribute("WEIGHTS_0"),o=r.getArray(),s=r.getComponentType(),a=r.getNormalized(),c=a?s:void 0,l=a?i.decodeNormalizedInt(1,s):Number.EPSILON,g=new Uint32Array(4*n).fill(0),u=o.slice(0,4*n).fill(0);for(let n=0;n<t;n++){Mt(e,n,"JOINTS",g),Mt(e,n,"WEIGHTS",u,c);let t=bt(u,c);if(0!==t){if(Math.abs(1-t)>l)for(let e=0;e<u.length;e++)if(a){const n=i.encodeNormalizedInt(u[e]/t,s);u[e]=i.decodeNormalizedInt(n,s)}else u[e]/=t;if(t=bt(u,c),a&&1!==t)for(let e=u.length-1;e>=0;e--)if(u[e]>0){u[e]+=i.encodeNormalizedInt(1-t,s);break}for(let e=u.length-1;e>=0;e--)0===u[e]&&(g[e]=0);wt(e,n,"JOINTS",g),wt(e,n,"WEIGHTS",u,c)}}}(e)}function Mt(e,t,n,r,o){let s;const a=[0,0,0,0];for(let c=0;s=e.getAttribute(`${n}_${c}`);c++){s.getElement(t,a);for(let e=0;e<4;e++)r[4*c+e]=o?i.encodeNormalizedInt(a[e],o):a[e]}return r}function wt(e,t,n,r,o){let s;const a=[0,0,0,0];for(let c=0;s=e.getAttribute(`${n}_${c}`);c++){for(let e=0;e<4;e++)a[e]=o?i.decodeNormalizedInt(r[4*c+e],o):r[4*c+e];s.setElement(t,a)}}function bt(e,t){let n=0;for(let r=0;r<e.length;r++)n+=t?i.decodeNormalizedInt(e[r],t):e[r];return n}const Nt=[Int8Array,Int16Array,Int32Array],{TRANSLATION:Rt,ROTATION:Ct,SCALE:Ot,WEIGHTS:vt}=l.TargetPath,Pt=[Rt,Ct,Ot],$t={pattern:/.*/,quantizationVolume:"mesh",quantizePosition:14,quantizeNormal:10,quantizeTexcoord:12,quantizeColor:8,quantizeWeight:8,quantizeGeneric:12,normalizeWeights:!0},xt=(e=$t)=>{const n=G({},$t,e);return F("quantize",async e=>{const r=e.getLogger(),o=e.getRoot();let s;e.createExtension(M).setRequired(!0),"scene"===n.quantizationVolume&&(s=Lt(function(e){const t=e[0];for(const n of e)le(t.min,t.min,n.min),ge(t.max,t.max,n.max);return t}(o.listMeshes().map(Bt))));for(const t of e.getRoot().listMeshes()){"mesh"===n.quantizationVolume&&(s=Lt(Bt(t))),s&&n.pattern.test("POSITION")&&(qt(e,t,s),kt(t,1/s.scale));for(const r of t.listPrimitives()){zt(e,r,s,n);for(const t of r.listTargets())zt(e,t,s,n)}}await e.transform(Le({propertyTypes:[t.ACCESSOR,t.SKIN,t.MATERIAL]}),Ne({propertyTypes:[t.ACCESSOR,t.MATERIAL]})),r.debug("quantize: Complete.")})};function zt(t,n,r,o){const s=t.getLogger();for(const t of n.listSemantics()){if(!o.pattern.test(t))continue;const c=n.getAttribute(t),{bits:l,ctor:g}=Ft(t,c,s,o);if(!g)continue;if(l<8||l>16)throw new Error("quantize: Requires bits = 8–16.");if(c.getComponentSize()<=l/8)continue;const u=c.clone();if("POSITION"===t){const t=r.scale,o=[];n instanceof e?oe(o,Wt(r)):((i=o)[0]=(a=[1/t,1/t,1/t])[0],i[1]=0,i[2]=0,i[3]=0,i[4]=0,i[5]=a[1],i[6]=0,i[7]=0,i[8]=0,i[9]=0,i[10]=a[2],i[11]=0,i[12]=0,i[13]=0,i[14]=0,i[15]=1);for(let e=0,t=[0,0,0],n=u.getCount();e<n;e++)u.getElement(e,t),u.setElement(e,pe(t,t,o))}Gt(u,g,l),n.swap(c,u)}var i,a;if(o.normalizeWeights&&n.getAttribute("WEIGHTS_0")&&It(n,Infinity),n instanceof e&&n.getIndices()&&n.listAttributes().length&&n.listAttributes()[0].getCount()<65535){const e=n.getIndices();e.setArray(new Uint16Array(e.getArray()))}}function Lt(e){const{min:t,max:n}=e,r=Math.max((n[0]-t[0])/2,(n[1]-t[1])/2,(n[2]-t[2])/2);return{offset:[t[0]+(n[0]-t[0])/2,t[1]+(n[1]-t[1])/2,t[2]+(n[2]-t[2])/2],scale:r}}function qt(e,t,n){const r=Wt(n);for(const o of t.listParents()){if(!(o instanceof A))continue;const s=o.listParents().filter(e=>e instanceof l),i=s.some(e=>Pt.includes(e.getTargetPath())),a=o.listChildren().length>0;if(o.getSkin()){o.setSkin(_t(o.getSkin(),n));continue}let c;a||i?(c=e.createNode("").setMesh(t),o.addChild(c).setMesh(null),s.filter(e=>e.getTargetPath()===vt).forEach(e=>e.setTargetNode(c))):c=o;const g=c.getMatrix();se(g,g,r),c.setMatrix(g)}}function _t(e,t){e=e.clone();const n=Wt(t),r=e.getInverseBindMatrices().clone(),o=[];for(let e=0,t=r.getCount();e<t;e++)r.getElement(e,o),se(o,o,n),r.setElement(e,o);return e.setInverseBindMatrices(r)}function kt(e,t){for(const n of e.listPrimitives()){let e=n.getMaterial();if(!e)continue;let r=e.getExtension("KHR_materials_volume");!r||r.getThicknessFactor()<=0||(r=r.clone().setThicknessFactor(r.getThicknessFactor()*t),e=e.clone().setExtension("KHR_materials_volume",r),n.setMaterial(e))}}function Gt(e,t,n){const r=new t(e.getArray().length),o=Nt.includes(t)?1:0,s=n-o,i=8*t.BYTES_PER_ELEMENT-o,a=Math.pow(2,s)-1,c=i-s,l=2*s-i;for(let t=0,n=0,o=[];t<e.getCount();t++){e.getElement(t,o);for(let e=0;e<o.length;e++){let t=Math.round(Math.abs(o[e])*a);t=t<<c|t>>l,r[n++]=t*Math.sign(o[e])}}e.setArray(r).setNormalized(!0).setSparse(!1)}function Ft(e,t,n,r){const o=t.getMinNormalized([]),s=t.getMaxNormalized([]);let i,a;if("POSITION"===e)i=r.quantizePosition,a=i<=8?Int8Array:Int16Array;else if("NORMAL"===e||"TANGENT"===e)i=r.quantizeNormal,a=i<=8?Int8Array:Int16Array;else if(e.startsWith("COLOR_"))i=r.quantizeColor,a=i<=8?Uint8Array:Uint16Array;else if(e.startsWith("TEXCOORD_")){if(o.some(e=>e<0)||s.some(e=>e>1))return n.warn(`quantize: Skipping ${e}; out of [0,1] range.`),{bits:-1};i=r.quantizeTexcoord,a=i<=8?Uint8Array:Uint16Array}else{if(e.startsWith("JOINTS_"))return i=Math.max(...t.getMax([]))<=255?8:16,a=i<=8?Uint8Array:Uint16Array,t.getComponentSize()>i/8&&t.setArray(new a(t.getArray())),{bits:-1};if(e.startsWith("WEIGHTS_")){if(o.some(e=>e<0)||s.some(e=>e>1))return n.warn(`quantize: Skipping ${e}; out of [0,1] range.`),{bits:-1};i=r.quantizeWeight,a=i<=8?Uint8Array:Uint16Array}else{if(!e.startsWith("_"))throw new Error(`quantize: Unexpected semantic, "${e}".`);if(o.some(e=>e<-1)||s.some(e=>e>1))return n.warn(`quantize: Skipping ${e}; out of [-1,1] range.`),{bits:-1};i=r.quantizeGeneric,a=a=o.some(e=>e<0)?i<=8?Int8Array:Int16Array:i<=8?Uint8Array:Uint16Array}}return{bits:i,ctor:a}}function Bt(e){const t=[],n=[];for(const r of e.listPrimitives()){const e=r.getAttribute("POSITION");e&&t.push(e);for(const e of r.listTargets()){const t=e.getAttribute("POSITION");t&&n.push(t)}}if(0===t.length)throw new Error('quantize: Missing "POSITION" attribute.');const r=Ut(t,3);if(n.length>0){const{min:e,max:t}=Ut(n,3);le(r.min,r.min,le(e,ue(e,e,2),[0,0,0])),ge(r.max,r.max,ge(t,ue(t,t,2),[0,0,0]))}return r}function Ut(e,t){const n=new Array(t).fill(Infinity),r=new Array(t).fill(-Infinity),o=[],s=[];for(const i of e){i.getMinNormalized(o),i.getMaxNormalized(s);for(let e=0;e<t;e++)n[e]=Math.min(n[e],o[e]),r[e]=Math.max(r[e],s[e])}return{min:n,max:r}}function Wt(e){return r=e.offset,f=(s=(n=[0,0,0,1])[0])*(l=s+s),p=s*(g=(i=n[1])+i),m=s*(u=(a=n[2])+a),h=i*u,y=(c=n[3])*l,T=c*g,E=c*u,I=(o=[e.scale,e.scale,e.scale])[1],M=o[2],(t=[])[0]=(1-((d=i*g)+(A=a*u)))*(S=o[0]),t[1]=(p+E)*S,t[2]=(m-T)*S,t[3]=0,t[4]=(p-E)*I,t[5]=(1-(f+A))*I,t[6]=(h+y)*I,t[7]=0,t[8]=(m+T)*M,t[9]=(h-y)*M,t[10]=(1-(f+d))*M,t[11]=0,t[12]=r[0],t[13]=r[1],t[14]=r[2],t[15]=1,t;var t,n,r,o,s,i,a,c,l,g,u,f,p,m,d,h,A,y,T,E,S,I,M}const Ht={level:"high"},jt=e=>{const t=G({},Ht,e),n=t.encoder;if(!n)throw new Error('meshopt: encoder dependency required — install "meshoptimizer".');return F("meshopt",async e=>{await e.transform(Et({encoder:n,target:"size"}),xt({pattern:"medium"===t.level?/.*/:/^(POSITION|TEXCOORD|JOINTS|WEIGHTS)(_\d+)?$/,quantizePosition:14,quantizeTexcoord:12,quantizeColor:8,quantizeNormal:8})),e.createExtension(N).setRequired(!0).setEncoderOptions({method:"medium"===t.level?N.EncoderMethod.QUANTIZE:N.EncoderMethod.FILTER})})},Dt={};function Vt(e=Dt){return G({},Dt,e),F("metalRough",async e=>{const t=e.getLogger();if(!e.getRoot().listExtensionsUsed().map(e=>e.extensionName).includes("KHR_materials_pbrSpecularGlossiness"))return void t.warn("metalRough: KHR_materials_pbrSpecularGlossiness not found on document.");const n=e.createExtension(R),r=e.createExtension(C),o=e.createExtension(O),s=new Set;for(const t of e.getRoot().listMaterials()){const o=t.getExtension("KHR_materials_pbrSpecularGlossiness");if(!o)continue;const i=r.createSpecular().setSpecularFactor(1).setSpecularColorFactor(o.getSpecularFactor());s.add(o.getSpecularGlossinessTexture()),s.add(t.getBaseColorTexture()),s.add(t.getMetallicRoughnessTexture()),t.setBaseColorFactor(o.getDiffuseFactor()).setMetallicFactor(0).setRoughnessFactor(1).setExtension("KHR_materials_ior",n.createIOR().setIOR(1e3)).setExtension("KHR_materials_specular",i);const a=o.getDiffuseTexture();a&&(t.setBaseColorTexture(a),t.getBaseColorTextureInfo().copy(o.getDiffuseTextureInfo()));const c=o.getSpecularGlossinessTexture();if(c){const n=o.getSpecularGlossinessTextureInfo(),r=e.createTexture();await U(c,r,(e,t,n)=>{e.set(t,n,3,255)}),i.setSpecularTexture(r),i.setSpecularColorTexture(r),i.getSpecularTextureInfo().copy(n),i.getSpecularColorTextureInfo().copy(n);const s=o.getGlossinessFactor(),a=e.createTexture();await U(c,a,(e,t,n)=>{const r=255-Math.round(e.get(t,n,3)*s);e.set(t,n,0,0),e.set(t,n,1,r),e.set(t,n,2,0),e.set(t,n,3,255)}),t.setMetallicRoughnessTexture(a),t.getMetallicRoughnessTextureInfo().copy(n)}else i.setSpecularColorFactor(o.getSpecularFactor()),t.setRoughnessFactor(1-o.getGlossinessFactor());t.setExtension("KHR_materials_pbrSpecularGlossiness",null)}o.dispose();for(const e of s)e&&1===e.listParents().length&&e.dispose();t.debug("metalRough: Complete.")})}const Xt={};function Kt(e=Xt){return G({},Xt,e),F("unweld",e=>{const t=e.getLogger(),n=new Map;for(const r of e.getRoot().listMeshes())for(const e of r.listPrimitives()){const r=e.getIndices();if(!r)continue;const o=e.getAttribute("POSITION").getCount();for(const o of e.listAttributes())e.swap(o,Jt(o,r,t,n)),1===o.listParents().length&&o.dispose();for(const o of e.listTargets())for(const e of o.listAttributes())o.swap(e,Jt(e,r,t,n)),1===e.listParents().length&&e.dispose();const s=e.getAttribute("POSITION").getCount();t.debug(`unweld: ${V(o,s)} vertices.`),e.setIndices(null),1===r.listParents().length&&r.dispose()}t.debug("unweld: Complete.")})}function Jt(e,t,n,r){if(r.has(e)&&r.get(e).has(t))return n.debug(`unweld: Cache hit for reused attribute, "${e.getName()}".`),r.get(e).get(t);const o=e.clone(),s=e.getArray().constructor;o.setArray(new s(t.getCount()*e.getElementSize()));const i=[];for(let n=0;n<t.getCount();n++)o.setElement(n,e.getElement(t.getScalar(n),i));return r.has(e)||r.set(e,new Map),r.get(e).set(t,o),o}const Zt={overwrite:!1};function Qt(e=Zt){const t=G({},Zt,e);return F("normals",async e=>{const n=e.getLogger();let r=0;await e.transform(Kt());for(const o of e.getRoot().listMeshes())for(const s of o.listPrimitives()){const o=s.getAttribute("POSITION");let i=s.getAttribute("NORMAL");if(t.overwrite&&i)i.dispose();else if(i){n.debug("normals: Skipping primitive: NORMAL found.");continue}i=e.createAccessor().setArray(new Float32Array(3*o.getCount())).setType("VEC3");const a=[0,0,0],c=[0,0,0],l=[0,0,0];for(let e=0;e<o.getCount();e+=3){o.getElement(e+0,a),o.getElement(e+1,c),o.getElement(e+2,l);const t=Yt(a,c,l);i.setElement(e+0,t),i.setElement(e+1,t),i.setElement(e+2,t)}s.setAttribute("NORMAL",i),r++}r?n.debug("normals: Complete."):n.warn("normals: No qualifying primitives found. See debug output.")})}function Yt(e,t,n){const r=[t[0]-e[0],t[1]-e[1],t[2]-e[2]],o=[n[0]-e[0],n[1]-e[1],n[2]-e[2]];return fe([0,0,0],[r[1]*o[2]-r[2]*o[1],r[2]*o[0]-r[0]*o[2],r[0]*o[1]-r[1]*o[0]])}const en={animations:!0,meshes:!0},tn=(e=en)=>{const n=G({},en,e);return F("partition",async e=>{const r=e.getLogger();!1!==n.meshes&&function(e,t,n){const r=new Set(e.getRoot().listBuffers().map(e=>e.getURI()));e.getRoot().listMeshes().forEach((o,s)=>{if(Array.isArray(n.meshes)&&!n.meshes.includes(o.getName()))return void t.debug(`partition: Skipping mesh #${s} with name "${o.getName()}".`);t.debug(`partition: Creating buffer for mesh "${o.getName()}".`);const i=e.createBuffer(o.getName()).setURI(nn(o.getName()||"mesh",r));o.listPrimitives().forEach(e=>{const t=e.getIndices();t&&t.setBuffer(i),e.listAttributes().forEach(e=>e.setBuffer(i)),e.listTargets().forEach(e=>{e.listAttributes().forEach(e=>e.setBuffer(i))})})})}(e,r,n),!1!==n.animations&&function(e,t,n){const r=new Set(e.getRoot().listBuffers().map(e=>e.getURI()));e.getRoot().listAnimations().forEach((o,s)=>{if(Array.isArray(n.animations)&&!n.animations.includes(o.getName()))return void t.debug(`partition: Skipping animation #${s} with name "${o.getName()}".`);t.debug(`partition: Creating buffer for animation "${o.getName()}".`);const i=e.createBuffer(o.getName()).setURI(nn(o.getName()||"animation",r));o.listSamplers().forEach(e=>{const t=e.getInput(),n=e.getOutput();t&&t.setBuffer(i),n&&n.setBuffer(i)})})}(e,r,n),n.meshes||n.animations||r.warn("partition: Select animations or meshes to create a partition."),await e.transform(Le({propertyTypes:[t.BUFFER]})),r.debug("partition: Complete.")})};function nn(e,t){let n=`${e}.bin`,r=1;for(;t.has(n);)n=`${e}_${r++}.bin`;return n}function rn(){var e=new re(4);return re!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0),e[3]=1,e}function on(e,t){var n=an(e,t);return Math.acos(2*n*n-1)}function sn(e,t,n,r){var o,s,i,a,c,l=t[0],g=t[1],u=t[2],f=t[3],p=n[0],m=n[1],d=n[2],h=n[3];return(s=l*p+g*m+u*d+f*h)<0&&(s=-s,p=-p,m=-m,d=-d,h=-h),1-s>1e-6?(o=Math.acos(s),i=Math.sin(o),a=Math.sin((1-r)*o)/i,c=Math.sin(r*o)/i):(a=1-r,c=r),e[0]=a*l+c*p,e[1]=a*g+c*m,e[2]=a*u+c*d,e[3]=a*f+c*h,e}var an=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3]};ae(),ce(1,0,0),ce(0,1,0),rn(),rn(),ie();const cn={tolerance:1e-4},ln=(e=cn)=>{const n=G({},cn,e);return F("resample",async(e,r)=>{const o=new Set,s=e.getRoot().listAccessors().length,i=e.getLogger();let a=!1;for(const t of e.getRoot().listAnimations()){const e=new Map;for(const n of t.listChannels())e.set(n.getSampler(),n.getTargetPath());for(const r of t.listSamplers())"weights"!==e.get(r)?"STEP"!==r.getInterpolation()&&"LINEAR"!==r.getInterpolation()||(o.add(r.getInput()),o.add(r.getOutput()),gn(r,e.get(r),n)):a=!0}for(const e of Array.from(o.values()))e.listParents().some(e=>!(e instanceof c))||e.dispose();e.getRoot().listAccessors().length>s&&!B(r,"resample","dedup")&&await e.transform(Ne({propertyTypes:[t.ACCESSOR]})),a&&i.warn("resample: Skipped optimizing morph target keyframes, not yet supported."),i.debug("resample: Complete.")})};function gn(e,t,n){const r=e.getInput().clone().setSparse(!1),o=e.getOutput().clone().setSparse(!1),s=n.tolerance,a=e.getInterpolation(),c=r.getCount()-1,l=[],g=[],u=[],f=[];let p=1;for(let e=1;e<c;++e){const n=r.getScalar(p-1),c=r.getScalar(e),m=r.getScalar(e+1),d=(c-n)/(m-n);let h=!1;if(c!==m&&(1!==e||c!==r.getScalar(0)))if(o.getElement(p-1,f),o.getElement(e,g),o.getElement(e+1,u),"LINEAR"===a&&"rotation"===t){const e=sn(l,f,u,d),t=on(f,g)+on(g,u);h=!i.eq(g,e,s)||t+Number.EPSILON>=Math.PI}else if("LINEAR"===a){const e=fn(l,f,u,d);h=!i.eq(g,e,s)}else"STEP"===a&&(h=!i.eq(g,f)||!i.eq(g,u));h&&(e!==p&&(r.setScalar(p,r.getScalar(e)),o.setElement(p,o.getElement(e,l))),p++)}c>0&&(r.setScalar(p,r.getScalar(c)),o.setElement(p,o.getElement(c,l)),p++),p!==r.getCount()?(r.setArray(r.getArray().slice(0,p)),o.setArray(o.getArray().slice(0,p*o.getElementSize())),e.setInput(r),e.setOutput(o)):(r.dispose(),o.dispose())}function un(e,t,n){return e*(1-n)+t*n}function fn(e,t,n,r){for(let o=0;o<t.length;o++)e[o]=un(t[o],n[o],r);return e}const pn={name:"",fps:10,pattern:/.*/,sort:!0};function mn(e=pn){const t=G({},pn,e);return F("sequence",e=>{const n=e.getLogger(),r=e.getRoot(),o=t.fps,s=r.listNodes().filter(e=>e.getName().match(t.pattern));t.sort&&s.sort((e,t)=>e.getName()>t.getName()?1:-1);const i=e.createAnimation(t.name),a=r.listBuffers()[0];s.forEach((t,n)=>{let r,c;0===n?(r=[n/o,(n+1)/o],c=[1,1,1,0,0,0]):n===s.length-1?(r=[(n-1)/o,n/o],c=[0,0,0,1,1,1]):(r=[(n-1)/o,n/o,(n+1)/o],c=[0,0,0,1,1,1,0,0,0]);const g=e.createAccessor().setArray(new Float32Array(r)).setBuffer(a),u=e.createAccessor().setArray(new Float32Array(c)).setBuffer(a).setType(y.Type.VEC3),f=e.createAnimationSampler().setInterpolation(T.Interpolation.STEP).setInput(g).setOutput(u),p=e.createAnimationChannel().setTargetNode(t).setTargetPath(l.TargetPath.SCALE).setSampler(f);i.addSampler(f).addChannel(p)}),n.debug("sequence: Complete.")})}const dn={tolerance:1e-4,overwrite:!0};function hn(e=dn){const n=G({},dn,e);if(n.tolerance>.1||n.tolerance<0)throw new Error("weld: Requires 0 ≤ tolerance ≤ 0.1");return F("weld",async(e,r)=>{const o=e.getLogger();for(const t of e.getRoot().listMeshes())for(const r of t.listPrimitives())An(e,r,n);B(r,"weld","dedup")||await e.transform(Ne({propertyTypes:[t.ACCESSOR]})),o.debug("weld: Complete.")})}function An(t,n,r){n.getIndices()&&!r.overwrite||n.getMode()!==e.Mode.POINTS&&(0===r.tolerance?function(e,t){if(t.getIndices())return;const n=t.listAttributes()[0],r=n.getCount(),o=n.getBuffer(),s=e.createAccessor().setBuffer(o).setType(y.Type.SCALAR).setArray(Z(r));t.setIndices(s)}(t,n):function(e,t,n){const r=e.getLogger(),o=t.getAttribute("POSITION"),s=t.getIndices()||e.createAccessor().setArray(Z(o.getCount())),i=new Uint32Array(new Set(s.getArray())),a=Math.max(n.tolerance,Number.EPSILON),c={};for(const e of t.listSemantics()){const n=t.getAttribute(e);c[e]=Sn(e,n,a)}var l;r.debug(`weld: Tolerance thresholds: ${l=c,Object.entries(l).map(([e,t])=>`${e}=${t}`).join(", ")}`);const g=[0,0,0],u=[0,0,0];i.sort((e,t)=>(o.getElement(e,g),o.getElement(t,u),g[0]>u[0]?1:-1));const f=Z(i.length),p=Z(i.length),m=o.getCount();let d=0,h=0;for(let e=0;e<i.length;e++){const n=i[e];for(let r=e-1;r>=0;r--){const e=f[i[r]];if(o.getElement(n,g),o.getElement(e,u),Math.abs(g[0]-u[0])>c.POSITION)break;h++;const s=t.listSemantics().every(r=>In(t.getAttribute(r),n,e,c[r])),a=t.listTargets().every(t=>t.listSemantics().every(r=>In(t.getAttribute(r),n,e,c[r])));if(s&&a){f[n]=e;break}}p[n]=f[n]===n?d++:p[f[n]]}r.debug(`weld: Iterations per vertex: ${Math.round(h/i.length)} (avg)`),r.debug(`weld: ${V(m,d)} vertices.`);const A=s.getCount(),y=Z(A,i.length);for(let e=0;e<A;e++)y[e]=p[s.getScalar(e)];t.setIndices(s.clone().setArray(y)),1===s.listParents().length&&s.dispose();for(const e of t.listAttributes())yn(t,e,p,d);for(const e of t.listTargets())for(const t of e.listAttributes())yn(e,t,p,d)}(t,n,r))}function yn(e,t,n,r){const o=(a=t.getArray(),c=r*t.getElementSize(),new(0,a.constructor)(c)),s=t.clone().setArray(o),i=new Uint8Array(r);var a,c;for(let e=0,r=[];e<n.length;e++)i[n[e]]||(s.setElement(n[e],t.getElement(e,r)),i[n[e]]=1);e.swap(t,s),1===t.listParents().length&&t.dispose()}const Tn=[],En=[];function Sn(e,t,n){return"NORMAL"===e||"TANGENT"===e?.5:e.startsWith("COLOR_")?.01:e.startsWith("TEXCOORD_")?1e-4:e.startsWith("JOINTS_")?0:e.startsWith("WEIGHTS_")?.01:(Tn.length=En.length=0,t.getMinNormalized(Tn),t.getMaxNormalized(En),n*(Math.max(...En)-Math.min(...Tn)||1))}function In(e,t,n,r,o){e.getElement(t,Tn),e.getElement(n,En);for(let t=0,n=e.getElementSize();t<n;t++)if(Math.abs(Tn[t]-En[t])>r)return!1;return!0}const Mn={ratio:.5,error:.001,lockBorder:!1},wn=n=>{const r=G({},Mn,n),o=r.simplifier;if(!o)throw new Error('simplify: simplifier dependency required — install "meshoptimizer".');return F("simplify",async(n,s)=>{const i=n.getLogger();await o.ready,await n.transform(hn({overwrite:!1}));for(const t of n.getRoot().listMeshes())for(const o of t.listPrimitives())o.getMode()===e.Mode.TRIANGLES?bn(n,o,r):i.warn(`simplify: Skipping primitive of mesh "${t.getName()}": Requires TRIANGLES draw mode.`);B(s,"simplify","dedup")||await n.transform(Ne({propertyTypes:[t.ACCESSOR]})),i.debug("simplify: Complete.")})};function bn(e,t,n){const r=G({},Mn,n),o=r.simplifier,s=e.getLogger(),i=t.getAttribute("POSITION"),a=t.getIndices(),c=i.getCount();let l=i.getArray(),g=a.getArray();if(i.getComponentType()!==y.ComponentType.FLOAT)if(i.getNormalized()){const e=l,t=new Float32Array(e.length);for(let n=0,r=i.getCount(),o=[];n<r;n++)o=i.getElement(n,o),i.setArray(t).setElement(n,o).setArray(e);l=t}else l=new Float32Array(l);a.getComponentType()!==y.ComponentType.UNSIGNED_INT&&(g=new Uint32Array(g));const u=3*Math.floor(r.ratio*c/3),[f,p]=o.simplify(g,l,3,u,r.error,r.lockBorder?["LockBorder"]:[]),[m,d]=o.compactMesh(f);s.debug(`simplify: ${V(i.getCount(),d)} vertices, error: ${p.toFixed(4)}.`);for(const e of X(t)){const n=e.clone();J(n,m,d),K(t,e,n),1===e.listParents().length&&e.dispose()}const h=a.clone();return h.setArray(c<=65534?new Uint16Array(f):f),t.setIndices(h),1===a.listParents().length&&a.dispose(),t}const Nn={ratio:1/3};function Rn(e=Nn){const t=G({},Nn,e).ratio;if(t<0||t>1)throw new Error("sparse: Ratio must be between 0 and 1.");return F("sparse",e=>{const n=e.getRoot(),r=e.getLogger();let o=0;for(const e of n.listAccessors()){const n=e.getCount(),r=Array(e.getElementSize()).fill(0),s=Array(e.getElementSize()).fill(0);let a=0;for(let o=0;o<n&&(e.getElement(o,s),i.eq(s,r,0)||a++,!(a/n>=t));o++);const c=a/n<t;c!==e.getSparse()&&(e.setSparse(c),o++)}r.debug(`sparse: Updated ${o} accessors.`),r.debug("sparse: Complete.")})}const Cn="textureResize";var On;!function(e){e.LANCZOS3="lanczos3",e.LANCZOS2="lanczos2"}(On||(On={}));const vn={size:[2048,2048],filter:On.LANCZOS3,pattern:null,slots:null};function Pn(e=vn){const t=G({},vn,e);return F(Cn,async e=>{const n=e.getLogger();for(const r of e.getRoot().listTextures()){const e=r.getName(),o=r.getURI();if(t.pattern&&!t.pattern.test(e)&&!t.pattern.test(o)){n.debug(`${Cn}: Skipping, excluded by "pattern" parameter.`);continue}if("image/png"!==r.getMimeType()&&"image/jpeg"!==r.getMimeType()){n.warn(`${Cn}: Skipping, unsupported texture type "${r.getMimeType()}".`);continue}const s=yt(r);if(t.slots&&!s.some(e=>{var n;return null==(n=t.slots)?void 0:n.test(e)})){n.debug(`${Cn}: Skipping, [${s.join(", ")}] excluded by "slots" parameter.`);continue}const[i,a]=t.size,[c,l]=r.getSize();if(c<=i&&l<=a){n.debug(`${Cn}: Skipping, not within size range.`);continue}let g=c,u=l;g>i&&(u=Math.floor(u*(i/g)),g=i),u>a&&(g=Math.floor(g*(a/u)),u=a);const f=r.getImage(),p=await S(f,r.getMimeType()),m=q(new Uint8Array(g*u*4),[g,u,4]);n.debug(`${Cn}: Resizing "${o||e}", ${p.shape} → ${m.shape}...`),n.debug(`${Cn}: Slots → [${s.join(", ")}]`);try{t.filter===On.LANCZOS3?_(p,m):k(p,m)}catch(t){if(t instanceof Error){n.warn(`${Cn}: Failed to resize "${o||e}": "${t.message}".`);continue}throw t}r.setImage(await I(m,r.getMimeType()))}n.debug(`${Cn}: Complete.`)})}const $n="textureCompress",xn=["jpeg","png","webp","avif"],zn=["image/jpeg","image/png","image/webp","image/avif"],Ln={resizeFilter:On.LANCZOS3,pattern:null,formats:null,slots:null,quality:null,effort:null,lossless:!1,nearLossless:!1},qn=function(e){const t=G({},Ln,e),n=t.encoder,r=t.targetFormat,o=t.resize,s=t.resizeFilter,i=t.pattern,c=t.formats,l=t.slots;if(!n)throw new Error(`${r}: encoder dependency required — install "sharp".`);return F($n,async e=>{const g=e.getLogger(),u=e.getRoot().listTextures();await Promise.all(u.map(async(u,f)=>{const m=yt(u),d=ht(u),A=u.getURI()||u.getName()||`${f+1}/${e.getRoot().listTextures().length}`,y=`${$n}(${A})`;if(!zn.includes(u.getMimeType()))return void g.debug(`${y}: Skipping, unsupported texture type "${u.getMimeType()}".`);if(i&&!i.test(u.getName())&&!i.test(u.getURI()))return void g.debug(`${y}: Skipping, excluded by "pattern" parameter.`);if(c&&!c.test(u.getMimeType()))return void g.debug(`${y}: Skipping, "${u.getMimeType()}" excluded by "formats" parameter.`);if(l&&m.length&&!m.some(e=>l.test(e)))return void g.debug(`${y}: Skipping, [${m.join(", ")}] excluded by "slots" parameter.`);if("jpeg"===t.targetFormat&&d&h.A)return void g.warn(`${y}: Skipping, [${m.join(", ")}] requires alpha channel.`);const T=function(e){const t=e.getMimeType(),n=t.split("/").pop();if(!n||!xn.includes(n))throw new Error(`Unknown MIME type "${t}".`);return n}(u),E=r||T,S=u.getMimeType(),I=`image/${E}`;g.debug(`${y}: Format = ${T} → ${E}`),g.debug(`${y}: Slots = [${m.join(", ")}]`);let M={};switch(E){case"jpeg":M={quality:t.quality};break;case"png":M={quality:t.quality,effort:_n(t.effort,100,10)};break;case"webp":M={quality:t.quality,effort:_n(t.effort,100,6),lossless:t.lossless,nearLossless:t.nearLossless};break;case"avif":M={quality:t.quality,effort:_n(t.effort,100,9),lossless:t.lossless}}const w=u.getImage(),b=n(w).toFormat(E,M);o&&b.resize(o[0],o[1],{fit:"inside",kernel:s,withoutEnlargement:!0});const N=a.toView(await b.toBuffer()),R=w.byteLength,C=N.byteLength;let O="";if(S===I&&C>=R)O=" (SKIPPED)";else if(S===I)u.setImage(N);else{const e=p.mimeTypeToExtension(S),t=p.mimeTypeToExtension(I),n=u.getURI().replace(new RegExp(`\\.${e}$`),`.${t}`);u.setImage(N).setMimeType(I).setURI(n)}g.debug(`${y}: Size = ${j(R)} → ${j(C)}${O}`)}));const f=e.createExtension(v);u.some(e=>"image/webp"===e.getMimeType())?f.setRequired(!0):f.dispose();const m=e.createExtension(P);u.some(e=>"image/avif"===e.getMimeType())?m.setRequired(!0):m.dispose(),g.debug(`${$n}: Complete.`)})};function _n(e,t,n){return null==e?null:Math.round(e/t*n)}const kn={overwrite:!1};function Gn(e=kn){if(!e.generateTangents)throw new Error('tangents: generateTangents callback required — install "mikktspace".');const t=G({},kn,e);return F("tangents",e=>{const n=e.getLogger(),r=new Map,o=new Map;let s=0;for(const i of e.getRoot().listMeshes()){const a=i.getName(),c=i.listPrimitives();for(let i=0;i<c.length;i++){const l=c[i];if(!Bn(l,n,a,i,t.overwrite))continue;const g=Fn(l),u=l.getAttribute("POSITION").getArray(),f=l.getAttribute("NORMAL").getArray(),p=l.getAttribute(g).getArray(),m=r.get(u)||E();r.set(u,m);const d=r.get(f)||E();r.set(f,d);const h=r.get(p)||E();r.set(p,h);const A=l.getAttribute("TANGENT");A&&2===A.listParents().length&&A.dispose();const y=`${m}|${d}|${h}`;let T=o.get(y);if(T){n.debug(`tangents: Found cache for primitive ${i} of mesh "${a}".`),l.setAttribute("TANGENT",T),s++;continue}n.debug(`tangents: Generating for primitive ${i} of mesh "${a}".`);const S=l.getAttribute("POSITION").getBuffer(),I=t.generateTangents(u instanceof Float32Array?u:new Float32Array(u),f instanceof Float32Array?f:new Float32Array(f),p instanceof Float32Array?p:new Float32Array(p));for(let e=3;e<I.length;e+=4)I[e]*=-1;T=e.createAccessor().setBuffer(S).setArray(I).setType("VEC4"),l.setAttribute("TANGENT",T),o.set(y,T),s++}}s?n.debug("tangents: Complete."):n.warn("tangents: No qualifying primitives found. See debug output.")})}function Fn(e){const t=e.getMaterial();if(!t)return"TEXCOORD_0";const n=t.getNormalTextureInfo();if(!n)return"TEXCOORD_0";const r=`TEXCOORD_${n.getTexCoord()}`;return e.getAttribute(r)?r:"TEXCOORD_0"}function Bn(t,n,r,o,s){return t.getMode()===e.Mode.TRIANGLES&&t.getAttribute("POSITION")&&t.getAttribute("NORMAL")&&t.getAttribute("TEXCOORD_0")?t.getAttribute("TANGENT")&&!s?(n.debug(`tangents: Skipping primitive ${o} of mesh "${r}": TANGENT found.`),!1):!t.getIndices()||(n.warn(`tangents: Skipping primitive ${o} of mesh "${r}": primitives must be unwelded.`),!1):(n.debug(`tangents: Skipping primitive ${o} of mesh "${r}": primitives must have attributes=[POSITION, NORMAL, TEXCOORD_0] and mode=TRIANGLES.`),!1)}const Un=()=>e=>{const t=e.createExtension($).createUnlit();e.getRoot().listMaterials().forEach(e=>{e.setExtension("KHR_materials_unlit",t)})},Wn={},Hn=(e=Wn)=>(G({},Wn,e),F("unpartition",async e=>{const t=e.getLogger(),n=e.getRoot().listBuffers()[0];e.getRoot().listAccessors().forEach(e=>e.setBuffer(n)),e.getRoot().listBuffers().forEach((e,t)=>t>0?e.dispose():null),t.debug("unpartition: Complete.")}));export{$e as DRACO_DEFAULTS,ke as FLATTEN_DEFAULTS,gt as JOIN_DEFAULTS,Ht as MESHOPT_DEFAULTS,$t as QUANTIZE_DEFAULTS,Mn as SIMPLIFY_DEFAULTS,Ln as TEXTURE_COMPRESS_DEFAULTS,vn as TEXTURE_RESIZE_DEFAULTS,On as TextureResizeFilter,dn as WELD_DEFAULTS,ee as center,ne as clearNodeParent,Ie as clearNodeTransform,we as colorspace,St as createLayoutPlan,F as createTransform,Ne as dedup,Oe as dequantize,xe as draco,Ge as flatten,W as getGLPrimitiveCount,Fe as getNodeScene,ht as getTextureChannelMask,Be as inspect,Qe as instance,B as isTransformPending,ut as join,nt as joinPrimitives,te as listNodeScenes,dt as listTextureChannels,At as listTextureInfo,yt as listTextureSlots,jt as meshopt,Vt as metalRough,Qt as normals,tn as partition,Le as prune,xt as quantize,Et as reorder,ln as resample,mn as sequence,wn as simplify,bn as simplifyPrimitive,It as sortPrimitiveWeights,Rn as sparse,Gn as tangents,qn as textureCompress,Pn as textureResize,Ee as transformMesh,he as transformPrimitive,Un as unlit,Hn as unpartition,Kt as unweld,hn as weld,An as weldPrimitive}; | ||
import{Primitive as e,PropertyType as t,Document as n,getBounds as r,Scene as o,PrimitiveTarget as s,MathUtils as i,BufferUtils as a,Root as c,AnimationChannel as l,Texture as g,TextureInfo as u,ExtensionProperty as f,ImageUtils as p,ComponentTypeToTypedArray as m,Material as d,TextureChannel as h,Node as A,Accessor as y,AnimationSampler as E,uuid as T}from"@gltf-transform/core";import{getPixels as S,savePixels as I}from"ndarray-pixels";import{KHRMeshQuantization as M,KHRDracoMeshCompression as w,EXTMeshGPUInstancing as b,EXTMeshoptCompression as N,KHRMaterialsIOR as R,KHRMaterialsSpecular as C,KHRMaterialsPBRSpecularGlossiness as O,EXTTextureWebP as v,EXTTextureAVIF as P,KHRMaterialsUnlit as $}from"@gltf-transform/extensions";import{read as x,KHR_DF_MODEL_ETC1S as z,KHR_DF_MODEL_UASTC as L}from"ktx-parse";import q from"ndarray";import{lanczos3 as _,lanczos2 as k}from"ndarray-lanczos";function G(){return(G=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function F(e,t){return Object.defineProperty(t,"name",{value:e}),t}function B(e,t,n){return!!e&&e.stack.lastIndexOf(t)<e.stack.lastIndexOf(n)}async function U(e,t,n){if(!e)return null;const r=e.getImage();if(!r)return null;const o=await S(r,e.getMimeType());for(let e=0;e<o.shape[0];++e)for(let t=0;t<o.shape[1];++t)n(o,e,t);const s=await I(o,"image/png");return t.setImage(s).setMimeType("image/png")}function W(t){const n=t.getIndices(),r=t.getAttribute("POSITION");switch(t.getMode()){case e.Mode.POINTS:return r.getCount();case e.Mode.LINES:return n?n.getCount()/2:r.getCount()/2;case e.Mode.LINE_LOOP:return r.getCount();case e.Mode.LINE_STRIP:return r.getCount()-1;case e.Mode.TRIANGLES:return n?n.getCount()/3:r.getCount()/3;case e.Mode.TRIANGLE_STRIP:case e.Mode.TRIANGLE_FAN:return r.getCount()-2;default:throw new Error("Unexpected mode: "+t.getMode())}}class H{constructor(){this._map=new Map}get size(){return this._map.size}has(e){return this._map.has(e)}add(e,t){let n=this._map.get(e);return n||(n=new Set,this._map.set(e,n)),n.add(t),this}get(e){return this._map.get(e)||new Set}keys(){return this._map.keys()}}function j(e,t=2){if(0===e)return"0 Bytes";const n=t<0?0:t,r=Math.floor(Math.log(e)/Math.log(1e3));return parseFloat((e/Math.pow(1e3,r)).toFixed(n))+" "+["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"][r]}function D(e){return e.toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}function V(e,t){return`${D(e)} → ${D(t)} (${function(e,t,n=2){return(e>t?"–":"+")+(Math.abs(e-t)/e*100).toFixed(n)+"%"}(e,t)})`}function X(e){const t=[];for(const n of e.listAttributes())t.push(n);for(const n of e.listTargets())for(const e of n.listAttributes())t.push(e);return Array.from(new Set(t))}function K(e,t,n){e.swap(t,n);for(const r of e.listTargets())r.swap(t,n)}function J(e,t,n){const r=e.getElementSize(),o=e.getCount(),s=e.getArray(),i=s.slice(0,n*r);for(let e=0;e<o;e++)for(let n=0;n<r;n++)i[t[e]*r+n]=s[e*r+n];e.setArray(i)}function Z(e,t=e){const n=t<=65534?new Uint16Array(e):new Uint32Array(e);for(let e=0;e<n.length;e++)n[e]=e;return n}function Q(e){const t=n.fromGraph(e.getGraph()),r=e.getMaterial();return`${t.getRoot().listMaterials().indexOf(r)}|${e.getMode()}|${!!e.getIndices()}|${e.listSemantics().sort().map(t=>{const n=e.getAttribute(t);return`${t}:${n.getElementSize()}:${n.getComponentType()}`}).join("+")}|${e.listTargets().map(t=>t.listSemantics().sort().map(t=>{const n=e.getAttribute(t);return`${t}:${n.getElementSize()}:${n.getComponentType()}`}).join("+")).join("~")}`}const Y={pivot:"center"};function ee(e=Y){const t=G({},Y,e);return F("center",e=>{const n=e.getLogger(),o=e.getRoot(),s=o.listAnimations().length>0||o.listSkins().length>0;e.getRoot().listScenes().forEach((i,a)=>{let c;if(n.debug(`center: Scene ${a+1} / ${o.listScenes().length}.`),"string"==typeof t.pivot){const e=r(i);c=[(e.max[0]-e.min[0])/2+e.min[0],(e.max[1]-e.min[1])/2+e.min[1],(e.max[2]-e.min[2])/2+e.min[2]],"above"===t.pivot&&(c[1]=e.max[1]),"below"===t.pivot&&(c[1]=e.min[1])}else c=t.pivot;n.debug(`center: Pivot "${c.join(", ")}".`);const l=[-1*c[0],-1*c[1],-1*c[2]];if(s){n.debug("center: Model contains animation or skin. Adding a wrapper node.");const t=e.createNode("Pivot").setTranslation(l);i.listChildren().forEach(e=>t.addChild(e)),i.addChild(t)}else n.debug("center: Skipping wrapper, offsetting all root nodes."),i.listChildren().forEach(e=>{const t=e.getTranslation();e.setTranslation([t[0]+l[0],t[1]+l[1],t[2]+l[2]])})}),n.debug("center: Complete.")})}function te(e){const t=new Set;let n,r=e;for(;n=r.getParentNode();){if(t.has(n))throw new Error("Circular dependency in scene graph.");t.add(n),r=n}return r.listParents().filter(e=>e instanceof o)}function ne(e){const t=te(e),n=e.getParentNode();if(!n)return e;e.setMatrix(e.getWorldMatrix()),n.removeChild(e);for(const n of t)n.addChild(e);return e}var re="undefined"!=typeof Float32Array?Float32Array:Array;function oe(e,t){var n=t[0],r=t[1],o=t[2],s=t[3],i=t[4],a=t[5],c=t[6],l=t[7],g=t[8],u=t[9],f=t[10],p=t[11],m=t[12],d=t[13],h=t[14],A=t[15],y=n*a-r*i,E=n*c-o*i,T=n*l-s*i,S=r*c-o*a,I=r*l-s*a,M=o*l-s*c,w=g*d-u*m,b=g*h-f*m,N=g*A-p*m,R=u*h-f*d,C=u*A-p*d,O=f*A-p*h,v=y*O-E*C+T*R+S*N-I*b+M*w;return v?(e[0]=(a*O-c*C+l*R)*(v=1/v),e[1]=(o*C-r*O-s*R)*v,e[2]=(d*M-h*I+A*S)*v,e[3]=(f*I-u*M-p*S)*v,e[4]=(c*N-i*O-l*b)*v,e[5]=(n*O-o*N+s*b)*v,e[6]=(h*T-m*M-A*E)*v,e[7]=(g*M-f*T+p*E)*v,e[8]=(i*C-a*N+l*w)*v,e[9]=(r*N-n*C-s*w)*v,e[10]=(m*I-d*T+A*y)*v,e[11]=(u*T-g*I-p*y)*v,e[12]=(a*b-i*R-c*w)*v,e[13]=(n*R-r*b+o*w)*v,e[14]=(d*E-m*S-h*y)*v,e[15]=(g*S-u*E+f*y)*v,e):null}function se(e,t,n){var r=t[0],o=t[1],s=t[2],i=t[3],a=t[4],c=t[5],l=t[6],g=t[7],u=t[8],f=t[9],p=t[10],m=t[11],d=t[12],h=t[13],A=t[14],y=t[15],E=n[0],T=n[1],S=n[2],I=n[3];return e[0]=E*r+T*a+S*u+I*d,e[1]=E*o+T*c+S*f+I*h,e[2]=E*s+T*l+S*p+I*A,e[3]=E*i+T*g+S*m+I*y,e[4]=(E=n[4])*r+(T=n[5])*a+(S=n[6])*u+(I=n[7])*d,e[5]=E*o+T*c+S*f+I*h,e[6]=E*s+T*l+S*p+I*A,e[7]=E*i+T*g+S*m+I*y,e[8]=(E=n[8])*r+(T=n[9])*a+(S=n[10])*u+(I=n[11])*d,e[9]=E*o+T*c+S*f+I*h,e[10]=E*s+T*l+S*p+I*A,e[11]=E*i+T*g+S*m+I*y,e[12]=(E=n[12])*r+(T=n[13])*a+(S=n[14])*u+(I=n[15])*d,e[13]=E*o+T*c+S*f+I*h,e[14]=E*s+T*l+S*p+I*A,e[15]=E*i+T*g+S*m+I*y,e}function ie(){var e=new re(9);return re!=Float32Array&&(e[1]=0,e[2]=0,e[3]=0,e[5]=0,e[6]=0,e[7]=0),e[0]=1,e[4]=1,e[8]=1,e}function ae(){var e=new re(3);return re!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0),e}function ce(e,t,n){var r=new re(3);return r[0]=e,r[1]=t,r[2]=n,r}function le(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e[2]=Math.min(t[2],n[2]),e}function ge(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e[2]=Math.max(t[2],n[2]),e}function ue(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e[2]=t[2]*n,e}function fe(e,t){var n=t[0],r=t[1],o=t[2],s=n*n+r*r+o*o;return s>0&&(s=1/Math.sqrt(s)),e[0]=t[0]*s,e[1]=t[1]*s,e[2]=t[2]*s,e}function pe(e,t,n){var r=t[0],o=t[1],s=t[2],i=n[3]*r+n[7]*o+n[11]*s+n[15];return e[0]=(n[0]*r+n[4]*o+n[8]*s+n[12])/(i=i||1),e[1]=(n[1]*r+n[5]*o+n[9]*s+n[13])/i,e[2]=(n[2]*r+n[6]*o+n[10]*s+n[14])/i,e}function me(e,t,n){var r=t[0],o=t[1],s=t[2];return e[0]=r*n[0]+o*n[3]+s*n[6],e[1]=r*n[1]+o*n[4]+s*n[7],e[2]=r*n[2]+o*n[5]+s*n[8],e}function de(){var e=new re(4);return re!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0,e[3]=0),e}function he(e,t,n=new Set){var r;const o=e.getAttribute("POSITION"),s=(null==(r=e.getIndices())?void 0:r.getArray())||Z(o.getCount());o&&Ae(t,o,s,new Set(n));const i=e.getAttribute("NORMAL");i&&ye(t,i,s,new Set(n));const a=e.getAttribute("TANGENT");a&&Ee(t,a,s,new Set(n));for(const r of e.listTargets()){const e=r.getAttribute("POSITION");e&&Ae(t,e,s,new Set(n));const o=r.getAttribute("NORMAL");o&&ye(t,o,s,new Set(n));const i=r.getAttribute("TANGENT");i&&Ee(t,i,s,new Set(n))}for(let e=0;e<s.length;e++)n.add(s[e])}function Ae(e,t,n,r){const o=new Float32Array(3*t.getCount()),s=t.getElementSize();for(let e=0,n=[],r=t.getCount();e<r;e++)o.set(t.getElement(e,n),e*s);const i=ae();for(let s=0;s<n.length;s++){const a=n[s];r.has(a)||(t.getElement(a,i),pe(i,i,e),o.set(i,3*a),r.add(a))}t.setArray(o).setNormalized(!1)}function ye(e,t,n,r){const o=ie();var s,i;(s=o)[0]=(i=e)[0],s[1]=i[1],s[2]=i[2],s[3]=i[4],s[4]=i[5],s[5]=i[6],s[6]=i[8],s[7]=i[9],s[8]=i[10],function(e,t){var n=t[0],r=t[1],o=t[2],s=t[3],i=t[4],a=t[5],c=t[6],l=t[7],g=t[8],u=g*i-a*l,f=-g*s+a*c,p=l*s-i*c,m=n*u+r*f+o*p;m&&(e[0]=u*(m=1/m),e[1]=(-g*r+o*l)*m,e[2]=(a*r-o*i)*m,e[3]=f*m,e[4]=(g*n-o*c)*m,e[5]=(-a*n+o*s)*m,e[6]=p*m,e[7]=(-l*n+r*c)*m,e[8]=(i*n-r*s)*m)}(o,o),function(e,t){if(e===t){var n=t[1],r=t[2],o=t[5];e[1]=t[3],e[2]=t[6],e[3]=n,e[5]=t[7],e[6]=r,e[7]=o}else e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8]}(o,o);const a=ae();for(let e=0;e<n.length;e++){const s=n[e];r.has(s)||(t.getElement(s,a),me(a,a,o),fe(a,a),t.setElement(s,a),r.add(s))}}function Ee(e,t,n,r){const o=ae(),s=de();for(let i=0;i<n.length;i++){const a=n[i];if(r.has(a))continue;t.getElement(a,s);const[c,l,g]=s;o[0]=e[0]*c+e[4]*l+e[8]*g,o[1]=e[1]*c+e[5]*l+e[9]*g,o[2]=e[2]*c+e[6]*l+e[10]*g,fe(o,o),s[0]=o[0],s[1]=o[1],s[2]=o[2],t.setElement(a,s),r.add(a)}}function Te(n,r,o=!1,i){for(const e of n.listPrimitives())if(e.listParents().some(e=>e.propertyType===t.MESH&&e!==n)){const t=e.clone();n.swap(e,t);for(const e of t.listTargets()){const n=e.clone();t.swap(e,n)}}if(!o){const t=new Set([...n.listPrimitives(),...n.listPrimitives().flatMap(e=>e.listTargets())]),r=new Map;for(const o of n.listPrimitives())for(const n of X(o))n.listParents().some(n=>(n instanceof e||n instanceof s)&&!t.has(n))&&!r.has(n)&&r.set(n,n.clone());for(const e of t)for(const[t,n]of r)e.swap(t,n)}i=i||new Set;for(const e of n.listPrimitives())he(e,r,i)}Math.hypot||(Math.hypot=function(){for(var e=0,t=arguments.length;t--;)e+=arguments[t]*arguments[t];return Math.sqrt(e)}),ae(),de();const Se=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];function Ie(e){const t=e.getMesh(),n=e.getMatrix();t&&!i.eq(n,Se)&&Te(t,n);for(const t of e.listChildren()){const e=t.getMatrix();se(e,e,n),t.setMatrix(e)}return e.setMatrix(Se)}const Me="colorspace";function we(e){return F(Me,t=>{const n=t.getLogger();if("linear"===e.inputEncoding)return void n.info(`${Me}: Vertex colors already linear. Skipping conversion.`);if("sRGB"!==e.inputEncoding)return void n.error(`${Me}: Unknown input encoding "${e.inputEncoding}" – should be "sRGB" or "linear". Skipping conversion.`);const r=new Set;function o(e){return e<.04045?.0773993808*e:Math.pow(.9478672986*e+.0521327014,2.4)}function s(e){const t=[0,0,0];let n;for(let s=0;n=e.getAttribute(`COLOR_${s}`);s++)if(!r.has(n)){for(let e=0;e<n.getCount();e++)n.getElement(e,t),t[0]=o(t[0]),t[1]=o(t[1]),t[2]=o(t[2]),n.setElement(e,t);r.add(n)}}t.getRoot().listMeshes().forEach(e=>e.listPrimitives().forEach(s)),n.debug(`${Me}: Complete.`)})}const be={propertyTypes:[t.ACCESSOR,t.MESH,t.TEXTURE,t.MATERIAL]},Ne=function(e=be){const n=G({},be,e),r=new Set(n.propertyTypes);for(const e of n.propertyTypes)if(!be.propertyTypes.includes(e))throw new Error(`dedup: Unsupported deduplication on type "${e}".`);return F("dedup",e=>{const n=e.getLogger();r.has(t.ACCESSOR)&&function(e,t){const n=new Set,r=new Set,o=new Set,s=new Set,i=t.getRoot().listMeshes();i.forEach(e=>{e.listPrimitives().forEach(e=>{e.listAttributes().forEach(e=>r.add(e));const t=e.getIndices();t&&n.add(t)})});for(const e of t.getRoot().listAnimations())for(const t of e.listSamplers()){const e=t.getInput(),n=t.getOutput();e&&o.add(e),n&&s.add(n)}function c(e){const t=new Map;for(let n=0;n<e.length;n++){const r=e[n],o=a.toView(r.getArray());if(!t.has(r))for(let n=0;n<e.length;n++){const s=e[n];r!==s&&(t.has(s)||r.getType()===s.getType()&&r.getComponentType()===s.getComponentType()&&r.getCount()===s.getCount()&&r.getNormalized()===s.getNormalized()&&a.equals(o,a.toView(s.getArray()))&&t.set(s,r))}}return t}const l=c(Array.from(n));e.debug(`dedup: Found ${l.size} duplicates among ${n.size} indices.`);const g=c(Array.from(r));e.debug(`dedup: Found ${g.size} duplicates among ${r.size} attributes.`);const u=c(Array.from(o)),f=c(Array.from(s));e.debug(`dedup: Found ${u.size+f.size} duplicates among ${o.size+s.size} animation accessors.`),i.forEach(e=>{e.listPrimitives().forEach(e=>{e.listAttributes().forEach(t=>{g.has(t)&&e.swap(t,g.get(t))});const t=e.getIndices();t&&l.has(t)&&e.swap(t,l.get(t))})}),Array.from(l.keys()).forEach(e=>e.dispose()),Array.from(g.keys()).forEach(e=>e.dispose());for(const e of t.getRoot().listAnimations())for(const t of e.listSamplers()){const e=t.getInput(),n=t.getOutput();e&&u.has(e)&&t.swap(e,u.get(e)),n&&f.has(n)&&t.swap(n,f.get(n))}Array.from(u.keys()).forEach(e=>e.dispose()),Array.from(f.keys()).forEach(e=>e.dispose())}(n,e),r.has(t.TEXTURE)&&function(e,t){const n=t.getRoot(),r=n.listTextures(),o=new Map;for(let e=0;e<r.length;e++){const t=r[e],n=t.getImage();if(!o.has(t))for(let e=0;e<r.length;e++){const s=r[e],i=s.getImage();if(t===s)continue;if(o.has(s))continue;if(t.getMimeType()!==s.getMimeType())continue;const c=t.getSize(),l=s.getSize();c&&l&&c[0]===l[0]&&c[1]===l[1]&&n&&i&&a.equals(n,i)&&o.set(s,t)}}e.debug(`dedup: Found ${o.size} duplicates among ${n.listTextures().length} textures.`),Array.from(o.entries()).forEach(([e,t])=>{e.listParents().forEach(n=>{n instanceof c||n.swap(e,t)}),e.dispose()})}(n,e),r.has(t.MATERIAL)&&function(e,t){const n=t.getRoot(),r=n.listMaterials(),o=new Map,s=new Set(["name"]);for(let e=0;e<r.length;e++){const t=r[e];if(!o.has(t))for(let e=0;e<r.length;e++){const n=r[e];t!==n&&(o.has(n)||t.equals(n,s)&&o.set(n,t))}}e.debug(`dedup: Found ${o.size} duplicates among ${n.listMaterials().length} materials.`),Array.from(o.entries()).forEach(([e,t])=>{e.listParents().forEach(n=>{n instanceof c||n.swap(e,t)}),e.dispose()})}(n,e),r.has(t.MESH)&&function(e,n){const r=n.getRoot(),o=new Map;r.listAccessors().forEach((e,t)=>o.set(e,t)),r.listMaterials().forEach((e,t)=>o.set(e,t));const s=r.listMeshes().length,i=new Map;for(const e of r.listMeshes()){const n=[];for(const t of e.listPrimitives())n.push(Re(t,o));const r=n.join(";");if(i.has(r)){const n=i.get(r);e.listParents().forEach(r=>{r.propertyType!==t.ROOT&&r.swap(e,n)}),e.dispose()}else i.set(r,e)}e.debug(`dedup: Found ${s-i.size} duplicates among ${s} meshes.`)}(n,e),n.debug("dedup: Complete.")})};function Re(t,n){const r=[];for(const e of t.listSemantics()){const o=t.getAttribute(e);r.push(e+":"+n.get(o))}if(t instanceof e){const e=t.getIndices();e&&r.push("indices:"+n.get(e));const o=t.getMaterial();o&&r.push("material:"+n.get(o)),r.push("mode:"+t.getMode());for(const e of t.listTargets())r.push("target:"+Re(e,n))}return r.join(",")}const Ce={pattern:/^((?!JOINTS_).)*$/};function Oe(e=Ce){const t=G({},Ce,e);return F("dequantize",e=>{const n=e.getLogger();for(const n of e.getRoot().listMeshes())for(const e of n.listPrimitives())ve(e,t);e.createExtension(M).dispose(),n.debug("dequantize: Complete.")})}function ve(e,t){for(const n of e.listSemantics())Pe(n,e.getAttribute(n),t);for(const n of e.listTargets())for(const e of n.listSemantics())Pe(e,n.getAttribute(e),t)}function Pe(e,t,n){if(!t.getArray())return;if(!n.pattern.test(e))return;if(t.getComponentSize()>=4)return;const r=t.getArray(),o=new Float32Array(r.length);for(let e=0,n=t.getCount(),s=[];e<n;e++)s=t.getElement(e,s),t.setArray(o).setElement(e,s).setArray(r);t.setArray(o).setNormalized(!1)}const $e={method:"edgebreaker",encodeSpeed:5,decodeSpeed:5,quantizePosition:14,quantizeNormal:10,quantizeColor:8,quantizeTexcoord:12,quantizeGeneric:12,quantizationVolume:"mesh"},xe=(e=$e)=>{const t=G({},$e,e);return F("draco",e=>{e.createExtension(w).setRequired(!0).setEncoderOptions({method:"edgebreaker"===t.method?w.EncoderMethod.EDGEBREAKER:w.EncoderMethod.SEQUENTIAL,encodeSpeed:t.encodeSpeed,decodeSpeed:t.decodeSpeed,quantizationBits:{POSITION:t.quantizePosition,NORMAL:t.quantizeNormal,COLOR:t.quantizeColor,TEX_COORD:t.quantizeTexcoord,GENERIC:t.quantizeGeneric},quantizationVolume:t.quantizationVolume})})},ze={propertyTypes:[t.NODE,t.SKIN,t.MESH,t.CAMERA,t.PRIMITIVE,t.PRIMITIVE_TARGET,t.ANIMATION,t.MATERIAL,t.TEXTURE,t.ACCESSOR,t.BUFFER],keepLeaves:!1,keepAttributes:!0},Le=function(e=ze){const n=G({},ze,e),r=new Set(n.propertyTypes);return F("prune",e=>{const s=e.getLogger(),i=e.getRoot(),a=e.getGraph(),g={};if(r.has(t.MESH))for(const e of i.listMeshes())e.listPrimitives().length>0||(e.dispose(),m(e));if(r.has(t.NODE)&&!n.keepLeaves&&i.listScenes().forEach(function e(n){if(n.listChildren().forEach(e),n instanceof o)return;const r=a.listParentEdges(n).some(e=>{const n=e.getParent().propertyType;return n!==t.ROOT&&n!==t.SCENE&&n!==t.NODE});0!==a.listChildren(n).length||r||(n.dispose(),m(n))}),r.has(t.NODE)&&i.listNodes().forEach(u),r.has(t.SKIN)&&i.listSkins().forEach(u),r.has(t.MESH)&&i.listMeshes().forEach(u),r.has(t.CAMERA)&&i.listCameras().forEach(u),r.has(t.PRIMITIVE)&&f(a,t.PRIMITIVE),r.has(t.PRIMITIVE_TARGET)&&f(a,t.PRIMITIVE_TARGET),!n.keepAttributes&&r.has(t.ACCESSOR))for(const t of i.listMeshes())for(const n of t.listPrimitives()){const t=_e(e,n.getMaterial()),r=qe(n,t);p(n,r),n.listTargets().forEach(e=>p(e,r))}if(r.has(t.ANIMATION))for(const e of i.listAnimations()){for(const t of e.listChannels())t.getTargetNode()||(t.dispose(),m(t));if(e.listChannels().length)e.listSamplers().forEach(u);else{const t=e.listSamplers();u(e),t.forEach(u)}}if(r.has(t.MATERIAL)&&i.listMaterials().forEach(u),r.has(t.TEXTURE)&&i.listTextures().forEach(u),r.has(t.ACCESSOR)&&i.listAccessors().forEach(u),r.has(t.BUFFER)&&i.listBuffers().forEach(u),Object.keys(g).length){const e=Object.keys(g).map(e=>`${e} (${g[e]})`).join(", ");s.info(`prune: Removed types... ${e}`)}else s.info("prune: No unused properties found.");function u(e){e.listParents().filter(e=>!(e instanceof c||e instanceof l)).length||(e.dispose(),m(e))}function f(e,t){e.listEdges().map(e=>e.getParent()).filter(e=>e.propertyType===t).forEach(u)}function p(e,t){for(const n of t)e.setAttribute(n,null)}function m(e){g[e.propertyType]=g[e.propertyType]||0,g[e.propertyType]++}s.debug("prune: Complete.")})};function qe(e,t){const n=[];for(const r of e.listSemantics())"TANGENT"!==r||t.has(r)?(r.startsWith("TEXCOORD_")&&!t.has(r)||r.startsWith("COLOR_")&&"COLOR_0"!==r)&&n.push(r):n.push(r);return n}function _e(e,t,n=new Set){if(!t)return n;const r=e.getGraph().listChildEdges(t),o=new Set;for(const e of r)e.getChild()instanceof g&&o.add(e.getName());for(const t of r){const r=t.getName(),s=t.getChild();s instanceof u&&o.has(r.replace(/Info$/,""))&&n.add(`TEXCOORD_${s.getTexCoord()}`),s instanceof g&&r.match(/normalTexture/i)&&n.add("TANGENT"),s instanceof f&&_e(e,s,n)}return n}const ke={};function Ge(e=ke){return G({},ke,e),F("flatten",async e=>{const n=e.getRoot(),r=e.getLogger(),o=new Set;for(const e of n.listSkins())for(const t of e.listJoints())o.add(t);const s=new Set;for(const e of n.listAnimations())for(const t of e.listChannels()){const e=t.getTargetNode();e&&s.add(e)}const i=new Set,a=new Set;for(const e of n.listScenes())e.traverse(e=>{const t=e.getParentNode();t&&((o.has(t)||i.has(t))&&i.add(e),(s.has(t)||a.has(t))&&a.add(e))});for(const e of n.listScenes())e.traverse(e=>{s.has(e)||i.has(e)||a.has(e)||ne(e)});s.size&&r.debug("flatten: Flattening node hierarchies with TRS animation not yet supported."),await e.transform(Le({propertyTypes:[t.NODE],keepLeaves:!1})),r.debug("flatten: Complete.")})}function Fe(e){return te(e)[0]||null}function Be(e){return{scenes:Ue(e),meshes:We(e),materials:He(e),textures:je(e),animations:De(e)}}function Ue(e){return{properties:e.getRoot().listScenes().map(e=>{const t=e.listChildren()[0],n=r(e);return{name:e.getName(),rootName:t?t.getName():"",bboxMin:Ke(n.min),bboxMax:Ke(n.max)}})}}function We(e){return{properties:e.getRoot().listMeshes().map(e=>{const n=e.listParents().filter(e=>e.propertyType!==t.ROOT).length;let r=0,o=0;const s=new Set,i=new Set,a=new Set;e.listPrimitives().forEach(e=>{for(const t of e.listSemantics()){const n=e.getAttribute(t);s.add(t+":"+Je(n)),a.add(n)}for(const t of e.listTargets())t.listAttributes().forEach(e=>a.add(e));const t=e.getIndices();t&&(i.add(Je(t)),a.add(t)),o+=e.listAttributes()[0].getCount(),r+=W(e)});let c=0;Array.from(a).forEach(e=>c+=e.getArray().byteLength);const l=e.listPrimitives().map(e=>Ve[e.getMode()]);return{name:e.getName(),mode:Array.from(new Set(l)),primitives:e.listPrimitives().length,glPrimitives:r,vertices:o,indices:Array.from(i).sort(),attributes:Array.from(s).sort(),instances:n,size:c}})}}function He(e){return{properties:e.getRoot().listMaterials().map(n=>{const r=n.listParents().filter(e=>e.propertyType!==t.ROOT).length,o=new Set(n.listExtensions()),s=e.getGraph().listEdges().filter(e=>{const t=e.getChild(),r=e.getParent();return t instanceof g&&r===n||!!(t instanceof g&&r instanceof f&&o.has(r))}).map(e=>e.getName());return{name:n.getName(),instances:r,textures:s,alphaMode:n.getAlphaMode(),doubleSided:n.getDoubleSided()}})}}function je(e){return{properties:e.getRoot().listTextures().map(n=>{const r=n.listParents().filter(e=>e.propertyType!==t.ROOT).length,o=e.getGraph().listParentEdges(n).filter(e=>e.getParent().propertyType!==t.ROOT).map(e=>e.getName()),s=p.getSize(n.getImage(),n.getMimeType());let i="";if("image/ktx2"===n.getMimeType()){const e=x(n.getImage()).dataFormatDescriptor[0];e.colorModel===z?i="ETC1S":e.colorModel===L&&(i="UASTC")}return{name:n.getName(),uri:n.getURI(),slots:Array.from(new Set(o)),instances:r,mimeType:n.getMimeType(),compression:i,resolution:s?s.join("x"):"",size:n.getImage().byteLength,gpuSize:p.getVRAMByteLength(n.getImage(),n.getMimeType())}})}}function De(e){return{properties:e.getRoot().listAnimations().map(e=>{let t=Infinity,n=-Infinity;e.listSamplers().forEach(e=>{const r=e.getInput();r&&(t=Math.min(t,r.getMin([])[0]),n=Math.max(n,r.getMax([])[0]))});let r=0,o=0;const s=new Set;return e.listSamplers().forEach(e=>{const t=e.getInput(),n=e.getOutput();t&&(o+=t.getCount(),s.add(t),n&&s.add(n))}),Array.from(s).forEach(e=>{r+=e.getArray().byteLength}),{name:e.getName(),channels:e.listChannels().length,samplers:e.listSamplers().length,duration:Math.round(1e3*(n-t))/1e3,keyframes:o,size:r}})}}const Ve=["POINTS","LINES","LINE_LOOP","LINE_STRIP","TRIANGLES","TRIANGLE_STRIP","TRIANGLE_FAN"],Xe={Float32Array:"f32",Uint32Array:"u32",Uint16Array:"u16",Uint8Array:"u8",Int32Array:"i32",Int16Array:"i16",Int8Array:"i8"};function Ke(e){for(let t=0;t<e.length;t++)e[t].toFixed&&(e[t]=Number(e[t].toFixed(5)));return e}function Je(e){const t=e.getArray();return(Xe[t.constructor.name]||"?")+(e.getNormalized()?"_norm":"")}const Ze={min:2};function Qe(e=Ze){const t=G({},Ze,e);return F("instance",e=>{const n=e.getLogger(),r=e.getRoot(),o=e.createExtension(b);if(r.listAnimations().length)return n.warn("instance: Instancing is not currently supported for animated models."),void n.debug("instance: Complete.");let s=0,a=0;for(const c of r.listScenes()){const r=new Map;c.traverse(e=>{const t=e.getMesh();t&&r.set(t,(r.get(t)||new Set).add(e))});const l=[];for(const g of Array.from(r.keys())){const u=Array.from(r.get(g));if(u.length<t.min)continue;if(u.some(e=>e.getSkin()))continue;const f=et(e,o,g,u.length),p=f.getAttribute("TRANSLATION"),m=f.getAttribute("ROTATION"),d=f.getAttribute("SCALE"),h=e.createNode().setMesh(g).setExtension("EXT_mesh_gpu_instancing",f);c.addChild(h);let A=!1,y=!1,E=!1;for(let e=0;e<u.length;e++){let t,n,r;const o=u[e];p.setElement(e,t=o.getWorldTranslation()),m.setElement(e,n=o.getWorldRotation()),d.setElement(e,r=o.getWorldScale()),i.eq(t,[0,0,0])||(A=!0),i.eq(n,[0,0,0,1])||(y=!0),i.eq(r,[1,1,1])||(E=!0),o.setMesh(null),l.push(o)}A||p.dispose(),y||m.dispose(),E||d.dispose(),Ye(l,n),s++,a+=u.length}}n.info(s>0?`instance: Created ${s} batches, with ${a} total instances.`:`instance: No meshes with ≥${t.min} parent nodes were found.`),0===o.listProperties().length&&o.dispose(),n.debug("instance: Complete.")})}function Ye(e,t){let n,r=0;for(;n=e.pop();){if(n.listChildren().length||n.getCamera()||n.getMesh()||n.getSkin()||n.listExtensions().length)continue;const t=n.getParentNode();t&&e.push(t),n.dispose(),r++}t.debug(`instance: Removed ${r} unused nodes.`)}function et(e,t,n,r){const o=n.listPrimitives()[0].getAttribute("POSITION").getBuffer(),s=e.createAccessor().setType("VEC3").setArray(new Float32Array(3*r)).setBuffer(o),i=e.createAccessor().setType("VEC4").setArray(new Float32Array(4*r)).setBuffer(o),a=e.createAccessor().setType("VEC3").setArray(new Float32Array(3*r)).setBuffer(o);return t.createInstancedMesh().setAttribute("TRANSLATION",s).setAttribute("ROTATION",i).setAttribute("SCALE",a)}const tt={skipValidation:!1};function nt(e,t={}){t=G({},tt,t);const r=e[0],o=n.fromGraph(r.getGraph());if(!t.skipValidation&&new Set(e.map(Q)).size>1)throw new Error("Requires ≥2 Primitives, sharing the same Material and Mode, with compatible vertex attributes and indices.");const s=[],i=[];let a=0,c=0;for(const t of e){const e=rt(t),n=[];for(let t=0;t<e.length;t++){const r=e[t];void 0===n[r]&&(n[r]=a++),c++}s.push(new Uint32Array(n)),i.push(e)}const l=o.createPrimitive().setMode(r.getMode()).setMaterial(r.getMaterial());for(const e of r.listSemantics()){const t=r.getAttribute(e),n=m[t.getComponentType()],s=o.createAccessor().setType(t.getType()).setBuffer(t.getBuffer()).setNormalized(t.getNormalized()).setArray(new n(a*t.getElementSize()));l.setAttribute(e,s)}const g=(r.getIndices()?Z(a):null)&&o.createAccessor().setBuffer(r.getIndices().getBuffer()).setArray(Z(c,a));l.setIndices(g);let u=0;for(let t=0;t<s.length;t++){const n=e[t],r=s[t],o=i[t],a=u;let c=a;for(const e of l.listSemantics()){const t=n.getAttribute(e),s=l.getAttribute(e),i=[];c=a;for(let e=0;e<o.length;e++){const n=o[e];t.getElement(n,i),s.setElement(r[n],i),g&&g.setScalar(c++,r[n])}}u=c}return l}function rt(e){const t=e.getIndices();return t?t.getArray():Z(e.getAttribute("POSITION").getCount())}const{ROOT:ot,NODE:st,MESH:it,PRIMITIVE:at,ACCESSOR:ct}=t,lt=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],gt={keepMeshes:!1,keepNamed:!1};function ut(e=gt){const t=G({},gt,e);return F("join",async e=>{const n=e.getRoot(),r=e.getLogger();for(const r of n.listScenes())ft(e,r,t),r.traverse(n=>ft(e,n,t));await e.transform(Le({propertyTypes:[st,it,at,ct],keepLeaves:!1,keepAttributes:!0})),r.debug("join: Complete.")})}function ft(e,n,r){const o=e.getLogger(),s={},i=n.listChildren();for(let e=0;e<i.length;e++){const t=i[e];if(t.listParents().some(e=>e instanceof l))continue;const n=t.getMesh();if(n&&!t.getExtension("EXT_mesh_gpu_instancing")&&!t.getSkin())for(const o of n.listPrimitives()){if(o.listTargets().length>0)continue;const i=o.getMaterial();if(i&&i.getExtension("KHR_materials_volume"))continue;let a=Q(o);const c=n.getName()||t.getName();(r.keepMeshes||r.keepNamed&&c)&&(a+=`|${e}`),a in s||(s[a]={prims:[],primMeshes:[],primNodes:[],dstNode:t,dstMesh:void 0});const l=s[a];l.prims.push(o),l.primNodes.push(t)}}const a=Object.values(s).filter(({prims:e})=>e.length>1),c=new Set(a.flatMap(e=>e.primNodes));for(const e of c){const t=e.getMesh();t.listParents().some(t=>t.propertyType!==ot&&e!==t)&&e.setMesh(t.clone())}for(const e of a){const{dstNode:t,primNodes:n}=e;e.dstMesh=t.getMesh(),e.primMeshes=n.map(e=>e.getMesh())}for(const e of a){const{prims:n,primNodes:r,primMeshes:s,dstNode:i,dstMesh:a}=e,c=i.getMatrix();for(let e=0;e<n.length;e++){const o=r[e];let a=n[e];s[e].removePrimitive(a),(a.listParents().some(e=>e.propertyType!==t.ROOT)||mt(a))&&(a=n[e]=pt(n[e])),o!==i&&(se(lt,oe(lt,c),o.getMatrix()),he(a,lt))}const l=nt(n),g=l.listAttributes()[0].getCount();a.addPrimitive(l),o.debug(`join: Joined Primitives (${n.length}) containing ${D(g)} vertices under Node "${i.getName()}".`)}}function pt(e){const t=e.clone();for(const e of t.listSemantics())t.setAttribute(e,t.getAttribute(e).clone());const n=t.getIndices();return n&&t.setIndices(n.clone()),t}function mt(e){for(const t of e.listAttributes())for(const n of t.listParents())if(n!==e&&n.propertyType!==ot)return!0;return!1}function dt(e){const t=ht(e),n=[];return t&h.R&&n.push(h.R),t&h.G&&n.push(h.G),t&h.B&&n.push(h.B),t&h.A&&n.push(h.A),n}function ht(e){const r=n.fromGraph(e.getGraph());let o=0;for(const n of r.getGraph().listParentEdges(e)){const e=n.getParent();let{channels:s}=n.getAttributes();s&&"baseColorTexture"===n.getName()&&e instanceof d&&e.getAlphaMode()===d.AlphaMode.OPAQUE&&(s&=~h.A),s?o|=s:e.propertyType!==t.ROOT&&r.getLogger().warn(`Missing attribute ".channels" on edge, "${n.getName()}".`)}return o}function At(e){const t=e.getGraph(),n=[];for(const r of t.listParentEdges(e)){const e=r.getParent(),o=r.getName()+"Info";for(const r of t.listChildEdges(e)){const e=r.getChild();e instanceof u&&r.getName()===o&&n.push(e)}}return n}function yt(e){const t=n.fromGraph(e.getGraph()).getRoot(),r=e.getGraph().listParentEdges(e).filter(e=>e.getParent()!==t).map(e=>e.getName());return Array.from(new Set(r))}const Et={target:"size"};function Tt(n){const r=G({},Et,n),o=r.encoder;if(!o)throw new Error('reorder: encoder dependency required — install "meshoptimizer".');return F("reorder",async n=>{const s=n.getLogger();await o.ready;const i=St(n);for(const t of i.indicesToAttributes.keys()){const n=t.clone();let s=n.getArray().slice();s instanceof Uint32Array||(s=new Uint32Array(s));const[a,c]=o.reorderMesh(s,i.indicesToMode.get(t)===e.Mode.TRIANGLES,"size"===r.target);n.setArray(c<=65534?new Uint16Array(s):s);for(const e of i.indicesToAttributes.get(t)){const r=e.clone();J(r,a,c);for(const o of i.attributesToPrimitives.get(e))if(o.getIndices()===t&&o.swap(t,n),o.getIndices()===n){o.swap(e,r);for(const t of o.listTargets())t.swap(e,r)}}}await n.transform(Le({propertyTypes:[t.ACCESSOR]})),i.indicesToAttributes.size?s.debug("reorder: Complete."):s.warn("reorder: No qualifying primitives found; may need to weld first.")})}function St(e){const t=new H,n=new Map,r=new H;for(const o of e.getRoot().listMeshes())for(const e of o.listPrimitives()){const o=e.getIndices();if(o){n.set(o,e.getMode());for(const n of X(e))t.add(o,n),r.add(n,e)}}return{indicesToAttributes:t,indicesToMode:n,attributesToPrimitives:r}}function It(e,t=Infinity){if(Number.isFinite(t)&&t%4||t<=0)throw new Error("Limit must be positive multiple of four.");const n=e.getAttribute("POSITION").getCount(),r=e.listSemantics().filter(e=>e.startsWith("WEIGHTS_")).length,o=new Uint16Array(4*r),s=new Float32Array(4*r),a=new Float32Array(4*r),c=new Uint32Array(4*r),l=new Uint32Array(4*r);for(let t=0;t<n;t++){Mt(e,t,"WEIGHTS",s),Mt(e,t,"JOINTS",c);for(let e=0;e<4*r;e++)o[e]=e;o.sort((e,t)=>s[e]>s[t]?-1:1);for(let e=0;e<o.length;e++)a[e]=s[o[e]],l[e]=c[o[e]];wt(e,t,"WEIGHTS",a),wt(e,t,"JOINTS",l)}for(let n=r;4*n>t;n--){const t=e.getAttribute("WEIGHTS_"+(n-1)),r=e.getAttribute("JOINTS_"+(n-1));e.setAttribute("WEIGHTS_"+(n-1),null),e.setAttribute("JOINTS_"+(n-1),null),1===t.listParents().length&&t.dispose(),1===r.listParents().length&&r.dispose()}!function(e){if(!function(e){const t=e.listSemantics().filter(e=>e.startsWith("WEIGHTS_")).map(t=>e.getAttribute(t)),n=t.map(e=>e.getNormalized()),r=t.map(e=>e.getComponentType());return 1===new Set(n).size&&1===new Set(r).size}(e))return;const t=e.getAttribute("POSITION").getCount(),n=e.listSemantics().filter(e=>e.startsWith("WEIGHTS_")).length,r=e.getAttribute("WEIGHTS_0"),o=r.getArray(),s=r.getComponentType(),a=r.getNormalized(),c=a?s:void 0,l=a?i.decodeNormalizedInt(1,s):Number.EPSILON,g=new Uint32Array(4*n).fill(0),u=o.slice(0,4*n).fill(0);for(let n=0;n<t;n++){Mt(e,n,"JOINTS",g),Mt(e,n,"WEIGHTS",u,c);let t=bt(u,c);if(0!==t){if(Math.abs(1-t)>l)for(let e=0;e<u.length;e++)if(a){const n=i.encodeNormalizedInt(u[e]/t,s);u[e]=i.decodeNormalizedInt(n,s)}else u[e]/=t;if(t=bt(u,c),a&&1!==t)for(let e=u.length-1;e>=0;e--)if(u[e]>0){u[e]+=i.encodeNormalizedInt(1-t,s);break}for(let e=u.length-1;e>=0;e--)0===u[e]&&(g[e]=0);wt(e,n,"JOINTS",g),wt(e,n,"WEIGHTS",u,c)}}}(e)}function Mt(e,t,n,r,o){let s;const a=[0,0,0,0];for(let c=0;s=e.getAttribute(`${n}_${c}`);c++){s.getElement(t,a);for(let e=0;e<4;e++)r[4*c+e]=o?i.encodeNormalizedInt(a[e],o):a[e]}return r}function wt(e,t,n,r,o){let s;const a=[0,0,0,0];for(let c=0;s=e.getAttribute(`${n}_${c}`);c++){for(let e=0;e<4;e++)a[e]=o?i.decodeNormalizedInt(r[4*c+e],o):r[4*c+e];s.setElement(t,a)}}function bt(e,t){let n=0;for(let r=0;r<e.length;r++)n+=t?i.decodeNormalizedInt(e[r],t):e[r];return n}const Nt=[Int8Array,Int16Array,Int32Array],{TRANSLATION:Rt,ROTATION:Ct,SCALE:Ot,WEIGHTS:vt}=l.TargetPath,Pt=[Rt,Ct,Ot],$t={pattern:/.*/,quantizationVolume:"mesh",quantizePosition:14,quantizeNormal:10,quantizeTexcoord:12,quantizeColor:8,quantizeWeight:8,quantizeGeneric:12,normalizeWeights:!0},xt=(e=$t)=>{const n=G({},$t,e);return F("quantize",async e=>{const r=e.getLogger(),o=e.getRoot();let s;e.createExtension(M).setRequired(!0),"scene"===n.quantizationVolume&&(s=Lt(function(e){const t=e[0];for(const n of e)le(t.min,t.min,n.min),ge(t.max,t.max,n.max);return t}(o.listMeshes().map(Bt))));for(const t of e.getRoot().listMeshes()){"mesh"===n.quantizationVolume&&(s=Lt(Bt(t))),s&&n.pattern.test("POSITION")&&(qt(e,t,s),kt(t,1/s.scale));for(const r of t.listPrimitives()){zt(e,r,s,n);for(const t of r.listTargets())zt(e,t,s,n)}}await e.transform(Le({propertyTypes:[t.ACCESSOR,t.SKIN,t.MATERIAL]}),Ne({propertyTypes:[t.ACCESSOR,t.MATERIAL]})),r.debug("quantize: Complete.")})};function zt(t,n,r,o){const s=t.getLogger();for(const t of n.listSemantics()){if(!o.pattern.test(t))continue;const c=n.getAttribute(t),{bits:l,ctor:g}=Ft(t,c,s,o);if(!g)continue;if(l<8||l>16)throw new Error("quantize: Requires bits = 8–16.");if(c.getComponentSize()<=l/8)continue;const u=c.clone();if("POSITION"===t){const t=r.scale,o=[];n instanceof e?oe(o,Wt(r)):((i=o)[0]=(a=[1/t,1/t,1/t])[0],i[1]=0,i[2]=0,i[3]=0,i[4]=0,i[5]=a[1],i[6]=0,i[7]=0,i[8]=0,i[9]=0,i[10]=a[2],i[11]=0,i[12]=0,i[13]=0,i[14]=0,i[15]=1);for(let e=0,t=[0,0,0],n=u.getCount();e<n;e++)u.getElement(e,t),u.setElement(e,pe(t,t,o))}Gt(u,g,l),n.swap(c,u)}var i,a;if(o.normalizeWeights&&n.getAttribute("WEIGHTS_0")&&It(n,Infinity),n instanceof e&&n.getIndices()&&n.listAttributes().length&&n.listAttributes()[0].getCount()<65535){const e=n.getIndices();e.setArray(new Uint16Array(e.getArray()))}}function Lt(e){const{min:t,max:n}=e,r=Math.max((n[0]-t[0])/2,(n[1]-t[1])/2,(n[2]-t[2])/2);return{offset:[t[0]+(n[0]-t[0])/2,t[1]+(n[1]-t[1])/2,t[2]+(n[2]-t[2])/2],scale:r}}function qt(e,t,n){const r=Wt(n);for(const o of t.listParents()){if(!(o instanceof A))continue;const s=o.listParents().filter(e=>e instanceof l),i=s.some(e=>Pt.includes(e.getTargetPath())),a=o.listChildren().length>0;if(o.getSkin()){o.setSkin(_t(o.getSkin(),n));continue}let c;a||i?(c=e.createNode("").setMesh(t),o.addChild(c).setMesh(null),s.filter(e=>e.getTargetPath()===vt).forEach(e=>e.setTargetNode(c))):c=o;const g=c.getMatrix();se(g,g,r),c.setMatrix(g)}}function _t(e,t){e=e.clone();const n=Wt(t),r=e.getInverseBindMatrices().clone(),o=[];for(let e=0,t=r.getCount();e<t;e++)r.getElement(e,o),se(o,o,n),r.setElement(e,o);return e.setInverseBindMatrices(r)}function kt(e,t){for(const n of e.listPrimitives()){let e=n.getMaterial();if(!e)continue;let r=e.getExtension("KHR_materials_volume");!r||r.getThicknessFactor()<=0||(r=r.clone().setThicknessFactor(r.getThicknessFactor()*t),e=e.clone().setExtension("KHR_materials_volume",r),n.setMaterial(e))}}function Gt(e,t,n){const r=new t(e.getArray().length),o=Nt.includes(t)?1:0,s=n-o,i=8*t.BYTES_PER_ELEMENT-o,a=Math.pow(2,s)-1,c=i-s,l=2*s-i;for(let t=0,n=0,o=[];t<e.getCount();t++){e.getElement(t,o);for(let e=0;e<o.length;e++){let t=Math.round(Math.abs(o[e])*a);t=t<<c|t>>l,r[n++]=t*Math.sign(o[e])}}e.setArray(r).setNormalized(!0).setSparse(!1)}function Ft(e,t,n,r){const o=t.getMinNormalized([]),s=t.getMaxNormalized([]);let i,a;if("POSITION"===e)i=r.quantizePosition,a=i<=8?Int8Array:Int16Array;else if("NORMAL"===e||"TANGENT"===e)i=r.quantizeNormal,a=i<=8?Int8Array:Int16Array;else if(e.startsWith("COLOR_"))i=r.quantizeColor,a=i<=8?Uint8Array:Uint16Array;else if(e.startsWith("TEXCOORD_")){if(o.some(e=>e<0)||s.some(e=>e>1))return n.warn(`quantize: Skipping ${e}; out of [0,1] range.`),{bits:-1};i=r.quantizeTexcoord,a=i<=8?Uint8Array:Uint16Array}else{if(e.startsWith("JOINTS_"))return i=Math.max(...t.getMax([]))<=255?8:16,a=i<=8?Uint8Array:Uint16Array,t.getComponentSize()>i/8&&t.setArray(new a(t.getArray())),{bits:-1};if(e.startsWith("WEIGHTS_")){if(o.some(e=>e<0)||s.some(e=>e>1))return n.warn(`quantize: Skipping ${e}; out of [0,1] range.`),{bits:-1};i=r.quantizeWeight,a=i<=8?Uint8Array:Uint16Array}else{if(!e.startsWith("_"))throw new Error(`quantize: Unexpected semantic, "${e}".`);if(o.some(e=>e<-1)||s.some(e=>e>1))return n.warn(`quantize: Skipping ${e}; out of [-1,1] range.`),{bits:-1};i=r.quantizeGeneric,a=a=o.some(e=>e<0)?i<=8?Int8Array:Int16Array:i<=8?Uint8Array:Uint16Array}}return{bits:i,ctor:a}}function Bt(e){const t=[],n=[];for(const r of e.listPrimitives()){const e=r.getAttribute("POSITION");e&&t.push(e);for(const e of r.listTargets()){const t=e.getAttribute("POSITION");t&&n.push(t)}}if(0===t.length)throw new Error('quantize: Missing "POSITION" attribute.');const r=Ut(t,3);if(n.length>0){const{min:e,max:t}=Ut(n,3);le(r.min,r.min,le(e,ue(e,e,2),[0,0,0])),ge(r.max,r.max,ge(t,ue(t,t,2),[0,0,0]))}return r}function Ut(e,t){const n=new Array(t).fill(Infinity),r=new Array(t).fill(-Infinity),o=[],s=[];for(const i of e){i.getMinNormalized(o),i.getMaxNormalized(s);for(let e=0;e<t;e++)n[e]=Math.min(n[e],o[e]),r[e]=Math.max(r[e],s[e])}return{min:n,max:r}}function Wt(e){return r=e.offset,f=(s=(n=[0,0,0,1])[0])*(l=s+s),p=s*(g=(i=n[1])+i),m=s*(u=(a=n[2])+a),h=i*u,y=(c=n[3])*l,E=c*g,T=c*u,I=(o=[e.scale,e.scale,e.scale])[1],M=o[2],(t=[])[0]=(1-((d=i*g)+(A=a*u)))*(S=o[0]),t[1]=(p+T)*S,t[2]=(m-E)*S,t[3]=0,t[4]=(p-T)*I,t[5]=(1-(f+A))*I,t[6]=(h+y)*I,t[7]=0,t[8]=(m+E)*M,t[9]=(h-y)*M,t[10]=(1-(f+d))*M,t[11]=0,t[12]=r[0],t[13]=r[1],t[14]=r[2],t[15]=1,t;var t,n,r,o,s,i,a,c,l,g,u,f,p,m,d,h,A,y,E,T,S,I,M}const Ht={level:"high"},jt=e=>{const t=G({},Ht,e),n=t.encoder;if(!n)throw new Error('meshopt: encoder dependency required — install "meshoptimizer".');return F("meshopt",async e=>{await e.transform(Tt({encoder:n,target:"size"}),xt({pattern:"medium"===t.level?/.*/:/^(POSITION|TEXCOORD|JOINTS|WEIGHTS)(_\d+)?$/,quantizePosition:14,quantizeTexcoord:12,quantizeColor:8,quantizeNormal:8})),e.createExtension(N).setRequired(!0).setEncoderOptions({method:"medium"===t.level?N.EncoderMethod.QUANTIZE:N.EncoderMethod.FILTER})})},Dt={};function Vt(e=Dt){return G({},Dt,e),F("metalRough",async e=>{const t=e.getLogger();if(!e.getRoot().listExtensionsUsed().map(e=>e.extensionName).includes("KHR_materials_pbrSpecularGlossiness"))return void t.warn("metalRough: KHR_materials_pbrSpecularGlossiness not found on document.");const n=e.createExtension(R),r=e.createExtension(C),o=e.createExtension(O),s=new Set;for(const t of e.getRoot().listMaterials()){const o=t.getExtension("KHR_materials_pbrSpecularGlossiness");if(!o)continue;const i=r.createSpecular().setSpecularFactor(1).setSpecularColorFactor(o.getSpecularFactor());s.add(o.getSpecularGlossinessTexture()),s.add(t.getBaseColorTexture()),s.add(t.getMetallicRoughnessTexture()),t.setBaseColorFactor(o.getDiffuseFactor()).setMetallicFactor(0).setRoughnessFactor(1).setExtension("KHR_materials_ior",n.createIOR().setIOR(1e3)).setExtension("KHR_materials_specular",i);const a=o.getDiffuseTexture();a&&(t.setBaseColorTexture(a),t.getBaseColorTextureInfo().copy(o.getDiffuseTextureInfo()));const c=o.getSpecularGlossinessTexture();if(c){const n=o.getSpecularGlossinessTextureInfo(),r=e.createTexture();await U(c,r,(e,t,n)=>{e.set(t,n,3,255)}),i.setSpecularTexture(r),i.setSpecularColorTexture(r),i.getSpecularTextureInfo().copy(n),i.getSpecularColorTextureInfo().copy(n);const s=o.getGlossinessFactor(),a=e.createTexture();await U(c,a,(e,t,n)=>{const r=255-Math.round(e.get(t,n,3)*s);e.set(t,n,0,0),e.set(t,n,1,r),e.set(t,n,2,0),e.set(t,n,3,255)}),t.setMetallicRoughnessTexture(a),t.getMetallicRoughnessTextureInfo().copy(n)}else i.setSpecularColorFactor(o.getSpecularFactor()),t.setRoughnessFactor(1-o.getGlossinessFactor());t.setExtension("KHR_materials_pbrSpecularGlossiness",null)}o.dispose();for(const e of s)e&&1===e.listParents().length&&e.dispose();t.debug("metalRough: Complete.")})}const Xt={};function Kt(e=Xt){return G({},Xt,e),F("unweld",e=>{const t=e.getLogger(),n=new Map;for(const r of e.getRoot().listMeshes())for(const e of r.listPrimitives()){const r=e.getIndices();if(!r)continue;const o=e.getAttribute("POSITION").getCount();for(const o of e.listAttributes())e.swap(o,Jt(o,r,t,n)),1===o.listParents().length&&o.dispose();for(const o of e.listTargets())for(const e of o.listAttributes())o.swap(e,Jt(e,r,t,n)),1===e.listParents().length&&e.dispose();const s=e.getAttribute("POSITION").getCount();t.debug(`unweld: ${V(o,s)} vertices.`),e.setIndices(null),1===r.listParents().length&&r.dispose()}t.debug("unweld: Complete.")})}function Jt(e,t,n,r){if(r.has(e)&&r.get(e).has(t))return n.debug(`unweld: Cache hit for reused attribute, "${e.getName()}".`),r.get(e).get(t);const o=e.clone(),s=e.getArray().constructor;o.setArray(new s(t.getCount()*e.getElementSize()));const i=[];for(let n=0;n<t.getCount();n++)o.setElement(n,e.getElement(t.getScalar(n),i));return r.has(e)||r.set(e,new Map),r.get(e).set(t,o),o}const Zt={overwrite:!1};function Qt(e=Zt){const t=G({},Zt,e);return F("normals",async e=>{const n=e.getLogger();let r=0;await e.transform(Kt());for(const o of e.getRoot().listMeshes())for(const s of o.listPrimitives()){const o=s.getAttribute("POSITION");let i=s.getAttribute("NORMAL");if(t.overwrite&&i)i.dispose();else if(i){n.debug("normals: Skipping primitive: NORMAL found.");continue}i=e.createAccessor().setArray(new Float32Array(3*o.getCount())).setType("VEC3");const a=[0,0,0],c=[0,0,0],l=[0,0,0];for(let e=0;e<o.getCount();e+=3){o.getElement(e+0,a),o.getElement(e+1,c),o.getElement(e+2,l);const t=Yt(a,c,l);i.setElement(e+0,t),i.setElement(e+1,t),i.setElement(e+2,t)}s.setAttribute("NORMAL",i),r++}r?n.debug("normals: Complete."):n.warn("normals: No qualifying primitives found. See debug output.")})}function Yt(e,t,n){const r=[t[0]-e[0],t[1]-e[1],t[2]-e[2]],o=[n[0]-e[0],n[1]-e[1],n[2]-e[2]];return fe([0,0,0],[r[1]*o[2]-r[2]*o[1],r[2]*o[0]-r[0]*o[2],r[0]*o[1]-r[1]*o[0]])}const en={animations:!0,meshes:!0},tn=(e=en)=>{const n=G({},en,e);return F("partition",async e=>{const r=e.getLogger();!1!==n.meshes&&function(e,t,n){const r=new Set(e.getRoot().listBuffers().map(e=>e.getURI()));e.getRoot().listMeshes().forEach((o,s)=>{if(Array.isArray(n.meshes)&&!n.meshes.includes(o.getName()))return void t.debug(`partition: Skipping mesh #${s} with name "${o.getName()}".`);t.debug(`partition: Creating buffer for mesh "${o.getName()}".`);const i=e.createBuffer(o.getName()).setURI(nn(o.getName()||"mesh",r));o.listPrimitives().forEach(e=>{const t=e.getIndices();t&&t.setBuffer(i),e.listAttributes().forEach(e=>e.setBuffer(i)),e.listTargets().forEach(e=>{e.listAttributes().forEach(e=>e.setBuffer(i))})})})}(e,r,n),!1!==n.animations&&function(e,t,n){const r=new Set(e.getRoot().listBuffers().map(e=>e.getURI()));e.getRoot().listAnimations().forEach((o,s)=>{if(Array.isArray(n.animations)&&!n.animations.includes(o.getName()))return void t.debug(`partition: Skipping animation #${s} with name "${o.getName()}".`);t.debug(`partition: Creating buffer for animation "${o.getName()}".`);const i=e.createBuffer(o.getName()).setURI(nn(o.getName()||"animation",r));o.listSamplers().forEach(e=>{const t=e.getInput(),n=e.getOutput();t&&t.setBuffer(i),n&&n.setBuffer(i)})})}(e,r,n),n.meshes||n.animations||r.warn("partition: Select animations or meshes to create a partition."),await e.transform(Le({propertyTypes:[t.BUFFER]})),r.debug("partition: Complete.")})};function nn(e,t){let n=`${e}.bin`,r=1;for(;t.has(n);)n=`${e}_${r++}.bin`;return n}function rn(){var e=new re(4);return re!=Float32Array&&(e[0]=0,e[1]=0,e[2]=0),e[3]=1,e}function on(e,t){var n=an(e,t);return Math.acos(2*n*n-1)}function sn(e,t,n,r){var o,s,i,a,c,l=t[0],g=t[1],u=t[2],f=t[3],p=n[0],m=n[1],d=n[2],h=n[3];return(s=l*p+g*m+u*d+f*h)<0&&(s=-s,p=-p,m=-m,d=-d,h=-h),1-s>1e-6?(o=Math.acos(s),i=Math.sin(o),a=Math.sin((1-r)*o)/i,c=Math.sin(r*o)/i):(a=1-r,c=r),e[0]=a*l+c*p,e[1]=a*g+c*m,e[2]=a*u+c*d,e[3]=a*f+c*h,e}var an=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3]};ae(),ce(1,0,0),ce(0,1,0),rn(),rn(),ie();const cn={tolerance:1e-4},ln=(e=cn)=>{const n=G({},cn,e);return F("resample",async(e,r)=>{const o=new Set,s=e.getRoot().listAccessors().length,i=e.getLogger();let a=!1;for(const t of e.getRoot().listAnimations()){const e=new Map;for(const n of t.listChannels())e.set(n.getSampler(),n.getTargetPath());for(const r of t.listSamplers())"weights"!==e.get(r)?"STEP"!==r.getInterpolation()&&"LINEAR"!==r.getInterpolation()||(o.add(r.getInput()),o.add(r.getOutput()),gn(r,e.get(r),n)):a=!0}for(const e of Array.from(o.values()))e.listParents().some(e=>!(e instanceof c))||e.dispose();e.getRoot().listAccessors().length>s&&!B(r,"resample","dedup")&&await e.transform(Ne({propertyTypes:[t.ACCESSOR]})),a&&i.warn("resample: Skipped optimizing morph target keyframes, not yet supported."),i.debug("resample: Complete.")})};function gn(e,t,n){const r=e.getInput().clone().setSparse(!1),o=e.getOutput().clone().setSparse(!1),s=n.tolerance,a=e.getInterpolation(),c=r.getCount()-1,l=[],g=[],u=[],f=[];let p=1;for(let e=1;e<c;++e){const n=r.getScalar(p-1),c=r.getScalar(e),m=r.getScalar(e+1),d=(c-n)/(m-n);let h=!1;if(c!==m&&(1!==e||c!==r.getScalar(0)))if(o.getElement(p-1,f),o.getElement(e,g),o.getElement(e+1,u),"LINEAR"===a&&"rotation"===t){const e=sn(l,f,u,d),t=on(f,g)+on(g,u);h=!i.eq(g,e,s)||t+Number.EPSILON>=Math.PI}else if("LINEAR"===a){const e=fn(l,f,u,d);h=!i.eq(g,e,s)}else"STEP"===a&&(h=!i.eq(g,f)||!i.eq(g,u));h&&(e!==p&&(r.setScalar(p,r.getScalar(e)),o.setElement(p,o.getElement(e,l))),p++)}c>0&&(r.setScalar(p,r.getScalar(c)),o.setElement(p,o.getElement(c,l)),p++),p!==r.getCount()?(r.setArray(r.getArray().slice(0,p)),o.setArray(o.getArray().slice(0,p*o.getElementSize())),e.setInput(r),e.setOutput(o)):(r.dispose(),o.dispose())}function un(e,t,n){return e*(1-n)+t*n}function fn(e,t,n,r){for(let o=0;o<t.length;o++)e[o]=un(t[o],n[o],r);return e}const pn={name:"",fps:10,pattern:/.*/,sort:!0};function mn(e=pn){const t=G({},pn,e);return F("sequence",e=>{const n=e.getLogger(),r=e.getRoot(),o=t.fps,s=r.listNodes().filter(e=>e.getName().match(t.pattern));t.sort&&s.sort((e,t)=>e.getName()>t.getName()?1:-1);const i=e.createAnimation(t.name),a=r.listBuffers()[0];s.forEach((t,n)=>{let r,c;0===n?(r=[n/o,(n+1)/o],c=[1,1,1,0,0,0]):n===s.length-1?(r=[(n-1)/o,n/o],c=[0,0,0,1,1,1]):(r=[(n-1)/o,n/o,(n+1)/o],c=[0,0,0,1,1,1,0,0,0]);const g=e.createAccessor().setArray(new Float32Array(r)).setBuffer(a),u=e.createAccessor().setArray(new Float32Array(c)).setBuffer(a).setType(y.Type.VEC3),f=e.createAnimationSampler().setInterpolation(E.Interpolation.STEP).setInput(g).setOutput(u),p=e.createAnimationChannel().setTargetNode(t).setTargetPath(l.TargetPath.SCALE).setSampler(f);i.addSampler(f).addChannel(p)}),n.debug("sequence: Complete.")})}const dn={tolerance:1e-4,overwrite:!0};function hn(e=dn){const n=G({},dn,e);if(n.tolerance>.1||n.tolerance<0)throw new Error("weld: Requires 0 ≤ tolerance ≤ 0.1");return F("weld",async(e,r)=>{const o=e.getLogger();for(const t of e.getRoot().listMeshes())for(const r of t.listPrimitives())An(e,r,n);B(r,"weld","dedup")||await e.transform(Ne({propertyTypes:[t.ACCESSOR]})),o.debug("weld: Complete.")})}function An(t,n,r){n.getIndices()&&!r.overwrite||n.getMode()!==e.Mode.POINTS&&(0===r.tolerance?function(e,t){if(t.getIndices())return;const n=t.listAttributes()[0],r=n.getCount(),o=n.getBuffer(),s=e.createAccessor().setBuffer(o).setType(y.Type.SCALAR).setArray(Z(r));t.setIndices(s)}(t,n):function(e,t,n){const r=e.getLogger(),o=t.getAttribute("POSITION"),s=t.getIndices()||e.createAccessor().setArray(Z(o.getCount())),i=new Uint32Array(new Set(s.getArray())),a=Math.max(n.tolerance,Number.EPSILON),c={};for(const e of t.listSemantics()){const n=t.getAttribute(e);c[e]=Sn(e,n,a)}var l;r.debug(`weld: Tolerance thresholds: ${l=c,Object.entries(l).map(([e,t])=>`${e}=${t}`).join(", ")}`);const g=[0,0,0],u=[0,0,0];i.sort((e,t)=>(o.getElement(e,g),o.getElement(t,u),g[0]>u[0]?1:-1));const f=Z(i.length),p=Z(i.length),m=o.getCount();let d=0,h=0;for(let e=0;e<i.length;e++){const n=i[e];for(let r=e-1;r>=0;r--){const e=f[i[r]];if(o.getElement(n,g),o.getElement(e,u),Math.abs(g[0]-u[0])>c.POSITION)break;h++;const s=t.listSemantics().every(r=>In(t.getAttribute(r),n,e,c[r])),a=t.listTargets().every(t=>t.listSemantics().every(r=>In(t.getAttribute(r),n,e,c[r])));if(s&&a){f[n]=e;break}}p[n]=f[n]===n?d++:p[f[n]]}r.debug(`weld: Iterations per vertex: ${Math.round(h/i.length)} (avg)`),r.debug(`weld: ${V(m,d)} vertices.`);const A=s.getCount(),y=Z(A,i.length);for(let e=0;e<A;e++)y[e]=p[s.getScalar(e)];t.setIndices(s.clone().setArray(y)),1===s.listParents().length&&s.dispose();for(const e of t.listAttributes())yn(t,e,p,d);for(const e of t.listTargets())for(const t of e.listAttributes())yn(e,t,p,d)}(t,n,r))}function yn(e,t,n,r){const o=(a=t.getArray(),c=r*t.getElementSize(),new(0,a.constructor)(c)),s=t.clone().setArray(o),i=new Uint8Array(r);var a,c;for(let e=0,r=[];e<n.length;e++)i[n[e]]||(s.setElement(n[e],t.getElement(e,r)),i[n[e]]=1);e.swap(t,s),1===t.listParents().length&&t.dispose()}const En=[],Tn=[];function Sn(e,t,n){return"NORMAL"===e||"TANGENT"===e?.5:e.startsWith("COLOR_")?.01:e.startsWith("TEXCOORD_")?1e-4:e.startsWith("JOINTS_")?0:e.startsWith("WEIGHTS_")?.01:(En.length=Tn.length=0,t.getMinNormalized(En),t.getMaxNormalized(Tn),n*(Math.max(...Tn)-Math.min(...En)||1))}function In(e,t,n,r,o){e.getElement(t,En),e.getElement(n,Tn);for(let t=0,n=e.getElementSize();t<n;t++)if(Math.abs(En[t]-Tn[t])>r)return!1;return!0}const Mn={ratio:.5,error:.001,lockBorder:!1},wn=n=>{const r=G({},Mn,n),o=r.simplifier;if(!o)throw new Error('simplify: simplifier dependency required — install "meshoptimizer".');return F("simplify",async(n,s)=>{const i=n.getLogger();await o.ready,await n.transform(hn({overwrite:!1}));for(const t of n.getRoot().listMeshes())for(const o of t.listPrimitives())o.getMode()===e.Mode.TRIANGLES?bn(n,o,r):i.warn(`simplify: Skipping primitive of mesh "${t.getName()}": Requires TRIANGLES draw mode.`);B(s,"simplify","dedup")||await n.transform(Ne({propertyTypes:[t.ACCESSOR]})),i.debug("simplify: Complete.")})};function bn(e,t,n){const r=G({},Mn,n),o=r.simplifier,s=e.getLogger(),i=t.getAttribute("POSITION"),a=t.getIndices(),c=i.getCount();let l=i.getArray(),g=a.getArray();if(i.getComponentType()!==y.ComponentType.FLOAT)if(i.getNormalized()){const e=l,t=new Float32Array(e.length);for(let n=0,r=i.getCount(),o=[];n<r;n++)o=i.getElement(n,o),i.setArray(t).setElement(n,o).setArray(e);l=t}else l=new Float32Array(l);a.getComponentType()!==y.ComponentType.UNSIGNED_INT&&(g=new Uint32Array(g));const u=3*Math.floor(r.ratio*c/3),[f,p]=o.simplify(g,l,3,u,r.error,r.lockBorder?["LockBorder"]:[]),[m,d]=o.compactMesh(f);s.debug(`simplify: ${V(i.getCount(),d)} vertices, error: ${p.toFixed(4)}.`);for(const e of X(t)){const n=e.clone();J(n,m,d),K(t,e,n),1===e.listParents().length&&e.dispose()}const h=a.clone();return h.setArray(c<=65534?new Uint16Array(f):f),t.setIndices(h),1===a.listParents().length&&a.dispose(),t}const Nn={ratio:1/3};function Rn(e=Nn){const t=G({},Nn,e).ratio;if(t<0||t>1)throw new Error("sparse: Ratio must be between 0 and 1.");return F("sparse",e=>{const n=e.getRoot(),r=e.getLogger();let o=0;for(const e of n.listAccessors()){const n=e.getCount(),r=Array(e.getElementSize()).fill(0),s=Array(e.getElementSize()).fill(0);let a=0;for(let o=0;o<n&&(e.getElement(o,s),i.eq(s,r,0)||a++,!(a/n>=t));o++);const c=a/n<t;c!==e.getSparse()&&(e.setSparse(c),o++)}r.debug(`sparse: Updated ${o} accessors.`),r.debug("sparse: Complete.")})}const Cn="textureResize";var On;!function(e){e.LANCZOS3="lanczos3",e.LANCZOS2="lanczos2"}(On||(On={}));const vn={size:[2048,2048],filter:On.LANCZOS3,pattern:null,slots:null};function Pn(e=vn){const t=G({},vn,e);return F(Cn,async e=>{const n=e.getLogger();for(const r of e.getRoot().listTextures()){const e=r.getName(),o=r.getURI();if(t.pattern&&!t.pattern.test(e)&&!t.pattern.test(o)){n.debug(`${Cn}: Skipping, excluded by "pattern" parameter.`);continue}if("image/png"!==r.getMimeType()&&"image/jpeg"!==r.getMimeType()){n.warn(`${Cn}: Skipping, unsupported texture type "${r.getMimeType()}".`);continue}const s=yt(r);if(t.slots&&!s.some(e=>{var n;return null==(n=t.slots)?void 0:n.test(e)})){n.debug(`${Cn}: Skipping, [${s.join(", ")}] excluded by "slots" parameter.`);continue}const[i,a]=t.size,[c,l]=r.getSize();if(c<=i&&l<=a){n.debug(`${Cn}: Skipping, not within size range.`);continue}let g=c,u=l;g>i&&(u=Math.floor(u*(i/g)),g=i),u>a&&(g=Math.floor(g*(a/u)),u=a);const f=r.getImage(),p=await S(f,r.getMimeType()),m=q(new Uint8Array(g*u*4),[g,u,4]);n.debug(`${Cn}: Resizing "${o||e}", ${p.shape} → ${m.shape}...`),n.debug(`${Cn}: Slots → [${s.join(", ")}]`);try{t.filter===On.LANCZOS3?_(p,m):k(p,m)}catch(t){if(t instanceof Error){n.warn(`${Cn}: Failed to resize "${o||e}": "${t.message}".`);continue}throw t}r.setImage(await I(m,r.getMimeType()))}n.debug(`${Cn}: Complete.`)})}const $n="textureCompress",xn=["jpeg","png","webp","avif"],zn=["image/jpeg","image/png","image/webp","image/avif"],Ln={resizeFilter:On.LANCZOS3,pattern:null,formats:null,slots:null,quality:null,effort:null,lossless:!1,nearLossless:!1},qn=function(e){const t=G({},Ln,e),n=t.targetFormat,r=t.pattern,o=t.formats,s=t.slots;if(!t.encoder)throw new Error(`${n}: encoder dependency required — install "sharp".`);return F($n,async e=>{const i=e.getLogger(),a=e.getRoot().listTextures();await Promise.all(a.map(async(a,c)=>{const l=yt(a),g=ht(a),u=a.getURI()||a.getName()||`${c+1}/${e.getRoot().listTextures().length}`,f=`${$n}(${u})`;if(!zn.includes(a.getMimeType()))return void i.debug(`${f}: Skipping, unsupported texture type "${a.getMimeType()}".`);if(r&&!r.test(a.getName())&&!r.test(a.getURI()))return void i.debug(`${f}: Skipping, excluded by "pattern" parameter.`);if(o&&!o.test(a.getMimeType()))return void i.debug(`${f}: Skipping, "${a.getMimeType()}" excluded by "formats" parameter.`);if(s&&l.length&&!l.some(e=>s.test(e)))return void i.debug(`${f}: Skipping, [${l.join(", ")}] excluded by "slots" parameter.`);if("jpeg"===t.targetFormat&&g&h.A)return void i.warn(`${f}: Skipping, [${l.join(", ")}] requires alpha channel.`);const p=kn(a);i.debug(`${f}: Format = ${p} → ${n||p}`),i.debug(`${f}: Slots = [${l.join(", ")}]`);const m=a.getImage(),d=m.byteLength;await _n(a,t);const A=a.getImage(),y=A.byteLength,E=m===A?" (SKIPPED":"";i.debug(`${f}: Size = ${j(d)} → ${j(y)}${E}`)}));const c=e.createExtension(v);a.some(e=>"image/webp"===e.getMimeType())?c.setRequired(!0):c.dispose();const l=e.createExtension(P);a.some(e=>"image/avif"===e.getMimeType())?l.setRequired(!0):l.dispose(),i.debug(`${$n}: Complete.`)})};async function _n(e,t){const n=G({},Ln,t),r=n.encoder;if(!r)throw new Error(`${n.targetFormat}: encoder dependency required — install "sharp".`);const o=kn(e),s=n.targetFormat||o,i=e.getMimeType(),c=`image/${s}`;let l={};switch(s){case"jpeg":l={quality:n.quality};break;case"png":l={quality:n.quality,effort:Gn(n.effort,100,10)};break;case"webp":l={quality:n.quality,effort:Gn(n.effort,100,6),lossless:n.lossless,nearLossless:n.nearLossless};break;case"avif":l={quality:n.quality,effort:Gn(n.effort,100,9),lossless:n.lossless}}const g=e.getImage(),u=r(g).toFormat(s,l);n.resize&&u.resize(n.resize[0],n.resize[1],{fit:"inside",kernel:n.resizeFilter,withoutEnlargement:!0});const f=a.toView(await u.toBuffer());if(!(i===c&&f.byteLength>=g.byteLength))if(i===c)e.setImage(f);else{const t=p.mimeTypeToExtension(i),n=p.mimeTypeToExtension(c),r=e.getURI().replace(new RegExp(`\\.${t}$`),`.${n}`);e.setImage(f).setMimeType(c).setURI(r)}}function kn(e){const t=e.getMimeType(),n=t.split("/").pop();if(!n||!xn.includes(n))throw new Error(`Unknown MIME type "${t}".`);return n}function Gn(e,t,n){return null==e?null:Math.round(e/t*n)}const Fn={overwrite:!1};function Bn(e=Fn){if(!e.generateTangents)throw new Error('tangents: generateTangents callback required — install "mikktspace".');const t=G({},Fn,e);return F("tangents",e=>{const n=e.getLogger(),r=new Map,o=new Map;let s=0;for(const i of e.getRoot().listMeshes()){const a=i.getName(),c=i.listPrimitives();for(let i=0;i<c.length;i++){const l=c[i];if(!Wn(l,n,a,i,t.overwrite))continue;const g=Un(l),u=l.getAttribute("POSITION").getArray(),f=l.getAttribute("NORMAL").getArray(),p=l.getAttribute(g).getArray(),m=r.get(u)||T();r.set(u,m);const d=r.get(f)||T();r.set(f,d);const h=r.get(p)||T();r.set(p,h);const A=l.getAttribute("TANGENT");A&&2===A.listParents().length&&A.dispose();const y=`${m}|${d}|${h}`;let E=o.get(y);if(E){n.debug(`tangents: Found cache for primitive ${i} of mesh "${a}".`),l.setAttribute("TANGENT",E),s++;continue}n.debug(`tangents: Generating for primitive ${i} of mesh "${a}".`);const S=l.getAttribute("POSITION").getBuffer(),I=t.generateTangents(u instanceof Float32Array?u:new Float32Array(u),f instanceof Float32Array?f:new Float32Array(f),p instanceof Float32Array?p:new Float32Array(p));for(let e=3;e<I.length;e+=4)I[e]*=-1;E=e.createAccessor().setBuffer(S).setArray(I).setType("VEC4"),l.setAttribute("TANGENT",E),o.set(y,E),s++}}s?n.debug("tangents: Complete."):n.warn("tangents: No qualifying primitives found. See debug output.")})}function Un(e){const t=e.getMaterial();if(!t)return"TEXCOORD_0";const n=t.getNormalTextureInfo();if(!n)return"TEXCOORD_0";const r=`TEXCOORD_${n.getTexCoord()}`;return e.getAttribute(r)?r:"TEXCOORD_0"}function Wn(t,n,r,o,s){return t.getMode()===e.Mode.TRIANGLES&&t.getAttribute("POSITION")&&t.getAttribute("NORMAL")&&t.getAttribute("TEXCOORD_0")?t.getAttribute("TANGENT")&&!s?(n.debug(`tangents: Skipping primitive ${o} of mesh "${r}": TANGENT found.`),!1):!t.getIndices()||(n.warn(`tangents: Skipping primitive ${o} of mesh "${r}": primitives must be unwelded.`),!1):(n.debug(`tangents: Skipping primitive ${o} of mesh "${r}": primitives must have attributes=[POSITION, NORMAL, TEXCOORD_0] and mode=TRIANGLES.`),!1)}const Hn=()=>e=>{const t=e.createExtension($).createUnlit();e.getRoot().listMaterials().forEach(e=>{e.setExtension("KHR_materials_unlit",t)})},jn={},Dn=(e=jn)=>(G({},jn,e),F("unpartition",async e=>{const t=e.getLogger(),n=e.getRoot().listBuffers()[0];e.getRoot().listAccessors().forEach(e=>e.setBuffer(n)),e.getRoot().listBuffers().forEach((e,t)=>t>0?e.dispose():null),t.debug("unpartition: Complete.")}));export{$e as DRACO_DEFAULTS,ke as FLATTEN_DEFAULTS,gt as JOIN_DEFAULTS,Ht as MESHOPT_DEFAULTS,$t as QUANTIZE_DEFAULTS,Mn as SIMPLIFY_DEFAULTS,Ln as TEXTURE_COMPRESS_DEFAULTS,vn as TEXTURE_RESIZE_DEFAULTS,On as TextureResizeFilter,dn as WELD_DEFAULTS,ee as center,ne as clearNodeParent,Ie as clearNodeTransform,we as colorspace,_n as compressTexture,St as createLayoutPlan,F as createTransform,Ne as dedup,Oe as dequantize,xe as draco,Ge as flatten,W as getGLPrimitiveCount,Fe as getNodeScene,ht as getTextureChannelMask,Be as inspect,Qe as instance,B as isTransformPending,ut as join,nt as joinPrimitives,te as listNodeScenes,dt as listTextureChannels,At as listTextureInfo,yt as listTextureSlots,jt as meshopt,Vt as metalRough,Qt as normals,tn as partition,Le as prune,xt as quantize,Tt as reorder,ln as resample,mn as sequence,wn as simplify,bn as simplifyPrimitive,It as sortPrimitiveWeights,Rn as sparse,Bn as tangents,qn as textureCompress,Pn as textureResize,Te as transformMesh,he as transformPrimitive,Hn as unlit,Dn as unpartition,Kt as unweld,hn as weld,An as weldPrimitive}; | ||
//# sourceMappingURL=functions.modern.js.map |
@@ -1,2 +0,2 @@ | ||
import { Transform, vec2 } from '@gltf-transform/core'; | ||
import { Texture, Transform, vec2 } from '@gltf-transform/core'; | ||
import { TextureResizeFilter } from './texture-resize.js'; | ||
@@ -38,2 +38,3 @@ type Format = (typeof FORMATS)[number]; | ||
} | ||
export type CompressTextureOptions = Omit<TextureCompressOptions, 'pattern' | 'formats' | 'slots'>; | ||
export declare const TEXTURE_COMPRESS_DEFAULTS: Required<Omit<TextureCompressOptions, 'resize' | 'targetFormat' | 'encoder'>>; | ||
@@ -48,4 +49,4 @@ /** | ||
* ```javascript | ||
* import { textureCompress } from '@gltf-transform/functions'; | ||
* import sharp from 'sharp'; | ||
* import { textureCompress } from '@gltf-transform/functions'; | ||
* | ||
@@ -61,4 +62,4 @@ * // (A) Optimize without conversion. | ||
* encoder: sharp, | ||
* codec: 'webp', | ||
* formats: /.*\/ | ||
* targetFormat: 'webp', | ||
* slots: /^(?!normalTexture).*$/ // exclude normal maps | ||
* }) | ||
@@ -69,2 +70,24 @@ * ); | ||
export declare const textureCompress: (_options: TextureCompressOptions) => Transform; | ||
/** | ||
* Optimizes a single {@link Texture}, optionally resizing or converting to JPEG, PNG, WebP, or AVIF formats. | ||
* | ||
* Requires `sharp`, and is available only in Node.js environments. | ||
* | ||
* Example: | ||
* | ||
* ```javascript | ||
* import { compressTexture } from '@gltf-transform/functions'; | ||
* import sharp from 'sharp'; | ||
* | ||
* const texture = document.getRoot().listTextures() | ||
* .find((texture) => texture.getName() === 'MyTexture'); | ||
* | ||
* await compressTexture(texture, { | ||
* encoder: sharp, | ||
* targetFormat: 'webp', | ||
* resize: [1024, 1024] | ||
* }); | ||
* ``` | ||
*/ | ||
export declare function compressTexture(texture: Texture, _options: CompressTextureOptions): Promise<void>; | ||
export {}; |
{ | ||
"name": "@gltf-transform/functions", | ||
"version": "3.1.1", | ||
"version": "3.1.2", | ||
"repository": "github:donmccurdy/glTF-Transform", | ||
@@ -38,4 +38,4 @@ "homepage": "https://gltf-transform.donmccurdy.com/functions.html", | ||
"dependencies": { | ||
"@gltf-transform/core": "^3.1.1", | ||
"@gltf-transform/extensions": "^3.1.1", | ||
"@gltf-transform/core": "^3.1.2", | ||
"@gltf-transform/extensions": "^3.1.2", | ||
"ktx-parse": "^0.5.0", | ||
@@ -56,3 +56,3 @@ "ndarray": "^1.0.19", | ||
}, | ||
"gitHead": "349535ca33d443fb58523a06f5afdd4d980da6fe" | ||
"gitHead": "7a7621cad44f8890233f7867841f8e039b49cd28" | ||
} |
@@ -50,2 +50,4 @@ import { BufferUtils, Document, ImageUtils, Texture, TextureChannel, Transform, vec2 } from '@gltf-transform/core'; | ||
export type CompressTextureOptions = Omit<TextureCompressOptions, 'pattern' | 'formats' | 'slots'>; | ||
export const TEXTURE_COMPRESS_DEFAULTS: Required<Omit<TextureCompressOptions, 'resize' | 'targetFormat' | 'encoder'>> = | ||
@@ -71,4 +73,4 @@ { | ||
* ```javascript | ||
* import { textureCompress } from '@gltf-transform/functions'; | ||
* import sharp from 'sharp'; | ||
* import { textureCompress } from '@gltf-transform/functions'; | ||
* | ||
@@ -84,4 +86,4 @@ * // (A) Optimize without conversion. | ||
* encoder: sharp, | ||
* codec: 'webp', | ||
* formats: /.*\/ | ||
* targetFormat: 'webp', | ||
* slots: /^(?!normalTexture).*$/ // exclude normal maps | ||
* }) | ||
@@ -95,4 +97,2 @@ * ); | ||
const targetFormat = options.targetFormat as Format | undefined; | ||
const resize = options.resize as vec2 | undefined; | ||
const resizeFilter = options.resizeFilter as TextureResizeFilter; | ||
const patternRe = options.pattern; | ||
@@ -141,72 +141,15 @@ const formatsRe = options.formats; | ||
const dstFormat = targetFormat || srcFormat; | ||
const srcMimeType = texture.getMimeType(); | ||
const dstMimeType = `image/${dstFormat}`; | ||
logger.debug(`${prefix}: Format = ${srcFormat} → ${dstFormat}`); | ||
logger.debug(`${prefix}: Slots = [${slots.join(', ')}]`); | ||
// COMPRESS: Run compression library. | ||
let encoderOptions: sharp.JpegOptions | sharp.PngOptions | sharp.WebpOptions | sharp.AvifOptions = {}; | ||
switch (dstFormat) { | ||
case 'jpeg': | ||
encoderOptions = { quality: options.quality } as sharp.JpegOptions; | ||
break; | ||
case 'png': | ||
encoderOptions = { | ||
quality: options.quality, | ||
effort: remap(options.effort, 100, 10), | ||
} as sharp.PngOptions; | ||
break; | ||
case 'webp': | ||
encoderOptions = { | ||
quality: options.quality, | ||
effort: remap(options.effort, 100, 6), | ||
lossless: options.lossless, | ||
nearLossless: options.nearLossless, | ||
} as sharp.WebpOptions; | ||
break; | ||
case 'avif': | ||
encoderOptions = { | ||
quality: options.quality, | ||
effort: remap(options.effort, 100, 9), | ||
lossless: options.lossless, | ||
} as sharp.AvifOptions; | ||
break; | ||
} | ||
const srcImage = texture.getImage()!; | ||
const instance = encoder(srcImage).toFormat(dstFormat, encoderOptions); | ||
const srcByteLength = srcImage.byteLength; | ||
// Resize. | ||
if (resize) { | ||
instance.resize(resize[0], resize[1], { | ||
fit: 'inside', | ||
kernel: resizeFilter, | ||
withoutEnlargement: true, | ||
}); | ||
} | ||
await compressTexture(texture, options); | ||
const dstImage = BufferUtils.toView(await instance.toBuffer()); | ||
const srcByteLength = srcImage.byteLength; | ||
const dstImage = texture.getImage()!; | ||
const dstByteLength = dstImage.byteLength; | ||
let flag = ''; | ||
const flag = srcImage === dstImage ? ' (SKIPPED' : ''; | ||
if (srcMimeType === dstMimeType && dstByteLength >= srcByteLength) { | ||
// Skip if src/dst formats match and dst is larger than the original. | ||
flag = ' (SKIPPED)'; | ||
} else if (srcMimeType === dstMimeType) { | ||
// Overwrite if src/dst formats match and dst is smaller than the original. | ||
texture.setImage(dstImage); | ||
} else { | ||
// Overwrite, then update path and MIME type if src/dst formats differ. | ||
const srcExtension = ImageUtils.mimeTypeToExtension(srcMimeType); | ||
const dstExtension = ImageUtils.mimeTypeToExtension(dstMimeType); | ||
const dstURI = texture.getURI().replace(new RegExp(`\\.${srcExtension}$`), `.${dstExtension}`); | ||
texture.setImage(dstImage).setMimeType(dstMimeType).setURI(dstURI); | ||
} | ||
logger.debug(`${prefix}: Size = ${formatBytes(srcByteLength)} → ${formatBytes(dstByteLength)}${flag}`); | ||
@@ -236,2 +179,97 @@ }) | ||
/** | ||
* Optimizes a single {@link Texture}, optionally resizing or converting to JPEG, PNG, WebP, or AVIF formats. | ||
* | ||
* Requires `sharp`, and is available only in Node.js environments. | ||
* | ||
* Example: | ||
* | ||
* ```javascript | ||
* import { compressTexture } from '@gltf-transform/functions'; | ||
* import sharp from 'sharp'; | ||
* | ||
* const texture = document.getRoot().listTextures() | ||
* .find((texture) => texture.getName() === 'MyTexture'); | ||
* | ||
* await compressTexture(texture, { | ||
* encoder: sharp, | ||
* targetFormat: 'webp', | ||
* resize: [1024, 1024] | ||
* }); | ||
* ``` | ||
*/ | ||
export async function compressTexture(texture: Texture, _options: CompressTextureOptions) { | ||
const options = { ...TEXTURE_COMPRESS_DEFAULTS, ..._options } as Required<CompressTextureOptions>; | ||
const encoder = options.encoder as typeof sharp | null; | ||
if (!encoder) { | ||
throw new Error(`${options.targetFormat}: encoder dependency required — install "sharp".`); | ||
} | ||
const srcFormat = getFormat(texture); | ||
const dstFormat = options.targetFormat || srcFormat; | ||
const srcMimeType = texture.getMimeType(); | ||
const dstMimeType = `image/${dstFormat}`; | ||
let encoderOptions: sharp.JpegOptions | sharp.PngOptions | sharp.WebpOptions | sharp.AvifOptions = {}; | ||
switch (dstFormat) { | ||
case 'jpeg': | ||
encoderOptions = { quality: options.quality } as sharp.JpegOptions; | ||
break; | ||
case 'png': | ||
encoderOptions = { | ||
quality: options.quality, | ||
effort: remap(options.effort, 100, 10), | ||
} as sharp.PngOptions; | ||
break; | ||
case 'webp': | ||
encoderOptions = { | ||
quality: options.quality, | ||
effort: remap(options.effort, 100, 6), | ||
lossless: options.lossless, | ||
nearLossless: options.nearLossless, | ||
} as sharp.WebpOptions; | ||
break; | ||
case 'avif': | ||
encoderOptions = { | ||
quality: options.quality, | ||
effort: remap(options.effort, 100, 9), | ||
lossless: options.lossless, | ||
} as sharp.AvifOptions; | ||
break; | ||
} | ||
const srcImage = texture.getImage()!; | ||
const instance = encoder(srcImage).toFormat(dstFormat, encoderOptions); | ||
// Resize. | ||
if (options.resize) { | ||
instance.resize(options.resize[0], options.resize[1], { | ||
fit: 'inside', | ||
kernel: options.resizeFilter, | ||
withoutEnlargement: true, | ||
}); | ||
} | ||
const dstImage = BufferUtils.toView(await instance.toBuffer()); | ||
const srcByteLength = srcImage.byteLength; | ||
const dstByteLength = dstImage.byteLength; | ||
if (srcMimeType === dstMimeType && dstByteLength >= srcByteLength) { | ||
// Skip if src/dst formats match and dst is larger than the original. | ||
return; | ||
} else if (srcMimeType === dstMimeType) { | ||
// Overwrite if src/dst formats match and dst is smaller than the original. | ||
texture.setImage(dstImage); | ||
} else { | ||
// Overwrite, then update path and MIME type if src/dst formats differ. | ||
const srcExtension = ImageUtils.mimeTypeToExtension(srcMimeType); | ||
const dstExtension = ImageUtils.mimeTypeToExtension(dstMimeType); | ||
const dstURI = texture.getURI().replace(new RegExp(`\\.${srcExtension}$`), `.${dstExtension}`); | ||
texture.setImage(dstImage).setMimeType(dstMimeType).setURI(dstURI); | ||
} | ||
} | ||
function getFormat(texture: Texture): Format { | ||
@@ -238,0 +276,0 @@ const mimeType = texture.getMimeType(); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1151103
6232