rgbd 1.0.1 → 1.0.3

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/index.js CHANGED
@@ -1,4 +1,4 @@
1
- var f,b=["color-src","depth-src","grid-size","focal-length","depth-min","depth-max","cam-radius","cam-max-theta","cam-max-phi","cam-smoothness","cam-zoom-amount","boomerang-speed","background-color","img-zoom-amount","xr-enable-button","xr-recenter-yaw","xr-recenter-radius"],I=`#version 300 es
1
+ var f,b=["color-src","depth-src","grid-size","focal-length","depth-min","depth-max","cam-radius","cam-max-theta","cam-max-phi","cam-smoothness","cam-zoom-amount","boomerang-speed","background-color","img-zoom-amount","xr-button","xr-recenter-yaw","xr-recenter-radius"],I=`#version 300 es
2
2
 
3
3
  precision mediump float;
4
4
  precision mediump int;
@@ -74,9 +74,9 @@ void main()
74
74
  {
75
75
  fragColor = texture(u_colorImage, v_uv);
76
76
  }
77
- `,y=typeof window<"u"&&typeof HTMLElement<"u"&&typeof document<"u";y?f=class extends HTMLElement{constructor(){super(),this.s={GRID_SIZE:250,FOCAL_LENGTH:1200,DEPTH_MIN:.1,DEPTH_MAX:10,CAM_RADIUS:1.5,CAM_MAX_THETA:Math.PI/32,CAM_MAX_PHI:Math.PI/32,CAM_SMOOTHNESS:.9,CAM_ZOOM_AMOUNT:.2,BOOMERANG_SPEED:.001,BACKGROUND_COLOR:[0,0,0],IMG_ZOOM_AMOUNT:0,XR_RECENTER_RADIUS:.25,XR_RECENTER_YAW:45},this.U=null,this.i=null,this.t=null,this.d=null,this.n=null,this.P=null,this.O={},this.p=null,this.m={x:0,y:0,hovered:!1},this.o={theta:Math.PI,phi:0,radius:this.s.CAM_RADIUS},this.F=0,this.b=null,this.G=!1,this.$=null,this.tt=null,this.et=this.D.bind(this),this.it=this.xt.bind(this),this.st=this.At.bind(this),this.v=this.H.bind(this),this.ht=!1,this.a=null,this.T=null,this.R=null,this.h=null,this.Et=!1,this.g=null,this.U=this.attachShadow({mode:"open"});let t=document.createElement("div");t.style.position="relative",t.style.width="100%",t.style.height="100%",t.style.display="flex",t.style.alignItems="center",t.style.justifyContent="center",t.style.background="black",this.U.appendChild(t);let e=document.createElement("style");e.textContent=`
77
+ `,T=typeof window<"u"&&typeof HTMLElement<"u"&&typeof document<"u";T?f=class extends HTMLElement{constructor(){super(),this.s={GRID_SIZE:250,FOCAL_LENGTH:1200,DEPTH_MIN:.1,DEPTH_MAX:10,CAM_RADIUS:1.5,CAM_MAX_THETA:Math.PI/32,CAM_MAX_PHI:Math.PI/32,CAM_SMOOTHNESS:.9,CAM_ZOOM_AMOUNT:.2,BOOMERANG_SPEED:.001,BACKGROUND_COLOR:[0,0,0],IMG_ZOOM_AMOUNT:0,XR_RECENTER_RADIUS:.5,XR_RECENTER_YAW:45},this.U=null,this.i=null,this.t=null,this.d=null,this.n=null,this.P=null,this.O={},this.p=null,this.m={x:0,y:0,hovered:!1},this.o={theta:Math.PI,phi:0,radius:this.s.CAM_RADIUS},this.X=0,this.T=null,this.F=!1,this.$=null,this.tt=null,this.et=this.D.bind(this),this.it=this.gt.bind(this),this.st=this._t.bind(this),this.v=this.G.bind(this),this.ht=!1,this.a=null,this.R=null,this.C=null,this.h=null,this.At=!1,this.g=null,this.U=this.attachShadow({mode:"open"});let t=document.createElement("div");t.style.position="relative",t.style.width="100%",t.style.height="100%",t.style.display="flex",t.style.alignItems="center",t.style.justifyContent="center",t.style.background="black",this.U.appendChild(t);let e=document.createElement("style");e.textContent=`
78
78
  :host { display: inline-block; width: 300px; height: 200px; }
79
79
  :host([fullbleed]) { display:block; width:100%; height:100%; }
80
80
  canvas { touch-action: none; }
