@babylonjs/viewer
Version:
The Babylon Viewer aims to simplify a specific but common Babylon.js use case: loading, viewing, and interacting with a 3D model.
3 lines • 126 kB
JavaScript
import{cq as e,cr as t,cs as s,aV as i,i as n,b1 as a,c as o,a7 as r,F as l,aE as h,aW as c,V as u,y as d,ct as _,aH as f,C as p,cu as m,br as g,aY as x,be as b,bc as y,bq as M,cv as S,M as v,aU as w,bl as R,aD as T,cw as C,b3 as A,T as q,a as D,ca as k,p as L,ci as F,cx as P,cy as z,cz as E,bn as B,cA as O,w as I,cB as U}from"./index-OM-TXt9s.esm.min.js";import"./thinInstanceMesh-CpqLNoqY.esm.min.js";import"./tools-BD_NEqcj.esm.min.js";import{I as W,A as N}from"./assetContainer-BpKLnjKZ.esm.min.js";import"./buffer-DAhrDBRW.esm.min.js";import"./shaderMaterial-dqH3UF0Q.esm.min.js";import{R as V}from"./ray.core-BGAt3Tqp.esm.min.js";import{S as G}from"./standardMaterial.pure-CDkApYCL.esm.min.js";import"./prepass.defines-izweOGjj.esm.min.js";import"./material.detailMapConfiguration-CnvG2ZB5.esm.min.js";e(),t(),s();class X extends i{_isShaderMaterial(e){return!!e&&"ShaderMaterial"===e.getClassName()}constructor(e,t=null,s=null,i=null,l,h,c,u){super(e,t,s,i,l),this.useVertexColor=h,this.useVertexAlpha=c,this.color=new n(1,1,1),this.alpha=1,this._shaderLanguage=0,this._ownsMaterial=!1,i&&(this.color=i.color.clone(),this.alpha=i.alpha,this.useVertexColor=i.useVertexColor,this.useVertexAlpha=i.useVertexAlpha),this.intersectionThreshold=.1;const d={attributes:[r.PositionKind],uniforms:["world","viewProjection"],needAlphaBlending:!0,defines:[],useClipPlane:null,shaderLanguage:0};if(this.useVertexAlpha?d.defines.push("#define VERTEXALPHA"):d.needAlphaBlending=!1,this.useVertexColor?(d.defines.push("#define VERTEXCOLOR"),d.attributes.push(r.ColorKind)):(d.uniforms.push("color"),this._color4=new a),u)this.material=u;else{this.getScene().getEngine().isWebGPU&&!X.ForceGLSL&&(this._shaderLanguage=1),d.shaderLanguage=this._shaderLanguage,d.extraInitializationsAsync=async()=>{1===this._shaderLanguage?await Promise.all([import("./color.vertex-DrvaSxOI.esm.min.js"),import("./color.fragment-B3acZgq-.esm.min.js")]):await Promise.all([import("./color.vertex-DZSWTOP_.esm.min.js"),import("./color.fragment-JT4DIjR0.esm.min.js")])};const e=new o("colorShader",this.getScene(),"color",d,!1);e.doNotSerialize=!0,this._ownsMaterial=!0,this._setInternalMaterial(e)}}getClassName(){return"LinesMesh"}get material(){return this._internalAbstractMeshDataInfo._material}set material(e){const t=this.material;if(t===e)return;const s=t&&this._ownsMaterial;this._ownsMaterial=!1,this._setInternalMaterial(e),s&&t?.dispose()}_setInternalMaterial(e){this._setMaterial(e),this.material&&(this.material.fillMode=l.LineListDrawMode,this.material.disableLighting=!0)}get checkCollisions(){return!1}set checkCollisions(e){}_bind(e,t){if(!this._geometry)return this;const s=this.isUnIndexed?null:this._geometry.getIndexBuffer();if(!this._userInstancedBuffersStorage||this.hasThinInstances?this._geometry._bind(t,s):this._geometry._bind(t,s,this._userInstancedBuffersStorage.vertexBuffers,this._userInstancedBuffersStorage.vertexArrayObjects),!this.useVertexColor&&this._isShaderMaterial(this.material)){const{r:e,g:t,b:s}=this.color;this._color4.set(e,t,s,this.alpha),this.material.setColor4("color",this._color4)}return this}_draw(e,t,s){if(!this._geometry||!this._geometry.getVertexBuffers()||!this._unIndexed&&!this._geometry.getIndexBuffer())return this;const i=this.getScene().getEngine();return this._unIndexed?i.drawArraysType(l.LineListDrawMode,e.verticesStart,e.verticesCount,s):i.drawElementsType(l.LineListDrawMode,e.indexStart,e.indexCount,s),this}dispose(e,t=!1,s){s||(this._ownsMaterial||t)&&this.material?.dispose(!1,!1,!0),super.dispose(e)}clone(e,t=null,s){if(t&&void 0===t._addToSceneRootNodes){const s=t;return s.source=this,new X(e,this.getScene(),s.parent,s.source,s.doNotCloneChildren)}return new X(e,this.getScene(),t,this,s)}createInstance(e){const t=new j(e,this);if(this.instancedBuffers){t.instancedBuffers={};for(const e in this.instancedBuffers)t.instancedBuffers[e]=this.instancedBuffers[e]}return t}serialize(e){super.serialize(e),e.color=this.color.asArray(),e.alpha=this.alpha}static Parse(e,t){const s=new X(e.name,t);return s.color=n.FromArray(e.color),s.alpha=e.alpha,s}}X.ForceGLSL=!1;class j extends W{constructor(e,t){super(e,t),this.intersectionThreshold=t.intersectionThreshold}getClassName(){return"InstancedLinesMesh"}}function H(e){const t=[],s=[],i=e.lines,n=e.colors,a=[];let o=0;for(let e=0;e<i.length;e++){const r=i[e];for(let i=0;i<r.length;i++){const{x:l,y:h,z:c}=r[i];if(s.push(l,h,c),n){const t=n[e],{r:s,g:o,b:r,a:l}=t[i];a.push(s,o,r,l)}i>0&&(t.push(o-1),t.push(o)),o++}}const r=new c;return r.indices=t,r.positions=s,n&&(r.colors=a),r}function Y(e){const t=e.dashSize||3,s=e.gapSize||1,i=e.dashNb||200,n=e.points,a=[],o=[],r=u.Zero();let l,h,d,_=0,f=0;for(d=0;d<n.length-1;d++)n[d+1].subtractToRef(n[d],r),_+=r.length();const p=_/i,m=t*p/(t+s);for(d=0;d<n.length-1;d++){n[d+1].subtractToRef(n[d],r),l=Math.floor(r.length()/p),r.normalize();for(let e=0;e<l;e++)h=p*e,a.push(n[d].x+h*r.x,n[d].y+h*r.y,n[d].z+h*r.z),a.push(n[d].x+(h+m)*r.x,n[d].y+(h+m)*r.y,n[d].z+(h+m)*r.z),o.push(f,f+1),f+=2}const g=new c;return g.positions=a,g.indices=o,g}function Z(e,t,s=null){const i=t.instance,n=t.lines,a=t.colors;if(i){const e=i.getVerticesData(r.PositionKind);let t,s;a&&(t=i.getVerticesData(r.ColorKind));let o=0,l=0;for(let i=0;i<n.length;i++){const r=n[i];for(let n=0;n<r.length;n++)e[o]=r[n].x,e[o+1]=r[n].y,e[o+2]=r[n].z,a&&t&&(s=a[i],t[l]=s[n].r,t[l+1]=s[n].g,t[l+2]=s[n].b,t[l+3]=s[n].a,l+=4),o+=3}return i.updateVerticesData(r.PositionKind,e,!1,!1),a&&t&&i.updateVerticesData(r.ColorKind,t,!1,!1),i.refreshBoundingInfo(),i}const o=new X(e,s,null,void 0,void 0,!!a,t.useVertexAlpha,t.material);return H(t).applyToMesh(o,t.updatable),o}X.prototype.enableEdgesRendering??=h("LinesMesh","enableEdgesRendering"),j.prototype.enableEdgesRendering??=h("InstancedLinesMesh","enableEdgesRendering");let Q=!1;Q||(Q=!0,c.CreateLineSystem=H,c.CreateDashedLines=Y,i.CreateLines=(e,t,s=null,i=!1,n=null)=>function(e,t,s=null){const i=t.colors?[t.colors]:null;return Z(e,{lines:[t.points],updatable:t.updatable,instance:t.instance,colors:i,useVertexAlpha:t.useVertexAlpha,material:t.material},s)}(e,{points:t,updatable:i,instance:n},s),i.CreateDashedLines=(e,t,s,i,n,a=null,o,r)=>function(e,t,s=null){const i=t.points,n=t.instance,a=t.gapSize||1,o=t.dashSize||3;if(n){const e=e=>{const t=u.Zero(),s=e.length/6;let a,o,r,l,h=0,c=0;for(r=0;r<i.length-1;r++)i[r+1].subtractToRef(i[r],t),h+=t.length();const d=h/s,_=n._creationDataStorage.dashSize,f=_*d/(_+n._creationDataStorage.gapSize);for(r=0;r<i.length-1;r++)for(i[r+1].subtractToRef(i[r],t),a=Math.floor(t.length()/d),t.normalize(),l=0;l<a&&c<e.length;)o=d*l,e[c]=i[r].x+o*t.x,e[c+1]=i[r].y+o*t.y,e[c+2]=i[r].z+o*t.z,e[c+3]=i[r].x+(o+f)*t.x,e[c+4]=i[r].y+(o+f)*t.y,e[c+5]=i[r].z+(o+f)*t.z,c+=6,l++;for(;c<e.length;)e[c]=i[r].x,e[c+1]=i[r].y,e[c+2]=i[r].z,c+=3};return(t.dashNb||t.dashSize||t.gapSize||t.useVertexAlpha||t.material)&&d.Warn("You have used an option other than points with the instance option. Please be aware that these other options will be ignored."),n.updateMeshPositions(e,!1),n}const r=new X(e,s,null,void 0,void 0,void 0,t.useVertexAlpha,t.material);return Y(t).applyToMesh(r,t.updatable),r._creationDataStorage=new _,r._creationDataStorage.dashSize=o,r._creationDataStorage.gapSize=a,r}(e,{points:t,dashSize:s,gapSize:i,dashNb:n,updatable:o,instance:r},a));const $=.28209479177387814;async function K(e,t,s){const i=new Promise((i,n)=>{const a=s.createCanvasImage();if(!a)throw new Error("Failed to create ImageBitmap");let o;if(a.onload=()=>{try{const e=s.createCanvas(a.width,a.height);if(!e)throw new Error("Failed to create canvas");const t=e.getContext("2d");if(!t)throw new Error("Failed to get 2D context");t.drawImage(a,0,0);const n=t.getImageData(0,0,e.width,e.height);i({bits:new Uint8Array(n.data.buffer),width:n.width,height:n.height})}catch(e){n(`Error loading image ${a.src} with exception: ${e}`)}},a.onerror=e=>{n(`Error loading image ${a.src} with exception: ${e}`)},a.crossOrigin="anonymous","string"==typeof e){if(!t)throw new Error("filename is required when using a URL");a.src=e+t}else{const t=new Blob([e],{type:"image/webp"});o=URL.createObjectURL(t),a.src=o}});return await i}async function J(e,t,s){let i,n;if(e instanceof Map){n=e;const t=n.get("meta.json");if(!t)throw new Error("meta.json not found in files Map");i=JSON.parse((new TextDecoder).decode(t))}else i=e;const a=[...i.means.files,...i.scales.files,...i.quats.files,...i.sh0.files];i.shN&&a.push(...i.shN.files);const o=await Promise.all(a.map(async e=>{if(n&&n.has(e)){const t=n.get(e);return await K(t,e,s.getEngine())}return await K(t,e,s.getEngine())}));return await async function(e,t,s){const i=e.count?e.count:e.means.shape[0],n=new ArrayBuffer(32*i),a=new Float32Array(n),o=new Float32Array(n),r=new Uint8ClampedArray(n),l=new Uint8ClampedArray(n),h=e=>Math.sign(e)*(Math.exp(Math.abs(e))-1),c=t[0].bits,u=t[1].bits;if(!Array.isArray(e.means.mins)||!Array.isArray(e.means.maxs))throw new Error("Missing arrays in SOG data.");for(let t=0;t<i;t++){const s=4*t;for(let i=0;i<3;i++){const n=e.means.mins[i],o=e.means.maxs[i],r=u[s+i]<<8|c[s+i],l=m.Lerp(n,o,r/65535);a[8*t+i]=h(l)}}const d=t[2].bits;if(2===e.version){if(!e.scales.codebook)throw new Error("Missing codebook in SOG version 2 scales data.");for(let t=0;t<i;t++){const s=4*t;for(let i=0;i<3;i++){const n=e.scales.codebook[d[s+i]],a=Math.exp(n);o[8*t+3+i]=a}}}else{if(!Array.isArray(e.scales.mins)||!Array.isArray(e.scales.maxs))throw new Error("Missing arrays in SOG scales data.");for(let t=0;t<i;t++){const s=4*t;for(let i=0;i<3;i++){const n=d[s+i],a=m.Lerp(e.scales.mins[i],e.scales.maxs[i],n/255),r=Math.exp(a);o[8*t+3+i]=r}}}const _=t[4].bits;if(2===e.version){if(!e.sh0.codebook)throw new Error("Missing codebook in SOG version 2 sh0 data.");for(let t=0;t<i;t++){const s=4*t;for(let i=0;i<3;i++){const n=.5+e.sh0.codebook[_[s+i]]*$;r[32*t+24+i]=Math.max(0,Math.min(255,Math.round(255*n)))}r[32*t+24+3]=_[s+3]}}else{if(!Array.isArray(e.sh0.mins)||!Array.isArray(e.sh0.maxs))throw new Error("Missing arrays in SOG sh0 data.");for(let t=0;t<i;t++){const s=4*t;for(let i=0;i<4;i++){const n=e.sh0.mins[i],a=e.sh0.maxs[i],o=_[s+i],l=m.Lerp(n,a,o/255);let h;h=i<3?.5+l*$:1/(1+Math.exp(-l)),r[32*t+24+i]=Math.max(0,Math.min(255,Math.round(255*h)))}}}const f=e=>2*(e/255-.5)/Math.SQRT2,p=t[3].bits;for(let e=0;e<i;e++){const t=p[4*e+0],s=p[4*e+1],i=p[4*e+2],n=p[4*e+3],a=f(t),o=f(s),r=f(i),h=n-252,c=a*a+o*o+r*r,u=Math.sqrt(Math.max(0,1-c));let d;switch(h){case 0:d=[u,a,o,r];break;case 1:d=[a,u,o,r];break;case 2:d=[a,o,u,r];break;case 3:d=[a,o,r,u];break;default:throw new Error("Invalid quaternion mode")}l[32*e+28+0]=127.5*d[0]+127.5,l[32*e+28+1]=127.5*d[1]+127.5,l[32*e+28+2]=127.5*d[2]+127.5,l[32*e+28+3]=127.5*d[3]+127.5}if(e.shN){const a=e.shN.bands?(e.shN.bands+1)**2-1:e.shN.shape[1]/3,o=void 0!==e.shN.bands&&null!==e.shN.bands?e.shN.bands:Math.round(Math.sqrt(a+1)-1),r=t[5].bits,l=t[6].bits,h=t[5].width,c=3*a,u=Math.ceil(c/16),d=s.getEngine().getCaps().maxTextureSize,_=Math.ceil(i/d),f=g(u,_*d*4*4);if(2===e.version){if(!e.shN.codebook)throw new Error("Missing codebook in SOG version 2 shN data.");for(let t=0;t<i;t++){const s=l[4*t+0]+(l[4*t+1]<<8),i=s%64*a,n=Math.floor(s/64);for(let s=0;s<a;s++)for(let a=0;a<3;a++){const o=3*s+a,l=Math.floor(o/16),c=f[l],u=o%16,d=16*t,_=127.5*e.shN.codebook[r[4*(i+s)+a+n*h*4]]+127.5;c[u+d]=Math.max(0,Math.min(255,_))}}}else for(let t=0;t<i;t++){const s=l[4*t+0]+(l[4*t+1]<<8),i=s%64*a,n=Math.floor(s/64),o=e.shN.mins,c=e.shN.maxs;for(let e=0;e<3;e++)for(let s=0;s<a/3;s++){const a=3*s+e,l=Math.floor(a/16),u=f[l],d=a%16,_=16*t,p=127.5*m.Lerp(o,c,r[4*(i+s)+e+n*h*4]/255)+127.5;u[d+_]=Math.max(0,Math.min(255,p))}}return await new Promise(e=>{e({mode:0,data:n,hasVertexColors:!1,sh:f,shDegree:o})})}return await new Promise(e=>{e({mode:0,data:n,hasVertexColors:!1})})}(i,o,s)}function ee(e,t){return function(e,t,s,i){const n=new f(t,s,i,p.TEXTUREFORMAT_RGBA,e,!1,!1,p.TEXTURE_NEAREST_SAMPLINGMODE,p.TEXTURETYPE_UNSIGNED_BYTE);return n.wrapU=p.TEXTURE_CLAMP_ADDRESSMODE,n.wrapV=p.TEXTURE_CLAMP_ADDRESSMODE,n}(e,t.bits,t.width,t.height)}async function te(e,t,s){const i=s.getEngine();if("function"==typeof createImageBitmap)try{const n=t.toLowerCase().endsWith(".png")?"image/png":"image/webp";let a;if("string"==typeof e){const s=await x.LoadFileAsync(e+t,!0);a=new Blob([s],{type:n})}else a=new Blob([e],{type:n});const o=await createImageBitmap(a,{premultiplyAlpha:"none",colorSpaceConversion:"none"});try{const e=new f(null,o.width,o.height,p.TEXTUREFORMAT_RGBA,s,!1,!1,p.TEXTURE_NEAREST_SAMPLINGMODE,p.TEXTURETYPE_UNSIGNED_BYTE);e.wrapU=p.TEXTURE_CLAMP_ADDRESSMODE,e.wrapV=p.TEXTURE_CLAMP_ADDRESSMODE;const t=e.getInternalTexture();return t&&i.updateDynamicTexture(t,o,!1,!1),e}finally{o.close()}}catch{}return ee(s,await K(e,t,i))}function se(e,t,s,i){const n=e=>Math.sign(e)*(Math.exp(Math.abs(e))-1);if(!Array.isArray(e.means.mins)||!Array.isArray(e.means.maxs))throw new Error("Missing arrays in SOG data.");const a=new Float32Array(4*i);for(let o=0;o<i;o++){const i=4*o;for(let r=0;r<3;r++){const l=s[i+r]<<8|t[i+r],h=m.Lerp(e.means.mins[r],e.means.maxs[r],l/65535);a[4*o+r]=n(h)}a[4*o+3]=1}return a}async function ie(e,t,s,i=!0,n,a){let o,r;if(e instanceof Map){r=e;const t=r.get("meta.json");if(!t)throw new Error("meta.json not found in files Map");o=JSON.parse((new TextDecoder).decode(t))}else o=e;const l=async e=>{if(r&&r.has(e))return await K(r.get(e),e,s.getEngine());if(n){const i=new Uint8Array(await n.loadFileAsync(t+e,a));return await K(i,e,s.getEngine())}return await K(t,e,s.getEngine())},h=async e=>{if(r&&r.has(e))return await te(r.get(e),e,s);if(n){const i=new Uint8Array(await n.loadFileAsync(t+e,a));return await te(i,e,s)}return await te(t,e,s)},c=[...o.scales.files,...o.quats.files,...o.sh0.files,...o.shN?.files??[]];let u,d,_,m,g,x=null;if(i){const[e,t]=await Promise.all([Promise.all(o.means.files.map(l)),Promise.all(c.map(h))]);x=[e[0],e[1]],g=t,u=ee(s,e[0]),d=ee(s,e[1]),_=e[0].width,m=e[0].height}else{const[e,t]=await Promise.all([Promise.all(o.means.files.map(h)),Promise.all(c.map(h))]);g=t,u=e[0],d=e[1];const s=u.getSize();_=s.width,m=s.height}const b=o.count??o.means.shape[0],y=_*m;if(y<b)throw new Error(`SOG texture contains ${y} texels, but metadata references ${b} splats.`);const M=g[0],S=g[1],v=g[2];let w,R,T,C=0,A=0;if(o.shN&&g.length>=5&&(w=g[3],R=g[4],C=o.shN.bands?(o.shN.bands+1)**2-1:o.shN.shape[1]/3,A=o.shN.bands??Math.round(Math.sqrt(C+1)-1)),2===o.version){const e=256,t=new Float32Array(3*e);o.scales.codebook&&t.set(o.scales.codebook.slice(0,e),0),o.sh0.codebook&&t.set(o.sh0.codebook.slice(0,e),e),o.shN?.codebook&&t.set(o.shN.codebook.slice(0,e),2*e),T=new f(t,3*e,1,p.TEXTUREFORMAT_R,s,!1,!1,p.TEXTURE_NEAREST_SAMPLINGMODE,p.TEXTURETYPE_FLOAT),T.wrapU=p.TEXTURE_CLAMP_ADDRESSMODE,T.wrapV=p.TEXTURE_CLAMP_ADDRESSMODE}const q=o.means.mins,D=o.means.maxs,k={version:2===o.version?2:1,splatCount:b,shDegree:A,meansTextureL:u,meansTextureU:d,scalesTexture:M,quatsTexture:S,sh0Texture:v,shCentroidsTexture:w,shLabelsTexture:R,codebookTexture:T,meansMin:[q[0],q[1],q[2]],meansMax:[D[0],D[1],D[2]],scalesMin:Array.isArray(o.scales.mins)?[o.scales.mins[0],o.scales.mins[1],o.scales.mins[2]]:void 0,scalesMax:Array.isArray(o.scales.maxs)?[o.scales.maxs[0],o.scales.maxs[1],o.scales.maxs[2]]:void 0,sh0Min:Array.isArray(o.sh0.mins)?[o.sh0.mins[0],o.sh0.mins[1],o.sh0.mins[2],o.sh0.mins[3]]:void 0,sh0Max:Array.isArray(o.sh0.maxs)?[o.sh0.maxs[0],o.sh0.maxs[1],o.sh0.maxs[2],o.sh0.maxs[3]]:void 0,shnMin:"number"==typeof o.shN?.mins?o.shN.mins:void 0,shnMax:"number"==typeof o.shN?.maxs?o.shN.maxs:void 0,shCoeffCount:C,positions:x?se(o,x[0].bits,x[1].bits,b):new Float32Array(0)};return{mode:0,data:new ArrayBuffer(0),hasVertexColors:!1,shDegree:A,sogTextures:k}}const ne="precision highp float;\nattribute vec3 position;\nvoid main() {\n gl_Position = vec4(position.xy, 0.0, 1.0);\n}\n",ae="\nattribute position : vec3<f32>;\n@vertex\nfn main(input : VertexInputs) -> FragmentInputs {\n vertexOutputs.position = vec4<f32>(input.position.xy, 0.0, 1.0);\n}\n";class oe{get supportsAsyncCentersReadback(){const e=this._scene.getEngine();if(e.isWebGPU)return!0;const t=e;return!!t._gl&&"function"==typeof t._readPixelsAsync&&(t.webGLVersion??0)>=2}get textureSize(){return this._textureSize}get textures(){return this._mrt.textures}get shTextures(){return this._shMrts.map(e=>e.textures[0])}get rotationTextures(){return this._rotMrt?this._rotMrt.textures:[]}constructor(e,t,s,i,n){if(this._copyMaterial=null,this._relayoutMapData=null,this._relayoutMapTexture=null,this._backupMrt=null,this._disposed=!1,this._readFbo=null,this._shMrts=[],this._ownsShMrts=!1,this._shMaterial=null,this._shCopyMaterial=null,this._backupShMrts=null,this._rotMrt=null,this._ownsRotMrt=!1,this._rotMaterial=null,this._rotCopyMaterial=null,this._backupRotMrt=null,this._scene=e,this._shaderLanguage=e.getEngine().isWebGPU?1:0,this._capacity=Math.max(1,t),s?(this._mrt=s.mrt,this._textureSize=s.width,this._baseOffset=s.baseOffset,this._ownsMrt=!1):(this._textureSize=Math.max(1,Math.ceil(Math.sqrt(Math.max(1,t)))),this._baseOffset=0,this._ownsMrt=!0,this._mrt=this._createMrt("gsWorkBuffer",!0)),i&&i.textureCount>0){if(i.externalMrts)this._shMrts=i.externalMrts.slice(0,i.textureCount),this._ownsShMrts=!1;else{for(let e=0;e<i.textureCount;e++)this._shMrts.push(this._createShMrt(`gsWorkBufferSh${e}`,!0));this._ownsShMrts=!0}this._shMaterial=this._createShMaterial()}n&&(n.externalMrt?(this._rotMrt=n.externalMrt,this._ownsRotMrt=!1):(this._rotMrt=this._createRotMrt("gsWorkBufferRot",!0),this._ownsRotMrt=!0),this._rotMaterial=this._createRotMaterial()),this._material=this._createMaterial(),this._quad=this._createQuad(),this._quad.material=this._material,this._ownsMrt||this.isRelayoutReady()}rebindAtlas(e){this._ownsMrt||(this._mrt=e)}rebindShAtlas(e){!this._ownsShMrts&&e&&this._shMrts.length&&(this._shMrts=e.slice(0,this._shMrts.length))}rebindRotAtlas(e){!this._ownsRotMrt&&e&&this._rotMrt&&(this._rotMrt=e)}setBaseOffset(e){this._ownsMrt||(this._baseOffset=e)}get canBackup(){return!this._disposed&&!this._ownsMrt&&this.isRelayoutReady()}backupRegion(){if(this._disposed||this._ownsMrt)return;if(!this.isRelayoutReady())return void d.Warn("GaussianSplattingWorkBuffer: backup skipped because the copy shaders are not ready; streamed region data may be lost on the atlas rebuild.");const e=this._textureSize,t=Math.max(1,Math.floor(this._capacity/e)),s=Math.floor(this._baseOffset/e);if(this._backupMrt||(this._backupMrt=this._createMrt("gsAtlasBackup",!1,e,t)),this._renderRelayoutPass(this._backupMrt,this._mrt.textures,this._mrt.textures[0],0,e,e,0,-s),this._shMrts.length&&this._shCopyMaterial){this._backupShMrts||(this._backupShMrts=this._shMrts.map((s,i)=>this._createShMrt(`gsShAtlasBackup${i}`,!1,e,t)));for(let t=0;t<this._shMrts.length;t++)this._renderShCopyPass(this._backupShMrts[t],this._shMrts[t].textures[0],this._mrt.textures[0],0,e,e,0,-s)}this._rotMrt&&this._rotCopyMaterial&&(this._backupRotMrt||(this._backupRotMrt=this._createRotMrt("gsRotAtlasBackup",!1,e,t)),this._renderRotCopyPass(this._backupRotMrt,this._rotMrt.textures,this._mrt.textures[0],0,e,e,0,-s)),this._quad.material=this._material}restoreRegion(){if(this._disposed||this._ownsMrt||!this._backupMrt||!this._copyMaterial)return;const e=this._textureSize,t=Math.max(1,Math.floor(this._capacity/e)),s=Math.floor(this._baseOffset/e),i=this._scene.getEngine();i.enableScissor(0,s,e,t);try{if(this._renderRelayoutPass(this._mrt,this._backupMrt.textures,this._backupMrt.textures[0],0,e,e,0,s),this._backupShMrts&&this._shMrts.length&&this._shCopyMaterial)for(let t=0;t<this._shMrts.length&&t<this._backupShMrts.length;t++)this._renderShCopyPass(this._shMrts[t],this._backupShMrts[t].textures[0],this._mrt.textures[0],0,e,e,0,s);this._backupRotMrt&&this._rotMrt&&this._rotCopyMaterial&&this._renderRotCopyPass(this._rotMrt,this._backupRotMrt.textures,this._mrt.textures[0],0,e,e,0,s)}finally{i.disableScissor(),this._quad.material=this._material}if(this._backupMrt.dispose(),this._backupMrt=null,this._backupShMrts){for(const e of this._backupShMrts)e.dispose();this._backupShMrts=null}this._backupRotMrt?.dispose(),this._backupRotMrt=null}_createMrt(e,t,s=this._textureSize,i=this._textureSize){const n=this._scene.getEngine()._caps.textureHalfFloatRender?p.TEXTURETYPE_HALF_FLOAT:p.TEXTURETYPE_FLOAT,o=new b(e,{width:s,height:i},4,this._scene,{types:[p.TEXTURETYPE_FLOAT,n,n,p.TEXTURETYPE_UNSIGNED_BYTE],samplingModes:[p.TEXTURE_NEAREST_SAMPLINGMODE,p.TEXTURE_NEAREST_SAMPLINGMODE,p.TEXTURE_NEAREST_SAMPLINGMODE,p.TEXTURE_NEAREST_SAMPLINGMODE],formats:[p.TEXTUREFORMAT_RGBA,p.TEXTUREFORMAT_RGBA,p.TEXTUREFORMAT_RGBA,p.TEXTUREFORMAT_RGBA],generateDepthBuffer:!1,generateDepthTexture:!1,generateMipMaps:!1},[`${e}Centers`,`${e}CovA`,`${e}CovB`,`${e}Colors`]);return o.clearColor=new a(0,0,0,0),o.renderList=[],t&&o.onClearObservable.add(()=>{}),o}_createShMrt(e,t,s=this._textureSize,i=this._textureSize){const n=new b(e,{width:s,height:i},1,this._scene,{types:[p.TEXTURETYPE_UNSIGNED_INTEGER],formats:[p.TEXTUREFORMAT_RGBA_INTEGER],samplingModes:[p.TEXTURE_NEAREST_SAMPLINGMODE],generateDepthBuffer:!1,generateDepthTexture:!1,generateMipMaps:!1},[e]);return n.clearColor=new a(0,0,0,0),n.renderList=[],t&&n.onClearObservable.add(()=>{}),n}_createRotMrt(e,t,s=this._textureSize,i=this._textureSize){const n=this._scene.getEngine()._caps.textureHalfFloatRender?p.TEXTURETYPE_HALF_FLOAT:p.TEXTURETYPE_FLOAT,o=new b(e,{width:s,height:i},3,this._scene,{types:[n,n,n],formats:[p.TEXTUREFORMAT_RGBA,p.TEXTUREFORMAT_RGBA,p.TEXTUREFORMAT_RGBA],samplingModes:[p.TEXTURE_NEAREST_SAMPLINGMODE,p.TEXTURE_NEAREST_SAMPLINGMODE,p.TEXTURE_NEAREST_SAMPLINGMODE],generateDepthBuffer:!1,generateDepthTexture:!1,generateMipMaps:!1},[`${e}A`,`${e}B`,`${e}Scale`]);return o.clearColor=new a(0,0,0,0),o.renderList=[],t&&o.onClearObservable.add(()=>{}),o}async decodeAsync(e,t){if(this._disposed)return;this._applyPack(e);const s=null!==this._shMaterial&&this._shMrts.length>0;s&&this._applyShPack(e);const i=null!==this._rotMaterial&&null!==this._rotMrt;i&&this._applyRotPack(e),await new Promise(n=>{const a=()=>{if(this._disposed)return void n();if(!this._material.isReady(this._quad)||s&&!this._shMaterial.isReady(this._quad)||i&&!this._rotMaterial.isReady(this._quad))return void this._scene.onBeforeRenderObservable.addOnce(a);const o=this._textureSize,r=this._baseOffset+t;this._material.setInt("uOffset",r),s&&this._shMaterial.setInt("uOffset",r),i&&this._rotMaterial.setInt("uOffset",r);const l=Math.floor(r/o),h=Math.max(1,Math.ceil((r+e.splatCount)/o)-l),c=this._scene.getEngine();c.enableScissor(0,l,o,h);try{if(this._quad.material=this._material,this._mrt.renderList=[this._quad],this._mrt.render(),s){for(let e=0;e<this._shMrts.length;e++)this._shMaterial.setInt("uShTextureIndex",e),this._quad.material=this._shMaterial,this._shMrts[e].renderList=[this._quad],this._shMrts[e].render();this._quad.material=this._material}i&&(this._quad.material=this._rotMaterial,this._rotMrt.renderList=[this._quad],this._rotMrt.render(),this._quad.material=this._material)}finally{c.disableScissor()}n()};this._scene.onBeforeRenderObservable.addOnce(a)})}isRelayoutReady(){if(this._disposed)return!1;this._copyMaterial||(this._copyMaterial=this._createCopyMaterial()),this._shMrts.length&&!this._shCopyMaterial&&(this._shCopyMaterial=this._createShCopyMaterial()),this._rotMrt&&!this._rotCopyMaterial&&(this._rotCopyMaterial=this._createRotCopyMaterial()),this._bindCopyMaterialsToAtlas();const e=0===this._shMrts.length||null!==this._shCopyMaterial&&this._shCopyMaterial.isReady(this._quad),t=!this._rotMrt||null!==this._rotCopyMaterial&&this._rotCopyMaterial.isReady(this._quad);return this._copyMaterial.isReady(this._quad)&&e&&t}_bindCopyMaterialsToAtlas(){const e=this._mrt.textures;if(this._copyMaterial&&(this._copyMaterial.setTexture("uMapTex",e[0]),this._copyMaterial.setTexture("uSrc0",e[0]),this._copyMaterial.setTexture("uSrc1",e[1]),this._copyMaterial.setTexture("uSrc2",e[2]),this._copyMaterial.setTexture("uSrc3",e[3])),this._shCopyMaterial&&this._shMrts.length&&(this._shCopyMaterial.setTexture("uMapTex",e[0]),this._shCopyMaterial.setTexture("uSrcSh",this._shMrts[0].textures[0])),this._rotCopyMaterial&&this._rotMrt){const t=this._rotMrt.textures;this._rotCopyMaterial.setTexture("uMapTex",e[0]),this._rotCopyMaterial.setTexture("uSrc0",t[0]),this._rotCopyMaterial.setTexture("uSrc1",t[1]),this._rotCopyMaterial.setTexture("uSrc2",t[2])}}relayoutSync(e){if(this._disposed||!this._copyMaterial)return;const t=this._textureSize,s=t,i=this._ownsMrt?t:Math.max(1,Math.floor(this._capacity/t));this._relayoutMapData||(this._relayoutMapData=new Float32Array(s*i));const n=this._relayoutMapData;n.fill(-1),n.set(e.subarray(0,Math.min(e.length,n.length))),this._relayoutMapTexture?this._relayoutMapTexture.update(n):this._relayoutMapTexture=new f(n,s,i,p.TEXTUREFORMAT_R,this._scene,!1,!1,p.TEXTURE_NEAREST_SAMPLINGMODE,p.TEXTURETYPE_FLOAT);const a=this._relayoutMapTexture;if(this._ownsMrt){const e=this._createMrt("gsRelayoutTemp",!1);try{this._renderRelayoutPass(e,this._mrt.textures,a,1),this._renderRelayoutPass(this._mrt,e.textures,a,0)}finally{e.dispose()}if(this._shMrts.length&&this._shCopyMaterial)for(let e=0;e<this._shMrts.length;e++){const t=this._createShMrt("gsShRelayoutTemp",!1);try{this._renderShCopyPass(t,this._shMrts[e].textures[0],a,1),this._renderShCopyPass(this._shMrts[e],t.textures[0],a,0)}finally{t.dispose()}}if(this._rotMrt&&this._rotCopyMaterial){const e=this._createRotMrt("gsRotRelayoutTemp",!1);try{this._renderRotCopyPass(e,this._rotMrt.textures,a,1),this._renderRotCopyPass(this._rotMrt,e.textures,a,0)}finally{e.dispose()}}return void(this._quad.material=this._material)}const o=Math.floor(this._baseOffset/t),r=i,l=this._scene.getEngine(),h=this._createMrt("gsRelayoutTemp",!1,t,r),c=this._shMrts.length&&this._shCopyMaterial?this._shMrts.map((e,s)=>this._createShMrt(`gsShRelayoutTemp${s}`,!1,t,r)):[],u=this._rotMrt&&this._rotCopyMaterial?this._createRotMrt("gsRotRelayoutTemp",!1,t,r):null;try{this._renderRelayoutPass(h,this._mrt.textures,a,1,t,t,this._baseOffset,0);for(let e=0;e<c.length;e++)this._renderShCopyPass(c[e],this._shMrts[e].textures[0],a,1,t,t,this._baseOffset,0);u&&this._renderRotCopyPass(u,this._rotMrt.textures,a,1,t,t,this._baseOffset,0),l.enableScissor(0,o,t,r);try{this._renderRelayoutPass(this._mrt,h.textures,a,0,t,t,0,o);for(let e=0;e<c.length;e++)this._renderShCopyPass(this._shMrts[e],c[e].textures[0],a,0,t,t,0,o);u&&this._renderRotCopyPass(this._rotMrt,u.textures,a,0,t,t,0,o)}finally{l.disableScissor()}}finally{h.dispose();for(const e of c)e.dispose();u?.dispose(),this._quad.material=this._material}}_renderRelayoutPass(e,t,s,i,n=this._textureSize,a=this._textureSize,o=0,r=0){const l=this._copyMaterial;l.setTexture("uMapTex",s),l.setTexture("uSrc0",t[0]),l.setTexture("uSrc1",t[1]),l.setTexture("uSrc2",t[2]),l.setTexture("uSrc3",t[3]),l.setInt("uDstWidth",n),l.setInt("uSrcWidth",a),l.setInt("uUseMap",i),l.setInt("uSrcBaseOffset",o),l.setInt("uDstBaseRow",r),this._quad.material=l,e.renderList=[this._quad],e.render()}_createCopyMaterial(){const e=1===this._shaderLanguage,t=new o("gsWorkBufferRelayout",this._scene,{vertexSource:e?ae:ne,fragmentSource:e?"\nvar uMapTexSampler : sampler;\nvar uMapTex : texture_2d<f32>;\nvar uSrc0Sampler : sampler;\nvar uSrc0 : texture_2d<f32>;\nvar uSrc1Sampler : sampler;\nvar uSrc1 : texture_2d<f32>;\nvar uSrc2Sampler : sampler;\nvar uSrc2 : texture_2d<f32>;\nvar uSrc3Sampler : sampler;\nvar uSrc3 : texture_2d<f32>;\n\nuniform uDstWidth : i32;\nuniform uSrcWidth : i32;\nuniform uUseMap : i32;\n// Region-scoped relayout (hosted compound atlas), both default 0 (standalone square path unchanged).\nuniform uSrcBaseOffset : i32;\nuniform uDstBaseRow : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n var srcIdx : i32;\n if (uniforms.uUseMap == 1) {\n let m : f32 = textureLoad(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = uniforms.uSrcBaseOffset + i32(m + 0.5);\n } else {\n srcIdx = (p.y - uniforms.uDstBaseRow) * uniforms.uDstWidth + p.x;\n }\n let s : vec2<i32> = vec2<i32>(srcIdx - (srcIdx / uniforms.uSrcWidth) * uniforms.uSrcWidth, srcIdx / uniforms.uSrcWidth);\n fragmentOutputs.fragData0 = textureLoad(uSrc0, s, 0);\n fragmentOutputs.fragData1 = textureLoad(uSrc1, s, 0);\n fragmentOutputs.fragData2 = textureLoad(uSrc2, s, 0);\n fragmentOutputs.fragData3 = textureLoad(uSrc3, s, 0);\n}\n":"precision highp float;\nprecision highp int;\n\nuniform sampler2D uMapTex;\nuniform sampler2D uSrc0;\nuniform sampler2D uSrc1;\nuniform sampler2D uSrc2;\nuniform sampler2D uSrc3;\nuniform int uDstWidth;\nuniform int uSrcWidth;\nuniform int uUseMap;\n// Region-scoped relayout (hosted compound atlas), both default 0 (standalone square path unchanged):\n// uSrcBaseOffset — added to the map's (region-local) source index so pass 1 reads the correct GLOBAL atlas texel.\n// uDstBaseRow — subtracted from the atlas destination row so pass 2's identity copy reads the region-local temp.\nuniform int uSrcBaseOffset;\nuniform int uDstBaseRow;\n\nlayout(location = 0) out vec4 glFragData[4];\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int srcIdx;\n if (uUseMap == 1) {\n float m = texelFetch(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = uSrcBaseOffset + int(m + 0.5);\n } else {\n srcIdx = (p.y - uDstBaseRow) * uDstWidth + p.x;\n }\n ivec2 s = ivec2(srcIdx - (srcIdx / uSrcWidth) * uSrcWidth, srcIdx / uSrcWidth);\n glFragData[0] = texelFetch(uSrc0, s, 0);\n glFragData[1] = texelFetch(uSrc1, s, 0);\n glFragData[2] = texelFetch(uSrc2, s, 0);\n glFragData[3] = texelFetch(uSrc3, s, 0);\n}\n"},{attributes:["position"],uniforms:["uDstWidth","uSrcWidth","uUseMap","uSrcBaseOffset","uDstBaseRow"],samplers:["uMapTex","uSrc0","uSrc1","uSrc2","uSrc3"],shaderLanguage:this._shaderLanguage});return t.backFaceCulling=!1,t.disableDepthWrite=!0,t}_renderShCopyPass(e,t,s,i,n=this._textureSize,a=this._textureSize,o=0,r=0){const l=this._shCopyMaterial;l.setTexture("uMapTex",s),l.setTexture("uSrcSh",t),l.setInt("uDstWidth",n),l.setInt("uSrcWidth",a),l.setInt("uUseMap",i),l.setInt("uSrcBaseOffset",o),l.setInt("uDstBaseRow",r),this._quad.material=l,e.renderList=[this._quad],e.render()}_createShCopyMaterial(){const e=1===this._shaderLanguage,t=new o("gsWorkBufferShCopy",this._scene,{vertexSource:e?ae:ne,fragmentSource:e?'\nvar uMapTexSampler : sampler;\nvar uMapTex : texture_2d<f32>;\n// Integer source sampled via textureLoad only — NO paired sampler (a sampler on a Uint texture fails WebGPU\n// validation: "None of the supported sample types (Uint)"). Mirrors the draw shader\'s shTexture0 declaration.\nvar uSrcSh : texture_2d<u32>;\n\nuniform uDstWidth : i32;\nuniform uSrcWidth : i32;\nuniform uUseMap : i32;\nuniform uSrcBaseOffset : i32;\nuniform uDstBaseRow : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n var srcIdx : i32;\n if (uniforms.uUseMap == 1) {\n let m : f32 = textureLoad(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = uniforms.uSrcBaseOffset + i32(m + 0.5);\n } else {\n srcIdx = (p.y - uniforms.uDstBaseRow) * uniforms.uDstWidth + p.x;\n }\n let s : vec2<i32> = vec2<i32>(srcIdx - (srcIdx / uniforms.uSrcWidth) * uniforms.uSrcWidth, srcIdx / uniforms.uSrcWidth);\n // Wrap in an explicit vec4<u32> so the WGSL processor emits an integer fragData location (its detection keys\n // off a literal vec4<u32>/vec4u in the assignment; a bare textureLoad(...) would default to vec4<f32>).\n fragmentOutputs.fragData0 = vec4<u32>(textureLoad(uSrcSh, s, 0));\n}\n':"precision highp float;\nprecision highp int;\nprecision highp usampler2D;\n\nuniform sampler2D uMapTex;\nuniform usampler2D uSrcSh;\nuniform int uDstWidth;\nuniform int uSrcWidth;\nuniform int uUseMap;\nuniform int uSrcBaseOffset;\nuniform int uDstBaseRow;\n\nlayout(location = 0) out uvec4 outSh;\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int srcIdx;\n if (uUseMap == 1) {\n float m = texelFetch(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = uSrcBaseOffset + int(m + 0.5);\n } else {\n srcIdx = (p.y - uDstBaseRow) * uDstWidth + p.x;\n }\n ivec2 s = ivec2(srcIdx - (srcIdx / uSrcWidth) * uSrcWidth, srcIdx / uSrcWidth);\n outSh = texelFetch(uSrcSh, s, 0);\n}\n"},{attributes:["position"],uniforms:["uDstWidth","uSrcWidth","uUseMap","uSrcBaseOffset","uDstBaseRow"],samplers:["uMapTex","uSrcSh"],shaderLanguage:this._shaderLanguage});return t.backFaceCulling=!1,t.disableDepthWrite=!0,t}_renderRotCopyPass(e,t,s,i,n=this._textureSize,a=this._textureSize,o=0,r=0){const l=this._rotCopyMaterial;l.setTexture("uMapTex",s),l.setTexture("uSrc0",t[0]),l.setTexture("uSrc1",t[1]),l.setTexture("uSrc2",t[2]),l.setInt("uDstWidth",n),l.setInt("uSrcWidth",a),l.setInt("uUseMap",i),l.setInt("uSrcBaseOffset",o),l.setInt("uDstBaseRow",r),this._quad.material=l,e.renderList=[this._quad],e.render()}_createRotCopyMaterial(){const e=1===this._shaderLanguage,t=new o("gsWorkBufferRotCopy",this._scene,{vertexSource:e?ae:ne,fragmentSource:e?"\nvar uMapTexSampler : sampler;\nvar uMapTex : texture_2d<f32>;\nvar uSrc0Sampler : sampler;\nvar uSrc0 : texture_2d<f32>;\nvar uSrc1Sampler : sampler;\nvar uSrc1 : texture_2d<f32>;\nvar uSrc2Sampler : sampler;\nvar uSrc2 : texture_2d<f32>;\n\nuniform uDstWidth : i32;\nuniform uSrcWidth : i32;\nuniform uUseMap : i32;\nuniform uSrcBaseOffset : i32;\nuniform uDstBaseRow : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n var srcIdx : i32;\n if (uniforms.uUseMap == 1) {\n let m : f32 = textureLoad(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = uniforms.uSrcBaseOffset + i32(m + 0.5);\n } else {\n srcIdx = (p.y - uniforms.uDstBaseRow) * uniforms.uDstWidth + p.x;\n }\n let s : vec2<i32> = vec2<i32>(srcIdx - (srcIdx / uniforms.uSrcWidth) * uniforms.uSrcWidth, srcIdx / uniforms.uSrcWidth);\n fragmentOutputs.fragData0 = textureLoad(uSrc0, s, 0);\n fragmentOutputs.fragData1 = textureLoad(uSrc1, s, 0);\n fragmentOutputs.fragData2 = textureLoad(uSrc2, s, 0);\n}\n":"precision highp float;\nprecision highp int;\n\nuniform sampler2D uMapTex;\nuniform sampler2D uSrc0;\nuniform sampler2D uSrc1;\nuniform sampler2D uSrc2;\nuniform int uDstWidth;\nuniform int uSrcWidth;\nuniform int uUseMap;\nuniform int uSrcBaseOffset;\nuniform int uDstBaseRow;\n\nlayout(location = 0) out vec4 glFragData[3];\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int srcIdx;\n if (uUseMap == 1) {\n float m = texelFetch(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = uSrcBaseOffset + int(m + 0.5);\n } else {\n srcIdx = (p.y - uDstBaseRow) * uDstWidth + p.x;\n }\n ivec2 s = ivec2(srcIdx - (srcIdx / uSrcWidth) * uSrcWidth, srcIdx / uSrcWidth);\n glFragData[0] = texelFetch(uSrc0, s, 0);\n glFragData[1] = texelFetch(uSrc1, s, 0);\n glFragData[2] = texelFetch(uSrc2, s, 0);\n}\n"},{attributes:["position"],uniforms:["uDstWidth","uSrcWidth","uUseMap","uSrcBaseOffset","uDstBaseRow"],samplers:["uMapTex","uSrc0","uSrc1","uSrc2"],shaderLanguage:this._shaderLanguage});return t.backFaceCulling=!1,t.disableDepthWrite=!0,t}async readCentersRangeAsync(e,t){if(this._disposed||t<=0||!this.supportsAsyncCentersReadback)return null;const s=this._textureSize,i=this._baseOffset+e,n=Math.floor(i/s),a=Math.ceil((i+t)/s)-n,o=4*(i-n*s),r=o+4*t,l=this._mrt.textures[0],h=this._scene.getEngine();if(h.isWebGPU){const e=await l.readPixels(0,0,null,!0,!0,0,n,s,a);if(this._disposed||!e)return null;const t=e instanceof Float32Array?e:new Float32Array(e.buffer,e.byteOffset,e.byteLength/4);return t.length>=r?t.subarray(o,r):null}const c=h,u=c._gl,d=l.getInternalTexture()?._hardwareTexture?.underlyingResource;if(!d)return null;const _=new Float32Array(s*a*4);this._readFbo||(this._readFbo=u.createFramebuffer());const f=c._currentFramebuffer;u.bindFramebuffer(u.FRAMEBUFFER,this._readFbo),u.framebufferTexture2D(u.FRAMEBUFFER,u.COLOR_ATTACHMENT0,u.TEXTURE_2D,d,0),u.readBuffer(u.COLOR_ATTACHMENT0);const p=c._readPixelsAsync(0,n,s,a,u.RGBA,u.FLOAT,_);return u.bindFramebuffer(u.FRAMEBUFFER,f),f||u.readBuffer(u.BACK),p?(await p,this._disposed||_.length<r?null:_.subarray(o,r)):null}dispose(){if(this._disposed=!0,this._readFbo&&(this._scene.getEngine()._gl?.deleteFramebuffer(this._readFbo),this._readFbo=null),this._quad.dispose(),this._material.dispose(!0,!1),this._shMaterial?.dispose(!0,!1),this._rotMaterial?.dispose(!0,!1),this._copyMaterial?.dispose(!0,!1),this._shCopyMaterial?.dispose(!0,!1),this._rotCopyMaterial?.dispose(!0,!1),this._relayoutMapTexture?.dispose(),this._backupMrt?.dispose(),this._backupMrt=null,this._backupShMrts){for(const e of this._backupShMrts)e.dispose();this._backupShMrts=null}if(this._backupRotMrt?.dispose(),this._backupRotMrt=null,this._ownsMrt&&this._mrt.dispose(),this._ownsShMrts)for(const e of this._shMrts)e.dispose();this._shMrts=[],this._ownsRotMrt&&this._rotMrt?.dispose(),this._rotMrt=null}_createQuad(){const e=new i("gsWorkBufferQuad",this._scene),t=new c;return t.positions=[-1,-1,0,3,-1,0,-1,3,0],t.indices=[0,1,2],t.applyToMesh(e),this._scene.removeMesh(e),e}_createMaterial(){const e=1===this._shaderLanguage,t=new o("gsSogDecode",this._scene,{vertexSource:e?ae:ne,fragmentSource:e?"\nvar sogMeansLTexSampler : sampler;\nvar sogMeansLTex : texture_2d<f32>;\nvar sogMeansUTexSampler : sampler;\nvar sogMeansUTex : texture_2d<f32>;\nvar sogScalesTexSampler : sampler;\nvar sogScalesTex : texture_2d<f32>;\nvar sogQuatsTexSampler : sampler;\nvar sogQuatsTex : texture_2d<f32>;\nvar sogSh0TexSampler : sampler;\nvar sogSh0Tex : texture_2d<f32>;\nvar sogCodebookTexSampler : sampler;\nvar sogCodebookTex : texture_2d<f32>;\n\nuniform sogMeansMin : vec3<f32>;\nuniform sogMeansMax : vec3<f32>;\nuniform sogScalesMin : vec3<f32>;\nuniform sogScalesMax : vec3<f32>;\nuniform sogSh0Min : vec4<f32>;\nuniform sogSh0Max : vec4<f32>;\nuniform uVersion : i32;\nuniform uOffset : i32;\nuniform uCount : i32;\nuniform uDestWidth : i32;\nuniform uSrcWidth : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n let global : i32 = p.y * uniforms.uDestWidth + p.x;\n if (global < uniforms.uOffset || global >= uniforms.uOffset + uniforms.uCount) {\n discard;\n }\n let k : i32 = global - uniforms.uOffset;\n let src : vec2<i32> = vec2<i32>(k - (k / uniforms.uSrcWidth) * uniforms.uSrcWidth, k / uniforms.uSrcWidth);\n\n let mL : vec3<f32> = textureLoad(sogMeansLTex, src, 0).xyz;\n let mU : vec3<f32> = textureLoad(sogMeansUTex, src, 0).xyz;\n let sRaw : vec3<f32> = textureLoad(sogScalesTex, src, 0).xyz;\n let qRaw : vec4<f32> = textureLoad(sogQuatsTex, src, 0);\n let c0 : vec4<f32> = textureLoad(sogSh0Tex, src, 0);\n\n let q16 : vec3<f32> = (mU * 256.0 + mL) * (255.0 / 65535.0);\n let nPos : vec3<f32> = mix(uniforms.sogMeansMin, uniforms.sogMeansMax, q16);\n let center : vec3<f32> = sign(nPos) * (exp(abs(nPos)) - vec3<f32>(1.0));\n\n var splatScale : vec3<f32>;\n if (uniforms.uVersion == 2) {\n let sIdx : vec3<f32> = floor(sRaw * 255.0 + 0.5);\n splatScale.x = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.x), 0), 0).r);\n splatScale.y = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.y), 0), 0).r);\n splatScale.z = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.z), 0), 0).r);\n } else {\n splatScale = exp(mix(uniforms.sogScalesMin, uniforms.sogScalesMax, sRaw));\n }\n\n let invSqrt2 : f32 = 0.70710678118;\n let qabc : vec3<f32> = (qRaw.xyz - vec3<f32>(0.5)) * 2.0 * invSqrt2;\n let qMode : i32 = i32(qRaw.w * 255.0 + 0.5) - 252;\n let qd : f32 = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\n var quat : vec4<f32>;\n if (qMode == 0) {\n quat = vec4<f32>(qd, qabc.x, qabc.y, qabc.z);\n } else if (qMode == 1) {\n quat = vec4<f32>(qabc.x, qd, qabc.y, qabc.z);\n } else if (qMode == 2) {\n quat = vec4<f32>(qabc.x, qabc.y, qd, qabc.z);\n } else {\n quat = vec4<f32>(qabc.x, qabc.y, qabc.z, qd);\n }\n\n let qw : f32 = quat.x;\n let qx : f32 = quat.y;\n let qy : f32 = quat.z;\n let qz : f32 = quat.w;\n let R : mat3x3<f32> = mat3x3<f32>(\n 1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\n 2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\n 2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\n );\n let S2 : mat3x3<f32> = mat3x3<f32>(\n 4.0 * splatScale.x * splatScale.x, 0.0, 0.0,\n 0.0, 4.0 * splatScale.y * splatScale.y, 0.0,\n 0.0, 0.0, 4.0 * splatScale.z * splatScale.z\n );\n let Sigma : mat3x3<f32> = R * S2 * transpose(R);\n\n let SH_C0 : f32 = 0.28209479177387814;\n var colRgb : vec3<f32>;\n var colA : f32;\n if (uniforms.uVersion == 2) {\n var c3 : vec3<f32>;\n c3.x = textureLoad(sogCodebookTex, vec2<i32>(256 + i32(c0.x * 255.0 + 0.5), 0), 0).r;\n c3.y = textureLoad(sogCodebookTex, vec2<i32>(256 + i32(c0.y * 255.0 + 0.5), 0), 0).r;\n c3.z = textureLoad(sogCodebookTex, vec2<i32>(256 + i32(c0.z * 255.0 + 0.5), 0), 0).r;\n colRgb = vec3<f32>(0.5) + c3 * SH_C0;\n colA = c0.w;\n } else {\n let cLerp : vec4<f32> = mix(uniforms.sogSh0Min, uniforms.sogSh0Max, c0);\n colRgb = vec3<f32>(0.5) + cLerp.xyz * SH_C0;\n colA = 1.0 / (1.0 + exp(-cLerp.w));\n }\n\n fragmentOutputs.fragData0 = vec4<f32>(center, 1.0);\n fragmentOutputs.fragData1 = vec4<f32>(Sigma[0][0], Sigma[0][1], Sigma[0][2], Sigma[1][1]);\n fragmentOutputs.fragData2 = vec4<f32>(Sigma[1][2], Sigma[2][2], 0.0, 0.0);\n fragmentOutputs.fragData3 = vec4<f32>(colRgb, colA);\n}\n":"precision highp float;\nprecision highp int;\n\nuniform sampler2D sogMeansLTex;\nuniform sampler2D sogMeansUTex;\nuniform sampler2D sogScalesTex;\nuniform sampler2D sogQuatsTex;\nuniform sampler2D sogSh0Tex;\nuniform sampler2D sogCodebookTex;\n\nuniform vec3 sogMeansMin;\nuniform vec3 sogMeansMax;\nuniform vec3 sogScalesMin;\nuniform vec3 sogScalesMax;\nuniform vec4 sogSh0Min;\nuniform vec4 sogSh0Max;\nuniform int uVersion;\nuniform int uOffset;\nuniform int uCount;\nuniform int uDestWidth;\nuniform int uSrcWidth;\n\nlayout(location = 0) out vec4 glFragData[4];\n\nmat3 transposeM(mat3 m) {\n return mat3(m[0][0], m[1][0], m[2][0], m[0][1], m[1][1], m[2][1], m[0][2], m[1][2], m[2][2]);\n}\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int global = p.y * uDestWidth + p.x;\n if (global < uOffset || global >= uOffset + uCount) {\n discard;\n }\n int k = global - uOffset;\n ivec2 src = ivec2(k - (k / uSrcWidth) * uSrcWidth, k / uSrcWidth);\n\n vec3 mL = texelFetch(sogMeansLTex, src, 0).xyz;\n vec3 mU = texelFetch(sogMeansUTex, src, 0).xyz;\n vec3 sRaw = texelFetch(sogScalesTex, src, 0).xyz;\n vec4 qRaw = texelFetch(sogQuatsTex, src, 0);\n vec4 c0 = texelFetch(sogSh0Tex, src, 0);\n\n // Position: q16 = (u<<8)|l normalized; n = lerp(min,max,q16); pos = sign(n)*(exp(|n|)-1)\n vec3 q16 = (mU * 256.0 + mL) * (255.0 / 65535.0);\n vec3 nPos = mix(sogMeansMin, sogMeansMax, q16);\n vec3 center = sign(nPos) * (exp(abs(nPos)) - vec3(1.0));\n\n // Scale (v1: lerp+exp ; v2: codebook lookup)\n vec3 splatScale;\n if (uVersion == 2) {\n vec3 sIdx = floor(sRaw * 255.0 + 0.5);\n splatScale.x = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.x), 0), 0).r);\n splatScale.y = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.y), 0), 0).r);\n splatScale.z = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.z), 0), 0).r);\n } else {\n splatScale = exp(mix(sogScalesMin, sogScalesMax, sRaw));\n }\n\n // Quaternion (largest-omitted, mode in alpha as 252 + omitted-index)\n const float invSqrt2 = 0.70710678118;\n vec3 qabc = (qRaw.xyz - vec3(0.5)) * 2.0 * invSqrt2;\n int qMode = int(qRaw.w * 255.0 + 0.5) - 252;\n float qd = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\n vec4 quat;\n if (qMode == 0) {\n quat = vec4(qd, qabc.x, qabc.y, qabc.z);\n } else if (qMode == 1) {\n quat = vec4(qabc.x, qd, qabc.y, qabc.z);\n } else if (qMode == 2) {\n quat = vec4(qabc.x, qabc.y, qd, qabc.z);\n } else {\n quat = vec4(qabc.x, qabc.y, qabc.z, qd);\n }\n\n float qw = quat.x, qx = quat.y, qy = quat.z, qz = quat.w;\n mat3 R = mat3(\n 1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\n 2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\n 2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\n );\n mat3 S2 = mat3(\n 4.0 * splatScale.x * splatScale.x, 0.0, 0.0,\n 0.0, 4.0 * splatScale.y * splatScale.y, 0.0,\n 0.0, 0.0, 4.0 * splatScale.z * splatScale.z\n );\n mat3 Sigma = R * S2 * transposeM(R);\n\n // Color (sh0)\n const float SH_C0 = 0.28209479177387814;\n vec3 colRgb;\n float colA;\n if (uVersion == 2) {\n vec3 c3;\n c3.x = texelFetch(sogCodebookTex, ivec2(256 + int(c0.x * 255.0 + 0.5), 0), 0).r;\n c3.y = texelFetch(sogCodebookTex, ivec2(256 + int(c0.y * 255.0 + 0.5), 0), 0).r;\n c3.z = texelFetch(sogCodebookTex, ivec2(256 + int(c0.z * 255.0 + 0.5), 0), 0).r;\n colRgb = vec3(0.5) + c3 * SH_C0;\n colA = c0.w;\n } else {\n vec4 cLerp = mix(sogSh0Min, sogSh0Max, c0);\n colRgb = vec3(0.5) + cLerp.xyz * SH_C0;\n colA = 1.0 / (1.0 + exp(-cLerp.w));\n }\n\n glFragData[0] = vec4(center, 1.0);\n glFragData[1] = vec4(Sigma[0][0], Sigma[0][1], Sigma[0][2], Sigma[1][1]);\n glFragData[2] = vec4(Sigma[1][2], Sigma[2][2], 0.0, 0.0);\n glFragData[3] = vec4(colRgb, colA);\n}\n"},{attributes:["position"],uniforms:["sogMeansMin","sogMeansMax","sogScalesMin","sogScalesMax","sogSh0Min","sogSh0Max","uVersion","uOffset","uCount","uDestWidth","uSrcWidth"],samplers:["sogMeansLTex","sogMeansUTex","sogScalesTex","sogQuatsTex","sogSh0Tex","sogCodebookTex"],shaderLanguage:this._shaderLanguage});return t.backFaceCulling=!1,t.disableDepthWrite=!0,t}_applyPack(e){const t=this._material,s=e.meansTextureL.getSize().width;t.setTexture("sogMeansLTex",e.meansTextureL),t.setTexture("sogMeansUTex",e.meansTextureU),t.setTexture("sogScalesTex",e.scalesTexture),t.setTexture("sogQuatsTex",e.quatsTexture),t.setTexture("sogSh0Tex",e.sh0Texture),t.setTexture("sogCodebookTex",e.codebookTexture??e.sh0Texture),t.setVector3("sogMeansMin",new u(e.meansMin[0],e.meansMin[1],e.meansMin[2])),t.setVector3("sogMeansMax",new u(e.meansMax[0],e.meansMax[1],e.meansMax[2]));const i=e.scalesMin??[0,0,0],n=e.scalesMax??[0,0,0];t.setVector3("sogScalesMin",new u(i[0],i[1],i[2])),t.setVector3("sogScalesMax",new u(n[0],n[1],n[2]));const a=e.sh0Min??[0,0,0,0],o=e.sh0Max??[0,0,0,0];t.setVector4("sogSh0Min",new y(a[0],a[1],a[2],a[3])),t.setVector4("sogSh0Max",new y(o[0],o[1],o[2],o[3])),t.setInt("uVersion",e.version),t.setInt("uCount",e.splatCount),t.setInt("uDestWidth",this._textureSize),t.setInt("uSrcWidth",s)}_createShMaterial(){const e=1===this._shaderLanguage,t=new o("gsSogShDecodeToWorkBuffer",this._scene,{vertexSource:e?ae:ne,fragmentSource:e?"\nvar sogShLabelsTexSampler : sampler;\nvar sogShLabelsTex : texture_2d<f32>;\nvar sogShCentroidsTexSampler : sampler;\nvar sogShCentroidsTex : texture_2d<f32>;\nvar sogCodebookTexSampler : sampler;\nvar sogCodebookTex : texture_2d<f32>;\n\nuniform sogShnMin : f32;\nuniform sogShnMax : f32;\nuniform uVersion : i32;\nuniform uOffset : i32;\nuniform uCount : i32;\nuniform uDestWidth : i32;\nuniform uSrcWidth : i32;\nuniform uCoeffs : i32;\nuniform uShTextureIndex : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n let global : i32 = p.y * uniforms.uDestWidth + p.x;\n if (global < uniforms.uOffset || global >= uniforms.uOffset + uniforms.uCount) {\n discard;\n }\n let kLocal : i32 = global - uniforms.uOffset;\n\n let lsz : vec2<i32> = vec2<i32>(textureDimensions(sogShLabelsTex, 0));\n let lsrc : vec2<i32> = vec2<i32>(kLocal - (kLocal / lsz.x) * lsz.x, kLocal / lsz.x);\n let labelRaw : vec4<f32> = textureLoad(sogShLabelsTex, lsrc, 0);\n let n : i32 = i32(labelRaw.r * 255.0 + 0.5) + i32(labelRaw.g * 255.0 + 0.5) * 256;\n let u : i32 = (n - (n / 64) * 64) * uniforms.uCoeffs;\n let v : i32 = n / 64;\n\n var packed : array<u32, 4> = array<u32, 4>(0u, 0u, 0u, 0u);\n\n for (var b : i32 = 0; b < 16; b = b + 1) {\n let s : i32 = uniforms.uShTextureIndex * 16 + b;\n let kc : i32 = s / 3;\n let j : i32 = s - kc * 3;\n var byteVal : f32 = 128.0;\n if (kc < uniforms.uCoeffs) {\n let centroidRaw : vec4<f32> = textureLoad(sogShCentroidsTex, vec2<i32>(u + kc, v), 0);\n var ch : f32 = centroidRaw.b;\n if (j == 0) { ch = centroidRaw.r; } else if (j == 1) { ch = centroidRaw.g; }\n var coeff : f32;\n if (uniforms.uVersion == 2) {\n let cidx : i32 = i32(ch * 255.0 + 0.5);\n coeff = textureLoad(sogCodebookTex, vec2<i32>(512 + cidx, 0), 0).r;\n } else {\n coeff = mix(uniforms.sogShnMin, uniforms.sogShnMax, ch);\n }\n byteVal = clamp(coeff * 127.5 + 127.5, 0.0, 255.0);\n }\n let bv : u32 = u32(byteVal + 0.5);\n let comp : i32 = b / 4;\n packed[comp] = packed[comp] | (bv << u32((b - comp * 4) * 8));\n }\n fragmentOutputs.fragData0 = vec4<u32>(packed[0], packed[1], packed[2], packed[3]);\n}\n":"precision highp float;\nprecision highp int;\n\nuniform sampler2D sogShLabelsTex;\nuniform sampler2D sogShCentroidsTex;\nuniform sampler2D sogCodebookTex;\nuniform float sogShnMin;\nuniform float sogShnMax;\nuniform int uVersion;\nuniform int uOffset;\nuniform int uCount;\nuniform int uDestWidth;\nuniform int uSrcWidth;\nuniform int uCoeffs;\nuniform int uShTextureIndex;\n\nlayout(location = 0) out uvec4 outSh;\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int global = p.y * uDestWidth + p.x;\n if (global < uOffset || global >= uOffset + uCount) {\n discard;\n }\n int kLocal = global - uOffset;\n\n // 16-bit label for this source splat (LSB in r, MSB in g), indexed over the labels texture's own width.\n ivec2 lsz = textureSize(sogShLabelsTex, 0);\n ivec2 lsrc = ivec2(kLocal - (kLocal / lsz.x) * lsz.x, kLocal / lsz.x);\n vec4 labelRaw = texelFetch(sogShLabelsTex, lsrc, 0);\n int n = int(labelRaw.r * 255.0 + 0.5) + int(labelRaw.g * 255.0 + 0.5) * 256;\n int u = (n - (n / 64) * 64) * uCoeffs;\n int v = n / 64;\n\n uint packed0 = 0u;\n uint packed1 = 0u;\n uint packed2 = 0u;\n uint packed3 = 0u;\n\n for (int b = 0; b < 16; b++) {\n int s = uShTextureIndex * 16 + b; // flat SH scalar index\n int kc = s / 3; // higher-order coefficient (0-based)\n int j = s - kc * 3; // channel (0=r,1=g,2=b)\n float byteVal = 128.0; // neutral (decompose(128) ~= 0)\n if (kc < uCoeffs) {\n vec4 centroidRaw = texelFetch(sogShCentroidsTex, ivec2(u + kc, v), 0);\n float ch = (j == 0) ? centroidRaw.r : ((j == 1) ? centroidRaw.g : centroidRaw.b);\n float coeff;\n if (uVersion == 2) {\n int cidx = int(ch * 255.0 + 0.5);\n coeff = texelFetch(sogCodebookTex, ivec2(512 + cidx, 0), 0).r;\n } else {\n coeff = mix(sogShnMin, sogShnMax, ch);\n }\n byteVal = clamp(coeff * 127.5 + 127.5, 0.0, 255.0);\n }\n uint bv = uint(byteVal + 0.5);\n int comp = b / 4;\n uint contrib = bv << uint((b - comp * 4) * 8);\n if (comp == 0) { packed0 |= contrib; }\n else if (comp == 1) { packed1 |= contrib; }\n else if (comp == 2) { packed2 |= contrib; }\n else { packed3 |= contrib; }\n }\n outSh = uvec4(packed0, packed1, packed2, packed3);\n}\n"},{attributes:["position"],uniforms:["sogShnMin","sogShnMax","uVersion","uOffset","uCount","uDestWidth","uSrcWidth","uCoeffs","uShTextureIndex"],samplers:["sogShLabelsTex","sogShCentroidsTex","sogCodebookTex"],shaderLanguage:this._shaderLanguage});return t.backFaceCulling=!1,t.disableDepthWrite=!0,t}_applyShPack(e){const t=this._shMaterial,s=!!e.shLabelsTexture&&!!e.shCentroidsTexture,i=e.shLabelsTexture??e.sh0Texture,n=e.shCentroidsTexture??e.sh0Texture;t.setTexture("sogShLabelsTex",i),t.setTexture("sogShCentroidsTex",n),t.setTexture("sogCodebookTex",e.codebookTexture??i),t.setFloat("sogShnMin",e.shnMin??0),t.setFloat("sogShnMax",e.shnMax??0),t.setInt("uVersion",e.version),t.setInt("uCount",e.splatCount),t.setInt("uDestWidth",this._textureSize),t.setInt("uSrcWidth",i.getSize().width),t.setInt("uCoeffs",s?e.shCoeffCount:0)}_createRotMaterial(){const e=1===this._shaderLanguage,t=new o("gsSogRotDecodeToWorkBuffer",this._scene,{vertexSource:e?ae:ne,fragmentSource:e?"\nvar sogScalesTexSampler : sampler;\nvar sogScalesTex : texture_2d<f32>;\nvar sogQuatsTexSampler : sampler;\nvar sogQuatsTex : texture_2d<f32>;\nvar sogCodebookTexSampler : sampler;\nvar sogCodebookTex : texture_2d<f32>;\n\nuniform sogScalesMin : vec3<f32>;\nuniform sogScalesMax : vec3<f32>;\nuniform uVersion : i32;\nuniform uOffset : i32;\nuniform uCount : i32;\nuniform uDestWidth : i32;\nuniform uSrcWidth : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n let global : i32 = p.y * uniforms.uDestWidth + p.x;\n if (global < uniforms.uOffset || global >= uniforms.uOffset + uniforms.uCount) {\n discard;\n }\n let k : i32 = global - uniforms.uOffset;\n let src : vec2<i32> = vec2<i32>(k - (k / uniforms.uSrcWidth) * uniforms.uSrcWidth, k / uniforms.uSrcWidth);\n\n let sRaw : vec3<f32> = textureLoad(sogScalesTex, src, 0).xyz;\n let qRaw : vec4<f32> = textureLoad(sogQuatsTex, src, 0);\n\n var splatScale : vec3<f32>;\n if (uniforms.uVersion == 2) {\n let sIdx : vec3<f32> = floor(sRaw * 255.0 + 0.5);\n splatScale.x = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.x), 0), 0).r);\n splatScale.y = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.y), 0), 0).r);\n splatScale.z = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.z), 0), 0).r);\n } else {\n splatScale = exp(mix(uniforms.sogScalesMin, uniforms.sogScalesMax, sRaw));\n }\n\n let invSqrt2 : f32 = 0.70710678118;\n let qabc : vec3<f32> = (qRaw.xyz - vec3<f32>(0.5)) * 2.0 * invSqrt2;\n let qMode : i32 = i32(qRaw.w * 255.0 + 0.5) - 252;\n let qd : f32 = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\n var quat : vec4<f32>;\n if (qMode == 0) {\n quat = vec4<f32>(qd, qabc.x, qabc.y, qabc.z);\n } else if (qMode == 1) {\n quat = vec4<f32>(qabc.x, qd, qabc.y, qabc.z);\n } else if (qMode == 2) {\n quat = vec4<f32>(qabc.x, qabc.y, qd, qabc.z);\n } else {\n quat = vec4<f32>(qabc.x, qabc.y, qabc.z, qd);\n }\n\n let qw : f32 = quat.x;\n let qx : f32 = quat.y;\n let qy : f32 = quat.z;\n let qz : f32 = quat.w;\n let R : mat3x3<f32> = mat3x3<f32>(\n 1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\n 2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\n 2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\n );\n\n fragmentOutputs.fragData0 = vec4<f32>(R[0], R[1].x);\n fragmentOutputs.fragData1 = vec4<f32>(R[1].y, R[1].z, R[2].x, R[2].y);\n fragmentOutputs.fragData2 = vec4<f32>(R[2].z, 2.0 * splatScale.x, 2.0 * splatScale.y, 2.0 * splatScale.z);\n}\n":"precision highp float;\nprecision highp int;\n\nuniform sampler2D sogScalesTex;\nuniform sampler2D sogQuatsTex;\nuniform sampler2D sogCodebookTex;\n\nuniform vec3 sogScalesMin;\nuniform vec3 sogScalesMax;\nuniform int uVersion;\nuniform int uOffset;\nuniform int uCount;\nuniform int uDestWidth;\nuniform int uSrcWidth;\n\nlayout(location = 0) out vec4 glFragData[3];\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int global = p.y * uDestWidth + p.x;\n if (global < uOffset || global >= uOffset + uCount) {\n discard;\n }\n int k = global - uOffset;\n ivec2 src = ivec2(k - (k / uSrcWidth) * uSrcWidth, k / uSrcWidth);\n\n vec3 sRaw = texelFetch(sogScalesTex, src, 0).xyz;\n vec4 qRaw = texelFetch(sogQuatsTex, src, 0);\n\n vec3 splatScale;\n if (uVersion == 2) {\n vec3 sIdx = floor(sRaw * 255.0 + 0.5);\n splatScale.x = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.x), 0), 0).r);\n splatScale.y = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.y), 0), 0).r);\n splatScale.z = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.z), 0), 0).r);\n } else {\n splatScale = exp(mix(sogScalesMin, sogScalesMax, sRaw));\n }\n\n const float invSqrt2 = 0.70710678118;\n vec3 qabc = (qRaw.xyz - vec3(0.5)) * 2.0 * invSqrt2;\n int qMode = int(qRaw.w * 255.0 + 0.5) - 252;\n float qd = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\n vec4 quat;\n if (qMode == 0) {\n quat = vec4(qd, qabc.x, qabc.y, qabc.z);\n } else if (qMode == 1) {\n quat = vec4(qabc.x, qd, qabc.y, qabc.z);\n } else if (qMode == 2) {\n quat = vec4(qabc.x, qabc.y, qd, qabc.z);\n } else {\n quat = vec4(qabc.x, qabc.y, qabc.z, qd);\n }\n\n float qw = quat.x, qx = quat.y, qy = quat.z, qz = quat.w;\n mat3 R = mat3(\n 1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\n 2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\n 2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\n );\n\n glFragData[0] = vec4(R[0], R[1].x);\n glFragData[1] = vec4(R[1].y, R[1].z, R[2].x, R[2].y);\n glFragData[2] = vec4(R[2].z, 2.0 * splatScale.x, 2.0 * splatScale.y, 2.0 * splatScale.z);\n}\n"},{attributes:["position"],uniforms:["sogScalesMin","sogScalesMax","uVersion","uOffset","uCount","uDestWidth","uSrcWidth"],samplers:["sogScalesTex","sogQuatsTex","sogCodebookTex"],shaderLanguage:this._shaderLanguage});return t.backFaceCulling=!1,t.disableDepthWrite=!0,t}_applyRotPack(e){const t=this._rotMaterial,s=e.scalesTexture.getSize().width;t.setTexture("sogScalesTex",e.scalesTexture),t.setTexture("sogQuatsTex",e.quatsTexture),t.setTexture("sogCodebookTex",e.codebookTexture??e.scalesTexture);const i=e.scalesMin??[0,0,0],n=e.scalesMax??[0,0,0];t.setVector3("sogScalesMin",new u(i[0],i[1],i[2])),t.setVector3("sogScalesMax",new u(n[0],n[1],n[2])),t.setInt("uVersion",e.version),t.setInt("uCount",e.splatCount),t.setInt("uDestWidth",this._textureSize),t.setInt("uSrcWidth",s)}}class re{constructor(e){this._activeCount=0,this._queue=[],this._pending=new Map,this._groups=new Map,this._disposed=!1,this.maxConcurrent=Math.max(1,e?.maxConcurrent??2),this.maxRetries=Math.max(0,e?.maxRetries??2)}get isIdle(){return 0===this._pending.size}async loadFileAsync(e,t){if(this._disposed)throw new Error("GaussianSplattingDownloadManager has been disposed.");const s=this._pending.get(e);if(s)return await s.promise;const i={url:e,groupId:t,settled:!1,cancelled:!1,started:!1,slotReleased:!1};if(i.promise=new Promise((e,t)=>{i.resolve=e,i.reject=t}),this._pending.set(e,i),void 0!==t){let s=this._groups.get(t);s||(s=new Set,this._groups.set(t,s)),s.add(e)}return this._queue.push(i),this._pump(),await i.promise}cancel(e){const t=this._pending.get(e);t&&this._abort(t,new Error(`GaussianSplattingDownloadManager: download cancelled (${e}).`))}cancelGroup(e){const t=this._groups.get(e);if(t){for(const e of Array.from(t))this.cancel(e);this._groups.delete(e)}}dispose(){if(!this._disposed){this._disposed=!0,this._queue.length=0;for(const e of Array.from(this._pending.values()))this._abort(e,new Error("GaussianSplattingDownloadManager has been disposed."))}}_abort(e,t){if(e.settled)return;e.cancelled=!0;const s=this._queue.indexOf(e);-1!==s&&this._queue.splice(s,1),e.request?.abort(),e.cancelAttempt?.(t),this._settle(e,()=>e.reject(t)),e.started&&this._releaseSlot(e)}_settle(e,t){if(!e.settled){if(e.settled=!0,this._pending.delete(e.url),void 0!==e.groupId){const t=this._groups.get(e.groupId);t&&(t.delete(e.url),0===t.size&&this._groups.delete(e.groupId))}t()}}_releaseSlot(e){e.slotReleased||(e.slotReleased=!0,this._activeCount--,this._pump())}_pump(){for(;!this._disposed&&this._activeCount<this.maxConcurrent&&this._queue.length>0;){const e=this._queue.shift();e.settled||(e.started=!0,this._activeCount++,this._runTaskAsync(e).finally(()=>{this._releaseSlot(e)}))}}async _runTaskAsync(e){let t;for(let s=0;s<=this.maxRetries;s++){if(this._disposed||e.cancelled)return;try{const t=await this._downloadAttemptAsync(e);return void this._settle(e,()=>e.resolve(t))}catch(s){if(e.cancelAttempt=void 0,this._disposed||e.cancelled)return;t=s}}this._settle(e,()=>e.reject(t))}async _downloadAttemptAsync(e){return await new Promise((t,s)=>{e.cancelAttempt=s,e.request=x.LoadFile(e.url,e=>t(e),void 0,void 0,!0,(t,i)=>s(i instanceof Error?i:new Error(`GaussianSplattingDownloadManager: failed to load ${e.url}.`)))})}}class le{constructor(){this._offset=0,this._size=0,this._free=!0,this._prev=null,this._next=null,this._prevFree=null,this._nextFree=null,this._bucket=-1}get offset(){return this._offset}get size(){return this._size}}class he{constructor(e=0,t=1.1){if(this._headAll=null,this._tailAll=null,this._freeBucketHeads=[],this._pool=[],this._capacity=0,this._usedSize=0,this._freeSize=0,this._freeRegionCount=0,this._growMultiplier=t,e>0){this._capacity=e,this._freeSize=e;const t=this._obtain(0,e,!0);this._headAll=t,this._tailAll=t,this._addToBucket(t)}}get capacity(){return this._capacity}get usedSize(){return this._usedSize}get freeSize(){return this._freeSize}get fragmentation(){return this._freeSize>0?1-1/this._freeRegionCount:0}allocate(e){if(e<=0)return null;const t=this._findFreeBlock(e);if(!t)return null;if(this._usedSize+=e,this._freeSize-=e,t._size===e)return t._free=!1,this._removeFromBucket(t),t;const s=this._obtain(t._offset,e,!1);return t._offset+=e,t._size-=e,this._rebucket(t),this._insertAfterInMainList(s,t._prev),s}free(e){if(!e||e._free)return;e._free=!0,this._usedSize-=e._size,this._freeSize+=e._size;const t=e._prev,s=e._next,i=t&&t._free,n=s&&s._free;i&&n?(t._size+=e._size+s._size,this._removeFromMainList(e),this._removeFromMainList(s),this._removeFromBucket(s),this._release(e),this._release(s),this._rebucket(t)):i?(t._size+=e._size,this._removeFromMainList(e),this._release(e),this._rebucket(t)):n?(e._size+=s._size,this._removeFromMainList(s),this._removeFromBucket(s),this._release(s),this._addToBucket(e)):this._addToBucket(e)}grow(e){if(e<=this._capacity)return;const t=e-this._capacity;if(this._capacity=e,this._freeSize+=t,this._tailAll&&this._tailAll._free)this._tailAll._size+=t,this._rebucket(this._tailAll);else{const e=this._obtain(this._capacity-t,t,!0);this._insertAfterInMainList(e,this._tailAll),this._addToBucket(e)}}defrag(e=0,t=new Set){return t.clear(),0===this._freeRegionCount||(0===e?this._defragFull(t):this._defragIncremental(e,t)),t}updateAllocation(e,t){for(let t=0;t<e.length;t++)this.free(e[t]);for(let e=0;e<t.length;e++){const s=t[e],i=this.allocate(s);if(!i){let i=s;for(let s=e+1;s<t.length;s++)i+=t[s];const n=this._usedSize+i,a=Math.ceil(n*this._growMultiplier);a>this._capacity&&this.grow(a),this.defrag(0);for(let s=e;s<t.length;s++)t[s]=this.allocate(t[s]);return!0}t[e]=i}return!1}_bucketFor(e){return 31-Math.clz32(e)}_addToBucket(e){const t=this._bucketFor(e._size);for(e._bucket=t;t>=this._freeBucketHeads.length;)this._freeBucketHeads.push(null);e._prevFree=null,e._nextFree=this._freeBucketHeads[t],this._freeBucketHeads[t]&&(this._freeBucketHeads[t]._prevFree=e),this._freeBucketHeads[t]=e,this._freeRegionCount++}_removeFromBucket(e){const t=e._bucket;e._prevFree?e._prevFree._nextFree=e._nextFree:this._freeBucketHeads[t]=e._nextFree,e._nextFree&&(e._nextFree._prevFree=e._prevFree),e._prevFree=null,e._nextFree=null,e._bucket=-1,this._freeRegionCount--}_rebucket(e){this._bucketFor(e._size)!==e._bucket&&(this._removeFromBucket(e),this._addToBucket(e))}_obtain(e,t,s){const i=this._pool.length>0?this._pool.pop():new le;return i._offset=e,i._size=t,i._free=s,i._prev=null,i._next=null,i._prevFree=null,i._nextFree=null,i._bucket=-1,i}_release(e){e._prev=null,e._next=null,e._prevFree=null,e._nextFree=null,e._bucket=-1,this._pool.push(e)}_insertAfterInMainList(e,t){null===t?(e._prev=null,e._next=this._headAll,this._headAll&&(this._headAll._prev=e),this._headAll=e,this._tailAll||(this._tailAll=e)):(e._prev=t,e._next=t._next,t._next&&(t._next._prev=e),t._next=e,this._tailAll===t&&(this._tailAll=e))}_removeFromMainList(e){e._prev?e._prev._next=e._next:this._headAll=e._next,e._next?e._next._prev=e._prev:this._tailAll=e._prev,e._prev=null,e._next=null}_findFreeBlock(e){const t=this._bucketFor(e),s=this._freeBucketHeads.length;if(t<s){let s=null,i=this._freeBucketHeads[t];for(;i&&!(i._size>=e&&(!s||i._size<s._size)&&(s=i,i._size===e));)i=i._nextFree;if(s)return s}for(let e=t+1;e<s;e++)if(this._freeBucketHeads[e])return this._freeBucketHeads[e];return null}_defragFull(e){for(let e=0;e<this._freeBucketHeads.length;e++){let t=this._freeBucketHeads[e];for(;t;){const e=t._nextFree;this._removeFromMainList(t),t._prevFree=null,t._nextFree=null,t._bucket=-1,this._pool.push(t),t=e}this._freeBucketHeads[e]=null}this._freeRegionCount=0;let t=0,s=this._headAll;for(;s;)s._offset!==t&&(s._offset=t,e.add(s)),t+=s._size,s=s._next;const i=this._capacity-t;if(i>0){const e=this._obtain(t,i,!0);this._insertAfterInMainList(e,this._tailAll),this._addToBucket(e)}}_defragIncremental(e,t){const s=Math.ceil(e/2),i=e-s;for(let e=0;e<s;e++){let e=this._tailAll;for(;e&&e._free;)e=e._prev;if(!e)break;const s=this._findFreeBlock(e._size);if(!s||s._offset>=e._offset)break;this._moveBlock(e,s),t.add(e)}let n=this._headAll;for(let e=0;e<i&&n;){const s=n._next;if(n._free&&s&&!s._free){const i=s,a=n;i._offset=a._offset,a._offset=i._offset+i._size;const o=a._prev,r=i._next;if(i._prev=o,i._next=a,a._prev=i,a._next=r,o?o._next=i:this._headAll=i,r?r._prev=a:this._tailAll=a,a._next&&a._next._free){const e=a._next;a._size+=e._size,this._removeFromMainList(e),this._removeFromBucket(e),this._release(e),this._rebucket(a)}t.add(i),e++,n=a._next}else n=s}}_moveBlock(e,t){const s=e._size,i=t._offset,n=e._prev;this._removeFromMainList(e);const a=this._obtain(e._offset,s,!0);if(this._insertAfterInMainList(a,n),this._addToBucket(a),a._next&&a._next._free){const e=a._next;a._size+=e._size,this._removeFromMainList(e),this._removeFromBucket(e),this._release(e),this._rebucket(a)}if(a._prev&&a._prev._free){const e=a._prev;e._size+=a._size,this._removeFromMainList(a),this._removeFromBucket(a),this._release(a),this._rebucket(e)}if(e._offset=i,t._size===s){const s=t._prev;this._removeFromMainList(t),this._removeFromBucket(t),this._release(t),this._insertAfterInMainList(e,s)}else t._offset+=s,t._size-=s,this._rebucket(t),this._insertAfterInMainList(e,t._prev)}}class ce{constructor(e,t,s){this._blocks=new Map,this._cooldown=new Map,this._pinned=new Set,this._allocator=new he(e),this._cooldownFrames=Math.max(0,t),this._onEvict=s}get capacity(){return this._allocator.capacity}get residentCount(){return this._blocks.size}get freeSize(){return this._allocator.freeSize}has(e){return this._blocks.has(e)}offset(e){return this._blocks.get(e)?.offset}allocate(e,t){const s=this._blocks.get(e);if(s)return s.offset;let i=this._allocator.allocate(t);return i||(this._evictAllCooled(),i=this._allocator.allocate(t),i)?(this._blocks.set(e,i),i.offset):null}pin(e,t){const s=this.allocate(e,t);return null!==s&&this._pinned.add(e),s}free(e){if(this._pinned.has(e))return;const t=this._blocks.get(e);t&&(this._allocator.free(t),this._blocks.delete(e),this._cooldown.delete(e))}compact(){const e=new Map;for(const[t,s]of Array.from(this._blocks))e.set(t,s.offset);this._allocator.defrag(0);const t=[];for(const[s,i]of Array.from(this._blocks)){const n=e.get(s);n!==i.offset&&t.push({file:s,oldOffset:n,newOffset:i.offset,count:i.size})}return t}getResidentBlocks(){const e=[];for(const[t,s]of Array.from(this._blocks))e.push({file:t,offset:s.offset,count:s.size});return e}scheduleEviction(e){!this._pinned.has(e)&&this._blocks.has(e)&&this._cooldown.set(e,this._cooldownFrames)}cancelEviction(e){this._cooldown.delete(e)}tick(){if(0===this._cooldown.size)return[];const e=[];for(const[t,s]of Array.from(this._cooldown))s<=1?e.push(t):this._cooldown.set(t,s-1);for(const t of e)this._evict(t);return e}dispose(){this._blocks.clear(),this._cooldown.clear(),this._pinned.clear()}_evictAllCooled(){const e=Array.from(this._cooldown.keys());for(const t of e)this._evict(t)}_evict(e){const t=this._blocks.get(e);t&&(this._allocator.free(t),this._blocks.delete(e)),this._cooldown.delete(e),this._onEvict(e)}}const ue=Math.tan(22.5*Math.PI/180),de=new v,_e=new u,fe=new u,pe=new u,me=new u(0,0,1),ge=[[0,1],[1,2],[2,3],[3,0],[4,5],[5,6],[6,7],[7,4],[0,4],[1,5],[2,6],[3,7]],xe=2*ge.length,be=[new a(1,.2,.2,1),new a(1,.6,.1,1),new a(1,1,.2,1),new a(.3,1,.3,1),new a(.2,1,1,1),new a(.4,.5,1,1),new a(.9,.4,1,1),new a(1,1,1,1)];class ye extends M{static IsLODMetadata(e){if("object"!=typeof e||null===e)return!1;const t=e;return"number"==typeof t.lodLevels&&Array.isArray(t.filenames)&&"object"==typeof t.tree&&null!==t.tree}constructor(e,t,s,i,n={}){super(e,null,i,!1),this._leafNodes=[],this._lodBaseDistance=5,this._lodMultiplier=3,this._lodBehindPenalty=1,this._lodRangeMin=0,this._maxDecodesPerFrame=1,this._lodCooldownFrames=10,this._lodUpdateInterval=4,this._lodUpdateDistance=.5,this._maxDetailLod=0,this._frustumCulling=!0,this._frustumPlanes=[new S(0,0,0,0),new S(0,0,0,0),new S(0,0,0,0),new S(0,0,0,0),new S(0,0,0,0),new S(0,0,0,0)],this._cullViewProj=new v,this._workBuffer=null,this._streamShDegree=0,this._shTextureCount=0,this._needsRotationScale=!1,this._useGpuPositionReadback=!1,this._readbackCandidate=!1,this._readbackProbed=!1,this._residency=null,this._fileCounts=new Map,this._fileMeta=new Map,this._decodedFiles=new Set,this._loadingFiles=new Set,this._decodeQueue=[],this._fileRefs=new Map,this._cancelledDecodes=new Set,this._evictionEnabled=!1,this._residentBudget=0,this._maxResidentSplats=0,this._memoryBudgetMb=0,this._evictionCooldownFrames=100,this._decodeGate=Promise.resolve(),this._relayoutOldOffsets=new Map,this._relayoutSrcIndex=null,this._environmentRange=null,this._environmentFiles=null,this._lodObserver=null,this._baseLayerReady=!1,this._framesSinceLodUpdate=0,this._lastLodCamPos=new u(1/0,1/0,1/0),this._forceLodUpdate=!1,this._boundsMin=new u(Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE),this._boundsMax=new u(-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE),this._debugDisplay=!1,this._debugLodSource="optimal",this._debugMesh=null,this._debugObserver=null,this._debugColorData=null,this._debugSignature=0,this._disposed=!1,this._hostCompound=null,this._host=null,this._positionBase=0,this._unsubBeforeRebuild=null,this._unsubAfterRebuild=null,this._hostUnsubRemove=null,this._hostUnsubDispose=null,this._partReleasedByHost=!1,this._positionSnapshot=null,this._partReadyPromise=null,this._partReadyResolve=null,this._partReadyReject=null,this._partReadySettled=!1,this._metadata=t,this._rootUrl=s,this._streamOptions=n,this._hostCompound=n.hostCompound??null,this._decodeSh=n.decodeSh??!0,this._needsRotationScale=n.needsRotationScale??!1;const a=Math.max(0,t.lodLevels-1);if(this._lodRangeMax=a,void 0!==n.lodBaseDistance&&(this._lodBaseDistance=Math.max(.1,n.lodBaseDistance)),void 0!==n.lodMultiplier&&(this._lodMultiplier=Math.max(1.2,n.lodMultiplier)),void 0!==n.lodBehindPenalty&&(this._lodBehindPenalty=Math.max(1,n.lodBehindPenalty)),void 0!==n.lodRangeMin&&(this._lodRangeMin=Math.max(0,Math.min(n.lodRangeMin,a))),void 0!==n.lodRangeMax&&(this._lodRangeMax=Math.max(this._lodRangeMin,Math.min(n.lodRangeMax,a))),void 0!==n.maxDecodesPerFrame&&(this._maxDecodesPerFrame=Math.max(1,n.maxDecodesPerFrame)),void 0!==n.lodCooldownFrames&&(this._lodCooldownFrames=Math.max(0,n.lodCooldownFrames)),void 0!==n.lodUpdateInterval&&(this._lodUpdateInterval=Math.max(1,n.lodUpdateInterval)),void 0!==n.lodUpdateDistance&&(this._lodUpdateDistance=Math.max(0,n.lodUpdateDistance)),void 0!==n.maxDetailLod&&(this._maxDetailLod=Math.max(0,Math.floor(n.maxDetailLod))),void 0!==n.frustumCulling&&(this._frustumCulling=n.frustumCulling),n.debugLodSource&&(this._debugLodSource=n.debugLodSource),void 0!==n.evictionCooldownFrames&&(this._evictionCooldownFrames=Math.max(0,Math.floor(n.evictionCooldownFrames))),void 0!==n.maxResidentSplats&&n.maxResidentSplats>0&&(this._maxResidentSplats=Math.floor(n.maxResidentSplats)),void 0!==n.memoryBudgetMb&&n.memoryBudgetMb>0&&(this._memoryBudgetMb=n.memoryBudgetMb),this._downloadManager=new re({maxConcurrent:n.maxConcurrentDownloads,maxRetries:n.maxDownloadRetries}),this._hostCompound){this.setEnabled(!1),this.isPickable=!1,this.doNotSerialize=!0,this._partReadyPromise=new Promise((e,t)=>{this._partReadyResolve=e,this._partReadyReject=t}),this._partReadyPromise.catch(()=>{});const e=this._hostCompound.onDisposeObservable.add(()=>{this._disposed||(this._partReleasedByHost=!0,this.dispose())});this._hostUnsubDispose=()=>this._hostCompound.onDisposeObservable.remove(e)}else this.scaling.y*=-1,this.rotation.x=-Math.PI/2;this._collectLodEntries(t.tree),n.debugDisplay&&(this.debugDisplay=!0),this._streamAllAsync().then(()=>{const e=this._partReadySettled;this._rejectPartReady("GaussianSplattingStream: stream produced no splats."),e||!this._hostCompound||this._disposed||this._disposeAndReclaim()},e=>{d.Error("GaussianSplattingStream: streaming failed: "+(e?.message??e)),this._rejectPartReady("GaussianSplattingStream: streaming failed: "+(e?.message??e)),this._hostCompound&&!this._disposed&&this._disposeAndReclaim()})}getClassName(){return"GaussianSplattingStream"}isReady(e=!1){return!!this._hostCompound||super.isReady(e)}get streamingPartProxy(){return this._host?.proxy??null}async whenPartReadyAsync(){await(this._partReadyPromise??Promise.resolve())}_resolvePartReady(){this._partReadySettled||(this._partReadySettled=!0,this._partReadyResolve?.())}_rejectPartReady(e){this._partReadySettled||(this._partReadySettled=!0,this._partReadyReject?.(new Error(e)))}async whenSettledAsync(e=3){if(this._disposed)return;this._forceLodUpdate=!0;const t=Math.max(1,e),s=this._scene;let i=0;const n=()=>this._isLoadingIdle()&&this._sinkIsDepthSortSettled?++i>=t:(i=0,!1);if(s.getEngine().activeRenderLoops.length>0)return void await new Promise(e=>{let t=null;t=s.onAfterRenderObservable.add(()=>{(this._disposed||n())&&(t&&(s.onAfterRenderObservable.remove(t),t=null),e())})});const a=s.getEngine(),o=globalThis.requestAnimationFrame;for(;!this._disposed;){if(a.beginFrame(),s.render(),a.endFrame(),n())return;await new Promise(e=>{"function"==typeof o?o(()=>e()):setTimeout(e,16)})}}_isLoadingIdle(){return this._baseLayerReady&&0===this._decodeQueue.length&&0===this._loadingFiles.size&&this._downloadManager.isIdle}get maxDetailLod(){return this._maxDetailLod}set maxDetailLod(e){const t=Math.max(0,Math.floor(e));this._maxDetailLod!==t&&(this._maxDetailLod=t,this._forceLodUpdate=!0)}get maxLodLevel(){return Math.max(0,this._metadata.lodLevels-1)}get frustumCulling(){return this._frustumCulling}set frustumCulling(e){this._frustumCulling!==e&&(this._frustumCulling=e,this._forceLodUpdate=!0)}get debugDisplay(){return this._debugDisplay}set debugDisplay(e){this._debugDisplay!==e&&(this._debugDisplay=e,e?this._refreshDebugDisplay():this._clearDebugDisplay())}get debugLodSource(){return this._debugLodSource}set debugLodSource(e){this._debugLodSource!==e&&(this._debugLodSource=e,this._debugDisplay&&this._refreshDebugDisplay())}dispose(e){this._disposed||(this._disposed=!0,this._rejectPartReady("GaussianSplattingStream: disposed before the part was ready."),this._unsubBeforeRebuild?.(),this._unsubAfterRebuild?.(),this._unsubBeforeRebuild=null,this._unsubAfterRebuild=null,this._hostUnsubRemove?.(),this._hostUnsubDispose?.(),this._hostUnsubRemove=null,this._hostUnsubDispose=null,this._host&&this._hostCompound&&!this._partReleasedByHost&&!this._hostCompound.isDisposed()&&this._hostCompound.removePart(this._host.partIndex),this._host=null,this._lodObserver&&(this._scene.onBeforeRenderObservable.remove(this._lodObserver),this._lodObserver=null),this._clearDebugDisplay(),this._downloadManager.dispose(),this._residency?.dispose(),this._residency=null,this._workBuffer?.dispose(),this._workBuffer=null,super.dispose(e))}_disposeAndReclaim(){const e=this._hostCompound,t=!!this._host&&!this._partReleasedByHost;this.dispose(),t&&e&&!e.isDisposed()&&e.compactAtlas()}_getEffectiveWorldMatrix(e){return this._host?this._host.proxy.computeWorldMatrix(e):this.computeWorldMatrix(e)}evaluateOptimalLods(e=this._scene.activeCamera){if(!e||0===this._leafNodes.length)return;const t=Math.max(0,this._metadata.lodLevels-1),s=this._lodBaseDistance,i=this._lodMultiplier,n=this._lodBehindPenalty,a=this._lodRangeMin,o=this._lodRangeMax,r=this._scene.getEngine().getAspectRatio(e)||1;let l=Math.tan(.5*e.fov);e.fovMode===w.FOVMODE_HORIZONTAL_FIXED&&(l/=r);const h=l*r,c=Math.min(l,h)/ue;this._getEffectiveWorldMatrix(!1).invertToRef(de);const d=u.TransformCoordinatesToRef(e.globalPosition,de,_e),_=d.x,f=d.y,p=d.z;let m=0,g=0,x=0;if(n>1){e.getDirectionToRef(me,pe);const t=u.TransformNormalToRef(pe,de,fe);t.normalize(),m=t.x,g=t.y,x=t.z}for(const e of this._leafNodes){const r=e.bound.min,l=e.bound.max,h=(_<r[0]?r[0]:_>l[0]?l[0]:_)-_,u=(f<r[1]?r[1]:f>l[1]?l[1]:f)-f,d=(p<r[2]?r[2]:p>l[2]?l[2]:p)-p,b=Math.sqrt(h*h+u*u+d*d);let y=b;if(n>1&&b>.01){const e=(m*h+g*u+x*d)/b;e<0&&(y=b*(1+-e*(n-1)))}const M=y*c;let S;if(0===t||M<s)S=0;else for(S=t;S>1&&M<s*Math.pow(i,S-1);)S--;S<a?S=a:S>o&&(S=o),this._frustumCulling&&!1===e.inFrustum&&(S=o),e.optimalLod=S}}_displayedLodLevel(e){return"optimal"===this._debugLodSource?e.optimalLod??e.activeLod??0:e.activeLod??0}_refreshDebugDisplay(){"optimal"===this._debugLodSource&&this.evaluateOptimalLods(),this._buildDebugMesh();const e=this._debugDisplay;e&&!this._debugObserver?this._debugObserver=this._scene.onBeforeRenderObservable.add(()=>this._onDebugFrame()):!e&&this._debugObserver&&(this._scene.onBeforeRenderObservable.remove(this._debugObserver),this._debugObserver=null)}_onDebugFrame(){"optimal"===this._debugLodSource&&this.evaluateOptimalLods(),this._computeDebugSignature()!==this._debugSignature&&this._updateDebugColors()}_buildDebugMesh(){this._debugMesh&&(this._debugMesh.dispose(),this._debugMesh=null),this._debugColorData=null;const e=[],t=[];for(const s of this._leafNodes){const i=be[this._displayedLodLevel(s)%be.length],n=s.bound.min,a=s.bound.max,o=[new u(n[0],n[1],n[2]),new u(a[0],n[1],n[2]),new u(a[0],a[1],n[2]),new u(n[0],a[1],n[2]),new u(n[0],n[1],a[2]),new u(a[0],n[1],a[2]),new u(a[0],a[1],a[2]),new u(n[0],a[1],a[2])];for(const s of ge)e.push([o[s[0]],o[s[1]]]),t.push([i,i])}if(this._debugSignature=this._computeDebugSignature(),0===e.length)return;const s=Z(this.name+"_lodDebug",{lines:e,colors:t,updatable:!0,useVertexAlpha:!1},this._scene);s.parent=this,s.isPickable=!1,s.doNotSerialize=!0,s.reservedDataStore={hidden:!0},this._debugMesh=s,this._debugColorData=new Float32Array(this._leafNodes.length*xe*4)}_updateDebugColors(){if(!this._debugMesh||!this._debugColorData)return;const e=this._debugColorData;let t=0;for(const s of this._leafNodes){const i=be[this._displayedLodLevel(s)%be.length];for(let s=0;s<xe;s++)e[t++]=i.r,e[t++]=i.g,e[t++]=i.b,e[t++]=i.a}this._debugMesh.updateVerticesData(r.ColorKind,e),this._debugSignature=this._computeDebugSignature()}_computeDebugSignature(){let e=0;for(const t of this._leafNodes)e=31*e+this._displayedLodLevel(t)|0;return e}_clearDebugDisplay(){this._debugObserver&&(this._scene.onBeforeRenderObservable.remove(this._debugObserver),this._debugObserver=null),this._debugMesh&&(this._debugMesh.dispose(),this._debugMesh=null),this._debugColorData=null,this._debugSignature=0}_collectLodEntries(e){if(e.children){for(const t of e.children)this._collectLodEntries(t);return}if(!e.lods)return;const t=[];for(const s of Object.keys(e.lods)){const i=Number(s),n=e.lods[s];Number.isFinite(i)&&n&&n.count>0&&t.push(i)}0!==t.length&&(t.sort((e,t)=>e-t),e.availableLevels=t,e.baseLod=t[t.length-1],e.activeLod=void 0,e.lodCooldown=0,e.inFrustum=!0,e.cullBounds=new R(u.FromArray(e.bound.min),u.FromArray(e.bound.max)),this._leafNodes.push(e))}async _streamAllAsync(){const e=this._collectAllFileIds(),t=await this._gatherCountsAsync(e);if(this._disposed)return;this._resolveResidentBudget();let s=1;t>0&&(s+=t);for(const t of e){const e=this._fileCounts.get(t);void 0!==e&&e>0&&(s+=e)}if(s<=1)return;this._evictionEnabled=this._residentBudget>0&&this._residentBudget<s;const i=this._evictionEnabled?Math.max(this._residentBudget,1):s;if(this._residency=new ce(i,this._evictionCooldownFrames,e=>this._onFileEvicted(e)),this._residency.pin(-2,1),t>0){const e=this._residency.pin(-1,t);null!==e?this._environmentRange={offset:e,count:t}:(d.Warn("GaussianSplattingStream: environment does not fit the memory budget; skipping it."),this._environmentFiles=null)}if(this._hostCompound){const e=v.Compose(new u(1,-1,1),T.RotationYawPitchRoll(0,-Math.PI/2,0),u.ZeroReadOnly),t=this._hostCompound.reserveStreamingPart(i,e,this.name+"_part",this._shTextureCount,this._streamShDegree,this._needsRotationScale);this._host=t,this._positionBase=t.base;const s=this._hostCompound,n=s.onPartRemovedObservable.add(e=>{!this._disposed&&this._host&&e===this._host.partIndex&&(this._partReleasedByHost=!0,this.dispose())});this._hostUnsubRemove=()=>s.onPartRemovedObservable.remove(n);const a=this._shTextureCount>0&&t.shMrtAtlas?{textureCount:this._shTextureCount,externalMrts:t.shMrtAtlas}:void 0,o=this._needsRotationScale&&t.rotMrtAtlas?{externalMrt:t.rotMrtAtlas}:void 0;this._workBuffer=new oe(this._scene,t.capacity,{mrt:t.mrtAtlas,width:t.atlasWidth,baseOffset:t.base},a,o),this._readbackCandidate=this._workBuffer.supportsAsyncCentersReadback,this._splatPositions=t.splatPositions,this._vertexCount=i;const r=this._workBuffer;this._unsubBeforeRebuild=t.onBeforeAtlasRebuild(()=>{r.backupRegion(),this._positionSnapshot=this._splatPositions?this._splatPositions.slice(4*this._positionBase,4*(this._positionBase+this._vertexCount)):null}),this._unsubAfterRebuild=t.onAfterAtlasRebuild(()=>{t.mrtAtlas&&r.rebindAtlas(t.mrtAtlas),r.rebindShAtlas(t.shMrtAtlas),r.rebindRotAtlas(t.rotMrtAtlas),this._positionBase=t.base,r.setBaseOffset(t.base),r.restoreRegion(),this._splatPositions=t.splatPositions,this._positionSnapshot&&this._splatPositions&&(this._splatPositions.set(this._positionSnapshot,4*this._positionBase),this._positionSnapshot=null)}),t.setActiveRanges([])}else{const e=this._shTextureCount>0?{textureCount:this._shTextureCount}:void 0,t=this._needsRotationScale?{}:void 0;this._workBuffer=new oe(this._scene,i,void 0,e,t),this._readbackCandidate=this._workBuffer.supportsAsyncCentersReadback;const s=new Float32Array(4*i),n=this._workBuffer.textures,a=e?this._workBuffer.shTextures:void 0,o=t?this._workBuffer.rotationTextures:void 0;this._setExternalWorkBuffer(n[0],n[1],n[2],n[3],s,i,a,this._streamShDegree,o),this.setSplatIndexRanges([]),this.setEnabled(!0)}if(this._host&&this._workBuffer&&(await this._waitForCanBackupAsync(this._workBuffer),this._disposed))return;this._environmentRange&&this._environmentFiles&&await this._decodeEnvironmentAsync(),this._environmentFiles=null;const n=new Set;for(const e of this._leafNodes){const t=e.lods[String(e.baseLod)];t&&this._fileCounts.has(t.file)&&n.add(t.file)}for(const e of Array.from(n)){if(this._disposed)return;await this._decodeFileAsync(e)}this._disposed||(this._baseLayerReady=!0,this._lodObserver||(this._lodObserver=this._scene.onBeforeRenderObservable.add(()=>this._onLodFrame())),this._resolvePartReady())}async _waitForCanBackupAsync(e){for(let t=0;t<600&&!this._disposed;t++){if(e.canBackup)return;await new Promise(e=>this._scene.onBeforeRenderObservable.addOnce(()=>e()))}this._disposed||e.canBackup||d.Warn("GaussianSplattingStream: backup/restore copy shaders did not compile in time; a grow/compaction before they are ready may drop streamed data.")}_resolveResidentBudget(){let e=this._maxResidentSplats;if(this._memoryBudgetMb>0){const t=this._scene.getEngine().getCaps().textureHalfFloatRender?24:48,s=84+16*this._shTextureCount+(this._needsRotationScale?t:0),i=Math.floor(1024*this._memoryBudgetMb*1024/s);e=e>0?Math.min(e,i):i}this._residentBudget=e}_collectAllFileIds(){const e=new Set;for(const t of this._leafNodes)for(const s of t.availableLevels){const i=t.lods[String(s)];i&&e.add(i.file)}return Array.from(e).sort((e,t)=>e-t)}async _gatherCountsAsync(e){let t=0,s=0,i=0;const n=e=>{const t=ye._GetShInfo(e);t.degree>s&&(s=t.degree),t.coeffs>i&&(i=t.coeffs)};if(this._metadata.environment)try{const e=this._rootUrl+this._metadata.environment,s=await this._downloadManager.loadFileAsync(e),i=await this._unzipAsync(new Uint8Array(s)),a=i.get("meta.json");if(a){const e=JSON.parse((new TextDecoder).decode(a));t=ye._GetSplatCount(e),n(e),this._environmentFiles=i}}catch(e){d.Warn("GaussianSplattingStream: failed to load environment: "+(e?.message??e))}await Promise.all(e.map(async e=>{const t=this._metadata.filenames[e];if(t)try{const s=this._rootUrl+t,i=s.substring(0,s.lastIndexOf("/")+1),n=await this._downloadManager.loadFileAsync(s),a=JSON.parse((new TextDecoder).decode(new Uint8Array(n)));this._fileCounts.set(e,ye._GetSplatCount(a)),this._fileMeta.set(e,{sogData:a,subRootUrl:i})}catch(e){d.Warn(`GaussianSplattingStream: failed to load metadata for ${t}: ${e?.message??e}`)}else d.Warn(`GaussianSplattingStream: missing filename for file index ${e}.`)}));for(const{sogData:e}of this._fileMeta.values())n(e);return this._decodeSh&&s>0&&i>0&&(this._streamShDegree=s,this._shTextureCount=Math.ceil(3*i/16)),t}_enqueueDecode(e){this._decodedFiles.has(e)||this._loadingFiles.has(e)||!this._fileMeta.has(e)||-1===this._decodeQueue.indexOf(e)&&this._decodeQueue.push(e)}_pumpDecodeQueue(){let e=0;for(;this._decodeQueue.length>0&&e<this._maxDecodesPerFrame;){const t=this._decodeQueue.shift();this._decodedFiles.has(t)||this._loadingFiles.has(t)||(e++,this._decodeFileAsync(t).catch(e=>{d.Warn("GaussianSplattingStream: decode failed: "+(e?.message??e))}))}}_applyPositions(e,t,s){this._splatPositions.set(e,4*(this._positionBase+t)),this._updateBounds(e,s),this._sinkPostPositionsRange(t,s)}_sinkSetActiveRanges(e){this._host?this._host.setActiveRanges(e):this.setSplatIndexRanges(e)}_sinkPostPositionsRange(e,t){this._host?this._host.postPositionsRange(e,t):this._postWorkerPositionsRange(e,t)}_sinkNotifyDataChanged(){this._host?this._host.notifyDataChanged():this._notifyWorkerNewData()}get _sinkIsDepthSortSettled(){return this._host?this._host.isDepthSortSettled:this._isDepthSortSettled}async _probeReadbackAsync(e,t,s){if(this._readbackProbed=!0,!this._workBuffer)return;const i=Math.min(t,1024);let n=!1;try{const t=await this._workBuffer.readCentersRangeAsync(e,i);if(this._disposed)return;if(t&&t.length>=4*i){n=!0;for(let e=0;e<i&&n;e++)for(let i=0;i<3;i++){const a=t[4*e+i],o=s[4*e+i];if(Math.abs(a-o)>.01*(1+Math.abs(o))){n=!1;break}}}}catch{n=!1}this._useGpuPositionReadback=n,d.Log(n?"GaussianSplattingStream: GPU position readback validated; streamed LOD positions are read back from the GPU.":"GaussianSplattingStream: GPU position readback unavailable; decoding LOD positions on the CPU.")}async _applyDecodedPositionsAsync(e,t,s){if(this._useGpuPositionReadback&&this._workBuffer){const e=await this._workBuffer.readCentersRangeAsync(t,s);if(this._disposed)return!1;if(e&&this._splatPositions)return this._applyPositions(e,t,s),!0}const i=e.positions.length>=4*s?e.positions.subarray(0,4*s):null;return!(!i||!this._splatPositions)&&(this._applyPositions(i,t,s),!this._readbackProbed&&this._readbackCandidate&&await this._probeReadbackAsync(t,s,i),!0)}async _decodeEnvironmentAsync(){if(!this._environmentRange||!this._environmentFiles||!this._workBuffer)return;const e=this._environmentRange;try{const t=(await ie(this._environmentFiles,"",this._scene,!this._useGpuPositionReadback,this._downloadManager)).sogTextures;if(!t)return;try{if(this._disposed||!this._workBuffer)return;if(await this._workBuffer.decodeAsync(t,e.offset),this._disposed)return;if(await this._applyDecodedPositionsAsync(t,e.offset,e.count),this._disposed)return;this._refreshActiveRanges()}finally{ye._DisposePack(t)}}catch(e){d.Warn("GaussianSplattingStream: failed to decode environment: "+(e?.message??e))}}async _decodeFileAsync(e){if(this._decodedFiles.has(e)||this._loadingFiles.has(e)||!this._residency)return;const t=this._fileMeta.get(e),s=this._fileCounts.get(e);if(!t||void 0===s)return;this._loadingFiles.add(e),this._cancelledDecodes.delete(e);let i=!1;try{const n=(await ie(t.sogData,t.subRootUrl,this._scene,!this._useGpuPositionReadback,this._downloadManager,e)).sogTextures;if(!n)return;const a=await this._acquireDecodeGateAsync();try{if(this._disposed||!this._workBuffer||this._cancelledDecodes.has(e))return;let t=this._residency.allocate(e,s);if(null===t&&(t=await this._relayoutAndAllocateAsync(e,s)),null===t)return void(this._cancelledDecodes.has(e)||d.Warn(`GaussianSplattingStream: resident memory budget full; skipping LOD file ${e}.`));if(i=!0,this._disposed||!this._workBuffer||this._cancelledDecodes.has(e))return;if(await this._workBuffer.decodeAsync(n,t),this._disposed||this._cancelledDecodes.has(e))return;if(await this._applyDecodedPositionsAsync(n,t,s),this._disposed)return;this._decodedFiles.add(e),this._applyDesiredLods()&&this._refreshActiveRanges()}finally{ye._DisposePack(n),a()}}catch(t){if(!this._cancelledDecodes.has(e))throw t}finally{i&&!this._decodedFiles.has(e)&&this._residency.free(e),this._loadingFiles.delete(e),this._cancelledDecodes.delete(e)}}async _acquireDecodeGateAsync(){const e=this._decodeGate;let t;return this._decodeGate=new Promise(e=>{t=e}),await e,t}async _relayoutAndAllocateAsync(e,t){return this._residency&&this._workBuffer?this._residency.freeSize<t?null:await new Promise(s=>{const i=()=>{!this._disposed&&this._residency&&this._workBuffer&&!this._cancelledDecodes.has(e)?this._workBuffer.isRelayoutReady()?(this._performRelayout(),s(this._residency.allocate(e,t))):this._scene.onBeforeRenderObservable.addOnce(i):s(null)};this._scene.onBeforeRenderObservable.addOnce(i)}):null}_performRelayout(){if(!this._residency||!this._workBuffer||!this._splatPositions)return;const e=this._relayoutOldOffsets;e.clear();for(const t of this._residency.getResidentBlocks())e.set(t.file,t.offset);if(0===this._residency.compact().length)return;const t=this._residency.capacity;this._relayoutSrcIndex&&this._relayoutSrcIndex.length===t||(this._relayoutSrcIndex=new Float32Array(t));const s=this._relayoutSrcIndex;s.fill(-1);const i=this._residency.getResidentBlocks();for(const t of i){const i=e.get(t.file);for(let e=0;e<t.count;e++)s[t.offset+e]=i+e}this._workBuffer.relayoutSync(s);const n=this._splatPositions,a=this._positionBase;i.sort((e,t)=>e.offset-t.offset);for(const t of i){const s=e.get(t.file);s!==t.offset&&n.copyWithin(4*(a+t.offset),4*(a+s),4*(a+s+t.count))}if(this._environmentRange){const e=this._residency.offset(-1);void 0!==e&&(this._environmentRange.offset=e)}this._sinkNotifyDataChanged(),this._refreshActiveRanges()}_onFileEvicted(e){this._decodedFiles.delete(e)}_cappedLevelForNode(e,t){const s=e.availableLevels,i=this._maxDetailLod;let n=-1,a=Number.POSITIVE_INFINITY;for(const e of s){if(e<i)continue;const s=Math.abs(e-t);s<a&&(n=e,a=s)}return n<0?e.baseLod:n}_computeTargetLevels(){for(const e of this._leafNodes){const t=e.optimalLod??e.baseLod;e.targetLevel=this._cappedLevelForNode(e,t)}}_applyDesiredLods(){let e=!1;for(const t of this._leafNodes){if(t.lodCooldown&&t.lodCooldown>0)continue;const s=t.targetLevel??t.baseLod;let i;if(s!==t.activeLod){const n=t.lods[String(s)];n&&(this._decodedFiles.has(n.file)?(this._switchActiveFile(t,n.file),t.activeLod=s,t.lodCooldown=this._lodCooldownFrames,e=!0):i=n.file)}t.pendingFile!==i&&(void 0!==t.pendingFile&&this._releaseFileRef(t.pendingFile),void 0!==i&&this._acquirePendingFile(i),t.pendingFile=i)}return e}_switchActiveFile(e,t){e.activeFile!==t&&(void 0!==e.activeFile&&this._releaseFileRef(e.activeFile),this._acquireFileRef(t),e.activeFile=t)}_acquireFileRef(e){const t=(this._fileRefs.get(e)??0)+1;this._fileRefs.set(e,t),1===t&&this._residency?.cancelEviction(e)}_acquirePendingFile(e){this._acquireFileRef(e),this._enqueueDecode(e)}_releaseFileRef(e){const t=(this._fileRefs.get(e)??0)-1;if(t>0)return void this._fileRefs.set(e,t);if(this._fileRefs.delete(e),this._decodedFiles.has(e))return void(this._evictionEnabled&&this._residency?.scheduleEviction(e));const s=this._decodeQueue.indexOf(e);-1!==s&&this._decodeQueue.splice(s,1),this._loadingFiles.has(e)&&(this._cancelledDecodes.add(e),this._downloadManager.cancelGroup(e))}_onLodFrame(){if(this._disposed||!this._baseLayerReady)return;let e=!1;for(const t of this._leafNodes)t.lodCooldown&&t.lodCooldown>0&&(t.lodCooldown--,0===t.lodCooldown&&void 0!==t.targetLevel&&t.targetLevel!==t.activeLod&&(e=!0));this._evictionEnabled&&this._residency?.tick(),this._pumpDecodeQueue();const t=this._updateNodeFrustum();let s=this._forceLodUpdate||t||e;if(!s&&++this._framesSinceLodUpdate>=this._lodUpdateInterval){const e=this._scene.activeCamera,t=this._lodUpdateDistance;(!e||u.DistanceSquared(e.globalPosition,this._lastLodCamPos)>=t*t)&&(e&&this._lastLodCamPos.copyFrom(e.globalPosition),s=!0)}s&&(this._forceLodUpdate=!1,this._framesSinceLodUpdate=0,this.evaluateOptimalLods(this._scene.activeCamera),this._computeTargetLevels(),this._applyDesiredLods()&&this._refreshActiveRanges())}_updateNodeFrustum(){const e=this._scene.activeCamera;let t=!1;if(!this._frustumCulling||!e){for(const e of this._leafNodes)!1===e.inFrustum&&(e.inFrustum=!0,t=!0);return t}const s=this._getEffectiveWorldMatrix(!1);e.getViewMatrix().multiplyToRef(e.getProjectionMatrix(),this._cullViewProj),C.GetPlanesToRef(this._cullViewProj,this._frustumPlanes);for(const e of this._leafNodes){e.cullBounds.update(s);const i=e.cullBounds.isInFrustum(this._frustumPlanes);i!==e.inFrustum&&(e.inFrustum=i,t=!0)}return t}static _GetSplatCount(e){return e.count??(Array.isArray(e.means.shape)?e.means.shape[0]:0)}static _GetShInfo(e){if(!e.shN)return{degree:0,coeffs:0};let t=0;const s=e.shN.bands;if("number"==typeof s&&Number.isFinite(s)&&s>0)t=Math.floor(s);else if(Array.isArray(e.shN.shape)&&Number.isFinite(e.shN.shape[1])&&e.shN.shape[1]>0){const s=Math.floor(e.shN.shape[1]/3);t=s>0?Math.round(Math.sqrt(s+1)-1):0}return t>0?(t>4&&(d.Warn(`GaussianSplattingStream: SH degree ${t} exceeds the maximum supported (4); clamping.`),t=4),{degree:t,coeffs:(t+1)**2-1}):{degree:0,coeffs:0}}static _DisposePack(e){e.meansTextureL.dispose(),e.meansTextureU.dispose(),e.scalesTexture.dispose(),e.quatsTexture.dispose(),e.sh0Texture.dispose(),e.shCentroidsTexture?.dispose(),e.shLabelsTexture?.dispose(),e.codebookTexture?.dispose()}_updateBounds(e,t){const s=this._boundsMin,i=this._boundsMax;for(let n=0;n<t;n++){const t=e[4*n+0],a=e[4*n+1],o=e[4*n+2];s.minimizeInPlaceFromFloats(t,a,o),i.maximizeInPlaceFromFloats(t,a,o)}this._host?this._host.expandBounds(s,i):this.setBoundingInfo(new R(s,i))}_refreshActiveRanges(){const e=[];this._environmentRange&&e.push({offset:this._environmentRange.offset,count:this._environmentRange.count});for(const t of this._leafNodes){if(void 0===t.activeLod)continue;const s=t.lods[String(t.activeLod)];if(!s)continue;const i=this._residency?.offset(s.file);void 0!==i&&e.push({offset:i+s.offset,count:s.count})}this._sinkSetActiveRanges(ye._CoalesceRanges(e))}static _CoalesceRanges(e){if(e.length<=1)return e;const t=e.slice().sort((e,t)=>e.offset-t.offset),s=[{offset:t[0].offset,count:t[0].count}];for(let e=1;e<t.length;e++){const i=s[s.length-1],n=t[e],a=i.offset+i.count;if(n.offset<=a){const e=Math.max(a,n.offset+n.count);i.count=e-i.offset}else s.push({offset:n.offset,count:n.count})}return s}async _unzipAsync(e){let t=this._streamOptions.fflate;t||(void 0===window.fflate&&await x.LoadScriptAsync(this._streamOptions.deflateURL??"https://unpkg.com/fflate/umd/index.js"),t=window.fflate);const s=t.unzipSync(e),i=new Map;for(const[e,t]of Object.entries(s))i.set(e,t);return i}}class Me{constructor(e,t,s,i,n){this.idx=0,this.color=new a(1,1,1,1),this.position=u.Zero(),this.rotation=u.Zero(),this.uv=new A(0,0),this.velocity=u.Zero(),this.pivot=u.Zero(),this.translateFromPivot=!1,this._pos=0,this._ind=0,this.groupId=0,this.idxInGroup=0,this._stillInvisible=!1,this._rotationMatrix=[1,0,0,0,1,0,0,0,1],this.parentId=null,this._globalPosition=u.Zero(),this.idx=e,this._group=t,this.groupId=s,this.idxInGroup=i,this._pcs=n}get size(){return this.size}set size(e){this.size=e}get quaternion(){return this.rotationQuaternion}set quaternion(e){this.rotationQuaternion=e}intersectsMesh(e,t){if(!e.hasBoundingInfo)return!1;if(!this._pcs.mesh)throw new Error("Point Cloud System doesnt contain the Mesh");if(t)return e.getBoundingInfo().boundingSphere.intersectsPoint(this.position.add(this._pcs.mesh.position));const s=e.getBoundingInfo().boundingBox,i=s.maximumWorld.x,n=s.minimumWorld.x,a=s.maximumWorld.y,o=s.minimumWorld.y,r=s.maximumWorld.z,l=s.minimumWorld.z,h=this.position.x+this._pcs.mesh.position.x,c=this.position.y+this._pcs.mesh.position.y,u=this.position.z+this._pcs.mesh.position.z;return n<=h&&h<=i&&o<=c&&c<=a&&l<=u&&u<=r}getRotationMatrix(e){let t;if(this.rotationQuaternion)t=this.rotationQuaternion;else{t=q.Quaternion[0];const e=this.rotation;T.RotationYawPitchRollToRef(e.y,e.x,e.z,t)}t.toRotationMatrix(e)}}class Se{get groupID(){return this.groupId}set groupID(e){this.groupId=e}constructor(e,t){this.groupId=e,this._positionFunction=t}}var ve;!function(e){e[e.Color=2]="Color",e[e.UV=1]="UV",e[e.Random=0]="Random",e[e.Stated=3]="Stated"}(ve||(ve={}));class we{get positions(){return this._positions32}get colors(){return this._colors32}get uvs(){return this._uvs32}constructor(e,t,s,i){this.particles=new Array,this.nbParticles=0,this.counter=0,this.vars={},this._promises=[],this._positions=new Array,this._indices=new Array,this._normals=new Array,this._colors=new Array,this._uvs=new Array,this._updatable=!0,this._isVisibilityBoxLocked=!1,this._alwaysVisible=!1,this._groups=new Array,this._groupCounter=0,this._computeParticleColor=!0,this._computeParticleTexture=!0,this._computeParticleRotation=!0,this._computeBoundingBox=!1,this._isReady=!1,this.name=e,this._size=t,this._scene=s||D.LastCreatedScene,i&&void 0!==i.updatable?this._updatable=i.updatable:this._updatable=!0}async buildMeshAsync(e){return await Promise.all(this._promises),this._isReady=!0,await this._buildMeshAsync(e)}async _buildMeshAsync(e){0===this.nbParticles&&this.addPoints(1),this._positions32=new Float32Array(this._positions),this._uvs32=new Float32Array(this._uvs),this._colors32=new Float32Array(this._colors);const t=new c;t.set(this._positions32,r.PositionKind),this._uvs32.length>0&&t.set(this._uvs32,r.UVKind);let s=0;this._colors32.length>0&&(s=1,t.set(this._colors32,r.ColorKind));const a=new i(this.name,this._scene);t.applyToMesh(a,this._updatable),this.mesh=a,this._positions=null,this._uvs=null,this._colors=null,this._updatable||(this.particles.length=0);let o=e;return o||(o=new G("point cloud material",this._scene),o.emissiveColor=new n(s,s,s),o.disableLighting=!0,o.pointsCloud=!0,o.pointSize=this._size),a.material=o,a}_addParticle(e,t,s,i){const n=new Me(e,t,s,i,this);return this.particles.push(n),n}_randomUnitVector(e){e.position=new u(Math.random(),Math.random(),Math.random()),e.color=new a(1,1,1,1)}_getColorIndicesForCoord(e,t,s,i){const n=e._groupImageData,o=s*(4*i)+4*t,r=[o,o+1,o+2,o+3],l=r[1],h=r[2],c=r[3],u=n[r[0]],d=n[l],_=n[h],f=n[c];return new a(u/255,d/255,_/255,f)}_setPointsColorOrUV(e,t,s,i,o,l,h,c){c=c??0,s&&e.updateFacetData();const d=2*e.getBoundingInfo().boundingSphere.radius;let _=e.getVerticesData(r.PositionKind);const f=e.getIndices(),p=e.getVerticesData(r.UVKind+(c?c+1:"")),m=e.getVerticesData(r.ColorKind),g=u.Zero();e.computeWorldMatrix();const x=e.getWorldMatrix();if(!x.isIdentity()){_=_.slice(0);for(let e=0;e<_.length/3;e++)u.TransformCoordinatesFromFloatsToRef(_[3*e],_[3*e+1],_[3*e+2],x,g),_[3*e]=g.x,_[3*e+1]=g.y,_[3*e+2]=g.z}let b,M,S,v,w,R,T,C,q,D,L,F,P;const z=u.Zero(),E=u.Zero(),B=u.Zero(),O=u.Zero(),I=u.Zero();let U,W,N,G,X,j;const H=A.Zero(),Y=A.Zero(),Z=A.Zero(),Q=A.Zero(),$=A.Zero();let K,J,ee,te,se,ie,ne,ae,oe,re,le,he;const ce=y.Zero(),ue=y.Zero(),de=y.Zero(),_e=y.Zero(),fe=y.Zero();let pe,me,ge,xe;h=h||0;let be,ye,Me,Se,ve,we,Re,Te=new y(0,0,0,1);const Ce=new V(u.Zero(),new u(1,0,0));let Ae,qe;for(let r=0;r<f.length/3;r++){let c,g,x,y,A,V,De,ke;M=f[3*r],S=f[3*r+1],v=f[3*r+2],w=_[3*M],R=_[3*M+1],T=_[3*M+2],C=_[3*S],q=_[3*S+1],D=_[3*S+2],L=_[3*v],F=_[3*v+1],P=_[3*v+2],z.set(w,R,T),E.set(C,q,D),B.set(L,F,P),E.subtractToRef(z,O),B.subtractToRef(E,I),p&&(U=p[2*M],W=p[2*M+1],N=p[2*S],G=p[2*S+1],X=p[2*v],j=p[2*v+1],H.set(U,W),Y.set(N,G),Z.set(X,j),Y.subtractToRef(H,Q),Z.subtractToRef(Y,$)),m&&i&&(K=m[4*M],J=m[4*M+1],ee=m[4*M+2],te=m[4*M+3],se=m[4*S],ie=m[4*S+1],ne=m[4*S+2],ae=m[4*S+3],oe=m[4*v],re=m[4*v+1],le=m[4*v+2],he=m[4*v+3],ce.set(K,J,ee,te),ue.set(se,ie,ne,ae),de.set(oe,re,le,he),ue.subtractToRef(ce,_e),de.subtractToRef(ue,fe));const Le=new n(0,0,0),Fe=new n(0,0,0);let Pe,ze;for(let _=0;_<t._groupDensity[r];_++)b=this.particles.length,this._addParticle(b,t,this._groupCounter,r+_),ze=this.particles[b],pe=Math.sqrt(k(0,1)),me=k(0,1),ge=z.add(O.scale(pe)).add(I.scale(pe*me)),s&&(be=e.getFacetNormal(r).normalize().scale(-1),ye=O.clone().normalize(),Me=u.Cross(be,ye),Se=k(0,2*Math.PI),ve=ye.scale(Math.cos(Se)).add(Me.scale(Math.sin(Se))),Se=k(.1,Math.PI/2),qe=ve.scale(Math.cos(Se)).add(be.scale(Math.sin(Se))),Ce.origin=ge.add(qe.scale(1e-5)),Ce.direction=qe,Ce.length=d,Ae=Ce.intersectsMesh(e),Ae.hit&&(Re=Ae.pickedPoint.subtract(ge).length(),we=k(0,1)*Re,ge.addInPlace(qe.scale(we)))),ze.position=ge.clone(),this._positions.push(ze.position.x,ze.position.y,ze.position.z),void 0!==i?p&&(xe=H.add(Q.scale(pe)).add($.scale(pe*me)),i?o&&null!==t._groupImageData?(c=t._groupImgWidth,g=t._groupImgHeight,Pe=this._getColorIndicesForCoord(t,Math.round(xe.x*c),Math.round(xe.y*g),c),ze.color=Pe,this._colors.push(Pe.r,Pe.g,Pe.b,Pe.a)):m?(Te=ce.add(_e.scale(pe)).add(fe.scale(pe*me)),ze.color=new a(Te.x,Te.y,Te.z,Te.w),this._colors.push(Te.x,Te.y,Te.z,Te.w)):(Te=ce.set(Math.random(),Math.random(),Math.random(),1),ze.color=new a(Te.x,Te.y,Te.z,Te.w),this._colors.push(Te.x,Te.y,Te.z,Te.w)):(ze.uv=xe.clone(),this._uvs.push(ze.uv.x,ze.uv.y))):(l?(Le.set(l.r,l.g,l.b),x=k(-h,h),y=k(-h,h),ke=Le.toHSV(),A=ke.r,V=ke.g+x,De=ke.b+y,V<0&&(V=0),V>1&&(V=1),De<0&&(De=0),De>1&&(De=1),n.HSVtoRGBToRef(A,V,De,Fe),Te.set(Fe.r,Fe.g,Fe.b,1)):Te=ce.set(Math.random(),Math.random(),Math.random(),1),ze.color=new a(Te.x,Te.y,Te.z,Te.w),this._colors.push(Te.x,Te.y,Te.z,Te.w))}}_colorFromTexture(e,t,s){if(null===e.material)return d.Warn(e.name+"has no material."),t._groupImageData=null,void this._setPointsColorOrUV(e,t,s,!0,!1);const i=e.material.getActiveTextures();if(0===i.length)return d.Warn(e.name+"has no usable texture."),t._groupImageData=null,void this._setPointsColorOrUV(e,t,s,!0,!1);const n=e.clone();n.setEnabled(!1),this._promises.push(new Promise(e=>{L.WhenAllReady(i,()=>{let a=t._textureNb;a<0&&(a=0),a>i.length-1&&(a=i.length-1);const o=()=>{t._groupImgWidth=i[a].getSize().width,t._groupImgHeight=i[a].getSize().height,this._setPointsColorOrUV(n,t,s,!0,!0,void 0,void 0,i[a].coordinatesIndex),n.dispose(),e()};t._groupImageData=null;const r=i[a].readPixels();r?r.then(e=>{t._groupImageData=e,o()}):o()})}))}_calculateDensity(e,t,s){let i,n,a,o,r,l,h,c,d,_,f,p;const m=u.Zero(),g=u.Zero(),x=u.Zero(),b=u.Zero(),y=u.Zero(),M=u.Zero();let S;const v=[];let w=0;const R=s.length/3;for(let e=0;e<R;e++)i=s[3*e],n=s[3*e+1],a=s[3*e+2],o=t[3*i],r=t[3*i+1],l=t[3*i+2],h=t[3*n],c=t[3*n+1],d=t[3*n+2],_=t[3*a],f=t[3*a+1],p=t[3*a+2],m.set(o,r,l),g.set(h,c,d),x.set(_,f,p),g.subtractToRef(m,b),x.subtractToRef(g,y),u.CrossToRef(b,y,M),S=.5*M.length(),w+=S,v[e]=w;const T=new Array(R);let C=e;for(let e=R-1;e>0;e--){const t=v[e];if(0===t)T[e]=0;else{const s=(t-v[e-1])/t*C,i=Math.floor(s),n=s-i,a=i+Number(Math.random()<n);T[e]=a,C-=a}}return T[0]=C,T}addPoints(e,t=this._randomUnitVector){const s=new Se(this._groupCounter,t);let i,n=this.nbParticles;for(let t=0;t<e;t++)i=this._addParticle(n,s,this._groupCounter,t),s&&s._positionFunction&&s._positionFunction(i,n,t),this._positions.push(i.position.x,i.position.y,i.position.z),i.color&&this._colors.push(i.color.r,i.color.g,i.color.b,i.color.a),i.uv&&this._uvs.push(i.uv.x,i.uv.y),n++;return this.nbParticles+=e,this._groupCounter++,this._groupCounter}addSurfacePoints(e,t,s,i,n){let o=s||0;(isNaN(o)||o<0||o>3)&&(o=0);const l=e.getVerticesData(r.PositionKind),h=e.getIndices();this._groups.push(this._groupCounter);const c=new Se(this._groupCounter,null);switch(c._groupDensity=this._calculateDensity(t,l,h),2===o?c._textureNb=i||0:i=i||new a(1,1,1,1),o){case 2:this._colorFromTexture(e,c,!1);break;case 1:this._setPointsColorOrUV(e,c,!1,!1,!1);break;case 0:this._setPointsColorOrUV(e,c,!1);break;case 3:this._setPointsColorOrUV(e,c,!1,void 0,void 0,i,n)}return this.nbParticles+=t,this._groupCounter++,this._groupCounter-1}addVolumePoints(e,t,s,i,n){let o=s||0;(isNaN(o)||o<0||o>3)&&(o=0);const l=e.getVerticesData(r.PositionKind),h=e.getIndices();this._groups.push(this._groupCounter);const c=new Se(this._groupCounter,null);switch(c._groupDensity=this._calculateDensity(t,l,h),2===o?c._textureNb=i||0:i=i||new a(1,1,1,1),o){case 2:this._colorFromTexture(e,c,!0);break;case 1:this._setPointsColorOrUV(e,c,!0,!1,!1);break;case 0:this._setPointsColorOrUV(e,c,!0);break;case 3:this._setPointsColorOrUV(e,c,!0,void 0,void 0,i,n)}return this.nbParticles+=t,this._groupCounter++,this._groupCounter-1}setParticles(e=0,t=this.nbParticles-1,s=!0){if(!this._updatable||!this._isReady)return this;this.beforeUpdateParticles(e,t,s);const i=q.Matrix[0],n=this.mesh,a=this._colors32,o=this._positions32,l=this._uvs32,h=q.Vector3,c=h[5].copyFromFloats(1,0,0),u=h[6].copyFromFloats(0,1,0),d=h[7].copyFromFloats(0,0,1),_=h[8].setAll(Number.MAX_VALUE),f=h[9].setAll(-Number.MAX_VALUE);let p,m,g,x;if(v.IdentityToRef(i),this.mesh?.isFacetDataEnabled&&(this._computeBoundingBox=!0),t=t>=this.nbParticles?this.nbParticles-1:t,this._computeBoundingBox&&(0!=e||t!=this.nbParticles-1)){const e=this.mesh?.getBoundingInfo();e&&(_.copyFrom(e.minimum),f.copyFrom(e.maximum))}for(let s=e;s<=t;s++){const e=this.particles[s];p=e.idx,m=3*p,g=4*p,x=2*p,this.updateParticle(e);const t=e._rotationMatrix,n=e.position,a=e._globalPosition;this._computeParticleRotation&&e.getRotationMatrix(i);if(null!==e.parentId){const s=this.particles[e.parentId],o=s._rotationMatrix,r=s._globalPosition,l=n.x*o[1]+n.y*o[4]+n.z*o[7],h=n.x*o[0]+n.y*o[3]+n.z*o[6],c=n.x*o[2]+n.y*o[5]+n.z*o[8];if(a.x=r.x+h,a.y=r.y+l,a.z=r.z+c,this._computeParticleRotation){const e=i.m;t[0]=e[0]*o[0]+e[1]*o[3]+e[2]*o[6],t[1]=e[0]*o[1]+e[1]*o[4]+e[2]*o[7],t[2]=e[0]*o[2]+e[1]*o[5]+e[2]*o[8],t[3]=e[4]*o[0]+e[5]*o[3]+e[6]*o[6],t[4]=e[4]*o[1]+e[5]*o[4]+e[6]*o[7],t[5]=e[4]*o[2]+e[5]*o[5]+e[6]*o[8],t[6]=e[8]*o[0]+e[9]*o[3]+e[10]*o[6],t[7]=e[8]*o[1]+e[9]*o[4]+e[10]*o[7],t[8]=e[8]*o[2]+e[9]*o[5]+e[10]*o[8]}}else if(a.x=0,a.y=0,a.z=0,this._computeParticleRotation){const e=i.m;t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[4],t[4]=e[5],t[5]=e[6],t[6]=e[8],t[7]=e[9],t[8]=e[10]}const r=h[11];e.translateFromPivot?r.setAll(0):r.copyFrom(e.pivot);const l=h[0];l.copyFrom(e.position);const b=l.x-e.pivot.x,y=l.y-e.pivot.y,M=l.z-e.pivot.z;let S=b*t[0]+y*t[3]+M*t[6],v=b*t[1]+y*t[4]+M*t[7],w=b*t[2]+y*t[5]+M*t[8];S+=r.x,v+=r.y,w+=r.z;const R=o[m]=a.x+c.x*S+u.x*v+d.x*w,T=o[m+1]=a.y+c.y*S+u.y*v+d.y*w,C=o[m+2]=a.z+c.z*S+u.z*v+d.z*w;if(this._computeBoundingBox&&(_.minimizeInPlaceFromFloats(R,T,C),f.maximizeInPlaceFromFloats(R,T,C)),this._computeParticleColor&&e.color){const t=e.color,s=this._colors32;s[g]=t.r,s[g+1]=t.g,s[g+2]=t.b,s[g+3]=t.a}if(this._computeParticleTexture&&e.uv){const t=e.uv,s=this._uvs32;s[x]=t.x,s[x+1]=t.y}}return n&&(s&&(this._computeParticleColor&&n.updateVerticesData(r.ColorKind,a,!1,!1),this._computeParticleTexture&&n.updateVerticesData(r.UVKind,l,!1,!1),n.updateVerticesData(r.PositionKind,o,!1,!1)),this._computeBoundingBox&&(n.hasBoundingInfo?n.getBoundingInfo().reConstruct(_,f,n._worldMatrix):n.buildBoundingInfo(_,f,n._worldMatrix))),this.afterUpdateParticles(e,t,s),this}dispose(){this.mesh?.dispose(),this.vars=null,this._positions=null,this._indices=null,this._normals=null,this._uvs=null,this._colors=null,this._indices32=null,this._positions32=null,this._uvs32=null,this._colors32=null}refreshVisibleSize(){return this._isVisibilityBoxLocked||this.mesh?.refreshBoundingInfo(),this}setVisibilityBox(e){if(!this.mesh)return;const t=e/2;this.mesh.buildBoundingInfo(new u(-t,-t,-t),new u(t,t,t))}get isAlwaysVisible(){return this._alwaysVisible}set isAlwaysVisible(e){this.mesh&&(this._alwaysVisible=e,this.mesh.alwaysSelectAsActiveMesh=e)}set computeParticleRotation(e){this._computeParticleRotation=e}set computeParticleColor(e){this._computeParticleColor=e}set computeParticleTexture(e){this._computeParticleTexture=e}get computeParticleColor(){return this._computeParticleColor}get computeParticleTexture(){return this._computeParticleTexture}set computeBoundingBox(e){this._computeBoundingBox=e}get computeBoundingBox(){return this._computeBoundingBox}initParticles(){}recycleParticle(e){return e}updateParticle(e){return e}beforeUpdateParticles(e,t,s){}afterUpdateParticles(e,t,s){}}let Re=0;const Te=.28209479177387814;let Ce=null,Ae=null;async function qe(e){if(Ce&&Ae===e)return await Ce;const t=async function(e,t){return await new Promise((s,i)=>{let n,a;if(F())n=window,a="window";else{if("undefined"==typeof self)return void i(new Error("Cannot load script module outside of a window or a worker"));n=self,a="self"}n._LoadScriptModuleResolve||(n._LoadScriptModuleResolve={}),n._LoadScriptModuleResolve[Re]=s,e+=`\n ${a}._LoadScriptModuleResolve[${Re}](returnedValue);\n ${a}._LoadScriptModuleResolve[${Re}] = undefined;\n `,Re++,x.LoadScript(e,void 0,(e,t)=>{i(t||new Error(e))},t,!0)})}(`import createSpzModule from '${e}';\n const module = await createSpzModule();\n const returnedValue = module;`);return Ae=e,Ce=t,await t}async function De(e,t){return await P(function*(e,t,s=!1){const i=e.numPoints,n=new ArrayBuffer(32*i),a=new Float32Array(n),o=new Uint8Array(n),r=e.positions,l=e.scales,h=e.colors,c=e.alphas,u=e.rotations;let d=null;const _=e.shDegree;let f,p,m=null,x=0,b=null,y=null,M=null;if(_>0&&e.sh.length>0){x=3*((_+1)*(_+1)-1);const s=Math.ceil(x/16),n=t.getEngine().getCaps().maxTextureSize,a=Math.ceil(i/n);d=g(s,a*n*4*4),b=new Int32Array(s),y=new Int32Array(s);for(let e=0;e<s;e++)b[e]=16*e,y[e]=Math.min(16*(e+1),x);M=d,m=e.sh}for(let e=0;e<i;e++){const t=8*e,i=32*e,n=3*e,d=4*e;a[t+0]=r[n+0],a[t+1]=r[n+1],a[t+2]=r[n+2],a[t+3]=Math.exp(l[n+0]),a[t+4]=Math.exp(l[n+1]),a[t+5]=Math.exp(l[n+2]);const _=255*(.5+Te*h[n+0]),f=255*(.5+Te*h[n+1]),p=255*(.5+Te*h[n+2]);o[i+24]=_<=0?0:_>=255?255:_+.5|0,o[i+25]=f<=0?0:f>=255?255:f+.5|0,o[i+26]=p<=0?0:p>=255?255:p+.5|0,o[i+27]=1/(1+Math.exp(-c[e]))*255+.5|0;const g=127.5*u[d+3]+127.5,S=127.5*u[d+0]+127.5,v=127.5*u[d+1]+127.5,w=127.5*u[d+2]+127.5;if(o[i+28]=g<=0?0:g>=255?255:g+.5|0,o[i+29]=S<=0?0:S>=255?255:S+.5|0,o[i+30]=v<=0?0:v>=255?255:v+.5|0,o[i+31]=w<=0?0:w>=255?255:w+.5|0,m&&M&&b&&y){const t=e*x,s=16*e;for(let e=0;e<M.length;e++){const i=M[e],n=b[e],a=y[e];for(let e=n;e<a;e++){const a=128*m[t+e]+128;i[s+e-n]=a<=0?0:a>=255?255:a+.5|0}}}e%32768==0&&s&&(yield)}if(e.extensions)for(const t of e.extensions){const e=t;if(void 0!==e.safeOrbitRadiusMin){f=e.safeOrbitRadiusMin,p=[e.safeOrbitElevationMin,e.safeOrbitElevationMax];break}}return{mode:0,data:n,hasVertexColors:!1,sh:null!==d?d:void 0,shDegree:_>0?_:void 0,trainedWithAntialiasing:!!e.antialiased,safeOrbitCameraRadiusMin:f,safeOrbitCameraElevationMinMax:p}}(e,t,!0),z())}class ke{constructor(e={}){this.name=E.name,this._assetContainer=null,this.extensions=E.extensions,this._loadingOptions={...ke._DefaultLoadingOptions,...e}}createPlugin(e){return new ke(e[E.name])}async importMeshAsync(e,t,s,i,n,a){const o=this._tryCreateLODStream(t,s,i);return o?{meshes:[o],particleSystems:[],skeletons:[],animationGroups:[],transformNodes:[],geometries:[],lights:[],spriteManagers:[]}:await this._parseAsync(e,t,s,i).then(e=>({meshes:e,particleSystems:[],skeletons:[],animationGroups:[],transformNodes:[],geometries:[],lights:[],spriteManagers:[]}))}_tryCreateLODStream(e,t,s){if("string"!=typeof t)return null;let i;try{i=JSON.parse(t)}catch{return null}if(!ye.IsLODMetadata(i))return null;const n=e._blockEntityCollection;e._blockEntityCollection=!!this._assetContainer;try{const t=new ye("GaussianSplattingStream",i,s,e,{deflateURL:this._loadingOptions.deflateURL,fflate:this._loadingOptions.fflate});return t._parentContainer=this._assetContainer,t}finally{e._blockEntityCollection=n}}static _BuildPointCloud(e,t){if(!t.byteLength)return!1;const s=new Uint8Array(t),i=new Float32Array(t),n=s.length/32;return e.addPoints(n,function(e,t){const n=i[8*t+0],o=i[8*t+1],r=i[8*t+2];e.position=new u(n,o,r);const l=s[32*t+24+0]/255,h=s[32*t+24+1]/255,c=s[32*t+24+2]/255;e.color=new a(l,h,c,1)}),!0}static _BuildMesh(e,t){const s=new i("PLYMesh",e),n=new Uint8Array(t.data),a=new Float32Array(t.data),o=n.length/32,r=[],l=new c;for(let e=0;e<o;e++){const t=a[8*e+0],s=a[8*e+1],i=a[8*e+2];r.push(t,s,i)}if(t.hasVertexColors){const e=new Float32Array(4*o);for(let t=0;t<o;t++){const s=n[32*t+24+0]/255,i=n[32*t+24+1]/255,a=n[32*t+24+2]/255;e[4*t+0]=s,e[4*t+1]=i,e[4*t+2]=a,e[4*t+3]=1}l.colors=e}return l.positions=r,l.indices=t.faces,l.applyToMesh(s),s}async _unzipWithFFlateAsync(e){let t=this._loadingOptions.fflate;t||(void 0===window.fflate&&await x.LoadScriptAsync(this._loadingOptions.deflateURL??"https://unpkg.com/fflate/umd/index.js"),t=window.fflate);const{unzipSync:s}=t,i=s(e),n=new Map;for(const[e,t]of Object.entries(i))n.set(e,t);return n}_parseAsync(e,t,s,i){const n=[],a=e=>{t._blockEntityCollection=!!this._assetContainer;const s=this._loadingOptions.gaussianSplattingMesh??new M("GaussianSplatting",null,t,this._loadingOptions.keepInRam,this._loadingOptions.needsRotationScaleTextures);s._parentContainer=this._assetContainer,n.push(s),e.sogTextures?s.setSogTextureData(e.sogTextures):s.updateData(e.data,e.sh,{flipY:!1},void 0,e.shDegree),s.scaling.y*=-1,s.computeWorldMatrix(!0),s.safeOrbitCameraLimits=ke._ExtractSafeOrbitLimits(e),t._blockEntityCollection=!1},o=t.getEngine();let r=this._loadingOptions.useSogTextures;r&&!o.isWebGPU&&o.version<2&&(d.Warn("SPLATFileLoader: useSogTextures requires WebGL2 or WebGPU. Falling back to CPU path."),r=!1);const l=r?ie:J;if("string"==typeof s){const e=JSON.parse(s);if(e&&e.means&&e.scales&&e.quats&&e.sh0)return new Promise((s,o)=>{l(e,i,t).then(e=>{a(e),s(n)}).catch(e=>{o(new Error("Failed to parse SOG data.",{cause:e}))})})}const h=s instanceof ArrayBuffer?new Uint8Array(s):s;if(80===h[0]&&75===h[1])return new Promise((e,s)=>{this._unzipWithFFlateAsync(h).then(o=>{l(o,i,t).then(t=>{a(t),e(n)}).catch(e=>{s(new Error("Failed to parse SOG zip data.",{cause:e}))})})});const c=e=>{ke._ConvertPLYToSplat(s).then(async s=>{switch(t._blockEntityCollection=!!this._assetContainer,s.mode){case 0:{const e=this._loadingOptions.gaussianSplattingMesh??new M("GaussianSplatting",null,t,this._loadingOptions.keepInRam,this._loadingOptions.needsRotationScaleTextures);switch(e._parentContainer=this._assetContainer,n.push(e),e.updateData(s.data,s.sh,{flipY:!1},void 0,s.shDegree),e.scaling.y*=-1,"RightHanded"===s.chirality&&(e.scaling.y*=-1),s.upAxis){case"X":e.rotation=new u(0,0,Math.PI/2);break;case"Y":e.rotation=new u(0,0,Math.PI);break;case"Z":e.rotation=new u(-Math.PI/2,Math.PI,0)}e.computeWorldMatrix(!0),e.safeOrbitCameraLimits=ke._ExtractSafeOrbitLimits(s)}break;case 1:{const e=new we("PointCloud",1,t);ke._BuildPointCloud(e,s.data)?await e.buildMeshAsync().then(e=>{n.push(e)}):e.dispose()}break;case 2:if(!s.faces)throw new Error("PLY mesh doesn't contain face informations.");n.push(ke._BuildMesh(t,s));break;default:throw new Error("Unsupported Splat mode")}t._blockEntityCollection=!1,this.applyAutoCameraLimits(ke._ExtractSafeOrbitLimits(s),t),e(n)})},_=31===h[0]&&139===h[1],f=78===h[0]&&71===h[1]&&83===h[2]&&80===h[3];if(!_&&!f)return new Promise(e=>{c(e)});const p=(e,s)=>{t._blockEntityCollection=!!this._assetContainer;const i=this._loadingOptions.gaussianSplattingMesh??new M("GaussianSplatting",null,t,this._loadingOptions.keepInRam,this._loadingOptions.needsRotationScaleTextures);if(e.trainedWithAntialiasing){const e=i.material;e.kernelSize=.1,e.compensation=!0}i._parentContainer=this._assetContainer,n.push(i),i.updateData(e.data,e.sh,{flipY:!1},void 0,e.shDegree),this._loadingOptions.flipY||(i.scaling.y*=-1,i.computeWorldMatrix(!0)),t._blockEntityCollection=!1;const a=ke._ExtractSafeOrbitLimits(e);i.safeOrbitCameraLimits=a,this.applyAutoCameraLimits(a,t),s(n)};if(this._loadingOptions.spzLibraryUrl)return qe(this._loadingOptions.spzLibraryUrl).then(e=>De(e.loadSpzFromBuffer(new Uint8Array(s),{to:e.CoordinateSystem.RUB}),t).then(e=>new Promise(t=>{p(e,t)})));if(f)return Promise.reject(new Error("SPZ V4+ files (NGSP format) are not supported by the native fallback loader. Please provide a valid 'spzLibraryUrl' in the loading options to use the WASM-based SPZ library, or ensure WebAssembly is available in your environment."));const x=new ReadableStream({start(e){e.enqueue(new Uint8Array(s)),e.close()}}),b=new DecompressionStream("gzip"),y=x.pipeThrough(b);return new Promise(e=>{new Response(y).arrayBuffer().then(s=>{(function(e,t){const s=new Uint8Array(e),i=new Uint32Array(e.slice(0,12)),n=i[2],a=s[12],o=s[13],r=s[14],l=s[15],h=i[1];if(l||1347635022!=i[0]||h<2||h>4)return new Promise(e=>{e({mode:3,data:new ArrayBuffer(0),hasVertexColors:!1})});const c=new ArrayBuffer(32*n),u=1/(1<<o),d=new Int32Array(1),_=new Uint8Array(d.buffer),f=function(e,t){return _[0]=e[t+0],_[1]=e[t+1],_[2]=e[t+2],_[3]=128&e[t+2]?255:0,d[0]*u};let p=16;const x=new Float32Array(c),b=new Float32Array(c),y=new Uint8ClampedArray(c),M=new Uint8ClampedArray(c);for(let e=0;e<n;e++)x[8*e+0]=f(s,p+0),x[8*e+1]=f(s,p+3),x[8*e+2]=f(s,p+6),p+=9;for(let e=0;e<n;e++){for(let t=0;t<3;t++){const i=(s[p+n+3*e+t]-127.5)/38.25;y[32*e+24+t]=m.Clamp(255*(.5+Te*i),0,255)}y[32*e+24+3]=s[p+e]}p+=4*n;for(let e=0;e<n;e++)b[8*e+3+0]=Math.exp(s[p+0]/16-10),b[8*e+3+1]=Math.exp(s[p+1]/16-10),b[8*e+3+2]=Math.exp(s[p+2]/16-10),p+=3;if(h>=3){const e=Math.SQRT1_2;for(let t=0;t<n;t++){const i=[s[p+0],s[p+1],s[p+2],s[p+3]],n=i[0]+(i[1]<<8)+(i[2]<<16)+(i[3]<<24),a=511,o=[],r=n>>>30;let l=n,h=0;for(let t=3;t>=0;--t)if(t!==r){const s=l&a,i=l>>>9&1;l>>>=10,o[t]=e*(s/a),1===i&&(o[t]=-o[t]),h+=o[t]*o[t]}const c=1-h;o[r]=Math.sqrt(Math.max(c,0));const u=[3,0,1,2];for(let e=0;e<4;e++)M[32*t+28+e]=Math.round(127.5+127.5*o[u[e]]);p+=4}}else for(let e=0;e<n;e++){const t=s[p+0],i=s[p+1],n=s[p+2],a=t/127.5-1,o=i/127.5-1,r=n/127.5-1;M[32*e+28+1]=t,M[32*e+28+2]=i,M[32*e+28+3]=n;const l=1-(a*a+o*o+r*r);M[32*e+28+0]=127.5+127.5*Math.sqrt(l<0?0:l),p+=3}if(a){const e=3*((a+1)*(a+1)-1),i=Math.ceil(e/16);let o=p;const l=t.getEngine().getCaps().maxTextureSize,h=Math.ceil(n/l),u=g(i,h*l*4*4);for(let t=0;t<n;t++)for(let i=0;i<e;i++){const e=s[o++],n=Math.floor(i/16);u[n][i%16+16*t]=e}return new Promise(e=>{e({mode:0,data:c,hasVertexColors:!1,sh:u,shDegree:a,trainedWithAntialiasing:!!r})})}return new Promise(e=>{e({mode:0,data:c,hasVertexColors:!1,trainedWithAntialiasing:!!r})})})(s,t,this._loadingOptions).then(t=>{p(t,e)})}).catch(()=>{c(e)})})}static _ExtractSafeOrbitLimits(e){return void 0===e.safeOrbitCameraRadiusMin&&void 0===e.safeOrbitCameraElevationMinMax?null:{radiusMin:e.safeOrbitCameraRadiusMin,elevationMinMax:e.safeOrbitCameraElevationMinMax}}applyAutoCameraLimits(e,t){if(!this._loadingOptions.disableAutoCameraLimits&&e&&"ArcRotateCamera"===t.activeCamera?.getClassName()){const s=t.activeCamera;e.elevationMinMax&&(s.lowerBetaLimit=.5*Math.PI-e.elevationMinMax[1],s.upperBetaLimit=.5*Math.PI-e.elevationMinMax[0]),e.radiusMin&&(s.lowerRadiusLimit=e.radiusMin)}}loadAssetContainerAsync(e,t,s){const i=new N(e);return this._assetContainer=i,this.importMeshAsync(null,e,t,s).then(e=>{for(const t of e.meshes)i.meshes.push(t);return this._assetContainer=null,i}).catch(e=>{throw this._assetContainer=null,e})}loadAsync(e,t,s){return this.importMeshAsync(null,e,t,s).then(()=>{})}static _ConvertPLYToSplat(e){const t=new Uint8Array(e),s=(new TextDecoder).decode(t.slice(0,10240)),i="end_header\n",n=s.indexOf(i);if(n<0||!s)return new Promise(t=>{t({mode:0,data:e,rawSplat:!0})});const a=parseInt(/element vertex (\d+)\n/.exec(s)[1]),o=/element face (\d+)\n/.exec(s);let r=0;o&&(r=parseInt(o[1]));const l=/element chunk (\d+)\n/.exec(s);let h=0;l&&(h=parseInt(l[1]));let c=0,u=0;const _={double:8,int:4,uint:4,float:4,short:2,ushort:2,uint16:2,uchar:1,list:0},f=0,p=1,m=2,g=3,x=4,b=5;let y=p;const S=[],v=s.slice(0,n).split("\n"),w={};for(const t of v)if(t.startsWith("property ")){const[,s,i]=t.split(" ");if(y==p)u+=_[s];else if(y==f)S.push({name:i,type:s,offset:c}),c+=_[s];else if(y==m)S.push({name:i,type:s,offset:c});else if(y==g){const t=new DataView(e,u,2*_.float);w.safeOrbitCameraElevationMinMax=[t.getFloat32(0,!0),t.getFloat32(4,!0)]}else if(y==x){const t=new DataView(e,u,_.float);w.safeOrbitCameraRadiusMin=t.getFloat32(0,!0)}else if(y==b){const t=new DataView(e,u,_.uchar);"up_axis"==i?w.upAxis=0==t.getUint8(0)?"X":1==t.getUint8(0)?"Y":"Z":"chirality"==i&&(w.chirality=0==t.getUint8(0)?"LeftHanded":"RightHanded")}_[s]||d.Warn(`Unsupported property type: ${s}.`)}else if(t.startsWith("element ")){const[,e]=t.split(" ");"chunk"==e?y=p:"vertex"==e?y=f:"sh"==e?y=m:"safe_orbit_camera_elevation_min_max_radians"==e?y=g:"safe_orbit_camera_radius_min"==e?y=x:"up_axis"!=e&&"chirality"!=e||(y=b)}const R=c,T=u;return M.ConvertPLYWithSHToSplatAsync(e).then(async t=>{const s=new DataView(e,n+11);let i=T*h+R*a;const o=[];if(r)for(let e=0;e<r;e++){const e=s.getUint8(i);if(3==e){i+=1;for(let t=0;t<e;t++){const e=s.getUint32(i+4*(2-t),!0);o.push(e)}i+=12}}if(h)return await new Promise(e=>{e({mode:0,data:t.buffer,sh:t.sh,shDegree:t.shDegree,faces:o,hasVertexColors:!1,compressed:!0,rawSplat:!1})});let l=0,c=0;const u=["x","y","z","scale_0","scale_1","scale_2","opacity","rot_0","rot_1","rot_2","rot_3"],d=["red","green","blue","f_dc_0","f_dc_1","f_dc_2"];for(let e=0;e<S.length;e++){const t=S[e];u.includes(t.name)&&l++,d.includes(t.name)&&c++}const _=l==u.length&&c>=3,f=r?2:_?0:1;return await new Promise(e=>{e({...w,mode:f,data:t.buffer,sh:t.sh,shDegree:t.shDegree,faces:o,hasVertexColors:!!c,compressed:!1,rawSplat:!1})})})}}ke._DefaultLoadingOptions={keepInRam:!1,flipY:!1,needsRotationScaleTextures:!1,spzLibraryUrl:"object"==typeof WebAssembly?"https://unpkg.com/@adobe/spz@0.2.2/dist/spz.js":void 0};let Le=!1;function Fe(){Le||(Le=!0,B(new ke))}let Pe=!1;Pe||(Pe=!0,O.prototype.createDynamicTexture=function(e,t,s,i){const n=new I(this,4);return n.baseWidth=e,n.baseHeight=t,s&&(e=this.needPOTTextures?U(e,this._caps.maxTextureSize):e,t=this.needPOTTextures?U(t,this._caps.maxTextureSize):t),n.width=e,n.height=t,n.isReady=!1,n.generateMipMaps=s,n.samplingMode=i,this.updateTextureSamplingMode(i,n),this._internalTexturesCache.push(n),n},O.prototype.updateDynamicTexture=function(e,t,s,i=!1,n,a=!1,o=!1){if(!e)return;const r=this._gl,l=r.TEXTURE_2D,h=this._bindTextureDirectly(l,e,!0,a);this._unpackFlipY(void 0===s?e.invertY:s),i&&r.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,1);const c=this._getWebGLTextureType(e.type),u=this._getInternalFormat(n||e.format),d=this._getRGBABufferInternalSizedFormat(e.type,u);r.texImage2D(l,0,d,u,c,t),e.generateMipMaps&&r.generateMipmap(l),h||this._bindTextureDirectly(l,null),i&&r.pixelStorei(r.UNPACK_PREMULTIPLY_ALPHA_WEBGL,0),n&&(e.format=n),e._dynamicTextureSource=t,e._premulAlpha=i,e.invertY=s||!1,e.isReady=!0}),Fe();export{Fe as RegisterSPLATFileLoader,ke as SPLATFileLoader};
//# sourceMappingURL=splatFileLoader-BjgGRBfE.esm.min.js.map