@speridlabs/visus 2.4.2 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.d.ts +120 -2
- package/dist/main.es.js +1163 -949
- package/dist/main.umd.js +80 -12
- package/dist/react.d.ts +10 -1
- package/dist/react.es.js +1092 -875
- package/package.json +1 -1
package/dist/main.umd.js
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
|
-
(function(
|
|
2
|
-
Please include <script src="https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.min.js"><\/script> before loading visus/main.umd.js`);function xt(a){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(a){for(const e in a)if(e!=="default"){const s=Object.getOwnPropertyDescriptor(a,e);Object.defineProperty(t,e,s.get?s:{enumerable:!0,get:()=>a[e]})}}return t.default=a,Object.freeze(t)}const l=xt(et);class gt{constructor(){x(this,"min",new l.Vector3(1/0,1/0,1/0));x(this,"max",new l.Vector3(-1/0,-1/0,-1/0));x(this,"center",new l.Vector3);x(this,"halfExtents",new l.Vector3)}reset(){this.min.set(1/0,1/0,1/0),this.max.set(-1/0,-1/0,-1/0),this.center.set(0,0,0),this.halfExtents.set(0,0,0)}expandByPoint(t){this.min.x=Math.min(this.min.x,t.x),this.min.y=Math.min(this.min.y,t.y),this.min.z=Math.min(this.min.z,t.z),this.max.x=Math.max(this.max.x,t.x),this.max.y=Math.max(this.max.y,t.y),this.max.z=Math.max(this.max.z,t.z),this.updateDerived()}expandByBox(t){this.min.x=Math.min(this.min.x,t.min.x),this.min.y=Math.min(this.min.y,t.min.y),this.min.z=Math.min(this.min.z,t.min.z),this.max.x=Math.max(this.max.x,t.max.x),this.max.y=Math.max(this.max.y,t.max.y),this.max.z=Math.max(this.max.z,t.max.z),this.updateDerived()}updateDerived(){this.center.addVectors(this.min,this.max).multiplyScalar(.5),this.halfExtents.subVectors(this.max,this.min).multiplyScalar(.5)}containsPoint(t){return t.x>=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.max.y&&t.z>=this.min.z&&t.z<=this.max.z}toBox3(){return new l.Box3().set(this.min,this.max)}clone(){const t=new gt;return t.min.copy(this.min),t.max.copy(this.max),t.center.copy(this.center),t.halfExtents.copy(this.halfExtents),t}}class Xt{constructor(t=0){x(this,"numSplats",0);x(this,"positions");x(this,"rotations");x(this,"scales");x(this,"colors");x(this,"opacities");x(this,"boundingBox",new gt);this.numSplats=t,this.allocateBuffers(t)}allocateBuffers(t){this.positions=new Float32Array(t*3),this.rotations=new Float32Array(t*4),this.scales=new Float32Array(t*3),this.colors=new Float32Array(t*3),this.opacities=new Float32Array(t)}setSplat(t,e,s,n,r,o){if(t>=this.numSplats)throw new Error(`Splat index out of bounds: ${t} >= ${this.numSplats}`);const i=t*3,u=t*4,y=t*3,m=t*3;this.positions[i]=e.x,this.positions[i+1]=e.y,this.positions[i+2]=e.z,this.rotations[u]=s.x,this.rotations[u+1]=s.y,this.rotations[u+2]=s.z,this.rotations[u+3]=s.w,this.scales[y]=n.x,this.scales[y+1]=n.y,this.scales[y+2]=n.z,this.colors[m]=r.r,this.colors[m+1]=r.g,this.colors[m+2]=r.b,this.opacities[t]=o}getSplat(t){if(t>=this.numSplats)throw new Error(`Splat index out of bounds: ${t} >= ${this.numSplats}`);const e=t*3,s=t*4,n=t*3,r=t*3;return{position:new l.Vector3(this.positions[e],this.positions[e+1],this.positions[e+2]),rotation:new l.Quaternion(this.rotations[s],this.rotations[s+1],this.rotations[s+2],this.rotations[s+3]),scale:new l.Vector3(Math.exp(this.scales[n]),Math.exp(this.scales[n+1]),Math.exp(this.scales[n+2])),color:new l.Color(this.colors[r],this.colors[r+1],this.colors[r+2]),opacity:this.opacities[t]}}calculateBoundingBox(){this.boundingBox.reset();const t=new l.Vector3;for(let e=0;e<this.numSplats;e++){const s=e*3;t.set(this.positions[s],this.positions[s+1],this.positions[s+2]),this.boundingBox.expandByPoint(t)}return this.boundingBox}createDebugGeometry(){const t=new l.BufferGeometry;t.setAttribute("position",new l.BufferAttribute(this.positions,3));const e=new Float32Array(this.numSplats*3),s=new l.Quaternion,n=new l.Euler;for(let r=0;r<this.numSplats;r++){const o=r*4,i=r*3;s.set(this.rotations[o],this.rotations[o+1],this.rotations[o+2],this.rotations[o+3]),n.setFromQuaternion(s),e[i]=n.x,e[i+1]=n.y,e[i+2]=n.z}return t.setAttribute("rotation",new l.BufferAttribute(e,3)),t.setAttribute("scale",new l.BufferAttribute(this.scales,3)),t.setAttribute("color",new l.BufferAttribute(this.colors,3)),t.setAttribute("opacity",new l.BufferAttribute(this.opacities,1)),t}dispose(){this.numSplats=0,this.scales=new Float32Array(0),this.colors=new Float32Array(0),this.positions=new Float32Array(0),this.rotations=new Float32Array(0),this.opacities=new Float32Array(0)}}class _t{constructor(t,e,s){x(this,"ranges");x(this,"version",1);x(this,"numSplats",0);x(this,"boundingBox",new gt);x(this,"sh0");x(this,"quats");x(this,"scales");x(this,"means_l");x(this,"means_u");this.ranges=e,this.numSplats=t,this.sh0=s.sh0,this.quats=s.quats,this.scales=s.scales,this.means_l=s.means_l,this.means_u=s.means_u,this.boundingBox=this.calculateBoundingBox()}calculateBoundingBox(){this.boundingBox.reset();const{mins:t,maxs:e}=this.ranges.means,s=n=>Math.sign(n)*(Math.exp(Math.abs(n))-1);return this.boundingBox.center.set((s(t[0])+s(e[0]))*.5,(s(t[1])+s(e[1]))*.5,(s(t[2])+s(e[2]))*.5),this.boundingBox.halfExtents.set((s(e[0])-s(t[0]))*.5,(s(e[1])-s(t[1]))*.5,(s(e[2])-s(t[2]))*.5),this.boundingBox}dispose(){this.sh0.dispose(),this.quats.dispose(),this.scales.dispose(),this.means_l.dispose(),this.means_u.dispose()}}class Tt{constructor(t,e,s){x(this,"ranges");x(this,"version",2);x(this,"numSplats",0);x(this,"boundingBox",new gt);x(this,"sh0");x(this,"quats");x(this,"scales");x(this,"means_l");x(this,"means_u");this.ranges=e,this.numSplats=t,this.sh0=s.sh0,this.quats=s.quats,this.scales=s.scales,this.means_l=s.means_l,this.means_u=s.means_u,this.boundingBox=this.calculateBoundingBox()}calculateBoundingBox(){this.boundingBox.reset();const{mins:t,maxs:e}=this.ranges.means,s=n=>Math.sign(n)*(Math.exp(Math.abs(n))-1);return this.boundingBox.center.set((s(t[0])+s(e[0]))*.5,(s(t[1])+s(e[1]))*.5,(s(t[2])+s(e[2]))*.5),this.boundingBox.halfExtents.set((s(e[0])-s(t[0]))*.5,(s(e[1])-s(t[1]))*.5,(s(e[2])-s(t[2]))*.5),this.boundingBox}dispose(){this.sh0.dispose(),this.quats.dispose(),this.scales.dispose(),this.means_l.dispose(),this.means_u.dispose()}}class At{constructor(t,e,s,n,r,o,i,u){x(this,"numSplats");x(this,"textureWidth");x(this,"textureHeight");x(this,"ranges");x(this,"centers");x(this,"boundingBox");x(this,"packedColor");x(this,"packedGeometry");this.numSplats=t,this.textureWidth=e,this.textureHeight=s,this.boundingBox=u,this.ranges=i,this.centers=n,this.packedColor=o,this.packedGeometry=r}dispose(){this.centers=new Float32Array(0),this.packedColor=new Uint8Array(0),this.packedGeometry=new Uint32Array(0)}}class Vt extends l.EventDispatcher{constructor(){super();x(this,"worker");x(this,"centers",null);x(this,"orderTexture",null);x(this,"chunks",null);x(this,"lastCameraPosition",new l.Vector3);x(this,"lastCameraDirection",new l.Vector3);const e=this.createWorkerCode(),s=new Blob([e],{type:"application/javascript"});this.worker=new Worker(URL.createObjectURL(s)),this.worker.onmessage=this.onWorkerMessage.bind(this)}onWorkerMessage(e){if(!this.orderTexture||!this.orderTexture.image)return console.error("SplatSorter: Order texture not initialized!");const{order:s,count:n}=e.data,r=this.orderTexture.image.data;if(!(r instanceof Uint32Array))return console.error("SplatSorter: Order texture data is not a Uint32Array!");r.set(new Uint32Array(s)),this.orderTexture.source.data.updateRanges||(this.orderTexture.source.data.updateRanges=[]),this.orderTexture.needsUpdate=!0;const o=r.buffer.slice(0),i={order:o};this.worker.postMessage(i,[o]),this.dispatchEvent({type:"updated",count:n})}init(e,s,n,r=!1){if(!e||!(e.image.data instanceof Uint32Array))throw new Error("SplatSorter: Invalid orderTexture provided. Must be DataTexture with Uint32Array data.");if(!s||s.length%3!==0)throw new Error("SplatSorter: Invalid centers array provided. Length must be multiple of 3.");if(e.image.data.length<s.length/3)throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");if(s.buffer.byteLength===0)throw new Error("SplatSorter: positions buffer is detached (likely React StrictMode + cached asset). ");const o=s.length/3;this.orderTexture=e,r?this.centers=null:this.centers=s.slice();const i=this.orderTexture.image.data;for(let h=0;h<o;h++)i[h]=h;this.orderTexture.source.data.updateRanges||(this.orderTexture.source.data.updateRanges=[]),this.orderTexture.needsUpdate=!0;const u=i.buffer.slice(0),y=r?s.buffer:s.buffer.slice(0),m={order:u,centers:y},c=[u,y];if(n){this.chunks=n.slice();const h=this.chunks.buffer.slice(0);m.chunks=h,c.push(h)}this.worker.postMessage(m,c),queueMicrotask(()=>{this.dispatchEvent({type:"updated",count:o})})}setMapping(e){if(!this.centers)return console.warn("SplatSorter: Cannot set mapping before initialization.");let s;const n=[];if(!e){const u=this.centers.buffer.slice(0);return s={centers:u,mapping:null},n.push(u),this.worker.postMessage(s,n)}const r=new Float32Array(e.length*3);for(let u=0;u<e.length;u++){const y=e[u];if(y*3+2>=this.centers.length){console.warn(`SplatSorter: Mapping index ${y} out of bounds.`);continue}const m=y*3,c=u*3;r[c+0]=this.centers[m+0],r[c+1]=this.centers[m+1],r[c+2]=this.centers[m+2]}const o=r.buffer.slice(0),i=e.buffer.slice(0);s={centers:o,mapping:i},n.push(o,i),this.worker.postMessage(s,n)}setCamera(e,s){const n=this.lastCameraPosition.distanceToSquared(e)>1e-7,r=this.lastCameraDirection.dot(s)<.9999;if(!n&&!r)return;this.lastCameraPosition.copy(e),this.lastCameraDirection.copy(s);const o={cameraPosition:{x:e.x,y:e.y,z:e.z},cameraDirection:{x:s.x,y:s.y,z:s.z}};this.worker.postMessage(o)}dispose(){this.worker&&this.worker.terminate(),this.orderTexture=null,this.centers=null,this.chunks=null}createWorkerCode(){return`(${(function(){let s=null,n=null,r=null,o=null,i=null,u=null,y=!1;const m={x:0,y:0,z:0},c={x:0,y:0,z:0},h={x:0,y:0,z:0},d={x:0,y:0,z:0};let w=null,A=null;const b=32,z=new Array(b).fill(0),_=new Array(b).fill(0),F=new Array(b).fill(0),O=(k,M,B)=>{for(;k<=M;){const S=M+k>>1,g=B(S);if(g>0)k=S+1;else if(g<0)M=S-1;else return S}return~k},V=()=>{if(!s||!n||!i||!u)return;if(n.length===0){const p={order:s.buffer,count:0};self.postMessage(p,[s.buffer]),s=null;return}const k=i.x,M=i.y,B=i.z,S=u.x,g=u.y,v=u.z,U=1e-4,T=Math.abs(k-m.x)>U||Math.abs(M-m.y)>U||Math.abs(B-m.z)>U,I=Math.abs(S-c.x)>U||Math.abs(g-c.y)>U||Math.abs(v-c.z)>U;if(!y&&!T&&!I)return;y=!1,m.x=k,m.y=M,m.z=B,c.x=S,c.y=g,c.z=v;let P=1/0,f=-1/0;for(let p=0;p<8;++p){const E=p&1?h.x:d.x,L=p&2?h.y:d.y,q=p&4?h.z:d.z,G=E*S+L*g+q*v;P=Math.min(P,G),f=Math.max(f,G)}const C=n.length/3,Y=f-P,R=(1<<Math.max(10,Math.min(20,Math.ceil(Math.log2(C/4)))))+1;if((!w||w.length!==C)&&(w=new Uint32Array(C)),!A||A.length!==R?A=new Uint32Array(R):A.fill(0),Y<1e-7){for(let p=0;p<C;++p)w[p]=0;A[0]=C}else if(r&&r.length>0){const p=r.length/6;z.fill(0);for(let q=0;q<p;++q){const G=q*6,Q=r[G+0],$=r[G+1],J=r[G+2],N=r[G+3],tt=Q*S+$*g+J*v-P,nt=tt-N,rt=tt+N,ft=Math.max(0,Math.floor(nt*b/Y)),pt=Math.min(b,Math.ceil(rt*b/Y));for(let lt=ft;lt<pt;++lt)z[lt]++}let E=0;for(let q=0;q<b;++q)E+=z[q];F[0]=0,_[0]=0;for(let q=1;q<b;++q)F[q-1]=z[q-1]/E*R>>>0,_[q]=_[q-1]+F[q-1];F[b-1]=z[b-1]/E*R>>>0;const L=Y/b;for(let q=0;q<C;++q){const G=q*3,Q=n[G+0],$=n[G+1],J=n[G+2],N=Q*S+$*g+J*v,nt=(f-N)/L,rt=Math.max(0,Math.min(b-1,Math.floor(nt))),ft=nt-rt,pt=_[rt]+F[rt]*ft>>>0,lt=Math.min(pt,R-1);w[q]=lt,A[lt]++}}else{const p=(R-1)/Y;for(let E=0;E<C;++E){const L=E*3,q=n[L+0],G=n[L+1],Q=n[L+2],$=q*S+G*g+Q*v,N=(f-$)*p>>>0,tt=Math.min(N,R-1);w[E]=tt,A[tt]++}}for(let p=1;p<R;p++)A[p]+=A[p-1];for(let p=C-1;p>=0;p--){const E=w[p],L=--A[E];s[L]=o?o[p]:p}const K=k*S+M*g+B*v,X=p=>{if(!s)return-1/0;const E=s[p],L=E;if(!n||L*3+2>=n.length)return-1/0;const q=L*3;return n[q]*S+n[q+1]*g+n[q+2]*v-K};let Z=C;if(C>0&&X(C-1)<0){const p=O(0,C-1,X);Z=p<0?~p:p}const D={order:s.buffer,count:Z};self.postMessage(D,[s.buffer]),s=null};self.onmessage=k=>{const M=k.data;M.order&&(s=new Uint32Array(M.order));let B=!1;if(M.centers&&(n=new Float32Array(M.centers),B=!0,y=!0),Object.prototype.hasOwnProperty.call(M,"mapping")&&(o=M.mapping?new Uint32Array(M.mapping):null,y=!0),M.chunks){if(r=new Float32Array(M.chunks),r.length>0&&r[3]>0)for(let S=0;S<r.length/6;++S){const g=S*6,v=r[g+0],U=r[g+1],T=r[g+2],I=r[g+3],P=r[g+4],f=r[g+5];r[g+0]=(v+I)*.5,r[g+1]=(U+P)*.5,r[g+2]=(T+f)*.5,r[g+3]=Math.sqrt((I-v)**2+(P-U)**2+(f-T)**2)*.5}y=!0}if(B&&n&&n.length>0){h.x=d.x=n[0],h.y=d.y=n[1],h.z=d.z=n[2];for(let S=1;S<n.length/3;S++){const g=S*3;h.x=Math.min(h.x,n[g+0]),d.x=Math.max(d.x,n[g+0]),h.y=Math.min(h.y,n[g+1]),d.y=Math.max(d.y,n[g+1]),h.z=Math.min(h.z,n[g+2]),d.z=Math.max(d.z,n[g+2])}}else B&&n&&n.length===0&&(h.x=d.x=h.y=d.y=h.z=d.z=0);M.cameraPosition&&(i=M.cameraPosition),M.cameraDirection&&(u=M.cameraDirection),V()}}).toString()})();`}}class Ut{constructor(t){x(this,"packedGeometry");x(this,"packedColor");x(this,"orderTexture");x(this,"width");x(this,"height");this.width=t.textureWidth,this.height=t.textureHeight,this.packedColor=this.createColorTexture(t),this.packedGeometry=this.createGeometryTexture(t),this.orderTexture=this.createOrderTexture(t.numSplats)}createGeometryTexture(t){const e=new l.DataTexture(t.packedGeometry,this.width,this.height,l.RGBAIntegerFormat,l.UnsignedIntType);return e.internalFormat="RGBA32UI",e.minFilter=l.NearestFilter,e.magFilter=l.NearestFilter,e.needsUpdate=!0,e}createColorTexture(t){const e=new l.DataTexture(t.packedColor,this.width,this.height,l.RGBAFormat,l.UnsignedByteType);return e.minFilter=l.NearestFilter,e.magFilter=l.NearestFilter,e.needsUpdate=!0,e}createOrderTexture(t){const e=new Uint32Array(this.width*this.height);for(let n=0;n<t;n++)e[n]=n;const s=new l.DataTexture(e,this.width,this.height,l.RedIntegerFormat,l.UnsignedIntType);return s.minFilter=l.NearestFilter,s.magFilter=l.NearestFilter,s.needsUpdate=!0,s}dispose(){this.packedGeometry.dispose(),this.packedColor.dispose(),this.orderTexture.dispose()}}const Qt=`
|
|
1
|
+
(function(j,te){typeof exports=="object"&&typeof module<"u"?te(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],te):(j=typeof globalThis<"u"?globalThis:j||self,te(j.Visus={},j.THREE))})(this,function(j,te){"use strict";var _t=Object.defineProperty;var kt=(j,te,ge)=>te in j?_t(j,te,{enumerable:!0,configurable:!0,writable:!0,value:ge}):j[te]=ge;var d=(j,te,ge)=>kt(j,typeof te!="symbol"?te+"":te,ge);if(typeof THREE>"u")throw new Error(`Visus UMD build requires Three.js as a global "THREE".
|
|
2
|
+
Please include <script src="https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.min.js"><\/script> before loading visus/main.umd.js`);function ge(a){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(a){for(const t in a)if(t!=="default"){const s=Object.getOwnPropertyDescriptor(a,t);Object.defineProperty(e,t,s.get?s:{enumerable:!0,get:()=>a[t]})}}return e.default=a,Object.freeze(e)}const c=ge(te);class xe{constructor(){d(this,"min",new c.Vector3(1/0,1/0,1/0));d(this,"max",new c.Vector3(-1/0,-1/0,-1/0));d(this,"center",new c.Vector3);d(this,"halfExtents",new c.Vector3)}reset(){this.min.set(1/0,1/0,1/0),this.max.set(-1/0,-1/0,-1/0),this.center.set(0,0,0),this.halfExtents.set(0,0,0)}expandByPoint(e){this.min.x=Math.min(this.min.x,e.x),this.min.y=Math.min(this.min.y,e.y),this.min.z=Math.min(this.min.z,e.z),this.max.x=Math.max(this.max.x,e.x),this.max.y=Math.max(this.max.y,e.y),this.max.z=Math.max(this.max.z,e.z),this.updateDerived()}expandByBox(e){this.min.x=Math.min(this.min.x,e.min.x),this.min.y=Math.min(this.min.y,e.min.y),this.min.z=Math.min(this.min.z,e.min.z),this.max.x=Math.max(this.max.x,e.max.x),this.max.y=Math.max(this.max.y,e.max.y),this.max.z=Math.max(this.max.z,e.max.z),this.updateDerived()}updateDerived(){this.center.addVectors(this.min,this.max).multiplyScalar(.5),this.halfExtents.subVectors(this.max,this.min).multiplyScalar(.5)}containsPoint(e){return e.x>=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}toBox3(){return new c.Box3().set(this.min,this.max)}clone(){const e=new xe;return e.min.copy(this.min),e.max.copy(this.max),e.center.copy(this.center),e.halfExtents.copy(this.halfExtents),e}}class tt{constructor(e=0){d(this,"numSplats",0);d(this,"positions");d(this,"rotations");d(this,"scales");d(this,"colors");d(this,"opacities");d(this,"boundingBox",new xe);this.numSplats=e,this.allocateBuffers(e)}allocateBuffers(e){this.positions=new Float32Array(e*3),this.rotations=new Float32Array(e*4),this.scales=new Float32Array(e*3),this.colors=new Float32Array(e*3),this.opacities=new Float32Array(e)}setSplat(e,t,s,n,r,i){if(e>=this.numSplats)throw new Error(`Splat index out of bounds: ${e} >= ${this.numSplats}`);const o=e*3,u=e*4,y=e*3,m=e*3;this.positions[o]=t.x,this.positions[o+1]=t.y,this.positions[o+2]=t.z,this.rotations[u]=s.x,this.rotations[u+1]=s.y,this.rotations[u+2]=s.z,this.rotations[u+3]=s.w,this.scales[y]=n.x,this.scales[y+1]=n.y,this.scales[y+2]=n.z,this.colors[m]=r.r,this.colors[m+1]=r.g,this.colors[m+2]=r.b,this.opacities[e]=i}getSplat(e){if(e>=this.numSplats)throw new Error(`Splat index out of bounds: ${e} >= ${this.numSplats}`);const t=e*3,s=e*4,n=e*3,r=e*3;return{position:new c.Vector3(this.positions[t],this.positions[t+1],this.positions[t+2]),rotation:new c.Quaternion(this.rotations[s],this.rotations[s+1],this.rotations[s+2],this.rotations[s+3]),scale:new c.Vector3(Math.exp(this.scales[n]),Math.exp(this.scales[n+1]),Math.exp(this.scales[n+2])),color:new c.Color(this.colors[r],this.colors[r+1],this.colors[r+2]),opacity:this.opacities[e]}}calculateBoundingBox(){this.boundingBox.reset();const e=new c.Vector3;for(let t=0;t<this.numSplats;t++){const s=t*3;e.set(this.positions[s],this.positions[s+1],this.positions[s+2]),this.boundingBox.expandByPoint(e)}return this.boundingBox}createDebugGeometry(){const e=new c.BufferGeometry;e.setAttribute("position",new c.BufferAttribute(this.positions,3));const t=new Float32Array(this.numSplats*3),s=new c.Quaternion,n=new c.Euler;for(let r=0;r<this.numSplats;r++){const i=r*4,o=r*3;s.set(this.rotations[i],this.rotations[i+1],this.rotations[i+2],this.rotations[i+3]),n.setFromQuaternion(s),t[o]=n.x,t[o+1]=n.y,t[o+2]=n.z}return e.setAttribute("rotation",new c.BufferAttribute(t,3)),e.setAttribute("scale",new c.BufferAttribute(this.scales,3)),e.setAttribute("color",new c.BufferAttribute(this.colors,3)),e.setAttribute("opacity",new c.BufferAttribute(this.opacities,1)),e}dispose(){this.numSplats=0,this.scales=new Float32Array(0),this.colors=new Float32Array(0),this.positions=new Float32Array(0),this.rotations=new Float32Array(0),this.opacities=new Float32Array(0)}}class Ve{constructor(e,t,s){d(this,"ranges");d(this,"version",1);d(this,"numSplats",0);d(this,"boundingBox",new xe);d(this,"sh0");d(this,"quats");d(this,"scales");d(this,"means_l");d(this,"means_u");this.ranges=t,this.numSplats=e,this.sh0=s.sh0,this.quats=s.quats,this.scales=s.scales,this.means_l=s.means_l,this.means_u=s.means_u,this.boundingBox=this.calculateBoundingBox()}calculateBoundingBox(){this.boundingBox.reset();const{mins:e,maxs:t}=this.ranges.means,s=n=>Math.sign(n)*(Math.exp(Math.abs(n))-1);return this.boundingBox.center.set((s(e[0])+s(t[0]))*.5,(s(e[1])+s(t[1]))*.5,(s(e[2])+s(t[2]))*.5),this.boundingBox.halfExtents.set((s(t[0])-s(e[0]))*.5,(s(t[1])-s(e[1]))*.5,(s(t[2])-s(e[2]))*.5),this.boundingBox}dispose(){this.sh0.dispose(),this.quats.dispose(),this.scales.dispose(),this.means_l.dispose(),this.means_u.dispose()}}class Oe{constructor(e,t,s){d(this,"ranges");d(this,"version",2);d(this,"numSplats",0);d(this,"boundingBox",new xe);d(this,"sh0");d(this,"quats");d(this,"scales");d(this,"means_l");d(this,"means_u");this.ranges=t,this.numSplats=e,this.sh0=s.sh0,this.quats=s.quats,this.scales=s.scales,this.means_l=s.means_l,this.means_u=s.means_u,this.boundingBox=this.calculateBoundingBox()}calculateBoundingBox(){this.boundingBox.reset();const{mins:e,maxs:t}=this.ranges.means,s=n=>Math.sign(n)*(Math.exp(Math.abs(n))-1);return this.boundingBox.center.set((s(e[0])+s(t[0]))*.5,(s(e[1])+s(t[1]))*.5,(s(e[2])+s(t[2]))*.5),this.boundingBox.halfExtents.set((s(t[0])-s(e[0]))*.5,(s(t[1])-s(e[1]))*.5,(s(t[2])-s(e[2]))*.5),this.boundingBox}dispose(){this.sh0.dispose(),this.quats.dispose(),this.scales.dispose(),this.means_l.dispose(),this.means_u.dispose()}}class Ae{constructor(e,t,s,n,r,i,o,u){d(this,"numSplats");d(this,"textureWidth");d(this,"textureHeight");d(this,"ranges");d(this,"centers");d(this,"boundingBox");d(this,"packedColor");d(this,"packedGeometry");this.numSplats=e,this.textureWidth=t,this.textureHeight=s,this.boundingBox=u,this.ranges=o,this.centers=n,this.packedColor=i,this.packedGeometry=r}dispose(){this.centers=new Float32Array(0),this.packedColor=new Uint8Array(0),this.packedGeometry=new Uint32Array(0)}}class Re extends c.EventDispatcher{constructor(){super();d(this,"worker");d(this,"centers",null);d(this,"orderTexture",null);d(this,"chunks",null);d(this,"lastCameraPosition",new c.Vector3);d(this,"lastCameraDirection",new c.Vector3);const t=this.createWorkerCode(),s=new Blob([t],{type:"application/javascript"});this.worker=new Worker(URL.createObjectURL(s)),this.worker.onmessage=this.onWorkerMessage.bind(this)}onWorkerMessage(t){if(!this.orderTexture||!this.orderTexture.image)return console.error("SplatSorter: Order texture not initialized!");const{order:s,count:n}=t.data,r=this.orderTexture.image.data;if(!(r instanceof Uint32Array))return console.error("SplatSorter: Order texture data is not a Uint32Array!");r.set(new Uint32Array(s)),this.orderTexture.source.data.updateRanges||(this.orderTexture.source.data.updateRanges=[]),this.orderTexture.needsUpdate=!0;const i=r.buffer.slice(0),o={order:i};this.worker.postMessage(o,[i]),this.dispatchEvent({type:"updated",count:n})}init(t,s,n,r=!1){if(!t||!(t.image.data instanceof Uint32Array))throw new Error("SplatSorter: Invalid orderTexture provided. Must be DataTexture with Uint32Array data.");if(!s||s.length%3!==0)throw new Error("SplatSorter: Invalid centers array provided. Length must be multiple of 3.");if(t.image.data.length<s.length/3)throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");if(s.buffer.byteLength===0)throw new Error("SplatSorter: positions buffer is detached (likely React StrictMode + cached asset). ");const i=s.length/3;this.orderTexture=t,r?this.centers=null:this.centers=s.slice();const o=this.orderTexture.image.data;for(let h=0;h<i;h++)o[h]=h;this.orderTexture.source.data.updateRanges||(this.orderTexture.source.data.updateRanges=[]),this.orderTexture.needsUpdate=!0;const u=o.buffer.slice(0),y=r?s.buffer:s.buffer.slice(0),m={order:u,centers:y},l=[u,y];if(n){this.chunks=n.slice();const h=this.chunks.buffer.slice(0);m.chunks=h,l.push(h)}this.worker.postMessage(m,l),queueMicrotask(()=>{this.dispatchEvent({type:"updated",count:i})})}setMapping(t){if(!this.centers)return console.warn("SplatSorter: Cannot set mapping before initialization.");let s;const n=[];if(!t){const u=this.centers.buffer.slice(0);return s={centers:u,mapping:null},n.push(u),this.worker.postMessage(s,n)}const r=new Float32Array(t.length*3);for(let u=0;u<t.length;u++){const y=t[u];if(y*3+2>=this.centers.length){console.warn(`SplatSorter: Mapping index ${y} out of bounds.`);continue}const m=y*3,l=u*3;r[l+0]=this.centers[m+0],r[l+1]=this.centers[m+1],r[l+2]=this.centers[m+2]}const i=r.buffer.slice(0),o=t.buffer.slice(0);s={centers:i,mapping:o},n.push(i,o),this.worker.postMessage(s,n)}setCamera(t,s){const n=this.lastCameraPosition.distanceToSquared(t)>1e-7,r=this.lastCameraDirection.dot(s)<.9999;if(!n&&!r)return;this.lastCameraPosition.copy(t),this.lastCameraDirection.copy(s);const i={cameraPosition:{x:t.x,y:t.y,z:t.z},cameraDirection:{x:s.x,y:s.y,z:s.z}};this.worker.postMessage(i)}dispose(){this.worker&&this.worker.terminate(),this.orderTexture=null,this.centers=null,this.chunks=null}createWorkerCode(){return`(${(function(){let s=null,n=null,r=null,i=null,o=null,u=null,y=!1;const m={x:0,y:0,z:0},l={x:0,y:0,z:0},h={x:0,y:0,z:0},f={x:0,y:0,z:0};let w=null,A=null;const b=32,B=new Array(b).fill(0),F=new Array(b).fill(0),P=new Array(b).fill(0),U=(C,M,k)=>{for(;C<=M;){const S=M+C>>1,x=k(S);if(x>0)C=S+1;else if(x<0)M=S-1;else return S}return~C},O=()=>{if(!s||!n||!o||!u)return;if(n.length===0){const g={order:s.buffer,count:0};self.postMessage(g,[s.buffer]),s=null;return}const C=o.x,M=o.y,k=o.z,S=u.x,x=u.y,v=u.z,R=1e-4,V=Math.abs(C-m.x)>R||Math.abs(M-m.y)>R||Math.abs(k-m.z)>R,I=Math.abs(S-l.x)>R||Math.abs(x-l.y)>R||Math.abs(v-l.z)>R;if(!y&&!V&&!I)return;y=!1,m.x=C,m.y=M,m.z=k,l.x=S,l.y=x,l.z=v;let q=1/0,p=-1/0;for(let g=0;g<8;++g){const E=g&1?h.x:f.x,L=g&2?h.y:f.y,D=g&4?h.z:f.z,G=E*S+L*x+D*v;q=Math.min(q,G),p=Math.max(p,G)}const _=n.length/3,Y=p-q,T=(1<<Math.max(10,Math.min(20,Math.ceil(Math.log2(_/4)))))+1;if((!w||w.length!==_)&&(w=new Uint32Array(_)),!A||A.length!==T?A=new Uint32Array(T):A.fill(0),Y<1e-7){for(let g=0;g<_;++g)w[g]=0;A[0]=_}else if(r&&r.length>0){const g=r.length/6;B.fill(0);for(let D=0;D<g;++D){const G=D*6,Q=r[G+0],H=r[G+1],J=r[G+2],$=r[G+3],ee=Q*S+H*x+J*v-q,ne=ee-$,ae=ee+$,fe=Math.max(0,Math.floor(ne*b/Y)),pe=Math.min(b,Math.ceil(ae*b/Y));for(let le=fe;le<pe;++le)B[le]++}let E=0;for(let D=0;D<b;++D)E+=B[D];P[0]=0,F[0]=0;for(let D=1;D<b;++D)P[D-1]=B[D-1]/E*T>>>0,F[D]=F[D-1]+P[D-1];P[b-1]=B[b-1]/E*T>>>0;const L=Y/b;for(let D=0;D<_;++D){const G=D*3,Q=n[G+0],H=n[G+1],J=n[G+2],$=Q*S+H*x+J*v,ne=(p-$)/L,ae=Math.max(0,Math.min(b-1,Math.floor(ne))),fe=ne-ae,pe=F[ae]+P[ae]*fe>>>0,le=Math.min(pe,T-1);w[D]=le,A[le]++}}else{const g=(T-1)/Y;for(let E=0;E<_;++E){const L=E*3,D=n[L+0],G=n[L+1],Q=n[L+2],H=D*S+G*x+Q*v,$=(p-H)*g>>>0,ee=Math.min($,T-1);w[E]=ee,A[ee]++}}for(let g=1;g<T;g++)A[g]+=A[g-1];for(let g=_-1;g>=0;g--){const E=w[g],L=--A[E];s[L]=i?i[g]:g}const K=C*S+M*x+k*v,X=g=>{if(!s)return-1/0;const E=s[g],L=E;if(!n||L*3+2>=n.length)return-1/0;const D=L*3;return n[D]*S+n[D+1]*x+n[D+2]*v-K};let Z=_;if(_>0&&X(_-1)<0){const g=U(0,_-1,X);Z=g<0?~g:g}const z={order:s.buffer,count:Z};self.postMessage(z,[s.buffer]),s=null};self.onmessage=C=>{const M=C.data;M.order&&(s=new Uint32Array(M.order));let k=!1;if(M.centers&&(n=new Float32Array(M.centers),k=!0,y=!0),Object.prototype.hasOwnProperty.call(M,"mapping")&&(i=M.mapping?new Uint32Array(M.mapping):null,y=!0),M.chunks){if(r=new Float32Array(M.chunks),r.length>0&&r[3]>0)for(let S=0;S<r.length/6;++S){const x=S*6,v=r[x+0],R=r[x+1],V=r[x+2],I=r[x+3],q=r[x+4],p=r[x+5];r[x+0]=(v+I)*.5,r[x+1]=(R+q)*.5,r[x+2]=(V+p)*.5,r[x+3]=Math.sqrt((I-v)**2+(q-R)**2+(p-V)**2)*.5}y=!0}if(k&&n&&n.length>0){h.x=f.x=n[0],h.y=f.y=n[1],h.z=f.z=n[2];for(let S=1;S<n.length/3;S++){const x=S*3;h.x=Math.min(h.x,n[x+0]),f.x=Math.max(f.x,n[x+0]),h.y=Math.min(h.y,n[x+1]),f.y=Math.max(f.y,n[x+1]),h.z=Math.min(h.z,n[x+2]),f.z=Math.max(f.z,n[x+2])}}else k&&n&&n.length===0&&(h.x=f.x=h.y=f.y=h.z=f.z=0);M.cameraPosition&&(o=M.cameraPosition),M.cameraDirection&&(u=M.cameraDirection),O()}}).toString()})();`}}const Ue={spread:{type:"spread",defaultDuration:3,shaderCode:`
|
|
3
|
+
void applyAnimation(
|
|
4
|
+
inout vec3 position,
|
|
5
|
+
inout vec3 scale,
|
|
6
|
+
inout vec4 color,
|
|
7
|
+
float progress,
|
|
8
|
+
vec3 center
|
|
9
|
+
) {
|
|
10
|
+
const float DIST_K = 0.3;
|
|
11
|
+
const float WAVE_GAIN = 1.2;
|
|
12
|
+
const float SPHERE_LOG = -6.0;
|
|
13
|
+
const float INV_WAVE_W = 20.0; // 1.0 / 0.05 wave width, precomputed
|
|
14
|
+
const vec3 GOLD = vec3(1.0, 1.0, 1.0); // pure white
|
|
15
|
+
|
|
16
|
+
float dist = length(position - center);
|
|
17
|
+
float normalizedDist = 1.0 - exp(-dist * DIST_K);
|
|
18
|
+
float waveProgress = progress * WAVE_GAIN;
|
|
19
|
+
|
|
20
|
+
float revealed = step(normalizedDist, waveProgress);
|
|
21
|
+
scale = mix(vec3(SPHERE_LOG), scale, revealed);
|
|
22
|
+
|
|
23
|
+
float glowIntensity = clamp(1.0 - abs(normalizedDist - waveProgress) * INV_WAVE_W, 0.0, 1.0);
|
|
24
|
+
color.rgb = mix(color.rgb, GOLD, glowIntensity);
|
|
25
|
+
}
|
|
26
|
+
`},wave:{type:"wave",defaultDuration:3,shaderCode:`
|
|
27
|
+
void applyAnimation(
|
|
28
|
+
inout vec3 position,
|
|
29
|
+
inout vec3 scale,
|
|
30
|
+
inout vec4 color,
|
|
31
|
+
float progress,
|
|
32
|
+
vec3 center
|
|
33
|
+
) {
|
|
34
|
+
const float DIST_K = 0.3;
|
|
35
|
+
const float WAVE_GAIN = 1.2;
|
|
36
|
+
const float INV_WAVE_W = 20.0;
|
|
37
|
+
const vec3 GLOW = vec3(1.0, 1.0, 1.0);
|
|
38
|
+
|
|
39
|
+
float dist = length(position - center);
|
|
40
|
+
float normalizedDist = 1.0 - exp(-dist * DIST_K);
|
|
41
|
+
float waveProgress = progress * WAVE_GAIN;
|
|
42
|
+
|
|
43
|
+
float glowIntensity = clamp(1.0 - abs(normalizedDist - waveProgress) * INV_WAVE_W, 0.0, 1.0);
|
|
44
|
+
color.rgb = mix(color.rgb, GLOW, glowIntensity);
|
|
45
|
+
}
|
|
46
|
+
`},none:{type:"none",defaultDuration:0,shaderCode:`
|
|
47
|
+
void applyAnimation(
|
|
48
|
+
inout vec3 position,
|
|
49
|
+
inout vec3 scale,
|
|
50
|
+
inout vec4 color,
|
|
51
|
+
float progress,
|
|
52
|
+
vec3 center
|
|
53
|
+
) {}
|
|
54
|
+
`}},Ie=a=>Ue[a]??Ue.none,Le={linear:a=>a,easeInQuad:a=>a*a,easeOutQuad:a=>a*(2-a),easeInOutQuad:a=>a<.5?2*a*a:-1+(4-2*a)*a,easeInCubic:a=>a*a*a,easeOutCubic:a=>1-Math.pow(1-a,3),easeInOutCubic:a=>a<.5?4*a*a*a:1-Math.pow(-2*a+2,3)/2,easeOutExpo:a=>a===1?1:1-Math.pow(2,-10*a)},st=a=>Le[a]??Le.linear;class Ge{constructor(e){d(this,"_progress",0);d(this,"_isPlaying",!1);d(this,"_isComplete",!1);d(this,"_startTime",0);d(this,"_duration");d(this,"_delay");d(this,"_easing");d(this,"_type");d(this,"_autoPlay");d(this,"_center",new c.Vector3);const t=Ie(e.type);this._type=e.type,this._duration=e.duration??t.defaultDuration,this._delay=e.delay??0,this._easing=st(e.easing??"easeOutCubic"),this._autoPlay=e.autoPlay??!0}get progress(){return this._progress}get isPlaying(){return this._isPlaying}get isComplete(){return this._isComplete}get type(){return this._type}get center(){return this._center}setCenter(e){this._center.copy(e)}play(){this._startTime=-1,this._isPlaying=!0,this._isComplete=!1,this._progress=0}stop(){this._isPlaying=!1}reset(){this._progress=0,this._isPlaying=!1,this._isComplete=!1,this._startTime=0}complete(){this._progress=1,this._isPlaying=!1,this._isComplete=!0}update(e){if(!this._isPlaying)return!1;this._startTime<0&&(this._startTime=e+this._delay);const t=e-this._startTime;if(t<0)return!1;const s=Math.min(t/this._duration,1);return this._progress=this._easing(s),s>=1&&(this._isPlaying=!1,this._isComplete=!0,this._progress=1),!0}shouldAutoPlay(){return this._autoPlay&&!this._isComplete}}class We{constructor(e){d(this,"packedGeometry");d(this,"packedColor");d(this,"orderTexture");d(this,"width");d(this,"height");this.width=e.textureWidth,this.height=e.textureHeight,this.packedColor=this.createColorTexture(e),this.packedGeometry=this.createGeometryTexture(e),this.orderTexture=this.createOrderTexture(e.numSplats)}createGeometryTexture(e){const t=new c.DataTexture(e.packedGeometry,this.width,this.height,c.RGBAIntegerFormat,c.UnsignedIntType);return t.internalFormat="RGBA32UI",t.minFilter=c.NearestFilter,t.magFilter=c.NearestFilter,t.needsUpdate=!0,t}createColorTexture(e){const t=new c.DataTexture(e.packedColor,this.width,this.height,c.RGBAFormat,c.UnsignedByteType);return t.minFilter=c.NearestFilter,t.magFilter=c.NearestFilter,t.needsUpdate=!0,t}createOrderTexture(e){const t=new Uint32Array(this.width*this.height);for(let n=0;n<e;n++)t[n]=n;const s=new c.DataTexture(t,this.width,this.height,c.RedIntegerFormat,c.UnsignedIntType);return s.minFilter=c.NearestFilter,s.magFilter=c.NearestFilter,s.needsUpdate=!0,s}dispose(){this.packedGeometry.dispose(),this.packedColor.dispose(),this.orderTexture.dispose()}}const Ne=`
|
|
3
55
|
precision highp float;
|
|
4
56
|
precision highp int;
|
|
5
57
|
precision highp usampler2D;
|
|
@@ -22,6 +74,12 @@ uniform vec3 scalesMax;
|
|
|
22
74
|
uniform vec3 sh0Min;
|
|
23
75
|
uniform vec3 sh0Max;
|
|
24
76
|
|
|
77
|
+
// --- Animation Uniforms ---
|
|
78
|
+
uniform float animationProgress; // 0 = start, 1 = complete
|
|
79
|
+
uniform vec3 animationCenter; // Center point for animation
|
|
80
|
+
|
|
81
|
+
/* @ANIMATION_CODE */
|
|
82
|
+
|
|
25
83
|
// --- Attributes ---
|
|
26
84
|
in uint splatInstanceIndex;
|
|
27
85
|
|
|
@@ -120,11 +178,10 @@ void main() {
|
|
|
120
178
|
else if (mode == 2u) quat = vec4(abc.xy, d, abc.z); // stored (w,x,z)
|
|
121
179
|
else quat = vec4(abc, d); // stored (w,x,y)
|
|
122
180
|
|
|
123
|
-
// Decompress Scale
|
|
181
|
+
// Decompress Scale (log-space)
|
|
124
182
|
uvec3 sB = unpackBytes(geom.w).xyz;
|
|
125
183
|
vec3 sNorm = vec3(sB) * (1.0 / 255.0);
|
|
126
|
-
vec3
|
|
127
|
-
vec3 scale = exp(sLerp); // log scale stored
|
|
184
|
+
vec3 scale = mix(scalesMin, scalesMax, sNorm); // log-space scale
|
|
128
185
|
|
|
129
186
|
// Decompress Color & Opacity
|
|
130
187
|
vec4 clr;
|
|
@@ -132,6 +189,12 @@ void main() {
|
|
|
132
189
|
clr.rgb = vec3(0.5) + sh * SH_C0;
|
|
133
190
|
clr.a = colorRaw.a; // Opacity passed directly (linear or sigmoid handled by loader)
|
|
134
191
|
|
|
192
|
+
// --- Apply Animation (modifies position, scale, color in place) ---
|
|
193
|
+
/* @ANIMATION_CALL */
|
|
194
|
+
|
|
195
|
+
// Convert log-space scale to linear scale
|
|
196
|
+
scale = exp(scale);
|
|
197
|
+
|
|
135
198
|
// --- Standard Gaussian Splat Projection ---
|
|
136
199
|
|
|
137
200
|
// View Space Setup
|
|
@@ -185,9 +248,12 @@ void main() {
|
|
|
185
248
|
float l2 = 2.0 * min(sqrt(2.0 * lambda2), vmin);
|
|
186
249
|
|
|
187
250
|
// Discard tiny splats
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
251
|
+
// TODO: this branch might create some performance issues - check
|
|
252
|
+
if (animationProgress >= 1.0) {
|
|
253
|
+
if (l1 < 2.0 && l2 < 2.0) {
|
|
254
|
+
gl_Position = DISCARD_VERTEX;
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
191
257
|
}
|
|
192
258
|
|
|
193
259
|
vec2 diagVec = normalize(vec2(offDiagonal, lambda1 - diagonal1));
|
|
@@ -221,7 +287,7 @@ void main() {
|
|
|
221
287
|
vUv = clippedUV;
|
|
222
288
|
vColor = vec4(max(clr.rgb, vec3(0.0)), clr.a);
|
|
223
289
|
}
|
|
224
|
-
`,
|
|
290
|
+
`,nt=`
|
|
225
291
|
precision highp float;
|
|
226
292
|
|
|
227
293
|
in vec4 vColor; // Color and opacity passed from vertex shader
|
|
@@ -253,7 +319,9 @@ void main(void) {
|
|
|
253
319
|
// Premultiply color by alpha (required for correct blending)
|
|
254
320
|
fragColor = vec4(vColor.rgb * alpha, alpha);
|
|
255
321
|
}
|
|
256
|
-
`;class Ot extends l.ShaderMaterial{constructor(t={}){const e={packedGeometry:{value:null},packedColor:{value:null},splatOrder:{value:null},meansMin:{value:new l.Vector3},meansMax:{value:new l.Vector3},scalesMin:{value:new l.Vector3},scalesMax:{value:new l.Vector3},sh0Min:{value:new l.Vector3},sh0Max:{value:new l.Vector3},texWidth:{value:0},viewport:{value:new l.Vector2(1,1)},numSplats:{value:0}};super({uniforms:e,vertexShader:Qt,fragmentShader:Jt,transparent:!0,glslVersion:l.GLSL3,blendSrc:l.OneFactor,blendSrcAlpha:l.OneFactor,blending:l.CustomBlending,blendEquation:l.AddEquation,blendEquationAlpha:l.AddEquation,blendDst:l.OneMinusSrcAlphaFactor,blendDstAlpha:l.OneMinusSrcAlphaFactor,depthTest:!0,depthWrite:!1,side:l.DoubleSide,alphaTest:t.alphaTest??0,toneMapped:t.toneMapped??!1}),t.alphaHash&&(this.alphaHash=!0,this.depthWrite=!0,this.blending=l.NoBlending)}setTexWidth(t){this.uniforms.texWidth.value=t|0}updateViewport(t,e){this.uniforms.viewport.value.set(t,e)}setPackedGeometry(t){this.uniforms.packedGeometry.value=t}setPackedColor(t){this.uniforms.packedColor.value=t}setOrderTexture(t){this.uniforms.splatOrder.value=t}setRanges(t){this.uniforms.meansMin.value.copy(t.means.min),this.uniforms.meansMax.value.copy(t.means.max),this.uniforms.scalesMin.value.copy(t.scales.min),this.uniforms.scalesMax.value.copy(t.scales.max),this.uniforms.sh0Min.value.copy(t.sh0.min),this.uniforms.sh0Max.value.copy(t.sh0.max)}setNumSplats(t){this.uniforms.numSplats.value=t}}const vt=class vt extends l.Mesh{constructor(e,s={}){const n=new Ot(s),r=vt.createInstancedGeometry(e.numSplats,vt.INSTANCE_SIZE);super(r,n);x(this,"sorter");x(this,"options");x(this,"splatData");x(this,"textureManager");x(this,"material");x(this,"geometry");x(this,"lastCameraPositionLocal",new l.Vector3);x(this,"lastCameraDirectionLocal",new l.Vector3);x(this,"invModelMatrix",new l.Matrix4);x(this,"_vpW",-1);x(this,"_vpH",-1);x(this,"_size",new l.Vector2);x(this,"_camPosW",new l.Vector3);x(this,"_camDirW",new l.Vector3);x(this,"_camPosL",new l.Vector3);x(this,"_camDirL",new l.Vector3);x(this,"onSorterUpdated",e=>{const s=e.count;this.geometry.instanceCount=Math.ceil(s/vt.INSTANCE_SIZE),this.material.setNumSplats(s)});this.geometry=r,this.material=n,this.options={autoSort:!0,...s},this.splatData=e,this.frustumCulled=!1,this.sorter=new Vt,this.textureManager=new Ut(e);let o=this.createChunks()||void 0;o===null&&console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."),o=void 0,this.sorter.addEventListener("updated",this.onSorterUpdated),this.sorter.init(this.textureManager.orderTexture,this.splatData.centers,o??void 0,!this.options.keepSplatData),this.material.setRanges(e.ranges),this.material.setTexWidth(e.textureWidth),this.material.setPackedColor(this.textureManager.packedColor),this.material.setOrderTexture(this.textureManager.orderTexture),this.material.setPackedGeometry(this.textureManager.packedGeometry),this.material.setNumSplats(0),this.geometry.boundingBox=e.boundingBox.toBox3(),this.geometry.boundingSphere=new l.Sphere,this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere),this.options.keepSplatData||(this.splatData=null)}static createInstancedGeometry(e,s){const n=Math.ceil(e/s),r=new l.BufferGeometry,o=new Float32Array([-1,-1,0,1,-1,0,1,1,0,-1,1,0]),i=new Uint16Array([0,1,2,0,2,3]),u=new Float32Array(4*3*s);for(let h=0;h<s;h++){const d=h*4*3;for(let w=0;w<4;w++)u[d+w*3+0]=o[w*3+0],u[d+w*3+1]=o[w*3+1],u[d+w*3+2]=h}const y=new Uint32Array(6*s);for(let h=0;h<s;h++){const d=h*6,w=h*4;y[d+0]=i[0]+w,y[d+1]=i[1]+w,y[d+2]=i[2]+w,y[d+3]=i[3]+w,y[d+4]=i[4]+w,y[d+5]=i[5]+w}r.setAttribute("position",new l.BufferAttribute(u,3)),r.setIndex(new l.BufferAttribute(y,1));const m=new l.InstancedBufferGeometry;m.index=r.index,m.setAttribute("position",r.getAttribute("position"));const c=new Uint32Array(n);for(let h=0;h<n;h++)c[h]=h*s;return m.setAttribute("splatInstanceIndex",new l.InstancedBufferAttribute(c,1,!1)),m.instanceCount=0,m}createChunks(){if(!this.splatData)return null;const e=this.splatData.boundingBox;return e.min.x===1/0||e.max.x===-1/0?null:new Float32Array([e.min.x,e.min.y,e.min.z,e.max.x,e.max.y,e.max.z])}updateViewport(e,s){e===this._vpW&&s===this._vpH||(this._vpW=e,this._vpH=s,this.material.updateViewport(e,s))}sort(e){e.getWorldPosition(this._camPosW),e.getWorldDirection(this._camDirW),this.invModelMatrix.copy(this.matrixWorld).invert(),this._camPosL.copy(this._camPosW).applyMatrix4(this.invModelMatrix),this._camDirL.copy(this._camDirW).transformDirection(this.invModelMatrix);const s=this.lastCameraPositionLocal.distanceToSquared(this._camPosL)>1e-6,n=this.lastCameraDirectionLocal.dot(this._camDirL)<.999;this.options.autoSort&&(s||n)&&(this.lastCameraPositionLocal.copy(this._camPosL),this.lastCameraDirectionLocal.copy(this._camDirL),this.sorter.setCamera(this._camPosL,this._camDirL))}onBeforeRender(e,s,n){this.sort(n),e.getSize(this._size),this.updateViewport(this._size.x,this._size.y)}dispose(){this.sorter.removeEventListener("updated",this.onSorterUpdated),this.sorter.dispose(),this.geometry.dispose(),this.material.dispose(),this.textureManager.dispose()}};x(vt,"INSTANCE_SIZE",128);let It=vt;const yt=.28209479177387814;class Mt{static packPly(t){const e=t.numSplats,s=Math.ceil(Math.sqrt(e)),n=Math.ceil(e/s),r=s*n,{ranges:o,colorScale:i}=this.calculatePlyRanges(t),u=new Uint32Array(r*4),y=new Uint8Array(r*4),m=new l.Quaternion;for(let c=0;c<e;c++){const h=c*4,d=c*3,w=c*4,A=t.positions[d+0],b=t.positions[d+1],z=t.positions[d+2],_=this.clamp01(this.norm(A,o.means.min.x,o.means.max.x)),F=this.clamp01(this.norm(b,o.means.min.y,o.means.max.y)),O=this.clamp01(this.norm(z,o.means.min.z,o.means.max.z)),V=_*65535|0,k=F*65535|0,M=O*65535|0;u[h+0]=this.pack4Bytes(V&255,k&255,M&255,0),u[h+1]=this.pack4Bytes(V>>8,k>>8,M>>8,0),m.set(t.rotations[w],t.rotations[w+1],t.rotations[w+2],t.rotations[w+3]).normalize();let B=m.w,S=m.x,g=m.y,v=m.z;const U=Math.abs(B),T=Math.abs(S),I=Math.abs(g),P=Math.abs(v);let f=0,C=U;T>C&&(C=T,f=1),I>C&&(C=I,f=2),P>C&&(C=P,f=3),(f===0?B:f===1?S:f===2?g:v)<0&&(B=-B,S=-S,g=-g,v=-v);let W=0,R=0,K=0;f===0&&(W=S,R=g,K=v),f===1&&(W=B,R=g,K=v),f===2&&(W=B,R=S,K=v),f===3&&(W=B,R=S,K=g);const X=rt=>Math.min(255,Math.max(0,Math.round((.5+rt/Math.SQRT2)*255)));u[h+2]=this.pack4Bytes(X(W),X(R),X(K),f);const Z=this.norm(t.scales[d+0],o.scales.min.x,o.scales.max.x),D=this.norm(t.scales[d+1],o.scales.min.y,o.scales.max.y),p=this.norm(t.scales[d+2],o.scales.min.z,o.scales.max.z);u[h+3]=this.pack4Bytes(Math.floor(Z*255),Math.floor(D*255),Math.floor(p*255),0);const E=this.clamp01(t.colors[d+0]*i),L=this.clamp01(t.colors[d+1]*i),q=this.clamp01(t.colors[d+2]*i),G=(E-.5)/yt,Q=(L-.5)/yt,$=(q-.5)/yt,J=this.clamp01(this.norm(G,o.sh0.min.x,o.sh0.max.x)),N=this.clamp01(this.norm(Q,o.sh0.min.y,o.sh0.max.y)),tt=this.clamp01(this.norm($,o.sh0.min.z,o.sh0.max.z)),nt=this.clamp01(t.opacities[c]);y[h+0]=Math.round(J*255),y[h+1]=Math.round(N*255),y[h+2]=Math.round(tt*255),y[h+3]=Math.round(nt*255)}return new At(e,s,n,t.positions,u,y,o,t.boundingBox)}static packSogs(t){var g,v,U;const e=t.numSplats;let s=Math.ceil(Math.sqrt(e)),n=Math.ceil(e/s);const r=((g=t.means_l)==null?void 0:g.image)??((v=t.sh0)==null?void 0:v.image)??((U=t.quats)==null?void 0:U.image);r&&typeof r.width=="number"&&typeof r.height=="number"&&(s=r.width,n=r.height);const o=s*n;if(o<e)throw new Error(`SOG v1 texture too small: ${s}x${n}=${o} < count=${e}`);const i=this.convertSogsRanges(t.ranges),u=t.ranges.means.mins[0],y=t.ranges.means.mins[1],m=t.ranges.means.mins[2],c=t.ranges.means.maxs[0],h=t.ranges.means.maxs[1],d=t.ranges.means.maxs[2],w=T=>Math.sign(T)*(Math.exp(Math.abs(T))-1),A=new l.Vector3(w(u),w(y),w(m)),b=new l.Vector3(w(c),w(h),w(d));i.means.min.copy(A),i.means.max.copy(b);const z=t,_=this.getPixels(z.means_l),F=this.getPixels(z.means_u),O=this.getPixels(z.quats),V=this.getPixels(z.scales),k=this.getPixels(z.sh0),M=new Uint32Array(o*4),B=new Uint8Array(o*4),S=new Float32Array(e*3);for(let T=0;T<e;T++){const I=T*4,P=F[I+0],f=_[I+0],C=F[I+1],Y=_[I+1],W=F[I+2],R=_[I+2],K=(P<<8|f)/65535,X=(C<<8|Y)/65535,Z=(W<<8|R)/65535,D=this.sogsDecode(K,u,c),p=this.sogsDecode(X,y,h),E=this.sogsDecode(Z,m,d);S[T*3+0]=D,S[T*3+1]=p,S[T*3+2]=E;const L=this.clamp01(this.norm(D,A.x,b.x))*65535|0,q=this.clamp01(this.norm(p,A.y,b.y))*65535|0,G=this.clamp01(this.norm(E,A.z,b.z))*65535|0;M[I+0]=this.pack4Bytes(L&255,q&255,G&255,0),M[I+1]=this.pack4Bytes(L>>8,q>>8,G>>8,0),M[I+3]=this.pack4Bytes(V[I],V[I+1],V[I+2],0);const $=O[I+3]-252;M[I+2]=this.pack4Bytes(O[I+0],O[I+1],O[I+2],$),B[I+0]=k[I],B[I+1]=k[I+1],B[I+2]=k[I+2];const J=k[I+3]/255,N=t.ranges.sh0.mins[3]+(t.ranges.sh0.maxs[3]-t.ranges.sh0.mins[3])*J,tt=1/(1+Math.exp(-N));B[I+3]=Math.round(Math.max(0,Math.min(1,tt))*255)}return new At(e,s,n,S,M,B,i,t.boundingBox)}static packSog2(t){var U,T,I;const e=t.numSplats;let s=Math.ceil(Math.sqrt(e)),n=Math.ceil(e/s);const r=((U=t.means_l)==null?void 0:U.image)??((T=t.sh0)==null?void 0:T.image)??((I=t.quats)==null?void 0:I.image);r&&typeof r.width=="number"&&typeof r.height=="number"&&(s=r.width,n=r.height);const o=s*n;if(o<e)throw new Error(`SOG v2 texture too small: ${s}x${n}=${o} < count=${e}`);const i=t.ranges.means.mins[0],u=t.ranges.means.mins[1],y=t.ranges.means.mins[2],m=t.ranges.means.maxs[0],c=t.ranges.means.maxs[1],h=t.ranges.means.maxs[2],d=P=>Math.sign(P)*(Math.exp(Math.abs(P))-1),w=new l.Vector3(d(i),d(u),d(y)),A=new l.Vector3(d(m),d(c),d(h)),b=P=>{let f=1/0,C=-1/0;for(const R of P)Number.isFinite(R)&&(f=Math.min(f,R),C=Math.max(C,R));(!Number.isFinite(f)||!Number.isFinite(C))&&(f=0,C=1);const Y=C-f||1,W=new Uint8Array(256);for(let R=0;R<256;R++){const X=((R<P.length&&Number.isFinite(P[R])?P[R]:f+(C-f)*(R/255))-f)/Y,Z=Math.max(0,Math.min(255,Math.round(X*255)));W[R]=Z}return{cbMin:f,cbMax:C,lut:W}},z=b(t.ranges.scales.codebook),_=b(t.ranges.sh0.codebook),F={means:{min:w.clone(),max:A.clone()},scales:{min:new l.Vector3(z.cbMin,z.cbMin,z.cbMin),max:new l.Vector3(z.cbMax,z.cbMax,z.cbMax)},sh0:{min:new l.Vector3(_.cbMin,_.cbMin,_.cbMin),max:new l.Vector3(_.cbMax,_.cbMax,_.cbMax)}},O=this.getPixels(t.means_l),V=this.getPixels(t.means_u),k=this.getPixels(t.quats),M=this.getPixels(t.scales),B=this.getPixels(t.sh0),S=new Uint32Array(o*4),g=new Uint8Array(o*4),v=new Float32Array(e*3);for(let P=0;P<e;P++){const f=P*4,C=V[f+0],Y=O[f+0],W=V[f+1],R=O[f+1],K=V[f+2],X=O[f+2],Z=(C<<8|Y)/65535,D=(W<<8|R)/65535,p=(K<<8|X)/65535,E=this.sogsDecode(Z,i,m),L=this.sogsDecode(D,u,c),q=this.sogsDecode(p,y,h);v[P*3+0]=E,v[P*3+1]=L,v[P*3+2]=q;const G=this.clamp01(this.norm(E,w.x,A.x))*65535|0,Q=this.clamp01(this.norm(L,w.y,A.y))*65535|0,$=this.clamp01(this.norm(q,w.z,A.z))*65535|0;S[f+0]=this.pack4Bytes(G&255,Q&255,$&255,0),S[f+1]=this.pack4Bytes(G>>8,Q>>8,$>>8,0);const N=k[f+3]-252&3;S[f+2]=this.pack4Bytes(k[f+0],k[f+1],k[f+2],N);const tt=z.lut[M[f+0]],nt=z.lut[M[f+1]],rt=z.lut[M[f+2]];S[f+3]=this.pack4Bytes(tt,nt,rt,0),g[f+0]=_.lut[B[f+0]],g[f+1]=_.lut[B[f+1]],g[f+2]=_.lut[B[f+2]],g[f+3]=B[f+3]}return new At(e,s,n,v,S,g,F,t.boundingBox)}static pack4Bytes(t,e,s,n){return(t&255)<<24|(e&255)<<16|(s&255)<<8|n&255}static getPixels(t){const e=t.image,s=e.width,n=e.height;if(e.data&&(e.data instanceof Uint8Array||e.data instanceof Uint8ClampedArray))return new Uint8Array(e.data);const r=document.createElement("canvas");r.width=s,r.height=n;const o=r.getContext("2d",{willReadFrequently:!0});if(!o)throw new Error("Canvas init failed");return o.drawImage(e,0,0),new Uint8Array(o.getImageData(0,0,s,n).data)}static convertSogsRanges(t){const e=s=>new l.Vector3(s[0],s[1],s[2]);return{sh0:{min:e(t.sh0.mins),max:e(t.sh0.maxs)},means:{min:e(t.means.mins),max:e(t.means.maxs)},scales:{min:e(t.scales.mins),max:e(t.scales.maxs)}}}static calculatePlyRanges(t){const e=new l.Vector3(1/0,1/0,1/0),s=new l.Vector3(-1/0,-1/0,-1/0),n=new l.Vector3(1/0,1/0,1/0),r=new l.Vector3(-1/0,-1/0,-1/0),o=new l.Vector3(1/0,1/0,1/0),i=new l.Vector3(-1/0,-1/0,-1/0);let u=0;for(let m=0;m<t.numSplats;m++){const c=m*3,h=t.positions[c+0],d=t.positions[c+1],w=t.positions[c+2];e.x=Math.min(e.x,h),s.x=Math.max(s.x,h),e.y=Math.min(e.y,d),s.y=Math.max(s.y,d),e.z=Math.min(e.z,w),s.z=Math.max(s.z,w),n.x=Math.min(n.x,t.scales[c]),r.x=Math.max(r.x,t.scales[c]),n.y=Math.min(n.y,t.scales[c+1]),r.y=Math.max(r.y,t.scales[c+1]),n.z=Math.min(n.z,t.scales[c+2]),r.z=Math.max(r.z,t.scales[c+2]),u=Math.max(u,t.colors[c],t.colors[c+1],t.colors[c+2])}const y=u>1.5?1/255:1;for(let m=0;m<t.numSplats;m++){const c=m*3,h=this.clamp01(t.colors[c+0]*y),d=this.clamp01(t.colors[c+1]*y),w=this.clamp01(t.colors[c+2]*y),A=(h-.5)/yt,b=(d-.5)/yt,z=(w-.5)/yt;o.x=Math.min(o.x,A),i.x=Math.max(i.x,A),o.y=Math.min(o.y,b),i.y=Math.max(i.y,b),o.z=Math.min(o.z,z),i.z=Math.max(i.z,z)}return{colorScale:y,ranges:{sh0:{min:o,max:i},means:{min:e,max:s},scales:{min:n,max:r}}}}static clamp01(t){return Math.max(0,Math.min(1,t))}static norm(t,e,s){return(t-e)/(s-e||1)}static sogsDecode(t,e,s){const n=e+(s-e)*t;return Math.sign(n)*(Math.exp(Math.abs(n))-1)}}class Kt extends l.Loader{constructor(e){super(e);x(this,"requestId",0);x(this,"worker");x(this,"pendingCallbacks",new Map);this.withCredentials=!0;const s=this.createWorkerCode(),n=new Blob([s],{type:"application/javascript"});this.worker=new Worker(URL.createObjectURL(n)),this.worker.onmessage=this.onWorkerMessage.bind(this)}onWorkerMessage(e){const{requestId:s,error:n,result:r}=e.data,o=this.pendingCallbacks.get(s);if(!o)return console.warn(`PlyLoader: Received response for unknown request ${s}`);if(this.pendingCallbacks.delete(s),n)return o.reject(new Error(n));if(!r)return o.reject(new Error("Worker returned no result"));try{const i=new Xt(0);i.numSplats=r.numSplats,i.positions=new Float32Array(r.positions),i.rotations=new Float32Array(r.rotations),i.scales=new Float32Array(r.scales),i.colors=new Float32Array(r.colors),i.opacities=new Float32Array(r.opacities),i.boundingBox.min.set(r.boundingBox.minX,r.boundingBox.minY,r.boundingBox.minZ),i.boundingBox.max.set(r.boundingBox.maxX,r.boundingBox.maxY,r.boundingBox.maxZ),this.worker.terminate();const u=Mt.packPly(i);i.dispose(),o.resolve(u)}catch(i){o.reject(i)}}load(e,s,n,r){const o=new l.FileLoader(this.manager);o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setPath(this.path),o.setWithCredentials(this.withCredentials),o.load(e,i=>{this.parseAsync(i).then(u=>{s&&s(u)}).catch(u=>{r?r(u):console.error(u),this.manager.itemError(e)})},n,r)}loadAsync(e,s){return new Promise((n,r)=>{const o=new l.FileLoader(this.manager);o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setPath(this.path),o.setWithCredentials(this.withCredentials),o.load(e,i=>{this.parseAsync(i).then(n).catch(u=>{r(u),this.manager.itemError(e)})},s,i=>{r(i),this.manager.itemError(e)})})}parseAsync(e){return new Promise((s,n)=>{const r=this.requestId++;this.pendingCallbacks.set(r,{resolve:s,reject:n});const o={requestId:r,buffer:e};this.worker.postMessage(o,[e])})}dispose(){this.worker&&this.worker.terminate(),this.pendingCallbacks.clear()}createWorkerCode(){return`(${(function(){self.onmessage=n=>{const{requestId:r,buffer:o}=n.data;try{const i=s(o),u={requestId:r,result:i};self.postMessage(u,[i.positions,i.rotations,i.scales,i.colors,i.opacities])}catch(i){const u={requestId:r,error:i instanceof Error?i.message:String(i)};self.postMessage(u)}};function s(n){const r=new TextDecoder,o=new Uint8Array(n),i=[112,108,121,10],u=`
|
|
322
|
+
`;class je extends c.ShaderMaterial{constructor(t={}){const s={packedGeometry:{value:null},packedColor:{value:null},splatOrder:{value:null},meansMin:{value:new c.Vector3},meansMax:{value:new c.Vector3},scalesMin:{value:new c.Vector3},scalesMax:{value:new c.Vector3},sh0Min:{value:new c.Vector3},sh0Max:{value:new c.Vector3},texWidth:{value:0},viewport:{value:new c.Vector2(1,1)},numSplats:{value:0},animationProgress:{value:1},animationCenter:{value:new c.Vector3}};super({uniforms:s,vertexShader:Ne,fragmentShader:nt,transparent:!0,glslVersion:c.GLSL3,blendSrc:c.OneFactor,blendSrcAlpha:c.OneFactor,blending:c.CustomBlending,blendEquation:c.AddEquation,blendEquationAlpha:c.AddEquation,blendDst:c.OneMinusSrcAlphaFactor,blendDstAlpha:c.OneMinusSrcAlphaFactor,depthTest:!0,depthWrite:!1,side:c.DoubleSide,alphaTest:t.alphaTest??0,toneMapped:t.toneMapped??!1});d(this,"_shaderTemplate");t.alphaHash&&(this.alphaHash=!0,this.depthWrite=!0,this.blending=c.NoBlending),this._shaderTemplate=Ne}setTexWidth(t){this.uniforms.texWidth.value=t|0}updateViewport(t,s){this.uniforms.viewport.value.set(t,s)}setPackedGeometry(t){this.uniforms.packedGeometry.value=t}setPackedColor(t){this.uniforms.packedColor.value=t}setOrderTexture(t){this.uniforms.splatOrder.value=t}setRanges(t){this.uniforms.meansMin.value.copy(t.means.min),this.uniforms.meansMax.value.copy(t.means.max),this.uniforms.scalesMin.value.copy(t.scales.min),this.uniforms.scalesMax.value.copy(t.scales.max),this.uniforms.sh0Min.value.copy(t.sh0.min),this.uniforms.sh0Max.value.copy(t.sh0.max)}setNumSplats(t){this.uniforms.numSplats.value=t}setAnimation(t){let s=this._shaderTemplate;t&&t.type!=="none"?(s=s.replace("/* @ANIMATION_CODE */",t.shaderCode),s=s.replace("/* @ANIMATION_CALL */",`if (animationProgress < 1.0) {
|
|
323
|
+
applyAnimation(modelCenter, scale, clr, animationProgress, animationCenter);
|
|
324
|
+
}`)):(s=s.replace("/* @ANIMATION_CODE */",""),s=s.replace("/* @ANIMATION_CALL */","")),this.vertexShader=s,this.needsUpdate=!0}setAnimationProgress(t){this.uniforms.animationProgress.value=t}setAnimationCenter(t){this.uniforms.animationCenter.value.copy(t)}}const ve=class ve extends c.Mesh{constructor(t,s={}){const n=new je(s),r=ve.createInstancedGeometry(t.numSplats,ve.INSTANCE_SIZE);super(r,n);d(this,"sorter");d(this,"options");d(this,"splatData");d(this,"textureManager");d(this,"animation",null);d(this,"material");d(this,"geometry");d(this,"lastCameraPositionLocal",new c.Vector3);d(this,"lastCameraDirectionLocal",new c.Vector3);d(this,"invModelMatrix",new c.Matrix4);d(this,"_vpW",-1);d(this,"_vpH",-1);d(this,"_size",new c.Vector2);d(this,"_camPosW",new c.Vector3);d(this,"_camDirW",new c.Vector3);d(this,"_camPosL",new c.Vector3);d(this,"_camDirL",new c.Vector3);d(this,"onSorterUpdated",t=>{const s=t.count;this.geometry.instanceCount=Math.ceil(s/ve.INSTANCE_SIZE),this.material.setNumSplats(s)});this.geometry=r,this.material=n,this.options={autoSort:!0,...s},this.splatData=t,this.frustumCulled=!1,this.sorter=new Re,this.textureManager=new We(t);let i=this.createChunks()||void 0;if(i===null&&console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."),i=void 0,this.sorter.addEventListener("updated",this.onSorterUpdated),this.sorter.init(this.textureManager.orderTexture,this.splatData.centers,i??void 0,!this.options.keepSplatData),this.material.setRanges(t.ranges),this.material.setTexWidth(t.textureWidth),this.material.setPackedColor(this.textureManager.packedColor),this.material.setOrderTexture(this.textureManager.orderTexture),this.material.setPackedGeometry(this.textureManager.packedGeometry),this.material.setNumSplats(0),s.animation&&s.animation.type!=="none"){this.animation=new Ge(s.animation);const o=new c.Vector3;t.boundingBox.toBox3().getCenter(o),this.animation.setCenter(o);const u=Ie(s.animation.type);this.material.setAnimation(u),this.material.setAnimationCenter(o),this.material.setAnimationProgress(0)}this.geometry.boundingBox=t.boundingBox.toBox3(),this.geometry.boundingSphere=new c.Sphere,this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere),this.options.keepSplatData||(this.splatData=null)}static createInstancedGeometry(t,s){const n=Math.ceil(t/s),r=new c.BufferGeometry,i=new Float32Array([-1,-1,0,1,-1,0,1,1,0,-1,1,0]),o=new Uint16Array([0,1,2,0,2,3]),u=new Float32Array(4*3*s);for(let h=0;h<s;h++){const f=h*4*3;for(let w=0;w<4;w++)u[f+w*3+0]=i[w*3+0],u[f+w*3+1]=i[w*3+1],u[f+w*3+2]=h}const y=new Uint32Array(6*s);for(let h=0;h<s;h++){const f=h*6,w=h*4;y[f+0]=o[0]+w,y[f+1]=o[1]+w,y[f+2]=o[2]+w,y[f+3]=o[3]+w,y[f+4]=o[4]+w,y[f+5]=o[5]+w}r.setAttribute("position",new c.BufferAttribute(u,3)),r.setIndex(new c.BufferAttribute(y,1));const m=new c.InstancedBufferGeometry;m.index=r.index,m.setAttribute("position",r.getAttribute("position"));const l=new Uint32Array(n);for(let h=0;h<n;h++)l[h]=h*s;return m.setAttribute("splatInstanceIndex",new c.InstancedBufferAttribute(l,1,!1)),m.instanceCount=0,m}createChunks(){if(!this.splatData)return null;const t=this.splatData.boundingBox;return t.min.x===1/0||t.max.x===-1/0?null:new Float32Array([t.min.x,t.min.y,t.min.z,t.max.x,t.max.y,t.max.z])}updateViewport(t,s){t===this._vpW&&s===this._vpH||(this._vpW=t,this._vpH=s,this.material.updateViewport(t,s))}sort(t){t.getWorldPosition(this._camPosW),t.getWorldDirection(this._camDirW),this.invModelMatrix.copy(this.matrixWorld).invert(),this._camPosL.copy(this._camPosW).applyMatrix4(this.invModelMatrix),this._camDirL.copy(this._camDirW).transformDirection(this.invModelMatrix);const s=this.lastCameraPositionLocal.distanceToSquared(this._camPosL)>1e-6,n=this.lastCameraDirectionLocal.dot(this._camDirL)<.999;this.options.autoSort&&(s||n)&&(this.lastCameraPositionLocal.copy(this._camPosL),this.lastCameraDirectionLocal.copy(this._camDirL),this.sorter.setCamera(this._camPosL,this._camDirL))}onBeforeRender(t,s,n){if(this.sort(n),t.getSize(this._size),this.updateViewport(this._size.x,this._size.y),this.animation){if(!this.animation.isPlaying&&this.animation.shouldAutoPlay())return this.animation.play();if(!this.animation.isPlaying||this.animation.isComplete)return;const r=performance.now()/1e3;this.animation.update(r)&&this.material.setAnimationProgress(this.animation.progress)}}dispose(){this.sorter.removeEventListener("updated",this.onSorterUpdated),this.sorter.dispose(),this.geometry.dispose(),this.material.dispose(),this.textureManager.dispose()}};d(ve,"INSTANCE_SIZE",128);let _e=ve;const ye=.28209479177387814;class Me{static packPly(e){const t=e.numSplats,s=Math.ceil(Math.sqrt(t)),n=Math.ceil(t/s),r=s*n,{ranges:i,colorScale:o}=this.calculatePlyRanges(e),u=new Uint32Array(r*4),y=new Uint8Array(r*4),m=new c.Quaternion;for(let l=0;l<t;l++){const h=l*4,f=l*3,w=l*4,A=e.positions[f+0],b=e.positions[f+1],B=e.positions[f+2],F=this.clamp01(this.norm(A,i.means.min.x,i.means.max.x)),P=this.clamp01(this.norm(b,i.means.min.y,i.means.max.y)),U=this.clamp01(this.norm(B,i.means.min.z,i.means.max.z)),O=F*65535|0,C=P*65535|0,M=U*65535|0;u[h+0]=this.pack4Bytes(O&255,C&255,M&255,0),u[h+1]=this.pack4Bytes(O>>8,C>>8,M>>8,0),m.set(e.rotations[w],e.rotations[w+1],e.rotations[w+2],e.rotations[w+3]).normalize();let k=m.w,S=m.x,x=m.y,v=m.z;const R=Math.abs(k),V=Math.abs(S),I=Math.abs(x),q=Math.abs(v);let p=0,_=R;V>_&&(_=V,p=1),I>_&&(_=I,p=2),q>_&&(_=q,p=3),(p===0?k:p===1?S:p===2?x:v)<0&&(k=-k,S=-S,x=-x,v=-v);let W=0,T=0,K=0;p===0&&(W=S,T=x,K=v),p===1&&(W=k,T=x,K=v),p===2&&(W=k,T=S,K=v),p===3&&(W=k,T=S,K=x);const X=ae=>Math.min(255,Math.max(0,Math.round((.5+ae/Math.SQRT2)*255)));u[h+2]=this.pack4Bytes(X(W),X(T),X(K),p);const Z=this.norm(e.scales[f+0],i.scales.min.x,i.scales.max.x),z=this.norm(e.scales[f+1],i.scales.min.y,i.scales.max.y),g=this.norm(e.scales[f+2],i.scales.min.z,i.scales.max.z);u[h+3]=this.pack4Bytes(Math.floor(Z*255),Math.floor(z*255),Math.floor(g*255),0);const E=this.clamp01(e.colors[f+0]*o),L=this.clamp01(e.colors[f+1]*o),D=this.clamp01(e.colors[f+2]*o),G=(E-.5)/ye,Q=(L-.5)/ye,H=(D-.5)/ye,J=this.clamp01(this.norm(G,i.sh0.min.x,i.sh0.max.x)),$=this.clamp01(this.norm(Q,i.sh0.min.y,i.sh0.max.y)),ee=this.clamp01(this.norm(H,i.sh0.min.z,i.sh0.max.z)),ne=this.clamp01(e.opacities[l]);y[h+0]=Math.round(J*255),y[h+1]=Math.round($*255),y[h+2]=Math.round(ee*255),y[h+3]=Math.round(ne*255)}return new Ae(t,s,n,e.positions,u,y,i,e.boundingBox)}static packSogs(e){var x,v,R;const t=e.numSplats;let s=Math.ceil(Math.sqrt(t)),n=Math.ceil(t/s);const r=((x=e.means_l)==null?void 0:x.image)??((v=e.sh0)==null?void 0:v.image)??((R=e.quats)==null?void 0:R.image);r&&typeof r.width=="number"&&typeof r.height=="number"&&(s=r.width,n=r.height);const i=s*n;if(i<t)throw new Error(`SOG v1 texture too small: ${s}x${n}=${i} < count=${t}`);const o=this.convertSogsRanges(e.ranges),u=e.ranges.means.mins[0],y=e.ranges.means.mins[1],m=e.ranges.means.mins[2],l=e.ranges.means.maxs[0],h=e.ranges.means.maxs[1],f=e.ranges.means.maxs[2],w=V=>Math.sign(V)*(Math.exp(Math.abs(V))-1),A=new c.Vector3(w(u),w(y),w(m)),b=new c.Vector3(w(l),w(h),w(f));o.means.min.copy(A),o.means.max.copy(b);const B=e,F=this.getPixels(B.means_l),P=this.getPixels(B.means_u),U=this.getPixels(B.quats),O=this.getPixels(B.scales),C=this.getPixels(B.sh0),M=new Uint32Array(i*4),k=new Uint8Array(i*4),S=new Float32Array(t*3);for(let V=0;V<t;V++){const I=V*4,q=P[I+0],p=F[I+0],_=P[I+1],Y=F[I+1],W=P[I+2],T=F[I+2],K=(q<<8|p)/65535,X=(_<<8|Y)/65535,Z=(W<<8|T)/65535,z=this.sogsDecode(K,u,l),g=this.sogsDecode(X,y,h),E=this.sogsDecode(Z,m,f);S[V*3+0]=z,S[V*3+1]=g,S[V*3+2]=E;const L=this.clamp01(this.norm(z,A.x,b.x))*65535|0,D=this.clamp01(this.norm(g,A.y,b.y))*65535|0,G=this.clamp01(this.norm(E,A.z,b.z))*65535|0;M[I+0]=this.pack4Bytes(L&255,D&255,G&255,0),M[I+1]=this.pack4Bytes(L>>8,D>>8,G>>8,0),M[I+3]=this.pack4Bytes(O[I],O[I+1],O[I+2],0);const H=U[I+3]-252;M[I+2]=this.pack4Bytes(U[I+0],U[I+1],U[I+2],H),k[I+0]=C[I],k[I+1]=C[I+1],k[I+2]=C[I+2];const J=C[I+3]/255,$=e.ranges.sh0.mins[3]+(e.ranges.sh0.maxs[3]-e.ranges.sh0.mins[3])*J,ee=1/(1+Math.exp(-$));k[I+3]=Math.round(Math.max(0,Math.min(1,ee))*255)}return new Ae(t,s,n,S,M,k,o,e.boundingBox)}static packSog2(e){var R,V,I;const t=e.numSplats;let s=Math.ceil(Math.sqrt(t)),n=Math.ceil(t/s);const r=((R=e.means_l)==null?void 0:R.image)??((V=e.sh0)==null?void 0:V.image)??((I=e.quats)==null?void 0:I.image);r&&typeof r.width=="number"&&typeof r.height=="number"&&(s=r.width,n=r.height);const i=s*n;if(i<t)throw new Error(`SOG v2 texture too small: ${s}x${n}=${i} < count=${t}`);const o=e.ranges.means.mins[0],u=e.ranges.means.mins[1],y=e.ranges.means.mins[2],m=e.ranges.means.maxs[0],l=e.ranges.means.maxs[1],h=e.ranges.means.maxs[2],f=q=>Math.sign(q)*(Math.exp(Math.abs(q))-1),w=new c.Vector3(f(o),f(u),f(y)),A=new c.Vector3(f(m),f(l),f(h)),b=q=>{let p=1/0,_=-1/0;for(const T of q)Number.isFinite(T)&&(p=Math.min(p,T),_=Math.max(_,T));(!Number.isFinite(p)||!Number.isFinite(_))&&(p=0,_=1);const Y=_-p||1,W=new Uint8Array(256);for(let T=0;T<256;T++){const X=((T<q.length&&Number.isFinite(q[T])?q[T]:p+(_-p)*(T/255))-p)/Y,Z=Math.max(0,Math.min(255,Math.round(X*255)));W[T]=Z}return{cbMin:p,cbMax:_,lut:W}},B=b(e.ranges.scales.codebook),F=b(e.ranges.sh0.codebook),P={means:{min:w.clone(),max:A.clone()},scales:{min:new c.Vector3(B.cbMin,B.cbMin,B.cbMin),max:new c.Vector3(B.cbMax,B.cbMax,B.cbMax)},sh0:{min:new c.Vector3(F.cbMin,F.cbMin,F.cbMin),max:new c.Vector3(F.cbMax,F.cbMax,F.cbMax)}},U=this.getPixels(e.means_l),O=this.getPixels(e.means_u),C=this.getPixels(e.quats),M=this.getPixels(e.scales),k=this.getPixels(e.sh0),S=new Uint32Array(i*4),x=new Uint8Array(i*4),v=new Float32Array(t*3);for(let q=0;q<t;q++){const p=q*4,_=O[p+0],Y=U[p+0],W=O[p+1],T=U[p+1],K=O[p+2],X=U[p+2],Z=(_<<8|Y)/65535,z=(W<<8|T)/65535,g=(K<<8|X)/65535,E=this.sogsDecode(Z,o,m),L=this.sogsDecode(z,u,l),D=this.sogsDecode(g,y,h);v[q*3+0]=E,v[q*3+1]=L,v[q*3+2]=D;const G=this.clamp01(this.norm(E,w.x,A.x))*65535|0,Q=this.clamp01(this.norm(L,w.y,A.y))*65535|0,H=this.clamp01(this.norm(D,w.z,A.z))*65535|0;S[p+0]=this.pack4Bytes(G&255,Q&255,H&255,0),S[p+1]=this.pack4Bytes(G>>8,Q>>8,H>>8,0);const $=C[p+3]-252&3;S[p+2]=this.pack4Bytes(C[p+0],C[p+1],C[p+2],$);const ee=B.lut[M[p+0]],ne=B.lut[M[p+1]],ae=B.lut[M[p+2]];S[p+3]=this.pack4Bytes(ee,ne,ae,0),x[p+0]=F.lut[k[p+0]],x[p+1]=F.lut[k[p+1]],x[p+2]=F.lut[k[p+2]],x[p+3]=k[p+3]}return new Ae(t,s,n,v,S,x,P,e.boundingBox)}static pack4Bytes(e,t,s,n){return(e&255)<<24|(t&255)<<16|(s&255)<<8|n&255}static getPixels(e){const t=e.image,s=t.width,n=t.height;if(t.data&&(t.data instanceof Uint8Array||t.data instanceof Uint8ClampedArray))return new Uint8Array(t.data);const r=document.createElement("canvas");r.width=s,r.height=n;const i=r.getContext("2d",{willReadFrequently:!0});if(!i)throw new Error("Canvas init failed");return i.drawImage(t,0,0),new Uint8Array(i.getImageData(0,0,s,n).data)}static convertSogsRanges(e){const t=s=>new c.Vector3(s[0],s[1],s[2]);return{sh0:{min:t(e.sh0.mins),max:t(e.sh0.maxs)},means:{min:t(e.means.mins),max:t(e.means.maxs)},scales:{min:t(e.scales.mins),max:t(e.scales.maxs)}}}static calculatePlyRanges(e){const t=new c.Vector3(1/0,1/0,1/0),s=new c.Vector3(-1/0,-1/0,-1/0),n=new c.Vector3(1/0,1/0,1/0),r=new c.Vector3(-1/0,-1/0,-1/0),i=new c.Vector3(1/0,1/0,1/0),o=new c.Vector3(-1/0,-1/0,-1/0);let u=0;for(let m=0;m<e.numSplats;m++){const l=m*3,h=e.positions[l+0],f=e.positions[l+1],w=e.positions[l+2];t.x=Math.min(t.x,h),s.x=Math.max(s.x,h),t.y=Math.min(t.y,f),s.y=Math.max(s.y,f),t.z=Math.min(t.z,w),s.z=Math.max(s.z,w),n.x=Math.min(n.x,e.scales[l]),r.x=Math.max(r.x,e.scales[l]),n.y=Math.min(n.y,e.scales[l+1]),r.y=Math.max(r.y,e.scales[l+1]),n.z=Math.min(n.z,e.scales[l+2]),r.z=Math.max(r.z,e.scales[l+2]),u=Math.max(u,e.colors[l],e.colors[l+1],e.colors[l+2])}const y=u>1.5?1/255:1;for(let m=0;m<e.numSplats;m++){const l=m*3,h=this.clamp01(e.colors[l+0]*y),f=this.clamp01(e.colors[l+1]*y),w=this.clamp01(e.colors[l+2]*y),A=(h-.5)/ye,b=(f-.5)/ye,B=(w-.5)/ye;i.x=Math.min(i.x,A),o.x=Math.max(o.x,A),i.y=Math.min(i.y,b),o.y=Math.max(o.y,b),i.z=Math.min(i.z,B),o.z=Math.max(o.z,B)}return{colorScale:y,ranges:{sh0:{min:i,max:o},means:{min:t,max:s},scales:{min:n,max:r}}}}static clamp01(e){return Math.max(0,Math.min(1,e))}static norm(e,t,s){return(e-t)/(s-t||1)}static sogsDecode(e,t,s){const n=t+(s-t)*e;return Math.sign(n)*(Math.exp(Math.abs(n))-1)}}class at extends c.Loader{constructor(t,s){super(t);d(this,"requestId",0);d(this,"worker");d(this,"pendingCallbacks",new Map);this.withCredentials=(s==null?void 0:s.withCredentials)??!1;const n=this.createWorkerCode(),r=new Blob([n],{type:"application/javascript"});this.worker=new Worker(URL.createObjectURL(r)),this.worker.onmessage=this.onWorkerMessage.bind(this)}onWorkerMessage(t){const{requestId:s,error:n,result:r}=t.data,i=this.pendingCallbacks.get(s);if(!i)return console.warn(`PlyLoader: Received response for unknown request ${s}`);if(this.pendingCallbacks.delete(s),n)return i.reject(new Error(n));if(!r)return i.reject(new Error("Worker returned no result"));try{const o=new tt(0);o.numSplats=r.numSplats,o.positions=new Float32Array(r.positions),o.rotations=new Float32Array(r.rotations),o.scales=new Float32Array(r.scales),o.colors=new Float32Array(r.colors),o.opacities=new Float32Array(r.opacities),o.boundingBox.min.set(r.boundingBox.minX,r.boundingBox.minY,r.boundingBox.minZ),o.boundingBox.max.set(r.boundingBox.maxX,r.boundingBox.maxY,r.boundingBox.maxZ),this.worker.terminate();const u=Me.packPly(o);o.dispose(),i.resolve(u)}catch(o){i.reject(o)}}load(t,s,n,r){const i=new c.FileLoader(this.manager);i.setResponseType("arraybuffer"),i.setRequestHeader(this.requestHeader),i.setPath(this.path),i.setWithCredentials(this.withCredentials),i.load(t,o=>{this.parseAsync(o).then(u=>{s&&s(u)}).catch(u=>{r?r(u):console.error(u),this.manager.itemError(t)})},n,r)}loadAsync(t,s){return new Promise((n,r)=>{const i=new c.FileLoader(this.manager);i.setResponseType("arraybuffer"),i.setRequestHeader(this.requestHeader),i.setPath(this.path),i.setWithCredentials(this.withCredentials),i.load(t,o=>{this.parseAsync(o).then(n).catch(u=>{r(u),this.manager.itemError(t)})},s,o=>{r(o),this.manager.itemError(t)})})}parseAsync(t){return new Promise((s,n)=>{const r=this.requestId++;this.pendingCallbacks.set(r,{resolve:s,reject:n});const i={requestId:r,buffer:t};this.worker.postMessage(i,[t])})}dispose(){this.worker&&this.worker.terminate(),this.pendingCallbacks.clear()}createWorkerCode(){return`(${(function(){self.onmessage=n=>{const{requestId:r,buffer:i}=n.data;try{const o=s(i),u={requestId:r,result:o};self.postMessage(u,[o.positions,o.rotations,o.scales,o.colors,o.opacities])}catch(o){const u={requestId:r,error:o instanceof Error?o.message:String(o)};self.postMessage(u)}};function s(n){const r=new TextDecoder,i=new Uint8Array(n),o=[112,108,121,10],u=`
|
|
257
325
|
end_header
|
|
258
|
-
`;for(let
|
|
259
|
-
`),h=[];let d=null;for(let D=1;D<c.length;D++){const p=c[D].trim();if(p===""||p==="end_header")continue;const E=p.split(" ");switch(E[0]){case"format":d=E[1];break;case"element":h.push({name:E[1],count:parseInt(E[2],10),properties:[]});break;case"property":if(h.length===0)throw new Error("Invalid PLY file: Property without element");h[h.length-1].properties.push({type:E[1],name:E[2]});break}}if(d!=="binary_little_endian")throw new Error(`Unsupported PLY format: ${d}`);const w=h.find(D=>D.name==="vertex");if(!w)throw new Error("Invalid PLY file: No vertex element found");const A=w.count,b=new Float32Array(A*3),z=new Float32Array(A*4),_=new Float32Array(A*3),F=new Float32Array(A*3),O=new Float32Array(A),V=new DataView(n);let k=y;const M=D=>w.properties.findIndex(p=>p.name===D),B=M("x"),S=M("y"),g=M("z"),v=[M("rot_0"),M("rot_1"),M("rot_2"),M("rot_3")],U=[M("scale_0"),M("scale_1"),M("scale_2")],T=[M("f_dc_0"),M("f_dc_1"),M("f_dc_2")],I=M("opacity");if([B,S,g,...v,...U,...T,I].some(D=>D===-1))throw new Error("Invalid PLY file: Missing required properties");const f=.28209479177387814,C=D=>{if(D>0)return 1/(1+Math.exp(-D));const p=Math.exp(D);return p/(1+p)};let Y=1/0,W=1/0,R=1/0,K=-1/0,X=-1/0,Z=-1/0;for(let D=0;D<A;D++){const p=[];for(let Rt=0;Rt<w.properties.length;Rt++){const Zt=w.properties[Rt].type;let ht;switch(Zt){case"char":ht=V.getInt8(k),k+=1;break;case"uchar":ht=V.getUint8(k),k+=1;break;case"short":ht=V.getInt16(k,!0),k+=2;break;case"ushort":ht=V.getUint16(k,!0),k+=2;break;case"int":ht=V.getInt32(k,!0),k+=4;break;case"uint":ht=V.getUint32(k,!0),k+=4;break;case"float":ht=V.getFloat32(k,!0),k+=4;break;case"double":ht=V.getFloat64(k,!0),k+=8;break;default:throw new Error(`Unsupported property type: ${Zt}`)}p.push(ht)}const E=p[B],L=p[S],q=p[g],G=D*3;b[G]=E,b[G+1]=L,b[G+2]=q,Y=Math.min(Y,E),W=Math.min(W,L),R=Math.min(R,q),K=Math.max(K,E),X=Math.max(X,L),Z=Math.max(Z,q);let Q=p[v[1]],$=p[v[2]],J=p[v[3]],N=p[v[0]];const tt=Math.sqrt(Q*Q+$*$+J*J+N*N);tt>0&&(Q/=tt,$/=tt,J/=tt,N/=tt),N<0&&(Q=-Q,$=-$,J=-J,N=-N);const nt=D*4;z[nt]=Q,z[nt+1]=$,z[nt+2]=J,z[nt+3]=N;const rt=D*3;_[rt]=p[U[0]],_[rt+1]=p[U[1]],_[rt+2]=p[U[2]];let ft=.5+p[T[0]]*f,pt=.5+p[T[1]]*f,lt=.5+p[T[2]]*f;ft=Math.max(0,Math.min(1,ft)),pt=Math.max(0,Math.min(1,pt)),lt=Math.max(0,Math.min(1,lt));const Pt=D*3;F[Pt]=ft,F[Pt+1]=pt,F[Pt+2]=lt,O[D]=C(p[I])}return{numSplats:A,positions:b.buffer,rotations:z.buffer,scales:_.buffer,colors:F.buffer,opacities:O.buffer,boundingBox:{minX:Y,minY:W,minZ:R,maxX:K,maxY:X,maxZ:Z}}}}).toString()})();`}}var st=Uint8Array,wt=Uint16Array,te=Int32Array,Lt=new st([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),Gt=new st([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),ee=new st([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Wt=function(a,t){for(var e=new wt(31),s=0;s<31;++s)e[s]=t+=1<<a[s-1];for(var n=new te(e[30]),s=1;s<30;++s)for(var r=e[s];r<e[s+1];++r)n[r]=r-e[s]<<5|s;return{b:e,r:n}},jt=Wt(Lt,2),Nt=jt.b,se=jt.r;Nt[28]=258,se[258]=28;for(var ne=Wt(Gt,0),re=ne.b,Ct=new wt(32768),j=0;j<32768;++j){var ut=(j&43690)>>1|(j&21845)<<1;ut=(ut&52428)>>2|(ut&13107)<<2,ut=(ut&61680)>>4|(ut&3855)<<4,Ct[j]=((ut&65280)>>8|(ut&255)<<8)>>1}for(var bt=function(a,t,e){for(var s=a.length,n=0,r=new wt(t);n<s;++n)a[n]&&++r[a[n]-1];var o=new wt(t);for(n=1;n<t;++n)o[n]=o[n-1]+r[n-1]<<1;var i;if(e){i=new wt(1<<t);var u=15-t;for(n=0;n<s;++n)if(a[n])for(var y=n<<4|a[n],m=t-a[n],c=o[a[n]-1]++<<m,h=c|(1<<m)-1;c<=h;++c)i[Ct[c]>>u]=y}else for(i=new wt(s),n=0;n<s;++n)a[n]&&(i[n]=Ct[o[a[n]-1]++]>>15-a[n]);return i},St=new st(288),j=0;j<144;++j)St[j]=8;for(var j=144;j<256;++j)St[j]=9;for(var j=256;j<280;++j)St[j]=7;for(var j=280;j<288;++j)St[j]=8;for(var $t=new st(32),j=0;j<32;++j)$t[j]=5;var ae=bt(St,9,1),oe=bt($t,5,1),Bt=function(a){for(var t=a[0],e=1;e<a.length;++e)a[e]>t&&(t=a[e]);return t},ot=function(a,t,e){var s=t/8|0;return(a[s]|a[s+1]<<8)>>(t&7)&e},zt=function(a,t){var e=t/8|0;return(a[e]|a[e+1]<<8|a[e+2]<<16)>>(t&7)},ie=function(a){return(a+7)/8|0},Dt=function(a,t,e){return(t==null||t<0)&&(t=0),(e==null||e>a.length)&&(e=a.length),new st(a.subarray(t,e))},ce=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],at=function(a,t,e){var s=new Error(t||ce[a]);if(s.code=a,Error.captureStackTrace&&Error.captureStackTrace(s,at),!e)throw s;return s},le=function(a,t,e,s){var n=a.length,r=s?s.length:0;if(!n||t.f&&!t.l)return e||new st(0);var o=!e,i=o||t.i!=2,u=t.i;o&&(e=new st(n*3));var y=function($){var J=e.length;if($>J){var N=new st(Math.max(J*2,$));N.set(e),e=N}},m=t.f||0,c=t.p||0,h=t.b||0,d=t.l,w=t.d,A=t.m,b=t.n,z=n*8;do{if(!d){m=ot(a,c,1);var _=ot(a,c+1,3);if(c+=3,_)if(_==1)d=ae,w=oe,A=9,b=5;else if(_==2){var k=ot(a,c,31)+257,M=ot(a,c+10,15)+4,B=k+ot(a,c+5,31)+1;c+=14;for(var S=new st(B),g=new st(19),v=0;v<M;++v)g[ee[v]]=ot(a,c+v*3,7);c+=M*3;for(var U=Bt(g),T=(1<<U)-1,I=bt(g,U,1),v=0;v<B;){var P=I[ot(a,c,T)];c+=P&15;var F=P>>4;if(F<16)S[v++]=F;else{var f=0,C=0;for(F==16?(C=3+ot(a,c,3),c+=2,f=S[v-1]):F==17?(C=3+ot(a,c,7),c+=3):F==18&&(C=11+ot(a,c,127),c+=7);C--;)S[v++]=f}}var Y=S.subarray(0,k),W=S.subarray(k);A=Bt(Y),b=Bt(W),d=bt(Y,A,1),w=bt(W,b,1)}else at(1);else{var F=ie(c)+4,O=a[F-4]|a[F-3]<<8,V=F+O;if(V>n){u&&at(0);break}i&&y(h+O),e.set(a.subarray(F,V),h),t.b=h+=O,t.p=c=V*8,t.f=m;continue}if(c>z){u&&at(0);break}}i&&y(h+131072);for(var R=(1<<A)-1,K=(1<<b)-1,X=c;;X=c){var f=d[zt(a,c)&R],Z=f>>4;if(c+=f&15,c>z){u&&at(0);break}if(f||at(2),Z<256)e[h++]=Z;else if(Z==256){X=c,d=null;break}else{var D=Z-254;if(Z>264){var v=Z-257,p=Lt[v];D=ot(a,c,(1<<p)-1)+Nt[v],c+=p}var E=w[zt(a,c)&K],L=E>>4;E||at(3),c+=E&15;var W=re[L];if(L>3){var p=Gt[L];W+=zt(a,c)&(1<<p)-1,c+=p}if(c>z){u&&at(0);break}i&&y(h+131072);var q=h+D;if(h<W){var G=r-W,Q=Math.min(W,q);for(G+h<0&&at(3);h<Q;++h)e[h]=s[G+h]}for(;h<q;++h)e[h]=e[h-W]}}t.l=d,t.p=X,t.b=h,t.f=m,d&&(m=1,t.m=A,t.d=w,t.n=b)}while(!m);return h!=e.length&&o?Dt(e,0,h):e.subarray(0,h)},he=new st(0),ct=function(a,t){return a[t]|a[t+1]<<8},it=function(a,t){return(a[t]|a[t+1]<<8|a[t+2]<<16|a[t+3]<<24)>>>0},Et=function(a,t){return it(a,t)+it(a,t+4)*4294967296};function ue(a,t){return le(a,{i:2},t&&t.out,t&&t.dictionary)}var qt=typeof TextDecoder<"u"&&new TextDecoder,me=0;try{qt.decode(he,{stream:!0}),me=1}catch{}var de=function(a){for(var t="",e=0;;){var s=a[e++],n=(s>127)+(s>223)+(s>239);if(e+n>a.length)return{s:t,r:Dt(a,e-1)};n?n==3?(s=((s&15)<<18|(a[e++]&63)<<12|(a[e++]&63)<<6|a[e++]&63)-65536,t+=String.fromCharCode(55296|s>>10,56320|s&1023)):n&1?t+=String.fromCharCode((s&31)<<6|a[e++]&63):t+=String.fromCharCode((s&15)<<12|(a[e++]&63)<<6|a[e++]&63):t+=String.fromCharCode(s)}};function fe(a,t){if(t){for(var e="",s=0;s<a.length;s+=16384)e+=String.fromCharCode.apply(null,a.subarray(s,s+16384));return e}else{if(qt)return qt.decode(a);var n=de(a),r=n.s,e=n.r;return e.length&&at(8),r}}var pe=function(a,t){return t+30+ct(a,t+26)+ct(a,t+28)},xe=function(a,t,e){var s=ct(a,t+28),n=fe(a.subarray(t+46,t+46+s),!(ct(a,t+8)&2048)),r=t+46+s,o=it(a,t+20),i=e&&o==4294967295?ge(a,r):[o,it(a,t+24),it(a,t+42)],u=i[0],y=i[1],m=i[2];return[ct(a,t+10),u,y,n,r+ct(a,t+30)+ct(a,t+32),m]},ge=function(a,t){for(;ct(a,t)!=1;t+=4+ct(a,t+2));return[Et(a,t+12),Et(a,t+4),Et(a,t+20)]};function ye(a,t){for(var e={},s=a.length-22;it(a,s)!=101010256;--s)(!s||a.length-s>65558)&&at(13);var n=ct(a,s+8);if(!n)return{};var r=it(a,s+16),o=r==4294967295||n==65535;if(o){var i=it(a,s-12);o=it(a,i)==101075792,o&&(n=it(a,i+32),r=it(a,i+48))}for(var u=0;u<n;++u){var y=xe(a,r,o),m=y[0],c=y[1],h=y[2],d=y[3],w=y[4],A=y[5],b=pe(a,A);r=w,m?m==8?e[d]=ue(a.subarray(b,b+c),{out:new st(h)}):at(14,"unknown compression type "+m):e[d]=Dt(a,b,b+c)}return e}const kt=a=>typeof a=="number"&&Number.isFinite(a),mt=(a,t)=>{const e=a[t];if(typeof e!="object"||e===null)throw new Error(`Invalid SOG metadata section: ${t}`);return e},dt=(a,t)=>{const e=a.files;if(!Array.isArray(e))throw new Error(`${t}.files is not an array`);if(!e.every(s=>typeof s=="string"))throw new Error(`${t}.files contains non-strings`);return e},Ft=(a,t)=>{const e=a.mins,s=a.maxs;if(!Array.isArray(e)||e.length!==3)throw new Error(`${t}.mins must be length-3`);if(!Array.isArray(s)||s.length!==3)throw new Error(`${t}.maxs must be length-3`);if(![...e,...s].every(kt))throw new Error(`${t}.mins/maxs must be finite numbers`);return{mins:[e[0],e[1],e[2]],maxs:[s[0],s[1],s[2]]}},we=(a,t)=>{const e=a.mins,s=a.maxs;if(!Array.isArray(e)||e.length!==4)throw new Error(`${t}.mins must be length-4`);if(!Array.isArray(s)||s.length!==4)throw new Error(`${t}.maxs must be length-4`);if(![...e,...s].every(kt))throw new Error(`${t}.mins/maxs must be finite numbers`);return{mins:[e[0],e[1],e[2],e[3]],maxs:[s[0],s[1],s[2],s[3]]}},Ht=(a,t)=>{const e=a.codebook;if(!Array.isArray(e))throw new Error(`${t}.codebook is not an array`);if(!e.every(kt))throw new Error(`${t}.codebook contains non-finite numbers`);return e},Yt=a=>{if(typeof a!="object"||a===null)throw new Error("Invalid SOG metadata: not an object");const t=a,e=t.version??1;if(e!==1&&e!==2)throw new Error(`Unsupported SOG version: ${String(e)}`);if(e===1){const m=mt(t,"means"),c=mt(t,"sh0"),h=mt(t,"quats"),d=mt(t,"scales"),w=typeof t.count=="number"&&Number.isFinite(t.count)?t.count:void 0,A=Array.isArray(m.shape)?m.shape:void 0,b=A&&typeof A[0]=="number"?A[0]:void 0;if(w===void 0&&b===void 0)throw new Error("Invalid SOGS metadata: unable to determine splat count");if(w!==void 0&&b!==void 0&&w!==b)throw new Error("Inconsistent SOGS metadata: count does not match means.shape[0]");return{version:1,numSplats:(w??b)|0,files:{sh0:dt(c,"sh0"),means:dt(m,"means"),quats:dt(h,"quats"),scales:dt(d,"scales")},ranges:{sh0:we(c,"sh0"),means:Ft(m,"means"),scales:Ft(d,"scales")}}}const s=t.count;if(!kt(s))throw new Error('Invalid SOG v2 metadata: missing/invalid "count"');const n=s|0,r=mt(t,"means"),o=mt(t,"sh0"),i=mt(t,"quats"),u=mt(t,"scales");return{version:2,numSplats:n,files:{sh0:dt(o,"sh0"),means:dt(r,"means"),quats:dt(i,"quats"),scales:dt(u,"scales")},ranges:{means:Ft(r,"means"),sh0:{codebook:Ht(o,"sh0")},scales:{codebook:Ht(u,"scales")}},antialias:typeof t.antialias=="boolean"?t.antialias:void 0}};class ve extends l.Loader{constructor(t){super(t),this.withCredentials=!0}isZipBuffer(t){if(t.byteLength<4)return!1;const e=new Uint8Array(t,0,4);return e[0]===80&&e[1]===75&&e[2]===3&&e[3]===4}load(t,e,s,n){const r=new l.FileLoader(this.manager);r.setResponseType("arraybuffer"),r.setRequestHeader(this.requestHeader),r.setPath(this.path),r.setWithCredentials(this.withCredentials),r.load(t,o=>{this.parseAsync(t,o).then(i=>{e&&e(i)}).catch(i=>{this.manager.itemError(t),n&&n(i),console.error("Error loading SOGS meta:",i)})},s,n)}loadAsync(t,e){return new Promise((s,n)=>{const r=new l.FileLoader(this.manager);r.setResponseType("arraybuffer"),r.setRequestHeader(this.requestHeader),r.setPath(this.path),r.setWithCredentials(this.withCredentials),r.load(t,o=>{this.parseAsync(t,o).then(s).catch(i=>{n(i),this.manager.itemError(t)})},e,o=>{n(o),this.manager.itemError(t)})})}async parseAsync(t,e){if(!(e instanceof ArrayBuffer))throw new Error("SOGS loader: expected ArrayBuffer payload");if(this.isZipBuffer(e))return this.parseZipAsync(e);const n=new TextDecoder("utf-8").decode(e),r=JSON.parse(n);return this.parseMetaAsync(t,r)}async parseMetaAsync(t,e){const s=Yt(e),{numSplats:n,files:r,ranges:o,version:i}=s,u=new l.TextureLoader(this.manager);u.setPath(this.path),u.setRequestHeader(this.requestHeader),u.setWithCredentials(this.withCredentials);const y=(F,O)=>{try{return new URL(O,F).toString()}catch{return F.substring(0,F.lastIndexOf("/")+1)+O}},m=(F,O)=>{const V=y(t,F);return new Promise((k,M)=>{u.load(V,B=>{B.generateMipmaps=!1,B.magFilter=l.NearestFilter,B.minFilter=l.NearestFilter,B.flipY=!1,k(B)},void 0,B=>{const S=B instanceof Error?B.message:String(B);M(new Error(`SOGS loader: failed to load ${O} (${F}): ${S}`))})})};if(!Array.isArray(r.sh0)||r.sh0.length<1)throw new Error("SOGS loader: files.sh0 must have at least 1 entry (sh0)");if(!Array.isArray(r.means)||r.means.length<2)throw new Error("SOGS loader: files.means must have at least 2 entries (means_l, means_u)");if(!Array.isArray(r.quats)||r.quats.length<1)throw new Error("SOGS loader: files.quats must have at least 1 entry");if(!Array.isArray(r.scales)||r.scales.length<1)throw new Error("SOGS loader: files.scales must have at least 1 entry");const[c,h,d,w,A]=await Promise.all([m(r.means[0],"means_l"),m(r.means[1],"means_u"),m(r.quats[0],"quats"),m(r.scales[0],"scales"),m(r.sh0[0],"sh0")]),b={means_l:c,means_u:h,quats:d,scales:w,sh0:A};if(i===1){const F=new _t(n,o,b),O=Mt.packSogs(F);return F.dispose(),O}const z=new Tt(n,o,b),_=Mt.packSog2(z);return z.dispose(),_}async parseZipAsync(t){const e=ye(new Uint8Array(t)),s=Object.keys(e),n=s.find(g=>g.toLowerCase().endsWith("meta.json"))??null;if(!n)throw new Error("SOGS loader: zip missing meta.json");const r=n.includes("/")?n.slice(0,n.lastIndexOf("/")+1):"",o=new TextDecoder,i=JSON.parse(o.decode(e[n])),u=Yt(i),{numSplats:y,files:m,ranges:c,version:h}=u,d=g=>g.replace(/\\/g,"/").replace(/^\.?\//,""),w=g=>{const v=d(g),U=[d(r+v),v];for(const P of U){const f=e[P];if(f)return f}const T=v.split("/").pop(),I=s.find(P=>d(P).endsWith("/"+v))??s.find(P=>d(P).endsWith("/"+T))??s.find(P=>d(P)===T)??null;if(I)return e[I];throw new Error(`SOGS loader: zip missing file "${g}"`)},A=g=>{const v=g.toLowerCase();return v.endsWith(".png")?"image/png":v.endsWith(".jpg")||v.endsWith(".jpeg")?"image/jpeg":v.endsWith(".webp")?"image/webp":"application/octet-stream"},b=new l.TextureLoader(this.manager);b.setRequestHeader(this.requestHeader),b.setWithCredentials(this.withCredentials);const z=(g,v)=>{const U=w(g),T=new Blob([U],{type:A(g)}),I=URL.createObjectURL(T);return new Promise((P,f)=>{b.load(I,C=>{URL.revokeObjectURL(I),C.generateMipmaps=!1,C.magFilter=l.NearestFilter,C.minFilter=l.NearestFilter,C.flipY=!1,P(C)},void 0,C=>{URL.revokeObjectURL(I);const Y=C instanceof Error?C.message:String(C);f(new Error(`SOGS loader: failed to load ${v} from zip (${g}): ${Y}`))})})};if(!Array.isArray(m.sh0)||m.sh0.length<1)throw new Error("SOGS loader: files.sh0 must have at least 1 entry (sh0)");if(!Array.isArray(m.means)||m.means.length<2)throw new Error("SOGS loader: files.means must have at least 2 entries (means_l, means_u)");if(!Array.isArray(m.quats)||m.quats.length<1)throw new Error("SOGS loader: files.quats must have at least 1 entry");if(!Array.isArray(m.scales)||m.scales.length<1)throw new Error("SOGS loader: files.scales must have at least 1 entry");const[_,F,O,V,k]=await Promise.all([z(m.means[0],"means_l"),z(m.means[1],"means_u"),z(m.quats[0],"quats"),z(m.scales[0],"scales"),z(m.sh0[0],"sh0")]),M={means_l:_,means_u:F,quats:O,scales:V,sh0:k};if(h===1){const g=new _t(y,c,M),v=Mt.packSogs(g);return g.dispose(),v}const B=new Tt(y,c,M),S=Mt.packSog2(B);return B.dispose(),S}}const Me="0.3.0";H.BoundingBox=gt,H.PlyLoader=Kt,H.SogsLoader=ve,H.SplatData=At,H.SplatMaterial=Ot,H.SplatMesh=It,H.SplatSorter=Vt,H.TextureManager=Ut,H.VERSION=Me,Object.defineProperty(H,Symbol.toStringTag,{value:"Module"})});
|
|
326
|
+
`;for(let z=0;z<o.length;z++)if(i[z]!==o[z])throw new Error("Invalid PLY file: Missing magic bytes");let y=0;for(let z=0;z<i.length-u.length;z++){let g=!0;for(let E=0;E<u.length;E++)if(i[z+E]!==u.charCodeAt(E)){g=!1;break}if(g){y=z+u.length;break}}if(y===0)throw new Error("Invalid PLY file: Could not find end of header");const l=r.decode(i.subarray(0,y)).split(`
|
|
327
|
+
`),h=[];let f=null;for(let z=1;z<l.length;z++){const g=l[z].trim();if(g===""||g==="end_header")continue;const E=g.split(" ");switch(E[0]){case"format":f=E[1];break;case"element":h.push({name:E[1],count:parseInt(E[2],10),properties:[]});break;case"property":if(h.length===0)throw new Error("Invalid PLY file: Property without element");h[h.length-1].properties.push({type:E[1],name:E[2]});break}}if(f!=="binary_little_endian")throw new Error(`Unsupported PLY format: ${f}`);const w=h.find(z=>z.name==="vertex");if(!w)throw new Error("Invalid PLY file: No vertex element found");const A=w.count,b=new Float32Array(A*3),B=new Float32Array(A*4),F=new Float32Array(A*3),P=new Float32Array(A*3),U=new Float32Array(A),O=new DataView(n);let C=y;const M=z=>w.properties.findIndex(g=>g.name===z),k=M("x"),S=M("y"),x=M("z"),v=[M("rot_0"),M("rot_1"),M("rot_2"),M("rot_3")],R=[M("scale_0"),M("scale_1"),M("scale_2")],V=[M("f_dc_0"),M("f_dc_1"),M("f_dc_2")],I=M("opacity");if([k,S,x,...v,...R,...V,I].some(z=>z===-1))throw new Error("Invalid PLY file: Missing required properties");const p=.28209479177387814,_=z=>{if(z>0)return 1/(1+Math.exp(-z));const g=Math.exp(z);return g/(1+g)};let Y=1/0,W=1/0,T=1/0,K=-1/0,X=-1/0,Z=-1/0;for(let z=0;z<A;z++){const g=[];for(let Fe=0;Fe<w.properties.length;Fe++){const et=w.properties[Fe].type;let he;switch(et){case"char":he=O.getInt8(C),C+=1;break;case"uchar":he=O.getUint8(C),C+=1;break;case"short":he=O.getInt16(C,!0),C+=2;break;case"ushort":he=O.getUint16(C,!0),C+=2;break;case"int":he=O.getInt32(C,!0),C+=4;break;case"uint":he=O.getUint32(C,!0),C+=4;break;case"float":he=O.getFloat32(C,!0),C+=4;break;case"double":he=O.getFloat64(C,!0),C+=8;break;default:throw new Error(`Unsupported property type: ${et}`)}g.push(he)}const E=g[k],L=g[S],D=g[x],G=z*3;b[G]=E,b[G+1]=L,b[G+2]=D,Y=Math.min(Y,E),W=Math.min(W,L),T=Math.min(T,D),K=Math.max(K,E),X=Math.max(X,L),Z=Math.max(Z,D);let Q=g[v[1]],H=g[v[2]],J=g[v[3]],$=g[v[0]];const ee=Math.sqrt(Q*Q+H*H+J*J+$*$);ee>0&&(Q/=ee,H/=ee,J/=ee,$/=ee),$<0&&(Q=-Q,H=-H,J=-J,$=-$);const ne=z*4;B[ne]=Q,B[ne+1]=H,B[ne+2]=J,B[ne+3]=$;const ae=z*3;F[ae]=g[R[0]],F[ae+1]=g[R[1]],F[ae+2]=g[R[2]];let fe=.5+g[V[0]]*p,pe=.5+g[V[1]]*p,le=.5+g[V[2]]*p;fe=Math.max(0,Math.min(1,fe)),pe=Math.max(0,Math.min(1,pe)),le=Math.max(0,Math.min(1,le));const Te=z*3;P[Te]=fe,P[Te+1]=pe,P[Te+2]=le,U[z]=_(g[I])}return{numSplats:A,positions:b.buffer,rotations:B.buffer,scales:F.buffer,colors:P.buffer,opacities:U.buffer,boundingBox:{minX:Y,minY:W,minZ:T,maxX:K,maxY:X,maxZ:Z}}}}).toString()})();`}}var se=Uint8Array,we=Uint16Array,rt=Int32Array,$e=new se([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),He=new se([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),it=new se([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Ye=function(a,e){for(var t=new we(31),s=0;s<31;++s)t[s]=e+=1<<a[s-1];for(var n=new rt(t[30]),s=1;s<30;++s)for(var r=t[s];r<t[s+1];++r)n[r]=r-t[s]<<5|s;return{b:t,r:n}},Ze=Ye($e,2),Xe=Ze.b,ot=Ze.r;Xe[28]=258,ot[258]=28;for(var ct=Ye(He,0),lt=ct.b,ke=new we(32768),N=0;N<32768;++N){var ue=(N&43690)>>1|(N&21845)<<1;ue=(ue&52428)>>2|(ue&13107)<<2,ue=(ue&61680)>>4|(ue&3855)<<4,ke[N]=((ue&65280)>>8|(ue&255)<<8)>>1}for(var be=function(a,e,t){for(var s=a.length,n=0,r=new we(e);n<s;++n)a[n]&&++r[a[n]-1];var i=new we(e);for(n=1;n<e;++n)i[n]=i[n-1]+r[n-1]<<1;var o;if(t){o=new we(1<<e);var u=15-e;for(n=0;n<s;++n)if(a[n])for(var y=n<<4|a[n],m=e-a[n],l=i[a[n]-1]++<<m,h=l|(1<<m)-1;l<=h;++l)o[ke[l]>>u]=y}else for(o=new we(s),n=0;n<s;++n)a[n]&&(o[n]=ke[i[a[n]-1]++]>>15-a[n]);return o},Se=new se(288),N=0;N<144;++N)Se[N]=8;for(var N=144;N<256;++N)Se[N]=9;for(var N=256;N<280;++N)Se[N]=7;for(var N=280;N<288;++N)Se[N]=8;for(var Qe=new se(32),N=0;N<32;++N)Qe[N]=5;var ht=be(Se,9,1),ut=be(Qe,5,1),Be=function(a){for(var e=a[0],t=1;t<a.length;++t)a[t]>e&&(e=a[t]);return e},ie=function(a,e,t){var s=e/8|0;return(a[s]|a[s+1]<<8)>>(e&7)&t},ze=function(a,e){var t=e/8|0;return(a[t]|a[t+1]<<8|a[t+2]<<16)>>(e&7)},mt=function(a){return(a+7)/8|0},Ee=function(a,e,t){return(e==null||e<0)&&(e=0),(t==null||t>a.length)&&(t=a.length),new se(a.subarray(e,t))},dt=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],re=function(a,e,t){var s=new Error(e||dt[a]);if(s.code=a,Error.captureStackTrace&&Error.captureStackTrace(s,re),!t)throw s;return s},ft=function(a,e,t,s){var n=a.length,r=s?s.length:0;if(!n||e.f&&!e.l)return t||new se(0);var i=!t,o=i||e.i!=2,u=e.i;i&&(t=new se(n*3));var y=function(H){var J=t.length;if(H>J){var $=new se(Math.max(J*2,H));$.set(t),t=$}},m=e.f||0,l=e.p||0,h=e.b||0,f=e.l,w=e.d,A=e.m,b=e.n,B=n*8;do{if(!f){m=ie(a,l,1);var F=ie(a,l+1,3);if(l+=3,F)if(F==1)f=ht,w=ut,A=9,b=5;else if(F==2){var C=ie(a,l,31)+257,M=ie(a,l+10,15)+4,k=C+ie(a,l+5,31)+1;l+=14;for(var S=new se(k),x=new se(19),v=0;v<M;++v)x[it[v]]=ie(a,l+v*3,7);l+=M*3;for(var R=Be(x),V=(1<<R)-1,I=be(x,R,1),v=0;v<k;){var q=I[ie(a,l,V)];l+=q&15;var P=q>>4;if(P<16)S[v++]=P;else{var p=0,_=0;for(P==16?(_=3+ie(a,l,3),l+=2,p=S[v-1]):P==17?(_=3+ie(a,l,7),l+=3):P==18&&(_=11+ie(a,l,127),l+=7);_--;)S[v++]=p}}var Y=S.subarray(0,C),W=S.subarray(C);A=Be(Y),b=Be(W),f=be(Y,A,1),w=be(W,b,1)}else re(1);else{var P=mt(l)+4,U=a[P-4]|a[P-3]<<8,O=P+U;if(O>n){u&&re(0);break}o&&y(h+U),t.set(a.subarray(P,O),h),e.b=h+=U,e.p=l=O*8,e.f=m;continue}if(l>B){u&&re(0);break}}o&&y(h+131072);for(var T=(1<<A)-1,K=(1<<b)-1,X=l;;X=l){var p=f[ze(a,l)&T],Z=p>>4;if(l+=p&15,l>B){u&&re(0);break}if(p||re(2),Z<256)t[h++]=Z;else if(Z==256){X=l,f=null;break}else{var z=Z-254;if(Z>264){var v=Z-257,g=$e[v];z=ie(a,l,(1<<g)-1)+Xe[v],l+=g}var E=w[ze(a,l)&K],L=E>>4;E||re(3),l+=E&15;var W=lt[L];if(L>3){var g=He[L];W+=ze(a,l)&(1<<g)-1,l+=g}if(l>B){u&&re(0);break}o&&y(h+131072);var D=h+z;if(h<W){var G=r-W,Q=Math.min(W,D);for(G+h<0&&re(3);h<Q;++h)t[h]=s[G+h]}for(;h<D;++h)t[h]=t[h-W]}}e.l=f,e.p=X,e.b=h,e.f=m,f&&(m=1,e.m=A,e.d=w,e.n=b)}while(!m);return h!=t.length&&i?Ee(t,0,h):t.subarray(0,h)},pt=new se(0),ce=function(a,e){return a[e]|a[e+1]<<8},oe=function(a,e){return(a[e]|a[e+1]<<8|a[e+2]<<16|a[e+3]<<24)>>>0},De=function(a,e){return oe(a,e)+oe(a,e+4)*4294967296};function gt(a,e){return ft(a,{i:2},e&&e.out,e&&e.dictionary)}var Pe=typeof TextDecoder<"u"&&new TextDecoder,xt=0;try{Pe.decode(pt,{stream:!0}),xt=1}catch{}var yt=function(a){for(var e="",t=0;;){var s=a[t++],n=(s>127)+(s>223)+(s>239);if(t+n>a.length)return{s:e,r:Ee(a,t-1)};n?n==3?(s=((s&15)<<18|(a[t++]&63)<<12|(a[t++]&63)<<6|a[t++]&63)-65536,e+=String.fromCharCode(55296|s>>10,56320|s&1023)):n&1?e+=String.fromCharCode((s&31)<<6|a[t++]&63):e+=String.fromCharCode((s&15)<<12|(a[t++]&63)<<6|a[t++]&63):e+=String.fromCharCode(s)}};function wt(a,e){if(e){for(var t="",s=0;s<a.length;s+=16384)t+=String.fromCharCode.apply(null,a.subarray(s,s+16384));return t}else{if(Pe)return Pe.decode(a);var n=yt(a),r=n.s,t=n.r;return t.length&&re(8),r}}var vt=function(a,e){return e+30+ce(a,e+26)+ce(a,e+28)},Mt=function(a,e,t){var s=ce(a,e+28),n=wt(a.subarray(e+46,e+46+s),!(ce(a,e+8)&2048)),r=e+46+s,i=oe(a,e+20),o=t&&i==4294967295?bt(a,r):[i,oe(a,e+24),oe(a,e+42)],u=o[0],y=o[1],m=o[2];return[ce(a,e+10),u,y,n,r+ce(a,e+30)+ce(a,e+32),m]},bt=function(a,e){for(;ce(a,e)!=1;e+=4+ce(a,e+2));return[De(a,e+12),De(a,e+4),De(a,e+20)]};function St(a,e){for(var t={},s=a.length-22;oe(a,s)!=101010256;--s)(!s||a.length-s>65558)&&re(13);var n=ce(a,s+8);if(!n)return{};var r=oe(a,s+16),i=r==4294967295||n==65535;if(i){var o=oe(a,s-12);i=oe(a,o)==101075792,i&&(n=oe(a,o+32),r=oe(a,o+48))}for(var u=0;u<n;++u){var y=Mt(a,r,i),m=y[0],l=y[1],h=y[2],f=y[3],w=y[4],A=y[5],b=vt(a,A);r=w,m?m==8?t[f]=gt(a.subarray(b,b+l),{out:new se(h)}):re(14,"unknown compression type "+m):t[f]=Ee(a,b,b+l)}return t}const Ce=a=>typeof a=="number"&&Number.isFinite(a),me=(a,e)=>{const t=a[e];if(typeof t!="object"||t===null)throw new Error(`Invalid SOG metadata section: ${e}`);return t},de=(a,e)=>{const t=a.files;if(!Array.isArray(t))throw new Error(`${e}.files is not an array`);if(!t.every(s=>typeof s=="string"))throw new Error(`${e}.files contains non-strings`);return t},qe=(a,e)=>{const t=a.mins,s=a.maxs;if(!Array.isArray(t)||t.length!==3)throw new Error(`${e}.mins must be length-3`);if(!Array.isArray(s)||s.length!==3)throw new Error(`${e}.maxs must be length-3`);if(![...t,...s].every(Ce))throw new Error(`${e}.mins/maxs must be finite numbers`);return{mins:[t[0],t[1],t[2]],maxs:[s[0],s[1],s[2]]}},At=(a,e)=>{const t=a.mins,s=a.maxs;if(!Array.isArray(t)||t.length!==4)throw new Error(`${e}.mins must be length-4`);if(!Array.isArray(s)||s.length!==4)throw new Error(`${e}.maxs must be length-4`);if(![...t,...s].every(Ce))throw new Error(`${e}.mins/maxs must be finite numbers`);return{mins:[t[0],t[1],t[2],t[3]],maxs:[s[0],s[1],s[2],s[3]]}},Je=(a,e)=>{const t=a.codebook;if(!Array.isArray(t))throw new Error(`${e}.codebook is not an array`);if(!t.every(Ce))throw new Error(`${e}.codebook contains non-finite numbers`);return t},Ke=a=>{if(typeof a!="object"||a===null)throw new Error("Invalid SOG metadata: not an object");const e=a,t=e.version??1;if(t!==1&&t!==2)throw new Error(`Unsupported SOG version: ${String(t)}`);if(t===1){const m=me(e,"means"),l=me(e,"sh0"),h=me(e,"quats"),f=me(e,"scales"),w=typeof e.count=="number"&&Number.isFinite(e.count)?e.count:void 0,A=Array.isArray(m.shape)?m.shape:void 0,b=A&&typeof A[0]=="number"?A[0]:void 0;if(w===void 0&&b===void 0)throw new Error("Invalid SOGS metadata: unable to determine splat count");if(w!==void 0&&b!==void 0&&w!==b)throw new Error("Inconsistent SOGS metadata: count does not match means.shape[0]");return{version:1,numSplats:(w??b)|0,files:{sh0:de(l,"sh0"),means:de(m,"means"),quats:de(h,"quats"),scales:de(f,"scales")},ranges:{sh0:At(l,"sh0"),means:qe(m,"means"),scales:qe(f,"scales")}}}const s=e.count;if(!Ce(s))throw new Error('Invalid SOG v2 metadata: missing/invalid "count"');const n=s|0,r=me(e,"means"),i=me(e,"sh0"),o=me(e,"quats"),u=me(e,"scales");return{version:2,numSplats:n,files:{sh0:de(i,"sh0"),means:de(r,"means"),quats:de(o,"quats"),scales:de(u,"scales")},ranges:{means:qe(r,"means"),sh0:{codebook:Je(i,"sh0")},scales:{codebook:Je(u,"scales")}},antialias:typeof e.antialias=="boolean"?e.antialias:void 0}};class Ct extends c.Loader{constructor(e,t){super(e),this.withCredentials=(t==null?void 0:t.withCredentials)??!1}isZipBuffer(e){if(e.byteLength<4)return!1;const t=new Uint8Array(e,0,4);return t[0]===80&&t[1]===75&&t[2]===3&&t[3]===4}load(e,t,s,n){const r=new c.FileLoader(this.manager);r.setResponseType("arraybuffer"),r.setRequestHeader(this.requestHeader),r.setPath(this.path),r.setWithCredentials(this.withCredentials),r.load(e,i=>{this.parseAsync(e,i).then(o=>{t&&t(o)}).catch(o=>{this.manager.itemError(e),n&&n(o),console.error("Error loading SOGS meta:",o)})},s,n)}loadAsync(e,t){return new Promise((s,n)=>{const r=new c.FileLoader(this.manager);r.setResponseType("arraybuffer"),r.setRequestHeader(this.requestHeader),r.setPath(this.path),r.setWithCredentials(this.withCredentials),r.load(e,i=>{this.parseAsync(e,i).then(s).catch(o=>{n(o),this.manager.itemError(e)})},t,i=>{n(i),this.manager.itemError(e)})})}async parseAsync(e,t){if(!(t instanceof ArrayBuffer))throw new Error("SOGS loader: expected ArrayBuffer payload");if(this.isZipBuffer(t))return this.parseZipAsync(t);const n=new TextDecoder("utf-8").decode(t),r=JSON.parse(n);return this.parseMetaAsync(e,r)}async parseMetaAsync(e,t){const s=Ke(t),{numSplats:n,files:r,ranges:i,version:o}=s,u=new c.TextureLoader(this.manager);u.setPath(this.path),u.setRequestHeader(this.requestHeader),u.setWithCredentials(this.withCredentials);const y=(P,U)=>{try{return new URL(U,P).toString()}catch{return P.substring(0,P.lastIndexOf("/")+1)+U}},m=(P,U)=>{const O=y(e,P);return new Promise((C,M)=>{u.load(O,k=>{k.generateMipmaps=!1,k.magFilter=c.NearestFilter,k.minFilter=c.NearestFilter,k.flipY=!1,C(k)},void 0,k=>{const S=k instanceof Error?k.message:String(k);M(new Error(`SOGS loader: failed to load ${U} (${P}): ${S}`))})})};if(!Array.isArray(r.sh0)||r.sh0.length<1)throw new Error("SOGS loader: files.sh0 must have at least 1 entry (sh0)");if(!Array.isArray(r.means)||r.means.length<2)throw new Error("SOGS loader: files.means must have at least 2 entries (means_l, means_u)");if(!Array.isArray(r.quats)||r.quats.length<1)throw new Error("SOGS loader: files.quats must have at least 1 entry");if(!Array.isArray(r.scales)||r.scales.length<1)throw new Error("SOGS loader: files.scales must have at least 1 entry");const[l,h,f,w,A]=await Promise.all([m(r.means[0],"means_l"),m(r.means[1],"means_u"),m(r.quats[0],"quats"),m(r.scales[0],"scales"),m(r.sh0[0],"sh0")]),b={means_l:l,means_u:h,quats:f,scales:w,sh0:A};if(o===1){const P=new Ve(n,i,b),U=Me.packSogs(P);return P.dispose(),U}const B=new Oe(n,i,b),F=Me.packSog2(B);return B.dispose(),F}async parseZipAsync(e){const t=St(new Uint8Array(e)),s=Object.keys(t),n=s.find(x=>x.toLowerCase().endsWith("meta.json"))??null;if(!n)throw new Error("SOGS loader: zip missing meta.json");const r=n.includes("/")?n.slice(0,n.lastIndexOf("/")+1):"",i=new TextDecoder,o=JSON.parse(i.decode(t[n])),u=Ke(o),{numSplats:y,files:m,ranges:l,version:h}=u,f=x=>x.replace(/\\/g,"/").replace(/^\.?\//,""),w=x=>{const v=f(x),R=[f(r+v),v];for(const q of R){const p=t[q];if(p)return p}const V=v.split("/").pop(),I=s.find(q=>f(q).endsWith("/"+v))??s.find(q=>f(q).endsWith("/"+V))??s.find(q=>f(q)===V)??null;if(I)return t[I];throw new Error(`SOGS loader: zip missing file "${x}"`)},A=x=>{const v=x.toLowerCase();return v.endsWith(".png")?"image/png":v.endsWith(".jpg")||v.endsWith(".jpeg")?"image/jpeg":v.endsWith(".webp")?"image/webp":"application/octet-stream"},b=new c.TextureLoader(this.manager);b.setRequestHeader(this.requestHeader),b.setWithCredentials(this.withCredentials);const B=(x,v)=>{const R=w(x),V=new Blob([R],{type:A(x)}),I=URL.createObjectURL(V);return new Promise((q,p)=>{b.load(I,_=>{URL.revokeObjectURL(I),_.generateMipmaps=!1,_.magFilter=c.NearestFilter,_.minFilter=c.NearestFilter,_.flipY=!1,q(_)},void 0,_=>{URL.revokeObjectURL(I);const Y=_ instanceof Error?_.message:String(_);p(new Error(`SOGS loader: failed to load ${v} from zip (${x}): ${Y}`))})})};if(!Array.isArray(m.sh0)||m.sh0.length<1)throw new Error("SOGS loader: files.sh0 must have at least 1 entry (sh0)");if(!Array.isArray(m.means)||m.means.length<2)throw new Error("SOGS loader: files.means must have at least 2 entries (means_l, means_u)");if(!Array.isArray(m.quats)||m.quats.length<1)throw new Error("SOGS loader: files.quats must have at least 1 entry");if(!Array.isArray(m.scales)||m.scales.length<1)throw new Error("SOGS loader: files.scales must have at least 1 entry");const[F,P,U,O,C]=await Promise.all([B(m.means[0],"means_l"),B(m.means[1],"means_u"),B(m.quats[0],"quats"),B(m.scales[0],"scales"),B(m.sh0[0],"sh0")]),M={means_l:F,means_u:P,quats:U,scales:O,sh0:C};if(h===1){const x=new Ve(y,l,M),v=Me.packSogs(x);return x.dispose(),v}const k=new Oe(y,l,M),S=Me.packSog2(k);return k.dispose(),S}}const It="0.3.0";j.AnimationController=Ge,j.BoundingBox=xe,j.PlyLoader=at,j.SogsLoader=Ct,j.SplatData=Ae,j.SplatMaterial=je,j.SplatMesh=_e,j.SplatSorter=Re,j.TextureManager=We,j.VERSION=It,j.getEffect=Ie,Object.defineProperty(j,Symbol.toStringTag,{value:"Module"})});
|
package/dist/react.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { FC } from 'react';
|
|
2
2
|
import type { ThreeElements } from '@react-three/fiber';
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
PlyLoader,
|
|
5
|
+
SplatMesh,
|
|
6
|
+
SplatMeshOptions,
|
|
7
|
+
AnimationOptions,
|
|
8
|
+
} from '@speridlabs/visus';
|
|
4
9
|
|
|
5
10
|
export type SplatFileType = 'ply' | 'sogs';
|
|
6
11
|
|
|
@@ -14,6 +19,10 @@ export interface SplatProps extends Omit<ThreeElements['mesh'], 'args'> {
|
|
|
14
19
|
type?: SplatFileType;
|
|
15
20
|
/** Options passed to the underlying SplatMesh */
|
|
16
21
|
splatOptions?: SplatMeshOptions;
|
|
22
|
+
/** Animation configuration */
|
|
23
|
+
animation?: AnimationOptions;
|
|
24
|
+
/** Whether to send credentials with the request (default: false) */
|
|
25
|
+
withCredentials?: boolean;
|
|
17
26
|
debug?: boolean;
|
|
18
27
|
}
|
|
19
28
|
|