81
- .cover-img, .cover-video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none; }
82
- `,this.U.appendChild(e),this.i=document.createElement("canvas"),this.i.style.width="100%",this.i.style.height="100%",this.i.style.objectFit="contain",this.i.setAttribute("role","img"),this.i.setAttribute("aria-label","3D image"),t.appendChild(this.i),this.g=document.createElement("button"),this.g.textContent="Enter VR",Object.assign(this.g.style,{position:"absolute",display:"none",top:"1%",right:"1%",color:"white",background:"rgba(0,0,0,0.4)",padding:"8px 8px",fontFamily:"monospace",fontSize:"20px",borderRadius:"8px",border:"1px solid white",backdropFilter:"blur(6px)",whiteSpace:"pre"}),t.appendChild(this.g),this.g.addEventListener("click",()=>{this.a?this.nt():this.Mt()})}connectedCallback(){this.X();let t;try{this.bt(),t=!1}catch{t=!0}this.i.addEventListener("resize",this.et),this.i.addEventListener("mousemove",this.it),this.i.addEventListener("mouseleave",this.st),t?this.B():(this.D(),this.G=!0,this.F=performance.now(),this.b=requestAnimationFrame(this.v)),this.rt()}disconnectedCallback(){this.G=!1,cancelAnimationFrame(this.b),this.i.removeEventListener("resize",this.et),this.i.removeEventListener("mousemove",this.it),this.i.removeEventListener("mouseleave",this.st);try{this.a&&(this.a.end(),this.a=null,this.Et=!1)}catch{}try{if(this.n){let t=this.n;this.P&&t.deleteProgram(this.P);for(let e in this.O)t.deleteTexture(this.O[e].tex)}}catch{}}setViewMatrix(t){this.$=t&&t.length===16?new Float32Array(t):null}setProjectionMatrix(t){this.tt=t&&t.length===16?new Float32Array(t):null}get width(){return this.A(this.t)}get height(){return this.E(this.t)}bt(){let t=this.i.getContext("webgl2",{antialias:!0,alpha:!1});if(!t)throw new Error("WebGL not supported");this.n=t;let e=this.vt(t,I,P);if(!e)return;this.P=e,t.useProgram(e);let i=this.ot(t),s=this.ot(t);this.O.color=i,this.O.depth=s,this._("color",this.t),this._("depth",this.d);let h=t.getUniformLocation(e,"u_colorImage"),n=t.getUniformLocation(e,"u_depthImage");t.uniform1i(h,0),t.uniform1i(n,1),this.p={uProjection:t.getUniformLocation(e,"u_projMat"),uView:t.getUniformLocation(e,"u_viewMat"),uImageSize:t.getUniformLocation(e,"u_imageSize"),uFocal:t.getUniformLocation(e,"u_focal"),uDepthMin:t.getUniformLocation(e,"u_depthMin"),uDepthMax:t.getUniformLocation(e,"u_depthMax"),uGridSegs:t.getUniformLocation(e,"u_grid"),uXr:t.getUniformLocation(e,"u_xr")}}at(t=null){if(!this.n)return;let e=this.n;e.bindFramebuffer(e.FRAMEBUFFER,t),e.useProgram(this.P),e.clearColor(...this.s.BACKGROUND_COLOR,1),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT),e.enable(e.DEPTH_TEST)}ut(t,e){if(!this.n)return;let i=this.n,s=this.A(this.t),h=this.E(this.t),n=s/h,r=Math.max(1,Math.floor(this.s.GRID_SIZE)),o=Math.max(1,Math.round(r/n));i.uniform2f(this.p.uImageSize,s,h),i.uniform1f(this.p.uFocal,this.s.FOCAL_LENGTH),i.uniform1f(this.p.uDepthMin,this.s.DEPTH_MIN),i.uniform1f(this.p.uDepthMax,this.s.DEPTH_MAX),i.uniform2i(this.p.uGridSegs,r,o),i.uniform1ui(this.p.uXr,this.a?1:0),i.uniformMatrix4fv(this.p.uView,!1,t),i.uniformMatrix4fv(this.p.uProjection,!1,e),i.drawArrays(i.TRIANGLES,0,r*o*6)}H(t,e){if(!this.G)return;let i=t-this.F;this.F=t,this.ct(),this.m.hovered||(this.m.x=Math.sin(t*this.s.BOOMERANG_SPEED),this.m.y=Math.sin(t*this.s.BOOMERANG_SPEED*.5+Math.PI));let s=this.m.x*this.s.CAM_MAX_THETA+Math.PI,h=-this.m.y*this.s.CAM_MAX_PHI,n=this.s.CAM_RADIUS*(1-this.s.CAM_ZOOM_AMOUNT),r=this.m.hovered?n:this.s.CAM_RADIUS;if(this.o.theta=this.M(s,this.o.theta,i),this.o.phi=this.M(h,this.o.phi,i),this.o.radius=this.M(r,this.o.radius,i),this.a){let o=this.T.getOffsetReferenceSpace(new XRRigidTransform({x:this.h.x,y:this.h.y,z:this.h.z},{x:0,y:Math.sin(this.h.yaw*.5),z:0,w:Math.cos(this.h.yaw*.5)}));this.h.x=this.M(0,this.h.x,i),this.h.y=this.M(0,this.h.y,i),this.h.z=this.M(0,this.h.z,i),this.h.yaw=this.M(0,this.h.yaw,i);let a=e.getViewerPose(this.T).transform;this.R||(this.R=a);let u=this.R,c=a.position.x-u.position.x,l=a.position.y-u.position.y,p=a.position.z-u.position.z,d=this.lt(a.orientation);(Math.abs(d-this.lt(u.orientation))>this.s.XR_RECENTER_YAW*Math.PI/180||Math.hypot(c,l,p)>this.s.XR_RECENTER_RADIUS)&&(this.h.x=-a.position.x,this.h.y=-a.position.y,this.h.z=-a.position.z,this.h.yaw=-d,this.T=this.T.getOffsetReferenceSpace(new XRRigidTransform(a.position,{x:0,y:Math.sin(d*.5),z:0,w:Math.cos(d*.5)})),this.R=null);let R=e.session,C=e.getViewerPose(o);if(!C){R.requestAnimationFrame(this.v);return}let S=R.renderState.baseLayer;this.at(S.framebuffer);for(let v of C.views){let M=S.getViewport(v);this.n.viewport(M.x,M.y,M.width,M.height);let O=new Float32Array(v.transform.inverse.matrix),D=new Float32Array(v.projectionMatrix);this.ut(O,D)}}else{let o=this.i.width/this.i.height,a=[this.o.radius*Math.cos(this.o.phi)*Math.sin(this.o.theta),this.o.radius*Math.sin(this.o.phi),this.s.CAM_RADIUS+this.o.radius*Math.cos(this.o.phi)*Math.cos(this.o.theta)],u=[0,0,this.s.CAM_RADIUS],c=[0,-1,0],l=this.height*(1-this.s.IMG_ZOOM_AMOUNT),p=2*Math.atan(l/(2*this.s.FOCAL_LENGTH)),d=this.$||new Float32Array(this.yt(a,u,c)),w=this.tt||new Float32Array(this.Tt(p,o,.1,100));this.at(),this.ut(d,w)}this.a?this.b=e.session.requestAnimationFrame(this.v):this.b=requestAnimationFrame(this.v)}rt(){this.ht&&navigator.xr&&navigator.xr.isSessionSupported?navigator.xr.isSessionSupported("immersive-vr").then(t=>{this.g.style.display=t?"block":"none"}).catch(()=>{this.g.style.display="none"}):this.g.style.display="none"}async Mt(){if(!this.a)try{let t=await navigator.xr.requestSession("immersive-vr",{optionalFeatures:["local-floor","bounded-floor"]});this.n.makeXRCompatible&&await this.n.makeXRCompatible(),this.D();let e=new XRWebGLLayer(t,this.n);await t.updateRenderState({baseLayer:e});let i=await t.requestReferenceSpace("local");this.a=t,this.T=i,this.R=null,this.h={x:0,y:0,z:0,yaw:0},cancelAnimationFrame(this.b),t.addEventListener("end",()=>{this.nt()}),t.requestAnimationFrame(this.v)}catch(t){console.warn("Unable to start XR session",t)}}async nt(){if(this.a){try{await this.a.end()}catch{}this.a=null,this.T=null,this.R=null,this.D(),this.b=requestAnimationFrame(this.v)}}xt(t){let e=this.i.getBoundingClientRect();this.m.hovered=!0,this.m.x=(t.clientX-e.left)/e.width*2-1,this.m.y=(t.clientY-e.top)/e.height*2-1}At(){this.m.hovered=!1}D(){let t=window.devicePixelRatio||1,e=this.i.parentElement;if(!e)return;let i=e.clientWidth,s=e.clientHeight,h=this.A(this.t)||1,n=this.E(this.t)||1,r=h/n,o=i,a=o/r;a>s&&(a=s,o=a*r);let u=Math.max(1,Math.floor((this.a?i:o)*t)),c=Math.max(1,Math.floor((this.a?s:a)*t));this.i.width=u,this.i.height=c,this.n&&this.n.viewport(0,0,u,c)}X(){let t=this.s;if(this.hasAttribute("grid-size")&&(t.GRID_SIZE=parseInt(this.getAttribute("grid-size"))??t.GRID_SIZE),this.hasAttribute("focal-length")&&(t.FOCAL_LENGTH=parseFloat(this.getAttribute("focal-length"))??t.FOCAL_LENGTH),this.hasAttribute("depth-min")&&(t.DEPTH_MIN=parseFloat(this.getAttribute("depth-min"))??t.DEPTH_MIN),this.hasAttribute("depth-max")&&(t.DEPTH_MAX=parseFloat(this.getAttribute("depth-max"))??t.DEPTH_MAX),this.hasAttribute("cam-radius")&&(t.CAM_RADIUS=parseFloat(this.getAttribute("cam-radius"))??t.CAM_RADIUS),this.hasAttribute("cam-max-theta")&&(t.CAM_MAX_THETA=parseFloat(this.getAttribute("cam-max-theta"))??t.CAM_MAX_THETA),this.hasAttribute("cam-max-phi")&&(t.CAM_MAX_PHI=parseFloat(this.getAttribute("cam-max-phi"))??t.CAM_MAX_PHI),this.hasAttribute("cam-smoothness")&&(t.CAM_SMOOTHNESS=parseFloat(this.getAttribute("cam-smoothness"))??t.CAM_SMOOTHNESS),this.hasAttribute("cam-zoom-amount")&&(t.CAM_ZOOM_AMOUNT=parseFloat(this.getAttribute("cam-zoom-amount"))??t.CAM_ZOOM_AMOUNT),this.hasAttribute("boomerang-speed")&&(t.BOOMERANG_SPEED=parseFloat(this.getAttribute("boomerang-speed"))??t.BOOMERANG_SPEED),this.hasAttribute("background-color"))try{let e=this.getAttribute("background-color").split(",").map(Number);e.length===3&&(t.BACKGROUND_COLOR=e)}catch{}this.hasAttribute("img-zoom-amount")&&(t.IMG_ZOOM_AMOUNT=parseFloat(this.getAttribute("img-zoom-amount"))??t.IMG_ZOOM_AMOUNT),this.ht=this.hasAttribute("xr-enable-button"),this.hasAttribute("xr-recenter-yaw")&&(t.XR_RECENTER_YAW=parseFloat(this.getAttribute("xr-recenter-yaw"))??t.XR_RECENTER_YAW),this.hasAttribute("xr-recenter-radius")&&(t.XR_RECENTER_RADIUS=parseFloat(this.getAttribute("xr-recenter-radius"))??t.XR_RECENTER_RADIUS),this.rt()}dt(t,e,i){let s=t.createShader(e);return t.shaderSource(s,i),t.compileShader(s),t.getShaderParameter(s,t.COMPILE_STATUS)?s:(console.error(t.getShaderInfoLog(s)),t.deleteShader(s),null)}vt(t,e,i){let s=this.dt(t,t.VERTEX_SHADER,e),h=this.dt(t,t.FRAGMENT_SHADER,i);if(!s||!h)return null;let n=t.createProgram();return t.attachShader(n,s),t.attachShader(n,h),t.linkProgram(n),t.getProgramParameter(n,t.LINK_STATUS)?(t.deleteShader(s),t.deleteShader(h),n):(console.error(t.getProgramInfoLog(n)),t.deleteProgram(n),null)}ot(t){let e=t.createTexture();return t.bindTexture(t.TEXTURE_2D,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),{tex:e,width:0,height:0}}_(t,e){if(!this.n)return;let i=this.n,s=this.O[t];if(i.activeTexture(t==="color"?i.TEXTURE0:i.TEXTURE1),i.bindTexture(i.TEXTURE_2D,s.tex),!this.W(e)){i.texImage2D(i.TEXTURE_2D,0,i.RGBA,1,1,0,i.RGBA,i.UNSIGNED_BYTE,new Uint8Array([0,0,0,0]));return}try{i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,!1),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,i.RGBA,i.UNSIGNED_BYTE,e),(this.A(e)!=s.width||this.E(e)!=s.height)&&(this.D(),s.width=this.A(e),s.height=this.E(e))}catch{}}Tt(t,e,i,s){let h=1/Math.tan(t/2);return[h/e,0,0,0,0,h,0,0,0,0,(s+i)/(i-s),-1,0,0,2*s*i/(i-s),0]}yt(t,e,i){function s(u){let c=Math.hypot(...u)||1;return u.map(l=>l/c)}function h(u,c){return[u[1]*c[2]-u[2]*c[1],u[2]*c[0]-u[0]*c[2],u[0]*c[1]-u[1]*c[0]]}function n(u,c){return u.map((l,p)=>l-c[p])}let r=s(n(t,e)),o=s(h(i,r)),a=h(r,o);return[o[0],a[0],r[0],0,o[1],a[1],r[1],0,o[2],a[2],r[2],0,-(o[0]*t[0]+o[1]*t[1]+o[2]*t[2]),-(a[0]*t[0]+a[1]*t[1]+a[2]*t[2]),-(r[0]*t[0]+r[1]*t[1]+r[2]*t[2]),1]}lt(t){return Math.atan2(2*(t.w*t.y+t.x*t.z),1-2*(t.y*t.y+t.x*t.x))}M(t,e,i){let s=(1-this.s.CAM_SMOOTHNESS)*i/16.67,h=Math.sign(t-e);return e+=(t-e)*s,Math.sign(t-e)!==h&&(e=t),e}B(){throw new Error("Must implement _createFallback")}ct(){}W(t){throw new Error("Must implement _isSourceReady")}A(t){throw new Error("Must implement _getSourceWidth")}E(t){throw new Error("Must implement _getSourceHeight")}}:f=class{};var g=class extends f{static get observedAttributes(){return b}constructor(){super(),this.t=new Image,this.d=new Image,this.t.crossOrigin="anonymous",this.d.crossOrigin="anonymous",this.t.onload=()=>this._("color",this.t),this.d.onload=()=>this._("depth",this.d)}attributeChangedCallback(t,e,i){e!==i&&(t==="color-src"?this.t.src=i||"":t==="depth-src"?this.d.src=i||"":this.X())}B(){this.t.style.display="block",this.t.classList.add("cover-img"),this.i.parentElement.appendChild(this.t)}W(t){return t&&t.complete&&t.naturalWidth>0}A(t){return t?t.width:1}E(t){return t?t.height:1}};var _=class{constructor(){this.context=null,this.sourceNodes=null,this.gainNode=null,this.volume=1,this.sampleRate=0,this.numChannels=0,this.timeSuspended=0,this.timeOffset=0,this.lastTime=0,this.context=null,this.isPaused=!1,this.loopHandle=null}start(t={}){if(this.context)throw new Error("Audio manager already started!");this.audioEnabled=t.audioEnabled??!0,this.sampleRate=t.sampleRate??44100,this.numChannels=t.numChannels??2,this.context=new AudioContext({sampleRate:this.sampleRate}),this.isPaused&&this.context.suspend(),this.sourceNodes=new Set,this.gainNode=this.context.createGain(),this.gainNode.gain.value=this.volume,this.gainNode.connect(this.context.destination),this.timeSuspended=0,this.timeOffset=0,this.lastTime=performance.now(),this.loopHandle=setInterval(()=>{let e=performance.now();!this.isPaused&&this.context.state==="suspended"&&(this.timeSuspended+=(e-this.lastTime)/1e3),this.lastTime=e},t.updateInterval??10),this.context.onstatechange=()=>{let e=performance.now();this.context?.state==="running"&&(this.timeSuspended+=(e-this.lastTime)/1e3),this.lastTime=e}}async stop(){if(!this.context)throw new Error("Audio manager not started!");clearInterval(this.loopHandle),this.loopHandle=null,await this.context.suspend(),this.context=null}started(){return this.context!=null}getTime(){return(this.context?.currentTime??0)+this.timeSuspended+this.timeOffset}getLatency(){return this.context?(this.context.outputLatency??0)+this.context.baseLatency:0}getVideoTime(){return this.getTime()-this.getLatency()}setVideoTime(t){if(t+=this.getLatency(),this.sourceNodes!=null){for(let e of this.sourceNodes)try{e.stop()}catch{}this.sourceNodes.clear()}this.timeOffset=t-((this.context?.currentTime??0)+this.timeSuspended)}setVolume(t){this.volume=t,this.gainNode&&(this.gainNode.gain.value=t)}async resumeContext(){if(!this.context)throw new Error("Audio manager not started!");this.context.state==="suspended"&&!this.isPaused&&await this.context.resume()}async pause(){this.isPaused||(this.context&&await this.context.suspend(),this.isPaused=!0)}async play(){this.isPaused&&(this.context&&await this.context.resume(),this.isPaused=!1)}scheduleChunk(t,e){let i=t[0].length;if(i<=0)return;let s=this.context.createBuffer(this.numChannels,i,this.sampleRate);for(let h=0;h<this.numChannels;h++)s.copyToChannel(t[h],h);if(e-=this.timeSuspended+this.timeOffset,e>this.context.currentTime&&this.context.state!=="suspended"){let h=this.context.createBufferSource();h.buffer=s,h.connect(this.gainNode),this.sourceNodes.add(h),h.onended=()=>this.sourceNodes.delete(h),h.start(e)}this.playHead+=s.duration}};import*as x from"mp4box";var T=class{constructor(t,e){this.l=t,this.ft=0,this.wt=e}write(t){let e=new ArrayBuffer(t.byteLength);new Uint8Array(e).set(t),e.fileStart=this.ft,this.ft+=e.byteLength,this.l.appendBuffer(e)}close(){this.l.flush(),this.wt()}},A=class{constructor(t,e,{onConfig:i,onChunk:s,onEndOfStream:h}){if(this.V=e,this.mt=i,this.Rt=s,this.l=x.createFile(),this.l.onReady=this.Ct.bind(this),this.l.onSamples=this.St.bind(this),t instanceof ArrayBuffer)t.fileStart=0,this.l.appendBuffer(t),this.l.flush(),h();else{let n=new T(this.l,h);fetch(t).then(r=>{r.body.pipeTo(new WritableStream(n,{highWaterMark:2}))})}}pt(t){let i=this.l.getTrackById(t.id).mdia.minf.stbl.stsd.entries[0];if(this.V)return i.esds.esd.descs[0].descs[0].data;{let s=i.avcC||i.hvcC||i.vpcC||i.av1C;if(!s)return null;let h=new x.DataStream(void 0,0,x.DataStream.BIG_ENDIAN);return s.write(h),new Uint8Array(h.buffer,8)}}Ct(t){if(this.V){let e=t.audioTracks[0];this.mt(e?{codec:e.codec,sampleRate:e.audio.sample_rate,numberOfChannels:e.audio.channel_count,description:this.pt(e)}:null),e&&this.l.setExtractionOptions(e.id)}else{let e=t.videoTracks[0];this.mt({codec:e.codec.startsWith("vp08")?"vp8":e.codec,codedHeight:e.video.height,codedWidth:e.video.width,description:this.pt(e)}),this.l.setExtractionOptions(e.id)}this.l.start()}St(t,e,i){for(let s of i){let h;this.V?h=EncodedAudioChunk:h=EncodedVideoChunk,this.Rt(new h({type:s.is_sync?"key":"delta",timestamp:1e6*s.cts/s.timescale,duration:1e6*s.duration/s.timescale,data:s.data}))}}};var L=1,E=class extends f{static get observedAttributes(){return b.concat(["autoplay","loop","muted","controls"])}constructor(){super(),this.r=[],this.u=[],this.c=[],this.j=!1,this.Z=!1,this.I=!0,this.e=new _,this.e.pause(),this.Y=!1,this.C=document.createElement("div"),this.C.classList.add("rgbd-controls"),Object.assign(this.C.style,{position:"absolute",bottom:"1%",left:"50%",transform:"translateX(-50%)",display:"none",alignItems:"center",justifyContent:"center",gap:"8px",background:"rgba(0, 0, 0, 0.4)",padding:"8px 8px",borderRadius:"8px",backdropFilter:"blur(6px)",boxSizing:"border-box",width:"50%",flexWrap:"wrap"}),this.shadowRoot.appendChild(this.C),this.L=document.createElement("button"),Object.assign(this.L.style,{border:"none",background:"transparent",color:"white",fontSize:"24px",cursor:"pointer",padding:"4px",flexShrink:"0"}),this.C.appendChild(this.L),this.L.addEventListener("click",()=>{this.paused?this.play():this.pause()}),this.f=document.createElement("input"),this.f.type="range",this.f.min="0",this.f.max="1",this.f.value="0",this.f.step="any",Object.assign(this.f.style,{flex:"1 1 auto",minWidth:"120px",maxWidth:"100%",cursor:"pointer",accentColor:"#fff"}),this.C.appendChild(this.f),this.f.addEventListener("input",()=>{let t=this.r[0];if(!t||!t.duration)return;let e=t.startTime+this.f.value*t.duration;this.currentTime=e})}disconnectedCallback(){this.e.started()&&this.e.stop(),super.disconnectedCallback()}attributeChangedCallback(t,e,i){e!==i&&(t==="color-src"?this.clear().then(()=>{this.r=[this.S(i,0,!1)],this.c=[this.S(i,0,!0)],this.K=this.r[0],this.q=this.c[0]}):t==="depth-src"?(this.u=[this.S(i,0,!1)],this.J=this.u[0]):t==="autoplay"?(this.j=this.hasAttribute("autoplay"),this.j&&this.e.play()):t==="loop"?this.Z=this.hasAttribute("loop"):t==="muted"?(this.I=this.hasAttribute("muted"),this.e.setVolume(this.I?0:1),!this.I&&this.e.started()&&this.e.resumeContext()):t==="controls"?(this.Y=this.hasAttribute("controls"),this.C.style.display=this.Y?"flex":"none"):this.X())}async play(){await this.e.play()}async pause(){await this.e.pause()}async clear(){for(this.t=null,this.d=null,this._("color",null),this._("depth",null),this.K=null,this.J=null,this.q=null;this.r.length>0;)this.N(this.r.shift());for(;this.u.length>0;)this.N(this.u.shift());for(;this.c.length>0;)this.N(this.c.shift());this.currentTime=0,this.e.started()&&await this.e.stop()}enqueue(t,e,i){this.r.push(this.S(t,i,!1)),this.u.push(this.S(e,i,!1)),this.c.push(this.S(t,i,!0))}get paused(){return this.e.isPaused}get currentTime(){return this.e.getVideoTime()}set currentTime(t){let e=i=>{if(i.length==0)return;this.N(i[0]),i[0]=this.k(i[0],i[0].startTime);let s=i[0];s.demuxer!=null&&console.error("Demuxing not yet finished!");let h=Number.MAX_VALUE,n=-1;for(let r=0;r<s.chunks.length;r++){if(s.chunks[r].type!=="key")continue;let o=Math.abs(t-(s.startTime+s.chunks[r].timestamp/1e6));o<h&&(h=o,n=r)}n<0||(s.curChunk=n)};this.e.setVideoTime(t),this.Q=null,e(this.r),e(this.u),e(this.c)}get volume(){return this.e.volume}set volume(t){this.e.setVolume(t)}Ot(t){if(this.e.started()){if(t==null)return;if(t.sampleRate!=this.e.sampleRate)throw new Error("Audio configs have mismatched sample rates!");if(t.numberOfChannels!=this.e.numChannels)throw new Error("Audio configs have mismatched channel counts!")}else this.e.start(t?{sampleRate:t.sampleRate,numChannels:t.numberOfChannels,volume:1}:{audioEnabled:!1}),this.I||this.e.resumeContext()}gt(t,e){let i=e+t.timestamp/1e6,s=[];for(let h=0;h<t.numberOfChannels;h++){let n=new Float32Array(t.numberOfFrames);t.copyTo(n,{planeIndex:h,format:"f32-planar"}),s.push(n)}this.e.scheduleChunk(s,i)}S(t,e,i){let s={startTime:e,isAudio:i,duration:0,demuxer:null,decoder:null,chunks:[],frames:[],curChunk:0},h;return i?h=AudioDecoder:h=VideoDecoder,s.decoder=new h({output:n=>{i?this.gt(n,s.startTime):s.frames.push(n)},error:n=>{console.error("Decoder encountered an error while decoding: ",n)}}),s.demuxer=new A(t,i,{onConfig:n=>{s.config=n,n?s.decoder?.configure(n):s.done=!0,i&&this.Ot(n)},onChunk:n=>{s.chunks?.push(n),s.duration=Math.max(s.duration,(n.timestamp+n.duration)/1e6)},onEndOfStream:()=>{s.demuxer=null}}),s}k(t,e){let i={startTime:e,isAudio:t.isAudio,duration:t.duration,demuxer:null,decoder:null,config:t.config,chunks:t.chunks,frames:[],curChunk:0},s;return t.isAudio?s=AudioDecoder:s=VideoDecoder,i.decoder=new s({output:h=>{i.isAudio?this.gt(h,i.startTime):i.frames.push(h)},error:h=>{console.error("Decoder encountered an error while decoding: ",h)}}),t.config?i.decoder.configure(t.config):i.done=!0,i}Dt(){let t=!this.paused;this.L.textContent=t?"\u23F8\uFE0F":"\u25B6\uFE0F";let e=this.r[0];if(!e||!e.duration){this.f.value=0;return}let i=this.currentTime-e.startTime,s=Math.max(0,Math.min(1,i/e.duration));this.f.value=s}H(t,e){let i=(h,n)=>{let r=h[n];for(;r.curChunk<r.chunks.length;){let o=r.chunks[r.curChunk];if(r.startTime+o.timestamp/1e6>this.e.getVideoTime()+L)break;r.decoder.decode(o),r.curChunk++}if(r.curChunk>=r.chunks.length&&!r.demuxer&&r.decoder){let o=r.decoder;o.flush().then(()=>{o.close(),r.done=!0}),r.decoder=null}};for(let h=0;h<this.r.length;h++)i(this.r,h);for(let h=0;h<this.u.length;h++)i(this.u,h);for(let h=0;h<this.c.length;h++)this.c[h].config!=null&&i(this.c,h);let s=h=>h?h.done&&h.frames.length==1:!1;s(this.r[0])&&s(this.u[0])&&(this.r.shift(),this.u.shift(),this._t=!0),this.c[0]?.done&&this.c.shift(),this.Z&&this.r.length==0&&this.u.length==0&&this.c.length==0&&this.K!=null&&this.J!=null&&(this.e.setVideoTime(0),this.r=[this.k(this.K,0)],this.u=[this.k(this.J,0)],this.q!=null&&(this.c=[this.k(this.q,0)])),this.Y&&this.Dt(),super.H(t,e)}B(){this.t=document.createElement("video"),this.t.style.display="block",this.t.classList.add("cover-video"),this.t.muted=this.I,this.t.autoplay=this.j,this.t.loop=this.Z,this.t.src=this.getAttribute("color-src"),this.i.parentElement.appendChild(this.t)}ct(){let t=this.r[0],e=this.u[0];if(!t||!e)return;let i=this.e.getVideoTime(),s=this.Q!=null?Math.abs(i-this.Q):Number.MAX_VALUE,h=-1;for(let n=0;n<Math.min(t.frames.length,e.frames.length);n++){let r=Math.abs(i-(t.startTime+t.frames[n].timestamp/1e6));if(r<=s)s=r,h=n;else break}if(!(h<0)){this._t&&(this.t.close(),this.d.close(),this._t=!1),this.t=t.frames[h],this.d=e.frames[h],this.Q=t.startTime+this.t.timestamp/1e6,this.t?.timestamp!==this.d?.timestamp&&console.error("Color and depth frames have mismatched PTS"),this._("color",this.t),this._("depth",this.d);for(let n=0;n<h;n++)t.frames.shift().close(),e.frames.shift().close()}}W(t){return t instanceof VideoFrame}A(t){return t?t.codedWidth:1}E(t){return t?t.codedHeight:1}N(t){t.decoder?.close(),t.decoder=null;for(let e=0;e<t.frames.length;e++)t.frames[e].close()}};y&&(customElements.define("rgbd-img",g),customElements.define("rgbd-video",E));
81
+ .fallback { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: contain; }
82
+ `,this.U.appendChild(e),this.i=document.createElement("canvas"),this.i.style.width="100%",this.i.style.height="100%",this.i.style.objectFit="contain",this.i.setAttribute("role","img"),this.i.setAttribute("aria-label","3D image"),t.appendChild(this.i),this.g=document.createElement("button"),this.g.textContent="Enter VR",Object.assign(this.g.style,{position:"absolute",display:"none",top:"1%",right:"1%",color:"white",background:"rgba(0,0,0,0.4)",padding:"8px 8px",fontFamily:"monospace",fontSize:"20px",borderRadius:"8px",border:"1px solid white",backdropFilter:"blur(6px)",whiteSpace:"pre"}),t.appendChild(this.g),this.g.addEventListener("click",()=>{this.a?this.exitXR():this.enterXR()})}connectedCallback(){this.H();let t;try{this.Et(),t=!1}catch{t=!0}this.i.addEventListener("resize",this.et),this.i.addEventListener("mousemove",this.it),this.i.addEventListener("mouseleave",this.st),t?this.B():(this.D(),this.F=!0,this.X=performance.now(),this.T=requestAnimationFrame(this.v)),this.nt()}disconnectedCallback(){this.F=!1,cancelAnimationFrame(this.T),this.i.removeEventListener("resize",this.et),this.i.removeEventListener("mousemove",this.it),this.i.removeEventListener("mouseleave",this.st);try{this.a&&(this.a.end(),this.a=null,this.At=!1)}catch{}try{if(this.n){let t=this.n;this.P&&t.deleteProgram(this.P);for(let e in this.O)t.deleteTexture(this.O[e].tex)}}catch{}}setViewMatrix(t){this.$=t&&t.length===16?new Float32Array(t):null}setProjectionMatrix(t){this.tt=t&&t.length===16?new Float32Array(t):null}async enterXR(){if(!this.a)try{let t=await navigator.xr.requestSession("immersive-vr",{optionalFeatures:["local-floor","bounded-floor"]});this.n.makeXRCompatible&&await this.n.makeXRCompatible(),this.D();let e=new XRWebGLLayer(t,this.n);await t.updateRenderState({baseLayer:e});let i=await t.requestReferenceSpace("local");this.a=t,this.R=i,this.C=null,this.h={x:0,y:0,z:0,yaw:0},cancelAnimationFrame(this.T),t.addEventListener("end",()=>{this.exitXR()}),t.requestAnimationFrame(this.v)}catch(t){console.warn("Unable to start XR session",t)}}async exitXR(){if(this.a){try{await this.a.end()}catch{}this.a=null,this.R=null,this.C=null,this.D(),this.T=requestAnimationFrame(this.v)}}get width(){return this.E(this.t)}get height(){return this.M(this.t)}Et(){let t=this.i.getContext("webgl2",{antialias:!0,alpha:!1});if(!t)throw new Error("WebGL not supported");this.n=t;let e=this.Mt(t,I,P);if(!e)return;this.P=e,t.useProgram(e);let i=this.rt(t),s=this.rt(t);this.O.color=i,this.O.depth=s,this._("color",this.t),this._("depth",this.d);let h=t.getUniformLocation(e,"u_colorImage"),n=t.getUniformLocation(e,"u_depthImage");t.uniform1i(h,0),t.uniform1i(n,1),this.p={uProjection:t.getUniformLocation(e,"u_projMat"),uView:t.getUniformLocation(e,"u_viewMat"),uImageSize:t.getUniformLocation(e,"u_imageSize"),uFocal:t.getUniformLocation(e,"u_focal"),uDepthMin:t.getUniformLocation(e,"u_depthMin"),uDepthMax:t.getUniformLocation(e,"u_depthMax"),uGridSegs:t.getUniformLocation(e,"u_grid"),uXr:t.getUniformLocation(e,"u_xr")}}ot(t=null){if(!this.n)return;let e=this.n;e.bindFramebuffer(e.FRAMEBUFFER,t),e.useProgram(this.P),e.clearColor(...this.s.BACKGROUND_COLOR,1),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT),e.enable(e.DEPTH_TEST)}at(t,e){if(!this.n)return;let i=this.n,s=this.E(this.t),h=this.M(this.t),n=s/h,r=Math.max(1,Math.floor(this.s.GRID_SIZE)),o=Math.max(1,Math.round(r/n));i.uniform2f(this.p.uImageSize,s,h),i.uniform1f(this.p.uFocal,this.s.FOCAL_LENGTH),i.uniform1f(this.p.uDepthMin,this.s.DEPTH_MIN),i.uniform1f(this.p.uDepthMax,this.s.DEPTH_MAX),i.uniform2i(this.p.uGridSegs,r,o),i.uniform1ui(this.p.uXr,this.a?1:0),i.uniformMatrix4fv(this.p.uView,!1,t),i.uniformMatrix4fv(this.p.uProjection,!1,e),i.drawArrays(i.TRIANGLES,0,r*o*6)}G(t,e){if(!this.F)return;let i=t-this.X;this.X=t,this.ut(),this.m.hovered||(this.m.x=Math.sin(t*this.s.BOOMERANG_SPEED),this.m.y=Math.sin(t*this.s.BOOMERANG_SPEED*.5+Math.PI));let s=this.m.x*this.s.CAM_MAX_THETA+Math.PI,h=-this.m.y*this.s.CAM_MAX_PHI,n=this.s.CAM_RADIUS*(1-this.s.CAM_ZOOM_AMOUNT),r=this.m.hovered?n:this.s.CAM_RADIUS;if(this.o.theta=this.b(s,this.o.theta,i),this.o.phi=this.b(h,this.o.phi,i),this.o.radius=this.b(r,this.o.radius,i),this.a){let o=this.R.getOffsetReferenceSpace(new XRRigidTransform({x:this.h.x,y:this.h.y,z:this.h.z},{x:0,y:Math.sin(this.h.yaw*.5),z:0,w:Math.cos(this.h.yaw*.5)}));this.h.x=this.b(0,this.h.x,i),this.h.y=this.b(0,this.h.y,i),this.h.z=this.b(0,this.h.z,i),this.h.yaw=this.b(0,this.h.yaw,i);let a=e.getViewerPose(this.R).transform;this.C||(this.C=a);let u=this.C,c=a.position.x-u.position.x,l=a.position.y-u.position.y,p=a.position.z-u.position.z,d=this.ct(a.orientation);(Math.abs(d-this.ct(u.orientation))>this.s.XR_RECENTER_YAW*Math.PI/180||Math.hypot(c,l,p)>this.s.XR_RECENTER_RADIUS)&&(this.h.x=-a.position.x,this.h.y=-a.position.y,this.h.z=-a.position.z,this.h.yaw=-d,this.R=this.R.getOffsetReferenceSpace(new XRRigidTransform(a.position,{x:0,y:Math.sin(d*.5),z:0,w:Math.cos(d*.5)})),this.C=null);let R=e.session,C=e.getViewerPose(o);if(!C){R.requestAnimationFrame(this.v);return}let S=R.renderState.baseLayer;this.ot(S.framebuffer);for(let y of C.views){let M=S.getViewport(y);this.n.viewport(M.x,M.y,M.width,M.height);let O=new Float32Array(y.transform.inverse.matrix),D=new Float32Array(y.projectionMatrix);this.at(O,D)}}else{let o=this.i.width/this.i.height,a=[this.o.radius*Math.cos(this.o.phi)*Math.sin(this.o.theta),this.o.radius*Math.sin(this.o.phi),this.s.CAM_RADIUS+this.o.radius*Math.cos(this.o.phi)*Math.cos(this.o.theta)],u=[0,0,this.s.CAM_RADIUS],c=[0,-1,0],l=this.height*(1-this.s.IMG_ZOOM_AMOUNT),p=2*Math.atan(l/(2*this.s.FOCAL_LENGTH)),d=this.$||new Float32Array(this.bt(a,u,c)),w=this.tt||new Float32Array(this.yt(p,o,.1,100));this.ot(),this.at(d,w)}this.a?this.T=e.session.requestAnimationFrame(this.v):this.T=requestAnimationFrame(this.v)}nt(){this.ht&&navigator.xr&&navigator.xr.isSessionSupported?navigator.xr.isSessionSupported("immersive-vr").then(t=>{this.g.style.display=t?"block":"none"}).catch(()=>{this.g.style.display="none"}):this.g.style.display="none"}gt(t){let e=this.i.getBoundingClientRect();this.m.hovered=!0,this.m.x=(t.clientX-e.left)/e.width*2-1,this.m.y=(t.clientY-e.top)/e.height*2-1}_t(){this.m.hovered=!1}D(){let t=window.devicePixelRatio||1,e=this.i.parentElement;if(!e)return;let i=e.clientWidth,s=e.clientHeight,h=this.E(this.t)||1,n=this.M(this.t)||1,r=h/n,o=i,a=o/r;a>s&&(a=s,o=a*r);let u=Math.max(1,Math.floor((this.a?i:o)*t)),c=Math.max(1,Math.floor((this.a?s:a)*t));this.i.width=u,this.i.height=c,this.n&&this.n.viewport(0,0,u,c)}H(){let t=this.s;if(this.hasAttribute("grid-size")&&(t.GRID_SIZE=parseInt(this.getAttribute("grid-size"))??t.GRID_SIZE),this.hasAttribute("focal-length")&&(t.FOCAL_LENGTH=parseFloat(this.getAttribute("focal-length"))??t.FOCAL_LENGTH),this.hasAttribute("depth-min")&&(t.DEPTH_MIN=parseFloat(this.getAttribute("depth-min"))??t.DEPTH_MIN),this.hasAttribute("depth-max")&&(t.DEPTH_MAX=parseFloat(this.getAttribute("depth-max"))??t.DEPTH_MAX),this.hasAttribute("cam-radius")&&(t.CAM_RADIUS=parseFloat(this.getAttribute("cam-radius"))??t.CAM_RADIUS),this.hasAttribute("cam-max-theta")&&(t.CAM_MAX_THETA=parseFloat(this.getAttribute("cam-max-theta"))??t.CAM_MAX_THETA),this.hasAttribute("cam-max-phi")&&(t.CAM_MAX_PHI=parseFloat(this.getAttribute("cam-max-phi"))??t.CAM_MAX_PHI),this.hasAttribute("cam-smoothness")&&(t.CAM_SMOOTHNESS=parseFloat(this.getAttribute("cam-smoothness"))??t.CAM_SMOOTHNESS),this.hasAttribute("cam-zoom-amount")&&(t.CAM_ZOOM_AMOUNT=parseFloat(this.getAttribute("cam-zoom-amount"))??t.CAM_ZOOM_AMOUNT),this.hasAttribute("boomerang-speed")&&(t.BOOMERANG_SPEED=parseFloat(this.getAttribute("boomerang-speed"))??t.BOOMERANG_SPEED),this.hasAttribute("background-color"))try{let e=this.getAttribute("background-color").split(",").map(Number);e.length===3&&(t.BACKGROUND_COLOR=e)}catch{}this.hasAttribute("img-zoom-amount")&&(t.IMG_ZOOM_AMOUNT=parseFloat(this.getAttribute("img-zoom-amount"))??t.IMG_ZOOM_AMOUNT),this.ht=this.hasAttribute("xr-button"),this.hasAttribute("xr-recenter-yaw")&&(t.XR_RECENTER_YAW=parseFloat(this.getAttribute("xr-recenter-yaw"))??t.XR_RECENTER_YAW),this.hasAttribute("xr-recenter-radius")&&(t.XR_RECENTER_RADIUS=parseFloat(this.getAttribute("xr-recenter-radius"))??t.XR_RECENTER_RADIUS),this.nt()}lt(t,e,i){let s=t.createShader(e);return t.shaderSource(s,i),t.compileShader(s),t.getShaderParameter(s,t.COMPILE_STATUS)?s:(console.error(t.getShaderInfoLog(s)),t.deleteShader(s),null)}Mt(t,e,i){let s=this.lt(t,t.VERTEX_SHADER,e),h=this.lt(t,t.FRAGMENT_SHADER,i);if(!s||!h)return null;let n=t.createProgram();return t.attachShader(n,s),t.attachShader(n,h),t.linkProgram(n),t.getProgramParameter(n,t.LINK_STATUS)?(t.deleteShader(s),t.deleteShader(h),n):(console.error(t.getProgramInfoLog(n)),t.deleteProgram(n),null)}rt(t){let e=t.createTexture();return t.bindTexture(t.TEXTURE_2D,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),{tex:e,width:0,height:0}}_(t,e){if(!this.n)return;let i=this.n,s=this.O[t];if(i.activeTexture(t==="color"?i.TEXTURE0:i.TEXTURE1),i.bindTexture(i.TEXTURE_2D,s.tex),!this.W(e)){i.texImage2D(i.TEXTURE_2D,0,i.RGBA,1,1,0,i.RGBA,i.UNSIGNED_BYTE,new Uint8Array([0,0,0,0]));return}try{i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,!1),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,i.RGBA,i.UNSIGNED_BYTE,e),(this.E(e)!=s.width||this.M(e)!=s.height)&&(this.D(),s.width=this.E(e),s.height=this.M(e))}catch{}}yt(t,e,i,s){let h=1/Math.tan(t/2);return[h/e,0,0,0,0,h,0,0,0,0,(s+i)/(i-s),-1,0,0,2*s*i/(i-s),0]}bt(t,e,i){function s(u){let c=Math.hypot(...u)||1;return u.map(l=>l/c)}function h(u,c){return[u[1]*c[2]-u[2]*c[1],u[2]*c[0]-u[0]*c[2],u[0]*c[1]-u[1]*c[0]]}function n(u,c){return u.map((l,p)=>l-c[p])}let r=s(n(t,e)),o=s(h(i,r)),a=h(r,o);return[o[0],a[0],r[0],0,o[1],a[1],r[1],0,o[2],a[2],r[2],0,-(o[0]*t[0]+o[1]*t[1]+o[2]*t[2]),-(a[0]*t[0]+a[1]*t[1]+a[2]*t[2]),-(r[0]*t[0]+r[1]*t[1]+r[2]*t[2]),1]}ct(t){return Math.atan2(2*(t.w*t.y+t.x*t.z),1-2*(t.y*t.y+t.x*t.x))}b(t,e,i){let s=(1-this.s.CAM_SMOOTHNESS)*i/16.67,h=Math.sign(t-e);return e+=(t-e)*s,Math.sign(t-e)!==h&&(e=t),e}B(){throw new Error("Must implement _createFallback")}ut(){}W(t){throw new Error("Must implement _isSourceReady")}E(t){throw new Error("Must implement _getSourceWidth")}M(t){throw new Error("Must implement _getSourceHeight")}}:f=class{};var x=class extends f{static get observedAttributes(){return b}constructor(){super(),this.t=new Image,this.d=new Image,this.t.crossOrigin="anonymous",this.d.crossOrigin="anonymous",this.t.onload=()=>this._("color",this.t),this.d.onload=()=>this._("depth",this.d)}attributeChangedCallback(t,e,i){e!==i&&(t==="color-src"?this.t.src=i||"":t==="depth-src"?this.d.src=i||"":this.H())}B(){this.t.style.display="block",this.t.classList.add("fallback"),this.i.parentElement.appendChild(this.t)}W(t){return t&&t.complete&&t.naturalWidth>0}E(t){return t?t.width:1}M(t){return t?t.height:1}};var g=class{constructor(){this.context=null,this.sourceNodes=null,this.gainNode=null,this.volume=1,this.sampleRate=0,this.numChannels=0,this.timeSuspended=0,this.timeOffset=0,this.lastTime=0,this.context=null,this.isPaused=!1,this.loopHandle=null}start(t={}){if(this.context)throw new Error("Audio manager already started!");this.audioEnabled=t.audioEnabled??!0,this.sampleRate=t.sampleRate??44100,this.numChannels=t.numChannels??2,this.context=new AudioContext({sampleRate:this.sampleRate}),this.isPaused&&this.context.suspend(),this.sourceNodes=new Set,this.gainNode=this.context.createGain(),this.gainNode.gain.value=this.volume,this.gainNode.connect(this.context.destination),this.timeSuspended=0,this.timeOffset=0,this.lastTime=performance.now(),this.loopHandle=setInterval(()=>{let e=performance.now();!this.isPaused&&this.context.state==="suspended"&&(this.timeSuspended+=(e-this.lastTime)/1e3),this.lastTime=e},t.updateInterval??10),this.context.onstatechange=()=>{let e=performance.now();this.context?.state==="running"&&(this.timeSuspended+=(e-this.lastTime)/1e3),this.lastTime=e}}async stop(){if(!this.context)throw new Error("Audio manager not started!");clearInterval(this.loopHandle),this.loopHandle=null,await this.context.suspend(),this.context=null}started(){return this.context!=null}getTime(){return(this.context?.currentTime??0)+this.timeSuspended+this.timeOffset}getLatency(){return this.context?(this.context.outputLatency??0)+this.context.baseLatency:0}getVideoTime(){return this.getTime()-this.getLatency()}setVideoTime(t){if(t+=this.getLatency(),this.sourceNodes!=null){for(let e of this.sourceNodes)try{e.stop()}catch{}this.sourceNodes.clear()}this.timeOffset=t-((this.context?.currentTime??0)+this.timeSuspended)}setVolume(t){this.volume=t,this.gainNode&&(this.gainNode.gain.value=t)}async resumeContext(){if(!this.context)throw new Error("Audio manager not started!");this.context.state==="suspended"&&!this.isPaused&&await this.context.resume()}async pause(){this.isPaused||(this.context&&await this.context.suspend(),this.isPaused=!0)}async play(){this.isPaused&&(this.context&&await this.context.resume(),this.isPaused=!1)}scheduleChunk(t,e){let i=t[0].length;if(i<=0)return;let s=this.context.createBuffer(this.numChannels,i,this.sampleRate);for(let h=0;h<this.numChannels;h++)s.copyToChannel(t[h],h);if(e-=this.timeSuspended+this.timeOffset,e>this.context.currentTime&&this.context.state!=="suspended"){let h=this.context.createBufferSource();h.buffer=s,h.connect(this.gainNode),this.sourceNodes.add(h),h.onended=()=>this.sourceNodes.delete(h),h.start(e)}this.playHead+=s.duration}};import*as _ from"mp4box";var v=class{constructor(t,e){this.l=t,this.dt=0,this.Tt=e}write(t){let e=new ArrayBuffer(t.byteLength);new Uint8Array(e).set(t),e.fileStart=this.dt,this.dt+=e.byteLength,this.l.appendBuffer(e)}close(){this.l.flush(),this.Tt()}},A=class{constructor(t,e,{onConfig:i,onChunk:s,onEndOfStream:h}){if(this.V=e,this.ft=i,this.vt=s,this.l=_.createFile(),this.l.onReady=this.wt.bind(this),this.l.onSamples=this.Rt.bind(this),t instanceof ArrayBuffer)t.fileStart=0,this.l.appendBuffer(t),this.l.flush(),h();else{let n=new v(this.l,h);fetch(t).then(r=>{r.body.pipeTo(new WritableStream(n,{highWaterMark:2}))})}}mt(t){let i=this.l.getTrackById(t.id).mdia.minf.stbl.stsd.entries[0];if(this.V)return i.esds.esd.descs[0].descs[0].data;{let s=i.avcC||i.hvcC||i.vpcC||i.av1C;if(!s)return null;let h=new _.DataStream(void 0,0,_.DataStream.BIG_ENDIAN);return s.write(h),new Uint8Array(h.buffer,8)}}wt(t){if(this.V){let e=t.audioTracks[0];this.ft(e?{codec:e.codec,sampleRate:e.audio.sample_rate,numberOfChannels:e.audio.channel_count,description:this.mt(e)}:null),e&&this.l.setExtractionOptions(e.id)}else{let e=t.videoTracks[0];this.ft({codec:e.codec.startsWith("vp08")?"vp8":e.codec,codedHeight:e.video.height,codedWidth:e.video.width,description:this.mt(e)}),this.l.setExtractionOptions(e.id)}this.l.start()}Rt(t,e,i){for(let s of i){let h;this.V?h=EncodedAudioChunk:h=EncodedVideoChunk,this.vt(new h({type:s.is_sync?"key":"delta",timestamp:1e6*s.cts/s.timescale,duration:1e6*s.duration/s.timescale,data:s.data}))}}};var L=1,E=class extends f{static get observedAttributes(){return b.concat(["autoplay","loop","muted","controls"])}constructor(){super(),this.r=[],this.u=[],this.c=[],this.j=!1,this.Z=!1,this.I=!0,this.e=new g,this.e.pause(),this.Y=!1,this.A=document.createElement("div"),this.A.classList.add("rgbd-controls"),Object.assign(this.A.style,{position:"absolute",bottom:"1%",left:"50%",transform:"translateX(-50%)",display:"none",alignItems:"center",justifyContent:"center",gap:"8px",background:"rgba(0, 0, 0, 0.4)",padding:"8px 8px",borderRadius:"8px",backdropFilter:"blur(6px)",boxSizing:"border-box",width:"50%",flexWrap:"wrap"}),this.shadowRoot.appendChild(this.A),this.L=document.createElement("button"),Object.assign(this.L.style,{border:"none",background:"transparent",color:"white",fontSize:"24px",cursor:"pointer",padding:"4px",flexShrink:"0"}),this.A.appendChild(this.L),this.L.addEventListener("click",()=>{this.paused?this.play():this.pause()}),this.f=document.createElement("input"),this.f.type="range",this.f.min="0",this.f.max="1",this.f.value="0",this.f.step="any",Object.assign(this.f.style,{flex:"1 1 auto",minWidth:"120px",maxWidth:"100%",cursor:"pointer",accentColor:"#fff"}),this.A.appendChild(this.f),this.f.addEventListener("input",()=>{let t=this.r[0];if(!t||!t.duration)return;let e=t.startTime+this.f.value*t.duration;this.currentTime=e})}disconnectedCallback(){this.e.started()&&this.e.stop(),super.disconnectedCallback()}attributeChangedCallback(t,e,i){e!==i&&(t==="color-src"?this.clear().then(()=>{this.r=[this.S(i,0,!1)],this.c=[this.S(i,0,!0)],this.K=this.r[0],this.q=this.c[0]}):t==="depth-src"?(this.u=[this.S(i,0,!1)],this.J=this.u[0]):t==="autoplay"?(this.j=this.hasAttribute("autoplay"),this.j&&this.e.play()):t==="loop"?this.Z=this.hasAttribute("loop"):t==="muted"?(this.I=this.hasAttribute("muted"),this.e.setVolume(this.I?0:1),!this.I&&this.e.started()&&this.e.resumeContext()):t==="controls"?(this.Y=this.hasAttribute("controls"),this.A.style.display=this.Y?"flex":"none"):this.H())}async play(){await this.e.play()}async pause(){await this.e.pause()}async clear(){for(this.t=null,this.d=null,this._("color",null),this._("depth",null),this.K=null,this.J=null,this.q=null;this.r.length>0;)this.N(this.r.shift());for(;this.u.length>0;)this.N(this.u.shift());for(;this.c.length>0;)this.N(this.c.shift());this.currentTime=0,this.e.started()&&await this.e.stop()}enqueue(t,e,i){this.r.push(this.S(t,i,!1)),this.u.push(this.S(e,i,!1)),this.c.push(this.S(t,i,!0))}get paused(){return this.e.isPaused}get currentTime(){return this.e.getVideoTime()}set currentTime(t){let e=i=>{if(i.length==0)return;this.N(i[0]),i[0]=this.k(i[0],i[0].startTime);let s=i[0];s.demuxer!=null&&console.error("Demuxing not yet finished!");let h=Number.MAX_VALUE,n=-1;for(let r=0;r<s.chunks.length;r++){if(s.chunks[r].type!=="key")continue;let o=Math.abs(t-(s.startTime+s.chunks[r].timestamp/1e6));o<h&&(h=o,n=r)}n<0||(s.curChunk=n)};this.e.setVideoTime(t),this.Q=null,e(this.r),e(this.u),e(this.c)}get volume(){return this.e.volume}set volume(t){this.e.setVolume(t)}Ct(t){if(this.e.started()){if(t==null)return;if(t.sampleRate!=this.e.sampleRate)throw new Error("Audio configs have mismatched sample rates!");if(t.numberOfChannels!=this.e.numChannels)throw new Error("Audio configs have mismatched channel counts!")}else this.e.start(t?{sampleRate:t.sampleRate,numChannels:t.numberOfChannels,volume:1}:{audioEnabled:!1}),this.I||this.e.resumeContext()}pt(t,e){let i=e+t.timestamp/1e6,s=[];for(let h=0;h<t.numberOfChannels;h++){let n=new Float32Array(t.numberOfFrames);t.copyTo(n,{planeIndex:h,format:"f32-planar"}),s.push(n)}this.e.scheduleChunk(s,i)}S(t,e,i){let s={startTime:e,isAudio:i,duration:0,demuxer:null,decoder:null,chunks:[],frames:[],curChunk:0},h;return i?h=AudioDecoder:h=VideoDecoder,s.decoder=new h({output:n=>{i?this.pt(n,s.startTime):s.frames.push(n)},error:n=>{console.error("Decoder encountered an error while decoding: ",n)}}),s.demuxer=new A(t,i,{onConfig:n=>{s.config=n,n?s.decoder?.configure(n):s.done=!0,i&&this.Ct(n)},onChunk:n=>{s.chunks?.push(n),s.duration=Math.max(s.duration,(n.timestamp+n.duration)/1e6)},onEndOfStream:()=>{s.demuxer=null}}),s}k(t,e){let i={startTime:e,isAudio:t.isAudio,duration:t.duration,demuxer:null,decoder:null,config:t.config,chunks:t.chunks,frames:[],curChunk:0},s;return t.isAudio?s=AudioDecoder:s=VideoDecoder,i.decoder=new s({output:h=>{i.isAudio?this.pt(h,i.startTime):i.frames.push(h)},error:h=>{console.error("Decoder encountered an error while decoding: ",h)}}),t.config?i.decoder.configure(t.config):i.done=!0,i}St(){let t=!this.paused;this.L.textContent=t?"\u23F8\uFE0F":"\u25B6\uFE0F";let e=this.r[0];if(!e||!e.duration){this.f.value=0;return}let i=this.currentTime-e.startTime,s=Math.max(0,Math.min(1,i/e.duration));this.f.value=s}G(t,e){let i=(h,n)=>{let r=h[n];for(;r.curChunk<r.chunks.length;){let o=r.chunks[r.curChunk];if(r.startTime+o.timestamp/1e6>this.e.getVideoTime()+L)break;r.decoder.decode(o),r.curChunk++}if(r.curChunk>=r.chunks.length&&!r.demuxer&&r.decoder){let o=r.decoder;o.flush().then(()=>{o.close(),r.done=!0}),r.decoder=null}};for(let h=0;h<this.r.length;h++)i(this.r,h);for(let h=0;h<this.u.length;h++)i(this.u,h);for(let h=0;h<this.c.length;h++)this.c[h].config!=null&&i(this.c,h);let s=h=>h?h.done&&h.frames.length==1:!1;s(this.r[0])&&s(this.u[0])&&(this.r.shift(),this.u.shift(),this.xt=!0),this.c[0]?.done&&this.c.shift(),this.Z&&this.r.length==0&&this.u.length==0&&this.c.length==0&&this.K!=null&&this.J!=null&&(this.e.setVideoTime(0),this.r=[this.k(this.K,0)],this.u=[this.k(this.J,0)],this.q!=null&&(this.c=[this.k(this.q,0)])),this.Y&&this.St(),super.G(t,e)}B(){this.t=document.createElement("video"),this.t.style.display="block",this.t.classList.add("fallback"),this.t.controls=this.A,this.t.muted=this.I,this.t.loop=this.Z,this.t.autoplay=this.j,this.t.src=this.getAttribute("color-src"),this.i.parentElement.appendChild(this.t),this.A.style.display="none"}ut(){let t=this.r[0],e=this.u[0];if(!t||!e)return;let i=this.e.getVideoTime(),s=this.Q!=null?Math.abs(i-this.Q):Number.MAX_VALUE,h=-1;for(let n=0;n<Math.min(t.frames.length,e.frames.length);n++){let r=Math.abs(i-(t.startTime+t.frames[n].timestamp/1e6));if(r<=s)s=r,h=n;else break}if(!(h<0)){this.xt&&(this.t.close(),this.d.close(),this.xt=!1),this.t=t.frames[h],this.d=e.frames[h],this.Q=t.startTime+this.t.timestamp/1e6,this.t?.timestamp!==this.d?.timestamp&&console.error("Color and depth frames have mismatched PTS"),this._("color",this.t),this._("depth",this.d);for(let n=0;n<h;n++)t.frames.shift().close(),e.frames.shift().close()}}W(t){return t instanceof VideoFrame}E(t){return t?t.codedWidth:1}M(t){return t?t.codedHeight:1}N(t){t.decoder?.close(),t.decoder=null;for(let e=0;e<t.frames.length;e++)t.frames[e].close()}};T&&(customElements.define("rgbd-img",x),customElements.define("rgbd-video",E));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rgbd",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
package/dist/rgbd.js DELETED
@@ -1,82 +0,0 @@
1
- var b=class{constructor(){this.context=null,this.sourceNodes=null,this.gainNode=null,this.volume=1,this.sampleRate=0,this.numChannels=0,this.timeSuspended=0,this.timeOffset=0,this.lastTime=0,this.context=null,this.isPaused=!1,this.loopHandle=null}start(a={}){if(this.context)throw new Error("Audio manager already started!");this.audioEnabled=a.audioEnabled??!0,this.sampleRate=a.sampleRate??44100,this.numChannels=a.numChannels??2,this.context=new AudioContext({sampleRate:this.sampleRate}),this.isPaused&&this.context.suspend(),this.sourceNodes=new Set,this.gainNode=this.context.createGain(),this.gainNode.gain.value=this.volume,this.gainNode.connect(this.context.destination),this.timeSuspended=0,this.timeOffset=0,this.lastTime=performance.now(),this.loopHandle=setInterval(()=>{let o=performance.now();!this.isPaused&&this.context.state==="suspended"&&(this.timeSuspended+=(o-this.lastTime)/1e3),this.lastTime=o},a.updateInterval??10),this.context.onstatechange=()=>{let o=performance.now();this.context?.state==="running"&&(this.timeSuspended+=(o-this.lastTime)/1e3),this.lastTime=o}}async stop(){if(!this.context)throw new Error("Audio manager not started!");clearInterval(this.loopHandle),this.loopHandle=null,await this.context.suspend(),this.context=null}started(){return this.context!=null}getTime(){return(this.context?.currentTime??0)+this.timeSuspended+this.timeOffset}getLatency(){return this.context?(this.context.outputLatency??0)+this.context.baseLatency:0}getVideoTime(){return this.getTime()-this.getLatency()}setVideoTime(a){if(a+=this.getLatency(),this.sourceNodes!=null){for(let o of this.sourceNodes)try{o.stop()}catch{}this.sourceNodes.clear()}this.timeOffset=a-((this.context?.currentTime??0)+this.timeSuspended)}setVolume(a){this.volume=a,this.gainNode&&(this.gainNode.gain.value=a)}async resumeContext(){if(!this.context)throw new Error("Audio manager not started!");this.context.state==="suspended"&&!this.isPaused&&await this.context.resume()}async pause(){this.isPaused||(this.context&&await this.context.suspend(),this.isPaused=!0)}async play(){this.isPaused&&(this.context&&await this.context.resume(),this.isPaused=!1)}scheduleChunk(a,o){let p=a[0].length;if(p<=0)return;let m=this.context.createBuffer(this.numChannels,p,this.sampleRate);for(let c=0;c<this.numChannels;c++)m.copyToChannel(a[c],c);if(o-=this.timeSuspended+this.timeOffset,o>this.context.currentTime&&this.context.state!=="suspended"){let c=this.context.createBufferSource();c.buffer=m,c.connect(this.gainNode),this.sourceNodes.add(c),c.onended=()=>this.sourceNodes.delete(c),c.start(o)}this.playHead+=m.duration}};import*as E from"mp4box";var C=class{constructor(a,o){this.l=a,this.$=0,this._t=o}write(a){let o=new ArrayBuffer(a.byteLength);new Uint8Array(o).set(a),o.fileStart=this.$,this.$+=o.byteLength,this.l.appendBuffer(o)}close(){this.l.flush(),this._t()}},M=class{constructor(a,o,{onConfig:p,onChunk:m,onEndOfStream:c}){if(this.U=o,this.tt=p,this.xt=m,this.l=E.createFile(),this.l.onReady=this.At.bind(this),this.l.onSamples=this.Et.bind(this),a instanceof ArrayBuffer)a.fileStart=0,this.l.appendBuffer(a),this.l.flush(),c();else{let w=new C(this.l,c);fetch(a).then(g=>{g.body.pipeTo(new WritableStream(w,{highWaterMark:2}))})}}et(a){let p=this.l.getTrackById(a.id).mdia.minf.stbl.stsd.entries[0];if(this.U)return p.esds.esd.descs[0].descs[0].data;{let m=p.avcC||p.hvcC||p.vpcC||p.av1C;if(!m)return null;let c=new E.DataStream(void 0,0,E.DataStream.BIG_ENDIAN);return m.write(c),new Uint8Array(c.buffer,8)}}At(a){if(this.U){let o=a.audioTracks[0];this.tt(o?{codec:o.codec,sampleRate:o.audio.sample_rate,numberOfChannels:o.audio.channel_count,description:this.et(o)}:null),o&&this.l.setExtractionOptions(o.id)}else{let o=a.videoTracks[0];this.tt({codec:o.codec.startsWith("vp08")?"vp8":o.codec,codedHeight:o.video.height,codedWidth:o.video.width,description:this.et(o)}),this.l.setExtractionOptions(o.id)}this.l.start()}Et(a,o,p){for(let m of p){let c;this.U?c=EncodedAudioChunk:c=EncodedVideoChunk,this.xt(new c({type:m.is_sync?"key":"delta",timestamp:1e6*m.cts/m.timescale,duration:1e6*m.duration/m.timescale,data:m.data}))}}};var U=typeof window<"u"&&typeof HTMLElement<"u"&&typeof document<"u",T,S,O;if(!U)T=class{},S=class{},O=class{};else{let p=function(g){return Math.atan2(2*(g.w*g.y+g.x*g.z),1-2*(g.y*g.y+g.x*g.x))},v=`#version 300 es
2
-
3
- precision mediump float;
4
- precision mediump int;
5
-
6
- uniform sampler2D u_depthImage;
7
- uniform mat4 u_projMat;
8
- uniform mat4 u_viewMat;
9
- uniform vec2 u_imageSize;
10
- uniform float u_focal;
11
- uniform float u_depthMin;
12
- uniform float u_depthMax;
13
- uniform ivec2 u_grid;
14
- uniform uint u_xr;
15
-
16
- out vec2 v_uv;
17
-
18
- void main()
19
- {
20
- int vid = gl_VertexID;
21
- int quad = vid / 6;
22
- int v = vid - quad * 6;
23
-
24
- int widthGrid = u_grid.x;
25
- int heightGrid = u_grid.y;
26
-
27
- int x = quad % widthGrid;
28
- int y = quad / widthGrid;
29
-
30
- float fx = float(x) / float(widthGrid);
31
- float fy = float(y) / float(heightGrid);
32
- float fx1 = float(x + 1) / float(widthGrid);
33
- float fy1 = float(y + 1) / float(heightGrid);
34
-
35
- vec2 uv00 = vec2(fx , 1.0 - fy);
36
- vec2 uv10 = vec2(fx1, 1.0 - fy);
37
- vec2 uv01 = vec2(fx , 1.0 - fy1);
38
- vec2 uv11 = vec2(fx1, 1.0 - fy1);
39
-
40
- vec2 uv;
41
- if (v == 0) uv = uv00;
42
- else if (v == 1) uv = uv10;
43
- else if (v == 2) uv = uv01;
44
- else if (v == 3) uv = uv10;
45
- else if (v == 4) uv = uv11;
46
- else uv = uv01;
47
-
48
- float depth = texture(u_depthImage, uv).r;
49
- float z = mix(u_depthMin, u_depthMax, depth);
50
- if(u_xr != 0u)
51
- z *= -1.0;
52
-
53
- vec2 pixelPos = uv * u_imageSize;
54
- vec2 pos = (pixelPos - u_imageSize * 0.5) * z / u_focal;
55
- if(u_xr != 0u)
56
- pos.x *= -1.0;
57
-
58
- v_uv = uv;
59
- gl_Position = u_projMat * u_viewMat * vec4(pos.x, pos.y, z, 1.0);
60
- }
61
-
62
- `,a=`#version 300 es
63
-
64
- precision mediump float;
65
-
66
- in vec2 v_uv;
67
-
68
- out vec4 fragColor;
69
-
70
- uniform sampler2D u_colorImage;
71
- uniform sampler2D u_depthImage;
72
-
73
- void main()
74
- {
75
- fragColor = texture(u_colorImage, v_uv);
76
- }
77
- `;class m extends HTMLElement{constructor(){super(),this.s={GRID_SIZE:250,FOCAL_LENGTH:1200,DEPTH_MIN:.1,DEPTH_MAX:10,CAM_RADIUS:1.5,CAM_MAX_THETA:Math.PI/40,CAM_MAX_PHI:Math.PI/64,CAM_SMOOTHNESS:.9,CAM_ZOOM_AMOUNT:.2,BOOMERANG_SPEED:0,BACKGROUND_COLOR:[0,0,0],IMG_ZOOM_AMOUNT:0,XR_RECENTER_RADIUS:1,XR_RECENTER_YAW:45},this.G=null,this.i=null,this.t=null,this.d=null,this.n=null,this.P=null,this.O={},this.p=null,this.f={x:0,y:0,hovered:!1},this.o={theta:Math.PI,phi:0,radius:this.s.CAM_RADIUS},this.F=0,this.v=null,this.H=!1,this.it=null,this.st=null,this.ht=this.D.bind(this),this.nt=this.Mt.bind(this),this.rt=this.vt.bind(this),this.b=this.X.bind(this),this.ot=!1,this.a=null,this.T=null,this.R=null,this.h=null,this.yt=!1,this.g=null,this.G=this.attachShadow({mode:"open"});let t=document.createElement("div");t.style.position="relative",t.style.width="100%",t.style.height="100%",t.style.display="flex",t.style.alignItems="center",t.style.justifyContent="center",t.style.background="black",this.G.appendChild(t);let e=document.createElement("style");e.textContent=`
78
- :host { display: inline-block; width: 300px; height: 200px; }
79
- :host([fullbleed]) { display:block; width:100%; height:100%; }
80
- canvas { touch-action: none; }
81
- .cover-img, .cover-video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none; }
82
- `,this.G.appendChild(e),this.i=document.createElement("canvas"),this.i.style.width="100%",this.i.style.height="100%",this.i.style.objectFit="contain",this.i.setAttribute("role","img"),this.i.setAttribute("aria-label","3D image"),t.appendChild(this.i),this.g=document.createElement("button"),this.g.textContent="Enter VR",Object.assign(this.g.style,{position:"absolute",display:"none",top:"1%",right:"1%",color:"white",background:"rgba(0,0,0,0.4)",padding:"8px 8px",fontFamily:"monospace",fontSize:"20px",borderRadius:"8px",border:"1px solid white",backdropFilter:"blur(6px)",whiteSpace:"pre"}),t.appendChild(this.g),this.g.addEventListener("click",()=>{this.a?this.at():this.bt()})}connectedCallback(){this.B();let t;try{this.Tt(),t=!1}catch{t=!0}this.i.addEventListener("resize",this.ht),this.i.addEventListener("mousemove",this.nt),this.i.addEventListener("mouseleave",this.rt),t?this.W():(this.D(),this.H=!0,this.F=performance.now(),this.v=requestAnimationFrame(this.b)),this.ut()}disconnectedCallback(){this.H=!1,cancelAnimationFrame(this.v),this.i.removeEventListener("resize",this.ht),this.i.removeEventListener("mousemove",this.nt),this.i.removeEventListener("mouseleave",this.rt);try{this.a&&(this.a.end(),this.a=null,this.yt=!1)}catch{}try{if(this.n){let t=this.n;this.P&&t.deleteProgram(this.P);for(let e in this.O)t.deleteTexture(this.O[e].tex)}}catch{}}setViewMatrix(t){this.it=t&&t.length===16?new Float32Array(t):null}setProjectionMatrix(t){this.st=t&&t.length===16?new Float32Array(t):null}get width(){return this.A(this.t)}get height(){return this.E(this.t)}Tt(){let t=this.i.getContext("webgl2",{antialias:!0,alpha:!1});if(!t)throw new Error("WebGL not supported");this.n=t;let e=this.wt(t,v,a);if(!e)return;this.P=e,t.useProgram(e);let i=this.ct(t),s=this.ct(t);this.O.color=i,this.O.depth=s,this._("color",this.t),this._("depth",this.d);let h=t.getUniformLocation(e,"u_colorImage"),n=t.getUniformLocation(e,"u_depthImage");t.uniform1i(h,0),t.uniform1i(n,1),this.p={uProjection:t.getUniformLocation(e,"u_projMat"),uView:t.getUniformLocation(e,"u_viewMat"),uImageSize:t.getUniformLocation(e,"u_imageSize"),uFocal:t.getUniformLocation(e,"u_focal"),uDepthMin:t.getUniformLocation(e,"u_depthMin"),uDepthMax:t.getUniformLocation(e,"u_depthMax"),uGridSegs:t.getUniformLocation(e,"u_grid"),uXr:t.getUniformLocation(e,"u_xr")}}lt(t=null){if(!this.n)return;let e=this.n;e.bindFramebuffer(e.FRAMEBUFFER,t),e.useProgram(this.P),e.clearColor(...this.s.BACKGROUND_COLOR,1),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT),e.enable(e.DEPTH_TEST)}dt(t,e){if(!this.n)return;let i=this.n,s=this.A(this.t),h=this.E(this.t),n=s/h,r=Math.max(1,Math.floor(this.s.GRID_SIZE)),u=Math.max(1,Math.round(r/n));i.uniform2f(this.p.uImageSize,s,h),i.uniform1f(this.p.uFocal,this.s.FOCAL_LENGTH),i.uniform1f(this.p.uDepthMin,this.s.DEPTH_MIN),i.uniform1f(this.p.uDepthMax,this.s.DEPTH_MAX),i.uniform2i(this.p.uGridSegs,r,u),i.uniform1ui(this.p.uXr,this.a?1:0),i.uniformMatrix4fv(this.p.uView,!1,t),i.uniformMatrix4fv(this.p.uProjection,!1,e),i.drawArrays(i.TRIANGLES,0,r*u*6)}X(t,e){if(!this.H)return;let i=t-this.F;this.F=t,this.mt(),this.f.hovered||(this.f.x=Math.sin(t*this.s.BOOMERANG_SPEED),this.f.y=Math.sin(t*this.s.BOOMERANG_SPEED*.5+Math.PI));let s=this.f.x*this.s.CAM_MAX_THETA+Math.PI,h=-this.f.y*this.s.CAM_MAX_PHI,n=this.s.CAM_RADIUS*(1-this.s.CAM_ZOOM_AMOUNT),r=this.f.hovered?n:this.s.CAM_RADIUS;if(this.o.theta=this.M(s,this.o.theta,i),this.o.phi=this.M(h,this.o.phi,i),this.o.radius=this.M(r,this.o.radius,i),this.a){let u=this.T.getOffsetReferenceSpace(new XRRigidTransform({x:this.h.x,y:this.h.y,z:this.h.z},{x:0,y:Math.sin(this.h.yaw*.5),z:0,w:Math.cos(this.h.yaw*.5)}));this.h.x=this.M(0,this.h.x,i),this.h.y=this.M(0,this.h.y,i),this.h.z=this.M(0,this.h.z,i),this.h.yaw=this.M(0,this.h.yaw,i);let l=e.getViewerPose(this.T).transform;this.R||(this.R=l);let d=this.R,f=l.position.x-d.position.x,_=l.position.y-d.position.y,A=l.position.z-d.position.z,x=p(l.orientation);(Math.abs(x-p(d.orientation))>this.s.XR_RECENTER_YAW*Math.PI/180||Math.hypot(f,_,A)>this.s.XR_RECENTER_RADIUS)&&(this.h.x=-l.position.x,this.h.y=-l.position.y,this.h.z=-l.position.z,this.h.yaw=-x,this.T=this.T.getOffsetReferenceSpace(new XRRigidTransform(l.position,{x:0,y:Math.sin(x*.5),z:0,w:Math.cos(x*.5)})),this.R=null);let I=e.session,P=e.getViewerPose(u);if(!P){I.requestAnimationFrame(this.b);return}let L=I.renderState.baseLayer;this.lt(L.framebuffer);for(let R of P.views){let y=L.getViewport(R);this.n.viewport(y.x,y.y,y.width,y.height);let N=new Float32Array(R.transform.inverse.matrix),k=new Float32Array(R.projectionMatrix);this.dt(N,k)}}else{let u=this.i.width/this.i.height,l=[this.o.radius*Math.cos(this.o.phi)*Math.sin(this.o.theta),this.o.radius*Math.sin(this.o.phi),this.s.CAM_RADIUS+this.o.radius*Math.cos(this.o.phi)*Math.cos(this.o.theta)],d=[0,0,this.s.CAM_RADIUS],f=[0,-1,0],_=this.height*(1-this.s.IMG_ZOOM_AMOUNT),A=2*Math.atan(_/(2*this.s.FOCAL_LENGTH)),x=this.it||new Float32Array(this.Rt(l,d,f)),D=this.st||new Float32Array(this.Ct(A,u,.1,100));this.lt(),this.dt(x,D)}this.a?this.v=e.session.requestAnimationFrame(this.b):this.v=requestAnimationFrame(this.b)}ut(){this.ot&&navigator.xr&&navigator.xr.isSessionSupported?navigator.xr.isSessionSupported("immersive-vr").then(t=>{this.g.style.display=t?"block":"none"}).catch(()=>{this.g.style.display="none"}):this.g.style.display="none"}async bt(){if(!this.a)try{let t=await navigator.xr.requestSession("immersive-vr",{optionalFeatures:["local-floor","bounded-floor"]});this.n.makeXRCompatible&&await this.n.makeXRCompatible(),this.D();let e=new XRWebGLLayer(t,this.n);await t.updateRenderState({baseLayer:e});let i=await t.requestReferenceSpace("local");this.a=t,this.T=i,this.R=null,this.h={x:0,y:0,z:0,yaw:0},cancelAnimationFrame(this.v),t.addEventListener("end",()=>{this.at()}),t.requestAnimationFrame(this.b)}catch(t){console.warn("Unable to start XR session",t)}}async at(){if(this.a){try{await this.a.end()}catch{}this.a=null,this.T=null,this.R=null,this.D(),this.v=requestAnimationFrame(this.b)}}Mt(t){let e=this.i.getBoundingClientRect();this.f.hovered=!0,this.f.x=(t.clientX-e.left)/e.width*2-1,this.f.y=(t.clientY-e.top)/e.height*2-1}vt(){this.f.hovered=!1}D(){let t=window.devicePixelRatio||1,e=this.i.parentElement;if(!e)return;let i=e.clientWidth,s=e.clientHeight,h=this.A(this.t)||1,n=this.E(this.t)||1,r=h/n,u=i,l=u/r;l>s&&(l=s,u=l*r);let d=Math.max(1,Math.floor((this.a?i:u)*t)),f=Math.max(1,Math.floor((this.a?s:l)*t));this.i.width=d,this.i.height=f,this.n&&this.n.viewport(0,0,d,f)}B(){let t=this.s;if(this.hasAttribute("grid-size")&&(t.GRID_SIZE=parseInt(this.getAttribute("grid-size"))??t.GRID_SIZE),this.hasAttribute("focal-length")&&(t.FOCAL_LENGTH=parseFloat(this.getAttribute("focal-length"))??t.FOCAL_LENGTH),this.hasAttribute("depth-min")&&(t.DEPTH_MIN=parseFloat(this.getAttribute("depth-min"))??t.DEPTH_MIN),this.hasAttribute("depth-max")&&(t.DEPTH_MAX=parseFloat(this.getAttribute("depth-max"))??t.DEPTH_MAX),this.hasAttribute("cam-radius")&&(t.CAM_RADIUS=parseFloat(this.getAttribute("cam-radius"))??t.CAM_RADIUS),this.hasAttribute("cam-max-theta")&&(t.CAM_MAX_THETA=parseFloat(this.getAttribute("cam-max-theta"))??t.CAM_MAX_THETA),this.hasAttribute("cam-max-phi")&&(t.CAM_MAX_PHI=parseFloat(this.getAttribute("cam-max-phi"))??t.CAM_MAX_PHI),this.hasAttribute("cam-smoothness")&&(t.CAM_SMOOTHNESS=parseFloat(this.getAttribute("cam-smoothness"))??t.CAM_SMOOTHNESS),this.hasAttribute("cam-zoom-amount")&&(t.CAM_ZOOM_AMOUNT=parseFloat(this.getAttribute("cam-zoom-amount"))??t.CAM_ZOOM_AMOUNT),this.hasAttribute("boomerang-speed")&&(t.BOOMERANG_SPEED=parseFloat(this.getAttribute("boomerang-speed"))??t.BOOMERANG_SPEED),this.hasAttribute("background-color"))try{let e=this.getAttribute("background-color").split(",").map(Number);e.length===3&&(t.BACKGROUND_COLOR=e)}catch{}this.hasAttribute("img-zoom-amount")&&(t.IMG_ZOOM_AMOUNT=parseFloat(this.getAttribute("img-zoom-amount"))??t.IMG_ZOOM_AMOUNT),this.ot=this.hasAttribute("allow-xr"),this.hasAttribute("xr-recenter-yaw")&&(t.XR_RECENTER_YAW=parseFloat(this.getAttribute("xr-recenter-yaw"))??t.XR_RECENTER_YAW),this.hasAttribute("xr-recenter-radius")&&(t.XR_RECENTER_RADIUS=parseFloat(this.getAttribute("xr-recenter-radius"))??t.XR_RECENTER_RADIUS),this.ut()}ft(t,e,i){let s=t.createShader(e);return t.shaderSource(s,i),t.compileShader(s),t.getShaderParameter(s,t.COMPILE_STATUS)?s:(console.error(t.getShaderInfoLog(s)),t.deleteShader(s),null)}wt(t,e,i){let s=this.ft(t,t.VERTEX_SHADER,e),h=this.ft(t,t.FRAGMENT_SHADER,i);if(!s||!h)return null;let n=t.createProgram();return t.attachShader(n,s),t.attachShader(n,h),t.linkProgram(n),t.getProgramParameter(n,t.LINK_STATUS)?(t.deleteShader(s),t.deleteShader(h),n):(console.error(t.getProgramInfoLog(n)),t.deleteProgram(n),null)}ct(t){let e=t.createTexture();return t.bindTexture(t.TEXTURE_2D,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),{tex:e,width:0,height:0}}_(t,e){if(!this.n)return;let i=this.n,s=this.O[t];if(i.activeTexture(t==="color"?i.TEXTURE0:i.TEXTURE1),i.bindTexture(i.TEXTURE_2D,s.tex),!this.V(e)){i.texImage2D(i.TEXTURE_2D,0,i.RGBA,1,1,0,i.RGBA,i.UNSIGNED_BYTE,new Uint8Array([0,0,0,0]));return}try{i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,!1),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,i.RGBA,i.UNSIGNED_BYTE,e),(this.A(e)!=s.width||this.E(e)!=s.height)&&(this.D(),s.width=this.A(e),s.height=this.E(e))}catch{}}Ct(t,e,i,s){let h=1/Math.tan(t/2);return[h/e,0,0,0,0,h,0,0,0,0,(s+i)/(i-s),-1,0,0,2*s*i/(i-s),0]}Rt(t,e,i){function s(d){let f=Math.hypot(...d)||1;return d.map(_=>_/f)}function h(d,f){return[d[1]*f[2]-d[2]*f[1],d[2]*f[0]-d[0]*f[2],d[0]*f[1]-d[1]*f[0]]}function n(d,f){return d.map((_,A)=>_-f[A])}let r=s(n(t,e)),u=s(h(i,r)),l=h(r,u);return[u[0],l[0],r[0],0,u[1],l[1],r[1],0,u[2],l[2],r[2],0,-(u[0]*t[0]+u[1]*t[1]+u[2]*t[2]),-(l[0]*t[0]+l[1]*t[1]+l[2]*t[2]),-(r[0]*t[0]+r[1]*t[1]+r[2]*t[2]),1]}M(t,e,i){let s=(1-this.s.CAM_SMOOTHNESS)*i/16.67,h=Math.sign(t-e);return e+=(t-e)*s,Math.sign(t-e)!==h&&(e=t),e}W(){throw new Error("Must implement _createFallback")}mt(){}V(t){throw new Error("Must implement _isSourceReady")}A(t){throw new Error("Must implement _getSourceWidth")}E(t){throw new Error("Must implement _getSourceHeight")}}T=m;class c extends T{static get observedAttributes(){return["color-src","depth-src","grid-size","focal-length","depth-min","depth-max","cam-radius","cam-max-theta","cam-max-phi","cam-fov","cam-smoothness","boomerang-speed","background-color","allow-xr"]}constructor(){super(),this.t=new Image,this.d=new Image,this.t.crossOrigin="anonymous",this.d.crossOrigin="anonymous",this.t.onload=()=>this._("color",this.t),this.d.onload=()=>this._("depth",this.d)}attributeChangedCallback(t,e,i){e!==i&&(t==="color-src"?this.t.src=i||"":t==="depth-src"?this.d.src=i||"":this.B())}W(){this.t.style.display="block",this.t.classList.add("cover-img"),this.i.parentElement.appendChild(this.t)}V(t){return t&&t.complete&&t.naturalWidth>0}A(t){return t?t.width:1}E(t){return t?t.height:1}}S=c;class w extends T{static get observedAttributes(){return["color-src","depth-src","grid-size","focal-length","depth-min","depth-max","cam-radius","cam-max-theta","cam-max-phi","cam-fov","cam-smoothness","boomerang-speed","background-color","allow-xr","autoplay","loop","muted","controls"]}constructor(){super(),this.r=[],this.u=[],this.c=[],this.j=!1,this.Y=!1,this.I=!0,this.e=new b,this.e.pause(),this.Z=!1,this.C=document.createElement("div"),this.C.classList.add("rgbd-controls"),Object.assign(this.C.style,{position:"absolute",bottom:"1%",left:"50%",transform:"translateX(-50%)",display:"none",alignItems:"center",justifyContent:"center",gap:"8px",background:"rgba(0, 0, 0, 0.4)",padding:"8px 8px",borderRadius:"8px",backdropFilter:"blur(6px)",boxSizing:"border-box",width:"50%",flexWrap:"wrap"}),this.shadowRoot.appendChild(this.C),this.L=document.createElement("button"),Object.assign(this.L.style,{border:"none",background:"transparent",color:"white",fontSize:"24px",cursor:"pointer",padding:"4px",flexShrink:"0"}),this.C.appendChild(this.L),this.L.addEventListener("click",()=>{this.paused?this.play():this.pause()}),this.m=document.createElement("input"),this.m.type="range",this.m.min="0",this.m.max="1",this.m.value="0",this.m.step="any",Object.assign(this.m.style,{flex:"1 1 auto",minWidth:"120px",maxWidth:"100%",cursor:"pointer",accentColor:"#fff"}),this.C.appendChild(this.m),this.m.addEventListener("input",()=>{let t=this.r[0];if(!t||!t.duration)return;let e=t.startTime+this.m.value*t.duration;this.currentTime=e})}disconnectedCallback(){this.e.started()&&this.e.stop(),super.disconnectedCallback()}attributeChangedCallback(t,e,i){e!==i&&(t==="color-src"?this.clear().then(()=>{this.r=[this.S(i,0,!1)],this.c=[this.S(i,0,!0)],this.K=this.r[0],this.q=this.c[0]}):t==="depth-src"?(this.u=[this.S(i,0,!1)],this.Q=this.u[0]):t==="autoplay"?(this.j=this.hasAttribute("autoplay"),this.j&&this.e.play()):t==="loop"?this.Y=this.hasAttribute("loop"):t==="muted"?(this.I=this.hasAttribute("muted"),this.e.setVolume(this.I?0:1),!this.I&&this.e.started()&&this.e.resumeContext()):t==="controls"?(this.Z=this.hasAttribute("controls"),this.C.style.display=this.Z?"flex":"none"):this.B())}async play(){await this.e.play()}async pause(){await this.e.pause()}async clear(){for(this.t=null,this.d=null,this._("color",null),this._("depth",null),this.K=null,this.Q=null,this.q=null;this.r.length>0;)this.N(this.r.shift());for(;this.u.length>0;)this.N(this.u.shift());for(;this.c.length>0;)this.N(this.c.shift());this.currentTime=0,this.e.started()&&await this.e.stop()}enqueue(t,e,i){this.r.push(this.S(t,i,!1)),this.u.push(this.S(e,i,!1)),this.c.push(this.S(t,i,!0))}get paused(){return this.e.isPaused}get currentTime(){return this.e.getVideoTime()}set currentTime(t){let e=i=>{if(i.length==0)return;this.N(i[0]),i[0]=this.k(i[0],i[0].startTime);let s=i[0];s.demuxer!=null&&console.error("Demuxing not yet finished!");let h=Number.MAX_VALUE,n=-1;for(let r=0;r<s.chunks.length;r++){if(s.chunks[r].type!=="key")continue;let u=Math.abs(t-(s.startTime+s.chunks[r].timestamp/1e6));u<h&&(h=u,n=r)}n<0||(s.curChunk=n)};this.e.setVideoTime(t),this.J=null,e(this.r),e(this.u),e(this.c)}get volume(){return this.e.volume}set volume(t){this.e.setVolume(t)}St(t){if(this.e.started()){if(t==null)return;if(t.sampleRate!=this.e.sampleRate)throw new Error("Audio configs have mismatched sample rates!");if(t.numberOfChannels!=this.e.numChannels)throw new Error("Audio configs have mismatched channel counts!")}else this.e.start(t?{sampleRate:t.sampleRate,numChannels:t.numberOfChannels,volume:1}:{audioEnabled:!1}),this.I||this.e.resumeContext()}pt(t,e){let i=e+t.timestamp/1e6,s=[];for(let h=0;h<t.numberOfChannels;h++){let n=new Float32Array(t.numberOfFrames);t.copyTo(n,{planeIndex:h,format:"f32-planar"}),s.push(n)}this.e.scheduleChunk(s,i)}S(t,e,i){let s={startTime:e,isAudio:i,duration:0,demuxer:null,decoder:null,chunks:[],frames:[],curChunk:0},h;return i?h=AudioDecoder:h=VideoDecoder,s.decoder=new h({output:n=>{i?this.pt(n,s.startTime):s.frames.push(n)},error:n=>{console.error("Decoder encountered an error while decoding: ",n)}}),s.demuxer=new M(t,i,{onConfig:n=>{s.config=n,n?s.decoder?.configure(n):s.done=!0,i&&this.St(n)},onChunk:n=>{s.chunks?.push(n),s.duration=Math.max(s.duration,(n.timestamp+n.duration)/1e6)},onEndOfStream:()=>{s.demuxer=null}}),s}k(t,e){let i={startTime:e,isAudio:t.isAudio,duration:t.duration,demuxer:null,decoder:null,config:t.config,chunks:t.chunks,frames:[],curChunk:0},s;return t.isAudio?s=AudioDecoder:s=VideoDecoder,i.decoder=new s({output:h=>{i.isAudio?this.pt(h,i.startTime):i.frames.push(h)},error:h=>{console.error("Decoder encountered an error while decoding: ",h)}}),t.config?i.decoder.configure(t.config):i.done=!0,i}Ot(){let t=!this.paused;this.L.textContent=t?"\u23F8\uFE0F":"\u25B6\uFE0F";let e=this.r[0];if(!e||!e.duration){this.m.value=0;return}let i=this.currentTime-e.startTime,s=Math.max(0,Math.min(1,i/e.duration));this.m.value=s}X(t,e){let i=(h,n)=>{let r=h[n];for(;r.curChunk<r.chunks.length;){let u=r.chunks[r.curChunk];if(r.startTime+u.timestamp/1e6>this.e.getVideoTime()+1)break;r.decoder.decode(u),r.curChunk++}if(r.curChunk>=r.chunks.length&&!r.demuxer&&r.decoder){let u=r.decoder;u.flush().then(()=>{u.close(),r.done=!0}),r.decoder=null}};for(let h=0;h<this.r.length;h++)i(this.r,h);for(let h=0;h<this.u.length;h++)i(this.u,h);for(let h=0;h<this.c.length;h++)this.c[h].config!=null&&i(this.c,h);let s=h=>h?h.done&&h.frames.length==1:!1;s(this.r[0])&&s(this.u[0])&&(this.r.shift(),this.u.shift(),this.gt=!0),this.c[0]?.done&&this.c.shift(),this.Y&&this.r.length==0&&this.u.length==0&&this.c.length==0&&this.K!=null&&this.Q!=null&&(this.e.setVideoTime(0),this.r=[this.k(this.K,0)],this.u=[this.k(this.Q,0)],this.q!=null&&(this.c=[this.k(this.q,0)])),this.Z&&this.Ot(),super.X(t,e)}W(){this.t=document.createElement("video"),this.t.style.display="block",this.t.classList.add("cover-video"),this.t.muted=this.I,this.t.autoplay=this.j,this.t.loop=this.Y,this.t.src=this.getAttribute("color-src"),this.i.parentElement.appendChild(this.t)}mt(){let t=this.r[0],e=this.u[0];if(!t||!e)return;let i=this.e.getVideoTime(),s=this.J!=null?Math.abs(i-this.J):Number.MAX_VALUE,h=-1;for(let n=0;n<Math.min(t.frames.length,e.frames.length);n++){let r=Math.abs(i-(t.startTime+t.frames[n].timestamp/1e6));if(r<=s)s=r,h=n;else break}if(!(h<0)){this.gt&&(this.t.close(),this.d.close(),this.gt=!1),this.t=t.frames[h],this.d=e.frames[h],this.J=t.startTime+this.t.timestamp/1e6,this.t?.timestamp!==this.d?.timestamp&&console.error("Color and depth frames have mismatched PTS"),this._("color",this.t),this._("depth",this.d);for(let n=0;n<h;n++)t.frames.shift().close(),e.frames.shift().close()}}V(t){return t instanceof VideoFrame}A(t){return t?t.codedWidth:1}E(t){return t?t.codedHeight:1}N(t){t.decoder?.close(),t.decoder=null;for(let e=0;e<t.frames.length;e++)t.frames[e].close()}}O=w,customElements.define("rgbd-img",S),customElements.define("rgbd-video",O)}