@speridlabs/visus 1.0.0 → 1.0.2
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 +320 -320
- package/dist/main.es.js +649 -493
- package/dist/main.umd.js +26 -13
- package/dist/react.d.ts +1 -0
- package/dist/react.es.js +812 -649
- package/package.json +1 -1
package/dist/main.umd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
(function(I,
|
|
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 L(T){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(T){for(const n in T)if(n!=="default"){const e=Object.getOwnPropertyDescriptor(T,n);Object.defineProperty(t,n,e.get?e:{enumerable:!0,get:()=>T[n]})}}return t.default=T,Object.freeze(t)}const i=L(D);class Q{constructor(){f(this,"min",new i.Vector3(1/0,1/0,1/0));f(this,"max",new i.Vector3(-1/0,-1/0,-1/0));f(this,"center",new i.Vector3);f(this,"halfExtents",new i.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 i.Box3().set(this.min,this.max)}clone(){const t=new Q;return t.min.copy(this.min),t.max.copy(this.max),t.center.copy(this.center),t.halfExtents.copy(this.halfExtents),t}}class it{constructor(t=0){f(this,"numSplats",0);f(this,"positions");f(this,"rotations");f(this,"scales");f(this,"colors");f(this,"opacities");f(this,"centers");f(this,"boundingBox",new Q);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),this.centers=new Float32Array(t*3)}setSplat(t,n,e,r,s,o){if(t>=this.numSplats)throw new Error(`Splat index out of bounds: ${t} >= ${this.numSplats}`);const a=t*3,c=t*4,h=t*3,v=t*3;this.positions[a]=n.x,this.positions[a+1]=n.y,this.positions[a+2]=n.z,this.rotations[c]=e.x,this.rotations[c+1]=e.y,this.rotations[c+2]=e.z,this.rotations[c+3]=e.w,this.scales[h]=r.x,this.scales[h+1]=r.y,this.scales[h+2]=r.z,this.colors[v]=s.r,this.colors[v+1]=s.g,this.colors[v+2]=s.b,this.opacities[t]=o,this.centers[a]=n.x,this.centers[a+1]=n.y,this.centers[a+2]=n.z}getSplat(t){if(t>=this.numSplats)throw new Error(`Splat index out of bounds: ${t} >= ${this.numSplats}`);const n=t*3,e=t*4,r=t*3,s=t*3;return{position:new i.Vector3(this.positions[n],this.positions[n+1],this.positions[n+2]),rotation:new i.Quaternion(this.rotations[e],this.rotations[e+1],this.rotations[e+2],this.rotations[e+3]),scale:new i.Vector3(Math.exp(this.scales[r]),Math.exp(this.scales[r+1]),Math.exp(this.scales[r+2])),color:new i.Color(this.colors[s],this.colors[s+1],this.colors[s+2]),opacity:this.opacities[t]}}calculateBoundingBox(){this.boundingBox.reset();const t=new i.Vector3;for(let n=0;n<this.numSplats;n++){const e=n*3;t.set(this.positions[e],this.positions[e+1],this.positions[e+2]),this.boundingBox.expandByPoint(t)}return this.boundingBox}createDebugGeometry(){const t=new i.BufferGeometry;t.setAttribute("position",new i.BufferAttribute(this.positions,3));const n=new Float32Array(this.numSplats*3),e=new i.Quaternion,r=new i.Euler;for(let s=0;s<this.numSplats;s++){const o=s*4,a=s*3;e.set(this.rotations[o],this.rotations[o+1],this.rotations[o+2],this.rotations[o+3]),r.setFromQuaternion(e),n[a]=r.x,n[a+1]=r.y,n[a+2]=r.z}return t.setAttribute("rotation",new i.BufferAttribute(n,3)),t.setAttribute("scale",new i.BufferAttribute(this.scales,3)),t.setAttribute("color",new i.BufferAttribute(this.colors,3)),t.setAttribute("opacity",new i.BufferAttribute(this.opacities,1)),t}}class at extends i.EventDispatcher{constructor(){super();f(this,"worker");f(this,"centers",null);f(this,"orderTexture",null);f(this,"chunks",null);f(this,"lastCameraPosition",new i.Vector3);f(this,"lastCameraDirection",new i.Vector3);const n=this.createWorkerCode(),e=new Blob([n],{type:"application/javascript"});this.worker=new Worker(URL.createObjectURL(e)),this.worker.onmessage=this.onWorkerMessage.bind(this)}onWorkerMessage(n){if(!this.orderTexture||!this.orderTexture.image)return console.error("SplatSorter: Order texture not initialized!");const{order:e,count:r}=n.data,s=this.orderTexture.image.data;if(!(s instanceof Uint32Array))return console.error("SplatSorter: Order texture data is not a Uint32Array!");s.set(new Uint32Array(e)),this.orderTexture.needsUpdate=!0;const o=s.buffer.slice(0),a={order:o};this.worker.postMessage(a,[o]),this.dispatchEvent({type:"updated",count:r})}init(n,e,r){if(!n||!(n.image.data instanceof Uint32Array))throw new Error("SplatSorter: Invalid orderTexture provided. Must be DataTexture with Uint32Array data.");if(!e||e.length%3!==0)throw new Error("SplatSorter: Invalid centers array provided. Length must be multiple of 3.");if(n.image.data.length<e.length/3)throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");const s=e.length/3;this.orderTexture=n,this.centers=e.slice();const o=this.orderTexture.image.data;for(let y=0;y<s;y++)o[y]=y;this.orderTexture.needsUpdate=!0;const a=o.buffer.slice(0),c=this.centers.buffer.slice(0),h={order:a,centers:c},v=[a,c];if(r){this.chunks=r.slice();const y=this.chunks.buffer.slice(0);h.chunks=y,v.push(y)}this.worker.postMessage(h,v)}setMapping(n){if(!this.centers)return console.warn("SplatSorter: Cannot set mapping before initialization.");let e;const r=[];if(!n){const c=this.centers.buffer.slice(0);return e={centers:c,mapping:null},r.push(c),this.worker.postMessage(e,r)}const s=new Float32Array(n.length*3);for(let c=0;c<n.length;c++){const h=n[c];if(h*3+2>=this.centers.length){console.warn(`SplatSorter: Mapping index ${h} out of bounds.`);continue}const v=h*3,y=c*3;s[y+0]=this.centers[v+0],s[y+1]=this.centers[v+1],s[y+2]=this.centers[v+2]}const o=s.buffer.slice(0),a=n.buffer.slice(0);e={centers:o,mapping:a},r.push(o,a),this.worker.postMessage(e,r)}setCamera(n,e){const r=this.lastCameraPosition.distanceToSquared(n)>1e-7,s=this.lastCameraDirection.dot(e)<.9999;if(!r&&!s)return;this.lastCameraPosition.copy(n),this.lastCameraDirection.copy(e);const o={cameraPosition:{x:n.x,y:n.y,z:n.z},cameraDirection:{x:e.x,y:e.y,z:e.z}};this.worker.postMessage(o)}dispose(){this.worker&&this.worker.terminate(),this.orderTexture=null,this.centers=null,this.chunks=null}createWorkerCode(){return`(${(function(){let e=null,r=null,s=null,o=null,a=null,c=null,h=!1;const v={x:0,y:0,z:0},y={x:0,y:0,z:0},p={x:0,y:0,z:0},u={x:0,y:0,z:0};let l=null,b=null;const k=32,q=new Array(k).fill(0),W=new Array(k).fill(0),R=new Array(k).fill(0),H=(P,S,V)=>{for(;P<=S;){const M=S+P>>1,m=V(M);if(m>0)P=M+1;else if(m<0)S=M-1;else return M}return~P},N=()=>{if(!e||!r||!a||!c)return;if(r.length===0){const g={order:e.buffer,count:0};self.postMessage(g,[e.buffer]),e=null;return}const P=a.x,S=a.y,V=a.z,M=c.x,m=c.y,C=c.z,O=1e-4,_=Math.abs(P-v.x)>O||Math.abs(S-v.y)>O||Math.abs(V-v.z)>O,x=Math.abs(M-y.x)>O||Math.abs(m-y.y)>O||Math.abs(C-y.z)>O;if(!h&&!_&&!x)return;h=!1,v.x=P,v.y=S,v.z=V,y.x=M,y.y=m,y.z=C;let d=1/0,z=-1/0;for(let g=0;g<8;++g){const F=g&1?p.x:u.x,U=g&2?p.y:u.y,w=g&4?p.z:u.z,E=F*M+U*m+w*C;d=Math.min(d,E),z=Math.max(z,E)}const B=r.length/3,Y=z-d,A=(1<<Math.max(10,Math.min(20,Math.ceil(Math.log2(B/4)))))+1;if((!l||l.length!==B)&&(l=new Uint32Array(B)),!b||b.length!==A?b=new Uint32Array(A):b.fill(0),Y<1e-7){for(let g=0;g<B;++g)l[g]=0;b[0]=B}else if(s&&s.length>0){const g=s.length/6;q.fill(0);for(let w=0;w<g;++w){const E=w*6,$=s[E+0],J=s[E+1],tt=s[E+2],Z=s[E+3],G=$*M+J*m+tt*C-d,et=G-Z,K=G+Z,nt=Math.max(0,Math.floor(et*k/Y)),ot=Math.min(k,Math.ceil(K*k/Y));for(let X=nt;X<ot;++X)q[X]++}let F=0;for(let w=0;w<k;++w)F+=q[w];R[0]=0,W[0]=0;for(let w=1;w<k;++w)R[w-1]=q[w-1]/F*A>>>0,W[w]=W[w-1]+R[w-1];R[k-1]=q[k-1]/F*A>>>0;const U=Y/k;for(let w=0;w<B;++w){const E=w*3,$=r[E+0],J=r[E+1],tt=r[E+2],Z=$*M+J*m+tt*C,et=(z-Z)/U,K=Math.max(0,Math.min(k-1,Math.floor(et))),nt=et-K,ot=W[K]+R[K]*nt>>>0,X=Math.min(ot,A-1);l[w]=X,b[X]++}}else{const g=(A-1)/Y;for(let F=0;F<B;++F){const U=F*3,w=r[U+0],E=r[U+1],$=r[U+2],J=w*M+E*m+$*C,Z=(z-J)*g>>>0,G=Math.min(Z,A-1);l[F]=G,b[G]++}}for(let g=1;g<A;g++)b[g]+=b[g-1];for(let g=B-1;g>=0;g--){const F=l[g],U=--b[F];e[U]=o?o[g]:g}const bt=P*M+S*m+V*C,dt=g=>{if(!e)return-1/0;const F=e[g],U=F;if(!r||U*3+2>=r.length)return-1/0;const w=U*3;return r[w]*M+r[w+1]*m+r[w+2]*C-bt};let ft=B;if(B>0&&dt(B-1)<0){const g=H(0,B-1,dt);ft=g<0?~g:g}const Mt={order:e.buffer,count:ft};self.postMessage(Mt,[e.buffer]),e=null};self.onmessage=P=>{const S=P.data;S.order&&(e=new Uint32Array(S.order));let V=!1;if(S.centers&&(r=new Float32Array(S.centers),V=!0,h=!0),Object.prototype.hasOwnProperty.call(S,"mapping")&&(o=S.mapping?new Uint32Array(S.mapping):null,h=!0),S.chunks){if(s=new Float32Array(S.chunks),s.length>0&&s[3]>0)for(let M=0;M<s.length/6;++M){const m=M*6,C=s[m+0],O=s[m+1],_=s[m+2],x=s[m+3],d=s[m+4],z=s[m+5];s[m+0]=(C+x)*.5,s[m+1]=(O+d)*.5,s[m+2]=(_+z)*.5,s[m+3]=Math.sqrt((x-C)**2+(d-O)**2+(z-_)**2)*.5}h=!0}if(V&&r&&r.length>0){p.x=u.x=r[0],p.y=u.y=r[1],p.z=u.z=r[2];for(let M=1;M<r.length/3;M++){const m=M*3;p.x=Math.min(p.x,r[m+0]),u.x=Math.max(u.x,r[m+0]),p.y=Math.min(p.y,r[m+1]),u.y=Math.max(u.y,r[m+1]),p.z=Math.min(p.z,r[m+2]),u.z=Math.max(u.z,r[m+2])}}else V&&r&&r.length===0&&(p.x=u.x=p.y=u.y=p.z=u.z=0);S.cameraPosition&&(a=S.cameraPosition),S.cameraDirection&&(c=S.cameraDirection),N()}}).toString()})();`}}const pt=(T,t)=>{const n=ct(T),e=ct(t);return n|e<<16};function ct(T){const t=new Float32Array([T]),e=new Int32Array(t.buffer)[0];let r=e>>16&32768,s=e>>12&2047;const o=e>>23&255;return o<103?r:o>142?(r|=31744,r|=(o===255?0:1)&&e&8388607,r):o<113?(s|=2048,r|=(s>>114-o)+(s>>113-o&1),r):(r|=o-112<<10|s>>1,r+=s&1,r)}const mt=new ArrayBuffer(4),lt=new DataView(mt),xt=T=>(lt.setUint32(0,T,!0),lt.getFloat32(0,!0));class ht{constructor(t){f(this,"transformA");f(this,"transformB");f(this,"colorTexture");f(this,"orderTexture");f(this,"textureWidth");f(this,"textureHeight");const n=t.numSplats;this.textureWidth=Math.ceil(Math.sqrt(n)),this.textureHeight=Math.ceil(n/this.textureWidth),this.transformA=this.createTransformATexture(t),this.transformB=this.createTransformBTexture(t),this.colorTexture=this.createColorTexture(t),this.orderTexture=this.createOrderTexture(n)}createTransformATexture(t){const n=t.numSplats,e=new Float32Array(this.textureWidth*this.textureHeight*4);for(let s=0;s<n;s++){const o=s*4,a=s*3,c=s*4;e[o]=t.positions[a],e[o+1]=t.positions[a+1],e[o+2]=t.positions[a+2];const h=t.rotations[c+0],v=t.rotations[c+1],y=pt(h,v);e[o+3]=xt(y)}const r=new i.DataTexture(e,this.textureWidth,this.textureHeight,i.RGBAFormat,i.FloatType);return r.needsUpdate=!0,r.magFilter=i.NearestFilter,r.minFilter=i.NearestFilter,r}createTransformBTexture(t){const n=t.numSplats,e=new Float32Array(this.textureWidth*this.textureHeight*4);for(let s=0;s<n;s++){const o=s*4,a=s*3,c=s*4;e[o]=t.scales[a],e[o+1]=t.scales[a+1],e[o+2]=t.scales[a+2],e[o+3]=t.rotations[c+2]}const r=new i.DataTexture(e,this.textureWidth,this.textureHeight,i.RGBAFormat,i.FloatType);return r.needsUpdate=!0,r.magFilter=i.NearestFilter,r.minFilter=i.NearestFilter,r}createColorTexture(t){const n=t.numSplats,e=new Float32Array(this.textureWidth*this.textureHeight*4);for(let s=0;s<n;s++){const o=s*4,a=s*3;e[o]=t.colors[a],e[o+1]=t.colors[a+1],e[o+2]=t.colors[a+2],e[o+3]=t.opacities[s]}const r=new i.DataTexture(e,this.textureWidth,this.textureHeight,i.RGBAFormat,i.FloatType);return r.needsUpdate=!0,r}createOrderTexture(t){const n=new Uint32Array(this.textureWidth*this.textureHeight);for(let r=0;r<t;r++)n[r]=r;const e=new i.DataTexture(n,this.textureWidth,this.textureHeight,i.RedIntegerFormat,i.UnsignedIntType);return e.needsUpdate=!0,e}dispose(){this.transformA.dispose(),this.transformB.dispose(),this.colorTexture.dispose(),this.orderTexture.dispose()}}const gt=`
|
|
1
|
+
(function(I,P){typeof exports=="object"&&typeof module<"u"?P(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],P):(I=typeof globalThis<"u"?globalThis:I||self,P(I.Visus={},I.THREE))})(this,function(I,P){"use strict";var Me=Object.defineProperty;var Ae=(I,P,G)=>P in I?Me(I,P,{enumerable:!0,configurable:!0,writable:!0,value:G}):I[P]=G;var p=(I,P,G)=>Ae(I,typeof P!="symbol"?P+"":P,G);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 G(E){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(E){for(const t in E)if(t!=="default"){const o=Object.getOwnPropertyDescriptor(E,t);Object.defineProperty(e,t,o.get?o:{enumerable:!0,get:()=>E[t]})}}return e.default=E,Object.freeze(e)}const i=G(P);class ee{constructor(){p(this,"min",new i.Vector3(1/0,1/0,1/0));p(this,"max",new i.Vector3(-1/0,-1/0,-1/0));p(this,"center",new i.Vector3);p(this,"halfExtents",new i.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 i.Box3().set(this.min,this.max)}clone(){const e=new ee;return e.min.copy(this.min),e.max.copy(this.max),e.center.copy(this.center),e.halfExtents.copy(this.halfExtents),e}}class ie{constructor(e=0){p(this,"numSplats",0);p(this,"positions");p(this,"rotations");p(this,"scales");p(this,"colors");p(this,"opacities");p(this,"centers");p(this,"boundingBox",new ee);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),this.centers=new Float32Array(e*3)}setSplat(e,t,o,r,n,s){if(e>=this.numSplats)throw new Error(`Splat index out of bounds: ${e} >= ${this.numSplats}`);const a=e*3,c=e*4,f=e*3,m=e*3;this.positions[a]=t.x,this.positions[a+1]=t.y,this.positions[a+2]=t.z,this.rotations[c]=o.x,this.rotations[c+1]=o.y,this.rotations[c+2]=o.z,this.rotations[c+3]=o.w,this.scales[f]=r.x,this.scales[f+1]=r.y,this.scales[f+2]=r.z,this.colors[m]=n.r,this.colors[m+1]=n.g,this.colors[m+2]=n.b,this.opacities[e]=s,this.centers[a]=t.x,this.centers[a+1]=t.y,this.centers[a+2]=t.z}getSplat(e){if(e>=this.numSplats)throw new Error(`Splat index out of bounds: ${e} >= ${this.numSplats}`);const t=e*3,o=e*4,r=e*3,n=e*3;return{position:new i.Vector3(this.positions[t],this.positions[t+1],this.positions[t+2]),rotation:new i.Quaternion(this.rotations[o],this.rotations[o+1],this.rotations[o+2],this.rotations[o+3]),scale:new i.Vector3(Math.exp(this.scales[r]),Math.exp(this.scales[r+1]),Math.exp(this.scales[r+2])),color:new i.Color(this.colors[n],this.colors[n+1],this.colors[n+2]),opacity:this.opacities[e]}}calculateBoundingBox(){this.boundingBox.reset();const e=new i.Vector3;for(let t=0;t<this.numSplats;t++){const o=t*3;e.set(this.positions[o],this.positions[o+1],this.positions[o+2]),this.boundingBox.expandByPoint(e)}return this.boundingBox}createDebugGeometry(){const e=new i.BufferGeometry;e.setAttribute("position",new i.BufferAttribute(this.positions,3));const t=new Float32Array(this.numSplats*3),o=new i.Quaternion,r=new i.Euler;for(let n=0;n<this.numSplats;n++){const s=n*4,a=n*3;o.set(this.rotations[s],this.rotations[s+1],this.rotations[s+2],this.rotations[s+3]),r.setFromQuaternion(o),t[a]=r.x,t[a+1]=r.y,t[a+2]=r.z}return e.setAttribute("rotation",new i.BufferAttribute(t,3)),e.setAttribute("scale",new i.BufferAttribute(this.scales,3)),e.setAttribute("color",new i.BufferAttribute(this.colors,3)),e.setAttribute("opacity",new i.BufferAttribute(this.opacities,1)),e}}class ae extends i.EventDispatcher{constructor(){super();p(this,"worker");p(this,"centers",null);p(this,"orderTexture",null);p(this,"chunks",null);p(this,"lastCameraPosition",new i.Vector3);p(this,"lastCameraDirection",new i.Vector3);const t=this.createWorkerCode(),o=new Blob([t],{type:"application/javascript"});this.worker=new Worker(URL.createObjectURL(o)),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:o,count:r}=t.data,n=this.orderTexture.image.data;if(!(n instanceof Uint32Array))return console.error("SplatSorter: Order texture data is not a Uint32Array!");n.set(new Uint32Array(o)),this.orderTexture.needsUpdate=!0;const s=n.buffer.slice(0),a={order:s};this.worker.postMessage(a,[s]),this.dispatchEvent({type:"updated",count:r})}init(t,o,r){if(!t||!(t.image.data instanceof Uint32Array))throw new Error("SplatSorter: Invalid orderTexture provided. Must be DataTexture with Uint32Array data.");if(!o||o.length%3!==0)throw new Error("SplatSorter: Invalid centers array provided. Length must be multiple of 3.");if(t.image.data.length<o.length/3)throw new Error("SplatSorter: orderTexture data buffer is smaller than the number of splats.");const n=o.length/3;this.orderTexture=t,this.centers=o.slice();const s=this.orderTexture.image.data;for(let x=0;x<n;x++)s[x]=x;this.orderTexture.needsUpdate=!0;const a=s.buffer.slice(0),c=this.centers.buffer.slice(0),f={order:a,centers:c},m=[a,c];if(r){this.chunks=r.slice();const x=this.chunks.buffer.slice(0);f.chunks=x,m.push(x)}this.worker.postMessage(f,m)}setMapping(t){if(!this.centers)return console.warn("SplatSorter: Cannot set mapping before initialization.");let o;const r=[];if(!t){const c=this.centers.buffer.slice(0);return o={centers:c,mapping:null},r.push(c),this.worker.postMessage(o,r)}const n=new Float32Array(t.length*3);for(let c=0;c<t.length;c++){const f=t[c];if(f*3+2>=this.centers.length){console.warn(`SplatSorter: Mapping index ${f} out of bounds.`);continue}const m=f*3,x=c*3;n[x+0]=this.centers[m+0],n[x+1]=this.centers[m+1],n[x+2]=this.centers[m+2]}const s=n.buffer.slice(0),a=t.buffer.slice(0);o={centers:s,mapping:a},r.push(s,a),this.worker.postMessage(o,r)}setCamera(t,o){const r=this.lastCameraPosition.distanceToSquared(t)>1e-7,n=this.lastCameraDirection.dot(o)<.9999;if(!r&&!n)return;this.lastCameraPosition.copy(t),this.lastCameraDirection.copy(o);const s={cameraPosition:{x:t.x,y:t.y,z:t.z},cameraDirection:{x:o.x,y:o.y,z:o.z}};this.worker.postMessage(s)}dispose(){this.worker&&this.worker.terminate(),this.orderTexture=null,this.centers=null,this.chunks=null}createWorkerCode(){return`(${(function(){let o=null,r=null,n=null,s=null,a=null,c=null,f=!1;const m={x:0,y:0,z:0},x={x:0,y:0,z:0},v={x:0,y:0,z:0},d={x:0,y:0,z:0};let S=null,u=null;const M=32,q=new Array(M).fill(0),j=new Array(M).fill(0),H=new Array(M).fill(0),L=(T,A,F)=>{for(;T<=A;){const C=A+T>>1,y=F(C);if(y>0)T=C+1;else if(y<0)A=C-1;else return C}return~T},Y=()=>{if(!o||!r||!a||!c)return;if(r.length===0){const g={order:o.buffer,count:0};self.postMessage(g,[o.buffer]),o=null;return}const T=a.x,A=a.y,F=a.z,C=c.x,y=c.y,z=c.z,_=1e-4,R=Math.abs(T-m.x)>_||Math.abs(A-m.y)>_||Math.abs(F-m.z)>_,B=Math.abs(C-x.x)>_||Math.abs(y-x.y)>_||Math.abs(z-x.z)>_;if(!f&&!R&&!B)return;f=!1,m.x=T,m.y=A,m.z=F,x.x=C,x.y=y,x.z=z;let l=1/0,h=-1/0;for(let g=0;g<8;++g){const D=g&1?v.x:d.x,O=g&2?v.y:d.y,b=g&4?v.z:d.z,k=D*C+O*y+b*z;l=Math.min(l,k),h=Math.max(h,k)}const w=r.length/3,W=h-l,U=(1<<Math.max(10,Math.min(20,Math.ceil(Math.log2(w/4)))))+1;if((!S||S.length!==w)&&(S=new Uint32Array(w)),!u||u.length!==U?u=new Uint32Array(U):u.fill(0),W<1e-7){for(let g=0;g<w;++g)S[g]=0;u[0]=w}else if(n&&n.length>0){const g=n.length/6;q.fill(0);for(let b=0;b<g;++b){const k=b*6,J=n[k+0],K=n[k+1],te=n[k+2],Z=n[k+3],X=J*C+K*y+te*z-l,re=X-Z,Q=X+Z,ne=Math.max(0,Math.floor(re*M/W)),se=Math.min(M,Math.ceil(Q*M/W));for(let $=ne;$<se;++$)q[$]++}let D=0;for(let b=0;b<M;++b)D+=q[b];H[0]=0,j[0]=0;for(let b=1;b<M;++b)H[b-1]=q[b-1]/D*U>>>0,j[b]=j[b-1]+H[b-1];H[M-1]=q[M-1]/D*U>>>0;const O=W/M;for(let b=0;b<w;++b){const k=b*3,J=r[k+0],K=r[k+1],te=r[k+2],Z=J*C+K*y+te*z,re=(h-Z)/O,Q=Math.max(0,Math.min(M-1,Math.floor(re))),ne=re-Q,se=j[Q]+H[Q]*ne>>>0,$=Math.min(se,U-1);S[b]=$,u[$]++}}else{const g=(U-1)/W;for(let D=0;D<w;++D){const O=D*3,b=r[O+0],k=r[O+1],J=r[O+2],K=b*C+k*y+J*z,Z=(h-K)*g>>>0,X=Math.min(Z,U-1);S[D]=X,u[X]++}}for(let g=1;g<U;g++)u[g]+=u[g-1];for(let g=w-1;g>=0;g--){const D=S[g],O=--u[D];o[O]=s?s[g]:g}const V=T*C+A*y+F*z,he=g=>{if(!o)return-1/0;const D=o[g],O=D;if(!r||O*3+2>=r.length)return-1/0;const b=O*3;return r[b]*C+r[b+1]*y+r[b+2]*z-V};let fe=w;if(w>0&&he(w-1)<0){const g=L(0,w-1,he);fe=g<0?~g:g}const Se={order:o.buffer,count:fe};self.postMessage(Se,[o.buffer]),o=null};self.onmessage=T=>{const A=T.data;A.order&&(o=new Uint32Array(A.order));let F=!1;if(A.centers&&(r=new Float32Array(A.centers),F=!0,f=!0),Object.prototype.hasOwnProperty.call(A,"mapping")&&(s=A.mapping?new Uint32Array(A.mapping):null,f=!0),A.chunks){if(n=new Float32Array(A.chunks),n.length>0&&n[3]>0)for(let C=0;C<n.length/6;++C){const y=C*6,z=n[y+0],_=n[y+1],R=n[y+2],B=n[y+3],l=n[y+4],h=n[y+5];n[y+0]=(z+B)*.5,n[y+1]=(_+l)*.5,n[y+2]=(R+h)*.5,n[y+3]=Math.sqrt((B-z)**2+(l-_)**2+(h-R)**2)*.5}f=!0}if(F&&r&&r.length>0){v.x=d.x=r[0],v.y=d.y=r[1],v.z=d.z=r[2];for(let C=1;C<r.length/3;C++){const y=C*3;v.x=Math.min(v.x,r[y+0]),d.x=Math.max(d.x,r[y+0]),v.y=Math.min(v.y,r[y+1]),d.y=Math.max(d.y,r[y+1]),v.z=Math.min(v.z,r[y+2]),d.z=Math.max(d.z,r[y+2])}}else F&&r&&r.length===0&&(v.x=d.x=v.y=d.y=v.z=d.z=0);A.cameraPosition&&(a=A.cameraPosition),A.cameraDirection&&(c=A.cameraDirection),Y()}}).toString()})();`}}const pe=(E,e)=>{const t=ce(E),o=ce(e);return t|o<<16};function ce(E){const e=new Float32Array([E]),o=new Int32Array(e.buffer)[0];let r=o>>16&32768,n=o>>12&2047;const s=o>>23&255;return s<103?r:s>142?(r|=31744,r|=(s===255?0:1)&&o&8388607,r):s<113?(n|=2048,r|=(n>>114-s)+(n>>113-s&1),r):(r|=s-112<<10|n>>1,r+=n&1,r)}const me=new ArrayBuffer(4),le=new DataView(me),xe=E=>(le.setUint32(0,E,!0),le.getFloat32(0,!0));class ue{constructor(e){p(this,"transformA");p(this,"transformB");p(this,"colorTexture");p(this,"orderTexture");p(this,"textureWidth");p(this,"textureHeight");const t=e.numSplats;this.textureWidth=Math.ceil(Math.sqrt(t)),this.textureHeight=Math.ceil(t/this.textureWidth),this.transformA=this.createTransformATexture(e),this.transformB=this.createTransformBTexture(e),this.colorTexture=this.createColorTexture(e),this.orderTexture=this.createOrderTexture(t)}createTransformATexture(e){const t=e.numSplats,o=new Float32Array(this.textureWidth*this.textureHeight*4);for(let n=0;n<t;n++){const s=n*4,a=n*3,c=n*4;o[s]=e.positions[a],o[s+1]=e.positions[a+1],o[s+2]=e.positions[a+2];const f=e.rotations[c+0],m=e.rotations[c+1],x=pe(f,m);o[s+3]=xe(x)}const r=new i.DataTexture(o,this.textureWidth,this.textureHeight,i.RGBAFormat,i.FloatType);return r.needsUpdate=!0,r.magFilter=i.NearestFilter,r.minFilter=i.NearestFilter,r}createTransformBTexture(e){const t=e.numSplats,o=new Float32Array(this.textureWidth*this.textureHeight*4);for(let n=0;n<t;n++){const s=n*4,a=n*3,c=n*4;o[s]=e.scales[a],o[s+1]=e.scales[a+1],o[s+2]=e.scales[a+2],o[s+3]=e.rotations[c+2]}const r=new i.DataTexture(o,this.textureWidth,this.textureHeight,i.RGBAFormat,i.FloatType);return r.needsUpdate=!0,r.magFilter=i.NearestFilter,r.minFilter=i.NearestFilter,r}createColorTexture(e){const t=e.numSplats,o=new Float32Array(this.textureWidth*this.textureHeight*4);for(let n=0;n<t;n++){const s=n*4,a=n*3;o[s]=e.colors[a],o[s+1]=e.colors[a+1],o[s+2]=e.colors[a+2],o[s+3]=e.opacities[n]}const r=new i.DataTexture(o,this.textureWidth,this.textureHeight,i.RGBAFormat,i.FloatType);return r.needsUpdate=!0,r}createOrderTexture(e){const t=new Uint32Array(this.textureWidth*this.textureHeight);for(let r=0;r<e;r++)t[r]=r;const o=new i.DataTexture(t,this.textureWidth,this.textureHeight,i.RedIntegerFormat,i.UnsignedIntType);return o.needsUpdate=!0,o}dispose(){this.transformA.dispose(),this.transformB.dispose(),this.colorTexture.dispose(),this.orderTexture.dispose()}}const ge=`
|
|
3
3
|
precision highp float;
|
|
4
4
|
precision highp int;
|
|
5
5
|
precision highp usampler2D;
|
|
@@ -203,6 +203,10 @@ void main(void) {
|
|
|
203
203
|
float l1 = sqrt(lambda1) * scaleFactor; // scaleX
|
|
204
204
|
float l2 = sqrt(lambda2) * scaleFactor; // scaleY
|
|
205
205
|
|
|
206
|
+
float vmin = min(512.0, min(viewport.x, viewport.y));
|
|
207
|
+
l1 = min(l1, 2.0 * vmin);
|
|
208
|
+
l2 = min(l2, 2.0 * vmin);
|
|
209
|
+
|
|
206
210
|
// Early out tiny splats
|
|
207
211
|
if (l1 < 2.0 && l2 < 2.0) { // Check if smaller than ~2 pixel
|
|
208
212
|
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
@@ -213,14 +217,15 @@ void main(void) {
|
|
|
213
217
|
vec2 v1_scaled = l1 * v1_eigen;
|
|
214
218
|
vec2 v2_scaled = l2 * v2_eigen;
|
|
215
219
|
|
|
216
|
-
// --- FRUSTUM CHECK
|
|
220
|
+
// --- FRUSTUM CHECK (laxo, estilo PlayCanvas) ---
|
|
217
221
|
|
|
218
|
-
vec2
|
|
222
|
+
vec2 c = centerClip.ww / viewport; // pixel to clip
|
|
223
|
+
float r = max(l1, l2); // radius in pixels
|
|
219
224
|
|
|
220
|
-
//
|
|
221
|
-
if (any(greaterThan(abs(centerClip.xy)
|
|
222
|
-
|
|
223
|
-
|
|
225
|
+
// Remove if the center - radius is already out of -w..w
|
|
226
|
+
if (any(greaterThan(abs(centerClip.xy) - vec2(r) * c, centerClip.ww))) {
|
|
227
|
+
gl_Position = vec4(2.0, 2.0, 2.0, 1.0);
|
|
228
|
+
return;
|
|
224
229
|
}
|
|
225
230
|
|
|
226
231
|
// --- END FRUSTUM CHECK ---
|
|
@@ -249,12 +254,20 @@ void main(void) {
|
|
|
249
254
|
vColor = vec4(splatColor, splatOpacity);
|
|
250
255
|
vUv = clippedCornerOffset;
|
|
251
256
|
}
|
|
252
|
-
`,
|
|
257
|
+
`,ye=`
|
|
253
258
|
precision highp float;
|
|
254
259
|
|
|
255
260
|
varying vec4 vColor; // Color and opacity passed from vertex shader
|
|
256
261
|
varying vec2 vUv; // Quad UV coordinates (-1 to 1) passed from vertex shader
|
|
257
262
|
|
|
263
|
+
// Fast approximate e^x based on https://nic.schraudolph.org/pubs/Schraudolph99.pdf
|
|
264
|
+
const float EXP_A = 12102203.0; // ≈ 2^23 / ln(2)
|
|
265
|
+
const int EXP_BC_RMS = 1064866808; // (127 << 23) - 60801 * 8
|
|
266
|
+
float fastExp(float x) {
|
|
267
|
+
int i = int(EXP_A * x) + EXP_BC_RMS;
|
|
268
|
+
return intBitsToFloat(i);
|
|
269
|
+
}
|
|
270
|
+
|
|
258
271
|
void main(void) {
|
|
259
272
|
|
|
260
273
|
float distSq = dot(vUv, vUv); // Calculate squared distance from center (in the quad's coordinate system)
|
|
@@ -264,14 +277,14 @@ void main(void) {
|
|
|
264
277
|
// The factor 4.0 corresponds to the original implementation's scaling.
|
|
265
278
|
// factor = 1 / (2 * sigma^2), where sigma controls the spread.
|
|
266
279
|
// Using 4.0 implies sigma^2 = 1/8.
|
|
267
|
-
float alpha =
|
|
280
|
+
float alpha = fastExp(-distSq * 4.0) * vColor.a;
|
|
268
281
|
|
|
269
282
|
if (alpha < 1.0 / 255.0) discard; // Discard fragments with very low alpha
|
|
270
283
|
|
|
271
284
|
// Premultiply color by alpha (required for correct blending)
|
|
272
285
|
gl_FragColor = vec4(vColor.rgb * alpha, alpha);
|
|
273
286
|
}
|
|
274
|
-
`;class
|
|
287
|
+
`;class de extends i.ShaderMaterial{constructor(e={}){const t={transformA:{value:null},transformB:{value:null},splatColor:{value:null},splatOrder:{value:null},viewport:{value:new i.Vector2(1,1)},numSplats:{value:0}};super({vertexShader:ge,fragmentShader:ye,uniforms:t,transparent:!0,blending:i.CustomBlending,blendSrc:i.OneFactor,blendDst:i.OneMinusSrcAlphaFactor,blendSrcAlpha:i.OneFactor,blendDstAlpha:i.OneMinusSrcAlphaFactor,blendEquation:i.AddEquation,blendEquationAlpha:i.AddEquation,depthTest:!0,depthWrite:!1,side:i.DoubleSide,alphaTest:e.alphaTest!==void 0?e.alphaTest:0,toneMapped:e.toneMapped!==void 0?e.toneMapped:!1}),e.alphaHash&&(this.alphaHash=!0,this.depthWrite=!0,this.blending=i.NoBlending)}updateViewport(e,t){this.uniforms.viewport.value.set(e,t)}setTransformA(e){this.uniforms.transformA.value=e}setTransformB(e){this.uniforms.transformB.value=e}setColorTexture(e){this.uniforms.splatColor.value=e}setOrderTexture(e){this.uniforms.splatOrder.value=e}setNumSplats(e){this.uniforms.numSplats.value=e}}const N=class N extends i.Mesh{constructor(t,o={}){const r=(typeof window<"u"&&window.__VISUS_SPLAT_DEBUG__)===!0;r&&console.debug("[1/8] MESH SplatMesh: creating mesh with",t.numSplats,"splats");const n=new de(o),s=N.createInstancedGeometry(t.numSplats,N.INSTANCE_SIZE);r&&console.debug("[2/8] MESH SplatMesh: created instanced geometry with",Math.ceil(t.numSplats/N.INSTANCE_SIZE),"instances");super(s,n);p(this,"sorter");p(this,"splatData");p(this,"options");p(this,"textureManager");p(this,"material");p(this,"geometry");p(this,"lastCameraPositionLocal",new i.Vector3);p(this,"lastCameraDirectionLocal",new i.Vector3);p(this,"invModelMatrix",new i.Matrix4);this.geometry=s,this.material=n,this.splatData=t,this.frustumCulled=!1,this.options={autoSort:!0,...o},r&&console.debug("[3/8] MESH SplatMesh: initializing texture manager"),this.textureManager=new ue(t),this.sorter=new ae,r&&console.debug("[4/8] MESH SplatMesh: creating chunks for sorter");let a=this.createChunks()||void 0;a===null&&console.warn("Visus: Could not create sorter chunks, bounding box might be invalid."),a=void 0,r&&console.debug("[5/8] MESH SplatMesh: initializing sorter with",a?"chunks":"no chunks"),this.sorter.init(this.textureManager.orderTexture,this.splatData.centers,a??void 0),this.sorter.addEventListener("updated",c=>{const f=c.count;r&&console.debug("[6/8] MESH SplatMesh: sorter updated, rendering",f,"splats"),this.geometry.instanceCount=Math.ceil(f/N.INSTANCE_SIZE),this.material.setNumSplats(f)}),r&&console.debug("[7/8] MESH SplatMesh: setting up material textures"),this.material.setTransformA(this.textureManager.transformA),this.material.setTransformB(this.textureManager.transformB),this.material.setColorTexture(this.textureManager.colorTexture),this.material.setOrderTexture(this.textureManager.orderTexture),this.material.setNumSplats(0),this.geometry.boundingBox=t.boundingBox.toBox3(),this.geometry.boundingSphere=new i.Sphere,this.geometry.boundingBox.getBoundingSphere(this.geometry.boundingSphere),r&&console.debug("[8/8] MESH SplatMesh: mesh initialization complete, bounding box:",t.boundingBox)}static createInstancedGeometry(t,o){const r=(typeof window<"u"&&window.__VISUS_SPLAT_DEBUG__)===!0,n=Math.ceil(t/o);r&&console.debug("MESH createInstancedGeometry: creating geometry for",t,"splats,",n,"instances");const s=new i.BufferGeometry,a=new Float32Array([-1,-1,0,1,-1,0,1,1,0,-1,1,0]),c=new Uint16Array([0,1,2,0,2,3]),f=new Float32Array(4*3*o);for(let d=0;d<o;d++){const S=d*4*3;for(let u=0;u<4;u++)f[S+u*3+0]=a[u*3+0],f[S+u*3+1]=a[u*3+1],f[S+u*3+2]=d}const m=new Uint32Array(6*o);for(let d=0;d<o;d++){const S=d*6,u=d*4;m[S+0]=c[0]+u,m[S+1]=c[1]+u,m[S+2]=c[2]+u,m[S+3]=c[3]+u,m[S+4]=c[4]+u,m[S+5]=c[5]+u}s.setAttribute("position",new i.BufferAttribute(f,3)),s.setIndex(new i.BufferAttribute(m,1));const x=new i.InstancedBufferGeometry;x.index=s.index,x.setAttribute("position",s.getAttribute("position"));const v=new Uint32Array(n);for(let d=0;d<n;d++)v[d]=d*o;return x.setAttribute("splatInstanceIndex",new i.InstancedBufferAttribute(v,1,!1)),x.instanceCount=0,r&&console.debug("MESH createInstancedGeometry: geometry created with",x.attributes.position.count,"vertices"),x}createChunks(){const t=(typeof window<"u"&&window.__VISUS_SPLAT_DEBUG__)===!0,o=this.splatData.boundingBox;if(o.min.x===1/0||o.max.x===-1/0)return t&&console.debug("MESH createChunks: invalid bounding box, cannot create chunks"),null;const r=new Float32Array([o.min.x,o.min.y,o.min.z,o.max.x,o.max.y,o.max.z]);return t&&console.debug("MESH createChunks: created chunks with bounding box",o),r}updateViewport(t,o){(typeof window<"u"&&window.__VISUS_SPLAT_DEBUG__)===!0&&console.debug("MESH updateViewport: updating viewport to",t,"x",o),this.material.updateViewport(t,o)}sort(t){const o=(typeof window<"u"&&window.__VISUS_SPLAT_DEBUG__)===!0,r=new i.Vector3,n=new i.Vector3;t.getWorldPosition(r),t.getWorldDirection(n),this.invModelMatrix.copy(this.matrixWorld).invert();const s=r.applyMatrix4(this.invModelMatrix),a=n.transformDirection(this.invModelMatrix),c=this.lastCameraPositionLocal.distanceToSquared(s)>1e-6,f=this.lastCameraDirectionLocal.dot(a)<.999;this.options.autoSort&&(c||f)&&(o&&console.debug("MESH sort: camera changed, triggering sort. Position changed:",c,"Direction changed:",f),this.lastCameraPositionLocal.copy(s),this.lastCameraDirectionLocal.copy(a),this.sorter.setCamera(s,a))}onBeforeRender(t,o,r){this.sort(r);const n=t.getSize(new i.Vector2);let{width:s,height:a}=n;const c=t.xr;if(c.enabled&&c.isPresenting){const f=c.getCamera().cameras[0].view;f&&(s=f.width,a=f.height)}this.updateViewport(s,a)}dispose(){const t=(typeof window<"u"&&window.__VISUS_SPLAT_DEBUG__)===!0;t&&console.debug("MESH dispose: cleaning up mesh resources"),this.sorter.dispose(),this.geometry.dispose(),this.material.dispose(),this.textureManager.dispose(),t&&console.debug("MESH dispose: mesh resources cleaned up")}};p(N,"INSTANCE_SIZE",128);let oe=N;class we extends i.Loader{load(e,t,o,r){(typeof window<"u"&&window.__VISUS_SPLAT_DEBUG__)===!0&&console.debug("[1/12] LOADER PlyLoader: loading",e);const s=new i.FileLoader(this.manager);s.setResponseType("arraybuffer"),s.setRequestHeader(this.requestHeader),s.setPath(this.path),s.setWithCredentials(this.withCredentials),s.load(e,a=>{try{if(t){const c=this.parse(a);t(c)}}catch(c){r?r(c):console.error(c),this.manager.itemError(e)}},o,r)}loadAsync(e,t){return new Promise((o,r)=>{const n=new i.FileLoader(this.manager);n.setResponseType("arraybuffer"),n.setRequestHeader(this.requestHeader),n.setPath(this.path),n.setWithCredentials(this.withCredentials),n.load(e,s=>{try{const a=this.parse(s);o(a)}catch(a){r(a),this.manager.itemError(e)}},t,s=>{r(s),this.manager.itemError(e)})})}parse(e){const t=(typeof window<"u"&&window.__VISUS_SPLAT_DEBUG__)===!0;t&&console.debug("[2/12] LOADER PlyLoader: starting parse, buffer size:",e.byteLength);const o=new TextDecoder,r=new Uint8Array(e),n=[112,108,121,10],s=`
|
|
275
288
|
end_header
|
|
276
|
-
`;for(let
|
|
277
|
-
`),
|
|
289
|
+
`;for(let l=0;l<n.length;l++)if(r[l]!==n[l])throw new Error("Invalid PLY file: Missing magic bytes");t&&console.debug("[3/12] LOADER PlyLoader: PLY magic bytes verified");let a=0;for(let l=0;l<r.length-s.length;l++){let h=!0;for(let w=0;w<s.length;w++)if(r[l+w]!==s.charCodeAt(w)){h=!1;break}if(h){a=l+s.length;break}}if(a===0)throw new Error("Invalid PLY file: Could not find end of header");t&&console.debug("[4/12] LOADER PlyLoader: header length:",a);const c=o.decode(r.subarray(0,a));t&&console.debug("[5/12] LOADER PlyLoader: header text:",c);const f=c.split(`
|
|
290
|
+
`),m=[];let x=null;for(let l=1;l<f.length;l++){const h=f[l].trim();if(h===""||h==="end_header")continue;const w=h.split(" ");switch(w[0]){case"format":x=w[1],t&&console.debug("[6/12] LOADER PlyLoader: format detected:",x);break;case"element":m.push({name:w[1],count:parseInt(w[2],10),properties:[]}),t&&console.debug("[6/12] LOADER PlyLoader: element found:",w[1],"count:",w[2]);break;case"property":if(m.length===0)throw new Error("Invalid PLY file: Property without element");m[m.length-1].properties.push({type:w[1],name:w[2],storage:null}),t&&console.debug("[6/12] LOADER PlyLoader: property found:",w[2],"type:",w[1]);break}}if(x!=="binary_little_endian")throw new Error(`Unsupported PLY format: ${x}`);const v=m.find(l=>l.name==="vertex");if(!v)throw new Error("Invalid PLY file: No vertex element found");t&&console.debug("[7/12] LOADER PlyLoader: vertex element properties:",v.properties.map(l=>l.name));const d=new ie(v.count);t&&console.debug("[8/12] LOADER PlyLoader: created SplatData for",v.count,"splats");const S=new DataView(e);let u=a;const M=l=>v.properties.findIndex(h=>h.name===l),q=M("x"),j=M("y"),H=M("z"),L=[M("rot_0"),M("rot_1"),M("rot_2"),M("rot_3")],Y=[M("scale_0"),M("scale_1"),M("scale_2")],T=[M("f_dc_0"),M("f_dc_1"),M("f_dc_2")],A=M("opacity");if(t&&console.debug("[9/12] LOADER PlyLoader: property indices:",{position:[q,j,H],rotation:L,scale:Y,color:T,opacity:A}),[q,j,H,...L,...Y,...T,A].some(l=>l===-1))throw new Error("Invalid PLY file: Missing required properties");const C=.28209479177387814,y=l=>{if(l>0)return 1/(1+Math.exp(-l));const h=Math.exp(l);return h/(1+h)};t&&console.debug("[10/12] LOADER PlyLoader: starting binary data parsing, offset:",u);const z=new i.Vector3,_=new i.Quaternion,R=new i.Vector3,B=new i.Color;for(let l=0;l<v.count;l++){t&&l%1e4===0&&console.debug(`[10/12] LOADER PlyLoader: processing splat ${l}/${v.count} (${(l/v.count*100).toFixed(1)}%)`);const h=[];for(let W=0;W<v.properties.length;W++){const U=v.properties[W].type;let V;switch(U){case"char":V=S.getInt8(u),u+=1;break;case"uchar":V=S.getUint8(u),u+=1;break;case"short":V=S.getInt16(u,!0),u+=2;break;case"ushort":V=S.getUint16(u,!0),u+=2;break;case"int":V=S.getInt32(u,!0),u+=4;break;case"uint":V=S.getUint32(u,!0),u+=4;break;case"float":V=S.getFloat32(u,!0),u+=4;break;case"double":V=S.getFloat64(u,!0),u+=8;break;default:throw new Error(`Unsupported property type: ${U}`)}h.push(V)}z.set(h[q],h[j],h[H]),_.set(h[L[1]],h[L[2]],h[L[3]],h[L[0]]).normalize(),t&&l<5&&console.debug(`[10/12] LOADER PlyLoader: splat ${l} rotation:`,{original:[h[L[0]],h[L[1]],h[L[2]],h[L[3]]],processed:[_.x,_.y,_.z,_.w]}),R.set(h[Y[0]],h[Y[1]],h[Y[2]]),B.set(.5+h[T[0]]*C,.5+h[T[1]]*C,.5+h[T[2]]*C),B.r=Math.max(0,Math.min(1,B.r)),B.g=Math.max(0,Math.min(1,B.g)),B.b=Math.max(0,Math.min(1,B.b));const w=y(h[A]);t&&l<3&&console.debug(`[10/12] LOADER PlyLoader: splat ${l} data:`,{position:[z.x,z.y,z.z],rotation:[_.x,_.y,_.z,_.w],scale:[R.x,R.y,R.z],color:[B.r,B.g,B.b],opacity:w}),d.setSplat(l,z,_,R,B,w)}return t&&console.debug("[11/12] LOADER PlyLoader: finished parsing all splats, calculating bounding box"),d.calculateBoundingBox(),t&&console.debug("[12/12] LOADER PlyLoader: parsing complete, bounding box:",{min:[d.boundingBox.min.x,d.boundingBox.min.y,d.boundingBox.min.z],max:[d.boundingBox.max.x,d.boundingBox.max.y,d.boundingBox.max.z]}),d}}const ve="0.3.0";I.BoundingBox=ee,I.PlyLoader=we,I.SplatData=ie,I.SplatMaterial=de,I.SplatMesh=oe,I.SplatSorter=ae,I.TextureManager=ue,I.VERSION=ve,Object.defineProperty(I,Symbol.toStringTag,{value:"Module"})});
|