UNPKG

luma-splatting-for-babylonjs

Version:
4 lines (3 loc) 3.55 kB
(function(n,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("@babylonjs/core")):typeof define=="function"&&define.amd?define(["exports","@babylonjs/core"],t):(n=typeof globalThis<"u"?globalThis:n||self,t(n["luma-splatting-for-babylonjs"]={},n.BABYLON))})(this,function(n,t){"use strict";var Q=Object.defineProperty;var Y=(n,t,m)=>t in n?Q(n,t,{enumerable:!0,configurable:!0,writable:!0,value:m}):n[t]=m;var P=(n,t,m)=>Y(n,typeof t!="symbol"?t+"":t,m);const m=async p=>{var y;const o=`https://webapp.engineeringlumalabs.com/api/v3/captures/${p}/public`,s=await fetch(o,{method:"GET",headers:{"Content-Type":"application/json"}}).then(a=>a.json());if(!((y=s.response)!=null&&y.artifacts))return null;const l=s.response.artifacts,u=l.find(a=>a.type==="gs_point_cloud"),h=l.find(a=>a.type==="gs_point_cloud_meta");return!u||!h?null:{metaFileUrl:h.url,plyFilesUrl:u.url}},L=p=>(c,o)=>(s,l)=>(p-c)/(o-c)*(l-s)+s,V=(p,c)=>{var G;const o=new Uint8Array(p),s=new TextDecoder().decode(o.slice(0,1024*10)),l=`end_header `,u=s.indexOf(l);if(u<0||!s)return p;const h=(G=/element vertex (\d+)\n/.exec(s))==null?void 0:G[1];if(!h)throw new Error("cannot parse vertex count from header!");const y=Number.parseInt(h);let a=0;const M={double:8,int:4,uint:4,float:4,short:2,ushort:2,uchar:1},B=[],R=s.slice(0,u).split(` `).filter(r=>r.startsWith("property "));for(const r of R){const[k,f,i]=r.split(" ");if(B.push({name:i,type:f,offset:a}),!M[f])throw new Error(`Unsupported property type: ${f}`);a+=M[f]}const b=3*4+3*4+4+4,g=.28209479177387814,z=new DataView(p,u+l.length),w=new ArrayBuffer(b*y),_=new t.Quaternion;for(let r=0;r<y;r++){const k=new Float32Array(w,r*b,3),f=new Float32Array(w,r*b+12,3),i=new Uint8ClampedArray(w,r*b+24,4),U=new Uint8ClampedArray(w,r*b+28,4);let O=255,$=0,q=0,I=0;for(let D=0;D<B.length;D++){const x=B[D];let d,e;switch(x.type){case"ushort":d=z.getUint16(x.offset+r*a,!0),e=L(d)(0,65535);break;case"uchar":d=z.getUint8(x.offset+r*a),e=L(d)(0,255);break;default:throw new Error(`Unsupported property type: ${x.type}`)}const{f_dc_max:j,f_dc_min:v,opacity_max:W,opacity_min:H,rotation_max:A,rotation_min:S,scale_max:E,scale_min:F,xyz_max:T,xyz_min:C}=c.gaussians.bounds;switch(x.name){case"x":k[0]=e(C[0],T[0]);break;case"y":k[1]=e(C[1],T[1]);break;case"z":k[2]=e(C[2],T[2]);break;case"scale_0":f[0]=Math.exp(e(F[0],E[0]));break;case"scale_1":f[1]=Math.exp(e(F[1],E[1]));break;case"scale_2":f[2]=Math.exp(e(F[2],E[2]));break;case"red":i[0]=d;break;case"green":i[1]=d;break;case"blue":i[2]=d;break;case"f_dc_0":i[0]=(.5+g*e(v[0],j[0]))*255;break;case"f_dc_1":i[1]=(.5+g*e(v[1],j[1]))*255;break;case"f_dc_2":i[2]=(.5+g*e(v[2],j[2]))*255;break;case"f_dc_3":i[3]=(.5+g*d)*255;break;case"opacity":i[3]=1/(1+Math.exp(-e(H[0],W[0])))*255;break;case"rot_0":O=e(S[0],A[0]);break;case"rot_1":$=e(S[1],A[1]);break;case"rot_2":q=e(S[2],A[2]);break;case"rot_3":I=e(S[3],A[3]);break}}_.set($,q,I,O),_.normalize(),U[0]=_.w*128+128,U[1]=_.x*128+128,U[2]=_.y*128+128,U[3]=_.z*128+128}return w};class N{constructor(c,o){P(this,"_splat");this.name=c,this.scene=o,this._splat=new t.GaussianSplattingMesh(c,null,o)}get splat(){return this._splat}async loadDataWithUuidAsync(c){const o=await m(c);if(!o)return;const{metaFileUrl:s,plyFilesUrl:l}=o,[u,h]=await Promise.all([fetch(l).then(a=>a.arrayBuffer()),fetch(s).then(a=>a.json())]),y=await V(u,h);this._splat=new t.GaussianSplattingMesh(this.name,null,this.scene),await this._splat.loadDataAsync(y)}}n.LumaGaussianSplatting=N,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})});