@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.
1 lines • 92.6 kB
JavaScript
import{cq as e,cr as t,cs as s,aV as i,i as n,b1 as o,c as a,a7 as r,F as l,aE as c,aW as h,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 y,bc as b,bq as w,cv as M,M as v,aU as S,bl as A,cw as T,b3 as C,T as F,aD as L,a as R,ca as D,p as P,ci as E,cx as k,cy as z,cz as q,bn as O,cA as B,w as I,cB as U}from"./index-BPURObVq.esm.min.js";import"./thinInstanceMesh-DOdJ7Zhn.esm.min.js";import"./tools-BGvNItez.esm.min.js";import{I as N,A as V}from"./assetContainer-CAncviZo.esm.min.js";import"./buffer-COJ0NvoM.esm.min.js";import"./shaderMaterial-CP03kcvR.esm.min.js";import{R as W}from"./ray.core-GrAvg8d_.esm.min.js";import{S as G}from"./standardMaterial.pure-BRp0YAN-.esm.min.js";import"./prepass.defines-DBIG3K_p.esm.min.js";import"./material.detailMapConfiguration-FEC73qwc.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,c,h,u){super(e,t,s,i,l),this.useVertexColor=c,this.useVertexAlpha=h,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 o),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-G5oo_PwN.esm.min.js"),import("./color.fragment-qKgvlunb.esm.min.js")]):await Promise.all([import("./color.vertex-TB6WGJxf.esm.min.js"),import("./color.fragment-CiaeUu3f.esm.min.js")])};const e=new a("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 N{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,o=[];let a=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:c,z:h}=r[i];if(s.push(l,c,h),n){const t=n[e],{r:s,g:a,b:r,a:l}=t[i];o.push(s,a,r,l)}i>0&&(t.push(a-1),t.push(a)),a++}}const r=new h;return r.indices=t,r.positions=s,n&&(r.colors=o),r}function Z(e){const t=e.dashSize||3,s=e.gapSize||1,i=e.dashNb||200,n=e.points,o=[],a=[],r=u.Zero();let l,c,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++)c=p*e,o.push(n[d].x+c*r.x,n[d].y+c*r.y,n[d].z+c*r.z),o.push(n[d].x+(c+m)*r.x,n[d].y+(c+m)*r.y,n[d].z+(c+m)*r.z),a.push(f,f+1),f+=2}const g=new h;return g.positions=o,g.indices=a,g}function Y(e,t,s=null){const i=t.instance,n=t.lines,o=t.colors;if(i){const e=i.getVerticesData(r.PositionKind);let t,s;o&&(t=i.getVerticesData(r.ColorKind));let a=0,l=0;for(let i=0;i<n.length;i++){const r=n[i];for(let n=0;n<r.length;n++)e[a]=r[n].x,e[a+1]=r[n].y,e[a+2]=r[n].z,o&&t&&(s=o[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),a+=3}return i.updateVerticesData(r.PositionKind,e,!1,!1),o&&t&&i.updateVerticesData(r.ColorKind,t,!1,!1),i.refreshBoundingInfo(),i}const a=new X(e,s,null,void 0,void 0,!!o,t.useVertexAlpha,t.material);return H(t).applyToMesh(a,t.updatable),a}X.prototype.enableEdgesRendering??=c("LinesMesh","enableEdgesRendering"),j.prototype.enableEdgesRendering??=c("InstancedLinesMesh","enableEdgesRendering");let Q=!1;Q||(Q=!0,h.CreateLineSystem=H,h.CreateDashedLines=Z,i.CreateLines=(e,t,s=null,i=!1,n=null)=>function(e,t,s=null){const i=t.colors?[t.colors]:null;return Y(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,o=null,a,r)=>function(e,t,s=null){const i=t.points,n=t.instance,o=t.gapSize||1,a=t.dashSize||3;if(n){const e=e=>{const t=u.Zero(),s=e.length/6;let o,a,r,l,c=0,h=0;for(r=0;r<i.length-1;r++)i[r+1].subtractToRef(i[r],t),c+=t.length();const d=c/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),o=Math.floor(t.length()/d),t.normalize(),l=0;l<o&&h<e.length;)a=d*l,e[h]=i[r].x+a*t.x,e[h+1]=i[r].y+a*t.y,e[h+2]=i[r].z+a*t.z,e[h+3]=i[r].x+(a+f)*t.x,e[h+4]=i[r].y+(a+f)*t.y,e[h+5]=i[r].z+(a+f)*t.z,h+=6,l++;for(;h<e.length;)e[h]=i[r].x,e[h+1]=i[r].y,e[h+2]=i[r].z,h+=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 Z(t).applyToMesh(r,t.updatable),r._creationDataStorage=new _,r._creationDataStorage.dashSize=a,r._creationDataStorage.gapSize=o,r}(e,{points:t,dashSize:s,gapSize:i,dashNb:n,updatable:a,instance:r},o));const K=.28209479177387814;async function $(e,t,s){const i=new Promise((i,n)=>{const o=s.createCanvasImage();if(!o)throw new Error("Failed to create ImageBitmap");let a;if(o.onload=()=>{try{const e=s.createCanvas(o.width,o.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(o,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 ${o.src} with exception: ${e}`)}},o.onerror=e=>{n(`Error loading image ${o.src} with exception: ${e}`)},o.crossOrigin="anonymous","string"==typeof e){if(!t)throw new Error("filename is required when using a URL");o.src=e+t}else{const t=new Blob([e],{type:"image/webp"});a=URL.createObjectURL(t),o.src=a}});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 o=[...i.means.files,...i.scales.files,...i.quats.files,...i.sh0.files];i.shN&&o.push(...i.shN.files);const a=await Promise.all(o.map(async e=>{if(n&&n.has(e)){const t=n.get(e);return await $(t,e,s.getEngine())}return await $(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),o=new Float32Array(n),a=new Float32Array(n),r=new Uint8ClampedArray(n),l=new Uint8ClampedArray(n),c=e=>Math.sign(e)*(Math.exp(Math.abs(e))-1),h=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],a=e.means.maxs[i],r=u[s+i]<<8|h[s+i],l=m.Lerp(n,a,r/65535);o[8*t+i]=c(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]],o=Math.exp(n);a[8*t+3+i]=o}}}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],o=m.Lerp(e.scales.mins[i],e.scales.maxs[i],n/255),r=Math.exp(o);a[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]]*K;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],o=e.sh0.maxs[i],a=_[s+i],l=m.Lerp(n,o,a/255);let c;c=i<3?.5+l*K:1/(1+Math.exp(-l)),r[32*t+24+i]=Math.max(0,Math.min(255,Math.round(255*c)))}}}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],o=f(t),a=f(s),r=f(i),c=n-252,h=o*o+a*a+r*r,u=Math.sqrt(Math.max(0,1-h));let d;switch(c){case 0:d=[u,o,a,r];break;case 1:d=[o,u,a,r];break;case 2:d=[o,a,u,r];break;case 3:d=[o,a,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 o=e.shN.bands?(e.shN.bands+1)**2-1:e.shN.shape[1]/3,a=void 0!==e.shN.bands&&null!==e.shN.bands?e.shN.bands:Math.round(Math.sqrt(o+1)-1),r=t[5].bits,l=t[6].bits,c=t[5].width,h=3*o,u=Math.ceil(h/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*o,n=Math.floor(s/64);for(let s=0;s<o;s++)for(let o=0;o<3;o++){const a=3*s+o,l=Math.floor(a/16),h=f[l],u=a%16,d=16*t,_=127.5*e.shN.codebook[r[4*(i+s)+o+n*c*4]]+127.5;h[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*o,n=Math.floor(s/64),a=e.shN.mins,h=e.shN.maxs;for(let e=0;e<3;e++)for(let s=0;s<o/3;s++){const o=3*s+e,l=Math.floor(o/16),u=f[l],d=o%16,_=16*t,p=127.5*m.Lerp(a,h,r[4*(i+s)+e+n*c*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:a})})}return await new Promise(e=>{e({mode:0,data:n,hasVertexColors:!1})})}(i,a,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 o;if("string"==typeof e){const s=await x.LoadFileAsync(e+t,!0);o=new Blob([s],{type:n})}else o=new Blob([e],{type:n});const a=await createImageBitmap(o,{premultiplyAlpha:"none",colorSpaceConversion:"none"});try{const e=new f(null,a.width,a.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,a,!1,!1),e}finally{a.close()}}catch{}return ee(s,await $(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 o=new Float32Array(4*i);for(let a=0;a<i;a++){const i=4*a;for(let r=0;r<3;r++){const l=s[i+r]<<8|t[i+r],c=m.Lerp(e.means.mins[r],e.means.maxs[r],l/65535);o[4*a+r]=n(c)}o[4*a+3]=1}return o}async function ie(e,t,s,i=!0,n,o){let a,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");a=JSON.parse((new TextDecoder).decode(t))}else a=e;const l=async e=>{if(r&&r.has(e))return await $(r.get(e),e,s.getEngine());if(n){const i=new Uint8Array(await n.loadFileAsync(t+e,o));return await $(i,e,s.getEngine())}return await $(t,e,s.getEngine())},c=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,o));return await te(i,e,s)}return await te(t,e,s)},h=[...a.scales.files,...a.quats.files,...a.sh0.files,...a.shN?.files??[]];let u,d,_,m,g,x=null;if(i){const[e,t]=await Promise.all([Promise.all(a.means.files.map(l)),Promise.all(h.map(c))]);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(a.means.files.map(c)),Promise.all(h.map(c))]);g=t,u=e[0],d=e[1];const s=u.getSize();_=s.width,m=s.height}const y=a.count??a.means.shape[0],b=_*m;if(b<y)throw new Error(`SOG texture contains ${b} texels, but metadata references ${y} splats.`);const w=g[0],M=g[1],v=g[2];let S,A,T,C=0,F=0;if(a.shN&&g.length>=5&&(S=g[3],A=g[4],C=a.shN.bands?(a.shN.bands+1)**2-1:a.shN.shape[1]/3,F=a.shN.bands??Math.round(Math.sqrt(C+1)-1)),2===a.version){const e=256,t=new Float32Array(3*e);a.scales.codebook&&t.set(a.scales.codebook.slice(0,e),0),a.sh0.codebook&&t.set(a.sh0.codebook.slice(0,e),e),a.shN?.codebook&&t.set(a.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 L=a.means.mins,R=a.means.maxs,D={version:2===a.version?2:1,splatCount:y,shDegree:F,meansTextureL:u,meansTextureU:d,scalesTexture:w,quatsTexture:M,sh0Texture:v,shCentroidsTexture:S,shLabelsTexture:A,codebookTexture:T,meansMin:[L[0],L[1],L[2]],meansMax:[R[0],R[1],R[2]],scalesMin:Array.isArray(a.scales.mins)?[a.scales.mins[0],a.scales.mins[1],a.scales.mins[2]]:void 0,scalesMax:Array.isArray(a.scales.maxs)?[a.scales.maxs[0],a.scales.maxs[1],a.scales.maxs[2]]:void 0,sh0Min:Array.isArray(a.sh0.mins)?[a.sh0.mins[0],a.sh0.mins[1],a.sh0.mins[2],a.sh0.mins[3]]:void 0,sh0Max:Array.isArray(a.sh0.maxs)?[a.sh0.maxs[0],a.sh0.maxs[1],a.sh0.maxs[2],a.sh0.maxs[3]]:void 0,shnMin:"number"==typeof a.shN?.mins?a.shN.mins:void 0,shnMax:"number"==typeof a.shN?.maxs?a.shN.maxs:void 0,shCoeffCount:C,positions:x?se(a,x[0].bits,x[1].bits,y):new Float32Array(0)};return{mode:0,data:new ArrayBuffer(0),hasVertexColors:!1,shDegree:F,sogTextures:D}}const ne="precision highp float;\nattribute vec3 position;\nvoid main() {\n gl_Position = vec4(position.xy, 0.0, 1.0);\n}\n",oe="\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 ae{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}constructor(e,t){this._copyMaterial=null,this._relayoutMapData=null,this._relayoutMapTexture=null,this._disposed=!1,this._readFbo=null,this._scene=e,this._shaderLanguage=e.getEngine().isWebGPU?1:0,this._textureSize=Math.max(1,Math.ceil(Math.sqrt(Math.max(1,t)))),this._mrt=this._createMrt("gsWorkBuffer",!0),this._material=this._createMaterial(),this._quad=this._createQuad(),this._quad.material=this._material}_createMrt(e,t){const s=this._scene.getEngine()._caps.textureHalfFloatRender?p.TEXTURETYPE_HALF_FLOAT:p.TEXTURETYPE_FLOAT,i=new y(e,{width:this._textureSize,height:this._textureSize},4,this._scene,{types:[p.TEXTURETYPE_FLOAT,s,s,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 i.clearColor=new o(0,0,0,0),i.renderList=[],t&&i.onClearObservable.add(()=>{}),i}async decodeAsync(e,t){this._disposed||(this._applyPack(e,t),await new Promise(e=>{const t=()=>{this._disposed?e():this._material.isReady(this._quad)?(this._mrt.renderList=[this._quad],this._mrt.render(),e()):this._scene.onBeforeRenderObservable.addOnce(t)};this._scene.onBeforeRenderObservable.addOnce(t)}))}isRelayoutReady(){return!this._disposed&&(this._copyMaterial||(this._copyMaterial=this._createCopyMaterial()),this._copyMaterial.isReady(this._quad))}relayoutSync(e){if(this._disposed||!this._copyMaterial)return;const t=this._textureSize;this._relayoutMapData||(this._relayoutMapData=new Float32Array(t*t));const s=this._relayoutMapData;s.fill(-1),s.set(e.subarray(0,Math.min(e.length,s.length))),this._relayoutMapTexture?this._relayoutMapTexture.update(s):this._relayoutMapTexture=new f(s,t,t,p.TEXTUREFORMAT_R,this._scene,!1,!1,p.TEXTURE_NEAREST_SAMPLINGMODE,p.TEXTURETYPE_FLOAT);const i=this._relayoutMapTexture,n=this._createMrt("gsRelayoutTemp",!1);try{this._renderRelayoutPass(n,this._mrt.textures,i,1),this._renderRelayoutPass(this._mrt,n.textures,i,0)}finally{n.dispose(),this._quad.material=this._material}}_renderRelayoutPass(e,t,s,i){const n=this._copyMaterial;n.setTexture("uMapTex",s),n.setTexture("uSrc0",t[0]),n.setTexture("uSrc1",t[1]),n.setTexture("uSrc2",t[2]),n.setTexture("uSrc3",t[3]),n.setInt("uDstWidth",this._textureSize),n.setInt("uSrcWidth",this._textureSize),n.setInt("uUseMap",i),this._quad.material=n,e.renderList=[this._quad],e.render()}_createCopyMaterial(){const e=1===this._shaderLanguage,t=new a("gsWorkBufferRelayout",this._scene,{vertexSource:e?oe: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\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 = i32(m + 0.5);\n } else {\n srcIdx = p.y * 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\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 = int(m + 0.5);\n } else {\n srcIdx = p.y * 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"],samplers:["uMapTex","uSrc0","uSrc1","uSrc2","uSrc3"],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=Math.floor(e/s),n=Math.ceil((e+t)/s)-i,o=4*(e-i*s),a=o+4*t,r=this._mrt.textures[0],l=this._scene.getEngine();if(l.isWebGPU){const e=await r.readPixels(0,0,null,!0,!0,0,i,s,n);if(this._disposed||!e)return null;const t=e instanceof Float32Array?e:new Float32Array(e.buffer,e.byteOffset,e.byteLength/4);return t.length>=a?t.subarray(o,a):null}const c=l,h=c._gl,u=r.getInternalTexture()?._hardwareTexture?.underlyingResource;if(!u)return null;const d=new Float32Array(s*n*4);this._readFbo||(this._readFbo=h.createFramebuffer());const _=c._currentFramebuffer;h.bindFramebuffer(h.FRAMEBUFFER,this._readFbo),h.framebufferTexture2D(h.FRAMEBUFFER,h.COLOR_ATTACHMENT0,h.TEXTURE_2D,u,0),h.readBuffer(h.COLOR_ATTACHMENT0);const f=c._readPixelsAsync(0,i,s,n,h.RGBA,h.FLOAT,d);return h.bindFramebuffer(h.FRAMEBUFFER,_),_||h.readBuffer(h.BACK),f?(await f,this._disposed||d.length<a?null:d.subarray(o,a)):null}dispose(){this._disposed=!0,this._readFbo&&(this._scene.getEngine()._gl?.deleteFramebuffer(this._readFbo),this._readFbo=null),this._quad.dispose(),this._material.dispose(!0,!1),this._copyMaterial?.dispose(!0,!1),this._relayoutMapTexture?.dispose(),this._mrt.dispose()}_createQuad(){const e=new i("gsWorkBufferQuad",this._scene),t=new h;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 a("gsSogDecode",this._scene,{vertexSource:e?oe: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,t){const s=this._material,i=e.meansTextureL.getSize().width;s.setTexture("sogMeansLTex",e.meansTextureL),s.setTexture("sogMeansUTex",e.meansTextureU),s.setTexture("sogScalesTex",e.scalesTexture),s.setTexture("sogQuatsTex",e.quatsTexture),s.setTexture("sogSh0Tex",e.sh0Texture),s.setTexture("sogCodebookTex",e.codebookTexture??e.sh0Texture),s.setVector3("sogMeansMin",new u(e.meansMin[0],e.meansMin[1],e.meansMin[2])),s.setVector3("sogMeansMax",new u(e.meansMax[0],e.meansMax[1],e.meansMax[2]));const n=e.scalesMin??[0,0,0],o=e.scalesMax??[0,0,0];s.setVector3("sogScalesMin",new u(n[0],n[1],n[2])),s.setVector3("sogScalesMax",new u(o[0],o[1],o[2]));const a=e.sh0Min??[0,0,0,0],r=e.sh0Max??[0,0,0,0];s.setVector4("sogSh0Min",new b(a[0],a[1],a[2],a[3])),s.setVector4("sogSh0Max",new b(r[0],r[1],r[2],r[3])),s.setInt("uVersion",e.version),s.setInt("uOffset",t),s.setInt("uCount",e.splatCount),s.setInt("uDestWidth",this._textureSize),s.setInt("uSrcWidth",i)}}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 ce{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,o=Math.ceil(n*this._growMultiplier);o>this._capacity&&this.grow(o),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,o=n;i._offset=o._offset,o._offset=i._offset+i._size;const a=o._prev,r=i._next;if(i._prev=a,i._next=o,o._prev=i,o._next=r,a?a._next=i:this._headAll=i,r?r._prev=o:this._tailAll=o,o._next&&o._next._free){const e=o._next;o._size+=e._size,this._removeFromMainList(e),this._removeFromBucket(e),this._release(e),this._rebucket(o)}t.add(i),e++,n=o._next}else n=s}}_moveBlock(e,t){const s=e._size,i=t._offset,n=e._prev;this._removeFromMainList(e);const o=this._obtain(e._offset,s,!0);if(this._insertAfterInMainList(o,n),this._addToBucket(o),o._next&&o._next._free){const e=o._next;o._size+=e._size,this._removeFromMainList(e),this._removeFromBucket(e),this._release(e),this._rebucket(o)}if(o._prev&&o._prev._free){const e=o._prev;e._size+=o._size,this._removeFromMainList(o),this._removeFromBucket(o),this._release(o),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 he{constructor(e,t,s){this._blocks=new Map,this._cooldown=new Map,this._pinned=new Set,this._allocator=new ce(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,ye=[new o(1,.2,.2,1),new o(1,.6,.1,1),new o(1,1,.2,1),new o(.3,1,.3,1),new o(.2,1,1,1),new o(.4,.5,1,1),new o(.9,.4,1,1),new o(1,1,1,1)];class be extends w{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 M(0,0,0,0),new M(0,0,0,0),new M(0,0,0,0),new M(0,0,0,0),new M(0,0,0,0),new M(0,0,0,0)],this._cullViewProj=new v,this._workBuffer=null,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._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._metadata=t,this._rootUrl=s,this._streamOptions=n;const o=Math.max(0,t.lodLevels-1);this._lodRangeMax=o,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,o))),void 0!==n.lodRangeMax&&(this._lodRangeMax=Math.max(this._lodRangeMin,Math.min(n.lodRangeMax,o))),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)));let a=0;if(void 0!==n.maxResidentSplats&&n.maxResidentSplats>0&&(a=Math.floor(n.maxResidentSplats)),void 0!==n.memoryBudgetMb&&n.memoryBudgetMb>0){const e=Math.floor(1024*n.memoryBudgetMb*1024/84);a=a>0?Math.min(a,e):e}this._residentBudget=a,this._downloadManager=new re({maxConcurrent:n.maxConcurrentDownloads,maxRetries:n.maxDownloadRetries}),this.scaling.y*=-1,this.rotation.x=-Math.PI/2,this._collectLodEntries(t.tree),n.debugDisplay&&(this.debugDisplay=!0),this._streamAllAsync().catch(e=>{d.Error("GaussianSplattingStream: streaming failed: "+(e?.message??e))})}getClassName(){return"GaussianSplattingStream"}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._isDepthSortSettled?++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 o=s.getEngine(),a=globalThis.requestAnimationFrame;for(;!this._disposed;){if(o.beginFrame(),s.render(),o.endFrame(),n())return;await new Promise(e=>{"function"==typeof a?a(()=>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=!0,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)}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,o=this._lodRangeMin,a=this._lodRangeMax,r=this._scene.getEngine().getAspectRatio(e)||1;let l=Math.tan(.5*e.fov);e.fovMode===S.FOVMODE_HORIZONTAL_FIXED&&(l/=r);const c=l*r,h=Math.min(l,c)/ue;this.computeWorldMatrix(!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,c=(_<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,y=Math.sqrt(c*c+u*u+d*d);let b=y;if(n>1&&y>.01){const e=(m*c+g*u+x*d)/y;e<0&&(b=y*(1+-e*(n-1)))}const w=b*h;let M;if(0===t||w<s)M=0;else for(M=t;M>1&&w<s*Math.pow(i,M-1);)M--;M<o?M=o:M>a&&(M=a),this._frustumCulling&&!1===e.inFrustum&&(M=a),e.optimalLod=M}}_displayedLodLevel(e){return"optimal"===this._debugLodSource?e.optimalLod??e.activeLod??0:e.activeLod??0}_refreshDebugDisplay(){"optimal"===this._debugLodS